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()))
|
---|