def test_alternating_offers_mechanism_fails_on_no_offerer(): p = SAOMechanism( outcomes=10, n_steps=10, dynamic_entry=False, publish_n_acceptances=True, publish_proposer=True, ) to_be_offered = [(0, ), (1, ), (2, )] to_be_accepted = [(2, )] a1 = LimitedOutcomesAcceptor(acceptable_outcomes=to_be_offered) a2 = LimitedOutcomesAcceptor(acceptable_outcomes=to_be_accepted) p.add(a1, ufun=MappingUtilityFunction(lambda x: x[0] + 1.0)) p.add(a2, ufun=MappingUtilityFunction(lambda x: x[0] + 1.0)) try: p.run() except RuntimeError: pass a1offers = [ s.current_offer for s in p.history if s.current_proposer == a1.id ] a2offers = [ s.current_offer for s in p.history if s.current_proposer == a2.id ] assert len(p.history) > 0 assert len(a2offers) == 0, "acceptor did not offer" assert len(a1offers) == 0, "acceptor did not offer" assert p.agreement is None, "no agreement"
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 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 test_a_session(): start = time.monotonic() p = SAOMechanism(outcomes=50, n_steps=50) for _ in range(4): p.add(LimitedOutcomesNegotiator(outcomes=50, p_ending=0.01, name=f'agent {_}') , ufun=HyperRectangleUtilityFunction([None], [lambda x: x[0]])) p.run() # print(f'{len(p.negotiators)} negotiators') assert len(p.history) > 0
def test_alternating_offers_mechanism_with_one_agent_run(): n_outcomes, n_steps = 10, 10 accepted = [(2, ), (3, ), (4, ), (5, )] neg = SAOMechanism(outcomes=n_outcomes, n_steps=n_steps) opponent = LimitedOutcomesNegotiator( acceptable_outcomes=accepted, acceptance_probabilities=[1.0] * len(accepted), ) neg.add(opponent) neg.add(opponent) assert neg.pareto_frontier(sort_by_welfare=True)[0] == [(1.0, )] neg.run()
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_tough_asp_negotiator(): a1 = ToughNegotiator(dynamic_ufun=False) a2 = AspirationNegotiator(dynamic_ufun=False, aspiration_type='conceder') outcomes = [(_,) for _ in range(10)] u1 = np.linspace(0.0, 1.0, len(outcomes)) u2 = 1.0 - u1 neg = SAOMechanism(outcomes=outcomes, n_steps=20) neg.add(a1, ufun=u1) neg.add(a2, ufun=u2) neg.run() a1offers = [s.current_offer for s in neg.history if s.current_offerer == a1.id] a2offers = [s.current_offer for s in neg.history if s.current_offerer == a2.id] assert a1.offerable_outcomes is None if len(a1offers) > 0: assert len(set(a1offers)) == 1 and a1offers[-1] == (9,) assert len(set(a2offers)) >= 0
def test_best_only_asp_negotiator(): a1 = OnlyBestNegotiator(dynamic_ufun=False, min_utility=0.9, top_fraction=0.1) a2 = AspirationNegotiator(dynamic_ufun=False, aspiration_type='conceder') outcomes = [(_,) for _ in range(20)] u1 = np.linspace(0.0, 1.0, len(outcomes)) u2 = 1.0 - u1 neg = SAOMechanism(outcomes=outcomes, n_steps=200) neg.add(a1, ufun=u1) neg.add(a2, ufun=u2) neg.run() a1offers = [s.current_offer for s in neg.history if s.current_offerer == a1.id] a2offers = [s.current_offer for s in neg.history if s.current_offerer == a2.id] assert a1.offerable_outcomes is None if len(a1offers) > 0: assert len(set(a1offers)) <= 2 and min([u1[_[0]] for _ in a1offers if _ is not None]) >= 0.9 assert len(set(a2offers)) >= 1
def test_tough_asp_negotiator(): a1 = ToughNegotiator() a2 = AspirationNegotiator(aspiration_type="conceder") outcomes = [(_, ) for _ in range(10)] u1 = np.linspace(0.0, 1.0, len(outcomes)) u2 = 1.0 - u1 neg = SAOMechanism(outcomes=outcomes, n_steps=100, outcome_type=tuple) neg.add(a1, ufun=u1) neg.add(a2, ufun=u2) neg.run() a1offers = neg.negotiator_offers(a1.id) a2offers = neg.negotiator_offers(a2.id) assert a1._offerable_outcomes is None if len(a1offers) > 0: assert len(set(a1offers)) == 1 and a1offers[-1] == (9, ) assert len(set(a2offers)) >= 0
def test_best_only_asp_negotiator(): a1 = OnlyBestNegotiator(min_utility=0.9, top_fraction=0.1) a2 = AspirationNegotiator(aspiration_type="conceder") outcomes = [(_, ) for _ in range(20)] u1 = np.linspace(0.0, 1.0, len(outcomes)) u2 = 1.0 - u1 neg = SAOMechanism(outcomes=outcomes, n_steps=200) neg.add(a1, ufun=u1) neg.add(a2, ufun=u2) neg.run() a1offers = neg.negotiator_offers(a1.id) a2offers = neg.negotiator_offers(a2.id) assert a1._offerable_outcomes is None if len(a1offers) > 0: assert (len(set(a1offers)) <= 2 and min([u1[_[0]] for _ in a1offers if _ is not None]) >= 0.9) assert len(set(a2offers)) >= 1
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 test_tough_tit_for_tat_negotiator(): a1 = ToughNegotiator() a2 = NaiveTitForTatNegotiator() outcomes = [(_, ) for _ in range(10)] u1 = np.linspace(0.0, 1.0, len(outcomes)) u2 = 1.0 - u1 neg = SAOMechanism(outcomes=outcomes, n_steps=100, outcome_type=tuple) neg.add(a1, ufun=u1) neg.add(a2, ufun=u2) neg.run() a1offers = neg.negotiator_offers(a1.id) a2offers = neg.negotiator_offers(a2.id) # print(a1offers) # print(a2offers) assert a1._offerable_outcomes is None if len(a1offers) > 0: assert len(set(a1offers)) == 1 and a1offers[-1] == (9, ) assert len(set(a2offers)) >= 0
def test_acceptable_outcomes(): p = SAOMechanism(outcomes=6, n_steps=10) p.add( LimitedOutcomesNegotiator(name="seller", acceptable_outcomes=[(2, ), (3, ), (5, )])) p.add( LimitedOutcomesNegotiator(name="buyer", acceptable_outcomes=[(1, ), (4, ), (3, )])) state = p.run() assert state.agreement == (3, )
def test_asp_negotaitor(): a1 = AspirationNegotiator(assume_normalized=True, name="a1") a2 = AspirationNegotiator(assume_normalized=False, name="a2") outcomes = [(_, ) for _ in range(10)] u1 = np.linspace(0.0, 1.0, len(outcomes)) u2 = 1.0 - u1 neg = SAOMechanism(outcomes=outcomes, n_steps=100) neg.add(a1, ufun=u1) neg.add(a2, ufun=u2) neg.run() a1offers = neg.negotiator_offers(a1.id) a2offers = neg.negotiator_offers(a2.id) assert a1offers[0] == (9, ) assert a2offers[0] == (0, ) for i, offer in enumerate(_[0] for _ in a1offers): assert i == 0 or offer <= a1offers[i - 1][0] for i, offer in enumerate(_[0] for _ in a2offers): assert i == 0 or offer >= a2offers[i - 1][0] assert neg.state.agreement is not None assert neg.state.agreement in ((4, ), (5, ))
def test_tit_for_tat_negotiators(): a1 = NaiveTitForTatNegotiator(name="a1") a2 = NaiveTitForTatNegotiator(name="a2") outcomes = [(_, ) for _ in range(10)] u1 = np.linspace(0.0, 1.0, len(outcomes)) u2 = 1.0 - u1 neg = SAOMechanism(outcomes=outcomes, n_steps=100, avoid_ultimatum=False) neg.add(a1, ufun=u1) neg.add(a2, ufun=u2) neg.run() a1offers = neg.negotiator_offers(a1.id) a2offers = neg.negotiator_offers(a2.id) # print(a1offers) # print(a2offers) assert a1offers[0] == (9, ) assert a2offers[0] == (0, ) for i, offer in enumerate(_[0] for _ in a1offers): assert i == 0 or offer <= a1offers[i - 1][0] for i, offer in enumerate(_[0] for _ in a2offers): assert i == 0 or offer >= a2offers[i - 1][0] assert neg.state.agreement is not None assert neg.state.agreement in ((4, ), (5, ))
def test_same_utility_leads_to_agreement(): n_outcomes, n_steps = 10, 10 accepted = [(2, ), (3, ), (4, ), (5, )] neg = SAOMechanism(outcomes=n_outcomes, n_steps=n_steps) opponent = LimitedOutcomesNegotiator( acceptable_outcomes=accepted, acceptance_probabilities=[1.0] * len(accepted), ) acceptor = LimitedOutcomesAcceptor( acceptable_outcomes=accepted, acceptance_probabilities=[1.0] * len(accepted), ) neg.add(opponent) neg.add(acceptor) assert neg.pareto_frontier(sort_by_welfare=True)[0] == [(1.0, 1.0)] state = neg.run() assert state.agreement is not None assert state.step < 4
def test_can_run_from_checkpoint(tmp_path, single_checkpoint, checkpoint_every, exist_ok): import shutil new_folder: Path = tmp_path / unique_name("empty", sep="") second_folder: Path = tmp_path / unique_name("second", sep="") new_folder.mkdir(parents=True, exist_ok=True) shutil.rmtree(new_folder) new_folder.mkdir(parents=True, exist_ok=True) filename = "mechanism" second_folder.mkdir(parents=True, exist_ok=True) 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]) mechanism.run() files = list(new_folder.glob("*")) 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 runner = CheckpointRunner(folder=new_folder) assert len(runner.steps) * 2 == len(files) assert runner.current_step == -1 assert runner.loaded_object is None runner.step() assert runner.current_step == (0 if not single_checkpoint else runner.steps[-1]) assert isinstance(runner.loaded_object, SAOMechanism) assert runner.loaded_object.state.step == runner.current_step runner.reset() assert len(runner.steps) * 2 == len(files) assert runner.current_step == -1 assert runner.loaded_object is None runner.goto(runner.last_step, exact=True) assert isinstance(runner.loaded_object, SAOMechanism) assert runner.loaded_object.state.step == runner.current_step runner.goto(runner.next_step, exact=True) assert isinstance(runner.loaded_object, SAOMechanism) assert runner.loaded_object.state.step == runner.current_step runner.goto(runner.previous_step, exact=True) assert isinstance(runner.loaded_object, SAOMechanism) assert runner.loaded_object.state.step == runner.current_step runner.goto(runner.first_step, exact=True) assert isinstance(runner.loaded_object, SAOMechanism) assert runner.loaded_object.state.step == runner.current_step runner.reset() runner.run()
def test_can_run_from_checkpoint(tmp_path, checkpoint_every, exist_ok, copy, fork_after_reset): import shutil new_folder: Path = tmp_path / unique_name("empty", sep="") second_folder: Path = tmp_path / unique_name("second", sep="") new_folder.mkdir(parents=True, exist_ok=True) shutil.rmtree(new_folder) new_folder.mkdir(parents=True, exist_ok=True) second_folder.mkdir(parents=True, exist_ok=True) shutil.rmtree(second_folder) second_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=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], aspiration_type="conceder", ) mechanism.run() files = list(new_folder.glob("*")) if 0 < checkpoint_every <= n_steps: 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 runner = CheckpointRunner(folder=new_folder) assert len(runner.steps) * 2 == len(files) assert runner.current_step == -1 assert runner.loaded_object is None runner.step() assert runner.current_step == 0 assert isinstance(runner.loaded_object, SAOMechanism) assert runner.loaded_object.state.step == runner.current_step runner.reset() assert len(runner.steps) * 2 == len(files) assert runner.current_step == -1 assert runner.loaded_object is None runner.goto(runner.last_step, exact=True) assert isinstance(runner.loaded_object, SAOMechanism) assert runner.loaded_object.state.step == runner.current_step runner.goto(runner.next_step, exact=True) assert isinstance(runner.loaded_object, SAOMechanism) assert runner.loaded_object.state.step == runner.current_step runner.goto(runner.previous_step, exact=True) assert isinstance(runner.loaded_object, SAOMechanism) assert runner.loaded_object.state.step == runner.current_step runner.goto(runner.first_step, exact=True) assert isinstance(runner.loaded_object, SAOMechanism) assert runner.loaded_object.state.step == runner.current_step runner.reset() if fork_after_reset: m = runner.fork(copy_past_checkpoints=copy, folder=second_folder) assert m is None return runner.step() m = runner.fork(copy_past_checkpoints=copy, folder=second_folder) if copy: step = runner.current_step assert len(list(second_folder.glob("*"))) >= 2 assert len(list(second_folder.glob(f"*{step}.mechanism"))) > 0 else: assert len(list(second_folder.glob("*"))) == 0 assert isinstance(m, SAOMechanism) step = m.current_step m.step() assert m.current_step == step + 1 state = m.run() assert state.agreement is not None runner.reset() assert len(runner.steps) * 2 == len(files) assert runner.current_step == -1 assert runner.loaded_object is None runner.goto(runner.last_step, exact=True) assert isinstance(runner.loaded_object, SAOMechanism) assert runner.loaded_object.state.step == runner.current_step runner.goto(runner.next_step, exact=True) assert isinstance(runner.loaded_object, SAOMechanism) assert runner.loaded_object.state.step == runner.current_step runner.goto(runner.previous_step, exact=True) assert isinstance(runner.loaded_object, SAOMechanism) assert runner.loaded_object.state.step == runner.current_step runner.goto(runner.first_step, exact=True) assert isinstance(runner.loaded_object, SAOMechanism) assert runner.loaded_object.state.step == runner.current_step runner.reset() runner.run()