1 | from copy import copy
|
---|
2 | from decimal import Decimal
|
---|
3 | from typing import Dict, cast, Optional
|
---|
4 |
|
---|
5 | from pyson.JsonGetter import JsonGetter
|
---|
6 |
|
---|
7 | from geniusweb.issuevalue.DiscreteValue import DiscreteValue
|
---|
8 | from geniusweb.issuevalue.DiscreteValueSet import DiscreteValueSet
|
---|
9 | from geniusweb.issuevalue.Value import Value
|
---|
10 | from geniusweb.issuevalue.ValueSet import ValueSet
|
---|
11 | from geniusweb.profile.utilityspace.ValueSetUtilities import ValueSetUtilities
|
---|
12 | from geniusweb.utils import toStr
|
---|
13 |
|
---|
14 |
|
---|
15 | class DiscreteValueSetUtilities (ValueSetUtilities) :
|
---|
16 | '''
|
---|
17 | Links a set of values to utilities for that value. Does not link to some
|
---|
18 | issue so may need further checking when used for an actual issue. Constructor
|
---|
19 | guarantees that
|
---|
20 | <ul>
|
---|
21 | <li>All values in the provided map (the utilities) are in [0,1]
|
---|
22 | <li>All keys are proper {@link DiscreteValue}s
|
---|
23 | </ul>
|
---|
24 | '''
|
---|
25 |
|
---|
26 | def __init__(self, valueUtilities: Dict[DiscreteValue, Decimal] ):
|
---|
27 | '''
|
---|
28 | create new object based on the given mapping from values to utilities.
|
---|
29 |
|
---|
30 | @param valueUtils map with key {@link DiscreteValue}s and value a Double
|
---|
31 | in the range [0,1].
|
---|
32 | @throws NullPointerException if one of the args is null
|
---|
33 | @throws IllegalArgumentException if values are not in range [0,1].
|
---|
34 |
|
---|
35 | '''
|
---|
36 |
|
---|
37 | if valueUtilities == None:
|
---|
38 | raise ValueError("valueUtils==null")
|
---|
39 |
|
---|
40 | if None in valueUtilities.keys():
|
---|
41 | raise ValueError("one of the keys in valueUtils is null")
|
---|
42 |
|
---|
43 | for v in valueUtilities.values():
|
---|
44 | if v==None or v<Decimal("0") or v>Decimal("1"):
|
---|
45 | raise ValueError("Weights in valueUtils must all be in [0,1]")
|
---|
46 |
|
---|
47 | self._valueUtilities = copy(valueUtilities);
|
---|
48 |
|
---|
49 | #Override
|
---|
50 | def getUtility(self, value:Optional[Value]) -> Decimal:
|
---|
51 | if not value in self._valueUtilities:
|
---|
52 | return Decimal("0")
|
---|
53 | return self._valueUtilities[value] # type: ignore
|
---|
54 |
|
---|
55 | @JsonGetter("valueUtilities")
|
---|
56 | def getUtilities(self) -> Dict[DiscreteValue, Decimal] :
|
---|
57 | '''
|
---|
58 | @return copy of the value-utility pair map.
|
---|
59 | '''
|
---|
60 | return copy(self._valueUtilities)
|
---|
61 |
|
---|
62 |
|
---|
63 | #Override
|
---|
64 | def isFitting(self, valueset:ValueSet ) ->str:
|
---|
65 | if not isinstance(valueset, DiscreteValueSet):
|
---|
66 | return "The utilities are for a discrete valueset but the given values are "\
|
---|
67 | + str(valueset);
|
---|
68 |
|
---|
69 | discvalueset = cast(DiscreteValueSet, valueset)
|
---|
70 | if self._valueUtilities.keys() != set(discvalueset.getValues()):
|
---|
71 | return "The values in the set " + str(valueset) \
|
---|
72 | + " do not match the values mapped to utilities " \
|
---|
73 | + str(self._valueUtilities.keys());
|
---|
74 | return cast(str,None)
|
---|
75 |
|
---|
76 | def __repr__(self):
|
---|
77 | return "DiscreteValueSetUtilities" + toStr(self._valueUtilities)
|
---|
78 |
|
---|
79 |
|
---|
80 | def __hash__(self):
|
---|
81 | return hash(tuple(self._valueUtilities.items()))
|
---|
82 |
|
---|
83 | def __eq__(self, other):
|
---|
84 | return isinstance(other, self.__class__) and \
|
---|
85 | self._valueUtilities == other._valueUtilities
|
---|
86 |
|
---|