source: geniuswebcore/test/geniusweb/profile/utilityspace/LinearAdditiveTest2.py@ 75

Last change on this file since 75 was 73, checked in by Bart Vastenhouw, 3 years ago

Fix for IssueValue hashcode.

File size: 8.8 KB
Line 
1from decimal import Decimal
2import json
3from pathlib import Path
4from typing import Dict
5import unittest
6
7from pyson.ObjectMapper import ObjectMapper
8# from unitpy.GeneralTests import GeneralTests
9
10from geniusweb.issuevalue.Bid import Bid
11from geniusweb.issuevalue.DiscreteValue import DiscreteValue
12from geniusweb.issuevalue.DiscreteValueSet import DiscreteValueSet
13from geniusweb.issuevalue.Domain import Domain
14from geniusweb.issuevalue.NumberValue import NumberValue
15from geniusweb.issuevalue.ValueSet import ValueSet
16from geniusweb.profile.Profile import Profile
17from geniusweb.profile.utilityspace.DiscreteValueSetUtilities import DiscreteValueSetUtilities
18from geniusweb.profile.utilityspace.LinearAdditiveUtilitySpace import LinearAdditiveUtilitySpace
19from geniusweb.profile.utilityspace.ValueSetUtilities import ValueSetUtilities
20
21
22class LinearAdditiveTest(unittest.TestCase): #, GeneralTests[LinearAdditiveUtilitySpace]):
23 pyson=ObjectMapper()
24
25 yesno = DiscreteValueSet([DiscreteValue("yes"), DiscreteValue("no")])
26 leasecarvals = yesno
27 permcontractvals = yesno
28 carreervals=DiscreteValueSet([DiscreteValue("low"),DiscreteValue("medium"),DiscreteValue("high")])
29 ftevals=DiscreteValueSet([DiscreteValue("0.6"),DiscreteValue("0.8"),DiscreteValue("1.0")])
30 salaryvals=DiscreteValueSet([DiscreteValue("2000"),DiscreteValue("2500"),
31 DiscreteValue("3000"),DiscreteValue("3500"),DiscreteValue("4000")])
32 workfromhomevals=DiscreteValueSet([DiscreteValue("0"),DiscreteValue("1"),DiscreteValue("2")])
33
34 jobsdomain = Domain("jobs", {"lease car":leasecarvals, "permanent contract":permcontractvals, \
35 "career development opportunities":carreervals, "fte":ftevals, \
36 "salary": salaryvals, "work from home": workfromhomevals })
37 N0=Decimal("0")
38 N1=Decimal("1")
39 N025=Decimal("0.25")
40 N03=Decimal("0.3")
41 N05=Decimal("0.5")
42 N075=Decimal("0.75")
43
44 leasevarutils = DiscreteValueSetUtilities({DiscreteValue("no"):N0, DiscreteValue("yes"):N1})
45 leasevarutils2 = DiscreteValueSetUtilities({DiscreteValue("no"):N0, DiscreteValue("yes"):N075})
46 permcontrutils = DiscreteValueSetUtilities({DiscreteValue("no"):N0, DiscreteValue("yes"):N1})
47 carreerutils = DiscreteValueSetUtilities({DiscreteValue("high"):N1,DiscreteValue("low"):N0,DiscreteValue("medium"):N05})
48 fteutils = DiscreteValueSetUtilities({DiscreteValue("1.0"):N075,DiscreteValue("0.6"):N025,DiscreteValue("0.8"):N05})
49 salaryutils = DiscreteValueSetUtilities({DiscreteValue("4000"):N1,DiscreteValue("2500"):N025,DiscreteValue("3500"):N075,
50 DiscreteValue("2000"):N0,DiscreteValue("3000"):N03})
51 fromhomeutils = DiscreteValueSetUtilities({DiscreteValue("1"):N05,DiscreteValue("2"):Decimal("0.666666666666"),
52 DiscreteValue("0"):Decimal("0.333333333")})
53 utils:Dict[str, ValueSetUtilities] = {'lease car': leasevarutils, 'permanent contract':permcontrutils, 'career development opportunities': carreerutils,
54 'fte':fteutils, 'salary':salaryutils, 'work from home':fromhomeutils }
55 utils2:Dict[str, ValueSetUtilities] = {'lease car': leasevarutils2, 'permanent contract':permcontrutils, 'career development opportunities': carreerutils,
56 'fte':fteutils, 'salary':salaryutils, 'work from home':fromhomeutils }
57 weights:Dict[str, Decimal] = {"lease car":Decimal("0.06"),"permanent contract":Decimal("0.16"),
58 "career development opportunities":Decimal("0.04"),"fte":Decimal("0.32"),
59 "salary":Decimal("0.24"),"work from home":Decimal("0.18")}
60 weights2:Dict[str, Decimal] = {"lease car":Decimal("0.06"),"permanent contract":Decimal("0.16"),
61 "career development opportunities":Decimal("0.05"),"fte":Decimal("0.31"),
62 "salary":Decimal("0.24"),"work from home":Decimal("0.18")}
63
64 jobs=LinearAdditiveUtilitySpace(jobsdomain, "jobs1",utils, weights )
65 jobs1=LinearAdditiveUtilitySpace(jobsdomain, "jobs1",utils, weights )
66 jobs2=LinearAdditiveUtilitySpace(jobsdomain, "jobs2",utils, weights )
67 jobs3=LinearAdditiveUtilitySpace(jobsdomain, "jobs",utils2, weights )
68 jobs4=LinearAdditiveUtilitySpace(jobsdomain, "jobs",utils, weights2 )
69
70 # A real jobs profile from profiles server
71 # "reservationBid":null was added because toJson will also add this (even though it's the default value)
72 jobsstr = '{"LinearAdditiveUtilitySpace":{"issueUtilities":{' \
73 + '"lease car":{"DiscreteValueSetUtilities":{"valueUtilities":{"no":0,"yes":1}}},' \
74 + '"permanent contract":{"DiscreteValueSetUtilities":{"valueUtilities":{"no":0,"yes":1}}},' \
75 + '"career development opportunities":{"DiscreteValueSetUtilities":{"valueUtilities":{"high":1,"low":0,"medium":0.5}}},' \
76 + '"fte":{"DiscreteValueSetUtilities":{"valueUtilities":{"1.0":0.75,"0.6":0.25,"0.8":0.5}}},' \
77 + '"salary":{"DiscreteValueSetUtilities":{"valueUtilities":{"4000":1,"2500":0.25,"3500":0.75,"2000":0,"3000":0.3}}},' \
78 + '"work from home":{"DiscreteValueSetUtilities":{"valueUtilities":{"1":0.5,"2":0.666666666666,"0":0.333333333}}}},' \
79 + '"issueWeights":{"lease car":0.06,"permanent contract":0.16,' \
80 + '"career development opportunities":0.04,"fte":0.32,"salary":0.24,"work from home":0.18},' \
81 + '"domain":{"name":"jobs","issuesValues":{"lease car":{"values":["yes","no"]},"permanent contract":{"values":["yes","no"]},"career development opportunities":{"values":["low","medium","high"]},"fte":{"values":["0.6","0.8","1.0"]},"salary":{"values":["2000","2500","3000","3500","4000"]},"work from home":{"values":["0","1","2"]}}},'\
82 + '"name":"jobs1", "reservationBid":null}}'
83
84 jobsjson = json.loads(jobsstr)
85
86 partystr='{"LinearAdditiveUtilitySpace":{"domain":{"name":"party","issuesValues":{"Invitations":{"values":["Plain","Photo","Custom, Handmade","Custom, Printed"]},"Music":{"values":["MP3","DJ","Band"]},"Drinks":{"values":["Non-Alcoholic","Beer Only","Handmade Cocktails","Catering"]},"Cleanup":{"values":["Water and Soap","Specialized Materials","Special Equiment","Hired Help"]},"Food":{"values":["Chips and Nuts","Finger-Food","Handmade Food","Catering"]},"Location":{"values":["Party Tent","Your Dorm","Party Room","Ballroom"]}}},"name":"party1","issueUtilities":{"Invitations":{"DiscreteValueSetUtilities":{"valueUtilities":{"Plain":0.24,"Custom, Printed":0.48,"Photo":0.74,"Custom, Handmade":1}}},"Music":{"DiscreteValueSetUtilities":{"valueUtilities":{"DJ":0.99,"Band":0.35,"MP3":0.65}}},"Drinks":{"DiscreteValueSetUtilities":{"valueUtilities":{"Handmade Cocktails":0.672,"Non-Alcoholic":0.263,"Beer Only":0.98,"Catering":0.334}}},"Cleanup":{"DiscreteValueSetUtilities":{"valueUtilities":{"Special Equiment":0.32,"Water and Soap":0.65,"Specialized Materials":0.96,"Hired Help":0.31}}},"Food":{"DiscreteValueSetUtilities":{"valueUtilities":{"Finger-Food":0.52,"Handmade Food":0.51,"Catering":0.25,"Chips and Nuts":0.75}}},"Location":{"DiscreteValueSetUtilities":{"valueUtilities":{"Your Dorm":0.23,"Ballroom":0.77,"Party Room":0.99,"Party Tent":0.52}}}},"issueWeights":{"Invitations":0.05,"Music":0.19,"Drinks":0.28,"Cleanup":0.10,"Food":0.19,"Location":0.19},"reservationBid":null}}'
87 partyjson = json.loads(partystr)
88
89 def testSerialize(self):
90 print(self.pyson.toJson(self.jobs))
91 self.maxDiff=None
92 self.assertEqual(self.jobsjson, self.pyson.toJson(self.jobs))
93
94 def testDeserialize(self):
95 self.assertEqual(self.jobs, self.pyson.parse(self.jobsjson, Profile))
96
97 def testDeserializeJapanTrip(self):
98 serialized = Path("test/resources/japantrip1.json").read_text("utf-8")
99 jsonobj=json.loads(serialized)
100 profile:Profile = self.pyson.parse(jsonobj, Profile);
101 self.assertEquals("japantrip1", profile.getName())
102 self.assertEquals("japantrip", profile.getDomain().getName())
103
104 def testDeserializeParty1(self):
105 print( str(self.pyson.parse(self.partyjson, Profile)))
106
107 def testEquals(self):
108 self.assertEqual(self.jobs,self.jobs1)
109 self.assertEqual(hash(self.jobs),hash(self.jobs1))
110 self.assertNotEqual(self.jobs,self.jobs2)
111 self.assertNotEqual(hash(self.jobs),hash(self.jobs2))
112 self.assertNotEqual(self.jobs,self.jobs3)
113 self.assertNotEqual(hash(self.jobs),hash(self.jobs3))
114 self.assertNotEqual(self.jobs,self.jobs4)
115 self.assertNotEqual(hash(self.jobs),hash(self.jobs4))
116
117
118 def testUtil(self):
119 bid=Bid({"lease car":DiscreteValue("yes"), "permanent contract":DiscreteValue("yes"), \
120 "career development opportunities": DiscreteValue("low"), \
121 "fte": DiscreteValue("0.8"), "salary":DiscreteValue("2500"), "work from home": DiscreteValue("1") });
122 # 0.06 * 1 + 0.16 * 1 + 0.04 * 0 + 0.32 * 0.5 + 0.24 * 0.25 + 0.18 * 0.5
123 self.assertEqual(Decimal("0.53"), self.jobs.getUtility(bid))
Note: See TracBrowser for help on using the repository browser.