1 | package agents.anac.y2019.ibasic.boacomponents;
|
---|
2 |
|
---|
3 | import java.util.ArrayList;
|
---|
4 | import java.util.List;
|
---|
5 | import java.util.Map;
|
---|
6 |
|
---|
7 | import genius.core.Bid;
|
---|
8 | import genius.core.boaframework.AcceptanceStrategy;
|
---|
9 | import genius.core.boaframework.Actions;
|
---|
10 | import genius.core.boaframework.NegotiationSession;
|
---|
11 | import genius.core.boaframework.OfferingStrategy;
|
---|
12 | import genius.core.boaframework.OpponentModel;
|
---|
13 | import genius.core.boaframework.SortedOutcomeSpace;
|
---|
14 | import genius.core.uncertainty.UserModel;
|
---|
15 | import genius.core.utility.AbstractUtilitySpace;
|
---|
16 |
|
---|
17 |
|
---|
18 | public class IBasicAS extends AcceptanceStrategy {
|
---|
19 |
|
---|
20 | //Our own model of the opponent
|
---|
21 | IBasicOM opponentModel;
|
---|
22 |
|
---|
23 | //The Utility Space used to evaluate the utility of a received bid.
|
---|
24 | AbstractUtilitySpace utilSpace;
|
---|
25 | Boolean first = false;
|
---|
26 | UserModel usermodel;
|
---|
27 | SortedOutcomeSpace outcomespace;
|
---|
28 |
|
---|
29 | //The reservation value and the minimum threshold we eventually use in the optimal stopping algrithm.
|
---|
30 | double reservationValue;
|
---|
31 | double minThreshold;
|
---|
32 |
|
---|
33 | //We keep track of the best bid of the opponent, worse bid of the opponent (according to our own utility) and the current round.
|
---|
34 | double lowestBidYet = 1;
|
---|
35 |
|
---|
36 | //We keep track of the history of the opponents bids.
|
---|
37 | List<Bid> opponentHistory = new ArrayList<>();
|
---|
38 |
|
---|
39 | //We override the init method in order to initialize the usermodel and bidOrder at the start of the session.
|
---|
40 | @Override
|
---|
41 | public void init(NegotiationSession negotiationSession, OfferingStrategy offeringStrategy,
|
---|
42 | OpponentModel opponentModel, Map<String, Double> parameters) throws Exception {
|
---|
43 | super.init(negotiationSession, parameters);
|
---|
44 |
|
---|
45 | //Sets the utility space and determines the reservation value.
|
---|
46 | this.utilSpace = negotiationSession.getUtilitySpace();
|
---|
47 | reservationValue = utilSpace.getReservationValueUndiscounted();
|
---|
48 | usermodel = negotiationSession.getUserModel();
|
---|
49 |
|
---|
50 | this.opponentModel = (IBasicOM) opponentModel;
|
---|
51 | //If we operate under preference uncertainty, we switch to a corresponding utility space.
|
---|
52 | if (negotiationSession.getUserModel() != null) {
|
---|
53 | this.utilSpace = IBasicPU.createUtilitySpace(negotiationSession.getDomain(), negotiationSession.getUserModel());}
|
---|
54 |
|
---|
55 | this.outcomespace = new SortedOutcomeSpace(utilSpace);
|
---|
56 | negotiationSession.setOutcomeSpace(this.outcomespace);
|
---|
57 | }
|
---|
58 |
|
---|
59 | //This method determines the acceptability of the received bid.
|
---|
60 | @Override
|
---|
61 | public Actions determineAcceptability()
|
---|
62 | {
|
---|
63 | //First it saves the last received bid of the opponent and the last bid we placed.
|
---|
64 | Bid receivedBid = negotiationSession.getOpponentBidHistory().getLastBid();
|
---|
65 |
|
---|
66 | //We save the last utility of the opponent
|
---|
67 | double lastOpponentBidUtil = this.utilSpace.getUtility(receivedBid);
|
---|
68 |
|
---|
69 | //We get the time that the session is playing in.
|
---|
70 | double totalTime = negotiationSession.getTimeline().getTotalTime();
|
---|
71 | double currentRound = negotiationSession.getTimeline().getCurrentTime();
|
---|
72 |
|
---|
73 | //The first thing we check, is that if this utility is 1 or if we are in the final round, we accept straight away.
|
---|
74 | if(lastOpponentBidUtil == 1) {
|
---|
75 | return Actions.Accept;
|
---|
76 | }
|
---|
77 |
|
---|
78 | //In case that there are no placed bids, we know that we have to give the first bid, which we do by rejecting.
|
---|
79 | if (receivedBid == null) {
|
---|
80 | first = true;
|
---|
81 | return Actions.Reject;
|
---|
82 | }
|
---|
83 |
|
---|
84 | //If we have less than 30 bids in our bid ranking, we use a simple heuristic instead of the cplex method.
|
---|
85 | if(usermodel != null) {
|
---|
86 | if (usermodel.getBidRanking().getSize() < 30)
|
---|
87 | {
|
---|
88 | if (currentRound <= totalTime-2)
|
---|
89 | {
|
---|
90 | if (receivedBid == negotiationSession.getUserModel().getBidRanking().getBidOrder().get(negotiationSession.getUserModel().getBidRanking().getBidOrder().size()-1)) {
|
---|
91 | return Actions.Accept;
|
---|
92 | }
|
---|
93 | }
|
---|
94 | else if (currentRound >= negotiationSession.getTimeline().getTotalTime()-1) {
|
---|
95 | return Actions.Accept;
|
---|
96 | }
|
---|
97 | return Actions.Reject;
|
---|
98 | }
|
---|
99 | }
|
---|
100 |
|
---|
101 | //We keep track of the worse bid until now. This is used later in this method to determine the optimal stopping interval.
|
---|
102 | if (lastOpponentBidUtil < lowestBidYet) {
|
---|
103 | lowestBidYet = lastOpponentBidUtil;
|
---|
104 | }
|
---|
105 |
|
---|
106 | //If we are in the final round, we accept all bids above our reservation value or else we break.
|
---|
107 | if (currentRound >= totalTime-1 && lastOpponentBidUtil > reservationValue) {
|
---|
108 |
|
---|
109 | return Actions.Accept;
|
---|
110 | }
|
---|
111 | else if (currentRound >= totalTime-1 && lastOpponentBidUtil <= reservationValue) {
|
---|
112 | return Actions.Break;
|
---|
113 | }
|
---|
114 |
|
---|
115 | //If we are in the final 3 rounds, we use our optimal stopping criteria to determine our minimal acceptance threshold.
|
---|
116 | else if (currentRound >= totalTime-3 && currentRound < totalTime-1)
|
---|
117 | {
|
---|
118 | //Either the reservation value or the lowest received bid, which one is the highest, becomes the minimal threshold over which the optimal stopping criteria is calculated.
|
---|
119 | if (reservationValue > lowestBidYet) {
|
---|
120 | minThreshold = reservationValue;
|
---|
121 | }
|
---|
122 | else {
|
---|
123 | minThreshold = lowestBidYet;
|
---|
124 | }
|
---|
125 |
|
---|
126 | //Optimal Stopping Criteria: For this we perform the optimal stopping criteria between the interval of the bestbid of the opponent and the worse bid of the opponent.
|
---|
127 | if(lastOpponentBidUtil >= (lowestBidYet + (OptimalStoppingFunction((totalTime - currentRound))*(1 - minThreshold)))) {
|
---|
128 | return Actions.Accept;
|
---|
129 | }
|
---|
130 | }
|
---|
131 |
|
---|
132 | //For the rest of the negotiation session, we use two stages: one where simply have a hard threshold: 93 and one where we follow a curve which is dependent on the concession rate of the opponent
|
---|
133 | else if(currentRound < totalTime -3)
|
---|
134 | {
|
---|
135 | //At 60% of the session, we determine the concession rate of the opponent.
|
---|
136 | double concessionrate = 0;
|
---|
137 | if (currentRound == (int) (negotiationSession.getTimeline().getTotalTime() * 0.6)) {
|
---|
138 | concessionrate = -0.04 + (this.opponentModel.EvaluateConsessionOpp()/ 4);
|
---|
139 | }
|
---|
140 | //For the first stage of the session, between 0.0 and 0.6, we accept a hard threshold of nothing less than 0.93 utility
|
---|
141 | if (currentRound <= 0.6*totalTime && lastOpponentBidUtil > 0.93 && lastOpponentBidUtil > reservationValue) {
|
---|
142 | return Actions.Accept;
|
---|
143 | }
|
---|
144 | //For the second stage (before the optimal stopping criteria) we follow the function below.
|
---|
145 | else if (currentRound >= 0.6 *totalTime) {
|
---|
146 | if (lastOpponentBidUtil > reservationValue && lastOpponentBidUtil > (0.93) - ((0.1 + concessionrate) * Math.pow(negotiationSession.getTimeline().getTime(), 7))) {
|
---|
147 | return Actions.Accept;
|
---|
148 | }
|
---|
149 | }
|
---|
150 | }
|
---|
151 | return Actions.Reject;
|
---|
152 | }
|
---|
153 |
|
---|
154 | //The optimal stopping method is a recursive method where we receive the amount of rounds that are left and we calculate the optimal stopping threshold for that round.
|
---|
155 | public double OptimalStoppingFunction(double time)
|
---|
156 | {
|
---|
157 | if (time <= 1) {
|
---|
158 | return 0;
|
---|
159 | }
|
---|
160 | else {
|
---|
161 | return 0.5 + (0.5 * Math.pow(OptimalStoppingFunction(time-1), 2));
|
---|
162 | }
|
---|
163 | }
|
---|
164 |
|
---|
165 | @Override
|
---|
166 | public String getName()
|
---|
167 | {
|
---|
168 | return "IBasicAS";
|
---|
169 | }
|
---|
170 |
|
---|
171 | }
|
---|