source: CSE3210/agent33/acceptance_strategy.py

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

#6 Added CSE3210 parties

File size: 5.3 KB
Line 
1import time
2import numpy as np
3from abc import abstractmethod
4
5from geniusweb.issuevalue.Bid import Bid
6from geniusweb.profile.Profile import Profile
7from geniusweb.progress.Progress import Progress
8
9from .utility import AgentUtility
10
11
12class AbstractAcceptanceStrategy:
13 """
14 Abstract class enables us to efficiently test different acceptance strategies.
15 """
16
17 def __init__(self, profile: Profile = None, progress: Progress = None, utility: AgentUtility = None):
18 self._profile = profile
19 self._progress = progress
20 self._utility = utility
21
22 def set_profile(self, profile):
23 self._profile = profile
24
25 def set_progress(self, progress):
26 self._progress = progress
27
28 @abstractmethod
29 def accept(self, bid: Bid):
30 pass
31
32
33class CombiAcceptanceStrategy(AbstractAcceptanceStrategy):
34 """
35 tested acceptance strategy, not the final one used, based on a combination of time based and if the bid is better than next.
36 """
37
38 def accept(self, bid: Bid):
39 """
40 acceptance strategy based on combination of time and is bid better than next.
41 """
42 progress = self._progress.get(time.time() * 1000)
43 profile: Profile = self._profile.getProfile()
44 reservation_bid = profile.getReservationBid()
45 if reservation_bid is not None:
46 return (self._isGoodLastBidBetterThanNext(bid) or (progress > .8 and self._isGoodAdjustingConstant(bid))) \
47 and profile.isPreferredOrEqual(profile.getReservationBid(), bid)
48 else:
49 return self._isGoodLastBidBetterThanNext(bid) or (progress > .8 and self._isGoodAdjustingConstant(bid))
50
51 def _isGoodLastBidBetterThanNext(self, bid: Bid):
52 """
53 checks if the incoming bid is better than our next bid.
54 """
55 if bid is None:
56 return False
57
58 profile = self._profile.getProfile()
59 utilityBid = profile.getUtility(bid)
60 utilityNextBid = self._utility.get_last_own_bid_utility()
61 return utilityBid > utilityNextBid
62
63 def _isGoodAdjustingConstant(self, bid: Bid):
64 """
65 Checks if the bid is good when compared to an adjusting constant, like the max utility of all received bids.
66 """
67 if bid is None:
68 return False
69 profile = self._profile.getProfile()
70 bidHistory, utilityHistory, bools = list(zip(*self._utility.get_bid_history()))
71 alpha = max(0.7, max(utilityHistory)) # can also be exchanged for average, base alpha can also be adjusted
72
73 return profile.getUtility(bid) > alpha
74
75
76class BetterThanOwnAcceptanceStrategy(AbstractAcceptanceStrategy):
77 """
78 Not used acceptance strategy based on whether the received bid has a better utility than the last bid we offered.
79 """
80
81 def accept(self, bid: Bid):
82 if bid is None:
83 return False
84
85 profile = self._profile.getProfile()
86 progress = self._progress.get(time.time() * 1000)
87
88 max_util = self._last_made_bid_utility if hasattr(self, "_last_made_bid_utility") else 1
89 # very basic approach that accepts if the offer is valued above 0.6 and
90 # 80% of the rounds towards the deadline have passed
91 return profile.getUtility(bid) > max_util
92
93
94class BetterThanEstimated(AbstractAcceptanceStrategy):
95 """
96 This is the acceptance strategy used, accepts a bid if the received bid offers a similar utility for both parties.
97 The max difference allowed increases as the negotiation progresses in order to avoid losing a deal.
98 """
99
100 def __init__(self, fall_off_util=2, fall_off_difference=4, profile: Profile = None, progress: Progress = None,
101 utility: AgentUtility = None):
102 super(BetterThanEstimated, self).__init__(profile, progress, utility)
103 self.fall_off_util = fall_off_util
104 self.fall_off_difference = fall_off_difference
105
106 def accept(self, bid: Bid):
107 """
108 Acceptance method that will compare the estimated opponent utility and our received utility, from there it will decide
109 to accept the bid based on the progress of the negotiation.
110 """
111 opponent_utility = self.get_utility(bid)
112 own_utility = self._profile.getProfile().getUtility(bid).__float__()
113 max_difference = (np.e ** -(1 - (self._progress.get(time.time() * 1000) ** 2))) / self.fall_off_difference
114
115 reservation_bid = self._profile.getProfile().getReservationBid()
116 if reservation_bid is not None:
117 return (own_utility - opponent_utility) > -max_difference and (own_utility > (1 - max_difference * self.fall_off_util)) and \
118 self._profile.getProfile().isPreferredOrEqual(self._profile.getProfile().getReservationBid(), bid)
119
120 else:
121 return (own_utility - opponent_utility) > -max_difference and (own_utility > (1 - max_difference * self.fall_off_util))
122
123 def get_utility(self, bid):
124 """
125 Method to retrieve the estimated utility of the opponent.
126 """
127 opponent_issue_percentage = self._utility.get_opponent_issue_count()
128 opponent_issue_weights = self._utility.get_weight_heuristic()
129 return self._utility.rate_bid(bid, opponent_issue_percentage, opponent_issue_weights)
Note: See TracBrowser for help on using the repository browser.