Giter VIP home page Giter VIP logo

scml's Introduction

Overview

docs Documentation Status run in binder
tests
package
Gitter
General Join the chat at https://gitter.im/scml-anac/community Standard Join the chat at https://gitter.im/scml-anac/standard Collusion Join the chat at https://gitter.im/scml-anac/collusion OneShot Join the chat at https://gitter.im/scml-anac/one-shot

ANAC Supply Chain Management League Platform

Overview

This repository is the official platform for running ANAC Supply Chain Management Leagues. It will contain a package called scmlXXXX for the competition run in year XXXX. For example scml2019 will contain all files related to the 2019's version of the competition.

Installation

pip install scml

You can also install the in-development version with:

pip install https://github.com/yasserfarouk/scml/archive/master.zip

We only support python 3.10 and 3.11. The reason python 3.12 is not yet supported is that stable_baselines3 is not supporting it yet.

Documentation

https://scml.readthedocs.io

Development

To run the all tests run:

tox

Note, to combine the coverage data from all the tox environments run:

Windows
set PYTEST_ADDOPTS=--cov-append
tox
Other
PYTEST_ADDOPTS=--cov-append tox

scml's People

Contributors

gitter-badger avatar kevinzhou96 avatar snyk-bot avatar yasserfarouk avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

scml's Issues

OneShotSyncAgent timing issue

In some negotiation rounds, OneShotSyncAgent's counter_all method will get called before first_proposals. Since both agents are suppose to submit first proposals in each negotiation, this seems like it might be a bug.

To Reproduce

class MySyncAgent(OneShotSyncAgent):
    new_step = False

    def step(self):
        self.new_step = True

    def counter_all(self, offers, states):
        """Respond to a set of offers given the negotiation state of each."""
        if self.new_step:
            raise RuntimeError("counter_all before first_proposals")
        return dict(zip(self.negotiators.keys(),
                        [SAOResponse(ResponseType.END_NEGOTIATION, None)]
                        * len(self.negotiators)
                       ))

    def get_offer(self, negotiator_id: str):
        ami = self.get_ami(negotiator_id)
        quantity_issue = ami.issues[QUANTITY]
        unit_price_issue = ami.issues[UNIT_PRICE]

        offer = [-1] * 3
        offer[QUANTITY] = quantity_issue.max_value
        offer[TIME] = self.awi.current_step
        offer[UNIT_PRICE] = unit_price_issue.max_value
        return offer

    def first_proposals(self):
        """Decide a first proposal on every negotiation.
        Returning None for a negotiation means ending it."""
        self.new_step = False
        return  dict(zip(
                self.negotiators.keys(),
                (self.get_offer(neg_id) for neg_id in self.negotiators.keys())
        ))

This will raise "RuntimeError: counter_all before first_proposals"

Expected behavior
Each round consists of a call to init or step, followed by a call to first_proposals, followed by >= 0 calls to counter_all.

OS: Mac OS 10.14

Agent dependencies

We're trying to upload our agent, which depends on xgboost. We've included xgboost in our dependencies list, but the test comes back with the error

EXCEPTION
Failed on: 2021-08-01 20:30:24.065072 UTC
No module named xgboost
Traceback (most recent call last):
File "./python/runagent.py", line 169, in main
agent_class = get_class(class_name, module_name=module_name)
File "/vol/home/ymohamm1/scmlweb/python/.venv/lib/python3.8/site-packages/negmas/helpers.py", line 1082, in get_class
module = importlib.import_module(module_name)
File "/home/ymohamm1/.pyenv/versions/3.8.10/lib/python3.8/importlib/__init__.py", line 127, in import_module
return _bootstrap._gcd_import(name[level:], package, level)
File "", line 1014, in _gcd_import
File "", line 991, in _find_and_load
File "", line 975, in _find_and_load_unlocked
File "", line 671, in _load_unlocked
File "", line 848, in exec_module
File "", line 219, in _call_with_frames_removed
File "/vol/home/ymohamm1/scmlweb/agents/team_corleone/godfather/godfather.py", line 59, in
import xgboost as xgb
ModuleNotFoundError: No module named xgboost

DEBUGGING INFO
PATH: /vol/home/ymohamm1/scmlweb/storage/app/files/team_corleone/202181824242424__20092__GodfatherGoldfish__0.0.4.zip
Class Name: GoldfishParetoEmpiricalGodfatherAgent
team_id: team_corleone
team_name: Team Corleone
apath: godfather.godfather
MODULE NAME: godfather.godfather
END OF REPORT

Dependencies list: numpy;tabulate;time;copy;typing;enum;random;warnings;xgboost;pandas;pathlib.

Any idea what we're doing wrong?

no running negotiations in SCML2020OneShotWorld when update to 0.3.3

Describe the bug
When scml is updated from 0.3.1 -> 0.3.3, there are no running negotiations during running of SCML2020OneShotWorld.

I have debug it, can not enter into while any(running) in the function negmas.World._step_negotiation.
In version 0.3.0, did not find this problem, whether something is needed to be considered in version 0.3.3?

To Reproduce
Steps to reproduce the behavior:

  1. Generate SCML2020OneShotWorld, agent_types: RandomOneShotAgent
  2. No error, but can not see negotiation behavior

Expected behavior
Could see negotiations between agents

Screenshots
0.3.3.PNG
can not enter into while any(running)
stats.PNG
after running of World, print the world.states, n_negotiations is always 0

Desktop (please complete the following information):

  • OS: ubuntu
  • Browser: firefox
  • Version: OS version 18.04

Additional context

  • agent_types=[RandomOneShotAgent]
  • n_processes=2
  • n_agents_per_process=1
  • n_lines=10
  • n_steps=10

Trading prices are not updated

Hi,
self.awi.trading_prices gives the list of catalog prices each step. It seems it is not updated although product flow occurs.

my_consumers in OneShotAWI

Describe the bug
There may be a problem with my_consumers in OneShotAWI.

To Reproduce
Steps to reproduce the behavior:

  1. Create a SCMLOneShotWorld
  2. agent.awi.my_consumers
  3. See the result of agent which in self.level==0

Expected behavior
agent is 00MyB@0

The supplier of the agent (level 0) is the SELLER(SYSTEM), but the consumer of the agent is the agent in the next level (level 1, e.g. 02Gre@1, 03Gre@1), not the same level agent(level 0).

Screenshots
bug.png

Desktop (please complete the following information):

  • OS: Ubuntu 18.04
  • SCML: 0.3.3

Negotiation request from a bankrupted agent

Negotiation requests might be received from bankrupted agents.

Here some information from logged data:
Negotiation request from: 05BCS@1
Current partners (not bankrupted): ['SELLER', '02MMM@1', '04Dec@1']
Bankrupted agents: ['03BCS@1', '05BCS@1']

I use the last version of scml.
I've observed this bug several times and the bankrupted agent was BCS each time.

Partial list of agents scores

Discussed in #94

Originally posted by eranhirs May 15, 2022
After adding a few agents to the competitors list in myagent.py (from the skeleton), in the final table of agents I sometimes get a partial list.
Is it intentionally not showing all agents? I also sometimes get agents I don't have in my list, such as SingleAgreementAspirationAgent, where are they coming from?

The negotiator ID in oneshot is not always the same as the partner ID!!

Hi one question just pumped up. So in oneshot does negotiator_id received in propose() or respond() really equals to the id of your partner? I had a local test which shows that the negotiator_id are always something like '02Ran@0-19edad1e-db6b-4d3a-9ecb-f8423034ded7', while self.awi.my_consumers are ['SELLER'] or something like ['04Ran@1', '05Ran@1', '06Ran@1', '07Ran@1']. So what does self.awi.my_consumers or self.awi.my_supplies return and how can we get the id of my opponents?

Originally posted by @rezunli96 in #20 (comment)

Exogenous contract quantity in OneShot can be greater than 10

Describe the bug
In the AWI's state, the exogenous quantity of the contract isn't limited by n_lines

To Reproduce

from scml.oneshot import OneShotAWI
a = OneShotAWI(world, world.agents['02Ran@0'])
177
a.state()
177
OneShotState(exogenous_input_quantity=14, exogenous_input_price=126, exogenous_output_quantity=0, exogenous_output_price=0, disposal_cost=0.5649356894772987, shortfall_penalty=0.5808409998388839, current_balance=13011.819059385482)

Expected behavior
exogenous_input_quantity should be capped at 10

General Discussion about the OneShot track

What is your work environment?
Any

Describe the topic you would like to discuss
This a general space for discussing topics related to the one-shot track. You can also add your own issue using the new issue option in Github.

Additional context
Let's help each other make amazing agents :-)

IndexError when a world is generated with equal_exogenous_sales=True

Describe the bug

IndexError is raised when I generate SCML2023OneShotWorld with equal_exogenous_sales=True or equal_exogenous_supply=True.

To Reproduce

Generate a world like below.

world = SCML2023OneShotWorld(
    **SCML2023OneShotWorld.generate(
        agent_types=seller_types + buyer_types,
        agent_processes=agent_processes,
        n_processes=2,
        n_steps=n_steps,
        random_agent_types=False,
        production_costs=2,
        exogenous_price_dev=0.0,
        equal_exogenous_sales=True,
        equal_exogenous_supply=True
    )
)

Expected behavior

A world is generated successfully.

Actual behavior

IndexError is raised.

  File "~/scml-a4rcvv/entry.py", line 100, in run
    **SCML2023OneShotWorld.generate(
  File "~/scml-a4rcvv/.venv/lib/python3.10/site-packages/scml/oneshot/world.py", line 914, in generate
    exogenous_supplies = distribute_quantities(
  File "~/scml-a4rcvv/.venv/lib/python3.10/site-packages/scml/common.py", line 186, in distribute_quantities
    return [np.asarray([values[_]] * a, dtype=int) for _ in range(n_steps)]
  File "~/scml-a4rcvv/.venv/lib/python3.10/site-packages/scml/common.py", line 186, in <listcomp>
    return [np.asarray([values[_]] * a, dtype=int) for _ in range(n_steps)]
IndexError: list index out of range

Desktop (please complete the following information):

  • OS: macOS 13.2.1 (Apple Silicon)
  • Python version: 3.10.10
  • scml version: 0.5.6

Additional Context

Possible workaround is to give cap_exogenous_quantities=False to **SCML2023OneShotWorld.generate().

world = SCML2023OneShotWorld(
    **SCML2023OneShotWorld.generate(
        agent_types=seller_types + buyer_types,
        agent_processes=agent_processes,
        n_processes=2,
        n_steps=n_steps,
        random_agent_types=False,
        production_costs=2,
        equal_exogenous_supply=True,
        equal_exogenous_sales=True,
        cap_exogenous_quantities=False
    )
)

It seems that, in common.py, len(limit) is equal to the number of agents, and len(values) is originally equal to n_steps. zip(values, limit) changes len(values) to the number of agents.

Utility does not match exogenous contracts

Describe the bug
Mismatch between awi.current_exogenous_input_quantity/awi.current_exogenous_output_quantity and SCML utility function.

To Reproduce
Run this inside respond or counter_all or anywhere:

ex_quant = (self.awi.current_exogenous_input_quantity
    if self.awi.profile.input_product == 0 else
    self.awi.current_exogenous_output_quantity)
is_selling = self.awi.profile.input_product == 0

utils = []
for i in range(11):
    o = [-1, -1, -1]
    o[UNIT_PRICE] = 20
    o[QUANTITY] = i
    utils.append(self.ufun.from_offers([o], [is_selling]))
best_u, best_quant = max([(u, idx) for idx, u in enumerate(utils)])

print("selling", is_selling)
print("ex quant", ex_quant)
print("best quantity", best_quant)
assert (not self.awi.profile.input_product == 0) or best_quant >= ex_quant, "best: {}, exog: {}".format(best_quant, ex_quant)

Assertion should fail within a few hundred steps.

Expected behavior
Assertion should be true because a seller should never (I think) get more utility by under-fulfilling its exogenous contracts.

scml 0.4.7, negmas 0.8.6

Can't call current inventory method from AWI

Hey there,

I am following the guides from: http://www.yasserm.com/scml/scml2020docs/tutorials/03.develop_agent_scml2020.html. Currently, I am trying to access my agent's inventory. Unfortunately, I am getting following error when I try to call 'self.awi.current_inventory(self.awi.my_input_product)':

AttributeError: 'AWI' object has no attribute 'current_inventory'.

I was wondering if the method is changed somewhat, checked the methods in http://www.yasserm.com/scml/scml2020docs/api/scml.scml2020.AWI.html, and could not find any method regarding the inventory. In SCML 2021, is it the agent designer's choice to keep track of the inventory?

OS: Windows
Version: 10

Best regards.

OneShotSyncAgent timing issue 2: "step" called during "counter_all"

I'm back with another one: in some negotiation rounds, OneShotSyncAgent's step method will get called during counter_all.

To Reproduce

import datetime

class MySyncAgent(OneShotSyncAgent):
    in_counter_all = False

    def step(self):
        if self.in_counter_all:
            raise RuntimeError("uh-oh")
    
    @staticmethod
    def delay():
        """Tune this to take ~3s"""
        before = datetime.datetime.now()
        a = 0
        for i in range(100000000):
            a *= i
        after = datetime.datetime.now()
        print("delay time:", after - before)

    def counter_all(self, offers, states):
        self.in_counter_all = True
        self.delay()
        self.in_counter_all = False

        return {
            k: SAOResponse(ResponseType.REJECT_OFFER, v)
            for k, v in self.first_proposals().items()
        }

    def first_proposals(self):
        return  dict(zip(
                self.negotiators.keys(),
                (self.get_offer(neg_id) for neg_id in self.negotiators.keys())
        ))

    def get_offer(self, negotiator_id: str):
        ami = self.get_ami(negotiator_id)
        quantity_issue = ami.issues[QUANTITY]
        unit_price_issue = ami.issues[UNIT_PRICE]

        offer = [-1] * 3
        offer[QUANTITY] = quantity_issue.max_value
        offer[TIME] = self.awi.current_step
        offer[UNIT_PRICE] = unit_price_issue.max_value
        return offer

I tuned delay to take about 3 seconds. On my machine, this raises "RuntimeError: uh-oh" after a while.

Expected behavior
A round does not end while counter_all is in progress.

OS: Mac OS 10.14

General Discussion about the Collusion track

What is your work environment?
Any

Describe the topic you would like to discuss
This a general space for discussing topics related to the collusion track. You can also add your own issue using the new issue option in Github.

Additional context
Let's help each other make amazing agents :-)

GreedyOneShotAgent mismatch

The code given in the tutorials for GreedyOneShotAgent does not match the implementation in scml.oneshot.agents.GreedyOneShotAgent.

The implementation in the scml package corresponds to what's labelled in the tutorial as "LearningGreedyAgent" (except without inheritance from AdaptiveGreedyAgent, so I suspect it might be broken).

Expected behavior: I'd think it would make the most sense to change the implementation of GreedyOneShotAgent to match what's in the tutorial, and maybe add an scml.oneshot.agents.LearningGreedyAgent as well.

Negotiations not limited to 20 rounds?

It appears that the 20-round negotiation limit might not be enforced.

To Reproduce
Full test file included in a comment, but here's the agent:

class MyOver21SimpleAgent(OneShotAgent):
    count_offers = defaultdict(int)

    def step(self):
        count_offers = defaultdict(int)

    def propose(self, negotiator_id: str, state) -> "Outcome":
        self.count_offers[negotiator_id] += 1
        if self.count_offers[negotiator_id] > 10:
            warnings.warn("high count {}".format(self.count_offers[negotiator_id]))

        return self.best_offer(negotiator_id)

    def respond(self, negotiator_id, state, offer):
        return ResponseType.REJECT_OFFER

    def best_offer(self, negotiator_id):
        ami = self.get_ami(negotiator_id)
        if not ami:
            return None

        quantity_issue = ami.issues[QUANTITY]
        unit_price_issue = ami.issues[UNIT_PRICE]

        offer = [-1] * 3
        offer[TIME] = self.awi.current_step
        offer[QUANTITY] = quantity_issue.max_value
        offer[UNIT_PRICE] = unit_price_issue.max_value

        return tuple(offer)

Expected behavior
We expect to stop getting respond calls from an opponent once we've responded to them 20 times.

scml 0.4.8, negmas 0.8.7

General Discussion about the Standard Track

What is your work environment?
Any

Describe the topic you would like to discuss
This a general space for discussing topics related to the standard track. You can also add your own issue using the new issue option in Github.

Additional context
Let's help each other make amazing agents :-)

Utility Function Calculation

Describe the bug
Utility function calculation doesn't match description in paper

To Reproduce
My agent's state is:
OneShotState(exogenous_input_quantity=6, exogenous_input_price=66, exogenous_output_quantity=0, exogenous_output_price=0, disposal_cost=0.010749528219285567, shortfall_penalty=0.47583515219370137, current_balance=2625.8255824262014)
agent.awi.trading_prices = array([10., 17., 29.])
cagent.awi.catalog_prices = array([10, 14, 29])

agent.ufun([6, 0, 15]) = 18
agent.ufun([7, 0, 15]) = 13.368697784675417

Issues:

  1. the agent.ufun.output_penalty_scale is set to the trading price of the input instead of the output
    agent.ufun.output_penalty_scale = cagent.ufun.input_penalty_scale = 10

  2. If I take an agent in the second level, I get
    agent.ufun.output_penalty_scale = agent.ufun.input_penalty_scale = 14 which is the catalog price instead of the trading price.

  3. agent.ufun([6, 0, 15]) - agent.ufun.shortfall_penalty*agent.ufun.output_penalty_scale - agent.ufun([7, 0, 15]) = 0
    I think this should be equal to the production cost instead of 0 since we're charged $m_a Q^{*out}$ not $m_a Q^{out}$ according to equation 5

error on running

when import scml i got error:

from scml.scml2020 import *

File "C:\Anaconda3\lib\site-packages\scml_init_.py", line 5, in
from .scml2019 import *
File "C:\Anaconda3\lib\site-packages\scml\scml2019_init_.py", line 89, in
from .common import *
File "C:\Anaconda3\lib\site-packages\scml\scml2019\common.py", line 12, in
from negmas.outcomes import OutcomeType, Issue
File "C:\Anaconda3\lib\site-packages\negmas_init_.py", line 7, in
from .common import *
File "C:\Anaconda3\lib\site-packages\negmas\common.py", line 17, in
from .java import to_dict, to_java
File "C:\Anaconda3\lib\site-packages\negmas\java.py", line 13, in
from pandas import json_normalize
ImportError: cannot import name 'json_normalize' from 'pandas' (C:\Anaconda3\lib\site-packages\pandas_init_.py)

OneShot tournaments cannot be run properly.

When I executed following OneShot tournaments, the created world had more than two processes like this figure.
This situation happened after I upgraded scml to ver0.4.6.

    results = anac2021_oneshot(
        competitors=tournament_types,
        non_competitors=tournament_types,
        n_configs=5,  # number of different configurations to generate
        n_competitors_per_world=None,
        n_runs_per_world=1,  # number of times to repeat every simulation (with agent assignment)
        n_steps=10,  # number of days (simulation steps) per simulation
        print_exceptions=True,
    )

image

Average production cost

Describe the bug
Average production cost is the same between level 1 and level 2 when it should be double on level 2. I put this in discussion instead of filing an issue where it's more proper.

To Reproduce

agent_types = [RandomOneShotAgent, SyncRandomOneShotAgent, GreedyOneShotAgent, GreedySingleAgreementAgent]

val_0 = 0
val_1 = 0
val_2 = 0
val_3 = 3
val_4 = 4
val_5 = 5
n = 1000
for i in range(n):
    world = SCML2020OneShotWorld(
        **SCML2020OneShotWorld.generate(
            agent_types=agent_types,
            n_steps=50
        ),
        construct_graphs=True,
    )
    if i == 0:
        print(world.agent_profiles)

    val_0 += world.agent_profiles[list(world.agent_profiles.keys())[0]].cost
    val_1 += world.agent_profiles[list(world.agent_profiles.keys())[1]].cost
    val_2 += world.agent_profiles[list(world.agent_profiles.keys())[2]].cost
    val_3 += world.agent_profiles[list(world.agent_profiles.keys())[3]].cost
    val_4 += world.agent_profiles[list(world.agent_profiles.keys())[4]].cost
    val_5 += world.agent_profiles[list(world.agent_profiles.keys())[5]].cost
print(np.array([val_0, val_1, val_2, val_3, val_4, val_5])/n)


defaultdict(<class 'list'>, {'00SyR@0': OneShotProfile(cost=6, input_product=0, n_lines=10, shortfall_penalty_mean=0.7077609276422603, disposal_cost_mean=0.8855099889110551, shortfall_penalty_dev=0.05173409710349367, disposal_cost_dev=0.04921604085230723), '01GSA@0': OneShotProfile(cost=4, input_product=0, n_lines=10, shortfall_penalty_mean=0.5263103223795285, disposal_cost_mean=0.5201459953792971, shortfall_penalty_dev=0.044325413557489104, disposal_cost_dev=0.008711963878956994), '02Ran@0': OneShotProfile(cost=7, input_product=0, n_lines=10, shortfall_penalty_mean=0.7358165454416139, disposal_cost_mean=0.8990585669339071, shortfall_penalty_dev=0.06862436053457982, disposal_cost_dev=0.05497332260213158), '03GSA@1': OneShotProfile(cost=8, input_product=1, n_lines=10, shortfall_penalty_mean=0.6088231183711137, disposal_cost_mean=0.6677210453076889, shortfall_penalty_dev=0.05990315501649243, disposal_cost_dev=0.053014124340221), '04GSA@1': OneShotProfile(cost=9, input_product=1, n_lines=10, shortfall_penalty_mean=0.8639006169834454, disposal_cost_mean=0.677402915478307, shortfall_penalty_dev=0.04869479899135038, disposal_cost_dev=0.043469001032185775), '05SyR@1': OneShotProfile(cost=9, input_product=1, n_lines=10, shortfall_penalty_mean=0.9355877619447468, disposal_cost_mean=0.9469732340406642, shortfall_penalty_dev=0.05625999398377608, disposal_cost_dev=0.028563629972440628)})

[5.404 5.578 5.632 5.645 5.405 5.653]

Expected behavior
The average for the level 2 agents should be 11 instead of 5.5

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.