[74] | 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))
|
---|