1 | package genius.core.protocol;
|
---|
2 |
|
---|
3 | import java.util.List;
|
---|
4 | import java.util.Map;
|
---|
5 | import java.util.concurrent.ExecutionException;
|
---|
6 |
|
---|
7 | import genius.core.AgentID;
|
---|
8 | import genius.core.Bid;
|
---|
9 | import genius.core.actions.Action;
|
---|
10 | import genius.core.exceptions.NegotiationPartyTimeoutException;
|
---|
11 | import genius.core.parties.NegotiationParty;
|
---|
12 | import genius.core.session.ActionException;
|
---|
13 | import genius.core.session.Round;
|
---|
14 | import genius.core.session.Session;
|
---|
15 | import genius.core.session.SessionManager;
|
---|
16 | import genius.core.session.Turn;
|
---|
17 |
|
---|
18 | /**
|
---|
19 | * The protocol describes if the negotiation is finished, what the agreement is,
|
---|
20 | * which actions can be done in the next round.
|
---|
21 | * <p>
|
---|
22 | * The protocol is executed for example by the
|
---|
23 | * {@link genius.core.session.SessionManager}.
|
---|
24 | *
|
---|
25 | * <h1>Specification</h1> A protocol should be used as follows.
|
---|
26 | * <ol>
|
---|
27 | * <li>The first time, {@link #beforeSession(Session, List)} should be called
|
---|
28 | * and all agents should receive the actions accordingly.
|
---|
29 | * <li>For each round in the session:
|
---|
30 | * <ol>
|
---|
31 | * <li>{@link #getRoundStructure(List, Session)} should be called to determine
|
---|
32 | * the {@link Round}
|
---|
33 | * <li>For each {@link Turn} in the {@link Round} :
|
---|
34 | * <ol>
|
---|
35 | * <li>the {@link Turn#getParty()} agent should be called with the specified
|
---|
36 | * allowed actions.
|
---|
37 | * <li>The agent returns a picked action
|
---|
38 | * <li>{@link #getActionListeners(List)} should be called to get a list of which
|
---|
39 | * agents need to hear the picked action of this agent.
|
---|
40 | * </ol>
|
---|
41 | * <li>{@link #isFinished(Session, List)} should be checked after the round is
|
---|
42 | * complete to see if there are other rounds . If so, repeat
|
---|
43 | * </ol>
|
---|
44 | * <li>When a session is completely done, {@link #afterSession(Session, List)}
|
---|
45 | * should be called
|
---|
46 | * </ol>
|
---|
47 | *
|
---|
48 | * @author David Festen
|
---|
49 | */
|
---|
50 | public interface MultilateralProtocol {
|
---|
51 |
|
---|
52 | /**
|
---|
53 | * Get the structure of the current round. Each round, this method receives
|
---|
54 | * a list of all the {@link genius.core.parties.NegotiationParty} and the
|
---|
55 | * complete {@link Session} which can be used to diversify the round
|
---|
56 | * structure at some point during the session.
|
---|
57 | *
|
---|
58 | * @param parties
|
---|
59 | * The parties currently participating
|
---|
60 | * @param session
|
---|
61 | * The complete session history
|
---|
62 | * @return A list of possible actions
|
---|
63 | */
|
---|
64 | Round getRoundStructure(List<NegotiationParty> parties, Session session);
|
---|
65 |
|
---|
66 | /**
|
---|
67 | * Returns a list of Actions to be sent to
|
---|
68 | * {@link NegotiationParty#receiveMessage(AgentID, Action)} . This will get
|
---|
69 | * called just before the session starts. If some initialization with needs
|
---|
70 | * to be done by the protocol, it can be done here.
|
---|
71 | *
|
---|
72 | *
|
---|
73 | * @param session
|
---|
74 | * The upcoming {@link Session}
|
---|
75 | * @param parties
|
---|
76 | * The {@link NegotiationParty}s that will participate in the
|
---|
77 | * session
|
---|
78 | */
|
---|
79 | Map<NegotiationParty, List<Action>> beforeSession(Session session, List<NegotiationParty> parties)
|
---|
80 | throws NegotiationPartyTimeoutException, ExecutionException, InterruptedException;
|
---|
81 |
|
---|
82 | /**
|
---|
83 | * This will get called just after ending the session. If the protocol needs
|
---|
84 | * to do some post session steps, it can be done here. Protocols should not
|
---|
85 | * handle {@link NegotiationParty#negotiationEnded(Bid)} as these are always
|
---|
86 | * called by the {@link SessionManager}.
|
---|
87 | *
|
---|
88 | * @param session
|
---|
89 | * The session instance that was used for the session
|
---|
90 | * @param parties
|
---|
91 | * The parties that participated in the session
|
---|
92 | */
|
---|
93 | void afterSession(Session session, List<NegotiationParty> parties);
|
---|
94 |
|
---|
95 | /**
|
---|
96 | * Apply the action according to the protocol. All actions done by all
|
---|
97 | * agents come through this method. The protocol should check here if the
|
---|
98 | * agent's action is actually allowed and contains the proper data.
|
---|
99 | *
|
---|
100 | * @param action
|
---|
101 | * action to apply. The Agent ID in the action already has been
|
---|
102 | * checked when this is called.
|
---|
103 | * @param session
|
---|
104 | * the current state of this session
|
---|
105 | * @throws ActionException
|
---|
106 | * if the proposed action is illegal according to the protocol.
|
---|
107 | */
|
---|
108 | void applyAction(Action action, Session session) throws ActionException;
|
---|
109 |
|
---|
110 | /**
|
---|
111 | * Check if the protocol is done or still busy. If this method returns true,
|
---|
112 | * the {@link genius.core.session.SessionManager} will not start a new
|
---|
113 | * {@link Round} after the current one. It will however finish all the turns
|
---|
114 | * described in the
|
---|
115 | * {@link #getRoundStructure(java.util.List, genius.core.session.Session)}
|
---|
116 | * method.
|
---|
117 | *
|
---|
118 | * @param session
|
---|
119 | * the current state of this session
|
---|
120 | * @param parties
|
---|
121 | * all the parties involved in the negotiation
|
---|
122 | * @return true if the protocol is finished
|
---|
123 | */
|
---|
124 | boolean isFinished(Session session, List<NegotiationParty> parties);
|
---|
125 |
|
---|
126 | /**
|
---|
127 | * Get a map of parties that are listening to each other's response. All
|
---|
128 | * these listeners should be informed whenever a party takes an action. See
|
---|
129 | * also the default implementations
|
---|
130 | * {@link DefaultMultilateralProtocol#listenToAll(List)} and
|
---|
131 | * {@link DefaultMultilateralProtocol#listenToNone(List)}
|
---|
132 | *
|
---|
133 | * @param parties
|
---|
134 | * The parties involved in the current negotiation
|
---|
135 | * @return A map where the key is a {@link NegotiationParty} that is
|
---|
136 | * responding to a {@link NegotiationParty#chooseAction(List)}
|
---|
137 | * event, and the value is a list of {@link NegotiationParty}s that
|
---|
138 | * are listening to that key party's response.
|
---|
139 | */
|
---|
140 | Map<NegotiationParty, List<NegotiationParty>> getActionListeners(List<NegotiationParty> parties);
|
---|
141 |
|
---|
142 | /**
|
---|
143 | * This method should return the current agreement.
|
---|
144 | * <p/>
|
---|
145 | * Some protocols only have an agreement at the negotiation session, make
|
---|
146 | * sure that this method returns null until the end of the session in that
|
---|
147 | * case, because this method might be queried at intermediary steps.
|
---|
148 | *
|
---|
149 | * @param session
|
---|
150 | * The complete session history up to this point
|
---|
151 | * @param parties
|
---|
152 | * The parties involved in the current negotiation
|
---|
153 | * @return The agreed upon bid or null if no agreement
|
---|
154 | */
|
---|
155 | Bid getCurrentAgreement(Session session, List<NegotiationParty> parties);
|
---|
156 |
|
---|
157 | /**
|
---|
158 | * Gets the number of parties that currently agree to the offer. For
|
---|
159 | * protocols that either have an agreement or not, you can set this number
|
---|
160 | * to 0 until an agreement is found, and then set this value to the number
|
---|
161 | * of parties.
|
---|
162 | *
|
---|
163 | * @param session
|
---|
164 | * the current state of this session
|
---|
165 | * @param parties
|
---|
166 | * The parties currently participating
|
---|
167 | * @return the number of parties agreeing to the current agreement
|
---|
168 | */
|
---|
169 | int getNumberOfAgreeingParties(Session session, List<NegotiationParty> parties);
|
---|
170 |
|
---|
171 | /**
|
---|
172 | * Overwrites the rest of the protocol and sets the protocol state to finish
|
---|
173 | */
|
---|
174 | void endNegotiation();
|
---|
175 |
|
---|
176 | /**
|
---|
177 | * Overwrites the rest of the protocol and sets the protocol state to finish
|
---|
178 | *
|
---|
179 | * @param reason
|
---|
180 | * Optionally give a reason why the protocol is finished.
|
---|
181 | */
|
---|
182 | void endNegotiation(String reason);
|
---|
183 |
|
---|
184 | }
|
---|