source: ANL2022/gea_agent/utils/opponent_model.py

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

#6 added ANAC2022 parties

File size: 4.2 KB
Line 
1from collections import defaultdict
2
3from geniusweb.issuevalue.Bid import Bid
4from geniusweb.issuevalue.DiscreteValueSet import DiscreteValueSet
5from geniusweb.issuevalue.Domain import Domain
6from geniusweb.issuevalue.Value import Value
7
8
9class OpponentModel:
10 def __init__(self, domain: Domain):
11 self.offers = []
12 self.domain = domain
13
14 self.issue_estimators = {
15 i: IssueEstimator(v) for i, v in domain.getIssuesValues().items()
16 }
17
18
19 def update(self, bid: Bid):
20 # keep track of all bids received
21 self.offers.append(bid)
22
23 # update all issue estimators with the value that is offered for that issue
24 for issue_id, issue_estimator in self.issue_estimators.items():
25 issue_estimator.update(bid.getValue(issue_id))
26
27 def get_predicted_utility(self, bid: Bid):
28 if len(self.offers) == 0 or bid is None:
29 return 0
30
31 # initiate
32 total_issue_weight = 0.0
33 value_utilities = []
34 issue_weights = []
35
36 for issue_id, issue_estimator in self.issue_estimators.items():
37 # get the value that is set for this issue in the bid
38 value: Value = bid.getValue(issue_id)
39
40 # collect both the predicted weight for the issue and
41 # predicted utility of the value within this issue
42 value_utilities.append(issue_estimator.get_value_utility(value))
43 issue_weights.append(issue_estimator.weight)
44
45 total_issue_weight += issue_estimator.weight
46
47 # normalise the issue weights such that the sum is 1.0
48 if total_issue_weight == 0.0:
49 issue_weights = [1 / len(issue_weights) for _ in issue_weights]
50 else:
51 issue_weights = [iw / total_issue_weight for iw in issue_weights]
52
53 # calculate predicted utility by multiplying all value utilities with their issue weight
54 predicted_utility = sum(
55 [iw * vu for iw, vu in zip(issue_weights, value_utilities)]
56 )
57
58 return predicted_utility
59
60
61class IssueEstimator:
62 def __init__(self, value_set: DiscreteValueSet):
63 if not isinstance(value_set, DiscreteValueSet):
64 raise TypeError(
65 "This issue estimator only supports issues with discrete values"
66 )
67
68 self.bids_received = 0
69 self.max_value_count = 0
70 self.num_values = value_set.size()
71 self.value_trackers = defaultdict(ValueEstimator)
72 self.weight = 0
73
74 def update(self, value: Value):
75 self.bids_received += 1
76
77 # get the value tracker of the value that is offered
78 value_tracker = self.value_trackers[value]
79
80 # register that this value was offered
81 value_tracker.update()
82
83 # update the count of the most common offered value
84 self.max_value_count = max([value_tracker.count, self.max_value_count])
85
86 # update predicted issue weight
87 # the intuition here is that if the values of the receiverd offers spread out over all
88 # possible values, then this issue is likely not important to the opponent (weight == 0.0).
89 # If all received offers proposed the same value for this issue,
90 # then the predicted issue weight == 1.0
91 equal_shares = self.bids_received / self.num_values
92 self.weight = (self.max_value_count - equal_shares) / (
93 self.bids_received - equal_shares
94 )
95
96 # recalculate all value utilities
97 for value_tracker in self.value_trackers.values():
98 value_tracker.recalculate_utility(self.max_value_count, self.weight)
99
100 def get_value_utility(self, value: Value):
101 if value in self.value_trackers:
102 return self.value_trackers[value].utility
103
104 return 0
105
106
107class ValueEstimator:
108 def __init__(self):
109 self.count = 0
110 self.utility = 0
111
112 def update(self):
113 self.count += 1
114
115 def recalculate_utility(self, max_value_count: int, weight: float):
116 if weight < 1:
117 mod_value_count = ((self.count + 1) ** (1 - weight)) - 1
118 mod_max_value_count = ((max_value_count + 1) ** (1 - weight)) - 1
119
120 self.utility = mod_value_count / mod_max_value_count
121 else:
122 self.utility = 1
Note: See TracBrowser for help on using the repository browser.