source: ANL2022/Pinar_Agent/Pinar_Agent.py

Last change on this file was 75, checked in by wouter, 21 months ago

#6 added ANAC2022 parties

File size: 9.9 KB
Line 
1import json
2import logging
3from time import time
4from typing import cast
5
6from geniusweb.actions.Accept import Accept
7from geniusweb.actions.Action import Action
8from geniusweb.actions.Offer import Offer
9from geniusweb.actions.PartyId import PartyId
10from geniusweb.bidspace.AllBidsList import AllBidsList
11from geniusweb.inform.ActionDone import ActionDone
12from geniusweb.inform.Finished import Finished
13from geniusweb.inform.Inform import Inform
14from geniusweb.inform.Settings import Settings
15from geniusweb.inform.YourTurn import YourTurn
16from geniusweb.issuevalue.Bid import Bid
17from geniusweb.issuevalue.Domain import Domain
18from geniusweb.party.Capabilities import Capabilities
19from geniusweb.party.DefaultParty import DefaultParty
20from geniusweb.profile.utilityspace.LinearAdditiveUtilitySpace import (
21 LinearAdditiveUtilitySpace,
22)
23from geniusweb.profileconnection.ProfileConnectionFactory import (
24 ProfileConnectionFactory,
25)
26from geniusweb.progress.ProgressTime import ProgressTime
27from geniusweb.references.Parameters import Parameters
28from tudelft_utilities_logging.ReportToLogger import ReportToLogger
29
30from .utils.Pinar_Agent_Brain import Pinar_Agent_Brain
31
32
33class Pinar_Agent(DefaultParty):
34 def __init__(self):
35 super().__init__()
36 self.logger: ReportToLogger = self.getReporter()
37
38 self.domain: Domain = None
39 self.parameters: Parameters = None
40 self.profile: LinearAdditiveUtilitySpace = None
41 self.sorted_bids = None
42
43 self.progress: ProgressTime = None
44 self.me: PartyId = None
45 self.opponent_id: str = None
46 self.settings: Settings = None
47 self.storage_dir: str = None
48
49 self.last_received_bid: Bid = None
50
51 self.agent_brain = Pinar_Agent_Brain()
52
53 self.storage_data = {}
54 self.isFirstRound = True
55 self.last_trained_time = 0
56
57 self.logger.log(logging.INFO, "party is initialized")
58
59 def notifyChange(self, data: Inform):
60 """MUST BE IMPLEMENTED
61 This is the entry point of all interaction with your agent after is has been initialised.
62 How to handle the received data is based on its class type.
63
64 Args:
65 info (Inform): Contains either a request for action or information.
66 """
67
68 # a Settings message is the first message that will be send to your
69 # agent containing all the information about the negotiation session.
70 if isinstance(data, Settings):
71 self.settings = cast(Settings, data)
72 self.me = self.settings.getID()
73
74 # progress towards the deadline has to be tracked manually through the use of the Progress object
75 self.progress = self.settings.getProgress()
76
77 self.parameters = self.settings.getParameters()
78 self.storage_dir = self.parameters.get("storage_dir")
79 # the profile contains the preferences of the agent over the domain
80 profile_connection = ProfileConnectionFactory.create(
81 data.getProfile().getURI(), self.getReporter()
82 )
83 self.profile = profile_connection.getProfile()
84 self.domain = self.profile.getDomain()
85 all_bids = AllBidsList(self.domain)
86 if not self.sorted_bids:
87 self.sorted_bids = sorted(all_bids, key=lambda x: self.profile.getUtility(x),
88 reverse=True)
89 self.agent_brain.fill_domain_and_profile(self.domain, self.profile)
90
91 profile_connection.close()
92
93 # ActionDone informs you of an action (an offer or an accept)
94 # that is performed by one of the agents (including yourself).
95 elif isinstance(data, ActionDone):
96 action = cast(ActionDone, data).getAction()
97 actor = action.getActor()
98
99 # ignore action if it is our action
100 if actor != self.me:
101 # obtain the name of the opponent, cutting of the position ID.
102 self.opponent_id = str(actor).rsplit("_", 1)[0]
103
104 if self.isFirstRound:
105 self.load_data()
106 self.isFirstRound = False
107 # process action done by opponent
108 self.opponent_action(action)
109
110 # YourTurn notifies you that it is your turn to act
111 elif isinstance(data, YourTurn):
112 # execute a turn
113 self.my_turn()
114
115 # Finished will be send if the negotiation has ended (through agreement or deadline)
116 elif isinstance(data, Finished):
117 self.save_data()
118 # terminate the agent MUST BE CALLED
119 self.logger.log(logging.INFO, "party is terminating:")
120 super().terminate()
121 else:
122 self.logger.log(logging.WARNING, "Ignoring unknown info " + str(data))
123
124 def getCapabilities(self) -> Capabilities:
125 """MUST BE IMPLEMENTED
126 Method to indicate to the protocol what the capabilities of this agent are.
127 Leave it as is for the ANL 2022 competition
128
129 Returns:
130 Capabilities: Capabilities representation class
131 """
132 return Capabilities(
133 set(["SAOP"]),
134 set(["geniusweb.profile.utilityspace.LinearAdditive"]),
135 )
136
137 def send_action(self, action: Action):
138 """Sends an action to the opponent(s)
139
140 Args:
141 action (Action): action of this agent
142 """
143 self.getConnection().send(action)
144
145 # give a description of your agent
146 def getDescription(self) -> str:
147 """MUST BE IMPLEMENTED
148 Returns a description of your agent. 1 or 2 sentences.
149
150 Returns:
151 str: Agent description
152 """
153 return "Precious Intelligent Negotiation Agreement Robot(Pinar) that empowered by LightGBM tries to find opponent weak side"
154
155 def opponent_action(self, action):
156 """Process an action that was received from the opponent.
157
158 Args:
159 action (Action): action of opponent
160 """
161 # if it is an offer, set the last received bid
162 if isinstance(action, Offer):
163 bid = cast(Offer, action).getBid()
164 progress_time = float(self.progress.get(time() * 1000))
165 if bid not in self.agent_brain.offers_unique:
166 if len(self.agent_brain.offers_unique) <= 8 and progress_time < 0.81:
167 self.agent_brain.add_opponent_offer_to_self_x_and_self_y(bid, progress_time)
168 self.agent_brain.evaluate_data_according_to_lig_gbm(progress_time)
169 self.last_trained_time = progress_time
170 elif self.last_trained_time + 0.1 > progress_time and self.agent_brain.lgb_model is not None:
171 self.agent_brain.evaluate_opponent_utility_for_all_my_important_bid(progress_time)
172 self.last_trained_time = progress_time
173
174 self.agent_brain.keep_opponent_offer_in_a_list(bid, progress_time)
175 # set bid as last received
176 self.last_received_bid = bid
177
178 def my_turn(self):
179 """This method is called when it is our turn. It should decide upon an action
180 to perform and send this action to the opponent.
181 """
182 # check if the last received offer is good enough
183 if self.accept_condition(self.last_received_bid):
184 # if so, accept the offer
185 action = Accept(self.me, self.last_received_bid)
186 else:
187 # if not, find a bid to propose as counter offer
188 progress_time = float(self.progress.get(time() * 1000))
189 bid = self.agent_brain.find_bid(progress_time)
190 action = Offer(self.me, bid)
191
192 # send the action
193 self.send_action(action)
194
195 def save_data(self):
196 """This method is called after the negotiation is finished. It can be used to store data
197 for learning capabilities. Note that no extensive calculations can be done within this method.
198 Taking too much time might result in your agent being killed, so use it for storage only.
199 """
200 try:
201 if 'offerNumberUnique' in self.storage_data.keys():
202 self.storage_data['offerNumberUnique'].append(len(self.agent_brain.offers_unique))
203 else:
204 self.storage_data['offerNumberUnique'] = [len(self.agent_brain.offers_unique)]
205 if 'acceptance_condition' in self.storage_data.keys():
206 self.storage_data['acceptance_condition'].append(self.agent_brain.acceptance_condition)
207 else:
208 self.storage_data['acceptance_condition'] = [self.agent_brain.acceptance_condition]
209 if 'model_feature_importance' in self.storage_data.keys():
210 self.storage_data['model_feature_importance'].append(self.agent_brain.model_feature_importance())
211 else:
212 self.storage_data['model_feature_importance'] = [self.agent_brain.model_feature_importance()]
213
214 with open(f"{self.storage_dir}/{self.opponent_id}data.md", "w") as f:
215 f.write(json.dumps(self.storage_data))
216
217 except Exception:
218 pass
219
220 def load_data(self):
221 if self.opponent_id is not None and self.storage_dir is not None:
222 try:
223 with open(self.storage_dir + "/" + self.opponent_id + "data.md") as file:
224 self.storage_data = json.load(file)
225 self.this_session_is_first_match_for_this_opponent = False
226 except Exception:
227 pass
228
229 def accept_condition(self, bid: Bid) -> bool:
230 if bid is None:
231 return False
232
233 # progress of the negotiation session between 0 and 1 (1 is deadline)
234 progress = self.progress.get(time() * 1000)
235
236 return self.agent_brain.is_acceptable(bid, progress)
Note: See TracBrowser for help on using the repository browser.