source: src/main/java/negotiator/boaframework/opponentmodel/nash/IssueEvaluationDiscrete.java

Last change on this file was 127, checked in by Wouter Pasman, 6 years ago

#41 ROLL BACK of rev.126 . So this version is equal to rev. 125

File size: 8.9 KB
Line 
1package negotiator.boaframework.opponentmodel.nash;
2
3import java.util.HashMap;
4import java.util.List;
5import java.util.Map.Entry;
6
7import genius.core.issue.IssueDiscrete;
8import genius.core.issue.Value;
9import genius.core.issue.ValueDiscrete;
10
11/**
12 * The IssueEvaluationDiscrete class evaluates an issue. It keeps track of the frequency with which the evaluated
13 * negotiator picks values, and bases the importance of the values on this.
14 *
15 * The class uses two hashmaps, which are constantly up to date:
16 * - The list with the chosen frequency per value.
17 * - The list of normalized weights based on the frequencies.
18 *
19 * @author Roland van der Linden
20 *
21 */
22public class IssueEvaluationDiscrete extends AIssueEvaluation
23{
24 // ********************************
25 // Fields
26 // ********************************
27
28 //This hashmap holds the number of times a certain value has been chosen.
29 //Each value of an issue is represented by a String (must be unique).
30 protected HashMap<String, Integer> valueFrequencyMap;
31 //This hashmap holds the normalized estimated weights of the values in the issue.
32 //This is based on the number of times a value has been chosen, relative to the number
33 //of times a choice was made. So presumably, the more often a value is chosen,
34 //the more preferable it is.
35 //Values range in between 1 and 0, with the most important value having weight 1.
36 //Note that the weight of a value is UNRELATED to the weight of the issue itself (in this class).
37 //Each value of an issue is represented by a String (must be unique).
38 private HashMap<String, Double> normalizedValueWeightMap;
39
40
41 // ********************************
42 // Constructor & init
43 // ********************************
44
45 /**
46 * This constructs the IssueEvaluationDiscrete. You need to
47 * provide the IssueDiscrete which needs to be evaluated so we can
48 * initialize the corresponding fields.
49 * @param issueD The issueDiscrete that needs to be evaluated. May not be null.
50 */
51 public IssueEvaluationDiscrete(IssueDiscrete issueD)
52 {
53 super(issueD);
54
55 this.initValueFrequencyMap();
56 this.initValueWeightMap();
57 }
58
59 /**
60 * This method will initialize the valueFrequencyMap. We insert a representing string
61 * for each value in the issue. We also set the frequency of each value to zero.
62 */
63 protected void initValueFrequencyMap()
64 {
65 List<ValueDiscrete> discreteValues = this.getIssueDiscrete().getValues();
66 this.valueFrequencyMap = new HashMap<String, Integer>(discreteValues.size());
67
68 //Get all possible values of the discrete issue and give all of them frequency zero.
69 for(ValueDiscrete vd : discreteValues)
70 this.valueFrequencyMap.put(vd.getValue(), 0);
71 }
72
73 /**
74 * This method will initialize the normalizedValueWeightMap. We insert a representing string
75 * for each value in the issue. We set the weight of each value to -1. Note that those
76 * values should never be used.
77 */
78 private void initValueWeightMap()
79 {
80 List<ValueDiscrete> discreteValues = this.getIssueDiscrete().getValues();
81 this.normalizedValueWeightMap = new HashMap<String, Double>(discreteValues.size());
82
83 //Get all possible values of the discrete issue and them weight -1.
84 for(ValueDiscrete vd : discreteValues)
85 this.normalizedValueWeightMap.put(vd.getValue(), -1.0);
86 }
87
88
89 // ********************************
90 // Update
91 // ********************************
92
93 /**
94 * This method updates the IssueEvaluationDiscrete, based on the value that has been offered to us
95 * in a new bid. We will first receiveMessage the valueFrequencyMap based on the newly chosen value, and then receiveMessage
96 * the normalizedValueWeightMap based on the new frequencies.
97 * @param chosenValue The value of the issue we are evaluating that has just been chosen. May not be null.
98 */
99 @Override
100 public void updateIssueEvaluation(Value chosenValue)
101 {
102 super.updateIssueEvaluation(chosenValue);
103
104 this.updateValueFrequencyMap(chosenValue);
105 this.updateValueWeightMap();
106 }
107
108
109 /**
110 * This method updates the valueFrequencyMap for the IssueDiscrete we are evaluating.
111 * Based on the value that has been chosen, we add +1 to the amount of times the
112 * value has been chosen in the past.
113 */
114 protected void updateValueFrequencyMap(Value chosenValue)
115 {
116 if(!(chosenValue instanceof ValueDiscrete))
117 throw new IllegalArgumentException("The IssueEvaluationDiscrete receiveMessage method requires a ValueDiscrete value. It is now a: " + chosenValue.getClass().getSimpleName());
118
119 ValueDiscrete valueD = (ValueDiscrete)chosenValue;
120
121 //Calculate the new frequency.
122 Integer newFrequency = 1 + this.valueFrequencyMap.get(valueD.getValue());
123
124 //Remove the old frequency of the discrete value, and insert the new one.
125 this.valueFrequencyMap.put(valueD.getValue(), newFrequency);
126 }
127
128 /**
129 * This method updates the normalizedValueWeightMap. The weight of the value with the highest frequency
130 * is 1. The weight of the other values is scaled according to their frequency relatively to the highest frequency.
131 *
132 */
133 private void updateValueWeightMap()
134 {
135 int highestFrequency = this.getHighestFrequency();
136
137 //We do not allow calculation if no frequencies have been entered, so we throw
138 //an exception if the highestFrequency is zero.
139 if(highestFrequency <= 0)
140 throw new IllegalStateException("ValueWeight calculations are not supported when no frequencies have been set.");
141
142 //And then we normalize the weight of each value based on their frequency divided by the highestFrequency.
143 for(Entry<String, Integer> entry : this.valueFrequencyMap.entrySet())
144 {
145 double newValueWeight = (double)entry.getValue() / (double)highestFrequency;
146 this.normalizedValueWeightMap.put(entry.getKey(), newValueWeight);
147 }
148 }
149
150
151 // **************************************
152 // Getters
153 // **************************************
154
155 /**
156 * This method gives us the casted IssueDiscrete object
157 * we are evaluating.
158 * @return The IssueDiscrete we are evaluating.
159 */
160 public IssueDiscrete getIssueDiscrete()
161 {
162 return (IssueDiscrete)this.issue;
163 }
164
165 /**
166 * This returns the number of possible values for the discrete issue.
167 */
168 public int getNumberOfDiscreteValues()
169 {
170 return this.getIssueDiscrete().getNumberOfValues();
171 }
172
173 /**
174 * This method returns the sum of the frequencies in the valueFrequencyMap.
175 * This should be equal to the number of offered values.
176 */
177 protected int getSummedFrequency()
178 {
179 if(!this.isFirstValueOffered())
180 throw new IllegalStateException("Frequency calculations are not supported when no values have been offered yet.");
181
182 int result = 0;
183
184 for(Integer valueFrequency : this.valueFrequencyMap.values())
185 result += valueFrequency;
186
187 return result;
188 }
189
190 /**
191 * This method returns the highest frequency that can be
192 * found in the valueFrequencyMap.
193 */
194 protected int getHighestFrequency()
195 {
196 if(!this.isFirstValueOffered())
197 throw new IllegalStateException("Frequency calculations are not supported when no values have been offered yet.");
198
199 int highestFrequency = -1;
200
201 for(Integer valueFrequency : this.valueFrequencyMap.values())
202 if(valueFrequency > highestFrequency)
203 highestFrequency = valueFrequency;
204
205 return highestFrequency;
206 }
207
208 /**
209 * This method returns the percentage of the highest frequency.
210 * So we return the frequency of the value with the highest frequency and divide it with the total number of values chosen.
211 * @return
212 */
213 protected double getPercentageOfHighestFrequency()
214 {
215 if(!this.isFirstValueOffered())
216 throw new IllegalStateException("Frequency calculations are not supported when no values have been offered yet.");
217
218 return (double)getHighestFrequency() / (double)getSummedFrequency();
219 }
220
221 /**
222 * This method returns the normalized weight of the given value.
223 *
224 * Note that the weight of the most important value (measured by it's frequency) is 1,
225 * and the others values' weights are scaled relatively to their frequency.
226 */
227 @Override
228 public double getNormalizedValueWeight(Value value)
229 {
230 //We do not offer correct normalized valueWeights when no values have been offered yet,
231 //so the correct behavior would be to throw an exception.
232 if(!this.isFirstValueOffered())
233 throw new IllegalStateException("ValueWeight calculations are not supported when no values have been offered yet.");
234
235 ValueDiscrete valueD = (ValueDiscrete)value;
236 String discreteValue = valueD.getValue();
237 return this.normalizedValueWeightMap.get(discreteValue);
238 }
239
240 /**
241 * This returns a string representation of the issueEvaluation.
242 * @return The string representation.
243 */
244 public String toString()
245 {
246 String result = super.toString();
247 String nl = "\n";
248
249 result += "===== ValueFrequencyMap =====" + nl;
250 result += "===== NormalizedValueWeightMap =====" + nl;
251 result += "##### END #####" + nl;
252
253 return result;
254 }
255}
Note: See TracBrowser for help on using the repository browser.