def _start_negotiations( self, product: int, sell: bool, step: int, qvalues: Tuple[int, int], uvalues: Tuple[int, int], tvalues: Tuple[int, int], partners: List[str], ) -> None: # negotiate with all suppliers of the input product I need to produce issues = [ Issue(qvalues, name="quantity"), Issue(tvalues, name="time"), Issue(uvalues, name="uvalues"), ] for partner in partners: negotiator = self.negotiator(sell, issues=issues) self.neg_history[sell][negotiator.id] = [] self.awi.request_negotiation( is_buy=not sell, product=product, quantity=qvalues, unit_price=uvalues, time=tvalues, partner=partner, negotiator=negotiator, )
def test_lap_ufun_partial_ranking(): issues = [Issue(5, "Price"), Issue(5, "Distance")] gt = {(o["Price"], o["Distance"]): 0.2 * o["Price"] - 0.45 * o["Distance"] for o in Issue.enumerate(issues, astype=dict)} ufun = RankingLAPUfunLearner(issues=issues, degree=1) ufun.fit(ranking_list=[(4, 0), (3, 0), (3, 1), (2, 4), (0, 4)]) assert ufun.theta[0] > 0.0 > ufun.theta[1]
def __init__(self, name: str = 'dlr_negotiation_game', game_type: str = "DRLNegotiation", issues: Optional[List[Issue]] = None, n_steps: int = 100, competitors: Optional[List[Negotiator]] = None, env=None): if competitors is None: competitors = [ MyDRLNegotiator(name="c1", is_seller=False, env=env, init_proposal=False), MyOpponentNegotiator(name="c2", env=env) ] # Default issues used for negotiation game if not issues: issues = [ Issue(values=10, name="quantity"), Issue(values=n_steps, name="delivery_time"), Issue(values=100, name="unit_price") ] super().__init__(name=name, game_type=game_type, issues=issues, n_steps=n_steps, competitors=competitors, env=env)
def _start_negotiations( self, product: int, sell: bool, step: int, qvalues: Tuple[int, int], uvalues: Tuple[int, int], tvalues: Tuple[int, int], partners: List[str], ) -> None: super()._start_negotiations(product, sell, step, qvalues, uvalues, tvalues, partners) issues = [ Issue(qvalues, name="quantity"), Issue(tvalues, name="time"), Issue(uvalues, name="uvalues"), ] sortpartner = {} if self.awi.current_step > 4: reportstep = ((self.awi.current_step // 5) - 1) * 5 for k in self.awi.reports_at_step(reportstep).values(): for ne in partners: if ne == k.agent_id and k.breach_level < 1.0: sortpartner[k.agent_id] = k.breach_level if len(sortpartner) != 0: sortpartners = sorted(sortpartner.items(), key=lambda x: x[1]) sortpartners_list = [i[0] for i in sortpartners] for partner in sortpartners_list: self.awi.request_negotiation( is_buy=not sell, product=product, quantity=qvalues, unit_price=uvalues, time=tvalues, partner=partner, negotiator=self.negotiator(sell, issues=issues), ) else: for partner in partners: self.awi.request_negotiation( is_buy=not sell, product=product, quantity=qvalues, unit_price=uvalues, time=tvalues, partner=partner, negotiator=self.negotiator(sell, issues=issues), ) else: for partner in partners: self.awi.request_negotiation( is_buy=not sell, product=product, quantity=qvalues, unit_price=uvalues, time=tvalues, partner=partner, negotiator=self.negotiator(sell, issues=issues), )
def test_ufun_quality_error_sums(kind): issues = [Issue(5, "Price"), Issue(5, "Distance")] gt = {(o["Price"], o["Distance"]): 0.2 * o["Price"] - 0.45 * o["Distance"] for o in Issue.enumerate(issues, astype=dict)} full_ranking = [ _[0] for _ in sorted( zip(gt.keys(), gt.values()), key=lambda x: x[1], reverse=True) ] ufun = RankingLAPUfunLearner(issues=issues, degree=1, kind=kind) assert (_ufun_objective( [0.2, -0.45], ranking=full_ranking, fs=ufun.fs, n_params=ufun.n_params, tolerance=ufun.tolerance, kind=ufun.kind, ) == 0.0) assert (_ufun_objective( [0.2, 0.4], ranking=full_ranking, fs=ufun.fs, n_params=ufun.n_params, tolerance=ufun.tolerance, kind=ufun.kind, ) > 0.0)
def test_can_run_all_negotiators(asdict): from negmas.helpers import instantiate issues = [Issue((0.0, 1.0), name="price"), Issue(10, name="quantity")] weights = dict(price=1.0, quantity=1.0) if asdict else (1.0, 1.0) for outcome_type in [tuple, dict]: outcomes = Issue.enumerate(issues, max_n_outcomes=100, astype=outcome_type) neg_types = [ ( "RandomNegotiator", dict(ufun=LinearUtilityFunction(weights=weights)), ), ( "AspirationNegotiator", dict(ufun=LinearUtilityFunction(weights=weights)), ), ( "LimitedOutcomesNegotiator", dict(acceptance_probabilities=0.5), ), ( "LimitedOutcomesAcceptor", dict(acceptance_probabilities=0.5), ), ( "ToughNegotiator", dict(ufun=LinearUtilityFunction(weights=weights)), ), ( "OnlyBestNegotiator", dict(ufun=LinearUtilityFunction(weights=weights)), ), ( "NaiveTitForTatNegotiator", dict(ufun=LinearUtilityFunction(weights=weights)), ), ( "SimpleTitForTatNegotiator", dict(ufun=LinearUtilityFunction(weights=weights)), ), ( "NiceNegotiator", dict(ufun=LinearUtilityFunction(weights=weights)), ), ] for i, (neg_type, params) in enumerate(neg_types): for n2, p2 in neg_types: print(f"{neg_type} <> {n2}") n1 = instantiate("negmas.sao." + neg_type, **params) n2 = instantiate("negmas.sao." + n2, **p2) m = SAOMechanism(n_steps=30, issues=issues, outcome_type=dict if asdict else tuple) m.add(n1) m.add(n2) m.run() assert not m.running
def get_domain_issues( domain_file_name: str, force_single_issue=False, max_n_outcomes: int = 1e6, n_discretization: Optional[int] = None, keep_issue_names=True, keep_value_names=True, safe_parsing=False, ) -> Union[Dict[str, Issue], List[Issue]]: """ Returns the issues of a given XML domain (Genius Format) Args: domain_file_name: force_single_issue: max_n_outcomes: n_discretization: keep_issue_names: keep_value_names: safe_parsing: Returns: List or Dict of issues """ issues, issues_details, mechanism = None, None, None if domain_file_name is not None: domain_file_name = str(domain_file_name) issues_details, _ = Issue.from_genius( domain_file_name, force_single_issue=False, keep_issue_names=True, keep_value_names=True, safe_parsing=safe_parsing, n_discretization=n_discretization, ) if force_single_issue: issues, _ = Issue.from_genius( domain_file_name, force_single_issue=force_single_issue, keep_issue_names=keep_issue_names, keep_value_names=keep_value_names, max_n_outcomes=max_n_outcomes, n_discretization=n_discretization, ) if issues is None: return [] else: issues, _ = Issue.from_genius( domain_file_name, force_single_issue=force_single_issue, keep_issue_names=keep_issue_names, keep_value_names=keep_value_names, safe_parsing=safe_parsing, n_discretization=n_discretization, ) return issues if not force_single_issue else [issues]
def start_negotiations( self, product: int, quantity: int, unit_price: int, time: int, to_buy: bool ) -> None: """ Starts a set of negotiations to by/sell the product with the given limits Args: product: product type. If it is an input product, negotiations to buy it will be started otherweise to sell. quantity: The maximum quantity to negotiate about unit_price: The maximum/minimum unit price for buy/sell time: The maximum/minimum time for buy/sell to_buy: Is the negotiation to buy or to sell Remarks: - This method assumes that products cannot be in my_input_products and my_output_products """ if quantity < 1 or unit_price < 1 or time < self.awi.current_step + 1: self.awi.logdebug( f"Less than 2 valid issues (q:{quantity}, u:{unit_price}, t:{time})" ) return # choose ranges for the negotiation agenda. cprice = self.awi.catalog_prices[product] qvalues = (1, quantity) if to_buy: uvalues = (1, cprice) tvalues = (self.awi.current_step + 1, time - 1) partners = self.awi.all_suppliers[product] else: uvalues = (cprice, 2 * cprice) tvalues = (time + 1, self.awi.n_steps - 1) partners = self.awi.all_consumers[product] issues = [ Issue(qvalues, name="quantity", value_type=int), Issue(tvalues, name="time", value_type=int), Issue(uvalues, name="unit_price", value_type=int), ] if Issue.num_outcomes(issues) < 2: self.awi.logdebug( f"Less than 2 issues for product {product}: {[str(_) for _ in issues]}" ) return # negotiate with all suppliers of the input product I need to produce for partner in partners: self.awi.request_negotiation( is_buy=to_buy, product=product, quantity=qvalues, unit_price=uvalues, time=tvalues, partner=partner, negotiator=self.negotiator(not to_buy, issues=issues), )
def test_ranking(ascending): issues = [Issue(5, "Price"), Issue(5, "Distance")] outcomes = Issue.enumerate(issues, astype=tuple) ufun = util.UtilityFunction.generate_random(1, outcomes=outcomes)[0] rank = ranking(ufun, outcomes, ascending=ascending) for r1, r2 in zip(rank[:-1], rank[1:]): assert (ascending and ufun(r1) <= ufun(r2)) or (not ascending and ufun(r1) >= ufun(r2))
def current_output_issues(self) -> List[Issue]: if self.my_output_product == 0: issues = [] else: u, t, q = self._owner._make_issues(self.my_output_product) issues = [ Issue(values=q, name="quantity"), Issue(values=t, name="time"), Issue(values=u, name="unit_price"), ] return issues
def test_partial_ranking(ascending, fraction): issues = [Issue(5, "Price"), Issue(5, "Distance")] outcomes = Issue.enumerate(issues, astype=tuple) ufun = util.UtilityFunction.generate_random(1, outcomes=outcomes)[0] rank = partial(ranking(ufun, outcomes, ascending=ascending), fraction) assert len(rank) == int(len(outcomes) * fraction + 0.5) for r1, r2 in zip(rank[:-1], rank[1:]): assert (ascending and ufun(r1) <= ufun(r2)) or (not ascending and ufun(r1) >= ufun(r2))
def test_can_create_all_negotiator_types(): from negmas.helpers import instantiate issues = [Issue((0.0, 1.0), name="price"), Issue(10, name="quantity")] for outcome_type in [tuple, dict]: outcomes = Issue.enumerate(issues, max_n_outcomes=100, astype=outcome_type) neg_types = [ ( "RandomNegotiator", dict(ufun=LinearUtilityFunction( weights=dict(price=1.0, quantity=1.0))), ), ("LimitedOutcomesNegotiator", dict()), ("LimitedOutcomesAcceptor", dict()), ( "AspirationNegotiator", dict(ufun=LinearUtilityFunction( weights=dict(price=1.0, quantity=1.0))), ), ( "ToughNegotiator", dict(ufun=LinearUtilityFunction( weights=dict(price=1.0, quantity=1.0))), ), ( "OnlyBestNegotiator", dict(ufun=LinearUtilityFunction( weights=dict(price=1.0, quantity=1.0))), ), ( "NaiveTitForTatNegotiator", dict(ufun=LinearUtilityFunction( weights=dict(price=1.0, quantity=1.0))), ), ( "SimpleTitForTatNegotiator", dict(ufun=LinearUtilityFunction( weights=dict(price=1.0, quantity=1.0))), ), ( "NiceNegotiator", dict(ufun=LinearUtilityFunction( weights=dict(price=1.0, quantity=1.0))), ), ] for neg_type, params in neg_types: _ = instantiate("negmas.sao." + neg_type, **params)
def test_from_outcomes(): issues = Issues(price=[2, 3], cost=[1, 2, 3], delivery=["yes", "no"]) found = Issue.from_outcomes(Issue.enumerate(issues.issues)) for i, f in zip(issues.issues, found): assert i.name == f.name assert all(a == b for a, b in zip(sorted(i.values), f._values)) issues = Issues(price=(1, 7), cost=(0, 5), delivery=["yes", "no"]) found = Issue.from_outcomes(Issue.enumerate(issues.issues, max_n_outcomes=1000), numeric_as_ranges=True) for i, f in zip(issues.issues, found): v = sorted(i.values) assert i.name == f.name assert f._values[0] >= v[0] and f._values[1] <= v[1]
def join( self, ami: AgentMechanismInterface, state: MechanismState, *, ufun: Optional["UtilityFunction"] = None, role: str = "agent", ) -> bool: if ufun is None: ufun = self.__ufun_received result = super().join(ami=ami, state=state, ufun=ufun, role=role) if ( result and ufun is not None and (self.utility_file_name is None or self.domain_file_name is None) ): domain_file = tempfile.NamedTemporaryFile("w") self.domain_file_name = domain_file.name domain_file.write(Issue.to_xml_str(ami.issues)) domain_file.close() utility_file = tempfile.NamedTemporaryFile("w") self.utility_file_name = utility_file.name utility_file.write( UtilityFunction.to_xml_str( ufun, issues=ami.issues, discount_factor=self.discount ) ) utility_file.close() return result
def test_cannot_start_a_neg_with_no_outcomes(): world = DummyWorld(n_steps=10) a, b = DummyAgent(name="a"), DummyAgent(name="b") world.join(a) world.join(b) assert not a.awi.request_negotiation_about( issues=[Issue((1, 0))], partners=[a.id, b.id], req_id="1234")
def test_issues_construction(): issues = Issues(price=(0.0, 1.0), cost=[1, 2, 3], delivery=["yes", "no"]) assert len(issues.issues) == 3 assert str( issues ) == "price: (0.0, 1.0)\ncost: [1, 2, 3]\ndelivery: ['yes', 'no']" assert issues.is_infinite() assert not issues.is_finite() assert all( a == b for a, b in zip(issues.types, ["continuous", "discrete", "discrete"])) issues = Issues.from_single_issue(Issue(10, "issue")) assert len(issues.issues) == 1 assert str(issues) == "issue: (0, 9)" issues = Issues(price=[2, 3], cost=[1, 2, 3], delivery=["yes", "no"]) assert issues.is_finite() assert not issues.is_infinite() assert issues.cardinality == issues.num_outcomes == 2 * 3 * 2 valid = issues.rand_valid() invalid = issues.rand_invalid() assert outcome_in_range(valid, issues.outcome_range) assert outcome_in_range(invalid, issues.outcome_range)
def test_single_agreement_gets_one_agreement(n_negs, strict): from negmas.mechanisms import Mechanism from negmas.sao import SAOSingleAgreementRandomController, AspirationNegotiator c = SAOSingleAgreementRandomController(strict=strict) negs = [ SAOMechanism(issues=[Issue((0.0, 1.0), "price")], n_steps=50, outcome_type=tuple) for _ in range(n_negs) ] for i, neg in enumerate(negs): neg.add( AspirationNegotiator(aspiration_type="linear", name=f"opponent-{i}"), ufun=LinearUtilityFunction(weights=[1.0]), ) neg.add(c.create_negotiator(name=f"against-{i}")) Mechanism.runall(negs, True) agreements = [neg.state.agreement for neg in negs] if strict: # assert that the controller never had multiple agreements assert sum(_ is not None for _ in agreements) == 1 else: # assert that the controller never accepted twice. It may still have multiple agreements though assert (len([ neg.state.agreement for neg in negs if neg.state.agreement is not None and neg.state.current_proposer.startswith("opponent") ]) < 2)
def test_loops_are_broken(keep_order): """Tests that loops formed by concurrent negotiations are broken for syn controllers""" from negmas.mechanisms import Mechanism from negmas.sao import SAOSingleAgreementAspirationController a, b, c = ( SAOSingleAgreementAspirationController( ufun=MappingUtilityFunction(lambda x: x["price"]), strict=False ), SAOSingleAgreementAspirationController( ufun=MappingUtilityFunction(lambda x: x["price"]), strict=False ), SAOSingleAgreementAspirationController( ufun=MappingUtilityFunction(lambda x: x["price"]), strict=False ), ) n1 = SAOMechanism( name="ab", issues=[Issue((0.0, 1.0), "price")], n_steps=50, outcome_type=dict, ) n2 = SAOMechanism( name="ac", issues=[Issue((0.0, 1.0), "price")], n_steps=50, outcome_type=dict, ) n3 = SAOMechanism( name="bc", issues=[Issue((0.0, 1.0), "price")], n_steps=50, outcome_type=dict, ) n1.add(a.create_negotiator(name="a>b")) n1.add(b.create_negotiator(name="b>a")) n2.add(a.create_negotiator(name="a>c")) n2.add(c.create_negotiator(name="c>a")) n3.add(b.create_negotiator(name="b>c")) n3.add(c.create_negotiator(name="c>b")) negs = [n1, n2, n3] Mechanism.runall(negs, keep_order) agreements = [neg.state.agreement for neg in negs] assert not keep_order or sum(_ is not None for _ in agreements) > 0
def test_opponent_negotiator(): from drl_negotiation.negotiator import MyOpponentNegotiator from negmas import Issue, SAOMechanism from drl_negotiation.utility_functions import MyUtilityFunction name = "test_opponent_negotiator" # seller weights = (0, 0.25, 1) issues = [ Issue(values=10, name="quantity"), Issue(values=100, name="delivery_time"), Issue(values=100, name="unit_price") ] mechanism = SAOMechanism(issues=issues, n_steps=100) ufun = MyUtilityFunction(weights=weights, ami=mechanism.ami) opponent_negotiator = MyOpponentNegotiator(name=name, ufun=ufun) mechanism.add(opponent_negotiator)
def step(self): global results self.current_step = self.awi.current_step if (self.current_step == 2 and self.name.endswith('1')) or (self.current_step == 4 and self.name.endswith('2')): issues = [Issue(10)] partners = self.awi.state['partners'] self.request_negotiation(partners=[_.name for _ in partners] + [self.name], issues=issues) results.append(f'{self.name} started negotiation with {partners[0].name}') results.append(f'{self.name}: step {self.current_step}')
def negotiator(self, is_seller: bool, issues=None, outcomes=None) -> SAONegotiator: if outcomes is None and ( issues is None or not Issue.enumerate(issues, astype=tuple) ): return None params = self.negotiator_params params["ufun"] = self.create_ufun( is_seller=is_seller, outcomes=outcomes, issues=issues ) return instantiate(self.negotiator_type, **params)
def _start_negotiations(self, product, sell, step, qvalues, uvalues, tvalues, partners): issues = [ Issue(qvalues, name="quantity"), Issue(tvalues, name="time"), Issue(uvalues, name="uvalues"), ] for partner in partners: if partner in self.brothers: self.neg_extras["brother"] = True else: self.neg_extras["brother"] = False if sell: if self.did_sell: self.neg_extras["threshold"] = min( 0.9, self.neg_extras["threshold"] + 0.05 * 2) else: self.neg_extras["threshold"] = max( 0.4, self.neg_extras["threshold"] - 0.05 * 4) else: if self.did_buy: self.neg_extras["threshold"] = min( 0.9, self.neg_extras["threshold"] + 0.05 * 2) else: self.neg_extras["threshold"] = max( 0.4, self.neg_extras["threshold"] - 0.05 * 4) neg = self.negotiator(sell, issues=issues) self.awi.request_negotiation( is_buy=not sell, product=product, quantity=qvalues, unit_price=uvalues, time=tvalues, partner=partner, extra=self.neg_extras, negotiator=neg, )
def test_issue_generation_defaults(): options = ["a", "b", "c"] issues = Issue.generate([(0.0, 1.0), options, 5]) assert len(issues) == 3 assert (issues[0].is_continuous() and issues[0].values[0] == 0.0 and issues[0].values[1] == 1.0) for i, o in enumerate(options): assert issues[1].values[i] == o assert issues[2].values == 5 for i, issue in enumerate(issues): assert str(i) == issue.name
def on_ufun_changed(self): super().on_ufun_changed() presort = self.presort if (not presort and all(i.is_countable() for i in self._ami.issues) and Issue.num_outcomes( self._ami.issues) >= self.n_outcomes_to_force_presort): presort = True if presort: outcomes = self._ami.discrete_outcomes() uvals = self.utility_function.eval_all(outcomes) uvals_outcomes = [(u, o) for u, o in zip(uvals, outcomes) if u >= self.utility_function.reserved_value] self.ordered_outcomes = sorted( uvals_outcomes, key=lambda x: float(x[0]) if x[0] is not None else float("-inf"), reverse=True, ) if self.assume_normalized: self.ufun_min, self.ufun_max = 0.0, 1.0 elif len(self.ordered_outcomes) < 1: self.ufun_max = self.ufun_min = self.utility_function.reserved_value else: if self.ufun_max is None: self.ufun_max = self.ordered_outcomes[0][0] if self.ufun_min is None: # we set the minimum utility to the minimum finite value above both reserved_value for j in range(len(self.ordered_outcomes) - 1, -1, -1): self.ufun_min = self.ordered_outcomes[j][0] if self.ufun_min is not None and self.ufun_min > float( "-inf"): break if (self.ufun_min is not None and self.ufun_min < self.reserved_value): self.ufun_min = self.reserved_value else: if (self.ufun_min is None or self.ufun_max is None or self.best_outcome is None or self.worst_outcome is None): mn, mx, self.worst_outcome, self.best_outcome = utility_range( self.ufun, return_outcomes=True, issues=self._ami.issues) if self.ufun_min is None: self.ufun_min = mn if self.ufun_max is None: self.ufun_max = mx if self.ufun_min < self.reserved_value: self.ufun_min = self.reserved_value if self.ufun_max < self.ufun_min: self.ufun_max = self.ufun_min self.presorted = presort self.n_trials = 10
def negotiator(self, is_seller: bool, issues=None) -> Optional[SAONegotiator]: """Creates a negotiator""" if issues is None or not Issue.enumerate(issues, astype=tuple): return None return AspirationNegotiator( ufun=self.create_ufun(is_seller=is_seller, issues=issues), assume_normalized=True, )
def test_lap_ufun_full_ranking(): issues = [Issue(5, "Price"), Issue(5, "Distance")] gt = {(o["Price"], o["Distance"]): 0.2 * o["Price"] - 0.45 * o["Distance"] for o in Issue.enumerate(issues, astype=dict)} full_ranking = [ _[0] for _ in sorted( zip(gt.keys(), gt.values()), key=lambda x: x[1], reverse=True) ] for kind in ("error_sums", "errors"): ufun = RankingLAPUfunLearner(issues=issues, degree=1, kind=kind) ufun.fit(ranking_list=full_ranking) learned_ranking = [ _[0] for _ in sorted( zip(ufun.uvals.keys(), ufun.uvals.values()), key=lambda x: x[1], reverse=True, ) ] if kind == "error_sums": assert full_ranking == learned_ranking, f"Failed on {kind}" assert (ufun.ranking_error(gt=MappingUtilityFunction( lambda o: 0.2 * o[0] - 0.45 * o[1])) == 0.0)
def reset(self, env=None): self._dissociate() if env: self.set_env(env=env) self._action = None self._proposal_offer = None self._current_offer_offer = None if self.init_proposal: self._ip = Issue.sample(issues=[Issue(self._ip_range)], n_outcomes=1, astype=tuple)[0] self._rp = Issue.sample(issues=[Issue(self._rp_range)], n_outcomes=1, astype=tuple)[0] if "ip" in self.ufun.__dict__: self.ufun.ip = self._ip self.set_proposal_offer(self._ip) if "rp" in self.ufun.__dict__: self.ufun.rp = self._rp self.end_time = 1
def step(self): global results if self.awi is None: return self.__current_step = self.awi.current_step if (self.__current_step == 2 and self.name.endswith("1")) or ( self.__current_step == 4 and self.name.endswith("2") ): issues = [Issue(10, name="i1")] partners = self.awi.state["partners"] self._request_negotiation( partners=[_.name for _ in partners] + [self.name], issues=issues ) results.append(f"{self.name} started negotiation with {partners[0].name}") results.append(f"{self.name}: step {self.__current_step}")
def before_step(self): self.__endall = not self.awi.is_first_level and not self.awi.is_last_level if self.__endall: return # we assume that we are either in the first or the latest layer # and calculate our ufun limits and reserved value self.ufun.reserved_value = self.ufun.from_contracts([]) self._reserved_value = self.ufun.reserved_value AspirationMixin.aspiration_init( self, max_aspiration=1.0, aspiration_type=float(random.randint(1, 4)) if random.random() < 0.7 else random.random(), above_reserved_value=False, ) # if self.awi.current_exogenous_input_quantity or self.awi.current_exogenous_output_quantity: # breakpoint() self._limit = self.ufun.find_limit(True, int(self.awi.is_last_level), int(self.awi.is_first_level)) self._max_utility = self._limit.utility urange = self._max_utility - self._reserved_value if urange <= 1e-5: urange = 1e-5 self._urange = urange if self.awi.is_last_level: self._best = (self._limit.input_quantity, self._limit.input_price) else: self._best = (self._limit.output_quantity, self._limit.output_price) # compile a list of all outcomes with their utilities and sort it # descendigly by utility issues = (self.awi.current_output_issues if self.awi.is_first_level else self.awi.current_output_issues) outcomes = list(Issue.enumerate(issues, astype=tuple)) self._outcomes = sorted( zip( ((self.ufun.from_offers([_], [self.awi.is_first_level]) - self._reserved_value) / (self._urange) for _ in outcomes), outcomes, ), key=lambda x: -x[0], ) self._last_index = 0
def __init__( self, *args, issues: Optional[List[Issue]], outcomes: List[Outcome] = None, **kwargs, ): super().__init__(*args, **kwargs) if issues is None and outcomes is None: raise ValueError("Neither issues nor outcomes was given") self.issues = issues if outcomes is not None: self.outcomes = [ outcome.values() if isinstance(outcome, dict) else outcome if isinstance(outcome, tuple) else outcome.astuple() for outcome in outcomes ] else: self.outcomes = Issue.enumerate(issues=issues, astype=tuple) self.issue_names = [issue.name for issue in issues]