source: src/main/java/genius/core/DomainImpl.java@ 256

Last change on this file since 256 was 127, checked in by Wouter Pasman, 6 years ago

#41 ROLL BACK of rev.126 . So this version is equal to rev. 125

File size: 12.7 KB
Line 
1package genius.core;
2
3import java.io.BufferedReader;
4import java.io.File;
5import java.io.FileNotFoundException;
6import java.io.FileReader;
7import java.io.IOException;
8import java.io.Serializable;
9import java.util.ArrayList;
10import java.util.Enumeration;
11import java.util.HashMap;
12import java.util.List;
13import java.util.Random;
14
15import genius.core.issue.ISSUETYPE;
16import genius.core.issue.Issue;
17import genius.core.issue.IssueDiscrete;
18import genius.core.issue.IssueInteger;
19import genius.core.issue.IssueReal;
20import genius.core.issue.Objective;
21import genius.core.issue.Value;
22import genius.core.issue.ValueInteger;
23import genius.core.issue.ValueReal;
24import genius.core.xml.SimpleDOMParser;
25import genius.core.xml.SimpleElement;
26
27/**
28 * Implementation of Domain. Representation of the outcome space of a scenario.
29 *
30 * @author Dmytro Tykhonov & Koen Hindriks
31 */
32public class DomainImpl implements Domain, Serializable {
33 /**
34 *
35 */
36 private static final long serialVersionUID = -8729366996052137300L;
37 private Objective fObjectivesRoot = new Objective();
38 private String name = "";
39 private SimpleElement root;
40
41 /**
42 * Creates an empty domain.
43 */
44 public DomainImpl() {
45 }
46
47 /**
48 * @return XML-representation of this domain.
49 */
50 public SimpleElement getXMLRoot() {
51 return root;
52 }
53
54 /**
55 * Creates a domain given an XML-representation of the domain.
56 *
57 * @param root
58 * XML-representation of the domain.
59 */
60 public DomainImpl(SimpleElement root) {
61 this.root = root;
62 loadTreeFromXML(root);
63 }
64
65 /**
66 * Creates a domain given the path to a file with an XML-representation.
67 *
68 * @param filename
69 * @throws Exception
70 */
71 public DomainImpl(String filename) throws IOException {
72 this(new File(filename));
73 name = filename;
74 }
75
76 /**
77 * read a domain from a file.
78 *
79 * @param domainFile
80 * file containing the domain
81 * @throws IOException
82 * @throws Exception
83 * if file not found or containing unreadable (non xml) data.
84 */
85 public DomainImpl(File domainFile) throws IOException {
86 if (!domainFile.exists()) {
87 throw new FileNotFoundException("File does not exist " + domainFile);
88 }
89 name = domainFile.getAbsolutePath();
90 SimpleDOMParser parser = new SimpleDOMParser();
91 BufferedReader file = new BufferedReader(new FileReader(domainFile));
92 root = parser.parse(file);
93
94 SimpleElement xml_utility_space;
95 try {
96 xml_utility_space = (SimpleElement) (root.getChildByTagName("utility_space")[0]);
97 } catch (Exception err) {
98 throw new IOException("Can't read from " + domainFile + ", incorrect format of file");
99 }
100 loadTreeFromXML(xml_utility_space);
101 }
102
103 @Override
104 public final Objective getObjectivesRoot() {
105 return fObjectivesRoot;
106 }
107
108 /**
109 * Sets a new domain root.
110 *
111 * @param ob
112 * The new root Objective
113 */
114 public final void setObjectivesRoot(Objective ob) {
115 fObjectivesRoot = ob;
116 }
117
118 /**
119 * @param pRoot
120 * The SimpleElement that contains the root of the Objective
121 * tree.
122 */
123 private final void loadTreeFromXML(SimpleElement pRoot) {
124 // SimpleElement root contains a LinkedList with SimpleElements.
125 /*
126 * Structure of the file:
127 *
128 * pRoot contains information about how many items there exist in the
129 * utilityspace. The first SimpleElement under pRoot contains the root
130 * objective of the tree, with a number of objective as tagnames.
131 */
132
133 // Get the number of issues:
134
135 // Get the actual root Objective.
136 SimpleElement root = (SimpleElement) (pRoot.getChildByTagName("objective")[0]);
137 int rootIndex = Integer.valueOf(root.getAttribute("index"));
138 Objective objAlmostRoot = new Objective();
139 objAlmostRoot.setNumber(rootIndex);
140 String name = root.getAttribute("name");
141 if (name != null)
142 objAlmostRoot.setName(name);
143 else
144 objAlmostRoot.setName("root"); // just in case.
145 // set objAlmostRoot attributes based on pRoot
146
147 fObjectivesRoot = buildTreeRecursive(root, objAlmostRoot);
148
149 }
150
151 // added by Herbert
152 /**
153 *
154 * @param currentLevelRoot
155 * The current SimpleElement containing the information for the
156 * Objective on this level.
157 * @param currentParent
158 * parent of the current level of this branch of the tree.
159 * @return The current parent of this level of the tree, with the children
160 * attached.
161 */
162
163 private final Objective buildTreeRecursive(SimpleElement currentLevelRoot, Objective currentParent) {
164 Object[] currentLevelObjectives = currentLevelRoot.getChildByTagName("objective");
165 Object[] currentLevelIssues = currentLevelRoot.getChildByTagName("issue");
166 for (int i = 0; i < currentLevelObjectives.length; i++) {
167 SimpleElement childObjectives = (SimpleElement) currentLevelObjectives[i];
168 int obj_index = Integer.valueOf(childObjectives.getAttribute("index"));
169 Objective child = new Objective(currentParent);
170 child.setNumber(obj_index);
171 // Set child attributes based on childObjectives.
172 child.setName(childObjectives.getAttribute("name"));
173
174 currentParent.addChild(buildTreeRecursive(childObjectives, child));
175
176 }
177
178 for (int j = 0; j < currentLevelIssues.length; j++) {
179 Issue child = null;
180
181 SimpleElement childIssues = (SimpleElement) currentLevelIssues[j];
182 // check type of issue
183 String name = childIssues.getAttribute("name");
184 int index = Integer.parseInt(childIssues.getAttribute("index"));
185
186 // Collect issue value type from XML file.
187 String type = childIssues.getAttribute("type");
188 String vtype = childIssues.getAttribute("vtype");
189 ISSUETYPE issueType;
190 if (type == null) {
191 issueType = ISSUETYPE.DISCRETE;
192 } else if (type.equals(vtype)) {
193 // Both "type" as well as "vtype" attribute, but consistent.
194 issueType = ISSUETYPE.convertToType(type);
195 } else if (type != null && vtype == null) { // Used label "type"
196 // instead of label
197 // "vtype".
198 issueType = ISSUETYPE.convertToType(type);
199 } else {
200 System.out.println("Conflicting value types specified for issue in template file.");
201 // TODO: Define exception.
202 // For now: use "type" label.
203 issueType = ISSUETYPE.convertToType(type);
204 }
205
206 // Collect values and/or corresponding parameters for issue type.
207 Object[] xml_items;
208 Object[] xml_item;
209 int nrOfItems, minI, maxI;
210 double minR, maxR;
211 String[] values;
212 String[] desc;
213 switch (issueType) {
214 case DISCRETE:
215 // Collect discrete values for discrete-valued issue from xml
216 // template
217 xml_items = childIssues.getChildByTagName("item");
218 nrOfItems = xml_items.length;
219
220 values = new String[nrOfItems];
221 desc = new String[nrOfItems];
222 for (int k = 0; k < nrOfItems; k++) {
223 // TODO: check range of indexes.
224 values[k] = ((SimpleElement) xml_items[k]).getAttribute("value");
225 desc[k] = ((SimpleElement) xml_items[k]).getAttribute("description");
226 }
227 child = new IssueDiscrete(name, index, values, desc, currentParent);
228 break;
229 case INTEGER:
230 // Collect range bounds for integer-valued issue from xml
231 // template
232 xml_item = childIssues.getChildByTagName("range");
233 minI = Integer.valueOf(childIssues.getAttribute("lowerbound"));
234 maxI = Integer.valueOf(childIssues.getAttribute("upperbound"));
235 child = new IssueInteger(name, index, minI, maxI, currentParent);
236 break;
237 case REAL:
238 // Collect range bounds for integer-valued issue from xml
239 // template
240 xml_item = childIssues.getChildByTagName("range");
241 minR = Double.valueOf(((SimpleElement) xml_item[0]).getAttribute("lowerbound"));
242 maxR = Double.valueOf(((SimpleElement) xml_item[0]).getAttribute("upperbound"));
243 child = new IssueReal(name, index, minR, maxR);
244 break;
245 default: // By default, createFrom discrete-valued issue
246 // Collect discrete values for discrete-valued issue from xml
247 // template
248 xml_items = childIssues.getChildByTagName("item");
249 nrOfItems = xml_items.length;
250 values = new String[nrOfItems];
251 child = new IssueDiscrete(name, index, values, currentParent);
252 break;
253 }
254
255 // Descriptions?
256 child.setNumber(index);
257 try {
258 currentParent.addChild(child);
259 } catch (Exception e) {
260 System.out.println("child is NULL");
261 e.printStackTrace();
262
263 }
264 }
265
266 return currentParent;
267 }
268
269 @Override
270 public Bid getRandomBid(Random r) {
271 if (r == null)
272 r = new Random();
273 HashMap<Integer, Value> values = new HashMap<Integer, Value>();
274
275 int lNrOfOptions, lOptionIndex;
276
277 // For each issue, compute a random value to return in bid.
278 for (Issue lIssue : getIssues()) {
279 switch (lIssue.getType()) {
280 case DISCRETE:
281 IssueDiscrete lIssueDiscrete = (IssueDiscrete) lIssue;
282 lNrOfOptions = lIssueDiscrete.getNumberOfValues();
283 lOptionIndex = Double.valueOf(r.nextDouble() * (lNrOfOptions)).intValue();
284 if (lOptionIndex >= lNrOfOptions)
285 lOptionIndex = lNrOfOptions - 1;
286 values.put(lIssue.getNumber(), lIssueDiscrete.getValue(lOptionIndex));
287 break;
288 case INTEGER:
289 lNrOfOptions = ((IssueInteger) lIssue).getUpperBound() - ((IssueInteger) lIssue).getLowerBound() + 1;
290 lOptionIndex = Double.valueOf(r.nextDouble() * (lNrOfOptions)).intValue();
291 if (lOptionIndex >= lNrOfOptions)
292 lOptionIndex = lNrOfOptions - 1;
293 values.put(lIssue.getNumber(),
294 new ValueInteger(((IssueInteger) lIssue).getLowerBound() + lOptionIndex));
295 break;
296 case REAL:
297 IssueReal lIssueReal = (IssueReal) lIssue;
298 lNrOfOptions = lIssueReal.getNumberOfDiscretizationSteps();
299 double lOneStep = (lIssueReal.getUpperBound() - lIssueReal.getLowerBound()) / lNrOfOptions;
300 lOptionIndex = Double.valueOf(r.nextDouble() * (lNrOfOptions)).intValue();
301 if (lOptionIndex >= lNrOfOptions)
302 lOptionIndex = lNrOfOptions - 1;
303 values.put(lIssue.getNumber(), new ValueReal(lIssueReal.getLowerBound() + lOneStep * lOptionIndex));
304 break;
305 }
306 }
307 try {
308 return new Bid(this, values);
309 } catch (Exception e) {
310 System.out.println("problem getrandombid:" + e.getMessage());
311 }
312 return null;
313 }
314
315 /**
316 * Creates an XML representation of this domain.
317 *
318 * @return the SimpleElements representation of this Domain or
319 * <code>null</code> when there was an error.
320 */
321 public SimpleElement toXML() {
322 SimpleElement root = new SimpleElement("negotiation_template");
323 SimpleElement utilRoot = new SimpleElement("utility_space");
324 // set attributes for this domain
325 utilRoot.setAttribute("number_of_issues", "" + fObjectivesRoot.getChildCount());
326 utilRoot.addChildElement(fObjectivesRoot.toXML());
327 root.addChildElement(utilRoot);
328 return root;
329 }
330
331 @Override
332 public List<Objective> getObjectives() {
333 Enumeration<Objective> objectives = fObjectivesRoot.getPreorderEnumeration();
334 ArrayList<Objective> objectivelist = new ArrayList<Objective>();
335 while (objectives.hasMoreElements())
336 objectivelist.add(objectives.nextElement());
337 return objectivelist;
338 }
339
340 @Override
341 public List<Issue> getIssues() {
342 Enumeration<Objective> issues = fObjectivesRoot.getPreorderIssueEnumeration();
343 ArrayList<Issue> issuelist = new ArrayList<Issue>();
344 while (issues.hasMoreElements())
345 issuelist.add((Issue) issues.nextElement());
346 return issuelist;
347 }
348
349 @Override
350 public long getNumberOfPossibleBids() {
351 List<Issue> lIssues = getIssues();
352 if (lIssues.isEmpty()) {
353 return 0;
354 }
355 long lNumberOfPossibleBids = (long) 1;
356 for (Issue lIssue : lIssues) {
357 switch (lIssue.getType()) {
358 case DISCRETE:
359 lNumberOfPossibleBids = lNumberOfPossibleBids * ((IssueDiscrete) lIssue).getNumberOfValues();
360 break;
361 case REAL:
362 lNumberOfPossibleBids = lNumberOfPossibleBids * ((IssueReal) lIssue).getNumberOfDiscretizationSteps();
363 break;
364 case INTEGER:
365 lNumberOfPossibleBids = lNumberOfPossibleBids
366 * ((IssueInteger) lIssue).getNumberOfDiscretizationSteps();
367 break;
368 default:
369 System.out.println("Unsupported type " + lIssue.getType());
370 break;
371
372 }
373 }
374 return lNumberOfPossibleBids;
375 }
376
377 @Override
378 public int hashCode() {
379 final int prime = 31;
380 int result = 1;
381 result = prime * result + ((fObjectivesRoot == null) ? 0 : fObjectivesRoot.hashCode());
382 return result;
383 }
384
385 @Override
386 public boolean equals(Object obj) {
387 if (this == obj)
388 return true;
389 if (obj == null)
390 return false;
391 if (getClass() != obj.getClass())
392 return false;
393 DomainImpl other = (DomainImpl) obj;
394 if (fObjectivesRoot == null) {
395 if (other.fObjectivesRoot != null)
396 return false;
397 } else if (!fObjectivesRoot.equals(other.fObjectivesRoot))
398 return false;
399 return true;
400 }
401
402 @Override
403 public String getName() {
404 return name;
405 }
406}
Note: See TracBrowser for help on using the repository browser.