Пример #1
0
def test_nothing_happens_with_do_nothing(buy_missing, n_processes, initial_balance):
    world = generate_world(
        [DoNothingAgent],
        buy_missing_products=buy_missing,
        n_processes=n_processes,
        name=unique_name(
            f"scml2020tests/single/doing_nothing/"
            f"{'Buy' if buy_missing else 'Fine'}_p{n_processes}_b{initial_balance}",
            add_time=True,
            rand_digits=4,
        ),
        initial_balance=initial_balance,
        bankruptcy_limit=initial_balance,
        compact=COMPACT,
        no_logs=NOLOGS,
    )
    world.run()
    assert len(world.contracts_per_step) == 0
    for a, f, p in world.afp:
        if is_system_agent(a.id):
            continue
        if (
            a.awi.my_input_product == 0
            or a.awi.my_input_product == a.awi.n_processes - 1
        ):
            assert f.current_balance <= initial_balance, (
                f"{a.name} (process {a.awi.my_input_product} of {a.awi.n_processes})'s balance "
                f"should go down"
            )
Пример #2
0
def test_agents_go_bankrupt(n_processes):
    buy_missing = True
    world = generate_world(
        [RandomAgent],
        buy_missing_products=buy_missing,
        n_processes=n_processes,
        name=unique_name(
            f"scml2020tests/single/bankrupt/"
            f"{'Buy' if buy_missing else 'Fine'}_p{n_processes}",
            add_time=True,
            rand_digits=4,
        ),
        initial_balance=0,
        bankruptcy_limit=0,
        n_steps=10,
        compact=COMPACT,
        no_logs=NOLOGS,
    )
    world.run()
    #    assert len(world.signed_contracts) + len(world.cancelled_contracts) == 0
    for a, f, p in world.afp:
        if is_system_agent(a.id):
            continue
        if (
            a.awi.my_input_product == 0
            or a.awi.my_input_product == a.awi.n_processes - 1
        ):
            assert f.current_balance <= 0, (
                f"{a.name} (process {a.awi.my_input_product} of {a.awi.n_processes})'s balance "
                f"should go down"
            )
            assert f.is_bankrupt, (
                f"{a.name} (process {a.awi.my_input_product} of {a.awi.n_processes}) should "
                f"be bankrupt (balance = {f.current_balance}, inventory={f.current_inventory})"
            )
Пример #3
0
def test_ufun_penalty_scales_are_correct(penalties_scale):
    from scml.oneshot.ufun import OneShotUFun

    world = SCML2020OneShotWorld(
        **SCML2020OneShotWorld.generate(
            MyIndNeg,
            n_agents_per_process=3,
            n_processes=2,
            n_steps=30,
            penalties_scale=penalties_scale,
        ),
        compact=True,
        no_logs=True,
    )
    for _ in range(30):
        old_trading = world.trading_prices.copy()
        world.step()
        for _, a in world.agents.items():
            if is_system_agent(a.id):
                continue
            u: OneShotUFun = a.ufun
            if penalties_scale == "trading":
                assert (u.output_penalty_scale
                        # == a.awi.trading_prices[a.awi.my_output_product]
                        == old_trading[a.awi.my_output_product])
                assert (u.input_penalty_scale
                        # == a.awi.trading_prices[a.awi.my_input_product]
                        == old_trading[a.awi.my_input_product])
            else:
                assert (u.output_penalty_scale == a.awi.catalog_prices[
                    a.awi.my_output_product])
                assert (u.input_penalty_scale == a.awi.catalog_prices[
                    a.awi.my_input_product])
Пример #4
0
def test_production_cost_increase():
    from scml.scml2020 import SCML2021World
    from scml.scml2020.agents import DecentralizingAgent

    NPROCESSES = 5
    costs = [[] for _ in range(NPROCESSES)]
    for _ in range(100):
        world = SCML2021World(
            **SCML2021World.generate(
                DecentralizingAgent,
                n_agents_per_process=10,
                n_processes=NPROCESSES,
            ),
            compact=True,
            no_logs=True,
        )
        for aid in world.agent_profiles.keys():
            if is_system_agent(aid):
                continue
            profile = world.agent_profiles[aid]
            costs[profile.input_products[0]].append(
                profile.costs[:, profile.input_products[0]].mean())
    mean_costs = [sum(_) / len(_) for _ in costs]
    assert all([
        b > (0.5 * (i + 2) / (i + 1)) * a
        for i, (a, b) in enumerate(zip(mean_costs[:-1], mean_costs[1:]))
    ]), f"non-ascending costs {mean_costs}"
Пример #5
0
def test_basic_awi_info_suppliers_consumers():
    world = SCML2020OneShotWorld(
        **SCML2020OneShotWorld.generate(
            agent_types=RandomOneShotAgent,
            n_steps=10,
            n_processes=2,
            compact=True,
            no_logs=True,
        )
    )
    for aid in world.agents:
        if is_system_agent(aid):
            continue
        a = world.agents[aid]
        assert a.id in a.awi.all_suppliers[a.awi.my_output_product]
        assert a.id in a.awi.all_consumers[a.awi.my_input_product]
        assert a.awi.my_consumers == world.agent_consumers[aid]
        assert a.awi.my_suppliers == world.agent_suppliers[aid]
        l = a.awi.my_input_product
        assert all(
            _.endswith(str(l - 1)) or a.awi.is_system(_) for _ in a.awi.my_suppliers
        )
        assert all(
            _.endswith(str(l + 1)) or a.awi.is_system(_) for _ in a.awi.my_consumers
        )
Пример #6
0
def test_ufun_min_max():
    world = SCML2020OneShotWorld(
        **SCML2020OneShotWorld.generate(agent_types=[RandomOneShotAgent], n_steps=10),
        construct_graphs=True,
    )
    world.step()
    for aid, agent in world.agents.items():
        if is_system_agent(aid):
            continue
        ufun = agent.make_ufun()
        mn, mx = ufun.min_utility, ufun.max_utility
        assert mx > mn or mx == mn == 0
Пример #7
0
def test_do_nothing_goes_bankrupt():
    world = generate_world([MyOneShotDoNothing],
                           2,
                           1000,
                           4,
                           cash_availability=0.001)
    world.run()
    for aid, agent in world.agents.items():
        if is_system_agent(aid):
            continue
        assert world.is_bankrupt[
            aid], f"Agent {aid} is not bankrupt with balance {world.current_balance(aid)} and initial_balance of {world.initial_balances[aid]}"
        assert agent.awi.is_bankrupt()
Пример #8
0
    def benchmark_data(self, agent, world, seller=True):
        #TODO: data for benchmarkign purposes, info_callabck,
        # will be rendered when display is true
        # how to compare different companies, Ratio Analysis
        # https://www.investopedia.com/ask/answers/032315/how-does-ratio-analysis-make-it-easier-compare-different-companies.asp
        # price-to-earnings ratio and net profit margin
        # Margin Ratios and  Return Ratios
        # https://corporatefinanceinstitute.com/resources/knowledge/finance/profitability-ratios/
        profitability = []
        initial_balances = []
        factories = [
            _ for _ in world.factories if not is_system_agent(_.agent_id)
        ]
        for i, factory in enumerate(factories):
            initial_balances.append(factory.initial_balance)
        normalize = all(_ != 0 for _ in initial_balances)

        for _ in world.agents:
            if world.agents[_].action_callback == "system": continue
            if world.agents[_] in world.heuristic_agents:
                if normalize:
                    profitability.append((
                        agent.state.f[2] - agent.state.f[0]
                    ) / agent.state.f[0] - ([
                        f.current_balance
                        for f in factories if f.agent_id == world.agents[_].id
                    ][0] - [
                        f.initial_balance
                        for f in factories if f.agent_id == world.agents[_].id
                    ][0]) / [
                        f.initial_balance
                        for f in factories if f.agent_id == world.agents[_].id
                    ][0])
                else:
                    profitability.append((
                        agent.state.f[2] - agent.state.f[0]
                    ) - ([
                        f.current_balance
                        for f in factories if f.agent_id == world.agents[_].id
                    ][0] - [
                        f.initial_balance
                        for f in factories if f.agent_id == world.agents[_].id
                    ][0]))

        return {"profitability": profitability}
Пример #9
0
def test_ufun_min_max_in_world():
    for _ in range(20):
        world = SCML2020OneShotWorld(
            **SCML2020OneShotWorld.generate(agent_types=[RandomOneShotAgent],
                                            n_steps=10),
            construct_graphs=False,
            compact=True,
            no_logs=True,
        )
        world.step()
        for aid, agent in world.agents.items():
            if is_system_agent(aid):
                continue
            ufun = agent.make_ufun(add_exogenous=True)
            ufun.find_limit(True)
            ufun.find_limit(False)
            mn, mx = ufun.min_utility, ufun.max_utility
            assert mx >= mn
Пример #10
0
def test_quantity_distribution(n_processes):
    from pprint import pformat

    for _ in range(20):
        world = generate_world(
            [MyOneShotAgent],
            n_processes=n_processes,
            compact=True,
            no_logs=True,
        )
        for contracts in world.exogenous_contracts.values():
            for c in contracts:
                for p in c.partners:
                    if is_system_agent(p):
                        continue
                    lines = world.agent_profiles[p].n_lines
                    assert (
                        lines >= c.agreement["quantity"] >= 0
                    ), f"Contract: {str(c)} has negative or more quantity than n. lines {lines}\n{pformat(world.info)}"
Пример #11
0
def generate_world(
    agent_types,
    n_processes=3,
    n_steps=10,
    n_agents_per_process=2,
    n_lines=10,
    initial_balance=None,
    buy_missing_products=True,
    **kwargs,
):
    kwargs["no_logs"] = True
    kwargs["compact"] = True
    world = SCML2021World(**SCML2021World.generate(
        agent_types,
        n_processes=n_processes,
        n_steps=n_steps,
        n_lines=n_lines,
        n_agents_per_process=n_agents_per_process,
        initial_balance=initial_balance,
        buy_missing_products=buy_missing_products,
        **kwargs,
    ))
    for s1, s2 in zip(world.suppliers[:-1], world.suppliers[1:]):
        assert len(set(s1).intersection(set(s2))) == 0
    for s1, s2 in zip(world.consumers[:-1], world.consumers[1:]):
        assert len(set(s1).intersection(set(s2))) == 0
    for p in range(n_processes):
        assert len(world.suppliers[p + 1]) == n_agents_per_process
        assert len(world.consumers[p]) == n_agents_per_process
    for a in world.agents.keys():
        if is_system_agent(a):
            continue
        assert len(world.agent_inputs[a]) == 1
        assert len(world.agent_outputs[a]) == 1
        assert len(world.agent_processes[a]) == 1
        assert len(
            world.agent_suppliers[a]) == (n_agents_per_process if
                                          world.agent_inputs[a][0] != 0 else 1)
        assert len(world.agent_consumers[a]) == (
            n_agents_per_process
            if world.agent_outputs[a][0] != n_processes else 1)
    return world
Пример #12
0
    def __init__(self, configuration=None, *args, **kwargs):
        # maddpg drived agents, heuristic agents, script drived agents, interative agents
        # self.agents = []
        # SELLER, BUYER
        self.system_entities = []

        # communication channel dimensionality
        self.dim_c = 2
        # negotiation management dimensionality
        self.dim_m = DIM_M  # seller
        self.dim_b = DIM_B  # buyer

        # simulation timestep
        self.dt = 0.1

        # world done
        self.__done = False

        # set up the scml2020world
        if configuration is None:
            configuration = SCML2020World.generate(*args, **kwargs)

        self.configuration = copy.deepcopy(configuration)

        super().__init__(**self.configuration)
        # set action_callback for agent which hasnot it
        for agent in self.agents.values():
            if not hasattr(agent, 'action_callback'):
                if is_system_agent(agent.id):
                    agent.action_callback = 'system'
                    self.system_entities.append(agent)
                else:
                    agent.action_callback = 'heuristic'

            if not hasattr(agent, 'interactive'):
                agent.interactive = False

            if not hasattr(agent, 'state'):
                agent.state = AgentState()
Пример #13
0
def test_trading_prices_updated(n_agents, n_processes, n_steps):
    from scml.scml2020 import SCML2021World
    from negmas.helpers import force_single_thread

    eps = 1e-3

    world = SCML2021World(
        **SCML2021World.generate(
            [MyRandomAgent] * n_processes,
            n_agents_per_process=n_agents,
            n_processes=n_processes,
            n_steps=n_steps,
        ),
        compact=True,
        no_logs=True,
    )
    catalog_prices = world.catalog_prices
    diffs = np.zeros_like(catalog_prices)

    # we start at catlaog prices
    for aid, agent in world.agents.items():
        assert np.abs(agent.awi.trading_prices - catalog_prices).max() < eps

    force_single_thread(True)
    for _ in range(n_steps):
        world.step()
        trading_prices = None
        for aid, agent in world.agents.items():
            if is_system_agent(aid):
                continue
            trading_prices = agent.awi.trading_prices.copy()
            break
        diffs = np.maximum(diffs, np.abs(trading_prices - catalog_prices))

    assert diffs.max() > eps
    force_single_thread(False)
Пример #14
0
def check_trading_explosion(world, checked_types=(PricePumpingAgent, )):
    stats = world.stats_df
    contracts = pd.DataFrame(world.saved_contracts)
    negotiations = pd.DataFrame(world.saved_negotiations)
    for aid, agent in world.agents.items():
        if is_system_agent(aid):
            continue
        if not agent.awi.is_last_level or not any(
                issubclass(agent.__class__, _) for _ in checked_types):
            continue
        # all sellers should go bankrupt
        assert world.is_bankrupt[aid]
        assert agent.awi.is_bankrupt()
        # bankrupt agents remain bankrupt
        bankrupt = stats[f"bankrupt_{aid}"].values.astype(bool)
        bankrupt_first_index = np.where(bankrupt == True)[0][0]
        assert not np.any(bankrupt[:bankrupt_first_index])
        assert np.all(bankrupt[bankrupt_first_index:])

        # cannot become bankrupt without contracts
        assert (len(contracts.loc[(contracts.signed_at <= bankrupt_first_index)
                                  & (contracts.buyer_name == aid), :, ]) > 0)

        # no contracts after becoming bankrupt
        assert (len(contracts.loc[(contracts.signed_at > bankrupt_first_index)
                                  & (contracts.buyer_name == aid), :, ]) == 0)

        # no negotiations after becoming bankrupt
        assert (len(negotiations.loc[
            (negotiations.requested_at > bankrupt_first_index)
            & (negotiations.partners.apply(lambda x: aid in x)), :, ]) == 0)

        # some negotiations before becoming bankrupt
        assert (len(negotiations.loc[
            (negotiations.requested_at <= bankrupt_first_index)
            & (negotiations.partners.apply(lambda x: aid in x)), :, ]) > 0)
Пример #15
0
            n_lines=n_lines,
            n_agents_per_process=n_agents_per_process,
            initial_balance=initial_balance,
            buy_missing_products=buy_missing_products,
            **kwargs,
        )
    )
    for s1, s2 in zip(world.suppliers[:-1], world.suppliers[1:]):
        assert len(set(s1).intersection(set(s2))) == 0
    for s1, s2 in zip(world.consumers[:-1], world.consumers[1:]):
        assert len(set(s1).intersection(set(s2))) == 0
    for p in range(n_processes):
        assert len(world.suppliers[p + 1]) == n_agents_per_process
        assert len(world.consumers[p]) == n_agents_per_process
    for a in world.agents.keys():
        if is_system_agent(a):
            continue
        assert len(world.agent_inputs[a]) == 1
        assert len(world.agent_outputs[a]) == 1
        assert len(world.agent_processes[a]) == 1
        assert len(world.agent_suppliers[a]) == (
            n_agents_per_process if world.agent_inputs[a][0] != 0 else 1
        )
        assert len(world.agent_consumers[a]) == (
            n_agents_per_process if world.agent_outputs[a][0] != n_processes else 1
        )
    return world


@mark.parametrize("agent_type", types)
@given(buy_missing=st.booleans(), n_processes=st.integers(2, 4))