def test_pareto_frontier_does_not_depend_on_order(): u1 = [ 0.5337723805661662, 0.8532272031479199, 0.4781281413197942, 0.7242899747791032, 0.3461879818432919, 0.2608677043479706, 0.9419131964655383, 0.29368079952747694, 0.6093201983562316, 0.7066918086398718, ] u2 = [0.0, 0.0, 1.0, 1.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0.0] welfare = [_1 + _2 for _1, _2 in zip(u1, u2)] assert welfare.index(max(welfare)) == 3 f1 = MappingUtilityFunction(lambda o: u1[o[0]]) f2 = MappingUtilityFunction(lambda o: u2[o[0]]) assert all(f1((i,)) == u1[i] for i in range(10)) assert all(f2((i,)) == u2[i] for i in range(10)) p1, l1 = pareto_frontier([f1, f2], outcomes=[(_,) for _ in range(10)]) p2, l2 = pareto_frontier([f2, f1], outcomes=[(_,) for _ in range(10)]) assert p1 == [(0.9419131964655383, 0.0), (0.7242899747791032, 1.0)] assert p2 == [(1.0, 0.7242899747791032), (0.0, 0.9419131964655383)] assert l1 == [6, 3] assert l2 == list(reversed(l1)) assert len(p1) == len(p2) # reverse order of p2 p2 = [(_[1], _[0]) for _ in p2] for a in p1: assert a in p2
def add( self, negotiator: "Negotiator", *, ufun: Optional["UtilityFunction"] = None, role: Optional[str] = None, **kwargs, ) -> Optional[bool]: """Add an agent to the negotiation. Args: negotiator: The agent to be added. ufun: The utility function to use. If None, then the agent must already have a stored utility function otherwise it will fail to enter the negotiation. role: The role the agent plays in the negotiation mechanism. It is expected that mechanisms inheriting from this class will check this parameter to ensure that the role is a valid role and is still possible for negotiators to join on that role. Roles may include things like moderator, representative etc based on the mechanism Returns: * True if the agent was added. * False if the agent was already in the negotiation. * None if the agent cannot be added. """ if not self.can_enter(negotiator): return None if negotiator in self._negotiators: return False if isinstance(ufun, Iterable) and not isinstance(ufun, UtilityFunction): if isinstance(ufun, dict): ufun = MappingUtilityFunction(mapping=ufun, ami=self.ami) else: ufun = MappingUtilityFunction(mapping=dict( zip(self.outcomes, ufun)), ami=self.ami) if role is None: role = "agent" if negotiator.join(ami=self._get_ami(negotiator, role), state=self.state, ufun=ufun, role=role): self._negotiators.append(negotiator) self._negotiator_map[negotiator.id] = negotiator self._roles.append(role) self.role_of_agent[negotiator.uuid] = role self.agents_of_role[role].append(negotiator) if negotiator.ufun is not None: if hasattr(negotiator.ufun, "ami"): negotiator.ufun.ami = self.ami return True return None
def respond_to_negotiation_request( self, cfp: "CFP", partner: str ) -> Optional[Negotiator]: if self.awi.is_bankrupt(partner): return None profile = self.profiles.get(cfp.product) if profile is None: return None if profile.cv == 0: alpha_u, alpha_q = profile.alpha_u, profile.alpha_q else: alpha_u, alpha_q = tuple( dirichlet((profile.alpha_u, profile.alpha_q), size=1)[0] ) beta_u = pos_gauss(profile.beta_u, profile.cv) tau_u = pos_gauss(profile.tau_u, profile.cv) tau_q = pos_gauss(profile.tau_q, profile.cv) ufun = ComplexWeightedUtilityFunction( ufuns=[ MappingUtilityFunction( mapping=lambda x: 1 - x["unit_price"] ** tau_u / beta_u ), MappingUtilityFunction( mapping=functools.partial( JustInTimeConsumer._qufun, tau=tau_q, profile=profile ) ), ], weights=[alpha_u, alpha_q], name=self.name + "_" + partner[:4], ) negotiator = self.negotiator_type(name=self.name + "*" + partner[:4], ufun=ufun) # negotiator.utility_function = ufun return negotiator
def on_negotiation_request(self, cfp: "CFP", partner: str) -> Optional[NegotiatorProxy]: profile = self.profiles[cfp.product] if profile.cv == 0: alpha_u, alpha_q = profile.alpha_u, profile.alpha_q else: alpha_u, alpha_q = tuple( dirichlet((profile.alpha_u, profile.alpha_q), size=1)[0]) beta_u = pos_gauss(profile.beta_u, profile.cv) tau_u = pos_gauss(profile.tau_u, profile.cv) tau_q = pos_gauss(profile.tau_q, profile.cv) ufun = normalize(ComplexWeightedUtilityFunction( ufuns=[ MappingUtilityFunction( mapping=lambda x: 1 - x['unit_price']**tau_u / beta_u), MappingUtilityFunction(mapping=functools.partial( ScheduleDrivenConsumer._qufun, tau=tau_q, profile=profile)) ], weights=[alpha_u, alpha_q], name=self.name + '_' + partner), outcomes=cfp.outcomes, infeasible_cutoff=-1500) if self.negotiator_type == AspirationNegotiator: negotiator = self.negotiator_type(assume_normalized=True, name=self.name + '*' + partner, aspiration_type='boulware') else: negotiator = self.negotiator_type(name=self.name + '*' + partner) negotiator.name = self.name + '_' + partner negotiator.utility_function = ufun return negotiator
def respond_to_negotiation_request(self, cfp: "CFP", partner: str) -> Optional[Negotiator]: if self.awi.is_bankrupt(partner): return None profile = self.profiles.get(cfp.product) if profile is None: return None if profile.cv == 0: alpha_u, alpha_q = profile.alpha_u, profile.alpha_q else: alpha_u, alpha_q = tuple( dirichlet((profile.alpha_u, profile.alpha_q), size=1)[0]) beta_u = pos_gauss(profile.beta_u, profile.cv) tau_u = pos_gauss(profile.tau_u, profile.cv) tau_q = pos_gauss(profile.tau_q, profile.cv) ufun = ComplexWeightedUtilityFunction( ufuns=[ MappingUtilityFunction( mapping=lambda x: 1 - x["unit_price"]**tau_u / beta_u), MappingUtilityFunction(mapping=functools.partial( ScheduleDrivenConsumer._qufun, tau=tau_q, profile=profile)), ], weights=[alpha_u, alpha_q], name=self.name + "_" + partner, ) ufun.reserved_value = -1500 # ufun = normalize(, outcomes=cfp.outcomes, infeasible_cutoff=-1500) negotiator = self.negotiator_type(name=self.name + "*" + partner, ufun=ufun) # negotiator.utility_function = ufun return negotiator
def test_exceptions_are_saved(): n_outcomes, n_negotiators = 10, 2 mechanism = SAOMechanism( outcomes=n_outcomes, n_steps=n_outcomes, ignore_negotiator_exceptions=True ) ufuns = MappingUtilityFunction.generate_random( n_negotiators, outcomes=mechanism.outcomes ) mechanism.add(AspirationNegotiator(name=f"agent{0}"), ufun=ufuns[0]) mechanism.add(MyRaisingNegotiator(name=f"agent{1}"), ufun=ufuns[1]) assert mechanism.state.step == 0 mechanism.step() mechanism.step() mechanism.step() assert mechanism.state.step == 1 assert mechanism._current_offer is not None assert len(mechanism.stats) == 3 stats = mechanism.stats assert "times" in stats.keys() assert "exceptions" in stats.keys() assert stats["exceptions"] is not None assert len(stats["exceptions"]) == 1 # print(stats["exceptions"][mechanism.negotiators[1].id]) assert len(stats["exceptions"][mechanism.negotiators[1].id]) == 1 assert exception_str in stats["exceptions"][mechanism.negotiators[1].id][0] assert len(stats["exceptions"][mechanism.negotiators[0].id]) == 0
def test_neg_sync_loop(keep_order): # from pprint import pprint n_outcomes, n_steps = 10, 10 waste_center = 0.1 c1 = MySyncController(sleep_seconds=waste_center, name="c1") c2 = MySyncController(sleep_seconds=waste_center, name="c2") mechanisms = [] for m in range(2): mechanism = SAOMechanism( outcomes=n_outcomes, n_steps=n_steps, ignore_negotiator_exceptions=False, avoid_ultimatum=False, name=f"{m}", ) ufuns = MappingUtilityFunction.generate_random(2, outcomes=mechanism.outcomes) mechanism.add(c1.create_negotiator(ufun=ufuns[0], id=f"0-{m}", name=f"0-{m}")) mechanism.add(c2.create_negotiator(ufun=ufuns[1], id=f"1-{m}", name=f"1-{m}")) mechanisms.append(mechanism) SAOMechanism.runall(mechanisms, keep_order=keep_order) for mechanism in mechanisms: assert mechanism.state.started assert mechanism.state.agreement is None assert not mechanism.state.has_error assert not mechanism.state.broken assert mechanism.state.timedout assert mechanism.state.step == n_steps assert not mechanism.state.waiting assert len(mechanism.history) == n_steps
def test_pickling_mechanism(tmp_path): import dill as pickle file = tmp_path / "mechanism.pck" n_outcomes, n_negotiators = 5, 3 mechanism = SAOMechanism( outcomes=n_outcomes, n_steps=3, offering_is_accepting=True, avoid_ultimatum=False, ) ufuns = MappingUtilityFunction.generate_random(n_negotiators, outcomes=n_outcomes) for i in range(n_negotiators): mechanism.add(AspirationNegotiator(name=f"agent{i}"), ufun=ufuns[i]) assert mechanism.state.step == 0 with open(file, "wb") as f: pickle.dump(mechanism, f) with open(file, "rb") as f: pickle.load(f) assert mechanism.state.step == 0 mechanism.step() with open(file, "wb") as f: pickle.dump(mechanism, f) with open(file, "rb") as f: pickle.load(f) assert mechanism.state.step == 1
def init_limited_outcomes_acceptor( self, outcomes: Optional[Union[int, Iterable['Outcome']]] = None, acceptable_outcomes: Optional[Iterable['Outcome']] = None, acceptance_probabilities: Optional[List[float]] = None, p_ending=.05, p_no_response=0.0, ) -> None: """Constructor Args: acceptable_outcomes (Optional[Floats]): the set of acceptable outcomes. If None then it is assumed to be all the outcomes of the negotiation. acceptance_probabilities (Sequence[int]): probability of accepting each acceptable outcome. If None then it is assumed to be unity. p_no_response (float): probability of refusing to respond to offers p_ending (float): probability of ending negotiation Returns: None """ self.add_capabilities({ 'respond': True, }) if acceptable_outcomes is not None and outcomes is None: raise ValueError( 'If you are passing acceptable outcomes explicitly then outcomes must also be passed' ) if isinstance(outcomes, int): outcomes = [(_, ) for _ in range(outcomes)] self.outcomes = outcomes if acceptable_outcomes is not None: acceptable_outcomes = list(acceptable_outcomes) self.acceptable_outcomes = acceptable_outcomes if acceptable_outcomes is None: if acceptance_probabilities is None: acceptance_probabilities = [0.5] * len(outcomes) self.acceptable_outcomes = outcomes else: self.acceptable_outcomes = outcomes elif acceptance_probabilities is None: acceptance_probabilities = [1.0] * len(acceptable_outcomes) if outcomes is None: self.outcomes = [(_, ) for _ in range(len(acceptable_outcomes))] if self.outcomes is None: raise ValueError( 'Could not calculate all the outcomes. It is needed to assign a utility function' ) self.acceptance_probabilities = acceptance_probabilities u = [0.0] * len(self.outcomes) for p, o in zip(self.acceptance_probabilities, self.acceptable_outcomes): u[self.outcomes.index(o)] = p self.utility_function = MappingUtilityFunction( dict(zip(self.outcomes, u))) self.p_no_response = p_no_response self.p_ending = p_ending + p_no_response
def test_times_are_calculated(n_outcomes, n_negotiators, n_steps): mechanism = SAOMechanism(outcomes=n_outcomes, n_steps=8) ufuns = MappingUtilityFunction.generate_random(n_negotiators, outcomes=n_outcomes) for i in range(n_negotiators): mechanism.add(AspirationNegotiator(name=f"agent{i}"), ufun=ufuns[i]) assert mechanism.state.step == 0 _strt = time.perf_counter() for _ in range(n_steps): # print(f"Stepping: {_}") mechanism.step() time.sleep(0.01) duration = time.perf_counter() - _strt # assert mechanism.current_step == n_steps assert mechanism._current_offer is not None assert len(mechanism.stats) == 3 stats = mechanism.stats assert "round_times" in stats.keys() assert 0 < sum(stats["round_times"]) < duration assert "times" in stats.keys() assert "exceptions" in stats.keys() assert stats["times"] is not None assert stats["exceptions"] is not None assert len(stats["times"]) == n_negotiators assert len(stats["exceptions"]) == 0 for i in range(n_negotiators): assert 0 < stats["times"][mechanism.negotiators[i].id] < duration assert len(stats["exceptions"][mechanism.negotiators[i].id]) == 0 assert 0 < sum(stats["times"].values()) < duration
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_mechanism_can_run(n_negotiators): n_outcomes = 5 mechanism = SAOMechanism(outcomes=n_outcomes, n_steps=3) ufuns = MappingUtilityFunction.generate_random(n_negotiators, outcomes=n_outcomes) for i in range(n_negotiators): mechanism.add(AspirationNegotiator(name=f"agent{i}"), ufun=ufuns[i]) assert mechanism.state.step == 0 mechanism.step() mechanism.run()
def master(true_utilities, strategy_name="titration-0.05"): user = User( ufun=MappingUtilityFunction( dict(zip([(_,) for _ in range(n_outcomes)], true_utilities)), reserved_value=0.0, ), cost=cost, ) strategy = EStrategy(strategy=strategy_name) return user, strategy
def test_round_n_agents(n_negotiators): n_outcomes = 5 mechanism = SAOMechanism(outcomes=n_outcomes, n_steps=3) ufuns = MappingUtilityFunction.generate_random(n_negotiators, outcomes=n_outcomes) for i in range(n_negotiators): mechanism.add(AspirationNegotiator(name=f"agent{i}"), ufun=ufuns[i]) assert mechanism.state.step == 0 mechanism.step() assert mechanism.state.step == 1 assert mechanism._current_offer is not None
def test_ufun_range_general(n_issues): issues = [Issue(values=(0.0, 1.0), name=f"i{i}") for i in range(n_issues)] rs = [(i + 1.0) * random.random() for i in range(n_issues)] ufun = MappingUtilityFunction( mapping=lambda x: sum(r * v for r, v in zip(rs, outcome_as_tuple(x))), outcome_type=tuple, ) assert ufun([0.0] * n_issues) == 0.0 assert ufun([1.0] * n_issues) == sum(rs) rng = utility_range(ufun, issues=issues) assert rng[0] >= 0.0 assert rng[1] <= sum(rs)
def test_checkpointing_mechanism(tmp_path): file = tmp_path n_outcomes, n_negotiators = 5, 3 mechanism = SAOMechanism( outcomes=n_outcomes, n_steps=3, offering_is_accepting=True, avoid_ultimatum=False, ) ufuns = MappingUtilityFunction.generate_random(n_negotiators, outcomes=n_outcomes) for i in range(n_negotiators): mechanism.add(AspirationNegotiator(name=f"agent{i}"), ufun=ufuns[i]) assert mechanism.state.step == 0 file_name = mechanism.checkpoint(file) info = SAOMechanism.checkpoint_info(file_name) assert isinstance(info["time"], str) assert info["step"] == 0 assert info["type"].endswith("SAOMechanism") assert info["id"] == mechanism.id assert info["name"] == mechanism.name mechanism, info = SAOMechanism.from_checkpoint(file_name, return_info=True) assert isinstance(info["time"], str) assert info["step"] == 0 assert info["type"].endswith("SAOMechanism") assert info["id"] == mechanism.id assert info["name"] == mechanism.name assert mechanism.state.step == 0 mechanism.step() file_name = mechanism.checkpoint(file) info = SAOMechanism.checkpoint_info(file_name) assert isinstance(info["time"], str) assert info["step"] == 1 assert info["type"].endswith("SAOMechanism") assert info["id"] == mechanism.id assert info["name"] == mechanism.name mechanism, info = SAOMechanism.from_checkpoint(file_name, return_info=True) assert isinstance(info["time"], str) assert info["step"] == 1 assert info["type"].endswith("SAOMechanism") assert info["id"] == mechanism.id assert info["name"] == mechanism.name mechanism.run()
def test_neg_run_no_waiting(): n_outcomes, n_steps, waste = 10, 10, 0.5 mechanism = SAOMechanism( outcomes=n_outcomes, n_steps=n_steps, ignore_negotiator_exceptions=True ) ufuns = MappingUtilityFunction.generate_random(2, outcomes=mechanism.outcomes) mechanism.add(TimeWaster(name=f"agent{0}", sleep_seconds=waste, ufun=ufuns[0])) mechanism.add(TimeWaster(name=f"agent{1}", sleep_seconds=waste, ufun=ufuns[1])) mechanism.run() assert mechanism.state.agreement is None assert mechanism.state.started assert mechanism.state.timedout assert mechanism.state.step == n_steps assert not mechanism.state.waiting assert len(mechanism.history) == n_steps for _, v in mechanism.stats["times"].items(): assert v >= waste * n_steps
def test_mechanism_runall(n_negotiators, oia): n_outcomes = 5 mechanisms = [] for _ in range(10): mechanism = SAOMechanism( outcomes=n_outcomes, n_steps=random.randint(3, 20), offering_is_accepting=oia, avoid_ultimatum=False, ) ufuns = MappingUtilityFunction.generate_random(1, outcomes=n_outcomes) for i in range(n_negotiators): mechanism.add(AspirationNegotiator(name=f"agent{i}"), ufun=ufuns[0]) mechanisms.append(mechanism) states = SAOMechanism.runall(mechanisms) assert len(states) == 10 assert not any(_.running for _ in states)
def test_auto_checkpoint(tmp_path, single_checkpoint, checkpoint_every, exist_ok): import shutil new_folder: Path = tmp_path / unique_name("empty", sep="") new_folder.mkdir(parents=True, exist_ok=True) shutil.rmtree(new_folder) new_folder.mkdir(parents=True, exist_ok=True) filename = "mechanism" n_outcomes, n_negotiators = 5, 3 n_steps = 50 mechanism = SAOMechanism( outcomes=n_outcomes, n_steps=n_steps, offering_is_accepting=True, avoid_ultimatum=False, checkpoint_every=checkpoint_every, checkpoint_folder=new_folder, checkpoint_filename=filename, extra_checkpoint_info=None, exist_ok=exist_ok, single_checkpoint=single_checkpoint, ) ufuns = MappingUtilityFunction.generate_random(n_negotiators, outcomes=n_outcomes) for i in range(n_negotiators): mechanism.add( AspirationNegotiator(name=f"agent{i}"), ufun=ufuns[i], aspiration_type="conceder", ) mechanism.run() if 0 < checkpoint_every <= n_steps: if single_checkpoint: assert len(list(new_folder.glob("*"))) == 2 else: assert len(list(new_folder.glob("*"))) >= 2 * ( max(1, mechanism.state.step // checkpoint_every) ) elif checkpoint_every > n_steps: assert len(list(new_folder.glob("*"))) == 2 else: assert len(list(new_folder.glob("*"))) == 0
def __init__( self, outcomes: Union[int, List['Outcome']], name: str = None, parent: Controller = None, reserved_value: float = 0.0, p_acceptance=0.15, p_rejection=0.25, p_ending=0.1, can_propose=True ) -> None: super().__init__(name=name, parent=parent) # noinspection PyCallByClass self.init_ranodm_response(p_acceptance=p_acceptance, p_rejection=p_rejection, p_ending=p_ending) self.init_random_proposal() if isinstance(outcomes, int): outcomes = [(_,) for _ in range(outcomes)] self.capabilities['propose'] = can_propose self.utility_function = MappingUtilityFunction(dict(zip(outcomes, np.random.rand(len(outcomes)))) , reserved_value=reserved_value)
def test_mechanism_runs_with_offering_not_accepting(n_negotiators, oia): n_outcomes = 5 mechanism = SAOMechanism( outcomes=n_outcomes, n_steps=3, offering_is_accepting=oia, avoid_ultimatum=False ) ufuns = MappingUtilityFunction.generate_random(1, outcomes=n_outcomes) for i in range(n_negotiators): mechanism.add(AspirationNegotiator(name=f"agent{i}"), ufun=ufuns[0]) assert mechanism.state.step == 0 mechanism.step() assert mechanism._current_proposer.name == "agent0" assert mechanism._n_accepting == n_negotiators + int(oia) - 1 assert (mechanism.agreement is not None) is oia if mechanism.agreement is not None: return mechanism.step() assert mechanism._current_proposer.name == "agent0" assert mechanism._n_accepting == n_negotiators assert mechanism.agreement is not None
def test_neg_run_sync(n_negotiators): n_outcomes, n_steps = 10, 10 waste_edge, waste_center = 0.2, 0.1 c = MySyncController(sleep_seconds=waste_center) mechanisms, edge_names = [], [] for _ in range(n_negotiators): mechanism = SAOMechanism( outcomes=n_outcomes, n_steps=n_steps, ignore_negotiator_exceptions=True, avoid_ultimatum=False, ) ufuns = MappingUtilityFunction.generate_random(2, outcomes=mechanism.outcomes) edge_names.append(f"f{0}") mechanism.add( TimeWaster( name=f"agent{0}", id=f"a{0}", sleep_seconds=waste_edge, ufun=ufuns[0] ) ) mechanism.add(c.create_negotiator(ufun=ufuns[1])) mechanisms.append(mechanism) SAOMechanism.runall(mechanisms) for mechanism in mechanisms: assert mechanism.state.started assert mechanism.state.agreement is None assert not mechanism.state.has_error assert not mechanism.state.broken assert mechanism.state.timedout, print(f"Did not timeout!!\n{mechanism.state}") assert mechanism.state.step == n_steps assert not mechanism.state.waiting assert len(mechanism.history) == n_steps delay_center = 0.0 for k, v in mechanism.stats["times"].items(): if k in edge_names: assert v >= waste_edge * n_steps else: delay_center += v assert delay_center > n_steps * waste_center assert c.n_counter_all_calls == n_steps
def test_sync_controller(n_negotiations, n_negotiators, oia): n_outcomes = 2 mechanisms = [] controller = MySAOSync() for i in range(n_negotiators): mechanisms.append( SAOMechanism( outcomes=n_outcomes, n_steps=5, offering_is_accepting=oia, avoid_ultimatum=False, ) ) ufuns = MappingUtilityFunction.generate_random( n_negotiators, outcomes=n_outcomes ) for i in range(n_negotiators): mechanisms[-1].add(AspirationNegotiator(name=f"agent{i}"), ufun=ufuns[i]) mechanisms[-1].add(controller.create_negotiator()) states = SAOMechanism.runall(mechanisms) assert all(_.agreement is not None for _ in states)
def test_pareto_frontier_2(self): n_outcomes = 10 strategy = "titration-0.5" cost = 0.01 reserved_value = 0.1 outcomes = [(_,) for _ in range(n_outcomes)] accepted = [(2,), (3,), (4,), (5,)] elicitor_utilities = [ 0.5337723805661662, 0.8532272031479199, 0.4781281413197942, 0.7242899747791032, 0.3461879818432919, 0.2608677043479706, 0.9419131964655383, 0.29368079952747694, 0.6093201983562316, 0.7066918086398718, ] # list(np.random.rand(n_outcomes).tolist()) opponent_utilities = [ 1.0 if (_,) in accepted else 0.0 for _ in range(n_outcomes) ] frontier, frontier_locs = pareto_frontier( [ MappingUtilityFunction( lambda o: elicitor_utilities[o[0]], reserved_value=reserved_value, outcome_type=tuple, ), MappingUtilityFunction( lambda o: opponent_utilities[o[0]], reserved_value=reserved_value, outcome_type=tuple, ), ], outcomes=outcomes, sort_by_welfare=True, ) welfare = ( np.asarray(elicitor_utilities) + np.asarray(opponent_utilities) ).tolist() # print(f'frontier: {frontier}\nmax. welfare: {max(welfare)} at outcome: ({welfare.index(max(welfare))},)') # print(f'frontier_locs: frontier_locs') neg = SAOMechanism(outcomes=n_outcomes, n_steps=10, outcome_type=tuple) opponent = LimitedOutcomesNegotiator( acceptable_outcomes=accepted, acceptance_probabilities=[1.0] * len(accepted), ) eufun = MappingUtilityFunction( dict(zip(outcomes, elicitor_utilities)), reserved_value=reserved_value, outcome_type=tuple, ) user = User(ufun=eufun, cost=cost) strategy = EStrategy(strategy=strategy) strategy.on_enter(ami=neg.ami) elicitor = FullKnowledgeElicitor(strategy=strategy, user=user) neg.add(opponent) neg.add(elicitor) neg.run() f2, f2_outcomes = neg.pareto_frontier(sort_by_welfare=True) assert len(frontier) == len(f2) assert all([_1 == _2] for _1, _2 in zip(frontier, f2)) assert [_[0] for _ in f2_outcomes] == frontier_locs
SAOElicitingMechanism, User, next_query, possible_queries, OptimalIncrementalElicitor, ) from negmas.helpers import Distribution as U, instantiate from negmas.sao import AspirationNegotiator, LimitedOutcomesNegotiator, SAOMechanism from negmas.utilities import IPUtilityFunction, MappingUtilityFunction, pareto_frontier n_outcomes = 5 cost = 0.02 utility = 0.17682 accepted = [(0,), (2,)] ufun = MappingUtilityFunction( dict(zip([(_,) for _ in range(n_outcomes)], [utility] * n_outcomes)), reserved_value=0.0, ) import negmas.elicitation as elicitation all_countable_queries_elicitor_types = [ _ for _ in elicitation.__all__ if _.endswith("Elicitor") and not _.startswith("Base") and not "VOIOptimal" in _ ] @pytest.fixture def neg() -> SAOMechanism: return SAOMechanism(outcomes=[(_,) for _ in range(n_outcomes)])
def test_single_mechanism_history_with_waiting( avoid_ultimatum, n_steps, n_waits, n_waits2 ): n_outcomes, waste = 5, (0.0, 0.3) mechanism = SAOMechanism( outcomes=n_outcomes, n_steps=n_steps, ignore_negotiator_exceptions=False, avoid_ultimatum=avoid_ultimatum, ) ufuns = MappingUtilityFunction.generate_random(2, outcomes=mechanism.outcomes) mechanism.add( TimeWaster( name=f"agent{0}", sleep_seconds=waste, ufun=ufuns[0], n_waits=n_waits ) ) mechanism.add( TimeWaster( name=f"agent{1}", sleep_seconds=waste, ufun=ufuns[1], n_waits=n_waits2 ) ) mechanism.run() first = mechanism._selected_first n_negotiators = len(mechanism.negotiators) assert (not avoid_ultimatum and first == 0) or ( avoid_ultimatum and 0 <= first < n_negotiators ) assert mechanism.state.agreement is None assert mechanism.state.started assert mechanism.state.timedout or ( n_waits + n_waits2 > 0 and mechanism.state.broken ) assert mechanism.state.step == n_steps or ( n_waits + n_waits2 > 0 and mechanism.state.broken and mechanism.state.step <= n_steps ) assert not mechanism.state.waiting assert len(mechanism.history) == n_steps or ( n_waits + n_waits2 > 0 and mechanism.state.broken and len(mechanism.history) <= n_steps ) # check history details is correct s = [defaultdict(int), defaultdict(int)] r = [defaultdict(int), defaultdict(int)] h = [defaultdict(int), defaultdict(int)] first_offers = [] ignored_offers = [] for i, n in enumerate(mechanism.negotiators): # print(f"Received, offered, respones for {i} ({n})") # print( # list( # zip( # zip(n.received_offers.keys(), n.received_offers.values()), # zip(n.my_offers.keys(), n.my_offers.values()), # ) # ) # ) # all agents asked to offer first if avoid_ultimatum if avoid_ultimatum: assert n.received_offers[0] is None else: first_offers.append(n.received_offers[0] is None) # sent and received match for j, w in n.my_offers.items(): # cannot send mutlipe offers in the same step assert j not in s[i].keys() # cannot send None assert w is not None # or (j == 0 and not avoid_ultimatum) if j == 0 and i != first and avoid_ultimatum: # cannot have more than n_negotiators - 1 ignored offers assert len(ignored_offers) < n_negotiators - 1 ignored_offers.append(w[0]) continue s[i][j] = w[0] for j, w in n.received_offers.items(): # cannot receive multiple ofers in the same step assert j not in r[i].keys() # canont be asked to start offering except in the first step assert w is not None or j == 0 # this is the first agent to offer, ignore its first step if (first == i and j == 0) or (avoid_ultimatum and j == 0): # if this is the first agent, its first thing recieved must be None assert w is None continue assert ( w is not None ), f"None outcome agent {i} @ {j} (avoid={avoid_ultimatum}) first is {first}" r[i][j] = w[0] # a single agent is asked to offer first if not avoid_ultimatum if not avoid_ultimatum: assert any(first_offers) and not all(first_offers) # every agent is asked to offer and all except one are ignored if avoid_ultimatum if avoid_ultimatum: assert len(ignored_offers) == n_negotiators - 1 # reconstruct history neg_map = dict(zip((_.id for _ in mechanism.negotiators), [0, 1])) for state in mechanism.history: for _, w in state.new_offers: a = neg_map[_] # cannot see the same step twice in the history of an agent assert state.step not in h[a].keys() h[a][state.step] = w # no gaps in steps and all step sets start with 0 or 1 for i in range(len(mechanism.negotiators)): for x in (r, s, h): steps = list(x[i].keys()) if not steps: continue assert steps[0] in (0, 1) for _ in range(len(steps) - 1): assert steps[_] + 1 == steps[_ + 1] # pprint([s, r, h]) # history matches what is stored inside agents for i, n in enumerate(mechanism.negotiators): for j, w in s[i].items(): assert j in r[1 - i] or (j == 0) for j, w in r[i].items(): assert j in s[1 - i] or (j == 0 and not avoid_ultimatum) # s and r will not have matched indices but should have matched values s = [list(_.values()) for _ in s] r = [list(_.values()) for _ in r] h = [list(_[0] for _ in _.values()) for _ in h] # history matches what is stored inside agents for i, n in enumerate(mechanism.negotiators): for j, w in enumerate(s[i]): if j < len(r[1 - i]): assert r[1 - i][j] == w assert h[i][j] == w for j, w in enumerate(r[i]): assert s[1 - i][j] == w