1 | package genius.core.utility;
|
---|
2 |
|
---|
3 | import java.io.BufferedReader;
|
---|
4 | import java.io.File;
|
---|
5 | import java.io.FileReader;
|
---|
6 | import java.io.IOException;
|
---|
7 | import java.util.ArrayList;
|
---|
8 | import java.util.InvalidPropertiesFormatException;
|
---|
9 |
|
---|
10 | import genius.core.Bid;
|
---|
11 | import genius.core.Domain;
|
---|
12 | import genius.core.DomainImpl;
|
---|
13 | import genius.core.xml.SimpleDOMParser;
|
---|
14 | import genius.core.xml.SimpleElement;
|
---|
15 |
|
---|
16 | /**
|
---|
17 | *
|
---|
18 | * In the non-linear scenarios, the agents no longer have linear utility
|
---|
19 | * functions; instead, they can only sample their utility of a bid through the
|
---|
20 | * getUtility() method. The utility of an offer can be completely arbitrary, so
|
---|
21 | * there is no underlying structure you can use. In terms of the API of Genius,
|
---|
22 | * this means the agents no longer have access to methods pertaining to linear
|
---|
23 | * scenarios (e.g., getWeight()). Please use the getUtility() method to sample
|
---|
24 | * the utilities in the non-linear scenarios to search through the outcome
|
---|
25 | * space.
|
---|
26 | */
|
---|
27 | @SuppressWarnings("serial")
|
---|
28 | public class NonlinearUtilitySpace extends AbstractUtilitySpace {
|
---|
29 | private double maxUtilityValue;
|
---|
30 | private UtilityFunction nonlinearFunction;
|
---|
31 | private ArrayList<InclusiveHyperRectangle> allinclusiveConstraints;
|
---|
32 | private ArrayList<ExclusiveHyperRectangle> allexclusiveConstraints;
|
---|
33 | private SimpleElement fXMLRoot;
|
---|
34 |
|
---|
35 | /**
|
---|
36 | * Creates an empty nonlinear utility space.
|
---|
37 | */
|
---|
38 | public NonlinearUtilitySpace() {
|
---|
39 | super(new DomainImpl());
|
---|
40 | this.nonlinearFunction = new UtilityFunction();
|
---|
41 | this.allinclusiveConstraints = new ArrayList<InclusiveHyperRectangle>();
|
---|
42 | this.allexclusiveConstraints = new ArrayList<ExclusiveHyperRectangle>();
|
---|
43 | }
|
---|
44 |
|
---|
45 | public NonlinearUtilitySpace(Domain domain) {
|
---|
46 | super(domain);
|
---|
47 | this.nonlinearFunction = new UtilityFunction();
|
---|
48 | this.allinclusiveConstraints = new ArrayList<InclusiveHyperRectangle>();
|
---|
49 | this.allexclusiveConstraints = new ArrayList<ExclusiveHyperRectangle>();
|
---|
50 | }
|
---|
51 |
|
---|
52 | public NonlinearUtilitySpace(Domain domain, String fileName)
|
---|
53 | throws Exception {
|
---|
54 | super(domain);
|
---|
55 | this.nonlinearFunction = new UtilityFunction();
|
---|
56 | this.fileName = fileName;
|
---|
57 | this.allinclusiveConstraints = new ArrayList<InclusiveHyperRectangle>();
|
---|
58 | this.allexclusiveConstraints = new ArrayList<ExclusiveHyperRectangle>();
|
---|
59 |
|
---|
60 | if (!fileName.equals("")) {
|
---|
61 | SimpleDOMParser parser = new SimpleDOMParser();
|
---|
62 | BufferedReader file = new BufferedReader(
|
---|
63 | new FileReader(new File(fileName)));
|
---|
64 | SimpleElement root = parser.parse(file);
|
---|
65 | fXMLRoot = root;
|
---|
66 | loadNonlinearSpace(root);
|
---|
67 |
|
---|
68 | } else
|
---|
69 | throw new IOException();
|
---|
70 | }
|
---|
71 |
|
---|
72 | private ArrayList<InclusiveHyperRectangle> getAllInclusiveConstraints() {
|
---|
73 | return this.allinclusiveConstraints;
|
---|
74 | }
|
---|
75 |
|
---|
76 | private ArrayList<ExclusiveHyperRectangle> getAllExclusiveConstraints() {
|
---|
77 | return this.allexclusiveConstraints;
|
---|
78 | }
|
---|
79 |
|
---|
80 | /** create a clone of another utility space */
|
---|
81 | public NonlinearUtilitySpace(NonlinearUtilitySpace us) {
|
---|
82 | super(us.getDomain());
|
---|
83 | fileName = us.getFileName();
|
---|
84 | fXMLRoot = us.fXMLRoot;
|
---|
85 | maxUtilityValue = us.getMaxUtilityValue();
|
---|
86 | nonlinearFunction = us.getNonlinearFunction();
|
---|
87 | allinclusiveConstraints = us.getAllInclusiveConstraints();
|
---|
88 | allexclusiveConstraints = us.getAllExclusiveConstraints();
|
---|
89 | this.setDiscount(us.getDiscountFactor());
|
---|
90 | this.setReservationValue(us.getReservationValue());
|
---|
91 | }
|
---|
92 |
|
---|
93 | /**
|
---|
94 | * parse xml file and load nonlinear utility space
|
---|
95 | *
|
---|
96 | * @param rectangeElements
|
---|
97 | * @return
|
---|
98 | */
|
---|
99 | private ArrayList<Constraint> loadHyperRectangles(
|
---|
100 | Object[] rectangeElements) {
|
---|
101 |
|
---|
102 | ArrayList<Constraint> hyperRectangleConstraints = new ArrayList<Constraint>();
|
---|
103 |
|
---|
104 | for (int j = 0; j < rectangeElements.length; j++) {
|
---|
105 |
|
---|
106 | HyperRectangle rectangle = null;
|
---|
107 | ArrayList<Bound> boundlist = new ArrayList<Bound>();
|
---|
108 | Object[] bounds = null;
|
---|
109 |
|
---|
110 | if (((SimpleElement) rectangeElements[j])
|
---|
111 | .getChildByTagName("INCLUDES").length != 0) {
|
---|
112 | rectangle = new InclusiveHyperRectangle();
|
---|
113 | allinclusiveConstraints
|
---|
114 | .add((InclusiveHyperRectangle) rectangle);
|
---|
115 | bounds = ((SimpleElement) rectangeElements[j])
|
---|
116 | .getChildByTagName("INCLUDES");
|
---|
117 | }
|
---|
118 |
|
---|
119 | if (((SimpleElement) rectangeElements[j])
|
---|
120 | .getChildByTagName("EXCLUDES").length != 0) {
|
---|
121 | rectangle = new ExclusiveHyperRectangle();
|
---|
122 | allexclusiveConstraints
|
---|
123 | .add((ExclusiveHyperRectangle) rectangle);
|
---|
124 | bounds = ((SimpleElement) rectangeElements[j])
|
---|
125 | .getChildByTagName("EXCLUDES");
|
---|
126 | }
|
---|
127 |
|
---|
128 | if ((((SimpleElement) rectangeElements[j])
|
---|
129 | .getChildByTagName("INCLUDES").length == 0)
|
---|
130 | && (((SimpleElement) rectangeElements[j])
|
---|
131 | .getChildByTagName("EXCLUDES").length == 0)) {
|
---|
132 | rectangle = new InclusiveHyperRectangle(true);
|
---|
133 | } else {
|
---|
134 | for (int k = 0; k < bounds.length; k++) {
|
---|
135 | Bound b = new Bound(
|
---|
136 | ((SimpleElement) bounds[k]).getAttribute("index"),
|
---|
137 | ((SimpleElement) bounds[k]).getAttribute("min"),
|
---|
138 | ((SimpleElement) bounds[k]).getAttribute("max"));
|
---|
139 | boundlist.add(b);
|
---|
140 | }
|
---|
141 | rectangle.setBoundList(boundlist);
|
---|
142 | }
|
---|
143 |
|
---|
144 | rectangle.setUtilityValue(
|
---|
145 | Double.parseDouble(((SimpleElement) rectangeElements[j])
|
---|
146 | .getAttribute("utility")));
|
---|
147 | if (((SimpleElement) rectangeElements[j])
|
---|
148 | .getAttribute("weight") != null)
|
---|
149 | rectangle.setWeight(
|
---|
150 | Double.parseDouble(((SimpleElement) rectangeElements[j])
|
---|
151 | .getAttribute("weight")));
|
---|
152 |
|
---|
153 | hyperRectangleConstraints.add(rectangle);
|
---|
154 | }
|
---|
155 | return hyperRectangleConstraints;
|
---|
156 |
|
---|
157 | }
|
---|
158 |
|
---|
159 | private UtilityFunction loadUtilityFunction(SimpleElement utility) {
|
---|
160 |
|
---|
161 | UtilityFunction currentFunction = new UtilityFunction();
|
---|
162 | currentFunction.setAggregationType(AGGREGATIONTYPE
|
---|
163 | .getAggregationType(utility.getAttribute("aggregation")));
|
---|
164 | if (utility.getAttribute("weight") != null)
|
---|
165 | currentFunction.setWeight(
|
---|
166 | Double.parseDouble(utility.getAttribute("weight")));
|
---|
167 |
|
---|
168 | // similarly other constraint can be parsed and add to the constraints
|
---|
169 | // by adding a addConstraints method
|
---|
170 | currentFunction.setConstraints(loadHyperRectangles(
|
---|
171 | utility.getChildByTagName("hyperRectangle")));
|
---|
172 |
|
---|
173 | Object[] innerFunctions = utility.getChildByTagName("ufun");
|
---|
174 |
|
---|
175 | for (int k = 0; k < innerFunctions.length; k++) {
|
---|
176 | currentFunction.addUtilityFunction(
|
---|
177 | loadUtilityFunction(((SimpleElement) innerFunctions[k])));
|
---|
178 | }
|
---|
179 | return currentFunction;
|
---|
180 | }
|
---|
181 |
|
---|
182 | @Override
|
---|
183 | public SimpleElement toXML() throws IOException {
|
---|
184 | /**
|
---|
185 | * Instead of conversion, we read in the existing XML file from disk,
|
---|
186 | * plug in the reservation value and discount factor and return that.
|
---|
187 | */
|
---|
188 | SimpleElement root;
|
---|
189 | SimpleDOMParser parser = new SimpleDOMParser();
|
---|
190 | BufferedReader file = new BufferedReader(
|
---|
191 | new FileReader(new File(fileName)));
|
---|
192 | root = parser.parse(file);
|
---|
193 |
|
---|
194 | Object[] reservationelts = root.getChildByTagName("reservation");
|
---|
195 | if (reservationelts == null || reservationelts.length == 0
|
---|
196 | || !(reservationelts[0] instanceof SimpleElement)) {
|
---|
197 | throw new InvalidPropertiesFormatException(
|
---|
198 | "file does not contain reservation value");
|
---|
199 | }
|
---|
200 | Object[] discountelts = root.getChildByTagName("discount_factor");
|
---|
201 | if (discountelts == null || discountelts.length == 0
|
---|
202 | || !(discountelts[0] instanceof SimpleElement)) {
|
---|
203 | throw new InvalidPropertiesFormatException(
|
---|
204 | "file does not contain discount factor value");
|
---|
205 | }
|
---|
206 |
|
---|
207 | ((SimpleElement) reservationelts[0]).setAttribute("value",
|
---|
208 | "" + getReservationValueUndiscounted());
|
---|
209 |
|
---|
210 | ((SimpleElement) discountelts[0]).setAttribute("value",
|
---|
211 | "" + getDiscountFactor());
|
---|
212 |
|
---|
213 | return root;
|
---|
214 |
|
---|
215 | }
|
---|
216 |
|
---|
217 | private void loadNonlinearSpace(SimpleElement root) {
|
---|
218 |
|
---|
219 | // load reservation value
|
---|
220 | try {
|
---|
221 | if ((root.getChildByTagName("reservation") != null)
|
---|
222 | && (root.getChildByTagName("reservation").length > 0)) {
|
---|
223 | SimpleElement xml_reservation = (SimpleElement) (root
|
---|
224 | .getChildByTagName("reservation")[0]);
|
---|
225 | this.setReservationValue(
|
---|
226 | Double.valueOf(xml_reservation.getAttribute("value")));
|
---|
227 | System.out.println(
|
---|
228 | "Reservation value: " + this.getReservationValue());
|
---|
229 | }
|
---|
230 | } catch (Exception e) {
|
---|
231 | System.out.println("Utility space has no reservation value");
|
---|
232 | }
|
---|
233 | // load discount factor
|
---|
234 | try {
|
---|
235 | if ((root.getChildByTagName("discount_factor") != null)
|
---|
236 | && (root.getChildByTagName("discount_factor").length > 0)) {
|
---|
237 | SimpleElement xml_reservation = (SimpleElement) (root
|
---|
238 | .getChildByTagName("discount_factor")[0]);
|
---|
239 | double df = Double
|
---|
240 | .parseDouble(xml_reservation.getAttribute("value"));
|
---|
241 | this.setDiscount(validateDiscount(df));
|
---|
242 | System.out
|
---|
243 | .println("Discount value: " + this.getDiscountFactor());
|
---|
244 | }
|
---|
245 | } catch (Exception e) {
|
---|
246 | System.out.println("Utility space has no discount factor;");
|
---|
247 | }
|
---|
248 |
|
---|
249 | // load utility
|
---|
250 | Object utility = ((SimpleElement) root.getChildElements()[0])
|
---|
251 | .getChildByTagName("utility")[0];
|
---|
252 | this.setMaxUtilityValue(Double.parseDouble(
|
---|
253 | ((SimpleElement) utility).getAttribute("maxutility")));
|
---|
254 | this.nonlinearFunction = loadUtilityFunction(
|
---|
255 | (SimpleElement) ((SimpleElement) utility)
|
---|
256 | .getChildByTagName("ufun")[0]);
|
---|
257 | }
|
---|
258 |
|
---|
259 | private double getMaxUtilityValue() {
|
---|
260 | return maxUtilityValue;
|
---|
261 | }
|
---|
262 |
|
---|
263 | private void setMaxUtilityValue(double maxUtilityValue) {
|
---|
264 | this.maxUtilityValue = maxUtilityValue;
|
---|
265 | }
|
---|
266 |
|
---|
267 | @Override
|
---|
268 | public double getUtility(Bid bid) {
|
---|
269 | double result = nonlinearFunction.getUtility(bid)
|
---|
270 | / this.maxUtilityValue;
|
---|
271 |
|
---|
272 | if (result > 1)
|
---|
273 | return 1;
|
---|
274 | else
|
---|
275 | return result;
|
---|
276 | }
|
---|
277 |
|
---|
278 | /**
|
---|
279 | * Uses the original equals of {@link Object}.
|
---|
280 | */
|
---|
281 | @Override
|
---|
282 | public boolean equals(Object obj) {
|
---|
283 | return this == obj;
|
---|
284 | }
|
---|
285 |
|
---|
286 | private UtilityFunction getNonlinearFunction() {
|
---|
287 | return nonlinearFunction;
|
---|
288 | }
|
---|
289 |
|
---|
290 | @Override
|
---|
291 | public String toString() {
|
---|
292 |
|
---|
293 | String result = "";
|
---|
294 | for (InclusiveHyperRectangle rec : this.getAllInclusiveConstraints()) {
|
---|
295 | ArrayList<Bound> boundList = rec.getBoundList();
|
---|
296 | result += ("Rectangle: \n");
|
---|
297 | for (Bound bound : boundList) {
|
---|
298 | result += ("Issue with index " + bound.getIssueIndex() + " min:"
|
---|
299 | + bound.getMin() + " max:" + bound.getMax() + " \n");
|
---|
300 | }
|
---|
301 |
|
---|
302 | }
|
---|
303 | return result;
|
---|
304 | }
|
---|
305 |
|
---|
306 | @Override
|
---|
307 | public UtilitySpace copy() {
|
---|
308 | return new NonlinearUtilitySpace(this);
|
---|
309 | }
|
---|
310 |
|
---|
311 | @Override
|
---|
312 | public String isComplete() {
|
---|
313 | return null;
|
---|
314 | }
|
---|
315 | }
|
---|