source: src/main/java/genius/core/utility/AdditiveUtilitySpace.java

Last change on this file was 158, checked in by Tim Baarslag, 6 years ago

Build 9.1.7 ready

File size: 25.4 KB
Line 
1package genius.core.utility;
2
3import java.util.List;
4
5import java.util.Enumeration;
6import java.util.HashMap;
7import java.util.Map;
8import java.util.Map.Entry;
9import java.util.Set;
10import java.util.Vector;
11
12import java.io.BufferedReader;
13import java.io.File;
14import java.io.FileReader;
15import java.io.IOException;
16
17import genius.core.Bid;
18import genius.core.Domain;
19import genius.core.DomainImpl;
20import genius.core.issue.Issue;
21import genius.core.issue.IssueDiscrete;
22import genius.core.issue.Objective;
23import genius.core.xml.SimpleDOMParser;
24import genius.core.xml.SimpleElement;
25
26/**
27 * The additive utility space couples all objectives to weights and evaluators.
28 *
29 * @author D. Tykhonov, K. Hindriks, W. Pasman
30 */
31
32public class AdditiveUtilitySpace extends AbstractUtilitySpace {
33
34 /**
35 *
36 */
37 private static final long serialVersionUID = 8746748105840831474L;
38
39 private final Map<Objective, Evaluator> fEvaluators;
40
41 /**
42 * Creates an empty utility space.
43 */
44 public AdditiveUtilitySpace() {
45 this(new DomainImpl(), new HashMap<Objective, Evaluator>());
46 }
47
48 /**
49 * Creates a new utilityspace of the given domain.
50 *
51 * @param domain
52 * for which the utilityspace should be specified.
53 */
54 public AdditiveUtilitySpace(Domain domain) {
55 this(domain, new HashMap<Objective, Evaluator>());
56 }
57
58 public AdditiveUtilitySpace(Domain domain,
59 Map<Objective, Evaluator> fEvaluators) {
60 super(domain);
61 this.fEvaluators = fEvaluators;
62 normalizeWeights();
63 }
64
65 /**
66 * Create new default util space for a given domain.
67 *
68 * @param domain
69 * @param fileName
70 * to read domain from. Set fileName to "" if no file available,
71 * in which case default evaluators are loaded..
72 * @throws IOException
73 * if error occurs, e.g. if domain does not match the util
74 * space, or file not found.
75 */
76 public AdditiveUtilitySpace(Domain domain, String fileName)
77 throws IOException {
78 super(domain);
79 this.fileName = fileName;
80 fEvaluators = new HashMap<Objective, Evaluator>();
81 if (!fileName.equals(""))
82 loadTreeFromFile(fileName);
83 else { // add evaluator to all objectives
84 List<Objective> objectives = domain.getObjectives();
85 for (Objective obj : objectives) {
86 Evaluator eval = defaultEvaluator(obj);
87 fEvaluators.put(obj, eval);
88 }
89
90 }
91 }
92
93 /**
94 * Copies the data from another UtilitySpace.
95 *
96 * @param us
97 * utility space to be cloned.
98 */
99 public AdditiveUtilitySpace(AdditiveUtilitySpace us) {
100 super(us.getDomain());
101 fileName = us.getFileName();
102 fEvaluators = new HashMap<Objective, Evaluator>();
103 setReservationValue(us.getReservationValue());
104 // and clone the evaluators
105 for (Objective obj : getDomain().getObjectives()) {
106 Evaluator e = us.getEvaluator(obj.getNumber());
107 if (e != null)
108 fEvaluators.put(obj, e.clone());
109 /*
110 * else incomplete. But that seems allowed. especially, objectives
111 * (the non-Issues) won't generally have an evlauator
112 */
113 }
114 setDiscount(us.getDiscountFactor());
115 }
116
117 /**************** implements UtilitySpace ****************/
118
119 @Override
120 public double getUtility(Bid bid) {
121 double utility = 0;
122
123 Objective root = getDomain().getObjectivesRoot();
124 Enumeration<Objective> issueEnum = root.getPreorderIssueEnumeration();
125 while (issueEnum.hasMoreElements()) {
126 Objective is = issueEnum.nextElement();
127 Evaluator eval = fEvaluators.get(is);
128 if (eval == null) {
129 throw new IllegalArgumentException(
130 "UtilitySpace does not contain evaluator for issue "
131 + is + ". ");
132 }
133
134 switch (eval.getType()) {
135 case DISCRETE:
136 case INTEGER:
137 case REAL:
138 utility += eval.getWeight()
139 * eval.getEvaluation(this, bid, is.getNumber());
140 break;
141 case OBJECTIVE:
142 // we ignore OBJECTIVE. Not clear what it is and why.
143 break;
144 }
145 }
146 double result = utility;
147 if (result > 1)
148 return 1;
149 return result;
150 }
151
152 @Override
153 public SimpleElement toXML() throws IOException {
154 SimpleElement root = (getDomain().getObjectivesRoot()).toXML();
155 root = toXMLrecurse(root);
156 SimpleElement rootWrapper = new SimpleElement("utility_space");
157 rootWrapper.addChildElement(root);
158
159 SimpleElement discountFactor = new SimpleElement("discount_factor");
160 discountFactor.setAttribute("value", getDiscountFactor() + "");
161 rootWrapper.addChildElement(discountFactor);
162
163 SimpleElement reservationValue = new SimpleElement(RESERVATION);
164 reservationValue.setAttribute("value",
165 getReservationValueUndiscounted() + "");
166 rootWrapper.addChildElement(reservationValue);
167
168 return rootWrapper;
169 }
170
171 @Override
172 public String isComplete() {
173 /**
174 * This function *should* check that the domainSubtreeP is a subtree of
175 * the utilSubtreeP, and that all leaf nodes are complete. However
176 * currently we only check that all the leaf nodes are complete, We
177 * don't have the domain template here anymore. so we can only check
178 * that all fields are filled.
179 */
180 List<Issue> issues = getDomain().getIssues();
181 if (issues == null)
182 return "Utility space is not complete, in fact it is empty!";
183 String mess;
184 for (Issue issue : issues) {
185 Evaluator ev = getEvaluator(issue.getNumber());
186 if (ev == null)
187 return "issue " + issue.getName() + " has no evaluator";
188 mess = (ev.isComplete(issue));
189 if (mess != null)
190 return mess;
191 }
192 return null;
193 }
194
195 @Override
196 public String toString() {
197 String result = "";
198 for (Entry<Objective, Evaluator> entry : fEvaluators.entrySet()) {
199 result += ("Issue weight " + entry.getValue().getWeight() + "\n");
200 result += ("Values " + entry.getKey().getName() + ": "
201 + entry.getValue().toString() + "\n");
202 }
203 return result;
204 }
205
206 @Override
207 public boolean equals(Object obj) {
208 if (!(obj instanceof AdditiveUtilitySpace))
209 return false;
210 AdditiveUtilitySpace obj2 = (AdditiveUtilitySpace) obj;
211 if (!getDomain().equals(obj2.getDomain()))
212 return false;
213 for (Entry<Objective, Evaluator> entry : fEvaluators.entrySet()) {
214 Evaluator eval2 = obj2.getEvaluator(entry.getKey().getNumber());
215 if (!entry.getValue().equals(eval2)) {
216 return false;
217 }
218 }
219 return true;
220 }
221
222 @Override
223 public UtilitySpace copy() {
224 return new AdditiveUtilitySpace(this);
225 }
226
227 /************ Additive-specific functions *****************/
228
229 /**
230 * @return number of issues. This can only be used for linear utility
231 * functions.
232 */
233 public final int getNrOfEvaluators() {
234 return fEvaluators.size();
235 }
236
237 /**
238 * Returns the evaluator of an issue for the given index. This can only be
239 * used for linear utility functions.
240 *
241 * @param index
242 * The IDnumber of the Objective or Issue
243 * @return An Evaluator for the Objective or Issue.
244 */
245 public Evaluator getEvaluator(int index) {
246 Objective obj = getDomain().getObjectivesRoot().getObjective(index);
247 if (obj != null) {
248 return fEvaluators.get(obj);
249 } else
250 return null;
251 }
252
253 /**
254 * @param obj
255 * the objective for which an evaluator is needed
256 * @return evaluator for given objective, or null if no such objective.
257 */
258 public Evaluator getEvaluator(Objective obj) {
259 return fEvaluators.get(obj);
260 }
261
262 /**
263 * Returns the utility of one issue in the bid. Note that this value is in
264 * the range [0,1] as it is not normalized by the issue weight. Only works
265 * with linear utility spaces.
266 *
267 * @param pIssueIndex
268 * of the issue.
269 * @param bid
270 * @return evaluation of the value of the issue of the given bid.
271 */
272 public final double getEvaluation(int pIssueIndex, Bid bid) {
273 Object lObj = getDomain().getObjectivesRoot().getObjective(pIssueIndex);
274 Evaluator lEvaluator = fEvaluators.get(lObj);
275
276 return lEvaluator.getEvaluation(this, bid, pIssueIndex);
277 }
278
279 /**
280 *
281 * @param issueID
282 * The Issue or Objective to get the weight from
283 * @return The weight, or 0 if the objective doesn't exist. Only works with
284 * linear utility spaces.
285 */
286 public double getWeight(int issueID)
287 {
288 Objective ob = getDomain().getObjectivesRoot().getObjective(issueID);
289 if (ob != null) {
290 Evaluator ev = fEvaluators.get(ob);
291 if (ev != null) {
292 return ev.getWeight();
293 }
294 }
295
296// System.out.println("Objective of issue #" + issueID + " not found. Weight 0 returned.");
297 return 0.0;
298 }
299
300 public double getWeight(Objective obj) {
301
302 Evaluator ev = fEvaluators.get(obj);
303 if (ev != null) {
304 return ev.getWeight();
305 } else
306 return 0.0;
307 }
308
309 /**
310 * Method used to set the weight of the given objective. Only works if the
311 * objective has been unlockeed.
312 *
313 * @param objective
314 * of which the weights must be set.
315 * @param weight
316 * to which the weight of the objective must be set.
317 * @return the new weight of the issue after normalization.
318 */
319 public double setWeight(Objective objective, double weight) {
320 try {
321 Evaluator ev = fEvaluators.get(objective);
322 double oldWt = ev.getWeight();
323 if (!ev.weightLocked()) {
324 ev.setWeight(weight); // set weight
325 }
326 this.normalizeChildren(objective.getParent());
327 if (this.checkTreeNormalization()) {
328 return fEvaluators.get(objective).getWeight();
329 } else {
330 ev.setWeight(oldWt); // set the old weight back.
331 return fEvaluators.get(objective).getWeight();
332 }
333 } catch (NullPointerException npe) {
334 return -1;
335 }
336 }
337
338 public void setWeights(List<Issue> issues, double[] weights) {
339 try {
340 for (int i = 0; i < issues.size(); i++) {
341 Evaluator ev = fEvaluators.get(issues.get(i));
342 ev.setWeight(weights[i]); // set weight
343 }
344 } catch (NullPointerException npe) {
345 }
346 }
347
348 /**
349 * Helper function, evaluator values need to be normalized
350 */
351 public void normalizeWeights() {
352 double sum = 0.0;
353 for (Objective obj : fEvaluators.keySet()) {
354 sum += fEvaluators.get(obj).getWeight();
355 }
356
357 for (Objective obj : fEvaluators.keySet()) {
358 fEvaluators.get(obj)
359 .setWeight(fEvaluators.get(obj).getWeight() / sum);
360 }
361 }
362
363 /**
364 * @deprecated Use getObjective
365 *
366 * @param index
367 * The index of the issue to
368 * @return the indexed objective or issue
369 */
370 @Deprecated
371 public final Objective getIssue(int index) {
372 return getDomain().getIssues().get(index);
373 }
374
375 /**
376 * Sets an [Objective, evaluator] pair. Replaces old evaluator for
377 * objective.
378 *
379 * @param obj
380 * The Objective to attach an Evaluator to.
381 * @param ev
382 * The Evaluator to attach.
383 * @return The given evaluator.
384 */
385 public final Evaluator addEvaluator(Objective obj, Evaluator ev) {
386 fEvaluators.put(obj, ev);
387 return ev;
388 }
389
390 /**
391 * @return The set with all pairs of evaluators and objectives in this
392 * utility space.
393 */
394 public final Set<Map.Entry<Objective, Evaluator>> getEvaluators() {
395 return fEvaluators.entrySet();
396 }
397
398 /**
399 * Place a lock on the weight of an objective or issue. Mainly used to guide
400 * the normalization procedure.
401 *
402 * @param obj
403 * The objective or issue that is about to have it's weight
404 * locked.
405 * @return <code>true</code> if successful, <code>false</code> If the
406 * objective doesn't have an evaluator yet.
407 */
408 public final boolean lock(Objective obj) {
409 try {
410 fEvaluators.get(obj).lockWeight();
411 } catch (Exception e) {
412 e.printStackTrace();
413 return false;
414 }
415 return true;
416 }
417
418 /**
419 * Clear a lock on the weight of an objective or issue. Mainly used to guide
420 * the normalization procedure.
421 *
422 * @param obj
423 * The objective or issue that is having it's lock cleared.
424 * @return <code>true</code> If the lock is cleared, <code>false</code> if
425 * the objective or issue doesn't have an evaluator yet.
426 */
427 public final boolean unlock(Objective obj) {
428 try {
429 fEvaluators.get(obj).unlockWeight();
430 } catch (Exception e) {
431 e.printStackTrace();
432 return false;
433 }
434 return true;
435 }
436
437 /**
438 * Normalizes the weights of non-locked objectives of the given objective so
439 * that all objective weights they sum up to one.
440 *
441 * @param obj
442 * of which the weights must be normalized.
443 * @return all evaluators using getEvaluators().
444 */
445 public final Set<Map.Entry<Objective, Evaluator>> normalizeChildren(
446 Objective obj) {
447 Enumeration<Objective> childs = obj.children();
448 double RENORMALCORR = 0.05;
449 /*
450 * we add this to all weight sliders to solve the slider-stuck-at-0
451 * problem.
452 */
453 double weightSum = 0;
454 double lockedWeightSum = 0;
455 int freeCount = 0;
456 int lockedCount = 0;
457 while (childs.hasMoreElements()) {
458 Objective tmpObj = childs.nextElement();
459 try {
460 if (!fEvaluators.get(tmpObj).weightLocked()) {
461 weightSum += fEvaluators.get(tmpObj).getWeight();
462 freeCount++;
463 } else {
464 lockedWeightSum += fEvaluators.get(tmpObj).getWeight();
465 lockedCount++;
466 }
467 } catch (Exception e) {
468
469 // do nothing, we can encounter Objectives/issues without
470 // Evaluators.
471 }
472 }
473 if (freeCount + lockedCount == 1) {
474 Enumeration<Objective> singleChild = obj.children();
475 while (singleChild.hasMoreElements()) {
476 Objective tmpObj = singleChild.nextElement();
477 fEvaluators.get(tmpObj).setWeight(1.0);
478 }
479 }
480
481 if (freeCount > 1) {
482 Enumeration<Objective> normalChilds = obj.children();
483 while (normalChilds.hasMoreElements()) {
484 Objective tmpObj = normalChilds.nextElement();
485 double diff = (lockedWeightSum + weightSum) - 1.0;
486 // because of RENORMALCORR, total weight will get larger.
487 double correctedWeightSum = weightSum
488 + RENORMALCORR * freeCount;
489 try {
490
491 if (!fEvaluators.get(tmpObj).weightLocked()) {
492 double currentWeight = fEvaluators.get(tmpObj)
493 .getWeight();
494 double newWeight = currentWeight
495 - (diff * (currentWeight + RENORMALCORR)
496 / correctedWeightSum);
497 if (newWeight < 0) {
498 newWeight = 0;
499 }
500 fEvaluators.get(tmpObj).setWeight(newWeight);
501 }
502 } catch (Exception e) {
503 // do nothing, we can encounter Objectives/issues without
504 // Evaluators.
505 }
506
507 }
508
509 }
510
511 return getEvaluators();
512 }
513
514 /****************** private internal stuff *******************/
515
516 /**
517 * @param filename
518 * The name of the xml file to parse.
519 * @throws IOException
520 * if error occurs, e.g. file not found
521 */
522 protected boolean loadTreeFromFile(String filename) throws IOException {
523 SimpleDOMParser parser = new SimpleDOMParser();
524 BufferedReader file = new BufferedReader(
525 new FileReader(new File(filename)));
526 SimpleElement root = parser.parse(file);
527 return loadTreeRecursive(root);
528 }
529
530 /**
531 * Loads the weights and issues for the evaluators.
532 *
533 * @param root
534 * The current root of the XML structure.
535 * @return true iff error occured
536 */
537 protected boolean loadTreeRecursive(SimpleElement currentRoot) {
538 int nrOfWeights = 0;
539
540 int index;
541 // load reservation value
542 try {
543 if ((currentRoot.getChildByTagName(RESERVATION) != null)
544 && (currentRoot
545 .getChildByTagName(RESERVATION).length > 0)) {
546 SimpleElement xmlReservation = (SimpleElement) (currentRoot
547 .getChildByTagName(RESERVATION)[0]);
548 setReservationValue(
549 Double.valueOf(xmlReservation.getAttribute("value")));
550 }
551 } catch (Exception e) {
552 System.out.println("Utility space has no reservation value");
553 }
554 // load discount factor
555 try {
556 if ((currentRoot.getChildByTagName("discount_factor") != null)
557 && (currentRoot
558 .getChildByTagName("discount_factor").length > 0)) {
559 SimpleElement xmlReservation = (SimpleElement) (currentRoot
560 .getChildByTagName("discount_factor")[0]);
561 double df = Double
562 .parseDouble(xmlReservation.getAttribute("value"));
563 setDiscount(validateDiscount(df));
564 }
565 } catch (Exception e) {
566 System.out.println("Utility space has no discount factor;");
567 }
568
569 Vector<Evaluator> tmpEvaluator = new Vector<Evaluator>();
570 /*
571 * tmp vector with all Evaluators at this level. Used to normalize
572 * weigths.
573 */
574 EVALUATORTYPE evalType;
575 String type, etype;
576 Evaluator lEvaluator = null;
577
578 // Get the weights of the current children
579 Object[] xml_weights = currentRoot.getChildByTagName("weight");
580 nrOfWeights = xml_weights.length; // assuming each
581 HashMap<Integer, Double> tmpWeights = new HashMap<Integer, Double>();
582 for (int i = 0; i < nrOfWeights; i++) {
583 index = Integer.valueOf(
584 ((SimpleElement) xml_weights[i]).getAttribute("index"));
585 Double dval = Double.parseDouble(
586 ((SimpleElement) xml_weights[i]).getAttribute("value"));
587 tmpWeights.put(index, dval);
588 }
589
590 // Collect evaluations for each of the issue values from file.
591 // Assumption: Discrete-valued issues.
592 Object[] xml_issues = currentRoot.getChildByTagName("issue");
593 Object[] xml_objectives = currentRoot.getChildByTagName("objective");
594 Object[] xml_obj_issues = new Object[xml_issues.length
595 + xml_objectives.length];
596 int i_ind;
597 for (i_ind = 0; i_ind < xml_issues.length; i_ind++) {
598 xml_obj_issues[i_ind] = xml_issues[i_ind];
599 }
600 for (int o_ind = 0; (o_ind + i_ind) < xml_obj_issues.length; o_ind++) {
601 xml_obj_issues[(o_ind + i_ind)] = xml_objectives[o_ind];
602 }
603
604 for (int i = 0; i < xml_obj_issues.length; i++) {
605 index = Integer.valueOf(
606 ((SimpleElement) xml_obj_issues[i]).getAttribute("index"));
607 type = ((SimpleElement) xml_obj_issues[i]).getAttribute("type");
608 etype = ((SimpleElement) xml_obj_issues[i]).getAttribute("etype");
609 if (type == null) { // No value type specified.
610 evalType = EVALUATORTYPE.DISCRETE;
611 } else if (type.equals(etype)) {
612 evalType = EVALUATORTYPE.convertToType(type);
613 } else if (type != null && etype == null) {
614 evalType = EVALUATORTYPE.convertToType(type);
615 } else {
616 System.out.println(
617 "Conflicting value types specified for evaluators in utility template file.");
618 evalType = EVALUATORTYPE.convertToType(type);
619 }
620 if (tmpWeights.get(index) != null) {
621 switch (evalType) {
622 case DISCRETE:
623 lEvaluator = new EvaluatorDiscrete();
624 break;
625 case INTEGER:
626 lEvaluator = new EvaluatorInteger();
627 break;
628 case REAL:
629 lEvaluator = new EvaluatorReal();
630 break;
631 case OBJECTIVE:
632 lEvaluator = new EvaluatorObjective();
633 break;
634 }
635 lEvaluator.loadFromXML((SimpleElement) (xml_obj_issues[i]));
636
637 try {
638 fEvaluators.put(
639 getDomain().getObjectivesRoot().getObjective(index),
640 lEvaluator);
641 /*
642 * get the Objective or Issue.
643 */
644 } catch (Exception e) {
645 System.out.println("Domain-utilityspace mismatch");
646 e.printStackTrace();
647 return false;
648 }
649 }
650 try {
651 if (nrOfWeights != 0) {
652 double tmpdwt = tmpWeights.get(index).doubleValue();
653 Objective tmpob = getDomain().getObjectivesRoot()
654 .getObjective(index);
655 fEvaluators.get(tmpob).setWeight(tmpdwt);
656 }
657 } catch (Exception e) {
658 System.out.println(
659 "Evaluator-weight mismatch or no weight for this issue or objective.");
660 }
661 tmpEvaluator.add(lEvaluator); // for normalisation purposes.
662 }
663
664 // Recurse over all children:
665 boolean returnval = false;
666 Object[] objArray = currentRoot.getChildElements();
667 for (int i = 0; i < objArray.length; i++)
668 returnval = loadTreeRecursive((SimpleElement) objArray[i]);
669 return returnval;
670 }
671
672 /**
673 * Adds the utilities (weights) from this utility space to a given domain.
674 * It modifies the currentLevel so the return value is superfluous.
675 *
676 * @param currentLevel
677 * is pointer to a XML tree describing the domain.
678 * @return XML tree with the weights. NOTE: currentLevel is modified anyway.
679 */
680 private SimpleElement toXMLrecurse(SimpleElement currentLevel) {
681 // go through all tags.
682
683 Object[] Objectives = currentLevel.getChildByTagName("objective");
684
685 for (int objInd = 0; objInd < Objectives.length; objInd++) {
686 SimpleElement currentChild = (SimpleElement) Objectives[objInd];
687 int childIndex = Integer
688 .valueOf(currentChild.getAttribute("index"));
689 try {
690 Evaluator ev = fEvaluators.get(getDomain().getObjectivesRoot()
691 .getObjective(childIndex));
692 SimpleElement currentChildWeight = new SimpleElement("weight");
693 currentChildWeight.setAttribute("index", "" + childIndex);
694 currentChildWeight.setAttribute("value", "" + ev.getWeight());
695 currentLevel.addChildElement(currentChildWeight);
696 } catch (Exception e) {
697 // do nothing, not every node has an evaluator.
698 }
699 currentChild = toXMLrecurse(currentChild);
700 }
701
702 Object[] Issues = currentLevel.getChildByTagName("issue");
703
704 for (int issInd = 0; issInd < Issues.length; issInd++) {
705 SimpleElement issueL = (SimpleElement) Issues[issInd];
706
707 // set the weight
708 int childIndex = Integer.valueOf(issueL.getAttribute("index"));
709 Objective tmpEvObj = getDomain().getObjectivesRoot()
710 .getObjective(childIndex);
711 try {
712
713 Evaluator ev = fEvaluators.get(tmpEvObj);
714
715 SimpleElement currentChildWeight = new SimpleElement("weight");
716 currentChildWeight.setAttribute("index", "" + childIndex);
717 currentChildWeight.setAttribute("value", "" + ev.getWeight());
718 currentLevel.addChildElement(currentChildWeight);
719
720 String evtype_str = issueL.getAttribute("etype");
721 EVALUATORTYPE evtype = EVALUATORTYPE.convertToType(evtype_str);
722 switch (evtype) {
723 case DISCRETE:
724 // fill this issue with the relevant weights to items.
725 Object[] items = issueL.getChildByTagName("item");
726 for (int itemInd = 0; itemInd < items.length; itemInd++) {
727 IssueDiscrete theIssue = (IssueDiscrete) getDomain()
728 .getObjectivesRoot().getObjective(childIndex);
729
730 EvaluatorDiscrete dev = (EvaluatorDiscrete) ev;
731 Double eval = dev
732 .getDoubleValue(theIssue.getValue(itemInd));
733 ((SimpleElement) items[itemInd])
734 .setAttribute("evaluation", "" + eval);
735 }
736 break;
737 case INTEGER:
738 EvaluatorInteger iev = (EvaluatorInteger) ev;
739 issueL.setAttribute("lowerbound", "" + iev.getLowerBound());
740 issueL.setAttribute("upperbound", "" + iev.getUpperBound());
741
742 SimpleElement thisIntEval = new SimpleElement("evaluator");
743 thisIntEval.setAttribute("ftype", "linear");
744 thisIntEval.setAttribute("slope", "" + iev.getSlope());
745 thisIntEval.setAttribute("offset", "" + iev.getOffset());
746 issueL.addChildElement(thisIntEval);
747 break;
748 case REAL:
749 EvaluatorReal rev = (EvaluatorReal) ev;
750 SimpleElement thisRealEval = new SimpleElement("evaluator");
751 EVALFUNCTYPE revtype = rev.getFuncType();
752 if (revtype == EVALFUNCTYPE.LINEAR) {
753 thisRealEval.setAttribute("ftype", "linear");
754 thisRealEval.setAttribute("parameter1",
755 "" + rev.getLinearParam());
756 } else if (revtype == EVALFUNCTYPE.CONSTANT) {
757 thisRealEval.setAttribute("ftype", "constant");
758 thisRealEval.setAttribute("parameter0",
759 "" + rev.getConstantParam());
760 }
761 issueL.addChildElement(thisRealEval);
762 break;
763 }
764 } catch (Exception e) {
765 // do nothing, it could be that this objective/issue doesn't
766 // have an evaluator yet.
767 }
768
769 }
770
771 return currentLevel;
772 }
773
774 /**
775 * createFrom a default evaluator for a given Objective. This function is
776 * placed here, and not in Objective, because the Objectives should not be
777 * loaded with utility space functionality. The price we pay for that is
778 * that we now have an ugly switch inside the code, losing some modularity.
779 *
780 * @param obj
781 * the objective to createFrom an evaluator for
782 * @return the default evaluator
783 */
784 private Evaluator defaultEvaluator(Objective obj) {
785 if (obj.isObjective())
786 return new EvaluatorObjective();
787 // if not an objective then it must be an issue.
788 switch (((Issue) obj).getType()) {
789 case DISCRETE:
790 return new EvaluatorDiscrete();
791 case INTEGER:
792 return new EvaluatorInteger();
793 case REAL:
794 return new EvaluatorReal();
795 default:
796 System.out.println("INTERNAL ERROR: issue of type "
797 + ((Issue) obj).getType() + "has no default evaluator");
798 }
799 return null;
800 }
801
802 /**
803 * Checks the normalization throughout the tree. Will eventually replace
804 * checkNormalization
805 *
806 * @return true if the weigths are indeed normalized, false if they aren't.
807 */
808 private boolean checkTreeNormalization() {
809 return checkTreeNormalizationRecursive(getDomain().getObjectivesRoot());
810 }
811
812 /**
813 * Private helper function to check the normalisation throughout the tree.
814 *
815 * @param currentRoot
816 * The current parent node of the subtree we are going to check
817 * @return True if the weights are indeed normalized, false if they aren't.
818 */
819 private boolean checkTreeNormalizationRecursive(Objective currentRoot) {
820 boolean normalised = true;
821 double lSum = 0;
822
823 Enumeration<Objective> children = currentRoot.children();
824
825 while (children.hasMoreElements() && normalised) {
826
827 Objective tmpObj = children.nextElement();
828 lSum += (fEvaluators.get(tmpObj)).getWeight();
829
830 }
831 return (normalised && lSum > .98 && lSum < 1.02);
832 }
833
834 public Map<Objective, Evaluator> getfEvaluators() {
835 return fEvaluators;
836 }
837}
Note: See TracBrowser for help on using the repository browser.