source: src/main/java/genius/core/protocol/StackedAlternatingOffersProtocol.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: 6.7 KB
Line 
1package genius.core.protocol;
2
3import java.util.ArrayList;
4import java.util.HashMap;
5import java.util.List;
6import java.util.Map;
7import java.util.concurrent.ExecutionException;
8
9import genius.core.AgentID;
10import genius.core.Bid;
11import genius.core.actions.Accept;
12import genius.core.actions.Action;
13import genius.core.actions.EndNegotiation;
14import genius.core.actions.Inform;
15import genius.core.actions.Offer;
16import genius.core.exceptions.NegotiationPartyTimeoutException;
17import genius.core.parties.NegotiationParty;
18import genius.core.session.Round;
19import genius.core.session.Session;
20import genius.core.session.Turn;
21
22/**
23 * Implementation of an alternating offer protocol using offer/counter-offer.
24 * <p/>
25 * Protocol:
26 *
27 * <pre>
28 * The first agent makes an offer
29 * Other agents can accept or make a counter-offer
30 *
31 * If no agent makes a counter-offer, the negotiation end with this offer.
32 * Otherwise, the process continues until reaching deadline or agreement.
33 * </pre>
34 *
35 * @author David Festen
36 * @author Reyhan Aydogan
37 * @author Catholijn Jonker
38 */
39public class StackedAlternatingOffersProtocol extends DefaultMultilateralProtocol {
40
41 static final AgentID protocolID = new AgentID("StackedAlternatingOffersProtocol");
42
43 /**
44 * Get all possible actions for given party in a given session.
45 *
46 * @param parties
47 * @param session
48 * the current state of this session
49 * @return A list of possible actions
50 */
51
52 /**
53 * Defines the round structure.
54 *
55 * <pre>
56 * The first agent makes an offer
57 * Other agents can accept or make a counter-offer
58 * </pre>
59 *
60 * @param parties
61 * The parties currently participating
62 * @param session
63 * The complete session history
64 * @return A list of possible actions
65 */
66 @Override
67 public Round getRoundStructure(List<NegotiationParty> parties, Session session) {
68 Round round = new Round();
69 // we will create the very first action if this is the first round
70 boolean isVeryFirstAction = session.getRoundNumber() == 0;
71
72 for (NegotiationParty party : parties) {
73 if (isVeryFirstAction) {
74 // If this is the first party in the first round, it can not
75 // accept.
76 round.addTurn(new Turn(party, Offer.class, EndNegotiation.class));
77 } else {
78 // Each party can either accept the outstanding offer, or
79 // propose a counteroffer.
80 round.addTurn(new Turn(party, Accept.class, Offer.class, EndNegotiation.class));
81 }
82 isVeryFirstAction = false;
83 }
84
85 // return round structure
86 return round;
87 }
88
89 /**
90 * Will return the current agreement.
91 *
92 * @param session
93 * The complete session history up to this point
94 * @return The agreed upon bid or null if no agreement
95 */
96 @Override
97 public Bid getCurrentAgreement(Session session, List<NegotiationParty> parties) {
98
99 // if not all parties agree, we did not find an agreement
100 if (getNumberOfAgreeingParties(session, parties) < parties.size())
101 return null;
102
103 // all parties agreed, return most recent offer
104 return getMostRecentBid(session);
105 }
106
107 @Override
108 public int getNumberOfAgreeingParties(Session session, List<NegotiationParty> parties) {
109 int nAccepts = 0;
110 ArrayList<Action> actions = getMostRecentTwoRounds(session);
111 for (int i = actions.size() - 1; i >= 0; i--) {
112 if (actions.get(i) instanceof Accept) {
113 nAccepts++;
114 } else {
115 if (actions.get(i) instanceof Offer) {
116 // voting party also counts towards agreeing parties
117 nAccepts++;
118 }
119 // we found at least one not accepting party (offering/ending
120 // negotiation) so stop counting
121 break;
122 }
123 }
124 return nAccepts;
125 }
126
127 /**
128 * Get a list of all actions of the most recent two rounds
129 *
130 * @param session
131 * Session to extract the most recent two rounds out of
132 * @return A list of actions done in the most recent two rounds.
133 */
134 private ArrayList<Action> getMostRecentTwoRounds(Session session) {
135
136 // holds actions
137 ArrayList<Action> actions = new ArrayList<Action>();
138
139 // add previous round if exists
140 if (session.getRoundNumber() >= 2) {
141 Round round = session.getRounds().get(session.getRoundNumber() - 2);
142 for (Action action : round.getActions())
143 actions.add(action);
144 }
145
146 // add current round if exists (does not exists before any offer is
147 // made)
148 if (session.getRoundNumber() >= 1) {
149 Round round = session.getRounds().get(session.getRoundNumber() - 1);
150 for (Action action : round.getActions())
151 actions.add(action);
152 }
153
154 // return aggregated actions
155 return actions;
156 }
157
158 private Bid getMostRecentBid(Session session) {
159
160 // reverse rounds/actions until offer is found or return null
161 for (int roundIndex = session.getRoundNumber() - 1; roundIndex >= 0; roundIndex--) {
162 for (int actionIndex = session.getRounds().get(roundIndex).getActions().size()
163 - 1; actionIndex >= 0; actionIndex--) {
164 Action action = session.getRounds().get(roundIndex).getActions().get(actionIndex);
165 if (action instanceof Offer)
166 return ((Offer) action).getBid();
167 }
168 }
169
170 // No offer found, so return null (no most recent bid exists)
171 // since this is only possible when first party quits negotiation, it is
172 // probably a bug when this happens
173 System.err.println("Possible bug: No Offer was placed during negotiation");
174 return null;
175 }
176
177 /**
178 * If all agents accept the most recent offer, then this negotiation ends.
179 * Also, when any agent ends the negotiation (EndNegotiationAction) the
180 * negotiation ends
181 *
182 * @param session
183 * the current state of this session
184 * @return true if the protocol is finished
185 */
186 @Override
187 public boolean isFinished(Session session, List<NegotiationParty> parties) {
188 return getCurrentAgreement(session, parties) != null || session.getMostRecentAction() instanceof EndNegotiation;
189 }
190
191 /**
192 * Get a map of parties that are listening to each other.
193 *
194 * @return who is listening to who
195 */
196 @Override
197 public Map<NegotiationParty, List<NegotiationParty>> getActionListeners(List<NegotiationParty> parties) {
198
199 return listenToAll(parties);
200 }
201
202 @Override
203 public Map<NegotiationParty, List<Action>> beforeSession(Session session, final List<NegotiationParty> parties)
204 throws InterruptedException, ExecutionException, NegotiationPartyTimeoutException {
205 HashMap<NegotiationParty, List<Action>> map = new HashMap<NegotiationParty, List<Action>>();
206
207 for (NegotiationParty party : parties) {
208 ArrayList<Action> actions = new ArrayList<Action>();
209 actions.add(new Inform(protocolID, "NumberOfAgents", parties.size()));
210 map.put(party, actions);
211 }
212
213 return map;
214 }
215}
Note: See TracBrowser for help on using the repository browser.