[84] | 1 | from decimal import Decimal
|
---|
| 2 | from typing import Dict, List
|
---|
| 3 | import unittest
|
---|
| 4 | from unittest.mock import Mock
|
---|
| 5 |
|
---|
| 6 | from tudelft.utilities.immutablelist.Range import Range
|
---|
| 7 |
|
---|
| 8 | from geniusweb.bidspace.pareto.GenericPareto import GenericPareto
|
---|
| 9 | from geniusweb.issuevalue.Bid import Bid
|
---|
| 10 | from geniusweb.issuevalue.DiscreteValue import DiscreteValue
|
---|
| 11 | from geniusweb.issuevalue.DiscreteValueSet import DiscreteValueSet
|
---|
| 12 | from geniusweb.issuevalue.Domain import Domain
|
---|
| 13 | from geniusweb.issuevalue.NumberValue import NumberValue
|
---|
| 14 | from geniusweb.issuevalue.NumberValueSet import NumberValueSet
|
---|
| 15 | from geniusweb.issuevalue.Value import Value
|
---|
| 16 | from geniusweb.issuevalue.ValueSet import ValueSet
|
---|
| 17 | from geniusweb.profile.PartialOrdering import PartialOrdering
|
---|
| 18 |
|
---|
| 19 |
|
---|
| 20 | class GenericParetoTest(unittest.TestCase):
|
---|
| 21 | I1V2 = DiscreteValue("i1v2")
|
---|
| 22 | I1V1 = DiscreteValue("i1v1")
|
---|
| 23 | I2V1 = NumberValue(Decimal("2.00"))
|
---|
| 24 | I2V2 = NumberValue(Decimal("2.45"))
|
---|
| 25 | I2V3 = NumberValue(Decimal("2.90"))
|
---|
| 26 | DOMAINNAME = "testdomain"
|
---|
| 27 | ISSUE1 = "issue1"
|
---|
| 28 | ISSUE2 = "issue2"
|
---|
| 29 | issues:Dict[str, ValueSet] = {}
|
---|
| 30 |
|
---|
| 31 | def setUp(self):
|
---|
| 32 | discretevalues1 = []
|
---|
| 33 | discretevalues1.append(self.I1V1)
|
---|
| 34 | discretevalues1.append(self.I1V2)
|
---|
| 35 | values1 = DiscreteValueSet(discretevalues1)
|
---|
| 36 | self.issues[self.ISSUE1] = values1
|
---|
| 37 |
|
---|
| 38 | values2 = NumberValueSet(Range(Decimal(2), Decimal(3), Decimal("0.45")))
|
---|
| 39 | self.issues[self.ISSUE2] = values2
|
---|
| 40 |
|
---|
| 41 | self.domain = Domain(self.DOMAINNAME, self.issues)
|
---|
| 42 |
|
---|
| 43 | issuevalues:Dict[str, Value] = {}
|
---|
| 44 | issuevalues[self.ISSUE1] = self.I1V1
|
---|
| 45 | issuevalues[self.ISSUE2] = self.I2V1
|
---|
| 46 | self.bid1 = Bid(issuevalues)
|
---|
| 47 | issuevalues[self.ISSUE1] = self.I1V1
|
---|
| 48 | issuevalues[self.ISSUE2] = self.I2V2
|
---|
| 49 | self.bid2 = Bid(issuevalues)
|
---|
| 50 | issuevalues[self.ISSUE1] = self.I1V2
|
---|
| 51 | issuevalues[self.ISSUE2] = self.I2V1
|
---|
| 52 | self.bid3 = Bid(issuevalues)
|
---|
| 53 |
|
---|
| 54 | self.profile1 = Mock(PartialOrdering)
|
---|
| 55 | self.profile2 = Mock(PartialOrdering)
|
---|
| 56 | self.profile3 = Mock(PartialOrdering)
|
---|
| 57 | self.profile1.getDomain = Mock(return_value=self.domain)
|
---|
| 58 | self.profile2.getDomain = Mock(return_value=self.domain)
|
---|
| 59 | self.profile3.getDomain = Mock(return_value=self.domain)
|
---|
| 60 |
|
---|
| 61 | self.pareto = GenericPareto([self.profile1, self.profile2])
|
---|
| 62 |
|
---|
| 63 | def testgenericParetoTest(self):
|
---|
| 64 |
|
---|
| 65 | # fefault: there is no preference at all, all isPreferredOrEqual
|
---|
| 66 | # returns false and we can't remove pareto points.
|
---|
| 67 |
|
---|
| 68 | profiles:List[PartialOrdering] = [self.profile1, self.profile2]
|
---|
| 69 | # In python we need to set also False values
|
---|
| 70 | self.profile1.isPreferredOrEqual = Mock(return_value=False)
|
---|
| 71 | self.profile2.isPreferredOrEqual = Mock(return_value=False)
|
---|
| 72 | pareto = GenericPareto(profiles)
|
---|
| 73 |
|
---|
| 74 | points = pareto.getPoints()
|
---|
| 75 | self.assertEqual(6, len(points))
|
---|
| 76 |
|
---|
| 77 | def testgenericParetoTest1(self):
|
---|
| 78 |
|
---|
| 79 | # both prefer bid1 over any other bid.
|
---|
| 80 | self.profile1.isPreferredOrEqual.side_effect = \
|
---|
| 81 | lambda b1, b2: b1 == self.bid1
|
---|
| 82 | self.profile2.isPreferredOrEqual.side_effect = \
|
---|
| 83 | lambda b1, b2: b1 == self.bid1
|
---|
| 84 |
|
---|
| 85 | points = self.pareto.getPoints()
|
---|
| 86 | self.assertEqual(1, len(points))
|
---|
| 87 | self.assertEqual(self.bid1, next(iter(points)))
|
---|
| 88 |
|
---|
| 89 | def testgenericParetoTest2(self):
|
---|
| 90 |
|
---|
| 91 | # both prefer bid2 over any other bid.
|
---|
| 92 | self.profile1.isPreferredOrEqual.side_effect = \
|
---|
| 93 | lambda b1, b2: b1 == self.bid2
|
---|
| 94 | self.profile2.isPreferredOrEqual.side_effect = \
|
---|
| 95 | lambda b1, b2: b1 == self.bid2
|
---|
| 96 |
|
---|
| 97 | points = self.pareto.getPoints()
|
---|
| 98 | # since both prefer bid2, bid is pareto point.
|
---|
| 99 | self.assertEqual(1, len(points))
|
---|
| 100 | self.assertEqual(self.bid2, next(iter(points)))
|
---|
| 101 |
|
---|
| 102 | def testgenericParetoTest3(self):
|
---|
| 103 | # profile1 prefers bid1, profile2 prefers bid2.
|
---|
| 104 | # now neither bid1 nor bid2 are dominating each other
|
---|
| 105 | # and nor does bid1 or bid2 dominate anything else.
|
---|
| 106 | self.profile1.isPreferredOrEqual.side_effect = \
|
---|
| 107 | lambda b1, b2: b1 == self.bid1
|
---|
| 108 | self.profile2.isPreferredOrEqual.side_effect = \
|
---|
| 109 | lambda b1, b2: b1 == self.bid2
|
---|
| 110 |
|
---|
| 111 | points = self.pareto.getPoints()
|
---|
| 112 | # since both prefer bid2, bid is pareto point.
|
---|
| 113 | self.assertEquals(6, len(points))
|
---|
| 114 |
|
---|
| 115 | def testgenericParetoTest4(self):
|
---|
| 116 |
|
---|
| 117 | # profile1 prefers bid1, profile2 prefers bid2.
|
---|
| 118 | # but they both hate bid3.
|
---|
| 119 | self.profile1.isPreferredOrEqual.side_effect = \
|
---|
| 120 | lambda b1, b2: b1 == self.bid1 or b2 == self.bid3
|
---|
| 121 | self.profile2.isPreferredOrEqual.side_effect = \
|
---|
| 122 | lambda b1, b2: b2 == self.bid3 or b1 == self.bid2
|
---|
| 123 |
|
---|
| 124 | points = self.pareto.getPoints()
|
---|
| 125 | # both hate bid3 but don't agree on bid1/2. bid3 is ruled out.
|
---|
| 126 | self.assertEqual(5, len(points))
|
---|
| 127 |
|
---|
| 128 | def testNullNotOk(self):
|
---|
| 129 | self.assertRaises(ValueError,
|
---|
| 130 | lambda:GenericPareto([self.profile1, None, self.profile1]))
|
---|
| 131 |
|
---|
| 132 | def testImmutable(self):
|
---|
| 133 | list = [self.profile1, self.profile2]
|
---|
| 134 | pareto = GenericPareto(list)
|
---|
| 135 | # if we modify the list, the pareto should not change
|
---|
| 136 | list.append(self.profile3)
|
---|
| 137 | self.assertEqual(2, len(pareto.getProfiles()))
|
---|
| 138 |
|
---|
| 139 | # in python we just copy the list so adding should do nothing
|
---|
| 140 | def testGetParetoAndAdd(self):
|
---|
| 141 | list = self.pareto.getProfiles()
|
---|
| 142 | list.append(self.profile3)
|
---|
| 143 | self.assertEqual(2, len(self.pareto.getProfiles()))
|
---|
| 144 |
|
---|
| 145 | def testGetPointsAndAdd(self):
|
---|
| 146 | self.assertEqual(1, len(self.pareto.getPoints()))
|
---|
| 147 | list = self.pareto.getPoints()
|
---|
| 148 | list.add(self.bid1)
|
---|
| 149 | self.assertEqual(1, len(self.pareto.getPoints()))
|
---|