source: src/main/java/agents/anac/y2017/madagent/OpponentModel.java

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

Initial import : Genius 9.0.0

File size: 7.0 KB
Line 
1package agents.anac.y2017.madagent;
2
3import java.util.ArrayList;
4import java.util.Arrays;
5import java.util.Comparator;
6import java.util.HashMap;
7import java.util.List;
8
9import genius.core.Bid;
10import genius.core.issue.Issue;
11import genius.core.issue.Value;
12import genius.core.utility.UtilitySpace;
13
14public class OpponentModel {
15
16 private static final int MAXIMUM_BOULWARE_LEVEL = 5;
17 private static final int BOULWARE_MULTIPLIER = 10;
18
19 private class Preference {
20 private Issue issue;
21 private Value value;
22 private int count;
23 }
24
25 private class Weight {
26 private Issue issue;
27 private double value;
28 }
29
30 private UtilitySpace utilitySpace = null;
31 private Bid lastLastReceivedBid = null;
32 private Bid mostPreferredBid = null;
33 private double threshold = 0;
34 private int boulwareLevel = 0;
35 private int numberOfIssues = 0;
36 private List<Preference> preferences = null;
37
38 public OpponentModel(UtilitySpace utilitySpace, double threshold) {
39 this.utilitySpace = utilitySpace;
40 this.threshold = threshold;
41
42 numberOfIssues = utilitySpace.getDomain().getIssues().size();
43 preferences = new ArrayList<Preference>();
44 }
45
46 public void offer(Bid lastReceivedBid, double numberOfRounds) {
47 decideBoulwareLevel(lastReceivedBid);
48 addPreference(lastReceivedBid);
49 }
50
51 /*
52 * -------------------------- The Concept of Boulware Level
53 * -------------------------- - Boulware level is used for modifying the
54 * behavior of our agent. - If the boulware level is high, agent will
55 * increase threshold and will become more boulware. - The boulware level is
56 * decided by checking the offers of the opponent. - If the utilities of
57 * offers that is given by the opponent are low, according to our utility
58 * function, the boulware level will be high. - Boulware level is calculated
59 * by checking the previous offers. - Last last received bid is the bid
60 * received just before the last received bid.
61 */
62 public void decideBoulwareLevel(Bid lastReceivedBid) {
63 final double EDGE_OF_CONCEDING = threshold * 0.8;
64
65 if (lastLastReceivedBid == null)
66 lastLastReceivedBid = lastReceivedBid;
67
68 double lastLastReceivedUtility = utilitySpace.getUtility(lastLastReceivedBid);
69 double lastReceivedUtility = utilitySpace.getUtility(lastReceivedBid);
70 double finalReceivedUtility = (lastLastReceivedUtility + lastReceivedUtility) / 2;
71
72 /*
73 * If final received utility (the average of the last 2 utilities) is
74 * greater than the edge of conceding, the boulware level becomes 0
75 * which means that our agent is ready to concede.
76 */
77 if (finalReceivedUtility > EDGE_OF_CONCEDING)
78 boulwareLevel = 0;
79 else
80 boulwareLevel = (int) ((EDGE_OF_CONCEDING - finalReceivedUtility) * BOULWARE_MULTIPLIER);
81
82 /*
83 * The maximum boulware level is 5, so make it 5 if it's greater than 5.
84 */
85 if (boulwareLevel > MAXIMUM_BOULWARE_LEVEL)
86 boulwareLevel = MAXIMUM_BOULWARE_LEVEL;
87
88 lastLastReceivedBid = lastReceivedBid;
89 }
90
91 private void addPreference(Bid lastReceivedBid) {
92 /*
93 * Whenever a new offer is given, this method will be called For each
94 * item, number of occurrences will be stored in preferences list.
95 */
96 for (int issueNr = 1; issueNr <= numberOfIssues; issueNr++) {
97 Preference preference = new Preference();
98
99 preference.issue = lastReceivedBid.getIssues().get(issueNr - 1);
100 preference.value = lastReceivedBid.getValue(issueNr);
101 preference.count = 1;
102
103 int index = getIndexIfPreferredBefore(preference.value);
104
105 if (index == -1)
106 preferences.add(preference);
107 else
108 preferences.get(index).count++;
109 }
110 }
111
112 private int getIndexIfPreferredBefore(Value value) {
113 for (int i = 0; i < preferences.size(); i++)
114 if (preferences.get(i).value == value)
115 return i;
116
117 return -1;
118 }
119
120 public List<Bid> getAcceptableBids() {
121 /*
122 * Return list of bids that will possibly be accepted by the opponent.
123 */
124 computeMostPreferredBid();
125
126 List<Bid> acceptableBids = new ArrayList<Bid>();
127 Weight[] weights = getWeights();
128
129 for (double i = 1, previousWeight = 0; i < weights.length; i++) {
130 if (i > 2 && weights[(int) i].value - previousWeight > 0.02)
131 break;
132
133 Issue currentIssue = weights[(int) i].issue;
134 addBidsWithDifferentValues(acceptableBids, currentIssue);
135
136 previousWeight = weights[(int) i].value;
137 }
138
139 return acceptableBids;
140 }
141
142 public void computeMostPreferredBid() {
143 HashMap<Integer, Value> values = new HashMap<Integer, Value>();
144 sortPreferences();
145
146 for (int i = 0, j = 0; i < preferences.size() && j < numberOfIssues; i++) {
147 Issue currentIssue = preferences.get(i).issue;
148 Value currentValue = preferences.get(i).value;
149
150 if (!values.containsKey(currentIssue.getNumber())) {
151 values.put(currentIssue.getNumber(), currentValue);
152 j++;
153 }
154 }
155
156 mostPreferredBid = new Bid(utilitySpace.getDomain(), values);
157 }
158
159 private void sortPreferences() {
160 preferences.sort(new Comparator<Preference>() {
161 @Override
162 public int compare(Preference a, Preference b) {
163 return b.count - a.count;
164 }
165 });
166 }
167
168 private Weight[] getWeights() {
169 /* Estimates the weight of each issue. */
170 Weight[] weights = new Weight[numberOfIssues + 1];
171
172 calculateWeights(weights);
173 sortWeights(weights);
174
175 return weights;
176 }
177
178 private void calculateWeights(Weight[] weights) {
179 double sum = 0;
180
181 for (int i = 0, j = 0; i < preferences.size() && j < numberOfIssues; i++) {
182 Issue currentIssue = preferences.get(i).issue;
183 int issueId = currentIssue.getNumber();
184
185 if (weights[issueId] == null) {
186 weights[issueId] = new Weight();
187
188 weights[issueId].issue = currentIssue;
189 weights[issueId].value = preferences.get(i).count;
190
191 sum += weights[issueId].value;
192 j++;
193 }
194 }
195
196 for (int i = 1; i < weights.length; i++) // Normalizing the weights
197 weights[i].value /= sum;
198 }
199
200 private void sortWeights(Weight[] weights) {
201 weights[0] = new Weight();
202
203 Arrays.sort(weights, new Comparator<Weight>() {
204 @Override
205 public int compare(Weight a, Weight b) {
206 if (a.value > b.value)
207 return 1;
208 if (a.value < b.value)
209 return -1;
210
211 return 0;
212 }
213 });
214 }
215
216 private void addBidsWithDifferentValues(List<Bid> acceptableBids, Issue currentIssue) {
217 /*
218 * Modifies the most proffered bid by opponent to increase utility for
219 * our agent.
220 */
221 int issueId = currentIssue.getNumber();
222
223 List<Value> values = new ArrayList<Value>();
224 values.add(mostPreferredBid.getValue(issueId));
225
226 for (int j = 0; j < preferences.size(); j++)
227 if (preferences.get(j).issue == currentIssue)
228 if (!values.contains((preferences.get(j).value)))
229 values.add(preferences.get(j).value);
230
231 for (int j = 1; j < values.size(); j++) {
232 HashMap<Integer, Value> valueMap = mostPreferredBid.getValues();
233 valueMap.put(issueId, values.get(j));
234
235 acceptableBids.add(new Bid(utilitySpace.getDomain(), valueMap));
236 }
237 }
238
239 public double getNewThreshold() {
240 /*
241 * c is the constant value which makes threshold 1 if the boulware level
242 * is maximum (5)
243 */
244 final double c = (threshold * MAXIMUM_BOULWARE_LEVEL) / (1 - threshold);
245 return threshold * (1 + boulwareLevel / c);
246 }
247
248 public Bid getMostPreferredBid() {
249 return mostPreferredBid;
250 }
251}
Note: See TracBrowser for help on using the repository browser.