source: geniuswebcore/geniusweb/profile/utilityspace/NumberValueSetUtilities.py@ 62

Last change on this file since 62 was 59, checked in by Wouter Pasman, 3 years ago

#44 manual commit of first public release, because this will cause the dist directory to move

File size: 4.0 KB
Line 
1from decimal import Decimal, ROUND_HALF_UP
2from typing import cast, Optional
3
4from geniusweb.issuevalue.NumberValue import NumberValue
5from geniusweb.issuevalue.NumberValueSet import NumberValueSet
6from geniusweb.issuevalue.Value import Value
7from geniusweb.issuevalue.ValueSet import ValueSet
8from geniusweb.profile.utilityspace.ValueSetUtilities import ValueSetUtilities
9
10
11class NumberValueSetUtilities (ValueSetUtilities ):
12 '''
13 The low and high values (from a {@link NumberValueSet} are given each a
14 different utility. This linearly interpolates in-between utility values.
15 '''
16
17
18 def __init__(self, lowValue:Decimal,\
19 lowUtility:Decimal, highValue: Decimal, highUtility:Decimal) :
20 '''
21 @param lowValue the low value of the {@link Range}
22 @param lowUtility the utility of the {@link #lowValue}
23 @param highValue the high value of the {@link Range}. Must be
24 >lowValue.
25 @param highUtility the utility of the {@link #highValue}
26 '''
27 if lowValue == None or highValue == None or lowUtility == None \
28 or highUtility == None :
29 raise ValueError(\
30 "arguments lowValue, lowUtility, highValue and highUtility must be non-null");
31
32 if not self._isInZeroOne(lowUtility):
33 raise ValueError("lowUtility must be in [0,1]")
34
35 if not self._isInZeroOne(highUtility):
36 raise ValueError("highUtility must be in [0,1]")
37
38 if highValue<=lowValue:
39 raise ValueError("highValue must be > lowValue")
40
41 self._lowValue = lowValue
42 self._highValue = highValue
43 self._lowUtility = lowUtility
44 self._highUtility = highUtility
45
46 #Override
47 def getUtility(self, value:Value ) -> Decimal :
48 if not isinstance(value, NumberValue):
49 return Decimal("0");
50
51 x:Decimal = value.getValue()
52 if x<self._lowValue or x>self._highValue:
53 return Decimal("0")
54 # we need to be careful to avoid round errors from divides.
55 # so we return lowU + deltaU * (x-lowV) /deltaV
56 deltaU:Decimal = self._highUtility- self._lowUtility
57 deltaV:Decimal = self._highValue-self._lowValue
58
59 return (self._lowUtility + deltaU *(x-self._lowValue)/deltaV )\
60 .quantize(Decimal('1.00000000'), rounding=ROUND_HALF_UP)
61
62
63 #Override
64 def isFitting(self, valueset: ValueSet ) -> Optional[str]:
65 if not isinstance(valueset, NumberValueSet):
66 return "The utilities are for a number valueset but the given values are "\
67 + str(valueset);
68
69 numvalset= cast(NumberValueSet, valueset)
70 if numvalset.getRange().getLow() != self._lowValue:
71 return "the utilities are specified down to " + str(self._lowValue) \
72 + " but the valueset starts at " \
73 + str(numvalset.getRange().getLow())
74
75 if numvalset.getRange().getHigh() != self._highValue:
76 return "the utilities are specified up to " + str(self._highValue) \
77 + " but the valueset ends at " \
78 + str(numvalset.getRange().getHigh())
79 return None
80
81 def getLowValue(self) -> Decimal :
82 '''
83 @return the lowest value
84 '''
85 return self._lowValue;
86
87
88 def getHighValue(self) ->Decimal :
89 '''
90 @return the highest value
91 '''
92 return self._highValue
93
94 def getLowUtility(self) ->Decimal :
95 '''
96 @return the utility of the lowest value
97 '''
98 return self._lowUtility;
99
100 def getHighUtility(self) ->Decimal:
101 '''
102 @return the utility of the highest value
103 '''
104 return self._highUtility
105
106 def __repr__(self):
107 return "NumberValueSetUtilities[" + str(self._lowValue) + "->" + str(self._lowUtility) + "," \
108 + str(self._highValue) + "->" + str(self._highUtility) + "]"
109
110 def __hash__(self):
111 return hash((self._lowUtility, self._lowValue,self._highUtility, self._highValue))
112
113 def __eq__(self, other):
114 return isinstance(other, self.__class__) \
115 and self._highUtility == other._highUtility \
116 and self._highValue == other._highValue \
117 and self._lowUtility == other._lowUtility \
118 and self._lowValue == other._lowValue
119
120 def _isInZeroOne(self , value:Decimal) -> bool:
121 '''
122 Check if value is in range [0,1]
123
124 @param value
125 @return true if in range.
126 '''
127 return value >= Decimal("0") and value <= Decimal("1")
128
Note: See TracBrowser for help on using the repository browser.