1 | from abc import abstractmethod
|
---|
2 | import numpy as np
|
---|
3 | from typing import List, Union
|
---|
4 |
|
---|
5 | from geniusweb.bidspace.AllBidsList import AllBidsList
|
---|
6 | from geniusweb.issuevalue.Bid import Bid
|
---|
7 | from geniusweb.profileconnection.ProfileInterface import ProfileInterface
|
---|
8 |
|
---|
9 | from .utility import AgentUtility
|
---|
10 |
|
---|
11 |
|
---|
12 | class AbstractBiddingStrategy:
|
---|
13 |
|
---|
14 | def __init__(self, profile: ProfileInterface = None, utility: AgentUtility = None):
|
---|
15 | self._profile: ProfileInterface = profile
|
---|
16 | self._utility: AgentUtility = utility
|
---|
17 |
|
---|
18 | def set_profile(self, profile: ProfileInterface):
|
---|
19 | """Setter for profile interface"""
|
---|
20 | self._profile: ProfileInterface = profile
|
---|
21 |
|
---|
22 | def set_utility(self, utility: AgentUtility):
|
---|
23 | """Setter for utility interface"""
|
---|
24 | self._utility: AgentUtility = utility
|
---|
25 |
|
---|
26 |
|
---|
27 | @abstractmethod
|
---|
28 | def get_bid(self) -> Bid:
|
---|
29 | """Method for getting the next bid to make"""
|
---|
30 | pass
|
---|
31 |
|
---|
32 |
|
---|
33 | class BiddingStrategyDeterministic(AbstractBiddingStrategy):
|
---|
34 |
|
---|
35 | def __init__(self, profile=None, utility=None):
|
---|
36 | super().__init__(profile, utility)
|
---|
37 | self._last_made_bid_utility = None
|
---|
38 | if profile is not None:
|
---|
39 | self.bids = self.most_to_least_likely()
|
---|
40 | else:
|
---|
41 | self.bids = []
|
---|
42 |
|
---|
43 | def set_profile(self, profile):
|
---|
44 | """Setter for profile interface, intializes bids list"""
|
---|
45 | self._profile = profile
|
---|
46 | self.bids = self.most_to_least_likely()
|
---|
47 |
|
---|
48 | def get_bid(self):
|
---|
49 | """This strategy determines the rating for a set of bids and returns the bid with the highest expected opponent utility"""
|
---|
50 | possible_bids = []
|
---|
51 | for i in range(self._utility.speed_factor()):
|
---|
52 | possible_bids.append(self.bids.pop())
|
---|
53 | else:
|
---|
54 | possible_bids.append(self.bids.pop())
|
---|
55 |
|
---|
56 | distribution = self.get_bid_distribution(possible_bids)
|
---|
57 | bid = possible_bids[distribution.index(max(distribution))]
|
---|
58 | self._last_made_bid_utility = bid[1]
|
---|
59 | return bid[0]
|
---|
60 |
|
---|
61 |
|
---|
62 | def get_bid_distribution(self, bids):
|
---|
63 | """Method """
|
---|
64 | opponent_issue_percentage = self._utility.get_opponent_issue_count()
|
---|
65 | opponent_issue_weights = self._utility.get_weight_heuristic()
|
---|
66 |
|
---|
67 | distribution: List[float] = []
|
---|
68 | for bid in bids:
|
---|
69 | distribution.append(self._utility.rate_bid(bid[0], opponent_issue_percentage, opponent_issue_weights))
|
---|
70 |
|
---|
71 | total_rating: float = sum(distribution)
|
---|
72 | total_rating: Union[float, int] = total_rating if total_rating != 0 else 1
|
---|
73 | normalized_distribution: List[float] = list(map(lambda x: x / total_rating, distribution))
|
---|
74 |
|
---|
75 | # if normalized distribution is 0 for all entries, return a uniform distribution instead
|
---|
76 | if sum(normalized_distribution) == 0:
|
---|
77 | normalized_distribution = list(map(lambda x: 1 / len(normalized_distribution), normalized_distribution))
|
---|
78 |
|
---|
79 | return normalized_distribution
|
---|
80 |
|
---|
81 | def most_to_least_likely(self):
|
---|
82 | """
|
---|
83 | method for generating the most to least profitable bids in order
|
---|
84 | """
|
---|
85 | domain = self._profile.getProfile().getDomain()
|
---|
86 | all_bids = AllBidsList(domain)
|
---|
87 | bids_values = []
|
---|
88 | for bid in all_bids:
|
---|
89 | bids_values.append((bid, self._profile.getProfile().getUtility(bid)))
|
---|
90 | bids_values.sort(reverse=False, key=lambda x: x[1])
|
---|
91 | return bids_values
|
---|
92 |
|
---|
93 | def getIssueUtilities(self, issue, issue_values):
|
---|
94 | utility_values = []
|
---|
95 | for iv in issue_values:
|
---|
96 | bid = Bid({issue: iv})
|
---|
97 | utility_values.append(self._profile.getProfile().getUtility(bid))
|
---|
98 | return utility_values
|
---|
99 |
|
---|
100 |
|
---|
101 | class BiddingStrategyProbalistic(BiddingStrategyDeterministic):
|
---|
102 |
|
---|
103 | def __init__(self, profile=None, utility=None):
|
---|
104 | super().__init__(profile, utility)
|
---|
105 |
|
---|
106 |
|
---|
107 | def get_bid(self):
|
---|
108 | possible_bids = []
|
---|
109 | for i in range(self._utility.speed_factor()):
|
---|
110 | possible_bids.append(self.bids.pop())
|
---|
111 | else:
|
---|
112 | possible_bids.append(self.bids.pop())
|
---|
113 |
|
---|
114 | distribution = self.get_bid_distribution(possible_bids)
|
---|
115 | bid = possible_bids[np.random.choice(len(possible_bids), p=distribution)]
|
---|
116 | self._last_made_bid_utility = bid[1]
|
---|
117 | return bid[0]
|
---|
118 |
|
---|
119 |
|
---|
120 | class AgressiveBiddingStrategy(AbstractBiddingStrategy):
|
---|
121 | def __init__(self, profile=None, utility=None):
|
---|
122 | super().__init__(profile, utility)
|
---|
123 | self.bids = []
|
---|
124 |
|
---|
125 | def get_bid(self) -> Bid:
|
---|
126 | if len(self.bids) == 0:
|
---|
127 | self.bids = self.get_all_bids_higher_than(0.8)
|
---|
128 |
|
---|
129 | bid = self.bids[np.random.choice(len(self.bids))]
|
---|
130 | self.bids.remove(bid)
|
---|
131 |
|
---|
132 | return bid[0]
|
---|
133 |
|
---|
134 | def get_all_bids_higher_than(self, value: float) -> list:
|
---|
135 | domain = self._profile.getProfile().getDomain()
|
---|
136 | all_bids = AllBidsList(domain)
|
---|
137 | bids_values = []
|
---|
138 | for bid in all_bids:
|
---|
139 | bids_values.append((bid, self._profile.getProfile().getUtility(bid)))
|
---|
140 | bids_values.sort(reverse=False, key=lambda x: x[1])
|
---|
141 | return list(filter(lambda bid: bid[1] > value, bids_values))
|
---|