1 | package parties.in4010.q12015.group15;
|
---|
2 |
|
---|
3 | import java.util.ArrayList;
|
---|
4 | import java.util.HashMap;
|
---|
5 | import java.util.List;
|
---|
6 | import java.util.Map;
|
---|
7 | import java.util.Map.Entry;
|
---|
8 |
|
---|
9 | import genius.core.Bid;
|
---|
10 | import genius.core.issue.IssueDiscrete;
|
---|
11 | import genius.core.issue.Objective;
|
---|
12 | import genius.core.issue.Value;
|
---|
13 | import genius.core.issue.ValueDiscrete;
|
---|
14 | import genius.core.utility.AdditiveUtilitySpace;
|
---|
15 | import genius.core.utility.Evaluator;
|
---|
16 | import genius.core.utility.EvaluatorDiscrete;
|
---|
17 |
|
---|
18 | /**
|
---|
19 | * This Opponent Model uses frequency analysis to make preference profiles for
|
---|
20 | * all opponents. The issues that change the least often have higher weight. The
|
---|
21 | * options that appear the most often have the highest values. The opponent's
|
---|
22 | * strategy is evaluated in a way that it's possible to see if he concedes a lot
|
---|
23 | * or not.
|
---|
24 | * <p>
|
---|
25 | * Opponent model uses weights and therefore only supports
|
---|
26 | * {@link AdditiveUtilitySpace}.
|
---|
27 | */
|
---|
28 | public class OpponentModel {
|
---|
29 |
|
---|
30 | // Preference profile
|
---|
31 | private Map<String, AdditiveUtilitySpace> opponentUtilitySpaces = new HashMap<>();
|
---|
32 | private Map<String, AdditiveUtilitySpace> lastOpponentUtilitySpaces = new HashMap<>();
|
---|
33 | private Map<String, Bid> lastBids = new HashMap<>();
|
---|
34 | private AdditiveUtilitySpace emptyOpponentUtilitySpace;
|
---|
35 | private double n;
|
---|
36 |
|
---|
37 | // Opponent strategy
|
---|
38 | private Map<String, Map<BidUtilChange, Double>> utilChanges = new HashMap<>();
|
---|
39 |
|
---|
40 | public OpponentModel(AdditiveUtilitySpace utilSpace) {
|
---|
41 | System.out.println("INIT OpponentModel");
|
---|
42 | this.n = 0.1;
|
---|
43 |
|
---|
44 | initOpponentProfiles(utilSpace);
|
---|
45 | }
|
---|
46 |
|
---|
47 | /**
|
---|
48 | * Set up an empty profile for an opponent. All issues get equal weights and
|
---|
49 | * all options get equal values.
|
---|
50 | *
|
---|
51 | * @param utilSpace
|
---|
52 | */
|
---|
53 | public void initOpponentProfiles(AdditiveUtilitySpace utilSpace) {
|
---|
54 | emptyOpponentUtilitySpace = new AdditiveUtilitySpace(utilSpace);
|
---|
55 | double totalIssues = emptyOpponentUtilitySpace.getNrOfEvaluators();
|
---|
56 | double equalWeight = 1 / totalIssues;
|
---|
57 | for (Entry<Objective, Evaluator> eval : emptyOpponentUtilitySpace
|
---|
58 | .getEvaluators()) {
|
---|
59 | emptyOpponentUtilitySpace.unlock(eval.getKey());
|
---|
60 | eval.getValue().setWeight(equalWeight);
|
---|
61 |
|
---|
62 | try {
|
---|
63 | for (ValueDiscrete vd : ((IssueDiscrete) eval.getKey())
|
---|
64 | .getValues()) {
|
---|
65 | ((EvaluatorDiscrete) eval.getValue()).setEvaluation(vd, 1);
|
---|
66 | }
|
---|
67 | } catch (Exception ex) {
|
---|
68 | ex.printStackTrace();
|
---|
69 | }
|
---|
70 | }
|
---|
71 | }
|
---|
72 |
|
---|
73 | /**
|
---|
74 | * @param agent
|
---|
75 | * @param bid
|
---|
76 | * @return utility for agent for bid
|
---|
77 | */
|
---|
78 | public double getBidEvaluation(String agent, Bid bid) {
|
---|
79 | try {
|
---|
80 | return opponentUtilitySpaces.get(agent).getUtility(bid);
|
---|
81 | } catch (Exception e) {
|
---|
82 | System.out.println("OM Could not get bid evaluation");
|
---|
83 | e.printStackTrace();
|
---|
84 | }
|
---|
85 | return 0;
|
---|
86 | }
|
---|
87 |
|
---|
88 | /**
|
---|
89 | * @param agent
|
---|
90 | * @return utility for agent for his last offered bid
|
---|
91 | */
|
---|
92 | public double getLastBidEvaluation(String agent) {
|
---|
93 | try {
|
---|
94 | Bid lastBid = lastBids.get(agent);
|
---|
95 | return opponentUtilitySpaces.get(agent).getUtility(lastBid);
|
---|
96 | } catch (Exception e) {
|
---|
97 | System.out.println("OM Could not get last bid evaluation");
|
---|
98 | e.printStackTrace();
|
---|
99 | }
|
---|
100 | return 0;
|
---|
101 | }
|
---|
102 |
|
---|
103 | /**
|
---|
104 | * @param agentID
|
---|
105 | * @return true if agent is offering his first bid, otherwise false
|
---|
106 | */
|
---|
107 | private boolean isFirstBidFromAgent(String agentID) {
|
---|
108 | return !opponentUtilitySpaces.containsKey(agentID);
|
---|
109 | }
|
---|
110 |
|
---|
111 | /**
|
---|
112 | * Adds agent to opponent profiles and util change history
|
---|
113 | *
|
---|
114 | * @param agent
|
---|
115 | */
|
---|
116 | private void addAgent(String agent, Bid opponentBid) {
|
---|
117 | System.out.println("First bid for " + agent);
|
---|
118 | opponentUtilitySpaces.put(agent, new AdditiveUtilitySpace(
|
---|
119 | emptyOpponentUtilitySpace));
|
---|
120 | lastBids.put(agent, opponentBid);
|
---|
121 |
|
---|
122 | HashMap<BidUtilChange, Double> utilChangeValues = new HashMap<>();
|
---|
123 | utilChangeValues.put(BidUtilChange.AVERAGE_UTIL_CHANGE, 0.0);
|
---|
124 | utilChangeValues.put(BidUtilChange.TOTAL_UTIL_CHANGE, 0.0);
|
---|
125 | utilChanges.put(agent, utilChangeValues);
|
---|
126 | }
|
---|
127 |
|
---|
128 | /**
|
---|
129 | * Updates opponent model and opponent strategy model for agent regarding to
|
---|
130 | * his latest bid
|
---|
131 | *
|
---|
132 | * @param agent
|
---|
133 | * @param opponentBid
|
---|
134 | */
|
---|
135 | public void updateModel(String agent, Bid opponentBid, int rounds) {
|
---|
136 | System.out.println("----- OM -----");
|
---|
137 | System.out.println("Updating OM for: " + agent);
|
---|
138 |
|
---|
139 | if (isFirstBidFromAgent(agent)) {
|
---|
140 | addAgent(agent, opponentBid);
|
---|
141 | return;
|
---|
142 | }
|
---|
143 |
|
---|
144 | System.out.println("Last bid: " + lastBids.get(agent));
|
---|
145 | System.out.println("Curr bid: " + opponentBid);
|
---|
146 |
|
---|
147 | updateStrategy(agent, opponentBid, rounds);
|
---|
148 | updatePreferenceProfile(agent, opponentBid);
|
---|
149 |
|
---|
150 | }
|
---|
151 |
|
---|
152 | /**
|
---|
153 | * Updates the opponent's preference profile with frequency analysis
|
---|
154 | *
|
---|
155 | * @param agent
|
---|
156 | * @param opponentBid
|
---|
157 | */
|
---|
158 | private void updatePreferenceProfile(String agent, Bid opponentBid) {
|
---|
159 | saveLastUtilitySpace(agent);
|
---|
160 |
|
---|
161 | for (int i = 1; i <= opponentUtilitySpaces.get(agent)
|
---|
162 | .getNrOfEvaluators(); i++) {
|
---|
163 | Evaluator eval = opponentUtilitySpaces.get(agent).getEvaluator(i);
|
---|
164 | try {
|
---|
165 | Value currentVal = opponentBid.getValue(i);
|
---|
166 | Value lastVal = lastBids.get(agent).getValue(i);
|
---|
167 |
|
---|
168 | // weights
|
---|
169 | if (currentVal.equals(lastVal)) {
|
---|
170 | double currentWeight = eval.getWeight();
|
---|
171 | eval.setWeight(currentWeight + n);
|
---|
172 | }
|
---|
173 |
|
---|
174 | // values
|
---|
175 | ValueDiscrete currentValDiscrete = (ValueDiscrete) currentVal;
|
---|
176 | EvaluatorDiscrete evalDiscrete = (EvaluatorDiscrete) eval;
|
---|
177 | double valueBefore = evalDiscrete
|
---|
178 | .getDoubleValue(currentValDiscrete);
|
---|
179 | evalDiscrete.setEvaluationDouble(currentValDiscrete,
|
---|
180 | valueBefore + 1.0);
|
---|
181 | } catch (Exception e) {
|
---|
182 | System.out
|
---|
183 | .println("OM Could not update preference profile for "
|
---|
184 | + agent);
|
---|
185 | e.printStackTrace();
|
---|
186 | }
|
---|
187 | }
|
---|
188 |
|
---|
189 | normalizeWeights(agent);
|
---|
190 |
|
---|
191 | lastBids.put(agent, opponentBid);
|
---|
192 | }
|
---|
193 |
|
---|
194 | /**
|
---|
195 | * Updates information to model the opponent's strategy. It keeps track of
|
---|
196 | * the average change in the opponent's utility for his offers.
|
---|
197 | *
|
---|
198 | * @param agent
|
---|
199 | * @param opponentBid
|
---|
200 | * @param rounds
|
---|
201 | */
|
---|
202 | private void updateStrategy(String agent, Bid opponentBid, int rounds) {
|
---|
203 | double currentBidUtil = getBidEvaluation(agent, opponentBid);
|
---|
204 | double lastBidUtil = getLastBidEvaluation(agent);
|
---|
205 | double utilDiff = currentBidUtil - lastBidUtil;
|
---|
206 |
|
---|
207 | double currentTotalUtilChange = utilChanges.get(agent).get(
|
---|
208 | BidUtilChange.TOTAL_UTIL_CHANGE);
|
---|
209 | double totalUtilChangeAfter = currentTotalUtilChange + utilDiff;
|
---|
210 |
|
---|
211 | utilChanges.get(agent).put(BidUtilChange.TOTAL_UTIL_CHANGE,
|
---|
212 | totalUtilChangeAfter);
|
---|
213 | utilChanges.get(agent).put(BidUtilChange.AVERAGE_UTIL_CHANGE,
|
---|
214 | totalUtilChangeAfter / rounds);
|
---|
215 | }
|
---|
216 |
|
---|
217 | /**
|
---|
218 | * Normalizes weights for the opponent model for agent.
|
---|
219 | *
|
---|
220 | * @param agent
|
---|
221 | */
|
---|
222 | private void normalizeWeights(String agent) {
|
---|
223 | double sum = 0;
|
---|
224 |
|
---|
225 | for (Entry<Objective, Evaluator> eval : opponentUtilitySpaces
|
---|
226 | .get(agent).getEvaluators()) {
|
---|
227 | double weight = eval.getValue().getWeight();
|
---|
228 | sum += weight;
|
---|
229 | }
|
---|
230 |
|
---|
231 | for (Entry<Objective, Evaluator> eval : opponentUtilitySpaces
|
---|
232 | .get(agent).getEvaluators()) {
|
---|
233 | double weight = eval.getValue().getWeight();
|
---|
234 | eval.getValue().setWeight(weight / sum);
|
---|
235 | }
|
---|
236 | }
|
---|
237 |
|
---|
238 | /**
|
---|
239 | * @param agent
|
---|
240 | * @return last bid from agent
|
---|
241 | */
|
---|
242 | public Bid getLastBidFromAgent(String agent) {
|
---|
243 | return lastBids.get(agent);
|
---|
244 | }
|
---|
245 |
|
---|
246 | /**
|
---|
247 | * @return all opponents in current negotiation
|
---|
248 | */
|
---|
249 | public List<String> getOpponents() {
|
---|
250 | List<String> opponents = new ArrayList<>();
|
---|
251 | for (String opponent : opponentUtilitySpaces.keySet()) {
|
---|
252 | opponents.add(opponent);
|
---|
253 | }
|
---|
254 | return opponents;
|
---|
255 | }
|
---|
256 |
|
---|
257 | /**
|
---|
258 | * @param agent
|
---|
259 | * @return utility space for agent
|
---|
260 | */
|
---|
261 | public AdditiveUtilitySpace getUtilitySpace(String agent) {
|
---|
262 | return opponentUtilitySpaces.get(agent);
|
---|
263 | }
|
---|
264 |
|
---|
265 | /**
|
---|
266 | * @param agent
|
---|
267 | * @return utility space for agent before the last update
|
---|
268 | */
|
---|
269 | public AdditiveUtilitySpace getLastUtilitySpace(String agent) {
|
---|
270 | return lastOpponentUtilitySpaces.get(agent);
|
---|
271 | }
|
---|
272 |
|
---|
273 | /**
|
---|
274 | * Saves the agent's last utility space
|
---|
275 | *
|
---|
276 | * @param agent
|
---|
277 | */
|
---|
278 | private void saveLastUtilitySpace(String agent) {
|
---|
279 | lastOpponentUtilitySpaces.put(agent, new AdditiveUtilitySpace(
|
---|
280 | getUtilitySpace(agent)));
|
---|
281 | }
|
---|
282 |
|
---|
283 | /**
|
---|
284 | * @param agent
|
---|
285 | * @return the average of the utility change in the agent's bid
|
---|
286 | */
|
---|
287 | public double getAverageBidUtilityChangeForAgent(String agent) {
|
---|
288 | return utilChanges.get(agent).get(BidUtilChange.AVERAGE_UTIL_CHANGE);
|
---|
289 | }
|
---|
290 | }
|
---|