PK!ޛ AUTHORS.rst======= Credits ======= Development Lead ---------------- * Yasser Mohammad Contributors ------------ * Enrique Areyan * ? PK! CONTRIBUTING.rst.. highlight:: shell ============ Contributing ============ Contributions are welcome, and they are greatly appreciated! Every little bit helps, and credit will always be given. You can contribute in many ways: Types of Contributions ---------------------- Report Bugs ~~~~~~~~~~~ Report bugs at https://github.com/yasserfarouk/negmas/issues. If you are reporting a bug, please include: * Your operating system name and version. * Any details about your local setup that might be helpful in troubleshooting. * Detailed steps to reproduce the bug. Fix Bugs ~~~~~~~~ Look through the GitHub issues for bugs. Anything tagged with "bug" and "help wanted" is open to whoever wants to implement it. Implement Features ~~~~~~~~~~~~~~~~~~ Look through the GitHub issues for features. Anything tagged with "enhancement" and "help wanted" is open to whoever wants to implement it. Write Documentation ~~~~~~~~~~~~~~~~~~~ negmas could always use more documentation, whether as part of the official negmas docs, in docstrings, or even on the web in blog posts, articles, and such. Submit Feedback ~~~~~~~~~~~~~~~ The best way to send feedback is to file an issue at https://github.com/yasserfarouk/negmas/issues. If you are proposing a feature: * Explain in detail how it would work. * Keep the scope as narrow as possible, to make it easier to implement. * Remember that this is a volunteer-driven project, and that contributions are welcome :) Get Started! ------------ Ready to contribute? Here's how to set up `negmas` for local development. 1. Fork the `negmas` repo on GitHub. 2. Clone your fork locally:: $ git clone git@github.com:your_name_here/negmas.git 3. Install your local copy into a virtualenv. This is how you set up your fork for local development (assuming you are using poetry):: $ python -m venv venv $ source venv/bin/activate $ poetry install 4. Create a branch for local development:: $ git checkout -b name-of-your-bugfix-or-feature Now you can make your changes locally. 5. When you're done making changes, check that your changes pass flake8 and the tests, including testing other Python versions with tox:: $ flake8 negmas tests $ python setup.py test or py.test $ tox To get flake8 and tox, just pip install them into your virtualenv. 6. Commit your changes and push your branch to GitHub:: $ git add . $ git delete_bookmark -m "Your detailed description of your changes." $ git push origin name-of-your-bugfix-or-feature 7. Submit a pull request through the GitHub website. Pull Request Guidelines ----------------------- Before you submit a pull request, check that it meets these guidelines: 1. The pull request should include tests. 2. If the pull request adds functionality, the docs should be updated. Put your new functionality into a function with a docstring, and add the feature to the list in README.rst. 3. The pull request should work for Python 3.6, and 3.7. Check https://travis-ci.org/yasserfarouk/negmas/pull_requests and make sure that the tests pass for all supported Python versions. Tips ---- To run a subset of tests:: $ py.test tests.test_scml Deploying --------- A reminder for the maintainers on how to deploy. Make sure all your changes are committed (including an entry in HISTORY.rst). Then run:: $ bumpversion patch # possible: major / minor / patch $ git push $ git push --tags Travis will then deploy to PyPI if tests pass. PK!&Q HISTORY.rstHistory ======= Release 0.2.8 ------------- - adding commands to FactoryState. - Allowing JNegMAS to use GreedyFactoryManager. To do that, the Java factory manager must inherit from GreedyFactoryManager and its class name must end with either GreedyFactoryManager or GFM Release 0.2.7 ------------- - improving naming of java factory managers in log files. - guaranteeing serial tournaments when java factory managers are involved (to be lifter later). - adding links to the YouTube playlist in README - adhering to Black style Release 0.2.6 ------------- - documentation update - setting default world runs to 100 steps - rounding catalog prices and historical costs to money resolution - better defaults for negmas tournaments - adding warnings when running too many simulations. - added version command to negmas - corrected the way min_factories_per_level is handled during tournament config creation. - added --factories to negmas tournament command to control the minimum number of factories per level. - improving naming of managers and factories for debugging purposes - forcing reveal-names when giving debug option to any negmas command - adding short_type_name to all Entity objects for convenient printing Release 0.2.5 ------------- - improvements to ufun representation to speedup computation - making default factory managers slightly less risky in their behavior in long simulations and more risky in short ones - adding jnegmas-setup and genius-setup commands to download and install jenegmas and genius bridge - removing the logger mixin and replaced it with parameters to World and SCMLWorld - added compact parameter to SCMLWorld, tournament, and world generators to reduce the memory footprint - added --compact/--debug to the command line tools to avoid memory and log explosion setting the default to --compact - improving implementation of consumer ufun for cases with negative schedule - changing the return type of SCMLAWI.state from Factory to FactoryState to avoid modifying the original factory. For efficiency reasons, the profiles list is passed as it is and it is possible to modify it but that is forbidden by the laws of the game. - Speeding up and correcting financial report reception. - Making bankruptcy reporting system-wide - avoiding execution of contracts with negative or no quantity and logging ones with zero unit price. - documentation update - bug fix to resolve an issue with ufun calculation for consumers in case of over consumption. - make the default behavior of negmas command to reveal agent types in their names - preventing agents from publishing CFPs with the ID of other agents - documentation update - improved Java support - added option default_dump_extension to ~/negmas/config.json to enable changing the format of dumps from json to yaml. Currently json is the default. This included adding a helper function helpers.dump() to dump in the selected format (or overriding it by providing a file extension). - completing compatibility with SCML description (minor change to the consumer profile) - added two new options to negmas tournament command: anac2019std and anac2019collusion to simulate these two tracks of the ANAC 2019 SCML. Sabotage version will be added later. - added two new functions in apps.scml.utils anac2019_std, anac2019_collusion to simulate these two tracks of the ANAC 2019 SCML. Sabotage version will be added later. - added assign_managers() method to SCMLWorld to allow post-init assignment of managers to factories. - updating simulator documentation Release 0.2.2 ------------- * modifications to achieve compatibility with JNegMAS 0.2.0 * removing the unnecessary ufun property in Negotiator Release 0.2.0 ------------- * First ANAC 2019 SCML release * compatible with JNegMAS 0.2.0 Release 0.1.45 -------------- * implemented money and inventory hiding * added sugar methods to SCMLAWI that run execute for different commands: schedule_production, stop_production, schedule_job, hide_inventory, hide_money * added a json file ~/negmas/config.json to store all global configs * reading jar locations for both jnegmas and genius-bridge from config file * completed bankruptcy and liquidation implementation. * removed the unnecessary _world parameter from Entity * Added parameters to the SCML world to control compensation parameters and default price for products with no catalog prices. * Added contract nullification everywhere. * updated documentation to show all inherited members of all classes and to show all non-private members * Removing the bulletin-board from the public members of the AWI Release 0.1.42 -------------- * documentation improvement * basic bankruptcy implementation * bug fixes Release 0.1.40 -------------- * documentation update * implementing bank and insurance company disable/enable switches * implementing financial reports * implementing checks for bankruptcy in all built-in agents in SCML * implementing round timeout in SAOMechanism Release 0.1.33 -------------- * Moving to Travis CI for continuous integration, ReadTheDocs for documentation and Codacy for code quality Release 0.1.32 -------------- * Adding partial support to factory manager development using Java * Adding annotation control to SCML world simulation disallowing factory managers from sending arbitrary information to co-specifics * Removing some unnecessary dependencies * Moving development to poetry. Now we do not keep a setup.py file and rely on poetry install Release 0.1.3 ------------- * removing some unnecessary dependencies that may cause compilation issues Release 0.1.2 ------------- * First public release PK!WvLICENSENegMAS library (Negotiation oriented Multi-Agent System) Copyright (C) 2019 Yasser Mohammad This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.PK!ȇq README.rst.. image:: https://img.shields.io/pypi/pyversions/negmas.svg :target: https://pypi.python.org/pypi/negmas :alt: Python .. image:: https://img.shields.io/pypi/status/negmas.svg :target: https://pypi.python.org/pypi/negmas :alt: Pypi .. image:: https://img.shields.io/pypi/l/negmas.svg :target: https://pypi.python.org/pypi/negmas :alt: License .. image:: https://img.shields.io/pypi/dm/negmas.svg :target: https://pypi.python.org/pypi/negmas :alt: Downloads .. image:: https://img.shields.io/codacy/coverage/1b204fe0a69e41a298a175ea225d7b81.svg :target: https://app.codacy.com/project/yasserfarouk/negmas/dashboard :alt: Coveage .. image:: https://img.shields.io/codacy/grade/1b204fe0a69e41a298a175ea225d7b81.svg :target: https://app.codacy.com/project/yasserfarouk/negmas/dashboard :alt: Code Quality .. image:: https://img.shields.io/pypi/v/negmas.svg :target: https://pypi.python.org/pypi/negmas :alt: Pypi .. image:: https://img.shields.io/travis/yasserfarouk/negmas.svg :target: https://travis-ci.org/yasserfarouk/negmas :alt: Build Status .. image:: https://readthedocs.org/projects/negmas/badge/?version=latest :target: https://negmas/readthedocs.io/en/latest/?badge=latest :alt: Documentation Status .. image:: https://img.shields.io/badge/code%20style-black-000000.svg :target: https://github.com/ambv/black NegMAS is a python library for developing autonomous negotiation agents embedded in simulation environments. The name ``negmas`` stands for either NEGotiation MultiAgent System or NEGotiations Managed by Agent Simulations (your pick). The main goald of NegMAS is to advance the state of the art in situated simultaneous negotiations. Nevertheless, it can; and was used; in modeling simpler bilateral and multi-lateral negotiations, preference elicitation , etc. .. note:: A YouTube playlist to help you use NegMAS for ANAC2019_ SCM_ league can be found here_ .. _ANAC2019: http://web.tuat.ac.jp/~katfuji/ANAC2019 .. _SCM: http://web.tuat.ac.jp/~katfuji/ANAC2019/#scm .. _here: https://www.youtube.com/playlist?list=PLqvs51K2Mb8LlUQk2DHLGnWdGqhXMNOM- Introduction ============ This package was designed to help advance the state-of-art in negotiation research by providing an easy-to-use yet powerful platform for autonomous negotiation targeting situated simultaneous negotiations. It grew out of the NEC-AIST collaborative laboratory project. By *situated* negotiations, we mean those for which utility functions are not pre-ordained by fiat but are a natural result of a simulated business-like process. By *simultaneous* negotiations, we mean sessions of dependent negotiations for which the utility value of an agreement of one session is affected by what happens in other sessions. The documentation is available at: documentation_ .. _documentation: https://negmas.readthedocs.io/ Main Features ============= This platform was designed with both flexibility and scalability in mind. The key features of the NegMAS package are: #. The public API is decoupled from internal details allowing for scalable implementations of the same interaction protocols. #. Supports agents engaging in multiple concurrent negotiations. #. Provides support for inter-negotiation synchronization either through coupled utility functions or through central *control* agents. #. The package provides sample negotiators that can be used as templates for more complex negotiators. #. The package supports both mediated and unmediated negotiations. #. Supports both bilateral and multilateral negotiations. #. Novel negotiation protocols and simulated *worlds* can be added to the package as easily as adding novel negotiators. #. Allows for non-traditional negotiation scenarios including dynamic entry/exit from the negotiation. #. A large variety of built in utility functions. #. Utility functions can be active dynamic entities which allows the system to model a much wider range of dynamic ufuns compared with existing packages. #. A distributed system with the same interface and industrial-strength implementation is being created allowing agents developed for NegMAS to be seemingly employed in real-world business operations. To use negmas in a project .. code-block:: python import negmas The package was designed for many uses cases. On one extreme, it can be used by an end user who is interested in running one of the built-in negotiation protocols. On the other extreme, it can be used to develop novel kinds of negotiation agents, negotiation protocols, multi-agent simulations (usually involving situated negotiations), etc. Running existing negotiators/negotiation protocols ================================================== Using the package for negotiation can be as simple as the following code snippet: .. code-block:: python from negmas import SAOMechanism, AspirationNegotiator, MappingUtilityFunction session = SAOMechanism(outcomes=10, n_steps=100) negotiators = [AspirationNegotiator(name=f'a{_}') for _ in range(5)] for negotiator in negotiators: session.add(negotiator, ufun=MappingUtilityFunction(lambda x: random.random() * x[0])) session.run() In this snippet, we created a mechanism session with an outcome-space of *10* discrete outcomes that would run for *10* steps. Five agents with random utility functions are then created and *added* to the session. Finally the session is *run* to completion. The agreement (if any) can then be accessed through the *state* member of the session. The library provides several analytic and visualization tools to inspect negotiations. See the first tutorial on *Running a Negotiation* for more details. Developing a negotiator ======================= Developing a novel negotiator slightly more difficult by is still doable in few lines of code: .. code-block:: python from negmas.sao import SAONegotiator from negmas import ResponseType class MyAwsomeNegotiator(SAONegotiator): def __init__(self): # initialize the parents super().__init__(self) def respond(self, offer, state): # decide what to do when receiving an offer return ResponseType.ACCEPT_OFFER def propose(self, state): # proposed the required number of proposals (or less) pass By just implementing `respond()` and `propose()`. This negotiator is now capable of engaging in alternating offers negotiations. See the documentation of `Negotiator` for a full description of available functionality out of the box. Developing a negotiation protocol ================================= Developing a novel negotiation protocol is actually even simpler: .. code-block:: python from negmas.mechanisms import Mechanism class MyNovelProtocol(Mechanism): def __init__(self): super().__init__() def round(self): # one step of the protocol pass By implementing the single `round()` function, a new protocol is created. New negotiators can be added to the negotiation using `add()` and removed using `remove()`. See the documentation for a full description of `Mechanism` available functionality out of the box [Alternatively you can use `Protocol` instead of `Mechanism`]. Running a world simulation ========================== The *raison d'être* for NegMAS is to allow you to develop negotiation agents capable of behaving in realistic *business like* simulated environments. These simulations are called *worlds* in NegMAS. Agents interact with each other within these simulated environments trying to maximize some intrinsic utility function of the agent through several *possibly simultaneous* negotiations. The `situated` module provides all that you need to create such worlds. An example can be found in the `scml` package. This package implements a supply chain management system in which factory managers compete to maximize their profits in a market with only negotiations as the means of securing contracts. Acknowledgement =============== .. _Genius: http://ii.tudelft.nl/genius NegMAS tests use scenarios used in ANAC 2010 to ANAC 2018 competitions obtained from the Genius_ Platform. These domains can be found in the tests/data and notebooks/data folders. PK!y>negmas/__init__.py# -*- coding: utf-8 -*- """A framework for conducting multi-strand multilateral asynchronous negotiations on multiple issues.""" __author__ = """Yasser Mohammad""" __email__ = "yasserfarouk@gmail.com" __version__ = "__version__ = '0.2.8'" import json import pathlib NEGMAS_CONFIG = {} """Global configuration parameters for NegMAS""" CONFIG_KEY_JNEGMAS_JAR = "jnegmas_jar" """Key name for the JNegMAS jar in `NEGMAS_CONFIG`""" CONFIG_KEY_GENIUS_BRIDGE_JAR = "genius_bridge_jar" """Key name for the Genius bridge jar in `NEGMAS_CONFIG`""" # loading config file if any __conf_path = pathlib.Path("~/negmas/config.json").expanduser().absolute() if __conf_path.exists(): with open(__conf_path, "r") as f: NEGMAS_CONFIG = json.load(f) from .common import * from .outcomes import * from .utilities import * from .negotiators import * from .mechanisms import * from .sao import * from .inout import * from .genius import * from .situated import * __all__ = ( common.__all__ + outcomes.__all__ + utilities.__all__ + negotiators.__all__ + mechanisms.__all__ + sao.__all__ + inout.__all__ + genius.__all__ + situated.__all__ + ["generics", "helpers", "events", "apps", "tournaments"] ) PK!&DNNnegmas/apps/__init__.py"""This package contains all applications that utilize the situated module""" PK!>dnegmas/apps/scml/__init__.py""" The implementation file for all entities needed for ANAC-SCML 2019. Participants need to provide a class inherited from `FactoryManager` that implements all of its abstract functions. Participants can optionally override any other methods of this class or implement new `NegotiatorUtility` class. Simulation steps: ----------------- #. prepare custom stats (call `_pre_step_stats`) #. sign contracts that are to be signed at this step calling `on_contract_signed` as needed #. step all existing negotiations `negotiation_speed_multiple` times handling any failed negotiations and creating contracts for any resulting agreements #. run all `Entity` objects registered (i.e. all agents). `Consumer` s run first then `FactoryManager` s then `Miner` s #. execute contracts that are executable at this time-step handling any breaches #. Custom Simulation Steps: #. step all factories (`Factory` objects) running any pre-scheduled commands #. Apply interests and pay loans #. remove expired `CFP` s #. Deliver any products that are in transportation #. remove any negotiations that are completed! #. update basic stats #. update custom stats (call `_post_step_stats`) Remarks about re-negotiation on breaches: ----------------------------------------- - The victim is asked first to specify the negotiation agenda (issues) then the perpetrator - renegotiations for breaches run immediately to completion independent from settings of `negotiation_speed_multiplier` and `immediate_negotiations`. That include conclusion and signing of any resulting agreements. Remarks about timing: --------------------- - The order of events within a single time-step are as follows: #. Contracts scheduled to be signed are signed. #. Scheduled negotiations run for the predefined number of steps. Any negotiation that result in a contract or fail may trigger other negotiations. #. If `immediate_negotiations`, some of the newly added negotiations may be concluded/failed. #. Any newly concluded contracts that are to be signed at this step are signed #. Contracts are executed including full execution of any re-negotiations and breaches are handled. Notice that if re-negotiation leads to new contracts, these will be concluded and signed immediately at this step. Please note the following about contract execution: - Products are moved from the seller's storage to a temporary *truck* as long as they are available at the time of contract execution. Because contract execution happens *before* actual production, outputs from production processes *CANNOT* be sold at the same time-step. #. Production is executed on all factories. For a `Process` to start/continue on a `Line`, all its inputs required at this time-step **MUST** be available in storage of the corresponding factory *by this point*. This implies that it is impossible for any processes to start at time-step *0* except if initial storage was nonzero. `FactoryManager` s are informed about processes that cannot start due to storage or fund shortage (or cannot continue due to storage shortage) through an `on_production_failure` call. #. Outputs of the `Process` are generated at *the end* of the corresponding time-step. It is immediately moved to storage. Because outputs are generated at the *end* of the step and inputs are consumed at the beginning, a factory cannot use outputs of a process as inputs to another process that starts at the same time-step. #. Products are moved from the temporary *truck* to the buyer's storage after the `transportation_delay` have passed at the *end* of the time-step. Transportation completes at the *end* of the time-step no matter what is the value for `transportation_delay`. This means that if a `FactoryManager` believes that it can produce some product at time *t*, it should never contract to sell it before *t+d + 1* where *d* is the `transportation_delay` (the *1* comes from the fact that contract execution happens *before* production). Even for a zero transportation delay, you cannot produce something and sell it in the same time-step. Moreover, the buyer should never use the product to be delivered at time *t* as an input to a production process that needs it before step *t+1*. #. When contracts are executed, the funds are deducted from the buyer's wallet at the *beginning* of the simulation step and deposited in the seller's wallet at the *end* of that step (similar to what happens to the products). This means that a factory manager cannot use funds it receives from sales at time *t* for buying products before *t + 1*. Remarks about ANAC 2019 SCML League: ------------------------------------ Given the information above, and settings for the ANAC 2019 SCML you can confirm for yourself that the following rules are all correct: #. No agents except miners should contract on delivery at time *0*. #. `FactoryManager` s should never sign contracts to sell the output of their production with delivery at *t* except if this production starts at step *t* and the contract is signed no later than than *t-1*. #. If not all inputs are available in storage, `FactoryManager` s should never sign contracts to sell the output of production with delivery at *t* later than *t-2* (and that is optimistic). """ from .common import * from .schedulers import * from .awi import * from .agent import * from .bank import * from .insurance import * from .world import * from .factory_managers import * from .consumers import * from .miners import * from . import utils from . import helpers from .utils import * from .helpers import * from .simulators import * __all__ = ( common.__all__ + awi.__all__ + factory_managers.__all__ + bank.__all__ + insurance.__all__ + agent.__all__ + simulators.__all__ + utils.__all__ + helpers.__all__ + schedulers.__all__ + world.__all__ + consumers.__all__ + miners.__all__ + ["utils", "helpers"] ) PK! //negmas/apps/scml/agent.py"""The base class agent needed for all SCML agents.""" import itertools import math from abc import abstractmethod from collections import defaultdict from typing import Dict, List, Optional, Any, TYPE_CHECKING from negmas import UtilityFunction from ...common import AgentMechanismInterface from ...negotiators import Negotiator from ...outcomes import Issue from ...situated import Agent from ...situated import Contract, Breach from .common import ( ManufacturingProfileCompiled, ProductManufacturingInfo, Process, Product, Loan, CFP, FinancialReport, ) if TYPE_CHECKING: from .awi import SCMLAWI __all__ = ["SCMLAgent"] class SCMLAgent(Agent): """The base for all SCM Agents""" # @todo remove negotiator_type from here and add it independently to consumer, miner, and greedy_factory_manager def __init__(self, name: str = None): super().__init__(name=name) self.line_profiles: Dict[int, ManufacturingProfileCompiled] = {} """A mapping specifying for each `Process` index, all the profiles used to run it in the factory""" self.process_profiles: Dict[int, ManufacturingProfileCompiled] = {} """A mapping specifying for each `Process` index, all the profiles used to run it in the factory""" self.producing: Dict[int, List[ProductManufacturingInfo]] = defaultdict(list) """Mapping from a product to all manufacturing processes that can generate it""" self.consuming: Dict[int, List[ProductManufacturingInfo]] = defaultdict(list) """Mapping from a product to all manufacturing processes that can consume it""" self.compiled_profiles: List[ManufacturingProfileCompiled] = [] """All the profiles to be used by the factory belonging to this agent compiled to use indices""" self.immediate_negotiations = False """Whether or not negotiations start immediately upon registration (default is to start on the next production step)""" self.negotiation_speed_multiple: int = 1 """The number of negotiation rounds (steps) conducted in a single production step""" self.transportation_delay: int = 0 """Transportation delay in the system. Default is zero""" self.products: List[Product] = [] """List of products in the system""" self.processes: List[Process] = [] """List of processes in the system""" @property def awi(self) -> "SCMLAWI": """Returns the Agent-World-Interface through which the agent does all of its actions in the world. A single excption is request_negotiation for which it is recommended to actually call the helper method on the agent itself instead of directly calling the AWI version.""" return self._awi @awi.setter def awi(self, awi: "SCMLAWI"): """Sets the AWI. Not to be used by agents. Only used by the world simulation itself.""" self._awi = awi def init_(self): """The initialization function called by the world directly. It does the following actions by default: 1. copies some of the static world settings to the agent to make them available without calling the AWI. 2. prepares production related properties like producing, consuming, line_profiles, compiled_profiles, etc. 3. registers interest in all products that the agent can produce or consume in its factory. 4. finally it calls any custom initialization logic implemented in `init`() See Also: `init`, `step` """ # noinspection PyUnresolvedReferences self.products = self.awi.products # type: ignore # noinspection PyUnresolvedReferences self.processes = self.awi.processes # type: ignore self.negotiation_speed_multiple = self.awi.bb_read( "settings", "negotiation_speed_multiple" ) self.immediate_negotiations = self.awi.bb_read( "settings", "immediate_negotiations" ) self.transportation_delay = self.awi.bb_read( section="settings", key="transportation_delay" ) factory = self.awi.state if factory is None: raise ValueError("Cannot init any SCMLAgent without specifying a factory") profiles = factory.profiles self.line_profiles = defaultdict(list) self.process_profiles = defaultdict(list) self.compiled_profiles = [] self.producing = defaultdict(list) self.consuming = defaultdict(list) p2i = dict(zip(self.processes, range(len(self.processes)))) for index, profile in enumerate(profiles): compiled = ManufacturingProfileCompiled.from_manufacturing_profile( profile=profile, process2ind=p2i ) self.compiled_profiles.append(compiled) self.line_profiles[profile.line].append(compiled) self.process_profiles[profile.process].append(compiled) process = profile.process for outpt in process.outputs: step = int(math.ceil(outpt.step * profile.n_steps)) self.producing[outpt.product].append( ProductManufacturingInfo( profile=index, quantity=outpt.quantity, step=step ) ) for inpt in process.inputs: step = int(math.floor(inpt.step * profile.n_steps)) self.consuming[inpt.product].append( ProductManufacturingInfo( profile=index, quantity=inpt.quantity, step=step ) ) self.awi.register_interest( list(set(itertools.chain(self.producing.keys(), self.consuming.keys()))) ) self.init() def can_expect_agreement(self, cfp: "CFP", margin: int): """ Checks if it is possible in principle to get an agreement on this CFP by the time it becomes executable Args: margin: cfp: Returns: """ return ( cfp.max_time >= self.awi.current_step + 1 - int(self.immediate_negotiations) + margin ) def _create_annotation(self, cfp: "CFP"): """Creates full annotation based on a cfp that the agent is receiving""" partners = [self.id, cfp.publisher] annotation = {"cfp": cfp, "partners": partners} if cfp.is_buy: annotation["seller"] = self.id annotation["buyer"] = cfp.publisher else: annotation["buyer"] = self.id annotation["seller"] = cfp.publisher return annotation def _respond_to_negotiation_request( self, initiator: str, partners: List[str], issues: List[Issue], annotation: Dict[str, Any], mechanism: AgentMechanismInterface, role: Optional[str], req_id: Optional[str], ) -> Optional[Negotiator]: """ Called by the mechanism to ask for joining a negotiation. The agent can refuse by returning a None Args: initiator: The ID of the agent that initiated the negotiation request partners: The partner list (will include this agent) issues: The list of issues annotation: Any annotation specific to this negotiation. mechanism: The mechanism that started the negotiation role: The role of this agent in the negotiation req_id: The req_id passed to the AWI when starting the negotiation (only to the initiator). Returns: None to refuse the negotiation or a `Negotiator` object appropriate to the given mechanism to accept it. Remarks: - It is expected that world designers will introduce a better way to respond and override this function to call it """ cfp = annotation["cfp"] return self.respond_to_negotiation_request(cfp=cfp, partner=cfp.publisher) def request_negotiation( self, cfp: CFP, negotiator: Negotiator = None, ufun: UtilityFunction = None ) -> bool: """ Requests a negotiation from the AWI while keeping track of available negotiation requests Args: cfp: negotiator: ufun: Returns: Whether the negotiation request was successful indicating that the partner accepted the negotiation """ if negotiator is not None and ufun is not None: negotiator.utility_function = ufun req_id = self._add_negotiation_request_info( issues=cfp.issues, partners=[self.id, cfp.publisher], annotation=None, negotiator=negotiator, extra=None, ) return self.awi.request_negotiation(cfp=cfp, req_id=req_id) # ------------------------------------------------------------------ # EVENT CALLBACKS (Called by the `World` when certain events happen) # ------------------------------------------------------------------ @abstractmethod def confirm_loan(self, loan: Loan, bankrupt_if_rejected: bool) -> bool: """called by the world manager to confirm a loan if needed by the buyer of a contract that is about to be breached""" @abstractmethod def on_contract_nullified( self, contract: Contract, bankrupt_partner: str, compensation: float ) -> None: """Will be called whenever a contract the agent is involved in is nullified because another partner went bankrupt""" @abstractmethod def on_agent_bankrupt(self, agent_id: str) -> None: """ Will be called whenever any agent goes bankrupt Args: agent_id: The ID of the agent that went bankrupt Remarks: - Agents can go bankrupt in two cases: 1. Failing to pay one installments of a loan they bought and refusing (or being unable to) get another loan to pay it. 2. Failing to pay a penalty on a sell contract they failed to honor (and refusing or being unable to get a loan to pay for it). - All built-in agents ignore this call and they use the bankruptcy list ONLY to decide whether or not to negotiate in their `on_new_cfp` and `respond_to_negotiation_request` callbacks by pulling the bulletin-board using the helper function `is_bankrupt` of their AWI. """ @abstractmethod def confirm_partial_execution( self, contract: Contract, breaches: List[Breach] ) -> bool: """Will be called whenever a contract cannot be fully executed due to breaches by the other partner. Args: contract: The contract that was breached breaches: A list of all the breaches committed. Remarks: - Will not be called if both partners committed breaches. """ @abstractmethod def confirm_contract_execution(self, contract: Contract) -> bool: """Called before executing any agreement""" return True @abstractmethod def respond_to_negotiation_request( self, cfp: "CFP", partner: str ) -> Optional[Negotiator]: """Called when a prospective partner requests a negotiation to start""" @abstractmethod def on_new_cfp(self, cfp: "CFP"): """Called when a new CFP for a product for which the agent registered interest is published""" @abstractmethod def on_remove_cfp(self, cfp: "CFP"): """Called when a new CFP for a product for which the agent registered interest is removed""" @abstractmethod def on_new_report(self, report: FinancialReport): """Called whenever a financial report is published. Args: report: The financial report giving details of the standing of an agent at some time (see `FinancialReport`) Remarks: - Agents must opt-in to receive these calls by calling `receive_financial_reports` on their AWI """ PK!PJGC\C\negmas/apps/scml/awi.py""" Implements an agent-world-interface (see `AgentWorldInterface`) for the SCM world. """ from typing import Optional, List, Dict, Any from negmas import Issue from negmas.apps.scml.common import * from negmas.apps.scml.common import FactoryState from negmas.java import to_java, from_java, to_dict from negmas.situated import AgentWorldInterface, Contract, Action __all__ = ["SCMLAWI"] class SCMLAWI(AgentWorldInterface): """A single contact point between SCML agents and the world simulation. The agent can access the world simulation in one of two ways: 1. Attributes and methods available in this Agent-World-Interface 2. Attributes and methods in the `FactoryManager` object itself which provide handy shortcuts to the agent-world interface **Attributes** *Simulation settings* - `current_step` : Current simulation step - `default_signing_delay` : The grace period allowed between contract conclusion and signature by default (i.e. if not agreed upon during the negotiation) - `n_steps` : Total number of simulation steps. - `relative_time` : The fraction of total simulation time elapsed (it will be a number between 0 and 1) *Production Graph* - `products` : A list of `Product` objects giving all products defined in the world simulation - `processes` : A list of `Process` objects giving all products defined in the world simulation *Agent Related* - `state` : The current private state available to the agent. In SCML it is a `FactoryState` object. **Methods** *Production Control* - `schedule_job` : Schedules a `Job` for production sometime in the future - `schedule_production` : Schedules production using profile number instead of a `Job` object - `cancel_production` : Cancels already scheduled production (if it did not start yet) or stop a running production. - `execute` : A general function to execute any command on the factory. There is no need to directly call this function as the SCMLAWI provides convenient functions (e.g. `schedule_job` , `hide_funds` , etc) to achieve the same goal without having to worry about creating `Action` objects *Storage and Wallet Control* - `hide_funds` : Hides funds from the view of the simulator. Note that when bankruptcy is considered, hidden funds are visible to the simulator. - `hide_inventory` : Hides inventory from the view of the simulator. Note that when bankruptcy is considered, hidden funds are visible to the simulator. - `unhide_funds` : Un-hides funds hidden earlier with a call to `hide_funds` - `unhide_inventory` : Un-hides inventory hidden earlier with a call to `hide_inventory` *Negotiation and CFP Control* - `register_cfp` : Registers a Call-for-Proposals on the bulletin board. - `remove_cfp` : Removes a Call-for-Proposals from the bulletin board. - `request_negotiation` : Requests a negotiation based on the content of a CFP published on the bulletin-board. *It is recommended not to use this method directly and to request negotiations using the request_negotiation method of `FactoryManager` (i.e. use self.request_negotiation instead of self.awi.request_negotiation). This makes it possible for NegMAS to keep track of existing `requested_negotiations` and `running_negotiations` for you. *Notification Control* - `receive_financial_reports` : Register/unregisters interest in receiving financial reports for an agent, a set of agents or all agents. - `register_interest` : registers interest in receiving CFPs about a set of products. By default all `FactoryManager` objects are registered to receive all CFPs for any product they can produce or need to consumer according to their line-profiles. - `unregister_interest` : unregisters interest in receiving CFPs about a set of products. *Information about Other Agents* - `is_bankrupt` : Asks about the bankruptcy status of an agent - `receive_financial_reports` : Register/unregisters interest in receiving financial reports for an agent, a set of agents or all agents. - `reports_at` : reads *all* financial reports produced at a given time-step - `reports_for` : reads *all* financial reports of a given agent *Financial Control* - `evaluate_insurance` : Asks for the premium to be paid for insuring against partner breaches for a given contract - `buy_insurance` : Buys an insurance against partner breaches for a given contract *Bulletin-Board* The bulletin-board is a key-value store. These methods allows the agent to interact with it. *The `SCMLAWI` provides convenient functions for recording to the bulletin-board so you mostly need to use read/query functions*. - `bb_read` : Reads a complete section or a single value from the bulletin-board - `bb_query` : Returns all records in the given section/sections of the bulletin-board that satisfy a query - `bb_record` : Registers a record in the bulletin-board. - `bb_remove` : Removes a record from the bulletin-board. The following list of sections are available in the SCML Bulletin-Board (Use the exact string for the ``section`` parameter of any method starting with ``bb_``): - **cfps**: All CFPs currently on the board. The key is the CFP ID - **products**: A list of all products. The key is the product index/ID - **processes**: A list of all processes. The key is the product index/ID - **bankruptcy**: The bankruptcy list giving names of all bankrupt agents. - **reports_time**: Financial reports indexed by time. - **reports_agent**: Financial reports indexed by agent - **breaches**: Breach-list indexed by breach ID giving all breaches committed in the system - **settings**: Static settings of the simulation. The following settings are currently available: - *breach_penalty_society*: Penalty of breaches paid to society (as a fraction of contract value). This is always paid for every breach whether or not there is a negotiated breach. - *breach_penalty_victim*: Penalty of breaches paid to victim (as a fraction of contract value). This is always paid for every breach whether or not there is a negotiated breach. - *immediate_negotiations*: Whether negotiations start immediately when registered (the other possibility -- which is the default -- is for them to start at the next production step). - *negotiation_speed_multiple*: Number of negotiation steps that finish in a single production step. - *negotiation_n_steps*: Maximum allowed number of steps (rounds) in any negotiation - *negotiation_step_time_limit*: The maximum real-time allowed for each negotiation step (round) - *negotiation_time_limit*: The time limit for a complete negotiation. - *transportation_delay*: Transportation delay when products are moved between factories. Default is zero. - *transfer_delay*: The delay in transferring funds between factories when executing a contract. Default is zero. - *n_steps*: Number of simulation steps - *time_limit*: Time limit for the complete simulation - stats: Global statistics about the simulation. **Not available for SCML 2019 league**. *Logging* - `logerror` : Logs an error in the world simulation log file - `logwarning` : Logs a warning in the world simulation log file - `loginfo` : Logs information in the world simulation log file - `logdebug` : Logs debug information in the world simulation log file """ def register_cfp(self, cfp: CFP) -> None: """Registers a CFP""" self._world.n_new_cfps += 1 cfp.money_resolution = self._world.money_resolution cfp.publisher = ( self.agent.id ) # force the publisher to be the agent using this AWI. self.bb_record(section="cfps", key=cfp.id, value=cfp) def register_interest(self, products: List[int]) -> None: """registers interest in receiving callbacks about CFPs related to these products""" self._world.register_interest(agent=self.agent, products=products) def unregister_interest(self, products: List[int]) -> None: """registers interest in receiving callbacks about CFPs related to these products""" self._world.unregister_interest(agent=self.agent, products=products) def remove_cfp(self, cfp: CFP) -> bool: """Removes a CFP""" if self.agent.id != cfp.publisher: return False return self.bb_remove(section="cfps", key=str(hash(cfp))) def evaluate_insurance(self, contract: Contract, t: int = None) -> Optional[float]: """Can be called to evaluate the premium for insuring the given contract against breachs committed by others Args: contract: hypothetical contract t: time at which the policy is to be bought. If None, it means current step """ return self._world.evaluate_insurance(contract=contract, agent=self.agent, t=t) def buy_insurance(self, contract: Contract) -> bool: """Buys insurance for the contract by the premium calculated by the insurance company. Remarks: The agent can call `evaluate_insurance` to find the premium that will be used. """ return self._world.buy_insurance(contract=contract, agent=self.agent) def _create_annotation(self, cfp: "CFP"): """Creates full annotation based on a cfp that the agent is receiving""" partners = [self.agent.id, cfp.publisher] annotation = {"cfp": cfp, "partners": partners} if cfp.is_buy: annotation["seller"] = self.agent.id annotation["buyer"] = cfp.publisher else: annotation["buyer"] = self.agent.id annotation["seller"] = cfp.publisher return annotation def request_negotiation( self, cfp: CFP, req_id: str, roles: List[str] = None, mechanism_name: str = None, mechanism_params: Dict[str, Any] = None, ) -> bool: """ Requests a negotiation with the publisher of a given CFP Args: cfp: The CFP to negotiate about req_id: A string that is passed back to the caller in all callbacks related to this negotiation roles: The roles of the CFP publisher and the agent (in that order). By default no roles are passed (None) mechanism_name: The mechanism type to use. If not given the default mechanism from the world will be used mechanism_params: Parameters of the mechanism Returns: Success of failure of the negotiation Remarks: - The `SCMLAgent` class implements another request_negotiation method that does not receive a `req_id`. This helper method is recommended as it generates the required req_id and passes it keeping track of requested negotiations (and later of running negotiations). Call this method direclty *only* if you do not intend to use the `requested_negotiations` and `running_negotiations` properties of the `SCMLAgent` class """ default_annotation = self._create_annotation(cfp) return super().request_negotiation_about( issues=cfp.issues, req_id=req_id, partners=default_annotation["partners"], roles=roles, annotation=default_annotation, mechanism_name=mechanism_name, mechanism_params=mechanism_params, ) def request_negotiation_about( self, issues: List[Issue], partners: List[str], req_id: str, roles: List[str] = None, annotation: Optional[Dict[str, Any]] = None, mechanism_name: str = None, mechanism_params: Dict[str, Any] = None, ): """ Overrides the method of the same name in the base class to disable it in SCM Worlds. **Do not call this method** """ raise RuntimeError( "request_negotiation_about should never be called directly in the SCM world" ", call request_negotiation instead." ) def is_bankrupt(self, agent_id: str) -> bool: """ Checks whether the given agent is bankrupt Args: agent_id: Agent ID Returns: The bankruptcy state of the agent """ return bool(self.bb_read("bankruptcy", key=agent_id)) def reports_for(self, agent_id: str) -> List[FinancialReport]: """ Gets all financial reports of an agent (in the order of their publication) Args: agent_id: Agent ID Returns: """ reports = self.bb_read("reports_agent", key=agent_id) if reports is None: return [] return reports def reports_at(self, step: int = None) -> Dict[str, FinancialReport]: """ Gets all financial reports of all agents at a given step Args: step: Step at which the reports are required. If None, the last set of reports is returned Returns: A dictionary with agent IDs in keys and their financial reports at the given time as values """ if step is None: reports = self.bb_query(section="reports_time", query=None) reports = self.bb_read( "reports_time", key=str(max([int(_) for _ in reports.keys()])) ) else: reports = self.bb_read("reports_time", key=str(step)) if reports is None: return {} return reports def receive_financial_reports( self, receive: bool = True, agents: Optional[List[str]] = None ) -> None: """ Registers/unregisters interest in receiving financial reports Args: receive: True to receive and False to stop receiving agents: If given reception is enabled/disabled only for the given set of agents. Remarks: - by default financial reports are not sent to any agents. To opt-in to receive financial reports, call this method. """ self._world.receive_financial_reports(self.agent, receive, agents) @property def state(self) -> FactoryState: """Returns the private state of the agent in that world. In the SCML world, that is a reference to its factory. You are allowed to read information from the returned `Factory` but **not to modify it or call ANY methods on it that modify the state**. """ return self._world.get_private_state(self.agent) @property def products(self) -> List[Product]: """Products in the world""" return self._world.products @property def processes(self) -> List[Process]: """Processes in the world""" return self._world.processes # sugar functions (implementing actions that can all be done through execute def schedule_production( self, profile: int, step: int, contract: Optional[Contract] = None, override: bool = True, ) -> None: """ Schedules production on the agent's factory Args: profile: Index of the profile in the agent's `compiled_profiles` list step: The step to start production according to the given profile contract: The contract for which the production is scheduled (optional) override: Whether to override existing production jobs schedules at the same time. """ self.execute( action=Action( type="run", params={ "profile": profile, "time": step, "contract": contract, "override": override, }, ) ) def stop_production( self, line: int, step: int, contract: Optional[Contract], override: bool = True ): """ Stops/cancels production scheduled at the given line at the given time. Args: line: One of the factory lines (index) step: Step to stop/cancel production at contract: The contract for which the job is scheduled (optional) override: Whether to override existing production jobs schedules at the same time. """ self.execute(action=Action(type="stop", params={"line": line, "time": step})) cancel_production = stop_production """ Stops/cancels production scheduled at the given line at the given time. Args: line: One of the factory lines (index) step: Step to stop/cancel production at """ def schedule_job(self, job: Job, contract: Optional[Contract]): """ Schedules production using a `Job` object. This can be used to schedule any kind of job Args: job: The job description contract: The contract for which the job is scheduled (optional) Remarks: - Notice that actions that require the profile member of Job (run) never use the line member and vice versa. """ self.execute( action=Action( type=job.action, params={ "profile": job.profile, "time": job.time, "line": job.line, "contract": contract, "override": job.override, }, ) ) def hide_inventory(self, product: int, quantity: int) -> None: """ Hides the given quantity of the given product so that it is not accessible by the simulator and does not appear in reports etc. Args: product: product index quantity: the amount of the product to hide Remarks: - if the current quantity in storage of the product is less than the amount to be hidden, whatever quantity exists is hidden - hiding is always immediate """ self.execute( action=Action( type="hide_product", params={"product": product, "quantity": quantity} ) ) def hide_funds(self, amount: float) -> None: """ Hides the given amount of money so that it is not accessible by the simulator and does not appear in reports etc. Args: amount: The amount of money to hide Remarks: - if the current cash in the agent's wallet is less than the amount to be hidden, all the cash is hidden. - hiding is always immediate """ self.execute(action=Action(type="hide_funds", params={"amount": amount})) def unhide_inventory(self, product: int, quantity: int) -> None: """ Un-hides the given quantity of the given product so that it is not accessible by the simulator and does not appear in reports etc. Args: product: product index quantity: the amount of the product to hide Remarks: - if the current quantity in storage of the product is less than the amount to be hidden, whatever quantity exists is hidden - hiding is always immediate """ self.execute( action=Action( type="unhide_product", params={"product": product, "quantity": quantity} ) ) def unhide_funds(self, amount: float) -> None: """ Un-hides the given amount of money so that it is not accessible by the simulator and does not appear in reports etc. Args: amount: The amount of money to unhide Remarks: - if the current cash in the agent's wallet is less than the amount to be hidden, all the cash is hidden. - hiding is always immediate """ self.execute(action=Action(type="unhide_funds", params={"amount": amount})) class _ShadowSCMLAWI: """An SCMLAWI As seen by JNegMAS. This is an object that is not visible to python code. It is not directly called from python ever. It is only called from a corresponding Java object to represent an internal python object. Because of he way py4j works, we cannot just use dunders to implement this kind of object in general. We will have to implement each such class independently. This kind of classes will always have an internal Java class implementing a Java interface in Jnegmas that starts with Py. """ def to_java(self): return to_dict(self.shadow) def __init__(self, awi: SCMLAWI): self.shadow = awi def getProducts(self): return to_java(self.shadow.products) def getProcesses(self): return to_java(self.shadow.processes) def getState(self): return to_java(self.shadow.state) def relativeTime(self): return self.shadow.relative_time def getCurrentStep(self): return self.shadow.current_step def getNSteps(self): return self.shadow.n_steps def getDefaultSigningDelay(self): return self.shadow.default_signing_delay def requestNegotiation( self, cfp, req_id: str, roles=None, mechanism_name=None, mechanism_params=None ): return self.shadow.request_negotiation( from_java(cfp), req_id, roles, mechanism_name, mechanism_params ) def registerCFP(self, cfp: Dict[str, Any]) -> None: """Registers a CFP""" self.shadow.register_cfp(from_java(cfp)) def removeCFP(self, cfp: Dict[str, Any]) -> bool: """Removes a CFP""" return self.shadow.remove_cfp(from_java(cfp)) def registerInterest(self, products: List[int]) -> None: """registers interest in receiving callbacks about CFPs related to these products""" self.shadow.register_interest(from_java(products)) def unregisterInterest(self, products: List[int]) -> None: """registers interest in receiving callbacks about CFPs related to these products""" self.shadow.unregister_interest(from_java(products)) def evaluateInsurance( self, contract: Dict[str, Any], t: int = None ) -> Optional[float]: """Can be called to evaluate the premium for insuring the given contract against breaches committed by others Args: contract: hypothetical contract t: time at which the policy is to be bought. If None, it means current step """ result = self.shadow.evaluate_insurance(from_java(contract), t) if result < 0: return None return result def buyInsurance(self, contract: Dict[str, Any]) -> bool: """Buys insurance for the contract by the premium calculated by the insurance company. Remarks: The agent can call `evaluate_insurance` to find the premium that will be used. """ return self.shadow.buy_insurance(from_java(contract)) def loginfo(self, msg: str): return self.shadow.loginfo(msg) def logwarning(self, msg: str): return self.shadow.logwarning(msg) def logdebug(self, msg: str): return self.shadow.logdebug(msg) def logerror(self, msg: str): return self.shadow.logerror(msg) class Java: implements = ["jnegmas.apps.scml.awi.SCMLAWI"] PK!tcYv,v,negmas/apps/scml/bank.py"""Implements all builtin banks.""" from abc import ABC from collections import defaultdict from typing import Dict, List, Optional, TYPE_CHECKING, Any from negmas import Issue, Negotiator, Mechanism, AgentMechanismInterface, MechanismState from negmas.situated import Agent, RenegotiationRequest, Contract, Breach from .common import * if TYPE_CHECKING: from .agent import SCMLAgent __all__ = ["DefaultBank", "Bank"] class Bank(Agent, ABC): """Base class for all banks""" def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self._world = None def _respond_to_negotiation_request( self, initiator: str, partners: List[str], issues: List[Issue], annotation: Dict[str, Any], mechanism: AgentMechanismInterface, role: Optional[str], req_id: Optional[str], ) -> Optional[Negotiator]: pass def on_neg_request_rejected(self, req_id: str, by: Optional[List[str]]): pass def on_neg_request_accepted(self, req_id: str, mechanism: AgentMechanismInterface): pass def on_negotiation_failure( self, partners: List[str], annotation: Dict[str, Any], mechanism: AgentMechanismInterface, state: MechanismState, ) -> None: pass def on_negotiation_success( self, contract: Contract, mechanism: AgentMechanismInterface ) -> None: pass def on_contract_signed(self, contract: Contract) -> None: pass def on_contract_cancelled(self, contract: Contract, rejectors: List[str]) -> None: pass def sign_contract(self, contract: Contract) -> Optional[str]: pass def respond_to_negotiation_request( self, initiator: str, partners: List[str], issues: List[Issue], annotation: Dict[str, Any], mechanism: Mechanism, role: Optional[str], req_id: str, ) -> Optional[Negotiator]: pass class DefaultBank(Bank): """Represents a bank in the world""" def init(self): pass def respond_to_negotiation_request( self, initiator: str, partners: List[str], issues: List[Issue], annotation: Dict[str, Any], mechanism: Mechanism, role: Optional[str], req_id: str, ) -> Optional[Negotiator]: pass def __init__( self, minimum_balance: float, interest_rate: float, interest_max: float, balance_at_max_interest: float, installment_interest: float, time_increment: float, a2f: Dict[str, Factory], disabled: bool = False, name: str = None, ): super().__init__(name=name) self.storage: Dict[int, int] = defaultdict(int) self.wallet: float = 0.0 self.disabled = disabled self.loans: Dict[SCMLAgent, List[Loan]] = defaultdict(list) self.minimum_balance = minimum_balance self.interest_rate = interest_rate self.interest_max = interest_max self.installment_interest = installment_interest self.time_increment = time_increment self.balance_at_max_interest = balance_at_max_interest self._credit_rating: Dict[str, float] = defaultdict(float) self.a2f = a2f def set_renegotiation_agenda( self, contract: Contract, breaches: List[Breach] ) -> Optional[RenegotiationRequest]: return None def respond_to_renegotiation_request( self, contract: Contract, breaches: List[Breach], agenda: RenegotiationRequest ) -> Optional[Negotiator]: raise ValueError("The bank does not receive callbacks") def _evaluate_loan( self, agent: "SCMLAgent", amount: float, n_installments: int, starts_at: int, installment_loan=False, ) -> Optional[Loan]: """Evaluates the interest that will be imposed on the agent to buy_loan that amount""" if self.disabled: return None factory = self.a2f[agent.id] balance = factory.balance if self.interest_rate is None: return None interest = self.installment_interest if installment_loan else self.interest_rate if balance < 0 and self.interest_max is not None: interest += ( balance * (interest - self.interest_max) / self.balance_at_max_interest ) interest += max(0, starts_at - self.awi.current_step) * self.time_increment interest += self._credit_rating[agent.id] total = amount * (1 + interest) ** n_installments installment = total / n_installments if self.minimum_balance is not None and balance - total < -self.minimum_balance: return None return Loan( amount=amount, total=total, interest=interest, n_installments=n_installments, installment=installment, starts_at=starts_at, ) def evaluate_loan( self, agent: "SCMLAgent", amount: float, start_at: int, n_installments: int ) -> Optional[Loan]: """Evaluates the interest that will be imposed on the agent to buy_loan that amount""" if self.disabled: return None return self._evaluate_loan( agent=agent, amount=amount, n_installments=n_installments, installment_loan=False, starts_at=start_at, ) def _buy_loan( self, agent: "SCMLAgent", loan: Loan, beneficiary: Agent, contract: Optional[Contract], bankrupt_if_rejected=False, ) -> Optional[Loan]: if self.disabled: return None if loan is None: return loan factory = self.a2f[agent.id] if agent.confirm_loan(loan=loan, bankrupt_if_rejected=bankrupt_if_rejected): self.loans[agent].append(loan) self.awi.logdebug(f"Bank: {agent.name} borrowed {str(loan)}") factory.receive(loan.amount) factory.add_loan(loan.total) self.wallet -= loan.amount return loan elif bankrupt_if_rejected: # the agent rejected a loan with bankrupt_if_rejected, bankrupt the agent self._world.make_bankrupt( agent, amount=loan.amount, beneficiary=beneficiary, contract=contract ) return None return None def buy_loan( self, agent: "SCMLAgent", amount: float, n_installments: int, beneficiary: Agent, contract: Optional[Contract], force: bool = False, ) -> Optional[Loan]: """Gives a loan of amount to agent at the interest calculated using `evaluate_loan`""" if self.disabled: return None loan = self.evaluate_loan( amount=amount, agent=agent, n_installments=n_installments, start_at=self.awi.current_step, ) return self._buy_loan( agent=agent, loan=loan, bankrupt_if_rejected=force, beneficiary=beneficiary, contract=contract, ) def step(self): """Takes payments from agents""" # apply interests and pay loans # ----------------------------- if self.disabled: return t = self.awi.current_step delayed_payments = 0.0 # for every agent with loans for agent, loans in self.loans.items(): factory = self.a2f[agent.id] keep = [True] * len( loans ) # a flag to tell whether a loan is to be kept for future processing unpaid = [] # any new loans that may arise from failure to pay installments unavailable = 0.0 for i, loan in enumerate(loans): # if there are no remaining installments or I am in the grace period do not do anything if loan.n_installments <= 0 or loan.starts_at > t: continue # pay as much as possible from the agent's wallet (which may be zero) wallet = factory.wallet payment = max(0.0, min(loan.installment, wallet)) loan.amount -= payment factory.pay(payment) factory.add_loan(-payment) self.wallet += payment if payment >= loan.installment: # reduce the number of remaining installments if needed loan.n_installments -= 1 else: # if the payment is not enough for the installment, try to get a new loan unavailable += loan.installment - payment unpaid.append((i, loan)) # if the loan is completely paid, mark it for removal if loan.n_installments <= 0: keep[i] = False self.awi.logdebug( f"Bank: {agent.name} payed {payment} (of {loan.installment}) " f"[{loan.n_installments} remain]" ) if unavailable > 0.0: new_loan = self._evaluate_loan( agent=agent, amount=unavailable, n_installments=1, installment_loan=True, starts_at=t + 1, ) if new_loan is None: self._reduce_credit_rating(agent=agent, unavailable=unavailable) self.awi.logdebug( f"Bank: CR of {agent.name} was reduced for failure to pay {unavailable}" ) elif ( self._buy_loan( agent=agent, loan=new_loan, bankrupt_if_rejected=True, beneficiary=self, contract=None, ) is not None ): self.awi.logdebug( f"Bank: {agent.name} payed an installment by a new loan {str(new_loan)}" ) factory.add_loan(-new_loan.amount) factory.pay(new_loan.amount) self.wallet += new_loan.amount for indx, loan in unpaid: loan.amount -= loan.installment loan.n_installments -= 1 if loan.n_installments <= 0: keep[indx] = False # remove marked loans (that were completely paid) self.loans[agent] = [l for i, l in enumerate(loans) if keep[i]] # remove records of agents that paid all their loans self.loans = {k: v for k, v in self.loans.items() if len(v) > 0} def _reduce_credit_rating(self, agent: Agent, unavailable: float): """Updates the credit rating when the agent fails to pay an installment""" self._credit_rating[agent.id] -= unavailable def credit_rating(self, agent_id: str) -> float: if self.disabled: return 1 return self._credit_rating.get(agent_id, 1.0) PK!)Q^?negmas/apps/scml/common.py"""Common data-structures and objects used throughout the SCM world implementation""" import itertools import math import sys import uuid from collections import defaultdict, namedtuple from dataclasses import dataclass, field, InitVar from typing import Dict, Union, Tuple, Iterable, List, Optional, Any import numpy as np from negmas.outcomes import OutcomeType, Issue from negmas.situated import Contract INVALID_STEP = -1000 NO_PRODUCTION = -1 INVALID_UTILITY = -2000 g_last_product_id = 0 g_last_process_id = 0 __all__ = [ "Product", "Process", "InputOutput", "RunningCommandInfo", "INVALID_STEP", "NO_PRODUCTION", "INVALID_UTILITY", "ManufacturingProfile", "ManufacturingProfileCompiled", "ProductManufacturingInfo", "FactoryStatusUpdate", "Job", "ProductionNeed", "MissingInput", "ProductionReport", "ProductionFailure", "FinancialReport", "SCMLAgreement", "SCMLAction", "CFP", "Loan", "InsurancePolicy", "Factory", "FactoryState", ] @dataclass class Product: __slots__ = ["id", "production_level", "name", "expires_in", "catalog_price"] """A product that can be transacted in.""" id: int """Product index. Must be set during construction and **MUST** be unique for products in the same world""" production_level: int """The level of this product in the production graph.""" name: str """Object name""" expires_in: Optional[int] """Number of steps within which the product must be consumed. None means never""" catalog_price: Optional[float] """Catalog price of the product.""" def __str__(self): """String representation is simply the name""" return self.name + ( f"(cp:{self.catalog_price:0.02f})" if self.catalog_price is not None else "" ) def __post_init__(self): global g_last_product_id if self.id is None: self.id = g_last_product_id g_last_product_id += 1 if self.name is None: self.name = str(self.id) def __hash__(self): return self.id.__hash__() @dataclass(frozen=True) class InputOutput: """An input/output to a production process""" __slots__ = ["product", "quantity", "step"] product: int """Index of the product used as input or output""" quantity: int """Quantity needed/produced""" step: float """Relative time within the production at which the input is needed (output is produced)""" @dataclass class Process: __slots__ = [ "id", "production_level", "name", "inputs", "outputs", "historical_cost", ] id: int """A manufacturing process.""" production_level: int """The level of this process in the production graph""" name: str """Object name""" inputs: List[InputOutput] """list of input product name + quantity required and time of consumption relative to the time required for production (value from 0 to 1)""" outputs: List[InputOutput] """list of output product names, quantity required and when it becomes available relative to the time required for production (value from 0 to 1)""" historical_cost: Optional[float] """Average cost for running this process in some world. Filled by the world""" def __str__(self): """String representation is simply the name""" return self.name + ( f"(cp:{self.historical_cost})" if self.historical_cost is not None else "" ) def __post_init__(self): global g_last_process_id if self.id is None: self.id = g_last_process_id g_last_process_id += 1 if self.name is None: self.name = str(self.id) def __hash__(self): """The hash depends only on the name""" return str(self).__hash__() @dataclass class ManufacturingProfile: """The costs/time required for running a process on a line (with associated cancellation costs etc). This data-structure carries full information about the `Process` es instead of just its index as in `ManufacturingProfileCompiled`. It is intended to be used to construct factories See Also: `Factory` """ __slots__ = [ "n_steps", "cost", "initial_pause_cost", "running_pause_cost", "resumption_cost", "cancellation_cost", "line", "process", ] n_steps: int """Number of steps needed to complete the manufacturing""" cost: float """Cost of manufacturing""" initial_pause_cost: float """Cost of pausing incurred only at the step a pause is started""" running_pause_cost: float """Running cost of pausing""" resumption_cost: float """Cost of resuming a process""" cancellation_cost: float """Cost of cancelling the process before the last step""" line: int """The line index""" process: Process """The `Process` associated with this profile""" @dataclass class FactoryStatusUpdate: __slots__ = ["balance", "storage"] balance: float """The update to the balance""" storage: Dict[int, int] """The updates to be applied to the storage after this step""" def __post_init__(self): if not isinstance(self.storage, defaultdict): self.storage = defaultdict(int, self.storage) def make_empty(self) -> None: """Makes the update an empty one.""" self.balance = 0.0 self.storage = defaultdict(int) def combine(self, other: "FactoryStatusUpdate") -> None: """ Combines this status update with another one in place Args: other: The other status update Returns: None """ if other is None: return self.balance += other.balance to_remove = [] for k in itertools.chain(self.storage.keys(), other.storage.keys()): self.storage[k] += other.storage[k] if self.storage[k] == 0: to_remove.append(k) for k in to_remove: self.storage.pop(k, None) @classmethod def combine_sets( cls, dst: Dict[int, "FactoryStatusUpdate"], src: Dict[int, "FactoryStatusUpdate"], ): """ Combines a set of updates over time with another in place (overriding `first`) Args: dst: First set of updates to be combined into src: second set of updates to be combined from Returns: """ to_remove = [] for i, update in src.items(): dst[i].combine(update) if dst[i].balance == 0 and len(dst[i].storage) == 0: to_remove.append(i) for i in to_remove: dst.pop(i, None) return None @property def is_empty(self): return self.balance == 0 and ( len(self.storage) == 0 or sum(self.storage.values()) == 0 ) @classmethod def empty(cls): return FactoryStatusUpdate(balance=0.0, storage={}) def __str__(self): return ( f"balance: {self.balance}, " + f'{str({k: v for k, v in self.storage.items()}) if self.storage is not None else ""}' ) @dataclass class RunningCommandInfo: __slots__ = ["profile", "beg", "end", "action", "updates", "step", "paused"] profile: ManufacturingProfile """The manufacturing profile associated with this command. Most importantly, it gives the process and line""" beg: int """The time the command is to be executed""" end: int """The number of steps starting at `beg` for this command to end (it ends at end - 1)""" step: int """The time-step relative to `beg` at the factory is currently executing the `Process` indicated in `profile`. `step` will always go up by one every simulation step except if the command is paused where it does not change """ paused: bool """True if the command is paused""" action: str """The command type. For the current implementation it will always be run or none for no command""" updates: Dict[int, "FactoryStatusUpdate"] """The status updates implied by this command with their times relative to `beg`""" @property def n_steps(self) -> int: return self.end - self.beg def ended_before(self, t: int): return self.end <= t def started_on_or_after(self, t: int): return self.beg >= t def __str__(self): # if self.is_none: # return 'No command' return f"{self.action} {self.profile.process.id} [{self.beg}:{self.end - 1}]" @property def is_none(self): return self.action == "none" @is_none.setter def is_none(self, is_none): self.action = "none" @classmethod def do_nothing(cls): # noinspection PyTypeChecker return cls( profile=None, beg=-1, end=-1, action="none", updates={}, step=0, paused=False, ) @dataclass class Job: """Describes a job to be run on one production line of a `Factory`.""" __slots__ = ["profile", "time", "line", "action", "contract", "override"] profile: int """The process for run commands""" time: int """The time the command is to be executed""" line: int """Index of the line on which the job is to be scheduled. Notice that it will be ignored for `run` actions.""" action: str """The command type. For the current implementation it can be run/pause/resume/stop/cancel with `cancel` cancelling any other command type.""" contract: Optional[Contract] """The sell contract associated with the command""" override: bool """Whether to override existing commands when the job is to be executed.""" def __str__(self): s = f'{self.action} {self.profile if self.action == "run" else ""} at {self.time} on {self.line}' s += f'{" override" if self.override else ""}' if self.contract is not None: s += f" for {self.contract.id}" return s def is_cancelling(self, job: "Job") -> bool: """ Determines if the given jobs cancels this one Args: job: Returns: """ if self.line != job.line: return False return ( job.action == "cancel" or (self.action in ("run", "start") and job.action == "stop") or (self.action == "pause" and job.action == "resume") or (self.action == "resume" and job.action == "pause") ) @dataclass class ProductionNeed: """Describes some quantity of a product that is needed to honor a (sell) contract.""" __slots__ = [ "product", "needed_for", "quantity_to_buy", "quantity_in_storage", "step", ] product: int """The product needed""" needed_for: Contract """The contract for which the product is needed""" quantity_to_buy: int """The quantity need to be bought""" quantity_in_storage: int """The quantity already found in storage""" step: int """The time step at which the product is needed""" def __str__(self): """String representation is simply the name""" return ( f"Need {self.quantity_to_buy} ({self.quantity_in_storage} exist) of {self.product} at " + f" {self.step} for {self.needed_for}" ) @dataclass class MissingInput: __slots__ = ["product", "quantity"] product: int quantity: int def __str__(self): return f"{self.product}: {self.quantity}" @dataclass class ProductionFailure: __slots__ = ["line", "command", "missing_inputs", "missing_money", "missing_space"] line: int """ID of the line that failed""" command: RunningCommandInfo """Information about the command that failed""" missing_inputs: List[MissingInput] """The missing inputs if any with their quantities""" missing_money: float """The amount of money needed for production that is not available""" missing_space: int """The amount space needed in storage but not found""" def __str__(self): s = f"{str(self.command)} on {self.line} failed:" if self.missing_money > 0: s += f" money {self.missing_money}" if len(self.missing_inputs) > 0: s += f" inputs: {[str(_) for _ in self.missing_inputs]}" if self.missing_space > 0: s += f" space {self.missing_space}" return s @dataclass class ProductionReport: line: int """ID of the line""" started: Optional[RunningCommandInfo] """Commands started""" continuing: Optional[RunningCommandInfo] """Command that is continuing""" finished: Optional[RunningCommandInfo] """Command finished""" failure: Optional[ProductionFailure] """Failures""" updates: FactoryStatusUpdate """Updates applied to the factory""" @property def failed(self): return self.failure is not None @property def is_empty(self): return self.no_production and self.updates.is_empty @property def no_production(self): return self.started is None and self.finished is None and self.failure is None def __str__(self): if self.is_empty: return "" s = f"{self.line}: " if self.failed: s += f"{str(self.failure)} " else: if self.started is not None and self.finished is not None: s += f"started/finished {str(self.started)} " elif self.started is not None: s += f"started {str(self.started)} " elif self.finished is not None: s += f"finished {str(self.finished)} " if not self.updates.is_empty: s += f"{str(self.updates)}" return s @dataclass class SCMLAgreement(OutcomeType): time: int """delivery time""" unit_price: float """unit price""" quantity: int """quantity""" penalty: Optional[float] = None """penalty""" signing_delay: int = -1 """Delay between agreement conclusion and signing it to be binding""" @dataclass class CFP(OutcomeType): """A Call for proposal upon which a negotiation can start""" is_buy: bool """If true, the author wants to buy otherwise to sell. Non-negotiable.""" publisher: str """the publisher name. Non-negotiable.""" product: int """product ID. Non-negotiable.""" time: Union[int, Tuple[int, int], List[int]] """delivery time. May be negotiable.""" unit_price: Union[float, Tuple[float, float], List[float]] """unit price. May be negotiable.""" quantity: Union[int, Tuple[int, int], List[int]] """quantity. May be negotiable.""" penalty: Optional[Union[float, Tuple[float, float], List[float]]] = None """penalty per missing item in case the seller cannot provide the required quantity. May be negotiable.""" signing_delay: Optional[Union[int, Tuple[int, int], List[int]]] = None """The grace period after which the agents are asked to confirm signing the contract""" money_resolution: Optional[float] = None """If not None then it is the minimum unit of money (e.g. 1 for dollar, 0.01 for cent, etc)""" id: str = field(default_factory=lambda: str(uuid.uuid4()), init=True) """Unique CFP ID""" def __str__(self): s = f'{"buy" if self.is_buy else "sell"} ' s += f"{self.product} " s += f"(t: {self.time}, u: {self.unit_price}, q: {self.quantity}" if self.penalty is not None: s += f", penalty: {self.penalty}" if self.signing_delay is not None: s += f", sign after: {self.signing_delay}" s += ")" return s def satisfies(self, query: Dict[str, Any]) -> bool: """ Tests whether the CFP satisfies the conditions set by the query Args: query: A dictionary given the conditions. See `Remarks` for details Remarks: - The query dictionary can be used to specify any conditions that are required in the CFP. Only CFPs that satisfy ALL the conditions specified in the query are considered satisfying the query. The following keys can be set with corresponding meanings: is_buy True or False. If both are OK, just do not add this key publisher A string or `SCMLAgent` specifying a specific publisher publishers A list of publishers (see publisher key) product A string specifying a product name products A list of products (see product key) time A number, list or 2-items-tuple (range) specifying possible times to consider satisfactory unit_price A number, list or 2-items-tuple (range) specifying possible prices to consider satisfactory quantity A number, list or 2-items-tuple (range) specifying possible quantities to consider OK penalty A number, list or 2-items-tuple (range) specifying possible penalties to consider satisfactory """ def _overlap( a: Union[ int, float, Tuple[float, float], List[float], Tuple[int, int], List[int] ], b: Union[ float, Tuple[float, float], List[float], int, Tuple[int, int], List[int] ], ): def _test_single(a, b): if not isinstance(b, Iterable): return a == b if isinstance(b, tuple): return b[0] <= a <= b[1] return a in b if not isinstance(b, Iterable): a, b = b, a if not isinstance(a, Iterable): return _test_single(a, b) if isinstance(a, tuple): if isinstance(b, tuple): return b[0] <= a[0] <= b[1] or b[0] <= a[1] <= b[1] return any(_test_single(_, a) for _ in b) # type: ignore return any(_test_single(_, b) for _ in a) for k, v in query.items(): if k == "is_buy" and self.is_buy != v: return False if k == "publisher" and self.publisher != v: return False if k == "publishers" and self.publisher not in v: return False if k == "products" and self.product not in v: return False if k == "product_ids" and self.product not in v: return False if k == "product_indices" and self.product not in v: return False if k == "product" and self.product != v: return False if k == "product_id" and self.product != v: return False if k == "product_index" and self.product != v: return False if k == "time" and not _overlap(v, self.time): return False if k == "unit_price" and not _overlap(v, self.unit_price): return False if k == "penalty": if self.penalty is None and v is None: return True if self.penalty is None or v is None: return False if not _overlap(v, self.penalty): return False if k == "quantity" and not _overlap(v, self.quantity): return False return True @property def issues(self): """Returns the set of issues associated with this CFP. Notice that some of the issues may have a single value""" def _values(x, ensure_list=False, ensure_int=False): if isinstance(x, tuple) and ensure_list: if x[0] == x[1]: if ensure_list and self.money_resolution is not None: if ensure_int: return [ int( math.floor(x[0] / self.money_resolution) * self.money_resolution ) ] return [ math.floor(x[0] / self.money_resolution) * self.money_resolution ] else: if ensure_int: return [int(x[0])] return [x[0]] if isinstance(x[0], float) or isinstance(x[1], float): xs = ( int(math.floor(x[0] / self.money_resolution)), int(math.floor(x[1] / self.money_resolution)), ) xs = list( _ * self.money_resolution for _ in range(xs[0], xs[1] + 1) ) elif isinstance(x[0], int): xs = list(range(x[0], x[1] + 1)) else: xs = list(range(int(x[0]), int(x[1]) + 1)) if len(xs) == 0: if ensure_list and self.money_resolution is not None: if ensure_int: return [ int( math.floor(x[0] / self.money_resolution) * self.money_resolution ) ] return [ math.floor(x[0] / self.money_resolution) * self.money_resolution ] if ensure_int: return [int(x[0])] return [x[0]] if ensure_int: return list(set(int(_) for _ in xs)) return list(set(xs)) if isinstance(x, Iterable): if ensure_int: return list(set(int(_) for _ in x)) return list(set(x)) if ensure_int: return [int(x)] return [x] issues = [ Issue( name="time", values=_values(self.time, ensure_list=True, ensure_int=True), ), Issue( name="quantity", values=_values(self.quantity, ensure_list=True, ensure_int=True), ), Issue( name="unit_price", values=_values( self.unit_price, ensure_list=self.money_resolution is not None ), ), ] if self.penalty is not None: issues.append( Issue( name="penalty", values=_values( self.penalty, ensure_list=self.money_resolution is not None ), ) ) if self.signing_delay is not None: issues.append( Issue( name="signing_delay", values=_values(self.quantity, ensure_list=True, ensure_int=True), ) ) return issues @property def outcomes(self): return Issue.enumerate(issues=self.issues, max_n_outcomes=1000) @property def min_time(self): if isinstance(self.time, tuple): return self.time[0] elif isinstance(self.time, list): return min(self.time) return self.time @property def max_time(self): if isinstance(self.time, tuple): return self.time[1] elif isinstance(self.time, list): return max(self.time) return self.time @property def min_quantity(self): if isinstance(self.quantity, tuple): return self.quantity[0] elif isinstance(self.quantity, list): return min(self.quantity) return self.quantity @property def max_quantity(self): if isinstance(self.quantity, tuple): return self.quantity[1] elif isinstance(self.quantity, list): return max(self.quantity) return self.quantity @property def min_unit_price(self): if isinstance(self.unit_price, tuple): return self.unit_price[0] elif isinstance(self.unit_price, list): return min(self.unit_price) return self.unit_price @property def max_unit_price(self): if isinstance(self.unit_price, tuple): return self.unit_price[1] elif isinstance(self.unit_price, list): return max(self.unit_price) return self.unit_price @property def min_signing_delay(self): if self.signing_delay is None: return None if isinstance(self.signing_delay, tuple): return self.signing_delay[0] elif isinstance(self.signing_delay, list): return min(self.signing_delay) return self.signing_delay @property def max_signing_delay(self): if self.signing_delay is None: return None if isinstance(self.signing_delay, tuple): return self.signing_delay[1] elif isinstance(self.signing_delay, list): return max(self.signing_delay) return self.signing_delay @property def min_penalty(self): if self.penalty is None: return None if isinstance(self.penalty, tuple): return self.penalty[0] elif isinstance(self.penalty, list): return min(self.penalty) return self.penalty @property def max_penalty(self): if self.penalty is None: return None if isinstance(self.penalty, tuple): return self.penalty[1] elif isinstance(self.penalty, list): return max(self.penalty) return self.penalty def to_java(self): d = { "is_buy": self.is_buy, "publisher": self.publisher, "product": self.product, "id": self.id, "money_resolution": float(self.money_resolution) if self.money_resolution is not None else 0.0, "min_time": int(self.min_time), "max_time": int(self.max_time), "min_quantity": int(self.min_quantity), "max_quantity": int(self.max_quantity), "min_unit_price": float(self.min_unit_price), "max_unit_price": float(self.max_unit_price), "min_penalty": float(self.min_penalty) if self.min_penalty is not None else None, "max_penalty": float(self.max_penalty) if self.max_penalty is not None else None, "min_signing_delay": int(self.min_signing_delay) if self.min_signing_delay is not None else None, "max_signing_delay": int(self.max_signing_delay) if self.max_signing_delay is not None else None, } return d @classmethod def from_java( cls, idict: Dict[str, Any], class_name: Optional[str] = None ) -> "CFP": if idict["min_time"] == idict["max_time"]: t = idict["min_time"] else: t = (idict["min_time"], idict["max_time"]) if idict["min_quantity"] == idict["max_quantity"]: q = idict["min_quantity"] else: q = (idict["min_quantity"], idict["max_quantity"]) if idict["min_unit_price"] == idict["max_unit_price"]: up = idict["min_unit_price"] else: up = (idict["min_unit_price"], idict["max_unit_price"]) if not idict.get("min_penalty", None) or not idict.get("max_penalty", None): p = None else: if idict["min_penalty"] == idict["max_penalty"]: p = idict["min_penalty"] else: p = (idict["min_penalty"], idict["max_penalty"]) if not idict.get("min_signing_delay", None) or not idict.get( "max_signing_delay", None ): s = None else: if idict["min_signing_delay"] == idict["max_signing_delay"]: s = idict["min_signing_delay"] else: s = (idict["min_signing_delay"], idict["max_signing_delay"]) return cls( is_buy=idict["is_buy"], publisher=idict["publisher"], product=idict["product"], time=t, unit_price=up, quantity=q, penalty=p, signing_delay=s, money_resolution=idict.get("money_resolution", None), id=idict.get("id", None), ) @dataclass class SCMLAction: line: str """Line to execute the action on (need not be given if the profile is given""" profile: Optional[int] """Index of the profile to execute""" action: str """The action which may be start, stop, pause, resume""" time: int = 0 """Time to execute the action at""" @dataclass class ManufacturingProfileCompiled: """The costs/time required for running a process on a line (with associated cancellation costs etc). See Also: `Factory` """ __slots__ = [ "n_steps", "cost", "initial_pause_cost", "running_pause_cost", "resumption_cost", "cancellation_cost", "line", "process", ] n_steps: int """Number of steps needed to complete the manufacturing""" cost: float """Cost of manufacturing""" initial_pause_cost: float """Cost of pausing incurred only at the step a pause is started""" running_pause_cost: float """Running cost of pausing""" resumption_cost: float """Cost of resuming a process""" cancellation_cost: float """Cost of cancelling the process before the last step""" line: int """The line index""" process: int """The `Process` index""" @classmethod def from_manufacturing_profile( cls, profile: ManufacturingProfile, process2ind: Dict[Process, int] ): return ManufacturingProfileCompiled( n_steps=profile.n_steps, cost=profile.cost, initial_pause_cost=profile.initial_pause_cost, running_pause_cost=profile.running_pause_cost, resumption_cost=profile.resumption_cost, cancellation_cost=profile.cancellation_cost, line=profile.line, process=process2ind[profile.process], ) @dataclass class ProductManufacturingInfo: """Gives full information about a manufacturing process that can generate or consume a product. See Also: `consuming` and `producing` of `Factory` """ __slots__ = ["profile", "quantity", "step"] profile: int """The `ManufacturingProfile` index""" quantity: int """The quantity generated/consumed by running this manufacturing info""" step: int """The step from the beginning at which the `Product` is received/consumed""" @dataclass class FinancialReport: """Reports that financial standing of an agent at a given time in the simulation""" agent: str """Agent ID""" step: int """Time of the report""" cash: float """Cash at hand""" liabilities: float """Total liabilities (loans)""" inventory: float """Value of everything in the inventory priced at catalog prices.""" credit_rating: float """The agent's credit rating as a fraction of the maximum credit rating (1 indicates highest credit rating).""" @property def balance(self): """The balance of the agent defined as the difference between its available cash + inventory and its liabilities Remarks: - If the inventory was not calculated (due to having at least one product with unknown catalog price), it is used as zero in the equation. """ return ( self.cash + self.inventory - self.liabilities if self.inventory is not None else self.cash - self.liabilities ) @dataclass class Loan: amount: float """Loan amount""" starts_at: int """The time-step at which payment starts""" total: float """The total to be paid including the amount + interests""" interest: float """The interest rate per step""" installment: float """The amount to be paid in one installment""" n_installments: int """The number of installments""" def __str__(self): return ( f"{self.amount} @ {self.interest} paid in {self.n_installments} [{self.installment} each] " f"for a total {self.total} [starts at {self.starts_at}]" ) class Java: implements = ["jnegmas.apps.scml.common.Loan"] RunningNegotiationInfo = namedtuple( "RunningNegotiationInfo", ["negotiator", "annotation", "uuid", "extra"] ) """Keeps track of running negotiations for an agent""" NegotiationRequestInfo = namedtuple( "NegotiationRequestInfo", ["partners", "issues", "annotation", "uuid", "negotiator", "extra"], ) """Keeps track to negotiation requests that an agent sent""" @dataclass class InsurancePolicy: premium: float contract: Contract at_time: int against: "SCMLAgent" @dataclass class FactoryState: """Read Only State of a factory""" max_storage: int """Maximum storage allowed in this factory""" line_schedules: np.array """An array of n_lines * n_steps giving the line schedules""" storage: Dict[int, int] """Mapping from product index to the amount available in the inventory""" wallet: float """Money available for purchases""" hidden_money: float """Amount of money hidden by the agent""" hidden_storage: Dict[int, int] """Mapping from product index to the amount hidden by the agent""" loans: float """The total money owned as loans""" n_lines: int """The number of lines in the factory, will be set using the `profiles` input""" profiles: List[ManufacturingProfile] """A list of profiles used to initialize the factory""" next_step: int """Next simulation step for this factory""" commands: np.array """The production command currently running""" @dataclass class Factory: """Represents a factory within an SCML world. It is only accessed by the World so it need not be made public.""" initial_storage: InitVar[Dict[int, int]] """Initial storage""" initial_wallet: InitVar[float] = 0.0 """Initial Wallet""" id: str = field(default_factory=lambda: str(uuid.uuid4()), init=True) """Object name""" profiles: List[ManufacturingProfile] = field(default_factory=list) """A list of profiles used to initialize the factory""" max_storage: int = sys.maxsize """Maximum storage allowed in this factory""" min_storage: int = 0 """Minimum allowed storage per product""" min_balance: int = 0 """Minimum allowed balance""" initial_balance: float = field(init=False, default=0.0) """Initial balance of the factory""" _commands: np.array = field(init=False) """The production command currently running""" _line_schedules: np.array = field(init=False) _storage: Dict[int, int] = field( default_factory=lambda: defaultdict(int), init=False ) """Mapping from product index to the amount available in the inventory""" _total_storage: int = field(init=False, default=0) """Total storage""" _wallet: float = field(default=0, init=False) """Money available for purchases""" _hidden_money: float = field(default=0, init=False) """Amount of money hidden by the agent""" _hidden_storage: Dict[int, int] = field( default_factory=lambda: defaultdict(int), init=False ) """Mapping from product index to the amount hidden by the agent""" _loans: float = field(default=0.0, init=False) """The total money owned as loans""" _n_lines: int = field(init=False) """The number of lines in the factory, will be set using the `profiles` input""" _jobs: Dict[Tuple[int, int], Job] = field(default_factory=dict) """The jobs waiting to be run on the factory""" _next_step: int = field(init=False, default=0) """Current simulation step""" _carried_updates: FactoryStatusUpdate = field( init=False, default_factory=lambda: FactoryStatusUpdate.empty() ) """Carried updates from last executed command""" def __post_init__(self, initial_storage: Dict[int, int], initial_wallet=0.0): # no matter what are the line indices in the given profiles, the lines used by the factory # will be numbered from 0 to `n_lines` - 1 if self.max_storage is None or self.max_storage < 0: self.max_storage = sys.maxsize given_lines = sorted(list(set(p.line for p in self.profiles))) mapping = dict(zip(given_lines, range(len(given_lines)))) for profile in self.profiles: profile.line = mapping[profile.line] self._n_lines = len(given_lines) self._commands = np.array( [RunningCommandInfo.do_nothing() for _ in range(self._n_lines)] ) self._line_schedules = np.ones(self._n_lines, dtype=int) * NO_PRODUCTION self._storage = defaultdict(int) self._total_storage = 0 for k, v in initial_storage.items(): self._storage[k] = v self._total_storage += v self._wallet = initial_wallet self._carried_updates = FactoryStatusUpdate.empty() self.initial_balance = initial_wallet @property def hidden_money(self) -> float: return self._hidden_money @property def hidden_storage(self) -> Dict[int, int]: return self._hidden_storage @property def n_lines(self) -> int: return self._n_lines @property def commands(self) -> np.array: return self._commands @property def line_schedules(self) -> np.array: return self._line_schedules @property def wallet(self) -> float: return self._wallet @property def storage(self) -> Dict[int, int]: return self._storage @property def loans(self) -> float: return self._loans @property def total_storage(self) -> int: # assert len(self._storage) == 0 or min(self._storage.values()) >= self.min_storage, f'min {min(self._storage.values()) if len(self._storage) > 0 else 0} < {self.min_storage} storage {self._storage}' # assert (len(self._storage) == 0 and self._total_storage == 0) or \ # self._total_storage == sum(self._storage.values()), f'Total storage {self._total_storage} but the sum is {sum(self._storage.values())}' return self._total_storage @property def balance(self) -> float: """The total balance of the factory""" return self._wallet - self._loans @property def next_step(self) -> int: return self._next_step def add_loan(self, total: float) -> None: self._loans += total def receive(self, payment: float) -> None: self.pay(-payment) def pay(self, payment: float) -> None: if self._wallet - payment < self.min_balance: raise ValueError(f"Cannot pay {payment} as we have only {self._wallet}") self._wallet -= payment def transport_to(self, product: int, quantity: int) -> None: if self._storage[product] + quantity < self.min_storage: raise ValueError( f"Cannot transfer {quantity} of {product} as we have only {self._storage[product]} " f"(min {self.min_storage}, max {self.max_storage})" ) if self._total_storage + quantity > self.max_storage: raise ValueError( f"Cannot transfer {quantity} of {product} as we have only {self._storage[product]} " f"(min {self.min_storage}, max {self.max_storage})" ) self._storage[product] += quantity self._total_storage += quantity # @todo Schedulers and simulators do not know about transportation or transfer delays. They should # @todo Factory buy and sell functions do not take transportation and transfer delays into account def buy(self, product: int, quantity: int, price: float) -> None: if self._wallet < price or self._total_storage + quantity > self.max_storage: raise ValueError( f"Cannot buy {quantity} (total {self._total_storage}/{sum(self._storage.values())}) of " f"{product} for {price} (wallet {self._wallet} / balance {self.balance})" ) self._wallet -= price self._storage[product] += quantity self._total_storage += quantity def sell(self, product: int, quantity: int, price: float) -> None: if self._storage[product] < quantity + self.min_storage: raise ValueError( f"Cannot sell {quantity} (have {self._storage[product]}) of " f"{product} for {price} (wallet {self._wallet} / balance {self.balance})" ) self._storage[product] -= quantity self._total_storage -= quantity self._wallet += price def transport_from(self, product: int, quantity: int) -> None: self.transport_to(product=product, quantity=-quantity) def hide_funds(self, amount: float) -> None: to_hide = min(amount, self._wallet) self._hidden_money += to_hide self._wallet -= to_hide def hide_product(self, product: int, quantity: int) -> None: to_hide = min(quantity, self._storage.get(product, 0)) self._hidden_storage[product] += to_hide self._storage[product] -= to_hide def unhide_funds(self, amount: float) -> None: to_hide = min(amount, self._hidden_money) self._hidden_money -= to_hide self._wallet += to_hide def unhide_product(self, product: int, quantity: int) -> None: to_hide = min(quantity, self._hidden_storage.get(product, 0)) self._hidden_storage[product] -= to_hide self._storage[product] += to_hide def schedule(self, job: Job, override=False) -> None: """ Schedules the given job at its `time` and `line` optionally overriding whatever was already scheduled Args: job: override: Returns: Success/failure """ # you can only schedule jobs at the following simulation step t, line, profile = job.time, job.line, self.profiles[job.profile] if job.action in ("run", "start"): line = profile.line if t < self._next_step - 1 or line >= self._n_lines or line < 0: raise ValueError( f"cannot schedule at time {t} (current {self._next_step - 1}) on line {line} " f"of {self._n_lines}" ) existing_job = self._jobs.get((t, line), None) if existing_job is None: self._jobs[(t, line)] = job return if existing_job.is_cancelling(job): del self._jobs[(t, line)] return if not override: raise ValueError( f"Job {str(existing_job)} is scheduled at {t} and overriding is not allowed" ) self._jobs[(t, line)] = job def _apply_updates(self, updates: FactoryStatusUpdate) -> None: if updates.balance != 0.0: self._wallet += updates.balance if updates.storage is not None: for k, v in updates.storage.items(): self._storage[k] += v self._total_storage += v def step(self) -> List[ProductionReport]: reports = [] if not self._carried_updates.is_empty: reports.append( ProductionReport( line=-1, started=None, continuing=None, finished=None, failure=None, updates=self._carried_updates, ) ) self._apply_updates(self._carried_updates) self._carried_updates = FactoryStatusUpdate.empty() for line in range(self._n_lines): # step the current production process if self._commands[line].ended_before(self._next_step): self._commands[line].action = "none" report = self._step_line(line=line) reports.append(report) self._apply_updates(report.updates) self._next_step += 1 return reports def _run(self, profile: ManufacturingProfile, override=True) -> None: """running is executed at the beginning of the step t Args: profile: the profile to start giving both the line and process override: If true, override any running processes paying cancellation cost for these processes Remarks: - The output of a process that runs from step t to step t + n - 1 will only be in storage at step t + n """ # if I am not allowed to override, then this command has no effect and I return an empty status update t = self._next_step line = profile.line running_command = self._commands[line] if not running_command.is_none and not override: return process = profile.process n, cost = profile.n_steps, profile.cost updates = defaultdict(lambda: FactoryStatusUpdate.empty()) command = RunningCommandInfo( action="run", profile=profile, beg=t, end=t + n, updates=updates, paused=False, step=0, ) for need in process.inputs: updates[int(math.floor(need.step * n))].storage[ need.product ] -= need.quantity for output in process.outputs: updates[int(math.ceil(output.step * n))].storage[ output.product ] += output.quantity updates[0].balance -= cost # cancel the running command by stopping it and then run the new command if not running_command.is_none: self._stop(line=profile.line) self._commands[line] = command self._line_schedules[line] = process.id def _pause(self, line: int) -> None: """pausing is executed at the end of the step Args: line: the line on which the process is running Returns: Optional[Dict[int, FactoryStatusUpdate]]: The status updated for all times that need to be updated to cancel the command if it is not None. If None is returned then scheduling failed. Remarks: - Not implemented yet - pausing when nothing is running is not an error and will return an empty status update """ running_command = self._commands[line] if running_command.is_none: return running_command.updates[running_command.step].combine( FactoryStatusUpdate( balance=-running_command.profile.initial_pause_cost, storage={} ) ) running_command.paused = True def _resume(self, line: int) -> None: """resumption is executed at the end of the step (starting next step count down) Args: line: the line on which the process is running Returns: Optional[Dict[int, FactoryStatusUpdate]]: The status updated for all times that need to be updated to cancel the command if it is not None. If None is returned then scheduling failed. Remarks: - Not implemented yet - resuming when nothing is paused is not an error and will return an empty status update """ running_command = self._commands[line] if running_command.is_none: return profile = running_command.profile running_command.updates[running_command.step].combine( FactoryStatusUpdate(balance=-profile.resumption_cost, storage={}) ) running_command.paused = False def _stop(self, line: int) -> None: """stopping is executed at the beginning of the current step Args: line: the line on which the process is running Returns: Optional[Dict[int, FactoryStatusUpdate]]: The status updated for all times that need to be updated to cancel the command if it is not None. If None is returned then scheduling failed. Remarks: - stopping when nothing is running is not an error and will just return an empty schedule """ # stopping a no-action command is always successful running_command = self._commands[line] if running_command.is_none: return profile = running_command.profile t = self._next_step running_command.paused = False running_command.end = t + 1 running_command.updates = { running_command.step: running_command.updates[running_command.step].combine( FactoryStatusUpdate(balance=-profile.cancellation_cost, storage={}) ) } def _step_line(self, line: int) -> ProductionReport: """ Steps the line to the time-step `t` assuming that it is already stepped to time-step t-1 given the storage Args: line: the line to step Returns: ProductionReport """ t = self._next_step running_command = self._commands[line] job = self._jobs.get((t, line), None) updates = FactoryStatusUpdate.empty() if job is None and running_command.is_none: return ProductionReport( updates=updates, continuing=None, started=None, finished=None, failure=None, line=line, ) if job is not None: if job.action in ("run", "start"): self._run(profile=self.profiles[job.profile], override=job.override) elif job.action == "pause": self._pause(line=job.line) elif job.action == "resume": self._resume(line=job.line) elif job.action == "stop": self._stop(line=job.line) else: raise ValueError(f"action {job.action} is unknown") del self._jobs[(t, line)] # now all updates in the command are correct except for the running pause cost which we add here running_command = self._commands[line] profile = running_command.profile if running_command.paused: running_command.end += 1 running_command.updates = { k + 1: v for k, v in running_command.updates.items() } running_command.updates[running_command.step].combine( FactoryStatusUpdate(balance=-profile.running_pause_cost, storage={}) ) updates = running_command.updates.get(running_command.step, None) if not running_command.paused: running_command.step += 1 if updates is None or updates.is_empty: return ProductionReport( updates=FactoryStatusUpdate.empty(), continuing=running_command if running_command.beg < t else None, started=running_command if running_command.beg == t else None, finished=running_command if running_command.end <= t + 1 else None, failure=None, line=line, ) if updates is not None: del running_command.updates[running_command.step - 1] available_storage = self.max_storage - self._total_storage missing_inputs = [] missing_money = 0 failed = False missing_space = 0 if updates.balance < 0 and self._wallet < -updates.balance: failed = True missing_money = -updates.balance - self._wallet for product_id, quantity in updates.storage.items(): if quantity < 0 and self._storage.get(product_id, 0) < -quantity: failed = True missing_inputs.append( MissingInput(product=product_id, quantity=-quantity) ) elif quantity > 0: available_storage -= quantity if available_storage < 0: failed = True missing_space -= available_storage available_storage = 0 if failed: running_command.action = "none" failure = ProductionFailure( line=line, command=running_command, missing_money=missing_money, missing_inputs=missing_inputs, missing_space=missing_space, ) return ProductionReport( updates=FactoryStatusUpdate.empty(), continuing=running_command if running_command.beg < t else None, started=running_command if running_command.beg == t else None, finished=running_command if running_command.end <= t + 1 else None, failure=failure, line=line, ) if running_command.ended_before(t + 1): self._carried_updates.combine( running_command.updates.get( running_command.step, FactoryStatusUpdate.empty() ) ) return ProductionReport( updates=updates, continuing=running_command if running_command.beg < t else None, started=running_command if running_command.beg == t else None, finished=running_command if running_command.end <= t + 1 else None, failure=None, line=line, ) PK!=0|1|1negmas/apps/scml/consumers.pyimport functools import itertools import math from abc import ABC from random import random, randint from typing import TYPE_CHECKING from dataclasses import dataclass from numpy.random import dirichlet from negmas import AgentMechanismInterface, MechanismState from negmas.apps.scml import FinancialReport from negmas.events import Notification from negmas.helpers import ConfigReader, get_class from negmas.negotiators import Negotiator from negmas.outcomes import Issue from negmas.sao import AspirationNegotiator from negmas.situated import Contract, Breach from negmas.situated import RenegotiationRequest from negmas.utilities import ( normalize, ComplexWeightedUtilityFunction, MappingUtilityFunction, ) from .common import CFP from .agent import SCMLAgent from .helpers import pos_gauss if True: # from typing import Dict, Any, List, Optional, Union, Tuple from .common import Loan if TYPE_CHECKING: from .awi import SCMLAWI __all__ = ["Consumer", "ConsumptionProfile", "ScheduleDrivenConsumer"] @dataclass class ConsumptionProfile: schedule: Union[int, List[int]] = 0 underconsumption: float = 0.1 overconsumption: float = 0.01 dynamicity: float = 0.0 cv: float = 0.1 alpha_q: float = 0.5 alpha_u: float = 1.0 beta_q: float = 10.0 beta_u: float = 10.0 tau_q: float = 2 tau_u: float = 0.25 @classmethod def random(cls): return ConsumptionProfile( schedule=randint(0, 5), overconsumption=2 * random(), underconsumption=2 * random(), cv=random(), beta_q=99 * random() + 1, beta_u=99 * random() + 1, tau_q=3 * random(), tau_u=random(), ) def schedule_at(self, time: int) -> int: if isinstance(self.schedule, int): return self.schedule else: return self.schedule[time % len(self.schedule)] def schedule_within(self, time: Union[int, List[int], Tuple[int, int]]) -> int: if isinstance(time, int): return self.schedule_at(time) if isinstance(time, tuple): times = list(range(time[0], time[1] + 1)) else: times = time if isinstance(self.schedule, int): return self.schedule * len(times) return sum(self.schedule_at(t) for t in times) def set_schedule_at(self, time: int, value: int, n_steps: int) -> None: if isinstance(self.schedule, int): self.schedule = [self.schedule] * n_steps elif len(self.schedule) < n_steps: self.schedule = list( itertools.chain( *([self.schedule] * int(math.ceil(n_steps / len(self.schedule)))) ) ) self.schedule[time % len(self.schedule)] = value class Consumer(SCMLAgent, ABC): """Base class of all consumer classes""" pass class ScheduleDrivenConsumer(Consumer): """Consumer class""" def on_new_report(self, report: FinancialReport): pass def on_neg_request_rejected(self, req_id: str, by: Optional[List[str]]): pass def on_neg_request_accepted(self, req_id: str, mechanism: AgentMechanismInterface): pass def on_negotiation_failure( self, partners: List[str], annotation: Dict[str, Any], mechanism: AgentMechanismInterface, state: MechanismState, ) -> None: pass def on_negotiation_success( self, contract: Contract, mechanism: AgentMechanismInterface ) -> None: pass def on_contract_cancelled(self, contract: Contract, rejectors: List[str]) -> None: pass def on_contract_nullified( self, contract: Contract, bankrupt_partner: str, compensation: float ) -> None: pass def on_agent_bankrupt(self, agent_id: str) -> None: pass def confirm_partial_execution( self, contract: Contract, breaches: List[Breach] ) -> bool: return True def on_remove_cfp(self, cfp: "CFP"): pass MAX_UNIT_PRICE = 1e5 RELATIVE_MAX_PRICE = 2 def __init__( self, profiles: Dict[int, ConsumptionProfile] = None, negotiator_type="negmas.sao.AspirationNegotiator", consumption_horizon: Optional[int] = 20, immediate_cfp_update: bool = True, name=None, ): super().__init__(name=name) self.negotiator_type = get_class(negotiator_type, scope=globals()) self.profiles: Dict[int, ConsumptionProfile] = dict() self.secured_quantities: Dict[int, int] = dict() if profiles is not None: self.set_profiles(profiles=profiles) self.consumption_horizon = consumption_horizon self.immediate_cfp_update = immediate_cfp_update def on_new_cfp(self, cfp: "CFP") -> None: pass # consumers never respond to CFPs def init(self): if self.consumption_horizon is None: self.consumption_horizon = self.awi.n_steps self.awi.register_interest(list(self.profiles.keys())) def set_profiles(self, profiles: Dict[int, ConsumptionProfile]): self.profiles = profiles if profiles is not None else dict() self.secured_quantities = dict(zip(profiles.keys(), itertools.repeat(0))) def register_product_cfps(self, p: int, t: int, profile: ConsumptionProfile): current_schedule = profile.schedule_at(t) product = self.products[p] awi: SCMLAWI = self.awi if current_schedule <= 0: awi.bb_remove( section="cfps", query={"publisher": self.id, "time": t, "product_index": p}, ) return max_price = ( ScheduleDrivenConsumer.RELATIVE_MAX_PRICE * product.catalog_price if product.catalog_price is not None else ScheduleDrivenConsumer.MAX_UNIT_PRICE ) cfps = awi.bb_query( section="cfps", query={"publisher": self.id, "time": t, "product": p} ) if cfps is not None and len(cfps) > 0: for _, cfp in cfps.items(): if cfp.max_quantity != current_schedule: cfp = CFP( is_buy=True, publisher=self.id, product=p, time=t, unit_price=(0, max_price), quantity=(1, current_schedule), ) awi.bb_remove( section="cfps", query={"publisher": self.id, "time": t, "product": p}, ) awi.register_cfp(cfp) break else: cfp = CFP( is_buy=True, publisher=self.id, product=p, time=t, unit_price=(0, max_price), quantity=(1, current_schedule), ) awi.register_cfp(cfp) def step(self): if self.consumption_horizon is None: horizon = self.awi.n_steps else: horizon = min( self.awi.current_step + self.consumption_horizon + 1, self.awi.n_steps ) for p, profile in self.profiles.items(): for t in range( self.awi.current_step, horizon ): # + self.transportation_delay self.register_product_cfps(p=p, t=t, profile=profile) def confirm_contract_execution(self, contract: Contract) -> bool: return True @staticmethod def _qufun(outcome: Dict[str, Any], tau: float, profile: ConsumptionProfile): """The ufun value for quantity""" q, t = outcome["quantity"], outcome["time"] y = profile.schedule_within(t) o = profile.overconsumption u = profile.underconsumption if q == 0 and y != 0: return 0.0 if y <= 0: result = -o * ((q - y) ** tau) elif q > y: result = -o * (((q - y) / y) ** tau) elif q < y: result = -u * (((y - q) / y) ** tau) else: result = 1.0 result = math.exp(result) if isinstance(result, complex): result = result.real if result is None: result = -1000.0 return result def respond_to_negotiation_request( self, cfp: "CFP", partner: str ) -> Optional[Negotiator]: if self.awi.is_bankrupt(partner): return None 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 = 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) negotiator.name = self.name + "_" + partner negotiator.utility_function = ufun return negotiator def set_renegotiation_agenda( self, contract: Contract, breaches: List[Breach] ) -> Optional[RenegotiationRequest]: """ Received by partners in ascending order of their total breach levels in order to set the renegotiation agenda when contract execution fails Args: contract: The contract that was breached about which re-negotiation is offered breaches: The list of breaches by all parties for the breached contract. Returns: None if renegotiation is not to be started, otherwise a re-negotiation agenda. """ return None def respond_to_renegotiation_request( self, contract: Contract, breaches: List[Breach], agenda: RenegotiationRequest ) -> Optional[Negotiator]: """ Called to respond to a renegotiation request Args: agenda: Renegotiatio agenda (issues to renegotiate about). contract: The contract that was breached breaches: All breaches on that contract Returns: None to refuse to enter the negotiation, otherwise, a negotiator to use for this negotiation. """ return None def confirm_loan(self, loan: Loan, bankrupt_if_rejected: bool) -> bool: """called by the world manager to confirm a loan if needed by the buyer of a contract that is about to be breached""" return bankrupt_if_rejected def sign_contract(self, contract: Contract) -> Optional[str]: if contract is None: return None cfp: CFP = contract.annotation["cfp"] agreement = contract.agreement # type: ignore schedule = self.profiles[cfp.product].schedule_at(agreement["time"]) if schedule - agreement["quantity"] < 0: return None return self.id def on_contract_signed(self, contract: Contract): if contract is None: return cfp: CFP = contract.annotation["cfp"] agreement = contract.agreement # type: ignore self.secured_quantities[cfp.product] += agreement["quantity"] old_quantity = self.profiles[cfp.product].schedule_at(agreement["time"]) new_quantity = old_quantity - agreement["quantity"] t = agreement["time"] self.profiles[cfp.product].set_schedule_at( time=t, value=new_quantity, n_steps=self.awi.n_steps ) if self.immediate_cfp_update and new_quantity != old_quantity: self.register_product_cfps( p=cfp.product, t=t, profile=self.profiles[cfp.product] ) for negotiation in self._running_negotiations.values(): self.notify( negotiation.negotiator, Notification(type="ufun_modified", data=None) ) PK!5[YY$negmas/apps/scml/factory_managers.pyimport itertools from abc import abstractmethod, ABC from collections import defaultdict from negmas import ( Contract, Breach, Negotiator, MechanismState, AgentMechanismInterface, RenegotiationRequest, JavaSAONegotiator, UtilityFunction, JavaUtilityFunction, _ShadowAgentMechanismInterface, ) from negmas.apps.scml.simulators import FactorySimulator, FastFactorySimulator from negmas.apps.scml.simulators import storage_as_array, temporary_transaction from negmas.common import NamedObject from negmas.events import Notification from negmas.helpers import get_class, instantiate from negmas.helpers import snake_case from negmas.java import ( JavaCallerMixin, to_java, from_java, to_dict, java_link, PYTHON_CLASS_IDENTIFIER, ) from negmas.outcomes import Issue, Outcome from negmas.sao import _ShadowSAONegotiator from negmas.utilities import UtilityValue from .agent import SCMLAgent from .awi import _ShadowSCMLAWI, SCMLAWI from .common import ( SCMLAgreement, Factory, INVALID_UTILITY, CFP, Loan, ProductionFailure, FinancialReport, ) from .consumers import ScheduleDrivenConsumer, ConsumptionProfile from .schedulers import Scheduler, ScheduleInfo, GreedyScheduler if True: from typing import ( Dict, Iterable, Any, Callable, Collection, Type, List, Optional, Union, ) __all__ = [ "FactoryManager", "DoNothingFactoryManager", "GreedyFactoryManager", "JavaFactoryManager", "JavaDoNothingFactoryManager", "JavaGreedyFactoryManager", "JavaDummyMiddleMan", ] class FactoryManager(SCMLAgent, ABC): """Base factory manager class that will be inherited by participant negmas in ANAC 2019. The agent can access the world simulation in one of two ways: 1. Attributes and methods available in the Agent-World-Interface (See `SCMLAWI` documentation for those). 2. Attributes and methods in the `FactoryManager` object itself. All factory managers will have the following attributes and methods that simplify the interaction with the world simulation. Some of these attributes/methods are convenient ways to access functionality already available in the agent's internal `SCMLAWI`. **Attributes** *Agent information* - `id` : The unique ID assigned to this agent. This is unique system-wide and is what is used in contracts, CFPs, etc. - `name`: A name of the agent used for display purposes only. The simulator never accesses or uses this name except in printing and logging. - `uuid` : Another name of the `id` . - `type_name` : A string giving the type of the agent (as a fully qualified python class name). *Capabilities/Profiles* - `line_profiles` : A mapping specifying for each line index, all the profiles that can be run on it - `process_profiles` : A mapping specifying for each `Process` index, all the profiles used to run it in the factory - `producing` : Mapping from a product index to all manufacturing processes that can generate it - `consuming` : Mapping from a product index to all manufacturing processes that can consume it - `compiled_profiles` : All the profiles to be used by the factory belonging to this agent compiled to use process indices - `max_storage` : Maximum storage available to the agent. Zero, None or float('inf') all indicate unlimited storage. *Production Graph* (also accessible through *awi*) - `products` : List of products in the system - `processes` : List of processes in the system *Helper Objects* - `awi` : The `SCMLAWI` instance assigned to this agent. It can be used to interact with the simulation (See `SCMLAWI` documentation). - `simulator` : A `FactorySimulator` object that can be used to simulate what happens in the `Factory` assigned to this agent when given operations are conducted (e.g. production, paying money, etc). *Negotiations/Contracts* - `requested_negotiations` : A dynamic list of negotiations currently requested by the agent but not started. *Correct management of this list is only possible if the agent **always** uses `request_negotiation` method of this class (see methods later) rather than directly calling request_method on the `SCMLAWI` ( `awi` ) member. - `running_negotiations` : A dynamic list of negotiations currently running involving this agent. *Correct management of this list is only possible if the agent **always** uses `request_negotiation` method of this class (see methods later) rather than directly calling request_method on the `SCMLAWI` ( `awi` ) member. - `unsigned_contracts` : A dynamic list of negotiations contracts concluded involving this agent but not yet signed. *Correct management of this list is only possible if the agent **always** uses `request_negotiation` method of this class (see methods later) rather than directly calling request_method on the `SCMLAWI` ( `awi` ) member. *Simulation attributes* (also accessible through *awi*) - `transportation_delay` : The transportation delay in the system. - `current_step` : Current simulation step. - `immediate_negotiations` : Whether or not negotiations start immediately upon registration (default is to start on the next production step) - `negotiation_speed_multiple` : The number of negotiation rounds (steps) conducted in a single production step - `transportation_delay` : Transportation delay in the system. Default is zero **Methods** (Callable by the agent) *Actions on the world* - `request_negotiation` : Called to request a negotiation based on a `CFP` . *Scheduling and simulation helpers* - `can_expect_agreement` : Checks if it is possible in principle to get an agreement on this CFP by the time it becomes executable. **Callbacks** (Callable by the simulation) *Decision callbacks* (Called to make decisions) - Negotiation and Contracts - `respond_to_negotiation_request` : Decide whether or not to engage in a negotiation on a `CFP` that was published earlier by this factory manager. If accepted, the agent should return a `SAONegotiator` object. - `sign_contract` : Decide whether or not to sign the contract. If accepted, the agent should return its own ID. - `confirm_contract_execution` : Decide whether or not to go on with executing a contract that the agent already signed. If rejected (by returning `False` ), a refusal-to-execute breach will be recorded. - Breach related - `confirm_partial_execution` : Decide whether the agent agrees to partial execution. Called only when the the partner of this agent commits a partial breach (of level < 1) and this agent commits no breaches. - `set_renegotiation_agenda` : Decide what are the issues and ranges of acceptable values to re-negotiate about. Called only in case of breaches. - `respond_to_renegotiation_request` : Decide whether or not to engage in a re-negotiation. - Financial - `confirm_loan` : Decide whether or not to accept an offered loan. *In ANAC 2019 league, loans are not allowed and this callback will never be called by the simulator. *Time-dependent callbacks* (Information callback called at predefined times) - `init` : Called once before any production or negotiations to initiate the agent. - `step` : Called at every production step. *Information callbacks* (Called to inform the agent about events) - CFP related - `on_new_cfp` : Called whenever a `CFP` on a `Product` for which the agent has already registered interest (using `register_interest` method of its `awi`) is published. By default all agents register interest in the products they can consume or produce according to their profiles. - `on_remove_cfp` : Called whenever a `CFP` on a `Product` for which the agent has already registered interest (using `register_interest` method of its `awi`) is removed from the bulletin-board. - Negotiation related - `on_neg_request_accepted` : Called when a negotiation request of the agent is accepted - `on_neg_request_rejected` : Called when a negotiation request of the agent is rejected - `on_negotiation_success` : Called when a negotiation of which the agent is a party succeeds with an agreement. - `on_negotiation_failure` : Called when a negotiation of which the agent is a party ends without agreement. - Contract related - `on_contract_cancelled` : Called whenever a `Contract` of which the agent is a party is cancelled because the other party refused to sign it. - `on_contract_signed` : Called whenever a `Contract` of which the agent is a party is signed by both patners. - `on_contract_nullified` : Called whenever a `Contract` of which the agent is a party is nullified by the simulator as a part of bankruptcy processing. - Production related - `on_production_failure` : Called whenever a scheduled production (see `SCMLAWI` for production commands) fails - About other agents - `on_agent_bankrupt` : Called whenever another agent goes bankrupt - `on_new_report` : Called whenever a new report of another agent for which this agent has registered interest is published. Interest is registered using the agent's `awi` 's `receive_financial_reports` method. """ def __init__( self, name=None, simulator_type: Union[str, Type[FactorySimulator]] = FastFactorySimulator, ): super().__init__(name=name) self.transportation_delay = 0 """Transportation delay in the world""" self.simulator: Optional[FactorySimulator] = None """The simulator used by this agent""" self.simulator_type: Type[FactorySimulator] = get_class( simulator_type, scope=globals() ) """Simulator type (as a class)""" self.current_step = 0 """Current simulation step""" self.max_storage: int = 0 """Maximum storage available to the agent""" def init_(self): state: Factory = self.awi.state self.current_step = state.next_step self.max_storage = state.max_storage self.simulator = self.simulator_type( initial_wallet=state.wallet, initial_storage=state.storage, n_steps=self.awi.n_steps, n_products=len(self.awi.products), profiles=state.profiles, max_storage=self.max_storage, ) super().init_() def step_(self): state = self.awi.state self.simulator.set_state( self.current_step, wallet=state.wallet, loans=state.loans, storage=storage_as_array(state.storage, n_products=len(self.products)), line_schedules=state.line_schedules, ) self.current_step += 1 self.step() @abstractmethod def on_production_failure(self, failures: List[ProductionFailure]) -> None: """ Called with a list of `ProductionFailure` records on production failure Args: failures: Returns: """ class Java: implements = ["jnegmas.apps.scml.factory_managers.FactoryManager"] class DoNothingFactoryManager(FactoryManager): """The default factory manager that will be implemented by the committee of ANAC-SCML 2019""" def on_new_report(self, report: FinancialReport): pass def init(self): pass def step(self): pass def on_neg_request_rejected(self, req_id: str, by: Optional[List[str]]): pass def on_neg_request_accepted(self, req_id: str, mechanism: AgentMechanismInterface): pass def on_negotiation_failure( self, partners: List[str], annotation: Dict[str, Any], mechanism: AgentMechanismInterface, state: MechanismState, ) -> None: pass def on_negotiation_success( self, contract: Contract, mechanism: AgentMechanismInterface ) -> None: pass def on_contract_signed(self, contract: Contract) -> None: pass def on_contract_cancelled(self, contract: Contract, rejectors: List[str]) -> None: pass def sign_contract(self, contract: Contract) -> Optional[str]: return self.id def on_contract_nullified( self, contract: Contract, bankrupt_partner: str, compensation: float ) -> None: pass def on_agent_bankrupt(self, agent_id: str) -> None: pass def confirm_partial_execution( self, contract: Contract, breaches: List[Breach] ) -> bool: return True def on_remove_cfp(self, cfp: "CFP") -> None: pass def on_production_failure(self, failures: List[ProductionFailure]) -> None: pass def respond_to_negotiation_request( self, cfp: "CFP", partner: str ) -> Optional[Negotiator]: return None def confirm_contract_execution(self, contract: Contract) -> bool: return True def set_renegotiation_agenda( self, contract: Contract, breaches: List[Breach] ) -> Optional[RenegotiationRequest]: return None def respond_to_renegotiation_request( self, contract: Contract, breaches: List[Breach], agenda: RenegotiationRequest ) -> Optional[Negotiator]: return None def confirm_loan(self, loan: Loan, bankrupt_if_rejected: bool) -> bool: """called by the world manager to confirm a loan if needed by the buyer of a contract that is about to be breached""" return bankrupt_if_rejected def on_new_cfp(self, cfp: "CFP") -> None: pass class GreedyFactoryManager(DoNothingFactoryManager): """The default factory manager that will be implemented by the committee of ANAC-SCML 2019""" def on_production_failure(self, failures: List[ProductionFailure]) -> None: pass def confirm_loan(self, loan: Loan, bankrupt_if_rejected: bool) -> bool: return bankrupt_if_rejected def confirm_contract_execution(self, contract: Contract) -> bool: return True def set_renegotiation_agenda( self, contract: Contract, breaches: List[Breach] ) -> Optional[RenegotiationRequest]: return None def respond_to_renegotiation_request( self, contract: Contract, breaches: List[Breach], agenda: RenegotiationRequest ) -> Optional[Negotiator]: return None def __init__( self, name=None, simulator_type: Union[str, Type[FactorySimulator]] = FastFactorySimulator, scheduler_type: Union[str, Type[Scheduler]] = GreedyScheduler, scheduler_params: Optional[Dict[str, Any]] = None, optimism: float = 0.0, negotiator_type: Union[ str, Type[Negotiator] ] = "negmas.sao.AspirationNegotiator", negotiator_params: Optional[Dict[str, Any]] = None, n_retrials=5, use_consumer=True, reactive=True, sign_only_guaranteed_contracts=False, riskiness=0.0, max_insurance_premium: float = -1.0, ): super().__init__(name=name, simulator_type=simulator_type) self.negotiator_type = get_class(negotiator_type, scope=globals()) self.negotiator_params = ( negotiator_params if negotiator_params is not None else {} ) self.optimism = optimism self.ufun_factory: Union[ Type[NegotiatorUtility], Callable[[Any, Any], NegotiatorUtility] ] if optimism < 1e-6: self.ufun_factory = PessimisticNegotiatorUtility elif optimism > 1 - 1e-6: self.ufun_factory = OptimisticNegotiatorUtility else: self.ufun_factory: NegotiatorUtility = lambda agent, annotation: AveragingNegotiatorUtility( agent=agent, annotation=annotation, optimism=self.optimism ) self.max_insurance_premium = max_insurance_premium self.n_retrials = n_retrials self.n_neg_trials: Dict[str, int] = defaultdict(int) self.consumer = None self.use_consumer = use_consumer self.reactive = reactive self.sign_only_guaranteed_contracts = sign_only_guaranteed_contracts self.contract_schedules: Dict[str, ScheduleInfo] = {} self.riskiness = riskiness self.negotiation_margin = int(round(n_retrials * max(0.0, 1.0 - riskiness))) self.scheduler_type: Type[Scheduler] = get_class( scheduler_type, scope=globals() ) self.scheduler: Scheduler = None self.scheduler_params: Dict[ str, Any ] = scheduler_params if scheduler_params is not None else {} def total_utility(self, contracts: Collection[Contract] = ()) -> float: """Calculates the total utility for the agent of a collection of contracts""" if self.scheduler is None: raise ValueError("Cannot calculate total utility without a scheduler") min_concluded_at = self.awi.current_step min_sign_at = min_concluded_at + self.awi.default_signing_delay with temporary_transaction(self.scheduler): schedule = self.scheduler.schedule( contracts=contracts, assume_no_further_negotiations=False, ensure_storage_for=self.transportation_delay, start_at=min_sign_at, ) if not schedule.valid: return INVALID_UTILITY return schedule.final_balance def init(self): self.negotiation_margin = max( self.negotiation_margin, int(round(len(self.products) * max(0.0, 1.0 - self.riskiness))), ) if self.use_consumer: # @todo add the parameters of the consumption profile as parameters of the greedy factory manager profiles = dict( zip( self.consuming.keys(), ( ConsumptionProfile(schedule=[_] * self.awi.n_steps) for _ in itertools.repeat(0) ), ) ) self.consumer: ScheduleDrivenConsumer = ScheduleDrivenConsumer( profiles=profiles, consumption_horizon=self.awi.n_steps, immediate_cfp_update=True, name=self.name, ) self.consumer.id = self.id self.consumer.awi = self.awi self.consumer.init_() self.scheduler = self.scheduler_type( manager_id=self.id, awi=self.awi, max_insurance_premium=self.max_insurance_premium, **self.scheduler_params, ) self.scheduler.init( simulator=self.simulator, products=self.products, processes=self.processes, producing=self.producing, profiles=self.compiled_profiles, ) def respond_to_negotiation_request( self, cfp: "CFP", partner: str ) -> Optional[Negotiator]: if self.awi.is_bankrupt(partner): return None if self.use_consumer: return self.consumer.respond_to_negotiation_request( cfp=cfp, partner=partner ) else: neg = self.negotiator_type( name=self.name + "*" + partner, **self.negotiator_params ) neg.utility_function = self.ufun_factory( self, self._create_annotation(cfp=cfp) ) neg.utility_function.reserved_value = ( cfp.money_resolution if cfp.money_resolution is not None else 0.1 ) # neg.utility_function = normalize(self.ufun_factory(self, self._create_annotation(cfp=cfp)), # outcomes=cfp.outcomes, infeasible_cutoff=0) return neg def on_negotiation_success( self, contract: Contract, mechanism: AgentMechanismInterface ): if self.use_consumer: self.consumer.on_negotiation_success(contract, mechanism) def on_negotiation_failure( self, partners: List[str], annotation: Dict[str, Any], mechanism: AgentMechanismInterface, state: MechanismState, ) -> None: if self.use_consumer: self.consumer.on_negotiation_failure(partners, annotation, mechanism, state) cfp = annotation["cfp"] thiscfp = self.awi.bb_query(section="cfps", query=cfp.id, query_keys=True) if ( cfp.publisher != self.id and thiscfp is not None and len(thiscfp) > 0 and self.n_neg_trials[cfp.id] < self.n_retrials ): self.awi.logdebug(f"Renegotiating {self.n_neg_trials[cfp.id]} on {cfp}") self.on_new_cfp(cfp=annotation["cfp"]) def _execute_schedule(self, schedule: ScheduleInfo, contract: Contract) -> None: if self.simulator is None: raise ValueError("No factory simulator is defined") awi: SCMLAWI = self.awi total = contract.agreement["unit_price"] * contract.agreement["quantity"] product = contract.annotation["cfp"].product if contract.annotation["buyer"] == self.id: self.simulator.buy( product=product, quantity=contract.agreement["quantity"], price=total, t=contract.agreement["time"], ) if total <= 0 or self.max_insurance_premium < 0.0 or contract is None: return premium = awi.evaluate_insurance(contract=contract) if premium is None: return relative_premium = premium / total if relative_premium <= self.max_insurance_premium: awi.buy_insurance(contract=contract) self.simulator.pay(premium, self.awi.current_step) return # I am a seller self.simulator.sell( product=product, quantity=contract.agreement["quantity"], price=total, t=contract.agreement["time"], ) for job in schedule.jobs: if job.action == "run": awi.schedule_job(job, contract=contract) elif job.action == "stop": awi.stop_production( line=job.line, step=job.time, contract=contract, override=job.override, ) else: awi.schedule_job(job, contract=contract) self.simulator.schedule(job=job, override=False) for need in schedule.needs: if need.quantity_to_buy <= 0: continue product_id = need.product # self.simulator.reserve(product=product_id, quantity=need.quantity_to_buy, t=need.step) if self.use_consumer: self.consumer.profiles[product_id].schedule[ need.step ] += need.quantity_to_buy self.consumer.register_product_cfps( p=product_id, t=need.step, profile=self.consumer.profiles[product_id], ) continue product = self.products[product_id] if product.catalog_price is None: price_range = (0.0, 100.0) else: price_range = (0.5, 1.5 * product.catalog_price) # @todo check this. This error is raised sometimes if need.step < awi.current_step: continue # raise ValueError(f'need {need} at {need.step} while running at step {awi.current_step}') time = ( need.step if self.max_storage is not None else (awi.current_step, need.step) ) cfp = CFP( is_buy=True, publisher=self.id, product=product_id, time=time, unit_price=price_range, quantity=(1, int(1.1 * need.quantity_to_buy)), ) awi.register_cfp(cfp) def sign_contract(self, contract: Contract): if any(self.awi.is_bankrupt(partner) for partner in contract.partners): return None signature = self.id with temporary_transaction(self.scheduler): schedule = self.scheduler.schedule( assume_no_further_negotiations=False, contracts=[contract], ensure_storage_for=self.transportation_delay, start_at=self.awi.current_step + 1, ) if self.sign_only_guaranteed_contracts and ( not schedule.valid or len(schedule.needs) > 1 ): self.awi.logdebug( f"{self.name} refused to sign contract {contract.id} because it cannot be scheduled" ) return None # if schedule.final_balance <= self.simulator.final_balance: # self.awi.logdebug(f'{self.name} refused to sign contract {contract.id} because it is not expected ' # f'to lead to profit') # return None if schedule.valid: profit = schedule.final_balance - self.simulator.final_balance self.awi.logdebug( f"{self.name} singing contract {contract.id} expecting " f'{-profit if profit < 0 else profit} {"loss" if profit < 0 else "profit"}' ) else: self.awi.logdebug( f"{self.name} singing contract {contract.id} expecting breach" ) return None self.contract_schedules[contract.id] = schedule return signature def on_contract_signed(self, contract: Contract): if contract.annotation["buyer"] == self.id and self.use_consumer: self.consumer.on_contract_signed(contract) schedule = self.contract_schedules[contract.id] if schedule is not None and schedule.valid: self._execute_schedule(schedule=schedule, contract=contract) if contract.annotation["buyer"] != self.id or not self.use_consumer: for negotiation in self._running_negotiations.values(): self.notify( negotiation.negotiator, Notification(type="ufun_modified", data=None), ) def _process_buy_cfp(self, cfp: "CFP") -> None: if self.awi.is_bankrupt(cfp.publisher): return None if self.simulator is None or not self.can_expect_agreement( cfp=cfp, margin=self.negotiation_margin ): return if not self.can_produce(cfp=cfp): return neg = self.negotiator_type( name=self.name + ">" + cfp.publisher, **self.negotiator_params ) ufun = self.ufun_factory(self, self._create_annotation(cfp=cfp)) ufun.reserved_value = ( cfp.money_resolution if cfp.money_resolution is not None else 0.1 ) self.request_negotiation(negotiator=neg, cfp=cfp, ufun=ufun) # normalize(, outcomes=cfp.outcomes, infeasible_cutoff=-1) def _process_sell_cfp(self, cfp: "CFP"): if self.awi.is_bankrupt(cfp.publisher): return None if self.use_consumer: self.consumer.on_new_cfp(cfp=cfp) def on_new_cfp(self, cfp: "CFP") -> None: if not self.reactive: return if cfp.satisfies( query={"is_buy": True, "products": list(self.producing.keys())} ): self._process_buy_cfp(cfp) if cfp.satisfies( query={"is_buy": False, "products": list(self.consuming.keys())} ): self._process_sell_cfp(cfp) def step(self): if self.use_consumer: self.consumer.step() if self.reactive: return # 0. remove all my CFPs # self.awi.bb_remove(section='cfps', query={'publisher': self}) # respond to interesting CFPs # todo: should check time and sort products by interest etc cfps = self.awi.bb_query( section="cfps", query={"products": self.producing.keys(), "is_buy": True} ) if cfps is None: return for cfp in cfps.values(): self._process_buy_cfp(cfp) def can_produce(self, cfp: CFP, assume_no_further_negotiations=False) -> bool: """Whether or not we can produce the required item in time""" if cfp.product not in self.producing.keys(): return False agreement = SCMLAgreement( time=cfp.max_time, unit_price=cfp.max_unit_price, quantity=cfp.min_quantity ) min_concluded_at = self.awi.current_step + 1 - int(self.immediate_negotiations) min_sign_at = min_concluded_at + self.awi.default_signing_delay if cfp.max_time < min_sign_at + 1: # 1 is minimum time to produce the product return False with temporary_transaction(self.scheduler): schedule = self.scheduler.schedule( contracts=[ Contract( partners=[self.id, cfp.publisher], agreement=agreement, annotation=self._create_annotation(cfp=cfp), issues=cfp.issues, signed_at=min_sign_at, concluded_at=min_concluded_at, ) ], ensure_storage_for=self.transportation_delay, assume_no_further_negotiations=assume_no_further_negotiations, start_at=min_sign_at, ) return schedule.valid and self.can_secure_needs( schedule=schedule, step=self.awi.current_step ) def can_secure_needs(self, schedule: ScheduleInfo, step: int): """ Finds if it is possible in principle to arrange these needs at the given time. Args: schedule: step: Returns: """ needs = schedule.needs if len(needs) < 1: return True for need in needs: if need.quantity_to_buy > 0 and need.step < step + 1 - int( self.immediate_negotiations ): # @todo check this return False return True TotalUtilityFun = Callable[[Collection[Contract]], float] class NegotiatorUtility(UtilityFunction): """The utility function of a negotiator.""" def __init__( self, agent: GreedyFactoryManager, annotation: Dict[str, Any], name: Optional[str] = None, ): if name is None: name = ( agent.name + "*" + "*".join(_ for _ in annotation["partners"] if _ != agent.id) ) super().__init__(name=name) self.agent = agent self.annotation = annotation def _contracts(self, agreements: Iterable[SCMLAgreement]) -> Collection[Contract]: """Converts agreements/outcomes into contracts""" if self.ami is None: raise ValueError("No annotation is stored (No mechanism info)") annotation = self.ami.annotation return [ Contract( partners=annotation["partners"], agreement=a, annotation=annotation, issues=self.ami.issues, ) for a in agreements ] def _contract(self, agreement: SCMLAgreement) -> Contract: """Converts an agreement/outcome into a contract""" annotation = self.annotation return Contract( partners=annotation["partners"], agreement=agreement, annotation=annotation, issues=annotation["cfp"].issues, ) def _free_sale(self, agreement: SCMLAgreement) -> bool: return ( self.annotation["seller"] == self.agent.id and agreement["unit_price"] < 1e-6 ) def __call__(self, outcome: Outcome) -> Optional[UtilityValue]: if isinstance(outcome, dict): return self.call(agreement=SCMLAgreement(**outcome)) if isinstance(outcome, SCMLAgreement): return self.call(agreement=outcome) raise ValueError(f"Outcome: {outcome} cannot be converted to an SCMLAgreement") @abstractmethod def call(self, agreement: SCMLAgreement) -> Optional[UtilityValue]: """Called to evaluate a agreement""" def xml(self, issues: List[Issue]) -> str: return "NegotiatorUtility has not xml representation" class PessimisticNegotiatorUtility(NegotiatorUtility): """The utility function of a negotiator that assumes other negotiations currently open will fail.""" def call(self, agreement: SCMLAgreement) -> Optional[UtilityValue]: """An offer will be a tuple of one value which in turn will be a list of contracts""" if self._free_sale(agreement): return INVALID_UTILITY # contracts = self.agent.contracts # hypothetical = list(contracts) # hypothetical.append(self._contract(agreement)) hypothetical = [self._contract(agreement)] base_util = self.agent.simulator.final_balance hypothetical = self.agent.total_utility(hypothetical) if hypothetical < 0: return INVALID_UTILITY return hypothetical - base_util class OptimisticNegotiatorUtility(NegotiatorUtility): """The utility function of a negotiator that assumes other negotiations currently open will succeed.""" def call(self, agreement: SCMLAgreement) -> Optional[UtilityValue]: if self._free_sale(agreement): return INVALID_UTILITY # contracts = self.agent.contracts # hypothetical = list(contracts) # hypothetical.append(self._contract(agreement)) hypothetical = [self._contract(agreement)] for negotiation in self.agent.running_negotiations: # type: ignore negotiator = negotiation.negotiator current_offer = negotiator.my_last_proposal if current_offer is not None: hypothetical.append(self._contract(current_offer)) base_util = self.agent.simulator.final_balance hypothetical = self.agent.total_utility(list(hypothetical)) if hypothetical < 0: return INVALID_UTILITY return hypothetical - base_util class AveragingNegotiatorUtility(NegotiatorUtility): """A utility function that combines optimistic and pessimistic evaluators linearly using adjustable weight""" def __init__( self, agent: GreedyFactoryManager, annotation: Dict[str, Any], name: Optional[str] = None, optimism: float = 0.5, ): NamedObject.__init__(self=self, name=name) self.optimism = optimism self.optimistic = OptimisticNegotiatorUtility( agent=agent, annotation=annotation ) self.pessimistic = PessimisticNegotiatorUtility( agent=agent, annotation=annotation ) def call(self, agreement: SCMLAgreement) -> Optional[UtilityValue]: if self._free_sale(agreement): return INVALID_UTILITY opt, pess = self.optimistic(agreement), self.pessimistic(agreement) if opt is None or pess is None: return None return self.optimism * opt + (1 - self.optimism) * pess class JavaFactoryManager(FactoryManager, JavaCallerMixin): """Allows factory managers implemented in Java (using jnegmas) to participate in SCML worlds. Objects of this class is used to represent a java object to the python environment. This means that they *MUST* have the same interface as a python class (first class in the inheritance list). The `JavaCallerMixin` is used to enable it to connect to the java object it is representing. """ @property def type_name(self): """Overrides type name to give the internal java type name""" return "j" + snake_case( self._java_class_name.replace( "jnegmas.apps.scml.factory_managers.", "" ).replace("FactoryManager", "") ) @property def awi(self): return self._awi @awi.setter def awi(self, value): self._awi = value if self.python_shadow is not self: self.python_shadow._awi = value self.java_awi = _ShadowSCMLAWI(value) self._java_object.setAWI(self.java_awi) def init(self): if self.python_shadow is not self: self.python_shadow.simulator = self.simulator self._java_object.setSimulator(self.simulator) self._java_object.init() def step(self): return self._java_object.init() def on_neg_request_rejected(self, req_id: str, by: Optional[List[str]]): return self._java_object.onNegRequestRejected(req_id, by) def on_neg_request_accepted(self, req_id: str, mechanism: AgentMechanismInterface): return self._java_object.onNegRequestAccepted( req_id, java_link(_ShadowAgentMechanismInterface(mechanism)) ) def on_new_cfp(self, cfp: "CFP"): return from_java(self._java_object.onNewCFP(to_java(cfp))) def on_remove_cfp(self, cfp: "CFP"): return self._java_object.onRemoveCFP(to_java(cfp)) def on_contract_nullified( self, contract: Contract, bankrupt_partner: str, compensation: float ) -> None: self._java_object.onContractNullified( to_java(contract), bankrupt_partner, compensation ) def on_agent_bankrupt(self, agent_id: str) -> None: self._java_object.onAgentBankrupt(agent_id) def confirm_partial_execution( self, contract: Contract, breaches: List[Breach] ) -> bool: return self._java_object.confirmParialExecution( to_java(contract), to_java(breaches) ) def on_production_failure(self, failures: List[ProductionFailure]) -> None: return self._java_object.onProductionFailure(to_java(failures)) def confirm_loan(self, loan: Loan, bankrupt_if_rejected: bool) -> bool: return self._java_object.confirmLoan(to_java(loan), bankrupt_if_rejected) def confirm_contract_execution(self, contract: Contract) -> bool: return self._java_object.confirmContractExecution(to_java(contract)) def respond_to_negotiation_request( self, cfp: "CFP", partner: str ) -> Optional[Negotiator]: result = self._java_object.respondToNegotiationRequest(to_java(cfp), partner) if result is None: return result return JavaSAONegotiator(java_object=result, java_class_name=None) def on_negotiation_failure( self, partners: List[str], annotation: Dict[str, Any], mechanism: AgentMechanismInterface, state: MechanismState, ) -> None: return self._java_object.onNegotiationFailure( to_java(partners), annotation, java_link(_ShadowAgentMechanismInterface(mechanism)), to_java(state), ) def on_negotiation_success( self, contract: Contract, mechanism: AgentMechanismInterface ) -> None: return self._java_object.onNegotiationSuccess( to_java(contract), java_link(_ShadowAgentMechanismInterface(mechanism)) ) def on_contract_signed(self, contract: Contract) -> None: return self._java_object.onContractSigned(to_java(contract)) def on_contract_cancelled(self, contract: Contract, rejectors: List[str]) -> None: return self._java_object.onContractCancelled( to_java(contract), to_java(rejectors) ) def on_new_report(self, report: FinancialReport): pass def sign_contract(self, contract: Contract) -> Optional[str]: return from_java(self._java_object.signContract(to_java(contract))) def set_renegotiation_agenda( self, contract: Contract, breaches: List[Breach] ) -> Optional[RenegotiationRequest]: return from_java( self._java_object.setRenegotiationAgenda( to_java(contract), to_java(breaches) ) ) def respond_to_renegotiation_request( self, contract: Contract, breaches: List[Breach], agenda: RenegotiationRequest ) -> Optional[Negotiator]: return from_java( self._java_object.respondToRenegotiationRequest( to_java(contract), to_java(breaches), to_java(agenda) ) ) # handy constructors @classmethod def do_nothing_manager(cls): return JavaFactoryManager( java_class_name="jnegmas.apps.scml.factory_managers.DoNothingFactoryManager" ) @classmethod def greedy_manager(cls): return JavaFactoryManager( java_class_name="jnegmas.apps.scml.factory_managers.GreedyFactoryManager" ) def __init__( self, java_object=None, java_class_name: str = None, python_shadow: Optional[FactoryManager] = None, auto_load_java: bool = False, name=None, simulator_type: Union[str, Type[FactorySimulator]] = FastFactorySimulator, ): super().__init__(name=name, simulator_type=simulator_type) self.java_awi = None if java_class_name is not None: stem = java_class_name.split(".")[-1] if stem.endswith("GreedyFactoryManager") or stem.endswith("GFM"): python_shadow = GreedyFactoryManager( name=self.name, simulator_type=self.simulator_type ) python_shadow.id = self.id if python_shadow is None: python_shadow = self else: python_shadow = python_shadow self.python_shadow = python_shadow self._callback_shadow = self.python_shadow self.init_java_bridge( java_object=java_object, java_class_name=java_class_name, auto_load_java=auto_load_java, python_shadow_object=self, ) if java_object is None: map = to_dict(self) map.pop(PYTHON_CLASS_IDENTIFIER, None) map["simulatorType"] = self.simulator_type.__class__.__name__ self._java_object.fromMap(to_java(map)) def getNegotiationRequests(self): return to_java(self.requested_negotiations) def getRunningNegotiations(self): return to_java(self.running_negotiations) def requestNegotiation( self, cfp: CFP, negotiator: Negotiator = None, ufun: UtilityFunction = None ) -> bool: return self.request_negotiation( from_java(cfp), JavaSAONegotiator(negotiator, None), JavaUtilityFunction(ufun, None), ) def getLineProfiles(self): return to_java(self.line_profiles) def getProducing(self): return to_java(self.producing) def getConsuming(self): return to_java(self.consuming) def getCompiledProfiles(self): return to_java(self.compiled_profiles) def getProducts(self): return to_java(self.products) def getProcesses(self): return to_java(self.processes) def getContracts(self): return to_java(self.contracts) def getRequestedNegotiations(self): return to_java(self.requested_negotiations) def getRunningNegotiations(self): return to_java(self.running_negotiations) def requestNegotiation( self, cfp: CFP, negotiator: Negotiator = None, ufun: UtilityFunction = None ) -> bool: return self.request_negotiation( from_java(cfp), JavaSAONegotiator(negotiator, None), JavaUtilityFunction(ufun, None), ) def getID(self): return self.id def setID(self, value): self.id = value def getName(self): return self.name def setName(self, value): self.name = value def initPython(self): return self._callback_shadow.init() def stepPython(self): return self._callback_shadow.step() def onNegRequestRejected(self, req_id, rejectors): return self._callback_shadow.on_neg_request_rejected( req_id, from_java(rejectors) ) def onNegRequestAccepted(self, req_id, mechanism): return self._callback_shadow.on_neg_request_accepted( req_id, from_java(mechanism) ) def onNewCFP(self, cfp): return self._callback_shadow.on_new_cfp(from_java(cfp)) def onRemoveCFP(self, cfp): return self._callback_shadow.on_remove_cfp(from_java(cfp)) def onContractNullified(self, contract, bankruptPartner, compensation): return self._callback_shadow.on_contract_nullified( from_java(contract), bankruptPartner, compensation ) def onAgentBankrupt(self, agentId): return self._callback_shadow.on_agent_bankrupt(agentId) def confirmPartialExecution(self, contract, breaches): return self._callback_shadow.confirm_partial_execution( from_java(contract), from_java(breaches) ) def onProductionFailure(self, failures): return self._callback_shadow.on_production_failure(from_java(failures)) def confirmLoan(self, loan, bankruptIfRejected): return self._callback_shadow.confirm_loan(from_java(loan), bankruptIfRejected) def confirmContractExecution(self, contract): return self._callback_shadow.confirm_contract_execution(from_java(contract)) def respondToNegotiationRequest(self, cfp, partner): result = self._callback_shadow.respond_to_negotiation_request( from_java(cfp), partner ) if result is None: return None return _ShadowSAONegotiator(result) def onNegotiationFailure(self, partners, annotation, mechanism, state): return self._callback_shadow.on_negotiation_failure( from_java(partners), from_java(annotation), from_java(mechanism), from_java(state), ) def onNegotiationSuccess(self, contract, mechanism): return self._callback_shadow.on_negotiation_success( from_java(contract), from_java(mechanism) ) def onContractSigned(self, contract): return self._callback_shadow.on_contract_signed(from_java(contract)) def onContractCancelled(self, contract, rejectors): return self._callback_shadow.on_contract_cancelled( from_java(contract), from_java(rejectors) ) def onNewReport(self, report): return self._callback_shadow.on_new_report(from_java(report)) def signContract(self, contract): return self._callback_shadow.sign_contract(from_java(contract)) def setRenegotiationAgenda(self, contract, breaches): return to_java( self._callback_shadow.set_renegotiation_agenda( from_java(contract), from_java(breaches) ) ) def respondToRenegotiationRequest(self, contract, breaches, agenda): result = self._callback_shadow.respond_to_renegotiation_request( from_java(contract), from_java(breaches), from_java(agenda) ) if result is None: return result return _ShadowSAONegotiator(result) class Java: implements = ["jnegmas.apps.scml.factory_managers.FactoryManager"] class JavaDoNothingFactoryManager(JavaFactoryManager): def __init__( self, auto_load_java: bool = False, name=None, simulator_type: Union[str, Type[FactorySimulator]] = FastFactorySimulator, ): super().__init__( name=name, simulator_type=simulator_type, auto_load_java=auto_load_java, java_class_name="jnegmas.apps.scml.factory_managers.DoNothingFactoryManager", ) class JavaGreedyFactoryManager(JavaFactoryManager): def __init__( self, auto_load_java: bool = False, name=None, simulator_type: Union[str, Type[FactorySimulator]] = FastFactorySimulator, ): super().__init__( name=name, simulator_type=simulator_type, auto_load_java=auto_load_java, java_class_name="jnegmas.apps.scml.factory_managers.GreedyFactoryManager", python_shadow=lambda: GreedyFactoryManager( name=name, simulator_type=self.simulator_type ), ) class JavaDummyMiddleMan(JavaFactoryManager): def __init__( self, auto_load_java: bool = False, name=None, simulator_type: Union[str, Type[FactorySimulator]] = FastFactorySimulator, ): super().__init__( name=name, simulator_type=simulator_type, auto_load_java=auto_load_java, java_class_name="jnegmas.apps.scml.factory_managers.DummyMiddleMan", ) PK!negmas/apps/scml/helpers.pyfrom random import gauss import numpy as np __all__ = ["pos_gauss", "_safe_max", "zero_runs"] def pos_gauss(mu, sigma): """Returns a sample from a rectified gaussian""" x = gauss(mu, sigma) return abs(x) def _safe_max(a, b): if a is None: return b if b is None: return a return max(a, b) def zero_runs(a: np.array) -> np.array: """ Finds all runs of zero in an array Args: a: Input array (assumed to be 1D) Returns: np.array: A 2D array giving beginning and end (exclusive) of zero stretches in the input array. """ if len(a) == 0: return [] if np.all(np.equal(a, 0).view(np.int8)): return np.array([[0, len(a)]]) iszero = np.concatenate(([0], np.equal(a, 0).view(np.int8), [0])) absdiff = np.abs(np.diff(iszero)) # Runs start and end where absdiff is 1. ranges = np.where(absdiff == 1)[0].reshape(-1, 2) if len(ranges) == 0 and a[0] == 0: return np.array([[0, len(a)]]) return ranges PK!v;//negmas/apps/scml/insurance.pyfrom abc import ABC from collections import defaultdict from typing import Dict, Tuple, List, Optional, TYPE_CHECKING, Any from negmas import Mechanism, AgentMechanismInterface, MechanismState from negmas.negotiators import Negotiator from negmas.outcomes import Issue from negmas.situated import Agent, RenegotiationRequest, Breach, Contract from .agent import SCMLAgent from .common import InsurancePolicy, Factory if TYPE_CHECKING: from .world import SCMLWorld __all__ = ["DefaultInsuranceCompany", "InsuranceCompany"] class InsuranceCompany(Agent, ABC): """Base class for all insurance companies""" def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self._world: Optional[SCMLWorld] = None def _respond_to_negotiation_request( self, initiator: str, partners: List[str], issues: List[Issue], annotation: Dict[str, Any], mechanism: AgentMechanismInterface, role: Optional[str], req_id: Optional[str], ) -> Optional[Negotiator]: pass def on_neg_request_rejected(self, req_id: str, by: Optional[List[str]]): pass def on_neg_request_accepted(self, req_id: str, mechanism: AgentMechanismInterface): pass def on_negotiation_failure( self, partners: List[str], annotation: Dict[str, Any], mechanism: AgentMechanismInterface, state: MechanismState, ) -> None: pass def on_negotiation_success( self, contract: Contract, mechanism: AgentMechanismInterface ) -> None: pass def on_contract_signed(self, contract: Contract) -> None: pass def on_contract_cancelled(self, contract: Contract, rejectors: List[str]) -> None: pass def sign_contract(self, contract: Contract) -> Optional[str]: pass def respond_to_negotiation_request( self, initiator: str, partners: List[str], issues: List[Issue], annotation: Dict[str, Any], mechanism: Mechanism, role: Optional[str], req_id: str, ) -> Optional[Negotiator]: pass class DefaultInsuranceCompany(InsuranceCompany): """Represents an insurance company in the world""" def __init__( self, premium: float, premium_breach_increment: float, premium_time_increment: float, a2f: Dict[str, Factory], disabled=False, name: str = None, ): super().__init__(name=name) self.premium_breach_increment = premium_breach_increment self.premium = premium self.disabled = disabled self.premium_time_increment = premium_time_increment self.insured_contracts: Dict[Tuple[Contract, str], InsurancePolicy] = dict() self.storage: Dict[int, int] = defaultdict(int) self.wallet: float = 0.0 self.a2f = a2f def init(self): pass def set_renegotiation_agenda( self, contract: Contract, breaches: List[Breach] ) -> Optional[RenegotiationRequest]: return None def respond_to_renegotiation_request( self, contract: Contract, breaches: List[Breach], agenda: RenegotiationRequest ) -> Optional[Negotiator]: raise ValueError("The insurance company does not receive callbacks") def evaluate_insurance( self, contract: Contract, insured: SCMLAgent, against: SCMLAgent, t: int = None ) -> Optional[float]: """Can be called to evaluate the premium for insuring the given contract against breaches committed by others Args: against: The `SCMLAgent` to insure against contract: hypothetical contract insured: The `SCMLAgent` to buy the insurance t: time at which the policy is to be bought. If None, it means current step """ if self.disabled: return None # fail if no premium if self.premium is None: return None # assume the insurance is to be bought now if needed if t is None: t = self.awi.current_step # find the delay from contract signing. The more this is the more expensive the insurance will be if contract.signed_at is None: dt = 0 else: dt = max(0, t - contract.signed_at) # fail if the insurance is to be bought at or after the agreed upon delivery time if t >= contract.agreement.get("time", -1): return None # find the total breach of the agent I am insuring against. The more this is, the more expensive the insurance breaches = self.awi.bb_query(section="breaches", query={"perpetrator": against}) b = 0 if breaches is not None: for _, breach in breaches.items(): b += breach.level return (self.premium + b * self.premium_breach_increment) * ( 1 + self.premium_time_increment * dt ) def buy_insurance( self, contract: Contract, insured: SCMLAgent, against: SCMLAgent ) -> Optional[InsurancePolicy]: """Buys insurance for the contract by the premium calculated by the insurance company. Remarks: The agent can call `evaluate_insurance` to find the premium that will be used. """ if self.disabled: return None premium = self.evaluate_insurance( contract=contract, t=self.awi.current_step, insured=insured, against=against ) factory = self.a2f[insured.id] if premium is None or factory.wallet < premium: return None factory.pay(premium) self.wallet += premium policy = InsurancePolicy( contract=contract, at_time=self.awi.current_step, against=against, premium=premium, ) self.insured_contracts[(contract, against.id)] = policy return policy def pay_insurance(self, contract: Contract, perpetrator: SCMLAgent) -> bool: """ Args: contract: perpetrator: Returns: """ if self.disabled: return False if (contract, perpetrator.id) in self.insured_contracts.keys(): del self.insured_contracts[(contract, perpetrator.id)] return True return False def step(self): """does nothing""" PK!+k~~negmas/apps/scml/miners.pyfrom abc import ABC from collections import defaultdict from random import random from typing import TYPE_CHECKING from dataclasses import dataclass from numpy.random import dirichlet from negmas.apps.scml import FinancialReport from negmas.common import MechanismState, AgentMechanismInterface from negmas.helpers import ConfigReader, get_class from negmas.negotiators import Negotiator from negmas.outcomes import Issue from negmas.sao import AspirationNegotiator from negmas.situated import Contract, Breach from negmas.situated import RenegotiationRequest from negmas.utilities import LinearUtilityAggregationFunction, normalize from .agent import SCMLAgent from .helpers import pos_gauss if True: from typing import Dict, Any, List, Optional from .common import Loan __all__ = ["Miner", "MiningProfile", "ReactiveMiner"] @dataclass class MiningProfile: cv: float = 0.05 alpha_t: float = 1.0 alpha_q: float = 1.0 alpha_u: float = 1.0 beta_t: float = 1.0 beta_q: float = 100.0 beta_u: float = 100.0 tau_t: float = -0.25 tau_q: float = 0.25 tau_u: float = 1.0 @classmethod def random(cls): alpha_t, alpha_q, alpha_u = dirichlet((1, 1, 1), size=1)[0] tau_t, tau_q, tau_u = 2 * random() - 1, 2 * random() - 1, 2 * random() - 1 return MiningProfile( cv=random(), alpha_t=alpha_t, alpha_q=alpha_q, alpha_u=alpha_u, tau_t=tau_t, tau_q=tau_q, tau_u=tau_u, beta_t=1.5 * random(), beta_q=99 * random() + 1, beta_u=99 * random() + 1, ) class Miner(SCMLAgent, ABC): """Base class of all miners""" class ReactiveMiner(Miner): """Raw Material Generator""" def on_new_report(self, report: FinancialReport): pass def on_neg_request_rejected(self, req_id: str, by: Optional[List[str]]): pass def on_neg_request_accepted(self, req_id: str, mechanism: AgentMechanismInterface): pass def on_negotiation_success( self, contract: Contract, mechanism: AgentMechanismInterface ) -> None: pass def on_contract_signed(self, contract: Contract) -> None: pass def on_contract_cancelled(self, contract: Contract, rejectors: List[str]) -> None: pass def sign_contract(self, contract: Contract) -> Optional[str]: return self.id def on_contract_nullified( self, contract: Contract, bankrupt_partner: str, compensation: float ) -> None: pass def on_agent_bankrupt(self, agent_id: str) -> None: pass def confirm_partial_execution( self, contract: Contract, breaches: List[Breach] ) -> bool: return True def on_remove_cfp(self, cfp: "CFP"): pass def __init__( self, profiles: Dict[int, MiningProfile] = None, negotiator_type="negmas.sao.AspirationNegotiator", n_retrials=0, reactive=True, name=None, ): super().__init__(name=name) self.negotiator_type = get_class(negotiator_type, scope=globals()) self.profiles: Dict[int, MiningProfile] = {} self.n_neg_trials: Dict[str, int] = defaultdict(int) self.n_retrials = n_retrials self.reactive = reactive if profiles is not None: self.set_profiles(profiles=profiles) def init(self): self.awi.register_interest(list(self.profiles.keys())) def on_negotiation_failure( self, partners: List[str], annotation: Dict[str, Any], mechanism: AgentMechanismInterface, state: MechanismState, ) -> None: # noinspection PyUnusedLocal cfp = annotation["cfp"] super().on_negotiation_failure( partners=partners, annotation=annotation, mechanism=mechanism, state=state ) thiscfp = self.awi.bb_query(section="cfps", query=cfp.id, query_keys=True) if ( cfp.publisher != self.id and thiscfp is not None and len(thiscfp) > 0 and self.n_neg_trials[cfp.id] < self.n_retrials ): self.awi.logdebug(f"Renegotiating {self.n_neg_trials[cfp.id]} on {cfp}") self.on_new_cfp(cfp=annotation["cfp"]) def set_profiles(self, profiles: Dict[int, MiningProfile]): self.profiles = profiles if profiles is not None else dict() def _process_cfp(self, cfp: "CFP"): if self.awi.is_bankrupt(cfp.publisher) or not self.can_expect_agreement( cfp=cfp, margin=0 ): return profile = self.profiles.get(cfp.product, None) if profile is None: return if profile.cv == 0: alpha_u, alpha_q, alpha_t = ( profile.alpha_u, profile.alpha_q, profile.alpha_t, ) else: alpha_u, alpha_q, alpha_t = tuple( dirichlet((profile.alpha_u, profile.alpha_q, profile.alpha_t), size=1)[ 0 ] ) beta_u = pos_gauss(profile.beta_u, profile.cv) beta_t = pos_gauss(profile.beta_t, profile.cv) beta_q = pos_gauss(profile.beta_q, profile.cv) tau_u = pos_gauss(profile.tau_u, profile.cv) tau_t = pos_gauss(profile.tau_t, profile.cv) tau_q = pos_gauss(profile.tau_q, profile.cv) ufun = LinearUtilityAggregationFunction( issue_utilities={ "time": lambda x: x ** tau_t / beta_t, "quantity": lambda x: x ** tau_q / beta_q, "unit_price": lambda x: x ** tau_u / beta_u if x > 1e-7 else -2000.0, }, weights={"time": alpha_t, "quantity": alpha_q, "unit_price": alpha_u}, ) ufun.reserved_value = ( cfp.money_resolution if cfp.money_resolution is not None else 0.1 ) # ufun = normalize(, outcomes=cfp.outcomes, infeasible_cutoff=-1) if self.negotiator_type == AspirationNegotiator: negotiator = self.negotiator_type( name=self.name + "*" + cfp.publisher, dynamic_ufun=False, aspiration_type="boulware", ) else: negotiator = self.negotiator_type(name=self.name + "*" + cfp.publisher) self.n_neg_trials[cfp.id] += 1 self.request_negotiation(cfp=cfp, negotiator=negotiator, ufun=ufun) # normalize(ufun, outcomes=cfp.outcomes, infeasible_cutoff=None) def on_new_cfp(self, cfp: "CFP"): if self.reactive: if not cfp.satisfies(query={"products": list(self.profiles.keys())}): return self._process_cfp(cfp) def step(self): if not self.reactive: cfps = self.awi.bb_query( section="cfps", query_keys=False, query={"products": list(self.profiles.keys())}, ) if cfps is None: return cfps = cfps.values() for cfp in cfps: self._process_cfp(cfp) def confirm_contract_execution(self, contract: Contract) -> bool: return True def respond_to_negotiation_request( self, cfp: "CFP", partner: str ) -> Optional[Negotiator]: raise ValueError( "Miners should never receive negotiation requests as they publish no CFPs" ) def set_renegotiation_agenda( self, contract: Contract, breaches: List[Breach] ) -> Optional[RenegotiationRequest]: return None def respond_to_renegotiation_request( self, contract: Contract, breaches: List[Breach], agenda: RenegotiationRequest ) -> Optional[Negotiator]: return None def confirm_loan(self, loan: Loan, bankrupt_if_rejected: bool) -> bool: """called by the world manager to confirm a loan if needed by the buyer of a contract that is about to be breached""" return bankrupt_if_rejected PK!n~r~rnegmas/apps/scml/schedulers.pyimport math from abc import ABC, abstractmethod from typing import Dict, Any, Callable, Collection, List, Optional import numpy as np from dataclasses import dataclass, field from negmas.apps.scml.helpers import zero_runs from negmas.situated import Contract from .common import ( ProductionNeed, Job, Product, Process, ProductManufacturingInfo, SCMLAgreement, ManufacturingProfileCompiled, INVALID_UTILITY, ) from .simulators import FactorySimulator, transaction from .common import NO_PRODUCTION __all__ = ["ScheduleInfo", "Scheduler", "GreedyScheduler"] @dataclass class ScheduleInfo: final_balance: float """balance at the end of the schedule""" valid: bool = True """Is this a valid schedule?""" start: Optional[int] = None """The starting step of this schedule""" end: Optional[int] = None """The step after the last step in this simulation""" # these two attributes are not directly related to the schedule but with the scheduling operation that generated it needs: List[ProductionNeed] = field(default_factory=list) """The products needed but not still in storage needed to complete this schedule.""" jobs: List[Job] = field(default_factory=list) """The jobs that need to be scheduled""" failed_contracts: List[Contract] = field(default_factory=list) """A list of contracts that failed to be scheduled.""" ignored_contracts: List[Contract] = field(default_factory=list) """A list of contracts ignored for this schedule because they are in the past.""" def __str__(self): fail = ( str("fail " + "|".join(str(_) for _ in self.failed_contracts)) if len(self.failed_contracts) > 0 else "" ) ignored = ( str("ignored " + "|".join(str(_) for _ in self.ignored_contracts)) if len(self.ignored_contracts) > 0 else "" ) jobs = ( str("jobs " + "|".join(str(_) for _ in self.jobs)) if len(self.jobs) > 0 else "" ) updates, needs = "", "" if len(self.needs) > 0: needs = "needs :" + "\n\t".join(str(_) for _ in self.needs) result = f'{"valid" if self.valid else "invalid"} (ends before {self.end}):' for x in (fail, ignored, jobs, updates, needs): if len(x) > 0: result += "\n" + x return result def combine(self, other: "ScheduleInfo") -> None: self.valid = self.valid and other.valid if other.end is not None and self.end is not None: self.end = max(self.end, other.end) if other.needs is not None: self.needs.extend(other.needs) if other.jobs is not None: self.jobs.extend(other.jobs) if other.failed_contracts is not None: self.failed_contracts.extend(other.failed_contracts) if other.ignored_contracts is not None: self.ignored_contracts.extend(other.ignored_contracts) self.final_balance = other.final_balance class Scheduler(ABC): """Base class for all schedulers""" def __init__( self, manager_id: str, awi: "SCMLAWI", max_insurance_premium: float, horizon: Optional[int] = None, ): self.horizon = horizon self.n_steps = 0 self.n_lines = 0 self.simulator: FactorySimulator = None self.products: List[Product] = [] self.processes: List[Process] = [] self.profiles: List[ManufacturingProfileCompiled] = [] self.producing: Dict[int, List[ProductManufacturingInfo]] = {} self.manager_id = manager_id self.awi = awi self.max_insurance_premium = max_insurance_premium def bookmark(self) -> int: """Sets a bookmark to the current location Returns: bookmark ID """ return self.simulator.bookmark() def rollback(self, bookmark_id: int) -> bool: """Rolls back to the given bookmark ID Args: bookmark_id The bookmark ID returned from bookmark Remarks: - You can only rollback in the reverse order of bookmarks. If the bookmark ID given here is not the one at the top of the bookmarks stack, the rollback will fail (return False) """ return self.simulator.rollback(bookmark_id) def delete_bookmark(self, bookmark_id: int) -> bool: """Commits everything since the bookmark so it cannot be rolled back Args: bookmark_id The bookmark ID returned from bookmark Remarks: - You can only rollback in the reverse order of bookmarks. If the bookmark ID given here is not the one at the top of the bookmarks stack, the deletion will fail (return False) """ return self.simulator.delete_bookmark(bookmark_id) def init( self, simulator: FactorySimulator, products: List[Product], processes: List[Process], profiles: List[ManufacturingProfileCompiled], producing: Dict[int, List[ProductManufacturingInfo]], ): """Called by the FactoryManager after it is initialized""" self.simulator = simulator self.n_lines = self.simulator.n_lines self.n_steps = self.simulator.n_steps self.products = products self.processes = processes self.producing = producing self.profiles = profiles def schedule( self, contracts: Collection[Contract] = (), assume_no_further_negotiations=False, ensure_storage_for: int = 0, start_at: int = 0, ) -> ScheduleInfo: """ Schedules a set of contracts and returns either the search_for_schedule or None if infeasible Args: whatever it has scheduled before. If the state is given, it is taken as the initial state for scheduling contracts: The contracts to be scheduled assume_no_further_negotiations: whether to assume that more negotiations can take place (to secure production needs) ensure_storage_for: A minimum time to ensure that products are available in storage before contract delivery times (sell contracts). start_at: The time at which to start scheduling. No jobs will be scheduled before this time. Returns: `ScheduleInfo` describing the schedulo and any production needs and updates to be carried out. """ # initialize the state of the scheduler with initial knowledge # @todo make sure to take start into account. NOw I always schedule from the start start, end = 0, -1 for contract in contracts: if contract.agreement["time"] > end: end = contract.agreement["time"] + 1 if self.horizon is not None and end - start > self.horizon: end = start + self.horizon if end > self.n_steps: end = self.n_steps # if we have not new contracts, then we are done if len(contracts) == 0: return ScheduleInfo( valid=True, start=start, end=end, final_balance=self.simulator.final_balance, ) return self.find_schedule( contracts=contracts, start=start, end=end, assume_no_further_negotiations=assume_no_further_negotiations, ensure_storage_for=ensure_storage_for, start_at=start_at, ) @abstractmethod def find_schedule( self, contracts: Collection[Contract], start: int, end: int, assume_no_further_negotiations=False, ensure_storage_for: int = 0, start_at: int = 0, ) -> ScheduleInfo: """ Schedules a set of contracts and returns either the search_for_schedule or None if infeasible Args: start: end: contracts: assume_no_further_negotiations: ensure_storage_for: start_at: The time at which to start scheduling. No jobs will be scheduled before this time. Returns: Schedule information (See `ScheduleInfo` for its contents). """ class GreedyScheduler(Scheduler): """Default scheduler used by the DefaultFactoryManager""" def __getstate__(self): result = self.__dict__.copy() if "fields" in result.keys(): result.pop("fields", None) def __setstate__(self, state): self.__dict__ = state self.fields = [ self.total_unit_cost, self.unit_time, self.production_unit_cost, self.input_unit_cost, ] def __init__( self, manager_id: str, awi: "SCMLAWI", max_insurance_premium: float, horizon: Optional[int] = None, add_catalog_prices=True, strategy: str = "latest", profile_sorter: str = "total-cost>time", ): """ Args: manager_id: ID of the factory manager using this scheduler. awi: Agent-world interface (used to access insurance calculations and `n_steps`). max_insurance_premium: Maximum insurance premium over which the factory maanger will not buy insuracne horizon: Scheduling horizon (by default it is the number of simulation step in the AWI) add_catalog_prices: Whether to add total catalog price costs to costs of production strategy: How to schedule production. Possible values are earliest, latest, shortest, longest profile_sorter: The method used to sort profiles that can produce the same product Remarks: The following `production_strategy` values are supported: - earliest: Try to produce things as early as possible. Useful for infinite storage - latest: Try to produce things as late as possible. Useful for finite storage - shortest: Schedule in the time/line that has the shortest empty slot that is enough for production - longest: Schedule in the time/line that has the longest empty slot that is enough for production The `profile_sorter` string consists of one or more of the following sections separated by ``>`` characters to indicate sorting order. Costs are sorted ascendingly and times descendingly. Costs and times refer to unit cost/time (total divided by quantity generated): - time, t: profile production time per unit - input-cost, ic, icost: Input cost per unit only using catalog prices - production-cost, pc, pcost: Production cost as specified in the profile per unit - total-cost, tc, tcost: Total cost per unit including input cost """ super().__init__( manager_id=manager_id, horizon=horizon, awi=awi, max_insurance_premium=max_insurance_premium, ) self.add_catalog_prices = add_catalog_prices self.strategy = strategy self.fields: List[Callable[[ProductManufacturingInfo], float]] = [ self.total_unit_cost, self.unit_time, self.production_unit_cost, self.input_unit_cost, ] mapper = {"tc": 0, "t": 1, "pc": 2, "ic": 3} self.field_order: List[int] = [] sort_fields = profile_sorter.split(">") self.producing: Dict[int, List[ProductManufacturingInfo]] = {} for field_name in sort_fields: if field_name in ("time", "t"): self.field_order.append(mapper["t"]) elif field_name in ("total-cost", "tc", "tcost"): self.field_order.append(mapper["tc"]) elif field_name in ("production-cost", "pc", "pcost"): self.field_order.append(mapper["pc"]) elif field_name in ("input-cost", "ic", "icost"): self.field_order.append(mapper["ic"]) def init( self, simulator: FactorySimulator, products: List[Product], processes: List[Process], profiles: List[ManufacturingProfileCompiled], producing: Dict[int, List[ProductManufacturingInfo]], ): super().init( simulator=simulator, products=products, processes=processes, producing=producing, profiles=profiles, ) self.producing = { k: sorted(v, key=self._profile_sorter) for k, v in self.producing.items() } def _profile_sorter(self, info: ProductManufacturingInfo) -> Any: vals = [field(info) for field in self.fields] profile = self.profiles[info.profile] return tuple( [vals[indx] for indx in self.field_order] + [profile.line, profile.process] ) def unit_time(self, info: ProductManufacturingInfo) -> float: profile = self.profiles[info.profile] return profile.n_steps / info.quantity def total_cost(self, info: ProductManufacturingInfo) -> float: products = self.products profile = self.profiles[info.profile] process = self.processes[profile.process] production_cost = profile.cost def safe(x): return 0.0 if x is None else x inputs_cost = sum( safe(products[inp.product].catalog_price) * inp.quantity for inp in process.inputs ) return production_cost + inputs_cost def total_unit_cost(self, info: ProductManufacturingInfo) -> float: return self.total_cost(info=info) / info.quantity def production_cost(self, info: ProductManufacturingInfo) -> float: profile = self.profiles[info.profile] return profile.cost def production_unit_cost(self, info: ProductManufacturingInfo) -> float: return self.production_cost(info=info) / info.quantity def input_cost(self, info: ProductManufacturingInfo): products = self.products profile = self.profiles[info.profile] process = self.processes[profile.process] def safe(x): return 0.0 if x is None else x return sum( safe(products[inp.product].catalog_price) * inp.quantity for inp in process.inputs ) def input_unit_cost(self, info: ProductManufacturingInfo) -> float: return self.input_cost(info=info) / info.quantity # noinspection PyUnusedLocal def schedule_contract( self, contract: Contract, assume_no_further_negotiations=False, end: int = None, ensure_storage_for: int = 0, start_at: int = 0, ) -> ScheduleInfo: """ Schedules this contract if possible and returns information about the resulting schedule Args: contract: The contract being scheduled assume_no_further_negotiations: If true no further negotiations will be assumed possible end: The scheduling horizon (None for the default). ensure_storage_for: The number of steps all needs must be in storage before they are consumed in production start_at: No jobs will be scheduled before that time. Returns: Full schedule information including validity, line schedulers, production needs, etc (see `SchedulerInfo`). """ ignore_failures = not assume_no_further_negotiations simulator: FactorySimulator = self.simulator start = max(simulator.fixed_before, start_at) if end is None: end = simulator.n_steps if contract.agreement is None: return ScheduleInfo( end=end, final_balance=self.simulator.balance_at(end - 1) ) agreement: SCMLAgreement if isinstance(contract.agreement, dict): agreement = SCMLAgreement(**contract.agreement) else: agreement = contract.agreement # type: ignore t = agreement["time"] if t < start: return ScheduleInfo( end=end, final_balance=INVALID_UTILITY, valid=False, ignored_contracts=[contract], ) q, u = int(agreement["quantity"]), agreement["unit_price"] p = u * q pid: int = contract.annotation["cfp"].product if contract.annotation["buyer"] == self.manager_id: # I am a buyer # We do not ignore money shortage for buying. This means that the agent will not buy if the money it needs # may partially come from a sell contract that is not considered yet if not simulator.buy( product=pid, quantity=q, price=p, t=t, ignore_space_shortage=ignore_failures, ignore_money_shortage=ignore_failures, ): return ScheduleInfo( end=end, valid=False, failed_contracts=[contract], final_balance=INVALID_UTILITY, ) if p <= 0: return ScheduleInfo( valid=True, end=end, final_balance=self.simulator.balance_at(end - 1), ) insurance = self.awi.evaluate_insurance( contract=contract, t=self.awi.current_step ) if insurance is not None and insurance / p < self.max_insurance_premium: # if it is not possible to buy the insurance, the factory manager will not try to buy it. This is still # a valid schedule simulator.pay(insurance, t=t) return ScheduleInfo( valid=True, end=end, final_balance=self.simulator.balance_at(end - 1) ) elif contract.annotation["seller"] == self.manager_id: # I am a seller # if enough is available in storage and not reserved, just sell it q_needed = q - simulator.available_storage_at(t)[pid] if q_needed <= 0: if simulator.sell( product=pid, quantity=q, price=p, t=t, ignore_money_shortage=ignore_failures, ignore_inventory_shortage=ignore_failures, ): return ScheduleInfo( end=end, final_balance=self.simulator.balance_at(end - 1) ) else: return ScheduleInfo( end=end, valid=False, failed_contracts=[contract], final_balance=INVALID_UTILITY, ) jobs: List[Job] = [] needs: List[ProductionNeed] = [] with transaction(simulator) as bookmark: some_production = True while q_needed > 0 and some_production: some_production = False # I need now to schedule the production needed and calculate all required input products for info in self.producing[pid]: # find if it is possible to use the current process for producing the product profile = self.profiles[info.profile] line, process_index, profile_index = ( profile.line, profile.process, info.profile, ) q_produced, t_production = info.quantity, info.step current_schedule = simulator.line_schedules_to( t - ensure_storage_for - 1 )[line][start:] if len(current_schedule) < t_production: continue locs = zero_runs( (current_schedule != NO_PRODUCTION).astype(int) ) lengths = locs[:, 1] - locs[:, 0] indices = np.array(range(len(lengths))) indices = indices[lengths >= t_production] if len(indices) < 1: continue lengths, locs = lengths[indices], locs[indices] if self.strategy == "earliest": loc = locs[0, :] elif self.strategy == "latest": loc = locs[-1, :] - 1 loc[0] = loc[1] - t_production + 1 elif self.strategy == "shortest": sorted_lengths = sorted( zip(range(len(lengths)), lengths), key=lambda x: x[1] ) loc = locs[sorted_lengths[0][0], :] elif self.strategy == "longest": sorted_lengths = sorted( zip(range(len(lengths)), lengths), key=lambda x: x[1], reverse=True, ) loc = locs[sorted_lengths[0][0], :] else: raise ValueError( f"Unknown production strategy {self.strategy}" ) ptime = loc[0] + start job = Job( line=line, action="run", time=ptime, profile=profile_index, contract=contract, override=False, ) if not simulator.schedule( job, override=False, ignore_inventory_shortage=ignore_failures, ignore_money_shortage=ignore_failures, ignore_space_shortage=ignore_failures, ): continue # should never hit this jobs.append(job) # find the needs new_needs = [] process = self.processes[process_index] length = profile.n_steps for i in process.inputs: pind, quantity = i.product, i.quantity # I need the input to be available the step before production step = ptime + int(math.floor(i.step * length)) - 1 if step < 0: break available = max( 0, self.simulator.available_storage_at(step)[pind] - quantity, ) if available >= quantity: instore, tobuy = quantity, 0 else: instore, tobuy = available, quantity - available if tobuy > 0 or instore > 0: if step < start: break needs.append( ProductionNeed( product=pind, needed_for=contract, quantity_in_storage=instore, quantity_to_buy=tobuy, step=step, ) ) else: # all inputs can be secured in time # @todo consider stopping production after the product is available (+ ensure_storage_for) if needed q_needed -= q_produced some_production = True break if q_needed <= 0: # add the effect of selling if not simulator.sell( product=pid, quantity=q, price=p, t=t, ignore_money_shortage=ignore_failures, ignore_inventory_shortage=ignore_failures, ): simulator.rollback(bookmark) return ScheduleInfo( end=end, valid=False, failed_contracts=[contract], final_balance=INVALID_UTILITY, ) # add the effect of buying raw materials for need in needs: product_index = need.product product = self.products[product_index] catalog_price = product.catalog_price if catalog_price == 0 or need.quantity_to_buy <= 0: continue price = need.quantity_to_buy * catalog_price simulator.pay(price, t=need.step) # create schedule schedule = ScheduleInfo( jobs=jobs, end=end, needs=needs, failed_contracts=[], final_balance=self.simulator.balance_at(end - 1), ) return schedule simulator.rollback(bookmark) return ScheduleInfo( valid=False, failed_contracts=[contract], end=end, final_balance=self.simulator.balance_at(end - 1), ) raise ValueError( f"{self.manager_id} Not a seller of a buyer in Contract: {contract} with " f"annotation: {contract.annotation}" ) def schedule_contracts( self, contracts: Collection[Contract], end: int = None, assume_no_further_negotiations=False, ensure_storage_for: int = 0, start_at: int = 0, ) -> ScheduleInfo: """ Schedules a set of contracts and returns the `ScheduleInfo`. Args: contracts: Contracts to schedule assume_no_further_negotiations: If true, no further negotiations will be assumed to be possible end: The end of the simulation for the schedule (exclusive) ensure_storage_for: Ensure that the outcome will be at the storage for at least this time start_at: The timestep at which to start scheduling Returns: ScheduleInfo giving the schedule after these contracts is included. `valid` member can be used to check whether this is a valid contract """ simulator = self.simulator if end is None: end = simulator.n_steps result = ScheduleInfo( valid=True, end=end, final_balance=self.simulator.final_balance ) contracts = sorted(contracts, key=lambda x: x.agreement["time"]) for contract in contracts: new_schedule = self.schedule_contract( contract, end=end, ensure_storage_for=ensure_storage_for, assume_no_further_negotiations=assume_no_further_negotiations, start_at=start_at, ) result.combine(new_schedule) if new_schedule.valid: result.final_balance = self.simulator.final_balance else: result.final_balance = INVALID_UTILITY return result def find_schedule( self, contracts: Collection[Contract], start: int, end: int, assume_no_further_negotiations=False, ensure_storage_for: int = 0, start_at: int = 0, ): # Now, schedule the contracts schedule = self.schedule_contracts( contracts=contracts, end=end, ensure_storage_for=ensure_storage_for, assume_no_further_negotiations=assume_no_further_negotiations, start_at=start_at, ) # Mark the schedule as invalid if it has any production needs and we assume_no_further_negotiations if ( assume_no_further_negotiations and schedule.needs is not None and len(schedule.needs) > 0 ): schedule.valid = False return schedule return schedule PK!negmas/apps/scml/simulators.py"""Simulators module implementing factory simulation""" import math import sys from abc import ABC, abstractmethod from collections import defaultdict from typing import Dict, List, Optional import numpy as np from dataclasses import dataclass, field from contextlib import contextmanager from negmas.java import to_java, to_dict from .common import ManufacturingProfile, Job, Factory, NO_PRODUCTION __all__ = [ "FactorySimulator", "SlowFactorySimulator", "FastFactorySimulator", "transaction", "temporary_transaction", ] def storage_as_array(storage: Dict[int, int], n_products: int) -> np.array: """ Converts storage to an array Args: storage: A dictionary giving quantity for each product index n_products: number of products (size of the resulting array) Returns: """ a = np.zeros(n_products) for k, v in storage.items(): a[k] = v return a class FactorySimulator(ABC): """Simulates a factory allowing for prediction of storage/balance in the future. Args: initial_wallet: The initial amount of cash in the wallet initial_storage: initial inventory n_steps: number of simulation steps n_products: number of products in the world profiles: all profiles that the factory being simulated can run max_storage: maximum available storage space. """ def __init__( self, initial_wallet: float, initial_storage: Dict[int, int], n_steps: int, n_products: int, profiles: List[ManufacturingProfile], max_storage: Optional[int] = None, ): self._n_steps = n_steps self._max_storage = max_storage if max_storage is not None else sys.maxsize self._initial_wallet = initial_wallet self._initial_storage = np.zeros(n_products) for k, v in initial_storage.items(): self._initial_storage[k] = v self._profiles = profiles self._n_products = n_products self._reserved_storage = np.zeros(shape=(n_products, n_steps)) def _as_array(self, storage: Dict[int, int]): return storage_as_array(storage=storage, n_products=self._n_products) # ----------------- # FIXED PROPERTIES # ----------------- @property def max_storage(self) -> Optional[int]: """Maximum storage available""" return self._max_storage @property def n_steps(self) -> int: """Number of steps to predict ahead.""" return self._n_steps @property def initial_wallet(self) -> float: """Initial cash in wallet""" return self._initial_wallet @property def initial_storage(self) -> np.array: """Initial inventory""" return self._initial_storage @property @abstractmethod def n_lines(self): """Number of lines""" @property @abstractmethod def final_balance(self) -> float: """Final balance given everything scheduled so-far""" # ------------------------------- # DYNAMIC PROPERTIES (READ STATE) # ------------------------------- @abstractmethod def wallet_to(self, t: int) -> np.array: """ Returns the cash in wallet up to and including time t. Args: t: Time Returns: """ def wallet_at(self, t: int) -> float: """ Returns the cash in wallet *at* a given timestep (given all simulated actions) Args: t: Returns: """ return self.wallet_to(t)[-1] @abstractmethod def storage_to(self, t: int) -> np.array: """ Returns the storage of all products *up to* time t Args: t: Time Returns: An array of size `n_products` * `t` giving the quantity of each product in storage at every step up to `t`. """ def storage_at(self, t: int) -> np.array: """ Returns the storage of all products *at* time t Args: t: Time Returns: An array of size `n_products` giving the quantity of each product in storage at time-step `t`. See Also: `storage_to` `wallet_at` """ return self.storage_to(t)[:, -1] @abstractmethod def line_schedules_to(self, t: int) -> np.array: """ Returns the schedule of each line up to a given timestep Args: t: time Returns: An array of `n_lines` * `t` values giving the schedule up to `t`. Remarks: - A `NO_PRODUCTION` value means no production, otherwise the index of the process being run """ def line_schedules_at(self, t: int) -> np.array: """ Returns the schedule of each line at a given timestep Args: t: time Returns: An array of `n_lines` values giving the schedule up at `t`. Remarks: - A `NO_PRODUCTION` value means no production, otherwise the index of the process being run """ return self.line_schedules_to(t)[:, -1] def total_storage_to(self, t: int) -> np.array: """ The total storage *up to* a given time Args: t: time Returns: an array of size `t` giving the total quantity of stored products in the inventory up to timestep `t` See Also: `total_storage_at` `storage_to` """ return self.storage_to(t).sum(axis=0) def total_storage_at(self, t: int) -> int: """ The total storage *at* a given time Args: t: time Returns: an integer giving the total quantity of stored products in the inventory at timestep `t` See Also: `total_storage_to` `storage_at` """ return self.total_storage_to(t)[-1] def reserved_storage_to(self, t: int) -> np.array: """ Returns the *reserved* storage of all products *up to* time t Args: t: Time Returns: An array of size `n_products` * `t` giving the quantity of each product reserved at every step up to `t`. Remarks: - Reserved storage *is counted* in calls to `storage_at` , `total_storage_at` , `storage_to` , `total_storage_to` - Reserving quantities of products is a tool that can be used to avoid double counting availability of given products in the inventory for multiple contracts. See Also: `total_storage_at` `storage_at` `reserved_storage_at` """ return self._reserved_storage[:, : t + 1] def reserved_storage_at(self, t: int) -> np.array: """ Returns the *reserved* storage of all products *at* time t Args: t: Time Returns: An array of size `n_products` giving the quantity of each product reserved at time-step `t`. Remarks: - Reserved storage *is counted* in calls to `storage_at` , `total_storage_at` , `storage_to` , `total_storage_to` - Reserving quantities of products is a tool that can be used to avoid double counting availability of given products in the inventory for multiple contracts. See Also: `total_storage_to` `storage_to` `reserved_storage_at` """ return self._reserved_storage[:, t] def available_storage_to(self, t: int) -> np.array: """ Returns the *available* storage of all products *up to* time t. Args: t: Time Returns: An array of size `n_products` * `t` giving the quantity of each product available at every step up to `t`. Remarks: - Available storage is defined as the difference between storage and reserved storage. - Reserved storage *is counted* in calls to `storage_at` , `total_storage_at` , `storage_to` , `total_storage_to` - Reserving quantities of products is a tool that can be used to avoid double counting availability of given products in the inventory for multiple contracts. See Also: `total_storage_to` `storage_to` `reserved_storage_to` """ return self.storage_to(t) - self.reserved_storage_to(t) def available_storage_at(self, t: int) -> np.array: """ Returns the *available* storage of all products *at* time t Args: t: Time Returns: An array of size `n_products` giving the quantity of each product available at time-step `t`. Remarks: - Available storage is defined as the difference between storage and reserved storage. - Reserved storage *is counted* in calls to `storage_at` , `total_storage_at` , `storage_to` , `total_storage_to` - Reserving quantities of products is a tool that can be used to avoid double counting availability of given products in the inventory for multiple contracts. See Also: `total_storage_to` `storage_to` `reserved_storage_at` """ return self.storage_at(t) - self.reserved_storage_at(t) @abstractmethod def loans_to(self, t: int) -> np.array: """ Returns loans up to time t Args: t: time Returns: An array of `t` real numbers giving the loans registered at time-steps up to `t` """ def loans_at(self, t: int) -> float: """ Returns loans at time t Args: t: time """ return self.loans_to(t)[-1] def balance_at(self, t: int) -> float: """ Returns the balance fo the factory at time t. Args: t: time Remarks: - The balance is defined as the cash in wallet minus loans See Also: `loans_at` `wallet_at` """ return self.wallet_at(t) - self.loans_at(t) def balance_to(self, t: int) -> np.array: """ Returns the balance fo the factory *up to* time t. Args: t: time Remarks: - The balance is defined as the cash in wallet minus loans See Also: `loans_to` `wallet_to` """ return self.wallet_to(t) - self.loans_to(t) @property @abstractmethod def fixed_before(self): """Gives the time before which the schedule is fixed. See Also: `fix_before` """ # ------------------------- # OPERATIONS (UPDATE STATE) # ------------------------- @abstractmethod def set_state( self, t: int, storage: np.array, wallet: float, loans: float, line_schedules: np.array, ) -> None: """ Sets the current state at the given time-step. It implicitly causes a fix_before(t + 1) Args: t: Time step to set the state at storage: quantity of every product (array of integers of size `n_products`) wallet: Cash in wallet loans: Loans line_schedules: Line schedules (array of process numbers/NO_PRODUCTION of size `n_lines`) """ @abstractmethod def add_loan(self, total: float, t: int) -> bool: """ Adds a loan at the given time Args: total: Total amount of the loan t: time step to take the loan Returns: Success or failure Remarks: - Taking a loan is simulated as reception of money. Payment back of the loan is not simulated in this call. To simulate paying back the loan, use `pay` at the times of installment payments. """ def receive(self, payment: float, t: int) -> bool: """ Simulates receiving payment at time t Args: payment: Amount received t: time Returns: Success or failure """ return self.pay(-payment, t) @abstractmethod def pay(self, payment: float, t: int, ignore_money_shortage: bool = True) -> bool: """ Simulate payment at time t Args: payment: Amount payed t: time ignore_money_shortage: If True, shortage in money will be ignored and the wallet can go negative Returns: Success or failure """ @abstractmethod def transport_to( self, product: int, quantity: int, t: int, ignore_inventory_shortage: bool = True, ignore_space_shortage: bool = True, ) -> bool: """ Simulates transporting products to/from storage at time t Args: product: product ID (index) quantity: quantity to transport t: time ignore_inventory_shortage: Ignore shortage in the `product` which may lead to negative storage[product] ignore_space_shortage: Ignore the limit on total storage which may lead to total_storage > max_storage Returns: Success or failure """ @abstractmethod def buy( self, product: int, quantity: int, price: int, t: int, ignore_money_shortage: bool = True, ignore_space_shortage: bool = True, ) -> bool: """ Buy a given quantity of a product for a given price at some time t Args: product: Product to buy (ID/index) quantity: quantity to buy price: unit price t: time ignore_money_shortage: If True, shortage in money will be ignored and the wallet can go negative ignore_space_shortage: Ignore the limit on total storage which may lead to total_storage > max_storage Returns: Success or failure Remarks: - buy cannot ever have inventory shortage See Also: `sell` """ @abstractmethod def sell( self, product: int, quantity: int, price: int, t: int, ignore_money_shortage: bool = True, ignore_inventory_shortage: bool = True, ) -> bool: """ sell a given quantity of a product for a given price at some time t Args: product: Index/ID of the product to be sold quantity: quantity to be sold price: unit price t: time ignore_money_shortage: If True, shortage in money will be ignored and the wallet can go negative ignore_inventory_shortage: Ignore shortage in the `product` which may lead to negative storage[product] Returns: Success or failure Remarks: - sell cannot ever have space shortage See Also: `buy` """ @abstractmethod def schedule( self, job: Job, ignore_inventory_shortage=True, ignore_money_shortage=True, ignore_space_shortage=True, override=True, ) -> bool: """ Simulates scheduling the given job at its `time` and `line` optionally overriding whatever was already scheduled Args: job: Production job ignore_inventory_shortage: If true shortages in inputs will be ignored ignore_money_shortage: If true, shortage in money will be ignored ignore_space_shortage: If true, shortage in space will be ignored override: Whether the job should override any already registered job at its time-step Returns: Success/failure """ def reserve(self, product: int, quantity: int, t: int) -> bool: """ Simulates reserving the given quantity of the given product at times >= t. Args: product: Index/ID of the product being reserved quantity: quantity being reserved t: time Returns: Success/failure Remarks: - Reserved products show in calls to `storage_at` , `total_storage_at` etc. - Reserving a product does nothing more than mark some quantity as reserved for calls to `reserved_storage_at` and `available_storage_at`. - This feature can be used to simulate inventory hiding commands in the real factory and to avoid double counting of inventory when calculating needs for future contracts. """ self._reserved_storage[product, t] += quantity return True # ------------------ # HISTORY MANAGEMENT # ------------------ @abstractmethod def fix_before(self, t: int) -> bool: """ Fix the history before this point Args: t: time Returns: Success/failure Remarks: - After this function is called at any time-step `t`, there is no way to change any component of the factory state at any timestep before `t`. - This function is useful for *fixing* any difference between the simulator and the real state (in conjunction with `set_state`). See Also: `set_state` `fixed_before` """ @abstractmethod def bookmark(self) -> int: """Sets a bookmark to the current location Returns: bookmark ID Remarks: - Bookmarks can be used to implement transactions. See Also: `delete_bookmark` `rollback` `transaction` `temporary_transaction` """ @abstractmethod def rollback(self, bookmark_id: int) -> bool: """Rolls back to the given bookmark ID Args: bookmark_id The bookmark ID returned from bookmark Remarks: - You can only rollback in the reverse order of bookmarks. If the bookmark ID given here is not the one at the top of the bookmarks stack, the rollback will fail (return False) See Also: `delete_bookmark` `rollback` `transaction` `temporary_transaction` """ @abstractmethod def delete_bookmark(self, bookmark_id: int) -> bool: """Commits everything since the bookmark so it cannot be rolled back Args: bookmark_id The bookmark ID returned from bookmark Returns: Success/failure Remarks: - You can delete bookmarks in the reverse order of their creation only. If the bookmark ID given here is not the one at the top of the bookmarks stack, the deletion will fail (return False). See Also: `delete_bookmark` `rollback` `transaction` `temporary_transaction` """ @dataclass class _Bookmark: id: int jobs: Dict[int, List[int]] = field( default_factory=lambda: defaultdict(list), init=False ) buy_contracts: Dict[int, List[int]] = field( default_factory=lambda: defaultdict(list), init=False ) sell_contracts: Dict[int, List[int]] = field( default_factory=lambda: defaultdict(list), init=False ) payment_updates: Dict[int, float] = field( default_factory=lambda: defaultdict(float), init=False ) loans_updates: Dict[int, float] = field( default_factory=lambda: defaultdict(float), init=False ) storage_updates: Dict[int, Dict[int, int]] = field( default_factory=lambda: defaultdict(lambda: defaultdict(int)), init=False ) @dataclass class _State: t: int storage: np.array wallet: float loans: float line_schedules: np.array class SlowFactorySimulator(FactorySimulator): """A slow factory simulator that runs an internal factory to find-out what will happen in the future Remarks: - It is *much* faster to always access the properties/methods of this class in ascending time. If that is not the case, each time reversal will cause a complete reset. - It is recommended to call `fix_before` () to fix the past once a production step is completed. That will speed up operations """ def set_state( self, t: int, storage: np.array, wallet: float, loans: float, line_schedules: np.array, ) -> None: for i, s in enumerate(storage): d = s - self.storage_at(t)[i] if d == 0.0: continue self._storage_updates[t][i] += d d = self.wallet_at(t) - wallet if d != 0.0: self._payment_updates[t] -= d d = self.loans_at(t) - loans if d != 0.0: self._loans_updates[t] -= d expected_schedules = self.line_schedules_at(t) for i in range(self.n_lines): expected, actual = expected_schedules[i], line_schedules[i] if expected == actual: continue if expected == NO_PRODUCTION: raise ValueError( f"Expected no production at time {t} on line {i} but actually process " f"{actual} is running" ) if expected != actual and actual != NO_PRODUCTION: raise ValueError( f"Expected process {expected} at time {t} on line {i} but actually process " f"{actual} is running" ) self._line_schedules[i, t] = actual self.fix_before(t + 1) self._saved_states[t].append( _State( t=t, storage=storage.copy(), wallet=wallet, loans=loans, line_schedules=line_schedules.copy(), ) ) def delete_bookmark(self, bookmark_id: int) -> bool: if self._active_bookmark is None or self._active_bookmark.id != bookmark_id: raise ValueError(f"there is no active bookmark to delete") self._bookmarks, self._bookmarked_at = ( self._bookmarks[:-1], self._bookmarked_at[:-1], ) self._active_bookmark = ( self._bookmarks[-1] if len(self._bookmarks) > 0 else None ) self._active_bookmarked_at = ( self._bookmarked_at[-1] if len(self._bookmarked_at) > 0 else -1 ) return True def bookmark(self) -> int: bookmark = _Bookmark(id=len(self._bookmarks)) self._bookmarks.append(bookmark) self._bookmarked_at.append(self._factory.next_step) self._active_bookmark = bookmark self._active_bookmarked_at = self._bookmarked_at[-1] return bookmark.id def rollback(self, bookmark_id: int) -> bool: if self._active_bookmark is None or self._active_bookmark.id != bookmark_id: raise ValueError(f"there is no active bookmark to rollback") for t, payment in self._active_bookmark.payment_updates.items(): self._payment_updates[t] += payment for t, payment in self._active_bookmark.loans_updates.items(): self._loans_updates[t] += payment for t, storage in self._active_bookmark.storage_updates.items(): s = self._storage_updates[t] for k, v in storage: s[k] -= v for t, rolled_indices in self._active_bookmark.jobs.items(): self._jobs[t] = [ _ for i, _ in enumerate(self._jobs[t]) if i not in rolled_indices ] for t, rolled_indices in self._active_bookmark.buy_contracts.items(): self._buy_contracts[t] = [ _ for i, _ in enumerate(self._buy_contracts[t]) if i not in rolled_indices ] for t, rolled_indices in self._active_bookmark.sell_contracts.items(): self._sell_contracts[t] = [ _ for i, _ in enumerate(self._sell_contracts[t]) if i not in rolled_indices ] if self._factory.next_step != self._bookmarked_at: self.goto(self._active_bookmarked_at) return True @property def final_balance(self) -> float: self.goto(self.n_steps - 1) return self.balance_at(self.n_steps - 1) @property def n_lines(self): return self._factory.n_lines def fix_before(self, t: int) -> bool: self.goto(t) self._fixed_before = t invalid = [i for i, bt in enumerate(self._bookmarked_at) if bt < t] self._bookmarks = [_ for i, _ in enumerate(self._bookmarks) if i not in invalid] self._bookmarked_at = [ _ for i, _ in enumerate(self._bookmarked_at) if i not in invalid ] return True def __init__( self, initial_wallet: float, initial_storage: Dict[int, int], n_steps: int, n_products: int, profiles: List[ManufacturingProfile], max_storage: Optional[int], ): super().__init__( initial_wallet=initial_wallet, initial_storage=initial_storage, n_steps=n_steps, n_products=n_products, profiles=profiles, max_storage=max_storage, ) self._factory = Factory( initial_storage=initial_storage, initial_wallet=initial_wallet, profiles=profiles, max_storage=max_storage, ) self._jobs: Dict[int, List[(Job, bool, bool, bool, bool)]] = defaultdict(list) self._buy_contracts: Dict[int, List[(int, int, float)]] = defaultdict(list) self._sell_contracts: Dict[int, List[(int, int, float)]] = defaultdict(list) self._payment_updates: Dict[int, float] = defaultdict(float) self._loans_updates: Dict[int, float] = defaultdict(float) self._storage_updates: Dict[int, Dict[int, int]] = defaultdict( lambda: defaultdict(int) ) self._wallet = np.zeros(n_steps) self._loans = np.zeros(n_steps) self._storage = np.zeros(shape=(n_products, n_steps)) self._line_schedules = np.zeros(shape=(self._factory.n_lines, self._n_steps)) self._fixed_before = 0 self._bookmarks: List[_Bookmark] = [] self._active_bookmark: Optional[_Bookmark] = None self._active_bookmarked_at: int = -1 self._bookmarked_at: List[int] = [] self._saved_states: Dict[int, List[_State]] = defaultdict(list) def _update_state(self) -> None: t = self._factory.next_step - 1 if t < 0: return self._wallet[t] = self._factory.wallet self._loans[t] = self._factory.loans self._storage[:, t] = self._as_array(self._factory.storage) self._line_schedules[:, t] = np.array( list( NO_PRODUCTION if command.is_none else command.profile.process.id for command in self._factory.commands ) ) def reset_to(self, t: int) -> None: self._factory = Factory( initial_storage={ i: v for i, v in enumerate(self._initial_storage) if v != 0 }, initial_wallet=self._initial_wallet, profiles=self._profiles, ) for step in range(t + 1): self._factory.receive(payment=self._payment_updates.get(step, 0.0)) self._factory.add_loan(total=self._loans_updates.get(step, 0.0)) jobs = self._jobs.get(t, []) for job, override, ignore_storage, ignore_money, ignore_space in jobs: # @todo use ignore* here try: self._factory.schedule(job=job, override=override) except ValueError as err: print(err) contracts = self._buy_contracts.get(t, []) for product, quantity, price in contracts: try: self._factory.buy(product=product, quantity=quantity, price=price) except ValueError as err: print(err) contracts = self._sell_contracts.get(t, []) for product, quantity, price in contracts: try: self._factory.sell(product=product, quantity=quantity, price=price) except ValueError as err: print(err) inventory = self._storage_updates.get(step, {}) for product, quantity in inventory.items(): try: self._factory.transport_to(product, quantity) except ValueError as err: print(err) self._update_state() def goto(self, t: int) -> None: """ Steps the factory to the end of step t Args: t: time Returns: """ if t > self.n_steps - 1: t = self.n_steps - 1 if self._factory.next_step > t + 1: if t < self._fixed_before: return self.reset_to(t) while self._factory.next_step <= t: step = self._factory.next_step loan = self._loans_updates.get(step, None) if loan is not None: self._factory.add_loan(loan) payment = self._payment_updates.get(step, None) if payment is not None: self._factory.pay(payment) jobs = self._jobs.get(step, []) for job, override, ignore_storage, ignore_money, ignore_space in jobs: # @todo implement ignore_input_shortage inside the factory to use ignore_input_shortage here self._factory.schedule(job=job, override=override) self._factory.step() inventory = self._storage_updates.get(step, None) if inventory is not None: for product, quantity in inventory.items(): self._factory.transport_to(product, quantity) self._update_state() def wallet_to(self, t: int) -> np.array: if t < self._fixed_before: return self._wallet[: t + 1] self.goto(t) return self._wallet[: t + 1] def line_schedules_to(self, t: int) -> np.array: if t < self._fixed_before: return self._storage[:, : t + 1] self.goto(t) return self._line_schedules[:, : t + 1] def storage_to(self, t: int) -> np.array: if t < self._fixed_before: return self._storage[:, : t + 1] self.goto(t) return self._storage[:, : t + 1] def loans_to(self, t: int) -> float: if t < self._fixed_before: return self._loans[: t + 1] self.goto(t) return self._loans[: t + 1] def add_loan(self, total: float, t: int) -> bool: if t < self._fixed_before: raise ValueError( f"Cannot run operations in the past (t={t}, fixed before {self._fixed_before})" ) self._loans_updates[t] += total if self._active_bookmark: self._active_bookmark.loans_updates[t] += total return True def pay(self, payment: float, t: int, ignore_money_shortage: bool = True) -> bool: if t < self._fixed_before: raise ValueError( f"Cannot run operations in the past (t={t}, fixed before {self._fixed_before})" ) self._payment_updates[t] += payment if self._active_bookmark: self._active_bookmark.payment_updates[t] += payment return True def transport_to( self, product: int, quantity: int, t: int, ignore_inventory_shortage: bool = True, ignore_space_shortage: bool = True, ) -> bool: if t < self._fixed_before: raise ValueError( f"Cannot run operations in the past (t={t}, fixed before {self._fixed_before})" ) s = self._storage_updates[t] s[product] += quantity if self._active_bookmark: s = self._active_bookmark.storage_updates[t] s[product] += quantity return True def schedule( self, job: Job, ignore_inventory_shortage=True, ignore_money_shortage=True, ignore_space_shortage=True, override=True, ) -> bool: t = job.time if t < self._fixed_before: raise ValueError( f"Cannot run operations in the past (t={t}, fixed before {self._fixed_before})" ) self._jobs[t].append( ( job, override, ignore_inventory_shortage, ignore_money_shortage, ignore_space_shortage, ) ) if self._active_bookmark: self._active_bookmark.jobs[t].append(len(self._jobs[t])) return True def buy( self, product: int, quantity: int, price: int, t: int, ignore_money_shortage: bool = True, ignore_space_shortage: bool = True, ) -> bool: if t < self._fixed_before: raise ValueError( f"Cannot run operations in the past (t={t}, fixed before {self._fixed_before})" ) self._buy_contracts[t].append((product, quantity, price)) if self._active_bookmark: self._active_bookmark.buy_contracts[t].append(len(self._buy_contracts[t])) return True def sell( self, product: int, quantity: int, price: int, t: int, ignore_money_shortage: bool = True, ignore_inventory_shortage: bool = True, ) -> bool: if t < self._fixed_before: raise ValueError( f"Cannot run operations in the past (t={t}, fixed before {self._fixed_before})" ) self._sell_contracts[t].append((product, quantity, price)) if self._active_bookmark: self._active_bookmark.sell_contracts[t].append(len(self._sell_contracts[t])) return True @property def fixed_before(self): return self._fixed_before @dataclass class _FullBookmark: id: int wallet: np.array loans: np.array storage: np.array line_schedules: np.array has_jobs: np.array class FastFactorySimulator(FactorySimulator): """ A faster implementation of the `FactorySimulator` interface (compared with `SlowFactorySimulator`. """ def _as_array(self, storage: Dict[int, int]) -> np.array: a = np.zeros(self._n_products) for k, v in storage.items(): a[k] = v return a def __init__( self, initial_wallet: float, initial_storage: Dict[int, int], n_steps: int, n_products: int, profiles: List[ManufacturingProfile], max_storage: Optional[int], ): super().__init__( initial_wallet=initial_wallet, initial_storage=initial_storage, n_steps=n_steps, n_products=n_products, profiles=profiles, max_storage=max_storage, ) self._wallet = np.ones(n_steps) * initial_wallet self._loans = np.zeros(n_steps) self._storage = np.repeat( self._as_array(initial_storage).reshape((n_products, 1)), n_steps, axis=1 ) self._total_storage = self._storage.sum(axis=0) factory = Factory( initial_storage=initial_storage, initial_wallet=initial_wallet, profiles=profiles, max_storage=max_storage, ) self._profiles = factory.profiles self._n_lines = factory.n_lines self._line_schedules = ( np.ones(shape=(self._n_lines, self._n_steps)) * NO_PRODUCTION ) self._has_jobs = np.zeros(shape=(self._n_lines, self._n_steps), dtype=bool) self._fixed_before = 0 self._bookmarks: List[_FullBookmark] = [] self._active_bookmark: Optional[_FullBookmark] = None def init(self, *args, **kwargs): self.__init__(*args, **kwargs) @property def fixed_before(self): return self._fixed_before @property def n_lines(self): return self._n_lines @property def final_balance(self) -> float: return self._wallet[-1] - self._loans[-1] def wallet_to(self, t: int) -> np.array: return self._wallet[: t + 1] def storage_to(self, t: int) -> np.array: return self._storage[:, : t + 1] def line_schedules_to(self, t: int) -> np.array: return self._line_schedules[:, : t + 1] def loans_to(self, t: int) -> np.array: return self._loans[: t + 1] def add_loan(self, total: float, t: int) -> bool: if t < self._fixed_before: raise ValueError( f"Cannot run operations in the past (t={t}, fixed before {self._fixed_before})" ) self._loans[t:] += total return True def pay(self, payment: float, t: int, ignore_money_shortage: bool = True) -> bool: # @todo add minimum balance if t < self._fixed_before: raise ValueError( f"Cannot run operations in the past (t={t}, fixed before {self._fixed_before})" ) b = self._wallet[t:] b -= payment if b.min() < 0: b += payment return False return True def transport_to( self, product: int, quantity: int, t: int, ignore_inventory_shortage: bool = True, ignore_space_shortage: bool = True, ) -> bool: # @todo add minimum storage if t < self._fixed_before: raise ValueError( f"Cannot run operations in the past (t={t}, fixed before {self._fixed_before})" ) s, total = self._storage[product, t:].view(), self._total_storage[t:] s += quantity total += quantity if s.min() < 0 or total.max() > self.max_storage: s -= quantity total -= quantity return False return True def buy( self, product: int, quantity: int, price: int, t: int, ignore_money_shortage: bool = True, ignore_space_shortage: bool = True, ) -> bool: if t < self._fixed_before: raise ValueError( f"Cannot run operations in the past (t={t}, fixed before {self._fixed_before})" ) s, total = self._storage[product, t:].view(), self._total_storage[t:] s += quantity total += quantity b = self._wallet[t:] b -= price if total.max() > self.max_storage or b.min() < 0: s -= quantity total -= quantity b += price return False return True def sell( self, product: int, quantity: int, price: int, t: int, ignore_money_shortage: bool = True, ignore_inventory_shortage: bool = True, ) -> bool: if t < self._fixed_before: raise ValueError( f"Cannot run operations in the past (t={t}, fixed before {self._fixed_before})" ) s, total = self._storage[product, t:].view(), self._total_storage[t:] s -= quantity total -= quantity b = self._wallet[t:] b += price if s.min() < 0: s += quantity total += quantity b -= price return False return True def schedule( self, job: Job, ignore_inventory_shortage=True, ignore_money_shortage=True, ignore_space_shortage=True, override=True, ) -> bool: t, job_override = job.time, job.override if t < self._fixed_before: raise ValueError( f"Cannot run operations in the past (t={t}, fixed before {self._fixed_before})" ) if job_override: raise NotImplementedError( f"{self.__class__.__name__} does not support scheduling jobs with overriding" ) # job_line = job.line # only useful for stop/pause/resume that are not supported profile = self._profiles[job.profile] inputs, outputs, length, cost = ( profile.process.inputs, profile.process.outputs, profile.n_steps, profile.cost, ) line = profile.line # confirm that there is no other jobs already scheduled at this exact time: if self._has_jobs[line, t]: if override: raise NotImplementedError( f"{self.__class__.__name__} does not support scheduling more than a single " f"job at any time-step/line" ) return False # confirm that the line is not busy. If it was busy, and we are not overriding, fail. if not job_override and np.any( self._line_schedules[line, t : t + length] != NO_PRODUCTION ): return False # confirm that there is enough money to start production if (not ignore_money_shortage) and np.any(self._wallet[t:] < cost): return False # bookmark to be able to rollback at any error if job.action == "run": with transaction(self) as bookmark: if not self.pay(cost, t): self.rollback(bookmark) return False self._line_schedules[line, t : t + length] = profile.process.id for i in inputs: it = int(math.floor(i.step * length) + t) p, q = i.product, i.quantity if (not ignore_inventory_shortage) and np.any( self._storage[p, it:] < q ): self.rollback(bookmark) return False s, total = self._storage[p, it:].view(), self._total_storage[it:] s -= q total -= q for o in outputs: ot = int(math.ceil(o.step * length) + t) p, q = o.product, o.quantity if (not ignore_space_shortage) and np.any( self._total_storage[ot:] + q > self.max_storage ): self.rollback(bookmark) return False s, total = self._storage[p, ot:].view(), self._total_storage[ot:] s += q total += q return True raise NotImplementedError( f"{self.__class__.__name__} does not support scheduling {job.action} jobs" ) def fix_before(self, t: int) -> bool: self._fixed_before = t return True def delete_bookmark(self, bookmark_id: int) -> bool: if self._active_bookmark is None or self._active_bookmark.id != bookmark_id: raise ValueError(f"there is no active bookmark to delete") self._bookmarks = self._bookmarks[:-1] self._active_bookmark = ( self._bookmarks[-1] if len(self._bookmarks) > 0 else None ) return True def bookmark(self) -> int: bookmark = _FullBookmark( id=len(self._bookmarks), wallet=self._wallet.copy(), loans=self._loans.copy(), storage=self._storage.copy(), line_schedules=self._line_schedules.copy(), has_jobs=self._has_jobs.copy(), ) self._bookmarks.append(bookmark) self._active_bookmark = bookmark return bookmark.id def rollback(self, bookmark_id: int) -> bool: if self._active_bookmark is None or self._active_bookmark.id != bookmark_id: raise ValueError(f"there is no active bookmark to rollback") b = self._active_bookmark self._wallet, self._loans, self._storage = b.wallet, b.loans, b.storage self._line_schedules, self._has_jobs = b.line_schedules, b.has_jobs self._total_storage = self._storage.sum(axis=0) return True def set_state( self, t: int, storage: np.array, wallet: float, loans: float, line_schedules: np.array, ) -> None: self._storage[:, t:] += storage.reshape(self._n_products, 1) - self._storage[ :, t ].reshape(self._n_products, 1) self._wallet[t:] += wallet - self._wallet[t] self._loans[t:] += loans - self._loans[t] self._line_schedules[:, t] = line_schedules # @todo enable this again to confirm that simulation is correct. may be I set_state before the job is run on the simulator # expected_schedules = self._line_schedules[:, t] # for i in range(self.n_lines): # expected, actual = expected_schedules[i], line_schedules[i] # if expected == actual: # continue # if expected == NO_PRODUCTION: # raise ValueError(f'Expected no production at time {t} on line {i} but actually process ' # f'{actual} is running') # if expected != actual and actual != NO_PRODUCTION: # raise ValueError(f'Expected process {expected} at time {t} on line {i} but actually process ' # f'{actual} is running') # self._line_schedules[i, t] = actual self.fix_before(t) class Java: implements = ["jnegmas.apps.scml.simulators.FactorySimulator"] @contextmanager def transaction(simulator): """Runs the simulated actions then confirms them if they are not rolled back""" _bookmark = simulator.bookmark() yield _bookmark simulator.delete_bookmark(_bookmark) @contextmanager def temporary_transaction(simulator): """Runs the simulated actions then rolls them back""" _bookmark = simulator.bookmark() yield _bookmark simulator.rollback(_bookmark) simulator.delete_bookmark(_bookmark) class _ShadowFactorySimulator: """An FactorySimulator As seen by JNegMAS. This is an object that is not visible to python code. It is not directly called from python ever. It is only called from a corresponding Java object to represent an internal python object. Because of he way py4j works, we cannot just use dunders to implement this kind of object in general. We will have to implement each such class independently. This kind of classes will always have an internal Java class implementing a Java interface in Jnegmas that starts with Py. """ def __init__(self, simulator: FactorySimulator): self.shadow = simulator def maxStorage(self) -> int: return to_java(self.shadow.max_storage) def nSteps(self) -> int: return to_java(self.shadow.n_steps) def initialWallet(self) -> float: return to_java(self.shadow.initial_wallet) def initialStorage(self) -> List[int]: return to_java(self.shadow.initial_storage.tolist()) def nLines(self) -> int: return to_java(self.shadow.n_lines) def finalBalance(self) -> float: return to_java(self.shadow.final_balance) def walletTo(self, t: int) -> List[float]: return to_java(self.shadow.wallet_to(t).tolist()) def walletAt(self, t: int) -> float: return to_java(self.shadow.wallet_at(t)) def storageTo(self, t: int) -> List[int]: return to_java(self.shadow.storage_to(t).tolinst()) def storageAt(self, t: int) -> int: return to_java(self.shadow.storage_at(t)) def line_schedules_to(self, t: int) -> List[List[int]]: return to_java(self.shadow.line_schedules_to(t).tolist()) def line_schedules_at(self, t: int) -> List[int]: return to_java(self.shadow.line_schedules_at(t).tolist()) def totalStorageTo(self, t: int) -> List[int]: return to_java(self.shadow.total_storage_to(t).tolist()) def totalStorageAt(self, t: int) -> int: return to_java(self.shadow.total_storage_at(t)) def reservedStorageTo(self, t: int) -> List[int]: return to_java(self.shadow.reserved_storage_to(t).tolist()) def reservedStorageAt(self, t: int) -> int: return to_java(self.shadow.reserved_storage_at(t)) def availableStorageTo(self, t: int) -> List[int]: return to_java(self.shadow.available_storage_to(t).tolist()) def availableStorageAt(self, t: int) -> int: return to_java(self.shadow.available_storage_at(t)) def loansTo(self, t: int) -> List[float]: return to_java(self.shadow.loans_to(t).tolist()) def loansAt(self, t: int) -> float: return to_java(self.shadow.loans_at(t)) def balanceTo(self, t: int) -> List[float]: return to_java(self.shadow.balance_to(t).tolist()) def balanceAt(self, t: int) -> float: return to_java(self.shadow.balance_at(t)) def fixedBefore(self) -> int: return to_java(self.shadow.fixed_before) def setState( self, t: int, storage: List[int], wallet: float, loans: float, lineSchedules: List[int], ) -> None: self.shadow.set_state( t, storage=storage, wallet=wallet, loans=loans, line_schedules=lineSchedules ) def addLoan(self, total: float, t: int) -> bool: return self.shadow.add_loan(total=total, t=t) def receive(self, payment, t): return self.shadow.receive(payment, t) def pay(self, payment, t, ignoreMoneyShortage): return self.shadow.pay(payment, t, ignoreMoneyShortage) def transportTo( self, product, quantity, t, ignoreInventoryShortage, ignoreSpaceShortage ): return self.shadow.transport_to( product, quantity, t, ignoreInventoryShortage, ignoreSpaceShortage ) def buy( self, product, quantity, price, t, ignoreMoneyShortage, ignoreSpaceShortage ): return self.shadow.buy( product, quantity, price, t, ignoreMoneyShortage, ignoreSpaceShortage ) def sell( self, product, quantity, price, t, ignoreMoneyShortage, ignoreInventoryShortage ): return self.shadow.sell( product, quantity, price, t, ignoreMoneyShortage, ignoreInventoryShortage ) def schedule( self, job, ignoreInventoryShortage, ignoreMoneyShortage, ignoreSpaceShortage, override, ): return self.shadow.schedule( job, ignoreInventoryShortage, ignoreMoneyShortage, ignoreSpaceShortage, override, ) def reserve(self, product, quantity, t): return self.reserve(product, quantity, t) def fixBefore(self, t): return self.shadow.fix_before(t) def bookmark(self): return self.shadow.bookmark() def rollback(self, bookmarkId): return self.shadow.rollback(bookmarkId) def deleteBookmark(self, bookmarkId): return self.shadow.delete_bookmark(bookmarkId) def to_java(self): return to_dict(self.shadow) class Java: implements = ["jengmas.apps.scml.simulators.FactorySimulator"] PK!negmas/apps/scml/utils.pyimport copy import itertools import math import sys from os import PathLike from random import randint, random, shuffle import numpy as np from negmas import Agent from negmas.apps.scml import ( Product, MiningProfile, ReactiveMiner, ScheduleDrivenConsumer, InputOutput, Process, ManufacturingProfile, Factory, ConsumptionProfile, ) from negmas.helpers import get_class, instantiate, unique_name, get_full_type_name from negmas.java import to_dict from negmas.tournaments import WorldRunResults, TournamentResults, tournament from negmas.situated import Entity from .factory_managers import GreedyFactoryManager from .world import SCMLWorld if True: from typing import ( Tuple, Union, Type, Iterable, Sequence, Optional, Callable, Any, Dict, List, ) from .factory_managers import FactoryManager __all__ = [ "anac2019_world", "anac2019_tournament", "anac2019_collusion", "anac2019_std", "balance_calculator", ] def integer_cut(n: int, l: int, l_m: Union[int, List[int]]) -> List[int]: """ Generates l random integers that sum to n where each of them is at least l_m Args: n: total l: number of levels l_m: minimum per level Returns: """ if not isinstance(l_m, Iterable): l_m = [l_m] * l sizes = np.asarray(l_m) if n < sizes.sum(): raise ValueError( f"Cannot generate {l} numbers summing to {n} with a minimum summing to {sizes.sum()}" ) while sizes.sum() < n: sizes[randint(0, l - 1)] += 1 return list(sizes.tolist()) def _realin(rng: Union[Tuple[float, float], float]) -> float: """ Selects a random number within a range if given or the input if it was a float Args: rng: Range or single value Returns: the real within the given range """ if isinstance(rng, float): return rng if abs(rng[1] - rng[0]) < 1e-8: return rng[0] return rng[0] + random() * (rng[1] - rng[0]) def _intin(rng: Union[Tuple[int, int], int]) -> int: """ Selects a random number within a range if given or the input if it was an int Args: rng: Range or single value Returns: the int within the given range """ if isinstance(rng, int): return rng if rng[0] == rng[1]: return rng[0] return randint(rng[0], rng[1]) def anac2019_config_generator( n_competitors: int, n_agents_per_competitor: int, agent_names_reveal_type: bool = False, *, consumption_schedule: Tuple[int, int] = (0, 5), consumption_horizon: Tuple[int, int] = (10, 15), n_retrials: Union[int, Tuple[int, int]] = 5, negotiator_type: str = "negmas.sao.AspirationNegotiator", n_steps: Union[int, Tuple[int, int]] = (50, 100), n_miners: Union[int, Tuple[int, int]] = 5, n_consumers: Union[int, Tuple[int, int]] = 5, profile_cost: Tuple[float, float] = (1, 4), profile_time: Union[int, Tuple[int, int]] = 1, n_intermediate: Tuple[int, int] = (1, 4), min_n_factories: int = 5, n_default_managers: Tuple[int, int] = (1, 4), n_lines: int = 10, compact: bool = True, **kwargs, ) -> Dict[str, Any]: if isinstance(n_intermediate, Iterable): n_intermediate = list(n_intermediate) else: n_intermediate = [n_intermediate, n_intermediate] n_steps = _intin(n_steps) miner_type = ReactiveMiner consumer_type = ScheduleDrivenConsumer consumer_kwargs = { "negotiator_type": negotiator_type, "consumption_horizon": _intin(consumption_horizon), } miner_kwargs = {"negotiator_type": negotiator_type, "n_retrials": n_retrials} if negotiator_type is not None: for args in (consumer_kwargs, miner_kwargs): if "negotiator_type" not in args.keys(): args["negotiator_type"] = negotiator_type n_intermediate_levels = randint(*n_intermediate) products = [ Product(id=0, name="p0", catalog_price=1.0, production_level=0, expires_in=0) ] processes = [] miners = [ instantiate( miner_type, profiles={products[-1].id: MiningProfile()}, name=f"m_{i}", **miner_kwargs, ) for i in range(n_miners) ] factories = [] def _s(x): return x if x is not None else 0 if isinstance(profile_cost, tuple): historical_cost = (profile_cost[0] + profile_cost[1]) / 2.0 else: historical_cost = profile_cost historical_cost = (historical_cost * 0.85, historical_cost * 1.15) for level in range(n_intermediate_levels + 1): p = Process( name=f"p{level + 1}", inputs=[InputOutput(product=level, quantity=1, step=0.0)], production_level=level + 1, outputs=[InputOutput(product=level + 1, quantity=1, step=1.0)], historical_cost=_realin(historical_cost), id=level, ) new_product = Product( name=f"p{level + 1}", catalog_price=products[-1].catalog_price + p.historical_cost # keep this to the world to calculate _s(products[-1].catalog_price) + level + 1 , production_level=level + 1, id=level + 1, expires_in=0, ) processes.append(p) products.append(new_product) _DefaultFactoryManager = GreedyFactoryManager n_defaults = [] for level in range(n_intermediate_levels + 1): n_defaults.append(_intin(n_default_managers)) n_agents = n_agents_per_competitor * n_competitors n_a_list = integer_cut(n_agents, n_intermediate_levels + 1, 0) for i, n_a in enumerate(n_a_list): if n_a + n_defaults[i] < min_n_factories: n_defaults[i] += min_n_factories - (n_a + n_defaults[i]) n_f_list = [a + b for a, b in zip(n_defaults, n_a_list)] n_factories = sum(n_f_list) default_manager_params = { "negotiator_type": negotiator_type, "n_retrials": n_retrials, "sign_only_guaranteed_contracts": False, "use_consumer": True, "max_insurance_premium": float("inf"), } manager_types = [None] * n_factories manager_params = [None] * n_factories first_in_level = 0 for level in range(n_intermediate_levels + 1): n_d = n_defaults[level] n_f = n_f_list[level] assert ( n_d <= n_f ), f"Got {n_f} total factories at level {level} out of which {n_d} are default!!" for j in range(n_f): profiles = [] factory_time = _intin(profile_time) factory_cost = _realin(profile_cost) for k in range(n_lines): profiles.append( ManufacturingProfile( n_steps=factory_time, cost=factory_cost, initial_pause_cost=0, running_pause_cost=0, resumption_cost=0, cancellation_cost=0, line=k, process=processes[level], ) ) factory = Factory( id=f"f{level + 1}_{j}", max_storage=sys.maxsize, profiles=profiles, initial_storage={}, initial_wallet=1000.0, ) factories.append(factory) if j >= n_f - n_d: # default managers are last managers in the list manager_types[ first_in_level + j ] = "negmas.apps.scml.factory_managers.GreedyFactoryManager" params_ = default_manager_params.copy() if agent_names_reveal_type: params_["name"] = f"_df_{level + 1}_{j}" else: params_["name"] = None manager_params[first_in_level + j] = params_ first_in_level += n_f def create_schedule(): if isinstance(consumption_schedule, tuple) and len(consumption_schedule) == 2: return list( np.random.randint( consumption_schedule[0], consumption_schedule[1], n_steps ).tolist() ) return consumption_schedule consumers = [ instantiate( consumer_type, profiles={products[-1].id: ConsumptionProfile(schedule=create_schedule())}, name=f"c_{i}", **consumer_kwargs, ) for i in range(n_consumers) ] config = { "world_params": dict( name=unique_name("", add_time=True, rand_digits=4), time_limit=7200, neg_time_limit=120, neg_n_steps=20, neg_step_time_limit=10, negotiation_speed=21, default_signing_delay=1, transportation_delay=0, no_bank=True, breach_penalty_society=0.02, no_insurance=False, premium=0.1, premium_time_increment=0.1, premium_breach_increment=0.1, max_allowed_breach_level=None, breach_penalty_society_min=0.0, breach_penalty_victim=0.0, breach_move_max_product=True, initial_wallet_balances=1000.0, money_resolution=0.5, transfer_delay=0, start_negotiations_immediately=False, catalog_profit=0.15, financial_reports_period=10, default_price_for_products_without_one=1, compensation_fraction=0.5, n_steps=n_steps, compact=compact, **kwargs, ), "products": [to_dict(p, add_type_field=False, camel=False) for p in products], "processes": [to_dict(p, add_type_field=False, camel=False) for p in processes], "factories": [ { "profile": { "n_steps": f.profiles[0].n_steps, "cost": f.profiles[0].cost, "line": f.profiles[0].line, "process.id": f.profiles[0].process.id, }, "max_storage": sys.maxsize, "initial_wallet": 1000.0, "id": f.id, "n_lines": n_lines, } for f in factories ], "miners": [ dict( id=m.id, name=m.name, type=get_full_type_name(miner_type), args=miner_kwargs, profiles={ k: to_dict(v, add_type_field=False, camel=False) for k, v in m.profiles.items() }, ) for m in miners ], "consumers": [ dict( id=c.id, name=c.name, type=get_full_type_name(consumer_type), args=consumer_kwargs, profiles={ k: to_dict(v, add_type_field=False, camel=False) for k, v in c.profiles.items() }, ) for c in consumers ], "manager_types": [ get_full_type_name(_) if isinstance(_, FactoryManager) else _ for _ in manager_types ], "manager_params": manager_params, "n_factories_per_level": n_f_list, "agent_names_reveal_type": agent_names_reveal_type, "compact": compact, } config.update(kwargs) return config def anac2019_assigner( config: Dict[str, Any], max_n_worlds: int, n_agents_per_competitor: int = 1, competitors: Sequence[Type[Agent]] = (), params: Sequence[Dict[str, Any]] = (), ) -> List[Dict[str, Any]]: competitors = list( get_full_type_name(_) if not isinstance(_, str) and _ is not None else _ for _ in competitors ) n_competitors = len(competitors) params = ( list(params) if params is not None else [dict() for _ in range(n_competitors)] ) n_agents = n_agents_per_competitor * n_competitors agent_names_reveal_type = config.pop("agent_names_reveal_type", False) try: n_permutations = math.factorial(n_agents) except ArithmeticError: n_permutations = None manager_types = config["manager_types"] assignable_factories = [i for i, mtype in enumerate(manager_types) if mtype is None] agents = list(itertools.chain(*([competitors] * n_agents_per_competitor))) agent_params = list(itertools.chain(*([params] * n_agents_per_competitor))) configs = [] def _copy_config(c, indx): new_config = copy.deepcopy(c) new_config["world_params"]["name"] += f"{indx:05d}" for i, (a, p) in enumerate(permutation): new_config["manager_types"][assignable_factories[i]] = a new_config["manager_params"][assignable_factories[i]] = p return new_config if n_permutations is not None and ( max_n_worlds is None or n_permutations <= max_n_worlds ): k = 0 for permutation in itertools.permutations(zip(agents, agent_params)): assert len(permutation) == len(assignable_factories) configs.append(_copy_config(config, k)) k += 1 elif max_n_worlds is None: raise ValueError(f"Did not give max_n_worlds and cannot find n_permutations.") else: permutation = list(zip(agents, agent_params)) assert len(permutation) == len(assignable_factories) for k in range(max_n_worlds): shuffle(permutation) configs.append(_copy_config(config, k)) def shorten(long_name: str, d: Dict[str, Any]) -> str: if long_name.endswith("JavaFactoryManager"): long_name = d.get("java_class_name", long_name) name = ( long_name.split(".")[-1] .lower() .replace("factory_manager", "") .replace("manager", "") ) name = ( name.replace("factory", "") .replace("agent", "") .replace("miner", "m") .replace("consumer", "") ) if long_name.startswith("jnegmas"): name = f"j:{name}" return name if agent_names_reveal_type: for config in configs: nxt = 0 for i, (t, p, f) in enumerate( zip( config["manager_types"], config["manager_params"], config["factories"], ) ): if p.get("name", "").startswith("_df_"): continue p = p.copy() name_ = ( t.short_type_name if isinstance(t, Entity) else get_full_type_name(t) if not isinstance(t, str) else shorten(t, config["manager_params"][i]) ) p["name"] = f'{name_}@{f["id"][1:]}' config["manager_params"][i] = p nxt = nxt + 1 return configs def anac2019_world_generator(**kwargs): products = [Product(**p) for p in kwargs["products"]] processes = [Process(**p) for p in kwargs["processes"]] for process in processes: process.inputs = [InputOutput(**io) for io in process.inputs] process.outputs = [InputOutput(**io) for io in process.outputs] factories = [] for f in kwargs["factories"]: p = f["profile"] factories.append( Factory( initial_storage={}, initial_wallet=f["initial_wallet"], max_storage=f["max_storage"], id=f'{f["id"]}', profiles=[ ManufacturingProfile( n_steps=p["n_steps"], cost=p["cost"], line=p["line"], process=processes[p["process.id"]], cancellation_cost=0.0, initial_pause_cost=0.0, resumption_cost=0, running_pause_cost=0.0, ) for _ in range(f["n_lines"]) ], ) ) miners = [] for m in kwargs["miners"]: miner = instantiate( m["type"], **m["args"], name=m["name"], profiles={k: MiningProfile(**v) for k, v in m["profiles"].items()}, ) miner.id = m["id"] miners.append(miner) consumers = [] for c in kwargs["consumers"]: consumer = instantiate( c["type"], **c["args"], name=c["name"], profiles={k: ConsumptionProfile(**v) for k, v in c["profiles"].items()}, ) consumer.id = c["id"] consumers.append(consumer) kwargs.pop("n_factories_per_level", None) manager_types = kwargs.pop("manager_types", []) manager_params = kwargs.pop("manager_params", []) managers = [ instantiate(mt, **mp) for mt, mp in zip(manager_types, itertools.cycle(manager_params)) ] world = SCMLWorld( products=products, processes=processes, factories=factories, consumers=consumers, miners=miners, factory_managers=managers, **kwargs["world_params"], ) return world def anac2019_world( competitors: Sequence[Union[str, Type[FactoryManager]]] = (), params: Sequence[Dict[str, Any]] = (), randomize: bool = True, log_file_name: str = None, name: str = None, agent_names_reveal_type: bool = False, n_intermediate: Tuple[int, int] = (1, 4), n_miners=5, n_factories_per_level=11, n_agents_per_competitor=1, n_consumers=5, n_lines_per_factory=10, guaranteed_contracts=False, use_consumer=True, max_insurance_premium=100, n_retrials=5, negotiator_type: str = "negmas.sao.AspirationNegotiator", transportation_delay=0, default_signing_delay=0, max_storage=sys.maxsize, consumption_horizon=15, consumption=(3, 5), negotiation_speed=21, neg_time_limit=60 * 4, neg_n_steps=20, n_steps=100, time_limit=60 * 90, n_default_per_level: int = 5, compact: bool = False, ) -> SCMLWorld: """ Creates a world compatible with the ANAC 2019 competition. Note that Args: n_agents_per_competitor: Number of instantiations of each competing type. name: World name to use agent_names_reveal_type: If true, a snake_case version of the agent_type will prefix agent names randomize: If true, managers are assigned to factories randomly otherwise in the order they are giving (cycling). n_intermediate: n_default_per_level: competitors: A list of class names for the competitors params: A list of dictionaries giving parameters to pass to the competitors n_miners: number of miners of the single raw material n_factories_per_level: number of factories at every production level n_consumers: number of consumers of the final product n_steps: number of simulation steps n_lines_per_factory: number of lines in each factory negotiation_speed: The number of negotiation steps per simulation step. None means infinite default_signing_delay: The number of simulation between contract conclusion and signature neg_n_steps: The maximum number of steps of a single negotiation (that is double the number of rounds) neg_time_limit: The total time-limit of a single negotiation time_limit: The total time-limit of the simulation transportation_delay: The transportation delay n_retrials: The number of retrials the `Miner` and `GreedyFactoryManager` will try if negotiations fail max_insurance_premium: The maximum insurance premium accepted by `GreedyFactoryManager` (-1 to disable) use_consumer: If true, the `GreedyFactoryManager` will use an internal consumer for buying its needs guaranteed_contracts: If true, the `GreedyFactoryManager` will only sign contracts that it can guaratnee not to break. consumption_horizon: The number of steps for which `Consumer` publishes `CFP` s consumption: The consumption schedule will be sampled from a uniform distribution with these limits inclusive log_file_name: File name to store the logs negotiator_type: The negotiation factory used to create all negotiators max_storage: maximum storage capacity for all factory managers If None then it is unlimited compact: If True, then compact logs will be created to reduce memory footprint Returns: SCMLWorld ready to run Remarks: - Every production level n has one process only that takes n steps to complete """ competitors = list(competitors) params = ( list(params) if params is not None else [dict() for _ in range(len(competitors))] ) if n_factories_per_level == n_default_per_level and len(competitors) > 0: raise ValueError( f"All factories in all levels are occupied by the default factory manager. Either decrease" f" n_default_per_level ({n_default_per_level}) or increase n_factories_per_level " f" ({n_factories_per_level})" ) if isinstance(n_intermediate, Iterable): n_intermediate = list(n_intermediate) else: n_intermediate = [n_intermediate, n_intermediate] max_insurance_premium = None if max_insurance_premium < 0 else max_insurance_premium n_competitors = len(competitors) n_intermediate_levels_min = ( int(math.ceil(n_competitors / (n_factories_per_level - n_default_per_level))) - 1 ) if n_intermediate_levels_min > n_intermediate[1]: raise ValueError( f"Need {n_intermediate_levels_min} intermediate levels to run {n_competitors} competitors" ) n_intermediate[0] = max(n_intermediate_levels_min, n_intermediate[0]) competitors = [get_class(c) if isinstance(c, str) else c for c in competitors] if len(competitors) < 1: competitors.append(GreedyFactoryManager) params.append(dict()) world = SCMLWorld.chain_world( log_file_name=log_file_name, n_steps=n_steps, agent_names_reveal_type=agent_names_reveal_type, negotiation_speed=negotiation_speed, n_intermediate_levels=randint(*n_intermediate), n_miners=n_miners, n_consumers=n_consumers, n_factories_per_level=n_factories_per_level, consumption=consumption, consumer_kwargs={ "negotiator_type": negotiator_type, "consumption_horizon": consumption_horizon, }, miner_kwargs={"negotiator_type": negotiator_type, "n_retrials": n_retrials}, default_manager_params={ "negotiator_type": negotiator_type, "n_retrials": n_retrials, "sign_only_guaranteed_contracts": guaranteed_contracts, "use_consumer": use_consumer, "max_insurance_premium": max_insurance_premium, }, transportation_delay=transportation_delay, time_limit=time_limit, neg_time_limit=neg_time_limit, neg_n_steps=neg_n_steps, default_signing_delay=default_signing_delay, n_lines_per_factory=n_lines_per_factory, max_storage=max_storage, manager_types=competitors, manager_params=params, n_default_per_level=n_default_per_level, randomize=randomize, name=name, compact=compact, ) return world def balance_calculator(world: SCMLWorld, dry_run: bool) -> WorldRunResults: """A scoring function that scores factory managers' performance by the final balance only ignoring whatever still in their inventory. Args: world: The world which is assumed to be run up to the point at which the scores are to be calculated. dry_run: A boolean specifying whether this is a dry_run. For dry runs, only names and types are expected in the returned `WorldRunResults` Returns: WorldRunResults giving the names, scores, and types of factory managers. """ result = WorldRunResults(world_name=world.name, log_file_name=world.log_file_name) initial_balances = [] for manager in world.factory_managers: if "_df_" in manager.id: continue initial_balances.append(world.a2f[manager.id].initial_balance) normalize = all(_ != 0 for _ in initial_balances) for manager in world.factory_managers: if "_df_" in manager.id: continue factory = world.a2f[manager.id] result.names.append(manager.name) result.types.append(manager.type_name) if dry_run: result.scores.append(None) if normalize: result.scores.append( (factory.balance - factory.initial_balance) / factory.initial_balance ) else: result.scores.append(factory.balance - factory.initial_balance) return result def anac2019_tournament( competitors: Sequence[Union[str, Type[FactoryManager]]], agent_names_reveal_type=False, n_configs: int = 5, max_worlds_per_config: int = 1000, n_runs_per_world: int = 5, n_agents_per_competitor: int = 5, tournament_path: str = "./logs/tournaments", total_timeout: Optional[int] = 7200, parallelism="parallel", scheduler_ip: Optional[str] = None, scheduler_port: Optional[str] = None, tournament_progress_callback: Callable[[Optional[WorldRunResults]], None] = None, world_progress_callback: Callable[[Optional[SCMLWorld]], None] = None, name: str = None, verbose: bool = False, configs_only=False, compact=False, **kwargs, ) -> Union[TournamentResults, PathLike]: """ The function used to run ANAC 2019 SCML tournament (collusion track). Args: name: Tournament name competitors: A list of class names for the competitors agent_names_reveal_type: If true then the type of an agent should be readable in its name (most likely at its beginning). n_configs: The number of different world configs (up to competitor assignment) to be generated. max_worlds_per_config: The maximum number of worlds to run per config. If None, then all possible assignments of competitors within each config will be tried (all permutations). n_runs_per_world: Number of runs per world. All of these world runs will have identical competitor assignment and identical world configuration. n_agents_per_competitor: Number of agents per competitor total_timeout: Total timeout for the complete process tournament_path: Path at which to store all results. A scores.csv file will keep the scores and logs folder will keep detailed logs parallelism: Type of parallelism. Can be 'serial' for serial, 'parallel' for parallel and 'distributed' for distributed scheduler_port: Port of the dask scheduler if parallelism is dask, dist, or distributed scheduler_ip: IP Address of the dask scheduler if parallelism is dask, dist, or distributed world_progress_callback: A function to be called after everystep of every world run (only allowed for serial evaluation and should be used with cautious). tournament_progress_callback: A function to be called with `WorldRunResults` after each world finished processing verbose: Verbosity configs_only: If true, a config file for each compact: If true, effort will be made to reduce memory footprint including disableing most logs kwargs: Arguments to pass to the `world_generator` function Returns: `TournamentResults` The results of the tournament or a `PathLike` giving the location where configs were saved Remarks: Default parameters will be used in the league with the exception of `parallelism` which may use distributed processing """ return anac2019_collusion( competitors=competitors, agent_names_reveal_type=agent_names_reveal_type, n_configs=n_configs, max_worlds_per_config=max_worlds_per_config, n_runs_per_world=n_runs_per_world, n_agents_per_competitor=n_agents_per_competitor, tournament_path=tournament_path, total_timeout=total_timeout, parallelism=parallelism, scheduler_ip=scheduler_ip, scheduler_port=scheduler_port, tournament_progress_callback=tournament_progress_callback, world_progress_callback=world_progress_callback, name=name, verbose=verbose, compact=compact, configs_only=configs_only, **kwargs, ) def anac2019_std( competitors: Sequence[Union[str, Type[FactoryManager]]], agent_names_reveal_type=False, n_configs: int = 5, max_worlds_per_config: int = 1000, n_runs_per_world: int = 5, tournament_path: str = "./logs/tournaments", total_timeout: Optional[int] = 7200, parallelism="parallel", scheduler_ip: Optional[str] = None, scheduler_port: Optional[str] = None, tournament_progress_callback: Callable[[Optional[WorldRunResults]], None] = None, world_progress_callback: Callable[[Optional[SCMLWorld]], None] = None, name: str = None, verbose: bool = False, configs_only=False, compact=False, **kwargs, ) -> Union[TournamentResults, PathLike]: """ The function used to run ANAC 2019 SCML tournament (standard track). Args: name: Tournament name competitors: A list of class names for the competitors agent_names_reveal_type: If true then the type of an agent should be readable in its name (most likely at its beginning). n_configs: The number of different world configs (up to competitor assignment) to be generated. max_worlds_per_config: The maximum number of worlds to run per config. If None, then all possible assignments of competitors within each config will be tried (all permutations). n_runs_per_world: Number of runs per world. All of these world runs will have identical competitor assignment and identical world configuration. total_timeout: Total timeout for the complete process tournament_path: Path at which to store all results. A scores.csv file will keep the scores and logs folder will keep detailed logs parallelism: Type of parallelism. Can be 'serial' for serial, 'parallel' for parallel and 'distributed' for distributed scheduler_port: Port of the dask scheduler if parallelism is dask, dist, or distributed scheduler_ip: IP Address of the dask scheduler if parallelism is dask, dist, or distributed world_progress_callback: A function to be called after everystep of every world run (only allowed for serial evaluation and should be used with cautious). tournament_progress_callback: A function to be called with `WorldRunResults` after each world finished processing verbose: Verbosity configs_only: If true, a config file for each compact: If true, compact logs will be created and effort will be made to reduce the memory footprint kwargs: Arguments to pass to the `world_generator` function Returns: `TournamentResults` The results of the tournament or a `PathLike` giving the location where configs were saved Remarks: Default parameters will be used in the league with the exception of `parallelism` which may use distributed processing """ return tournament( competitors=competitors, agent_names_reveal_type=agent_names_reveal_type, n_configs=n_configs, n_runs_per_world=n_runs_per_world, max_worlds_per_config=max_worlds_per_config, tournament_path=tournament_path, total_timeout=total_timeout, parallelism=parallelism, scheduler_ip=scheduler_ip, scheduler_port=scheduler_port, tournament_progress_callback=tournament_progress_callback, world_progress_callback=world_progress_callback, name=name, verbose=verbose, configs_only=configs_only, n_agents_per_competitor=1, world_generator=anac2019_world_generator, config_generator=anac2019_config_generator, config_assigner=anac2019_assigner, score_calculator=balance_calculator, compact=compact, **kwargs, ) def anac2019_collusion( competitors: Sequence[Union[str, Type[FactoryManager]]], agent_names_reveal_type=False, n_configs: int = 5, max_worlds_per_config: int = 1000, n_runs_per_world: int = 5, n_agents_per_competitor: int = 5, tournament_path: str = "./logs/tournaments", total_timeout: Optional[int] = 7200, parallelism="parallel", scheduler_ip: Optional[str] = None, scheduler_port: Optional[str] = None, tournament_progress_callback: Callable[[Optional[WorldRunResults]], None] = None, world_progress_callback: Callable[[Optional[SCMLWorld]], None] = None, name: str = None, verbose: bool = False, configs_only=False, compact=False, **kwargs, ) -> Union[TournamentResults, PathLike]: """ The function used to run ANAC 2019 SCML tournament (collusion track). Args: name: Tournament name competitors: A list of class names for the competitors agent_names_reveal_type: If true then the type of an agent should be readable in its name (most likely at its beginning). n_configs: The number of different world configs (up to competitor assignment) to be generated. max_worlds_per_config: The maximum number of worlds to run per config. If None, then all possible assignments of competitors within each config will be tried (all permutations). n_runs_per_world: Number of runs per world. All of these world runs will have identical competitor assignment and identical world configuration. n_agents_per_competitor: Number of agents per competitor total_timeout: Total timeout for the complete process tournament_path: Path at which to store all results. A scores.csv file will keep the scores and logs folder will keep detailed logs parallelism: Type of parallelism. Can be 'serial' for serial, 'parallel' for parallel and 'distributed' for distributed scheduler_port: Port of the dask scheduler if parallelism is dask, dist, or distributed scheduler_ip: IP Address of the dask scheduler if parallelism is dask, dist, or distributed world_progress_callback: A function to be called after everystep of every world run (only allowed for serial evaluation and should be used with cautious). tournament_progress_callback: A function to be called with `WorldRunResults` after each world finished processing verbose: Verbosity configs_only: If true, a config file for each compact: If true, compact logs will be created and effort will be made to reduce the memory footprint kwargs: Arguments to pass to the `world_generator` function Returns: `TournamentResults` The results of the tournament or a `PathLike` giving the location where configs were saved Remarks: Default parameters will be used in the league with the exception of `parallelism` which may use distributed processing """ return tournament( competitors=competitors, agent_names_reveal_type=agent_names_reveal_type, n_configs=n_configs, n_runs_per_world=n_runs_per_world, max_worlds_per_config=max_worlds_per_config, tournament_path=tournament_path, total_timeout=total_timeout, n_agents_per_competitor=n_agents_per_competitor, parallelism=parallelism, scheduler_ip=scheduler_ip, scheduler_port=scheduler_port, tournament_progress_callback=tournament_progress_callback, world_progress_callback=world_progress_callback, name=name, verbose=verbose, configs_only=configs_only, world_generator=anac2019_world_generator, config_generator=anac2019_config_generator, config_assigner=anac2019_assigner, score_calculator=balance_calculator, compact=compact, **kwargs, ) PK!Lx؆؆negmas/apps/scml/world.pyimport copy import itertools import logging import math import sys import uuid from collections import defaultdict from random import shuffle, random, randint, sample, choices from typing import ( Optional, Callable, Type, Sequence, Dict, Tuple, Iterable, Any, Union, Set, Collection, List, ) import numpy as np import yaml from negmas import AgentMechanismInterface from negmas.events import Event, EventSource from negmas.helpers import instantiate, unique_name from negmas.outcomes import Issue from negmas.situated import World, Breach, Action, BreachProcessing, Contract, Agent from .agent import SCMLAgent from .bank import DefaultBank from .common import * from .consumers import ScheduleDrivenConsumer, ConsumptionProfile, Consumer from .factory_managers import GreedyFactoryManager, FactoryManager from .insurance import DefaultInsuranceCompany from .miners import ReactiveMiner, MiningProfile, Miner CONSUMER_SIMULATION_PRIORITY = 1 MANAGER_SIMULATION_PRIORITY = 2 MINER_SIMULATION_PRIORITY = 3 __all__ = ["SCMLWorld", "Factory"] def _realin(rng: Union[Tuple[float, float], float]) -> float: """ Selects a random number within a range if given or the input if it was a float Args: rng: Range or single value Returns: the real within the given range """ if isinstance(rng, float): return rng if abs(rng[1] - rng[0]) < 1e-8: return rng[0] return rng[0] + random() * (rng[1] - rng[0]) def _intin(rng: Union[Tuple[int, int], int]) -> int: """ Selects a random number within a range if given or the input if it was an int Args: rng: Range or single value Returns: the int within the given range """ if isinstance(rng, int): return rng if rng[0] == rng[1]: return rng[0] return randint(rng[0], rng[1]) class SCMLWorld(World): """The `World` class running a simulation of supply chain management.""" def __init__( self, products: Collection[Product], processes: Collection[Process], factories: List[Factory], consumers: List[Consumer], miners: List[Miner], factory_managers: Optional[List[FactoryManager]] = None # timing parameters , n_steps=100, time_limit=60 * 90, neg_n_steps=20, neg_time_limit=2 * 60, neg_step_time_limit=60, negotiation_speed=21 # bank parameters , no_bank=False, minimum_balance=0, interest_rate=0.1, interest_max=0.3, installment_interest=0.2, interest_time_increment=0.02, balance_at_max_interest=None # loan parameters , loan_installments=1 # insurance company parameters , no_insurance=False, premium=0.1, premium_time_increment=0.1, premium_breach_increment=0.1 # breach processing , max_allowed_breach_level=None, breach_processing=BreachProcessing.VICTIM_THEN_PERPETRATOR, breach_penalty_society=0.1, breach_penalty_society_min=0.0, breach_penalty_victim=0.0, breach_move_max_product=True # simulation parameters , initial_wallet_balances: Optional[int] = None, money_resolution=0.5, default_signing_delay=0, transportation_delay: int = 0, transfer_delay: int = 0, start_negotiations_immediately=False, catalog_profit=0.15, avg_process_cost_is_public=True, catalog_prices_are_public=True, strip_annotations=True, financial_reports_period=10 # bankruptcy parameters , default_price_for_products_without_one=1, compensation_fraction=0.5 # general parameters , log_file_name="", log_to_screen: bool = False, log_file_level=logging.DEBUG, log_screen_level=logging.ERROR, save_mechanism_state_in_contract=False, compact=False, save_signed_contracts: bool = True, save_cancelled_contracts: bool = True, save_negotiations: bool = True, save_resolved_breaches: bool = True, save_unresolved_breaches: bool = True, name: str = None, ): """ Args: products: processes: factories: consumers: miners: factory_managers: initial_wallet_balances: If not none, all factories will be forced to have this initial wallet balance n_steps: time_limit: negotiation_speed: neg_n_steps: neg_time_limit: minimum_balance: interest_rate: interest_max: max_allowed_breach_level: catalog_profit: avg_process_cost_is_public: catalog_prices_are_public: breach_processing: breach_penalty_society: breach_penalty_society_min: breach_penalty_victim: breach_move_max_product: premium: money_resolution: premium_time_increment: premium_breach_increment: default_signing_delay: transportation_delay: loan_installments: strip_annotations: If true, annotations for all negotiations will be stripped from any information other than the following: partners, seller, buyer, cfp log_file_name: name: """ if compact: save_mechanism_state_in_contract = False log_file_level = logging.ERROR log_screen_level = logging.CRITICAL save_cancelled_contracts = ( save_resolved_breaches ) = save_negotiations = False self.compact = compact super().__init__( bulletin_board=None, n_steps=n_steps, time_limit=time_limit, negotiation_speed=negotiation_speed, neg_n_steps=neg_n_steps, neg_time_limit=neg_time_limit, breach_processing=breach_processing, log_file_name=log_file_name, awi_type="negmas.apps.scml.SCMLAWI", default_signing_delay=default_signing_delay, start_negotiations_immediately=start_negotiations_immediately, neg_step_time_limit=neg_step_time_limit, mechanisms={"negmas.sao.SAOMechanism": {}}, log_to_screen=log_to_screen, log_file_level=log_file_level, log_screen_level=log_screen_level, name=name, save_signed_contracts=save_signed_contracts, save_negotiations=save_negotiations, save_cancelled_contracts=save_cancelled_contracts, save_resolved_breaches=save_resolved_breaches, save_unresolved_breaches=save_unresolved_breaches, ) self.compensation_fraction = compensation_fraction self.save_mechanism_state_in_contract = save_mechanism_state_in_contract self.default_price_for_products_without_one = ( default_price_for_products_without_one ) self.agents: Dict[str, SCMLAgent] = {} # just to help static type checkers if balance_at_max_interest is None: balance_at_max_interest = initial_wallet_balances self.strip_annotations = strip_annotations self.contracts: Dict[int, Set[Contract]] = defaultdict(set) self.bulletin_board.register_listener(event_type="new_record", listener=self) self.bulletin_board.register_listener( event_type="will_remove_record", listener=self ) self.bulletin_board.add_section("cfps") self.bulletin_board.add_section("products") self.bulletin_board.add_section("processes") self.bulletin_board.add_section("bankruptcy") self.bulletin_board.add_section("reports_time") self.bulletin_board.add_section("reports_agent") self.minimum_balance = minimum_balance self.money_resolution = money_resolution self.transportation_delay = transportation_delay self.breach_penalty_society = breach_penalty_society self.breach_move_max_product = breach_move_max_product self.breach_penalty_society_min = breach_penalty_society_min self.penalties = 0.0 self.financial_reports_period = financial_reports_period self.max_allowed_breach_level = max_allowed_breach_level self.catalog_profit = catalog_profit self.loan_installments = loan_installments self.breach_penalty_victim = breach_penalty_victim self.bulletin_board.record( section="settings", key="breach_penalty_society", value=breach_penalty_society, ) self.bulletin_board.record( section="settings", key="breach_penalty_victim", value=breach_penalty_victim ) self.bulletin_board.record( section="settings", key="immediate_negotiations", value=start_negotiations_immediately, ) self.bulletin_board.record( section="settings", key="negotiation_speed_multiple", value=negotiation_speed, ) self.bulletin_board.record( section="settings", key="negotiation_n_steps", value=neg_n_steps ) self.bulletin_board.record( section="settings", key="negotiation_step_time_limit", value=neg_step_time_limit, ) self.bulletin_board.record( section="settings", key="negotiation_time_limit", value=neg_time_limit ) self.bulletin_board.record( section="settings", key="transportation_delay", value=transportation_delay ) self.bulletin_board.record( section="settings", key="default_signing_delay", value=default_signing_delay ) self.bulletin_board.record( section="settings", key="breach_penalty_society_min", value=breach_penalty_society_min, ) self.bulletin_board.record( section="settings", key="financial_reports_period", value=financial_reports_period, ) self.bulletin_board.record( section="settings", key="transfer_delay", value=transfer_delay ) self.bulletin_board.record(section="settings", key="n_steps", value=n_steps) self.bulletin_board.record( section="settings", key="time_limit", value=time_limit ) self.avg_process_cost_is_public = avg_process_cost_is_public self.catalog_prices_are_public = catalog_prices_are_public self.initial_wallet_balances = initial_wallet_balances self.products: List[Product] = [] self.processes: List[Process] = [] self.factory_managers: List[FactoryManager] = [] self.miners: List[Miner] = [] self.consumers: List[Consumer] = [] self.set_products(products) self.set_processes(processes) self.factories = factories self.set_miners(miners) self.set_consumers(consumers) self.set_factory_managers(factory_managers) self._report_receivers: Dict[str, Set[SCMLAgent]] = defaultdict(set) # self._remove_processes_not_used_by_factories() # self._remove_products_not_used_by_processes() if catalog_prices_are_public or avg_process_cost_is_public: self._update_dynamic_product_process_info() if initial_wallet_balances is not None: for factory in self.factories: factory._wallet = initial_wallet_balances self.f2a: Dict[str, SCMLAgent] = {} self.a2f: Dict[str, Factory] = {} for factory, agent in zip(self.factories, self.factory_managers): self.f2a[factory.id] = agent self.a2f[agent.id] = factory for agent in self.consumers: factory = Factory( initial_storage={}, initial_wallet=0, profiles=[], min_balance=-np.inf ) factories.append(factory) self.f2a[factory.id] = agent self.a2f[agent.id] = factory for agent in self.miners: factory = Factory( initial_storage={}, initial_wallet=0.0, profiles=[], min_storage=-np.inf ) factories.append(factory) self.f2a[factory.id] = agent self.a2f[agent.id] = factory self.__interested_agents: List[List[SCMLAgent]] = [[]] * len(self.products) self.n_new_cfps = 0 self.__n_nullified = 0 self._transport: Dict[int, List[Tuple[SCMLAgent, int, int]]] = defaultdict(list) self._transfer: Dict[int, List[Tuple[SCMLAgent, float]]] = defaultdict(list) self.transfer_delay = transfer_delay self._n_production_failures = 0 self.bank = DefaultBank( minimum_balance=minimum_balance, interest_rate=interest_rate, interest_max=interest_max, balance_at_max_interest=balance_at_max_interest, installment_interest=installment_interest, time_increment=interest_time_increment, a2f=self.a2f, disabled=no_bank, name="bank", ) self.join(self.bank, simulation_priority=-1) self.insurance_company = DefaultInsuranceCompany( premium=premium, disabled=no_insurance, premium_breach_increment=premium_breach_increment, premium_time_increment=premium_time_increment, a2f=self.a2f, name="insurance_company", ) self.join(self.insurance_company) self.all_agents = {} for agent in itertools.chain( self.miners, self.consumers, self.factory_managers ): # type: ignore agent.init_() self.all_agents[agent.id] = agent # self.standing_jobs: Dict[int, List[Tuple[Factory, Job]]] = defaultdict(list) def join(self, x: "Agent", simulation_priority: int = 0): """Add an agent to the world. Args: x: The agent to be registered simulation_priority: The simulation priority. Entities with lower priorities will be stepped first during Returns: """ super().join(x=x, simulation_priority=simulation_priority) def save_config(self, file_name: str) -> None: d = {k: v for k, v in self.__dict__.items()} d["factory_manager_types"] = { manager.id: manager.short_type_name for manager in self.factory_managers } with open(file_name, "w") as file: yaml.safe_dump(d, file) def assign_managers( self, factory_managers=Iterable[Union[str, Type[FactoryManager], FactoryManager]], params: Optional[Iterable[Dict[str, Any]]] = None, ) -> None: """ Assigns existing factories to new factory managers created from the given types and parameters or actual managers Args: factory_managers: An iterable of `FactoryManager` objects type names or `FactoryManager` types to assign to params: parameters of the newly created managers Remarks: - factories are assigned in the same order they exist in the local `factories` attribute cycling through the input managers or types/params - If a `FactoryManager` object is given instead of a type or a string in the `factory_managers` collection, and the number of `factory_managers` is less than the number of factories in the world causing this object to cycle for more than one factory, it is assigned to the first such factory but then deep copies of it with new ids and names are assigned to the rest of the factories. That ensures that each manager has exactly one factory and that all factories are assigned exactly one unique manager. """ if params is None: params = [dict()] # todo add an exit function to agents and call it as they are leaving the world self.factory_managers, self.a2f, self.f2a = [], {}, {} for factory, (manager_type, manager_params) in zip( self.factories, itertools.cycle(zip(factory_managers, itertools.cycle(params))), ): if isinstance(manager_type, FactoryManager): manager = manager_type if manager.id in self.a2f.keys(): manager = copy.deepcopy(manager) manager.id = uuid.uuid4() manager.name = unique_name( manager.name, add_time=False, rand_digits=4 ) else: manager = instantiate(manager_type, **manager_params) self.join(manager, simulation_priority=MANAGER_SIMULATION_PRIORITY) self.factory_managers.append(manager) self.a2f[manager.id] = factory self.f2a[factory.id] = manager manager.init_() @classmethod def random_small( cls, n_production_levels: int = 1, n_factories: int = 10, factory_kwargs: Dict[str, Any] = None, miner_kwargs: Dict[str, Any] = None, consumer_kwargs: Dict[str, Any] = None, **kwargs, ): return cls.random( n_raw_materials=3, raw_material_price=(1, 3), n_final_products=3, n_production_levels=n_production_levels, n_products_per_level=4, n_processes_per_level=2, n_inputs_per_process=(1, 2), bias_toward_last_level_products=1.0, quantity_per_input=1, quantity_per_output=1, process_relative_cost=0.15, n_outputs_per_process=1, n_lines=2, lines_are_similar=True, n_processes_per_line=None, cost_for_line=(1.0, 5.0), n_production_steps=(1, 5), n_factories=n_factories, n_consumers=1, n_products_per_consumer=None, n_miners=1, n_products_per_miner=None, factory_kwargs=factory_kwargs, miner_kwargs=miner_kwargs, consumer_kwargs=consumer_kwargs, **kwargs, ) @classmethod def chain_world( cls, n_intermediate_levels=0, n_miners=5, n_factories_per_level=5, n_consumers: Union[int, Tuple[int, int], List[int]] = 5, n_steps=100, n_lines_per_factory=10, n_max_assignable_factories=None, log_file_name: str = None, agent_names_reveal_type: bool = False, negotiator_type: str = "negmas.sao.AspirationNegotiator", miner_type: Union[str, Type[Miner]] = ReactiveMiner, consumer_type: Union[str, Type[Consumer]] = ScheduleDrivenConsumer, max_storage: int = sys.maxsize, default_manager_params: Dict[str, Any] = None, miner_kwargs: Dict[str, Any] = None, consumption: Union[int, Tuple[int, int]] = (0, 5), consumer_kwargs: Dict[str, Any] = None, negotiation_speed: Optional[int] = None, manager_types: Sequence[Type[FactoryManager]] = (GreedyFactoryManager,), manager_params: Optional[Sequence[Dict[str, Any]]] = None, n_default_per_level: int = 0, default_factory_manager_type: Type[FactoryManager] = GreedyFactoryManager, randomize: bool = True, initial_wallet_balances=1000, process_cost: Union[float, Tuple[float, float]] = (1.0, 5.0), process_time: Union[int, Tuple[int, int]] = 1, interest_rate=float("inf"), interest_max=float("inf"), **kwargs, ): """ Creates a very small world in which only one raw material and one final product. The production graph is a series with `n_intermediate_levels` intermediate levels between the single raw material and single final product Args: n_max_assignable_factories: The maximum number of factories assigned to managers other than the default randomize: If true, the factory assignment is randomized n_default_per_level: The number of `GreedyFactoryManager` objects guaranteed at every level default_factory_manager_type: The `FactoryManager` type to use as the base for default_factory_managers. You can specify how many of this type exist at everly level by specifying `n_default_per_level`. If `n_default_per_level` is zero, this parameter has no effect. manager_types: A sequence of factory manager types to control the factories. manager_params: An optional sequence of dictionaries giving the parameters to pass to `manager_types`. consumer_type: Consumer type to use for all consumers miner_type: Miner type to use for all miners consumption: Consumption schedule n_intermediate_levels: The number of intermediate products n_miners: number of miners of the single raw material n_factories_per_level: number of factories at every production level n_consumers: number of consumers of the final product n_steps: number of simulation steps n_lines_per_factory: number of lines in each factory process_cost: The range of process costs. A uniform distribution will be used process_time: The range of process times. A unifrom distribution will be used log_file_name: File name to store the logs agent_names_reveal_type: If true, agent names will start with a snake_case version of their type name negotiator_type: The negotiation factory used to create all negotiators max_storage: maximum storage capacity for all factory managers If None then it is unlimited default_manager_params: keyword arguments to be used for constructing factory managers consumer_kwargs: keyword arguments to be used for constructing consumers miner_kwargs: keyword arguments to be used for constructing miners negotiation_speed: The number of negotiation steps per simulation step. None means infinite interest_max: Maximum interest rate interest_rate: Minimum interest rate initial_wallet_balances: initial wallet balances for all factories kwargs: Any other parameters are just passed to the world constructor Returns: SCMLWorld ready to run Remarks: - Every production level n has one process only that takes n steps to complete """ if default_manager_params is None: default_manager_params = {} if consumer_kwargs is None: consumer_kwargs = {} if miner_kwargs is None: miner_kwargs = {} if manager_params is None and len(manager_types) > 0: manager_params = [dict() for _ in range(len(manager_types))] if negotiator_type is not None: for args in (default_manager_params, consumer_kwargs, miner_kwargs): if "negotiator_type" not in args.keys(): args["negotiator_type"] = negotiator_type products = [ Product( id=0, name="p0", catalog_price=1.0, production_level=0, expires_in=0 ) ] processes = [] miners = [ instantiate( miner_type, profiles={products[-1].id: MiningProfile()}, name=f"m_{i}", **miner_kwargs, ) for i in range(n_miners) ] factories, managers = ( [], [None] * ((n_intermediate_levels + 1) * n_factories_per_level), ) def _s(x): return x if x is not None else 0 for level in range(n_intermediate_levels + 1): new_product = Product( name=f"p{level + 1}", catalog_price=None # keep this to the world to calculate _s(products[-1].catalog_price) + level + 1 , production_level=level + 1, id=level + 1, expires_in=0, ) p = Process( name=f"p{level + 1}", inputs=[InputOutput(product=level, quantity=1, step=0.0)], production_level=level + 1, outputs=[InputOutput(product=level + 1, quantity=1, step=1.0)], historical_cost=None, # keep this to the world to calculate level + 1 id=level, ) processes.append(p) products.append(new_product) assignable_factories = [] _DefaultFactoryManager = default_factory_manager_type for level in range(n_intermediate_levels + 1): default_factories = [] for j in range(n_factories_per_level): profiles = [] for k in range(n_lines_per_factory): profiles.append( ManufacturingProfile( n_steps=_intin(process_time), cost=_realin(process_cost), initial_pause_cost=0, running_pause_cost=0, resumption_cost=0, cancellation_cost=0, line=k, process=processes[level], ) ) factory = Factory( id=f"f{level + 1}_{j}", max_storage=max_storage, profiles=profiles, initial_storage={}, initial_wallet=initial_wallet_balances, ) factories.append(factory) if j >= n_default_per_level and ( n_max_assignable_factories is None or len(assignable_factories) < n_max_assignable_factories ): assignable_factories.append(j + level * n_factories_per_level) else: default_factories.append(j + level * n_factories_per_level) for j, indx in enumerate(default_factories): manager_name = unique_name(base="_df_", add_time=False, rand_digits=12) manager = _DefaultFactoryManager( name=manager_name, **default_manager_params ) if agent_names_reveal_type: manager.name = f"_df_{manager.short_type_name}@{level + 1}_{j}" managers[indx] = manager if randomize: shuffle(assignable_factories) for j, (index, (params, manager_type)) in enumerate( zip( assignable_factories, itertools.cycle(zip(manager_params, manager_types)), ) ): factory = factories[index] manager_name = ( f"{unique_name(base='', add_time=False, rand_digits=12)}@{factory.id}" ) manager = manager_type(name=manager_name, **params) if agent_names_reveal_type: manager.name = f"{manager.short_type_name}@{factory.id[1:]}" managers[index] = manager def create_schedule(): if isinstance(consumption, tuple) and len(consumption) == 2: return np.random.randint( consumption[0], consumption[1], n_steps ).tolist() return consumption consumers = [ instantiate( consumer_type, profiles={ products[-1].id: ConsumptionProfile(schedule=create_schedule()) }, name=f"c_{i}", **consumer_kwargs, ) for i in range(n_consumers) ] return SCMLWorld( products=products, processes=processes, factories=factories, consumers=consumers, miners=miners, n_steps=_intin(n_steps), factory_managers=managers, initial_wallet_balances=initial_wallet_balances, interest_rate=interest_rate, interest_max=interest_max, log_file_name=log_file_name, negotiation_speed=negotiation_speed, **kwargs, ) @classmethod def random( cls, n_raw_materials: Union[int, Tuple[int, int]] = (5, 10), raw_material_price: Union[float, Tuple[float, float]] = (1.0, 30.0), n_final_products: Union[int, Tuple[int, int]] = (3, 5), n_production_levels: Union[int, Tuple[int, int]] = (3, 5), n_products_per_level: Union[int, Tuple[int, int]] = (3, 5), n_processes_per_level: Union[int, Tuple[int, int]] = (6, 10), n_inputs_per_process: Union[int, Tuple[int, int]] = (2, 5), bias_toward_last_level_products: float = 0.0, quantity_per_input: Union[int, Tuple[int, int]] = (1, 10), input_step: Union[float, Tuple[float, float]] = 0.0, quantity_per_output: Union[int, Tuple[int, int]] = (1, 1), output_step: Union[float, Tuple[float, float]] = 1.0, process_relative_cost: Union[float, Tuple[float, float]] = (0.05, 0.4), n_outputs_per_process: Union[int, Tuple[int, int]] = (1, 1), n_lines: Union[int, Tuple[int, int]] = (3, 5), lines_are_similar: bool = False, n_processes_per_line: Union[int, Tuple[int, int]] = None, cost_for_line: Union[float, Tuple[float, float]] = (5.0, 50.0), n_production_steps: Union[int, Tuple[int, int]] = (2, 10), max_storage: Union[int, Tuple[int, int]] = 2000, n_factories: Union[int, Tuple[int, int]] = 20, n_consumers: Union[int, Tuple[int, int]] = 5, n_products_per_consumer: Union[int, Tuple[int, int]] = None, n_miners: Union[int, Tuple[int, int]] = 5, n_products_per_miner: Optional[Union[int, Tuple[int, int]]] = None, factory_manager_types: Union[ Type[FactoryManager], List[Type[FactoryManager]] ] = GreedyFactoryManager, consumer_types: Union[ Type[Consumer], List[Type[Consumer]] ] = ScheduleDrivenConsumer, miner_types: Union[Type[Miner], List[Type[Miner]]] = ReactiveMiner, negotiator_type="negmas.sao.AspirationNegotiator", initial_wallet_balance: Union[float, Tuple[float, float]] = 1000, factory_kwargs: Dict[str, Any] = None, miner_kwargs: Dict[str, Any] = None, consumer_kwargs: Dict[str, Any] = None, **kwargs, ): """ Creates a random SCML scenario with adjustable parameters. Args: n_raw_materials: Number of raw materials. Can be a value or a range. raw_material_price: Catalog prices for raw materials. Can be a value or a range. n_final_products: Number of final products. Can be a value or a range. n_production_levels: How deep is the production graph (number of intermediate products). Can be a value or a range. n_products_per_level: How many intermediate products per intermediate level. Can be a value or a range. n_processes_per_level: Number of processes in intermediate levels. Can be a value or a range. n_inputs_per_process: Number of inputs per process. Can be a value or a range. bias_toward_last_level_products: How biased are production processes toward using products from the last level below them (0 means not bias, 1 means only sample from this last level). A value between 0 and 1. quantity_per_input: How many items are needed for each input to a process. Can be a value or a range. input_step: When are inputs consumed during the production process. Can be a value or a range. Default 0 quantity_per_output: How many items are produced per output. Can be a value or a range. output_step: When are outputs created during the production process. Can be a value or a range. Default 1 process_relative_cost: Intrinsic relative cost of processes [Outputs will be produced at a cost of sum(input costs) * (1 + process_relative_cost)]. Can be a value or a range. n_outputs_per_process: Number of outputs per process. Can be a value or a range. n_lines: Number of lines per factory. Can be a value or a range. lines_are_similar: If true then all lins of the same factory will have the same production processes. n_processes_per_line: Number of processes that can be run on each line per factory. Can be a value or a range. cost_for_line: Cost for running a process on a line. Can be a value or a range. n_production_steps: Number of production steps per line. Can be a value or a range. max_storage: Maximum storage per factory. Can be a value or a range. n_factories: Number of factories. Can be a value or a range. n_consumers: Number of consumers. Can be a value or a range. n_products_per_consumer: Number of products per miner. If None then all final products will be assigned to every customer. Can be a value or a range. n_miners: Number of miners. Can be a value or a range. n_products_per_miner: Number of products per miner. If None then all raw materials will be assigned to every miner. Can be a value or a range. factory_manager_types: A callable for creating factory managers for the factories consumer_types: A callable for creating `Consumer` objects miner_types: A callable for creating `Miner` objects negotiator_type: A string that can be `eval`uated to a negotiator. initial_wallet_balance: The initial balance of all wallets factory_kwargs: keyword arguments to be used for constructing factory managers consumer_kwargs: keyword arguments to be used for constructing consumers miner_kwargs: keyword arguments to be used for constructing miners **kwargs: Returns: `SCMLWorld` The random world generated Remarks: - Most parameters accept either a single value or a 2-valued tuple. In the later case, it will sample a value within the range specified by the tuple (low, high) inclusive. For example the number of lines (n_lines) follows this pattern """ if factory_kwargs is None: factory_kwargs = {} if consumer_kwargs is None: consumer_kwargs = {} if miner_kwargs is None: miner_kwargs = {} if negotiator_type is not None: for args in (factory_kwargs, consumer_kwargs, miner_kwargs): if "negotiator_type" not in args.keys(): args["negotiator_type"] = negotiator_type def _sample_product( products: list, old_products: list, last_level_products: list, k: int ): if bias_toward_last_level_products < 1e-7: return sample(products, k=min(k, len(products))) elif bias_toward_last_level_products > 1 - 1e-7: return sample(last_level_products, min(k, len(last_level_products))) n_old, n_last = len(old_products), len(last_level_products) p_old = n_old / (n_old + n_last / bias_toward_last_level_products) if random() < p_old: return sample(old_products, min(k, len(old_products))) else: return sample(last_level_products, min(k, len(last_level_products))) products = [ Product( name=f"r_{ind}", catalog_price=_realin(raw_material_price), production_level=0, expires_in=0, id=ind, ) for ind in range(_intin(n_raw_materials)) ] raw_materials = products.copy() last_level_products = products # last level of products old_products: List[Product] = [] # products not including last level processes: List[Process] = [] def _adjust_level_of_production(new_products, new_processes): product_prices: Dict[Product, List[float]] = defaultdict( list ) # will keep the costs for generating products for process in new_processes: process.inputs = set( InputOutput( product=_.index, quantity=_intin(quantity_per_input), step=_realin(input_step), ) for _ in _sample_product( products=products, old_products=old_products, last_level_products=last_level_products, k=_intin(n_inputs_per_process), ) ) process.outputs = set( InputOutput( product=_.index, quantity=_intin(quantity_per_output), step=_realin(output_step), ) for _ in sample(new_products, _intin(n_outputs_per_process)) ) process.historical_cost = sum( products[_.product].catalog_price * _.quantity for _ in process.inputs ) process.historical_cost *= 1 + _realin(process_relative_cost) for output in process.outputs: product_prices[products[output.product]].append( process.historical_cost ) new_products = [_ for _ in product_prices.keys()] for product in new_products: product.catalog_price = sum(product_prices[product]) / len( product_prices[product] ) return new_products, new_processes n_levels = _intin(n_production_levels) if n_levels > 0: for level in range(n_levels): new_products = [ Product( name=f"intermediate_{level}_{ind}", production_level=level + 1, id=len(products) + ind, catalog_price=0, expires_in=0, ) for ind in range(_intin(n_products_per_level)) ] new_processes = [ Process( name=f"process_{level}_{ind}", production_level=level + 1, id=len(processes) + ind, historical_cost=0, inputs=set(), outputs=set(), ) for ind in range(_intin(n_processes_per_level)) ] new_products, new_processes = _adjust_level_of_production( new_products, new_processes ) products += new_products old_products += last_level_products last_level_products = new_products processes += new_processes final_products = [ Product( name=f"f_{ind}", production_level=n_levels + 1, id=len(products) + ind, catalog_price=0, expires_in=0, ) for ind in range(_intin(n_final_products)) ] new_processes = [ Process( name=f"process_final_{ind}", production_level=n_levels + 1, id=len(processes) + ind, historical_cost=0, inputs=set(), outputs=set(), ) for ind in range(_intin(n_processes_per_level)) ] final_products, new_processes = _adjust_level_of_production( final_products, new_processes ) products += final_products processes += new_processes else: final_products = raw_materials if n_processes_per_line is None: n_processes_per_line = len(processes) n_factories = _intin(n_factories) factories = [] for i in range(n_factories): profiles = [] if lines_are_similar: line_processes = sample(processes, _intin(n_processes_per_line)) profiles.extend( [ ManufacturingProfile( n_steps=_intin(n_production_steps), cost=_realin(cost_for_line), initial_pause_cost=0, running_pause_cost=0, resumption_cost=0, cancellation_cost=0, line=i, process=_, ) for _ in line_processes ] ) else: lines = [] for _ in range(_intin(n_lines)): line_processes = sample(processes, _intin(n_processes_per_line)) profiles.extend( [ ManufacturingProfile( n_steps=_intin(n_production_steps), cost=_realin(cost_for_line), initial_pause_cost=0, running_pause_cost=0, resumption_cost=0, cancellation_cost=0, line=i, process=_, ) for _ in line_processes ] ) factories.append( Factory( profiles=profiles, max_storage=_intin(max_storage), initial_storage={}, initial_wallet=_realin(initial_wallet_balance), ) ) def _ensure_list(x): if isinstance(x, Iterable): return list(x) else: return [x] miner_types_list, consumer_types_list, factory_manager_types_list = [ _ensure_list(_) for _ in (miner_types, consumer_types, factory_manager_types) ] factory_managers = [ current(**factory_kwargs) for current in choices(factory_manager_types_list, k=n_factories) ] miners = [ current(**miner_kwargs) for current in choices(miner_types_list, k=_intin(n_miners)) ] if n_products_per_miner is None: n_products_per_miner = len(raw_materials) if n_products_per_consumer is None: n_products_per_consumer = len(final_products) n_products_per_miner = min(n_products_per_miner, len(raw_materials)) n_products_per_consumer = min(n_products_per_consumer, len(final_products)) for miner in miners: _n = _intin(n_products_per_miner) mining_profiles = dict( zip( (_.index for _ in sample(raw_materials, _n)), [MiningProfile.random() for _ in range(_n)], ) ) miner.set_profiles(mining_profiles) consumers = [ current(**consumer_kwargs) for current in choices(consumer_types_list, k=_intin(n_consumers)) ] for consumer in consumers: _n = _intin(n_products_per_consumer) consumer_profiles = dict( zip( (_.index for _ in sample(final_products, _n)), [ConsumptionProfile.random() for _ in range(_n)], ) ) consumer.set_profiles(consumer_profiles) return SCMLWorld( products=products, processes=processes, factories=factories, consumers=consumers, miners=miners, factory_managers=factory_managers, initial_wallet_balances=None, **kwargs, ) def _update_dynamic_product_process_info(self): """Updates the catalog prices of all products based on the prices of their inputs""" # for process in self.processes: # for current in process.inputs: # self.products[current.product].consuming_processes.add((process, current.quantity)) # for current in process.outputs: # self.products[current.product].generating_processes.add((process, current.quantity)) # noinspection PyUnusedLocal def _or_for_none(a, b): return (a is None and b) or a or b product_costs: Dict[Product, List[float]] = defaultdict(list) process_costs: Dict[Process, List[float]] = defaultdict(list) producers: Dict[Product, List[Tuple[Process, int]]] = defaultdict(list) consumers: Dict[Product, List[Tuple[Process, int]]] = defaultdict(list) def production_record(process_: Process, product_: Product): for output_ in process_.outputs: if output_.product == product_.id: return process_, output_.quantity return None def consumption_record(process_: Process, product_: Product): for input_ in process_.inputs: if input_.product == product_.id: return process_, input_.quantity # sort products and processes by the production level. We assume here that production levels are well behaved products = sorted(self.products, key=lambda x: x.production_level) processes = sorted(self.processes, key=lambda x: x.production_level) # find the producers and consumers for every product. This builds the production graph and its inverse for product in products: for process in processes: precord = production_record(process, product) if precord is not None: producers[product].append(precord) crecord = consumption_record(process, product) if crecord is not None: consumers[product].append(crecord) # find the average manufacturing profile cost for every process for factory in self.factories: for profile_index, profile in enumerate(factory.profiles): process = profile.process if self.avg_process_cost_is_public: process_costs[process].append(profile.cost) process_costs_avg = { k: sum(v) / len(v) if len(v) > 0 else math.inf for k, v in process_costs.items() } # loop over all products finding the processes that can produce it and add a new cost example for this product for product in products: for process, quantity in producers[product]: if quantity == 0: continue # find the total input cost for a process that can produce the current product input_cost = 0.0 for input_ in process.inputs: iproduct = self.products[input_.product] if iproduct.catalog_price is None: if ( self.catalog_prices_are_public or self.avg_process_cost_is_public ): raise ValueError( f"Catalog prices should be public but product {product} is needed for process {process}" f" without a catalog price" ) return input_cost += iproduct.catalog_price * input_.quantity # append a new unit price for this product product_costs[product].append( (input_cost + process_costs_avg[process]) / quantity ) # now we have the product cost for all processes producing this product. Average them if ( product_costs.get(product, None) is None or len(product_costs[product]) < 1 ): continue avg_cost = sum(product_costs[product]) / len(product_costs[product]) if product.catalog_price is None: product.catalog_price = avg_cost * (1 + self.catalog_profit) # update the historical cost for processes if needed if self.avg_process_cost_is_public: for process in self.processes: if process.historical_cost is None: process.historical_cost = process_costs_avg[process] else: for process in self.processes: process.historical_cost = None # update the catalog prices by averaging all possible ways to create any product. if not self.catalog_prices_are_public: for product in self.products: product.catalog_price = None if self.money_resolution is not None: for product in self.products: if product.catalog_price is not None: product.catalog_price = ( math.floor(product.catalog_price / self.money_resolution) * self.money_resolution ) for process in self.processes: if process.historical_cost is not None: process.historical_cost = ( math.floor(process.historical_cost / self.money_resolution) * self.money_resolution ) def set_consumers(self, consumers: List[Consumer]): self.consumers = consumers for f in consumers: self.join(f, simulation_priority=CONSUMER_SIMULATION_PRIORITY) def set_miners(self, miners: List[Miner]): self.miners = miners for f in miners: self.join(f, simulation_priority=MINER_SIMULATION_PRIORITY) def set_factory_managers(self, factory_managers: Optional[List[FactoryManager]]): if factory_managers is None: factory_managers = [] self.factory_managers = factory_managers for f in factory_managers: self.join(f, simulation_priority=MANAGER_SIMULATION_PRIORITY) def set_processes(self, processes: Collection[Process]): if processes is None: self.processes = [] else: self.processes = list(processes) for v in self.processes: self.bulletin_board.record("processes", key=str(v), value=v) def set_products(self, products: Collection[Product]): if products is None: self.products = [] else: self.products = list(products) for v in self.products: self.bulletin_board.record("products", key=str(v), value=v) def _contract_execution_order(self, contracts: Collection[Contract]): def order(x: Contract): o = self.products[x.annotation["cfp"].product].production_level if o: return o return 0 return sorted(contracts, key=order) def execute( self, action: Action, agent: "Agent", callback: Callable[[Action, bool], Any] = None, ) -> bool: if not isinstance(agent, FactoryManager): if callback is not None: callback(action, False) self.logerror( f"{str(action)} received from {agent.id} which is {agent.__class__.__name__} not a FactoryManager" ) return False factory = self.a2f[agent.id] if factory is None: if callback is not None: callback(action, False) self.logerror(f"{str(action)} from {agent.id}: Unknown factory") return False if action.type == "hide_funds": factory.hide_funds(amount=action.params.get("amount", 0.0)) return True elif action.type == "unhide_funds": factory.unhide_funds(amount=action.params.get("amount", 0.0)) return True elif action.type in ("hide_product", "hide_products", "hide_inventory"): factory.hide_product( product=action.params.get("product", -1), quantity=action.params.get("quantity", 0), ) elif action.type in ("unhide_product", "unhide_products", "unhide_inventory"): factory.unhide_product( product=action.params.get("product", -1), quantity=action.params.get("quantity", 0), ) elif action.type not in ("run", "start", "stop", "pause", "resume"): raise ValueError(f"Unknown action {action.type} received {str(action)}") line, profile_index = ( action.params.get("line", None), action.params.get("profile", None), ) t = action.params.get("time", None) contract = action.params.get("contract", None) time = action.params.get("time", None) override = action.params.get("override", True) if ( (profile_index is None and line is None) or time is None or time < 0 or time > self.n_steps - 1 ): if callback is not None: callback(action, False) self.logerror( f"{str(action)} from {agent.id}: Neither profile index nor line is given or invalid time" ) return False if profile_index is not None: profile = factory.profiles[profile_index] if line is not None and profile.line != line: if callback is not None: callback(action, False) self.logerror( f"{str(action)} from {agent.id}: profile's line {profile.line} != given line {line}" ) return False line = profile.line job = Job( action=action.type, profile=profile_index, line=line, time=t, contract=contract, override=override, ) factory.schedule(job=job, override=override) if callback is not None: self.logdebug(f"{str(action)} from {agent.id}: Executed successfully") callback(action, True) return True def get_private_state(self, agent: "Agent") -> FactoryState: f = self.a2f[agent.id] return FactoryState( storage=f.storage, wallet=f.wallet, loans=f.loans, max_storage=f.max_storage, line_schedules=f.line_schedules, hidden_money=f.hidden_money, hidden_storage=f.hidden_storage, n_lines=f.n_lines, profiles=f.profiles, next_step=f.next_step, commands=f.commands, ) def receive_financial_reports( self, agent: SCMLAgent, receive: bool, agents: Optional[List[str]] ): """Registers interest/disinterest in receiving financial reports""" if agents is None: agents = self.agents.keys() if receive: for aid in agents: self._report_receivers[aid].add(agent) else: for aid in agents: self._report_receivers[aid].discard(agent) def _simulation_step(self): """A step of SCML simulation""" # publish financial reports # ------------------------- if self.current_step % self.financial_reports_period == 0: reports_agent = self.bulletin_board.data["reports_agent"] reports_time = self.bulletin_board.data["reports_time"] for agent in self.agents.values(): factory = self.a2f.get(agent.id, None) if factory is None: continue try: inventory = sum( self.products[product].catalog_price * quantity for product, quantity in factory.storage.items() ) except ArithmeticError: inventory = None report = FinancialReport( agent=agent.id, step=self.current_step, cash=factory.wallet, liabilities=factory.loans, inventory=inventory, credit_rating=self.bank.credit_rating(agent.id), ) if reports_agent.get(agent.id, None) is None: reports_agent[agent.id] = [] reports_agent[agent.id].append(report) if reports_time.get(self.current_step, None) is None: reports_time[self.current_step] = {} reports_time[self.current_step][agent.id] = report for receiver in self._report_receivers[agent.id]: receiver.on_new_report(report) # run standing jobs # ----------------- # for factory, job in self.standing_jobs.get(self.current_step, []): # factory.schedule_job(job=job, end=self.n_steps) # run factories # ------------- for factory in self.factories: manager = self.f2a[factory.id] reports = factory.step() if isinstance(manager, Consumer) or isinstance(manager, Miner): self.logdebug( f"{manager.name}: money={factory.wallet}" f", storage={str(dict(factory.storage))}" ) else: self.logdebug( f"{manager.name} (Factory {factory.id}): money={factory.wallet}" f", storage={str(dict(factory.storage))}" f", loans={factory.loans}" ) for report in reports: if not report.is_empty: self.logdebug(f"PRODUCTION>> {manager.name}: {str(report)}") failures = [] for report in reports: if report.failed: failures.append(report.failure) if len(failures) > 0: manager.on_production_failure(failures=failures) # finish transportation and money transfer # ----------------------------------------- transports = self._transport.get(self.current_step, []) for transport in transports: manager, product_id, q = transport self.a2f[manager.id].transport_to(product_id, q) transfers = self._transfer.get(self.current_step, []) for transfer in transfers: manager, money = transfer self.a2f[manager.id].receive(money) # remove expired CFPs # ------------------- cfps = self.bulletin_board.query(section="cfps", query=None) if cfps is not None: # new_cfps = dict() toremove = [] for key, cfp in cfps.items(): # we remove CFP with a max_time less than *or equal* to current step as all processing for current step # should already be complete by now if cfp.max_time <= self.current_step: toremove.append(key) for key in toremove: self.bulletin_board.remove(section="cfps", query=key, query_keys=True) def _pre_step_stats(self): # noinspection PyProtectedMember cfps = self.bulletin_board._data["cfps"] self._stats["n_cfps_on_board_before"].append(len(cfps) if cfps else 0) self._n_production_failures = 0 self.__n_nullified = 0 pass def _post_step_stats(self): """Saves relevant stats""" self._stats["n_cfps"].append(self.n_new_cfps) self.n_new_cfps = 0 # noinspection PyProtectedMember cfps = self.bulletin_board._data["cfps"] self._stats["n_cfps_on_board_after"].append(len(cfps) if cfps else 0) self._stats["n_contracts_nullified"].append(self.__n_nullified) market_size = 0 self._stats[f"_balance_bank"].append(self.bank.wallet) self._stats[f"_balance_society"].append(self.penalties) self._stats[f"_balance_insurance"].append(self.insurance_company.wallet) self._stats[f"_storage_insurance"].append( sum(self.insurance_company.storage.values()) ) internal_market_size = ( self.bank.wallet + self.penalties + self.insurance_company.wallet ) for a in itertools.chain(self.miners, self.consumers, self.factory_managers): self._stats[f"balance_{a.name}"].append(self.a2f[a.id].balance) self._stats[f"storage_{a.name}"].append(self.a2f[a.id].total_storage) market_size += self.a2f[a.id].balance self._stats["market_size"].append(market_size) self._stats["production_failures"].append( self._n_production_failures / len(self.factories) if len(self.factories) > 0 else np.nan ) self._stats["_market_size_total"].append(market_size + internal_market_size) def _execute_contract(self, contract: Contract) -> Set[Breach]: partners, agreement = ( set(self.agents[_] for _ in contract.partners), contract.agreement, ) cfp = contract.annotation["cfp"] # type: ignore breaches = set() quantity, unit_price = agreement["quantity"], agreement["unit_price"] if quantity < 1 or unit_price < 0.0: self.loginfo( f"Contract with quantity {quantity} and unit price {unit_price} will be ignored: " f"{str(contract)}" ) return breaches if unit_price < 1e-7: self.logdebug( f"Contract with zero unit_price ({unit_price}: {str(contract)}" ) # find out the values for vicitm and social penalties penalty_victim = agreement.get("penalty", None) if penalty_victim is not None and self.breach_penalty_victim is not None: # there is a defined penalty, find its value penalty_victim = penalty_victim if penalty_victim is not None else 0.0 penalty_victim += ( self.breach_penalty_victim if self.breach_penalty_victim is not None else 0.0 ) penalty_society = self.breach_penalty_society penalty_value = 0.0 # ask each partner to confirm the execution for partner in partners: if not partner.confirm_contract_execution(contract=contract): self.logdebug( f"{partner.name} refused execution og Contract {contract.id}" ) breaches.add( Breach( contract=contract, perpetrator=partner.id, # type: ignore victims=[_.id for _ in list(partners - {partner})], level=1.0, type="refusal", ) ) if len(breaches) > 0: return breaches # all partners agreed to execute the agreement -> execute it. pind = cfp.product buyer_id, seller_id = ( contract.annotation["buyer"], contract.annotation["seller"], ) buyer, seller = self.agents[buyer_id], self.agents[seller_id] seller_factory, buyer_factory = self.a2f[seller.id], self.a2f[buyer.id] product_breach, money_breach, penalty_breach_victim, penalty_breach_society = ( None, None, None, None, ) money = unit_price * quantity # first we will try to blindly execute the contract and will fall back to the more complex algorithm checking # all possibilities only if that failed try: if money > 0 or quantity > 0: self._move_product( buyer=buyer, seller=seller, quantity=quantity, money=money, product_id=pind, ) else: self.logdebug(f"Contract {contract.id} has no transfers") return breaches except ValueError: pass # check the seller available_quantity = ( seller_factory.storage.get(pind, 0) if not isinstance(seller, Miner) else quantity ) missing_quantity = max(0, quantity - available_quantity) if missing_quantity > 0: product_breach = missing_quantity / quantity penalty_values = [] for penalty, is_victim in ( (penalty_victim, True), (penalty_society, False), ): if penalty is None: penalty_values.append(0.0) continue # find out how much need to be paid for this penalty penalty_value = penalty * product_breach * quantity * unit_price # society penalty may have a minimum. If so, make sure the penalty value is at least as large as that if not is_victim and self.breach_penalty_society_min is not None: penalty_value = max(penalty_value, self.breach_penalty_society_min) penalty_values.append(penalty_value) # that is how much money is available in the wallet right now. Notice that loans do not count seller_balance = seller_factory.wallet # if the seller needs more than what she has in her wallet to pay the penalty, try a loan # Loans are mandatory for society penalty but the agent can refuse to pay a victim penalty if seller_balance < penalty_value: self.bank.buy_loan( agent=seller, amount=penalty_value - seller_balance, n_installments=self.loan_installments, force=True, beneficiary=buyer, contract=contract, ) for penalty, is_victim, penalty_value in ( (penalty_victim, True, penalty_values[0]), (penalty_society, False, penalty_values[1]), ): if penalty is None: continue # if the seller can pay the penalty then pay it and now there is no breach, otherwise pay as much as # possible. Notice that for society penalties, it should always be the case that the whole penalty # value is available in the wallet by now as loans are forced. paid_for_quantity, paid_penalties = 0, 0.0 if seller_factory.wallet >= penalty_value: # if there is enough money then pay the whole penalty paid_penalties = penalty_value else: # if there is not enough money then pay enough for the maximum number of items that can be paid if unit_price == 0: paid_for_quantity = missing_quantity else: paid_for_quantity = int( math.floor(seller_factory.wallet / unit_price) ) paid_penalties = unit_price * paid_for_quantity missing_quantity_unpaid_for = missing_quantity - paid_for_quantity if is_victim: penalty_breach_victim = missing_quantity_unpaid_for / quantity else: penalty_breach_society = missing_quantity_unpaid_for / quantity # actually pay the payable amount self.logdebug( f'Penalty: {seller.name} paid {paid_penalties} to {buyer.name if is_victim else "society"}' ) seller_factory.pay(paid_penalties) if is_victim: buyer_factory.receive(paid_penalties) # if we agreed on a penalty and the buyer paid it, then clear the product breach quantity -= paid_for_quantity money -= paid_for_quantity * unit_price missing_quantity -= paid_for_quantity if missing_quantity <= 0: product_breach = None else: product_breach = missing_quantity / quantity else: # if this is the society penalty, it does not affect the product_breach self.penalties += paid_penalties # pay penalties if there are any. Notice that penalties apply only to to seller. It makes no sense to have a # penalty on the buyer who already have no money to pay the contract value anyway. if penalty_breach_society is not None: breaches.add( Breach( contract=contract, perpetrator=seller.id, victims=[], level=penalty_breach_society, type="penalty_society", step=self.current_step, ) ) if penalty_breach_victim is not None: breaches.add( Breach( contract=contract, perpetrator=seller.id, victims=[buyer.id], level=penalty_breach_victim, type="penalty", step=self.current_step, ) ) # check the buyer available_money = ( buyer_factory.wallet if not isinstance(buyer, Consumer) else money ) missing_money = max(0.0, money - available_money) if missing_money > 0.0: # if the buyer cannot pay, then offer him a loan. The loan is always optional self.bank.buy_loan( agent=buyer, amount=missing_money, n_installments=self.loan_installments, force=False, beneficiary=seller, contract=contract, ) available_money = buyer_factory.wallet missing_money = max(0.0, money - available_money) # if there is still missing money after the loan is offered, then create a breach if missing_money > 0.0: money_breach = missing_money / money if product_breach is not None: # register the breach independent of insurance breaches.add( Breach( contract=contract, perpetrator=seller.id, victims=[buyer.id], level=product_breach, type="product", step=self.current_step, ) ) if money_breach is not None: # register the breach independent of insurance breaches.add( Breach( contract=contract, perpetrator=buyer.id, victims=[seller.id], level=money_breach, type="money", step=self.current_step, ) ) if len(breaches) > 0: return breaches # should never arrive here assert missing_quantity == 0 assert missing_money == 0 if money > 0 or quantity > 0: self._move_product( buyer=buyer, seller=seller, quantity=quantity, money=money, product_id=pind, ) else: self.logdebug(f"Contract {contract.id} has no transfers") return breaches def _move_product( self, buyer: SCMLAgent, seller: SCMLAgent, product_id: int, quantity: int, money: float, ): """Moves as much product and money between the buyer and seller""" seller_factory, buyer_factory = self.a2f[seller.id], self.a2f[buyer.id] if quantity > 0: seller_factory.transport_from(product_id, quantity) if self.transportation_delay < 1: buyer_factory.transport_to(product_id, quantity) else: self._transport[self.current_step + self.transportation_delay].append( (buyer, product_id, quantity) ) if money > 0: buyer_factory.pay(money) if self.transfer_delay < 1: seller_factory.receive(money) else: self._transfer[self.current_step + self.transfer_delay].append( (seller, money) ) self.logdebug( f"Moved {quantity} units of {self.products[product_id].name} from {seller.name} to {buyer.name} " f"for {money} dollars" ) def _complete_contract_execution( self, contract: Contract, breaches: List[Breach], resolution: Optional[Contract] ): """The resolution can either be None or a contract with the following items: The issues can be any or all of the following: immediate_quantity: int immediate_unit_price: float later_quantity: int later_unit_price: int later_penalty: float later_time: int """ partners, agreement = ( set(self.agents[_] for _ in contract.partners), contract.agreement, ) cfp = contract.annotation["cfp"] # type: ignore breaches = set() quantity, unit_price = agreement["quantity"], agreement["unit_price"] penalty_victim = agreement.get("penalty", None) if penalty_victim is not None and self.breach_penalty_victim is not None: # there is a defined penalty, find its value penalty_victim = penalty_victim if penalty_victim is not None else 0.0 penalty_victim += ( self.breach_penalty_victim if self.breach_penalty_victim is not None else 0.0 ) penalty_society = self.breach_penalty_society pind = cfp.product buyer_id, seller_id = ( contract.annotation["buyer"], contract.annotation["seller"], ) buyer, seller = self.agents[buyer_id], self.agents[seller_id] seller_factory, buyer_factory = self.a2f[seller.id], self.a2f[buyer.id] product_breach, money_breach, penalty_breach_victim, penalty_breach_society = ( None, None, None, None, ) if resolution is None: for breach in breaches: if breach.type == "product": product_breach = breach.level elif breach.type == "money": money_breach = breach.level elif breach.type == "penalty": penalty_breach_victim = breach.level elif breach.type == "penalty_society": penalty_breach_society = breach.level else: quantity = resolution.agreement.get("immediate_quantity", quantity) unit_price = resolution.agreement.get("immediate_unit_price", unit_price) # make and register new contract contract.annotation["renegotiation"] = True future_agreement = { "time": agreement.get("later_time", -1), "penalty": agreement.get("later_penalty", -1), "quantity": agreement.get("later_quantity", None), "unit_price": agreement.get("later_unit_price", 0.0), } new_contract = Contract( partners=contract.partners, annotation=contract.annotation, issues=contract.issues, agreement=SCMLAgreement(**future_agreement), concluded_at=self.current_step, to_be_signed_at=self.current_step, signed_at=self.current_step, mechanism_state=None, signatures=contract.partners, ) self.on_contract_concluded(new_contract, to_be_signed_at=self.current_step) self.on_contract_signed(contract=new_contract) for partner in partners: partner.on_contract_signed_(contract=new_contract) money = unit_price * quantity # check the seller available_quantity = ( seller_factory.storage.get(pind, 0) if not isinstance(seller, Miner) else quantity ) missing_quantity = max(0, quantity - available_quantity) # check the buyer available_money = ( buyer_factory.wallet if not isinstance(buyer, Consumer) else money ) missing_money = max(0.0, money - available_money) if missing_money > 0.0: money_breach = missing_money / money insured_quantity, insured_quantity_cost = 0, 0.0 insured_money, insured_money_quantity = 0.0, 0 # confirm partial execution perpetrators = set([b.perpetrator for b in breaches]) victims = set() if 0 < len(perpetrators) < len(partners): victims = set(partners) - set(perpetrators) execute = ( all( victim.confirm_partial_execution( contract=contract, breaches=list(breaches) ) for victim in victims ) if len(victims) > 0 else True ) if product_breach is not None and resolution is None: # apply insurances if they exist # register the breach independent of insurance if self.insurance_company.pay_insurance( contract=contract, perpetrator=seller ): # if the buyer has an insurance against the seller for this contract, then just give him the missing # quantity and proceed as if the contract was for the remaining quantity. Notice that the breach on the # seller is already registered by this time. # the insurance company can give as much as the buyer can buy. No loan is allowed here as the buyer was # already offered a loan earlier because surely if they have a deficit they committed a funds breach # buyer_deficit = missing_quantity * unit_price - buyer_factory.wallet # if buyer_deficit > 0: # self.bank.buy_loan(agent=buyer, amount=buyer_deficit, n_installments=self.loan_installments) if unit_price > 0: insured_quantity = min( missing_quantity, int(buyer_factory.wallet / unit_price) ) else: insured_quantity = missing_quantity self.logdebug( f"Insurance: {buyer.name} got {insured_quantity} of {self.products[pind].name} " f"from insurance ({missing_quantity} was missing" ) insured_quantity_cost = insured_quantity * unit_price buyer_factory.transport_to(product=pind, quantity=insured_quantity) buyer_factory.pay(insured_quantity_cost) self.insurance_company.storage[pind] -= insured_quantity self.insurance_company.wallet += insured_quantity_cost # we will only transfer the remaining quantity. missing_quantity -= insured_quantity quantity -= insured_quantity money -= insured_quantity * unit_price if money_breach is not None and resolution is None: # apply insurances if they exist. if self.insurance_company.pay_insurance( contract=contract, perpetrator=buyer ): # if the seller has an insurance against the buyer for this contract, then just give him the missing # money and proceed as if the contract was for the remaining amount. Notice that the breach on the # seller is already registered by this time. # the insurance company will provide enough money to buy whatever actually exist of the contract in the # seller's storage insured_money = min( missing_money, seller_factory.storage.get(pind, 0) * unit_price ) insured_money_quantity = int( insured_money // unit_price ) # I never come here if unit_price is zero. self.logdebug( f"Insurance: {seller.name} got {insured_money} dollars from insurance" ) seller_factory.receive(insured_money) seller_factory.transport_from( product=pind, quantity=insured_money_quantity ) self.insurance_company.wallet -= insured_money self.insurance_company.storage[pind] += insured_money_quantity # we will only transfer the remaining money. money -= insured_money missing_money -= insured_money quantity -= insured_money_quantity # missing quantity/money is now fully handled. Just remove them from the contract and execute the rest quantity -= missing_quantity + ( int(missing_money / unit_price) if unit_price != 0.0 else 0.0 ) money -= missing_money + missing_quantity * unit_price # confirm that the money and quantity match given the unit price. assert money == unit_price * quantity, ( f"invalid contract!! money {money}, quantity {quantity}" f", unit price {unit_price}, missing quantity {missing_quantity}, missing money {missing_money}" f", breaches: {[str(_) for _ in breaches]}, insured_quantity {insured_quantity}" f", insured_quantity_cost {insured_quantity_cost}, insured_money {insured_money}" f', insured_money_quantity {insured_money_quantity}, original quantity {agreement["quantity"]}' f', original money {agreement["unit_price"] * agreement["quantity"]}' ) # if money > unit_price * quantity: # money = unit_price * quantity # if unit_price != 0.0 and quantity > math.floor(money / unit_price): # quantity = int(math.floor(money / unit_price)) if money > 0 or quantity > 0: if execute: self._move_product( buyer=buyer, seller=seller, quantity=quantity, money=money, product_id=pind, ) else: self.logdebug( f"Contract {contract.id}: one of {[_.id for _ in victims]} refused partial execution." ) else: self.logdebug(f"Contract {contract.id} has no transfers") def _move_product_force( self, buyer: SCMLAgent, seller: SCMLAgent, product_id: int, quantity: int, money: float, ): """Moves as much product and money between the buyer and seller""" seller_factory, buyer_factory = self.a2f[seller.id], self.a2f[buyer.id] if isinstance(seller, Miner): available_quantity = quantity else: available_quantity = min( quantity, seller_factory.storage.get(product_id, 0) ) if isinstance(buyer, Consumer): available_money = money else: available_money = min(money, buyer_factory.wallet) self.logdebug( f"Moving {quantity} (available {available_quantity}) units of " f"{self.products[product_id].name} from {seller.name} " f"to {buyer.name} for {money} (available {available_money}) dollars" ) if available_quantity > 0: seller_factory.transport_from(product_id, available_quantity) if self.transportation_delay < 1: buyer_factory.transport_to(product_id, available_quantity) else: self._transport[self.current_step + self.transportation_delay].append( (buyer, product_id, available_quantity) ) if available_money > 0: buyer_factory.pay(available_money) if self.transfer_delay < 1: seller_factory.receive(available_money) else: self._transfer[self.current_step + self.transfer_delay].append( (seller, available_money) ) def register_interest(self, agent: SCMLAgent, products: List[int]) -> None: for product in products: self.__interested_agents[product] = list( set(self.__interested_agents[product] + [agent]) ) def unregister_interest(self, agent: SCMLAgent, products: List[int]) -> None: for product in products: try: self.__interested_agents[product].remove(agent) except ValueError: pass def make_bankrupt( self, agent: SCMLAgent, amount: float, beneficiary: Agent, contract: Optional[Contract], ) -> None: """Marks the agent as bankrupt""" self.bulletin_board.record( "bankruptcy", {"time": self.current_step}, key=agent.id ) for receiver in itertools.chain( self.miners, self.consumers, self.factory_managers ): receiver.on_agent_bankrupt(agent.id) # liquidate the bankrupt agent factory = self.a2f.get(agent.id, None) if factory is None: return # first sell everything the agent has in its factory at catalog prices for product_index, quantity in factory.storage.items(): price = self.products[product_index].catalog_price if price is None: price = self.default_price_for_products_without_one saved_min_storage, factory.min_storage = factory.min_storage, 0 factory.sell(product=product_index, quantity=quantity, price=price) payable = min(factory.wallet, amount) # second pay the beneficiary if contract is None: # beneficiary is the bank beneficiary: DefaultBank beneficiary.wallet += payable factory.pay(payable) keep_for_beneficiary = 0 else: # beneficiary is another agent keep_for_beneficiary = payable # nullify all future contracts available = factory.balance - keep_for_beneficiary owed = 0.0 nulled_contracts = [] for time, contracts in self.contracts.items(): if time < self.current_step: continue for contract in contracts: if agent.id in contract.partners: victim = [_ for _ in contract.partners if _ != agent.id][0] nulled_contracts.append((victim, contract)) owed += ( contract.agreement["quantity"] * contract.agreement["unit_price"] ) # calculate compensation fraction if available > owed: fraction = self.compensation_fraction else: fraction = self.compensation_fraction * available / owed for victim, contract in nulled_contracts: victim = self.all_agents.get(victim, None) if victim is None: continue factory = self.a2f.get(victim.id, None) if factory is None: continue compensation = ( fraction * contract.agreement["quantity"] * contract.agreement["unit_price"] ) victim.on_contract_nullified( contract=contract, bankrupt_partner=agent.id, compensation=compensation ) factory.receive(compensation) self.nullify_contract(contract) def nullify_contract(self, contract: Contract): self.__n_nullified += 1 contract.nullified_at = self.current_step def evaluate_insurance( self, contract: Contract, agent: SCMLAgent, t: int = None ) -> Optional[float]: """Can be called to evaluate the premium for insuring the given contract against breachs committed by others Args: agent: The agent buying the contract contract: hypothetical contract t: time at which the policy is to be bought. If None, it means current step """ against = [self.agents[_] for _ in contract.partners if _ != agent.id] if len(against) != 1: raise ValueError("Cannot find partner while evaluating insurance") return self.insurance_company.evaluate_insurance( contract=contract, insured=agent, against=against[0], t=t ) def buy_insurance(self, contract: Contract, agent: SCMLAgent) -> bool: """Buys insurance for the contract by the premium calculated by the insurance company. Remarks: The agent can call `evaluate_insurance` to find the premium that will be used. """ against = [self.agents[_] for _ in contract.partners if _ != agent.id] if len(against) != 1: raise ValueError("Cannot find partner while evaluating insurance") return ( self.insurance_company.buy_insurance( contract=contract, insured=agent, against=against[0] ) is not None ) def _process_annotation( self, annotation: Optional[Dict[str, Any]] ) -> Dict[str, Any]: """Processes an annotation stripping any extra information not allowed if necessary""" if annotation is None: return {} if not self.strip_annotations: return annotation annotation = { k: v for k, v in annotation.items() if k in ("partners", "cfp", "buyer", "seller") } return annotation def run_negotiation( self, caller: "Agent", issues: Collection[Issue], partners: Collection["Agent"], roles: Collection[str] = None, annotation: Optional[Dict[str, Any]] = None, mechanism_name: str = None, mechanism_params: Dict[str, Any] = None, ) -> Optional[Tuple[Contract, AgentMechanismInterface]]: annotation = self._process_annotation(annotation) return super().run_negotiation( caller=caller, issues=issues, annotation=annotation, partners=partners, roles=roles, mechanism_name=mechanism_name, mechanism_params=mechanism_params, ) def request_negotiation_about( self, req_id: str, caller: "Agent", issues: List[Issue], partners: List["Agent"], roles: List[str] = None, annotation: Optional[Dict[str, Any]] = None, mechanism_name: str = None, mechanism_params: Dict[str, Any] = None, ): annotation = self._process_annotation(annotation) return super().request_negotiation_about( req_id=req_id, caller=caller, issues=issues, annotation=annotation, partners=partners, roles=roles, mechanism_name=mechanism_name, mechanism_params=mechanism_params, ) @property def winners(self): """The winners of this world (factory managers with maximum wallet balance""" if len(self.factory_managers) < 1: return [] if 0.0 in [self.a2f[_.id].initial_balance for _ in self.factory_managers]: balances = sorted( ((self.a2f[_.id].balance, _) for _ in self.factory_managers), key=lambda x: x[0], reverse=True, ) else: balances = sorted( ( (self.a2f[_.id].balance / self.a2f[_.id].initial_balance, _) for _ in self.factory_managers ), key=lambda x: x[0], reverse=True, ) max_balance = balances[0][0] return [_[1] for _ in balances if _[0] >= max_balance] def on_event(self, event: Event, sender: "EventSource") -> None: """ Called whenever an event is raised for which the `World` is registered asa listener Args: event: The event sender: The sender Returns: None """ if event.type == "new_record" and event.data["section"] == "cfps": cfp = event.data["value"] product = cfp.product for m in self.__interested_agents[product]: if m.id != cfp.publisher: m.on_new_cfp(cfp) elif event.type == "will_remove_record" and event.data["section"] == "cfps": cfp = event.data["value"] product = cfp.product for m in self.__interested_agents[product]: if m.id != cfp.publisher: m.on_remove_cfp(cfp) def _contract_record(self, contract: Contract) -> Dict[str, Any]: c = { "id": contract.id, "seller_name": self.agents[contract.annotation["seller"]].name, "buyer_name": self.agents[contract.annotation["buyer"]].name, "seller_type": self.agents[ contract.annotation["seller"] ].__class__.__name__, "buyer_type": self.agents[contract.annotation["buyer"]].__class__.__name__, "product_name": self.products[contract.annotation["cfp"].product], "delivery_time": contract.agreement["time"], "quantity": contract.agreement["quantity"], "unit_price": contract.agreement["unit_price"], "signed_at": contract.signed_at if contract.signed_at is not None else -1, "nullified_at": contract.nullified_at if contract.nullified_at is not None else -1, "concluded_at": contract.concluded_at, "penalty": contract.agreement.get("penalty", np.nan), "signing_delay": contract.agreement.get("signing_delay", 0), "signatures": "|".join(str(_) for _ in contract.signatures), "issues": contract.issues if not self.compact else None, "seller": contract.annotation["seller"], "buyer": contract.annotation["buyer"], } if not self.compact: c.update(contract.annotation) c["n_neg_steps"] = contract.mechanism_state.step return c def _breach_record(self, breach: Breach) -> Dict[str, Any]: return { "perpetrator": breach.perpetrator, "perpetrator_name": breach.perpetrator, "level": breach.level, "type": breach.type, "time": breach.step, } def on_contract_signed(self, contract: Contract): super().on_contract_signed(contract=contract) self.contracts[contract.agreement["time"]].add(contract) def _get_executable_contracts(self) -> Collection[Contract]: """Called at every time-step to get the contracts that are `executable` at this point of the simulation""" return self.contracts.get(self.current_step, []) def _delete_executed_contracts(self) -> None: self.contracts.pop(self.current_step, None) def _contract_finalization_time(self, contract: Contract) -> int: """ Returns the time at which the given contract will complete execution Args: contract: Returns: """ return contract.agreement["time"] + self.transportation_delay def _contract_execution_time(self, contract: Contract) -> int: """ Returns the time at which the given contract will start execution Args: contract: Returns: """ return contract.agreement["time"] def _contract_size(self, contract: Contract) -> float: return contract.agreement["unit_price"] * contract.agreement["quantity"] @property def business_size(self) -> float: """The total business size defined as the total money transferred within the system""" return sum(self.stats["activity_level"]) @property def agreement_rate(self) -> float: """Fraction of negotiations ending in agreement and leading to signed contracts""" n_negs = sum(self.stats["n_negotiations"]) n_contracts = len(self._saved_contracts) return n_contracts / n_negs if n_negs != 0 else np.nan @property def cancellation_rate(self) -> float: """Fraction of negotiations ending in agreement and leading to signed contracts""" n_negs = sum(self.stats["n_negotiations"]) n_contracts = len(self._saved_contracts) n_signed_contracts = len( [_ for _ in self._saved_contracts.values() if _["signed"]] ) return (1.0 - n_signed_contracts / n_contracts) if n_contracts != 0 else np.nan @property def contract_execution_fraction(self) -> float: """Fraction of signed contracts successfully executed""" n_executed = sum(self.stats["n_contracts_executed"]) n_signed_contracts = len( [_ for _ in self._saved_contracts.values() if _["signed"]] ) return n_executed / n_signed_contracts if n_signed_contracts > 0 else np.nan @property def breach_rate(self) -> float: """Fraction of signed contracts that led to breaches""" n_breaches = sum(self.stats["n_breaches"]) n_signed_contracts = len( [_ for _ in self._saved_contracts.values() if _["signed"]] ) if n_signed_contracts != 0: return n_breaches / n_signed_contracts return np.nan PK!a))negmas/common.py"""Common data-structures and classes used by all other modules. This module does not import anything from the library except during type checking """ import typing import uuid from copy import deepcopy from dataclasses import dataclass, field, fields from typing import List, Optional, Any, TYPE_CHECKING from .helpers import unique_name from .java import to_java, to_dict, PYTHON_CLASS_IDENTIFIER if TYPE_CHECKING: from .mechanisms import Mechanism from .outcomes import Issue, Outcome __all__ = [ "NamedObject", "AgentMechanismInterface", "MechanismState", "register_all_mechanisms", "NegotiatorInfo", "_ShadowAgentMechanismInterface", ] _running_negotiations: typing.Dict[str, "Mechanism"] = {} @dataclass class NegotiatorInfo: name: str """Name of this negotiator""" id: str """ID unique to this negotiator""" type: str """Type of the negotiator as a string""" @dataclass class MechanismState: """Encapsulates the mechanism state at any point""" running: bool = False """Whether the negotiation has started and did not yet finish""" started: bool = False """Whether the negotiation has started""" step: int = 0 """The current round of the negotiation""" time: float = 0.0 """The current real time of the negotiation.""" relative_time: float = 0.0 """A number in the period [0, 1] giving the relative time of the negotiation. Relative time is calculated as ``max(step/n_steps, time/time_limit)``. """ broken: bool = False """True if the negotiation has started and ended with an END_NEGOTIATION""" timedout: bool = False """True if the negotiation was timedout""" agreement: Optional["Outcome"] = None """Agreement at the end of the negotiation (it is always None until an agreement is reached)""" n_negotiators: int = 0 """Number of agents currently in the negotiation. Notice that this may change over time if the mechanism supports dynamic entry""" has_error: bool = False """Does the mechanism have any errors""" error_details: str = "" """Details of the error if any""" @property def ended(self): return self.started and ( self.broken or self.timedout or (self.agreement is not None) ) def __str__(self): return str(self.__dict__) def __repr__(self): return self.__dict__.__repr__() def __hash__(self): return hash(str(self)) def __eq__(self, other): return self.__hash__() == other.__hash__() def __copy__(self): return AgentMechanismInterface(**self.__dict__) def __deepcopy__(self, memodict={}): d = {k: deepcopy(v) for k, v in self.__dict__.items()} return AgentMechanismInterface(**d) def __getitem__(self, item): """Makes the outcome type behave like a dict""" return self.__dict__[item] def keys(self): return self.__dict__.keys() def values(self): return self.__dict__.values() def asdict(self): """Converts the outcome to a dict containing all fields""" return {_.name: self.__dict__[_.name] for _ in fields(self)} class Java: implements = ["jnegmas.common.MechanismState"] @dataclass class AgentMechanismInterface: """All information of a negotiation visible to negotiators.""" id: str """Mechanism session ID. That is unique for all mechanisms""" n_outcomes: Optional[int] """Number of outcomes which may be None indicating infinity""" issues: List["Issue"] """Negotiation issues as a list of `Issue` objects""" outcomes: Optional[List["Outcome"]] """A lit of *all possible* outcomes for a negotiation. None if the number of outcomes is uncountable""" time_limit: float """The time limit in seconds for this negotiation session. None indicates infinity""" step_time_limit: float """The time limit in seconds for each step of this negotiation session. None indicates infinity""" n_steps: int """The allowed number of steps for this negotiation. None indicates infinity""" dynamic_entry: bool """Whether it is allowed for agents to enter/leave the negotiation after it starts""" max_n_agents: int """Maximum allowed number of agents in the session. None indicates no limit""" annotation: typing.Dict[str, Any] = field(default_factory=dict) """An arbitrary annotation as a `Dict[str, Any]` that is always available for all agents""" def random_outcomes( self, n: int = 1, astype: typing.Type["Outcome"] = dict ) -> List["Outcome"]: """ A set of random outcomes from the issues of this negotiation Args: n: number of outcomes requested astype: A type to cast the resulting outcomes to. Returns: List[Outcome]: List of `n` or less outcomes """ return _running_negotiations[self.id].random_outcomes(n=n, astype=astype) def discrete_outcomes( self, n_max: int = None, astype: typing.Type["Outcome"] = dict ) -> List["Outcome"]: """ A discrete set of outcomes that spans the outcome space Args: n_max: The maximum number of outcomes to return. If None, all outcomes will be returned for discrete issues astype: A type to cast the resulting outcomes to. Returns: List[Outcome]: List of `n` or less outcomes """ return _running_negotiations[self.id].discrete_outcomes( n_max=n_max, astype=astype ) def outcome_index(self, outcome: "Outcome") -> Optional[int]: """ The index of an outcome Args: outcome: The outcome asked about Returns: int: The index of this outcome in the list of outcomes. Only valid if n_outcomes is finite and not None. """ return _running_negotiations[self.id].outcome_index(outcome) @property def participants(self) -> List[NegotiatorInfo]: return _running_negotiations[self.id].participants @property def state(self) -> MechanismState: """ Access the current state of the mechanism. Remarks: - Whenever a method receives a `AgentMechanismInterface` object, it can always access the *current* state of the protocol by accessing this property. """ return _running_negotiations[self.id].state @property def requirements(self) -> dict: """ The protocol requirements Returns: - A dict of str/Any pairs giving the requirements """ return _running_negotiations[self.id].requirements @property def n_negotiators(self) -> int: """Syntactic sugar for state.n_agents""" return self.state.n_negotiators def __str__(self): return str(self.__dict__) def __repr__(self): return self.__dict__.__repr__() def __hash__(self): return hash(str(self)) def __eq__(self, other): d1 = self.__dict__ d2 = other.__dict__ for k in d1.keys(): if d2[k] != d1[k]: return False return True def __copy__(self): return AgentMechanismInterface(**self.__dict__) def __deepcopy__(self, memodict={}): d = {k: deepcopy(v) for k, v in self.__dict__.items()} return AgentMechanismInterface(**d) def __getitem__(self, item): """Makes the outcome type behave like a dict""" return self.__dict__[item] def keys(self): return self.__dict__.keys() def values(self): return self.__dict__.values() def asdict(self): """Converts the object to a dict containing all fields""" return {_.name: self.__dict__[_.name] for _ in fields(self)} class _ShadowAgentMechanismInterface: """Used to represent an AMI to Java. """ def randomOutcomes(self, n: int): return to_java(self.shadow.random_outcomes(n)) def discreteOutcomes(self, nMax: int): return to_java(self.shadow.discrete_outcomes(n_max=nMax)) def outcomeIndex(self, outcome) -> int: return to_java(self.shadow.outcome_index(outcome)) def getParticipants(self) -> List[NegotiatorInfo]: return to_java(to_java(self.shadow.participants)) def getOutcomes(self): return to_java(to_java(self.shadow.outcomes)) def getState(self) -> MechanismState: return to_java(self.shadow.state) def getRequirements(self) -> typing.Dict[str, Any]: return to_java(self.shadow.requirements) def getNNegotiators(self) -> int: return self.shadow.n_negotiators def __init__(self, ami: AgentMechanismInterface): self.shadow = ami def to_java(self): return to_dict(self.shadow) class Java: implements = ["jnegmas.common.AgentMechanismInterface"] def register_all_mechanisms(mechanisms: typing.Dict[str, "Mechanism"]) -> None: """registers the running mechanisms. Used internally. **DO NOT CALL THIS.**""" global _running_negotiations _running_negotiations = mechanisms class NamedObject(object): """The base class of all named entities. All named entities need to call this class's __init__() somewhere during initialization. Args: name (str): The given name of the entity. Notice that the class will add this to a base that depends on the child's class name. """ def __init__(self, name: str = None) -> None: if name is not None: name = str(name) self.__uuid = (f"{name}-" if name is not None else "") + str(uuid.uuid4()) if name is None or len(name) == 0: name = unique_name("", add_time=False, rand_digits=16) self.__name = name super().__init__() @classmethod def create(cls, *args, **kwargs): """Creates an object and returns a proxy to it.""" return cls(*args, **kwargs) @property def name(self): """A convenient name of the entity (intended primarily for printing/logging/debugging).""" return self.__name @name.setter def name(self, name): self.__name = name @property def uuid(self): """The unique ID of this entity""" return self.__uuid @uuid.setter def uuid(self, uuid): self.__uuid = uuid @property def id(self): """The unique ID of this entity""" return self.__uuid @id.setter def id(self, id): self.__uuid = id PK!/negmas/events.py"""Implements Event management""" import itertools import random from collections import defaultdict from typing import Any, Dict, Union, Optional, Set from dataclasses import dataclass from negmas import NamedObject __all__ = [ "Event", "EventSource", "EventSink", "Notification", "Notifier", "Notifiable", ] @dataclass class Event: __slots__ = ["type", "data"] type: str data: Any class EventSource: """An object capable of raising events""" def __init__(self): super().__init__() self.__sinks: Dict[str, list] = defaultdict(list) def announce(self, event: Event): """Raises an event and informs all event sinks that are registerd for notifications on this event type""" sinks = self.__sinks.get(event.type, []) random.shuffle(sinks) for sink in sinks: sink.on_event(event=event, sender=self) def register_listener(self, event_type: str, listener: "EventSink"): self.__sinks[event_type].append(listener) class EventSink: def on_event(self, event: Event, sender: EventSource): pass @dataclass class Notification: __slots__ = ["type", "data"] type: str data: Any class Notifier(NamedObject): def notify(self, notifiable: "Notifiable", notification: Notification): notifiable.on_notification(notification=notification, notifier=self.id) class Notifiable: def on_notification(self, notification: Notification, notifier: str) -> None: pass PK!J2J2negmas/external/NegLoader.class4/ ^                ! "#  $%  &'( ) * + ,-./ #0 "1 "2 345 6789 6: ; <= <+ <>? 1@A 3BCD 60E 8F GHI ;J GKL >JM @NO B0PQ ER ST DUV IW X WY 8Z [\ ] ^ _` _ab S+ ,c de Wf g 1hi [jkl m no ,p qr q+ <s tu B4v gw \ x y z^{ m| }~ p+    }; [ >  1    6 g v t [ 1  }^ 6 6 S m Z   [@ m     &     & Serialize InnerClassesjarNameLjava/lang/String;partiesLjava/util/HashMap; SignatureTLjava/util/HashMap;agents9Ljava/util/HashMap;is_party:Ljava/util/HashMap;infosKLjava/util/HashMap;ids;Ljava/util/HashMap;domains:Ljava/util/HashMap; util_spacesPLjava/util/HashMap; first_actions issues_allVLjava/util/HashMap;>; string2valuesLjava/util/HashMap;>;>; string2issuesfLjava/util/HashMap;>; timelinesILjava/util/HashMap;n_agentsI INTERNAL_SEP ENTRY_SEP FIELD_SEP()VCodeLineNumberTabletest&(Ljava/lang/String;)Ljava/lang/String; StackMapTable%.AcreateNegotiationInfo_(Ljava/lang/String;Ljava/lang/String;ZIJLjava/lang/String;)Lnegotiator/parties/NegotiationInfo;DEMOPV#on_negotiation_start=(Ljava/lang/String;IJJZLjava/lang/String;Ljava/lang/String;)V? create_agentactionToString/(Lnegotiator/actions/Action;)Ljava/lang/String; choose_actionchoose_action_agentichoose_action_partyreceive_message](Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Ljava/lang/Boolean;receive_mesasge_agentreceive_message_partyinit_str_val_conversion<(Ljava/lang/String;Ljava/util/ArrayList;)Ljava/util/HashMap;b(Ljava/lang/String;Ljava/util/ArrayList;)Ljava/util/HashMap;>;str2bid6(Ljava/lang/String;Ljava/lang/String;)Lnegotiator/Bid; informMessage(Ljava/lang/String;I)V(Ljava/lang/String;)VgetNamemain([Ljava/lang/String;)V SourceFile negload.java )../genius-8.0.4-jar-with-dependencies.jar <> <> <> java/util/HashMap java/util/ArrayList java/lang/StringBuilderJar   java/util/jar/JarInputStreamjava/io/FileInputStream    .class /\.    +negotiator/parties/AbstractNegotiationParty java/lang/Exception negotiator/DomainImpl'negotiator/utility/AdditiveUtilitySpace  &negotiator/timeline/ContinuousTimeline  $negotiator/timeline/DiscreteTimelinenegotiator/Deadline negotiator/AgentID4negotiator/persistent/DefaultPersistentDataContainerNegLoader$Serialize   "negotiator/parties/NegotiationInfo        negotiator/issue/Issue  java/lang/Boolean  negotiator/Agent 'Agent %s: time limit %d, step limit %d java/lang/Object      negotiator/actions/Offer    java/lang/Integer     negotiator/issue/Value Offer!negotiator/actions/EndNegotiationEndNegotiationnegotiator/actions/AcceptAcceptFailure  negotiator/timeline/TimeLineInfo        negotiator/issue/IssueDiscrete 'negotiator/utility/AbstractUtilitySpace    negotiator/Bid  negotiator/actions/InformNumberOfAgents !Received options: %s  --die-on-exit "#  NegLoaderpy4j/GatewayServer $ % & :Gateway to python started at port %d listening to port %d java/io/BufferedReaderjava/io/InputStreamReader '(UTF-8) * + , - .java/io/IOExceptionjava/util/jar/JarEntryjava/lang/Stringnegotiator/DeadlineTypejava/util/Iteratorjava/lang/Classnegotiator/actions/Actionjava/util/List[Ljava/lang/String;java/lang/SystemoutLjava/io/PrintStream;append-(Ljava/lang/String;)Ljava/lang/StringBuilder;toString()Ljava/lang/String;java/io/PrintStreamprintln(Ljava/io/InputStream;)VgetNextJarEntry()Ljava/util/jar/JarEntry;endsWith(Ljava/lang/String;)Z replaceAll8(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;add(Ljava/lang/Object;)ZforName%(Ljava/lang/String;)Ljava/lang/Class; newInstance()Ljava/lang/Object;getDescriptionprintStackTrace((Lnegotiator/Domain;Ljava/lang/String;)VTIMELnegotiator/DeadlineType;(I)VROUND(ILnegotiator/DeadlineType;)V(LNegLoader;)V(negotiator/persistent/PersistentDataTypeDISABLED*Lnegotiator/persistent/PersistentDataType;C(Ljava/io/Serializable;Lnegotiator/persistent/PersistentDataType;)V(Lnegotiator/utility/AbstractUtilitySpace;Lnegotiator/Deadline;Lnegotiator/timeline/TimeLineInfo;JLnegotiator/AgentID;Lnegotiator/persistent/PersistentDataContainer;)Vput8(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;valueOf(Z)Ljava/lang/Boolean; getDomain()Lnegotiator/Domain;negotiator/Domain getIssues()Ljava/util/List;iterator()Ljava/util/Iterator;hasNext()Znext(Ljava/lang/Object;)Vget&(Ljava/lang/Object;)Ljava/lang/Object; booleanValueinit'(Lnegotiator/parties/NegotiationInfo;)Vjava/lang/Long(J)Ljava/lang/Long;format<(Ljava/lang/String;[Ljava/lang/Object;)Ljava/io/PrintStream;java/util/UUID randomUUID()Ljava/util/UUID;isAssignableFrom(Ljava/lang/Class;)ZgetAgent()Lnegotiator/AgentID;getBid()Lnegotiator/Bid; getValues()Ljava/util/HashMap;keySet()Ljava/util/Set; java/util/SetintValue()I(I)Ljava/lang/Object;MapUtil mapToStringG(Ljava/util/Map;Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String; chooseAction-(Ljava/util/List;)Lnegotiator/actions/Action; incrementcontains(Ljava/lang/CharSequence;)Z'(Lnegotiator/AgentID;Lnegotiator/Bid;)V(Lnegotiator/AgentID;)VReceiveMessage(Lnegotiator/actions/Action;)VreceiveMessage2(Lnegotiator/AgentID;Lnegotiator/actions/Action;)Vequalssplit'(Ljava/lang/String;)[Ljava/lang/String; getNumber(I)Ljava/lang/Integer;)(Lnegotiator/Domain;Ljava/util/HashMap;)V;(Lnegotiator/AgentID;Ljava/lang/String;Ljava/lang/Object;)VparseInt(Ljava/lang/String;)I(Ljava/lang/Object;I)VstartgetListeningPortinLjava/io/InputStream;java/nio/charset/Charset.(Ljava/lang/String;)Ljava/nio/charset/Charset;2(Ljava/io/InputStream;Ljava/nio/charset/Charset;)V(Ljava/io/Reader;)VreadLineexit ^i******** * * * * ******Y*Y*Y*Y*Y*Y *Y *Y *Y *Y*Y*Y zqY Z[\]^#_(`-a2d7e<fAhFjLkRlXrcsntyuvwxyz{|}~YMY* !"Y#Y*$%N-&:$'(),'*+,-W+.:/!01:2N-45$3>$7=BERflw%7  L J6Y+7:8Y,9: :: ;Y<: =: >Y?: @Y A: 7 BYC:DYEY*FGH:IY    J:*KW*KW*  KW* KW* KW* LKW MN:*KW* *OKWY:P:QRS:TKW* KW:U=>3z -2=JNYm,/;>@Hh-%5 **+VWXD*+V1: *  ! +Y:  *+V1 Z*+V[:  \]^Y*+_SY`SY!`SaW:#>CDTWdi~U5   u+.MY+bc N1,d',01:*-LKW*-KW$,0[:*-LKW*-KW-M,45lm3:&/<GJS`kmnrJ  &+efMN+g+ghN-i:-j:Y:kl:Q9Rm:ndoSTVpqKW**r:Y,*s* +t%Y,*u* +v%Y,*w* Y,*x* F  !'0Ry |  )<?5((F*+VWX *+y*+zr*+V[M* +VWX>*+V{:Y: v|Wt|Wg|W,}:> >~*2  (1 5!?"I#S$[%c&k'?+r*+V1M* +VWX>*+V{:Y: v|Wt|Wg|W,:> >~*2 + ,-(.1/50?1I2S3[4c5k6?+N%*+VWX *+,-*+,-:;< *+V[:* +VWX6* +LKW*+:BY,C:: -sgY: 0-wvY: -utY:  L>A BC"D/E8FBGEHNI^KgLwNOPQ/. *+V1:* +VWX6* +LKW*+:BY,C:: -sgY: 0-wvY: -utY:  L>W XY"Z/[8\B]E^N_^agbwdefg/. ~YN,P:QgRS:T:-YKW::Q&Rp: -V q KW֧-* kl$m+n9oCpbqvrys|tF= ,m* +VN*+V:,5,*:Y::66  j 2:  *:  2:    25: * +V VS* +V V VKW Y->y z|"}$~.7Q\btX$ ,A>T4Y*+VBN*+V1*+VB-3W7Y*+VB*M*+V1*+VB,6X/*+VWX*+V12*+V[   rb<=^aW>*5*2:^YSaW= <˲^aWYNY-:6^YSYSaW.YY:W :b 2<AGMZbmry++p    EPK!negmas/external/__init__.pyPK!nNu,negmas/external/jnegmas-1.0-SNAPSHOT-all.jarPK  oN META-INF/PK MoNG!879META-INF/MANIFEST.MFMLK-. K-*ϳR03MuI,.RKMM,ӎ\\PK  oNjnegmas/PK LoNӠ(jnegmas/PyReadable.classSN@=X>c ƍ)11,P5RkZS VnM(R5&Mb=qNO& `;Y$!4fH_2Tq -~wMUe vy0-d9- k7w\[RG!U*Br&ce se]|ra> -]J6Ǡ{}Xl;u6,Rtڞɇ];GE `;(5Z8`=3&U3oܼҰE]nvNv.FԒʒĔrFq bJĜĤTk0ttb32p%e22BRP29yIY%l L Y؀" qPK LoNjnegmas/utilities/PK LoNbwT)jnegmas/utilities/PyUtilityFunction.classmj@QkV(=\zKE0׳ԙ!(w:qu9iUo\m@hI%1HN+S tK?PK LoNՎ2/jnegmas/utilities/AbstractUtilityFunction.classN@BQoxncPLPCm`HiI;5tqPӂmM9syx}p4u*6U5a Yg+̾7Maްk8ko:7;|**/\2zCjpӮ+˻@7VfIj{Rc!b(47}< &ɭ֖z֩i-zC}luYjcm{n4o hI*2!#~| c8czr){ӯ:1d9i3S1IiL 0O(_"U%b)gT'Sϲw__SV^l%ȊPK LoND:z'jnegmas/utilities/UtilityFunction.class;o>Nv6vvvFҢT̜TFВ̜̒JҼ<IJDFŬbRtfj>BFRļt}FeLmhX$+PK LoNjnegmas/outcomes/PK LoN7R2aljnegmas/outcomes/Issue.class;o>vvVv6FҢT̜T dz4U/+,A,+/5=7X?$9?7X, IKOJM. @PK LoNPcx"jnegmas/outcomes/OutcomeType.class;o>vvVv6FҢT̜TFҒԐʂTIJDFb|T>*ļt} L  $XPK LoNjnegmas/common/PK LoN')2)#jnegmas/common/MechanismState.class}O1N@!Ёh"Q(үSrN/ (а+vfgVϯWH njXo-!9;_Ex6YeyغtO\VAsWLfW:87zn9kB N;;/~)Wn8D`&L^^e F1`c.17oPK LoN#բ&"jnegmas/common/MechanismInfo.class}OJ@}ӤhK"x=o D{Pz߬k! Iy<dۋg1͛}8Cg)F8?7M-u*˚Iᕬ1=?q6-ᢨ^Y NvvVv6FҢT̜TFJĜĤTIJDFb} #HN?'1/]?)+5h#020I&PK LoN jnegmas/sao/PK LoN p&jnegmas/sao/AspirationNegotiator.classWksU~Om%m\TbQK ޠPq[ݸ)//t#_Ag88>6ٴc:9罝l߉h Q?)FZ\ɏb !겅LXbeC,w] ]^> "eYQ Ru0w+5 ʪp< gQn U+hpv]PUK- Cͪ5Ψ{I-jU5J欋yQ1攊*)Z1dVwqVy|MSjZHz/ `?Ղ*B Wj[b8=8bY1ӦkKS cU5՚`M$yjyW8Y=C{THFڛLfEHGHqǗ$Q"*eȒn#Sj%X|a{Qzu-MA9ߙn!ܬB}c \vaoNM]| :TnjGNu-=ske-a7)6at}u@zE7gdҮBv3qۈl?3ZAo$XP-kMWE$qTaq@*o>tV506wqqcýl7ty c*:gKdNaeO)9~:7NCܹp/s9 ƹb \WGڶ/ yV \u).R#ĕ n}~XDhr MmwRh߬ W~);p@8 YKv>&Z4;dnYl8b"1- @MBKziUV'f^W4H0>!#-^t^ Ӱ:$b9BGE{`Է3y`6k A*xYIf!wT>^LLD#H>D塗sa牠 a} o L T&yR$ʷITt_ޤ`pK$6){ :H><)L}. G)CiElc&흒8%츃/ sqRItL >?x'Gg;! ~A*1Iy%%*eˉe;qaB(F,auHaC`qk( k @FR?@'6o1/z) ʓ,ROiOv^ ؃D 'd\ݏd\7@Hةzo#8j1Vo7G*^EK #,{ށ1)uu\NXxgSAI&幇ۏj=G`%%bU~l[PӴӧx1mMH[S tA(ڞfȗOR4'[CZ".I]-+BZ#’*"ek>N%Egd\ qNM̴1|7ۛXjc&1q[mL|LYGo#*M&9A)huo) ȫ(`$׌112Tpפv %il>īRg)߉mے* PK LoNهBjnegmas/sao/SAONegotiator.classSKo@-nK_4Q2ءzr9ڧD:PkE;nUUO_|8oQ7:F0xL/ϫNEZ$}4sȪB\\[2Mg5}pwHWCbn,UOyMiCu]8чo/K+]`p8p0gp*[JmV`b֫xM@v SniKۂ=Ã"#Ó*>"i= PK LoNCK}Ɉ!jnegmas/sao/PySAONegotiator.class;o>nvvvvNv.FҢT̜TF`GĒ"IJDF鬼b|}4%  E9yIY% B0 Ή99I %MA1 X@H21PK LoNjnegmas/situated/PK LoNnaljnegmas/situated/Query.class;o>vvVv6FҢT̜T '4R/+,A,+/5=7X84$5E, IKOJM. @PK LoNxFX\z!jnegmas/situated/PyContract.class;o>Nv6vvvFҢT̜TFJIJDF鬼b̒Ē}F"ļt}TLP]bNNbRN*##33# db`PK LoNܝ~jnegmas/situated/Contract.classRKO@- E / zᾴ+,)-i&+=xm152ogvv??򐂦 *T8$rT3$#P2nوytd#R5\Cq`ZLOeL6Q_`wQS'ϝ9Fۘg5'T@-~O^̗/w#ȦX;c}MJ!in<YIᆷ;$|cx&Zdm2%w\%ȋVLCOgNހblC[  EWa=Db؈F@ mT"Ր.cXB^dUVd)1{@l/PK LoN_[0!&jnegmas/situated/PyBulletinBoard.classRNAF`_ٛza/^t(C]fIH2~eV w&Nuj {v2H1m-߫ux؈{;!{GHF+kJ?`iAxBܯ$w꭮hBZ NS,w>y͟ŕXPX'_OJ?N֮.ʿ i0mq))5H)adP Yw aPX~8S5){W7vvX(U8oցnu[:%lNJPK LoNni,jnegmas/situated/PyAgentWorldInterface.classSjAmr7%(ۆD.D3S;v^|(%*NU.N ئUH{SQЋ7Cv֋pv\J\ Ub;kkIM؊Fk}\9>?n 2ad> PK  oN.Ed jnegmas/JNegmasApp.classWwUlf2ݒ&}64@$6$6iKZjNI7lC_XA+G@"IJES؊0YNxw=&ދ^7a0|NJ|PLJb9N|@G | |'I2i1Y3y kZє7kNH{c-] ?X39; =$#D3悠~_*|%$(EQʉʔqfDOTx._y^TV,NZ|k<֐37y@G ¯ :lOjg" ^5Dkّ82c^z+[$%bM Pޖ F}} m;PWc&骧/w}E} //ۅ.$ .zf$P]hJ^&8xȋpO|dY9_7MmA[B$]8^J]h-\D&LJJG.~/abQi[=oM0/%ZW"˷?kK VuFdzB`M]YTi3I\"̹3gE7Έs#cg}vɦSR8K&A?.?zYu򛤄!u'GszGGW鼀R[QR/}%i!Vn%Րe'R"6[O%m;*ڷ#5g7Yp6@U"9)=cByRh>%UihM}ӈ4}ȱ| t 3ԫkD5QULb$F\.IrHk;Y0W?Uïr6t`ȧ܂FWF7FMR%fzg2PK MoN#jnegmas/apps/scml/factory_managers/PK MoNop*4jnegmas/apps/scml/factory_managers/ProductInfo.class;O06}Ж6  $Pqq*'Ab@H k0bKY_oۀAQæ-[>}Q*-`r.v"(N S, ů4F8qƨR-')C\aR)+2TфnZIz⤍)miSmBZ.F J2f+<30Lx`G1#mdW;!;ow s7CPӰOC* * 4|IFCz>%赪l|-+5feYne-ebatVᦕ>\u6ܝ,j/IJe.A|Qp\PL Z,{O=N znbg0htpbنjdղsq0B?C$y!(FfmϵU4ɢZљ8hjJt .DC"yItm:J0~ mbIJ4 &Tj7ټshOI0%dž2&jM~u;Pcz%[MU2M"f+[ ŕ}d{X ̴unA=Uײά<WLWC}߈~Z1yufnY·jчrKcK@ݐ bH AB,[v8~u]Dfj( >nJ{Z=Xr۷Htkޙ49 uZ'BhJ6qmP-[u0P=!QyZ fe}39S*ITGF5{gbE)9; 1JЏ j*Q$S,is"cˡ]X=PK LoNԼly7jnegmas/apps/scml/factory_managers/FactoryManager.classU_OAE/Fߎ4AbդPB|i]r{y1|0s{P5^fw73ݙx<*APb,,+يj PĚX-׏{V޶.JjY-l~$y7ƣQdP˽|_QۥE'YJaײw w*:b9sVo8Z$21c[NstwKbY70̋Qx$OG'S6/=i. ˌ @7U|1On68' :F\i:Ƥ)?ׯܙ7˟kNYQQy0A:QOHv˪!ql1?KYuҼwQrɏLSŚp/F]*;4l'k~w$0<`䛟g&P^)(%ܝig[9'ና p5[D} eXq:f7P_~ ۰wP߀=?PK MoNB}\@jnegmas/apps/scml/factory_managers/DoNothingFactoryManager.classVMs5~e;qb\BҴ@SR][ %VxWfw ?38p`Ïbx%7kǡ3a>Hڿ HvrvP!0a9I Hy8WVM澦dܤ=Z;LG`|谶M=vvا~æm33 NfvDQx>XNV-Ssk9W>Q[cuily~A8=,BW#X:~;em;F-tH ?_HGa-ٷ\!p5QטD.],I}̞g=곖Q IKcbޱ8}rЬ:&bVP9Pm}eSQnj%@BFIs:@K]aǨá BfP>Mx]0uqc2;1%0,,˚DVrw=cd皬dߴtf`6 +O7w k6;ev<. $\<瀈@/[@~N=+<[ch|]~èaV3$ɆFE\&5i&C;o; ~G-bo IWwOCni=E4x_b1I1G~XkjVXٻ ȧRe"RvSVZʮɔǐ G]OPHY-p S 9TH$wDjNH-"*;tB)t*)t<=LO☢aa0!$kTs62&V|t1@E!ȣo-x0}_P:OM"ƘX 7qd|5Q??/PK MoNӸl.2jnegmas/apps/scml/factory_managers/MiddleMan.classWksU~6I&\@ 6"TZI[ti$awox?A(3~s Q߳lM 3N&gy>>{U[q%. X[ 0ڐ%޳FWxJW@!% 0A CD)d%%Wu+r>6il5)F\@(-/)(iI/"-cŢB>cjSؒM͖D#A'hucBAUP&L ଀%"M v-橧+,?4?۝cY&#្ټb 9 p iWSX HTLf;l#"}-be(LXf&D,)Am_St74*IF)%B@oŕ.%fHظmg(rMaՐY*MVt6 񉙸6{D:?c6}M)JoRrS<Q[ R]ـ)`{Q<6[e47YZ4޺Pś𞥾9a{Z@ϐ5Zb޲<.܊Go gk#WQz42PK LoN&k9jnegmas/apps/scml/factory_managers/PyFactoryManager.classA @om" Q7EBadű`֢tH6z|8`)  ]{t|3I|̪b˹n?/KvIJ#X%zY/VW*aaLq܇q!_0B?0%O4L S gU$ԗ5 3B႐ ߮uqτ*~*~ '-ݓJf6Q.{I/k|^H&GO *y])*8`~ecFBjmko9L, zfxYVfOQu\`*T8/i蘼d\6ETH}*{ef2|3CߒxNΈ)M3ᖾU.rEdfʮ&l V19nxSFY>mJ_q"zPħoLwAm;d(UPE8?,5=f,=ZJjJ?LV&zghurndNUy=g%Q1\K_xnlF"AG=14MvϋM$%mm9Y;>cӂ$yCW>~CRG,g/aچ鳟)؟m9p(VDj }u4K5:vJĪq(EvsV#yvV5Ⱦ`of]5Dw2N͚c(] 8JTlbNY:[;aׁ{ʛ FtoxG{C?ંI^W0>̞:] oNa# 1|dSS4?⺎1|TǸXھ*:&pZGJ Sbi&gsb1,bIDꆎ9]=k&PF??,qʍ;k7\bQ\gͮTkrٹbӰcÚ&)&/;۠cW|FQF S+T8k8\Lx!g9ITw8~(IPn嚜)Ҩ##G9A`Yp^3e{hԻh6&b[f& 1ts't'-'BbZKLxaZ}oCCB̪׊"S+a*0"0A9;ږ & 6/b AKغm#x;`-a"wE&wHo TACU 譂>~ /~#U$8ZWkIFNGN7'X2I2y>yz792[ge9ԋ@XERO=웽L8PTB!v Tă"M! CTK/PG&(cz ^4w6J2a<3 AqN<˖[l%o}\cC3g@k{ȻjK=jƀ!giml{NȎYo.BZ^dGR&zj PK MoNjnegmas/apps/scml/common/PK MoNbN /jnegmas/apps/scml/common/ProductionReport.classU[Oe~fwaa8-T쁊`jXE-PhZvefw 镗^j&eklb%>)i~/2MMs"E,ѷ-jKy;A bYC +4#E\ŊlG1EBzĐaA/Fv[ߩ0T*,T*P+Qv̆͜mF%mJt%[,NŪm[v~_לqZֱ]ˮҠ fVe]p5*T>qYri4j)gfEɎFuʛKV+w<6N0; O,)'m9W-jXelwNYrʮD*\F\Q„oS*7%wSAUs?eȓ 㑑V!=cT֩YYWA1fza[գ'|U%QiW7̬;>IЦ%+o2c:%$:^u]ıF⊊,`N][r9mIjT|t"co눋HH"E t cDU\1&"OkvͼYֱAEZ­Ū*J:aC1 qjb+h?c^]Edk?<6oPGU|2,]6 UӻC=5.AW;*CTA=V&IEGZ^xk&ODWx׹% @FUuێ]݌$ -2IK 4dXa{h=kֶ'ld'Z착A6M`V95͕0UijV?U0uSyTteiv:j)k :el2RH?8BԷL[ܖzqg582*}M/Ъ-SW1z+Nv bQ%!BTĩ2q w *t4Ŕx ԡq`Bl>mhx<2-KG;Z:꒠vY}|GQcz>~#6bWavC'1 )Wzj|·GPD]Jt9ѕd?:CB&`4P6o;|sE^&w/lr%?Ad;a}GRX%>'GSxx<({}Lt%?vpiDQp(#G91L}V<&fϸSD|溘~ -|9qzVB /(G[# N2P&pHQĵu|l̎=}$C0~mēTbRzF!>C%,4d؟SԖ2?U&΄$g""]ׇZwBP_tz o0v3O;$Q*r&"wHf\^ȱUjPщ*Yg<5Uh=PK LoNQ2(jnegmas/apps/scml/common/SCMLAgent.classkPƟtMe.sYg_tQ2Cbe4f)MRT(s[Mr9ssJWeEXKCFSFK]Oq6zaxvq<'cr:\:r-"oOؙ0ԺCϲ]>1x<1&;2Lu}vۖT wa#0 O)8fP(өy#'s32C {-4 N'ւ a~)z#ӿj;]O:pft*VT<.P "瀱':Ͻ>ycAB$ۢN==C#ڟf/ fb~wi(ӺJX /aV Љe⨨n#F@ *zP1Ys1S&}θB݂lUSa)IMU_riU"^unDnRt 53Q rD_;E]L4aEBW }!'E2tgN8\oQEwPK MoNn%jnegmas/apps/scml/common/Breach.classRN@ëP1qcJXh.#be,CJ;5tewb>sN`YV`G]zO  1#PչnB{:A!0'&< ֧3m50lK5\vgԘhGߵGѧ􉪡zE Z@#eY?ys{1dQT玩- )3G‛:[NtSkinK=C@O:'6d[o1*ة +,2 1V(A3~$2] #b+^LZ*ڷD1#VLďgd`+ -6j PK MoNg1jnegmas/apps/scml/common/RunningCommandInfo.classTRA=@v BA]/x EphT&JfSɮU>-x'˞٠D ^tlo;< Gœ("xhQ'.qİ(x3#J.U1KQİq/21䪁56rvNHQ(]͕v-\iroWY$YQ``ˤ ghz)s*-q%C,?peN{*E0r{})K~ߑv S^/|c!DATbJq+iV_yJuS u)ݙ#Ś_ʊ+URn3(\7y*nRR /mW5]qKC_E纎8n Q9O<"1=Wjْ..vJN,ozeaWͬdnM- ⁷q,k ødaDt- .-d.3tm8&,L"0}a9*`F ` Ax3S&x9J0`:/CK45n]-/N◶SLj9RuIiILiId9Ez INU$gO5:#h :Mܢ[Ootm|P fb:֡M=t`>ՀO>ӀwkCO g jWC?sATa]l8hQw$qlx>[8G5]oHi3U;8K=ܯ7}X}j%vk'2oWc< 2!J]>Mw:Nrd*d,Ys-`?PK MoNc2jnegmas/apps/scml/common/FactoryStatusUpdate.classTAOQ-R@+TT@EE[ "*Foۥ,vw-IwMLs;NB m@KF@>ZIya\tZd`hL@{>]A7(bVɻ8疣Փsn1`x|C;D #7U׫. PD 0 #_rݴ4%H*ԁ5q %DAZ_y,9%sF@ !*'GH: a/Ҡr)גPK LoN=ñ0jnegmas/apps/scml/common/ProductionFailure.classUksT=v"GQRlj] iRhhk޴5! qq^EW<ܙ"v 7f# s%;q;H{q0UCE*SX8ΫŪ/T(Xƪ/UWq\TPz⸢ஊ$6fYZ& [RK{ l ږm b8n7mѽz б [=۶V%t{NQ`cy,=Tm_z.v]fy>V˒q>WW^kTebfUyjʈL,LAIIuvMۦ%Ys ]KchWctf-^խ6i:u+ΌP\ӽM3e(!'KۭBwI8b7W1PN,ON(Ɏә?`&Pyjj鹆j>Ot ҐCMU.- ;U7[{<.k7 Giix $+8=vDÏx 2'. 7pSr_J&7LN}Z&/gN6<{$l{f)nmGRؓ_M3~7Ɣ=%TfevQ,X%/W!9~>ߦeJA`~QJ>R+:==Cd =)oj qw>=d.F;|r??;}-|r&8 ]aQ*sc S#yҏ2y`0X<,pRXC8M`@>@Z1%n?$,㷟aȉ৞>^O_P/PAZ,(.PK MoN? "jnegmas/apps/scml/common/CFP.class[Pg h" x [ "h+M7&l]{{δ3:s>/u?ew|wsY?8/8D=ARTPQ\ D3c8Ϫ D#–9"*Ȃ[bX5'E>bDus*FE}^ŘT⌨/|YŸWxULHDtCy#7x+4DiNrIA}Ș կьnSv} B.UJ<>@͚V6uWz[i r[L;/IW3~c; Q░٦B\(iqSFF=`[W$x\)x(2%Y Zgb|L1q&P.g^} r)]3-cMB\RLeXgϘEb *z>_L42Y.eJ[yT{/z?x,Y#i isۥ/cґ$pvΑkڬ-ЁrB1%*+4L pXiY.cRûxSqs"}|A|VUl#m4|4㨆Ye9&q4>'N`Hð,'e_zmy cL|45[1Mp4|D\/t_UE[N.;xٹs*XmXJ\6x+$KM<$ʉ3~TӲ+~iRN*6~4ׄ&^vK'M/1Cѵv}Ҷr/A(x!QK~p+]y̕]6p+Orĕ\1Wvgs1ǝkM`58Kl܁G,}~kVpmGZPOjD891=iqFYwvs޹scf?~zelDIBRܐ4,0N0;*j8^ i0!aVŲң$ҺbUC!`=^S/V|t%ZUt-K -3n x0=2ˎ/£Us˭o5<*zO)mKSbtLA6(mF[sr*6gJ=Z&ʮ#6oy,6U:0:H05lnPګ0 -ߴyz5w1Ӯ^/m Vֶw^ɊYw(Z $}7nW[ZK-*2o= ~qtLKY53ٹua]xclwtotT7owv:Ć'!QQlx$x-qblNl/ T"~=Z6[-JEȈ #rn =I0G$+&|#z|8sYKK`#EZy/o<. !N`9Ò~!PѶ1Nebc,Pƣ-RNұGqؒdxhDH"~&btʕ. ]&tW#ү"0)NPp 1'{P A01Yp>E QgH^/Qۿ.GoFn PK MoN؇5O3jnegmas/apps/scml/common/RenegotiationRequest.classON0}פ @+6F6@/l $JuwUv Б;޻wOOH nj]g !99][ 8}ZwnY9Jvf[1&D82mz'7>wKŃ;̐r频D)_p+ZbQ7ZEcOEʘ1#g7&QLXb<]PK MoNdPb-jnegmas/apps/scml/common/ProductionNeed.classT]oG=c;Ͳ!MBK`;-N@ %$)P*E{c6w,R~Q_TLRշJ)g֎1ĕ23ss?\7PyX`c_JW\0ou ް3v]kgQ(qӸLrd~cېVDE@àմ9Rў#BpRlun} *hNHi^Z|. xW u֙xoTj3qL^G0AۼjjA /7IɃ0hU$9GiY:cuΎf֫<\<҃o:Fy?tقUz _(dNYȐAn&_?2Uj?c)q(<Daͽ噞d_mem`o9Ė:vn`99fY0Kso[:.4APup; \:kH.8y螫٧_opybd '!jFn!Lu`pJGfW,Tr7aO.mo90$=Ώ뻌ŧEnjx`&>=wq)UKd?1HP<0vs}SQ L:ޝ"8nx fFI` nlOX": !˱=>zvct";u1E1D63a49F_c.f_Y>5$g^ E|Bak꥜ݾ UCO,!_fBUcJ|(ك$>_f?PK MoN2m+jnegmas/apps/scml/common/MissingInput.classTkOP~κAT`%C3VFή%0Q Qt }9Cv[Y!3/C4ܦmcg&|"&KEVK`FhEH%t2"Lk<ʸB,U\ `F*EEn,)e"zXi3JV\XǐΡjmc'cIU!'3 }7D+qR)$ aaӏIsMd@0EVS!!oaH\Bu@LBwp$A BPKI&QHn f4YPK MoN}R#3;jnegmas/apps/scml/common/ManufacturingProfileCompiled.classTmSU~v  jADbj/%]f/O쌥qp͒,C99s *~-,j >UC ">0b9 +aZ[faV;Jүj_ˢ⚌e *RqO UY B+ cw<N{!Gc9#a ZdF mT.k[<5̀ ,d\_v\sz5bf&_w ao ߒ8Ifk\;f%-jTׄ #|=6ݖGרǞքX']#bF gF{2MKO),'vd¡Fߨ>hcOjL=Eq +|56"'oPᣥO$~6%˱0^"+P3ûqR{z{.s,>>.y_r)w_k|P ħR4p px,U.IA1`j $[Mŏ83.Šm0]x#Zf1(nuF7p3sy8%كoxs8 ʽ…6";&Q|wj׎ rI' b:93U,QG3]5F qPK LoN!w`%"jnegmas/apps/scml/common/Job.classTmSU~n%] ŶJCw+iiM nf0_W;#i8~sF_] ˞{9y׿#Ԓ+Ip]Ia]:fE1'򦎋 p;!װ) w=q)J5 v_oħ$4>86,1~4eT \gYۦ#p9oyz2n3[pĶَ_2m+Q~]A58QCeح6.{B&n{Ե&N=G]> 1ZrsG8ROY-MMUiyWnWXĽS|]π/CZ6rPK MoNSS*jnegmas/apps/scml/common/InputOutput.classT[SPBK؂wQĶ  ⅊ԩ∃chC $5=ag52#gBۡ}9='oYQ1]AB0d,c)8(2`RC*qe=>CFNS $(_e6;3Fh^B$g6P*M5lI-ڮ.pv,S%$^Jfumn0۳fUq̺nju^rzs n-` B5u2U7L=`vU0{@{)a\nEbVdsg*1cFk:,2OLH{9kMWd|X~y+Kk\fU,_ Ԑ@R{R&q,WX\75wiNB,,71T58y"D/vٶY ,zPY oY~-r}Ixs3KI[O]vL{FNR"99tDtj-Qf )'b$3Bn`[!;*lchGo 0F| M­\ij~GfH'HHK#"/ >He~ rbYʹ%K;ŘsKР-*%iӴ%a_Of569 m?PK MoNY.jnegmas/apps/scml/common/InsurancePolicy.classU{OP]*c| 6~Q"!|%沕QKך]$Ci72#YryswϹݯ~wNqbHC kvN8`JigR0!Q^q+X{̹Ozpy *XPi[- fȒ{߲Mrju|O}u,۲Y~ }n N+K˩Ѿ}ZE-:|~l:5n9?!K:ٛi` R!O"eeIz gf2>*O:EsѭX F $SuAfߪddmFd16a dsgUN9[=);< +&].XeGGug!wCvt[1Fj7żK8cj3n@9 :pJ9Y6=/Ri 53w2qF?:^F Hwvqnfܔh (00Y Ҕ%CJ&kY\&W)*iBI *2O}G$Ĉ[8\ǑeC4p,yAT_I(u*qy@k!j Vqv!<-ķIjwPK MoNjnegmas/apps/scml/awi/PK MoN{4?|U%jnegmas/apps/scml/awi/PySCMLAWI.classKB1ʼiZf?^B!EoWP z9vv yJɇ}Ϗ9;'ÙN8EQaC!bc Iji1A ZnAZ@?ِ!'jߌ=\(B[/5dHpd| Ej &RP[P8~Q3BoW4nΒn4ZJeC8o)ً bȨaӒݿ=5NLkf\/n5m)j>wmF~3FpY5~ͥ5xLWx.ʒlصi@-'mHYoz7`'֙Z {q\g ОPK  oNpy4j/PK 7'UMC,py4j/Py4JPythonClient.classmN@g)E<pǕ!h01NJIK d_ 2nWbv/gf?>h:pJ"g$3nFԏ)UN(N'zF~Ԕڅ{&1&1M=?׭cTN!W"Jv9Ȭ T6){ #WÿI]/3*3Ӈ((\IUqz'33dWb!'xH}ua 4 K {9%p,PBr-k@c pPK 7'UM?V(py4j/DefaultApplication.classuP]KA=}AoZVfQR!HOM6:^*Yps|}|8(&J&6,DPaCLzR3D+q? #=q;D[.UnR^䀡ǧ]J<.}WWCt.:v]BCtH"G`$+J}zҲL Y޵v;Q*BM /)&( al-X*lp0s= SDSD1#J6qY:aԳӫC^PK 7'UM#2 +py4j/Protocol.classX x[Օ>ǖdY^IlgC'd[N$ٱe'F_l%d$9ֲJHXR)3)t 3ӕaN2ّpg{=?=/셗h Kj;/;ǵUg'׋"Xة(rWX-6^i=eϵ^6*nZ5vYx'^k|_`'fx5*df;n1"ЬG6W#xWxmvqΝ%^l|yXb/bQ/Q8p!q*vఝܼmQxQ1_*X6N")DwxsDv /K J\v/ kZe7v=67716Ţd0 F\x׹% 3{[ /[[nߘe*hnl>5<>טk[Gc`*jw80&"Lw>vW1fA( ]ִ2Euַ{[/J m ]ҨphāύԠ85DiR@g .fr~ɠ {Z;m\noovW&5v3)MM'( ij\wRH0ڿ#GW>RH ij@ w"DzZ7=f_fw3/]4\&8ޅ7@xG4E6L:x@7Բ=]nӒuM8NvM>^5FTaX( Â'-ɁpBp,۶-KBSFC8T>zKLVr4B~5E "t!8 FڂqbK RbPx0DĥM :/勝aiFYSGu!MͰ2dw㱸qdg8Tϧ&~ry_` )-dj82nc0xӌŮXϘ.´k89`LAbըfжxx0 P){-JX{ҎlIĢHy&ΦH0ǒ-h9C5# &.PC(4(/Sd25FB #o[!QJL<OвӸԬE<ܤG =&ÐWOE LYgp(QQcRn7Cq5Dw}խjLOȌTKjk\M GZ_f80S{, >sl^%CJE@ 졉K*2lɘS }C+ā&$)N +Nt?he)2-=-40.p}qj![φ~=8DRa$Q̈D[Nh Z . '%U8pHm CjKXWj  u@ zB| mp4*Fw9< fJ/2͝=nu|%͜2` :x/r :xw}U#1g ie@SudztN87'T'|mu?o E/C.*F_waGsmӻz;zDhSG<u!zeW1?<ޓ*@O.O;~ N5RGRE ,r[p^p@S3)\Q:ֹh;"hrVz`7jӢQ{#ыe/9x!ppɝvCrJ -z&RyESgúhwv7/Q>L+a"sA6gPE_Mӫ=jHfSC3*c% 9cU/FYz(6)#n|9uphHe}Vf?JY/.[!d Z>:3e[ n'T741?zy^Z<){eX,Y5pDX9 3/1 'e1?Haz !5d;dG39ES=avb`ʫOdt\ֿY68!6~ݘJD ˲ GSZm9z#ңXvB9YZEU"3HT0aLv=:jcL&::iA0;A2#w=/3їD_ *}5/k@_k}&&7[@jo}&._6_U}7{L@kG z5LJ蹠4@4~#&QЇLtLt!Mt)`ØY_qWsr,Omz o@G(~izF|6Ś&wrNؽϴJs-ힾ{%ʵK(YF)o'y$A!.d!1MDI@!.`54kSS~' z$h!=.#u![;FG|TiTr4ELQ"{TD8$W\xf_zGAMZ^~KPsb_ -ԗPtv2N )Q;#V蕓Th??3'gs?9Aȇ|N2nOq>FڒQdDTh]*pHO4>3ytM.l =lӯp"t_vzvz<P7RlPf`d_ Ҝf*K7rgнYtq4K^=^I*ÿTf\~Hgt*.EY|Y,<1?._υr,Kŵ]!BMMGjjBhZ*MN7%|!b)SO2SVrB՜4O.w2ʉaQ23^ޥ$4= z;G=.M x3K_mlӱ\cY>)UK'8YlVMpӿҿI8 68(& .mR9pM:U]cRKT Za"t'`Msy<{<{9-+MW/tϧ_үK%ƒtl'h^/I9DA//E 5 \*@ D^l[SyH%( P._GSz7MH\Vrm۩2HFIZ+:u7<> ~.][IYVdT`CQ ?F8h~bA~Zگv؃@~nQl֎CGwza2nG{X3'd`=*?$nOQO~|Tkd:i7 EC~#6E.kX.?Tt)F}ۄKW@8_ߠi&,)oXoa / OIy[v?4Ⱦou^;Ad6^6GN'BKM~ .㟢xxτt γ^㔗l  cC2i;yk|hpnB;^ +11?{@uh]mNc; *_R) t&-RG&V#.`,Vs9z;I3.*TmOpب(;H% ډ t ifNUAzy)4.Up8] W~wz%Q ©`+YQc94+n *VRDSy*O241t%)-=@YrEYX-QNx!r.rVw\0MWe?$~xR|y6۲ qE6DLde6}D6M&r!rE2 vզbיN3RnQ;ېӡΔ: rIKsN J@&ċ &$RK:2 lFg}2#;fs2UDFf2ܚM<#x6'9?D6>_$?PK 7'UMQpy4j/Py4JJavaException.classuNP#*/(wpՈ571&*C=lI/*OqEsJC 4g̴_DR6lJRQPQdwc^K8i[wg ɐnؖqk/zݷ CnZw+}/tWc[8ݣJF r9,*ރ2-_&/{t{![һT*)xiujQ.?-W+np%R6AmMؾc SnK!E)9)+d^QD g4$ O:K EF1 i"P&)KLX@&h!қv$Tr#WHaȺD@vMŽ8F1L a2[F52IшF,|CٳPK 7'UMCv J py4j/JavaServer.classUmsD~8Q8IibvJxhݦq03o|8Jd#J ~0Mf>Nn0=:>~4551|C|aDh>CYEEiX0{*+خlGcnsp,^j2S/׻RCϭ:6sy{>3[¾Tk1s@Cgξb+SE[/+5<~d|ZSj f,uIgwrZJf3VpS:m݁\(XzݳWW3*+*WnmOX᥎<\oJb}mK=6ޢ!Tg-Z՗J>zD^l2^jz1BUT}kMmGvTq! bF1p=fAFèS#աm,h:΁ip|9\(w_zH`nϔ􅛁J ~Tzg+K DvR98OF2n Iv RHW3xq)]#)%E,UHxN[. $y oJ`|SgS<;WݍFH _#k$|E)>sw2Bi_*>$=_*;] )W@_E1rBe+#G![X%ex%]Ҧh=zHPK 7'UM py4j/CallbackConnection.classW |O$ !bP$ ́tH&dòggX[^jxUj=s(*m*>hWmmkof_~y}{L0X/pI-TW U\Qp ;eJeFku:qCpin2$028|Ku|[w pK!nwۄvCVw- 0(Ƃ`O+p_a}~ ÃxHؽOc:~$\S,s_jFT> { dՠm0wMsKCw[צp{M훺Z5wwUCqS˶z;ExsO4eryN$Z'{ؖ6E#״Q `wEY$fob\ܨIN&H=&8(U ӭM^KCI[$f6[v9j fnj7|{?X>PdF͞ Wq"9I j,ZX풖rӡYAe6+\Ǔ:4E&XoS|63Ɯ>/zO>G6,B=֠TP[rvӉ}BC%6ALȾi g'c ؚj n$5%brF)u } 7xZ3a!䐙p! '%"y<]"H ?65|XCNnB"CDs5I)xsx^ ^K6`0N0Ў | NSdN5e'"OUc2U9ȍ*/ W 7 |N oh;'Xʆw,?>l9Cq{kmIm~:*53bchJ_ m :eS8Süh]=4-8Kr -Z;zh:˃XMF-Z%0 LG -HiEAYM06t, X¬j]k%VMmZ |0OY)B{IDC+*tfL2񥠡4Lh7E#V,3˯z@I:.Ǻ{uXLF욅s)dy8ln#Lyo9ʋgS%kKynE"‡Cn`spВ_{PWܝxʙ#S6H?B&*.Z[bd;:;67u6hXv4G6YyPxbRiZ,^hǝxO/$泎%an̹j  /~5 [ שI(cXtE(<MR{;}2= & !^;P\~G/a>.b\HK}Vb5{9w^W2 v*\wǃp^®tR`&T2^"#${踏 w*uP]0) *!8 U2UO8H<ھxbjܜyiTҨTi5s/nΒ$K"d >a>*{SK JX85ޞln%6rE1zQYgiZɥjj%.K}A:]ǧ,[4Y^R i ҃,姅K@la-WUrGd"֣ڧ 6;ىXcsIaLc4 'y{<śi3YWf7Vh6a]R5Yr1#˖|XUQRBuw?2y`AFP_r njQơGjQG4Y,}b|anXKj!u}B_Pyk@]g9o2<|ыY 5eByTy尛x>Cc[+PK 7'UMSpy4j/ClientServer$1.class;o>#nvvvNFҢT̜TFAԼԢ"IJDF~׼̼tԒv.FJ,}d* Ewmk`kڵ}nn[vkw܀~w~w~|㗼/&xJ!J*Dz(7! Xw>D!;D ҟ|IcrƅAB h9Z.*Gr pi1-2'h&rrJUɧZx&yRnPkS)KeKBˆ+5J.Ja[%wij Z|ƭi|5n׸C o׉d9[xƝ!6\/kۃCLx;I3mMeLE=hf e0-_]nMdOL P6t1beWAFb$3F>GHLR)#if̾xiikTbê5-[vul_k5k[qL%-f2&34F3ﰵ"Sk=$xg\)eN`)n&69CXWK"nIm3fZSi;:ȴuwƍ X#WͱpjM|OoDSw`x2nUv2ZnC e;ԖhWh3&2ܺhı ǹZ2F%HtEc{֩$LS+>+^*[J4ћ7)VAb{Be6(:9A6FưwFM 5}K-UN@Bjgk m< j'dGQ(W^ UYC lƁV 9!_d͕.xY)ON+E 8D!TbM ^8f$dV˼ˈz*oc'S”8g5Za}<=ޙh*,ʝ^& `ׄaf1@ZiUZJ `+& "E^5XQ"wpM@U''ahwWPnj':Mk/nVOYަnW[w ZxrQ<ګѐ70v| 镩TtpRO6bh4nؐRߴ䏧Y鍩x_<$Wm62*B?l3HEؗݴv3.EN,_KnSbCD4^oF;t_xY"}x8!.yqw4f} O'#>m(_Mv'/}cwJtCwebx;HŌq R:I0\Y&[5t/I9MUҔiSb]w{}9y}JurNm:Nw4H7te8uR7եHL3f&z/66=2]e2f8Gpd`89Hp,LpVX:ȯ[F4 G[{ν_5O(ޫsdm&}J~Vps71,{ixNߡt}#58?|@2=z klt~ ŋ{e[6oVeTiJEbc1MLz@ 9b]:?n>Mн :ǷeO/huzDrϔs>!LfZEe­ݦ:LX Qk}LoӪxQUW <pbY[zkTVsNGuw|?S1AOt$ cӴ 61YdYsՍfFbJ-Ŧڳ)?-e?h܎O6QSFϸxY F[3fyyW&au!L6Bۂ3  B{4LW䣡xӚ-[7uкj;xw>Ouw3QT4o74I*uJzPws & S4=cL [ޡ`*'mv\& x+LSpez1OV>տ1eL.)ghfZ롕αsw9J[{ xL{nMirNꞖ\Q`~y^B@WڎjusP洲te9}n!~WK;rGٝ_ [cpijrZ3Q{j4˜yd c()J(ID!n¬RŸBZ`>ڏj}6hb:Z_EC?hP/]EGNjߙ{'߻0 BE$"BH>D{He%^[ؗqD;#' r $ cP;Aa! O(a*;A"'*GkӹG}PZDC xHrö:Kz ΜP1cno R#G}#tĖ«C~.)mn9aC9^UuzTGG-IGT@oQaz \~=6[aР-~O >J\'<6W7?'t+dD ̪=Ds (8DeCTx,Gb# OWݛ N*Ql#cnE<b(ru+"CTL~qBT!9J V9%hm.hxi^qzYjzB4gerkuGV~v4?OFLô˷ yIjeXT]+* 꼍+Fhl\HIj9*Q-jP̴aZ۞cM )TE_)t5 r)B+꠯vzvY䬗P_$ue7Woo$ i߂oc9pw02N9t,T@3Q3Z j qnˡ9CEˡ==NECp]$tk!PUI5ӫKD= O*a`LMrdKT|!pi0nE+sC0B255!Z߬5~7"5!8Np m#\uV5j|g}R~j|'igpR-AA6_6A=|<@^Gx'Q_:bW_S{7Z!=Gѥo}P þm0X1 W̝_BK݄rxA`p у@W`R,("+k_3>^F/)i}}F/%mXn+X@?8hr㾭ykfu5zqYgvnYQmCtb. oY; mV s{s0RCC@MHrL_A/PPU {X,td8؅u%4Ki Oeh4Vp]Ǖ(œ>x }gqJO4z)O z_B/Lz(܁v"7?ڕBKQ\EC*NBK5B,Xh#r-HuA9d -TY(P#X_n)*ܬ pYU!P !AaӅs8XTIn= |ќ+7zاOJ PK 7'UM1=oZ-py4j/GatewayServer$GatewayServerBuilder.classKped $@HxòVQLx%,nI63avݣoZUUl UzЃ=E|, X[k__w~OX1 ZhqZ3<,wOHcg縛p^G;]/p"xuhj)h1/+PR Zyy$BAA/'SC ڳXYž"m,3WYiSobHplw&yr|431yb@xi?: !Z,ܨ;7g:9:hg,v>9fX%mO9_,^/?7 @WV=t~2;k9mOL@ӰAj|Ǥب#cc.e,o-)'M|m:J#E;<FnVZ$cم[vU~f3,BƶOpʜ/zO#~$0FE,*568yXytY&ԅXJPp2~GɁcP:_ݳk#K(]HCh #chbF1OzFF}V{BcSBY}H7F E $D$E4$2K\Ccjw =1XF%LJBLVmtW}Y}q'P JfXx)q-7~+":hv +py4j/ClientServer$ClientServerBuilder.classmSW RyBŊhUT J7ÆllB}v&;Gs64 ν9gO~3Tᶂ6rT4cgwجYe&.>ٺ }6l>f4[*z@6>U𙂇s"%\ΑŢ@:3tgRdy+ռSl[f-@JH3WED*m9,X6mS=E޴wggIE$̒[Hޥ;thiܐ0msWHQVᱴ3Ӯcٻ-[*@׺e{tɅ6}1YTRޢݪKV>ǺUYʛŢãS5Lcy:j[v30ng</4|4ŨF0s&0A$ma oQՐ<OXrYʻ7Jp]F}Λ<},O#T̨[Dnڝ`{t׬w+tyQ\+OW,fCzmmr &BO}44qѬ|?þ?wH-uH獺?RN=h]x ~.Ui^0pȄ9Er MF<󲂘-b3*P^\A+h訠ӘˈU& +b ЉE'|M$!(*bު&_/ϸ*%VgZWBCLˤLˤLbˤLBˤL"ˤ8%\9[=*xx?IHnucu <﵏_[T/{uraUQ Yߋ:@VDY>ۅ6 w܆y i㒀a-b=jNn8QD* lok&k9%3;|㛊v1j` 1c`ۃS~KѝHm&t\ c\xjc1\4b+9b_x4"CQb7-(I"J.Fw]2&::p$mJѶMr}c;e%h;YOEU7ĉqk; U*ќ_Є˒ou]/"4wY.z>g-b^ 27h,Vz~İ F FҷͩPK 7'UMFppy4j/Py4JException.classuNAe'L0.#Ƚ43 .x>0V7TLWu__Ug>_^l`!?(U2g j`a.lkaץe1#en:^kc+M<7c 4q(: /4t*E_ -2W0DYe0BJ빀49_jF=0rbLWCxrNX4,ڲa SVHaPK 7'UM>  py4j/GatewayServerListener.classmP=O0<Ҕ~N9,DBQ"Q)>Aʎ%Ua;V2޻{>@~.[e<~!_"ܯdk9<"Q?q?~ZN);nXiϗˤPgrh(K+LXxx"jeR EK`49M+beSL)<'n]Y5Segp΅Vdnj h_g20cV;0Wg6u̓4hMe}@~Иcg $ 0z&\Z x"9ZEˎ s&QN{EWhW+@ʝ9I@k߬yޫ6u f3!1'CdJnRyiW~=R̎ь5.LH٢p5Ң֥M&-LH!(ozmm;QoZk9m'Lf1Ylf}K#]kۄtxJQnle%SS)=Em@yx)ҵMlStެ9d;ͨvMYڻXx6QZ\_b193f:~^'xMp:ڴv$S\,K3q13& `vO<2 '*%wn[ GN ]m u RIᑝW)SR4cQWd ;W)&9(^A5j() pT")`(09fRmE7K8j%j hOvt콩vo-uC>GMkuT>wa3}OC6@<Vs賲DadGJSX uSJyB'oJMmcPZUFR}l.AxyFtaI`;q ]ISsœU+h#t5uANzFZZ.jH%r׶I+tGE؆m=;0X2,RT'5 'r\&GYn]:K -1M+|O g+Z-U-վQ%'np#x ގ &GLzy_zS55zJ*=q[Nn OuG-wBM5bhfèc. >. >xӵRZ5E@mX (Na $jȢzGP :R=@}506vSBM5# bj^#5i18!G:_@P,ш޼"J2c?i]A+eKz|RKfsnp${U=H-gnrE4DM{Kq%w4ki/%h=YwlH߆A2%!$HjSǰgp$^**qcxYjyuBCh KCP`õCρ r㲪+=Zp(e-WTjo,rgH (@@v9 ya (S/nwl @>|аޢ7z* ]'MVttKaY|ff9Yf17yNmat|ތ8E1uG ETÇ @#b1O뤦OTahdqdw :xmuއP6شUq'7s E!,=ѴQa"Qtt}Yoq av|98Dp1,wqh=y78˽4#AC@]v-#l Y &^!2?cl-.G,%3*fBs4B])d-\6k+I Za:l<.tEӀsnۊyңKx`v-נr/b6;O9..b{-x۫hjsxg=iҟLiZI]\lIȴq$}4鑦Ii&vL{ߌFe%67~{}Û}3VG=(W5|E=շd]'?xfɃr<?Ŀz#1ThIT~"9(L2/Q#^Fݮ21+¹x?w:;M.6PCCD>Y%6|69VF :?5iF2FcF8P>E7)#ӘCK9Nj*EQ@ٝ2Xc#Fz0<ഺ{Fc$ >qKDs/}$x:9≠2p !ƓTػ-&*LH GTW fIf2;՗z: 7r[ɉEu6nf@yZ;eҴ?d1 ESJah`*̅0}fIf\YuU uJRJ4hPĩ2^BLwF7t3fqh Cb9ҒNGV?:ktn#rN0=.[v}{ߊqDCk# 1՗L ,r Ou%3z}Llɪ!3{& Ջ,*Sf3 c?g35M;W9%I.|; |ywRNSnF둑)ͺrHbmT:*vnwKcWT!t[:Ư9 X|ޘpAܼ^:6ͫ{ayGs'ߜ'Aq䈖)[JPTwJ7?X-yh; ,p&ž I8bU%}13q704#J.X%=r(h9^15٫U(=c uGWkwg"ͯ ˜w d3sggG瞎Psp{>ǟ38}tξ)tKV%\4hg&k^LKFI~%FN"K;j~'/^ aYW\M{01cիDgUi;M!,BA90׽at% 3U3 wP%^^WHU󐚽7t[v-ǽoUU1?m+S6MKȾY?́6C ,豚l Kj^gloVP[ȿE[< [jD|nR?zlrKs\_8jK<C]\c%<= *~TB>@Ejy=s u=8FPo40q>%6<ߦnbU.;wU^ Pu/z,zj[ѣfS,K~+>F zfr19lc'\C\yTh'm\+#*P.Vik4Ft̊ݭ&k]:SU?++5딚s;-_㲟.VWݩB7½XVS݌2j\joA=rZ!CWN !A궛zz1@>a->7W⤕4a?a$ JANָPNQlz몙7|Ț374Wx 89_^(旰QUY8Vv%o>ʥfK6xRRq,yGL(IL@O Hd*nIG8<gӥq{ȣ!&QEGح` ݊t6lLw HwbŮn°G{q/݇~ƽ1D;Pjz2%,/ ^^cE^JzSܛAuy dA=B_1^xeq;LyB&>le[V6} Q?A9NK2&PK 7'UMnHpy4j/GatewayServer.classZ |T?羙e@7!LaMBD`X!yL Zwkjb.U@i֪֭Z[ץn|?ۯ}w=,{9|-R,/xpW:%]x6Ṝ<'x/xx4ԃ_aE/d^/1PWs˜|ZNۋWyza*x+nvN9;U';{k{>n_ů{aAN!g|8{s*<7X&s-H>;*~7{*>{qᏼ>c&3Y.<3ߟ{E|ɋ/+ҋWYwfV_ci~78xs-N9y?y_9yDſe@dr'}N5?^#? >2@B.p4/TVDGx"Ch慫p*2+"[k &p$| &:\#p#Bd*ƨb,wbn1 ɜST(bjTWE*A hU(1e~VkݩG+;V=bM]报KWU^;33P GUE±x _uD-1q省ZaU*[Aȵꛛ7fnzaxisS5 `hUuDBβu͛WWZ[jsRS65,[V a!Fg<* En%9JGI5c[XRRaSWG$GvtŷE0(T$[ "dutYjꘆgDH-`餱Q=jB6I6낱8J_;Ƭ]ef_$#U@/<%R$[!X"C4H'Xb-3q^ h4eQ{$Μ+:Ҳ]Z(i$KZԁtƷ5Ea97`|0 Vo댷F΢4*e;&+B: 4Z)hTEZɬYu^پE6&G$4>Uo tGM >b#Z9 k$H,^EiW-W:(::93/|kp0$o f`B"_d[Ö3 Y^RY1 Ǔ-SuףmRrS#K)}G'0(1%YVޛdNb0E"eUUFډ;nbCTOkP.mmzToe@ȽnE0;Y57+L1ءX |g,Ug7JBN(| &) DiX|T姽fЬ#of:<cԁɳ]rLNfq29)$Npr2's9tCuAK #&q/ K^PzF⑖HH1SG۪\UDb& wĴϚ}|RM, y[@+Zz,ZV1"gQ'ʾɛ UyG h.cЯL_. _URMTM,5xM38G< Oi xI%!.oV|+cNÜs?~B],H-2 g/,5qXO) fLgY ipJU3sh+5TMW5!0|mXDXb8M4kb؀0r姉81dj+'|-@l:h85IX3D E-Bo EbmhD+ N@gnF[1>?h1mJMbqtn&$mEUlD5َe ѡHd9,"qND NrЧkjV,EԀKXNqw}=4ms)`S`&v6ny9s8+I{Q;+/4yq^ g|S>~CI T%pyTtYӪo7g@Tq&.a]*:N40DFi0-ETvʼnJU|IW:N, -Vq&ix2b]Qbɀ&_Ma8dcK8F&_TSBMYƼ4q;/nM!GlKk^5ؿ[S7 Ҫpظ0s:ؒf]NX:;stjг;iJCI=ro`ZqP;';kuud '@&#_Ǡ3hPҏl!(jk&>N^:Kf9ȢA$yGO PO.Y)>MsVY^f .tK!./i$7a. H(j*$8#ϨHiFFΰtkxNqfS.d eH[]MI5tP58 R2-)A:C&@.i-ϒ Or2͹Z?:1.)6A? bImQϴi'Sj@9րK/Nd'X6|W0MJY k H咓'c-NZ+yr9J*cUL| B*"&Mn!}@6}sƭ* n,n,z薹vn$nO$GLno'n=%nK ̞^YᅒUP\\\ }E͵Tks̶jc;׮d T =ɑlؽͶf?[v9GgPƙۨc/RM>OHø~ J/LdUNnv 0TI/]0͟?(n..Taz/AP=% pvg+ui/LY=9gQv6eO2NVK*s-mwQ:Ȇi#-N8Yx7_ ὰ3~؎_ŸHwc4L0=az,X c2Le0c#fD|*Nqw.ݨbRQ1]E/0eĠfbɱc(R=ZL%htPXXXXH &' wÈۘipWp+-rr?r?"=A{ AP?f)Ӱ!= p9p#/l{Aenݖ%-Kt[,mY۴hq ]-de+yV+̌TZF*.}_*%s' 7>,Rћr!Pf^0 Xg4QdY+GIFT q:70 MJY=߲qVfqVqQcx@B pێBP0Ӊ97 K`QC&BGrNp h 8F@qx :$?J^:6u :v?,-!T0 }Pr!B~,E KH5Ԗ[JY^HKEϑX{E͆eI@0UF]PZ,Iy)WD]ي5t5&^䱪x%6J*Nܔ g/V2׾>8RJP 3L^(`ȀBE"*D%LR6)+-)+mR$I9IJž8( ɐu}W {ȍb4Neϵ0! /12$rWTP{@%ngX%plT2J| D. F$QH*E b,&&16]Lly֛L0(&zRSv_[Ri2Ƃ:m"Kp&SuŦ.'txYGN d$S E ?E Ž BG P .Ee)27a@٤fHU2Tk)պO'lD$j.I5:GRRD R5:TH%$UIUARUTKIZAZL6|:T$ #VT $Ug+o\LJEgYW&ۅ;q¿b16{"+uikX0Sot$08/u3l|}yW)}idk֕-;}[h &"'b0\"n/F !8#J232QSSUyG)9ox .r\8sA̗98؟:J.)yP^IRܿZlˤ>8 N-6pJiVDE"tُ.ksd_uw dkɎDLkZ{7bq#,J*7w=}7[-a"yZn:p hM~SA|T[Ay {]=j+7֦NzmSumu2{2&C=dLvU >s=S~ڽ"jȍx^knSŦxr^%nf%L $|kOU#0fv Vgf,lݤ=3v]!"#:VvX׈eGஇ .d=P@ZRUQk>0btx\0L_Axp49oBx%)a81U~?\ V+b`.Ń6?Aɂ % $%*0OɃJ IUإtFIjzl ""],7Cp)G2ɶ eYFbx\ {`,4z^ƞ#yX&|%_)TpM0\KѺ}Undu?= 7R|7-4>,t?.xla0t7;|w~)zkh/ҶZa^ٞ/ekȇedp)s0e>q*e +dJ(W`j8UYk}te%lS!4@(…*\Y*kN4Oi+ e#n^0d^ݼ:aؼ:aļ:ayusQ2ƭzO=c7jw+{IN)N{yp> PK 7'UMR @4py4j/Py4JJavaServer.class}PMO@E|zZ.n/$$tRJpkے5qvYĽ{;\'2haPttS%*\{Z1@pHdpz W=Wer85}1w*o,rYmKz;5,;3pHֺee$fNm[Z_w28w[`Ƞ/Ga(O}J:6pMβdBnm/Ě o"WPe _HPDUT;P B`[V߷u vk{iMR PK 7'UM׻T Fpy4j/ReturnObject.classWKp-fQKI66' O$HKdG3%[$` spIU)l\PEfT`EY,ȂP9Mk絢w=sߴ?6]()؀a<\r´"DilTe^tC$=2i9.ObIe`UVwعL*捼^C⢙6xC`ʭ*M)vm*R7lf3v1W̫3z+*Nv8d-R?2JSO~+K~EЫ*FWU=I&`92\Z v :&5vߜ(XCpuihkyB%y z'֭gdmgbg> iT3G;_"ו7YWi{;\orf& uΊM{:ui*}T[C P"LK/ឹN{JYWPLqC=z#~E{#tB:\"ky1_?~Xx]_P(#'ɵ5[ [yqAJU/z{7fKON y3rC?-{* ;JgZ?3)ث~ߥjp/>?^TJRpc~>)~!v?K)[ R?8$g~pєnp N/ꔦ,, sA\i~6pK4sr]1?W+\i묜\}kFsu++)f\m~m%+! yk\kgvQ9v?W\u2]~ z?n5/׮n \ Wϵ\cR][\u(+#tPK 7'UMNpy4j/Py4JClientConnection.classmMN0ߔ.BpH7DBݱ@jT ٙ*R]^PI`Ay>?\Tsd],C.dTH3ff~;/I^W>kC τ L*'mR'0 SFy`Ι]ׅ"\ðq~׶ڶ0{td6/D <~+h0A`Zk[k 5v2~cE0e [ڗ42qcsSnYS{F_AqӶM-T֙mi6Ʈ=nlfޮ[dئ4o=XdukWcKkhT.njbF_[ML4Zڃ( ۸iKSMmmֶSMVGgkR9s:تjf|-+Ү6t٢fӱhKοdm pi&8.nĒ+!N/k*ZWPݫuC_=AIi9w.Ub~⍛ۛ[Ꙋ8SE1(*1$(bVFIES13-D1ufq眻6D,g%KݻM-k֮k]@nCMwtn޲k 'զoLk`WV)O^ pv3*բm0͢7aGɯt2D3Nu;[s5&iR(eFl3 U;у`jW!/e|AgɀrV>+t Oe씕:u U**o 782 +K=:+U-A~g_"mIOz?OVe/9'Ckw [ O??cEu _V;iO Xv߃V&de‰pV$"08JDaVڕ k|w.$n[x|3KJGg3>7]Cf!k=Cpa^-:g%a,T7Gсc؅x'8puZO~7x?[x1 =TCn&g=P1# v<  8Hwuh4mbBcR]X,~i3m`)Zg7Q8Yf:bW8R~ ]B*E? *rِX<*?NAϚV%ak5WڔPpLzjQI }/M LEv֔x%Ȫ:;52Zf`׃TeQcu=@w@ZvZ]65Zqeku!VrcveQ0ڞϨD ׅr%xkY/W=:Ɩ+DJ̆G;kUVe\vU©]Wg7Xi篧tnVLڶSG=~db2w 2eRD$k5j%2e fT,i*3YfaqO|^iWdNH#N?܃E@,eYM;-GoGo/xzۃ'm'>uK{Ϗ\ᜫ\cmv~z魴Ho]^W-y-8STVHVLxσU{Un@Y!eM(mU%Ue*Rx" |~Ngul?(xXjz] C>{ezVG]bخLND(cTe`?J);ЛmXH}|з;$#wqe+k ȅr G(HɷctP[0Mblkayyd7pX>~-O=g$)yN2J(eȗdE|//_{4rF,GqՈ\@3ڑF$lB5kJ\mǎcیKA~tĭv߻&h/ A죛؏ H!]x ~cYªcpH$O}>A,.aev"@ߺ@_R3iC>d!@H@HBrv^%8)0TNa=wp)xN_qm/Ǹ$?-)3R!JLF{2F~!{rsQ~paA1E (p§<vz <~/J Bw'bU |NBBlysow?7&C >4DCg47,Exh &!yQ~(@*Ln '|RbʏRec ZE1[0WѪaJYU**TC+5HF05V&qRRQvU-ujԫ2_Mu|lSc|?nPunTIhTP**9 Uo7RJ+rP$C]T\T㈃ˮB%RQ^nPkPU@eL\"(KRVpXy ErsX v2{GSg0]_@Ɲg^߅t3]H;vIѤAe9*ڋ /o9"FrcNǻcv׮LMw7j.GWSfYIɩdݴlsҜ3l[qPnv iI!V!VE -bE,-wva $ L<  F҆DmY#o)\˘4:W\`s#Pi]r*wQJ͏?wAzS [3xQ.W؅gi?[:ulP KB;8ⱾR7$Ye\~ܓ&HW!cA7^[4 ph5$[XѻVP#ߐN%lWGG 2MΩH5\P(2R!iܥޒ<4z:&q x0tis4̔RC#}-s͇57PK  oN py4j/model/PK 7'UMauL)"py4j/model/HelpPageGenerator.classWw=[<0*T(4Md#[Mic؆8cHK#h%钭{%-m5iIKnizz=iofl [Оw{ߌ܍5tt!0ᄎl GupRU,)aEi3Jppz 7LVK5*vnM9˵ i\%f1guA8~_ifטM,5j[@صq k񛵌O~KD<8X| uK8Gwj^?tZu*8D'wtx "]JP[|6eǦǽ^P8R;w΀",,gcQs25NT0k5GnkMy>FKFFs3pw_)ʠUfv\pNHe+IZ3GT!3C68>s=LAٕv95۪כ3݌ub9Y4Qyg F+8to0*U~u y?%)RA~u*~J؁4|i1ׯF=$ lE<| ]X$8 h "CitF(\ 7`e(ZҖiZN/kZةV纮X#]:b b3xElXt^5.7,qI8ަ0m/$:maEߍUC.~ .ַ+:lMl$[d;C(0<KK79jx<0GZG kq\lƣ c^L1!0)ȉQO"/EA\#GQ~WN@gۙE74fd.C%W ٫8!0!f[ 3~Ȭd#8a9F6wρ` =h_~ gkI3d &w $Y;E41Ϸ|{@Vb@5 ~aID3)i܆i$p}JSgci_Jk|c-|NZKLdCIs$Wgk`9aLNAcƳ$J̡/%M Cq;kጆ5|[w8 ݮ +e&Õ==tnf,wJsTT|=j"=Oc<ɝw@%Q3_`F.N\pXG-yYj@p1r`ԩZϡ>s)lA9ۜnfGvz^@s(=1XS EtFod{2GTwqV+xUt|?!~85 ?Sc kqo踈nn"㠎K8:~_i- + :~I>nt~}5{ϣv0ܖz"z uuZH lxC^ំwSh6FvZ FMfgf Pw*ֿKqixDsA˅^3hx^FNw i gQ69 o0MѼ ~rC Q$t7H=v7H?`2AX4oqɋu]elͳWoo^yp^>~T;W+xEq.qw-Zpe1s y;5 ۂ;~nnZnFc3 l+2F1͌nh*f7n|:kV=)z֢ RN5lSv({ 4ܣԲ~RmT0t-Hr7._bXY=ő)D BkM-bhSXZqnd`}G=D#2{V~c)&tbsyTnw5N@ENwR Ziv#y)TA~UQ~MQ~-׏HIXrEc%͇9@8ȵHK\(-rGF0LވȉF䙮FZˍjy8Bu Nq0JQc7]FS4xPQ!l2)ծ<,Y#乀5zS'<#0Ћ\`#><|,9G",x }?3nwvn m}IPX1&x"!.Zz8- PK 7'UMLpy4j/model/Py4JMember.classuSNQ]gfڡ@k墨J;EMQA`&%$6-2,S~oAF_|{ϙ^{͙?HG Yo9,:>YN3eZ伺[-hUWݪ L'{zORܬ2unw{vpZ.u'ӥRBrH)*v٫ %(Km *;v;ɗ:Pk9.߱}e}GQk5 m_6L٦SͮtΤ,ר;, (E:%'ּz;kѢ_2b)LxjbHb {ob L8u+%JO/շ,r^mityABAUdZb͜CBG KFq<" bCt2ނa#̘^Ȍ*Ӕ~Wh5&4=M=,yGZum^7)lԛ0ҿzfMDPj]%K>vn'(נsGT~E9Zn/%*I&0d@ su8Onp o@l>9{Ԅ=B2`2&PK 7'UMĝ5~py4j/model/Py4JField.classTRP hVQiC!U"*"2΀8/ I'My+ȌC9I:-0go=??CIi(\̈מ`Ȋy\0/BSAN^qcYksZcYU[79h2U75Aqq7W+|]m5V{}O\͏7b\y x p8% a>xXg$68"Ɖ%?+pW6&eyC׉u5C_jZNOKkU+*6O?@˰Zi&u4xs[tT>:߃8c>h|%t ~¤`{r]D !:ŒAB3Kg,K'{NƟA F!^X̜C3D&ЍEBιY/p$5\m.WmjAVuN#ڡ]zU1,/ qHMFF5Tr[#BE [1顶ix SH#u %_ nT/PK 7'UM8ʍ py4j/model/Py4JMethod.classURW= K6BX!ر &`c _#i"ER"l*v\:?I BWݷi~p{ f<,<{Ex A'H{b# }(ܓXYÌ'åi頴N L~D[DDӦdlA?o'*| gvBtLO) 4S|*Bj|=ՒkZ{JyMaM +[f9~v5jJa{^MBY@X:*vGBp!7ukdCv i!2^y߻r MOe,.@k+YVmq 9q.Zrbf"]*>1Ew5J:3ϯdW8dK Q1J"0/I*fRqTtEGR2 *2JE9<^(.k`/quVo0jW;@G$;r&\Ӄ~%V~: /3ntA/݉|{t*cnp\z 8D x 'pѡqK2F8H^(U M-Ct '^BgO`8xyO`_Ԁu_!wE3)`K ȗf  +BHAqHpJCʁcc/w^hNmNpI\ q`OyMpqݰMR_d$7mP˓ڶ ncE7h WZ]6qn1luv;c?c0^78_?mN?u.G!mo$m7,4žfk X!zSȤFޯap} 1s,BO*"ٱTPVb;#})#Ǻֶyuny2m>dJee$>yshu6O-'O9Ũ([L;L-fMӒJFLɍ;GucX;+\\hquM:1.= +ngnLj5;}FGT0Ӟ24@ vB a;4tQ!RDØn8eAUf1|AG0`>qO+V!48!̤!|O v38Y0eAV#Y͡8* "XLA, z\ 89Dq{1!̯ aeq2!n[ɤ#K02˘q4e WrT^Ŝغx Zuy=q N`uN kuaO5m"?إ쮙;-_J-`ôUg Ha`[e2e8vcfpY)f0v|i R=nb5܌yE|v;Ν <E5>* .$gukMcyͧPmDc%)v1\㉷me\K9c:b'I=CDܷ}ɺp!34~HoA0 5Z1N3GfO)YbaY6pkpw ! ٠XĂCP,4,!.e+'f_\X̧`Vw{ҳu:1H!"GO&jȻpk\!pMɫw~U vB[/H3X#]RH!Ȁm|I2.PK 7'UM;DN py4j/commands/FieldCommand.classW{=cKYcc0@@!!iꦭ!` †PR3GlY#F#7iith.ICSsHcIȐ~߼=;x:, lڰFNK,#Jø,_GG)-ÕoYp%3<sx^^x9ψgs2yQ (}I_W(|M_ Z&Us2+d'숆ޓ'O̍MOMOKg7rPk.\ΚEٹh0RXvsvapld`L#rcM')MW-9$|;mgM''d]̕4J++fa4|2gƼЭ+VR<~+L-g2c-x9'r^.4W5( 6E5eJd8[v 5DJyЕrYTx+i(ht|SǷ40,VЙ%X,ޜ<Ϩx}t7>:*Hv6-Q-#ܚ:^ocZst5oՑGSj9,WZ!=1F;–U5쾍Y z;S}k@DRvI['sR[dgټyZеF;.k hD:1%s{Ŗ'n zױ-xp!`ݮ>N9DIl418HQ27,򼌊8z *1JTvpg1^cwث"Z6"6x!q!UkJ4etT&'n=TK}ED:%Bױ߳b ]E IunM+ }9!ûUw]>W ާb).~CR>{>>c~|~RA>)7؏ix*<&?%*gd>tvt0'􎂕JwHZ*3g ,2RLO,C`E_njX cynSl-6#pu[&P;[z*?Fmo8[ñ3x֖Z\h|p`{b=ۏzR^ipwg Ƈ sPN2lBOfJKD+0ڰ$z&ؔ25T=F`Q'r$ %X1L#Гv3e.},5-cD~6V=}ܠkԂޓH{ ,bv|<4)kotbZE[l$m,IYb#X""Xٓ0rȫ+9`6,FIZ2%|aF_d'3*8tSg:HTxKfT\Msaj]/ +[NY+2G,+qTYo|,]!YӰ7mdF]'_ rI$yfi.1& +/#exE@wd^_2N;޾#ۼ5qHSc?T;.ZKf,2aO.yyz! S}#4 ~d[N~]^RlFjbF"-G'_NK j!C/4/*WqF>}nzw)NEOk~<*qTY%4KǙ8 na3OPke46 _zET juw`YCB"~.E4D}SdѼ"zlw3&^Nvf7mDR"s;lzGh8&槈c,!EE!4tIRvֹ:DCP=mwY].C~t'8!XUHUi.TWy'V|EWmRm~z[][Y=:"FԅzATX-æGD#B_Dz.\gw\ Xru!^O^'N]/rDk'k諟785仟\vvKXo!ܗr]mjkua3-70m7ěa2P=r$q$' tCw TҼSLBkkLN#\"Lx\,l,ҔUoCj8m?Lׅ6ZXΑJ 3;̥~PK 7'UM.x !py4j/commands/StreamCommand.classW[xGז=j8vz(%KQ֭VI kyl-%@K {@$ OO+<%+r,C?۳3̜9? }>|Lq"8.(,՝ꘁ19˩1)(zэRYu,@%QRO)|ZǃxHgBL|N>#xTS_Г921<4v<}hllha ݣ֢5n פ][?iRQ=iggasƱ݁_b.kc;WCk"9!vgxèraZzGT>ݬ<[kˆKn-VvdBrfJ =á6+,hؙ(,93>&_C2VڗjЈz zuI&ELg.Y`W.&wq^VJN@?v |;pMHK0nx ^2 7ͦVJ~"# g~N<}7f)n90Dj3y?4#5c<#?4-tUd{eQ7sB_W/8q+lWqIR15n b'M.YYeΏjQdk~8(jբs5 5l\SVyZ5 ms =Xz$KJ4h*m gƪ7D,-AOE$'yLzJۆDCYA$}7?Fn<*pHA#ݿ'𑷑~O|40\<PK 7'UMUo0<#py4j/commands/AbstractCommand.classWWU^Hh)ҪMqAl- mVaCC'wk]T=?x{!{s}wK~˯nAl1 q/ 0D)bcrq ǥM" $ΖAGRjHQce| C^Ghǃ8'47\sژ쟜mcĄ0&Lqcʈ&d<::V2N҄:OvDTʨ+1;4ce'{aͶ2))v+i%C{96pBecnj!ñ{FwǬ/B&Tk8:F3f,rIoxqYIJQ1GMc,v,rhw&fN"R7.'0.ې]r`eJ]N\e+v)/+h+*IBg'@nZ=ܭζ2XJ!׈cL*,IM;Y"Jbݓ֚pC1Vnh! +/+.f;yVqφ9c'碛YvbKҳf"hD˞} x4%c3,n>.1fer:p+ɪJx xot-L5ؤ-o┎kqt]:>:>‡kN[ uk' e1>>р/t|} Vi_k͘iM#!3 MÐe$3Cdo-7Uw,j ˣx.lz p5PG۞uQ׭ ]BoڢRWؕ6Q"%KYy&g̓2// lpsܙh>Sh7p5TVaM3vMnjw ,sylgIV mgm*(Mx=n% [n~JJ8GϢ"tWT)b䒈i^3ϥW/Lr`{t$_:D_8oFcܚO2UDC>0 IT0]Q JOR 5OSYh'$$bG.:rpSvE?Cm .3\@a>N G6g>UwPK 7'UMΐm!py4j/commands/MemoryCommand.classURF䛌=MSj{McJKb { 2}>ӿLcvG3Cd:c={.vAů'!9 w 3,x~HsmFB%t~,IXFA%c֏U>qۮ'BB)[[p50|n^,QyS)QDQ<(/"DdhT@2t1eY.W 䠉fBQ}N;Mi02Mcl.DP )[FWm_at6p_ü-lPe`W *2nMFŎMkd@g$_JW7\!Q.&#=\ab)YQg|CiT>ruW`Uw ǁCl _TQ`Pn D|+;{ث\7릡=1QY̶r8wBSt-f:j{s/kh{:js '^ UxrpC:F;5odzkӝ'YˬYfAWK/Y3׍eGJZ}lRNߙX#Vc<_:MZ蒆-x+$Vnasٽ^i,kV}o~nx#lt7 -3^x|4i 4!'7v Crm` Ȏ;¸eRMcV4+tH|4pݿe\LLBFHE|A'f3M!JTT oc:V=}l}(`  VN]ߌU:mJ]c|BXEv=5;4p1~6>ks}J3PK 7'UM3O/ * &py4j/commands/ConstructorCommand.classVkWWInBT4VmVC-DBD!рXC` H_nE]5ڵ?3 ԕ9>̟C1.05LF0LB \"Lr^A;xU>_%o0 Rg1Kwf[ L.i+ZʱbJʌR!5鞝W?Lng;pԨgWԨ?m[4~{,UldjEGg!d&g<&qtkF+ҙ׊e0`/G&k}K+)7mJ{2}=شMlO̓fjYX-}>kM~2le;j3ڲbd/ꬺ~:5a^IAfed^GFŦjcsKzV# T{J5 tmp\ؖC Լ]^ +PXViV̻z һ7am0^'LZVvs( ev06 %ETdt~ŐLZ'GpTAlKjbMK $V`E!VZCE*b o8!wTV#Qt{qx-`\xC<HxU)>\O-TVp&ucE"y{WMF17%SWph39:{~}ob=z='ޜlc+ vn.9u[y9h6E& =n 4dҶ?Ӆ7Idž,r 3dH&͚3c2m3oI}el~"s|Ii.Mzސ4 f@bcև[t( E(kƢ{Ƽw9)X;N^W3JjMtJJf-sUN1aԲLksc&>s7?ODX.g)h1J(Sܗ| %m LF#vEygс!tSz8 t7C|@`0 ĂU BOۏ3REg^[Ga13cy0KW΋]Kz\$zܝB~C< c?{+Hx}<;L/T%!:AZsװŷ J{WG$Iu1ULOXG} ) ti~MscvRj p)Nk﬋uwϓKn۴ FU.')d]PK 7'UM|^py4j/commands/CallCommand.class}TaWGI6`@ Z+THk!l jkK7 ,ds6V~VϩӞ_'O.e;3{;o{o}?nb_ n)Fŷ;jyM]SiUú6UhĦ{麥+0$lg C㹑e%fuw|{ZRnU2C*p 2.ْٓ +q_Xcd "tRu}l4m.ӰkpIM1~dv) rtDb9u.oչѢ+w]K.<T5:0?l~lB^sp5)Z j'%Il'ho ,1iȥX:1ZPk)$s"7p6unt8$שe<~<>6]H*FbxDxE>61> c$ru Qrĝ{eh7FUo#i p>LIC/KB7+_PK 7'UM+F|py4j/commands/Command.classeN0sSTDwq;  a:R:dC;^ }]'7 B%AhTɨ&2n5,bֻUKcЙl"^SB7a3γLQduveG*itYN~NO!df=Ε20/tķrap4*^z[j @8~P@hZmІcM. _sU&\ILUyҗftmOZErhwڔJ!˱c3_YstՅd|# lŶ$tji8']MHZ,eåQoܗ;6km>bhΔnֹ92V.BLȦq7Ґ~̩/N!޽V.ʑ̓m皸x*XmLG vjOXi5k!3ي!żO1Oz1H>F(&trA5=oZn`_{_pT,=opM±q5^!tش\fq,ݲׯeE!E"fH6l~:f6o1nt#zI4$]^t{q]sTmE[~}=4$oC.[xK^"(#'WV~7bQf,!$ aq=ܲp=ҲVi);)Ls{*D:WLDCW 1JC`w×6*17O ~ZеF'K0SX0Ay ݉J.Nkn![hO 7Ƃjֱ5H`cWlF|H EНN{Wǡ ^;)6ƒ W91$t'ff, {r=Ѝ0 ~h8J:ċC(C NaǤ_>Ω=d!=9\GSXhOTXX5 "HR/Tw >6~:?`ϭ~^d +Nc!ʧ f2\$7 }WU۴ۛYu[NW{޴Lg36gj%B6LKdբy"X6ācRV f78Sӫe CF)\(Ѣ2 _C\a);?v]g%  0?V0~ kx 1Noy;/y,0 \qkF.,N+wj;I5mC{ 2`Y8>a5y|6.Iͤ5Ja~G:Oi H @Pz4[bK<hW/ns%v` A\c*4)Ow1U}`݄1h~\3@T>OE_D]{X!U2fZ٣x 7{s[2*PK 7'UM  py4j/commands/ArrayCommand.classW |Ovvg $6JpŜFn0b9$Elae7&DG[}-V(^[{ߵVlE/oכ?4U" h nqnq3nn 6]S>C> u.*>:q@=W}_xaa1|\ ãbxLCNG5nxNq1  d~Qx./iSu_U|Mu74|3omk UHFGq)kMO6uw- *z{۶noj>{{w[WΎI>; ߞJfl3iEM6̒Q(XrtF;$<)E9MkGoG[q11{gudnU૩T)3{t94qv3.\)ڳLgisYX2mKR48SM##VaJ(LK&K&\TXLRP^x&_DOEm<%&\= 3ˊFڲ餳V1HʙPM:a2*b6c1){O װuYcP\ 4kڔQ3#5%u{(50!CC2![G-<|xrګ``JNG흤e$_"sY,Ҷ5ߞGt/)k AiOL\k9[- ΑB-*iucfq!Y-*Pfjzlj,ųՉ8uNK[# *h֞DFShBKhVG&=F_G%_/^DZW)AP)rx|q:OTJtVHhC)So^3 eRw;\pQfL찛5aSayi3f{xQS`f~-"gxe r⚢hɑNO.Rk_M[ȞNborZ]),Na*I^}ІjEM(Ԇs_Qi vvxd[q%ˤ*}b%X//)ker rmBK2y<iۨJ۹6,qHhn-Qj_uN9$ҳ#N=V)+0B32(,[ _$Id3;~煂"Efyx$u/bgk"{Fh̀w{Bsqf|OCPRI木̡ȡbcH]읩hr<[Y6$<^prx}c.EY8rqkDrVVgY@ u;g;X9(ugSx"n {H"DI]/u C<P91¯(*yfR g;z'yٸ9Rry0QS(}FWjH}R}́P ޅeUP1xe%x9,,xE!!*" 8UiS=̓TitiX QjRWPFx؁Aisk [i_ߜOK(o3qRm+褷`;RMJbt簋RQ*4jة!aa7|"!Q$R.Y(a 1ͪ}_pK"AB%T B TZI\KX&zA,86pHŠ/OK0_pbl$5>鋍DD Di1qZNtN$JMDE6QR &p#ͿT1~qiѷ_D.Dg SM>}`9o:kyV:P~>i-"DP5#Ed ʖ)FTH H'uJQM0{X k kq D1`qB6i7R".Ϯ Wv [>uJj:CJR*./җKeW;B=ek=e]e+ eW*3TS)7GG٥DTiA]CoR䈿Z Tqʴ ˙zTJίB=w ZuG=S)gz׻s~}=뭜ĝn7J!DYQէpV_}_̄}@Z LaunCesr4w)vk>Nb Μ xgJ50 Jp3Jq ϭ8ށU}dnC]"q(!;9QVqO 1/cP),@唽:2R o+S$gXeQJ4Ї¿D[?^D3{Lu8ACsBj$ӽg̾Ӭ^bwet.rHܜssp:`zV>D`{E.?QgOj>-П>'<'|^ _E|I($9Q{pX1Ӯh2+9>(u] zǦ&cScS}#CC=wO (} d5HL]\AmбLRP?M`ՎzFTTL I\1Uz|y鐇Ēdf*h\>}h1gfܵdh]Vr+(6M(34-v84m:Ǎ)bq#1a8;o^(n/-əT@k}ޜAi/W[v{ozvt̙QӘ>4qR%i,4W=P~LWPFM7$=!ZT\Id_ZVgxsEF*s␱,<$ g2ibͤ"I>X fa4*5ېR*=a:?W5{/C&h8͎>40f:+òOze#qs޺ 9;Kt?̥c.+f.Ū7%N$b4<ݎi'ncX^{oCP7t|ϫov[q/PeE̯8&c Yekf^c\1T8㨎_:Q1̉!חIoJoO.&d4< c6zl*~%_ [A+rj"VN?lD:?8Wo:' notuXUGäzZ&AeYL;K(AAu`صUWPJGF_ъe{-T(Jf^L- $dcfr12tĄmD*da]Eoo1kN=MDeSvDn.qܙ vY"JϤOt*h0Tx:?hCjwi+42Kѓ1Z\k/$K^;C**E[w"9o;]߅`AH4?A QYۼ^YAq+7WF@,8V0 x;vbwS{p}k|֒AIC9yډVe ۆ_ޖAYg. BYTMJp eb:fL؇<~lO+D^jA,]9+D_ԏh)u C>a U bЈ2gׅJKM;b tx/0EXso{f@O ̽pw`TB$)z wX)8Вr' E/fQ[ UğCYs:×0B v a _pQ{`U=}4pnΠ17tpNy uaTfpkxl0g $a˸0)˺J*pggy<(xȺ Z$ûSYnUxMq]X& ^a:+**vtFhxL(/y 񿥼6@yli<_jI|,YZ_ǕgTbqG8We tpc֎pM8,'~rT~Ϗ}~<xxG_AAXbqDEV(9*SbB*TKÆQ}ސH 7˳ N3t6 4wvt4F6v(P7>=1J`FIk SR557F47vw)Xղ3:ÂJNmjjIS'׏6XFB WdQ:xÕ#PJs9VR.TQpGsر[T&C~ T\T7,m(o"suGx$nr' io0O_ C EY,J_:8o*\lti&Ǿb&!mku𦥔ۅNJPz'#@)  |KhB/G89P(εYTu_ꈇ\d4 xC8_$޹ʓOa EgP[`6{_E,:Qr5.ȹ&i "EEհ$oijt*P9UdM|T"=B,ݏ!!&pY阋a~lY΢ۙm>ҨpQ@.QVs/a߅ bRwVg6YV"zD/Ŋߢײ<&x;0_?A+)yڼ@|˓uz../PK 7'UM[\ py4j/commands/AuthCommand.classUmSW~.Ya]FH_֗B mBT$J06Zu6XLvݻJ_di鹛1t2ss}s{͟;/\ 1,,͊4nh`2ҬF"'ok w!6#<-B&cn/tðw%Z*hֱ=aآl4|0bboym=Д2 k 1Ce[se%jl˲yoVcT\2pLQ6\K;NEY֫4]2q=!*?/(<7 ic95^.ms\K_IڳϷ=4Eӭ 0EWnVSwQҁR˅w.NUy⓻\}ENVM~iEtca8]GT4'l۝KI~ف[')ңw1i|)zΦi6Qٳ4^mD0d?Yb;xDT9pbD"N6aWn b 0eJ+|@0 0\EZ4,5@hF#D~D"9v#b=9*R(cG,!$ <KTg[?a&Ú{_J+8IF!=ֈrsXeܡg~}(Am1s4 1AHyZU@^ ႊd ))6My@ʿsWp PK 7'UMs*py4j/JVMView.classVWU;2 )/ ejmċ.̢؛uvN}/}SԩN߽3,2$vϽ{^~_ЂQCcc!4@8W 1*+a5料V- ۙՏoPR :6Rѧ*(3ֳJ=-zg ɥ2+S(䓢iG_*(鋩q }pזϒtOcIaWƗЌ֌<91Qs!>x%;gC\D(ѹpkjgb+bbEuՉ_P]B]g~(يJ>u8zv 1 э'<)uȘ$ P>n:O󍝡O%ă8C9+6{ˆ3` \1qdc K}.As-7w>Xٵ],'N#94 js $jm:,QP[4E"w^BʍA1m"%4#s-AXٝ Hu\)xG]$b/L%g1_1*7c8u=˝\>T__7^^MɍM%%%aDD{HحA^֎u[dmlܑh Ǔ??h T)q˸ȶͯ5^/k?CDxҼ6 *% cR{J ΩwQa_r_p}5v}83}d'Kh /4~i{|AiqQb\k.M=QwK ߏT.U|Nz?PK 7'UM{tpy4j/ClientServer.classW,,O&9q0$!GeEiLK{/bYrO$nKސB/w }ؿtQ}>ݝ~  N <؊d<#x4zcrL`$<&2yY63퀞ѓƌ 촑n;9g}qLed!M&LĞ[tt߰cSum&1rhywϘ`vҐ23لA5밷 vu̹l\NXx5[kr?>|VcjLLg!S9 cQƒ(oa&(-c,7E{VV[*ؔ4Rh-,ǯOҡ'պȔ8AѬ9MU17&'(=U״דWFoV[LaFn4M;u}gQ\/Bwr~&ۙ\d5LeN&' /v WXr̈́/Ņ;*ƭ?o\)PsS?dY\)9~! ~_+ ƀkpdns1ٍ|7(؏} > G 7&| ~+z?*S Zy4wptzg_(H)+x H}"Lm屻 +G>":ť KqYB'z>]D :M;N_TDKNTDKNTDK%MhR*w; hm\D]Ŀ-¿4A>"-t i (o19a1.NX밳֋PHd-kU>ܠj ֱ%FJ>jkIcޫ/8`؇ c/ʂc?6 1kPVb !iR%ܯ _pd+pUU] Wu.\ՅpU.s|Aa6]d <hݴ;mK"Z4_D/M 7ѮrXD&*E:7mѥij@{ ]P9F-.a_>8\Gps Gv籑Y'9NMoF+(8Et/>lǃ%S?B(4] {sx4YxNNqO={<x )SpO=s$TME9VDTKL KL}*iNRYjl/sT3W1אHHсd~XB*"TؐK1u!YbH}HB&Yf,Sɥ4d!C.7 CZ ҐVCVƐ y!k Y'0w[i-90`%z҂=~9ś;b̕ ]ɦlQV;n%V:1xp{b{kOL'{`1agbde3ɽvBP]ppW&KqAZ(9*ߖL$h&LL &3DA.mH`݅mJ̉l:[uZs"]y/J'O_A*2Vt/#@oՆސkۥ2R<:5/TݯRq572AII'um$"{=̩BؔԒN6gZ] ecqml'Hf" 1+;dG܃"e\kJRM٧PC%Ғ1$k~!ftH&q5Q9CĥܪEt% ]{E lp97jۑ;l}\Klu{r+[Lyrr'x۞O{ AOS`c5eN2̽@0mJ&w>F)"72` Y1"Tʱڑ e:X[C.FݔSuLvXW$r5&Y񸇯h%ҙT6I%8^GzQU*Ŵ@2uУ-n{+ܬ\Yŋ7m߼=fy9dyނ Ii /mٽ*D¹x8IvMXY*Y.bd ^ҋo9YF`+uY=(LM]_3{9Wxiͅ/16-(QL9k'Z~+TSWԕd7}orM] K"E.PB֕nMN/T:GM ?kP,yVF9t} _ Txq€'E>u%bY$]۷3JIQwBN]2ޫݶvPޫ{#F9~jcp㔸8̦3?M#xGy v6z LL;$ Fj]:$͡GƼks\*oP̯ ǂcZen~݈*zt*uOzM Zk3uiVjޏ0ֶ^hg#h!mk5RVXzvkS 28g7jKt6ZbE_A`eKp G%P%1ȡkS@Cø&f-5mǔf/u g#틤~FVi ,<P)/TieڰOvnIB̃' 2eC;rvS$D81ZAZ*Bsq}1_!| zzzzjQn>]nraxk4tshr276p.0 ߠeb.oXOxҷ'zt Z@^O"ַ|AxN:#,H ?ŋ<%K2 a/K-^|>i m%iW֊9C2&HA iܿ}Z'j4O&{ܪ9ZjïF)iU&iYھg|;ΝI2|#{-r^g ~CNo 0i>Dܜa;=T.4`{dGF.a{h{xb))f4c4+W2Mq1^vOxs4BēezJ!Oi|OƯ p+4tsUjOͳҜ yv!9-Yn'5<h"7sxbv4uB|y+yz4+JfU,7 -ҬxYun nHXnC!ɎVi !mnn.[rLNiə'X)kCbrF+o``h]uFF4JB[ F4l nVGdup҈35ñ%͛ѺNȞlͽY`;F[LT2^bAK-LSMg$mnIѶ foNӫ5 'X[pREEpAaGZvYj[k46靻hZI̶UY v'Fn@kI^0b)zXtIł`*پ:Ո2 P6X2 ̢@̻o[K?ȬYi'O&[NX pZ 1i8j4:6HpSib`dm0okґlLz-&X4jXhm&L P*tm0 ( tVL3plFĂ!&X 2ظS]( \^Ԓ ‰Ƒ4ޭ4T4\3u?\nqJ`|^.lx t l':cϏB:xS4!A,s Klq"ݻȞQ֊$k=B_|xbI>D,M1}Xgs8nd ӒuvJsG`?1Ӕ *Z -6`h`2c8wtq -j R`\Sӆd7u~P.~Ho B~93*u~oG}|8t;dXKx_(35ާ]JVwe_23cOEp4+R1T*I( e+e 톯H$mt@fs5?A1nDFlEZ6N:?ˇtz^} SIωtUּ/ pߎvQfL_ }' @VS8Za*.=J-fɖpڕF##ߚKyyU¢̐}K:_u~YE%ɌI_Wu~r i8@::fN}i럏t _@E\fȜV!՜FW鸑[K9'!Mr fH3H#ReQkH6Jw?g6;S,CW!&&N'+(C8ʂZ qTn#RJ-,9,g {^9勭XfGg,ђ`T%4֊-cڼ ِ̾?r87iʯD3)IRuai 5vGQ}FCF:݈0Z5sQo;A$FIUTK[Y~wK>L!SP${UxOxeo%'O,`}ɩt9&~oU@ֈWDI-2d,lʼ *j?r+f@s_Vo0ƺ0zĵI9->rJ_Ndb1j U8C=zZ\ƶT0iZ-nno\A6e)!N2d.% b{X5ZQ]ssSƦƍ-u2Mk8_Ӑ:`SD:a̢aY נDjSrR}N k_1\1d1Ɣ*_# QG ~7 6L W3^7s~,2_=lz-M"'|EsTDy$BT=mK(y{5Ux64!4;]ܤ/TTVy^g{a*2ZF-7WkDju$e$ѽ 0P#aөF1ݏnR2m|@*f7z)/M8%r'܁n*$T4{ix7R F(kFw,]Kn* Tq=4*0 x4!ut@K].FLLj}8qj4*OѴ^: ,2&)AE: h6hm/ /}t=C0ɚM&;bm#Ɏ&;be2 ,ׅrn=#=cD)AVO< % ;HO SLBYgpyP I.fnbz 7a1v+((GxE߂VuEdWK\¨<@qbYފQuӟY5@ש0Yrf#,j\$>HsĹ%顳.4=4 tPdGTMgXIhcv'MCPAZf!AhAPY 3NZP>< 3`TΜNOA̍=H``1l,` 7? @)@NciqN4,4>?h(N8b b k~>ASePiha>h+ j"Ct'}#2ӟ ()LSQcG.+D2rڿlH͍ind9> A`ϡ2~6X/.8FGiLvmUw@>I.PvYeg!I>d=0]\ b;X^,Vu P2|R Q #/4A.jIsjxLc̷c]+oykq>R,p~JuQaCX=␨Hu/E*#'h ʩ}$Smnʰw{Yz]Wi`krIW`^km-fd v'D 'GʙcY9)Ŕsr3?Xƚo7 H2NS3S6x6r| 8^ǡ  *xAYlp-r4Oj,a2jY6CHUg9s#| Bϒ%D7~A9H!~?PK 7'UM!tPpy4j/GatewayServer$1.class;o>#nvvvNFҢT̜TF!ĒԢ"IJDF~׼̼tԒv.FJ,}* }l0,VXb!s>e,n2 eM0L~ Uj+=޺ ð{MLnK_r-y"ԃP"D i_JIŰPt;-ԝ'OR8#[|ߨҢưVf:1ף07md^<!ndGW]]dA%D%&ulȮą]{a$F^W%#KcЇevCk*vF?tavFD,>2||:F8]6/, 63vcŬ!%C w bY]XN.؅EwpɰPK 7'UM* py4j/NetworkUtil.classViwU~K&Rb*DlKX4$X:ܶC3a2ӊ+ ox|M69?{>ϻ?؅G F<dG p S:Hx'dOxiLaaJ."3\+M.œ.<) RCQcI3NY)Nb?;+ [NZP:9И橽44NjhI9aØ㉉haZGio[8,l 眂˟Є`1аYfaa) =%?4̈@&9Lv\a@zWv5li!nrټeӼ6E6BJ3>ZWu}=ߐ^]v{:Bnj+Ը@6Q g 1we˞"XAַEw6QVUظFJV̔*XAmM+ %Fihym$ؒڭ۲S0 `y9}햫Q`b{MJ&zЫE/ ne¬4n IݸQ&+IٖajoR񖉷wV)Ng}|tic {R؇&>:>1)Κ &>_K3q^r\qU ͥ$ BǶBR=Oҽaa gQRS( ➔o$v%:S`%:n_5LAj N蚬T"LʄeV ߙ^_IBTr]WYAetԟ.f9525ݧ.vg)ys 31x'%2=  ʘTwpjw XpY[{2Rǡ}ۧgm"t:\/krr꭪I%RhqAQIU&NE[XeT#ýbJ*嶑JItbCUvytgZ ~1z4]@$%Ƶ_C|r|i1% N:OI׹ }E4_F[}%-KcV m%ӌKLfYzDfwNJ 4w%p7[xb"wO$)ZykbeZ;[iʚDo5\@/H#nOEezįpqw@SLmn7cH\ cD~S)X*" ^_CJ"uHLSѦl;3\YC$U*p$\*.Pv;>!$4$1Zā |Dg_Ks56V)ĨBa3kx(} y3xVu4ez8KeL>3{,bvel*bsѫXm].akk+"ǒKFDc}BFgxu?so_ N6 ]÷zCI&6КPK 7'UMFI7py4j/Py4JServerConnection.class;o>#v.vnFԒFa MIJD}5#GqFiIJ~y#f#F /-JNuIed 4 N-*K-rKM.+4ǦAl_Nb^RPY6200iV6(: H21pPK 7'UM~py4j/StringUtil.classuSMOQ=LJ"B[|T)jbAcaaNtapEܰpH4a_dLۀi{{%t &"."!!awD1&`\1"%uIS mb.${}r \EnQt͜a‘g2t4]]]S%yLPQlhֹ :MYm%˦VNZS* [;9YK:rb+rJvνhʛL.V0:]; n]} a9Cc9N a4FeNc1ez\5`|u<{RvqnW< ,ߐ5av U?H1vrKtҧ &2( PK  oNpy4j/reflection/PK 7'UM\K%py4j/reflection/MethodInvoker$1.classRn@=ӘRz%"\/(UR@OH+>AB@ 3gfvˏOŭ Nኃ2:XƊUXacPNeR&u^Z K!N2U/Tpߛ$#.ym;AiG5s>~*HG&"5xj.y ؠZ-?a9ae;A[@{c8U^H+z9XV9yD%=,zK18w#ɅEü%,tQ3͘'PK 7'UMaQ$py4j/reflection/ReflectionUtil.classS]oA=ײZQt*jPҗF&R8,#]mfcUՇQ;(e̹s??~x(аj`Hʰn<>:^J%CyqyЯIv^x!Sw<'(py4j/reflection/ReflectionEngine$1.classSN0=iCC6 + 61Cex+&EmJB\UmY_)k^ oml:Kl9ᕍ60q!S*Z -GGc ( }f~⾌ܦRBE{O@ w6Tw?VhI, gV3g:1d\";I2[ƈf }4j0Od.PK 7'UMC( #py4j/reflection/MethodInvoker.classX `S}hKi Hr)ZALGHsmnnC7<փ)" 69u&"}/M"ż]G$17nm~ .8pv wpA ;$r{ܻG>][>:5tQ=n܇n/E= G$~ 19yЍ恇ȕon7n<')j>n;7%?H4Ʌ?/x^ܘݘ4-%IyЅRWr\~Mz]$b@K  u|&GpTH9amw<*]T&le0&:Ա :A.)lKt\Mtt|Ku4`&t] yE,8~](~ͨF b&b(m|G%b.JE@]Td8=eV 8SF*?NVt~3!#+u-o06$^E^Ӱ{CSKbP6h:Uwо>0۪ެkى,m@3%۽urh!r*sOA(^ˏ bviit~X(H3RtW48N6A92EP3ѰxCfIw)?D4vyVUŲbȲ@}`Y"F%f Ofg^MA$G-Ϯ䞞4r9G[BkԇrlO6? Tg Z`lV$c,v^a` %6OUŒIem`>j5Zz=J.FR_]v )}HwHN[ܭ`k.mk8S!5z:]#n̕Y {yq1:m\a;"2Ґ/84.L>y;.0b?q/ȘZY~/=חP|e{w%G޹ʷI9=gQp4L ȵ逳I`y|dRRGES/-{:V`%GU||L[j\BiO.甒D}[ML{Lq܄IaF_m':pga\kV8ȣtAi=LJW+-(I^ZL>[0{T}ׅ)tА[r%ݣ[ =zy(ssj:):*빃!"C` .@h0N+X+6^D8x x'^Fa#`/6yս.%3PD~zW j$%{ʁm]j.E=\Y4uiAz(jP6fbEIy!(Q#p]lpVًrp>l+VՅ3މŎ._pAId,^{'Jw/|~\ʕ(p?]s4\S= Ռ Q`E yfP6q2W)8mYSBu)KK<$橅<%!.4$8RFmRa!σm c;*-Z\G [퍴&bLlo!ۈv;ؚİS'F-w׉ѾBnwa.U¸Uw wal&'5>Db x)TQe䎋Te#vYD#GpI>7BY4(Yii<`ee%|JSg8) SOMyL`"X }5xɒ&x4ѝz]p2q3rU!J W[Έx1%ΌXJKGwLKGD8J^ʷRf0)z]l%\tύKL߶4B F-G&LPK 7'UM0jG}py4j/reflection/LRUCache.classuS[OAvmmDRz)JjbK  ˖nIf/&*&OgIy999{׿o?ǂ Re dޖ;:F[ɭ<+2s qV^JWg:6Yc4*>ϫ5^e`/f*k)x<vo䉗5J)1mCtx<S\L^n$Gax|x >TYT,dQAHͺpܼ:2*Zs&wA&K{aݤvJ07ap}iw(;w6S}y;`ɿ 2~Gg}|ٮ\7E};`Ѵk`J§㛓@y !<E Da: }a&M5%Z!=JK^z1 {$˃H pQs'g$T~'p x\1DZa񌑔I)t$ƽ Β@GT"E0܂ UQET1Iђ$)qWS{]QJ2gHbG{:wtwt\wҧ񆗪N=nU3Sts-b14. u\[GT<Ď~r]=56؏ 3|Ǻ֩=OZU6"#%|q`0`9Fܚ;D *#7YCxf޿%ϧz: gOQVRc5(շX ITǟ['O٠syt+&iqMMP8ԿPK 7'UM@qC07py4j/reflection/CurrentThreadClassLoadingStrategy.classS]S@=ۆƆZAV8exm.!0ā/G9M*Ķrsޏ?} / xd6i *Sӱc[3ҞqhN4 +^r<rTOZ|^;'goFpc? N"#)؉~,y,]Un${,g?q;g\(U!Z9e,xXE\P`A$cq.rOEydܒ4zs0䕾-M0Hao* ha 1iGIpy(ZWϛGu"#~o*?vAA,7<8LOMFS ~z^ŷst,r[ tiZS P\,,LX[ԌM[F#{2Z9Rl")ct ':v$QDeDl+s5ԑ]vҼ,4jBbfjf4䳎7FŌ01vSzꮟ6fVte+z4c&Ʋ)%tTt~+rR3e9J̀(m*Ai8"q?W8,(fT{Ml9UtF5/+DH83^扏rA4i+\3jM)̐xlش2;lD@<3)%g.O1N[ֹ`RSp7"I/-#V 썏%#QtP!1:IMZtY-0\!k8xF{#E].U6Y㣸.0=LAv]:_v XH)O^nb*ԥKhN!d.W]zO/5| wr Kj5<٪V שt&5^q]ntM eDjXT@tx^|Iݔa?*umۼ5789N*†"|/ V4FPTrak2{=J #.c} fr1ƝE  8Gu"oI.ףZ5wkaµQQ?yԾfA9n%x ݀Q2` {c31fa{;tΆۂmwN5&Q!IݖlBZ xݫ]A DYPq=BGQxE@﹗JQB1| @ՄeB5lV=)؊o{~i(|?)#OnT{HcEe#m6q︍wb5}ؔ!/m^ < 'QI[ӼX#uj  Vb~j |y ^;BWfpqqz'Q9 ?LD |zFrޝk9eܼ2UһRc^rCI0X7su>O$ $Қ;L,1 +`u~OqGr_*^x /u䴫!i$__s&ߢsԠű=@zwwUyX^w?3~ۭ ҺPQ4RA+: C̼fO{Q3}4QVM 7{vq7y˼ePX]g*/* Dz34Q+(JXyz K׬k0f7R3# ~܆?hX!P)kxJdXSigXnMA*n2Ç3]02W;\ tIYM~a`l{g6P~fr=23S7C5}r+W'ʤv7Hje3j^-պ"b:gJH ŭFWUW*C%kXhQ5>< f_xRVZ<ܑ{{M:Ÿ%]gm; /Ȯn8 ٛ/ ȶd< b>mg!;td_GvMȾlM,d@6lat94<& *He'T=T" ?LVNݎ6$wav#[MW1B:M| 2[d [oS9 PK 7'UM|^)..py4j/reflection/RootClassLoadingStrategy.classR]OA=ӖԕBE/-Rk/ OXt;,,;d5End99Ι;?vn`/xV,:Xs.P?Љֱ@ @3ЉM*"1+2>XNX_T*̴IdG#:Y*3] wMړgl#UL"4n.BӺ-h|s{}%2x9s6svReزg$ UWawwV#o\E:1Kx.0m`D@.z|d]3IWk(I>@_߄J%28 A cnA >!rh`V{ۿP,\Tbc-5S,g9SWVj;7lկlYPK 7'UM$X\(py4j/reflection/PythonProxyHandler.classWWfw3צD--IHMcMD’i7I dw63,$VjZ>[GmB-  RTӟݙeݴ%{s=;߹gr/_ІhnjY8CU(Q?1>*O>c2>S >-l<.D?+s >/_PEOਂ'|Ix _U5u!4Yg-aYxNƷe< 3*2{ ?X?R֏eqZ/M֔aM85)A41+aI,=>s)''͌ƜL w5j-ݟT 笌vb{w ܾw{GmerƌTΔpK_m}=TzU7V"ֆ8&!445&Rߎ1#a9JXɘSfIVs3]*ƪcoI՗y37b?8Fv"d(A-d`:l&GgZI{*+EtL|i&-ӮRGh@U9d咩J"G%HtrDs9Ɋa3㘉!WBtXxYP*lڰsft6MiDSF6+<<5md efBhOZ6- j1zbɬ8;Bꗰb.+yX7?i WwJWhѯ-5sٛFa[VŚ}Jpyg5y tjf iT5 jrS5taW4\%jx ?#\'xc$kzE= ד ]qY븢ODQWf%ŢK%tvi%tC/^f˼G=$-@gNSfB<;AU~_ɸS*}p GBkk#Mbb0n3cV_Ɵ5%[=f.t]ӆ$tCl{fLDlwrFJI %}KviI/;e 0n#职}īU <{\f:,XQCcjƠ8X4U; ).wVDˉDɧ h*+ cTzQu{s+K@pnKh\g[$t{*#c-e(;{HU^!rEZY^!d4CFNV[.%;^CbsXrC4fo1 /("@+J#@.\u [Oe㪔4+ypjr̓{n- E!  ܱ˕pZ]Es%`sYHM!_sAMӆ365tYԆ<m_H#gk4jtg=>w ;p3;Z8-I.u%y,=e; G'5EX&KQNF$ZcV16_::ЇAt,H 133H܃QΆ1Qwig9p<P`CL?v8V-A?K܌ o6=x^\VjҜw͇   뜅퍅%ItDj5;^>pMQ\rX=y⭐p->BxFȰp,E|l/nGi`?GOr49L!O_4r@#w0 kLɈkLE/hoho%=،ZhmMғL$k+X"ncSi>\4DW8oxp`$&r,\CsR h/a#oa9 :!p.e>6u)0p<5mq`>H`"wH hS l>Z< &jc\D)΂^f!uܐ8\R1-ipG={=_+ 0J!"J15<tþaV]f:YG?j<6d=rV&Bf Ċ׶/gūˍ mn{[5Ek1KS]x^) rS [2$ac)˱i3vͤ[Rb<{kV0ݛF6%a/%ǭɐWܱ|qj5l(Λ^R5kEתzw(pP._Lv6)T-T&]g B1;\"NMz=pި1ըaRPX7nL`Ua2LT ;5ZWL/ɔOuܴ[m$}cҤֵп~NtM+?Z6j4'JL޳J-,YNI8'`8Cְ!l k:Tt:F1-$vftTHȿi^s5txS:kOHR>*u1 G$t\%#۔͑\ط Z\Pϻa&Nwgr|Zd=Pw y,ˍlNjժF}namdvDX[ &qRׂS-RNQ~rކZR=z (W]~~;c>g%R}2"YG =`zB/^G$ɤB9uDT(Ia;I)b~>L3D=WM\@Y2N,i@Y1 m-#3\k؝Oz6JmHkї#0N_bw>W蟈ODC;~5TwJqIw.ϰERy)ͱ< X}q:jXT\ad|EKC!% ($KU|hNqVo:I NB 5|78ጆOHtEnU >!=l4 60AzW6zplo>̪O",\, 8#϶dQ`3p P-a񳗵lb^kͽ9W>~}OeԇA<s\i"tdxUcƳ4]?\3O~y>/s-//%GKE:^ y, y_"z+Q/J}F~Z.xϓGAy{DKa{(YϠ=A]Tu{h mkp4RQr|a9,o6.­hN(GvE/.?h]㳙\Ek'. [V6DSgM-,͏xSi5BZCڂ{l ۀ̍dlgj֘smIɋn EbYauOCsp>6r"B0Dؔi`{[H_[]"(ǃ / *2$ xFW#[@xM(W1/Z]81Cn(V2螰!%2h e hf}ҥ`K(~ڀ9[ zs)iTwHe.3ȚBCv#Ǝ\7Ri;8ljaU$7ZM=QZr "g,ʰ{f;FxY[BGb`.Lb9긢{9߁TyEgL zX\=m[ł3jbr*G\K_K!bZ ꑃe4z?լuxL&ʟ=zMz13-uT=c}DphFnZ^@IkgW~l4nB4B=]9EV;u.=s|´*NHZq??C|No!4F:?4>#mkwsa)wMFypwp[(W)T!\Vatr#:?Ə}Ӄt 2KN?t\v]~ i5ڤ&d&{Oi-3u>, ::})Ma] Hʷà:+N`Ezq2-N@w;%]I_b<ޡߌ̌ LۢmLc:r8v׼ ^\Bi<: r=+$ҭ28pu$N"nTHər&GO4.u.UMmrEN– ,,Ҵ4cО w$GX[Eܘ!beN ˅'kTi.rU}9d7= <> /r]wߝvy)FM\cp2X^sZie]1V_:rJ=N;OFэDMɣg# ==yñ50prmN)-ݝ[v:Z u*a`kcFӅ\\v7m6= .,BDnʧF 6ʢOZq/%#j>JC0Fg7ƻoq~Y:A")YxNVH7P;›i71} /5*w NV>B<%ϓY>MǩW?rJz{:(4Y9N}_wG@>)R6K R,T̯rH+h*]eꕄ!@*ǔUFWЕJ,K_ @kM-_R9lznF7jtF7]6Êu(=Iԟ h+WU|o C=ry} 寒c0yӹǔJs-[Oh#U&q),v4 | UEn M4Lߠr,M:Rȭ֥*Xyע?jpy Fi/\1f~>߃=s f  UZNDf+ 0f `f; v Ct(̇s 9:=8@m,{cB8Єp LUy|wwRuАzxi+:/9`S!QI3,A) 4S0n 4 ufTUJ`3G#cVf=B4haW U"XG!M*^<;,yj.'Z+z∱&5%pUCӨ<רWyPoK -0?תp<[<$ {-Ӡ^Dsrڣ%gF}Y~h\ bغ-Ŷ&O6[CL'{4{y `n[Qw\PvffMٶ/%OD`M4MVFٲڴ3C^YVwmZږMdh<Mxq4WeQ4[U8C2[+IVսVk:3 I*D:5E#7V*/T -pgK88V*/?9A%\J4D!Ax-IDi/K`1J^JBOH}3/0 9c|/1jAS!S U[W[1TmAXCU] b9Pصvl|6ޔ}yE(SJ EslNnf,j+eu<$z36 \VJ3Vg:\pF%|F(vh!b)X R%MgBM>Zg;[!3Ty8~6Z:Cbmϐ! H $@ q bΑğ2SHY!gY6h,I0NG14tX> ZqBF F31yhHU#5ȘKfpݱaSFO1"h&eM9\?=80:NS40: Τ`g>;Ii}fa4҆QA0ڐh !ku`0zF?JsuCFϨ #ij͕ZA3܎*܎:e7tƹs ٲ2i6M'R~^ssgY'KHEB1ͥ..W$~!Vr;W)N(L+r5YGyreA_;ͨk? CoyX< dVGxF g}rIeULL BI(Bi;USV+ YqrKFB[~Nn)pnq,Gنq1Nj9q*EK7ۄG2#+[ fn a}rAfhiAR!rTF?r`%E ʘEz'ɆV$ipR E Gb bm'PC|i@ڈH ]mrgS;C *'ھ9-|(sFv8.NȰþdBYaXD1H%=Be?]?ܠp֭6E:t>6,|<]|H u/8;QX,!_!(tC3hoӗj=f$#~1pL+,*/7v`'dsT@;< 0<֜X_d?%qM- u}[;m6,|Ny'l; 7@W5wkVoq@mgZ-ZFs?GC6-kQQgtAģw!W񊑯jW4JBЩjW冹ʬ6ԍ ZC&.JN­I}$tPK t4UM|rzdg.META-INF/maven/net.sf.py4j/py4j/pom.propertiesSvOK-J,IMQHTM,KR.SO.Q02T00262Tpu Q020*K-*ϳ534г3J//-LK-+N+4J,*LKL. PK  oN AMETA-INF/PK MoNG!879)META-INF/MANIFEST.MFPK  oNAjnegmas/PK LoNӠ(jnegmas/PyReadable.classPK LoN[) jnegmas/PyCaller.classPK LoNARjnegmas/utilities/PK LoNbwT)jnegmas/utilities/PyUtilityFunction.classPK LoNՎ2/jnegmas/utilities/AbstractUtilityFunction.classPK LoND:z'jnegmas/utilities/UtilityFunction.classPK LoNA>jnegmas/outcomes/PK LoN7R2alojnegmas/outcomes/Issue.classPK LoNPcx" jnegmas/outcomes/OutcomeType.classPK LoNAjnegmas/common/PK LoN')2)#jnegmas/common/MechanismState.classPK LoN#բ&" jnegmas/common/MechanismInfo.classPK LoN8CU^m jnegmas/PyCallable.classPK LoN A jnegmas/sao/PK LoN p& jnegmas/sao/AspirationNegotiator.classPK LoNهBjnegmas/sao/SAONegotiator.classPK LoNCK}Ɉ!jnegmas/sao/PySAONegotiator.classPK LoNAjnegmas/situated/PK LoNnaljnegmas/situated/Query.classPK LoNxFX\z!Pjnegmas/situated/PyContract.classPK LoNܝ~ jnegmas/situated/Contract.classPK LoN_[0!&jnegmas/situated/PyBulletinBoard.classPK LoNni,8jnegmas/situated/PyAgentWorldInterface.classPK  oN.Ed 9jnegmas/JNegmasApp.classPK LoN A%jnegmas/apps/PK MoNA&jnegmas/apps/scml/PK LoNA2&jnegmas/apps/scml/simulators/PK LoNX<_5o&jnegmas/apps/scml/simulators/PyFactorySimulator.classPK MoN#Ak)jnegmas/apps/scml/factory_managers/PK MoNop*4)jnegmas/apps/scml/factory_managers/ProductInfo.classPK LoN߹$=*+jnegmas/apps/scml/factory_managers/GreedyFactoryManager.classPK LoNԼly7,1jnegmas/apps/scml/factory_managers/FactoryManager.classPK MoNB}\@3jnegmas/apps/scml/factory_managers/DoNothingFactoryManager.classPK MoNӸl.29jnegmas/apps/scml/factory_managers/MiddleMan.classPK LoN&k9?jnegmas/apps/scml/factory_managers/PyFactoryManager.classPK LoNFF?@jnegmas/apps/scml/factory_managers/AbstractFactoryManager.classPK MoNAHjnegmas/apps/scml/common/PK MoNbN /PHjnegmas/apps/scml/common/ProductionReport.classPK MoN[Ʈ3,Mjnegmas/apps/scml/common/ManufacturingProfile.classPK MoNѳa_t&+Qjnegmas/apps/scml/common/Process.classPK LoNJ#Tjnegmas/apps/scml/common/Loan.classPK LoNQ2(?Xjnegmas/apps/scml/common/SCMLAgent.classPK MoNn%Zjnegmas/apps/scml/common/Breach.classPK MoNg1|\jnegmas/apps/scml/common/RunningCommandInfo.classPK MoN?2b,_jnegmas/apps/scml/common/SCMLAgreement.classPK MoNc2dcjnegmas/apps/scml/common/FactoryStatusUpdate.classPK LoN=ñ0fjnegmas/apps/scml/common/ProductionFailure.classPK MoN? "jjnegmas/apps/scml/common/CFP.classPK MoNyr &5pjnegmas/apps/scml/common/Product.classPK MoN؇5O3sjnegmas/apps/scml/common/RenegotiationRequest.classPK MoNdPb-ujnegmas/apps/scml/common/ProductionNeed.classPK MoN2m+xjnegmas/apps/scml/common/MissingInput.classPK MoN}R#3;{jnegmas/apps/scml/common/ManufacturingProfileCompiled.classPK LoN!w`%"jnegmas/apps/scml/common/Job.classPK MoN\DP7jnegmas/apps/scml/common/ProductManufacturingInfo.classPK MoNSS*tjnegmas/apps/scml/common/InputOutput.classPK MoNY.wjnegmas/apps/scml/common/InsurancePolicy.classPK MoNAjnegmas/apps/scml/awi/PK MoN{4?|U%Rjnegmas/apps/scml/awi/PySCMLAWI.classPK  oNpy4j/PK 7'UMC,6py4j/Py4JPythonClient.classPK 7'UM?V(py4j/DefaultApplication.classPK 7'UM#2 +Cpy4j/Protocol.classPK 7'UMQpy4j/Py4JJavaException.classPK 7'UMCv J {py4j/JavaServer.classPK 7'UM ]py4j/CallbackConnection.classPK 7'UMSwpy4j/ClientServer$1.classPK 7'UMv[Sx^Hpy4j/CallbackClient$1.classPK 7'UM&$sO(py4j/Gateway.classPK 7'UM1=oZ-xpy4j/GatewayServer$GatewayServerBuilder.classPK 7'UMI>v +2py4j/ClientServer$ClientServerBuilder.classPK 7'UMAr py4j/Py4JNetworkException.classPK 7'UMFppy4j/Py4JException.classPK 7'UM>  py4j/GatewayServerListener.classPK 7'UMj )py4j/PythonClient.classPK 7'UMՂ-e%py4j/CallbackClient.classPK 7'UM ^)tpy4j/Py4JNetworkException$ErrorTime.classPK 7'UMnHpy4j/GatewayServer.classPK 7'UMR @4py4j/Py4JJavaServer.classPK 7'UM׻T F4py4j/ReturnObject.classPK 7'UMNt"py4j/Py4JClientConnection.classPK 7'UM\#py4j/Base64.classPK  oN p2py4j/model/PK 7'UMauL)"2py4j/model/HelpPageGenerator.classPK 7'UM!XY\9py4j/model/Py4JClass.classPK 7'UMLsBpy4j/model/Py4JMember.classPK 7'UMĝ5~?Epy4j/model/Py4JField.classPK 7'UM8ʍ VHpy4j/model/Py4JMethod.classPK  oN*Mpy4j/commands/PK 7'UMMNZ =XMpy4j/commands/ListCommand.classPK 7'UMWH$Xpy4j/commands/ExceptionCommand.classPK 7'UM;DN ]py4j/commands/FieldCommand.classPK 7'UM? dpy4j/commands/DirCommand.classPK 7'UM.x !npy4j/commands/StreamCommand.classPK 7'UMUo0<# vpy4j/commands/AbstractCommand.classPK 7'UMΐm!|py4j/commands/MemoryCommand.classPK 7'UM3O/ * &py4j/commands/ConstructorCommand.classPK 7'UM|^py4j/commands/CallCommand.classPK 7'UM+F|py4j/commands/Command.classPK 7'UM:#Hpy4j/commands/HelpPageCommand.classPK 7'UM0py4j/commands/ShutdownGatewayServerCommand.classPK 7'UM  py4j/commands/ArrayCommand.classPK 7'UM2h"ءpy4j/commands/JVMViewCommand.classPK 7'UM |%)py4j/commands/ReflectionCommand.classPK 7'UM[\ mpy4j/commands/AuthCommand.classPK 7'UMs*py4j/JVMView.classPK 7'UM{tɾpy4j/ClientServer.classPK 7'UMyt#rpy4j/GatewayConnection.classPK 7'UMc+!~py4j/ClientServerConnection.classPK 7'UM!tPvpy4j/GatewayServer$1.classPK 7'UM_l'Ipy4j/DefaultGatewayServerListener.classPK 7'UM* :py4j/NetworkUtil.classPK 7'UMz$Z$py4j/Py4JPythonClientPerThread.classPK 7'UMFI7py4j/Py4JServerConnection.classPK 7'UM~py4j/StringUtil.classPK 7'UMF##&py4j/Py4JAuthenticationException.classPK  oNpy4j/reflection/PK 7'UM\K%py4j/reflection/MethodInvoker$1.classPK 7'UMaQ$py4j/reflection/ReflectionUtil.classPK 7'UMﰐ>(ypy4j/reflection/ReflectionEngine$1.classPK 7'UMC( #spy4j/reflection/MethodInvoker.classPK 7'UM:"Zy*py4j/reflection/ClassLoadingStrategy.classPK 7'UM0jG}py4j/reflection/LRUCache.classPK 7'UMS V #py4j/reflection/TypeConverter.classPK 7'UM@qC07;py4j/reflection/CurrentThreadClassLoadingStrategy.classPK 7'UMq_)py4j/reflection/TypeUtil.classPK 7'UM|^)..,py4j/reflection/RootClassLoadingStrategy.classPK 7'UM$X\(.py4j/reflection/PythonProxyHandler.classPK 7'UM &7py4j/reflection/MethodDescriptor.classPK 7'UMOc8&<py4j/reflection/ReflectionEngine.classPK  oNRMETA-INF/maven/PK  oNRMETA-INF/maven/net.sf.py4j/PK  oN RMETA-INF/maven/net.sf.py4j/py4j/PK Z4UM"0f'+SMETA-INF/maven/net.sf.py4j/py4j/pom.xmlPK t4UM|rzdg.VMETA-INF/maven/net.sf.py4j/py4j/pom.propertiesPK*PWPK!d_GGnegmas/external/negload.javaimport java.util.jar.JarEntry; import java.util.jar.JarInputStream; import java.io.FileInputStream; import java.lang.Class; import java.io.BufferedReader; import java.io.InputStreamReader; import java.nio.charset.Charset; import py4j.GatewayServer; import java.io.Serializable; import java.util.HashMap; import java.util.ArrayList; import java.util.List; import java.util.UUID; import negotiator.AgentID; import negotiator.Bid; import negotiator.Deadline; import negotiator.DeadlineType; import negotiator.Domain; import negotiator.DomainImpl; import negotiator.actions.Accept; import negotiator.actions.Inform; import negotiator.actions.Action; import negotiator.actions.EndNegotiation; import negotiator.actions.Offer; import negotiator.issue.Issue; import negotiator.issue.IssueDiscrete; import negotiator.issue.Value; import negotiator.issue.ValueDiscrete; import negotiator.parties.AbstractNegotiationParty; import negotiator.parties.NegotiationInfo; import negotiator.persistent.DefaultPersistentDataContainer; import negotiator.persistent.PersistentDataType; import negotiator.timeline.ContinuousTimeline; import negotiator.timeline.DiscreteTimeline; import negotiator.timeline.TimeLineInfo; import negotiator.utility.AbstractUtilitySpace; import negotiator.utility.AdditiveUtilitySpace; import negotiator.Agent; import java.util.Map; class MapUtil { public static String mapToString(Map map , String entry_separator, String internal_separator) { StringBuilder stringBuilder = new StringBuilder(); for (String key : map.keySet()) { if (stringBuilder.length() > 0) { stringBuilder.append(entry_separator); } String value = map.get(key); //try { //stringBuilder.append((key != null ? URLEncoder.encode(key, "UTF-8") : "")); stringBuilder.append((key != null ? key : "")); stringBuilder.append(internal_separator); stringBuilder.append(value != null ? value : ""); //stringBuilder.append(value != null ? URLEncoder.encode(value, "UTF-8") : ""); //} catch (UnsupportedEncodingException e) { // throw new RuntimeException("This method requires UTF-8 encoding support", e); // } } return stringBuilder.toString(); } public static Map stringToMap(String input , String entry_separator, String internal_separator ) { Map map = new HashMap(); String[] nameValuePairs = input.split(entry_separator); for (String nameValuePair : nameValuePairs) { String[] nameValue = nameValuePair.split(internal_separator); //try { //map.put(URLDecoder.decode(nameValue[0], "UTF-8"), nameValue.length > 1 ? URLDecoder.decode( // nameValue[1], "UTF-8") : ""); map.put(nameValue[0], nameValue.length > 1 ? nameValue[1] : ""); //} catch (UnsupportedEncodingException e) { // throw new RuntimeException("This method requires UTF-8 encoding support", e); //} } return map; } } class NegLoader{ public String jarName = "genius-8.0.4-jar-with-dependencies.jar"; private HashMap parties = null; private HashMap agents = null; private HashMap is_party = null; private HashMap infos = null; private HashMap ids = null; private HashMap domains = null; private HashMap util_spaces = null; private HashMap first_actions = null; private HashMap > issues_all; private HashMap > > string2values = null; private HashMap > string2issues = null; private HashMap timelines = null; private int n_agents = 0; private String INTERNAL_SEP = "<>"; private String ENTRY_SEP = "<>"; private String FIELD_SEP = "<>"; public class Serialize implements Serializable{ } public NegLoader(){ parties = new HashMap(); agents = new HashMap(); is_party = new HashMap(); infos = new HashMap(); ids = new HashMap(); domains = new HashMap(); util_spaces = new HashMap(); first_actions = new HashMap(); string2values = new HashMap > >(); issues_all = new HashMap >(); timelines = new HashMap(); string2issues = new HashMap >(); } public String test(String class_name){ ArrayList classes = new ArrayList(); System.out.println("Jar " + jarName ); try { JarInputStream jarFile = new JarInputStream(new FileInputStream( jarName)); JarEntry jarEntry; while (true) { jarEntry = jarFile.getNextJarEntry(); if (jarEntry == null) { break; } if (jarEntry.getName().endsWith(".class")) { //System.out.println("Found " // + jarEntry.getName().replaceAll("/", "\\.")); classes.add(jarEntry.getName().replaceAll("/", "\\.")); } } Class clazz = Class.forName(class_name); System.out.println(clazz.toString()); //Constructor constructor = clazz.getConstructor(String.class, Integer.class); AbstractNegotiationParty instance = (AbstractNegotiationParty) clazz.newInstance(); return instance.getDescription(); } catch (Exception e) { e.printStackTrace(); } return ""; } private NegotiationInfo createNegotiationInfo(String domain_file_name, String utility_file_name, boolean real_time , int max_time, long seed, String agent_uuid) { try { DomainImpl domain = new DomainImpl(domain_file_name); AdditiveUtilitySpace utilSpace = new AdditiveUtilitySpace(domain, utility_file_name); TimeLineInfo timeline; DeadlineType tp; if(real_time) { tp = DeadlineType.TIME; timeline = new ContinuousTimeline(max_time); }else { tp = DeadlineType.ROUND; timeline = new DiscreteTimeline(max_time); } Deadline deadline = new Deadline(max_time, tp); long randomSeed = seed; AgentID agentID = new AgentID(agent_uuid); DefaultPersistentDataContainer storage = new DefaultPersistentDataContainer(new Serialize(), PersistentDataType.DISABLED); NegotiationInfo info = new NegotiationInfo(utilSpace, deadline, timeline, randomSeed, agentID, storage); infos.put(agent_uuid, info); ids.put(agent_uuid, agentID); util_spaces.put(agent_uuid, utilSpace); domains.put(agent_uuid, domain); timelines.put(agent_uuid, timeline); first_actions.put(agent_uuid, true); ArrayList issues = (ArrayList) utilSpace.getDomain().getIssues(); issues_all.put(agent_uuid, issues); string2values.put(agent_uuid, this.init_str_val_conversion(agent_uuid, issues)); HashMap striss = new HashMap(); for(Issue issue:issues){ striss.put(issue.toString(), issue); } string2issues.put(agent_uuid, striss); return info; } catch (Exception e) { // TODO: handle exception System.out.println(e); } return null; } public void on_negotiation_start( String agent_uuid, int n_agents, long n_steps, long time_limit, boolean real_time, String domain_file_name, String utility_file_name ){ this.n_agents = n_agents; if (is_party.get(agent_uuid)) { AbstractNegotiationParty agent = this.parties.get(agent_uuid); NegotiationInfo info = createNegotiationInfo(domain_file_name, utility_file_name, real_time , real_time ? (int) time_limit : (int) n_steps , 0, agent_uuid); if (info == null) return; parties.get(agent_uuid).init(info); }else{ Agent agent = this.agents.get(agent_uuid); agent.init(); } System.out.format("Agent %s: time limit %d, step limit %d\n", getName(agent_uuid) , time_limit, n_steps); } public String create_agent(String class_name){ try { //JarInputStream jarFile = new JarInputStream(new FileInputStream( // jarName)); Class clazz = Class.forName(class_name); String uuid = class_name + UUID.randomUUID().toString(); //Constructor constructor = clazz.getConstructor(String.class, Integer.class); if (AbstractNegotiationParty.class.isAssignableFrom(clazz)) { AbstractNegotiationParty agent = (AbstractNegotiationParty) clazz.newInstance(); this.is_party.put(uuid, true); this.parties.put(uuid, agent); }else{ Agent agent = (Agent) clazz.newInstance(); this.is_party.put(uuid, false); this.agents.put(uuid, agent); } return uuid; } catch (Exception e) { e.printStackTrace(); } return ""; } public String actionToString(Action action){ String id = action.getAgent().getName(); Bid bid = null; if(action instanceof Offer){ bid = ((Offer) action).getBid(); List issues = bid.getIssues(); HashMap vals = bid.getValues(); HashMap vals_str = new HashMap(); for (Integer key : vals.keySet()) { vals_str.put(issues.get(key-1).toString(), vals.get(key).toString()); } String bidString = MapUtil.mapToString(vals_str, ENTRY_SEP , INTERNAL_SEP); return id + FIELD_SEP + "Offer" + FIELD_SEP + bidString; } else if(action instanceof EndNegotiation) return id + FIELD_SEP + "EndNegotiation" + FIELD_SEP; else if(action instanceof Accept) return id + FIELD_SEP + "Accept" + FIELD_SEP; return id + FIELD_SEP + "Failure" + FIELD_SEP; } public String choose_action(String agent_uuid) { if (is_party.get(agent_uuid)) return choose_action_party(agent_uuid); return choose_action_agent(agent_uuid); } public String choose_action_agent(String agent_uuid) { Agent agent = agents.get(agent_uuid); boolean isFirstTurn = first_actions.get(agent_uuid); TimeLineInfo timeline = timelines.get(agent_uuid); List> validActions = new ArrayList>(); if(!isFirstTurn) validActions.add(Accept.class); validActions.add(EndNegotiation.class); validActions.add(Offer.class); negotiator.actions.Action action = agent.chooseAction(validActions); if(timeline instanceof DiscreteTimeline) ((DiscreteTimeline) timeline).increment(); return actionToString(action); } public String choose_action_party(String agent_uuid) { AbstractNegotiationParty agent = parties.get(agent_uuid); boolean isFirstTurn = first_actions.get(agent_uuid); TimeLineInfo timeline = timelines.get(agent_uuid); List> validActions = new ArrayList>(); if(!isFirstTurn) validActions.add(Accept.class); validActions.add(EndNegotiation.class); validActions.add(Offer.class); negotiator.actions.Action action = agent.chooseAction(validActions); if(timeline instanceof DiscreteTimeline) ((DiscreteTimeline) timeline).increment(); return actionToString(action); } public Boolean receive_message(String agent_uuid, String from_id , String typeOfAction, String bid_str){ if (is_party.get(agent_uuid)) return receive_message_party(agent_uuid, from_id, typeOfAction, bid_str); return receive_mesasge_agent(agent_uuid, from_id, typeOfAction, bid_str); } public Boolean receive_mesasge_agent(String agent_uuid, String from_id , String typeOfAction, String bid_str) { Agent agent = agents.get(agent_uuid); boolean isFirstTurn = first_actions.get(agent_uuid); if(isFirstTurn) first_actions.put(agent_uuid, false); Bid bid = str2bid(agent_uuid, bid_str); AgentID agentID = new AgentID(from_id); Action act = null; if (typeOfAction.contains("Offer")){ act = new Offer(agentID, bid); } else if(typeOfAction.contains("Accept")){ act = new Accept(agentID, bid); } else if(typeOfAction.contains("EndNegotiation")) act = new EndNegotiation(agentID); agent.ReceiveMessage(act); return true; } public Boolean receive_message_party(String agent_uuid, String from_id , String typeOfAction, String bid_str){ AbstractNegotiationParty agent = parties.get(agent_uuid); boolean isFirstTurn = first_actions.get(agent_uuid); if(isFirstTurn) first_actions.put(agent_uuid, false); Bid bid = str2bid(agent_uuid, bid_str); AgentID agentID = new AgentID(from_id); Action act = null; if (typeOfAction.contains("Offer")){ act = new Offer(agentID, bid); } else if(typeOfAction.contains("Accept")){ act = new Accept(agentID, bid); } else if(typeOfAction.contains("EndNegotiation")) act = new EndNegotiation(agentID); agent.receiveMessage(agentID, act); return true; } public HashMap> init_str_val_conversion(String agent_uuid, ArrayList issues){ HashMap> string2value = new HashMap> (); for(Issue issue:issues){ String issue_name = issue.toString(); string2value.put(issue_name, new HashMap()); List values = ((IssueDiscrete)issue).getValues(); for(Value value:values){ string2value.get(issue_name).put(value.toString(), value); } } return string2value; } public Bid str2bid(String agent_uuid, String bid_str){ AbstractUtilitySpace utilSpace = util_spaces.get(agent_uuid); ArrayList issues = issues_all.get(agent_uuid); //Bid bid = new Bid(utilSpace.getDomain());//.getRandomBid(new Random()); if(bid_str.equals("")) return null; String[] bid_strs = bid_str.split(ENTRY_SEP); HashMap vals = new HashMap(); for(String str:bid_strs) { String[] vs = str.split(INTERNAL_SEP); String issue_name = vs[0]; String val = vs.length > 1? vs[1]: ""; vals.put(string2issues.get(agent_uuid).get(issue_name).getNumber(), string2values.get(agent_uuid).get(issue_name).get(val)); } return new Bid(utilSpace.getDomain(), vals); } public void informMessage(String agent_uuid, int agent_num){ Inform inform = new Inform(ids.get(agent_uuid), "NumberOfAgents", agent_num); parties.get(agent_uuid).receiveMessage(ids.get(agent_uuid), inform); } public void informMessage(String agent_uuid){ Inform inform = new Inform(ids.get(agent_uuid), "NumberOfAgents", this.n_agents); parties.get(agent_uuid).receiveMessage(ids.get(agent_uuid), inform); } public String getName(String agent_uuid){ if (this.is_party.get(agent_uuid)) return parties.get(agent_uuid).getDescription(); else return agents.get(agent_uuid).getDescription(); } public static void main(String[] args) { int port = 25333; boolean dieOnBrokenPipe=false; System.out.format("Received options: "); for (int i = 0; i < args.length; i++) { String opt = args[i]; System.out.format("%s ", opt); if (opt.equals("--die-on-exit")) { dieOnBrokenPipe = true; } else { port = Integer.parseInt(opt); } } System.out.format("\n"); NegLoader app = new NegLoader(); // app is now the gateway.entry_point GatewayServer server = new GatewayServer(app, port); server.start(); int listening_port = server.getListeningPort(); System.out.format("Gateway to python started at port %d listening to port %d\n", port, listening_port); if (dieOnBrokenPipe) { /* Exit on EOF or broken pipe. This ensures that the server dies * if its parent program dies. */ try { BufferedReader stdin = new BufferedReader(new InputStreamReader(System.in, Charset.forName("UTF-8"))); stdin.readLine(); System.exit(0); } catch (java.io.IOException e) { System.exit(1); } } } } PK!pCnegmas/generics.pyr"""A set of generic classes and corresponding functions to iterate and index them. The main goal of having this module is to allow for flexible modeling of collections with *most* python builtin collections (e.g. `list`, `tuple`, `generator`) or even `Callable`\ s without awkward `isinstance` calls in other modules of the library. """ from typing import Iterable, Union, Mapping, Sequence, Callable, Any, Tuple, Dict __all__ = [ "IterableMapping", # A mapping combining dicts, lists, tuples, and generators "GenericMapping", # An iterable mapping or a callable (e.g. function/functor) # GenericMapping functions (apply to GMapping and IterableMapping) "gmap", # An index on an IterableMapping or a call on a Callable "gget", # Like `gmap` but can return a default value # IterableMapping functions (apply only to IterableMappings) "ienumerate", # enumerates a mapping as key-value pairs "iitems", # enumerates a mapping as key-value pairs "ivalues", # enumerates all values in a mapping (no keys) "ikeys", # enumerates all keys in a mapping (no values) "iget", # Similar to `gget` but applies only to IterableMappings ] # Generic classes that work with a variety of python mappings like collections or callables IterableMapping = Union[Mapping, Sequence] """Something that can be iterated upon with Key-value pairs (e.g. list, dict, tuple).""" GenericMapping = Union[Callable[[Any], Any], IterableMapping] """Something that can be indexed using [] or called using ()""" def gmap(group: GenericMapping, param: Any) -> Any: """Calls or indexes the group by the param Args: group: Either a Callable or a Mapping param: The parameters to use for mapping Examples: >>> gmap([1, 23, 44], 1) 23 >>> gmap({'a': 3, 'b': 5, 'c': 4}, 'c') 4 >>> gmap(lambda x: 3*x, 20) 60 Returns: """ if hasattr(group, "__call__"): return group(param) # type: ignore return group[param] # type: ignore def gget(x: GenericMapping, _key: Any, default=None) -> Any: """Get an item from an IterableMapping Args: x: the generic mapping _key: key (must be immutable) default: default value if no value attached with the key is found Examples: Example with a list >>> [gget([10, 20, 30], _) for _ in (0, 2,1, -1, 4)] [10, 30, 20, 30, None] Example with a dictionary >>> [gget({'a':10, 'b':20, 'c':30}, _) for _ in ('a', 'c','b', -1, 'd')] [10, 30, 20, None, None] Example with a tuple >>> [gget((10, 20, 30), _) for _ in (0, 2,1, -1, 4)] [10, 30, 20, 30, None] Example with a generator >>> [gget(range(10, 40, 10), _) for _ in (0, 2,1, -1, 4)] [10, 30, 20, 30, None] Returns: """ if hasattr(x, "apply"): # noinspection PyBroadException try: return x(_key) # type: ignore except Exception: return default else: return iget(x, _key, default) # type: ignore def ienumerate(x: IterableMapping) -> Iterable[Tuple[Any, Any]]: """Enumerates a GenericMapping. Args: x (IterableMapping): A generic mapping (see `GenericMapping`) Examples: Example with a list >>> for k, cutoff_utility in ienumerate([10, 20, 30]): print(k, cutoff_utility, end='-') 0 10-1 20-2 30- Example with a dictionary >>> for k, cutoff_utility in ienumerate({'a': 10, 'b': 20, 'c': 30}): print(k, cutoff_utility, end='-') a 10-b 20-c 30- Example with a tuple >>> for k, cutoff_utility in ienumerate((10, 20, 30)): print(k, cutoff_utility, end='-') 0 10-1 20-2 30- Example with a generator >>> for k, cutoff_utility in ienumerate(range(10, 40, 10)): print(k, cutoff_utility, end='-') 0 10-1 20-2 30- Returns: a generator/iterator with tuples of key-value pairs. """ if isinstance(x, Dict): return x.items() else: return enumerate(x) iitems = ienumerate def ivalues(x: IterableMapping) -> Iterable[Any]: """Returns all keys of the iterable. Args: x (IterableMapping): A generic mapping (see `GenericMapping`) Examples: Example with a list >>> for k in ivalues([10, 20, 30]): print(k, end='-') 10-20-30- Example with a dictionary >>> for k in ivalues({'a': 10, 'b': 20, 'c': 30}): print(k, end='-') 10-20-30- Example with a tuple >>> for k in ivalues((10, 20, 30)): print(k, end='-') 10-20-30- Example with a generator >>> for k in ivalues(range(10, 40, 10)): print(k, end='-') 10-20-30- Returns: a generator/iterator with tuples of key-value pairs. """ if isinstance(x, Dict): return list(x.values()) else: return x def ikeys(x: IterableMapping) -> Iterable[Any]: """Returns all keys of the iterable. Args: x (IterableMapping): A generic mapping (see `GenericMapping`) Examples: Example with a list >>> for k in ikeys([10, 20, 30]): print(k, end='-') 0-1-2- Example with a dictionary >>> for k in ikeys({'a': 10, 'b': 20, 'c': 30}): print(k, end='-') a-b-c- Example with a tuple >>> for k in ikeys((10, 20, 30)): print(k, end='-') 0-1-2- Example with a generator >>> for k in ikeys(range(10, 40, 10)): print(k, end='-') 0-1-2- Returns: a generator/iterator with tuples of key-value pairs. """ if isinstance(x, Dict): return list(x.keys()) else: return range(len(x)) # type: ignore def iget(x: IterableMapping, _key: Any, default=None) -> Any: """Get an item from an IterableMapping Args: x: the generic mapping _key: key (must be immutable) default: default value if no value attached with the key is found Examples: Example with a list >>> [iget([10, 20, 30], _) for _ in (0, 2,1, -1, 4)] [10, 30, 20, 30, None] Example with a dictionary >>> [iget({'a':10, 'b':20, 'c':30}, _) for _ in ('a', 'c','b', -1, 'd')] [10, 30, 20, None, None] Example with a tuple >>> [iget((10, 20, 30), _) for _ in (0, 2,1, -1, 4)] [10, 30, 20, 30, None] Example with a generator >>> [iget(range(10, 40, 10), _) for _ in (0, 2,1, -1, 4)] [10, 30, 20, 30, None] Returns: """ if isinstance(x, Dict): return x.get(_key, default) try: return x[_key] # type: ignore except IndexError: return default PK!Mwaanegmas/genius.py""" Genius Negotiator An agent used to connect to GENIUS agents (ver 8.0.4) and allow them to join negotiation mechanisms """ import pathlib import os import random import socket import subprocess import time import typing from typing import Optional, List, Tuple, Sequence import pkg_resources from py4j.java_gateway import JavaGateway, CallbackServerParameters, GatewayParameters from py4j.protocol import Py4JNetworkError from negmas import ( SAONegotiator, make_discounted_ufun, get_domain_issues, NEGMAS_CONFIG, CONFIG_KEY_GENIUS_BRIDGE_JAR, ) from negmas import ResponseType, load_genius_domain from negmas.common import * from negmas.utilities import UtilityFunction import json DEFAULT_JAVA_PORT = 25337 DEFAULT_PYTHON_PORT = 25338 if typing.TYPE_CHECKING: from negmas import Outcome __all__ = [ "GeniusNegotiator", # Most abstract kind of agent "init_genius_bridge", "genius_bridge_is_running", ] INTERNAL_SEP, ENTRY_SEP, FIELD_SEP = "<>", "<>", "<>" common_gateway: Optional[JavaGateway] = None common_port: int = 0 java_process = None python_port: int = 0 all_agent_based_agents = [ "agents.TestingAgent", "agents.SimpleANAC2013Agent", "agents.UIAgentExtended", "agents.SimilarityAgent", "agents.OptimalBidderU", "agents.TestAgent", "agents.SimpleTFTAgent", "agents.BayesianAgentForAuction", "agents.ABMPAgent", "agents.RandomIncreasingUtilAgent", "agents.OptimalBidder", "agents.SimpleAgentSavingBidHistory", "agents.SimpleAgent", "agents.UIAgent", "agents.DecUtilAgent", "agents.FuzzyAgent", "agents.TAgent", "agents.anac.y2013.AgentKF.AgentKF", "agents.anac.y2013.MetaAgent.portfolio.BRAMAgent2.BRAMAgent2", "agents.anac.y2013.MetaAgent.portfolio.IAMhaggler2012.agents2011.SouthamptonAgent", "agents.anac.y2013.MetaAgent.portfolio.OMACagent.OMACagent", "agents.anac.y2013.MetaAgent.portfolio.AgentLG.AgentLG", "agents.anac.y2013.MetaAgent.portfolio.AgentMR.AgentMR", "agents.anac.y2013.MetaAgent.portfolio.CUHKAgent.CUHKAgent", "agents.anac.y2013.MetaAgent.portfolio.thenegotiatorreloaded.BOAagent", "agents.anac.y2013.MetaAgent.MetaAgent2013", "agents.anac.y2013.GAgent.AgentI", "agents.anac.y2013.SlavaAgent.SlavaAgent", "agents.anac.y2013.TMFAgent.TMFAgent", "agents.anac.y2014.DoNA.DoNA", "agents.anac.y2014.DoNA.ClearDefaultStrategy", "agents.anac.y2014.AgentQuest.AgentQuest", "agents.anac.y2014.BraveCat.necessaryClasses.BOAagent", "agents.anac.y2014.Gangster.Gangster", "agents.anac.y2014.Aster.Aster", "agents.anac.y2014.AgentTRP.AgentTRP", "agents.anac.y2014.E2Agent.AnacSampleAgent", "agents.anac.y2014.Sobut.Sobut", "agents.anac.y2014.AgentYK.AgentYK", "agents.anac.y2014.KGAgent.KGAgent", "agents.anac.y2014.SimpaticoAgent.Simpatico", "agents.anac.y2014.Atlas.Atlas", "agents.anac.y2014.AgentTD.AgentTD", "agents.anac.y2014.ArisawaYaki.ArisawaYaki", "agents.anac.y2014.Flinch.Flinch", "agents.anac.y2014.AgentWhale.WhaleAgent", "agents.anac.y2014.AgentM.AgentM", "agents.anac.y2012.BRAMAgent2.BRAMAgent2", "agents.anac.y2012.IAMhaggler2012.agents2011.SouthamptonAgent", "agents.anac.y2012.OMACagent.OMACagent", "agents.anac.y2012.AgentLG.AgentLG", "agents.anac.y2012.MetaAgent.agents.GYRL.GYRL", "agents.anac.y2012.MetaAgent.agents.ShAgent.ShAgent", "agents.anac.y2012.MetaAgent.agents.Chameleon.Chameleon", "agents.anac.y2012.MetaAgent.agents.SimpleAgentNew.SimpleAgentNew", "agents.anac.y2012.MetaAgent.agents.LYY.LYYAgent", "agents.anac.y2012.MetaAgent.agents.WinnerAgent.WinnerAgent2", "agents.anac.y2012.MetaAgent.agents.DNAgent.DNAgent", "agents.anac.y2012.MetaAgent.agents.MrFriendly.MrFriendly", "agents.anac.y2012.MetaAgent.MetaAgent", "agents.anac.y2012.AgentMR.AgentMR", "agents.anac.y2012.CUHKAgent.CUHKAgent", "agents.anac.y2017.geneking.GeneKing", "agents.anac.y2010.AgentFSEGA.AgentFSEGA", "agents.anac.y2010.Yushu.Yushu", "agents.anac.y2010.Nozomi.Nozomi", "agents.anac.y2010.AgentSmith.AgentSmith", "agents.anac.y2010.Southampton.SouthamptonAgentNoExtras", "agents.anac.y2010.Southampton.SouthamptonAgentExtrasInterface", "agents.anac.y2010.Southampton.SouthamptonAgent", "agents.anac.y2010.AgentK.Agent_K", "agents.anac.y2011.TheNegotiator.TheNegotiator", "agents.anac.y2011.ValueModelAgent.ValueModelAgent", "agents.anac.y2011.HardHeaded.KLH", "agents.anac.y2011.Gahboninho.Gahboninho", "agents.anac.y2011.AgentK2.Agent_K2", "agents.anac.y2011.BramAgent.BRAMAgent", "agents.anac.y2011.IAMhaggler2011.IAMhaggler2011", "agents.anac.y2011.Nice_Tit_for_Tat.BilateralAgent", "agents.BayesianAgent", "agents.ABMPAgent2", "agents.QOAgent", "agents.SimpleAgt2", ] all_party_based_agents = [ "agents.ai2014.group12.Group12", "agents.ai2014.group7.Group7", "agents.ai2014.group9.Group9", "agents.ai2014.group8.Group8", "agents.ai2014.group1.Group1", "agents.ai2014.group6.Group6", "agents.ai2014.group11.Group11", "agents.ai2014.group10.Group10", "agents.ai2014.group3.Group3", "agents.ai2014.group4.Group4", "agents.ai2014.group5.Group5", "agents.ai2014.group2.Group2", "agents.anac.y2015.Mercury.Mercury", "agents.anac.y2015.RandomDance.RandomDance", "agents.anac.y2015.cuhkagent2015.CUHKAgent2015", "agents.anac.y2015.SENGOKU.SENGOKU", "agents.anac.y2015.DrageKnight.DrageKnight", "agents.anac.y2015.meanBot.MeanBot", "agents.anac.y2015.Phoenix.PhoenixParty", "agents.anac.y2015.pokerface.PokerFace", "agents.anac.y2015.agenth.AgentH", "agents.anac.y2015.ParsAgent.ParsAgent", "agents.anac.y2015.AgentHP.AgentHP", "agents.anac.y2015.JonnyBlack.JonnyBlack", "agents.anac.y2015.xianfa.XianFaAgent", "agents.anac.y2015.AresParty.AresParty", "agents.anac.y2015.fairy.kawaii", "agents.anac.y2015.Atlas3.Atlas3", "agents.anac.y2015.TUDMixedStrategyAgent.TUDMixedStrategyAgent", "agents.anac.y2015.AgentW.AgentW", "agents.anac.y2015.AgentNeo.Groupn", "agents.anac.y2015.agentBuyogV2.AgentBuyogMain", "agents.anac.y2015.AgentX.AgentX", "agents.anac.y2015.pnegotiator.BayesLearner", "agents.anac.y2015.pnegotiator.PNegotiator", "agents.anac.y2015.group2.Group2", "agents.anac.y2017.agentkn.AgentKN", "agents.anac.y2017.tucagent.TucAgent", "agents.anac.y2017.mosateam.Mosa", "agents.anac.y2017.parscat2.ParsCat2", "agents.anac.y2017.geneking.GeneKing", "agents.anac.y2017.parsagent3.ShahAgent", "agents.anac.y2017.mamenchis.Mamenchis", "agents.anac.y2017.madagent.MadAgent", "agents.anac.y2017.agentf.AgentF", "agents.anac.y2017.farma.Farma17", "agents.anac.y2017.caduceusdc16.CaduceusDC16", "agents.anac.y2017.limitator.Imitator", "agents.anac.y2017.simpleagent.SimpleAgent", "agents.anac.y2017.rubick.Rubick", "agents.anac.y2017.ponpokoagent.PonPokoAgent", "agents.anac.y2017.group3.Group3", "agents.anac.y2017.gin.Gin", "agents.anac.y2017.tangxun.taxibox", "agents.anac.y2016.terra.Terra", "agents.anac.y2016.maxoops.MaxOops", "agents.anac.y2016.grandma.GrandmaAgent", "agents.anac.y2016.clockworkagent.ClockworkAgent", "agents.anac.y2016.parscat.ParsCat", "agents.anac.y2016.caduceus.Caduceus", "agents.anac.y2016.caduceus.agents.RandomDance.RandomDance", "agents.anac.y2016.caduceus.agents.kawaii.kawaii", "agents.anac.y2016.caduceus.agents.Caduceus.Caduceus", "agents.anac.y2016.caduceus.agents.ParsAgent.ParsAgent", "agents.anac.y2016.caduceus.agents.agentBuyong.agentBuyong", "agents.anac.y2016.caduceus.agents.Atlas3.Atlas3", "agents.anac.y2016.agentlight.AgentLight", "agents.anac.y2016.pars2.ParsAgent2", "agents.anac.y2016.yxagent.YXAgent", "agents.anac.y2016.farma.Farma", "agents.anac.y2016.syagent.SYAgent", "agents.anac.y2016.ngent.Ngent", "agents.anac.y2016.agenthp2.AgentHP2_main", "agents.anac.y2016.atlas3.Atlas32016", "agents.anac.y2016.agentsmith.AgentSmith2016", "agents.anac.y2016.myagent.MyAgent", ] agent_based_negotiators = [] party_based_negotiators = [ # 'agents.ai2014.group12.Group12', # 'agents.ai2014.group7.Group7', # 'agents.ai2014.group9.Group9', # 'agents.ai2014.group1.Group1', # 'agents.ai2014.group6.Group6', # 'agents.ai2014.group11.Group11', # 'agents.ai2014.group10.Group10', # 'agents.ai2014.group3.Group3', # 'agents.ai2014.group4.Group4', # 'agents.ai2014.group5.Group5', # 'agents.ai2014.group2.Group2', "agents.anac.y2015.Mercury.Mercury", "agents.anac.y2015.RandomDance.RandomDance", "agents.anac.y2015.cuhkagent2015.CUHKAgent2015", "agents.anac.y2015.SENGOKU.SENGOKU", "agents.anac.y2015.DrageKnight.DrageKnight", "agents.anac.y2015.meanBot.MeanBot", "agents.anac.y2015.Phoenix.PhoenixParty", "agents.anac.y2015.pokerface.PokerFace", "agents.anac.y2015.agenth.AgentH", "agents.anac.y2015.ParsAgent.ParsAgent", # 'agents.anac.y2015.JonnyBlack.JonnyBlack', "agents.anac.y2015.AresParty.AresParty", "agents.anac.y2015.fairy.kawaii", "agents.anac.y2015.Atlas3.Atlas3", "agents.anac.y2015.TUDMixedStrategyAgent.TUDMixedStrategyAgent", "agents.anac.y2015.AgentNeo.Groupn", "agents.anac.y2015.agentBuyogV2.AgentBuyogMain", "agents.anac.y2015.AgentX.AgentX", # 'agents.anac.y2015.pnegotiator.BayesLearner', # 'agents.anac.y2015.pnegotiator.PNegotiator', # 'agents.anac.y2015.group2.Group2', "agents.anac.y2017.tucagent.TucAgent", "agents.anac.y2017.agentf.AgentF", "agents.anac.y2017.ponpokoagent.PonPokoAgent", "agents.anac.y2017.tangxun.taxibox", "agents.anac.y2016.terra.Terra", "agents.anac.y2016.grandma.GrandmaAgent", "agents.anac.y2016.clockworkagent.ClockworkAgent", "agents.anac.y2016.parscat.ParsCat", "agents.anac.y2016.caduceus.Caduceus", "agents.anac.y2016.caduceus.agents.RandomDance.RandomDance", "agents.anac.y2016.caduceus.agents.kawaii.kawaii", "agents.anac.y2016.caduceus.agents.Caduceus.Caduceus", "agents.anac.y2016.caduceus.agents.ParsAgent.ParsAgent", "agents.anac.y2016.caduceus.agents.agentBuyong.agentBuyong", "agents.anac.y2016.caduceus.agents.Atlas3.Atlas3", "agents.anac.y2016.pars2.ParsAgent2", "agents.anac.y2016.yxagent.YXAgent", "agents.anac.y2016.farma.Farma", "agents.anac.y2016.syagent.SYAgent", "agents.anac.y2016.ngent.Ngent", "agents.anac.y2016.atlas3.Atlas32016", "agents.anac.y2016.agentsmith.AgentSmith2016", "agents.anac.y2016.myagent.MyAgent", ] def init_genius_bridge(path: str = None, port: int = 0, force: bool = False) -> bool: """Initializes a genius connection Args: path: The path to a JAR file that runs negloader port: port number to use force: Force trial even if an existing bridge is initialized Returns: True if successful """ global common_gateway global common_port global java_process global python_port port = port if port > 0 else DEFAULT_JAVA_PORT if genius_bridge_is_running(port): return True if not force and common_gateway is not None and common_port == port: print("Java already initialized") return True path = NEGMAS_CONFIG.get(CONFIG_KEY_GENIUS_BRIDGE_JAR, None) if path is None: print( "Cannot find the path to genius bridge jar. Download the jar somewhere in your machine and add its path" 'to ~/negmas/config.json under the key "genius_bridge_jar".\n\nFor example, if you downloaded the jar' " to /path/to/your/jar then edit ~/negmas/config.json to read something like\n\n" '{\n\t"genius_bridge_jar": "/path/to/your/jar",\n\t.... rest of the config\n}\n\n' "You can find the jar at http://www.yasserm.com/scml/genius-8.0.4-bridge.jar" ) return False path = pathlib.Path(path).expanduser().absolute() try: subprocess.Popen( # ['java', '-jar', path, '--die-on-exit', f'{port}'] f"java -jar {path} --die-on-exit {port}", shell=True ) except (OSError, TimeoutError, RuntimeError, ValueError): return False time.sleep(0.5) gateway = JavaGateway( gateway_parameters=GatewayParameters(port=port), callback_server_parameters=CallbackServerParameters(port=0), ) python_port = gateway.get_callback_server().get_listening_port() gateway.java_gateway_server.resetCallbackClient( gateway.java_gateway_server.getCallbackClient().getAddress(), python_port ) common_gateway = gateway common_port = port return True class GeniusNegotiator(SAONegotiator): """Encapsulates a Genius Negotiator""" def __init__( self, java_class_name: str, port: int = None, domain_file_name: str = None, utility_file_name: str = None, keep_issue_names: bool = True, keep_value_names: bool = True, auto_load_java: bool = False, can_propose=True, genius_bridge_path: str = None, name: str = None, ): super().__init__(name=name) self.capabilities["propose"] = can_propose self.add_capabilities({"genius": True}) self.java = None self.java_class_name = java_class_name self.port = port self.connected = self._connect( path=genius_bridge_path, port=self.port, auto_load_java=auto_load_java ) self.java_uuid = self._create() self.uuid = self.java_uuid self.name = self.java_uuid self.domain_file_name = str(domain_file_name) self.utility_file_name = str(utility_file_name) self._my_last_offer = None self.keep_issue_names = keep_issue_names self.utility_function, self.discount = None, None if domain_file_name is not None: # we keep original issues details so that we can create appropriate answers to Java self.issues = get_domain_issues( domain_file_name=domain_file_name, keep_issue_names=True, keep_value_names=True, ) self.issue_names = [_.name for _ in self.issues] self.issue_index = dict(zip(self.issue_names, range(len(self.issue_names)))) if utility_file_name is not None: self.utility_function, self.discount = UtilityFunction.from_genius( utility_file_name, keep_issue_names=keep_issue_names, keep_value_names=keep_value_names, ) self.base_utility = self.utility_function pass @classmethod def negotiators(cls, agent_based=False, party_based=True) -> List[str]: """ Returns a list of all available agents in genius 8.4.0 Args: agent_based: Old agents based on the Java class Negotiator party_based: Newer agents based on the Java class AbstractNegotiationParty Returns: """ r = [] if agent_based: r += agent_based_negotiators if party_based: r += party_based_negotiators return r @classmethod def random_negotiator( cls, agent_based=True, party_based=True, port: int = None, domain_file_name: str = None, utility_file_name: str = None, keep_issue_names: bool = True, keep_value_names: bool = True, auto_load_java: bool = False, can_propose=True, name: str = None, ) -> "GeniusNegotiator": """ Returns an agent with a random class name Args: agent_based: Old agents based on the Java class Negotiator party_based: Newer agents based on the Java class AbstractNegotiationParty Returns: GeniusNegotiator an agent with a random java class """ agent_names = cls.negotiators(agent_based=agent_based, party_based=party_based) agent_name = agent_names[random.randint(0, len(agent_names) - 1)] return GeniusNegotiator( java_class_name=agent_name, port=port, domain_file_name=domain_file_name, utility_file_name=utility_file_name, keep_issue_names=keep_issue_names, keep_value_names=keep_value_names, auto_load_java=auto_load_java, can_propose=can_propose, name=name, ) @property def is_connected(self): return self.connected and self.java is not None def _create(self): """ Creates the agent Returns: Examples: >>> if genius_bridge_is_running(): ... a = GeniusNegotiator(java_class_name="agents.anac.y2015.Atlas3.Atlas3") ... a.java_uuid.startswith("agents.anac.y2015.Atlas3.Atlas3") ... else: ... True True >>> if genius_bridge_is_running(): ... len(a.java_uuid)- len(a.java_class_name) == 36 # length of UUID ... else: ... True True """ return self.java.create_agent(self.java_class_name) def _connect(self, path: str, port: int, auto_load_java: bool = False) -> bool: """ Returns: Examples: - Testing multilateral agent >>> if genius_bridge_is_running(): ... a = GeniusNegotiator(java_class_name="agents.anac.y2015.Atlas3.Atlas3") ... print(a.java_name) ... else: ... print('ANAC2015-6-Atlas') ANAC2015-6-Atlas - Testing bilateral agent >>> if genius_bridge_is_running(): ... b = GeniusNegotiator(java_class_name="agents.SimpleAgent") ... print(b.java_name) ... else: ... print('Agent SimpleAgent') Agent SimpleAgent """ if port is None: if auto_load_java: if common_gateway is None: init_genius_bridge(path=path) gateway = common_gateway self.java = gateway.entry_point port = DEFAULT_JAVA_PORT return True else: port = DEFAULT_JAVA_PORT gateway = JavaGateway( gateway_parameters=GatewayParameters(port=port, auto_close=True) ) if gateway is None: self.java = None return False self.java = gateway.entry_point return True @property def java_name(self): return self.java.getName(self.java_uuid) def test(self) -> str: return self.java.test(self.java_class_name) def on_negotiation_start(self, state: MechanismState) -> None: """Called when the info starts. Connects to the JVM. """ super().on_negotiation_start(state=state) info = self._ami if self.discount is not None and self.discount != 1.0: self.utility_function = make_discounted_ufun( self.utility_function, info=info, discount_per_round=self.discount, power_per_round=1.0, ) n_steps = -1 if info.n_steps is None else int(info.n_steps) # number of steps n_seconds = ( -1 if info.time_limit is None else int(info.time_limit) ) # time limit if n_steps * n_seconds > 0: # n_seconds take precedence n_steps = -1 self.java.on_negotiation_start( self.java_uuid, # java_uuid info.n_negotiators, # number of agents n_steps, n_seconds, n_seconds > 0, self.domain_file_name, # domain file self.utility_file_name, # Negotiator file ) def propose(self, state: MechanismState) -> "Outcome": if not self.capabilities["propose"]: return None if self._my_last_offer is None: # never responded before response, outcome = self.parse(self.java.choose_action(self.java_uuid)) if outcome is None: return None self._my_last_offer = outcome return outcome # we offered something before tmp = self._my_last_offer self._my_last_offer = None return tmp def respond(self, state: MechanismState, offer: "Outcome") -> "ResponseType": action = self.java.choose_action(self.java_uuid) response, self._my_last_offer = self.parse(action) return response def parse(self, action: str) -> Tuple[Optional[ResponseType], Optional["Outcome"]]: """ Parses an action into and a ResponseType and an Outcome (if one is included) Args: action: Returns: """ response, outcome = None, None id, typ_, bid_str = action.split(FIELD_SEP) if typ_ in ("Offer",) and (bid_str is not None and len(bid_str) > 0): try: if self.keep_issue_names: outcome = { _[0]: _[1] for _ in [ _.split(INTERNAL_SEP) for _ in bid_str.split(ENTRY_SEP) ] } else: outcome = tuple( _.split(INTERNAL_SEP)[1] for _ in bid_str.split(ENTRY_SEP) ) except: print(f"Failed for bid string: {bid_str} of action {action}") if typ_ == "Offer": response = ResponseType.REJECT_OFFER elif typ_ == "Accept": response = ResponseType.ACCEPT_OFFER elif typ_ == "EndNegotiation": response = ResponseType.END_NEGOTIATION else: raise ValueError(f"Unknown response: {typ_} in action {action}") return response, outcome def _outcome2str(self, outcome): output = "" if not isinstance(outcome, dict): outcome_dict = dict(zip(self.issue_names, outcome)) else: outcome_dict = outcome for i, v in outcome_dict.items(): output += f"{i}{INTERNAL_SEP}{v}{ENTRY_SEP}" output = output[: -len(ENTRY_SEP)] return output def __str__(self): name = super().__str__().split("/") return "/".join(name[:-1]) + f"/{self.java_class_name}/" + name[-1] def on_partner_proposal( self, state: MechanismState, agent_id: str, offer: "Outcome" ): if agent_id is self.id: return agent_info = [ _ for _ in self._ami.participants if _.id != self.id and _.id == agent_id ] if len(agent_info) == 0: return agent_info = agent_info[0] # if agent_info.type == 'genius_negotiator': # return self.java.receive_message( self.java_uuid, agent_id, "Offer", self._outcome2str(offer) ) def on_partner_response( self, state: MechanismState, agent_id: str, outcome: "Outcome", response: "ResponseType", ): if agent_id is self.id: return agent_info = [ _ for _ in self._ami.participants if _.id != self.id and _.id == agent_id ] if len(agent_info) == 0: return if outcome is None: return agent_info = agent_info[0] # if agent_info.type == 'genius_negotiator': # return bid = self._outcome2str(outcome) if response == ResponseType.END_NEGOTIATION: resp = "EndNegotiation" elif response == ResponseType.ACCEPT_OFFER: resp = "Accept" elif response == ResponseType.REJECT_OFFER: resp = "Reject" else: return self.java.receive_message(self.java_uuid, agent_id, resp, bid) def genius_bridge_is_running(port: int = None) -> bool: """ Checks whether a Genius Bridge is running. A genius bridge allows you to use `GeniusNegotiator` objects. Remarks: You can start a Genius Bridge in at least two ways: - execute the python function `init_genius_bridge()` in this module - run "negmas genius" on the terminal """ if port is None: port = DEFAULT_JAVA_PORT s = socket.socket() try: s.connect(("127.0.0.1", port)) return True except ConnectionRefusedError: return False except IndexError: return False except Py4JNetworkError: return False finally: s.close() PK!YQnegmas/helpers.py#!/usr/bin/env python """A set of utilities that can be used by agents developed for the platform. This set of utlities can be extended but must be backward compatible for at least two versions """ import datetime import importlib import json import logging import math import pathlib import string import sys from typing import ( List, Optional, Iterable, Union, Callable, Mapping, Any, Sequence, Tuple, Dict, Type, ) from typing import TYPE_CHECKING from negmas import NEGMAS_CONFIG if TYPE_CHECKING: pass import colorlog import numpy as np import os import random import re import scipy.stats as stats import inflect import stringcase from enum import Enum import yaml from negmas.generics import * import copy __all__ = [ "create_loggers", # 'MultiIssueUtilityFunctionMapping', "ReturnCause", "Distribution", # A probability distribution "snake_case", "camel_case", "unique_name", "is_nonzero_file", "pretty_string", "ConfigReader", "get_class", "import_by_name", "get_full_type_name", "instantiate", "humanize_time", "gmap", "ikeys", "Floats", "DEFAULT_DUMP_EXTENSION", "dump", ] # conveniently named classes """Maps from a single issue to a Negotiator function.""" # MultiIssueUtilityFunctionMapping = Union[ # Callable[['Issues'], 'UtilityFunction'], Mapping['Issues', 'UtilityFunction']] # type: ignore # """Maps between multiple issues and a Negotiator function.""" ParamList = List[Union[int, str]] GenericMappings = List[GenericMapping] IterableMappings = List[IterableMapping] # MultiIssueUtilityFunctionMappings = List[MultiIssueUtilityFunctionMapping] ParamLists = Iterable[ParamList] Floats = List[float] COMMON_LOG_FILE_NAME = "./logs/{}_{}.txt".format( "log", datetime.datetime.now().strftime("%Y%m%d-%H%M%S") ) MODULE_LOG_FILE_NAME: Dict[str, str] = dict() LOGS_BASE_DIR = "./logs" DEFAULT_DUMP_EXTENSION = NEGMAS_CONFIG.get("default_dump_extension", "json") class ReturnCause(Enum): TIMEOUT = 0 SUCCESS = 1 FAILURE = 2 def create_loggers( file_name: Optional[str] = None, module_name: Optional[str] = None, screen_level: Optional[int] = logging.WARNING, file_level: Optional[int] = logging.DEBUG, format_str: str = "%(asctime)s - %(levelname)s - %(message)s", colored: bool = True, app_wide_log_file: bool = True, module_wide_log_file: bool = False, ) -> logging.Logger: """ Create a set of loggers to report feedback. The logger created can log to both a file and the screen at the same time with adjustable level for each of them. The default is to log everything to the file and to log WARNING at least to the screen Args: module_wide_log_file: app_wide_log_file: file_name: The file to export_to the logs to. If None only the screen is used for logging. If empty, a time-stamp is used module_name: The module name to use. If not given the file name without .py is used screen_level: level of the screen logger file_level: level of the file logger format_str: the format of logged items colored: whether or not to try using colored logs Returns: logging.Logger: The logger """ if module_name is None: module_name = __file__.split("/")[-1][:-3] # create logger if it does not already exist logger = logging.getLogger(module_name) if len(logger.handlers) > 0: return logger logger.setLevel(logging.DEBUG) # create formatter if colored and "colorlog" in sys.modules and os.isatty(2): date_format = "%Y-%m-%d %H:%M:%S" cformat = "%(log_color)s" + format_str formatter = colorlog.ColoredFormatter( cformat, date_format, log_colors={ "DEBUG": "reset", "INFO": "green", "WARNING": "yellow", "ERROR": "red", "CRITICAL": "bold_red", }, ) else: formatter = logging.Formatter(format_str) if screen_level is not None: # create console handler and set level to logdebug screen_logger = logging.StreamHandler() screen_logger.setLevel(screen_level) # add formatter to ch screen_logger.setFormatter(formatter) # add ch to logger logger.addHandler(screen_logger) if file_name is not None and file_level is not None: file_name = str(file_name) if len(file_name) == 0: if app_wide_log_file: file_name = COMMON_LOG_FILE_NAME elif module_wide_log_file and module_name in MODULE_LOG_FILE_NAME.keys(): file_name = MODULE_LOG_FILE_NAME[module_name] else: file_name = "{}/{}_{}.txt".format( LOGS_BASE_DIR, module_name, datetime.datetime.now().strftime("%Y%m%d-%H%M%S"), ) MODULE_LOG_FILE_NAME[module_name] = file_name os.makedirs(f"{LOGS_BASE_DIR}", exist_ok=True) os.makedirs(os.path.dirname(file_name), exist_ok=True) # type: ignore file_logger = logging.FileHandler(file_name) file_logger.setLevel(file_level) file_logger.setFormatter(formatter) logger.addHandler(file_logger) return logger def snake_case(s: str) -> str: """ Converts a string from CamelCase to snake_case Example: >>> print(snake_case('ThisIsATest')) this_is_a_test Args: s: input string Returns: str: converted string """ return ( re.sub("(((?<=[a-z])[A-Z])|([A-Z](?![A-Z]|$)))", "_\\1", s).lower().strip("_") ) def camel_case( s: str, capitalize_first: bool = False, lower_first: bool = False ) -> str: """ Converts a string from snake_case to CamelCase Example: >>> print(camel_case('this_is_a_test')) thisIsATest >>> print(camel_case('this_is_a_test', capitalize_first=True)) ThisIsATest >>> print(camel_case('This_is_a_test', lower_first=True)) thisIsATest >>> print(camel_case('This_is_a_test')) ThisIsATest Args: s: input string capitalize_first: if true, the first character will be capitalized lower_first: If true, the first character will be lowered Returns: str: converted string """ if len(s) < 1: return s parts = s.split("_") if capitalize_first: parts = [_.capitalize() for _ in parts] elif lower_first: parts = [parts[0].lower()] + [_.capitalize() for _ in parts[1:]] else: parts = [parts[0]] + [_.capitalize() for _ in parts[1:]] return "".join(parts) def unique_name(base: str, add_time=True, rand_digits=8) -> str: """Return a unique name. Can be used to return a unique directory name on the givn base. Args: base: str (str): base path/string add_time (bool, optional): Defaults to True. Add current time rand_digits (int, optional): Defaults to 8. The number of random characters to add to the name Examples: >>> a = unique_name('') >>> len(a) == 8 + 1 + 6 + 8 True Returns: str: The unique name. """ if rand_digits > 0: characters = string.ascii_letters + string.digits password = "".join(random.choice(characters) for _ in range(rand_digits)) else: password = "" if add_time: _time = datetime.datetime.now().strftime("%Y%m%d-%H%M%S") else: _time = "" sub = _time + password return os.path.join(base, sub) if len(sub) > 0 else base def is_nonzero_file(fpath: str) -> bool: """Whether or not the path is for an existing nonzero file. Args: fpath: path to the file to test. It accepts both str and pathlib.Path """ return os.path.isfile(fpath) and os.path.getsize(fpath) > 0 def pretty_string(src: Any, tab_size=2, compact=False) -> str: """Recursively print nested elements. Args: src (Any): The source to be converted to a printable string tab_size (int): Tab size in spaces compact (bool): If true the output is converted into a single line Returns: str: The pretty version of the input Remarks: - This function assumes that the patterns `` "`` and ``":`` do not appear anywhere in the input. If they appear, the space, : will be removed. """ s = _pretty_string(src, dpth=0, current_key="", tab_size=tab_size) if compact: return s.replace("\n", "") else: return s.replace(' "', " ").replace('":', ":") def _pretty_string(src, dpth=0, current_key="", tab_size=2) -> str: """Recursively print nested elements. Args: dpth (int): Current depth current_key (str): Current key being printed tab_size: Tab size in spaces Returns: str: The pretty version of the input """ def tabs(n): return " " * n * tab_size # or 2 or 8 or... output = "" if isinstance(src, dict): output += tabs(dpth) + "{\n" for key, value in src.items(): output += _pretty_string(value, dpth + 1, key) + "\n" output += tabs(dpth) + "}" elif isinstance(src, list) or isinstance(src, tuple): output += tabs(dpth) + "[\n" for litem in src: output += _pretty_string(litem, dpth + 1) + "\n" output += tabs(dpth) + "]" else: if len(current_key) > 0: output += tabs(dpth) + '"%s":%s' % (current_key, src) else: output += tabs(dpth) + "%s" % src return output class LazyInitializable(object): """Base Negotiator for all agents Supports a set_params function that can be used for lazy initialization """ def __init__(self) -> None: super().__init__() def set_params(self, **kwargs) -> None: """Sets the attributes of the object. This function can be used to set the attributes of any object to the same values used in its construction which allows for lazy initialization. Args: **kwargs: The parameters usually passed to the constructor as a dict Example: >>> class A(LazyInitializable): ... def __init__(self, a=None, b=None) -> None: ... super().__init__() ... self.a = a ... self.b = b Now you can do the following:: >>> a = A() >>> a.set_params(a=3, b=2) which will be equivalent to: >>> b = A(a=3, b=2) Remarks: - See ``adjust_params()`` for an example in which the constuctor needs to do more processing than just assinging its inputs to instance members. """ for k, v in kwargs.items(): setattr(self, k, v) self.adjust_params() def adjust_params(self) -> None: """Adjust the internal attributes following ``set_attributes()`` or construction using ``__init__()``. This function needs to be implemented only if the constructor needs to do some processing on the inputs other than assigning it to instance attributes. In such case, move these adjustments to this function and call it in the constructor. Examples: >>> class A(object): ... def __init__(self, a=None, b=None): ... self.a = a ... self.b = b if b is not None else [] should now be defined as follows: >>> class A(LazyInitializable): ... def __init__(self, a, b): ... super().__init__() ... self.a = a ... self.b = b ... self.adjust_params() ... ... def adjust_params(self): ... if self.b is None: self.b = [] Remarks: - Remember to call `super().__init__()` first in your constructor and to call your `adjust_params()` by the end of the constructor. - The constructor should ONLY copy the parameters it receives to internal variables and then calls `adjust_params()` if any more processing is needed. This makes it possible to use `set_params()` with this object. - You should **never** call `adjust_params()` directly anywhere. """ pass class Distribution(object): """Any distribution from scipy.stats with overloading of addition and multiplication. Args: dtype (str): Data type of the distribution as a string. It must be one defined in `scipy.stats` loc (float): The location of the distribution (corresponds to mean in Gaussian) scale (float): The _scale of the distribution (corresponds to standard deviation in Gaussian) multipliers: An iterable of other distributon to *multiply* with this one adders: An iterable of other utility_priors to *add* to this one **kwargs: Examples: >>> d2 = Distribution('uniform') >>> print(d2.mean()) 0.5 >>> try: ... d = Distribution('something crazy') ... except ValueError as e: ... print(str(e)) Unknown distribution something crazy """ def __init__(self, dtype: str, **kwargs) -> None: super().__init__() dist = getattr(stats, dtype.lower(), None) if dist is None: raise ValueError(f"Unknown distribution {dtype}") if "loc" not in kwargs.keys(): kwargs["loc"] = 0.0 if "scale" not in kwargs.keys(): kwargs["scale"] = 1.0 self.dist = dist(**kwargs) self.dtype = dtype self.__cached = None @classmethod def around( cls, value: float = 0.5, range: Tuple[float, float] = (0.0, 1.0), uncertainty: float = 0.5, ) -> "Distribution": """ Generates a uniform distribution around the input value in the given range with given uncertainty Args: value: The value to generate the distribution around range: The range of possible values uncertainty: The uncertainty level required. 0.0 means no uncertainty and 1.0 means full uncertainty Returns: Distribution A uniform distribution around `value` with uncertainty (scale) `uncertainty` """ if uncertainty >= 1.0: return cls(dtype="uniform", loc=range[0], scale=range[1]) if uncertainty <= 0.0: return cls(dtype="uniform", loc=value, scale=0.0) scale = uncertainty * (range[1] - range[0]) loc = max(range[0], (random.random() - 1.0) * scale + value) if loc + scale > range[1]: loc -= loc + scale - range[1] return cls(dtype="uniform", loc=loc, scale=scale) def mean(self) -> float: if self.dtype != "uniform": raise NotImplementedError( "Only uniform distributions are supported for now" ) if self.scale < 1e-6: return self.loc mymean = self.dist.mean() return float(mymean) def __float__(self): return float(self.mean()) def __and__(self, other): if isinstance(other, float) or isinstance(other, int): return float(other) if self.dtype == "uniform": beg = max(self.loc, other.loc) end = min(self.scale + self.loc, other.loc + other.scale) return Distribution(self.dtype, loc=beg, scale=end - beg) raise NotImplementedError() def __or__(self, other): if isinstance(other, float) or isinstance(other, int): return float(other) if self.dtype == "uniform": raise NotImplementedError( "Current implementation assumes an overlap otherwise a mixture must be returned" ) beg = min(self.loc, other.loc) end = max(self.scale + self.loc, other.loc + other.scale) return Distribution(self.dtype, loc=beg, scale=end - beg) raise NotImplementedError() def prob(self, val: float) -> float: """Returns the probability for the given value """ return self.dist.prob(val) def sample(self, size: int = 1) -> np.ndarray: return self.dist.rvs(size=size) @property def loc(self): return self.dist.kwds.get("loc", 0.0) @property def scale(self): return self.dist.kwds.get("scale", 0.0) def __str__(self): if self.dtype == "uniform": return f"U({self.loc}, {self.loc+self.scale})" return f"{self.dtype}(loc:{self.loc}, scale:{self.scale})" def __copy__(self): cls = self.__class__ result = cls.__new__(cls) result.__dict__.update(self.__dict__) return result def __deepcopy__(self, memo): cls = self.__class__ result = cls.__new__(cls) memo[id(self)] = result for k, v in self.__dict__.items(): setattr(result, k, copy.deepcopy(v, memo)) return result __repr__ = __str__ def __sub__(self, other): return float(self) - other def __add__(self, other): return float(self) + other def __radd__(self, other): return float(self) + other def __mul__(self, other): return float(self) * float(other) def __rmul__(self, other): return float(other) * float(self) def __divmod__(self, other): return float(self).__divmod__(other) _inflect_engine = inflect.engine() class ConfigReader: @classmethod def _parse_children_config(cls, children, scope): """Parses children in the given scope""" remaining_children = {} myconfig = {} setters = [] for key, v in children.items(): k, class_name = cls._split_key(key) if isinstance(v, Dict): if class_name is None: class_name = stringcase.pascalcase(k) the_class = get_class(class_name=class_name, scope=scope) obj, obj_children = the_class.from_config( config=v, ignore_children=False, try_parsing_children=True, scope=scope, ) if obj_children is not None and len(obj_children) > 0: remaining_children[k] = obj_children setter_name = "set_" + k if hasattr(cls, setter_name): setters.append((setter_name, obj)) else: myconfig[k] = obj elif isinstance(v, Iterable) and not isinstance(v, str): singular = _inflect_engine.singular_noun(k) if singular is False: singular = k if class_name is None: class_name = stringcase.pascalcase(singular) setter_name = "set_" + k objs = [] for current in list(v): the_class = get_class(class_name=class_name, scope=scope) obj = the_class.from_config( config=current, ignore_children=True, try_parsing_children=True, scope=scope, ) objs.append(obj) if hasattr(cls, setter_name): setters.append((setter_name, objs)) else: myconfig[k] = objs else: # not a dictionary and not an iterable. remaining_children[k] = v return myconfig, remaining_children, setters @classmethod def _split_key(cls, key: str) -> Tuple[str, Optional[str]]: """Splits the key into a key name and a class name Remarks: - Note that if the given key has multiple colons the first two will be parsed as key name: class name and the rest will be ignored. This can be used to add comments """ keys = key.split(":") if len(keys) == 1: return keys[0], None else: return keys[0], keys[1] @classmethod def read_config( cls, config: Union[str, dict], section: str = None ) -> Dict[str, Any]: """ Reads the configuration from a file or a dict and prepares it for parsing Args: config: Either a file name or a dictionary section: A section in the file or a key in the dictionary to use for loading params Returns: A dict ready to be parsed by from_config Remarks: """ if isinstance(config, str): # If config is a string, assume it is a file and read it from the appropriate location def exists(nm): return os.path.exists(nm) and not os.path.isdir(nm) if not exists(config): name = pathlib.Path("./") / pathlib.Path(config) if exists(name): config = str(name.absolute()) else: name = (pathlib.Path("./.negmas") / config).absolute() if exists(name): config = str(name) else: name = ( pathlib.Path(os.path.expanduser("~/.negmas")) / config ).absolute() if exists(name): config = str(name) else: raise ValueError(f"Cannot find config in {config}.") with open(config, "r") as f: if config.endswith(".json"): config = json.load(f) elif config.endswith(".cfg"): config = eval(f.read()) elif config.endswith(".yaml") or config.endswith(".yml"): config = yaml.safe_load(f) else: raise ValueError(f"Cannot parse {config}") if section is not None: config = config[section] # type: ignore return config # type: ignore @classmethod def from_config( cls, config: Union[str, dict], section: str = None, ignore_children: bool = True, try_parsing_children: bool = True, scope=None, ): """ Creates an object of this class given the configuration info Args: config: Either a file name or a dictionary section: A section in the file or a key in the dictionary to use for loading params ignore_children: If true then children will be ignored and there will be a single return try_parsing_children: If true the children will first be parsed as `ConfigReader` classes if they are not simple types (e.g. int, str, float, Iterable[int|str|float] scope: The scope at which to evaluate any child classes. This MUST be passed as scope=globals() if you are having any children that are to be parsed. Returns: An object of cls if ignore_children is True or a tuple with an object of cls and a dictionary with children that were not parsed. Remarks: - This function will return an object of its class after passing the key-value pairs found in the config to the init function. - Requiring passing scope=globals() to this function is to get around the fact that in python eval() will be called with a globals dictionary based on the module in which the function is defined not called. This means that in general when eval() is called to create the children, it will not have access to the class definitions of these children (except if they happen to be imported in this file). To avoid this problem causing an undefined_name exception, the caller must pass her globals() as the scope. """ config = cls.read_config(config=config, section=section) if config is None: if ignore_children: return None else: return None, {} # now we have a dict called config which has our configuration myconfig = {} # parts of the config that can directly be parsed children = {} # parts of the config that need further parsing setters = ( [] ) # the setters are those configs that have a set_ function for them. def _is_simple(x): """Tests whether the input can directly be parsed""" return ( x is None or isinstance(x, int) or isinstance(x, str) or isinstance(x, float) or ( isinstance(x, Iterable) and not isinstance(x, dict) and all(_is_simple(_) for _ in list(x)) ) ) def _set_simple_config(key, v) -> Optional[Dict[str, Any]]: """Sets a simple value v for key taken into accout its class and the class we are constructing""" key_name, class_name = cls._split_key(key) _setter = "set_" + key_name params = {} if hasattr(cls, _setter): setters.append((_setter, v)) return None params[key_name] = ( v if class_name is None else get_class(class_name=class_name, scope=scope)(v) ) return params # read the configs key by key and try to parse anything that is simple enough to parse for k, v in config.items(): # type: ignore if isinstance(v, Dict): children[k] = v elif isinstance(v, Iterable) and not isinstance(v, str): lst = list(v) if all(_is_simple(_) for _ in lst): # that is a simple value of the form k:class_name = v. We construct class_name (if it exists) with v # notice that we need to remove class_name when setting the key in myconfig val = _set_simple_config(k, v) if val is not None: myconfig.update(val) else: children[k] = v # type: ignore else: # that is a simple value of the form k:class_name = v. We construct class_name (if it exists) with v val = _set_simple_config(k, v) if val is not None: myconfig.update(val) # now myconfig has all simply parsed parts and children has all non-parsed parts if len(children) > 0 and try_parsing_children: if scope is None: ValueError( f"scope is None but that is not allowed. You must pass scope=globals() or scope=locals() to " f"from_config. If your classes are defined in the global scope pass globals() and if they " f"are defined in local scope then pass locals(). You can only pass scope=None if you are " f"sure that all of the constructor parameters of the class you are creating are simple " f"values like ints floats and strings." ) parsed_conf, remaining_children, setters = cls._parse_children_config( children=children, scope=scope ) myconfig.update(parsed_conf) children = remaining_children main_object = cls(**myconfig) # type: ignore if try_parsing_children: # we will only have setters if we have children for setter, value in setters: getattr(main_object, setter)(value) if ignore_children: return main_object return main_object, children class Proxy: """A general proxy class.""" def __init__(self, obj): self._obj = obj def __getattr__(self, item): return getattr(self._obj, item) def get_full_type_name(t: Union[Type[Any], Callable]) -> str: """Gets the ful typename of a type. You *should not* pass an instance to this function but it may just work.""" if not hasattr(t, "__module__") and not hasattr(t, "__name__"): t = type(t) return t.__module__ + "." + t.__name__ def import_by_name(full_name: str) -> Any: """Imports something form a module using its full name""" if not isinstance(full_name, str): return full_name modules: List[str] = [] parts = full_name.split(".") modules = parts[:-1] module_name = ".".join(modules) item_name = parts[:-1] if len(modules) < 1: raise ValueError( f"Cannot get the object {item_name} in module {module_name} (modules {modules})" ) module = importlib.import_module(module_name) return getattr(module, item_name) def get_class( class_name: Union[str, Type], module_name: str = None, scope: dict = None ) -> Type: """Imports and creates a class object for the given class name""" if not isinstance(class_name, str): return class_name modules: List[str] = [] if module_name is not None: modules = module_name.split(".") modules += class_name.split(".") if len(modules) < 1: raise ValueError( f"Cannot get the class {class_name} in module {module_name} (modules {modules})" ) class_name = stringcase.pascalcase(modules[-1]) if len(modules) < 2: return eval(class_name, scope) module_name = ".".join(modules[:-1]) module = importlib.import_module(module_name) return getattr(module, class_name) def instantiate( class_name: Union[str, Type], module_name: str = None, scope: dict = None, **kwargs ) -> Any: """Imports and instantiates an object of a class""" return get_class(class_name, module_name)(**kwargs) def humanize_time(secs, align=False, always_show_all_units=False): """ Prints time that is given as seconds in human readable form. Useful only for times >=1sec. :param secs: float: number of seconds :param align: bool, optional: whether to align outputs so that they all take the same size (not implemented) :param always_show_all_units: bool, optional: Whether to always show days, hours, and minutes even when they are zeros. default False :return: str: formated string with the humanized form """ units = [("d", 86400), ("h", 3600), ("m", 60), ("s", 1)] parts = [] for unit, mul in units: if secs / mul >= 1 or mul == 1 or always_show_all_units: if mul > 1: n = int(math.floor(secs / mul)) secs -= n * mul else: n = secs if secs != int(secs) else int(secs) if align: parts.append("%2d%s%s" % (n, unit, "")) else: parts.append("%2d%s%s" % (n, unit, "")) return ":".join(parts) def dump(d: Any, file_name: Union[str, os.PathLike]) -> None: """ Saved an object depending on the extension of the file given. If the filename given has no extension, `DEFAULT_DUMP_EXTENSION` will be used Args: d: Object to save file_name: file name Remarks: - Supported formats are json, yaml - If None is given, the file will be created but will be empty """ file_name = pathlib.Path(file_name).expanduser().absolute() if file_name.suffix == "": file_name = pathlib.Path(str(file_name) + "." + DEFAULT_DUMP_EXTENSION) if d is None: with open(file_name, "w") as f: pass if file_name.suffix == ".json": with open(file_name, "w") as f: json.dump(d, f, sort_keys=True, indent=2) elif file_name.suffix == ".yaml": with open(file_name, "w") as f: yaml.safe_dump(d, f) else: raise ValueError(f"Unkown extension {file_name.suffix} for {file_name}") PK!rHrHnegmas/inout.py"""Defines import/export functionality """ import functools import operator import os import shutil from typing import List, Optional, Tuple, Union, Dict, Callable, Iterable import numpy as np import pkg_resources from negmas.generics import ivalues __all__ = [ "load_genius_domain", "load_genius_domain_from_folder", "convert_genius_domain_from_folder", "convert_genius_domain", "find_domain_and_utility_files", "get_domain_issues", ] import xml.etree.ElementTree as ET from os import listdir from negmas import Issue, enumerate_outcomes, make_discounted_ufun from negmas import Negotiator from negmas import UtilityFunction from negmas import SAOMechanism, AspirationNegotiator 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 load_genius_domain( domain_file_name: str, utility_file_names: Optional[List[str]] = None, agent_factories: Optional[ Union[Callable[[], Negotiator], List[Callable[[], Negotiator]]] ] = None, force_single_issue=False, cache_and_discretize_outcomes=False, max_n_outcomes: int = 1e6, n_discretization: Optional[int] = None, keep_issue_names=True, keep_value_names=True, normalize_utilities=True, n_steps=None, time_limit=3 * 60, # GENIUS uses 3min time limit by default max_n_agents=None, dynamic_entry=True, safe_parsing=False, ignore_reserved=False, ignore_discount=False, ) -> Tuple[Optional[SAOMechanism], List[dict], Union[Dict[str, Issue], List[Issue]]]: """ Loads a genius domain, creates appropriate negotiators if necessary Args: domain_file_name: utility_file_names: agent_factories: force_single_issue: cache_and_discretize_outcomes: max_n_outcomes: n_discretization: keep_issue_names: keep_value_names: normalize_utilities: n_steps: time_limit: max_n_agents: dynamic_entry: safe_parsing: ignore_reserved: ignore_discount: Returns: - mechanism (SAOMechanism): A mechanism for the given issues - agent_info (List[Dict]): All Negotiator functions from the given file - issues Union[Issue, Dict[str, Issue], List[Issue]]] : The 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 None, [], [] 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, ) agent_info = [] if utility_file_names is None: utility_file_names = [] utility_file_names = [str(_) for _ in utility_file_names] for ufname in utility_file_names: utility, discount_factor = UtilityFunction.from_genius( file_name=ufname, force_single_issue=force_single_issue, keep_issue_names=keep_issue_names, keep_value_names=keep_value_names, normalize_utility=normalize_utilities, domain_issues=issues_details, safe_parsing=safe_parsing, max_n_outcomes=max_n_outcomes, ignore_discount=ignore_discount, ignore_reserved=ignore_reserved, ) agent_info.append( { "ufun": utility, "reserved_value_func": utility.reserved_value if utility is not None else 0.0, "discount_factor": discount_factor, } ) outcomes = None try: if force_single_issue or cache_and_discretize_outcomes or len(issues) == 1: n_outcomes: float = functools.reduce( operator.mul, ( float(_.cardinality()) if not _.is_continuous() else float(n_discretization) if n_discretization is not None else np.inf for _ in ivalues(issues) ), 1.0, ) if n_outcomes < max_n_outcomes: outcomes = enumerate_outcomes(issues, keep_issue_names=keep_issue_names) except ValueError: pass if domain_file_name is not None: mechanism_name = ( domain_file_name.split("/")[-1][:-4] .replace("-domain", "") .replace("_domain", "") .replace("domain", "") ) mechanism = SAOMechanism( issues=issues, outcomes=outcomes, n_steps=n_steps, time_limit=time_limit, max_n_agents=max_n_agents, dynamic_entry=dynamic_entry, name=mechanism_name, keep_issue_names=keep_issue_names, ) if agent_info is not None and len(agent_info) > 0: for info in agent_info: info["ufun"] = ( info["ufun"] if info["discount_factor"] is None or info["discount_factor"] == 1.0 else make_discounted_ufun( ufun=info["ufun"], ami=mechanism.ami, discount_per_round=info["discount_factor"], power_per_round=1.0, ) ) if agent_factories is not None and agent_info is not None and len(agent_info) > 0: if not isinstance(agent_factories, Iterable): agent_factories = [agent_factories] * len(agent_info) agents = [factory() for factory in agent_factories[0 : len(agent_info)]] for a, info in zip(agents, agent_info): mechanism.add(a, ufun=info["ufun"]) return mechanism, agent_info, (issues if not force_single_issue else [issues]) def load_genius_domain_from_folder( folder_name: str, agent_factories: Optional[ Union[Callable[[], Negotiator], List[Callable[[], Negotiator]]] ] = None, force_single_issue=False, cache_and_discretize_outcomes=False, max_n_outcomes: int = 1e6, n_discretization: Optional[int] = None, keep_issue_names=True, keep_value_names=True, normalize_utilities=True, n_steps=None, time_limit=60, # GENIUS uses 3min time limit by default max_n_agents=None, dynamic_entry=True, safe_parsing=False, ignore_reserved=False, ignore_discount=False, ) -> Tuple[Optional[SAOMechanism], List[dict], Union[Dict[str, Issue], List[Issue]]]: """ Loads a genius domain from a folder. See ``load_genius_domain`` for more details. Args: folder_name: agent_factories: force_single_issue: cache_and_discretize_outcomes: max_n_outcomes: n_discretization: keep_issue_names: keep_value_names: normalize_utilities: n_steps: time_limit: max_n_agents: dynamic_entry: safe_parsing: ignore_reserved: ignore_discount: Returns: - mechanism (SAOMechanism): A mechanism for the given issues - agent_info (List[Dict]): All Negotiator functions from the given file - issues Union[Issue, Dict[str, Issue], List[Issue]]] : The issues Examples: >>> folder_name = pkg_resources.resource_filename('negmas', resource_name='tests/data/10issues') >>> mechanism, negotiators, issues = load_genius_domain_from_folder(folder_name ... , force_single_issue=False, keep_issue_names=False ... , keep_value_names=False, normalize_utilities=False) >>> print(len(issues)) 10 >>> print(len(negotiators)) 2 >>> print([type(a['ufun']) for a in negotiators]) [, ] >>> print(negotiators[0]['ufun'].outcome_ranges[0]) {1: (7.0, 9.0), 3: (2.0, 7.0), 5: (0.0, 8.0), 8: (0.0, 7.0)} >>> print(negotiators[0]['ufun'].mappings[0]) 97.0 >>> u = negotiators[0]['ufun'] >>> print(u(tuple([0.0] * len(issues)))) 0.0 >>> print(u(tuple([0.5] * len(issues)))) 186.0 Try loading and running a domain with predetermined agents: >>> mechanism, agents, issues = load_genius_domain_from_folder( ... pkg_resources.resource_filename('negmas', resource_name='tests/data/Laptop') ... , agent_factories=AspirationNegotiator ... , force_single_issue=True, keep_issue_names=False ... , keep_value_names=False) >>> state = mechanism.run() >>> state.agreement is not None True >>> mechanism, negotiators, issues = load_genius_domain_from_folder( ... pkg_resources.resource_filename('negmas', resource_name='tests/data/Laptop')) >>> len(issues), len(negotiators) (3, 2) >>> [type(a['ufun']) for a in negotiators] [, ] >>> mechanism, negotiators, issues = load_genius_domain_from_folder( ... pkg_resources.resource_filename('negmas', resource_name='tests/data/Laptop') ... , force_single_issue=True, keep_issue_names=False ... , keep_value_names=False) >>> len(issues), len(negotiators) (1, 2) >>> [type(a['ufun']) for a in negotiators] [, ] """ folder_name = str(folder_name) files = sorted(listdir(folder_name)) domain_file_name = None utility_file_names = [] for f in files: if not f.endswith(".xml") or f.endswith("pareto.xml"): continue full_name = folder_name + "/" + f root = ET.parse(full_name).getroot() if root.tag == "negotiation_template": domain_file_name = full_name elif root.tag == "utility_space": utility_file_names.append(full_name) return load_genius_domain( domain_file_name=domain_file_name, utility_file_names=utility_file_names, agent_factories=agent_factories, force_single_issue=force_single_issue, cache_and_discretize_outcomes=cache_and_discretize_outcomes, max_n_outcomes=max_n_outcomes, n_discretization=n_discretization, keep_issue_names=keep_issue_names, keep_value_names=keep_value_names, normalize_utilities=normalize_utilities, n_steps=n_steps, time_limit=time_limit, max_n_agents=max_n_agents, dynamic_entry=dynamic_entry, safe_parsing=safe_parsing, ignore_reserved=ignore_reserved, ignore_discount=ignore_discount, ) def find_domain_and_utility_files(folder_name) -> Tuple[str, List[str]]: """Finds the domain and utility_function files in a folder """ files = sorted(listdir(folder_name)) domain_file_name = None utility_file_names = [] for f in files: if not f.endswith(".xml") or f.endswith("pareto.xml"): continue full_name = folder_name + "/" + f root = ET.parse(full_name).getroot() if root.tag == "negotiation_template": domain_file_name = full_name elif root.tag == "utility_space": utility_file_names.append(full_name) return domain_file_name, utility_file_names def convert_genius_domain( src_domain_file_name: str, dst_domain_file_name: str, src_utility_file_names: Optional[List[str]] = None, dst_utility_file_names: Optional[List[str]] = None, force_single_issue=False, cache_and_discretize_outcomes=False, max_n_outcomes: int = 1e6, n_discretization: Optional[int] = None, keep_issue_names=True, keep_value_names=True, normalize_utilities=True, safe_parsing=False, ) -> bool: if ( not force_single_issue and not cache_and_discretize_outcomes and keep_issue_names and keep_value_names and not normalize_utilities ): # no need to do anything, just copy shutil.copy(src=src_domain_file_name, dst=dst_domain_file_name) for src, dst in zip(src_utility_file_names, dst_utility_file_names): shutil.copy(src=src, dst=dst) return True issues, issues_details, mechanism = None, None, None if src_domain_file_name is not None: issues_details, _ = Issue.from_genius( src_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( src_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, ) else: issues = issues_details if issues is None: return False Issue.to_genius( issues=issues, file_name=dst_domain_file_name, enumerate_integer=True ) if src_utility_file_names is None: src_utility_file_names = [] for ufname, dstfname in zip(src_utility_file_names, dst_utility_file_names): utility, discount_factor = UtilityFunction.from_genius( file_name=ufname, force_single_issue=force_single_issue, keep_issue_names=keep_issue_names, keep_value_names=keep_value_names, normalize_utility=normalize_utilities, domain_issues=issues_details, safe_parsing=safe_parsing, max_n_outcomes=max_n_outcomes, ) if utility is None: return False UtilityFunction.to_genius( u=utility, discount_factor=discount_factor, issues=issues, file_name=dstfname, ) return True def convert_genius_domain_from_folder( src_folder_name: str, dst_folder_name: str, **kwargs ) -> bool: """Loads a genius domain from a folder. See ``load_genius_domain`` for more details. """ os.makedirs(dst_folder_name, exist_ok=True) files = sorted(listdir(src_folder_name)) domain_file_name = None utility_file_names = [] for f in files: if not f.endswith(".xml") or f.endswith("pareto.xml"): continue full_name = src_folder_name + "/" + f root = ET.parse(full_name).getroot() if root.tag == "negotiation_template": domain_file_name = full_name elif root.tag == "utility_space": utility_file_names.append(full_name) success = convert_genius_domain( src_domain_file_name=domain_file_name, dst_domain_file_name=os.path.join( dst_folder_name, os.path.basename(domain_file_name) ), src_utility_file_names=utility_file_names, dst_utility_file_names=[ os.path.join(dst_folder_name, os.path.basename(_)) for _ in utility_file_names ], **kwargs ) if not success: if len(os.listdir(dst_folder_name)) == 0: shutil.rmtree(dst_folder_name, ignore_errors=True) return success PK!h=>^>^negmas/java.py""" Implements Java interoperability allowing parts of negmas to work smoothly with their Java counterparts in jnegmas """ import os import socket import subprocess import time from contextlib import contextmanager from typing import Optional, Dict, Any, Iterable, Union import numpy as np import pkg_resources from py4j.clientserver import ClientServer, JavaParameters, PythonParameters from py4j.java_collections import ( ListConverter, JavaMap, MapConverter, JavaList, JavaSet, ) from py4j.java_gateway import ( JavaGateway, GatewayParameters, CallbackServerParameters, JavaObject, ) # @todo use launch_gateway to start the java side. Will need to know the the jar location so jnegmas shoud save that # somewhere from py4j.protocol import Py4JNetworkError from .helpers import get_class, instantiate, camel_case, snake_case __all__ = [ "JavaCallerMixin", "JNegmasGateway", "to_java", "from_java", "jnegmas_bridge_is_running", "init_jnegmas_bridge", "jnegmas_connection", "from_java", "java_link", "to_dict", "PYTHON_CLASS_IDENTIFIER", ] DEFAULT_JNEGMAS_PATH = "external/jnegmas-1.0-SNAPSHOT-all.jar" PYTHON_CLASS_IDENTIFIER = "__python_class__" @contextmanager def jnegmas_connection( init: bool = False, path: Optional[str] = None, java_port=0, python_port=0, client_server=True, shutdown=True, ): """A connection to jnegmas that closes automatically""" if init: JNegmasGateway.start_java_side(path=path, java_port=java_port) JNegmasGateway.connect( java_port=java_port, python_port=python_port, client_server=client_server ) yield JNegmasGateway.gateway if shutdown: JNegmasGateway.shutdown() def init_jnegmas_bridge(path: Optional[str] = None, port: int = 0): JNegmasGateway.start_java_side(path=path, java_port=port) def jnegmas_bridge_is_running(port: int = None) -> bool: """ Checks whether a JNegMAS Bridge is running. This bridge is needed to use any objects in the jnegmas package Remarks: You can start a JNegMAS Bridge in at least two ways: - execute the python function `init_jnegmas_bridge()` in this module - run "negmas jnegmas" on the terminal """ return JNegmasGateway.is_running(port) class PyEntryPoint: """Used as an entry point from the java side allowing it to create objects in python and take initiative in calling python""" def create(self, class_name: str, params: Dict[str, Any]) -> Any: """ Creates a python object and returns it. Args: class_name: python full class name params: params to pass by value to the constructor of the object Remarks: - Notice that the returned object will only be usable in Java if it is implementing a Java interface which means that it *must* have an internal Java class with an `implements` list of interfaces that it implements. """ return from_java(params, fallback_class_name=class_name) def create_shadow(self, class_name: str, params: Dict[str, Any]) -> Any: lst = class_name.split(".") for ending in ("Negotiator", "FactoryManager", "UtilityFunction"): if lst[-1].endswith(ending): lst[-1] = "_Shadow" + ( ending if ending != "Negotiator" else "SAONegotiator" ) break else: lst[-1] = "_Shadow" + lst[-1] shadow_class_name = ".".join(lst) cls = get_class(shadow_class_name) obj = from_java(params, fallback_class_name=class_name) shadow = cls(obj) return shadow class Java: implements = ["jnegmas.EntryPoint"] class JNegmasGateway: DEFAULT_PYTHON_PORT = 25334 DEFAULT_JAVA_PORT = 25333 gateway: Optional[Union[JavaGateway, ClientServer]] = None @classmethod def start_java_side(cls, path: str = None, java_port: int = 0) -> None: """Initializes a connection to jnegmas Examples: # >>> start_java_side(port=35337) # >>> a = JNegmasGateway.do_nothing_manager() # >>> a.java_uuid.startswith('jnegmas') # True # >>> len(a.java_uuid)- len(a.java_class_name) == 36 # length of UUID # True """ if cls.gateway is not None: return if path is None: path = pkg_resources.resource_filename( "negmas", resource_name=DEFAULT_JNEGMAS_PATH ) java_port = java_port if java_port > 0 else cls.DEFAULT_JAVA_PORT if jnegmas_bridge_is_running(port=java_port): return path = os.path.abspath(os.path.expanduser(path)) try: subprocess.Popen( # ['java', '-jar', path, '--die-on-exit', f'{port}'] f"java -jar {path} --doe --client-server --port {java_port}", shell=True ) except FileNotFoundError: print(os.getcwd(), flush=True) raise FileNotFoundError([os.getcwd(), path]) except: pass time.sleep(0.5) cls.connect(auto_load_java=False) @classmethod def connect( cls, java_port: int = None, python_port: int = None, auto_load_java: bool = False, client_server: bool = True, ) -> bool: """ connects to jnegmas """ if not java_port: java_port = cls.DEFAULT_JAVA_PORT if not python_port: python_port = cls.DEFAULT_PYTHON_PORT if auto_load_java: if cls.gateway is None: cls.start_java_side(java_port=java_port) return True if cls.gateway is None: eager_load, auto_convert = True, True auto_field, auto_gc = True, False propagate_exceptions = False if client_server: cls.gateway = ClientServer( java_parameters=JavaParameters( port=java_port, auto_convert=auto_convert, eager_load=eager_load, auto_close=True, auto_gc=False, auto_field=auto_field, daemonize_memory_management=True, ), python_parameters=PythonParameters( port=python_port, propagate_java_exceptions=propagate_exceptions, daemonize=True, eager_load=eager_load, auto_gc=auto_gc, daemonize_connections=True, ), python_server_entry_point=PyEntryPoint(), ) else: pyparams = CallbackServerParameters( port=python_port, daemonize_connections=True, daemonize=True, eager_load=eager_load, propagate_java_exceptions=propagate_exceptions, ) cls.gateway = JavaGateway( gateway_parameters=GatewayParameters( port=java_port, auto_convert=auto_convert, auto_field=auto_field, eager_load=eager_load, auto_close=True, ), callback_server_parameters=pyparams, auto_convert=auto_convert, start_callback_server=True, eager_load=eager_load, python_server_entry_point=PyEntryPoint(), ) python_port = cls.gateway.get_callback_server().get_listening_port() cls.gateway.java_gateway_server.resetCallbackClient( cls.gateway.java_gateway_server.getCallbackClient().getAddress(), python_port, ) return True @classmethod def shutdown(cls): cls.gateway.shutdown(raise_exception=False) cls.gateway.shutdown_callback_server(raise_exception=False) @classmethod def is_running(cls, port): """ Checks whether a JNegMAS Bridge is running. This bridge is needed to use any objects in the jnegmas package Remarks: You can start a JNegMAS Bridge in at least two ways: - execute the python function `init_jnegmas_bridge()` in this module - run "negmas jnegmas" on the terminal """ if port is None: port = JNegmasGateway.DEFAULT_JAVA_PORT s = socket.socket() try: s.connect(("127.0.0.1", port)) return True except ConnectionRefusedError: return False except IndexError: return False except Py4JNetworkError: return False except Exception: return False finally: s.close() def java_identifier(s: str): if s != PYTHON_CLASS_IDENTIFIER: return camel_case(s) return s def to_dict(value, deep=True, add_type_field=True, camel=True): """Encodes the given value as nothing not more complex than simple dict of either dicts, lists or builtin numeric or string values Args: value: Any object deep: Whether we should go deep in the encoding or do a shallow encoding add_type_field: Whether to add a type field. If True, A field named `PYTHON_CLASS_IDENTIFIER` will be added giving the type of `value` camel: Convert to camel_case if True Remarks: - All iterables are converted to lists when `deep` is true. - If the `value` object has a `to_java` member, it will be called to do the conversion, otherwise its `__dict__` or `__slots__` member will be used. See Also: `from_java`, `PYTHON_CLASS_IDENTIFIER` """ def _j(s: str) -> str: if camel: return java_identifier(s) return str(s) def good_field(k: str): return ( not k.startswith("python_") and not k.startswith("java") and not (k != PYTHON_CLASS_IDENTIFIER and k.startswith("_")) ) if isinstance(value, JavaObject): return value if isinstance(value, dict): if not deep: return {_j(k): v for k, v in value.items()} return { _j(k): to_dict(v, add_type_field=add_type_field, camel=camel) for k, v in value.items() if good_field(k) } if isinstance(value, Iterable) and not deep: return value if isinstance(value, Iterable) and not isinstance(value, str): return [to_dict(_, add_type_field=add_type_field, camel=camel) for _ in value] if hasattr(value, "to_java"): converted = value.to_java() if isinstance(converted, dict): if add_type_field and (PYTHON_CLASS_IDENTIFIER not in converted.keys()): converted[PYTHON_CLASS_IDENTIFIER] = ( value.__class__.__module__ + "." + value.__class__.__name__ ) return {_j(k): v for k, v in converted.items()} else: return converted if hasattr(value, "__dict__"): if deep: d = { _j(k): to_dict(v, add_type_field=add_type_field, camel=camel) for k, v in value.__dict__.items() if good_field(k) } else: d = {_j(k): v for k, v in value.__dict__.items() if good_field(k)} if add_type_field: d[PYTHON_CLASS_IDENTIFIER] = ( value.__class__.__module__ + "." + value.__class__.__name__ ) # ugly ugly ugly ugly if "_NamedObject__uuid" in value.__dict__: d["id"] = value.__dict__["_NamedObject__uuid"] if "_NamedObject__name" in value.__dict__: d["name"] = value.__dict__["_NamedObject__name"] return d if hasattr(value, "__slots__"): if deep: d = dict( zip( (_j(k) for k in value.__slots__), ( to_dict( getattr(value, _), add_type_field=add_type_field, camel=camel, ) for _ in value.__slots__ ), ) ) else: d = dict( zip( (_j(k) for k in value.__slots__), (getattr(value, _) for _ in value.__slots__), ) ) if add_type_field: d[PYTHON_CLASS_IDENTIFIER] = ( value.__class__.__module__ + "." + value.__class__.__name__ ) return d # a builtin if isinstance(value, np.int64): return int(value) return value def java_link(obj, map=None): """ Creates a link in java to the object given without copying it. Args: obj: The object for which to create a java shadow map: construction parameters copyable: If true, we will assume that the java object is PyCopyable otherwise PyConstructable. Only checked if map is not None Returns: A java object. Cannot be used directly in python but can be used as an argument to a call to of a java object. """ class_name = obj.__class__.__module__ + "." + obj.__class__.__name__ lst = class_name.split(".") lst[0] = "j" + lst[0] if lst[-1].startswith("_Shadow"): lst[-1] = lst[-1][len("_Shadow") :] if lst[-1].startswith("Shadow"): lst[-1] = lst[-1][len("Shadow") :] lst[-1] = "Python" + lst[-1] class_name = ".".join(lst) java_obj = JNegmasGateway.gateway.entry_point.create(class_name, obj) if map is not None: java_obj.fromMap(map) else: java_obj.fromMap(to_dict(obj)) return java_obj def to_java(value, add_type_field=True, python_class_name: str = None): """Encodes the given value as nothing not more complex than simple dict of either dicts, lists or builtin numeric or string values Args: value: Any object add_type_field: If true, the `PYTHON_CLASS_IDENTIFIER` will be added with the python class field on it python_class_name: It given it overrides the class name written when `add_type_field` is True otherwise, the class name will be inferred as the __class__ of `value`. Remarks: - All iterables are converted to lists when `deep` is true. - If the `value` object has a `to_java` member, it will be called to do the conversion, otherwise its `__dict__` or `__slots__` member will be used. See Also: `from_java`, `PYTHON_CLASS_IDENTIFIER` """ if value is None: return None value = to_dict(value, deep=True, add_type_field=add_type_field) if isinstance(value, JavaObject): return value if isinstance(value, np.int64): return int(value) if isinstance(value, dict): for k, v in value.items(): if isinstance(v, np.int64): value[k] = int(v) if add_type_field and python_class_name is not None: value[PYTHON_CLASS_IDENTIFIER] = python_class_name return JNegmasGateway.gateway.entry_point.createJavaObjectFromMap(value) if isinstance(value, Iterable) and not isinstance(value, str): return ListConverter().convert( [ JNegmasGateway.gateway.entry_point.createJavaObjectFromMap(_) if isinstance(_, dict) else _ for _ in value ], JNegmasGateway.gateway._gateway_client, ) return value def python_identifier(k: str) -> str: """ Converts a key to snake case keeping dunder keys alone Args: k: string to be converted Returns: snake-case string """ return k if k.startswith("__") else snake_case(k) def from_java( d: Any, deep=True, remove_type_field=True, fallback_class_name: Optional[str] = None ): """Decodes a dict coming from java recovering all objects in the way Args: d: The value to be decoded. If it is not a dict, it is returned as it is. deep: If true, decode recursively remove_type_field: If true the field called `PYTHON_CLASS_IDENTIFIER` will be removed if found. fallback_class_name: If given, it is used as the fall-back type if ``PYTHON_CLASS_IDENTIFIER` is not in the dict. Remarks: - If the object is not a dict or if it has no `PYTHON_CLASS_IDENTIFIER` field and no `fallback_class_name` is given, the input `d` is returned as it is. It will not even be copied. See Also: `to_java`, `PYTHON_CLASS_IDENTIFIER` """ def good_field(k: str): return ( not k.startswith("python_") and not k.startswith("java") and not (k != PYTHON_CLASS_IDENTIFIER and k.startswith("_")) ) if d is None or isinstance(d, int) or isinstance(d, float) or isinstance(d, str): return d if isinstance(d, JavaList): return [_ for _ in d] if isinstance(d, JavaSet): return {_ for _ in d} if isinstance(d, JavaMap): if deep: d = {python_identifier(k): from_java(v) for k, v in d.items()} else: d = {python_identifier(k): v for k, v in d.items()} deep = False elif isinstance(d, JavaObject): d = JNegmasGateway.gateway.entry_point.toMap(d) if deep: d = {python_identifier(k): from_java(v) for k, v in d.items()} else: d = {python_identifier(k): v for k, v in d.items()} deep = False if isinstance(d, dict): if remove_type_field: python_class_name = d.pop(PYTHON_CLASS_IDENTIFIER, fallback_class_name) else: python_class_name = d.get(PYTHON_CLASS_IDENTIFIER, fallback_class_name) if python_class_name is not None: python_class_name = py_class_name(python_class_name) if python_class_name.endswith("Issue"): python_class = get_class("negmas.outcomes.Issue") else: python_class = get_class(python_class_name) # we resolve sub-objects first from the dict if deep is specified before calling from_java on the class if deep: d = { python_identifier(k): from_java(v) for k, v in d.items() if good_field(k) } # from_java needs to do a shallow conversion from a dict as deep conversion is taken care of already. if hasattr(python_class, "from_java"): return python_class.from_java( {python_identifier(k): v for k, v in d.items()}, python_class_name ) if deep: d = { python_identifier(k): from_java(v) for k, v in d.items() if good_field(k) } else: d = {python_identifier(k): v for k, v in d.items() if good_field(k)} return python_class(**d) return d raise (ValueError(str(d))) def py_class_name(python_class_name: str) -> str: """ Converts a class name that we got from Java to the corresponding class name in python Args: python_class_name: The class name we got from JNEgMAS Returns: The class name in negmas. """ lst = python_class_name.split(".") if lst[-1].startswith("Python"): lst[-1] = lst[-1][len("Python") :] python_class_name = ".".join(lst) return python_class_name class JavaCallerMixin: """A mixin to enable calling a java counterpart. This mixin can ONLY be used with a `NamedObject` because it uses its id property. Other than inheriting this mixin, you should call its `init_java_bridge` in your `__init__` (or whenever your object is initialized and you need to create the Java counterpart). You should then implement all your functions as calls to `java_object`. If for example you have a function `do_this`, you can just define it as follows: .. code def do_this(self, x, y, z) -> Type: return self.java_object.doThis(x, y, z) Notice that you cannot use named arguments when calling the function in `java_object` and that the names are converted to camelCase instead of snake_case. Moreover, property x will be implemented as a pair getX, setX on the Java side. If your class needs just to call the corresponding java object but is never called back from it then you are done after inheriting from this mixin. If your objects need to be called from the java counterpart, then you need to add the following to your class definition .. code class Java: implements = ['jnegmas.ClassName'] This assumes that your class is named `ClassName` and that there is an interface called `ClassName` defined in jnegmas that has the *same* public interface as your class (or whatever part of it to be called from Java). """ @classmethod def from_dict(cls, java_object, *args, **kwargs): """Creates a Python object representing the corresponding Java object""" obj = cls(*args, **kwargs) obj._java_object = java_object obj._connected = True obj._java_class_name = java_object.getClass().getSimpleName() return obj def init_java_bridge( self, java_object, java_class_name: str, auto_load_java: bool = False, python_shadow_object: Any = None, ): """ initializes a connection to the java bridge creating a member called `java_object` that can be used to access the counterpart object in Java Args: java_object: A java object that already exists of the correct type. If given no new objects will be created java_class_name: The type of the Java object to be created auto_load_java: When true, a JVM will be automatically created (if one is not available) python_shadow_object: A python object to shadow the java object. The object will just call the corresponding method on this shadow object whenever it needs. Remarks: - sets a member called java_object that can be used to access the corresponding Java object crated - if `python_shadow_object` is given, it must be an object of a type that has an internal class called Java which has a single member called 'implements' which is a list of one string element representing the Java interface being implemented (it must be either jnegmas.PyCallable or an extension of it). """ self._java_class_name = ( java_class_name if java_class_name is not None else java_object.getClass().getName() ) self._connected = JNegmasGateway.connect(auto_load_java=auto_load_java) self._java_object = ( java_object if java_object is not None else self._create(python_shadow_object) ) def _create(self, python_shadow: Any = None): """ Creates the internal object. Args: python_shadow: An object that has an internal Java class with implements = ['jnegmas.Callable'] """ if python_shadow is None: return JNegmasGateway.gateway.entry_point.create(self._java_class_name) return JNegmasGateway.gateway.entry_point.create( self._java_class_name, python_shadow ) PK!L  #negmas/logs/log_20190227-113253.txt2019-02-27 11:32:56,040 - INFO - 0/5 [20.00%]: SCMLWorld/20190227-113256EwL56: World Created 2019-02-27 11:32:56,040 - INFO - 0/5 [20.00%]: m_0 joined 2019-02-27 11:32:56,040 - INFO - 0/5 [20.00%]: m_1 joined 2019-02-27 11:32:56,040 - INFO - 0/5 [20.00%]: m_2 joined 2019-02-27 11:32:56,040 - INFO - 0/5 [20.00%]: m_3 joined 2019-02-27 11:32:56,040 - INFO - 0/5 [20.00%]: m_4 joined 2019-02-27 11:32:56,041 - INFO - 0/5 [20.00%]: c_0 joined 2019-02-27 11:32:56,041 - INFO - 0/5 [20.00%]: c_1 joined 2019-02-27 11:32:56,041 - INFO - 0/5 [20.00%]: c_2 joined 2019-02-27 11:32:56,042 - INFO - 0/5 [20.00%]: c_3 joined 2019-02-27 11:32:56,042 - INFO - 0/5 [20.00%]: c_4 joined 2019-02-27 11:32:56,042 - INFO - 0/5 [20.00%]: nGisiWgNZq6ITZM5 joined 2019-02-27 11:32:56,042 - INFO - 0/5 [20.00%]: jtgUe52RvEJgwBuN joined 2019-02-27 11:32:56,043 - INFO - 0/5 [20.00%]: 0 Negotiations/4 _entities 2019-02-27 11:32:56,044 - INFO - 0/5 [20.00%]: m_0 requested negmas.sao.SAOMechanism[None] with ['c_3', 'm_0'] (ID a5a0a546-96b7-4cce-a661-7a189fd75260) 2019-02-27 11:32:56,045 - INFO - 0/5 [20.00%]: m_0-ae38c93f-04bf-477a-809e-3d3de4b02340 request was accepted 2019-02-27 11:32:56,045 - INFO - 0/5 [20.00%]: m_1 requested negmas.sao.SAOMechanism[None] with ['c_3', 'm_1'] (ID 6f3956b9-7332-4398-8125-6dd5559fc8ad) 2019-02-27 11:32:56,046 - INFO - 0/5 [20.00%]: m_1-99b3c06e-66f7-4413-b0f8-af0919e75071 request was accepted 2019-02-27 11:32:56,047 - INFO - 0/5 [20.00%]: m_2 requested negmas.sao.SAOMechanism[None] with ['c_3', 'm_2'] (ID 67f940b1-8633-420b-a863-0d279842b1c7) 2019-02-27 11:32:56,048 - INFO - 0/5 [20.00%]: m_2-d279992c-cf29-4b38-b046-100294ca6f0c request was accepted 2019-02-27 11:32:56,049 - INFO - 0/5 [20.00%]: m_3 requested negmas.sao.SAOMechanism[None] with ['c_3', 'm_3'] (ID cc8032cf-a914-409f-b7ef-796454be4697) 2019-02-27 11:32:56,050 - INFO - 0/5 [20.00%]: m_3-e6312be7-fa79-44d2-9ae4-f684919060e5 request was accepted 2019-02-27 11:32:56,051 - INFO - 0/5 [20.00%]: m_4 requested negmas.sao.SAOMechanism[None] with ['c_3', 'm_4'] (ID 27e05a6d-ae92-4f43-bb56-3dcb48b53717) 2019-02-27 11:32:56,052 - INFO - 0/5 [20.00%]: m_4-cf4ba00c-de5e-4e64-9f2d-a8bf1c05fb02 request was accepted 2019-02-27 11:32:56,054 - INFO - 0/5 [20.00%]: m_0 requested negmas.sao.SAOMechanism[None] with ['c_3', 'm_0'] (ID 9d770709-361c-4af5-88f7-1ddef8fc1432) 2019-02-27 11:32:56,058 - INFO - 0/5 [20.00%]: m_0-ae38c93f-04bf-477a-809e-3d3de4b02340 request was accepted 2019-02-27 11:32:56,062 - INFO - 0/5 [20.00%]: m_1 requested negmas.sao.SAOMechanism[None] with ['c_3', 'm_1'] (ID 7bba8f3b-f2c7-4a81-8ed5-64868b40aeb1) 2019-02-27 11:32:56,063 - INFO - 0/5 [20.00%]: m_1-99b3c06e-66f7-4413-b0f8-af0919e75071 request was accepted 2019-02-27 11:32:56,064 - INFO - 0/5 [20.00%]: m_2 requested negmas.sao.SAOMechanism[None] with ['c_3', 'm_2'] (ID 617b5ce1-5277-45d3-9011-02817bab7381) 2019-02-27 11:32:56,064 - INFO - 0/5 [20.00%]: m_2-d279992c-cf29-4b38-b046-100294ca6f0c request was accepted 2019-02-27 11:32:56,066 - INFO - 0/5 [20.00%]: m_3 requested negmas.sao.SAOMechanism[None] with ['c_3', 'm_3'] (ID 4d31b384-a837-437f-9e1c-a1acb3f2bd95) 2019-02-27 11:32:56,066 - INFO - 0/5 [20.00%]: m_3-e6312be7-fa79-44d2-9ae4-f684919060e5 request was accepted 2019-02-27 11:32:56,067 - INFO - 0/5 [20.00%]: m_4 requested negmas.sao.SAOMechanism[None] with ['c_3', 'm_4'] (ID d69142b3-e14a-40fc-898e-e5550e945fbd) 2019-02-27 11:32:56,068 - INFO - 0/5 [20.00%]: m_4-cf4ba00c-de5e-4e64-9f2d-a8bf1c05fb02 request was accepted 2019-02-27 11:32:56,070 - INFO - 0/5 [20.00%]: m_0 requested negmas.sao.SAOMechanism[None] with ['c_4', 'm_0'] (ID c8c68c76-ff1b-49c4-a1e4-2f1efafa357c) 2019-02-27 11:32:56,070 - INFO - 0/5 [20.00%]: m_0-ae38c93f-04bf-477a-809e-3d3de4b02340 request was accepted 2019-02-27 11:32:56,071 - INFO - 0/5 [20.00%]: m_1 requested negmas.sao.SAOMechanism[None] with ['c_4', 'm_1'] (ID 54c1ef65-6e80-4050-938f-228ff383488f) 2019-02-27 11:32:56,072 - INFO - 0/5 [20.00%]: m_1-99b3c06e-66f7-4413-b0f8-af0919e75071 request was accepted 2019-02-27 11:32:56,073 - INFO - 0/5 [20.00%]: m_2 requested negmas.sao.SAOMechanism[None] with ['c_4', 'm_2'] (ID 8eb60e29-5ade-4325-82e7-20d7508291bc) 2019-02-27 11:32:56,074 - INFO - 0/5 [20.00%]: m_2-d279992c-cf29-4b38-b046-100294ca6f0c request was accepted 2019-02-27 11:32:56,075 - INFO - 0/5 [20.00%]: m_3 requested negmas.sao.SAOMechanism[None] with ['c_4', 'm_3'] (ID dec3250b-181c-47a3-8624-84dc0d3145c5) 2019-02-27 11:32:56,075 - INFO - 0/5 [20.00%]: m_3-e6312be7-fa79-44d2-9ae4-f684919060e5 request was accepted 2019-02-27 11:32:56,076 - INFO - 0/5 [20.00%]: m_4 requested negmas.sao.SAOMechanism[None] with ['c_4', 'm_4'] (ID 3c268240-5e0b-4b2f-a3c9-c781513d7141) 2019-02-27 11:32:56,077 - INFO - 0/5 [20.00%]: m_4-cf4ba00c-de5e-4e64-9f2d-a8bf1c05fb02 request was accepted 2019-02-27 11:32:56,078 - INFO - 0/5 [20.00%]: m_0 requested negmas.sao.SAOMechanism[None] with ['c_4', 'm_0'] (ID b9fc36dd-28cd-4c18-9f3f-7660462ddbc1) 2019-02-27 11:32:56,079 - INFO - 0/5 [20.00%]: m_0-ae38c93f-04bf-477a-809e-3d3de4b02340 request was accepted 2019-02-27 11:32:56,080 - INFO - 0/5 [20.00%]: m_1 requested negmas.sao.SAOMechanism[None] with ['c_4', 'm_1'] (ID a7f86548-a56c-469c-b252-44de2733d62c) 2019-02-27 11:32:56,081 - INFO - 0/5 [20.00%]: m_1-99b3c06e-66f7-4413-b0f8-af0919e75071 request was accepted 2019-02-27 11:32:56,082 - INFO - 0/5 [20.00%]: m_2 requested negmas.sao.SAOMechanism[None] with ['c_4', 'm_2'] (ID 38f5829c-ed00-447d-b942-8677d96d09a8) 2019-02-27 11:32:56,082 - INFO - 0/5 [20.00%]: m_2-d279992c-cf29-4b38-b046-100294ca6f0c request was accepted 2019-02-27 11:32:56,083 - INFO - 0/5 [20.00%]: m_3 requested negmas.sao.SAOMechanism[None] with ['c_4', 'm_3'] (ID 0daf00b1-1587-400b-9cc0-d7d746e095f0) 2019-02-27 11:32:56,084 - INFO - 0/5 [20.00%]: m_3-e6312be7-fa79-44d2-9ae4-f684919060e5 request was accepted 2019-02-27 11:32:56,085 - INFO - 0/5 [20.00%]: m_4 requested negmas.sao.SAOMechanism[None] with ['c_4', 'm_4'] (ID d68ec153-8945-47c5-a410-b928a037d726) 2019-02-27 11:32:56,086 - INFO - 0/5 [20.00%]: m_4-cf4ba00c-de5e-4e64-9f2d-a8bf1c05fb02 request was accepted 2019-02-27 11:32:56,088 - INFO - 0/5 [20.00%]: m_0 requested negmas.sao.SAOMechanism[None] with ['c_0', 'm_0'] (ID f934f5de-3393-49bb-90df-50d8af10f2c4) 2019-02-27 11:32:56,089 - INFO - 0/5 [20.00%]: m_0-ae38c93f-04bf-477a-809e-3d3de4b02340 request was accepted 2019-02-27 11:32:56,090 - INFO - 0/5 [20.00%]: m_1 requested negmas.sao.SAOMechanism[None] with ['c_0', 'm_1'] (ID 6152c0f8-4f30-4479-9da2-00f275969626) 2019-02-27 11:32:56,092 - INFO - 0/5 [20.00%]: m_1-99b3c06e-66f7-4413-b0f8-af0919e75071 request was accepted 2019-02-27 11:32:56,096 - INFO - 0/5 [20.00%]: m_2 requested negmas.sao.SAOMechanism[None] with ['c_0', 'm_2'] (ID c343545f-8116-4896-859a-dbf41617541e) 2019-02-27 11:32:56,097 - INFO - 0/5 [20.00%]: m_2-d279992c-cf29-4b38-b046-100294ca6f0c request was accepted 2019-02-27 11:32:56,101 - INFO - 0/5 [20.00%]: m_3 requested negmas.sao.SAOMechanism[None] with ['c_0', 'm_3'] (ID ef971054-83cf-4d5d-bd05-ff609f1f7ff7) 2019-02-27 11:32:56,103 - INFO - 0/5 [20.00%]: m_3-e6312be7-fa79-44d2-9ae4-f684919060e5 request was accepted 2019-02-27 11:32:56,105 - INFO - 0/5 [20.00%]: m_4 requested negmas.sao.SAOMechanism[None] with ['c_0', 'm_4'] (ID 7d875733-5282-4b99-9831-3286f17c045a) 2019-02-27 11:32:56,106 - INFO - 0/5 [20.00%]: m_4-cf4ba00c-de5e-4e64-9f2d-a8bf1c05fb02 request was accepted 2019-02-27 11:32:56,107 - INFO - 0/5 [20.00%]: m_0 requested negmas.sao.SAOMechanism[None] with ['c_0', 'm_0'] (ID 632fcd0e-9ff2-4024-954f-356767ce9668) 2019-02-27 11:32:56,108 - INFO - 0/5 [20.00%]: m_0-ae38c93f-04bf-477a-809e-3d3de4b02340 request was accepted 2019-02-27 11:32:56,109 - INFO - 0/5 [20.00%]: m_1 requested negmas.sao.SAOMechanism[None] with ['c_0', 'm_1'] (ID 49c70727-2114-4f79-a198-3259b79cc7ee) 2019-02-27 11:32:56,110 - INFO - 0/5 [20.00%]: m_1-99b3c06e-66f7-4413-b0f8-af0919e75071 request was accepted 2019-02-27 11:32:56,112 - INFO - 0/5 [20.00%]: m_2 requested negmas.sao.SAOMechanism[None] with ['c_0', 'm_2'] (ID d0bbd779-a5ed-470e-b459-d555ef66b814) 2019-02-27 11:32:56,114 - INFO - 0/5 [20.00%]: m_2-d279992c-cf29-4b38-b046-100294ca6f0c request was accepted 2019-02-27 11:32:56,119 - INFO - 0/5 [20.00%]: m_3 requested negmas.sao.SAOMechanism[None] with ['c_0', 'm_3'] (ID 0224430d-421a-4f72-9a94-aeaa817b5db8) 2019-02-27 11:32:56,120 - INFO - 0/5 [20.00%]: m_3-e6312be7-fa79-44d2-9ae4-f684919060e5 request was accepted 2019-02-27 11:32:56,123 - INFO - 0/5 [20.00%]: m_4 requested negmas.sao.SAOMechanism[None] with ['c_0', 'm_4'] (ID f53edf0a-402c-4b93-a523-40b0e8a9153e) 2019-02-27 11:32:56,124 - INFO - 0/5 [20.00%]: m_4-cf4ba00c-de5e-4e64-9f2d-a8bf1c05fb02 request was accepted 2019-02-27 11:32:56,126 - INFO - 0/5 [20.00%]: m_0 requested negmas.sao.SAOMechanism[None] with ['c_2', 'm_0'] (ID 7bdac465-abe6-411e-ad91-762fe11a1498) 2019-02-27 11:32:56,126 - INFO - 0/5 [20.00%]: m_0-ae38c93f-04bf-477a-809e-3d3de4b02340 request was accepted 2019-02-27 11:32:56,127 - INFO - 0/5 [20.00%]: m_1 requested negmas.sao.SAOMechanism[None] with ['c_2', 'm_1'] (ID 65bd0072-fae5-4d79-830d-0b8d09e6a6f8) 2019-02-27 11:32:56,128 - INFO - 0/5 [20.00%]: m_1-99b3c06e-66f7-4413-b0f8-af0919e75071 request was accepted 2019-02-27 11:32:56,129 - INFO - 0/5 [20.00%]: m_2 requested negmas.sao.SAOMechanism[None] with ['c_2', 'm_2'] (ID 49ca3fce-6e0c-4ab3-9dab-8d061dccf7f4) 2019-02-27 11:32:56,130 - INFO - 0/5 [20.00%]: m_2-d279992c-cf29-4b38-b046-100294ca6f0c request was accepted 2019-02-27 11:32:56,131 - INFO - 0/5 [20.00%]: m_3 requested negmas.sao.SAOMechanism[None] with ['c_2', 'm_3'] (ID 20459ba5-f7c3-4e15-b574-accc056150cd) 2019-02-27 11:32:56,131 - INFO - 0/5 [20.00%]: m_3-e6312be7-fa79-44d2-9ae4-f684919060e5 request was accepted 2019-02-27 11:32:56,132 - INFO - 0/5 [20.00%]: m_4 requested negmas.sao.SAOMechanism[None] with ['c_2', 'm_4'] (ID d6490831-7d43-48bc-ab24-8f0426c5e905) 2019-02-27 11:32:56,133 - INFO - 0/5 [20.00%]: m_4-cf4ba00c-de5e-4e64-9f2d-a8bf1c05fb02 request was accepted 2019-02-27 11:32:56,134 - INFO - 0/5 [20.00%]: m_0 requested negmas.sao.SAOMechanism[None] with ['c_2', 'm_0'] (ID 3fdb7495-228c-4e8f-8d0d-c96140c12240) 2019-02-27 11:32:56,135 - INFO - 0/5 [20.00%]: m_0-ae38c93f-04bf-477a-809e-3d3de4b02340 request was accepted 2019-02-27 11:32:56,136 - INFO - 0/5 [20.00%]: m_1 requested negmas.sao.SAOMechanism[None] with ['c_2', 'm_1'] (ID baaadb6d-c05d-49a6-9a7a-f489e450e924) 2019-02-27 11:32:56,136 - INFO - 0/5 [20.00%]: m_1-99b3c06e-66f7-4413-b0f8-af0919e75071 request was accepted 2019-02-27 11:32:56,137 - INFO - 0/5 [20.00%]: m_2 requested negmas.sao.SAOMechanism[None] with ['c_2', 'm_2'] (ID e4f252f3-c83d-4bfa-8f67-38bec8249f2b) 2019-02-27 11:32:56,138 - INFO - 0/5 [20.00%]: m_2-d279992c-cf29-4b38-b046-100294ca6f0c request was accepted 2019-02-27 11:32:56,139 - INFO - 0/5 [20.00%]: m_3 requested negmas.sao.SAOMechanism[None] with ['c_2', 'm_3'] (ID 70bdd9b1-ed8d-4842-a288-1a5e07265ea9) 2019-02-27 11:32:56,139 - INFO - 0/5 [20.00%]: m_3-e6312be7-fa79-44d2-9ae4-f684919060e5 request was accepted 2019-02-27 11:32:56,141 - INFO - 0/5 [20.00%]: m_4 requested negmas.sao.SAOMechanism[None] with ['c_2', 'm_4'] (ID d884b62c-412a-40ee-b70c-959a13df8abf) 2019-02-27 11:32:56,143 - INFO - 0/5 [20.00%]: m_4-cf4ba00c-de5e-4e64-9f2d-a8bf1c05fb02 request was accepted 2019-02-27 11:32:56,145 - INFO - 0/5 [20.00%]: m_0 requested negmas.sao.SAOMechanism[None] with ['c_1', 'm_0'] (ID c9293000-0e01-48a3-8665-589a50a6a3d9) 2019-02-27 11:32:56,146 - INFO - 0/5 [20.00%]: m_0-ae38c93f-04bf-477a-809e-3d3de4b02340 request was accepted 2019-02-27 11:32:56,148 - INFO - 0/5 [20.00%]: m_1 requested negmas.sao.SAOMechanism[None] with ['c_1', 'm_1'] (ID 8ffb3d2f-a6dd-4686-8f3e-b1eb565a6ffa) 2019-02-27 11:32:56,148 - INFO - 0/5 [20.00%]: m_1-99b3c06e-66f7-4413-b0f8-af0919e75071 request was accepted 2019-02-27 11:32:56,150 - INFO - 0/5 [20.00%]: m_2 requested negmas.sao.SAOMechanism[None] with ['c_1', 'm_2'] (ID d298c28a-40d2-477a-81e4-e3e7160227c0) 2019-02-27 11:32:56,151 - INFO - 0/5 [20.00%]: m_2-d279992c-cf29-4b38-b046-100294ca6f0c request was accepted 2019-02-27 11:32:56,153 - INFO - 0/5 [20.00%]: m_3 requested negmas.sao.SAOMechanism[None] with ['c_1', 'm_3'] (ID 2e77790f-97dc-4b6b-ba11-d52f3c15b75f) 2019-02-27 11:32:56,154 - INFO - 0/5 [20.00%]: m_3-e6312be7-fa79-44d2-9ae4-f684919060e5 request was accepted 2019-02-27 11:32:56,155 - INFO - 0/5 [20.00%]: m_4 requested negmas.sao.SAOMechanism[None] with ['c_1', 'm_4'] (ID 63c445d9-1ad1-464d-ad48-09f6f1d41e5a) 2019-02-27 11:32:56,156 - INFO - 0/5 [20.00%]: m_4-cf4ba00c-de5e-4e64-9f2d-a8bf1c05fb02 request was accepted 2019-02-27 11:32:56,157 - INFO - 0/5 [20.00%]: m_0 requested negmas.sao.SAOMechanism[None] with ['c_1', 'm_0'] (ID 0a48bcea-f61d-420f-9ae6-a46cbfd69f52) 2019-02-27 11:32:56,158 - INFO - 0/5 [20.00%]: m_0-ae38c93f-04bf-477a-809e-3d3de4b02340 request was accepted 2019-02-27 11:32:56,159 - INFO - 0/5 [20.00%]: m_1 requested negmas.sao.SAOMechanism[None] with ['c_1', 'm_1'] (ID e357fc45-3fb5-4658-b0eb-86aca1c1eef0) 2019-02-27 11:32:56,160 - INFO - 0/5 [20.00%]: m_1-99b3c06e-66f7-4413-b0f8-af0919e75071 request was accepted 2019-02-27 11:32:56,161 - INFO - 0/5 [20.00%]: m_2 requested negmas.sao.SAOMechanism[None] with ['c_1', 'm_2'] (ID 57cdc376-ae01-470f-81e6-56c6cfec98eb) 2019-02-27 11:32:56,174 - INFO - 0/5 [20.00%]: m_2-d279992c-cf29-4b38-b046-100294ca6f0c request was accepted 2019-02-27 11:32:56,176 - INFO - 0/5 [20.00%]: m_3 requested negmas.sao.SAOMechanism[None] with ['c_1', 'm_3'] (ID a3e4414b-133a-4227-a3e8-3891f4e7f5d7) 2019-02-27 11:32:56,176 - INFO - 0/5 [20.00%]: m_3-e6312be7-fa79-44d2-9ae4-f684919060e5 request was accepted 2019-02-27 11:32:56,178 - INFO - 0/5 [20.00%]: m_4 requested negmas.sao.SAOMechanism[None] with ['c_1', 'm_4'] (ID 918c1be5-2c6c-4bc5-8328-3b6635f73c77) 2019-02-27 11:32:56,178 - INFO - 0/5 [20.00%]: m_4-cf4ba00c-de5e-4e64-9f2d-a8bf1c05fb02 request was accepted 2019-02-27 11:32:56,178 - DEBUG - 0/5 [20.00%]: Factory e99d9a30-972a-4954-a82a-dd7afdef43ad: money=0, storage={}, loans=0.0 2019-02-27 11:32:56,178 - DEBUG - 0/5 [20.00%]: Factory c522c9c1-11e2-41e3-9250-b27a9522444b: money=0, storage={}, loans=0.0 2019-02-27 11:32:56,178 - DEBUG - 0/5 [20.00%]: Factory ff2a5bf9-bfbd-48a1-b5e7-c4dadc046f96: money=0, storage={}, loans=0.0 2019-02-27 11:32:56,179 - DEBUG - 0/5 [20.00%]: Factory 5e7733e2-db9b-4765-a33a-7e9fe2248fc5: money=0, storage={}, loans=0.0 2019-02-27 11:32:56,179 - DEBUG - 0/5 [20.00%]: Factory 852400c0-e73c-4484-91ec-ba8a9a901a8d: money=0, storage={}, loans=0.0 2019-02-27 11:32:56,179 - DEBUG - 0/5 [20.00%]: Factory e7a5def1-059e-49c4-aad9-e82c624fd8c4: money=0.0, storage={}, loans=0.0 2019-02-27 11:32:56,179 - DEBUG - 0/5 [20.00%]: Factory fdd8ea88-1272-4965-8317-13385e2d18dc: money=0.0, storage={}, loans=0.0 2019-02-27 11:32:56,179 - DEBUG - 0/5 [20.00%]: Factory af03e704-f500-48dc-b1f3-45d5d3cf60f3: money=0.0, storage={}, loans=0.0 2019-02-27 11:32:56,179 - DEBUG - 0/5 [20.00%]: Factory bcda6d74-adb6-450c-a9e4-06756aaeb456: money=0.0, storage={}, loans=0.0 2019-02-27 11:32:56,179 - DEBUG - 0/5 [20.00%]: Factory f621f922-b18a-4edb-b071-ef577b17d239: money=0.0, storage={}, loans=0.0 2019-02-27 11:32:56,180 - INFO - 1/5 [40.00%]: 50 Negotiations/4 _entities 2019-02-27 11:32:56,772 - DEBUG - 1/5 [40.00%]: Contract [signed]: ['c_0', 'm_4'] > {'time': 1, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_0-2e50318f-4595-4018-9486-4549326453e7: buy 0 (t: 1, u: (0, 2.0), q: (1, 4))', 'partners': "['c_0-2e50318f-4595-4018-9486-4549326453e7', 'm_4-cf4ba00c-de5e-4e64-9f2d-a8bf1c05fb02']", 'seller': 'm_4-cf4ba00c-de5e-4e64-9f2d-a8bf1c05fb02', 'buyer': 'c_0-2e50318f-4595-4018-9486-4549326453e7'} 2019-02-27 11:32:56,772 - DEBUG - 1/5 [40.00%]: Contract [signed]: ['c_4', 'm_1'] > {'time': 2, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_4-81d58b26-eabf-43d9-b58f-21b367075ff6: buy 0 (t: 2, u: (0, 2.0), q: (1, 3))', 'partners': "['c_4-81d58b26-eabf-43d9-b58f-21b367075ff6', 'm_1-99b3c06e-66f7-4413-b0f8-af0919e75071']", 'seller': 'm_1-99b3c06e-66f7-4413-b0f8-af0919e75071', 'buyer': 'c_4-81d58b26-eabf-43d9-b58f-21b367075ff6'} 2019-02-27 11:32:56,773 - DEBUG - 1/5 [40.00%]: Contract [cancelled]: ['c_4', 'm_3'] > {'time': 2, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_4-81d58b26-eabf-43d9-b58f-21b367075ff6: buy 0 (t: 2, u: (0, 2.0), q: (1, 3))', 'partners': "['c_4-81d58b26-eabf-43d9-b58f-21b367075ff6', 'm_3-e6312be7-fa79-44d2-9ae4-f684919060e5']", 'seller': 'm_3-e6312be7-fa79-44d2-9ae4-f684919060e5', 'buyer': 'c_4-81d58b26-eabf-43d9-b58f-21b367075ff6'} 2019-02-27 11:32:56,773 - DEBUG - 1/5 [40.00%]: Contract [signed]: ['c_2', 'm_0'] > {'time': 1, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_2-d804b0d2-8eb4-4afa-bb16-d2e4c8ebcdcb: buy 0 (t: 1, u: (0, 2.0), q: (1, 4))', 'partners': "['c_2-d804b0d2-8eb4-4afa-bb16-d2e4c8ebcdcb', 'm_0-ae38c93f-04bf-477a-809e-3d3de4b02340']", 'seller': 'm_0-ae38c93f-04bf-477a-809e-3d3de4b02340', 'buyer': 'c_2-d804b0d2-8eb4-4afa-bb16-d2e4c8ebcdcb'} 2019-02-27 11:32:56,774 - DEBUG - 1/5 [40.00%]: Contract [signed]: ['c_4', 'm_4'] > {'time': 1, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_4-81d58b26-eabf-43d9-b58f-21b367075ff6: buy 0 (t: 1, u: (0, 2.0), q: (1, 4))', 'partners': "['c_4-81d58b26-eabf-43d9-b58f-21b367075ff6', 'm_4-cf4ba00c-de5e-4e64-9f2d-a8bf1c05fb02']", 'seller': 'm_4-cf4ba00c-de5e-4e64-9f2d-a8bf1c05fb02', 'buyer': 'c_4-81d58b26-eabf-43d9-b58f-21b367075ff6'} 2019-02-27 11:32:56,774 - DEBUG - 1/5 [40.00%]: Contract [signed]: ['c_0', 'm_3'] > {'time': 2, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_0-2e50318f-4595-4018-9486-4549326453e7: buy 0 (t: 2, u: (0, 2.0), q: (1, 3))', 'partners': "['c_0-2e50318f-4595-4018-9486-4549326453e7', 'm_3-e6312be7-fa79-44d2-9ae4-f684919060e5']", 'seller': 'm_3-e6312be7-fa79-44d2-9ae4-f684919060e5', 'buyer': 'c_0-2e50318f-4595-4018-9486-4549326453e7'} 2019-02-27 11:32:56,775 - DEBUG - 1/5 [40.00%]: Contract [signed]: ['c_1', 'm_4'] > {'time': 2, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_1-3dbd2a2a-0c36-47bf-96c9-9754f7352219: buy 0 (t: 2, u: (0, 2.0), q: (1, 4))', 'partners': "['c_1-3dbd2a2a-0c36-47bf-96c9-9754f7352219', 'm_4-cf4ba00c-de5e-4e64-9f2d-a8bf1c05fb02']", 'seller': 'm_4-cf4ba00c-de5e-4e64-9f2d-a8bf1c05fb02', 'buyer': 'c_1-3dbd2a2a-0c36-47bf-96c9-9754f7352219'} 2019-02-27 11:32:56,776 - DEBUG - 1/5 [40.00%]: Contract [cancelled]: ['c_1', 'm_0'] > {'time': 2, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_1-3dbd2a2a-0c36-47bf-96c9-9754f7352219: buy 0 (t: 2, u: (0, 2.0), q: (1, 4))', 'partners': "['c_1-3dbd2a2a-0c36-47bf-96c9-9754f7352219', 'm_0-ae38c93f-04bf-477a-809e-3d3de4b02340']", 'seller': 'm_0-ae38c93f-04bf-477a-809e-3d3de4b02340', 'buyer': 'c_1-3dbd2a2a-0c36-47bf-96c9-9754f7352219'} 2019-02-27 11:32:56,777 - DEBUG - 1/5 [40.00%]: Contract [cancelled]: ['c_0', 'm_0'] > {'time': 1, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_0-2e50318f-4595-4018-9486-4549326453e7: buy 0 (t: 1, u: (0, 2.0), q: (1, 4))', 'partners': "['c_0-2e50318f-4595-4018-9486-4549326453e7', 'm_0-ae38c93f-04bf-477a-809e-3d3de4b02340']", 'seller': 'm_0-ae38c93f-04bf-477a-809e-3d3de4b02340', 'buyer': 'c_0-2e50318f-4595-4018-9486-4549326453e7'} 2019-02-27 11:32:56,777 - DEBUG - 1/5 [40.00%]: Contract [cancelled]: ['c_4', 'm_1'] > {'time': 1, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_4-81d58b26-eabf-43d9-b58f-21b367075ff6: buy 0 (t: 1, u: (0, 2.0), q: (1, 4))', 'partners': "['c_4-81d58b26-eabf-43d9-b58f-21b367075ff6', 'm_1-99b3c06e-66f7-4413-b0f8-af0919e75071']", 'seller': 'm_1-99b3c06e-66f7-4413-b0f8-af0919e75071', 'buyer': 'c_4-81d58b26-eabf-43d9-b58f-21b367075ff6'} 2019-02-27 11:32:56,778 - DEBUG - 1/5 [40.00%]: Contract [cancelled]: ['c_2', 'm_4'] > {'time': 1, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_2-d804b0d2-8eb4-4afa-bb16-d2e4c8ebcdcb: buy 0 (t: 1, u: (0, 2.0), q: (1, 4))', 'partners': "['c_2-d804b0d2-8eb4-4afa-bb16-d2e4c8ebcdcb', 'm_4-cf4ba00c-de5e-4e64-9f2d-a8bf1c05fb02']", 'seller': 'm_4-cf4ba00c-de5e-4e64-9f2d-a8bf1c05fb02', 'buyer': 'c_2-d804b0d2-8eb4-4afa-bb16-d2e4c8ebcdcb'} 2019-02-27 11:32:56,778 - DEBUG - 1/5 [40.00%]: Contract [signed]: ['c_3', 'm_0'] > {'time': 2, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_3-a48f2b83-a7b3-49ab-a0fb-729d4ae18c2d: buy 0 (t: 2, u: (0, 2.0), q: (1, 4))', 'partners': "['c_3-a48f2b83-a7b3-49ab-a0fb-729d4ae18c2d', 'm_0-ae38c93f-04bf-477a-809e-3d3de4b02340']", 'seller': 'm_0-ae38c93f-04bf-477a-809e-3d3de4b02340', 'buyer': 'c_3-a48f2b83-a7b3-49ab-a0fb-729d4ae18c2d'} 2019-02-27 11:32:56,779 - DEBUG - 1/5 [40.00%]: Contract [cancelled]: ['c_1', 'm_2'] > {'time': 2, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_1-3dbd2a2a-0c36-47bf-96c9-9754f7352219: buy 0 (t: 2, u: (0, 2.0), q: (1, 4))', 'partners': "['c_1-3dbd2a2a-0c36-47bf-96c9-9754f7352219', 'm_2-d279992c-cf29-4b38-b046-100294ca6f0c']", 'seller': 'm_2-d279992c-cf29-4b38-b046-100294ca6f0c', 'buyer': 'c_1-3dbd2a2a-0c36-47bf-96c9-9754f7352219'} 2019-02-27 11:32:56,779 - DEBUG - 1/5 [40.00%]: Contract [signed]: ['c_3', 'm_2'] > {'time': 1, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_3-a48f2b83-a7b3-49ab-a0fb-729d4ae18c2d: buy 0 (t: 1, u: (0, 2.0), q: (1, 3))', 'partners': "['c_3-a48f2b83-a7b3-49ab-a0fb-729d4ae18c2d', 'm_2-d279992c-cf29-4b38-b046-100294ca6f0c']", 'seller': 'm_2-d279992c-cf29-4b38-b046-100294ca6f0c', 'buyer': 'c_3-a48f2b83-a7b3-49ab-a0fb-729d4ae18c2d'} 2019-02-27 11:32:56,780 - DEBUG - 1/5 [40.00%]: Contract [cancelled]: ['c_0', 'm_2'] > {'time': 2, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_0-2e50318f-4595-4018-9486-4549326453e7: buy 0 (t: 2, u: (0, 2.0), q: (1, 3))', 'partners': "['c_0-2e50318f-4595-4018-9486-4549326453e7', 'm_2-d279992c-cf29-4b38-b046-100294ca6f0c']", 'seller': 'm_2-d279992c-cf29-4b38-b046-100294ca6f0c', 'buyer': 'c_0-2e50318f-4595-4018-9486-4549326453e7'} 2019-02-27 11:32:56,780 - DEBUG - 1/5 [40.00%]: Contract [cancelled]: ['c_3', 'm_0'] > {'time': 1, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_3-a48f2b83-a7b3-49ab-a0fb-729d4ae18c2d: buy 0 (t: 1, u: (0, 2.0), q: (1, 3))', 'partners': "['c_3-a48f2b83-a7b3-49ab-a0fb-729d4ae18c2d', 'm_0-ae38c93f-04bf-477a-809e-3d3de4b02340']", 'seller': 'm_0-ae38c93f-04bf-477a-809e-3d3de4b02340', 'buyer': 'c_3-a48f2b83-a7b3-49ab-a0fb-729d4ae18c2d'} 2019-02-27 11:32:56,780 - DEBUG - 1/5 [40.00%]: Contract [cancelled]: ['c_4', 'm_2'] > {'time': 2, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_4-81d58b26-eabf-43d9-b58f-21b367075ff6: buy 0 (t: 2, u: (0, 2.0), q: (1, 3))', 'partners': "['c_4-81d58b26-eabf-43d9-b58f-21b367075ff6', 'm_2-d279992c-cf29-4b38-b046-100294ca6f0c']", 'seller': 'm_2-d279992c-cf29-4b38-b046-100294ca6f0c', 'buyer': 'c_4-81d58b26-eabf-43d9-b58f-21b367075ff6'} 2019-02-27 11:32:56,781 - DEBUG - 1/5 [40.00%]: Contract [signed]: ['c_1', 'm_3'] > {'time': 1, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_1-3dbd2a2a-0c36-47bf-96c9-9754f7352219: buy 0 (t: 1, u: (0, 2.0), q: (1, 4))', 'partners': "['c_1-3dbd2a2a-0c36-47bf-96c9-9754f7352219', 'm_3-e6312be7-fa79-44d2-9ae4-f684919060e5']", 'seller': 'm_3-e6312be7-fa79-44d2-9ae4-f684919060e5', 'buyer': 'c_1-3dbd2a2a-0c36-47bf-96c9-9754f7352219'} 2019-02-27 11:32:56,781 - DEBUG - 1/5 [40.00%]: Contract [cancelled]: ['c_0', 'm_1'] > {'time': 1, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_0-2e50318f-4595-4018-9486-4549326453e7: buy 0 (t: 1, u: (0, 2.0), q: (1, 4))', 'partners': "['c_0-2e50318f-4595-4018-9486-4549326453e7', 'm_1-99b3c06e-66f7-4413-b0f8-af0919e75071']", 'seller': 'm_1-99b3c06e-66f7-4413-b0f8-af0919e75071', 'buyer': 'c_0-2e50318f-4595-4018-9486-4549326453e7'} 2019-02-27 11:32:56,781 - DEBUG - 1/5 [40.00%]: Contract [cancelled]: ['c_2', 'm_3'] > {'time': 1, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_2-d804b0d2-8eb4-4afa-bb16-d2e4c8ebcdcb: buy 0 (t: 1, u: (0, 2.0), q: (1, 4))', 'partners': "['c_2-d804b0d2-8eb4-4afa-bb16-d2e4c8ebcdcb', 'm_3-e6312be7-fa79-44d2-9ae4-f684919060e5']", 'seller': 'm_3-e6312be7-fa79-44d2-9ae4-f684919060e5', 'buyer': 'c_2-d804b0d2-8eb4-4afa-bb16-d2e4c8ebcdcb'} 2019-02-27 11:32:56,782 - DEBUG - 1/5 [40.00%]: Contract [cancelled]: ['c_4', 'm_4'] > {'time': 2, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_4-81d58b26-eabf-43d9-b58f-21b367075ff6: buy 0 (t: 2, u: (0, 2.0), q: (1, 3))', 'partners': "['c_4-81d58b26-eabf-43d9-b58f-21b367075ff6', 'm_4-cf4ba00c-de5e-4e64-9f2d-a8bf1c05fb02']", 'seller': 'm_4-cf4ba00c-de5e-4e64-9f2d-a8bf1c05fb02', 'buyer': 'c_4-81d58b26-eabf-43d9-b58f-21b367075ff6'} 2019-02-27 11:32:56,783 - DEBUG - 1/5 [40.00%]: Contract [signed]: ['c_2', 'm_2'] > {'time': 2, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_2-d804b0d2-8eb4-4afa-bb16-d2e4c8ebcdcb: buy 0 (t: 2, u: (0, 2.0), q: (1, 3))', 'partners': "['c_2-d804b0d2-8eb4-4afa-bb16-d2e4c8ebcdcb', 'm_2-d279992c-cf29-4b38-b046-100294ca6f0c']", 'seller': 'm_2-d279992c-cf29-4b38-b046-100294ca6f0c', 'buyer': 'c_2-d804b0d2-8eb4-4afa-bb16-d2e4c8ebcdcb'} 2019-02-27 11:32:56,783 - DEBUG - 1/5 [40.00%]: Contract [cancelled]: ['c_3', 'm_3'] > {'time': 2, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_3-a48f2b83-a7b3-49ab-a0fb-729d4ae18c2d: buy 0 (t: 2, u: (0, 2.0), q: (1, 4))', 'partners': "['c_3-a48f2b83-a7b3-49ab-a0fb-729d4ae18c2d', 'm_3-e6312be7-fa79-44d2-9ae4-f684919060e5']", 'seller': 'm_3-e6312be7-fa79-44d2-9ae4-f684919060e5', 'buyer': 'c_3-a48f2b83-a7b3-49ab-a0fb-729d4ae18c2d'} 2019-02-27 11:32:56,784 - DEBUG - 1/5 [40.00%]: Contract [cancelled]: ['c_3', 'm_4'] > {'time': 2, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_3-a48f2b83-a7b3-49ab-a0fb-729d4ae18c2d: buy 0 (t: 2, u: (0, 2.0), q: (1, 4))', 'partners': "['c_3-a48f2b83-a7b3-49ab-a0fb-729d4ae18c2d', 'm_4-cf4ba00c-de5e-4e64-9f2d-a8bf1c05fb02']", 'seller': 'm_4-cf4ba00c-de5e-4e64-9f2d-a8bf1c05fb02', 'buyer': 'c_3-a48f2b83-a7b3-49ab-a0fb-729d4ae18c2d'} 2019-02-27 11:32:56,785 - DEBUG - 1/5 [40.00%]: Contract [cancelled]: ['c_0', 'm_4'] > {'time': 2, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_0-2e50318f-4595-4018-9486-4549326453e7: buy 0 (t: 2, u: (0, 2.0), q: (1, 3))', 'partners': "['c_0-2e50318f-4595-4018-9486-4549326453e7', 'm_4-cf4ba00c-de5e-4e64-9f2d-a8bf1c05fb02']", 'seller': 'm_4-cf4ba00c-de5e-4e64-9f2d-a8bf1c05fb02', 'buyer': 'c_0-2e50318f-4595-4018-9486-4549326453e7'} 2019-02-27 11:32:56,787 - DEBUG - 1/5 [40.00%]: Contract [cancelled]: ['c_2', 'm_4'] > {'time': 2, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_2-d804b0d2-8eb4-4afa-bb16-d2e4c8ebcdcb: buy 0 (t: 2, u: (0, 2.0), q: (1, 3))', 'partners': "['c_2-d804b0d2-8eb4-4afa-bb16-d2e4c8ebcdcb', 'm_4-cf4ba00c-de5e-4e64-9f2d-a8bf1c05fb02']", 'seller': 'm_4-cf4ba00c-de5e-4e64-9f2d-a8bf1c05fb02', 'buyer': 'c_2-d804b0d2-8eb4-4afa-bb16-d2e4c8ebcdcb'} 2019-02-27 11:32:56,789 - DEBUG - 1/5 [40.00%]: Contract [cancelled]: ['c_1', 'm_4'] > {'time': 1, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_1-3dbd2a2a-0c36-47bf-96c9-9754f7352219: buy 0 (t: 1, u: (0, 2.0), q: (1, 4))', 'partners': "['c_1-3dbd2a2a-0c36-47bf-96c9-9754f7352219', 'm_4-cf4ba00c-de5e-4e64-9f2d-a8bf1c05fb02']", 'seller': 'm_4-cf4ba00c-de5e-4e64-9f2d-a8bf1c05fb02', 'buyer': 'c_1-3dbd2a2a-0c36-47bf-96c9-9754f7352219'} 2019-02-27 11:32:56,790 - DEBUG - 1/5 [40.00%]: Contract [cancelled]: ['c_2', 'm_0'] > {'time': 2, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_2-d804b0d2-8eb4-4afa-bb16-d2e4c8ebcdcb: buy 0 (t: 2, u: (0, 2.0), q: (1, 3))', 'partners': "['c_2-d804b0d2-8eb4-4afa-bb16-d2e4c8ebcdcb', 'm_0-ae38c93f-04bf-477a-809e-3d3de4b02340']", 'seller': 'm_0-ae38c93f-04bf-477a-809e-3d3de4b02340', 'buyer': 'c_2-d804b0d2-8eb4-4afa-bb16-d2e4c8ebcdcb'} 2019-02-27 11:32:56,790 - DEBUG - 1/5 [40.00%]: Contract [cancelled]: ['c_3', 'm_3'] > {'time': 1, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_3-a48f2b83-a7b3-49ab-a0fb-729d4ae18c2d: buy 0 (t: 1, u: (0, 2.0), q: (1, 3))', 'partners': "['c_3-a48f2b83-a7b3-49ab-a0fb-729d4ae18c2d', 'm_3-e6312be7-fa79-44d2-9ae4-f684919060e5']", 'seller': 'm_3-e6312be7-fa79-44d2-9ae4-f684919060e5', 'buyer': 'c_3-a48f2b83-a7b3-49ab-a0fb-729d4ae18c2d'} 2019-02-27 11:32:56,791 - DEBUG - 1/5 [40.00%]: Contract [cancelled]: ['c_2', 'm_1'] > {'time': 1, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_2-d804b0d2-8eb4-4afa-bb16-d2e4c8ebcdcb: buy 0 (t: 1, u: (0, 2.0), q: (1, 4))', 'partners': "['c_2-d804b0d2-8eb4-4afa-bb16-d2e4c8ebcdcb', 'm_1-99b3c06e-66f7-4413-b0f8-af0919e75071']", 'seller': 'm_1-99b3c06e-66f7-4413-b0f8-af0919e75071', 'buyer': 'c_2-d804b0d2-8eb4-4afa-bb16-d2e4c8ebcdcb'} 2019-02-27 11:32:56,792 - DEBUG - 1/5 [40.00%]: Contract [cancelled]: ['c_4', 'm_0'] > {'time': 1, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_4-81d58b26-eabf-43d9-b58f-21b367075ff6: buy 0 (t: 1, u: (0, 2.0), q: (1, 4))', 'partners': "['c_4-81d58b26-eabf-43d9-b58f-21b367075ff6', 'm_0-ae38c93f-04bf-477a-809e-3d3de4b02340']", 'seller': 'm_0-ae38c93f-04bf-477a-809e-3d3de4b02340', 'buyer': 'c_4-81d58b26-eabf-43d9-b58f-21b367075ff6'} 2019-02-27 11:32:56,792 - DEBUG - 1/5 [40.00%]: Contract [cancelled]: ['c_4', 'm_3'] > {'time': 1, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_4-81d58b26-eabf-43d9-b58f-21b367075ff6: buy 0 (t: 1, u: (0, 2.0), q: (1, 4))', 'partners': "['c_4-81d58b26-eabf-43d9-b58f-21b367075ff6', 'm_3-e6312be7-fa79-44d2-9ae4-f684919060e5']", 'seller': 'm_3-e6312be7-fa79-44d2-9ae4-f684919060e5', 'buyer': 'c_4-81d58b26-eabf-43d9-b58f-21b367075ff6'} 2019-02-27 11:32:56,793 - DEBUG - 1/5 [40.00%]: Contract [cancelled]: ['c_1', 'm_1'] > {'time': 2, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_1-3dbd2a2a-0c36-47bf-96c9-9754f7352219: buy 0 (t: 2, u: (0, 2.0), q: (1, 4))', 'partners': "['c_1-3dbd2a2a-0c36-47bf-96c9-9754f7352219', 'm_1-99b3c06e-66f7-4413-b0f8-af0919e75071']", 'seller': 'm_1-99b3c06e-66f7-4413-b0f8-af0919e75071', 'buyer': 'c_1-3dbd2a2a-0c36-47bf-96c9-9754f7352219'} 2019-02-27 11:32:56,793 - DEBUG - 1/5 [40.00%]: Contract [cancelled]: ['c_0', 'm_2'] > {'time': 1, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_0-2e50318f-4595-4018-9486-4549326453e7: buy 0 (t: 1, u: (0, 2.0), q: (1, 4))', 'partners': "['c_0-2e50318f-4595-4018-9486-4549326453e7', 'm_2-d279992c-cf29-4b38-b046-100294ca6f0c']", 'seller': 'm_2-d279992c-cf29-4b38-b046-100294ca6f0c', 'buyer': 'c_0-2e50318f-4595-4018-9486-4549326453e7'} 2019-02-27 11:32:56,794 - DEBUG - 1/5 [40.00%]: Contract [cancelled]: ['c_1', 'm_3'] > {'time': 2, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_1-3dbd2a2a-0c36-47bf-96c9-9754f7352219: buy 0 (t: 2, u: (0, 2.0), q: (1, 4))', 'partners': "['c_1-3dbd2a2a-0c36-47bf-96c9-9754f7352219', 'm_3-e6312be7-fa79-44d2-9ae4-f684919060e5']", 'seller': 'm_3-e6312be7-fa79-44d2-9ae4-f684919060e5', 'buyer': 'c_1-3dbd2a2a-0c36-47bf-96c9-9754f7352219'} 2019-02-27 11:32:56,794 - DEBUG - 1/5 [40.00%]: Contract [cancelled]: ['c_2', 'm_3'] > {'time': 2, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_2-d804b0d2-8eb4-4afa-bb16-d2e4c8ebcdcb: buy 0 (t: 2, u: (0, 2.0), q: (1, 3))', 'partners': "['c_2-d804b0d2-8eb4-4afa-bb16-d2e4c8ebcdcb', 'm_3-e6312be7-fa79-44d2-9ae4-f684919060e5']", 'seller': 'm_3-e6312be7-fa79-44d2-9ae4-f684919060e5', 'buyer': 'c_2-d804b0d2-8eb4-4afa-bb16-d2e4c8ebcdcb'} 2019-02-27 11:32:56,795 - DEBUG - 1/5 [40.00%]: Contract [cancelled]: ['c_3', 'm_4'] > {'time': 1, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_3-a48f2b83-a7b3-49ab-a0fb-729d4ae18c2d: buy 0 (t: 1, u: (0, 2.0), q: (1, 3))', 'partners': "['c_3-a48f2b83-a7b3-49ab-a0fb-729d4ae18c2d', 'm_4-cf4ba00c-de5e-4e64-9f2d-a8bf1c05fb02']", 'seller': 'm_4-cf4ba00c-de5e-4e64-9f2d-a8bf1c05fb02', 'buyer': 'c_3-a48f2b83-a7b3-49ab-a0fb-729d4ae18c2d'} 2019-02-27 11:32:56,795 - DEBUG - 1/5 [40.00%]: Contract [cancelled]: ['c_2', 'm_2'] > {'time': 1, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_2-d804b0d2-8eb4-4afa-bb16-d2e4c8ebcdcb: buy 0 (t: 1, u: (0, 2.0), q: (1, 4))', 'partners': "['c_2-d804b0d2-8eb4-4afa-bb16-d2e4c8ebcdcb', 'm_2-d279992c-cf29-4b38-b046-100294ca6f0c']", 'seller': 'm_2-d279992c-cf29-4b38-b046-100294ca6f0c', 'buyer': 'c_2-d804b0d2-8eb4-4afa-bb16-d2e4c8ebcdcb'} 2019-02-27 11:32:56,796 - DEBUG - 1/5 [40.00%]: Contract [cancelled]: ['c_3', 'm_1'] > {'time': 1, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_3-a48f2b83-a7b3-49ab-a0fb-729d4ae18c2d: buy 0 (t: 1, u: (0, 2.0), q: (1, 3))', 'partners': "['c_3-a48f2b83-a7b3-49ab-a0fb-729d4ae18c2d', 'm_1-99b3c06e-66f7-4413-b0f8-af0919e75071']", 'seller': 'm_1-99b3c06e-66f7-4413-b0f8-af0919e75071', 'buyer': 'c_3-a48f2b83-a7b3-49ab-a0fb-729d4ae18c2d'} 2019-02-27 11:32:56,796 - DEBUG - 1/5 [40.00%]: Contract [cancelled]: ['c_4', 'm_0'] > {'time': 2, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_4-81d58b26-eabf-43d9-b58f-21b367075ff6: buy 0 (t: 2, u: (0, 2.0), q: (1, 3))', 'partners': "['c_4-81d58b26-eabf-43d9-b58f-21b367075ff6', 'm_0-ae38c93f-04bf-477a-809e-3d3de4b02340']", 'seller': 'm_0-ae38c93f-04bf-477a-809e-3d3de4b02340', 'buyer': 'c_4-81d58b26-eabf-43d9-b58f-21b367075ff6'} 2019-02-27 11:32:56,797 - DEBUG - 1/5 [40.00%]: Contract [cancelled]: ['c_2', 'm_1'] > {'time': 2, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_2-d804b0d2-8eb4-4afa-bb16-d2e4c8ebcdcb: buy 0 (t: 2, u: (0, 2.0), q: (1, 3))', 'partners': "['c_2-d804b0d2-8eb4-4afa-bb16-d2e4c8ebcdcb', 'm_1-99b3c06e-66f7-4413-b0f8-af0919e75071']", 'seller': 'm_1-99b3c06e-66f7-4413-b0f8-af0919e75071', 'buyer': 'c_2-d804b0d2-8eb4-4afa-bb16-d2e4c8ebcdcb'} 2019-02-27 11:32:56,797 - DEBUG - 1/5 [40.00%]: Contract [cancelled]: ['c_1', 'm_2'] > {'time': 1, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_1-3dbd2a2a-0c36-47bf-96c9-9754f7352219: buy 0 (t: 1, u: (0, 2.0), q: (1, 4))', 'partners': "['c_1-3dbd2a2a-0c36-47bf-96c9-9754f7352219', 'm_2-d279992c-cf29-4b38-b046-100294ca6f0c']", 'seller': 'm_2-d279992c-cf29-4b38-b046-100294ca6f0c', 'buyer': 'c_1-3dbd2a2a-0c36-47bf-96c9-9754f7352219'} 2019-02-27 11:32:56,797 - DEBUG - 1/5 [40.00%]: Contract [cancelled]: ['c_1', 'm_1'] > {'time': 1, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_1-3dbd2a2a-0c36-47bf-96c9-9754f7352219: buy 0 (t: 1, u: (0, 2.0), q: (1, 4))', 'partners': "['c_1-3dbd2a2a-0c36-47bf-96c9-9754f7352219', 'm_1-99b3c06e-66f7-4413-b0f8-af0919e75071']", 'seller': 'm_1-99b3c06e-66f7-4413-b0f8-af0919e75071', 'buyer': 'c_1-3dbd2a2a-0c36-47bf-96c9-9754f7352219'} 2019-02-27 11:32:56,798 - DEBUG - 1/5 [40.00%]: Contract [cancelled]: ['c_1', 'm_0'] > {'time': 1, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_1-3dbd2a2a-0c36-47bf-96c9-9754f7352219: buy 0 (t: 1, u: (0, 2.0), q: (1, 4))', 'partners': "['c_1-3dbd2a2a-0c36-47bf-96c9-9754f7352219', 'm_0-ae38c93f-04bf-477a-809e-3d3de4b02340']", 'seller': 'm_0-ae38c93f-04bf-477a-809e-3d3de4b02340', 'buyer': 'c_1-3dbd2a2a-0c36-47bf-96c9-9754f7352219'} 2019-02-27 11:32:56,799 - DEBUG - 1/5 [40.00%]: Contract [cancelled]: ['c_0', 'm_3'] > {'time': 1, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_0-2e50318f-4595-4018-9486-4549326453e7: buy 0 (t: 1, u: (0, 2.0), q: (1, 4))', 'partners': "['c_0-2e50318f-4595-4018-9486-4549326453e7', 'm_3-e6312be7-fa79-44d2-9ae4-f684919060e5']", 'seller': 'm_3-e6312be7-fa79-44d2-9ae4-f684919060e5', 'buyer': 'c_0-2e50318f-4595-4018-9486-4549326453e7'} 2019-02-27 11:32:56,799 - DEBUG - 1/5 [40.00%]: Contract [cancelled]: ['c_3', 'm_2'] > {'time': 2, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_3-a48f2b83-a7b3-49ab-a0fb-729d4ae18c2d: buy 0 (t: 2, u: (0, 2.0), q: (1, 4))', 'partners': "['c_3-a48f2b83-a7b3-49ab-a0fb-729d4ae18c2d', 'm_2-d279992c-cf29-4b38-b046-100294ca6f0c']", 'seller': 'm_2-d279992c-cf29-4b38-b046-100294ca6f0c', 'buyer': 'c_3-a48f2b83-a7b3-49ab-a0fb-729d4ae18c2d'} 2019-02-27 11:32:56,800 - DEBUG - 1/5 [40.00%]: Contract [cancelled]: ['c_4', 'm_2'] > {'time': 1, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_4-81d58b26-eabf-43d9-b58f-21b367075ff6: buy 0 (t: 1, u: (0, 2.0), q: (1, 4))', 'partners': "['c_4-81d58b26-eabf-43d9-b58f-21b367075ff6', 'm_2-d279992c-cf29-4b38-b046-100294ca6f0c']", 'seller': 'm_2-d279992c-cf29-4b38-b046-100294ca6f0c', 'buyer': 'c_4-81d58b26-eabf-43d9-b58f-21b367075ff6'} 2019-02-27 11:32:56,800 - DEBUG - 1/5 [40.00%]: Contract [cancelled]: ['c_0', 'm_0'] > {'time': 2, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_0-2e50318f-4595-4018-9486-4549326453e7: buy 0 (t: 2, u: (0, 2.0), q: (1, 3))', 'partners': "['c_0-2e50318f-4595-4018-9486-4549326453e7', 'm_0-ae38c93f-04bf-477a-809e-3d3de4b02340']", 'seller': 'm_0-ae38c93f-04bf-477a-809e-3d3de4b02340', 'buyer': 'c_0-2e50318f-4595-4018-9486-4549326453e7'} 2019-02-27 11:32:56,801 - DEBUG - 1/5 [40.00%]: Contract [cancelled]: ['c_0', 'm_1'] > {'time': 2, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_0-2e50318f-4595-4018-9486-4549326453e7: buy 0 (t: 2, u: (0, 2.0), q: (1, 3))', 'partners': "['c_0-2e50318f-4595-4018-9486-4549326453e7', 'm_1-99b3c06e-66f7-4413-b0f8-af0919e75071']", 'seller': 'm_1-99b3c06e-66f7-4413-b0f8-af0919e75071', 'buyer': 'c_0-2e50318f-4595-4018-9486-4549326453e7'} 2019-02-27 11:32:56,802 - DEBUG - 1/5 [40.00%]: Contract [cancelled]: ['c_3', 'm_1'] > {'time': 2, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_3-a48f2b83-a7b3-49ab-a0fb-729d4ae18c2d: buy 0 (t: 2, u: (0, 2.0), q: (1, 4))', 'partners': "['c_3-a48f2b83-a7b3-49ab-a0fb-729d4ae18c2d', 'm_1-99b3c06e-66f7-4413-b0f8-af0919e75071']", 'seller': 'm_1-99b3c06e-66f7-4413-b0f8-af0919e75071', 'buyer': 'c_3-a48f2b83-a7b3-49ab-a0fb-729d4ae18c2d'} 2019-02-27 11:32:56,804 - INFO - 1/5 [40.00%]: m_0 requested negmas.sao.SAOMechanism[None] with ['c_3', 'm_0'] (ID 7f6e3ce7-957f-4208-a9d0-c176ade1fbc0) 2019-02-27 11:32:56,804 - INFO - 1/5 [40.00%]: m_0-ae38c93f-04bf-477a-809e-3d3de4b02340 request was accepted 2019-02-27 11:32:56,806 - INFO - 1/5 [40.00%]: m_1 requested negmas.sao.SAOMechanism[None] with ['c_3', 'm_1'] (ID ab87f260-e124-4ae4-8f49-65c02e3ae5e7) 2019-02-27 11:32:56,806 - INFO - 1/5 [40.00%]: m_1-99b3c06e-66f7-4413-b0f8-af0919e75071 request was accepted 2019-02-27 11:32:56,807 - INFO - 1/5 [40.00%]: m_2 requested negmas.sao.SAOMechanism[None] with ['c_3', 'm_2'] (ID f0332dd9-8318-4c86-b654-90f9f348620d) 2019-02-27 11:32:56,808 - INFO - 1/5 [40.00%]: m_2-d279992c-cf29-4b38-b046-100294ca6f0c request was accepted 2019-02-27 11:32:56,809 - INFO - 1/5 [40.00%]: m_3 requested negmas.sao.SAOMechanism[None] with ['c_3', 'm_3'] (ID a93dc3f2-a6a1-4384-9f3f-a1eec9fb746f) 2019-02-27 11:32:56,809 - INFO - 1/5 [40.00%]: m_3-e6312be7-fa79-44d2-9ae4-f684919060e5 request was accepted 2019-02-27 11:32:56,811 - INFO - 1/5 [40.00%]: m_4 requested negmas.sao.SAOMechanism[None] with ['c_3', 'm_4'] (ID c4240f91-f3b8-4759-8832-1bdddd0a5f39) 2019-02-27 11:32:56,811 - INFO - 1/5 [40.00%]: m_4-cf4ba00c-de5e-4e64-9f2d-a8bf1c05fb02 request was accepted 2019-02-27 11:32:56,812 - INFO - 1/5 [40.00%]: m_0 requested negmas.sao.SAOMechanism[None] with ['c_4', 'm_0'] (ID d2f603d3-96cd-426d-a73e-7a1ded96e3b2) 2019-02-27 11:32:56,813 - INFO - 1/5 [40.00%]: m_0-ae38c93f-04bf-477a-809e-3d3de4b02340 request was accepted 2019-02-27 11:32:56,814 - INFO - 1/5 [40.00%]: m_1 requested negmas.sao.SAOMechanism[None] with ['c_4', 'm_1'] (ID 1109b522-92b3-4426-839c-60000dbf7f75) 2019-02-27 11:32:56,814 - INFO - 1/5 [40.00%]: m_1-99b3c06e-66f7-4413-b0f8-af0919e75071 request was accepted 2019-02-27 11:32:56,815 - INFO - 1/5 [40.00%]: m_2 requested negmas.sao.SAOMechanism[None] with ['c_4', 'm_2'] (ID 4a1bcfeb-475d-4466-bffd-541db6467942) 2019-02-27 11:32:56,816 - INFO - 1/5 [40.00%]: m_2-d279992c-cf29-4b38-b046-100294ca6f0c request was accepted 2019-02-27 11:32:56,817 - INFO - 1/5 [40.00%]: m_3 requested negmas.sao.SAOMechanism[None] with ['c_4', 'm_3'] (ID 570ab525-6633-43d5-b1fa-a2dba135680f) 2019-02-27 11:32:56,817 - INFO - 1/5 [40.00%]: m_3-e6312be7-fa79-44d2-9ae4-f684919060e5 request was accepted 2019-02-27 11:32:56,818 - INFO - 1/5 [40.00%]: m_4 requested negmas.sao.SAOMechanism[None] with ['c_4', 'm_4'] (ID c084dfce-1892-4afd-b6e1-65df4d9db4f8) 2019-02-27 11:32:56,819 - INFO - 1/5 [40.00%]: m_4-cf4ba00c-de5e-4e64-9f2d-a8bf1c05fb02 request was accepted 2019-02-27 11:32:56,820 - INFO - 1/5 [40.00%]: m_0 requested negmas.sao.SAOMechanism[None] with ['c_0', 'm_0'] (ID f59be41a-607d-4597-9903-963b21852de5) 2019-02-27 11:32:56,821 - INFO - 1/5 [40.00%]: m_0-ae38c93f-04bf-477a-809e-3d3de4b02340 request was accepted 2019-02-27 11:32:56,822 - INFO - 1/5 [40.00%]: m_1 requested negmas.sao.SAOMechanism[None] with ['c_0', 'm_1'] (ID e87f549e-7c09-44c4-b0ed-cd895b93892a) 2019-02-27 11:32:56,822 - INFO - 1/5 [40.00%]: m_1-99b3c06e-66f7-4413-b0f8-af0919e75071 request was accepted 2019-02-27 11:32:56,823 - INFO - 1/5 [40.00%]: m_2 requested negmas.sao.SAOMechanism[None] with ['c_0', 'm_2'] (ID e3c6186c-ee23-426b-888a-c7568da1436a) 2019-02-27 11:32:56,824 - INFO - 1/5 [40.00%]: m_2-d279992c-cf29-4b38-b046-100294ca6f0c request was accepted 2019-02-27 11:32:56,825 - INFO - 1/5 [40.00%]: m_3 requested negmas.sao.SAOMechanism[None] with ['c_0', 'm_3'] (ID 077d0f7d-de1e-4232-93e0-0257c02b50c9) 2019-02-27 11:32:56,826 - INFO - 1/5 [40.00%]: m_3-e6312be7-fa79-44d2-9ae4-f684919060e5 request was accepted 2019-02-27 11:32:56,827 - INFO - 1/5 [40.00%]: m_4 requested negmas.sao.SAOMechanism[None] with ['c_0', 'm_4'] (ID 783c7c89-5fe9-41c3-a1e5-f2fd7c53863c) 2019-02-27 11:32:56,827 - INFO - 1/5 [40.00%]: m_4-cf4ba00c-de5e-4e64-9f2d-a8bf1c05fb02 request was accepted 2019-02-27 11:32:56,828 - INFO - 1/5 [40.00%]: m_0 requested negmas.sao.SAOMechanism[None] with ['c_2', 'm_0'] (ID b368e60e-0440-4507-9d5b-f30a5cebdb24) 2019-02-27 11:32:56,829 - INFO - 1/5 [40.00%]: m_0-ae38c93f-04bf-477a-809e-3d3de4b02340 request was accepted 2019-02-27 11:32:56,830 - INFO - 1/5 [40.00%]: m_1 requested negmas.sao.SAOMechanism[None] with ['c_2', 'm_1'] (ID ec1ecbe8-46f0-4cd0-a244-da285ce14a97) 2019-02-27 11:32:56,830 - INFO - 1/5 [40.00%]: m_1-99b3c06e-66f7-4413-b0f8-af0919e75071 request was accepted 2019-02-27 11:32:56,831 - INFO - 1/5 [40.00%]: m_2 requested negmas.sao.SAOMechanism[None] with ['c_2', 'm_2'] (ID 6fd72ad3-e511-44e5-908e-6af3c3e33adc) 2019-02-27 11:32:56,832 - INFO - 1/5 [40.00%]: m_2-d279992c-cf29-4b38-b046-100294ca6f0c request was accepted 2019-02-27 11:32:56,833 - INFO - 1/5 [40.00%]: m_3 requested negmas.sao.SAOMechanism[None] with ['c_2', 'm_3'] (ID 80a5082c-bb6b-4523-8e9e-8b35f2e1f8cb) 2019-02-27 11:32:56,833 - INFO - 1/5 [40.00%]: m_3-e6312be7-fa79-44d2-9ae4-f684919060e5 request was accepted 2019-02-27 11:32:56,834 - INFO - 1/5 [40.00%]: m_4 requested negmas.sao.SAOMechanism[None] with ['c_2', 'm_4'] (ID c2f5c841-55cc-474f-951f-c408b9efbc43) 2019-02-27 11:32:56,835 - INFO - 1/5 [40.00%]: m_4-cf4ba00c-de5e-4e64-9f2d-a8bf1c05fb02 request was accepted 2019-02-27 11:32:56,836 - INFO - 1/5 [40.00%]: m_0 requested negmas.sao.SAOMechanism[None] with ['c_1', 'm_0'] (ID 20625dbb-586b-4b73-89f6-bece5480ab2e) 2019-02-27 11:32:56,837 - INFO - 1/5 [40.00%]: m_0-ae38c93f-04bf-477a-809e-3d3de4b02340 request was accepted 2019-02-27 11:32:56,838 - INFO - 1/5 [40.00%]: m_1 requested negmas.sao.SAOMechanism[None] with ['c_1', 'm_1'] (ID e4d23044-fd4f-4fd2-882f-7745a66c28b2) 2019-02-27 11:32:56,838 - INFO - 1/5 [40.00%]: m_1-99b3c06e-66f7-4413-b0f8-af0919e75071 request was accepted 2019-02-27 11:32:56,839 - INFO - 1/5 [40.00%]: m_2 requested negmas.sao.SAOMechanism[None] with ['c_1', 'm_2'] (ID fc059906-1de6-40ef-80eb-c8b6f981d870) 2019-02-27 11:32:56,840 - INFO - 1/5 [40.00%]: m_2-d279992c-cf29-4b38-b046-100294ca6f0c request was accepted 2019-02-27 11:32:56,841 - INFO - 1/5 [40.00%]: m_3 requested negmas.sao.SAOMechanism[None] with ['c_1', 'm_3'] (ID ae6560ff-e0b4-42bd-95e2-bc0496d8f67e) 2019-02-27 11:32:56,842 - INFO - 1/5 [40.00%]: m_3-e6312be7-fa79-44d2-9ae4-f684919060e5 request was accepted 2019-02-27 11:32:56,843 - INFO - 1/5 [40.00%]: m_4 requested negmas.sao.SAOMechanism[None] with ['c_1', 'm_4'] (ID 60ab2bf6-8ec8-432a-97ed-f1bb38066750) 2019-02-27 11:32:56,843 - INFO - 1/5 [40.00%]: m_4-cf4ba00c-de5e-4e64-9f2d-a8bf1c05fb02 request was accepted 2019-02-27 11:32:56,843 - INFO - 1/5 [40.00%]: Executing c_2-d804b0d2-8eb4-4afa-bb16-d2e4c8ebcdcb, m_0-ae38c93f-04bf-477a-809e-3d3de4b02340 agreed on {'time': 1, 'quantity': 4, 'unit_price': 0.5} 2019-02-27 11:32:56,844 - DEBUG - 1/5 [40.00%]: Moved 4 units of p0 from m_0 to c_2 for 2.0 dollars 2019-02-27 11:32:56,844 - INFO - 1/5 [40.00%]: Executing c_4-81d58b26-eabf-43d9-b58f-21b367075ff6, m_4-cf4ba00c-de5e-4e64-9f2d-a8bf1c05fb02 agreed on {'time': 1, 'quantity': 4, 'unit_price': 0.5} 2019-02-27 11:32:56,844 - DEBUG - 1/5 [40.00%]: Moved 4 units of p0 from m_4 to c_4 for 2.0 dollars 2019-02-27 11:32:56,844 - INFO - 1/5 [40.00%]: Executing c_3-a48f2b83-a7b3-49ab-a0fb-729d4ae18c2d, m_2-d279992c-cf29-4b38-b046-100294ca6f0c agreed on {'time': 1, 'quantity': 3, 'unit_price': 0.5} 2019-02-27 11:32:56,844 - DEBUG - 1/5 [40.00%]: Moved 3 units of p0 from m_2 to c_3 for 1.5 dollars 2019-02-27 11:32:56,844 - INFO - 1/5 [40.00%]: Executing c_0-2e50318f-4595-4018-9486-4549326453e7, m_4-cf4ba00c-de5e-4e64-9f2d-a8bf1c05fb02 agreed on {'time': 1, 'quantity': 4, 'unit_price': 0.5} 2019-02-27 11:32:56,844 - DEBUG - 1/5 [40.00%]: Moved 4 units of p0 from m_4 to c_0 for 2.0 dollars 2019-02-27 11:32:56,844 - INFO - 1/5 [40.00%]: Executing c_1-3dbd2a2a-0c36-47bf-96c9-9754f7352219, m_3-e6312be7-fa79-44d2-9ae4-f684919060e5 agreed on {'time': 1, 'quantity': 4, 'unit_price': 0.5} 2019-02-27 11:32:56,844 - DEBUG - 1/5 [40.00%]: Moved 4 units of p0 from m_3 to c_1 for 2.0 dollars 2019-02-27 11:32:56,844 - DEBUG - 1/5 [40.00%]: Factory e99d9a30-972a-4954-a82a-dd7afdef43ad: money=-2.0, storage={}, loans=0.0 2019-02-27 11:32:56,844 - DEBUG - 1/5 [40.00%]: Factory c522c9c1-11e2-41e3-9250-b27a9522444b: money=-2.0, storage={}, loans=0.0 2019-02-27 11:32:56,844 - DEBUG - 1/5 [40.00%]: Factory ff2a5bf9-bfbd-48a1-b5e7-c4dadc046f96: money=-2.0, storage={}, loans=0.0 2019-02-27 11:32:56,844 - DEBUG - 1/5 [40.00%]: Factory 5e7733e2-db9b-4765-a33a-7e9fe2248fc5: money=-1.5, storage={}, loans=0.0 2019-02-27 11:32:56,844 - DEBUG - 1/5 [40.00%]: Factory 852400c0-e73c-4484-91ec-ba8a9a901a8d: money=-2.0, storage={}, loans=0.0 2019-02-27 11:32:56,844 - DEBUG - 1/5 [40.00%]: Factory e7a5def1-059e-49c4-aad9-e82c624fd8c4: money=2.0, storage={0: -4}, loans=0.0 2019-02-27 11:32:56,844 - DEBUG - 1/5 [40.00%]: Factory fdd8ea88-1272-4965-8317-13385e2d18dc: money=0.0, storage={}, loans=0.0 2019-02-27 11:32:56,844 - DEBUG - 1/5 [40.00%]: Factory af03e704-f500-48dc-b1f3-45d5d3cf60f3: money=1.5, storage={0: -3}, loans=0.0 2019-02-27 11:32:56,844 - DEBUG - 1/5 [40.00%]: Factory bcda6d74-adb6-450c-a9e4-06756aaeb456: money=2.0, storage={0: -4}, loans=0.0 2019-02-27 11:32:56,845 - DEBUG - 1/5 [40.00%]: Factory f621f922-b18a-4edb-b071-ef577b17d239: money=4.0, storage={0: -8}, loans=0.0 2019-02-27 11:32:56,845 - INFO - 2/5 [60.00%]: 25 Negotiations/4 _entities 2019-02-27 11:32:57,068 - DEBUG - 2/5 [60.00%]: Contract [signed]: ['c_0', 'm_2'] > {'time': 3, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_0-2e50318f-4595-4018-9486-4549326453e7: buy 0 (t: 3, u: (0, 2.0), q: (1, 4))', 'partners': "['c_0-2e50318f-4595-4018-9486-4549326453e7', 'm_2-d279992c-cf29-4b38-b046-100294ca6f0c']", 'seller': 'm_2-d279992c-cf29-4b38-b046-100294ca6f0c', 'buyer': 'c_0-2e50318f-4595-4018-9486-4549326453e7'} 2019-02-27 11:32:57,069 - DEBUG - 2/5 [60.00%]: Contract [cancelled]: ['c_0', 'm_0'] > {'time': 3, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_0-2e50318f-4595-4018-9486-4549326453e7: buy 0 (t: 3, u: (0, 2.0), q: (1, 4))', 'partners': "['c_0-2e50318f-4595-4018-9486-4549326453e7', 'm_0-ae38c93f-04bf-477a-809e-3d3de4b02340']", 'seller': 'm_0-ae38c93f-04bf-477a-809e-3d3de4b02340', 'buyer': 'c_0-2e50318f-4595-4018-9486-4549326453e7'} 2019-02-27 11:32:57,069 - DEBUG - 2/5 [60.00%]: Contract [signed]: ['c_1', 'm_2'] > {'time': 3, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_1-3dbd2a2a-0c36-47bf-96c9-9754f7352219: buy 0 (t: 3, u: (0, 2.0), q: (1, 4))', 'partners': "['c_1-3dbd2a2a-0c36-47bf-96c9-9754f7352219', 'm_2-d279992c-cf29-4b38-b046-100294ca6f0c']", 'seller': 'm_2-d279992c-cf29-4b38-b046-100294ca6f0c', 'buyer': 'c_1-3dbd2a2a-0c36-47bf-96c9-9754f7352219'} 2019-02-27 11:32:57,069 - DEBUG - 2/5 [60.00%]: Contract [cancelled]: ['c_0', 'm_3'] > {'time': 3, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_0-2e50318f-4595-4018-9486-4549326453e7: buy 0 (t: 3, u: (0, 2.0), q: (1, 4))', 'partners': "['c_0-2e50318f-4595-4018-9486-4549326453e7', 'm_3-e6312be7-fa79-44d2-9ae4-f684919060e5']", 'seller': 'm_3-e6312be7-fa79-44d2-9ae4-f684919060e5', 'buyer': 'c_0-2e50318f-4595-4018-9486-4549326453e7'} 2019-02-27 11:32:57,070 - DEBUG - 2/5 [60.00%]: Contract [signed]: ['c_4', 'm_2'] > {'time': 3, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_4-81d58b26-eabf-43d9-b58f-21b367075ff6: buy 0 (t: 3, u: (0, 2.0), q: (1, 3))', 'partners': "['c_4-81d58b26-eabf-43d9-b58f-21b367075ff6', 'm_2-d279992c-cf29-4b38-b046-100294ca6f0c']", 'seller': 'm_2-d279992c-cf29-4b38-b046-100294ca6f0c', 'buyer': 'c_4-81d58b26-eabf-43d9-b58f-21b367075ff6'} 2019-02-27 11:32:57,070 - DEBUG - 2/5 [60.00%]: Contract [signed]: ['c_3', 'm_1'] > {'time': 3, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_3-a48f2b83-a7b3-49ab-a0fb-729d4ae18c2d: buy 0 (t: 3, u: (0, 2.0), q: (1, 4))', 'partners': "['c_3-a48f2b83-a7b3-49ab-a0fb-729d4ae18c2d', 'm_1-99b3c06e-66f7-4413-b0f8-af0919e75071']", 'seller': 'm_1-99b3c06e-66f7-4413-b0f8-af0919e75071', 'buyer': 'c_3-a48f2b83-a7b3-49ab-a0fb-729d4ae18c2d'} 2019-02-27 11:32:57,070 - DEBUG - 2/5 [60.00%]: Contract [signed]: ['c_2', 'm_3'] > {'time': 3, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_2-d804b0d2-8eb4-4afa-bb16-d2e4c8ebcdcb: buy 0 (t: 3, u: (0, 2.0), q: (1, 3))', 'partners': "['c_2-d804b0d2-8eb4-4afa-bb16-d2e4c8ebcdcb', 'm_3-e6312be7-fa79-44d2-9ae4-f684919060e5']", 'seller': 'm_3-e6312be7-fa79-44d2-9ae4-f684919060e5', 'buyer': 'c_2-d804b0d2-8eb4-4afa-bb16-d2e4c8ebcdcb'} 2019-02-27 11:32:57,071 - DEBUG - 2/5 [60.00%]: Contract [cancelled]: ['c_4', 'm_3'] > {'time': 3, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_4-81d58b26-eabf-43d9-b58f-21b367075ff6: buy 0 (t: 3, u: (0, 2.0), q: (1, 3))', 'partners': "['c_4-81d58b26-eabf-43d9-b58f-21b367075ff6', 'm_3-e6312be7-fa79-44d2-9ae4-f684919060e5']", 'seller': 'm_3-e6312be7-fa79-44d2-9ae4-f684919060e5', 'buyer': 'c_4-81d58b26-eabf-43d9-b58f-21b367075ff6'} 2019-02-27 11:32:57,071 - DEBUG - 2/5 [60.00%]: Contract [cancelled]: ['c_1', 'm_3'] > {'time': 3, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_1-3dbd2a2a-0c36-47bf-96c9-9754f7352219: buy 0 (t: 3, u: (0, 2.0), q: (1, 4))', 'partners': "['c_1-3dbd2a2a-0c36-47bf-96c9-9754f7352219', 'm_3-e6312be7-fa79-44d2-9ae4-f684919060e5']", 'seller': 'm_3-e6312be7-fa79-44d2-9ae4-f684919060e5', 'buyer': 'c_1-3dbd2a2a-0c36-47bf-96c9-9754f7352219'} 2019-02-27 11:32:57,071 - DEBUG - 2/5 [60.00%]: Contract [cancelled]: ['c_3', 'm_0'] > {'time': 3, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_3-a48f2b83-a7b3-49ab-a0fb-729d4ae18c2d: buy 0 (t: 3, u: (0, 2.0), q: (1, 4))', 'partners': "['c_3-a48f2b83-a7b3-49ab-a0fb-729d4ae18c2d', 'm_0-ae38c93f-04bf-477a-809e-3d3de4b02340']", 'seller': 'm_0-ae38c93f-04bf-477a-809e-3d3de4b02340', 'buyer': 'c_3-a48f2b83-a7b3-49ab-a0fb-729d4ae18c2d'} 2019-02-27 11:32:57,072 - DEBUG - 2/5 [60.00%]: Contract [cancelled]: ['c_2', 'm_0'] > {'time': 3, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_2-d804b0d2-8eb4-4afa-bb16-d2e4c8ebcdcb: buy 0 (t: 3, u: (0, 2.0), q: (1, 3))', 'partners': "['c_2-d804b0d2-8eb4-4afa-bb16-d2e4c8ebcdcb', 'm_0-ae38c93f-04bf-477a-809e-3d3de4b02340']", 'seller': 'm_0-ae38c93f-04bf-477a-809e-3d3de4b02340', 'buyer': 'c_2-d804b0d2-8eb4-4afa-bb16-d2e4c8ebcdcb'} 2019-02-27 11:32:57,072 - DEBUG - 2/5 [60.00%]: Contract [cancelled]: ['c_1', 'm_4'] > {'time': 3, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_1-3dbd2a2a-0c36-47bf-96c9-9754f7352219: buy 0 (t: 3, u: (0, 2.0), q: (1, 4))', 'partners': "['c_1-3dbd2a2a-0c36-47bf-96c9-9754f7352219', 'm_4-cf4ba00c-de5e-4e64-9f2d-a8bf1c05fb02']", 'seller': 'm_4-cf4ba00c-de5e-4e64-9f2d-a8bf1c05fb02', 'buyer': 'c_1-3dbd2a2a-0c36-47bf-96c9-9754f7352219'} 2019-02-27 11:32:57,073 - DEBUG - 2/5 [60.00%]: Contract [cancelled]: ['c_1', 'm_1'] > {'time': 3, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_1-3dbd2a2a-0c36-47bf-96c9-9754f7352219: buy 0 (t: 3, u: (0, 2.0), q: (1, 4))', 'partners': "['c_1-3dbd2a2a-0c36-47bf-96c9-9754f7352219', 'm_1-99b3c06e-66f7-4413-b0f8-af0919e75071']", 'seller': 'm_1-99b3c06e-66f7-4413-b0f8-af0919e75071', 'buyer': 'c_1-3dbd2a2a-0c36-47bf-96c9-9754f7352219'} 2019-02-27 11:32:57,073 - DEBUG - 2/5 [60.00%]: Contract [cancelled]: ['c_0', 'm_4'] > {'time': 3, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_0-2e50318f-4595-4018-9486-4549326453e7: buy 0 (t: 3, u: (0, 2.0), q: (1, 4))', 'partners': "['c_0-2e50318f-4595-4018-9486-4549326453e7', 'm_4-cf4ba00c-de5e-4e64-9f2d-a8bf1c05fb02']", 'seller': 'm_4-cf4ba00c-de5e-4e64-9f2d-a8bf1c05fb02', 'buyer': 'c_0-2e50318f-4595-4018-9486-4549326453e7'} 2019-02-27 11:32:57,073 - DEBUG - 2/5 [60.00%]: Contract [cancelled]: ['c_3', 'm_2'] > {'time': 3, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_3-a48f2b83-a7b3-49ab-a0fb-729d4ae18c2d: buy 0 (t: 3, u: (0, 2.0), q: (1, 4))', 'partners': "['c_3-a48f2b83-a7b3-49ab-a0fb-729d4ae18c2d', 'm_2-d279992c-cf29-4b38-b046-100294ca6f0c']", 'seller': 'm_2-d279992c-cf29-4b38-b046-100294ca6f0c', 'buyer': 'c_3-a48f2b83-a7b3-49ab-a0fb-729d4ae18c2d'} 2019-02-27 11:32:57,074 - DEBUG - 2/5 [60.00%]: Contract [cancelled]: ['c_4', 'm_4'] > {'time': 3, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_4-81d58b26-eabf-43d9-b58f-21b367075ff6: buy 0 (t: 3, u: (0, 2.0), q: (1, 3))', 'partners': "['c_4-81d58b26-eabf-43d9-b58f-21b367075ff6', 'm_4-cf4ba00c-de5e-4e64-9f2d-a8bf1c05fb02']", 'seller': 'm_4-cf4ba00c-de5e-4e64-9f2d-a8bf1c05fb02', 'buyer': 'c_4-81d58b26-eabf-43d9-b58f-21b367075ff6'} 2019-02-27 11:32:57,074 - DEBUG - 2/5 [60.00%]: Contract [cancelled]: ['c_3', 'm_4'] > {'time': 3, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_3-a48f2b83-a7b3-49ab-a0fb-729d4ae18c2d: buy 0 (t: 3, u: (0, 2.0), q: (1, 4))', 'partners': "['c_3-a48f2b83-a7b3-49ab-a0fb-729d4ae18c2d', 'm_4-cf4ba00c-de5e-4e64-9f2d-a8bf1c05fb02']", 'seller': 'm_4-cf4ba00c-de5e-4e64-9f2d-a8bf1c05fb02', 'buyer': 'c_3-a48f2b83-a7b3-49ab-a0fb-729d4ae18c2d'} 2019-02-27 11:32:57,074 - DEBUG - 2/5 [60.00%]: Contract [cancelled]: ['c_4', 'm_0'] > {'time': 3, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_4-81d58b26-eabf-43d9-b58f-21b367075ff6: buy 0 (t: 3, u: (0, 2.0), q: (1, 3))', 'partners': "['c_4-81d58b26-eabf-43d9-b58f-21b367075ff6', 'm_0-ae38c93f-04bf-477a-809e-3d3de4b02340']", 'seller': 'm_0-ae38c93f-04bf-477a-809e-3d3de4b02340', 'buyer': 'c_4-81d58b26-eabf-43d9-b58f-21b367075ff6'} 2019-02-27 11:32:57,074 - DEBUG - 2/5 [60.00%]: Contract [cancelled]: ['c_2', 'm_2'] > {'time': 3, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_2-d804b0d2-8eb4-4afa-bb16-d2e4c8ebcdcb: buy 0 (t: 3, u: (0, 2.0), q: (1, 3))', 'partners': "['c_2-d804b0d2-8eb4-4afa-bb16-d2e4c8ebcdcb', 'm_2-d279992c-cf29-4b38-b046-100294ca6f0c']", 'seller': 'm_2-d279992c-cf29-4b38-b046-100294ca6f0c', 'buyer': 'c_2-d804b0d2-8eb4-4afa-bb16-d2e4c8ebcdcb'} 2019-02-27 11:32:57,075 - DEBUG - 2/5 [60.00%]: Contract [cancelled]: ['c_1', 'm_0'] > {'time': 3, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_1-3dbd2a2a-0c36-47bf-96c9-9754f7352219: buy 0 (t: 3, u: (0, 2.0), q: (1, 4))', 'partners': "['c_1-3dbd2a2a-0c36-47bf-96c9-9754f7352219', 'm_0-ae38c93f-04bf-477a-809e-3d3de4b02340']", 'seller': 'm_0-ae38c93f-04bf-477a-809e-3d3de4b02340', 'buyer': 'c_1-3dbd2a2a-0c36-47bf-96c9-9754f7352219'} 2019-02-27 11:32:57,075 - DEBUG - 2/5 [60.00%]: Contract [cancelled]: ['c_4', 'm_1'] > {'time': 3, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_4-81d58b26-eabf-43d9-b58f-21b367075ff6: buy 0 (t: 3, u: (0, 2.0), q: (1, 3))', 'partners': "['c_4-81d58b26-eabf-43d9-b58f-21b367075ff6', 'm_1-99b3c06e-66f7-4413-b0f8-af0919e75071']", 'seller': 'm_1-99b3c06e-66f7-4413-b0f8-af0919e75071', 'buyer': 'c_4-81d58b26-eabf-43d9-b58f-21b367075ff6'} 2019-02-27 11:32:57,075 - DEBUG - 2/5 [60.00%]: Contract [cancelled]: ['c_2', 'm_1'] > {'time': 3, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_2-d804b0d2-8eb4-4afa-bb16-d2e4c8ebcdcb: buy 0 (t: 3, u: (0, 2.0), q: (1, 3))', 'partners': "['c_2-d804b0d2-8eb4-4afa-bb16-d2e4c8ebcdcb', 'm_1-99b3c06e-66f7-4413-b0f8-af0919e75071']", 'seller': 'm_1-99b3c06e-66f7-4413-b0f8-af0919e75071', 'buyer': 'c_2-d804b0d2-8eb4-4afa-bb16-d2e4c8ebcdcb'} 2019-02-27 11:32:57,076 - DEBUG - 2/5 [60.00%]: Contract [cancelled]: ['c_2', 'm_4'] > {'time': 3, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_2-d804b0d2-8eb4-4afa-bb16-d2e4c8ebcdcb: buy 0 (t: 3, u: (0, 2.0), q: (1, 3))', 'partners': "['c_2-d804b0d2-8eb4-4afa-bb16-d2e4c8ebcdcb', 'm_4-cf4ba00c-de5e-4e64-9f2d-a8bf1c05fb02']", 'seller': 'm_4-cf4ba00c-de5e-4e64-9f2d-a8bf1c05fb02', 'buyer': 'c_2-d804b0d2-8eb4-4afa-bb16-d2e4c8ebcdcb'} 2019-02-27 11:32:57,076 - DEBUG - 2/5 [60.00%]: Contract [cancelled]: ['c_3', 'm_3'] > {'time': 3, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_3-a48f2b83-a7b3-49ab-a0fb-729d4ae18c2d: buy 0 (t: 3, u: (0, 2.0), q: (1, 4))', 'partners': "['c_3-a48f2b83-a7b3-49ab-a0fb-729d4ae18c2d', 'm_3-e6312be7-fa79-44d2-9ae4-f684919060e5']", 'seller': 'm_3-e6312be7-fa79-44d2-9ae4-f684919060e5', 'buyer': 'c_3-a48f2b83-a7b3-49ab-a0fb-729d4ae18c2d'} 2019-02-27 11:32:57,076 - DEBUG - 2/5 [60.00%]: Contract [cancelled]: ['c_0', 'm_1'] > {'time': 3, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_0-2e50318f-4595-4018-9486-4549326453e7: buy 0 (t: 3, u: (0, 2.0), q: (1, 4))', 'partners': "['c_0-2e50318f-4595-4018-9486-4549326453e7', 'm_1-99b3c06e-66f7-4413-b0f8-af0919e75071']", 'seller': 'm_1-99b3c06e-66f7-4413-b0f8-af0919e75071', 'buyer': 'c_0-2e50318f-4595-4018-9486-4549326453e7'} 2019-02-27 11:32:57,077 - INFO - 2/5 [60.00%]: m_0 requested negmas.sao.SAOMechanism[None] with ['c_3', 'm_0'] (ID 0850ac9e-8571-43fa-a0f4-04193a14f1fb) 2019-02-27 11:32:57,078 - INFO - 2/5 [60.00%]: m_0-ae38c93f-04bf-477a-809e-3d3de4b02340 request was accepted 2019-02-27 11:32:57,079 - INFO - 2/5 [60.00%]: m_1 requested negmas.sao.SAOMechanism[None] with ['c_3', 'm_1'] (ID 3ede8eb6-c6dc-4e74-93bc-892ecc16cfec) 2019-02-27 11:32:57,080 - INFO - 2/5 [60.00%]: m_1-99b3c06e-66f7-4413-b0f8-af0919e75071 request was accepted 2019-02-27 11:32:57,081 - INFO - 2/5 [60.00%]: m_2 requested negmas.sao.SAOMechanism[None] with ['c_3', 'm_2'] (ID 1d236773-b2c0-4ccb-bc49-34d3fdbfb19f) 2019-02-27 11:32:57,081 - INFO - 2/5 [60.00%]: m_2-d279992c-cf29-4b38-b046-100294ca6f0c request was accepted 2019-02-27 11:32:57,082 - INFO - 2/5 [60.00%]: m_3 requested negmas.sao.SAOMechanism[None] with ['c_3', 'm_3'] (ID 76af2581-043f-49fc-8ee8-7013d79de4ef) 2019-02-27 11:32:57,083 - INFO - 2/5 [60.00%]: m_3-e6312be7-fa79-44d2-9ae4-f684919060e5 request was accepted 2019-02-27 11:32:57,084 - INFO - 2/5 [60.00%]: m_4 requested negmas.sao.SAOMechanism[None] with ['c_3', 'm_4'] (ID a06f981b-0017-48b7-90c8-3f343489cc40) 2019-02-27 11:32:57,085 - INFO - 2/5 [60.00%]: m_4-cf4ba00c-de5e-4e64-9f2d-a8bf1c05fb02 request was accepted 2019-02-27 11:32:57,086 - INFO - 2/5 [60.00%]: m_0 requested negmas.sao.SAOMechanism[None] with ['c_4', 'm_0'] (ID f4853f03-ae8a-42eb-95b8-bd310e465a94) 2019-02-27 11:32:57,086 - INFO - 2/5 [60.00%]: m_0-ae38c93f-04bf-477a-809e-3d3de4b02340 request was accepted 2019-02-27 11:32:57,087 - INFO - 2/5 [60.00%]: m_1 requested negmas.sao.SAOMechanism[None] with ['c_4', 'm_1'] (ID fbf16469-7734-40a5-9171-94325c2e2a6f) 2019-02-27 11:32:57,088 - INFO - 2/5 [60.00%]: m_1-99b3c06e-66f7-4413-b0f8-af0919e75071 request was accepted 2019-02-27 11:32:57,091 - INFO - 2/5 [60.00%]: m_2 requested negmas.sao.SAOMechanism[None] with ['c_4', 'm_2'] (ID d21b24b5-ae86-4c76-bd0b-a90ea2aeffbe) 2019-02-27 11:32:57,092 - INFO - 2/5 [60.00%]: m_2-d279992c-cf29-4b38-b046-100294ca6f0c request was accepted 2019-02-27 11:32:57,093 - INFO - 2/5 [60.00%]: m_3 requested negmas.sao.SAOMechanism[None] with ['c_4', 'm_3'] (ID 183a60c5-86cb-4a56-ac9d-f5c75f6646a7) 2019-02-27 11:32:57,093 - INFO - 2/5 [60.00%]: m_3-e6312be7-fa79-44d2-9ae4-f684919060e5 request was accepted 2019-02-27 11:32:57,094 - INFO - 2/5 [60.00%]: m_4 requested negmas.sao.SAOMechanism[None] with ['c_4', 'm_4'] (ID 81fd446b-f514-4da2-8a6e-04dba67bf3ab) 2019-02-27 11:32:57,095 - INFO - 2/5 [60.00%]: m_4-cf4ba00c-de5e-4e64-9f2d-a8bf1c05fb02 request was accepted 2019-02-27 11:32:57,096 - INFO - 2/5 [60.00%]: m_0 requested negmas.sao.SAOMechanism[None] with ['c_0', 'm_0'] (ID ac9d47b0-7d3c-489b-99c1-5a27f173f612) 2019-02-27 11:32:57,097 - INFO - 2/5 [60.00%]: m_0-ae38c93f-04bf-477a-809e-3d3de4b02340 request was accepted 2019-02-27 11:32:57,098 - INFO - 2/5 [60.00%]: m_1 requested negmas.sao.SAOMechanism[None] with ['c_0', 'm_1'] (ID bbc6b4ee-82b2-4060-9de3-73153e76ec0b) 2019-02-27 11:32:57,099 - INFO - 2/5 [60.00%]: m_1-99b3c06e-66f7-4413-b0f8-af0919e75071 request was accepted 2019-02-27 11:32:57,101 - INFO - 2/5 [60.00%]: m_2 requested negmas.sao.SAOMechanism[None] with ['c_0', 'm_2'] (ID d3ad91c2-f895-4391-9f7e-1b4b4247a912) 2019-02-27 11:32:57,102 - INFO - 2/5 [60.00%]: m_2-d279992c-cf29-4b38-b046-100294ca6f0c request was accepted 2019-02-27 11:32:57,103 - INFO - 2/5 [60.00%]: m_3 requested negmas.sao.SAOMechanism[None] with ['c_0', 'm_3'] (ID 971c4950-92c2-47be-8be7-92fe7d91a970) 2019-02-27 11:32:57,104 - INFO - 2/5 [60.00%]: m_3-e6312be7-fa79-44d2-9ae4-f684919060e5 request was accepted 2019-02-27 11:32:57,105 - INFO - 2/5 [60.00%]: m_4 requested negmas.sao.SAOMechanism[None] with ['c_0', 'm_4'] (ID 62516311-d975-4460-8e51-3ed1d062f860) 2019-02-27 11:32:57,105 - INFO - 2/5 [60.00%]: m_4-cf4ba00c-de5e-4e64-9f2d-a8bf1c05fb02 request was accepted 2019-02-27 11:32:57,107 - INFO - 2/5 [60.00%]: m_0 requested negmas.sao.SAOMechanism[None] with ['c_2', 'm_0'] (ID 8d941d7e-771a-4554-84c9-38b2f69930dc) 2019-02-27 11:32:57,107 - INFO - 2/5 [60.00%]: m_0-ae38c93f-04bf-477a-809e-3d3de4b02340 request was accepted 2019-02-27 11:32:57,108 - INFO - 2/5 [60.00%]: m_1 requested negmas.sao.SAOMechanism[None] with ['c_2', 'm_1'] (ID 03af9d87-b35d-4316-9db4-af1ccb9bdb74) 2019-02-27 11:32:57,109 - INFO - 2/5 [60.00%]: m_1-99b3c06e-66f7-4413-b0f8-af0919e75071 request was accepted 2019-02-27 11:32:57,109 - INFO - 2/5 [60.00%]: m_2 requested negmas.sao.SAOMechanism[None] with ['c_2', 'm_2'] (ID f721adb6-7953-4131-b323-04be4c7328ad) 2019-02-27 11:32:57,110 - INFO - 2/5 [60.00%]: m_2-d279992c-cf29-4b38-b046-100294ca6f0c request was accepted 2019-02-27 11:32:57,111 - INFO - 2/5 [60.00%]: m_3 requested negmas.sao.SAOMechanism[None] with ['c_2', 'm_3'] (ID 5c7dd954-9815-4cd2-8e0c-f1cacf06fb86) 2019-02-27 11:32:57,112 - INFO - 2/5 [60.00%]: m_3-e6312be7-fa79-44d2-9ae4-f684919060e5 request was accepted 2019-02-27 11:32:57,112 - INFO - 2/5 [60.00%]: m_4 requested negmas.sao.SAOMechanism[None] with ['c_2', 'm_4'] (ID 411c709e-5d75-4d4d-9ee2-c10eed52437c) 2019-02-27 11:32:57,113 - INFO - 2/5 [60.00%]: m_4-cf4ba00c-de5e-4e64-9f2d-a8bf1c05fb02 request was accepted 2019-02-27 11:32:57,114 - INFO - 2/5 [60.00%]: m_0 requested negmas.sao.SAOMechanism[None] with ['c_1', 'm_0'] (ID c4ed8e4f-8a0c-4bb5-a72c-90d4a871982d) 2019-02-27 11:32:57,115 - INFO - 2/5 [60.00%]: m_0-ae38c93f-04bf-477a-809e-3d3de4b02340 request was accepted 2019-02-27 11:32:57,115 - INFO - 2/5 [60.00%]: m_1 requested negmas.sao.SAOMechanism[None] with ['c_1', 'm_1'] (ID 79979267-545f-4445-95fe-c3930e7dfb7d) 2019-02-27 11:32:57,116 - INFO - 2/5 [60.00%]: m_1-99b3c06e-66f7-4413-b0f8-af0919e75071 request was accepted 2019-02-27 11:32:57,117 - INFO - 2/5 [60.00%]: m_2 requested negmas.sao.SAOMechanism[None] with ['c_1', 'm_2'] (ID e1620c6b-52e7-4409-adfc-01625314b5e6) 2019-02-27 11:32:57,118 - INFO - 2/5 [60.00%]: m_2-d279992c-cf29-4b38-b046-100294ca6f0c request was accepted 2019-02-27 11:32:57,119 - INFO - 2/5 [60.00%]: m_3 requested negmas.sao.SAOMechanism[None] with ['c_1', 'm_3'] (ID 47c682c0-4793-4308-b461-26a09e5861d1) 2019-02-27 11:32:57,119 - INFO - 2/5 [60.00%]: m_3-e6312be7-fa79-44d2-9ae4-f684919060e5 request was accepted 2019-02-27 11:32:57,120 - INFO - 2/5 [60.00%]: m_4 requested negmas.sao.SAOMechanism[None] with ['c_1', 'm_4'] (ID 578f2198-91c1-4ec9-96b5-9430e3c3fbe7) 2019-02-27 11:32:57,121 - INFO - 2/5 [60.00%]: m_4-cf4ba00c-de5e-4e64-9f2d-a8bf1c05fb02 request was accepted 2019-02-27 11:32:57,121 - INFO - 2/5 [60.00%]: Executing c_4-81d58b26-eabf-43d9-b58f-21b367075ff6, m_1-99b3c06e-66f7-4413-b0f8-af0919e75071 agreed on {'time': 2, 'quantity': 3, 'unit_price': 0.5} 2019-02-27 11:32:57,121 - DEBUG - 2/5 [60.00%]: Moved 3 units of p0 from m_1 to c_4 for 1.5 dollars 2019-02-27 11:32:57,121 - INFO - 2/5 [60.00%]: Executing c_0-2e50318f-4595-4018-9486-4549326453e7, m_3-e6312be7-fa79-44d2-9ae4-f684919060e5 agreed on {'time': 2, 'quantity': 3, 'unit_price': 0.5} 2019-02-27 11:32:57,121 - DEBUG - 2/5 [60.00%]: Moved 3 units of p0 from m_3 to c_0 for 1.5 dollars 2019-02-27 11:32:57,121 - INFO - 2/5 [60.00%]: Executing c_3-a48f2b83-a7b3-49ab-a0fb-729d4ae18c2d, m_0-ae38c93f-04bf-477a-809e-3d3de4b02340 agreed on {'time': 2, 'quantity': 4, 'unit_price': 0.5} 2019-02-27 11:32:57,121 - DEBUG - 2/5 [60.00%]: Moved 4 units of p0 from m_0 to c_3 for 2.0 dollars 2019-02-27 11:32:57,121 - INFO - 2/5 [60.00%]: Executing c_2-d804b0d2-8eb4-4afa-bb16-d2e4c8ebcdcb, m_2-d279992c-cf29-4b38-b046-100294ca6f0c agreed on {'time': 2, 'quantity': 3, 'unit_price': 0.5} 2019-02-27 11:32:57,121 - DEBUG - 2/5 [60.00%]: Moved 3 units of p0 from m_2 to c_2 for 1.5 dollars 2019-02-27 11:32:57,121 - INFO - 2/5 [60.00%]: Executing c_1-3dbd2a2a-0c36-47bf-96c9-9754f7352219, m_4-cf4ba00c-de5e-4e64-9f2d-a8bf1c05fb02 agreed on {'time': 2, 'quantity': 4, 'unit_price': 0.5} 2019-02-27 11:32:57,121 - DEBUG - 2/5 [60.00%]: Moved 4 units of p0 from m_4 to c_1 for 2.0 dollars 2019-02-27 11:32:57,121 - DEBUG - 2/5 [60.00%]: Factory e99d9a30-972a-4954-a82a-dd7afdef43ad: money=-3.5, storage={}, loans=0.0 2019-02-27 11:32:57,122 - DEBUG - 2/5 [60.00%]: Factory c522c9c1-11e2-41e3-9250-b27a9522444b: money=-4.0, storage={}, loans=0.0 2019-02-27 11:32:57,122 - DEBUG - 2/5 [60.00%]: Factory ff2a5bf9-bfbd-48a1-b5e7-c4dadc046f96: money=-3.5, storage={}, loans=0.0 2019-02-27 11:32:57,122 - DEBUG - 2/5 [60.00%]: Factory 5e7733e2-db9b-4765-a33a-7e9fe2248fc5: money=-3.5, storage={}, loans=0.0 2019-02-27 11:32:57,122 - DEBUG - 2/5 [60.00%]: Factory 852400c0-e73c-4484-91ec-ba8a9a901a8d: money=-3.5, storage={}, loans=0.0 2019-02-27 11:32:57,122 - DEBUG - 2/5 [60.00%]: Factory e7a5def1-059e-49c4-aad9-e82c624fd8c4: money=4.0, storage={0: -8}, loans=0.0 2019-02-27 11:32:57,122 - DEBUG - 2/5 [60.00%]: Factory fdd8ea88-1272-4965-8317-13385e2d18dc: money=1.5, storage={0: -3}, loans=0.0 2019-02-27 11:32:57,122 - DEBUG - 2/5 [60.00%]: Factory af03e704-f500-48dc-b1f3-45d5d3cf60f3: money=3.0, storage={0: -6}, loans=0.0 2019-02-27 11:32:57,122 - DEBUG - 2/5 [60.00%]: Factory bcda6d74-adb6-450c-a9e4-06756aaeb456: money=3.5, storage={0: -7}, loans=0.0 2019-02-27 11:32:57,122 - DEBUG - 2/5 [60.00%]: Factory f621f922-b18a-4edb-b071-ef577b17d239: money=6.0, storage={0: -12}, loans=0.0 2019-02-27 11:32:57,122 - INFO - 3/5 [80.00%]: 25 Negotiations/4 _entities 2019-02-27 11:32:57,334 - DEBUG - 3/5 [80.00%]: Contract [cancelled]: ['c_3', 'm_0'] > {'time': 4, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_3-a48f2b83-a7b3-49ab-a0fb-729d4ae18c2d: buy 0 (t: 4, u: (0, 2.0), q: (1, 4))', 'partners': "['c_3-a48f2b83-a7b3-49ab-a0fb-729d4ae18c2d', 'm_0-ae38c93f-04bf-477a-809e-3d3de4b02340']", 'seller': 'm_0-ae38c93f-04bf-477a-809e-3d3de4b02340', 'buyer': 'c_3-a48f2b83-a7b3-49ab-a0fb-729d4ae18c2d'} 2019-02-27 11:32:57,334 - DEBUG - 3/5 [80.00%]: Contract [cancelled]: ['c_1', 'm_3'] > {'time': 4, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_1-3dbd2a2a-0c36-47bf-96c9-9754f7352219: buy 0 (t: 4, u: (0, 2.0), q: (1, 3))', 'partners': "['c_1-3dbd2a2a-0c36-47bf-96c9-9754f7352219', 'm_3-e6312be7-fa79-44d2-9ae4-f684919060e5']", 'seller': 'm_3-e6312be7-fa79-44d2-9ae4-f684919060e5', 'buyer': 'c_1-3dbd2a2a-0c36-47bf-96c9-9754f7352219'} 2019-02-27 11:32:57,335 - DEBUG - 3/5 [80.00%]: Contract [cancelled]: ['c_2', 'm_2'] > {'time': 4, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_2-d804b0d2-8eb4-4afa-bb16-d2e4c8ebcdcb: buy 0 (t: 4, u: (0, 2.0), q: (1, 3))', 'partners': "['c_2-d804b0d2-8eb4-4afa-bb16-d2e4c8ebcdcb', 'm_2-d279992c-cf29-4b38-b046-100294ca6f0c']", 'seller': 'm_2-d279992c-cf29-4b38-b046-100294ca6f0c', 'buyer': 'c_2-d804b0d2-8eb4-4afa-bb16-d2e4c8ebcdcb'} 2019-02-27 11:32:57,335 - DEBUG - 3/5 [80.00%]: Contract [cancelled]: ['c_1', 'm_4'] > {'time': 4, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_1-3dbd2a2a-0c36-47bf-96c9-9754f7352219: buy 0 (t: 4, u: (0, 2.0), q: (1, 3))', 'partners': "['c_1-3dbd2a2a-0c36-47bf-96c9-9754f7352219', 'm_4-cf4ba00c-de5e-4e64-9f2d-a8bf1c05fb02']", 'seller': 'm_4-cf4ba00c-de5e-4e64-9f2d-a8bf1c05fb02', 'buyer': 'c_1-3dbd2a2a-0c36-47bf-96c9-9754f7352219'} 2019-02-27 11:32:57,335 - DEBUG - 3/5 [80.00%]: Contract [cancelled]: ['c_1', 'm_1'] > {'time': 4, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_1-3dbd2a2a-0c36-47bf-96c9-9754f7352219: buy 0 (t: 4, u: (0, 2.0), q: (1, 3))', 'partners': "['c_1-3dbd2a2a-0c36-47bf-96c9-9754f7352219', 'm_1-99b3c06e-66f7-4413-b0f8-af0919e75071']", 'seller': 'm_1-99b3c06e-66f7-4413-b0f8-af0919e75071', 'buyer': 'c_1-3dbd2a2a-0c36-47bf-96c9-9754f7352219'} 2019-02-27 11:32:57,336 - DEBUG - 3/5 [80.00%]: Contract [cancelled]: ['c_1', 'm_2'] > {'time': 4, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_1-3dbd2a2a-0c36-47bf-96c9-9754f7352219: buy 0 (t: 4, u: (0, 2.0), q: (1, 3))', 'partners': "['c_1-3dbd2a2a-0c36-47bf-96c9-9754f7352219', 'm_2-d279992c-cf29-4b38-b046-100294ca6f0c']", 'seller': 'm_2-d279992c-cf29-4b38-b046-100294ca6f0c', 'buyer': 'c_1-3dbd2a2a-0c36-47bf-96c9-9754f7352219'} 2019-02-27 11:32:57,336 - DEBUG - 3/5 [80.00%]: Contract [cancelled]: ['c_2', 'm_3'] > {'time': 4, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_2-d804b0d2-8eb4-4afa-bb16-d2e4c8ebcdcb: buy 0 (t: 4, u: (0, 2.0), q: (1, 3))', 'partners': "['c_2-d804b0d2-8eb4-4afa-bb16-d2e4c8ebcdcb', 'm_3-e6312be7-fa79-44d2-9ae4-f684919060e5']", 'seller': 'm_3-e6312be7-fa79-44d2-9ae4-f684919060e5', 'buyer': 'c_2-d804b0d2-8eb4-4afa-bb16-d2e4c8ebcdcb'} 2019-02-27 11:32:57,336 - DEBUG - 3/5 [80.00%]: Contract [cancelled]: ['c_4', 'm_4'] > {'time': 4, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_4-81d58b26-eabf-43d9-b58f-21b367075ff6: buy 0 (t: 4, u: (0, 2.0), q: (1, 4))', 'partners': "['c_4-81d58b26-eabf-43d9-b58f-21b367075ff6', 'm_4-cf4ba00c-de5e-4e64-9f2d-a8bf1c05fb02']", 'seller': 'm_4-cf4ba00c-de5e-4e64-9f2d-a8bf1c05fb02', 'buyer': 'c_4-81d58b26-eabf-43d9-b58f-21b367075ff6'} 2019-02-27 11:32:57,337 - DEBUG - 3/5 [80.00%]: Contract [cancelled]: ['c_2', 'm_4'] > {'time': 4, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_2-d804b0d2-8eb4-4afa-bb16-d2e4c8ebcdcb: buy 0 (t: 4, u: (0, 2.0), q: (1, 3))', 'partners': "['c_2-d804b0d2-8eb4-4afa-bb16-d2e4c8ebcdcb', 'm_4-cf4ba00c-de5e-4e64-9f2d-a8bf1c05fb02']", 'seller': 'm_4-cf4ba00c-de5e-4e64-9f2d-a8bf1c05fb02', 'buyer': 'c_2-d804b0d2-8eb4-4afa-bb16-d2e4c8ebcdcb'} 2019-02-27 11:32:57,337 - DEBUG - 3/5 [80.00%]: Contract [cancelled]: ['c_0', 'm_2'] > {'time': 4, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_0-2e50318f-4595-4018-9486-4549326453e7: buy 0 (t: 4, u: (0, 2.0), q: (1, 4))', 'partners': "['c_0-2e50318f-4595-4018-9486-4549326453e7', 'm_2-d279992c-cf29-4b38-b046-100294ca6f0c']", 'seller': 'm_2-d279992c-cf29-4b38-b046-100294ca6f0c', 'buyer': 'c_0-2e50318f-4595-4018-9486-4549326453e7'} 2019-02-27 11:32:57,337 - DEBUG - 3/5 [80.00%]: Contract [cancelled]: ['c_4', 'm_3'] > {'time': 4, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_4-81d58b26-eabf-43d9-b58f-21b367075ff6: buy 0 (t: 4, u: (0, 2.0), q: (1, 4))', 'partners': "['c_4-81d58b26-eabf-43d9-b58f-21b367075ff6', 'm_3-e6312be7-fa79-44d2-9ae4-f684919060e5']", 'seller': 'm_3-e6312be7-fa79-44d2-9ae4-f684919060e5', 'buyer': 'c_4-81d58b26-eabf-43d9-b58f-21b367075ff6'} 2019-02-27 11:32:57,337 - DEBUG - 3/5 [80.00%]: Contract [cancelled]: ['c_4', 'm_1'] > {'time': 4, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_4-81d58b26-eabf-43d9-b58f-21b367075ff6: buy 0 (t: 4, u: (0, 2.0), q: (1, 4))', 'partners': "['c_4-81d58b26-eabf-43d9-b58f-21b367075ff6', 'm_1-99b3c06e-66f7-4413-b0f8-af0919e75071']", 'seller': 'm_1-99b3c06e-66f7-4413-b0f8-af0919e75071', 'buyer': 'c_4-81d58b26-eabf-43d9-b58f-21b367075ff6'} 2019-02-27 11:32:57,338 - DEBUG - 3/5 [80.00%]: Contract [cancelled]: ['c_0', 'm_4'] > {'time': 4, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_0-2e50318f-4595-4018-9486-4549326453e7: buy 0 (t: 4, u: (0, 2.0), q: (1, 4))', 'partners': "['c_0-2e50318f-4595-4018-9486-4549326453e7', 'm_4-cf4ba00c-de5e-4e64-9f2d-a8bf1c05fb02']", 'seller': 'm_4-cf4ba00c-de5e-4e64-9f2d-a8bf1c05fb02', 'buyer': 'c_0-2e50318f-4595-4018-9486-4549326453e7'} 2019-02-27 11:32:57,338 - DEBUG - 3/5 [80.00%]: Contract [cancelled]: ['c_4', 'm_2'] > {'time': 4, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_4-81d58b26-eabf-43d9-b58f-21b367075ff6: buy 0 (t: 4, u: (0, 2.0), q: (1, 4))', 'partners': "['c_4-81d58b26-eabf-43d9-b58f-21b367075ff6', 'm_2-d279992c-cf29-4b38-b046-100294ca6f0c']", 'seller': 'm_2-d279992c-cf29-4b38-b046-100294ca6f0c', 'buyer': 'c_4-81d58b26-eabf-43d9-b58f-21b367075ff6'} 2019-02-27 11:32:57,338 - DEBUG - 3/5 [80.00%]: Contract [cancelled]: ['c_2', 'm_1'] > {'time': 4, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_2-d804b0d2-8eb4-4afa-bb16-d2e4c8ebcdcb: buy 0 (t: 4, u: (0, 2.0), q: (1, 3))', 'partners': "['c_2-d804b0d2-8eb4-4afa-bb16-d2e4c8ebcdcb', 'm_1-99b3c06e-66f7-4413-b0f8-af0919e75071']", 'seller': 'm_1-99b3c06e-66f7-4413-b0f8-af0919e75071', 'buyer': 'c_2-d804b0d2-8eb4-4afa-bb16-d2e4c8ebcdcb'} 2019-02-27 11:32:57,339 - DEBUG - 3/5 [80.00%]: Contract [cancelled]: ['c_0', 'm_0'] > {'time': 4, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_0-2e50318f-4595-4018-9486-4549326453e7: buy 0 (t: 4, u: (0, 2.0), q: (1, 4))', 'partners': "['c_0-2e50318f-4595-4018-9486-4549326453e7', 'm_0-ae38c93f-04bf-477a-809e-3d3de4b02340']", 'seller': 'm_0-ae38c93f-04bf-477a-809e-3d3de4b02340', 'buyer': 'c_0-2e50318f-4595-4018-9486-4549326453e7'} 2019-02-27 11:32:57,339 - DEBUG - 3/5 [80.00%]: Contract [cancelled]: ['c_3', 'm_1'] > {'time': 4, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_3-a48f2b83-a7b3-49ab-a0fb-729d4ae18c2d: buy 0 (t: 4, u: (0, 2.0), q: (1, 4))', 'partners': "['c_3-a48f2b83-a7b3-49ab-a0fb-729d4ae18c2d', 'm_1-99b3c06e-66f7-4413-b0f8-af0919e75071']", 'seller': 'm_1-99b3c06e-66f7-4413-b0f8-af0919e75071', 'buyer': 'c_3-a48f2b83-a7b3-49ab-a0fb-729d4ae18c2d'} 2019-02-27 11:32:57,339 - DEBUG - 3/5 [80.00%]: Contract [cancelled]: ['c_2', 'm_0'] > {'time': 4, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_2-d804b0d2-8eb4-4afa-bb16-d2e4c8ebcdcb: buy 0 (t: 4, u: (0, 2.0), q: (1, 3))', 'partners': "['c_2-d804b0d2-8eb4-4afa-bb16-d2e4c8ebcdcb', 'm_0-ae38c93f-04bf-477a-809e-3d3de4b02340']", 'seller': 'm_0-ae38c93f-04bf-477a-809e-3d3de4b02340', 'buyer': 'c_2-d804b0d2-8eb4-4afa-bb16-d2e4c8ebcdcb'} 2019-02-27 11:32:57,340 - DEBUG - 3/5 [80.00%]: Contract [cancelled]: ['c_3', 'm_2'] > {'time': 4, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_3-a48f2b83-a7b3-49ab-a0fb-729d4ae18c2d: buy 0 (t: 4, u: (0, 2.0), q: (1, 4))', 'partners': "['c_3-a48f2b83-a7b3-49ab-a0fb-729d4ae18c2d', 'm_2-d279992c-cf29-4b38-b046-100294ca6f0c']", 'seller': 'm_2-d279992c-cf29-4b38-b046-100294ca6f0c', 'buyer': 'c_3-a48f2b83-a7b3-49ab-a0fb-729d4ae18c2d'} 2019-02-27 11:32:57,340 - DEBUG - 3/5 [80.00%]: Contract [cancelled]: ['c_3', 'm_3'] > {'time': 4, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_3-a48f2b83-a7b3-49ab-a0fb-729d4ae18c2d: buy 0 (t: 4, u: (0, 2.0), q: (1, 4))', 'partners': "['c_3-a48f2b83-a7b3-49ab-a0fb-729d4ae18c2d', 'm_3-e6312be7-fa79-44d2-9ae4-f684919060e5']", 'seller': 'm_3-e6312be7-fa79-44d2-9ae4-f684919060e5', 'buyer': 'c_3-a48f2b83-a7b3-49ab-a0fb-729d4ae18c2d'} 2019-02-27 11:32:57,340 - DEBUG - 3/5 [80.00%]: Contract [cancelled]: ['c_4', 'm_0'] > {'time': 4, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_4-81d58b26-eabf-43d9-b58f-21b367075ff6: buy 0 (t: 4, u: (0, 2.0), q: (1, 4))', 'partners': "['c_4-81d58b26-eabf-43d9-b58f-21b367075ff6', 'm_0-ae38c93f-04bf-477a-809e-3d3de4b02340']", 'seller': 'm_0-ae38c93f-04bf-477a-809e-3d3de4b02340', 'buyer': 'c_4-81d58b26-eabf-43d9-b58f-21b367075ff6'} 2019-02-27 11:32:57,341 - DEBUG - 3/5 [80.00%]: Contract [cancelled]: ['c_1', 'm_0'] > {'time': 4, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_1-3dbd2a2a-0c36-47bf-96c9-9754f7352219: buy 0 (t: 4, u: (0, 2.0), q: (1, 3))', 'partners': "['c_1-3dbd2a2a-0c36-47bf-96c9-9754f7352219', 'm_0-ae38c93f-04bf-477a-809e-3d3de4b02340']", 'seller': 'm_0-ae38c93f-04bf-477a-809e-3d3de4b02340', 'buyer': 'c_1-3dbd2a2a-0c36-47bf-96c9-9754f7352219'} 2019-02-27 11:32:57,341 - DEBUG - 3/5 [80.00%]: Contract [cancelled]: ['c_3', 'm_4'] > {'time': 4, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_3-a48f2b83-a7b3-49ab-a0fb-729d4ae18c2d: buy 0 (t: 4, u: (0, 2.0), q: (1, 4))', 'partners': "['c_3-a48f2b83-a7b3-49ab-a0fb-729d4ae18c2d', 'm_4-cf4ba00c-de5e-4e64-9f2d-a8bf1c05fb02']", 'seller': 'm_4-cf4ba00c-de5e-4e64-9f2d-a8bf1c05fb02', 'buyer': 'c_3-a48f2b83-a7b3-49ab-a0fb-729d4ae18c2d'} 2019-02-27 11:32:57,341 - DEBUG - 3/5 [80.00%]: Contract [cancelled]: ['c_0', 'm_3'] > {'time': 4, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_0-2e50318f-4595-4018-9486-4549326453e7: buy 0 (t: 4, u: (0, 2.0), q: (1, 4))', 'partners': "['c_0-2e50318f-4595-4018-9486-4549326453e7', 'm_3-e6312be7-fa79-44d2-9ae4-f684919060e5']", 'seller': 'm_3-e6312be7-fa79-44d2-9ae4-f684919060e5', 'buyer': 'c_0-2e50318f-4595-4018-9486-4549326453e7'} 2019-02-27 11:32:57,342 - DEBUG - 3/5 [80.00%]: Contract [cancelled]: ['c_0', 'm_1'] > {'time': 4, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_0-2e50318f-4595-4018-9486-4549326453e7: buy 0 (t: 4, u: (0, 2.0), q: (1, 4))', 'partners': "['c_0-2e50318f-4595-4018-9486-4549326453e7', 'm_1-99b3c06e-66f7-4413-b0f8-af0919e75071']", 'seller': 'm_1-99b3c06e-66f7-4413-b0f8-af0919e75071', 'buyer': 'c_0-2e50318f-4595-4018-9486-4549326453e7'} 2019-02-27 11:32:57,342 - INFO - 3/5 [80.00%]: Executing c_2-d804b0d2-8eb4-4afa-bb16-d2e4c8ebcdcb, m_3-e6312be7-fa79-44d2-9ae4-f684919060e5 agreed on {'time': 3, 'quantity': 3, 'unit_price': 0.5} 2019-02-27 11:32:57,342 - DEBUG - 3/5 [80.00%]: Moved 3 units of p0 from m_3 to c_2 for 1.5 dollars 2019-02-27 11:32:57,343 - INFO - 3/5 [80.00%]: Executing c_3-a48f2b83-a7b3-49ab-a0fb-729d4ae18c2d, m_1-99b3c06e-66f7-4413-b0f8-af0919e75071 agreed on {'time': 3, 'quantity': 4, 'unit_price': 0.5} 2019-02-27 11:32:57,343 - DEBUG - 3/5 [80.00%]: Moved 4 units of p0 from m_1 to c_3 for 2.0 dollars 2019-02-27 11:32:57,343 - INFO - 3/5 [80.00%]: Executing c_1-3dbd2a2a-0c36-47bf-96c9-9754f7352219, m_2-d279992c-cf29-4b38-b046-100294ca6f0c agreed on {'time': 3, 'quantity': 4, 'unit_price': 0.5} 2019-02-27 11:32:57,343 - DEBUG - 3/5 [80.00%]: Moved 4 units of p0 from m_2 to c_1 for 2.0 dollars 2019-02-27 11:32:57,343 - INFO - 3/5 [80.00%]: Executing c_4-81d58b26-eabf-43d9-b58f-21b367075ff6, m_2-d279992c-cf29-4b38-b046-100294ca6f0c agreed on {'time': 3, 'quantity': 3, 'unit_price': 0.5} 2019-02-27 11:32:57,343 - DEBUG - 3/5 [80.00%]: Moved 3 units of p0 from m_2 to c_4 for 1.5 dollars 2019-02-27 11:32:57,343 - INFO - 3/5 [80.00%]: Executing c_0-2e50318f-4595-4018-9486-4549326453e7, m_2-d279992c-cf29-4b38-b046-100294ca6f0c agreed on {'time': 3, 'quantity': 4, 'unit_price': 0.5} 2019-02-27 11:32:57,343 - DEBUG - 3/5 [80.00%]: Moved 4 units of p0 from m_2 to c_0 for 2.0 dollars 2019-02-27 11:32:57,343 - DEBUG - 3/5 [80.00%]: Factory e99d9a30-972a-4954-a82a-dd7afdef43ad: money=-5.5, storage={0: 4}, loans=0.0 2019-02-27 11:32:57,343 - DEBUG - 3/5 [80.00%]: Factory c522c9c1-11e2-41e3-9250-b27a9522444b: money=-6.0, storage={0: 4}, loans=0.0 2019-02-27 11:32:57,343 - DEBUG - 3/5 [80.00%]: Factory ff2a5bf9-bfbd-48a1-b5e7-c4dadc046f96: money=-5.0, storage={0: 4}, loans=0.0 2019-02-27 11:32:57,343 - DEBUG - 3/5 [80.00%]: Factory 5e7733e2-db9b-4765-a33a-7e9fe2248fc5: money=-5.5, storage={0: 3}, loans=0.0 2019-02-27 11:32:57,343 - DEBUG - 3/5 [80.00%]: Factory 852400c0-e73c-4484-91ec-ba8a9a901a8d: money=-5.0, storage={0: 4}, loans=0.0 2019-02-27 11:32:57,343 - DEBUG - 3/5 [80.00%]: Factory e7a5def1-059e-49c4-aad9-e82c624fd8c4: money=4.0, storage={0: -8}, loans=0.0 2019-02-27 11:32:57,343 - DEBUG - 3/5 [80.00%]: Factory fdd8ea88-1272-4965-8317-13385e2d18dc: money=3.5, storage={0: -7}, loans=0.0 2019-02-27 11:32:57,343 - DEBUG - 3/5 [80.00%]: Factory af03e704-f500-48dc-b1f3-45d5d3cf60f3: money=8.5, storage={0: -17}, loans=0.0 2019-02-27 11:32:57,343 - DEBUG - 3/5 [80.00%]: Factory bcda6d74-adb6-450c-a9e4-06756aaeb456: money=5.0, storage={0: -10}, loans=0.0 2019-02-27 11:32:57,343 - DEBUG - 3/5 [80.00%]: Factory f621f922-b18a-4edb-b071-ef577b17d239: money=6.0, storage={0: -12}, loans=0.0 2019-02-27 11:32:57,344 - INFO - 4/5 [100.00%]: 0 Negotiations/4 _entities 2019-02-27 11:32:57,344 - DEBUG - 4/5 [100.00%]: Factory e99d9a30-972a-4954-a82a-dd7afdef43ad: money=-5.5, storage={0: 7}, loans=0.0 2019-02-27 11:32:57,344 - DEBUG - 4/5 [100.00%]: Factory c522c9c1-11e2-41e3-9250-b27a9522444b: money=-6.0, storage={0: 8}, loans=0.0 2019-02-27 11:32:57,344 - DEBUG - 4/5 [100.00%]: Factory ff2a5bf9-bfbd-48a1-b5e7-c4dadc046f96: money=-5.0, storage={0: 7}, loans=0.0 2019-02-27 11:32:57,344 - DEBUG - 4/5 [100.00%]: Factory 5e7733e2-db9b-4765-a33a-7e9fe2248fc5: money=-5.5, storage={0: 7}, loans=0.0 2019-02-27 11:32:57,344 - DEBUG - 4/5 [100.00%]: Factory 852400c0-e73c-4484-91ec-ba8a9a901a8d: money=-5.0, storage={0: 7}, loans=0.0 2019-02-27 11:32:57,344 - DEBUG - 4/5 [100.00%]: Factory e7a5def1-059e-49c4-aad9-e82c624fd8c4: money=4.0, storage={0: -8}, loans=0.0 2019-02-27 11:32:57,344 - DEBUG - 4/5 [100.00%]: Factory fdd8ea88-1272-4965-8317-13385e2d18dc: money=3.5, storage={0: -7}, loans=0.0 2019-02-27 11:32:57,344 - DEBUG - 4/5 [100.00%]: Factory af03e704-f500-48dc-b1f3-45d5d3cf60f3: money=8.5, storage={0: -17}, loans=0.0 2019-02-27 11:32:57,344 - DEBUG - 4/5 [100.00%]: Factory bcda6d74-adb6-450c-a9e4-06756aaeb456: money=5.0, storage={0: -10}, loans=0.0 2019-02-27 11:32:57,344 - DEBUG - 4/5 [100.00%]: Factory f621f922-b18a-4edb-b071-ef577b17d239: money=6.0, storage={0: -12}, loans=0.0 2019-02-27 11:32:57,515 - INFO - 0/10 [10.00%]: SCMLWorld/20190227-113257mf3lw: World Created 2019-02-27 11:32:57,515 - INFO - 0/10 [10.00%]: m_0 joined 2019-02-27 11:32:57,515 - INFO - 0/10 [10.00%]: m_1 joined 2019-02-27 11:32:57,516 - INFO - 0/10 [10.00%]: m_2 joined 2019-02-27 11:32:57,516 - INFO - 0/10 [10.00%]: m_3 joined 2019-02-27 11:32:57,516 - INFO - 0/10 [10.00%]: m_4 joined 2019-02-27 11:32:57,516 - INFO - 0/10 [10.00%]: c_0 joined 2019-02-27 11:32:57,516 - INFO - 0/10 [10.00%]: c_1 joined 2019-02-27 11:32:57,516 - INFO - 0/10 [10.00%]: c_2 joined 2019-02-27 11:32:57,516 - INFO - 0/10 [10.00%]: c_3 joined 2019-02-27 11:32:57,516 - INFO - 0/10 [10.00%]: c_4 joined 2019-02-27 11:32:57,518 - INFO - 0/10 [10.00%]: k8JMRQcYue8AUSTH joined 2019-02-27 11:32:57,519 - INFO - 0/10 [10.00%]: IQazPOi4JWgWFnQx joined 2019-02-27 11:32:57,519 - INFO - 0/10 [10.00%]: 0 Negotiations/4 _entities 2019-02-27 11:32:57,522 - INFO - 0/10 [10.00%]: m_0 requested negmas.sao.SAOMechanism[None] with ['c_3', 'm_0'] (ID ed1a6f19-62f1-424e-9037-f1d146539147) 2019-02-27 11:32:57,525 - INFO - 0/10 [10.00%]: m_0-575672e1-efe8-4964-b340-4a6116793ce6 request was accepted 2019-02-27 11:32:57,526 - INFO - 0/10 [10.00%]: m_1 requested negmas.sao.SAOMechanism[None] with ['c_3', 'm_1'] (ID 525eb397-f633-494b-a966-38b7d3a3d239) 2019-02-27 11:32:57,528 - INFO - 0/10 [10.00%]: m_1-153ac158-9a57-4bca-8296-bae6389d1ce1 request was accepted 2019-02-27 11:32:57,529 - INFO - 0/10 [10.00%]: m_2 requested negmas.sao.SAOMechanism[None] with ['c_3', 'm_2'] (ID fdb365c3-5cba-4d4f-8adb-c8ca531b84ee) 2019-02-27 11:32:57,530 - INFO - 0/10 [10.00%]: m_2-84165933-f800-4373-8db2-96de0656eead request was accepted 2019-02-27 11:32:57,532 - INFO - 0/10 [10.00%]: m_3 requested negmas.sao.SAOMechanism[None] with ['c_3', 'm_3'] (ID b5359c73-aad0-4379-8a2a-6d8cda195835) 2019-02-27 11:32:57,533 - INFO - 0/10 [10.00%]: m_3-57429f75-c75c-4cb4-a9b4-ca5c83d682d1 request was accepted 2019-02-27 11:32:57,535 - INFO - 0/10 [10.00%]: m_4 requested negmas.sao.SAOMechanism[None] with ['c_3', 'm_4'] (ID 53046947-04d6-4020-bda4-6ea7788b3e8c) 2019-02-27 11:32:57,536 - INFO - 0/10 [10.00%]: m_4-839c8f96-e52b-40cd-a1ef-3bf468ec11cb request was accepted 2019-02-27 11:32:57,538 - INFO - 0/10 [10.00%]: m_0 requested negmas.sao.SAOMechanism[None] with ['c_3', 'm_0'] (ID 63910c05-90c5-4185-b8b3-cb0d191ea9bc) 2019-02-27 11:32:57,540 - INFO - 0/10 [10.00%]: m_0-575672e1-efe8-4964-b340-4a6116793ce6 request was accepted 2019-02-27 11:32:57,541 - INFO - 0/10 [10.00%]: m_1 requested negmas.sao.SAOMechanism[None] with ['c_3', 'm_1'] (ID 1ccb6bba-6acf-4de7-8b2a-ece03701d06e) 2019-02-27 11:32:57,542 - INFO - 0/10 [10.00%]: m_1-153ac158-9a57-4bca-8296-bae6389d1ce1 request was accepted 2019-02-27 11:32:57,543 - INFO - 0/10 [10.00%]: m_2 requested negmas.sao.SAOMechanism[None] with ['c_3', 'm_2'] (ID cd7a22cc-2ff3-49b9-becb-55d175efb43c) 2019-02-27 11:32:57,545 - INFO - 0/10 [10.00%]: m_2-84165933-f800-4373-8db2-96de0656eead request was accepted 2019-02-27 11:32:57,547 - INFO - 0/10 [10.00%]: m_3 requested negmas.sao.SAOMechanism[None] with ['c_3', 'm_3'] (ID 8ff287cb-d920-4899-ae49-77cd31cfc761) 2019-02-27 11:32:57,547 - INFO - 0/10 [10.00%]: m_3-57429f75-c75c-4cb4-a9b4-ca5c83d682d1 request was accepted 2019-02-27 11:32:57,548 - INFO - 0/10 [10.00%]: m_4 requested negmas.sao.SAOMechanism[None] with ['c_3', 'm_4'] (ID 70462f06-0511-49b8-8668-7098e399e4bb) 2019-02-27 11:32:57,549 - INFO - 0/10 [10.00%]: m_4-839c8f96-e52b-40cd-a1ef-3bf468ec11cb request was accepted 2019-02-27 11:32:57,551 - INFO - 0/10 [10.00%]: m_0 requested negmas.sao.SAOMechanism[None] with ['c_3', 'm_0'] (ID 887842e2-2f33-4770-bba7-a479f02101e5) 2019-02-27 11:32:57,553 - INFO - 0/10 [10.00%]: m_0-575672e1-efe8-4964-b340-4a6116793ce6 request was accepted 2019-02-27 11:32:57,554 - INFO - 0/10 [10.00%]: m_1 requested negmas.sao.SAOMechanism[None] with ['c_3', 'm_1'] (ID 6c3b3be4-977f-4740-8aad-1d3710cf3c0f) 2019-02-27 11:32:57,555 - INFO - 0/10 [10.00%]: m_1-153ac158-9a57-4bca-8296-bae6389d1ce1 request was accepted 2019-02-27 11:32:57,558 - INFO - 0/10 [10.00%]: m_2 requested negmas.sao.SAOMechanism[None] with ['c_3', 'm_2'] (ID 2f4ed088-ce2e-41aa-9ced-d3586d99f657) 2019-02-27 11:32:57,559 - INFO - 0/10 [10.00%]: m_2-84165933-f800-4373-8db2-96de0656eead request was accepted 2019-02-27 11:32:57,559 - INFO - 0/10 [10.00%]: m_3 requested negmas.sao.SAOMechanism[None] with ['c_3', 'm_3'] (ID ecbfa8c2-6e52-4ba9-9873-bed8f20b5a40) 2019-02-27 11:32:57,560 - INFO - 0/10 [10.00%]: m_3-57429f75-c75c-4cb4-a9b4-ca5c83d682d1 request was accepted 2019-02-27 11:32:57,561 - INFO - 0/10 [10.00%]: m_4 requested negmas.sao.SAOMechanism[None] with ['c_3', 'm_4'] (ID 6fef7d86-e044-408f-b24a-c963ebf71cb4) 2019-02-27 11:32:57,562 - INFO - 0/10 [10.00%]: m_4-839c8f96-e52b-40cd-a1ef-3bf468ec11cb request was accepted 2019-02-27 11:32:57,563 - INFO - 0/10 [10.00%]: m_0 requested negmas.sao.SAOMechanism[None] with ['c_3', 'm_0'] (ID 351474ab-54fa-4cfc-86d4-b038ee9bc4d6) 2019-02-27 11:32:57,564 - INFO - 0/10 [10.00%]: m_0-575672e1-efe8-4964-b340-4a6116793ce6 request was accepted 2019-02-27 11:32:57,568 - INFO - 0/10 [10.00%]: m_1 requested negmas.sao.SAOMechanism[None] with ['c_3', 'm_1'] (ID dfd9c9df-b1d4-4d61-8d56-44d3a91a4a48) 2019-02-27 11:32:57,569 - INFO - 0/10 [10.00%]: m_1-153ac158-9a57-4bca-8296-bae6389d1ce1 request was accepted 2019-02-27 11:32:57,574 - INFO - 0/10 [10.00%]: m_2 requested negmas.sao.SAOMechanism[None] with ['c_3', 'm_2'] (ID 338e4b7a-81c2-4b8f-b4fa-12695b163e9d) 2019-02-27 11:32:57,576 - INFO - 0/10 [10.00%]: m_2-84165933-f800-4373-8db2-96de0656eead request was accepted 2019-02-27 11:32:57,579 - INFO - 0/10 [10.00%]: m_3 requested negmas.sao.SAOMechanism[None] with ['c_3', 'm_3'] (ID f34f49a8-a6e7-45ec-a6d0-e8cedf973628) 2019-02-27 11:32:57,582 - INFO - 0/10 [10.00%]: m_3-57429f75-c75c-4cb4-a9b4-ca5c83d682d1 request was accepted 2019-02-27 11:32:57,585 - INFO - 0/10 [10.00%]: m_4 requested negmas.sao.SAOMechanism[None] with ['c_3', 'm_4'] (ID 0b41cdda-8f26-4193-91ce-13ec975546df) 2019-02-27 11:32:57,587 - INFO - 0/10 [10.00%]: m_4-839c8f96-e52b-40cd-a1ef-3bf468ec11cb request was accepted 2019-02-27 11:32:57,590 - INFO - 0/10 [10.00%]: m_0 requested negmas.sao.SAOMechanism[None] with ['c_4', 'm_0'] (ID 22ff7391-751d-4016-bde0-5628406b015f) 2019-02-27 11:32:57,591 - INFO - 0/10 [10.00%]: m_0-575672e1-efe8-4964-b340-4a6116793ce6 request was accepted 2019-02-27 11:32:57,593 - INFO - 0/10 [10.00%]: m_1 requested negmas.sao.SAOMechanism[None] with ['c_4', 'm_1'] (ID e8380eec-102a-4c3d-ae71-e93564002a48) 2019-02-27 11:32:57,594 - INFO - 0/10 [10.00%]: m_1-153ac158-9a57-4bca-8296-bae6389d1ce1 request was accepted 2019-02-27 11:32:57,596 - INFO - 0/10 [10.00%]: m_2 requested negmas.sao.SAOMechanism[None] with ['c_4', 'm_2'] (ID df8b9137-4f6a-449f-bdb0-a217b5855160) 2019-02-27 11:32:57,597 - INFO - 0/10 [10.00%]: m_2-84165933-f800-4373-8db2-96de0656eead request was accepted 2019-02-27 11:32:57,600 - INFO - 0/10 [10.00%]: m_3 requested negmas.sao.SAOMechanism[None] with ['c_4', 'm_3'] (ID 0cd7cf73-b697-448c-a202-676d57b9ca21) 2019-02-27 11:32:57,602 - INFO - 0/10 [10.00%]: m_3-57429f75-c75c-4cb4-a9b4-ca5c83d682d1 request was accepted 2019-02-27 11:32:57,603 - INFO - 0/10 [10.00%]: m_4 requested negmas.sao.SAOMechanism[None] with ['c_4', 'm_4'] (ID b236fcc8-dc06-4e80-a35e-d407fe5f5089) 2019-02-27 11:32:57,605 - INFO - 0/10 [10.00%]: m_4-839c8f96-e52b-40cd-a1ef-3bf468ec11cb request was accepted 2019-02-27 11:32:57,607 - INFO - 0/10 [10.00%]: m_0 requested negmas.sao.SAOMechanism[None] with ['c_4', 'm_0'] (ID 593986bb-6fd3-4e13-9de3-f8a53d5da01e) 2019-02-27 11:32:57,607 - INFO - 0/10 [10.00%]: m_0-575672e1-efe8-4964-b340-4a6116793ce6 request was accepted 2019-02-27 11:32:57,610 - INFO - 0/10 [10.00%]: m_1 requested negmas.sao.SAOMechanism[None] with ['c_4', 'm_1'] (ID 510c05ca-38a9-4ec0-9c9f-8adaedb5f32f) 2019-02-27 11:32:57,611 - INFO - 0/10 [10.00%]: m_1-153ac158-9a57-4bca-8296-bae6389d1ce1 request was accepted 2019-02-27 11:32:57,612 - INFO - 0/10 [10.00%]: m_2 requested negmas.sao.SAOMechanism[None] with ['c_4', 'm_2'] (ID e8e3439f-0a02-48f1-b392-312d9944755b) 2019-02-27 11:32:57,612 - INFO - 0/10 [10.00%]: m_2-84165933-f800-4373-8db2-96de0656eead request was accepted 2019-02-27 11:32:57,613 - INFO - 0/10 [10.00%]: m_3 requested negmas.sao.SAOMechanism[None] with ['c_4', 'm_3'] (ID 003d9783-445c-4ce1-ada8-a00941243455) 2019-02-27 11:32:57,614 - INFO - 0/10 [10.00%]: m_3-57429f75-c75c-4cb4-a9b4-ca5c83d682d1 request was accepted 2019-02-27 11:32:57,616 - INFO - 0/10 [10.00%]: m_4 requested negmas.sao.SAOMechanism[None] with ['c_4', 'm_4'] (ID ad99e192-2985-4d1f-88bb-bc025553071a) 2019-02-27 11:32:57,618 - INFO - 0/10 [10.00%]: m_4-839c8f96-e52b-40cd-a1ef-3bf468ec11cb request was accepted 2019-02-27 11:32:57,621 - INFO - 0/10 [10.00%]: m_0 requested negmas.sao.SAOMechanism[None] with ['c_4', 'm_0'] (ID c10c0fbd-ce0f-40cc-bfc9-2691031cf969) 2019-02-27 11:32:57,621 - INFO - 0/10 [10.00%]: m_0-575672e1-efe8-4964-b340-4a6116793ce6 request was accepted 2019-02-27 11:32:57,624 - INFO - 0/10 [10.00%]: m_1 requested negmas.sao.SAOMechanism[None] with ['c_4', 'm_1'] (ID 92fbe56f-24a0-4c4a-8f68-d36e5d4e9e14) 2019-02-27 11:32:57,625 - INFO - 0/10 [10.00%]: m_1-153ac158-9a57-4bca-8296-bae6389d1ce1 request was accepted 2019-02-27 11:32:57,628 - INFO - 0/10 [10.00%]: m_2 requested negmas.sao.SAOMechanism[None] with ['c_4', 'm_2'] (ID 4aef76e8-0482-43e4-8a7d-82d320fa7186) 2019-02-27 11:32:57,629 - INFO - 0/10 [10.00%]: m_2-84165933-f800-4373-8db2-96de0656eead request was accepted 2019-02-27 11:32:57,631 - INFO - 0/10 [10.00%]: m_3 requested negmas.sao.SAOMechanism[None] with ['c_4', 'm_3'] (ID abef7d88-0c2b-4601-9cae-68010bdfd8c0) 2019-02-27 11:32:57,633 - INFO - 0/10 [10.00%]: m_3-57429f75-c75c-4cb4-a9b4-ca5c83d682d1 request was accepted 2019-02-27 11:32:57,636 - INFO - 0/10 [10.00%]: m_4 requested negmas.sao.SAOMechanism[None] with ['c_4', 'm_4'] (ID 2c0b620f-da48-4b17-871c-79a8e4f45399) 2019-02-27 11:32:57,638 - INFO - 0/10 [10.00%]: m_4-839c8f96-e52b-40cd-a1ef-3bf468ec11cb request was accepted 2019-02-27 11:32:57,640 - INFO - 0/10 [10.00%]: m_0 requested negmas.sao.SAOMechanism[None] with ['c_4', 'm_0'] (ID d4f03ae8-3c18-48eb-b9c7-b302096e2519) 2019-02-27 11:32:57,642 - INFO - 0/10 [10.00%]: m_0-575672e1-efe8-4964-b340-4a6116793ce6 request was accepted 2019-02-27 11:32:57,644 - INFO - 0/10 [10.00%]: m_1 requested negmas.sao.SAOMechanism[None] with ['c_4', 'm_1'] (ID 5a44c4c3-abe7-4155-94b2-3667b0b33087) 2019-02-27 11:32:57,644 - INFO - 0/10 [10.00%]: m_1-153ac158-9a57-4bca-8296-bae6389d1ce1 request was accepted 2019-02-27 11:32:57,646 - INFO - 0/10 [10.00%]: m_2 requested negmas.sao.SAOMechanism[None] with ['c_4', 'm_2'] (ID c00b4350-3ba6-45a1-90ef-d7949f4b3f34) 2019-02-27 11:32:57,647 - INFO - 0/10 [10.00%]: m_2-84165933-f800-4373-8db2-96de0656eead request was accepted 2019-02-27 11:32:57,648 - INFO - 0/10 [10.00%]: m_3 requested negmas.sao.SAOMechanism[None] with ['c_4', 'm_3'] (ID 9f937eaa-47b4-43bd-aabb-8d0fbf4b50f6) 2019-02-27 11:32:57,649 - INFO - 0/10 [10.00%]: m_3-57429f75-c75c-4cb4-a9b4-ca5c83d682d1 request was accepted 2019-02-27 11:32:57,653 - INFO - 0/10 [10.00%]: m_4 requested negmas.sao.SAOMechanism[None] with ['c_4', 'm_4'] (ID 73216e6e-332f-470a-801f-f8043dee9961) 2019-02-27 11:32:57,654 - INFO - 0/10 [10.00%]: m_4-839c8f96-e52b-40cd-a1ef-3bf468ec11cb request was accepted 2019-02-27 11:32:57,657 - INFO - 0/10 [10.00%]: m_0 requested negmas.sao.SAOMechanism[None] with ['c_1', 'm_0'] (ID 38fa7238-e518-469c-81fa-bf3f17ec11d3) 2019-02-27 11:32:57,658 - INFO - 0/10 [10.00%]: m_0-575672e1-efe8-4964-b340-4a6116793ce6 request was accepted 2019-02-27 11:32:57,660 - INFO - 0/10 [10.00%]: m_1 requested negmas.sao.SAOMechanism[None] with ['c_1', 'm_1'] (ID 784943e2-d401-41a4-928f-d9ecb8e6e183) 2019-02-27 11:32:57,660 - INFO - 0/10 [10.00%]: m_1-153ac158-9a57-4bca-8296-bae6389d1ce1 request was accepted 2019-02-27 11:32:57,663 - INFO - 0/10 [10.00%]: m_2 requested negmas.sao.SAOMechanism[None] with ['c_1', 'm_2'] (ID bbdc73a9-606c-4e7a-a880-cab2ae6c003a) 2019-02-27 11:32:57,664 - INFO - 0/10 [10.00%]: m_2-84165933-f800-4373-8db2-96de0656eead request was accepted 2019-02-27 11:32:57,665 - INFO - 0/10 [10.00%]: m_3 requested negmas.sao.SAOMechanism[None] with ['c_1', 'm_3'] (ID a0f0178b-cc0c-4916-a36b-6f5479947d2f) 2019-02-27 11:32:57,666 - INFO - 0/10 [10.00%]: m_3-57429f75-c75c-4cb4-a9b4-ca5c83d682d1 request was accepted 2019-02-27 11:32:57,668 - INFO - 0/10 [10.00%]: m_4 requested negmas.sao.SAOMechanism[None] with ['c_1', 'm_4'] (ID b949a206-2fb8-4855-b4e1-009430beb62c) 2019-02-27 11:32:57,669 - INFO - 0/10 [10.00%]: m_4-839c8f96-e52b-40cd-a1ef-3bf468ec11cb request was accepted 2019-02-27 11:32:57,671 - INFO - 0/10 [10.00%]: m_0 requested negmas.sao.SAOMechanism[None] with ['c_1', 'm_0'] (ID 0c2b6aa6-b364-4c32-846e-a0ae106fcebf) 2019-02-27 11:32:57,672 - INFO - 0/10 [10.00%]: m_0-575672e1-efe8-4964-b340-4a6116793ce6 request was accepted 2019-02-27 11:32:57,674 - INFO - 0/10 [10.00%]: m_1 requested negmas.sao.SAOMechanism[None] with ['c_1', 'm_1'] (ID 46b905c3-a294-410a-a113-1a3f9ea2ba6a) 2019-02-27 11:32:57,675 - INFO - 0/10 [10.00%]: m_1-153ac158-9a57-4bca-8296-bae6389d1ce1 request was accepted 2019-02-27 11:32:57,676 - INFO - 0/10 [10.00%]: m_2 requested negmas.sao.SAOMechanism[None] with ['c_1', 'm_2'] (ID 60f172dd-cf42-44a6-a579-565194cdc332) 2019-02-27 11:32:57,677 - INFO - 0/10 [10.00%]: m_2-84165933-f800-4373-8db2-96de0656eead request was accepted 2019-02-27 11:32:57,677 - INFO - 0/10 [10.00%]: m_3 requested negmas.sao.SAOMechanism[None] with ['c_1', 'm_3'] (ID ada441af-fa10-44ec-8c92-a7e145e20a42) 2019-02-27 11:32:57,678 - INFO - 0/10 [10.00%]: m_3-57429f75-c75c-4cb4-a9b4-ca5c83d682d1 request was accepted 2019-02-27 11:32:57,679 - INFO - 0/10 [10.00%]: m_4 requested negmas.sao.SAOMechanism[None] with ['c_1', 'm_4'] (ID bb039555-3b01-49e9-8906-cf3d4fce3e2b) 2019-02-27 11:32:57,679 - INFO - 0/10 [10.00%]: m_4-839c8f96-e52b-40cd-a1ef-3bf468ec11cb request was accepted 2019-02-27 11:32:57,681 - INFO - 0/10 [10.00%]: m_0 requested negmas.sao.SAOMechanism[None] with ['c_1', 'm_0'] (ID 30474099-6598-4056-9068-8e5ffc34c635) 2019-02-27 11:32:57,682 - INFO - 0/10 [10.00%]: m_0-575672e1-efe8-4964-b340-4a6116793ce6 request was accepted 2019-02-27 11:32:57,683 - INFO - 0/10 [10.00%]: m_1 requested negmas.sao.SAOMechanism[None] with ['c_1', 'm_1'] (ID cca247a2-7dd3-43c2-93c4-b5c9c3cde5b5) 2019-02-27 11:32:57,685 - INFO - 0/10 [10.00%]: m_1-153ac158-9a57-4bca-8296-bae6389d1ce1 request was accepted 2019-02-27 11:32:57,686 - INFO - 0/10 [10.00%]: m_2 requested negmas.sao.SAOMechanism[None] with ['c_1', 'm_2'] (ID 8fe1b793-1e92-40e6-bf38-c407f36694c6) 2019-02-27 11:32:57,687 - INFO - 0/10 [10.00%]: m_2-84165933-f800-4373-8db2-96de0656eead request was accepted 2019-02-27 11:32:57,690 - INFO - 0/10 [10.00%]: m_3 requested negmas.sao.SAOMechanism[None] with ['c_1', 'm_3'] (ID 7ed954eb-ef36-408a-a920-048c5127498a) 2019-02-27 11:32:57,690 - INFO - 0/10 [10.00%]: m_3-57429f75-c75c-4cb4-a9b4-ca5c83d682d1 request was accepted 2019-02-27 11:32:57,691 - INFO - 0/10 [10.00%]: m_4 requested negmas.sao.SAOMechanism[None] with ['c_1', 'm_4'] (ID 3a634310-3cc7-48ba-9416-6b08d1182c6e) 2019-02-27 11:32:57,692 - INFO - 0/10 [10.00%]: m_4-839c8f96-e52b-40cd-a1ef-3bf468ec11cb request was accepted 2019-02-27 11:32:57,694 - INFO - 0/10 [10.00%]: m_0 requested negmas.sao.SAOMechanism[None] with ['c_1', 'm_0'] (ID 0870ed5c-579d-4b52-887c-824851916dcc) 2019-02-27 11:32:57,695 - INFO - 0/10 [10.00%]: m_0-575672e1-efe8-4964-b340-4a6116793ce6 request was accepted 2019-02-27 11:32:57,696 - INFO - 0/10 [10.00%]: m_1 requested negmas.sao.SAOMechanism[None] with ['c_1', 'm_1'] (ID 0611ea6f-2398-4d59-9c00-aec126624fe5) 2019-02-27 11:32:57,697 - INFO - 0/10 [10.00%]: m_1-153ac158-9a57-4bca-8296-bae6389d1ce1 request was accepted 2019-02-27 11:32:57,698 - INFO - 0/10 [10.00%]: m_2 requested negmas.sao.SAOMechanism[None] with ['c_1', 'm_2'] (ID dbc2e329-55db-4585-be26-799609447ec1) 2019-02-27 11:32:57,699 - INFO - 0/10 [10.00%]: m_2-84165933-f800-4373-8db2-96de0656eead request was accepted 2019-02-27 11:32:57,700 - INFO - 0/10 [10.00%]: m_3 requested negmas.sao.SAOMechanism[None] with ['c_1', 'm_3'] (ID 177f839a-2086-423c-9019-bb40d044ae8c) 2019-02-27 11:32:57,701 - INFO - 0/10 [10.00%]: m_3-57429f75-c75c-4cb4-a9b4-ca5c83d682d1 request was accepted 2019-02-27 11:32:57,703 - INFO - 0/10 [10.00%]: m_4 requested negmas.sao.SAOMechanism[None] with ['c_1', 'm_4'] (ID 2d1132cb-fc9a-479e-b476-dd680a9a2385) 2019-02-27 11:32:57,704 - INFO - 0/10 [10.00%]: m_4-839c8f96-e52b-40cd-a1ef-3bf468ec11cb request was accepted 2019-02-27 11:32:57,706 - INFO - 0/10 [10.00%]: m_0 requested negmas.sao.SAOMechanism[None] with ['c_0', 'm_0'] (ID 8755b940-338c-457c-a3c4-e64c2eee7097) 2019-02-27 11:32:57,708 - INFO - 0/10 [10.00%]: m_0-575672e1-efe8-4964-b340-4a6116793ce6 request was accepted 2019-02-27 11:32:57,709 - INFO - 0/10 [10.00%]: m_1 requested negmas.sao.SAOMechanism[None] with ['c_0', 'm_1'] (ID 84df5889-94de-4925-8617-2ed90fcb7530) 2019-02-27 11:32:57,709 - INFO - 0/10 [10.00%]: m_1-153ac158-9a57-4bca-8296-bae6389d1ce1 request was accepted 2019-02-27 11:32:57,710 - INFO - 0/10 [10.00%]: m_2 requested negmas.sao.SAOMechanism[None] with ['c_0', 'm_2'] (ID 65465fbd-801f-473b-8247-765655ee52ae) 2019-02-27 11:32:57,711 - INFO - 0/10 [10.00%]: m_2-84165933-f800-4373-8db2-96de0656eead request was accepted 2019-02-27 11:32:57,712 - INFO - 0/10 [10.00%]: m_3 requested negmas.sao.SAOMechanism[None] with ['c_0', 'm_3'] (ID b9d6b4cb-577f-491f-b730-8717a336f578) 2019-02-27 11:32:57,713 - INFO - 0/10 [10.00%]: m_3-57429f75-c75c-4cb4-a9b4-ca5c83d682d1 request was accepted 2019-02-27 11:32:57,714 - INFO - 0/10 [10.00%]: m_4 requested negmas.sao.SAOMechanism[None] with ['c_0', 'm_4'] (ID 3770798a-876d-46cc-be16-10829bfb1702) 2019-02-27 11:32:57,715 - INFO - 0/10 [10.00%]: m_4-839c8f96-e52b-40cd-a1ef-3bf468ec11cb request was accepted 2019-02-27 11:32:57,718 - INFO - 0/10 [10.00%]: m_0 requested negmas.sao.SAOMechanism[None] with ['c_0', 'm_0'] (ID 2c9ea40e-4b04-43aa-8413-4379a3034edb) 2019-02-27 11:32:57,719 - INFO - 0/10 [10.00%]: m_0-575672e1-efe8-4964-b340-4a6116793ce6 request was accepted 2019-02-27 11:32:57,721 - INFO - 0/10 [10.00%]: m_1 requested negmas.sao.SAOMechanism[None] with ['c_0', 'm_1'] (ID 45a822bd-2729-4433-9ec8-6560a6f9d295) 2019-02-27 11:32:57,721 - INFO - 0/10 [10.00%]: m_1-153ac158-9a57-4bca-8296-bae6389d1ce1 request was accepted 2019-02-27 11:32:57,723 - INFO - 0/10 [10.00%]: m_2 requested negmas.sao.SAOMechanism[None] with ['c_0', 'm_2'] (ID fa63d399-4abd-443b-a837-808fa6dc2243) 2019-02-27 11:32:57,725 - INFO - 0/10 [10.00%]: m_2-84165933-f800-4373-8db2-96de0656eead request was accepted 2019-02-27 11:32:57,727 - INFO - 0/10 [10.00%]: m_3 requested negmas.sao.SAOMechanism[None] with ['c_0', 'm_3'] (ID 9f57ce7c-2391-4c30-b251-04298f3efd23) 2019-02-27 11:32:57,727 - INFO - 0/10 [10.00%]: m_3-57429f75-c75c-4cb4-a9b4-ca5c83d682d1 request was accepted 2019-02-27 11:32:57,729 - INFO - 0/10 [10.00%]: m_4 requested negmas.sao.SAOMechanism[None] with ['c_0', 'm_4'] (ID f6cf5457-5998-462e-bad2-4fe4cc161f6f) 2019-02-27 11:32:57,730 - INFO - 0/10 [10.00%]: m_4-839c8f96-e52b-40cd-a1ef-3bf468ec11cb request was accepted 2019-02-27 11:32:57,731 - INFO - 0/10 [10.00%]: m_0 requested negmas.sao.SAOMechanism[None] with ['c_0', 'm_0'] (ID 337916f8-99ad-4c0b-8f0c-3c1d5c61c7cd) 2019-02-27 11:32:57,732 - INFO - 0/10 [10.00%]: m_0-575672e1-efe8-4964-b340-4a6116793ce6 request was accepted 2019-02-27 11:32:57,733 - INFO - 0/10 [10.00%]: m_1 requested negmas.sao.SAOMechanism[None] with ['c_0', 'm_1'] (ID 03867f42-1742-4cb8-85e6-b552b7b52311) 2019-02-27 11:32:57,735 - INFO - 0/10 [10.00%]: m_1-153ac158-9a57-4bca-8296-bae6389d1ce1 request was accepted 2019-02-27 11:32:57,736 - INFO - 0/10 [10.00%]: m_2 requested negmas.sao.SAOMechanism[None] with ['c_0', 'm_2'] (ID 0b38565c-bc2d-4fe7-8182-48cf6473b0b9) 2019-02-27 11:32:57,737 - INFO - 0/10 [10.00%]: m_2-84165933-f800-4373-8db2-96de0656eead request was accepted 2019-02-27 11:32:57,738 - INFO - 0/10 [10.00%]: m_3 requested negmas.sao.SAOMechanism[None] with ['c_0', 'm_3'] (ID d1f6e3cb-ec10-47db-b754-17174e737971) 2019-02-27 11:32:57,740 - INFO - 0/10 [10.00%]: m_3-57429f75-c75c-4cb4-a9b4-ca5c83d682d1 request was accepted 2019-02-27 11:32:57,741 - INFO - 0/10 [10.00%]: m_4 requested negmas.sao.SAOMechanism[None] with ['c_0', 'm_4'] (ID 5ff6a635-e770-4d4e-aac8-0a2b5101a674) 2019-02-27 11:32:57,742 - INFO - 0/10 [10.00%]: m_4-839c8f96-e52b-40cd-a1ef-3bf468ec11cb request was accepted 2019-02-27 11:32:57,743 - INFO - 0/10 [10.00%]: m_0 requested negmas.sao.SAOMechanism[None] with ['c_0', 'm_0'] (ID cb697d90-84f9-4afc-83bd-483e9bf48b84) 2019-02-27 11:32:57,744 - INFO - 0/10 [10.00%]: m_0-575672e1-efe8-4964-b340-4a6116793ce6 request was accepted 2019-02-27 11:32:57,745 - INFO - 0/10 [10.00%]: m_1 requested negmas.sao.SAOMechanism[None] with ['c_0', 'm_1'] (ID 8be07c2c-6aa2-4858-ad62-ece34afb5dac) 2019-02-27 11:32:57,746 - INFO - 0/10 [10.00%]: m_1-153ac158-9a57-4bca-8296-bae6389d1ce1 request was accepted 2019-02-27 11:32:57,747 - INFO - 0/10 [10.00%]: m_2 requested negmas.sao.SAOMechanism[None] with ['c_0', 'm_2'] (ID 9770a1ef-5e2a-42e0-a43d-7c4987108e1a) 2019-02-27 11:32:57,748 - INFO - 0/10 [10.00%]: m_2-84165933-f800-4373-8db2-96de0656eead request was accepted 2019-02-27 11:32:57,751 - INFO - 0/10 [10.00%]: m_3 requested negmas.sao.SAOMechanism[None] with ['c_0', 'm_3'] (ID 00be927e-00fd-42d2-a0ff-b0f5df172621) 2019-02-27 11:32:57,752 - INFO - 0/10 [10.00%]: m_3-57429f75-c75c-4cb4-a9b4-ca5c83d682d1 request was accepted 2019-02-27 11:32:57,753 - INFO - 0/10 [10.00%]: m_4 requested negmas.sao.SAOMechanism[None] with ['c_0', 'm_4'] (ID 07210016-373e-4008-9651-1717849230c6) 2019-02-27 11:32:57,754 - INFO - 0/10 [10.00%]: m_4-839c8f96-e52b-40cd-a1ef-3bf468ec11cb request was accepted 2019-02-27 11:32:57,756 - INFO - 0/10 [10.00%]: m_0 requested negmas.sao.SAOMechanism[None] with ['c_2', 'm_0'] (ID 99dcf7f6-b177-4e08-9878-de48ddb031ca) 2019-02-27 11:32:57,756 - INFO - 0/10 [10.00%]: m_0-575672e1-efe8-4964-b340-4a6116793ce6 request was accepted 2019-02-27 11:32:57,758 - INFO - 0/10 [10.00%]: m_1 requested negmas.sao.SAOMechanism[None] with ['c_2', 'm_1'] (ID 837826ee-5c45-4bfc-b0ec-8017efb72d55) 2019-02-27 11:32:57,758 - INFO - 0/10 [10.00%]: m_1-153ac158-9a57-4bca-8296-bae6389d1ce1 request was accepted 2019-02-27 11:32:57,760 - INFO - 0/10 [10.00%]: m_2 requested negmas.sao.SAOMechanism[None] with ['c_2', 'm_2'] (ID 9f151a88-d3d3-4ec2-a01a-219627182c93) 2019-02-27 11:32:57,761 - INFO - 0/10 [10.00%]: m_2-84165933-f800-4373-8db2-96de0656eead request was accepted 2019-02-27 11:32:57,762 - INFO - 0/10 [10.00%]: m_3 requested negmas.sao.SAOMechanism[None] with ['c_2', 'm_3'] (ID 9795e309-d519-46da-b70a-ae60428832b2) 2019-02-27 11:32:57,763 - INFO - 0/10 [10.00%]: m_3-57429f75-c75c-4cb4-a9b4-ca5c83d682d1 request was accepted 2019-02-27 11:32:57,764 - INFO - 0/10 [10.00%]: m_4 requested negmas.sao.SAOMechanism[None] with ['c_2', 'm_4'] (ID 1540c362-d345-49e5-b8e5-18e928f998aa) 2019-02-27 11:32:57,764 - INFO - 0/10 [10.00%]: m_4-839c8f96-e52b-40cd-a1ef-3bf468ec11cb request was accepted 2019-02-27 11:32:57,766 - INFO - 0/10 [10.00%]: m_0 requested negmas.sao.SAOMechanism[None] with ['c_2', 'm_0'] (ID 31025c1c-d742-4e39-8d60-c568c5975307) 2019-02-27 11:32:57,768 - INFO - 0/10 [10.00%]: m_0-575672e1-efe8-4964-b340-4a6116793ce6 request was accepted 2019-02-27 11:32:57,769 - INFO - 0/10 [10.00%]: m_1 requested negmas.sao.SAOMechanism[None] with ['c_2', 'm_1'] (ID 311c6274-9b48-4be5-94c3-a1b555b091e9) 2019-02-27 11:32:57,770 - INFO - 0/10 [10.00%]: m_1-153ac158-9a57-4bca-8296-bae6389d1ce1 request was accepted 2019-02-27 11:32:57,771 - INFO - 0/10 [10.00%]: m_2 requested negmas.sao.SAOMechanism[None] with ['c_2', 'm_2'] (ID 34560848-8e88-41ff-a6fc-722fb203bbd8) 2019-02-27 11:32:57,773 - INFO - 0/10 [10.00%]: m_2-84165933-f800-4373-8db2-96de0656eead request was accepted 2019-02-27 11:32:57,774 - INFO - 0/10 [10.00%]: m_3 requested negmas.sao.SAOMechanism[None] with ['c_2', 'm_3'] (ID 85001363-addf-4ada-9aba-87e0827fef1d) 2019-02-27 11:32:57,775 - INFO - 0/10 [10.00%]: m_3-57429f75-c75c-4cb4-a9b4-ca5c83d682d1 request was accepted 2019-02-27 11:32:57,776 - INFO - 0/10 [10.00%]: m_4 requested negmas.sao.SAOMechanism[None] with ['c_2', 'm_4'] (ID 1d72f635-ea1e-4121-a4d6-6948ea7653af) 2019-02-27 11:32:57,777 - INFO - 0/10 [10.00%]: m_4-839c8f96-e52b-40cd-a1ef-3bf468ec11cb request was accepted 2019-02-27 11:32:57,778 - INFO - 0/10 [10.00%]: m_0 requested negmas.sao.SAOMechanism[None] with ['c_2', 'm_0'] (ID 05e9578e-d5f9-4644-8f56-e8054a3ee0c4) 2019-02-27 11:32:57,778 - INFO - 0/10 [10.00%]: m_0-575672e1-efe8-4964-b340-4a6116793ce6 request was accepted 2019-02-27 11:32:57,779 - INFO - 0/10 [10.00%]: m_1 requested negmas.sao.SAOMechanism[None] with ['c_2', 'm_1'] (ID 2184d0d2-e1ab-49d0-990d-3c47f1f7a525) 2019-02-27 11:32:57,780 - INFO - 0/10 [10.00%]: m_1-153ac158-9a57-4bca-8296-bae6389d1ce1 request was accepted 2019-02-27 11:32:57,781 - INFO - 0/10 [10.00%]: m_2 requested negmas.sao.SAOMechanism[None] with ['c_2', 'm_2'] (ID 9fff3837-7533-4558-9164-4be87f15639b) 2019-02-27 11:32:57,781 - INFO - 0/10 [10.00%]: m_2-84165933-f800-4373-8db2-96de0656eead request was accepted 2019-02-27 11:32:57,782 - INFO - 0/10 [10.00%]: m_3 requested negmas.sao.SAOMechanism[None] with ['c_2', 'm_3'] (ID 53b20657-262c-4d00-8064-c91644b68fb6) 2019-02-27 11:32:57,783 - INFO - 0/10 [10.00%]: m_3-57429f75-c75c-4cb4-a9b4-ca5c83d682d1 request was accepted 2019-02-27 11:32:57,785 - INFO - 0/10 [10.00%]: m_4 requested negmas.sao.SAOMechanism[None] with ['c_2', 'm_4'] (ID 8a8fae5d-0717-45fe-91c3-ab6bca95702e) 2019-02-27 11:32:57,785 - INFO - 0/10 [10.00%]: m_4-839c8f96-e52b-40cd-a1ef-3bf468ec11cb request was accepted 2019-02-27 11:32:57,787 - INFO - 0/10 [10.00%]: m_0 requested negmas.sao.SAOMechanism[None] with ['c_2', 'm_0'] (ID 370d2a6e-1e5b-47f3-9178-157e6abeafc2) 2019-02-27 11:32:57,787 - INFO - 0/10 [10.00%]: m_0-575672e1-efe8-4964-b340-4a6116793ce6 request was accepted 2019-02-27 11:32:57,788 - INFO - 0/10 [10.00%]: m_1 requested negmas.sao.SAOMechanism[None] with ['c_2', 'm_1'] (ID 0952b9da-e1c2-4912-a51d-0151b340638e) 2019-02-27 11:32:57,789 - INFO - 0/10 [10.00%]: m_1-153ac158-9a57-4bca-8296-bae6389d1ce1 request was accepted 2019-02-27 11:32:57,791 - INFO - 0/10 [10.00%]: m_2 requested negmas.sao.SAOMechanism[None] with ['c_2', 'm_2'] (ID b1a0dd37-a0a0-407d-9032-6ee9736e6168) 2019-02-27 11:32:57,791 - INFO - 0/10 [10.00%]: m_2-84165933-f800-4373-8db2-96de0656eead request was accepted 2019-02-27 11:32:57,792 - INFO - 0/10 [10.00%]: m_3 requested negmas.sao.SAOMechanism[None] with ['c_2', 'm_3'] (ID f7f5eb89-2137-4710-ad5f-6bf58c19fb49) 2019-02-27 11:32:57,793 - INFO - 0/10 [10.00%]: m_3-57429f75-c75c-4cb4-a9b4-ca5c83d682d1 request was accepted 2019-02-27 11:32:57,794 - INFO - 0/10 [10.00%]: m_4 requested negmas.sao.SAOMechanism[None] with ['c_2', 'm_4'] (ID a7a9c4e1-c23f-4b89-af9e-eedc76b475b9) 2019-02-27 11:32:57,794 - INFO - 0/10 [10.00%]: m_4-839c8f96-e52b-40cd-a1ef-3bf468ec11cb request was accepted 2019-02-27 11:32:57,794 - DEBUG - 0/10 [10.00%]: Factory 2b84599b-e538-4212-b349-d4a05459c15b: money=0, storage={}, loans=0.0 2019-02-27 11:32:57,795 - DEBUG - 0/10 [10.00%]: Factory fed30dd7-5bba-4df3-9386-c2570ef237d4: money=0, storage={}, loans=0.0 2019-02-27 11:32:57,795 - DEBUG - 0/10 [10.00%]: Factory 2b9215ac-5da4-4788-8222-002f92ac7b3c: money=0, storage={}, loans=0.0 2019-02-27 11:32:57,795 - DEBUG - 0/10 [10.00%]: Factory 1f8923b6-aef8-4008-a31c-b18482add390: money=0, storage={}, loans=0.0 2019-02-27 11:32:57,795 - DEBUG - 0/10 [10.00%]: Factory 30f40890-1d90-499c-87f7-ac48be226a56: money=0, storage={}, loans=0.0 2019-02-27 11:32:57,795 - DEBUG - 0/10 [10.00%]: Factory f6c073fa-9343-49a7-b738-ccd0b9381c40: money=0.0, storage={}, loans=0.0 2019-02-27 11:32:57,795 - DEBUG - 0/10 [10.00%]: Factory 62cc9ee6-9600-42d1-83dd-216923d114b1: money=0.0, storage={}, loans=0.0 2019-02-27 11:32:57,795 - DEBUG - 0/10 [10.00%]: Factory e11f4f3c-15a1-461a-bd2c-632e07f82b5f: money=0.0, storage={}, loans=0.0 2019-02-27 11:32:57,795 - DEBUG - 0/10 [10.00%]: Factory 3583ffd0-fef8-4a83-be5d-0fa6562d4c9f: money=0.0, storage={}, loans=0.0 2019-02-27 11:32:57,795 - DEBUG - 0/10 [10.00%]: Factory eb0d4726-61b8-4266-8c97-4416e5746a6f: money=0.0, storage={}, loans=0.0 2019-02-27 11:32:57,796 - INFO - 1/10 [20.00%]: 100 Negotiations/4 _entities 2019-02-27 11:32:58,696 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_3', 'm_2'] > {'time': 3, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_3-ef402340-68d6-404a-8c4f-8ec5bead3987: buy 0 (t: 3, u: (0, 2.0), q: (1, 3))', 'partners': "['c_3-ef402340-68d6-404a-8c4f-8ec5bead3987', 'm_2-84165933-f800-4373-8db2-96de0656eead']", 'seller': 'm_2-84165933-f800-4373-8db2-96de0656eead', 'buyer': 'c_3-ef402340-68d6-404a-8c4f-8ec5bead3987'} 2019-02-27 11:32:58,700 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_1', 'm_2'] > {'time': 1, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_1-48b66a5d-80de-4f52-99f0-f2f3af13d7a3: buy 0 (t: 1, u: (0, 2.0), q: (1, 4))', 'partners': "['c_1-48b66a5d-80de-4f52-99f0-f2f3af13d7a3', 'm_2-84165933-f800-4373-8db2-96de0656eead']", 'seller': 'm_2-84165933-f800-4373-8db2-96de0656eead', 'buyer': 'c_1-48b66a5d-80de-4f52-99f0-f2f3af13d7a3'} 2019-02-27 11:32:58,701 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_4', 'm_4'] > {'time': 3, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_4-70a6b468-fb6c-4fd2-b7da-c47f020247d6: buy 0 (t: 3, u: (0, 2.0), q: (1, 4))', 'partners': "['c_4-70a6b468-fb6c-4fd2-b7da-c47f020247d6', 'm_4-839c8f96-e52b-40cd-a1ef-3bf468ec11cb']", 'seller': 'm_4-839c8f96-e52b-40cd-a1ef-3bf468ec11cb', 'buyer': 'c_4-70a6b468-fb6c-4fd2-b7da-c47f020247d6'} 2019-02-27 11:32:58,702 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_3', 'm_4'] > {'time': 1, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_3-ef402340-68d6-404a-8c4f-8ec5bead3987: buy 0 (t: 1, u: (0, 2.0), q: (1, 3))', 'partners': "['c_3-ef402340-68d6-404a-8c4f-8ec5bead3987', 'm_4-839c8f96-e52b-40cd-a1ef-3bf468ec11cb']", 'seller': 'm_4-839c8f96-e52b-40cd-a1ef-3bf468ec11cb', 'buyer': 'c_3-ef402340-68d6-404a-8c4f-8ec5bead3987'} 2019-02-27 11:32:58,703 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_1', 'm_0'] > {'time': 3, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_1-48b66a5d-80de-4f52-99f0-f2f3af13d7a3: buy 0 (t: 3, u: (0, 2.0), q: (1, 4))', 'partners': "['c_1-48b66a5d-80de-4f52-99f0-f2f3af13d7a3', 'm_0-575672e1-efe8-4964-b340-4a6116793ce6']", 'seller': 'm_0-575672e1-efe8-4964-b340-4a6116793ce6', 'buyer': 'c_1-48b66a5d-80de-4f52-99f0-f2f3af13d7a3'} 2019-02-27 11:32:58,705 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_2', 'm_2'] > {'time': 4, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_2-88fd8b76-1040-4e98-b476-5e965b64b2fb: buy 0 (t: 4, u: (0, 2.0), q: (1, 4))', 'partners': "['c_2-88fd8b76-1040-4e98-b476-5e965b64b2fb', 'm_2-84165933-f800-4373-8db2-96de0656eead']", 'seller': 'm_2-84165933-f800-4373-8db2-96de0656eead', 'buyer': 'c_2-88fd8b76-1040-4e98-b476-5e965b64b2fb'} 2019-02-27 11:32:58,706 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_1', 'm_2'] > {'time': 3, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_1-48b66a5d-80de-4f52-99f0-f2f3af13d7a3: buy 0 (t: 3, u: (0, 2.0), q: (1, 4))', 'partners': "['c_1-48b66a5d-80de-4f52-99f0-f2f3af13d7a3', 'm_2-84165933-f800-4373-8db2-96de0656eead']", 'seller': 'm_2-84165933-f800-4373-8db2-96de0656eead', 'buyer': 'c_1-48b66a5d-80de-4f52-99f0-f2f3af13d7a3'} 2019-02-27 11:32:58,708 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_1', 'm_3'] > {'time': 4, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_1-48b66a5d-80de-4f52-99f0-f2f3af13d7a3: buy 0 (t: 4, u: (0, 2.0), q: (1, 3))', 'partners': "['c_1-48b66a5d-80de-4f52-99f0-f2f3af13d7a3', 'm_3-57429f75-c75c-4cb4-a9b4-ca5c83d682d1']", 'seller': 'm_3-57429f75-c75c-4cb4-a9b4-ca5c83d682d1', 'buyer': 'c_1-48b66a5d-80de-4f52-99f0-f2f3af13d7a3'} 2019-02-27 11:32:58,709 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_2', 'm_3'] > {'time': 3, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_2-88fd8b76-1040-4e98-b476-5e965b64b2fb: buy 0 (t: 3, u: (0, 2.0), q: (1, 3))', 'partners': "['c_2-88fd8b76-1040-4e98-b476-5e965b64b2fb', 'm_3-57429f75-c75c-4cb4-a9b4-ca5c83d682d1']", 'seller': 'm_3-57429f75-c75c-4cb4-a9b4-ca5c83d682d1', 'buyer': 'c_2-88fd8b76-1040-4e98-b476-5e965b64b2fb'} 2019-02-27 11:32:58,709 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_0', 'm_3'] > {'time': 4, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_0-3998ad31-d504-4b35-bb85-3be6197f1ea0: buy 0 (t: 4, u: (0, 2.0), q: (1, 4))', 'partners': "['c_0-3998ad31-d504-4b35-bb85-3be6197f1ea0', 'm_3-57429f75-c75c-4cb4-a9b4-ca5c83d682d1']", 'seller': 'm_3-57429f75-c75c-4cb4-a9b4-ca5c83d682d1', 'buyer': 'c_0-3998ad31-d504-4b35-bb85-3be6197f1ea0'} 2019-02-27 11:32:58,710 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_0', 'm_2'] > {'time': 1, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_0-3998ad31-d504-4b35-bb85-3be6197f1ea0: buy 0 (t: 1, u: (0, 2.0), q: (1, 4))', 'partners': "['c_0-3998ad31-d504-4b35-bb85-3be6197f1ea0', 'm_2-84165933-f800-4373-8db2-96de0656eead']", 'seller': 'm_2-84165933-f800-4373-8db2-96de0656eead', 'buyer': 'c_0-3998ad31-d504-4b35-bb85-3be6197f1ea0'} 2019-02-27 11:32:58,711 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_3', 'm_0'] > {'time': 2, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_3-ef402340-68d6-404a-8c4f-8ec5bead3987: buy 0 (t: 2, u: (0, 2.0), q: (1, 4))', 'partners': "['c_3-ef402340-68d6-404a-8c4f-8ec5bead3987', 'm_0-575672e1-efe8-4964-b340-4a6116793ce6']", 'seller': 'm_0-575672e1-efe8-4964-b340-4a6116793ce6', 'buyer': 'c_3-ef402340-68d6-404a-8c4f-8ec5bead3987'} 2019-02-27 11:32:58,711 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_1', 'm_4'] > {'time': 1, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_1-48b66a5d-80de-4f52-99f0-f2f3af13d7a3: buy 0 (t: 1, u: (0, 2.0), q: (1, 4))', 'partners': "['c_1-48b66a5d-80de-4f52-99f0-f2f3af13d7a3', 'm_4-839c8f96-e52b-40cd-a1ef-3bf468ec11cb']", 'seller': 'm_4-839c8f96-e52b-40cd-a1ef-3bf468ec11cb', 'buyer': 'c_1-48b66a5d-80de-4f52-99f0-f2f3af13d7a3'} 2019-02-27 11:32:58,712 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_4', 'm_1'] > {'time': 3, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_4-70a6b468-fb6c-4fd2-b7da-c47f020247d6: buy 0 (t: 3, u: (0, 2.0), q: (1, 4))', 'partners': "['c_4-70a6b468-fb6c-4fd2-b7da-c47f020247d6', 'm_1-153ac158-9a57-4bca-8296-bae6389d1ce1']", 'seller': 'm_1-153ac158-9a57-4bca-8296-bae6389d1ce1', 'buyer': 'c_4-70a6b468-fb6c-4fd2-b7da-c47f020247d6'} 2019-02-27 11:32:58,712 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_2', 'm_0'] > {'time': 1, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_2-88fd8b76-1040-4e98-b476-5e965b64b2fb: buy 0 (t: 1, u: (0, 2.0), q: (1, 3))', 'partners': "['c_2-88fd8b76-1040-4e98-b476-5e965b64b2fb', 'm_0-575672e1-efe8-4964-b340-4a6116793ce6']", 'seller': 'm_0-575672e1-efe8-4964-b340-4a6116793ce6', 'buyer': 'c_2-88fd8b76-1040-4e98-b476-5e965b64b2fb'} 2019-02-27 11:32:58,712 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_0', 'm_3'] > {'time': 3, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_0-3998ad31-d504-4b35-bb85-3be6197f1ea0: buy 0 (t: 3, u: (0, 2.0), q: (1, 3))', 'partners': "['c_0-3998ad31-d504-4b35-bb85-3be6197f1ea0', 'm_3-57429f75-c75c-4cb4-a9b4-ca5c83d682d1']", 'seller': 'm_3-57429f75-c75c-4cb4-a9b4-ca5c83d682d1', 'buyer': 'c_0-3998ad31-d504-4b35-bb85-3be6197f1ea0'} 2019-02-27 11:32:58,713 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_0', 'm_3'] > {'time': 2, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_0-3998ad31-d504-4b35-bb85-3be6197f1ea0: buy 0 (t: 2, u: (0, 2.0), q: (1, 4))', 'partners': "['c_0-3998ad31-d504-4b35-bb85-3be6197f1ea0', 'm_3-57429f75-c75c-4cb4-a9b4-ca5c83d682d1']", 'seller': 'm_3-57429f75-c75c-4cb4-a9b4-ca5c83d682d1', 'buyer': 'c_0-3998ad31-d504-4b35-bb85-3be6197f1ea0'} 2019-02-27 11:32:58,713 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_1', 'm_2'] > {'time': 4, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_1-48b66a5d-80de-4f52-99f0-f2f3af13d7a3: buy 0 (t: 4, u: (0, 2.0), q: (1, 3))', 'partners': "['c_1-48b66a5d-80de-4f52-99f0-f2f3af13d7a3', 'm_2-84165933-f800-4373-8db2-96de0656eead']", 'seller': 'm_2-84165933-f800-4373-8db2-96de0656eead', 'buyer': 'c_1-48b66a5d-80de-4f52-99f0-f2f3af13d7a3'} 2019-02-27 11:32:58,713 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_1', 'm_1'] > {'time': 1, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_1-48b66a5d-80de-4f52-99f0-f2f3af13d7a3: buy 0 (t: 1, u: (0, 2.0), q: (1, 4))', 'partners': "['c_1-48b66a5d-80de-4f52-99f0-f2f3af13d7a3', 'm_1-153ac158-9a57-4bca-8296-bae6389d1ce1']", 'seller': 'm_1-153ac158-9a57-4bca-8296-bae6389d1ce1', 'buyer': 'c_1-48b66a5d-80de-4f52-99f0-f2f3af13d7a3'} 2019-02-27 11:32:58,714 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_2', 'm_0'] > {'time': 4, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_2-88fd8b76-1040-4e98-b476-5e965b64b2fb: buy 0 (t: 4, u: (0, 2.0), q: (1, 4))', 'partners': "['c_2-88fd8b76-1040-4e98-b476-5e965b64b2fb', 'm_0-575672e1-efe8-4964-b340-4a6116793ce6']", 'seller': 'm_0-575672e1-efe8-4964-b340-4a6116793ce6', 'buyer': 'c_2-88fd8b76-1040-4e98-b476-5e965b64b2fb'} 2019-02-27 11:32:58,714 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_0', 'm_4'] > {'time': 4, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_0-3998ad31-d504-4b35-bb85-3be6197f1ea0: buy 0 (t: 4, u: (0, 2.0), q: (1, 4))', 'partners': "['c_0-3998ad31-d504-4b35-bb85-3be6197f1ea0', 'm_4-839c8f96-e52b-40cd-a1ef-3bf468ec11cb']", 'seller': 'm_4-839c8f96-e52b-40cd-a1ef-3bf468ec11cb', 'buyer': 'c_0-3998ad31-d504-4b35-bb85-3be6197f1ea0'} 2019-02-27 11:32:58,715 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_1', 'm_2'] > {'time': 2, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_1-48b66a5d-80de-4f52-99f0-f2f3af13d7a3: buy 0 (t: 2, u: (0, 2.0), q: (1, 3))', 'partners': "['c_1-48b66a5d-80de-4f52-99f0-f2f3af13d7a3', 'm_2-84165933-f800-4373-8db2-96de0656eead']", 'seller': 'm_2-84165933-f800-4373-8db2-96de0656eead', 'buyer': 'c_1-48b66a5d-80de-4f52-99f0-f2f3af13d7a3'} 2019-02-27 11:32:58,716 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_2', 'm_2'] > {'time': 2, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_2-88fd8b76-1040-4e98-b476-5e965b64b2fb: buy 0 (t: 2, u: (0, 2.0), q: (1, 4))', 'partners': "['c_2-88fd8b76-1040-4e98-b476-5e965b64b2fb', 'm_2-84165933-f800-4373-8db2-96de0656eead']", 'seller': 'm_2-84165933-f800-4373-8db2-96de0656eead', 'buyer': 'c_2-88fd8b76-1040-4e98-b476-5e965b64b2fb'} 2019-02-27 11:32:58,716 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_0', 'm_0'] > {'time': 2, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_0-3998ad31-d504-4b35-bb85-3be6197f1ea0: buy 0 (t: 2, u: (0, 2.0), q: (1, 4))', 'partners': "['c_0-3998ad31-d504-4b35-bb85-3be6197f1ea0', 'm_0-575672e1-efe8-4964-b340-4a6116793ce6']", 'seller': 'm_0-575672e1-efe8-4964-b340-4a6116793ce6', 'buyer': 'c_0-3998ad31-d504-4b35-bb85-3be6197f1ea0'} 2019-02-27 11:32:58,717 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_1', 'm_3'] > {'time': 3, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_1-48b66a5d-80de-4f52-99f0-f2f3af13d7a3: buy 0 (t: 3, u: (0, 2.0), q: (1, 4))', 'partners': "['c_1-48b66a5d-80de-4f52-99f0-f2f3af13d7a3', 'm_3-57429f75-c75c-4cb4-a9b4-ca5c83d682d1']", 'seller': 'm_3-57429f75-c75c-4cb4-a9b4-ca5c83d682d1', 'buyer': 'c_1-48b66a5d-80de-4f52-99f0-f2f3af13d7a3'} 2019-02-27 11:32:58,718 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_2', 'm_3'] > {'time': 2, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_2-88fd8b76-1040-4e98-b476-5e965b64b2fb: buy 0 (t: 2, u: (0, 2.0), q: (1, 4))', 'partners': "['c_2-88fd8b76-1040-4e98-b476-5e965b64b2fb', 'm_3-57429f75-c75c-4cb4-a9b4-ca5c83d682d1']", 'seller': 'm_3-57429f75-c75c-4cb4-a9b4-ca5c83d682d1', 'buyer': 'c_2-88fd8b76-1040-4e98-b476-5e965b64b2fb'} 2019-02-27 11:32:58,719 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_4', 'm_4'] > {'time': 2, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_4-70a6b468-fb6c-4fd2-b7da-c47f020247d6: buy 0 (t: 2, u: (0, 2.0), q: (1, 3))', 'partners': "['c_4-70a6b468-fb6c-4fd2-b7da-c47f020247d6', 'm_4-839c8f96-e52b-40cd-a1ef-3bf468ec11cb']", 'seller': 'm_4-839c8f96-e52b-40cd-a1ef-3bf468ec11cb', 'buyer': 'c_4-70a6b468-fb6c-4fd2-b7da-c47f020247d6'} 2019-02-27 11:32:58,719 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_0', 'm_1'] > {'time': 3, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_0-3998ad31-d504-4b35-bb85-3be6197f1ea0: buy 0 (t: 3, u: (0, 2.0), q: (1, 3))', 'partners': "['c_0-3998ad31-d504-4b35-bb85-3be6197f1ea0', 'm_1-153ac158-9a57-4bca-8296-bae6389d1ce1']", 'seller': 'm_1-153ac158-9a57-4bca-8296-bae6389d1ce1', 'buyer': 'c_0-3998ad31-d504-4b35-bb85-3be6197f1ea0'} 2019-02-27 11:32:58,720 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_0', 'm_2'] > {'time': 3, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_0-3998ad31-d504-4b35-bb85-3be6197f1ea0: buy 0 (t: 3, u: (0, 2.0), q: (1, 3))', 'partners': "['c_0-3998ad31-d504-4b35-bb85-3be6197f1ea0', 'm_2-84165933-f800-4373-8db2-96de0656eead']", 'seller': 'm_2-84165933-f800-4373-8db2-96de0656eead', 'buyer': 'c_0-3998ad31-d504-4b35-bb85-3be6197f1ea0'} 2019-02-27 11:32:58,720 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_3', 'm_4'] > {'time': 4, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_3-ef402340-68d6-404a-8c4f-8ec5bead3987: buy 0 (t: 4, u: (0, 2.0), q: (1, 3))', 'partners': "['c_3-ef402340-68d6-404a-8c4f-8ec5bead3987', 'm_4-839c8f96-e52b-40cd-a1ef-3bf468ec11cb']", 'seller': 'm_4-839c8f96-e52b-40cd-a1ef-3bf468ec11cb', 'buyer': 'c_3-ef402340-68d6-404a-8c4f-8ec5bead3987'} 2019-02-27 11:32:58,721 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_4', 'm_3'] > {'time': 3, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_4-70a6b468-fb6c-4fd2-b7da-c47f020247d6: buy 0 (t: 3, u: (0, 2.0), q: (1, 4))', 'partners': "['c_4-70a6b468-fb6c-4fd2-b7da-c47f020247d6', 'm_3-57429f75-c75c-4cb4-a9b4-ca5c83d682d1']", 'seller': 'm_3-57429f75-c75c-4cb4-a9b4-ca5c83d682d1', 'buyer': 'c_4-70a6b468-fb6c-4fd2-b7da-c47f020247d6'} 2019-02-27 11:32:58,722 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_2', 'm_4'] > {'time': 2, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_2-88fd8b76-1040-4e98-b476-5e965b64b2fb: buy 0 (t: 2, u: (0, 2.0), q: (1, 4))', 'partners': "['c_2-88fd8b76-1040-4e98-b476-5e965b64b2fb', 'm_4-839c8f96-e52b-40cd-a1ef-3bf468ec11cb']", 'seller': 'm_4-839c8f96-e52b-40cd-a1ef-3bf468ec11cb', 'buyer': 'c_2-88fd8b76-1040-4e98-b476-5e965b64b2fb'} 2019-02-27 11:32:58,723 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_3', 'm_3'] > {'time': 2, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_3-ef402340-68d6-404a-8c4f-8ec5bead3987: buy 0 (t: 2, u: (0, 2.0), q: (1, 4))', 'partners': "['c_3-ef402340-68d6-404a-8c4f-8ec5bead3987', 'm_3-57429f75-c75c-4cb4-a9b4-ca5c83d682d1']", 'seller': 'm_3-57429f75-c75c-4cb4-a9b4-ca5c83d682d1', 'buyer': 'c_3-ef402340-68d6-404a-8c4f-8ec5bead3987'} 2019-02-27 11:32:58,724 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_4', 'm_0'] > {'time': 2, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_4-70a6b468-fb6c-4fd2-b7da-c47f020247d6: buy 0 (t: 2, u: (0, 2.0), q: (1, 3))', 'partners': "['c_4-70a6b468-fb6c-4fd2-b7da-c47f020247d6', 'm_0-575672e1-efe8-4964-b340-4a6116793ce6']", 'seller': 'm_0-575672e1-efe8-4964-b340-4a6116793ce6', 'buyer': 'c_4-70a6b468-fb6c-4fd2-b7da-c47f020247d6'} 2019-02-27 11:32:58,725 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_2', 'm_0'] > {'time': 2, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_2-88fd8b76-1040-4e98-b476-5e965b64b2fb: buy 0 (t: 2, u: (0, 2.0), q: (1, 4))', 'partners': "['c_2-88fd8b76-1040-4e98-b476-5e965b64b2fb', 'm_0-575672e1-efe8-4964-b340-4a6116793ce6']", 'seller': 'm_0-575672e1-efe8-4964-b340-4a6116793ce6', 'buyer': 'c_2-88fd8b76-1040-4e98-b476-5e965b64b2fb'} 2019-02-27 11:32:58,725 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_4', 'm_2'] > {'time': 4, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_4-70a6b468-fb6c-4fd2-b7da-c47f020247d6: buy 0 (t: 4, u: (0, 2.0), q: (1, 4))', 'partners': "['c_4-70a6b468-fb6c-4fd2-b7da-c47f020247d6', 'm_2-84165933-f800-4373-8db2-96de0656eead']", 'seller': 'm_2-84165933-f800-4373-8db2-96de0656eead', 'buyer': 'c_4-70a6b468-fb6c-4fd2-b7da-c47f020247d6'} 2019-02-27 11:32:58,725 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_3', 'm_1'] > {'time': 4, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_3-ef402340-68d6-404a-8c4f-8ec5bead3987: buy 0 (t: 4, u: (0, 2.0), q: (1, 3))', 'partners': "['c_3-ef402340-68d6-404a-8c4f-8ec5bead3987', 'm_1-153ac158-9a57-4bca-8296-bae6389d1ce1']", 'seller': 'm_1-153ac158-9a57-4bca-8296-bae6389d1ce1', 'buyer': 'c_3-ef402340-68d6-404a-8c4f-8ec5bead3987'} 2019-02-27 11:32:58,726 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_3', 'm_3'] > {'time': 4, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_3-ef402340-68d6-404a-8c4f-8ec5bead3987: buy 0 (t: 4, u: (0, 2.0), q: (1, 3))', 'partners': "['c_3-ef402340-68d6-404a-8c4f-8ec5bead3987', 'm_3-57429f75-c75c-4cb4-a9b4-ca5c83d682d1']", 'seller': 'm_3-57429f75-c75c-4cb4-a9b4-ca5c83d682d1', 'buyer': 'c_3-ef402340-68d6-404a-8c4f-8ec5bead3987'} 2019-02-27 11:32:58,726 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_3', 'm_2'] > {'time': 4, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_3-ef402340-68d6-404a-8c4f-8ec5bead3987: buy 0 (t: 4, u: (0, 2.0), q: (1, 3))', 'partners': "['c_3-ef402340-68d6-404a-8c4f-8ec5bead3987', 'm_2-84165933-f800-4373-8db2-96de0656eead']", 'seller': 'm_2-84165933-f800-4373-8db2-96de0656eead', 'buyer': 'c_3-ef402340-68d6-404a-8c4f-8ec5bead3987'} 2019-02-27 11:32:58,726 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_2', 'm_2'] > {'time': 1, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_2-88fd8b76-1040-4e98-b476-5e965b64b2fb: buy 0 (t: 1, u: (0, 2.0), q: (1, 3))', 'partners': "['c_2-88fd8b76-1040-4e98-b476-5e965b64b2fb', 'm_2-84165933-f800-4373-8db2-96de0656eead']", 'seller': 'm_2-84165933-f800-4373-8db2-96de0656eead', 'buyer': 'c_2-88fd8b76-1040-4e98-b476-5e965b64b2fb'} 2019-02-27 11:32:58,727 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_1', 'm_4'] > {'time': 4, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_1-48b66a5d-80de-4f52-99f0-f2f3af13d7a3: buy 0 (t: 4, u: (0, 2.0), q: (1, 3))', 'partners': "['c_1-48b66a5d-80de-4f52-99f0-f2f3af13d7a3', 'm_4-839c8f96-e52b-40cd-a1ef-3bf468ec11cb']", 'seller': 'm_4-839c8f96-e52b-40cd-a1ef-3bf468ec11cb', 'buyer': 'c_1-48b66a5d-80de-4f52-99f0-f2f3af13d7a3'} 2019-02-27 11:32:58,727 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_4', 'm_3'] > {'time': 4, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_4-70a6b468-fb6c-4fd2-b7da-c47f020247d6: buy 0 (t: 4, u: (0, 2.0), q: (1, 4))', 'partners': "['c_4-70a6b468-fb6c-4fd2-b7da-c47f020247d6', 'm_3-57429f75-c75c-4cb4-a9b4-ca5c83d682d1']", 'seller': 'm_3-57429f75-c75c-4cb4-a9b4-ca5c83d682d1', 'buyer': 'c_4-70a6b468-fb6c-4fd2-b7da-c47f020247d6'} 2019-02-27 11:32:58,727 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_0', 'm_4'] > {'time': 3, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_0-3998ad31-d504-4b35-bb85-3be6197f1ea0: buy 0 (t: 3, u: (0, 2.0), q: (1, 3))', 'partners': "['c_0-3998ad31-d504-4b35-bb85-3be6197f1ea0', 'm_4-839c8f96-e52b-40cd-a1ef-3bf468ec11cb']", 'seller': 'm_4-839c8f96-e52b-40cd-a1ef-3bf468ec11cb', 'buyer': 'c_0-3998ad31-d504-4b35-bb85-3be6197f1ea0'} 2019-02-27 11:32:58,728 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_1', 'm_4'] > {'time': 2, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_1-48b66a5d-80de-4f52-99f0-f2f3af13d7a3: buy 0 (t: 2, u: (0, 2.0), q: (1, 3))', 'partners': "['c_1-48b66a5d-80de-4f52-99f0-f2f3af13d7a3', 'm_4-839c8f96-e52b-40cd-a1ef-3bf468ec11cb']", 'seller': 'm_4-839c8f96-e52b-40cd-a1ef-3bf468ec11cb', 'buyer': 'c_1-48b66a5d-80de-4f52-99f0-f2f3af13d7a3'} 2019-02-27 11:32:58,728 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_1', 'm_0'] > {'time': 2, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_1-48b66a5d-80de-4f52-99f0-f2f3af13d7a3: buy 0 (t: 2, u: (0, 2.0), q: (1, 3))', 'partners': "['c_1-48b66a5d-80de-4f52-99f0-f2f3af13d7a3', 'm_0-575672e1-efe8-4964-b340-4a6116793ce6']", 'seller': 'm_0-575672e1-efe8-4964-b340-4a6116793ce6', 'buyer': 'c_1-48b66a5d-80de-4f52-99f0-f2f3af13d7a3'} 2019-02-27 11:32:58,728 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_0', 'm_2'] > {'time': 2, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_0-3998ad31-d504-4b35-bb85-3be6197f1ea0: buy 0 (t: 2, u: (0, 2.0), q: (1, 4))', 'partners': "['c_0-3998ad31-d504-4b35-bb85-3be6197f1ea0', 'm_2-84165933-f800-4373-8db2-96de0656eead']", 'seller': 'm_2-84165933-f800-4373-8db2-96de0656eead', 'buyer': 'c_0-3998ad31-d504-4b35-bb85-3be6197f1ea0'} 2019-02-27 11:32:58,729 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_0', 'm_4'] > {'time': 1, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_0-3998ad31-d504-4b35-bb85-3be6197f1ea0: buy 0 (t: 1, u: (0, 2.0), q: (1, 4))', 'partners': "['c_0-3998ad31-d504-4b35-bb85-3be6197f1ea0', 'm_4-839c8f96-e52b-40cd-a1ef-3bf468ec11cb']", 'seller': 'm_4-839c8f96-e52b-40cd-a1ef-3bf468ec11cb', 'buyer': 'c_0-3998ad31-d504-4b35-bb85-3be6197f1ea0'} 2019-02-27 11:32:58,729 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_2', 'm_3'] > {'time': 1, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_2-88fd8b76-1040-4e98-b476-5e965b64b2fb: buy 0 (t: 1, u: (0, 2.0), q: (1, 3))', 'partners': "['c_2-88fd8b76-1040-4e98-b476-5e965b64b2fb', 'm_3-57429f75-c75c-4cb4-a9b4-ca5c83d682d1']", 'seller': 'm_3-57429f75-c75c-4cb4-a9b4-ca5c83d682d1', 'buyer': 'c_2-88fd8b76-1040-4e98-b476-5e965b64b2fb'} 2019-02-27 11:32:58,730 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_2', 'm_0'] > {'time': 3, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_2-88fd8b76-1040-4e98-b476-5e965b64b2fb: buy 0 (t: 3, u: (0, 2.0), q: (1, 3))', 'partners': "['c_2-88fd8b76-1040-4e98-b476-5e965b64b2fb', 'm_0-575672e1-efe8-4964-b340-4a6116793ce6']", 'seller': 'm_0-575672e1-efe8-4964-b340-4a6116793ce6', 'buyer': 'c_2-88fd8b76-1040-4e98-b476-5e965b64b2fb'} 2019-02-27 11:32:58,730 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_4', 'm_2'] > {'time': 1, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_4-70a6b468-fb6c-4fd2-b7da-c47f020247d6: buy 0 (t: 1, u: (0, 2.0), q: (1, 4))', 'partners': "['c_4-70a6b468-fb6c-4fd2-b7da-c47f020247d6', 'm_2-84165933-f800-4373-8db2-96de0656eead']", 'seller': 'm_2-84165933-f800-4373-8db2-96de0656eead', 'buyer': 'c_4-70a6b468-fb6c-4fd2-b7da-c47f020247d6'} 2019-02-27 11:32:58,731 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_0', 'm_2'] > {'time': 4, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_0-3998ad31-d504-4b35-bb85-3be6197f1ea0: buy 0 (t: 4, u: (0, 2.0), q: (1, 4))', 'partners': "['c_0-3998ad31-d504-4b35-bb85-3be6197f1ea0', 'm_2-84165933-f800-4373-8db2-96de0656eead']", 'seller': 'm_2-84165933-f800-4373-8db2-96de0656eead', 'buyer': 'c_0-3998ad31-d504-4b35-bb85-3be6197f1ea0'} 2019-02-27 11:32:58,731 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_1', 'm_3'] > {'time': 2, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_1-48b66a5d-80de-4f52-99f0-f2f3af13d7a3: buy 0 (t: 2, u: (0, 2.0), q: (1, 3))', 'partners': "['c_1-48b66a5d-80de-4f52-99f0-f2f3af13d7a3', 'm_3-57429f75-c75c-4cb4-a9b4-ca5c83d682d1']", 'seller': 'm_3-57429f75-c75c-4cb4-a9b4-ca5c83d682d1', 'buyer': 'c_1-48b66a5d-80de-4f52-99f0-f2f3af13d7a3'} 2019-02-27 11:32:58,732 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_0', 'm_0'] > {'time': 4, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_0-3998ad31-d504-4b35-bb85-3be6197f1ea0: buy 0 (t: 4, u: (0, 2.0), q: (1, 4))', 'partners': "['c_0-3998ad31-d504-4b35-bb85-3be6197f1ea0', 'm_0-575672e1-efe8-4964-b340-4a6116793ce6']", 'seller': 'm_0-575672e1-efe8-4964-b340-4a6116793ce6', 'buyer': 'c_0-3998ad31-d504-4b35-bb85-3be6197f1ea0'} 2019-02-27 11:32:58,732 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_3', 'm_2'] > {'time': 1, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_3-ef402340-68d6-404a-8c4f-8ec5bead3987: buy 0 (t: 1, u: (0, 2.0), q: (1, 3))', 'partners': "['c_3-ef402340-68d6-404a-8c4f-8ec5bead3987', 'm_2-84165933-f800-4373-8db2-96de0656eead']", 'seller': 'm_2-84165933-f800-4373-8db2-96de0656eead', 'buyer': 'c_3-ef402340-68d6-404a-8c4f-8ec5bead3987'} 2019-02-27 11:32:58,732 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_4', 'm_1'] > {'time': 2, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_4-70a6b468-fb6c-4fd2-b7da-c47f020247d6: buy 0 (t: 2, u: (0, 2.0), q: (1, 3))', 'partners': "['c_4-70a6b468-fb6c-4fd2-b7da-c47f020247d6', 'm_1-153ac158-9a57-4bca-8296-bae6389d1ce1']", 'seller': 'm_1-153ac158-9a57-4bca-8296-bae6389d1ce1', 'buyer': 'c_4-70a6b468-fb6c-4fd2-b7da-c47f020247d6'} 2019-02-27 11:32:58,732 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_3', 'm_0'] > {'time': 1, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_3-ef402340-68d6-404a-8c4f-8ec5bead3987: buy 0 (t: 1, u: (0, 2.0), q: (1, 3))', 'partners': "['c_3-ef402340-68d6-404a-8c4f-8ec5bead3987', 'm_0-575672e1-efe8-4964-b340-4a6116793ce6']", 'seller': 'm_0-575672e1-efe8-4964-b340-4a6116793ce6', 'buyer': 'c_3-ef402340-68d6-404a-8c4f-8ec5bead3987'} 2019-02-27 11:32:58,733 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_3', 'm_1'] > {'time': 2, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_3-ef402340-68d6-404a-8c4f-8ec5bead3987: buy 0 (t: 2, u: (0, 2.0), q: (1, 4))', 'partners': "['c_3-ef402340-68d6-404a-8c4f-8ec5bead3987', 'm_1-153ac158-9a57-4bca-8296-bae6389d1ce1']", 'seller': 'm_1-153ac158-9a57-4bca-8296-bae6389d1ce1', 'buyer': 'c_3-ef402340-68d6-404a-8c4f-8ec5bead3987'} 2019-02-27 11:32:58,733 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_4', 'm_0'] > {'time': 4, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_4-70a6b468-fb6c-4fd2-b7da-c47f020247d6: buy 0 (t: 4, u: (0, 2.0), q: (1, 4))', 'partners': "['c_4-70a6b468-fb6c-4fd2-b7da-c47f020247d6', 'm_0-575672e1-efe8-4964-b340-4a6116793ce6']", 'seller': 'm_0-575672e1-efe8-4964-b340-4a6116793ce6', 'buyer': 'c_4-70a6b468-fb6c-4fd2-b7da-c47f020247d6'} 2019-02-27 11:32:58,734 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_1', 'm_3'] > {'time': 1, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_1-48b66a5d-80de-4f52-99f0-f2f3af13d7a3: buy 0 (t: 1, u: (0, 2.0), q: (1, 4))', 'partners': "['c_1-48b66a5d-80de-4f52-99f0-f2f3af13d7a3', 'm_3-57429f75-c75c-4cb4-a9b4-ca5c83d682d1']", 'seller': 'm_3-57429f75-c75c-4cb4-a9b4-ca5c83d682d1', 'buyer': 'c_1-48b66a5d-80de-4f52-99f0-f2f3af13d7a3'} 2019-02-27 11:32:58,734 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_0', 'm_0'] > {'time': 3, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_0-3998ad31-d504-4b35-bb85-3be6197f1ea0: buy 0 (t: 3, u: (0, 2.0), q: (1, 3))', 'partners': "['c_0-3998ad31-d504-4b35-bb85-3be6197f1ea0', 'm_0-575672e1-efe8-4964-b340-4a6116793ce6']", 'seller': 'm_0-575672e1-efe8-4964-b340-4a6116793ce6', 'buyer': 'c_0-3998ad31-d504-4b35-bb85-3be6197f1ea0'} 2019-02-27 11:32:58,735 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_2', 'm_3'] > {'time': 4, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_2-88fd8b76-1040-4e98-b476-5e965b64b2fb: buy 0 (t: 4, u: (0, 2.0), q: (1, 4))', 'partners': "['c_2-88fd8b76-1040-4e98-b476-5e965b64b2fb', 'm_3-57429f75-c75c-4cb4-a9b4-ca5c83d682d1']", 'seller': 'm_3-57429f75-c75c-4cb4-a9b4-ca5c83d682d1', 'buyer': 'c_2-88fd8b76-1040-4e98-b476-5e965b64b2fb'} 2019-02-27 11:32:58,735 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_1', 'm_1'] > {'time': 4, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_1-48b66a5d-80de-4f52-99f0-f2f3af13d7a3: buy 0 (t: 4, u: (0, 2.0), q: (1, 3))', 'partners': "['c_1-48b66a5d-80de-4f52-99f0-f2f3af13d7a3', 'm_1-153ac158-9a57-4bca-8296-bae6389d1ce1']", 'seller': 'm_1-153ac158-9a57-4bca-8296-bae6389d1ce1', 'buyer': 'c_1-48b66a5d-80de-4f52-99f0-f2f3af13d7a3'} 2019-02-27 11:32:58,736 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_0', 'm_3'] > {'time': 1, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_0-3998ad31-d504-4b35-bb85-3be6197f1ea0: buy 0 (t: 1, u: (0, 2.0), q: (1, 4))', 'partners': "['c_0-3998ad31-d504-4b35-bb85-3be6197f1ea0', 'm_3-57429f75-c75c-4cb4-a9b4-ca5c83d682d1']", 'seller': 'm_3-57429f75-c75c-4cb4-a9b4-ca5c83d682d1', 'buyer': 'c_0-3998ad31-d504-4b35-bb85-3be6197f1ea0'} 2019-02-27 11:32:58,737 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_4', 'm_3'] > {'time': 2, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_4-70a6b468-fb6c-4fd2-b7da-c47f020247d6: buy 0 (t: 2, u: (0, 2.0), q: (1, 3))', 'partners': "['c_4-70a6b468-fb6c-4fd2-b7da-c47f020247d6', 'm_3-57429f75-c75c-4cb4-a9b4-ca5c83d682d1']", 'seller': 'm_3-57429f75-c75c-4cb4-a9b4-ca5c83d682d1', 'buyer': 'c_4-70a6b468-fb6c-4fd2-b7da-c47f020247d6'} 2019-02-27 11:32:58,738 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_0', 'm_4'] > {'time': 2, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_0-3998ad31-d504-4b35-bb85-3be6197f1ea0: buy 0 (t: 2, u: (0, 2.0), q: (1, 4))', 'partners': "['c_0-3998ad31-d504-4b35-bb85-3be6197f1ea0', 'm_4-839c8f96-e52b-40cd-a1ef-3bf468ec11cb']", 'seller': 'm_4-839c8f96-e52b-40cd-a1ef-3bf468ec11cb', 'buyer': 'c_0-3998ad31-d504-4b35-bb85-3be6197f1ea0'} 2019-02-27 11:32:58,739 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_2', 'm_1'] > {'time': 1, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_2-88fd8b76-1040-4e98-b476-5e965b64b2fb: buy 0 (t: 1, u: (0, 2.0), q: (1, 3))', 'partners': "['c_2-88fd8b76-1040-4e98-b476-5e965b64b2fb', 'm_1-153ac158-9a57-4bca-8296-bae6389d1ce1']", 'seller': 'm_1-153ac158-9a57-4bca-8296-bae6389d1ce1', 'buyer': 'c_2-88fd8b76-1040-4e98-b476-5e965b64b2fb'} 2019-02-27 11:32:58,739 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_1', 'm_1'] > {'time': 3, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_1-48b66a5d-80de-4f52-99f0-f2f3af13d7a3: buy 0 (t: 3, u: (0, 2.0), q: (1, 4))', 'partners': "['c_1-48b66a5d-80de-4f52-99f0-f2f3af13d7a3', 'm_1-153ac158-9a57-4bca-8296-bae6389d1ce1']", 'seller': 'm_1-153ac158-9a57-4bca-8296-bae6389d1ce1', 'buyer': 'c_1-48b66a5d-80de-4f52-99f0-f2f3af13d7a3'} 2019-02-27 11:32:58,739 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_2', 'm_1'] > {'time': 2, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_2-88fd8b76-1040-4e98-b476-5e965b64b2fb: buy 0 (t: 2, u: (0, 2.0), q: (1, 4))', 'partners': "['c_2-88fd8b76-1040-4e98-b476-5e965b64b2fb', 'm_1-153ac158-9a57-4bca-8296-bae6389d1ce1']", 'seller': 'm_1-153ac158-9a57-4bca-8296-bae6389d1ce1', 'buyer': 'c_2-88fd8b76-1040-4e98-b476-5e965b64b2fb'} 2019-02-27 11:32:58,740 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_4', 'm_4'] > {'time': 4, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_4-70a6b468-fb6c-4fd2-b7da-c47f020247d6: buy 0 (t: 4, u: (0, 2.0), q: (1, 4))', 'partners': "['c_4-70a6b468-fb6c-4fd2-b7da-c47f020247d6', 'm_4-839c8f96-e52b-40cd-a1ef-3bf468ec11cb']", 'seller': 'm_4-839c8f96-e52b-40cd-a1ef-3bf468ec11cb', 'buyer': 'c_4-70a6b468-fb6c-4fd2-b7da-c47f020247d6'} 2019-02-27 11:32:58,740 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_4', 'm_3'] > {'time': 1, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_4-70a6b468-fb6c-4fd2-b7da-c47f020247d6: buy 0 (t: 1, u: (0, 2.0), q: (1, 4))', 'partners': "['c_4-70a6b468-fb6c-4fd2-b7da-c47f020247d6', 'm_3-57429f75-c75c-4cb4-a9b4-ca5c83d682d1']", 'seller': 'm_3-57429f75-c75c-4cb4-a9b4-ca5c83d682d1', 'buyer': 'c_4-70a6b468-fb6c-4fd2-b7da-c47f020247d6'} 2019-02-27 11:32:58,740 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_3', 'm_4'] > {'time': 2, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_3-ef402340-68d6-404a-8c4f-8ec5bead3987: buy 0 (t: 2, u: (0, 2.0), q: (1, 4))', 'partners': "['c_3-ef402340-68d6-404a-8c4f-8ec5bead3987', 'm_4-839c8f96-e52b-40cd-a1ef-3bf468ec11cb']", 'seller': 'm_4-839c8f96-e52b-40cd-a1ef-3bf468ec11cb', 'buyer': 'c_3-ef402340-68d6-404a-8c4f-8ec5bead3987'} 2019-02-27 11:32:58,741 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_2', 'm_1'] > {'time': 4, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_2-88fd8b76-1040-4e98-b476-5e965b64b2fb: buy 0 (t: 4, u: (0, 2.0), q: (1, 4))', 'partners': "['c_2-88fd8b76-1040-4e98-b476-5e965b64b2fb', 'm_1-153ac158-9a57-4bca-8296-bae6389d1ce1']", 'seller': 'm_1-153ac158-9a57-4bca-8296-bae6389d1ce1', 'buyer': 'c_2-88fd8b76-1040-4e98-b476-5e965b64b2fb'} 2019-02-27 11:32:58,741 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_1', 'm_4'] > {'time': 3, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_1-48b66a5d-80de-4f52-99f0-f2f3af13d7a3: buy 0 (t: 3, u: (0, 2.0), q: (1, 4))', 'partners': "['c_1-48b66a5d-80de-4f52-99f0-f2f3af13d7a3', 'm_4-839c8f96-e52b-40cd-a1ef-3bf468ec11cb']", 'seller': 'm_4-839c8f96-e52b-40cd-a1ef-3bf468ec11cb', 'buyer': 'c_1-48b66a5d-80de-4f52-99f0-f2f3af13d7a3'} 2019-02-27 11:32:58,741 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_4', 'm_4'] > {'time': 1, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_4-70a6b468-fb6c-4fd2-b7da-c47f020247d6: buy 0 (t: 1, u: (0, 2.0), q: (1, 4))', 'partners': "['c_4-70a6b468-fb6c-4fd2-b7da-c47f020247d6', 'm_4-839c8f96-e52b-40cd-a1ef-3bf468ec11cb']", 'seller': 'm_4-839c8f96-e52b-40cd-a1ef-3bf468ec11cb', 'buyer': 'c_4-70a6b468-fb6c-4fd2-b7da-c47f020247d6'} 2019-02-27 11:32:58,741 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_4', 'm_0'] > {'time': 3, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_4-70a6b468-fb6c-4fd2-b7da-c47f020247d6: buy 0 (t: 3, u: (0, 2.0), q: (1, 4))', 'partners': "['c_4-70a6b468-fb6c-4fd2-b7da-c47f020247d6', 'm_0-575672e1-efe8-4964-b340-4a6116793ce6']", 'seller': 'm_0-575672e1-efe8-4964-b340-4a6116793ce6', 'buyer': 'c_4-70a6b468-fb6c-4fd2-b7da-c47f020247d6'} 2019-02-27 11:32:58,742 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_1', 'm_1'] > {'time': 2, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_1-48b66a5d-80de-4f52-99f0-f2f3af13d7a3: buy 0 (t: 2, u: (0, 2.0), q: (1, 3))', 'partners': "['c_1-48b66a5d-80de-4f52-99f0-f2f3af13d7a3', 'm_1-153ac158-9a57-4bca-8296-bae6389d1ce1']", 'seller': 'm_1-153ac158-9a57-4bca-8296-bae6389d1ce1', 'buyer': 'c_1-48b66a5d-80de-4f52-99f0-f2f3af13d7a3'} 2019-02-27 11:32:58,742 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_2', 'm_2'] > {'time': 3, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_2-88fd8b76-1040-4e98-b476-5e965b64b2fb: buy 0 (t: 3, u: (0, 2.0), q: (1, 3))', 'partners': "['c_2-88fd8b76-1040-4e98-b476-5e965b64b2fb', 'm_2-84165933-f800-4373-8db2-96de0656eead']", 'seller': 'm_2-84165933-f800-4373-8db2-96de0656eead', 'buyer': 'c_2-88fd8b76-1040-4e98-b476-5e965b64b2fb'} 2019-02-27 11:32:58,742 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_2', 'm_4'] > {'time': 1, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_2-88fd8b76-1040-4e98-b476-5e965b64b2fb: buy 0 (t: 1, u: (0, 2.0), q: (1, 3))', 'partners': "['c_2-88fd8b76-1040-4e98-b476-5e965b64b2fb', 'm_4-839c8f96-e52b-40cd-a1ef-3bf468ec11cb']", 'seller': 'm_4-839c8f96-e52b-40cd-a1ef-3bf468ec11cb', 'buyer': 'c_2-88fd8b76-1040-4e98-b476-5e965b64b2fb'} 2019-02-27 11:32:58,743 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_4', 'm_1'] > {'time': 1, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_4-70a6b468-fb6c-4fd2-b7da-c47f020247d6: buy 0 (t: 1, u: (0, 2.0), q: (1, 4))', 'partners': "['c_4-70a6b468-fb6c-4fd2-b7da-c47f020247d6', 'm_1-153ac158-9a57-4bca-8296-bae6389d1ce1']", 'seller': 'm_1-153ac158-9a57-4bca-8296-bae6389d1ce1', 'buyer': 'c_4-70a6b468-fb6c-4fd2-b7da-c47f020247d6'} 2019-02-27 11:32:58,743 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_0', 'm_0'] > {'time': 1, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_0-3998ad31-d504-4b35-bb85-3be6197f1ea0: buy 0 (t: 1, u: (0, 2.0), q: (1, 4))', 'partners': "['c_0-3998ad31-d504-4b35-bb85-3be6197f1ea0', 'm_0-575672e1-efe8-4964-b340-4a6116793ce6']", 'seller': 'm_0-575672e1-efe8-4964-b340-4a6116793ce6', 'buyer': 'c_0-3998ad31-d504-4b35-bb85-3be6197f1ea0'} 2019-02-27 11:32:58,743 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_4', 'm_0'] > {'time': 1, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_4-70a6b468-fb6c-4fd2-b7da-c47f020247d6: buy 0 (t: 1, u: (0, 2.0), q: (1, 4))', 'partners': "['c_4-70a6b468-fb6c-4fd2-b7da-c47f020247d6', 'm_0-575672e1-efe8-4964-b340-4a6116793ce6']", 'seller': 'm_0-575672e1-efe8-4964-b340-4a6116793ce6', 'buyer': 'c_4-70a6b468-fb6c-4fd2-b7da-c47f020247d6'} 2019-02-27 11:32:58,743 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_4', 'm_2'] > {'time': 3, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_4-70a6b468-fb6c-4fd2-b7da-c47f020247d6: buy 0 (t: 3, u: (0, 2.0), q: (1, 4))', 'partners': "['c_4-70a6b468-fb6c-4fd2-b7da-c47f020247d6', 'm_2-84165933-f800-4373-8db2-96de0656eead']", 'seller': 'm_2-84165933-f800-4373-8db2-96de0656eead', 'buyer': 'c_4-70a6b468-fb6c-4fd2-b7da-c47f020247d6'} 2019-02-27 11:32:58,744 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_0', 'm_1'] > {'time': 4, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_0-3998ad31-d504-4b35-bb85-3be6197f1ea0: buy 0 (t: 4, u: (0, 2.0), q: (1, 4))', 'partners': "['c_0-3998ad31-d504-4b35-bb85-3be6197f1ea0', 'm_1-153ac158-9a57-4bca-8296-bae6389d1ce1']", 'seller': 'm_1-153ac158-9a57-4bca-8296-bae6389d1ce1', 'buyer': 'c_0-3998ad31-d504-4b35-bb85-3be6197f1ea0'} 2019-02-27 11:32:58,744 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_4', 'm_1'] > {'time': 4, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_4-70a6b468-fb6c-4fd2-b7da-c47f020247d6: buy 0 (t: 4, u: (0, 2.0), q: (1, 4))', 'partners': "['c_4-70a6b468-fb6c-4fd2-b7da-c47f020247d6', 'm_1-153ac158-9a57-4bca-8296-bae6389d1ce1']", 'seller': 'm_1-153ac158-9a57-4bca-8296-bae6389d1ce1', 'buyer': 'c_4-70a6b468-fb6c-4fd2-b7da-c47f020247d6'} 2019-02-27 11:32:58,744 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_2', 'm_4'] > {'time': 4, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_2-88fd8b76-1040-4e98-b476-5e965b64b2fb: buy 0 (t: 4, u: (0, 2.0), q: (1, 4))', 'partners': "['c_2-88fd8b76-1040-4e98-b476-5e965b64b2fb', 'm_4-839c8f96-e52b-40cd-a1ef-3bf468ec11cb']", 'seller': 'm_4-839c8f96-e52b-40cd-a1ef-3bf468ec11cb', 'buyer': 'c_2-88fd8b76-1040-4e98-b476-5e965b64b2fb'} 2019-02-27 11:32:58,745 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_3', 'm_3'] > {'time': 3, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_3-ef402340-68d6-404a-8c4f-8ec5bead3987: buy 0 (t: 3, u: (0, 2.0), q: (1, 3))', 'partners': "['c_3-ef402340-68d6-404a-8c4f-8ec5bead3987', 'm_3-57429f75-c75c-4cb4-a9b4-ca5c83d682d1']", 'seller': 'm_3-57429f75-c75c-4cb4-a9b4-ca5c83d682d1', 'buyer': 'c_3-ef402340-68d6-404a-8c4f-8ec5bead3987'} 2019-02-27 11:32:58,746 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_3', 'm_0'] > {'time': 4, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_3-ef402340-68d6-404a-8c4f-8ec5bead3987: buy 0 (t: 4, u: (0, 2.0), q: (1, 3))', 'partners': "['c_3-ef402340-68d6-404a-8c4f-8ec5bead3987', 'm_0-575672e1-efe8-4964-b340-4a6116793ce6']", 'seller': 'm_0-575672e1-efe8-4964-b340-4a6116793ce6', 'buyer': 'c_3-ef402340-68d6-404a-8c4f-8ec5bead3987'} 2019-02-27 11:32:58,746 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_4', 'm_2'] > {'time': 2, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_4-70a6b468-fb6c-4fd2-b7da-c47f020247d6: buy 0 (t: 2, u: (0, 2.0), q: (1, 3))', 'partners': "['c_4-70a6b468-fb6c-4fd2-b7da-c47f020247d6', 'm_2-84165933-f800-4373-8db2-96de0656eead']", 'seller': 'm_2-84165933-f800-4373-8db2-96de0656eead', 'buyer': 'c_4-70a6b468-fb6c-4fd2-b7da-c47f020247d6'} 2019-02-27 11:32:58,747 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_3', 'm_1'] > {'time': 1, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_3-ef402340-68d6-404a-8c4f-8ec5bead3987: buy 0 (t: 1, u: (0, 2.0), q: (1, 3))', 'partners': "['c_3-ef402340-68d6-404a-8c4f-8ec5bead3987', 'm_1-153ac158-9a57-4bca-8296-bae6389d1ce1']", 'seller': 'm_1-153ac158-9a57-4bca-8296-bae6389d1ce1', 'buyer': 'c_3-ef402340-68d6-404a-8c4f-8ec5bead3987'} 2019-02-27 11:32:58,748 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_2', 'm_4'] > {'time': 3, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_2-88fd8b76-1040-4e98-b476-5e965b64b2fb: buy 0 (t: 3, u: (0, 2.0), q: (1, 3))', 'partners': "['c_2-88fd8b76-1040-4e98-b476-5e965b64b2fb', 'm_4-839c8f96-e52b-40cd-a1ef-3bf468ec11cb']", 'seller': 'm_4-839c8f96-e52b-40cd-a1ef-3bf468ec11cb', 'buyer': 'c_2-88fd8b76-1040-4e98-b476-5e965b64b2fb'} 2019-02-27 11:32:58,748 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_1', 'm_0'] > {'time': 1, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_1-48b66a5d-80de-4f52-99f0-f2f3af13d7a3: buy 0 (t: 1, u: (0, 2.0), q: (1, 4))', 'partners': "['c_1-48b66a5d-80de-4f52-99f0-f2f3af13d7a3', 'm_0-575672e1-efe8-4964-b340-4a6116793ce6']", 'seller': 'm_0-575672e1-efe8-4964-b340-4a6116793ce6', 'buyer': 'c_1-48b66a5d-80de-4f52-99f0-f2f3af13d7a3'} 2019-02-27 11:32:58,749 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_1', 'm_0'] > {'time': 4, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_1-48b66a5d-80de-4f52-99f0-f2f3af13d7a3: buy 0 (t: 4, u: (0, 2.0), q: (1, 3))', 'partners': "['c_1-48b66a5d-80de-4f52-99f0-f2f3af13d7a3', 'm_0-575672e1-efe8-4964-b340-4a6116793ce6']", 'seller': 'm_0-575672e1-efe8-4964-b340-4a6116793ce6', 'buyer': 'c_1-48b66a5d-80de-4f52-99f0-f2f3af13d7a3'} 2019-02-27 11:32:58,749 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_0', 'm_1'] > {'time': 2, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_0-3998ad31-d504-4b35-bb85-3be6197f1ea0: buy 0 (t: 2, u: (0, 2.0), q: (1, 4))', 'partners': "['c_0-3998ad31-d504-4b35-bb85-3be6197f1ea0', 'm_1-153ac158-9a57-4bca-8296-bae6389d1ce1']", 'seller': 'm_1-153ac158-9a57-4bca-8296-bae6389d1ce1', 'buyer': 'c_0-3998ad31-d504-4b35-bb85-3be6197f1ea0'} 2019-02-27 11:32:58,749 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_3', 'm_3'] > {'time': 1, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_3-ef402340-68d6-404a-8c4f-8ec5bead3987: buy 0 (t: 1, u: (0, 2.0), q: (1, 3))', 'partners': "['c_3-ef402340-68d6-404a-8c4f-8ec5bead3987', 'm_3-57429f75-c75c-4cb4-a9b4-ca5c83d682d1']", 'seller': 'm_3-57429f75-c75c-4cb4-a9b4-ca5c83d682d1', 'buyer': 'c_3-ef402340-68d6-404a-8c4f-8ec5bead3987'} 2019-02-27 11:32:58,750 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_3', 'm_0'] > {'time': 3, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_3-ef402340-68d6-404a-8c4f-8ec5bead3987: buy 0 (t: 3, u: (0, 2.0), q: (1, 3))', 'partners': "['c_3-ef402340-68d6-404a-8c4f-8ec5bead3987', 'm_0-575672e1-efe8-4964-b340-4a6116793ce6']", 'seller': 'm_0-575672e1-efe8-4964-b340-4a6116793ce6', 'buyer': 'c_3-ef402340-68d6-404a-8c4f-8ec5bead3987'} 2019-02-27 11:32:58,750 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_3', 'm_4'] > {'time': 3, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_3-ef402340-68d6-404a-8c4f-8ec5bead3987: buy 0 (t: 3, u: (0, 2.0), q: (1, 3))', 'partners': "['c_3-ef402340-68d6-404a-8c4f-8ec5bead3987', 'm_4-839c8f96-e52b-40cd-a1ef-3bf468ec11cb']", 'seller': 'm_4-839c8f96-e52b-40cd-a1ef-3bf468ec11cb', 'buyer': 'c_3-ef402340-68d6-404a-8c4f-8ec5bead3987'} 2019-02-27 11:32:58,751 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_3', 'm_1'] > {'time': 3, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_3-ef402340-68d6-404a-8c4f-8ec5bead3987: buy 0 (t: 3, u: (0, 2.0), q: (1, 3))', 'partners': "['c_3-ef402340-68d6-404a-8c4f-8ec5bead3987', 'm_1-153ac158-9a57-4bca-8296-bae6389d1ce1']", 'seller': 'm_1-153ac158-9a57-4bca-8296-bae6389d1ce1', 'buyer': 'c_3-ef402340-68d6-404a-8c4f-8ec5bead3987'} 2019-02-27 11:32:58,751 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_3', 'm_2'] > {'time': 2, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_3-ef402340-68d6-404a-8c4f-8ec5bead3987: buy 0 (t: 2, u: (0, 2.0), q: (1, 4))', 'partners': "['c_3-ef402340-68d6-404a-8c4f-8ec5bead3987', 'm_2-84165933-f800-4373-8db2-96de0656eead']", 'seller': 'm_2-84165933-f800-4373-8db2-96de0656eead', 'buyer': 'c_3-ef402340-68d6-404a-8c4f-8ec5bead3987'} 2019-02-27 11:32:58,752 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_0', 'm_1'] > {'time': 1, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_0-3998ad31-d504-4b35-bb85-3be6197f1ea0: buy 0 (t: 1, u: (0, 2.0), q: (1, 4))', 'partners': "['c_0-3998ad31-d504-4b35-bb85-3be6197f1ea0', 'm_1-153ac158-9a57-4bca-8296-bae6389d1ce1']", 'seller': 'm_1-153ac158-9a57-4bca-8296-bae6389d1ce1', 'buyer': 'c_0-3998ad31-d504-4b35-bb85-3be6197f1ea0'} 2019-02-27 11:32:58,752 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_2', 'm_1'] > {'time': 3, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_2-88fd8b76-1040-4e98-b476-5e965b64b2fb: buy 0 (t: 3, u: (0, 2.0), q: (1, 3))', 'partners': "['c_2-88fd8b76-1040-4e98-b476-5e965b64b2fb', 'm_1-153ac158-9a57-4bca-8296-bae6389d1ce1']", 'seller': 'm_1-153ac158-9a57-4bca-8296-bae6389d1ce1', 'buyer': 'c_2-88fd8b76-1040-4e98-b476-5e965b64b2fb'} 2019-02-27 11:32:58,756 - INFO - 1/10 [20.00%]: m_0 requested negmas.sao.SAOMechanism[None] with ['c_3', 'm_0'] (ID a3cd7b9e-c815-45df-88de-1c6cd445adec) 2019-02-27 11:32:58,757 - INFO - 1/10 [20.00%]: m_0-575672e1-efe8-4964-b340-4a6116793ce6 request was accepted 2019-02-27 11:32:58,758 - INFO - 1/10 [20.00%]: m_1 requested negmas.sao.SAOMechanism[None] with ['c_3', 'm_1'] (ID b719d8a0-932c-447c-92ac-56898902cd15) 2019-02-27 11:32:58,759 - INFO - 1/10 [20.00%]: m_1-153ac158-9a57-4bca-8296-bae6389d1ce1 request was accepted 2019-02-27 11:32:58,759 - INFO - 1/10 [20.00%]: m_2 requested negmas.sao.SAOMechanism[None] with ['c_3', 'm_2'] (ID 4e198fc4-fc23-47c2-9018-037a1ae9c91d) 2019-02-27 11:32:58,760 - INFO - 1/10 [20.00%]: m_2-84165933-f800-4373-8db2-96de0656eead request was accepted 2019-02-27 11:32:58,761 - INFO - 1/10 [20.00%]: m_3 requested negmas.sao.SAOMechanism[None] with ['c_3', 'm_3'] (ID 39e91cd5-8e60-48b6-ac28-bbc56ba09b4b) 2019-02-27 11:32:58,762 - INFO - 1/10 [20.00%]: m_3-57429f75-c75c-4cb4-a9b4-ca5c83d682d1 request was accepted 2019-02-27 11:32:58,763 - INFO - 1/10 [20.00%]: m_4 requested negmas.sao.SAOMechanism[None] with ['c_3', 'm_4'] (ID f833fe67-10fb-4b2f-b11e-d9732ef06109) 2019-02-27 11:32:58,763 - INFO - 1/10 [20.00%]: m_4-839c8f96-e52b-40cd-a1ef-3bf468ec11cb request was accepted 2019-02-27 11:32:58,766 - INFO - 1/10 [20.00%]: m_0 requested negmas.sao.SAOMechanism[None] with ['c_4', 'm_0'] (ID b6004387-2b7e-46a0-8e71-024969c3fd68) 2019-02-27 11:32:58,766 - INFO - 1/10 [20.00%]: m_0-575672e1-efe8-4964-b340-4a6116793ce6 request was accepted 2019-02-27 11:32:58,767 - INFO - 1/10 [20.00%]: m_1 requested negmas.sao.SAOMechanism[None] with ['c_4', 'm_1'] (ID 9006e987-8dc7-4007-b91e-f742016dad36) 2019-02-27 11:32:58,768 - INFO - 1/10 [20.00%]: m_1-153ac158-9a57-4bca-8296-bae6389d1ce1 request was accepted 2019-02-27 11:32:58,769 - INFO - 1/10 [20.00%]: m_2 requested negmas.sao.SAOMechanism[None] with ['c_4', 'm_2'] (ID 7269e456-be69-49bf-90ce-cfa422027114) 2019-02-27 11:32:58,770 - INFO - 1/10 [20.00%]: m_2-84165933-f800-4373-8db2-96de0656eead request was accepted 2019-02-27 11:32:58,771 - INFO - 1/10 [20.00%]: m_3 requested negmas.sao.SAOMechanism[None] with ['c_4', 'm_3'] (ID 84a868a2-6183-43c0-945c-2137c37d2e80) 2019-02-27 11:32:58,772 - INFO - 1/10 [20.00%]: m_3-57429f75-c75c-4cb4-a9b4-ca5c83d682d1 request was accepted 2019-02-27 11:32:58,773 - INFO - 1/10 [20.00%]: m_4 requested negmas.sao.SAOMechanism[None] with ['c_4', 'm_4'] (ID 397724a8-596b-498c-ad57-b4706756e37e) 2019-02-27 11:32:58,773 - INFO - 1/10 [20.00%]: m_4-839c8f96-e52b-40cd-a1ef-3bf468ec11cb request was accepted 2019-02-27 11:32:58,775 - INFO - 1/10 [20.00%]: m_0 requested negmas.sao.SAOMechanism[None] with ['c_1', 'm_0'] (ID 272f9ee2-7b8d-4e89-83a1-07076a7b8408) 2019-02-27 11:32:58,776 - INFO - 1/10 [20.00%]: m_0-575672e1-efe8-4964-b340-4a6116793ce6 request was accepted 2019-02-27 11:32:58,777 - INFO - 1/10 [20.00%]: m_1 requested negmas.sao.SAOMechanism[None] with ['c_1', 'm_1'] (ID eee59962-fa49-431f-9a53-c22d34361a4b) 2019-02-27 11:32:58,778 - INFO - 1/10 [20.00%]: m_1-153ac158-9a57-4bca-8296-bae6389d1ce1 request was accepted 2019-02-27 11:32:58,779 - INFO - 1/10 [20.00%]: m_2 requested negmas.sao.SAOMechanism[None] with ['c_1', 'm_2'] (ID c0d3078c-c2fb-4ba9-b0d3-f8364d3b3b92) 2019-02-27 11:32:58,779 - INFO - 1/10 [20.00%]: m_2-84165933-f800-4373-8db2-96de0656eead request was accepted 2019-02-27 11:32:58,780 - INFO - 1/10 [20.00%]: m_3 requested negmas.sao.SAOMechanism[None] with ['c_1', 'm_3'] (ID 9bcd5e9d-098a-46d3-ba74-877886750e61) 2019-02-27 11:32:58,781 - INFO - 1/10 [20.00%]: m_3-57429f75-c75c-4cb4-a9b4-ca5c83d682d1 request was accepted 2019-02-27 11:32:58,782 - INFO - 1/10 [20.00%]: m_4 requested negmas.sao.SAOMechanism[None] with ['c_1', 'm_4'] (ID 932d9bd9-7205-4665-99b2-35ecbb6ed097) 2019-02-27 11:32:58,782 - INFO - 1/10 [20.00%]: m_4-839c8f96-e52b-40cd-a1ef-3bf468ec11cb request was accepted 2019-02-27 11:32:58,784 - INFO - 1/10 [20.00%]: m_0 requested negmas.sao.SAOMechanism[None] with ['c_0', 'm_0'] (ID f02b3777-79c8-4e74-aa84-e03f18a95823) 2019-02-27 11:32:58,785 - INFO - 1/10 [20.00%]: m_0-575672e1-efe8-4964-b340-4a6116793ce6 request was accepted 2019-02-27 11:32:58,787 - INFO - 1/10 [20.00%]: m_1 requested negmas.sao.SAOMechanism[None] with ['c_0', 'm_1'] (ID b19a2760-88cb-4647-b20c-50af66fadcf0) 2019-02-27 11:32:58,788 - INFO - 1/10 [20.00%]: m_1-153ac158-9a57-4bca-8296-bae6389d1ce1 request was accepted 2019-02-27 11:32:58,790 - INFO - 1/10 [20.00%]: m_2 requested negmas.sao.SAOMechanism[None] with ['c_0', 'm_2'] (ID 993f3549-05cb-4f71-b5a3-8fa9a0043a26) 2019-02-27 11:32:58,791 - INFO - 1/10 [20.00%]: m_2-84165933-f800-4373-8db2-96de0656eead request was accepted 2019-02-27 11:32:58,792 - INFO - 1/10 [20.00%]: m_3 requested negmas.sao.SAOMechanism[None] with ['c_0', 'm_3'] (ID 0da4bb7c-af7e-4f76-a936-423cb75dc1b5) 2019-02-27 11:32:58,792 - INFO - 1/10 [20.00%]: m_3-57429f75-c75c-4cb4-a9b4-ca5c83d682d1 request was accepted 2019-02-27 11:32:58,793 - INFO - 1/10 [20.00%]: m_4 requested negmas.sao.SAOMechanism[None] with ['c_0', 'm_4'] (ID 14428f47-70fa-41df-941d-937121dede6c) 2019-02-27 11:32:58,794 - INFO - 1/10 [20.00%]: m_4-839c8f96-e52b-40cd-a1ef-3bf468ec11cb request was accepted 2019-02-27 11:32:58,799 - INFO - 1/10 [20.00%]: m_0 requested negmas.sao.SAOMechanism[None] with ['c_2', 'm_0'] (ID b19ee9e6-978c-483c-92e7-973908267a22) 2019-02-27 11:32:58,800 - INFO - 1/10 [20.00%]: m_0-575672e1-efe8-4964-b340-4a6116793ce6 request was accepted 2019-02-27 11:32:58,802 - INFO - 1/10 [20.00%]: m_1 requested negmas.sao.SAOMechanism[None] with ['c_2', 'm_1'] (ID f7606358-a3c2-40f0-b2d7-58392a30daa1) 2019-02-27 11:32:58,803 - INFO - 1/10 [20.00%]: m_1-153ac158-9a57-4bca-8296-bae6389d1ce1 request was accepted 2019-02-27 11:32:58,805 - INFO - 1/10 [20.00%]: m_2 requested negmas.sao.SAOMechanism[None] with ['c_2', 'm_2'] (ID a645d67a-36ec-47d4-8dd9-4cb116e2be4d) 2019-02-27 11:32:58,805 - INFO - 1/10 [20.00%]: m_2-84165933-f800-4373-8db2-96de0656eead request was accepted 2019-02-27 11:32:58,806 - INFO - 1/10 [20.00%]: m_3 requested negmas.sao.SAOMechanism[None] with ['c_2', 'm_3'] (ID 93ef7211-788f-4770-948b-abf8314bb43b) 2019-02-27 11:32:58,807 - INFO - 1/10 [20.00%]: m_3-57429f75-c75c-4cb4-a9b4-ca5c83d682d1 request was accepted 2019-02-27 11:32:58,808 - INFO - 1/10 [20.00%]: m_4 requested negmas.sao.SAOMechanism[None] with ['c_2', 'm_4'] (ID bd1fb9c0-4e9b-4538-91ca-805e67d53bf1) 2019-02-27 11:32:58,809 - INFO - 1/10 [20.00%]: m_4-839c8f96-e52b-40cd-a1ef-3bf468ec11cb request was accepted 2019-02-27 11:32:58,809 - DEBUG - 1/10 [20.00%]: Factory 2b84599b-e538-4212-b349-d4a05459c15b: money=0, storage={}, loans=0.0 2019-02-27 11:32:58,809 - DEBUG - 1/10 [20.00%]: Factory fed30dd7-5bba-4df3-9386-c2570ef237d4: money=0, storage={}, loans=0.0 2019-02-27 11:32:58,809 - DEBUG - 1/10 [20.00%]: Factory 2b9215ac-5da4-4788-8222-002f92ac7b3c: money=0, storage={}, loans=0.0 2019-02-27 11:32:58,809 - DEBUG - 1/10 [20.00%]: Factory 1f8923b6-aef8-4008-a31c-b18482add390: money=0, storage={}, loans=0.0 2019-02-27 11:32:58,809 - DEBUG - 1/10 [20.00%]: Factory 30f40890-1d90-499c-87f7-ac48be226a56: money=0, storage={}, loans=0.0 2019-02-27 11:32:58,809 - DEBUG - 1/10 [20.00%]: Factory f6c073fa-9343-49a7-b738-ccd0b9381c40: money=0.0, storage={}, loans=0.0 2019-02-27 11:32:58,809 - DEBUG - 1/10 [20.00%]: Factory 62cc9ee6-9600-42d1-83dd-216923d114b1: money=0.0, storage={}, loans=0.0 2019-02-27 11:32:58,809 - DEBUG - 1/10 [20.00%]: Factory e11f4f3c-15a1-461a-bd2c-632e07f82b5f: money=0.0, storage={}, loans=0.0 2019-02-27 11:32:58,809 - DEBUG - 1/10 [20.00%]: Factory 3583ffd0-fef8-4a83-be5d-0fa6562d4c9f: money=0.0, storage={}, loans=0.0 2019-02-27 11:32:58,809 - DEBUG - 1/10 [20.00%]: Factory eb0d4726-61b8-4266-8c97-4416e5746a6f: money=0.0, storage={}, loans=0.0 2019-02-27 11:32:58,810 - INFO - 2/10 [30.00%]: 25 Negotiations/4 _entities 2019-02-27 11:32:59,096 - DEBUG - 2/10 [30.00%]: Contract [to be signed at 3]: ['c_4', 'm_3'] > {'time': 5, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_4-70a6b468-fb6c-4fd2-b7da-c47f020247d6: buy 0 (t: 5, u: (0, 2.0), q: (1, 3))', 'partners': "['c_4-70a6b468-fb6c-4fd2-b7da-c47f020247d6', 'm_3-57429f75-c75c-4cb4-a9b4-ca5c83d682d1']", 'seller': 'm_3-57429f75-c75c-4cb4-a9b4-ca5c83d682d1', 'buyer': 'c_4-70a6b468-fb6c-4fd2-b7da-c47f020247d6'} 2019-02-27 11:32:59,097 - DEBUG - 2/10 [30.00%]: Contract [to be signed at 3]: ['c_1', 'm_4'] > {'time': 5, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_1-48b66a5d-80de-4f52-99f0-f2f3af13d7a3: buy 0 (t: 5, u: (0, 2.0), q: (1, 3))', 'partners': "['c_1-48b66a5d-80de-4f52-99f0-f2f3af13d7a3', 'm_4-839c8f96-e52b-40cd-a1ef-3bf468ec11cb']", 'seller': 'm_4-839c8f96-e52b-40cd-a1ef-3bf468ec11cb', 'buyer': 'c_1-48b66a5d-80de-4f52-99f0-f2f3af13d7a3'} 2019-02-27 11:32:59,097 - DEBUG - 2/10 [30.00%]: Contract [to be signed at 3]: ['c_2', 'm_1'] > {'time': 5, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_2-88fd8b76-1040-4e98-b476-5e965b64b2fb: buy 0 (t: 5, u: (0, 2.0), q: (1, 4))', 'partners': "['c_2-88fd8b76-1040-4e98-b476-5e965b64b2fb', 'm_1-153ac158-9a57-4bca-8296-bae6389d1ce1']", 'seller': 'm_1-153ac158-9a57-4bca-8296-bae6389d1ce1', 'buyer': 'c_2-88fd8b76-1040-4e98-b476-5e965b64b2fb'} 2019-02-27 11:32:59,097 - DEBUG - 2/10 [30.00%]: Contract [to be signed at 3]: ['c_4', 'm_2'] > {'time': 5, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_4-70a6b468-fb6c-4fd2-b7da-c47f020247d6: buy 0 (t: 5, u: (0, 2.0), q: (1, 3))', 'partners': "['c_4-70a6b468-fb6c-4fd2-b7da-c47f020247d6', 'm_2-84165933-f800-4373-8db2-96de0656eead']", 'seller': 'm_2-84165933-f800-4373-8db2-96de0656eead', 'buyer': 'c_4-70a6b468-fb6c-4fd2-b7da-c47f020247d6'} 2019-02-27 11:32:59,098 - DEBUG - 2/10 [30.00%]: Contract [to be signed at 3]: ['c_2', 'm_4'] > {'time': 5, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_2-88fd8b76-1040-4e98-b476-5e965b64b2fb: buy 0 (t: 5, u: (0, 2.0), q: (1, 4))', 'partners': "['c_2-88fd8b76-1040-4e98-b476-5e965b64b2fb', 'm_4-839c8f96-e52b-40cd-a1ef-3bf468ec11cb']", 'seller': 'm_4-839c8f96-e52b-40cd-a1ef-3bf468ec11cb', 'buyer': 'c_2-88fd8b76-1040-4e98-b476-5e965b64b2fb'} 2019-02-27 11:32:59,098 - DEBUG - 2/10 [30.00%]: Contract [to be signed at 3]: ['c_3', 'm_0'] > {'time': 5, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_3-ef402340-68d6-404a-8c4f-8ec5bead3987: buy 0 (t: 5, u: (0, 2.0), q: (1, 3))', 'partners': "['c_3-ef402340-68d6-404a-8c4f-8ec5bead3987', 'm_0-575672e1-efe8-4964-b340-4a6116793ce6']", 'seller': 'm_0-575672e1-efe8-4964-b340-4a6116793ce6', 'buyer': 'c_3-ef402340-68d6-404a-8c4f-8ec5bead3987'} 2019-02-27 11:32:59,098 - DEBUG - 2/10 [30.00%]: Contract [to be signed at 3]: ['c_0', 'm_0'] > {'time': 5, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_0-3998ad31-d504-4b35-bb85-3be6197f1ea0: buy 0 (t: 5, u: (0, 2.0), q: (1, 3))', 'partners': "['c_0-3998ad31-d504-4b35-bb85-3be6197f1ea0', 'm_0-575672e1-efe8-4964-b340-4a6116793ce6']", 'seller': 'm_0-575672e1-efe8-4964-b340-4a6116793ce6', 'buyer': 'c_0-3998ad31-d504-4b35-bb85-3be6197f1ea0'} 2019-02-27 11:32:59,099 - DEBUG - 2/10 [30.00%]: Contract [to be signed at 3]: ['c_2', 'm_0'] > {'time': 5, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_2-88fd8b76-1040-4e98-b476-5e965b64b2fb: buy 0 (t: 5, u: (0, 2.0), q: (1, 4))', 'partners': "['c_2-88fd8b76-1040-4e98-b476-5e965b64b2fb', 'm_0-575672e1-efe8-4964-b340-4a6116793ce6']", 'seller': 'm_0-575672e1-efe8-4964-b340-4a6116793ce6', 'buyer': 'c_2-88fd8b76-1040-4e98-b476-5e965b64b2fb'} 2019-02-27 11:32:59,099 - DEBUG - 2/10 [30.00%]: Contract [to be signed at 3]: ['c_0', 'm_3'] > {'time': 5, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_0-3998ad31-d504-4b35-bb85-3be6197f1ea0: buy 0 (t: 5, u: (0, 2.0), q: (1, 3))', 'partners': "['c_0-3998ad31-d504-4b35-bb85-3be6197f1ea0', 'm_3-57429f75-c75c-4cb4-a9b4-ca5c83d682d1']", 'seller': 'm_3-57429f75-c75c-4cb4-a9b4-ca5c83d682d1', 'buyer': 'c_0-3998ad31-d504-4b35-bb85-3be6197f1ea0'} 2019-02-27 11:32:59,099 - DEBUG - 2/10 [30.00%]: Contract [to be signed at 3]: ['c_4', 'm_0'] > {'time': 5, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_4-70a6b468-fb6c-4fd2-b7da-c47f020247d6: buy 0 (t: 5, u: (0, 2.0), q: (1, 3))', 'partners': "['c_4-70a6b468-fb6c-4fd2-b7da-c47f020247d6', 'm_0-575672e1-efe8-4964-b340-4a6116793ce6']", 'seller': 'm_0-575672e1-efe8-4964-b340-4a6116793ce6', 'buyer': 'c_4-70a6b468-fb6c-4fd2-b7da-c47f020247d6'} 2019-02-27 11:32:59,100 - DEBUG - 2/10 [30.00%]: Contract [to be signed at 3]: ['c_3', 'm_1'] > {'time': 5, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_3-ef402340-68d6-404a-8c4f-8ec5bead3987: buy 0 (t: 5, u: (0, 2.0), q: (1, 3))', 'partners': "['c_3-ef402340-68d6-404a-8c4f-8ec5bead3987', 'm_1-153ac158-9a57-4bca-8296-bae6389d1ce1']", 'seller': 'm_1-153ac158-9a57-4bca-8296-bae6389d1ce1', 'buyer': 'c_3-ef402340-68d6-404a-8c4f-8ec5bead3987'} 2019-02-27 11:32:59,100 - DEBUG - 2/10 [30.00%]: Contract [to be signed at 3]: ['c_2', 'm_3'] > {'time': 5, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_2-88fd8b76-1040-4e98-b476-5e965b64b2fb: buy 0 (t: 5, u: (0, 2.0), q: (1, 4))', 'partners': "['c_2-88fd8b76-1040-4e98-b476-5e965b64b2fb', 'm_3-57429f75-c75c-4cb4-a9b4-ca5c83d682d1']", 'seller': 'm_3-57429f75-c75c-4cb4-a9b4-ca5c83d682d1', 'buyer': 'c_2-88fd8b76-1040-4e98-b476-5e965b64b2fb'} 2019-02-27 11:32:59,100 - DEBUG - 2/10 [30.00%]: Contract [to be signed at 3]: ['c_1', 'm_2'] > {'time': 5, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_1-48b66a5d-80de-4f52-99f0-f2f3af13d7a3: buy 0 (t: 5, u: (0, 2.0), q: (1, 3))', 'partners': "['c_1-48b66a5d-80de-4f52-99f0-f2f3af13d7a3', 'm_2-84165933-f800-4373-8db2-96de0656eead']", 'seller': 'm_2-84165933-f800-4373-8db2-96de0656eead', 'buyer': 'c_1-48b66a5d-80de-4f52-99f0-f2f3af13d7a3'} 2019-02-27 11:32:59,101 - DEBUG - 2/10 [30.00%]: Contract [to be signed at 3]: ['c_0', 'm_1'] > {'time': 5, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_0-3998ad31-d504-4b35-bb85-3be6197f1ea0: buy 0 (t: 5, u: (0, 2.0), q: (1, 3))', 'partners': "['c_0-3998ad31-d504-4b35-bb85-3be6197f1ea0', 'm_1-153ac158-9a57-4bca-8296-bae6389d1ce1']", 'seller': 'm_1-153ac158-9a57-4bca-8296-bae6389d1ce1', 'buyer': 'c_0-3998ad31-d504-4b35-bb85-3be6197f1ea0'} 2019-02-27 11:32:59,101 - DEBUG - 2/10 [30.00%]: Contract [to be signed at 3]: ['c_1', 'm_3'] > {'time': 5, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_1-48b66a5d-80de-4f52-99f0-f2f3af13d7a3: buy 0 (t: 5, u: (0, 2.0), q: (1, 3))', 'partners': "['c_1-48b66a5d-80de-4f52-99f0-f2f3af13d7a3', 'm_3-57429f75-c75c-4cb4-a9b4-ca5c83d682d1']", 'seller': 'm_3-57429f75-c75c-4cb4-a9b4-ca5c83d682d1', 'buyer': 'c_1-48b66a5d-80de-4f52-99f0-f2f3af13d7a3'} 2019-02-27 11:32:59,101 - DEBUG - 2/10 [30.00%]: Contract [to be signed at 3]: ['c_3', 'm_3'] > {'time': 5, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_3-ef402340-68d6-404a-8c4f-8ec5bead3987: buy 0 (t: 5, u: (0, 2.0), q: (1, 3))', 'partners': "['c_3-ef402340-68d6-404a-8c4f-8ec5bead3987', 'm_3-57429f75-c75c-4cb4-a9b4-ca5c83d682d1']", 'seller': 'm_3-57429f75-c75c-4cb4-a9b4-ca5c83d682d1', 'buyer': 'c_3-ef402340-68d6-404a-8c4f-8ec5bead3987'} 2019-02-27 11:32:59,101 - DEBUG - 2/10 [30.00%]: Contract [to be signed at 3]: ['c_2', 'm_2'] > {'time': 5, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_2-88fd8b76-1040-4e98-b476-5e965b64b2fb: buy 0 (t: 5, u: (0, 2.0), q: (1, 4))', 'partners': "['c_2-88fd8b76-1040-4e98-b476-5e965b64b2fb', 'm_2-84165933-f800-4373-8db2-96de0656eead']", 'seller': 'm_2-84165933-f800-4373-8db2-96de0656eead', 'buyer': 'c_2-88fd8b76-1040-4e98-b476-5e965b64b2fb'} 2019-02-27 11:32:59,102 - DEBUG - 2/10 [30.00%]: Contract [to be signed at 3]: ['c_1', 'm_0'] > {'time': 5, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_1-48b66a5d-80de-4f52-99f0-f2f3af13d7a3: buy 0 (t: 5, u: (0, 2.0), q: (1, 3))', 'partners': "['c_1-48b66a5d-80de-4f52-99f0-f2f3af13d7a3', 'm_0-575672e1-efe8-4964-b340-4a6116793ce6']", 'seller': 'm_0-575672e1-efe8-4964-b340-4a6116793ce6', 'buyer': 'c_1-48b66a5d-80de-4f52-99f0-f2f3af13d7a3'} 2019-02-27 11:32:59,102 - DEBUG - 2/10 [30.00%]: Contract [to be signed at 3]: ['c_4', 'm_1'] > {'time': 5, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_4-70a6b468-fb6c-4fd2-b7da-c47f020247d6: buy 0 (t: 5, u: (0, 2.0), q: (1, 3))', 'partners': "['c_4-70a6b468-fb6c-4fd2-b7da-c47f020247d6', 'm_1-153ac158-9a57-4bca-8296-bae6389d1ce1']", 'seller': 'm_1-153ac158-9a57-4bca-8296-bae6389d1ce1', 'buyer': 'c_4-70a6b468-fb6c-4fd2-b7da-c47f020247d6'} 2019-02-27 11:32:59,103 - DEBUG - 2/10 [30.00%]: Contract [to be signed at 3]: ['c_3', 'm_2'] > {'time': 5, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_3-ef402340-68d6-404a-8c4f-8ec5bead3987: buy 0 (t: 5, u: (0, 2.0), q: (1, 3))', 'partners': "['c_3-ef402340-68d6-404a-8c4f-8ec5bead3987', 'm_2-84165933-f800-4373-8db2-96de0656eead']", 'seller': 'm_2-84165933-f800-4373-8db2-96de0656eead', 'buyer': 'c_3-ef402340-68d6-404a-8c4f-8ec5bead3987'} 2019-02-27 11:32:59,103 - DEBUG - 2/10 [30.00%]: Contract [to be signed at 3]: ['c_3', 'm_4'] > {'time': 5, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_3-ef402340-68d6-404a-8c4f-8ec5bead3987: buy 0 (t: 5, u: (0, 2.0), q: (1, 3))', 'partners': "['c_3-ef402340-68d6-404a-8c4f-8ec5bead3987', 'm_4-839c8f96-e52b-40cd-a1ef-3bf468ec11cb']", 'seller': 'm_4-839c8f96-e52b-40cd-a1ef-3bf468ec11cb', 'buyer': 'c_3-ef402340-68d6-404a-8c4f-8ec5bead3987'} 2019-02-27 11:32:59,103 - DEBUG - 2/10 [30.00%]: Contract [to be signed at 3]: ['c_0', 'm_4'] > {'time': 5, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_0-3998ad31-d504-4b35-bb85-3be6197f1ea0: buy 0 (t: 5, u: (0, 2.0), q: (1, 3))', 'partners': "['c_0-3998ad31-d504-4b35-bb85-3be6197f1ea0', 'm_4-839c8f96-e52b-40cd-a1ef-3bf468ec11cb']", 'seller': 'm_4-839c8f96-e52b-40cd-a1ef-3bf468ec11cb', 'buyer': 'c_0-3998ad31-d504-4b35-bb85-3be6197f1ea0'} 2019-02-27 11:32:59,104 - DEBUG - 2/10 [30.00%]: Contract [to be signed at 3]: ['c_4', 'm_4'] > {'time': 5, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_4-70a6b468-fb6c-4fd2-b7da-c47f020247d6: buy 0 (t: 5, u: (0, 2.0), q: (1, 3))', 'partners': "['c_4-70a6b468-fb6c-4fd2-b7da-c47f020247d6', 'm_4-839c8f96-e52b-40cd-a1ef-3bf468ec11cb']", 'seller': 'm_4-839c8f96-e52b-40cd-a1ef-3bf468ec11cb', 'buyer': 'c_4-70a6b468-fb6c-4fd2-b7da-c47f020247d6'} 2019-02-27 11:32:59,104 - DEBUG - 2/10 [30.00%]: Contract [to be signed at 3]: ['c_0', 'm_2'] > {'time': 5, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_0-3998ad31-d504-4b35-bb85-3be6197f1ea0: buy 0 (t: 5, u: (0, 2.0), q: (1, 3))', 'partners': "['c_0-3998ad31-d504-4b35-bb85-3be6197f1ea0', 'm_2-84165933-f800-4373-8db2-96de0656eead']", 'seller': 'm_2-84165933-f800-4373-8db2-96de0656eead', 'buyer': 'c_0-3998ad31-d504-4b35-bb85-3be6197f1ea0'} 2019-02-27 11:32:59,104 - DEBUG - 2/10 [30.00%]: Contract [to be signed at 3]: ['c_1', 'm_1'] > {'time': 5, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_1-48b66a5d-80de-4f52-99f0-f2f3af13d7a3: buy 0 (t: 5, u: (0, 2.0), q: (1, 3))', 'partners': "['c_1-48b66a5d-80de-4f52-99f0-f2f3af13d7a3', 'm_1-153ac158-9a57-4bca-8296-bae6389d1ce1']", 'seller': 'm_1-153ac158-9a57-4bca-8296-bae6389d1ce1', 'buyer': 'c_1-48b66a5d-80de-4f52-99f0-f2f3af13d7a3'} 2019-02-27 11:32:59,106 - INFO - 2/10 [30.00%]: m_0 requested negmas.sao.SAOMechanism[None] with ['c_3', 'm_0'] (ID 92acffd8-37d3-4c6f-a87d-e753b33d2290) 2019-02-27 11:32:59,107 - INFO - 2/10 [30.00%]: m_0-575672e1-efe8-4964-b340-4a6116793ce6 request was accepted 2019-02-27 11:32:59,108 - INFO - 2/10 [30.00%]: m_1 requested negmas.sao.SAOMechanism[None] with ['c_3', 'm_1'] (ID 4bd57bd5-fd88-4e1f-8c22-1b7a78275177) 2019-02-27 11:32:59,109 - INFO - 2/10 [30.00%]: m_1-153ac158-9a57-4bca-8296-bae6389d1ce1 request was accepted 2019-02-27 11:32:59,110 - INFO - 2/10 [30.00%]: m_2 requested negmas.sao.SAOMechanism[None] with ['c_3', 'm_2'] (ID faaaebf3-9136-465f-bd49-91778df70f65) 2019-02-27 11:32:59,110 - INFO - 2/10 [30.00%]: m_2-84165933-f800-4373-8db2-96de0656eead request was accepted 2019-02-27 11:32:59,112 - INFO - 2/10 [30.00%]: m_3 requested negmas.sao.SAOMechanism[None] with ['c_3', 'm_3'] (ID 74940457-9773-4535-a28e-902dce617c31) 2019-02-27 11:32:59,112 - INFO - 2/10 [30.00%]: m_3-57429f75-c75c-4cb4-a9b4-ca5c83d682d1 request was accepted 2019-02-27 11:32:59,113 - INFO - 2/10 [30.00%]: m_4 requested negmas.sao.SAOMechanism[None] with ['c_3', 'm_4'] (ID 307b625b-d0ee-40b3-bf51-48fd4f639c84) 2019-02-27 11:32:59,114 - INFO - 2/10 [30.00%]: m_4-839c8f96-e52b-40cd-a1ef-3bf468ec11cb request was accepted 2019-02-27 11:32:59,116 - INFO - 2/10 [30.00%]: m_0 requested negmas.sao.SAOMechanism[None] with ['c_4', 'm_0'] (ID 7b522679-56c3-4985-844b-20744e0ac258) 2019-02-27 11:32:59,116 - INFO - 2/10 [30.00%]: m_0-575672e1-efe8-4964-b340-4a6116793ce6 request was accepted 2019-02-27 11:32:59,117 - INFO - 2/10 [30.00%]: m_1 requested negmas.sao.SAOMechanism[None] with ['c_4', 'm_1'] (ID ecdcade8-beba-43d4-9acf-59a74a5201da) 2019-02-27 11:32:59,118 - INFO - 2/10 [30.00%]: m_1-153ac158-9a57-4bca-8296-bae6389d1ce1 request was accepted 2019-02-27 11:32:59,120 - INFO - 2/10 [30.00%]: m_2 requested negmas.sao.SAOMechanism[None] with ['c_4', 'm_2'] (ID 534abf01-17f2-4856-b9d8-3fb4772459dc) 2019-02-27 11:32:59,120 - INFO - 2/10 [30.00%]: m_2-84165933-f800-4373-8db2-96de0656eead request was accepted 2019-02-27 11:32:59,121 - INFO - 2/10 [30.00%]: m_3 requested negmas.sao.SAOMechanism[None] with ['c_4', 'm_3'] (ID 5b1d5efa-f287-48e1-8467-d1d491979af8) 2019-02-27 11:32:59,122 - INFO - 2/10 [30.00%]: m_3-57429f75-c75c-4cb4-a9b4-ca5c83d682d1 request was accepted 2019-02-27 11:32:59,123 - INFO - 2/10 [30.00%]: m_4 requested negmas.sao.SAOMechanism[None] with ['c_4', 'm_4'] (ID 65f1e207-5f41-4d6d-9c6d-7a0125243c45) 2019-02-27 11:32:59,124 - INFO - 2/10 [30.00%]: m_4-839c8f96-e52b-40cd-a1ef-3bf468ec11cb request was accepted 2019-02-27 11:32:59,125 - INFO - 2/10 [30.00%]: m_0 requested negmas.sao.SAOMechanism[None] with ['c_1', 'm_0'] (ID 0a8b3391-4662-459d-ade4-3bae1b879905) 2019-02-27 11:32:59,126 - INFO - 2/10 [30.00%]: m_0-575672e1-efe8-4964-b340-4a6116793ce6 request was accepted 2019-02-27 11:32:59,127 - INFO - 2/10 [30.00%]: m_1 requested negmas.sao.SAOMechanism[None] with ['c_1', 'm_1'] (ID 6d9aad16-0627-496a-bca0-135978b46ccd) 2019-02-27 11:32:59,128 - INFO - 2/10 [30.00%]: m_1-153ac158-9a57-4bca-8296-bae6389d1ce1 request was accepted 2019-02-27 11:32:59,129 - INFO - 2/10 [30.00%]: m_2 requested negmas.sao.SAOMechanism[None] with ['c_1', 'm_2'] (ID 68184fb2-51ac-49f7-9321-d7698e6feb64) 2019-02-27 11:32:59,129 - INFO - 2/10 [30.00%]: m_2-84165933-f800-4373-8db2-96de0656eead request was accepted 2019-02-27 11:32:59,130 - INFO - 2/10 [30.00%]: m_3 requested negmas.sao.SAOMechanism[None] with ['c_1', 'm_3'] (ID 9e45f326-c592-40fb-a1a6-c9389bf7fd6f) 2019-02-27 11:32:59,131 - INFO - 2/10 [30.00%]: m_3-57429f75-c75c-4cb4-a9b4-ca5c83d682d1 request was accepted 2019-02-27 11:32:59,132 - INFO - 2/10 [30.00%]: m_4 requested negmas.sao.SAOMechanism[None] with ['c_1', 'm_4'] (ID 173f1bcb-5881-44d9-aa82-ac87bf9d7d0f) 2019-02-27 11:32:59,133 - INFO - 2/10 [30.00%]: m_4-839c8f96-e52b-40cd-a1ef-3bf468ec11cb request was accepted 2019-02-27 11:32:59,135 - INFO - 2/10 [30.00%]: m_0 requested negmas.sao.SAOMechanism[None] with ['c_0', 'm_0'] (ID 5add9c94-996c-40df-bdca-9205ca8d4ebe) 2019-02-27 11:32:59,135 - INFO - 2/10 [30.00%]: m_0-575672e1-efe8-4964-b340-4a6116793ce6 request was accepted 2019-02-27 11:32:59,137 - INFO - 2/10 [30.00%]: m_1 requested negmas.sao.SAOMechanism[None] with ['c_0', 'm_1'] (ID 895600ee-47f9-4e10-bde2-2e8766cd1fe6) 2019-02-27 11:32:59,137 - INFO - 2/10 [30.00%]: m_1-153ac158-9a57-4bca-8296-bae6389d1ce1 request was accepted 2019-02-27 11:32:59,140 - INFO - 2/10 [30.00%]: m_2 requested negmas.sao.SAOMechanism[None] with ['c_0', 'm_2'] (ID 8ad09674-3318-406b-a581-db703e95c849) 2019-02-27 11:32:59,140 - INFO - 2/10 [30.00%]: m_2-84165933-f800-4373-8db2-96de0656eead request was accepted 2019-02-27 11:32:59,141 - INFO - 2/10 [30.00%]: m_3 requested negmas.sao.SAOMechanism[None] with ['c_0', 'm_3'] (ID 8376c58e-9a9c-4019-a1f7-758e827b4d6e) 2019-02-27 11:32:59,142 - INFO - 2/10 [30.00%]: m_3-57429f75-c75c-4cb4-a9b4-ca5c83d682d1 request was accepted 2019-02-27 11:32:59,143 - INFO - 2/10 [30.00%]: m_4 requested negmas.sao.SAOMechanism[None] with ['c_0', 'm_4'] (ID bb9d5fad-f019-4ef4-af6d-cfdacd82123f) 2019-02-27 11:32:59,144 - INFO - 2/10 [30.00%]: m_4-839c8f96-e52b-40cd-a1ef-3bf468ec11cb request was accepted 2019-02-27 11:32:59,145 - INFO - 2/10 [30.00%]: m_0 requested negmas.sao.SAOMechanism[None] with ['c_2', 'm_0'] (ID 3391399a-c2a2-49c2-9eae-0bfe06413046) 2019-02-27 11:32:59,146 - INFO - 2/10 [30.00%]: m_0-575672e1-efe8-4964-b340-4a6116793ce6 request was accepted 2019-02-27 11:32:59,147 - INFO - 2/10 [30.00%]: m_1 requested negmas.sao.SAOMechanism[None] with ['c_2', 'm_1'] (ID fbe84a9d-718f-404e-a5e1-db38d7d59d0c) 2019-02-27 11:32:59,148 - INFO - 2/10 [30.00%]: m_1-153ac158-9a57-4bca-8296-bae6389d1ce1 request was accepted 2019-02-27 11:32:59,149 - INFO - 2/10 [30.00%]: m_2 requested negmas.sao.SAOMechanism[None] with ['c_2', 'm_2'] (ID a2010204-128a-4abc-b5a7-e61a1e3b750f) 2019-02-27 11:32:59,150 - INFO - 2/10 [30.00%]: m_2-84165933-f800-4373-8db2-96de0656eead request was accepted 2019-02-27 11:32:59,152 - INFO - 2/10 [30.00%]: m_3 requested negmas.sao.SAOMechanism[None] with ['c_2', 'm_3'] (ID a663c984-86fe-41a6-a961-fe06498c0e9c) 2019-02-27 11:32:59,152 - INFO - 2/10 [30.00%]: m_3-57429f75-c75c-4cb4-a9b4-ca5c83d682d1 request was accepted 2019-02-27 11:32:59,154 - INFO - 2/10 [30.00%]: m_4 requested negmas.sao.SAOMechanism[None] with ['c_2', 'm_4'] (ID dc2f3b43-ed40-4da8-9448-7c48f00decde) 2019-02-27 11:32:59,154 - INFO - 2/10 [30.00%]: m_4-839c8f96-e52b-40cd-a1ef-3bf468ec11cb request was accepted 2019-02-27 11:32:59,154 - INFO - 2/10 [30.00%]: Executing c_4-70a6b468-fb6c-4fd2-b7da-c47f020247d6, m_1-153ac158-9a57-4bca-8296-bae6389d1ce1 agreed on {'time': 2, 'quantity': 3, 'unit_price': 0.5} 2019-02-27 11:32:59,154 - DEBUG - 2/10 [30.00%]: Moved 3 units of p0 from m_1 to c_4 for 1.5 dollars 2019-02-27 11:32:59,154 - INFO - 2/10 [30.00%]: Executing c_0-3998ad31-d504-4b35-bb85-3be6197f1ea0, m_1-153ac158-9a57-4bca-8296-bae6389d1ce1 agreed on {'time': 2, 'quantity': 4, 'unit_price': 0.5} 2019-02-27 11:32:59,154 - DEBUG - 2/10 [30.00%]: Moved 4 units of p0 from m_1 to c_0 for 2.0 dollars 2019-02-27 11:32:59,155 - INFO - 2/10 [30.00%]: Executing c_2-88fd8b76-1040-4e98-b476-5e965b64b2fb, m_3-57429f75-c75c-4cb4-a9b4-ca5c83d682d1 agreed on {'time': 2, 'quantity': 4, 'unit_price': 0.5} 2019-02-27 11:32:59,155 - DEBUG - 2/10 [30.00%]: Moved 4 units of p0 from m_3 to c_2 for 2.0 dollars 2019-02-27 11:32:59,155 - INFO - 2/10 [30.00%]: Executing c_3-ef402340-68d6-404a-8c4f-8ec5bead3987, m_0-575672e1-efe8-4964-b340-4a6116793ce6 agreed on {'time': 2, 'quantity': 4, 'unit_price': 0.5} 2019-02-27 11:32:59,155 - DEBUG - 2/10 [30.00%]: Moved 4 units of p0 from m_0 to c_3 for 2.0 dollars 2019-02-27 11:32:59,155 - INFO - 2/10 [30.00%]: Executing c_1-48b66a5d-80de-4f52-99f0-f2f3af13d7a3, m_3-57429f75-c75c-4cb4-a9b4-ca5c83d682d1 agreed on {'time': 2, 'quantity': 3, 'unit_price': 0.5} 2019-02-27 11:32:59,155 - DEBUG - 2/10 [30.00%]: Moved 3 units of p0 from m_3 to c_1 for 1.5 dollars 2019-02-27 11:32:59,155 - DEBUG - 2/10 [30.00%]: Factory 2b84599b-e538-4212-b349-d4a05459c15b: money=-2.0, storage={}, loans=0.0 2019-02-27 11:32:59,155 - DEBUG - 2/10 [30.00%]: Factory fed30dd7-5bba-4df3-9386-c2570ef237d4: money=-1.5, storage={}, loans=0.0 2019-02-27 11:32:59,155 - DEBUG - 2/10 [30.00%]: Factory 2b9215ac-5da4-4788-8222-002f92ac7b3c: money=-2.0, storage={}, loans=0.0 2019-02-27 11:32:59,155 - DEBUG - 2/10 [30.00%]: Factory 1f8923b6-aef8-4008-a31c-b18482add390: money=-2.0, storage={}, loans=0.0 2019-02-27 11:32:59,155 - DEBUG - 2/10 [30.00%]: Factory 30f40890-1d90-499c-87f7-ac48be226a56: money=-1.5, storage={}, loans=0.0 2019-02-27 11:32:59,155 - DEBUG - 2/10 [30.00%]: Factory f6c073fa-9343-49a7-b738-ccd0b9381c40: money=2.0, storage={0: -4}, loans=0.0 2019-02-27 11:32:59,155 - DEBUG - 2/10 [30.00%]: Factory 62cc9ee6-9600-42d1-83dd-216923d114b1: money=3.5, storage={0: -7}, loans=0.0 2019-02-27 11:32:59,155 - DEBUG - 2/10 [30.00%]: Factory e11f4f3c-15a1-461a-bd2c-632e07f82b5f: money=0.0, storage={}, loans=0.0 2019-02-27 11:32:59,155 - DEBUG - 2/10 [30.00%]: Factory 3583ffd0-fef8-4a83-be5d-0fa6562d4c9f: money=3.5, storage={0: -7}, loans=0.0 2019-02-27 11:32:59,155 - DEBUG - 2/10 [30.00%]: Factory eb0d4726-61b8-4266-8c97-4416e5746a6f: money=0.0, storage={}, loans=0.0 2019-02-27 11:32:59,155 - INFO - 3/10 [40.00%]: 25 Negotiations/4 _entities 2019-02-27 11:32:59,391 - DEBUG - 3/10 [40.00%]: Contract [to be signed at 4]: ['c_0', 'm_0'] > {'time': 6, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_0-3998ad31-d504-4b35-bb85-3be6197f1ea0: buy 0 (t: 6, u: (0, 2.0), q: (1, 3))', 'partners': "['c_0-3998ad31-d504-4b35-bb85-3be6197f1ea0', 'm_0-575672e1-efe8-4964-b340-4a6116793ce6']", 'seller': 'm_0-575672e1-efe8-4964-b340-4a6116793ce6', 'buyer': 'c_0-3998ad31-d504-4b35-bb85-3be6197f1ea0'} 2019-02-27 11:32:59,391 - DEBUG - 3/10 [40.00%]: Contract [to be signed at 4]: ['c_0', 'm_4'] > {'time': 6, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_0-3998ad31-d504-4b35-bb85-3be6197f1ea0: buy 0 (t: 6, u: (0, 2.0), q: (1, 3))', 'partners': "['c_0-3998ad31-d504-4b35-bb85-3be6197f1ea0', 'm_4-839c8f96-e52b-40cd-a1ef-3bf468ec11cb']", 'seller': 'm_4-839c8f96-e52b-40cd-a1ef-3bf468ec11cb', 'buyer': 'c_0-3998ad31-d504-4b35-bb85-3be6197f1ea0'} 2019-02-27 11:32:59,392 - DEBUG - 3/10 [40.00%]: Contract [to be signed at 4]: ['c_4', 'm_2'] > {'time': 6, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_4-70a6b468-fb6c-4fd2-b7da-c47f020247d6: buy 0 (t: 6, u: (0, 2.0), q: (1, 4))', 'partners': "['c_4-70a6b468-fb6c-4fd2-b7da-c47f020247d6', 'm_2-84165933-f800-4373-8db2-96de0656eead']", 'seller': 'm_2-84165933-f800-4373-8db2-96de0656eead', 'buyer': 'c_4-70a6b468-fb6c-4fd2-b7da-c47f020247d6'} 2019-02-27 11:32:59,392 - DEBUG - 3/10 [40.00%]: Contract [to be signed at 4]: ['c_3', 'm_4'] > {'time': 6, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_3-ef402340-68d6-404a-8c4f-8ec5bead3987: buy 0 (t: 6, u: (0, 2.0), q: (1, 4))', 'partners': "['c_3-ef402340-68d6-404a-8c4f-8ec5bead3987', 'm_4-839c8f96-e52b-40cd-a1ef-3bf468ec11cb']", 'seller': 'm_4-839c8f96-e52b-40cd-a1ef-3bf468ec11cb', 'buyer': 'c_3-ef402340-68d6-404a-8c4f-8ec5bead3987'} 2019-02-27 11:32:59,392 - DEBUG - 3/10 [40.00%]: Contract [to be signed at 4]: ['c_0', 'm_1'] > {'time': 6, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_0-3998ad31-d504-4b35-bb85-3be6197f1ea0: buy 0 (t: 6, u: (0, 2.0), q: (1, 3))', 'partners': "['c_0-3998ad31-d504-4b35-bb85-3be6197f1ea0', 'm_1-153ac158-9a57-4bca-8296-bae6389d1ce1']", 'seller': 'm_1-153ac158-9a57-4bca-8296-bae6389d1ce1', 'buyer': 'c_0-3998ad31-d504-4b35-bb85-3be6197f1ea0'} 2019-02-27 11:32:59,392 - DEBUG - 3/10 [40.00%]: Contract [to be signed at 4]: ['c_2', 'm_2'] > {'time': 6, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_2-88fd8b76-1040-4e98-b476-5e965b64b2fb: buy 0 (t: 6, u: (0, 2.0), q: (1, 4))', 'partners': "['c_2-88fd8b76-1040-4e98-b476-5e965b64b2fb', 'm_2-84165933-f800-4373-8db2-96de0656eead']", 'seller': 'm_2-84165933-f800-4373-8db2-96de0656eead', 'buyer': 'c_2-88fd8b76-1040-4e98-b476-5e965b64b2fb'} 2019-02-27 11:32:59,393 - DEBUG - 3/10 [40.00%]: Contract [to be signed at 4]: ['c_3', 'm_2'] > {'time': 6, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_3-ef402340-68d6-404a-8c4f-8ec5bead3987: buy 0 (t: 6, u: (0, 2.0), q: (1, 4))', 'partners': "['c_3-ef402340-68d6-404a-8c4f-8ec5bead3987', 'm_2-84165933-f800-4373-8db2-96de0656eead']", 'seller': 'm_2-84165933-f800-4373-8db2-96de0656eead', 'buyer': 'c_3-ef402340-68d6-404a-8c4f-8ec5bead3987'} 2019-02-27 11:32:59,393 - DEBUG - 3/10 [40.00%]: Contract [to be signed at 4]: ['c_4', 'm_3'] > {'time': 6, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_4-70a6b468-fb6c-4fd2-b7da-c47f020247d6: buy 0 (t: 6, u: (0, 2.0), q: (1, 4))', 'partners': "['c_4-70a6b468-fb6c-4fd2-b7da-c47f020247d6', 'm_3-57429f75-c75c-4cb4-a9b4-ca5c83d682d1']", 'seller': 'm_3-57429f75-c75c-4cb4-a9b4-ca5c83d682d1', 'buyer': 'c_4-70a6b468-fb6c-4fd2-b7da-c47f020247d6'} 2019-02-27 11:32:59,393 - DEBUG - 3/10 [40.00%]: Contract [to be signed at 4]: ['c_2', 'm_1'] > {'time': 6, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_2-88fd8b76-1040-4e98-b476-5e965b64b2fb: buy 0 (t: 6, u: (0, 2.0), q: (1, 4))', 'partners': "['c_2-88fd8b76-1040-4e98-b476-5e965b64b2fb', 'm_1-153ac158-9a57-4bca-8296-bae6389d1ce1']", 'seller': 'm_1-153ac158-9a57-4bca-8296-bae6389d1ce1', 'buyer': 'c_2-88fd8b76-1040-4e98-b476-5e965b64b2fb'} 2019-02-27 11:32:59,394 - DEBUG - 3/10 [40.00%]: Contract [to be signed at 4]: ['c_4', 'm_0'] > {'time': 6, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_4-70a6b468-fb6c-4fd2-b7da-c47f020247d6: buy 0 (t: 6, u: (0, 2.0), q: (1, 4))', 'partners': "['c_4-70a6b468-fb6c-4fd2-b7da-c47f020247d6', 'm_0-575672e1-efe8-4964-b340-4a6116793ce6']", 'seller': 'm_0-575672e1-efe8-4964-b340-4a6116793ce6', 'buyer': 'c_4-70a6b468-fb6c-4fd2-b7da-c47f020247d6'} 2019-02-27 11:32:59,394 - DEBUG - 3/10 [40.00%]: Contract [to be signed at 4]: ['c_0', 'm_3'] > {'time': 6, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_0-3998ad31-d504-4b35-bb85-3be6197f1ea0: buy 0 (t: 6, u: (0, 2.0), q: (1, 3))', 'partners': "['c_0-3998ad31-d504-4b35-bb85-3be6197f1ea0', 'm_3-57429f75-c75c-4cb4-a9b4-ca5c83d682d1']", 'seller': 'm_3-57429f75-c75c-4cb4-a9b4-ca5c83d682d1', 'buyer': 'c_0-3998ad31-d504-4b35-bb85-3be6197f1ea0'} 2019-02-27 11:32:59,394 - DEBUG - 3/10 [40.00%]: Contract [to be signed at 4]: ['c_3', 'm_3'] > {'time': 6, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_3-ef402340-68d6-404a-8c4f-8ec5bead3987: buy 0 (t: 6, u: (0, 2.0), q: (1, 4))', 'partners': "['c_3-ef402340-68d6-404a-8c4f-8ec5bead3987', 'm_3-57429f75-c75c-4cb4-a9b4-ca5c83d682d1']", 'seller': 'm_3-57429f75-c75c-4cb4-a9b4-ca5c83d682d1', 'buyer': 'c_3-ef402340-68d6-404a-8c4f-8ec5bead3987'} 2019-02-27 11:32:59,395 - DEBUG - 3/10 [40.00%]: Contract [to be signed at 4]: ['c_4', 'm_1'] > {'time': 6, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_4-70a6b468-fb6c-4fd2-b7da-c47f020247d6: buy 0 (t: 6, u: (0, 2.0), q: (1, 4))', 'partners': "['c_4-70a6b468-fb6c-4fd2-b7da-c47f020247d6', 'm_1-153ac158-9a57-4bca-8296-bae6389d1ce1']", 'seller': 'm_1-153ac158-9a57-4bca-8296-bae6389d1ce1', 'buyer': 'c_4-70a6b468-fb6c-4fd2-b7da-c47f020247d6'} 2019-02-27 11:32:59,395 - DEBUG - 3/10 [40.00%]: Contract [to be signed at 4]: ['c_0', 'm_2'] > {'time': 6, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_0-3998ad31-d504-4b35-bb85-3be6197f1ea0: buy 0 (t: 6, u: (0, 2.0), q: (1, 3))', 'partners': "['c_0-3998ad31-d504-4b35-bb85-3be6197f1ea0', 'm_2-84165933-f800-4373-8db2-96de0656eead']", 'seller': 'm_2-84165933-f800-4373-8db2-96de0656eead', 'buyer': 'c_0-3998ad31-d504-4b35-bb85-3be6197f1ea0'} 2019-02-27 11:32:59,395 - DEBUG - 3/10 [40.00%]: Contract [to be signed at 4]: ['c_1', 'm_0'] > {'time': 6, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_1-48b66a5d-80de-4f52-99f0-f2f3af13d7a3: buy 0 (t: 6, u: (0, 2.0), q: (1, 4))', 'partners': "['c_1-48b66a5d-80de-4f52-99f0-f2f3af13d7a3', 'm_0-575672e1-efe8-4964-b340-4a6116793ce6']", 'seller': 'm_0-575672e1-efe8-4964-b340-4a6116793ce6', 'buyer': 'c_1-48b66a5d-80de-4f52-99f0-f2f3af13d7a3'} 2019-02-27 11:32:59,396 - DEBUG - 3/10 [40.00%]: Contract [to be signed at 4]: ['c_2', 'm_0'] > {'time': 6, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_2-88fd8b76-1040-4e98-b476-5e965b64b2fb: buy 0 (t: 6, u: (0, 2.0), q: (1, 4))', 'partners': "['c_2-88fd8b76-1040-4e98-b476-5e965b64b2fb', 'm_0-575672e1-efe8-4964-b340-4a6116793ce6']", 'seller': 'm_0-575672e1-efe8-4964-b340-4a6116793ce6', 'buyer': 'c_2-88fd8b76-1040-4e98-b476-5e965b64b2fb'} 2019-02-27 11:32:59,396 - DEBUG - 3/10 [40.00%]: Contract [to be signed at 4]: ['c_1', 'm_3'] > {'time': 6, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_1-48b66a5d-80de-4f52-99f0-f2f3af13d7a3: buy 0 (t: 6, u: (0, 2.0), q: (1, 4))', 'partners': "['c_1-48b66a5d-80de-4f52-99f0-f2f3af13d7a3', 'm_3-57429f75-c75c-4cb4-a9b4-ca5c83d682d1']", 'seller': 'm_3-57429f75-c75c-4cb4-a9b4-ca5c83d682d1', 'buyer': 'c_1-48b66a5d-80de-4f52-99f0-f2f3af13d7a3'} 2019-02-27 11:32:59,396 - DEBUG - 3/10 [40.00%]: Contract [to be signed at 4]: ['c_1', 'm_2'] > {'time': 6, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_1-48b66a5d-80de-4f52-99f0-f2f3af13d7a3: buy 0 (t: 6, u: (0, 2.0), q: (1, 4))', 'partners': "['c_1-48b66a5d-80de-4f52-99f0-f2f3af13d7a3', 'm_2-84165933-f800-4373-8db2-96de0656eead']", 'seller': 'm_2-84165933-f800-4373-8db2-96de0656eead', 'buyer': 'c_1-48b66a5d-80de-4f52-99f0-f2f3af13d7a3'} 2019-02-27 11:32:59,397 - DEBUG - 3/10 [40.00%]: Contract [to be signed at 4]: ['c_1', 'm_1'] > {'time': 6, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_1-48b66a5d-80de-4f52-99f0-f2f3af13d7a3: buy 0 (t: 6, u: (0, 2.0), q: (1, 4))', 'partners': "['c_1-48b66a5d-80de-4f52-99f0-f2f3af13d7a3', 'm_1-153ac158-9a57-4bca-8296-bae6389d1ce1']", 'seller': 'm_1-153ac158-9a57-4bca-8296-bae6389d1ce1', 'buyer': 'c_1-48b66a5d-80de-4f52-99f0-f2f3af13d7a3'} 2019-02-27 11:32:59,397 - DEBUG - 3/10 [40.00%]: Contract [to be signed at 4]: ['c_3', 'm_1'] > {'time': 6, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_3-ef402340-68d6-404a-8c4f-8ec5bead3987: buy 0 (t: 6, u: (0, 2.0), q: (1, 4))', 'partners': "['c_3-ef402340-68d6-404a-8c4f-8ec5bead3987', 'm_1-153ac158-9a57-4bca-8296-bae6389d1ce1']", 'seller': 'm_1-153ac158-9a57-4bca-8296-bae6389d1ce1', 'buyer': 'c_3-ef402340-68d6-404a-8c4f-8ec5bead3987'} 2019-02-27 11:32:59,398 - DEBUG - 3/10 [40.00%]: Contract [to be signed at 4]: ['c_2', 'm_4'] > {'time': 6, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_2-88fd8b76-1040-4e98-b476-5e965b64b2fb: buy 0 (t: 6, u: (0, 2.0), q: (1, 4))', 'partners': "['c_2-88fd8b76-1040-4e98-b476-5e965b64b2fb', 'm_4-839c8f96-e52b-40cd-a1ef-3bf468ec11cb']", 'seller': 'm_4-839c8f96-e52b-40cd-a1ef-3bf468ec11cb', 'buyer': 'c_2-88fd8b76-1040-4e98-b476-5e965b64b2fb'} 2019-02-27 11:32:59,398 - DEBUG - 3/10 [40.00%]: Contract [to be signed at 4]: ['c_4', 'm_4'] > {'time': 6, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_4-70a6b468-fb6c-4fd2-b7da-c47f020247d6: buy 0 (t: 6, u: (0, 2.0), q: (1, 4))', 'partners': "['c_4-70a6b468-fb6c-4fd2-b7da-c47f020247d6', 'm_4-839c8f96-e52b-40cd-a1ef-3bf468ec11cb']", 'seller': 'm_4-839c8f96-e52b-40cd-a1ef-3bf468ec11cb', 'buyer': 'c_4-70a6b468-fb6c-4fd2-b7da-c47f020247d6'} 2019-02-27 11:32:59,398 - DEBUG - 3/10 [40.00%]: Contract [to be signed at 4]: ['c_3', 'm_0'] > {'time': 6, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_3-ef402340-68d6-404a-8c4f-8ec5bead3987: buy 0 (t: 6, u: (0, 2.0), q: (1, 4))', 'partners': "['c_3-ef402340-68d6-404a-8c4f-8ec5bead3987', 'm_0-575672e1-efe8-4964-b340-4a6116793ce6']", 'seller': 'm_0-575672e1-efe8-4964-b340-4a6116793ce6', 'buyer': 'c_3-ef402340-68d6-404a-8c4f-8ec5bead3987'} 2019-02-27 11:32:59,399 - DEBUG - 3/10 [40.00%]: Contract [to be signed at 4]: ['c_2', 'm_3'] > {'time': 6, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_2-88fd8b76-1040-4e98-b476-5e965b64b2fb: buy 0 (t: 6, u: (0, 2.0), q: (1, 4))', 'partners': "['c_2-88fd8b76-1040-4e98-b476-5e965b64b2fb', 'm_3-57429f75-c75c-4cb4-a9b4-ca5c83d682d1']", 'seller': 'm_3-57429f75-c75c-4cb4-a9b4-ca5c83d682d1', 'buyer': 'c_2-88fd8b76-1040-4e98-b476-5e965b64b2fb'} 2019-02-27 11:32:59,399 - DEBUG - 3/10 [40.00%]: Contract [to be signed at 4]: ['c_1', 'm_4'] > {'time': 6, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_1-48b66a5d-80de-4f52-99f0-f2f3af13d7a3: buy 0 (t: 6, u: (0, 2.0), q: (1, 4))', 'partners': "['c_1-48b66a5d-80de-4f52-99f0-f2f3af13d7a3', 'm_4-839c8f96-e52b-40cd-a1ef-3bf468ec11cb']", 'seller': 'm_4-839c8f96-e52b-40cd-a1ef-3bf468ec11cb', 'buyer': 'c_1-48b66a5d-80de-4f52-99f0-f2f3af13d7a3'} 2019-02-27 11:32:59,401 - INFO - 3/10 [40.00%]: m_0 requested negmas.sao.SAOMechanism[None] with ['c_3', 'm_0'] (ID e0ceb45a-d612-4b6e-a145-03dff081305b) 2019-02-27 11:32:59,402 - INFO - 3/10 [40.00%]: m_0-575672e1-efe8-4964-b340-4a6116793ce6 request was accepted 2019-02-27 11:32:59,403 - INFO - 3/10 [40.00%]: m_1 requested negmas.sao.SAOMechanism[None] with ['c_3', 'm_1'] (ID f9ff2cfb-82e6-4131-9b89-c8e023ca5f42) 2019-02-27 11:32:59,404 - INFO - 3/10 [40.00%]: m_1-153ac158-9a57-4bca-8296-bae6389d1ce1 request was accepted 2019-02-27 11:32:59,405 - INFO - 3/10 [40.00%]: m_2 requested negmas.sao.SAOMechanism[None] with ['c_3', 'm_2'] (ID c22ad2c3-e468-4b60-88f9-c42422040835) 2019-02-27 11:32:59,406 - INFO - 3/10 [40.00%]: m_2-84165933-f800-4373-8db2-96de0656eead request was accepted 2019-02-27 11:32:59,407 - INFO - 3/10 [40.00%]: m_3 requested negmas.sao.SAOMechanism[None] with ['c_3', 'm_3'] (ID 05f1d477-2833-466f-adc7-49bf96974b3f) 2019-02-27 11:32:59,408 - INFO - 3/10 [40.00%]: m_3-57429f75-c75c-4cb4-a9b4-ca5c83d682d1 request was accepted 2019-02-27 11:32:59,410 - INFO - 3/10 [40.00%]: m_4 requested negmas.sao.SAOMechanism[None] with ['c_3', 'm_4'] (ID 4165227d-8180-427e-9460-03f5f6bccc76) 2019-02-27 11:32:59,412 - INFO - 3/10 [40.00%]: m_4-839c8f96-e52b-40cd-a1ef-3bf468ec11cb request was accepted 2019-02-27 11:32:59,414 - INFO - 3/10 [40.00%]: m_0 requested negmas.sao.SAOMechanism[None] with ['c_4', 'm_0'] (ID 53c91636-dfe6-49f1-a005-a4982d94c143) 2019-02-27 11:32:59,415 - INFO - 3/10 [40.00%]: m_0-575672e1-efe8-4964-b340-4a6116793ce6 request was accepted 2019-02-27 11:32:59,417 - INFO - 3/10 [40.00%]: m_1 requested negmas.sao.SAOMechanism[None] with ['c_4', 'm_1'] (ID 8b06dd7a-8446-43ba-88ad-85a2b6862eaa) 2019-02-27 11:32:59,418 - INFO - 3/10 [40.00%]: m_1-153ac158-9a57-4bca-8296-bae6389d1ce1 request was accepted 2019-02-27 11:32:59,420 - INFO - 3/10 [40.00%]: m_2 requested negmas.sao.SAOMechanism[None] with ['c_4', 'm_2'] (ID 23d713c3-cabd-4661-841f-8e532e463589) 2019-02-27 11:32:59,421 - INFO - 3/10 [40.00%]: m_2-84165933-f800-4373-8db2-96de0656eead request was accepted 2019-02-27 11:32:59,422 - INFO - 3/10 [40.00%]: m_3 requested negmas.sao.SAOMechanism[None] with ['c_4', 'm_3'] (ID 2b2e2af9-467c-451d-8c2d-563376a85fe8) 2019-02-27 11:32:59,423 - INFO - 3/10 [40.00%]: m_3-57429f75-c75c-4cb4-a9b4-ca5c83d682d1 request was accepted 2019-02-27 11:32:59,424 - INFO - 3/10 [40.00%]: m_4 requested negmas.sao.SAOMechanism[None] with ['c_4', 'm_4'] (ID 1ecdfb83-2861-408c-9aa2-4026d768d3ab) 2019-02-27 11:32:59,425 - INFO - 3/10 [40.00%]: m_4-839c8f96-e52b-40cd-a1ef-3bf468ec11cb request was accepted 2019-02-27 11:32:59,426 - INFO - 3/10 [40.00%]: m_0 requested negmas.sao.SAOMechanism[None] with ['c_1', 'm_0'] (ID 43388038-0199-4ba8-a213-36a6b8f8550f) 2019-02-27 11:32:59,427 - INFO - 3/10 [40.00%]: m_0-575672e1-efe8-4964-b340-4a6116793ce6 request was accepted 2019-02-27 11:32:59,428 - INFO - 3/10 [40.00%]: m_1 requested negmas.sao.SAOMechanism[None] with ['c_1', 'm_1'] (ID 77f3a3c5-f61c-4c03-8094-78ff1b375483) 2019-02-27 11:32:59,429 - INFO - 3/10 [40.00%]: m_1-153ac158-9a57-4bca-8296-bae6389d1ce1 request was accepted 2019-02-27 11:32:59,430 - INFO - 3/10 [40.00%]: m_2 requested negmas.sao.SAOMechanism[None] with ['c_1', 'm_2'] (ID 921220ad-fc95-4446-b3c2-dc2f9282bffb) 2019-02-27 11:32:59,430 - INFO - 3/10 [40.00%]: m_2-84165933-f800-4373-8db2-96de0656eead request was accepted 2019-02-27 11:32:59,431 - INFO - 3/10 [40.00%]: m_3 requested negmas.sao.SAOMechanism[None] with ['c_1', 'm_3'] (ID 0cf61f9c-315f-4b5a-8913-3d37cd3301e5) 2019-02-27 11:32:59,432 - INFO - 3/10 [40.00%]: m_3-57429f75-c75c-4cb4-a9b4-ca5c83d682d1 request was accepted 2019-02-27 11:32:59,433 - INFO - 3/10 [40.00%]: m_4 requested negmas.sao.SAOMechanism[None] with ['c_1', 'm_4'] (ID 22956261-3b98-4693-9bc9-71b55b98b018) 2019-02-27 11:32:59,434 - INFO - 3/10 [40.00%]: m_4-839c8f96-e52b-40cd-a1ef-3bf468ec11cb request was accepted 2019-02-27 11:32:59,435 - INFO - 3/10 [40.00%]: m_0 requested negmas.sao.SAOMechanism[None] with ['c_0', 'm_0'] (ID 8c7a994d-fdd1-48de-8837-684b93dd5c02) 2019-02-27 11:32:59,437 - INFO - 3/10 [40.00%]: m_0-575672e1-efe8-4964-b340-4a6116793ce6 request was accepted 2019-02-27 11:32:59,438 - INFO - 3/10 [40.00%]: m_1 requested negmas.sao.SAOMechanism[None] with ['c_0', 'm_1'] (ID cc4253ec-e0a3-4acc-915d-8f599d793c1e) 2019-02-27 11:32:59,441 - INFO - 3/10 [40.00%]: m_1-153ac158-9a57-4bca-8296-bae6389d1ce1 request was accepted 2019-02-27 11:32:59,443 - INFO - 3/10 [40.00%]: m_2 requested negmas.sao.SAOMechanism[None] with ['c_0', 'm_2'] (ID 72d916d7-69af-4aa0-8c7b-eb6dfa522d44) 2019-02-27 11:32:59,444 - INFO - 3/10 [40.00%]: m_2-84165933-f800-4373-8db2-96de0656eead request was accepted 2019-02-27 11:32:59,445 - INFO - 3/10 [40.00%]: m_3 requested negmas.sao.SAOMechanism[None] with ['c_0', 'm_3'] (ID 5a67b81b-500a-4a59-92ab-4d9c4dd65f1e) 2019-02-27 11:32:59,446 - INFO - 3/10 [40.00%]: m_3-57429f75-c75c-4cb4-a9b4-ca5c83d682d1 request was accepted 2019-02-27 11:32:59,448 - INFO - 3/10 [40.00%]: m_4 requested negmas.sao.SAOMechanism[None] with ['c_0', 'm_4'] (ID d5e43895-bce0-4a4e-b6a3-42bb6b41c87a) 2019-02-27 11:32:59,449 - INFO - 3/10 [40.00%]: m_4-839c8f96-e52b-40cd-a1ef-3bf468ec11cb request was accepted 2019-02-27 11:32:59,453 - INFO - 3/10 [40.00%]: m_0 requested negmas.sao.SAOMechanism[None] with ['c_2', 'm_0'] (ID 4f7439c8-2286-4437-b4b2-85306a128f93) 2019-02-27 11:32:59,454 - INFO - 3/10 [40.00%]: m_0-575672e1-efe8-4964-b340-4a6116793ce6 request was accepted 2019-02-27 11:32:59,456 - INFO - 3/10 [40.00%]: m_1 requested negmas.sao.SAOMechanism[None] with ['c_2', 'm_1'] (ID bef08c67-a153-4d64-8df5-41254cddeab0) 2019-02-27 11:32:59,457 - INFO - 3/10 [40.00%]: m_1-153ac158-9a57-4bca-8296-bae6389d1ce1 request was accepted 2019-02-27 11:32:59,459 - INFO - 3/10 [40.00%]: m_2 requested negmas.sao.SAOMechanism[None] with ['c_2', 'm_2'] (ID 64ae23d5-4119-41b0-9fba-a5490f5d6e1f) 2019-02-27 11:32:59,460 - INFO - 3/10 [40.00%]: m_2-84165933-f800-4373-8db2-96de0656eead request was accepted 2019-02-27 11:32:59,461 - INFO - 3/10 [40.00%]: m_3 requested negmas.sao.SAOMechanism[None] with ['c_2', 'm_3'] (ID cabb2269-7318-407a-9da5-df8a1cce1d80) 2019-02-27 11:32:59,461 - INFO - 3/10 [40.00%]: m_3-57429f75-c75c-4cb4-a9b4-ca5c83d682d1 request was accepted 2019-02-27 11:32:59,463 - INFO - 3/10 [40.00%]: m_4 requested negmas.sao.SAOMechanism[None] with ['c_2', 'm_4'] (ID d12b2b7c-ef08-44e3-92df-03c9ecb75557) 2019-02-27 11:32:59,463 - INFO - 3/10 [40.00%]: m_4-839c8f96-e52b-40cd-a1ef-3bf468ec11cb request was accepted 2019-02-27 11:32:59,463 - INFO - 3/10 [40.00%]: Executing c_3-ef402340-68d6-404a-8c4f-8ec5bead3987, m_0-575672e1-efe8-4964-b340-4a6116793ce6 agreed on {'time': 3, 'quantity': 3, 'unit_price': 0.5} 2019-02-27 11:32:59,463 - DEBUG - 3/10 [40.00%]: Moved 3 units of p0 from m_0 to c_3 for 1.5 dollars 2019-02-27 11:32:59,464 - INFO - 3/10 [40.00%]: Executing c_1-48b66a5d-80de-4f52-99f0-f2f3af13d7a3, m_1-153ac158-9a57-4bca-8296-bae6389d1ce1 agreed on {'time': 3, 'quantity': 4, 'unit_price': 0.5} 2019-02-27 11:32:59,464 - DEBUG - 3/10 [40.00%]: Moved 4 units of p0 from m_1 to c_1 for 2.0 dollars 2019-02-27 11:32:59,464 - INFO - 3/10 [40.00%]: Executing c_2-88fd8b76-1040-4e98-b476-5e965b64b2fb, m_0-575672e1-efe8-4964-b340-4a6116793ce6 agreed on {'time': 3, 'quantity': 3, 'unit_price': 0.5} 2019-02-27 11:32:59,464 - DEBUG - 3/10 [40.00%]: Moved 3 units of p0 from m_0 to c_2 for 1.5 dollars 2019-02-27 11:32:59,464 - INFO - 3/10 [40.00%]: Executing c_0-3998ad31-d504-4b35-bb85-3be6197f1ea0, m_4-839c8f96-e52b-40cd-a1ef-3bf468ec11cb agreed on {'time': 3, 'quantity': 3, 'unit_price': 0.5} 2019-02-27 11:32:59,464 - DEBUG - 3/10 [40.00%]: Moved 3 units of p0 from m_4 to c_0 for 1.5 dollars 2019-02-27 11:32:59,464 - INFO - 3/10 [40.00%]: Executing c_4-70a6b468-fb6c-4fd2-b7da-c47f020247d6, m_4-839c8f96-e52b-40cd-a1ef-3bf468ec11cb agreed on {'time': 3, 'quantity': 4, 'unit_price': 0.5} 2019-02-27 11:32:59,464 - DEBUG - 3/10 [40.00%]: Moved 4 units of p0 from m_4 to c_4 for 2.0 dollars 2019-02-27 11:32:59,464 - DEBUG - 3/10 [40.00%]: Factory 2b84599b-e538-4212-b349-d4a05459c15b: money=-3.5, storage={}, loans=0.0 2019-02-27 11:32:59,464 - DEBUG - 3/10 [40.00%]: Factory fed30dd7-5bba-4df3-9386-c2570ef237d4: money=-3.5, storage={}, loans=0.0 2019-02-27 11:32:59,464 - DEBUG - 3/10 [40.00%]: Factory 2b9215ac-5da4-4788-8222-002f92ac7b3c: money=-3.5, storage={}, loans=0.0 2019-02-27 11:32:59,464 - DEBUG - 3/10 [40.00%]: Factory 1f8923b6-aef8-4008-a31c-b18482add390: money=-3.5, storage={}, loans=0.0 2019-02-27 11:32:59,465 - DEBUG - 3/10 [40.00%]: Factory 30f40890-1d90-499c-87f7-ac48be226a56: money=-3.5, storage={}, loans=0.0 2019-02-27 11:32:59,465 - DEBUG - 3/10 [40.00%]: Factory f6c073fa-9343-49a7-b738-ccd0b9381c40: money=5.0, storage={0: -10}, loans=0.0 2019-02-27 11:32:59,465 - DEBUG - 3/10 [40.00%]: Factory 62cc9ee6-9600-42d1-83dd-216923d114b1: money=5.5, storage={0: -11}, loans=0.0 2019-02-27 11:32:59,465 - DEBUG - 3/10 [40.00%]: Factory e11f4f3c-15a1-461a-bd2c-632e07f82b5f: money=0.0, storage={}, loans=0.0 2019-02-27 11:32:59,465 - DEBUG - 3/10 [40.00%]: Factory 3583ffd0-fef8-4a83-be5d-0fa6562d4c9f: money=3.5, storage={0: -7}, loans=0.0 2019-02-27 11:32:59,465 - DEBUG - 3/10 [40.00%]: Factory eb0d4726-61b8-4266-8c97-4416e5746a6f: money=3.5, storage={0: -7}, loans=0.0 2019-02-27 11:32:59,465 - INFO - 4/10 [50.00%]: 25 Negotiations/4 _entities 2019-02-27 11:32:59,716 - DEBUG - 4/10 [50.00%]: Contract [to be signed at 5]: ['c_1', 'm_2'] > {'time': 7, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_1-48b66a5d-80de-4f52-99f0-f2f3af13d7a3: buy 0 (t: 7, u: (0, 2.0), q: (1, 3))', 'partners': "['c_1-48b66a5d-80de-4f52-99f0-f2f3af13d7a3', 'm_2-84165933-f800-4373-8db2-96de0656eead']", 'seller': 'm_2-84165933-f800-4373-8db2-96de0656eead', 'buyer': 'c_1-48b66a5d-80de-4f52-99f0-f2f3af13d7a3'} 2019-02-27 11:32:59,716 - DEBUG - 4/10 [50.00%]: Contract [to be signed at 5]: ['c_3', 'm_4'] > {'time': 7, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_3-ef402340-68d6-404a-8c4f-8ec5bead3987: buy 0 (t: 7, u: (0, 2.0), q: (1, 4))', 'partners': "['c_3-ef402340-68d6-404a-8c4f-8ec5bead3987', 'm_4-839c8f96-e52b-40cd-a1ef-3bf468ec11cb']", 'seller': 'm_4-839c8f96-e52b-40cd-a1ef-3bf468ec11cb', 'buyer': 'c_3-ef402340-68d6-404a-8c4f-8ec5bead3987'} 2019-02-27 11:32:59,717 - DEBUG - 4/10 [50.00%]: Contract [to be signed at 5]: ['c_4', 'm_0'] > {'time': 7, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_4-70a6b468-fb6c-4fd2-b7da-c47f020247d6: buy 0 (t: 7, u: (0, 2.0), q: (1, 4))', 'partners': "['c_4-70a6b468-fb6c-4fd2-b7da-c47f020247d6', 'm_0-575672e1-efe8-4964-b340-4a6116793ce6']", 'seller': 'm_0-575672e1-efe8-4964-b340-4a6116793ce6', 'buyer': 'c_4-70a6b468-fb6c-4fd2-b7da-c47f020247d6'} 2019-02-27 11:32:59,717 - DEBUG - 4/10 [50.00%]: Contract [to be signed at 5]: ['c_0', 'm_2'] > {'time': 7, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_0-3998ad31-d504-4b35-bb85-3be6197f1ea0: buy 0 (t: 7, u: (0, 2.0), q: (1, 3))', 'partners': "['c_0-3998ad31-d504-4b35-bb85-3be6197f1ea0', 'm_2-84165933-f800-4373-8db2-96de0656eead']", 'seller': 'm_2-84165933-f800-4373-8db2-96de0656eead', 'buyer': 'c_0-3998ad31-d504-4b35-bb85-3be6197f1ea0'} 2019-02-27 11:32:59,718 - DEBUG - 4/10 [50.00%]: Contract [to be signed at 5]: ['c_0', 'm_0'] > {'time': 7, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_0-3998ad31-d504-4b35-bb85-3be6197f1ea0: buy 0 (t: 7, u: (0, 2.0), q: (1, 3))', 'partners': "['c_0-3998ad31-d504-4b35-bb85-3be6197f1ea0', 'm_0-575672e1-efe8-4964-b340-4a6116793ce6']", 'seller': 'm_0-575672e1-efe8-4964-b340-4a6116793ce6', 'buyer': 'c_0-3998ad31-d504-4b35-bb85-3be6197f1ea0'} 2019-02-27 11:32:59,718 - DEBUG - 4/10 [50.00%]: Contract [to be signed at 5]: ['c_3', 'm_0'] > {'time': 7, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_3-ef402340-68d6-404a-8c4f-8ec5bead3987: buy 0 (t: 7, u: (0, 2.0), q: (1, 4))', 'partners': "['c_3-ef402340-68d6-404a-8c4f-8ec5bead3987', 'm_0-575672e1-efe8-4964-b340-4a6116793ce6']", 'seller': 'm_0-575672e1-efe8-4964-b340-4a6116793ce6', 'buyer': 'c_3-ef402340-68d6-404a-8c4f-8ec5bead3987'} 2019-02-27 11:32:59,718 - DEBUG - 4/10 [50.00%]: Contract [to be signed at 5]: ['c_2', 'm_3'] > {'time': 7, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_2-88fd8b76-1040-4e98-b476-5e965b64b2fb: buy 0 (t: 7, u: (0, 2.0), q: (1, 4))', 'partners': "['c_2-88fd8b76-1040-4e98-b476-5e965b64b2fb', 'm_3-57429f75-c75c-4cb4-a9b4-ca5c83d682d1']", 'seller': 'm_3-57429f75-c75c-4cb4-a9b4-ca5c83d682d1', 'buyer': 'c_2-88fd8b76-1040-4e98-b476-5e965b64b2fb'} 2019-02-27 11:32:59,719 - DEBUG - 4/10 [50.00%]: Contract [to be signed at 5]: ['c_1', 'm_4'] > {'time': 7, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_1-48b66a5d-80de-4f52-99f0-f2f3af13d7a3: buy 0 (t: 7, u: (0, 2.0), q: (1, 3))', 'partners': "['c_1-48b66a5d-80de-4f52-99f0-f2f3af13d7a3', 'm_4-839c8f96-e52b-40cd-a1ef-3bf468ec11cb']", 'seller': 'm_4-839c8f96-e52b-40cd-a1ef-3bf468ec11cb', 'buyer': 'c_1-48b66a5d-80de-4f52-99f0-f2f3af13d7a3'} 2019-02-27 11:32:59,719 - DEBUG - 4/10 [50.00%]: Contract [to be signed at 5]: ['c_2', 'm_4'] > {'time': 7, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_2-88fd8b76-1040-4e98-b476-5e965b64b2fb: buy 0 (t: 7, u: (0, 2.0), q: (1, 4))', 'partners': "['c_2-88fd8b76-1040-4e98-b476-5e965b64b2fb', 'm_4-839c8f96-e52b-40cd-a1ef-3bf468ec11cb']", 'seller': 'm_4-839c8f96-e52b-40cd-a1ef-3bf468ec11cb', 'buyer': 'c_2-88fd8b76-1040-4e98-b476-5e965b64b2fb'} 2019-02-27 11:32:59,720 - DEBUG - 4/10 [50.00%]: Contract [to be signed at 5]: ['c_4', 'm_1'] > {'time': 7, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_4-70a6b468-fb6c-4fd2-b7da-c47f020247d6: buy 0 (t: 7, u: (0, 2.0), q: (1, 4))', 'partners': "['c_4-70a6b468-fb6c-4fd2-b7da-c47f020247d6', 'm_1-153ac158-9a57-4bca-8296-bae6389d1ce1']", 'seller': 'm_1-153ac158-9a57-4bca-8296-bae6389d1ce1', 'buyer': 'c_4-70a6b468-fb6c-4fd2-b7da-c47f020247d6'} 2019-02-27 11:32:59,720 - DEBUG - 4/10 [50.00%]: Contract [to be signed at 5]: ['c_4', 'm_4'] > {'time': 7, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_4-70a6b468-fb6c-4fd2-b7da-c47f020247d6: buy 0 (t: 7, u: (0, 2.0), q: (1, 4))', 'partners': "['c_4-70a6b468-fb6c-4fd2-b7da-c47f020247d6', 'm_4-839c8f96-e52b-40cd-a1ef-3bf468ec11cb']", 'seller': 'm_4-839c8f96-e52b-40cd-a1ef-3bf468ec11cb', 'buyer': 'c_4-70a6b468-fb6c-4fd2-b7da-c47f020247d6'} 2019-02-27 11:32:59,720 - DEBUG - 4/10 [50.00%]: Contract [to be signed at 5]: ['c_3', 'm_1'] > {'time': 7, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_3-ef402340-68d6-404a-8c4f-8ec5bead3987: buy 0 (t: 7, u: (0, 2.0), q: (1, 4))', 'partners': "['c_3-ef402340-68d6-404a-8c4f-8ec5bead3987', 'm_1-153ac158-9a57-4bca-8296-bae6389d1ce1']", 'seller': 'm_1-153ac158-9a57-4bca-8296-bae6389d1ce1', 'buyer': 'c_3-ef402340-68d6-404a-8c4f-8ec5bead3987'} 2019-02-27 11:32:59,720 - DEBUG - 4/10 [50.00%]: Contract [to be signed at 5]: ['c_4', 'm_3'] > {'time': 7, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_4-70a6b468-fb6c-4fd2-b7da-c47f020247d6: buy 0 (t: 7, u: (0, 2.0), q: (1, 4))', 'partners': "['c_4-70a6b468-fb6c-4fd2-b7da-c47f020247d6', 'm_3-57429f75-c75c-4cb4-a9b4-ca5c83d682d1']", 'seller': 'm_3-57429f75-c75c-4cb4-a9b4-ca5c83d682d1', 'buyer': 'c_4-70a6b468-fb6c-4fd2-b7da-c47f020247d6'} 2019-02-27 11:32:59,721 - DEBUG - 4/10 [50.00%]: Contract [to be signed at 5]: ['c_0', 'm_4'] > {'time': 7, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_0-3998ad31-d504-4b35-bb85-3be6197f1ea0: buy 0 (t: 7, u: (0, 2.0), q: (1, 3))', 'partners': "['c_0-3998ad31-d504-4b35-bb85-3be6197f1ea0', 'm_4-839c8f96-e52b-40cd-a1ef-3bf468ec11cb']", 'seller': 'm_4-839c8f96-e52b-40cd-a1ef-3bf468ec11cb', 'buyer': 'c_0-3998ad31-d504-4b35-bb85-3be6197f1ea0'} 2019-02-27 11:32:59,721 - DEBUG - 4/10 [50.00%]: Contract [to be signed at 5]: ['c_2', 'm_0'] > {'time': 7, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_2-88fd8b76-1040-4e98-b476-5e965b64b2fb: buy 0 (t: 7, u: (0, 2.0), q: (1, 4))', 'partners': "['c_2-88fd8b76-1040-4e98-b476-5e965b64b2fb', 'm_0-575672e1-efe8-4964-b340-4a6116793ce6']", 'seller': 'm_0-575672e1-efe8-4964-b340-4a6116793ce6', 'buyer': 'c_2-88fd8b76-1040-4e98-b476-5e965b64b2fb'} 2019-02-27 11:32:59,722 - DEBUG - 4/10 [50.00%]: Contract [to be signed at 5]: ['c_0', 'm_3'] > {'time': 7, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_0-3998ad31-d504-4b35-bb85-3be6197f1ea0: buy 0 (t: 7, u: (0, 2.0), q: (1, 3))', 'partners': "['c_0-3998ad31-d504-4b35-bb85-3be6197f1ea0', 'm_3-57429f75-c75c-4cb4-a9b4-ca5c83d682d1']", 'seller': 'm_3-57429f75-c75c-4cb4-a9b4-ca5c83d682d1', 'buyer': 'c_0-3998ad31-d504-4b35-bb85-3be6197f1ea0'} 2019-02-27 11:32:59,723 - DEBUG - 4/10 [50.00%]: Contract [to be signed at 5]: ['c_4', 'm_2'] > {'time': 7, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_4-70a6b468-fb6c-4fd2-b7da-c47f020247d6: buy 0 (t: 7, u: (0, 2.0), q: (1, 4))', 'partners': "['c_4-70a6b468-fb6c-4fd2-b7da-c47f020247d6', 'm_2-84165933-f800-4373-8db2-96de0656eead']", 'seller': 'm_2-84165933-f800-4373-8db2-96de0656eead', 'buyer': 'c_4-70a6b468-fb6c-4fd2-b7da-c47f020247d6'} 2019-02-27 11:32:59,724 - DEBUG - 4/10 [50.00%]: Contract [to be signed at 5]: ['c_1', 'm_0'] > {'time': 7, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_1-48b66a5d-80de-4f52-99f0-f2f3af13d7a3: buy 0 (t: 7, u: (0, 2.0), q: (1, 3))', 'partners': "['c_1-48b66a5d-80de-4f52-99f0-f2f3af13d7a3', 'm_0-575672e1-efe8-4964-b340-4a6116793ce6']", 'seller': 'm_0-575672e1-efe8-4964-b340-4a6116793ce6', 'buyer': 'c_1-48b66a5d-80de-4f52-99f0-f2f3af13d7a3'} 2019-02-27 11:32:59,724 - DEBUG - 4/10 [50.00%]: Contract [to be signed at 5]: ['c_3', 'm_3'] > {'time': 7, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_3-ef402340-68d6-404a-8c4f-8ec5bead3987: buy 0 (t: 7, u: (0, 2.0), q: (1, 4))', 'partners': "['c_3-ef402340-68d6-404a-8c4f-8ec5bead3987', 'm_3-57429f75-c75c-4cb4-a9b4-ca5c83d682d1']", 'seller': 'm_3-57429f75-c75c-4cb4-a9b4-ca5c83d682d1', 'buyer': 'c_3-ef402340-68d6-404a-8c4f-8ec5bead3987'} 2019-02-27 11:32:59,725 - DEBUG - 4/10 [50.00%]: Contract [to be signed at 5]: ['c_3', 'm_2'] > {'time': 7, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_3-ef402340-68d6-404a-8c4f-8ec5bead3987: buy 0 (t: 7, u: (0, 2.0), q: (1, 4))', 'partners': "['c_3-ef402340-68d6-404a-8c4f-8ec5bead3987', 'm_2-84165933-f800-4373-8db2-96de0656eead']", 'seller': 'm_2-84165933-f800-4373-8db2-96de0656eead', 'buyer': 'c_3-ef402340-68d6-404a-8c4f-8ec5bead3987'} 2019-02-27 11:32:59,726 - DEBUG - 4/10 [50.00%]: Contract [to be signed at 5]: ['c_0', 'm_1'] > {'time': 7, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_0-3998ad31-d504-4b35-bb85-3be6197f1ea0: buy 0 (t: 7, u: (0, 2.0), q: (1, 3))', 'partners': "['c_0-3998ad31-d504-4b35-bb85-3be6197f1ea0', 'm_1-153ac158-9a57-4bca-8296-bae6389d1ce1']", 'seller': 'm_1-153ac158-9a57-4bca-8296-bae6389d1ce1', 'buyer': 'c_0-3998ad31-d504-4b35-bb85-3be6197f1ea0'} 2019-02-27 11:32:59,727 - DEBUG - 4/10 [50.00%]: Contract [to be signed at 5]: ['c_2', 'm_1'] > {'time': 7, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_2-88fd8b76-1040-4e98-b476-5e965b64b2fb: buy 0 (t: 7, u: (0, 2.0), q: (1, 4))', 'partners': "['c_2-88fd8b76-1040-4e98-b476-5e965b64b2fb', 'm_1-153ac158-9a57-4bca-8296-bae6389d1ce1']", 'seller': 'm_1-153ac158-9a57-4bca-8296-bae6389d1ce1', 'buyer': 'c_2-88fd8b76-1040-4e98-b476-5e965b64b2fb'} 2019-02-27 11:32:59,727 - DEBUG - 4/10 [50.00%]: Contract [to be signed at 5]: ['c_1', 'm_3'] > {'time': 7, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_1-48b66a5d-80de-4f52-99f0-f2f3af13d7a3: buy 0 (t: 7, u: (0, 2.0), q: (1, 3))', 'partners': "['c_1-48b66a5d-80de-4f52-99f0-f2f3af13d7a3', 'm_3-57429f75-c75c-4cb4-a9b4-ca5c83d682d1']", 'seller': 'm_3-57429f75-c75c-4cb4-a9b4-ca5c83d682d1', 'buyer': 'c_1-48b66a5d-80de-4f52-99f0-f2f3af13d7a3'} 2019-02-27 11:32:59,728 - DEBUG - 4/10 [50.00%]: Contract [to be signed at 5]: ['c_1', 'm_1'] > {'time': 7, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_1-48b66a5d-80de-4f52-99f0-f2f3af13d7a3: buy 0 (t: 7, u: (0, 2.0), q: (1, 3))', 'partners': "['c_1-48b66a5d-80de-4f52-99f0-f2f3af13d7a3', 'm_1-153ac158-9a57-4bca-8296-bae6389d1ce1']", 'seller': 'm_1-153ac158-9a57-4bca-8296-bae6389d1ce1', 'buyer': 'c_1-48b66a5d-80de-4f52-99f0-f2f3af13d7a3'} 2019-02-27 11:32:59,729 - DEBUG - 4/10 [50.00%]: Contract [to be signed at 5]: ['c_2', 'm_2'] > {'time': 7, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_2-88fd8b76-1040-4e98-b476-5e965b64b2fb: buy 0 (t: 7, u: (0, 2.0), q: (1, 4))', 'partners': "['c_2-88fd8b76-1040-4e98-b476-5e965b64b2fb', 'm_2-84165933-f800-4373-8db2-96de0656eead']", 'seller': 'm_2-84165933-f800-4373-8db2-96de0656eead', 'buyer': 'c_2-88fd8b76-1040-4e98-b476-5e965b64b2fb'} 2019-02-27 11:32:59,731 - INFO - 4/10 [50.00%]: m_0 requested negmas.sao.SAOMechanism[None] with ['c_3', 'm_0'] (ID 88639276-b102-410a-bfa7-508eb5572405) 2019-02-27 11:32:59,733 - INFO - 4/10 [50.00%]: m_0-575672e1-efe8-4964-b340-4a6116793ce6 request was accepted 2019-02-27 11:32:59,735 - INFO - 4/10 [50.00%]: m_1 requested negmas.sao.SAOMechanism[None] with ['c_3', 'm_1'] (ID 76fea4e9-d3fb-4f27-a202-6ccb1a175063) 2019-02-27 11:32:59,736 - INFO - 4/10 [50.00%]: m_1-153ac158-9a57-4bca-8296-bae6389d1ce1 request was accepted 2019-02-27 11:32:59,737 - INFO - 4/10 [50.00%]: m_2 requested negmas.sao.SAOMechanism[None] with ['c_3', 'm_2'] (ID 80f714de-77a3-419a-8fc3-6d368a8ee58d) 2019-02-27 11:32:59,738 - INFO - 4/10 [50.00%]: m_2-84165933-f800-4373-8db2-96de0656eead request was accepted 2019-02-27 11:32:59,739 - INFO - 4/10 [50.00%]: m_3 requested negmas.sao.SAOMechanism[None] with ['c_3', 'm_3'] (ID f2bb7047-456f-4637-b3d0-f36fd55a8160) 2019-02-27 11:32:59,741 - INFO - 4/10 [50.00%]: m_3-57429f75-c75c-4cb4-a9b4-ca5c83d682d1 request was accepted 2019-02-27 11:32:59,742 - INFO - 4/10 [50.00%]: m_4 requested negmas.sao.SAOMechanism[None] with ['c_3', 'm_4'] (ID be35fc7f-921e-49d0-95ae-6d5457931e4c) 2019-02-27 11:32:59,743 - INFO - 4/10 [50.00%]: m_4-839c8f96-e52b-40cd-a1ef-3bf468ec11cb request was accepted 2019-02-27 11:32:59,746 - INFO - 4/10 [50.00%]: m_0 requested negmas.sao.SAOMechanism[None] with ['c_4', 'm_0'] (ID 4553d572-d901-475a-9d8b-980b5661fec4) 2019-02-27 11:32:59,747 - INFO - 4/10 [50.00%]: m_0-575672e1-efe8-4964-b340-4a6116793ce6 request was accepted 2019-02-27 11:32:59,748 - INFO - 4/10 [50.00%]: m_1 requested negmas.sao.SAOMechanism[None] with ['c_4', 'm_1'] (ID c35ee52a-2fb3-4261-bf48-b07f5cf90c66) 2019-02-27 11:32:59,750 - INFO - 4/10 [50.00%]: m_1-153ac158-9a57-4bca-8296-bae6389d1ce1 request was accepted 2019-02-27 11:32:59,751 - INFO - 4/10 [50.00%]: m_2 requested negmas.sao.SAOMechanism[None] with ['c_4', 'm_2'] (ID 7d34f101-1992-404d-accc-7e0ffe31d897) 2019-02-27 11:32:59,752 - INFO - 4/10 [50.00%]: m_2-84165933-f800-4373-8db2-96de0656eead request was accepted 2019-02-27 11:32:59,754 - INFO - 4/10 [50.00%]: m_3 requested negmas.sao.SAOMechanism[None] with ['c_4', 'm_3'] (ID 92e9dafa-5cc4-4298-9085-f5363f6308a9) 2019-02-27 11:32:59,755 - INFO - 4/10 [50.00%]: m_3-57429f75-c75c-4cb4-a9b4-ca5c83d682d1 request was accepted 2019-02-27 11:32:59,758 - INFO - 4/10 [50.00%]: m_4 requested negmas.sao.SAOMechanism[None] with ['c_4', 'm_4'] (ID 45b39be4-5ea6-4717-bc8b-4c5b57420e7d) 2019-02-27 11:32:59,759 - INFO - 4/10 [50.00%]: m_4-839c8f96-e52b-40cd-a1ef-3bf468ec11cb request was accepted 2019-02-27 11:32:59,763 - INFO - 4/10 [50.00%]: m_0 requested negmas.sao.SAOMechanism[None] with ['c_1', 'm_0'] (ID 4e0dbc22-676d-427f-adcd-ec545d23bb0f) 2019-02-27 11:32:59,763 - INFO - 4/10 [50.00%]: m_0-575672e1-efe8-4964-b340-4a6116793ce6 request was accepted 2019-02-27 11:32:59,764 - INFO - 4/10 [50.00%]: m_1 requested negmas.sao.SAOMechanism[None] with ['c_1', 'm_1'] (ID 82ee143b-c897-4d71-a948-6d91296e7303) 2019-02-27 11:32:59,765 - INFO - 4/10 [50.00%]: m_1-153ac158-9a57-4bca-8296-bae6389d1ce1 request was accepted 2019-02-27 11:32:59,767 - INFO - 4/10 [50.00%]: m_2 requested negmas.sao.SAOMechanism[None] with ['c_1', 'm_2'] (ID 5640e889-747b-4f24-8a2a-8a682a80a836) 2019-02-27 11:32:59,767 - INFO - 4/10 [50.00%]: m_2-84165933-f800-4373-8db2-96de0656eead request was accepted 2019-02-27 11:32:59,769 - INFO - 4/10 [50.00%]: m_3 requested negmas.sao.SAOMechanism[None] with ['c_1', 'm_3'] (ID 5bb495ad-a305-4eab-b1c1-348f3848cf50) 2019-02-27 11:32:59,770 - INFO - 4/10 [50.00%]: m_3-57429f75-c75c-4cb4-a9b4-ca5c83d682d1 request was accepted 2019-02-27 11:32:59,771 - INFO - 4/10 [50.00%]: m_4 requested negmas.sao.SAOMechanism[None] with ['c_1', 'm_4'] (ID 8f4ca751-87c7-4e35-9971-7e17a6c64477) 2019-02-27 11:32:59,772 - INFO - 4/10 [50.00%]: m_4-839c8f96-e52b-40cd-a1ef-3bf468ec11cb request was accepted 2019-02-27 11:32:59,773 - INFO - 4/10 [50.00%]: m_0 requested negmas.sao.SAOMechanism[None] with ['c_0', 'm_0'] (ID 0d340d3a-5e0e-47f5-ac8c-212f0ddd3dcd) 2019-02-27 11:32:59,774 - INFO - 4/10 [50.00%]: m_0-575672e1-efe8-4964-b340-4a6116793ce6 request was accepted 2019-02-27 11:32:59,775 - INFO - 4/10 [50.00%]: m_1 requested negmas.sao.SAOMechanism[None] with ['c_0', 'm_1'] (ID 92ffbe30-83cc-4d6b-a63d-959ebe85ff28) 2019-02-27 11:32:59,776 - INFO - 4/10 [50.00%]: m_1-153ac158-9a57-4bca-8296-bae6389d1ce1 request was accepted 2019-02-27 11:32:59,777 - INFO - 4/10 [50.00%]: m_2 requested negmas.sao.SAOMechanism[None] with ['c_0', 'm_2'] (ID 47ab0531-bda5-443a-b1ad-c793113d483b) 2019-02-27 11:32:59,778 - INFO - 4/10 [50.00%]: m_2-84165933-f800-4373-8db2-96de0656eead request was accepted 2019-02-27 11:32:59,779 - INFO - 4/10 [50.00%]: m_3 requested negmas.sao.SAOMechanism[None] with ['c_0', 'm_3'] (ID 8e28a3bf-04c4-458d-8e97-31902e136c27) 2019-02-27 11:32:59,779 - INFO - 4/10 [50.00%]: m_3-57429f75-c75c-4cb4-a9b4-ca5c83d682d1 request was accepted 2019-02-27 11:32:59,780 - INFO - 4/10 [50.00%]: m_4 requested negmas.sao.SAOMechanism[None] with ['c_0', 'm_4'] (ID e5cc99d4-ed87-4582-b315-3bc107c1730c) 2019-02-27 11:32:59,781 - INFO - 4/10 [50.00%]: m_4-839c8f96-e52b-40cd-a1ef-3bf468ec11cb request was accepted 2019-02-27 11:32:59,783 - INFO - 4/10 [50.00%]: m_0 requested negmas.sao.SAOMechanism[None] with ['c_2', 'm_0'] (ID 564e359f-6f75-4904-86f8-e390bd4b636c) 2019-02-27 11:32:59,784 - INFO - 4/10 [50.00%]: m_0-575672e1-efe8-4964-b340-4a6116793ce6 request was accepted 2019-02-27 11:32:59,785 - INFO - 4/10 [50.00%]: m_1 requested negmas.sao.SAOMechanism[None] with ['c_2', 'm_1'] (ID 3d9c879e-bccf-4642-b384-e5b10536f861) 2019-02-27 11:32:59,786 - INFO - 4/10 [50.00%]: m_1-153ac158-9a57-4bca-8296-bae6389d1ce1 request was accepted 2019-02-27 11:32:59,788 - INFO - 4/10 [50.00%]: m_2 requested negmas.sao.SAOMechanism[None] with ['c_2', 'm_2'] (ID 97352283-9fcd-40cf-9537-a0b0ce8a013a) 2019-02-27 11:32:59,789 - INFO - 4/10 [50.00%]: m_2-84165933-f800-4373-8db2-96de0656eead request was accepted 2019-02-27 11:32:59,792 - INFO - 4/10 [50.00%]: m_3 requested negmas.sao.SAOMechanism[None] with ['c_2', 'm_3'] (ID 84436d98-6b03-4e85-9d48-805266c0e3ae) 2019-02-27 11:32:59,793 - INFO - 4/10 [50.00%]: m_3-57429f75-c75c-4cb4-a9b4-ca5c83d682d1 request was accepted 2019-02-27 11:32:59,795 - INFO - 4/10 [50.00%]: m_4 requested negmas.sao.SAOMechanism[None] with ['c_2', 'm_4'] (ID 2e2ca089-5e81-405a-9453-22e20cbd573e) 2019-02-27 11:32:59,796 - INFO - 4/10 [50.00%]: m_4-839c8f96-e52b-40cd-a1ef-3bf468ec11cb request was accepted 2019-02-27 11:32:59,796 - INFO - 4/10 [50.00%]: Executing c_4-70a6b468-fb6c-4fd2-b7da-c47f020247d6, m_3-57429f75-c75c-4cb4-a9b4-ca5c83d682d1 agreed on {'time': 4, 'quantity': 4, 'unit_price': 0.5} 2019-02-27 11:32:59,796 - DEBUG - 4/10 [50.00%]: Moved 4 units of p0 from m_3 to c_4 for 2.0 dollars 2019-02-27 11:32:59,796 - INFO - 4/10 [50.00%]: Executing c_2-88fd8b76-1040-4e98-b476-5e965b64b2fb, m_2-84165933-f800-4373-8db2-96de0656eead agreed on {'time': 4, 'quantity': 4, 'unit_price': 0.5} 2019-02-27 11:32:59,797 - DEBUG - 4/10 [50.00%]: Moved 4 units of p0 from m_2 to c_2 for 2.0 dollars 2019-02-27 11:32:59,797 - INFO - 4/10 [50.00%]: Executing c_1-48b66a5d-80de-4f52-99f0-f2f3af13d7a3, m_4-839c8f96-e52b-40cd-a1ef-3bf468ec11cb agreed on {'time': 4, 'quantity': 3, 'unit_price': 0.5} 2019-02-27 11:32:59,797 - DEBUG - 4/10 [50.00%]: Moved 3 units of p0 from m_4 to c_1 for 1.5 dollars 2019-02-27 11:32:59,797 - INFO - 4/10 [50.00%]: Executing c_0-3998ad31-d504-4b35-bb85-3be6197f1ea0, m_3-57429f75-c75c-4cb4-a9b4-ca5c83d682d1 agreed on {'time': 4, 'quantity': 4, 'unit_price': 0.5} 2019-02-27 11:32:59,797 - DEBUG - 4/10 [50.00%]: Moved 4 units of p0 from m_3 to c_0 for 2.0 dollars 2019-02-27 11:32:59,797 - INFO - 4/10 [50.00%]: Executing c_3-ef402340-68d6-404a-8c4f-8ec5bead3987, m_4-839c8f96-e52b-40cd-a1ef-3bf468ec11cb agreed on {'time': 4, 'quantity': 3, 'unit_price': 0.5} 2019-02-27 11:32:59,797 - DEBUG - 4/10 [50.00%]: Moved 3 units of p0 from m_4 to c_3 for 1.5 dollars 2019-02-27 11:32:59,797 - DEBUG - 4/10 [50.00%]: Factory 2b84599b-e538-4212-b349-d4a05459c15b: money=-5.5, storage={0: 4}, loans=0.0 2019-02-27 11:32:59,797 - DEBUG - 4/10 [50.00%]: Factory fed30dd7-5bba-4df3-9386-c2570ef237d4: money=-5.0, storage={0: 3}, loans=0.0 2019-02-27 11:32:59,797 - DEBUG - 4/10 [50.00%]: Factory 2b9215ac-5da4-4788-8222-002f92ac7b3c: money=-5.5, storage={0: 4}, loans=0.0 2019-02-27 11:32:59,797 - DEBUG - 4/10 [50.00%]: Factory 1f8923b6-aef8-4008-a31c-b18482add390: money=-5.0, storage={0: 4}, loans=0.0 2019-02-27 11:32:59,797 - DEBUG - 4/10 [50.00%]: Factory 30f40890-1d90-499c-87f7-ac48be226a56: money=-5.5, storage={0: 3}, loans=0.0 2019-02-27 11:32:59,797 - DEBUG - 4/10 [50.00%]: Factory f6c073fa-9343-49a7-b738-ccd0b9381c40: money=5.0, storage={0: -10}, loans=0.0 2019-02-27 11:32:59,797 - DEBUG - 4/10 [50.00%]: Factory 62cc9ee6-9600-42d1-83dd-216923d114b1: money=5.5, storage={0: -11}, loans=0.0 2019-02-27 11:32:59,798 - DEBUG - 4/10 [50.00%]: Factory e11f4f3c-15a1-461a-bd2c-632e07f82b5f: money=2.0, storage={0: -4}, loans=0.0 2019-02-27 11:32:59,798 - DEBUG - 4/10 [50.00%]: Factory 3583ffd0-fef8-4a83-be5d-0fa6562d4c9f: money=7.5, storage={0: -15}, loans=0.0 2019-02-27 11:32:59,798 - DEBUG - 4/10 [50.00%]: Factory eb0d4726-61b8-4266-8c97-4416e5746a6f: money=6.5, storage={0: -13}, loans=0.0 2019-02-27 11:32:59,798 - INFO - 5/10 [60.00%]: 25 Negotiations/4 _entities 2019-02-27 11:33:00,070 - DEBUG - 5/10 [60.00%]: Contract [to be signed at 6]: ['c_3', 'm_4'] > {'time': 8, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_3-ef402340-68d6-404a-8c4f-8ec5bead3987: buy 0 (t: 8, u: (0, 2.0), q: (1, 3))', 'partners': "['c_3-ef402340-68d6-404a-8c4f-8ec5bead3987', 'm_4-839c8f96-e52b-40cd-a1ef-3bf468ec11cb']", 'seller': 'm_4-839c8f96-e52b-40cd-a1ef-3bf468ec11cb', 'buyer': 'c_3-ef402340-68d6-404a-8c4f-8ec5bead3987'} 2019-02-27 11:33:00,071 - DEBUG - 5/10 [60.00%]: Contract [to be signed at 6]: ['c_3', 'm_3'] > {'time': 8, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_3-ef402340-68d6-404a-8c4f-8ec5bead3987: buy 0 (t: 8, u: (0, 2.0), q: (1, 3))', 'partners': "['c_3-ef402340-68d6-404a-8c4f-8ec5bead3987', 'm_3-57429f75-c75c-4cb4-a9b4-ca5c83d682d1']", 'seller': 'm_3-57429f75-c75c-4cb4-a9b4-ca5c83d682d1', 'buyer': 'c_3-ef402340-68d6-404a-8c4f-8ec5bead3987'} 2019-02-27 11:33:00,071 - DEBUG - 5/10 [60.00%]: Contract [to be signed at 6]: ['c_2', 'm_4'] > {'time': 8, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_2-88fd8b76-1040-4e98-b476-5e965b64b2fb: buy 0 (t: 8, u: (0, 2.0), q: (1, 4))', 'partners': "['c_2-88fd8b76-1040-4e98-b476-5e965b64b2fb', 'm_4-839c8f96-e52b-40cd-a1ef-3bf468ec11cb']", 'seller': 'm_4-839c8f96-e52b-40cd-a1ef-3bf468ec11cb', 'buyer': 'c_2-88fd8b76-1040-4e98-b476-5e965b64b2fb'} 2019-02-27 11:33:00,072 - DEBUG - 5/10 [60.00%]: Contract [to be signed at 6]: ['c_4', 'm_0'] > {'time': 8, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_4-70a6b468-fb6c-4fd2-b7da-c47f020247d6: buy 0 (t: 8, u: (0, 2.0), q: (1, 3))', 'partners': "['c_4-70a6b468-fb6c-4fd2-b7da-c47f020247d6', 'm_0-575672e1-efe8-4964-b340-4a6116793ce6']", 'seller': 'm_0-575672e1-efe8-4964-b340-4a6116793ce6', 'buyer': 'c_4-70a6b468-fb6c-4fd2-b7da-c47f020247d6'} 2019-02-27 11:33:00,072 - DEBUG - 5/10 [60.00%]: Contract [to be signed at 6]: ['c_0', 'm_2'] > {'time': 8, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_0-3998ad31-d504-4b35-bb85-3be6197f1ea0: buy 0 (t: 8, u: (0, 2.0), q: (1, 4))', 'partners': "['c_0-3998ad31-d504-4b35-bb85-3be6197f1ea0', 'm_2-84165933-f800-4373-8db2-96de0656eead']", 'seller': 'm_2-84165933-f800-4373-8db2-96de0656eead', 'buyer': 'c_0-3998ad31-d504-4b35-bb85-3be6197f1ea0'} 2019-02-27 11:33:00,072 - DEBUG - 5/10 [60.00%]: Contract [to be signed at 6]: ['c_0', 'm_4'] > {'time': 8, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_0-3998ad31-d504-4b35-bb85-3be6197f1ea0: buy 0 (t: 8, u: (0, 2.0), q: (1, 4))', 'partners': "['c_0-3998ad31-d504-4b35-bb85-3be6197f1ea0', 'm_4-839c8f96-e52b-40cd-a1ef-3bf468ec11cb']", 'seller': 'm_4-839c8f96-e52b-40cd-a1ef-3bf468ec11cb', 'buyer': 'c_0-3998ad31-d504-4b35-bb85-3be6197f1ea0'} 2019-02-27 11:33:00,073 - DEBUG - 5/10 [60.00%]: Contract [to be signed at 6]: ['c_4', 'm_4'] > {'time': 8, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_4-70a6b468-fb6c-4fd2-b7da-c47f020247d6: buy 0 (t: 8, u: (0, 2.0), q: (1, 3))', 'partners': "['c_4-70a6b468-fb6c-4fd2-b7da-c47f020247d6', 'm_4-839c8f96-e52b-40cd-a1ef-3bf468ec11cb']", 'seller': 'm_4-839c8f96-e52b-40cd-a1ef-3bf468ec11cb', 'buyer': 'c_4-70a6b468-fb6c-4fd2-b7da-c47f020247d6'} 2019-02-27 11:33:00,073 - DEBUG - 5/10 [60.00%]: Contract [to be signed at 6]: ['c_4', 'm_2'] > {'time': 8, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_4-70a6b468-fb6c-4fd2-b7da-c47f020247d6: buy 0 (t: 8, u: (0, 2.0), q: (1, 3))', 'partners': "['c_4-70a6b468-fb6c-4fd2-b7da-c47f020247d6', 'm_2-84165933-f800-4373-8db2-96de0656eead']", 'seller': 'm_2-84165933-f800-4373-8db2-96de0656eead', 'buyer': 'c_4-70a6b468-fb6c-4fd2-b7da-c47f020247d6'} 2019-02-27 11:33:00,073 - DEBUG - 5/10 [60.00%]: Contract [to be signed at 6]: ['c_3', 'm_0'] > {'time': 8, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_3-ef402340-68d6-404a-8c4f-8ec5bead3987: buy 0 (t: 8, u: (0, 2.0), q: (1, 3))', 'partners': "['c_3-ef402340-68d6-404a-8c4f-8ec5bead3987', 'm_0-575672e1-efe8-4964-b340-4a6116793ce6']", 'seller': 'm_0-575672e1-efe8-4964-b340-4a6116793ce6', 'buyer': 'c_3-ef402340-68d6-404a-8c4f-8ec5bead3987'} 2019-02-27 11:33:00,073 - DEBUG - 5/10 [60.00%]: Contract [to be signed at 6]: ['c_0', 'm_1'] > {'time': 8, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_0-3998ad31-d504-4b35-bb85-3be6197f1ea0: buy 0 (t: 8, u: (0, 2.0), q: (1, 4))', 'partners': "['c_0-3998ad31-d504-4b35-bb85-3be6197f1ea0', 'm_1-153ac158-9a57-4bca-8296-bae6389d1ce1']", 'seller': 'm_1-153ac158-9a57-4bca-8296-bae6389d1ce1', 'buyer': 'c_0-3998ad31-d504-4b35-bb85-3be6197f1ea0'} 2019-02-27 11:33:00,074 - DEBUG - 5/10 [60.00%]: Contract [to be signed at 6]: ['c_2', 'm_1'] > {'time': 8, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_2-88fd8b76-1040-4e98-b476-5e965b64b2fb: buy 0 (t: 8, u: (0, 2.0), q: (1, 4))', 'partners': "['c_2-88fd8b76-1040-4e98-b476-5e965b64b2fb', 'm_1-153ac158-9a57-4bca-8296-bae6389d1ce1']", 'seller': 'm_1-153ac158-9a57-4bca-8296-bae6389d1ce1', 'buyer': 'c_2-88fd8b76-1040-4e98-b476-5e965b64b2fb'} 2019-02-27 11:33:00,074 - DEBUG - 5/10 [60.00%]: Contract [to be signed at 6]: ['c_1', 'm_4'] > {'time': 8, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_1-48b66a5d-80de-4f52-99f0-f2f3af13d7a3: buy 0 (t: 8, u: (0, 2.0), q: (1, 3))', 'partners': "['c_1-48b66a5d-80de-4f52-99f0-f2f3af13d7a3', 'm_4-839c8f96-e52b-40cd-a1ef-3bf468ec11cb']", 'seller': 'm_4-839c8f96-e52b-40cd-a1ef-3bf468ec11cb', 'buyer': 'c_1-48b66a5d-80de-4f52-99f0-f2f3af13d7a3'} 2019-02-27 11:33:00,074 - DEBUG - 5/10 [60.00%]: Contract [to be signed at 6]: ['c_1', 'm_1'] > {'time': 8, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_1-48b66a5d-80de-4f52-99f0-f2f3af13d7a3: buy 0 (t: 8, u: (0, 2.0), q: (1, 3))', 'partners': "['c_1-48b66a5d-80de-4f52-99f0-f2f3af13d7a3', 'm_1-153ac158-9a57-4bca-8296-bae6389d1ce1']", 'seller': 'm_1-153ac158-9a57-4bca-8296-bae6389d1ce1', 'buyer': 'c_1-48b66a5d-80de-4f52-99f0-f2f3af13d7a3'} 2019-02-27 11:33:00,075 - DEBUG - 5/10 [60.00%]: Contract [to be signed at 6]: ['c_4', 'm_1'] > {'time': 8, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_4-70a6b468-fb6c-4fd2-b7da-c47f020247d6: buy 0 (t: 8, u: (0, 2.0), q: (1, 3))', 'partners': "['c_4-70a6b468-fb6c-4fd2-b7da-c47f020247d6', 'm_1-153ac158-9a57-4bca-8296-bae6389d1ce1']", 'seller': 'm_1-153ac158-9a57-4bca-8296-bae6389d1ce1', 'buyer': 'c_4-70a6b468-fb6c-4fd2-b7da-c47f020247d6'} 2019-02-27 11:33:00,075 - DEBUG - 5/10 [60.00%]: Contract [to be signed at 6]: ['c_2', 'm_2'] > {'time': 8, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_2-88fd8b76-1040-4e98-b476-5e965b64b2fb: buy 0 (t: 8, u: (0, 2.0), q: (1, 4))', 'partners': "['c_2-88fd8b76-1040-4e98-b476-5e965b64b2fb', 'm_2-84165933-f800-4373-8db2-96de0656eead']", 'seller': 'm_2-84165933-f800-4373-8db2-96de0656eead', 'buyer': 'c_2-88fd8b76-1040-4e98-b476-5e965b64b2fb'} 2019-02-27 11:33:00,075 - DEBUG - 5/10 [60.00%]: Contract [to be signed at 6]: ['c_4', 'm_3'] > {'time': 8, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_4-70a6b468-fb6c-4fd2-b7da-c47f020247d6: buy 0 (t: 8, u: (0, 2.0), q: (1, 3))', 'partners': "['c_4-70a6b468-fb6c-4fd2-b7da-c47f020247d6', 'm_3-57429f75-c75c-4cb4-a9b4-ca5c83d682d1']", 'seller': 'm_3-57429f75-c75c-4cb4-a9b4-ca5c83d682d1', 'buyer': 'c_4-70a6b468-fb6c-4fd2-b7da-c47f020247d6'} 2019-02-27 11:33:00,076 - DEBUG - 5/10 [60.00%]: Contract [to be signed at 6]: ['c_1', 'm_2'] > {'time': 8, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_1-48b66a5d-80de-4f52-99f0-f2f3af13d7a3: buy 0 (t: 8, u: (0, 2.0), q: (1, 3))', 'partners': "['c_1-48b66a5d-80de-4f52-99f0-f2f3af13d7a3', 'm_2-84165933-f800-4373-8db2-96de0656eead']", 'seller': 'm_2-84165933-f800-4373-8db2-96de0656eead', 'buyer': 'c_1-48b66a5d-80de-4f52-99f0-f2f3af13d7a3'} 2019-02-27 11:33:00,076 - DEBUG - 5/10 [60.00%]: Contract [to be signed at 6]: ['c_0', 'm_3'] > {'time': 8, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_0-3998ad31-d504-4b35-bb85-3be6197f1ea0: buy 0 (t: 8, u: (0, 2.0), q: (1, 4))', 'partners': "['c_0-3998ad31-d504-4b35-bb85-3be6197f1ea0', 'm_3-57429f75-c75c-4cb4-a9b4-ca5c83d682d1']", 'seller': 'm_3-57429f75-c75c-4cb4-a9b4-ca5c83d682d1', 'buyer': 'c_0-3998ad31-d504-4b35-bb85-3be6197f1ea0'} 2019-02-27 11:33:00,076 - DEBUG - 5/10 [60.00%]: Contract [to be signed at 6]: ['c_1', 'm_3'] > {'time': 8, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_1-48b66a5d-80de-4f52-99f0-f2f3af13d7a3: buy 0 (t: 8, u: (0, 2.0), q: (1, 3))', 'partners': "['c_1-48b66a5d-80de-4f52-99f0-f2f3af13d7a3', 'm_3-57429f75-c75c-4cb4-a9b4-ca5c83d682d1']", 'seller': 'm_3-57429f75-c75c-4cb4-a9b4-ca5c83d682d1', 'buyer': 'c_1-48b66a5d-80de-4f52-99f0-f2f3af13d7a3'} 2019-02-27 11:33:00,077 - DEBUG - 5/10 [60.00%]: Contract [to be signed at 6]: ['c_1', 'm_0'] > {'time': 8, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_1-48b66a5d-80de-4f52-99f0-f2f3af13d7a3: buy 0 (t: 8, u: (0, 2.0), q: (1, 3))', 'partners': "['c_1-48b66a5d-80de-4f52-99f0-f2f3af13d7a3', 'm_0-575672e1-efe8-4964-b340-4a6116793ce6']", 'seller': 'm_0-575672e1-efe8-4964-b340-4a6116793ce6', 'buyer': 'c_1-48b66a5d-80de-4f52-99f0-f2f3af13d7a3'} 2019-02-27 11:33:00,077 - DEBUG - 5/10 [60.00%]: Contract [to be signed at 6]: ['c_3', 'm_1'] > {'time': 8, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_3-ef402340-68d6-404a-8c4f-8ec5bead3987: buy 0 (t: 8, u: (0, 2.0), q: (1, 3))', 'partners': "['c_3-ef402340-68d6-404a-8c4f-8ec5bead3987', 'm_1-153ac158-9a57-4bca-8296-bae6389d1ce1']", 'seller': 'm_1-153ac158-9a57-4bca-8296-bae6389d1ce1', 'buyer': 'c_3-ef402340-68d6-404a-8c4f-8ec5bead3987'} 2019-02-27 11:33:00,077 - DEBUG - 5/10 [60.00%]: Contract [to be signed at 6]: ['c_0', 'm_0'] > {'time': 8, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_0-3998ad31-d504-4b35-bb85-3be6197f1ea0: buy 0 (t: 8, u: (0, 2.0), q: (1, 4))', 'partners': "['c_0-3998ad31-d504-4b35-bb85-3be6197f1ea0', 'm_0-575672e1-efe8-4964-b340-4a6116793ce6']", 'seller': 'm_0-575672e1-efe8-4964-b340-4a6116793ce6', 'buyer': 'c_0-3998ad31-d504-4b35-bb85-3be6197f1ea0'} 2019-02-27 11:33:00,077 - DEBUG - 5/10 [60.00%]: Contract [to be signed at 6]: ['c_3', 'm_2'] > {'time': 8, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_3-ef402340-68d6-404a-8c4f-8ec5bead3987: buy 0 (t: 8, u: (0, 2.0), q: (1, 3))', 'partners': "['c_3-ef402340-68d6-404a-8c4f-8ec5bead3987', 'm_2-84165933-f800-4373-8db2-96de0656eead']", 'seller': 'm_2-84165933-f800-4373-8db2-96de0656eead', 'buyer': 'c_3-ef402340-68d6-404a-8c4f-8ec5bead3987'} 2019-02-27 11:33:00,078 - DEBUG - 5/10 [60.00%]: Contract [to be signed at 6]: ['c_2', 'm_0'] > {'time': 8, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_2-88fd8b76-1040-4e98-b476-5e965b64b2fb: buy 0 (t: 8, u: (0, 2.0), q: (1, 4))', 'partners': "['c_2-88fd8b76-1040-4e98-b476-5e965b64b2fb', 'm_0-575672e1-efe8-4964-b340-4a6116793ce6']", 'seller': 'm_0-575672e1-efe8-4964-b340-4a6116793ce6', 'buyer': 'c_2-88fd8b76-1040-4e98-b476-5e965b64b2fb'} 2019-02-27 11:33:00,078 - DEBUG - 5/10 [60.00%]: Contract [to be signed at 6]: ['c_2', 'm_3'] > {'time': 8, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_2-88fd8b76-1040-4e98-b476-5e965b64b2fb: buy 0 (t: 8, u: (0, 2.0), q: (1, 4))', 'partners': "['c_2-88fd8b76-1040-4e98-b476-5e965b64b2fb', 'm_3-57429f75-c75c-4cb4-a9b4-ca5c83d682d1']", 'seller': 'm_3-57429f75-c75c-4cb4-a9b4-ca5c83d682d1', 'buyer': 'c_2-88fd8b76-1040-4e98-b476-5e965b64b2fb'} 2019-02-27 11:33:00,080 - INFO - 5/10 [60.00%]: m_0 requested negmas.sao.SAOMechanism[None] with ['c_3', 'm_0'] (ID b75907f9-87b2-4a01-8b38-06131d0a60d0) 2019-02-27 11:33:00,080 - INFO - 5/10 [60.00%]: m_0-575672e1-efe8-4964-b340-4a6116793ce6 request was accepted 2019-02-27 11:33:00,081 - INFO - 5/10 [60.00%]: m_1 requested negmas.sao.SAOMechanism[None] with ['c_3', 'm_1'] (ID bb279fb4-d943-4704-ad33-e266dfcf1c54) 2019-02-27 11:33:00,082 - INFO - 5/10 [60.00%]: m_1-153ac158-9a57-4bca-8296-bae6389d1ce1 request was accepted 2019-02-27 11:33:00,083 - INFO - 5/10 [60.00%]: m_2 requested negmas.sao.SAOMechanism[None] with ['c_3', 'm_2'] (ID 4f3acc74-5c10-41c7-945e-09027b8244ce) 2019-02-27 11:33:00,084 - INFO - 5/10 [60.00%]: m_2-84165933-f800-4373-8db2-96de0656eead request was accepted 2019-02-27 11:33:00,085 - INFO - 5/10 [60.00%]: m_3 requested negmas.sao.SAOMechanism[None] with ['c_3', 'm_3'] (ID fbf829f6-f44e-491b-b93a-5c1fdf9c096d) 2019-02-27 11:33:00,085 - INFO - 5/10 [60.00%]: m_3-57429f75-c75c-4cb4-a9b4-ca5c83d682d1 request was accepted 2019-02-27 11:33:00,087 - INFO - 5/10 [60.00%]: m_4 requested negmas.sao.SAOMechanism[None] with ['c_3', 'm_4'] (ID 2f9d256f-f6d9-4cbf-bd4c-5aeb62471fe9) 2019-02-27 11:33:00,087 - INFO - 5/10 [60.00%]: m_4-839c8f96-e52b-40cd-a1ef-3bf468ec11cb request was accepted 2019-02-27 11:33:00,089 - INFO - 5/10 [60.00%]: m_0 requested negmas.sao.SAOMechanism[None] with ['c_4', 'm_0'] (ID 9524a992-1f0f-4f0d-8fd0-380834fa8553) 2019-02-27 11:33:00,089 - INFO - 5/10 [60.00%]: m_0-575672e1-efe8-4964-b340-4a6116793ce6 request was accepted 2019-02-27 11:33:00,090 - INFO - 5/10 [60.00%]: m_1 requested negmas.sao.SAOMechanism[None] with ['c_4', 'm_1'] (ID 1ccc631d-f170-4b44-bc29-56134ba6580c) 2019-02-27 11:33:00,091 - INFO - 5/10 [60.00%]: m_1-153ac158-9a57-4bca-8296-bae6389d1ce1 request was accepted 2019-02-27 11:33:00,092 - INFO - 5/10 [60.00%]: m_2 requested negmas.sao.SAOMechanism[None] with ['c_4', 'm_2'] (ID 3d06e2e5-7474-4a53-b4d3-424fb5c0c806) 2019-02-27 11:33:00,092 - INFO - 5/10 [60.00%]: m_2-84165933-f800-4373-8db2-96de0656eead request was accepted 2019-02-27 11:33:00,094 - INFO - 5/10 [60.00%]: m_3 requested negmas.sao.SAOMechanism[None] with ['c_4', 'm_3'] (ID 72550e06-033f-4ce8-83cf-ed27340817c0) 2019-02-27 11:33:00,095 - INFO - 5/10 [60.00%]: m_3-57429f75-c75c-4cb4-a9b4-ca5c83d682d1 request was accepted 2019-02-27 11:33:00,096 - INFO - 5/10 [60.00%]: m_4 requested negmas.sao.SAOMechanism[None] with ['c_4', 'm_4'] (ID a833a9bf-d443-4210-8110-11e44398260f) 2019-02-27 11:33:00,097 - INFO - 5/10 [60.00%]: m_4-839c8f96-e52b-40cd-a1ef-3bf468ec11cb request was accepted 2019-02-27 11:33:00,101 - INFO - 5/10 [60.00%]: m_0 requested negmas.sao.SAOMechanism[None] with ['c_1', 'm_0'] (ID bc7daf21-b64b-4823-914e-fb35589db402) 2019-02-27 11:33:00,102 - INFO - 5/10 [60.00%]: m_0-575672e1-efe8-4964-b340-4a6116793ce6 request was accepted 2019-02-27 11:33:00,104 - INFO - 5/10 [60.00%]: m_1 requested negmas.sao.SAOMechanism[None] with ['c_1', 'm_1'] (ID ed263803-bd36-48b5-906b-c5dbd8ff394c) 2019-02-27 11:33:00,105 - INFO - 5/10 [60.00%]: m_1-153ac158-9a57-4bca-8296-bae6389d1ce1 request was accepted 2019-02-27 11:33:00,106 - INFO - 5/10 [60.00%]: m_2 requested negmas.sao.SAOMechanism[None] with ['c_1', 'm_2'] (ID 2f4dd4a6-03c2-4023-af0b-3605edad39a5) 2019-02-27 11:33:00,106 - INFO - 5/10 [60.00%]: m_2-84165933-f800-4373-8db2-96de0656eead request was accepted 2019-02-27 11:33:00,107 - INFO - 5/10 [60.00%]: m_3 requested negmas.sao.SAOMechanism[None] with ['c_1', 'm_3'] (ID a66e6571-2f59-46bc-87fb-183cbc168841) 2019-02-27 11:33:00,108 - INFO - 5/10 [60.00%]: m_3-57429f75-c75c-4cb4-a9b4-ca5c83d682d1 request was accepted 2019-02-27 11:33:00,109 - INFO - 5/10 [60.00%]: m_4 requested negmas.sao.SAOMechanism[None] with ['c_1', 'm_4'] (ID 52f70bf6-5685-4099-af97-f352ee4e9690) 2019-02-27 11:33:00,110 - INFO - 5/10 [60.00%]: m_4-839c8f96-e52b-40cd-a1ef-3bf468ec11cb request was accepted 2019-02-27 11:33:00,112 - INFO - 5/10 [60.00%]: m_0 requested negmas.sao.SAOMechanism[None] with ['c_0', 'm_0'] (ID 99bd5581-8ebe-4bbf-93e4-a9ba3c4a99fd) 2019-02-27 11:33:00,113 - INFO - 5/10 [60.00%]: m_0-575672e1-efe8-4964-b340-4a6116793ce6 request was accepted 2019-02-27 11:33:00,114 - INFO - 5/10 [60.00%]: m_1 requested negmas.sao.SAOMechanism[None] with ['c_0', 'm_1'] (ID 37b27b92-f3b8-4a56-ab85-1107f961ed93) 2019-02-27 11:33:00,115 - INFO - 5/10 [60.00%]: m_1-153ac158-9a57-4bca-8296-bae6389d1ce1 request was accepted 2019-02-27 11:33:00,116 - INFO - 5/10 [60.00%]: m_2 requested negmas.sao.SAOMechanism[None] with ['c_0', 'm_2'] (ID d17ebc94-ce6a-4fd6-ae9c-0fbb904344f3) 2019-02-27 11:33:00,117 - INFO - 5/10 [60.00%]: m_2-84165933-f800-4373-8db2-96de0656eead request was accepted 2019-02-27 11:33:00,119 - INFO - 5/10 [60.00%]: m_3 requested negmas.sao.SAOMechanism[None] with ['c_0', 'm_3'] (ID 38976ba6-fd26-409f-8c68-74c91d7d0ca3) 2019-02-27 11:33:00,120 - INFO - 5/10 [60.00%]: m_3-57429f75-c75c-4cb4-a9b4-ca5c83d682d1 request was accepted 2019-02-27 11:33:00,121 - INFO - 5/10 [60.00%]: m_4 requested negmas.sao.SAOMechanism[None] with ['c_0', 'm_4'] (ID 940870de-9c8a-4e3c-8fed-95ee31e00bde) 2019-02-27 11:33:00,122 - INFO - 5/10 [60.00%]: m_4-839c8f96-e52b-40cd-a1ef-3bf468ec11cb request was accepted 2019-02-27 11:33:00,124 - INFO - 5/10 [60.00%]: m_0 requested negmas.sao.SAOMechanism[None] with ['c_2', 'm_0'] (ID aeacea0b-75a0-40ed-b6fc-37ce45de09bf) 2019-02-27 11:33:00,124 - INFO - 5/10 [60.00%]: m_0-575672e1-efe8-4964-b340-4a6116793ce6 request was accepted 2019-02-27 11:33:00,125 - INFO - 5/10 [60.00%]: m_1 requested negmas.sao.SAOMechanism[None] with ['c_2', 'm_1'] (ID 949f7351-d60a-4f1f-9a7f-c9d6539619cc) 2019-02-27 11:33:00,126 - INFO - 5/10 [60.00%]: m_1-153ac158-9a57-4bca-8296-bae6389d1ce1 request was accepted 2019-02-27 11:33:00,127 - INFO - 5/10 [60.00%]: m_2 requested negmas.sao.SAOMechanism[None] with ['c_2', 'm_2'] (ID d3c56b25-d120-4e1d-99bb-92cac4b7d72d) 2019-02-27 11:33:00,128 - INFO - 5/10 [60.00%]: m_2-84165933-f800-4373-8db2-96de0656eead request was accepted 2019-02-27 11:33:00,129 - INFO - 5/10 [60.00%]: m_3 requested negmas.sao.SAOMechanism[None] with ['c_2', 'm_3'] (ID f0cb4eb4-3cd1-4bb0-b6dc-12488e604d33) 2019-02-27 11:33:00,129 - INFO - 5/10 [60.00%]: m_3-57429f75-c75c-4cb4-a9b4-ca5c83d682d1 request was accepted 2019-02-27 11:33:00,130 - INFO - 5/10 [60.00%]: m_4 requested negmas.sao.SAOMechanism[None] with ['c_2', 'm_4'] (ID de168fda-a09f-4c0a-ba06-516eea3dfd35) 2019-02-27 11:33:00,131 - INFO - 5/10 [60.00%]: m_4-839c8f96-e52b-40cd-a1ef-3bf468ec11cb request was accepted 2019-02-27 11:33:00,131 - INFO - 5/10 [60.00%]: Executing c_2-88fd8b76-1040-4e98-b476-5e965b64b2fb, m_3-57429f75-c75c-4cb4-a9b4-ca5c83d682d1 agreed on {'time': 5, 'quantity': 4, 'unit_price': 0.5} 2019-02-27 11:33:00,131 - DEBUG - 5/10 [60.00%]: Moved 4 units of p0 from m_3 to c_2 for 2.0 dollars 2019-02-27 11:33:00,131 - INFO - 5/10 [60.00%]: Executing c_1-48b66a5d-80de-4f52-99f0-f2f3af13d7a3, m_1-153ac158-9a57-4bca-8296-bae6389d1ce1 agreed on {'time': 5, 'quantity': 3, 'unit_price': 0.5} 2019-02-27 11:33:00,131 - DEBUG - 5/10 [60.00%]: Moved 3 units of p0 from m_1 to c_1 for 1.5 dollars 2019-02-27 11:33:00,131 - INFO - 5/10 [60.00%]: Executing c_0-3998ad31-d504-4b35-bb85-3be6197f1ea0, m_1-153ac158-9a57-4bca-8296-bae6389d1ce1 agreed on {'time': 5, 'quantity': 3, 'unit_price': 0.5} 2019-02-27 11:33:00,132 - DEBUG - 5/10 [60.00%]: Moved 3 units of p0 from m_1 to c_0 for 1.5 dollars 2019-02-27 11:33:00,132 - INFO - 5/10 [60.00%]: Executing c_3-ef402340-68d6-404a-8c4f-8ec5bead3987, m_3-57429f75-c75c-4cb4-a9b4-ca5c83d682d1 agreed on {'time': 5, 'quantity': 3, 'unit_price': 0.5} 2019-02-27 11:33:00,132 - DEBUG - 5/10 [60.00%]: Moved 3 units of p0 from m_3 to c_3 for 1.5 dollars 2019-02-27 11:33:00,132 - INFO - 5/10 [60.00%]: Executing c_4-70a6b468-fb6c-4fd2-b7da-c47f020247d6, m_4-839c8f96-e52b-40cd-a1ef-3bf468ec11cb agreed on {'time': 5, 'quantity': 3, 'unit_price': 0.5} 2019-02-27 11:33:00,132 - DEBUG - 5/10 [60.00%]: Moved 3 units of p0 from m_4 to c_4 for 1.5 dollars 2019-02-27 11:33:00,132 - DEBUG - 5/10 [60.00%]: Factory 2b84599b-e538-4212-b349-d4a05459c15b: money=-7.0, storage={0: 7}, loans=0.0 2019-02-27 11:33:00,132 - DEBUG - 5/10 [60.00%]: Factory fed30dd7-5bba-4df3-9386-c2570ef237d4: money=-6.5, storage={0: 7}, loans=0.0 2019-02-27 11:33:00,132 - DEBUG - 5/10 [60.00%]: Factory 2b9215ac-5da4-4788-8222-002f92ac7b3c: money=-7.5, storage={0: 7}, loans=0.0 2019-02-27 11:33:00,132 - DEBUG - 5/10 [60.00%]: Factory 1f8923b6-aef8-4008-a31c-b18482add390: money=-6.5, storage={0: 7}, loans=0.0 2019-02-27 11:33:00,132 - DEBUG - 5/10 [60.00%]: Factory 30f40890-1d90-499c-87f7-ac48be226a56: money=-7.0, storage={0: 7}, loans=0.0 2019-02-27 11:33:00,132 - DEBUG - 5/10 [60.00%]: Factory f6c073fa-9343-49a7-b738-ccd0b9381c40: money=5.0, storage={0: -10}, loans=0.0 2019-02-27 11:33:00,132 - DEBUG - 5/10 [60.00%]: Factory 62cc9ee6-9600-42d1-83dd-216923d114b1: money=8.5, storage={0: -17}, loans=0.0 2019-02-27 11:33:00,132 - DEBUG - 5/10 [60.00%]: Factory e11f4f3c-15a1-461a-bd2c-632e07f82b5f: money=2.0, storage={0: -4}, loans=0.0 2019-02-27 11:33:00,132 - DEBUG - 5/10 [60.00%]: Factory 3583ffd0-fef8-4a83-be5d-0fa6562d4c9f: money=11.0, storage={0: -22}, loans=0.0 2019-02-27 11:33:00,132 - DEBUG - 5/10 [60.00%]: Factory eb0d4726-61b8-4266-8c97-4416e5746a6f: money=8.0, storage={0: -16}, loans=0.0 2019-02-27 11:33:00,133 - INFO - 6/10 [70.00%]: 25 Negotiations/4 _entities 2019-02-27 11:33:00,397 - DEBUG - 6/10 [70.00%]: Contract [to be signed at 7]: ['c_3', 'm_0'] > {'time': 9, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_3-ef402340-68d6-404a-8c4f-8ec5bead3987: buy 0 (t: 9, u: (0, 2.0), q: (1, 4))', 'partners': "['c_3-ef402340-68d6-404a-8c4f-8ec5bead3987', 'm_0-575672e1-efe8-4964-b340-4a6116793ce6']", 'seller': 'm_0-575672e1-efe8-4964-b340-4a6116793ce6', 'buyer': 'c_3-ef402340-68d6-404a-8c4f-8ec5bead3987'} 2019-02-27 11:33:00,397 - DEBUG - 6/10 [70.00%]: Contract [to be signed at 7]: ['c_0', 'm_0'] > {'time': 9, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_0-3998ad31-d504-4b35-bb85-3be6197f1ea0: buy 0 (t: 9, u: (0, 2.0), q: (1, 4))', 'partners': "['c_0-3998ad31-d504-4b35-bb85-3be6197f1ea0', 'm_0-575672e1-efe8-4964-b340-4a6116793ce6']", 'seller': 'm_0-575672e1-efe8-4964-b340-4a6116793ce6', 'buyer': 'c_0-3998ad31-d504-4b35-bb85-3be6197f1ea0'} 2019-02-27 11:33:00,398 - DEBUG - 6/10 [70.00%]: Contract [to be signed at 7]: ['c_0', 'm_3'] > {'time': 9, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_0-3998ad31-d504-4b35-bb85-3be6197f1ea0: buy 0 (t: 9, u: (0, 2.0), q: (1, 4))', 'partners': "['c_0-3998ad31-d504-4b35-bb85-3be6197f1ea0', 'm_3-57429f75-c75c-4cb4-a9b4-ca5c83d682d1']", 'seller': 'm_3-57429f75-c75c-4cb4-a9b4-ca5c83d682d1', 'buyer': 'c_0-3998ad31-d504-4b35-bb85-3be6197f1ea0'} 2019-02-27 11:33:00,398 - DEBUG - 6/10 [70.00%]: Contract [to be signed at 7]: ['c_1', 'm_1'] > {'time': 9, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_1-48b66a5d-80de-4f52-99f0-f2f3af13d7a3: buy 0 (t: 9, u: (0, 2.0), q: (1, 4))', 'partners': "['c_1-48b66a5d-80de-4f52-99f0-f2f3af13d7a3', 'm_1-153ac158-9a57-4bca-8296-bae6389d1ce1']", 'seller': 'm_1-153ac158-9a57-4bca-8296-bae6389d1ce1', 'buyer': 'c_1-48b66a5d-80de-4f52-99f0-f2f3af13d7a3'} 2019-02-27 11:33:00,398 - DEBUG - 6/10 [70.00%]: Contract [to be signed at 7]: ['c_2', 'm_3'] > {'time': 9, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_2-88fd8b76-1040-4e98-b476-5e965b64b2fb: buy 0 (t: 9, u: (0, 2.0), q: (1, 4))', 'partners': "['c_2-88fd8b76-1040-4e98-b476-5e965b64b2fb', 'm_3-57429f75-c75c-4cb4-a9b4-ca5c83d682d1']", 'seller': 'm_3-57429f75-c75c-4cb4-a9b4-ca5c83d682d1', 'buyer': 'c_2-88fd8b76-1040-4e98-b476-5e965b64b2fb'} 2019-02-27 11:33:00,398 - DEBUG - 6/10 [70.00%]: Contract [to be signed at 7]: ['c_2', 'm_2'] > {'time': 9, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_2-88fd8b76-1040-4e98-b476-5e965b64b2fb: buy 0 (t: 9, u: (0, 2.0), q: (1, 4))', 'partners': "['c_2-88fd8b76-1040-4e98-b476-5e965b64b2fb', 'm_2-84165933-f800-4373-8db2-96de0656eead']", 'seller': 'm_2-84165933-f800-4373-8db2-96de0656eead', 'buyer': 'c_2-88fd8b76-1040-4e98-b476-5e965b64b2fb'} 2019-02-27 11:33:00,399 - DEBUG - 6/10 [70.00%]: Contract [to be signed at 7]: ['c_4', 'm_3'] > {'time': 9, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_4-70a6b468-fb6c-4fd2-b7da-c47f020247d6: buy 0 (t: 9, u: (0, 2.0), q: (1, 4))', 'partners': "['c_4-70a6b468-fb6c-4fd2-b7da-c47f020247d6', 'm_3-57429f75-c75c-4cb4-a9b4-ca5c83d682d1']", 'seller': 'm_3-57429f75-c75c-4cb4-a9b4-ca5c83d682d1', 'buyer': 'c_4-70a6b468-fb6c-4fd2-b7da-c47f020247d6'} 2019-02-27 11:33:00,399 - DEBUG - 6/10 [70.00%]: Contract [to be signed at 7]: ['c_2', 'm_4'] > {'time': 9, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_2-88fd8b76-1040-4e98-b476-5e965b64b2fb: buy 0 (t: 9, u: (0, 2.0), q: (1, 4))', 'partners': "['c_2-88fd8b76-1040-4e98-b476-5e965b64b2fb', 'm_4-839c8f96-e52b-40cd-a1ef-3bf468ec11cb']", 'seller': 'm_4-839c8f96-e52b-40cd-a1ef-3bf468ec11cb', 'buyer': 'c_2-88fd8b76-1040-4e98-b476-5e965b64b2fb'} 2019-02-27 11:33:00,399 - DEBUG - 6/10 [70.00%]: Contract [to be signed at 7]: ['c_3', 'm_1'] > {'time': 9, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_3-ef402340-68d6-404a-8c4f-8ec5bead3987: buy 0 (t: 9, u: (0, 2.0), q: (1, 4))', 'partners': "['c_3-ef402340-68d6-404a-8c4f-8ec5bead3987', 'm_1-153ac158-9a57-4bca-8296-bae6389d1ce1']", 'seller': 'm_1-153ac158-9a57-4bca-8296-bae6389d1ce1', 'buyer': 'c_3-ef402340-68d6-404a-8c4f-8ec5bead3987'} 2019-02-27 11:33:00,400 - DEBUG - 6/10 [70.00%]: Contract [to be signed at 7]: ['c_3', 'm_4'] > {'time': 9, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_3-ef402340-68d6-404a-8c4f-8ec5bead3987: buy 0 (t: 9, u: (0, 2.0), q: (1, 4))', 'partners': "['c_3-ef402340-68d6-404a-8c4f-8ec5bead3987', 'm_4-839c8f96-e52b-40cd-a1ef-3bf468ec11cb']", 'seller': 'm_4-839c8f96-e52b-40cd-a1ef-3bf468ec11cb', 'buyer': 'c_3-ef402340-68d6-404a-8c4f-8ec5bead3987'} 2019-02-27 11:33:00,400 - DEBUG - 6/10 [70.00%]: Contract [to be signed at 7]: ['c_3', 'm_3'] > {'time': 9, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_3-ef402340-68d6-404a-8c4f-8ec5bead3987: buy 0 (t: 9, u: (0, 2.0), q: (1, 4))', 'partners': "['c_3-ef402340-68d6-404a-8c4f-8ec5bead3987', 'm_3-57429f75-c75c-4cb4-a9b4-ca5c83d682d1']", 'seller': 'm_3-57429f75-c75c-4cb4-a9b4-ca5c83d682d1', 'buyer': 'c_3-ef402340-68d6-404a-8c4f-8ec5bead3987'} 2019-02-27 11:33:00,400 - DEBUG - 6/10 [70.00%]: Contract [to be signed at 7]: ['c_0', 'm_1'] > {'time': 9, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_0-3998ad31-d504-4b35-bb85-3be6197f1ea0: buy 0 (t: 9, u: (0, 2.0), q: (1, 4))', 'partners': "['c_0-3998ad31-d504-4b35-bb85-3be6197f1ea0', 'm_1-153ac158-9a57-4bca-8296-bae6389d1ce1']", 'seller': 'm_1-153ac158-9a57-4bca-8296-bae6389d1ce1', 'buyer': 'c_0-3998ad31-d504-4b35-bb85-3be6197f1ea0'} 2019-02-27 11:33:00,401 - DEBUG - 6/10 [70.00%]: Contract [to be signed at 7]: ['c_2', 'm_1'] > {'time': 9, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_2-88fd8b76-1040-4e98-b476-5e965b64b2fb: buy 0 (t: 9, u: (0, 2.0), q: (1, 4))', 'partners': "['c_2-88fd8b76-1040-4e98-b476-5e965b64b2fb', 'm_1-153ac158-9a57-4bca-8296-bae6389d1ce1']", 'seller': 'm_1-153ac158-9a57-4bca-8296-bae6389d1ce1', 'buyer': 'c_2-88fd8b76-1040-4e98-b476-5e965b64b2fb'} 2019-02-27 11:33:00,401 - DEBUG - 6/10 [70.00%]: Contract [to be signed at 7]: ['c_3', 'm_2'] > {'time': 9, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_3-ef402340-68d6-404a-8c4f-8ec5bead3987: buy 0 (t: 9, u: (0, 2.0), q: (1, 4))', 'partners': "['c_3-ef402340-68d6-404a-8c4f-8ec5bead3987', 'm_2-84165933-f800-4373-8db2-96de0656eead']", 'seller': 'm_2-84165933-f800-4373-8db2-96de0656eead', 'buyer': 'c_3-ef402340-68d6-404a-8c4f-8ec5bead3987'} 2019-02-27 11:33:00,401 - DEBUG - 6/10 [70.00%]: Contract [to be signed at 7]: ['c_4', 'm_4'] > {'time': 9, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_4-70a6b468-fb6c-4fd2-b7da-c47f020247d6: buy 0 (t: 9, u: (0, 2.0), q: (1, 4))', 'partners': "['c_4-70a6b468-fb6c-4fd2-b7da-c47f020247d6', 'm_4-839c8f96-e52b-40cd-a1ef-3bf468ec11cb']", 'seller': 'm_4-839c8f96-e52b-40cd-a1ef-3bf468ec11cb', 'buyer': 'c_4-70a6b468-fb6c-4fd2-b7da-c47f020247d6'} 2019-02-27 11:33:00,402 - DEBUG - 6/10 [70.00%]: Contract [to be signed at 7]: ['c_1', 'm_3'] > {'time': 9, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_1-48b66a5d-80de-4f52-99f0-f2f3af13d7a3: buy 0 (t: 9, u: (0, 2.0), q: (1, 4))', 'partners': "['c_1-48b66a5d-80de-4f52-99f0-f2f3af13d7a3', 'm_3-57429f75-c75c-4cb4-a9b4-ca5c83d682d1']", 'seller': 'm_3-57429f75-c75c-4cb4-a9b4-ca5c83d682d1', 'buyer': 'c_1-48b66a5d-80de-4f52-99f0-f2f3af13d7a3'} 2019-02-27 11:33:00,402 - DEBUG - 6/10 [70.00%]: Contract [to be signed at 7]: ['c_1', 'm_2'] > {'time': 9, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_1-48b66a5d-80de-4f52-99f0-f2f3af13d7a3: buy 0 (t: 9, u: (0, 2.0), q: (1, 4))', 'partners': "['c_1-48b66a5d-80de-4f52-99f0-f2f3af13d7a3', 'm_2-84165933-f800-4373-8db2-96de0656eead']", 'seller': 'm_2-84165933-f800-4373-8db2-96de0656eead', 'buyer': 'c_1-48b66a5d-80de-4f52-99f0-f2f3af13d7a3'} 2019-02-27 11:33:00,402 - DEBUG - 6/10 [70.00%]: Contract [to be signed at 7]: ['c_1', 'm_4'] > {'time': 9, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_1-48b66a5d-80de-4f52-99f0-f2f3af13d7a3: buy 0 (t: 9, u: (0, 2.0), q: (1, 4))', 'partners': "['c_1-48b66a5d-80de-4f52-99f0-f2f3af13d7a3', 'm_4-839c8f96-e52b-40cd-a1ef-3bf468ec11cb']", 'seller': 'm_4-839c8f96-e52b-40cd-a1ef-3bf468ec11cb', 'buyer': 'c_1-48b66a5d-80de-4f52-99f0-f2f3af13d7a3'} 2019-02-27 11:33:00,403 - DEBUG - 6/10 [70.00%]: Contract [to be signed at 7]: ['c_1', 'm_0'] > {'time': 9, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_1-48b66a5d-80de-4f52-99f0-f2f3af13d7a3: buy 0 (t: 9, u: (0, 2.0), q: (1, 4))', 'partners': "['c_1-48b66a5d-80de-4f52-99f0-f2f3af13d7a3', 'm_0-575672e1-efe8-4964-b340-4a6116793ce6']", 'seller': 'm_0-575672e1-efe8-4964-b340-4a6116793ce6', 'buyer': 'c_1-48b66a5d-80de-4f52-99f0-f2f3af13d7a3'} 2019-02-27 11:33:00,403 - DEBUG - 6/10 [70.00%]: Contract [to be signed at 7]: ['c_4', 'm_0'] > {'time': 9, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_4-70a6b468-fb6c-4fd2-b7da-c47f020247d6: buy 0 (t: 9, u: (0, 2.0), q: (1, 4))', 'partners': "['c_4-70a6b468-fb6c-4fd2-b7da-c47f020247d6', 'm_0-575672e1-efe8-4964-b340-4a6116793ce6']", 'seller': 'm_0-575672e1-efe8-4964-b340-4a6116793ce6', 'buyer': 'c_4-70a6b468-fb6c-4fd2-b7da-c47f020247d6'} 2019-02-27 11:33:00,403 - DEBUG - 6/10 [70.00%]: Contract [to be signed at 7]: ['c_2', 'm_0'] > {'time': 9, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_2-88fd8b76-1040-4e98-b476-5e965b64b2fb: buy 0 (t: 9, u: (0, 2.0), q: (1, 4))', 'partners': "['c_2-88fd8b76-1040-4e98-b476-5e965b64b2fb', 'm_0-575672e1-efe8-4964-b340-4a6116793ce6']", 'seller': 'm_0-575672e1-efe8-4964-b340-4a6116793ce6', 'buyer': 'c_2-88fd8b76-1040-4e98-b476-5e965b64b2fb'} 2019-02-27 11:33:00,404 - DEBUG - 6/10 [70.00%]: Contract [to be signed at 7]: ['c_0', 'm_4'] > {'time': 9, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_0-3998ad31-d504-4b35-bb85-3be6197f1ea0: buy 0 (t: 9, u: (0, 2.0), q: (1, 4))', 'partners': "['c_0-3998ad31-d504-4b35-bb85-3be6197f1ea0', 'm_4-839c8f96-e52b-40cd-a1ef-3bf468ec11cb']", 'seller': 'm_4-839c8f96-e52b-40cd-a1ef-3bf468ec11cb', 'buyer': 'c_0-3998ad31-d504-4b35-bb85-3be6197f1ea0'} 2019-02-27 11:33:00,404 - DEBUG - 6/10 [70.00%]: Contract [to be signed at 7]: ['c_4', 'm_2'] > {'time': 9, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_4-70a6b468-fb6c-4fd2-b7da-c47f020247d6: buy 0 (t: 9, u: (0, 2.0), q: (1, 4))', 'partners': "['c_4-70a6b468-fb6c-4fd2-b7da-c47f020247d6', 'm_2-84165933-f800-4373-8db2-96de0656eead']", 'seller': 'm_2-84165933-f800-4373-8db2-96de0656eead', 'buyer': 'c_4-70a6b468-fb6c-4fd2-b7da-c47f020247d6'} 2019-02-27 11:33:00,404 - DEBUG - 6/10 [70.00%]: Contract [to be signed at 7]: ['c_0', 'm_2'] > {'time': 9, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_0-3998ad31-d504-4b35-bb85-3be6197f1ea0: buy 0 (t: 9, u: (0, 2.0), q: (1, 4))', 'partners': "['c_0-3998ad31-d504-4b35-bb85-3be6197f1ea0', 'm_2-84165933-f800-4373-8db2-96de0656eead']", 'seller': 'm_2-84165933-f800-4373-8db2-96de0656eead', 'buyer': 'c_0-3998ad31-d504-4b35-bb85-3be6197f1ea0'} 2019-02-27 11:33:00,405 - DEBUG - 6/10 [70.00%]: Contract [to be signed at 7]: ['c_4', 'm_1'] > {'time': 9, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_4-70a6b468-fb6c-4fd2-b7da-c47f020247d6: buy 0 (t: 9, u: (0, 2.0), q: (1, 4))', 'partners': "['c_4-70a6b468-fb6c-4fd2-b7da-c47f020247d6', 'm_1-153ac158-9a57-4bca-8296-bae6389d1ce1']", 'seller': 'm_1-153ac158-9a57-4bca-8296-bae6389d1ce1', 'buyer': 'c_4-70a6b468-fb6c-4fd2-b7da-c47f020247d6'} 2019-02-27 11:33:00,406 - INFO - 6/10 [70.00%]: Executing c_3-ef402340-68d6-404a-8c4f-8ec5bead3987, m_1-153ac158-9a57-4bca-8296-bae6389d1ce1 agreed on {'time': 6, 'quantity': 4, 'unit_price': 0.5} 2019-02-27 11:33:00,406 - DEBUG - 6/10 [70.00%]: Moved 4 units of p0 from m_1 to c_3 for 2.0 dollars 2019-02-27 11:33:00,406 - INFO - 6/10 [70.00%]: Executing c_0-3998ad31-d504-4b35-bb85-3be6197f1ea0, m_1-153ac158-9a57-4bca-8296-bae6389d1ce1 agreed on {'time': 6, 'quantity': 3, 'unit_price': 0.5} 2019-02-27 11:33:00,406 - DEBUG - 6/10 [70.00%]: Moved 3 units of p0 from m_1 to c_0 for 1.5 dollars 2019-02-27 11:33:00,407 - INFO - 6/10 [70.00%]: Executing c_2-88fd8b76-1040-4e98-b476-5e965b64b2fb, m_1-153ac158-9a57-4bca-8296-bae6389d1ce1 agreed on {'time': 6, 'quantity': 4, 'unit_price': 0.5} 2019-02-27 11:33:00,407 - DEBUG - 6/10 [70.00%]: Moved 4 units of p0 from m_1 to c_2 for 2.0 dollars 2019-02-27 11:33:00,407 - INFO - 6/10 [70.00%]: Executing c_1-48b66a5d-80de-4f52-99f0-f2f3af13d7a3, m_1-153ac158-9a57-4bca-8296-bae6389d1ce1 agreed on {'time': 6, 'quantity': 4, 'unit_price': 0.5} 2019-02-27 11:33:00,407 - DEBUG - 6/10 [70.00%]: Moved 4 units of p0 from m_1 to c_1 for 2.0 dollars 2019-02-27 11:33:00,407 - INFO - 6/10 [70.00%]: Executing c_4-70a6b468-fb6c-4fd2-b7da-c47f020247d6, m_2-84165933-f800-4373-8db2-96de0656eead agreed on {'time': 6, 'quantity': 4, 'unit_price': 0.5} 2019-02-27 11:33:00,407 - DEBUG - 6/10 [70.00%]: Moved 4 units of p0 from m_2 to c_4 for 2.0 dollars 2019-02-27 11:33:00,407 - DEBUG - 6/10 [70.00%]: Factory 2b84599b-e538-4212-b349-d4a05459c15b: money=-8.5, storage={0: 11}, loans=0.0 2019-02-27 11:33:00,407 - DEBUG - 6/10 [70.00%]: Factory fed30dd7-5bba-4df3-9386-c2570ef237d4: money=-8.5, storage={0: 10}, loans=0.0 2019-02-27 11:33:00,407 - DEBUG - 6/10 [70.00%]: Factory 2b9215ac-5da4-4788-8222-002f92ac7b3c: money=-9.5, storage={0: 11}, loans=0.0 2019-02-27 11:33:00,407 - DEBUG - 6/10 [70.00%]: Factory 1f8923b6-aef8-4008-a31c-b18482add390: money=-8.5, storage={0: 10}, loans=0.0 2019-02-27 11:33:00,407 - DEBUG - 6/10 [70.00%]: Factory 30f40890-1d90-499c-87f7-ac48be226a56: money=-9.0, storage={0: 11}, loans=0.0 2019-02-27 11:33:00,407 - DEBUG - 6/10 [70.00%]: Factory f6c073fa-9343-49a7-b738-ccd0b9381c40: money=5.0, storage={0: -10}, loans=0.0 2019-02-27 11:33:00,407 - DEBUG - 6/10 [70.00%]: Factory 62cc9ee6-9600-42d1-83dd-216923d114b1: money=16.0, storage={0: -32}, loans=0.0 2019-02-27 11:33:00,407 - DEBUG - 6/10 [70.00%]: Factory e11f4f3c-15a1-461a-bd2c-632e07f82b5f: money=4.0, storage={0: -8}, loans=0.0 2019-02-27 11:33:00,407 - DEBUG - 6/10 [70.00%]: Factory 3583ffd0-fef8-4a83-be5d-0fa6562d4c9f: money=11.0, storage={0: -22}, loans=0.0 2019-02-27 11:33:00,407 - DEBUG - 6/10 [70.00%]: Factory eb0d4726-61b8-4266-8c97-4416e5746a6f: money=8.0, storage={0: -16}, loans=0.0 2019-02-27 11:33:00,407 - INFO - 7/10 [80.00%]: 0 Negotiations/4 _entities 2019-02-27 11:33:00,408 - INFO - 7/10 [80.00%]: Executing c_2-88fd8b76-1040-4e98-b476-5e965b64b2fb, m_3-57429f75-c75c-4cb4-a9b4-ca5c83d682d1 agreed on {'time': 7, 'quantity': 4, 'unit_price': 0.5} 2019-02-27 11:33:00,408 - DEBUG - 7/10 [80.00%]: Moved 4 units of p0 from m_3 to c_2 for 2.0 dollars 2019-02-27 11:33:00,408 - INFO - 7/10 [80.00%]: Executing c_4-70a6b468-fb6c-4fd2-b7da-c47f020247d6, m_0-575672e1-efe8-4964-b340-4a6116793ce6 agreed on {'time': 7, 'quantity': 4, 'unit_price': 0.5} 2019-02-27 11:33:00,408 - DEBUG - 7/10 [80.00%]: Moved 4 units of p0 from m_0 to c_4 for 2.0 dollars 2019-02-27 11:33:00,409 - INFO - 7/10 [80.00%]: Executing c_3-ef402340-68d6-404a-8c4f-8ec5bead3987, m_0-575672e1-efe8-4964-b340-4a6116793ce6 agreed on {'time': 7, 'quantity': 4, 'unit_price': 0.5} 2019-02-27 11:33:00,409 - DEBUG - 7/10 [80.00%]: Moved 4 units of p0 from m_0 to c_3 for 2.0 dollars 2019-02-27 11:33:00,409 - INFO - 7/10 [80.00%]: Executing c_0-3998ad31-d504-4b35-bb85-3be6197f1ea0, m_1-153ac158-9a57-4bca-8296-bae6389d1ce1 agreed on {'time': 7, 'quantity': 3, 'unit_price': 0.5} 2019-02-27 11:33:00,409 - DEBUG - 7/10 [80.00%]: Moved 3 units of p0 from m_1 to c_0 for 1.5 dollars 2019-02-27 11:33:00,409 - INFO - 7/10 [80.00%]: Executing c_1-48b66a5d-80de-4f52-99f0-f2f3af13d7a3, m_3-57429f75-c75c-4cb4-a9b4-ca5c83d682d1 agreed on {'time': 7, 'quantity': 3, 'unit_price': 0.5} 2019-02-27 11:33:00,409 - DEBUG - 7/10 [80.00%]: Moved 3 units of p0 from m_3 to c_1 for 1.5 dollars 2019-02-27 11:33:00,409 - DEBUG - 7/10 [80.00%]: Factory 2b84599b-e538-4212-b349-d4a05459c15b: money=-10.0, storage={0: 14}, loans=0.0 2019-02-27 11:33:00,409 - DEBUG - 7/10 [80.00%]: Factory fed30dd7-5bba-4df3-9386-c2570ef237d4: money=-10.0, storage={0: 13}, loans=0.0 2019-02-27 11:33:00,409 - DEBUG - 7/10 [80.00%]: Factory 2b9215ac-5da4-4788-8222-002f92ac7b3c: money=-11.5, storage={0: 15}, loans=0.0 2019-02-27 11:33:00,409 - DEBUG - 7/10 [80.00%]: Factory 1f8923b6-aef8-4008-a31c-b18482add390: money=-10.5, storage={0: 13}, loans=0.0 2019-02-27 11:33:00,409 - DEBUG - 7/10 [80.00%]: Factory 30f40890-1d90-499c-87f7-ac48be226a56: money=-11.0, storage={0: 14}, loans=0.0 2019-02-27 11:33:00,409 - DEBUG - 7/10 [80.00%]: Factory f6c073fa-9343-49a7-b738-ccd0b9381c40: money=9.0, storage={0: -18}, loans=0.0 2019-02-27 11:33:00,409 - DEBUG - 7/10 [80.00%]: Factory 62cc9ee6-9600-42d1-83dd-216923d114b1: money=17.5, storage={0: -35}, loans=0.0 2019-02-27 11:33:00,409 - DEBUG - 7/10 [80.00%]: Factory e11f4f3c-15a1-461a-bd2c-632e07f82b5f: money=4.0, storage={0: -8}, loans=0.0 2019-02-27 11:33:00,409 - DEBUG - 7/10 [80.00%]: Factory 3583ffd0-fef8-4a83-be5d-0fa6562d4c9f: money=14.5, storage={0: -29}, loans=0.0 2019-02-27 11:33:00,409 - DEBUG - 7/10 [80.00%]: Factory eb0d4726-61b8-4266-8c97-4416e5746a6f: money=8.0, storage={0: -16}, loans=0.0 2019-02-27 11:33:00,409 - INFO - 8/10 [90.00%]: 0 Negotiations/4 _entities 2019-02-27 11:33:00,410 - INFO - 8/10 [90.00%]: Executing c_0-3998ad31-d504-4b35-bb85-3be6197f1ea0, m_3-57429f75-c75c-4cb4-a9b4-ca5c83d682d1 agreed on {'time': 8, 'quantity': 4, 'unit_price': 0.5} 2019-02-27 11:33:00,410 - DEBUG - 8/10 [90.00%]: Moved 4 units of p0 from m_3 to c_0 for 2.0 dollars 2019-02-27 11:33:00,410 - INFO - 8/10 [90.00%]: Executing c_2-88fd8b76-1040-4e98-b476-5e965b64b2fb, m_3-57429f75-c75c-4cb4-a9b4-ca5c83d682d1 agreed on {'time': 8, 'quantity': 4, 'unit_price': 0.5} 2019-02-27 11:33:00,410 - DEBUG - 8/10 [90.00%]: Moved 4 units of p0 from m_3 to c_2 for 2.0 dollars 2019-02-27 11:33:00,410 - INFO - 8/10 [90.00%]: Executing c_3-ef402340-68d6-404a-8c4f-8ec5bead3987, m_0-575672e1-efe8-4964-b340-4a6116793ce6 agreed on {'time': 8, 'quantity': 3, 'unit_price': 0.5} 2019-02-27 11:33:00,411 - DEBUG - 8/10 [90.00%]: Moved 3 units of p0 from m_0 to c_3 for 1.5 dollars 2019-02-27 11:33:00,411 - INFO - 8/10 [90.00%]: Executing c_1-48b66a5d-80de-4f52-99f0-f2f3af13d7a3, m_1-153ac158-9a57-4bca-8296-bae6389d1ce1 agreed on {'time': 8, 'quantity': 3, 'unit_price': 0.5} 2019-02-27 11:33:00,411 - DEBUG - 8/10 [90.00%]: Moved 3 units of p0 from m_1 to c_1 for 1.5 dollars 2019-02-27 11:33:00,411 - INFO - 8/10 [90.00%]: Executing c_4-70a6b468-fb6c-4fd2-b7da-c47f020247d6, m_0-575672e1-efe8-4964-b340-4a6116793ce6 agreed on {'time': 8, 'quantity': 3, 'unit_price': 0.5} 2019-02-27 11:33:00,411 - DEBUG - 8/10 [90.00%]: Moved 3 units of p0 from m_0 to c_4 for 1.5 dollars 2019-02-27 11:33:00,411 - DEBUG - 8/10 [90.00%]: Factory 2b84599b-e538-4212-b349-d4a05459c15b: money=-12.0, storage={0: 17}, loans=0.0 2019-02-27 11:33:00,411 - DEBUG - 8/10 [90.00%]: Factory fed30dd7-5bba-4df3-9386-c2570ef237d4: money=-11.5, storage={0: 17}, loans=0.0 2019-02-27 11:33:00,411 - DEBUG - 8/10 [90.00%]: Factory 2b9215ac-5da4-4788-8222-002f92ac7b3c: money=-13.5, storage={0: 19}, loans=0.0 2019-02-27 11:33:00,411 - DEBUG - 8/10 [90.00%]: Factory 1f8923b6-aef8-4008-a31c-b18482add390: money=-12.0, storage={0: 17}, loans=0.0 2019-02-27 11:33:00,411 - DEBUG - 8/10 [90.00%]: Factory 30f40890-1d90-499c-87f7-ac48be226a56: money=-12.5, storage={0: 18}, loans=0.0 2019-02-27 11:33:00,411 - DEBUG - 8/10 [90.00%]: Factory f6c073fa-9343-49a7-b738-ccd0b9381c40: money=12.0, storage={0: -24}, loans=0.0 2019-02-27 11:33:00,411 - DEBUG - 8/10 [90.00%]: Factory 62cc9ee6-9600-42d1-83dd-216923d114b1: money=19.0, storage={0: -38}, loans=0.0 2019-02-27 11:33:00,411 - DEBUG - 8/10 [90.00%]: Factory e11f4f3c-15a1-461a-bd2c-632e07f82b5f: money=4.0, storage={0: -8}, loans=0.0 2019-02-27 11:33:00,411 - DEBUG - 8/10 [90.00%]: Factory 3583ffd0-fef8-4a83-be5d-0fa6562d4c9f: money=18.5, storage={0: -37}, loans=0.0 2019-02-27 11:33:00,411 - DEBUG - 8/10 [90.00%]: Factory eb0d4726-61b8-4266-8c97-4416e5746a6f: money=8.0, storage={0: -16}, loans=0.0 2019-02-27 11:33:00,411 - INFO - 9/10 [100.00%]: 0 Negotiations/4 _entities 2019-02-27 11:33:00,412 - DEBUG - 9/10 [100.00%]: Factory 2b84599b-e538-4212-b349-d4a05459c15b: money=-12.0, storage={0: 20}, loans=0.0 2019-02-27 11:33:00,412 - DEBUG - 9/10 [100.00%]: Factory fed30dd7-5bba-4df3-9386-c2570ef237d4: money=-11.5, storage={0: 20}, loans=0.0 2019-02-27 11:33:00,412 - DEBUG - 9/10 [100.00%]: Factory 2b9215ac-5da4-4788-8222-002f92ac7b3c: money=-13.5, storage={0: 23}, loans=0.0 2019-02-27 11:33:00,412 - DEBUG - 9/10 [100.00%]: Factory 1f8923b6-aef8-4008-a31c-b18482add390: money=-12.0, storage={0: 21}, loans=0.0 2019-02-27 11:33:00,412 - DEBUG - 9/10 [100.00%]: Factory 30f40890-1d90-499c-87f7-ac48be226a56: money=-12.5, storage={0: 22}, loans=0.0 2019-02-27 11:33:00,412 - DEBUG - 9/10 [100.00%]: Factory f6c073fa-9343-49a7-b738-ccd0b9381c40: money=12.0, storage={0: -24}, loans=0.0 2019-02-27 11:33:00,412 - DEBUG - 9/10 [100.00%]: Factory 62cc9ee6-9600-42d1-83dd-216923d114b1: money=19.0, storage={0: -38}, loans=0.0 2019-02-27 11:33:00,412 - DEBUG - 9/10 [100.00%]: Factory e11f4f3c-15a1-461a-bd2c-632e07f82b5f: money=4.0, storage={0: -8}, loans=0.0 2019-02-27 11:33:00,413 - DEBUG - 9/10 [100.00%]: Factory 3583ffd0-fef8-4a83-be5d-0fa6562d4c9f: money=18.5, storage={0: -37}, loans=0.0 2019-02-27 11:33:00,413 - DEBUG - 9/10 [100.00%]: Factory eb0d4726-61b8-4266-8c97-4416e5746a6f: money=8.0, storage={0: -16}, loans=0.0 PK!p |#  #negmas/logs/log_20190227-113345.txt2019-02-27 11:33:47,565 - INFO - 0/5 [20.00%]: SCMLWorld/20190227-113347EwL56: World Created 2019-02-27 11:33:47,566 - INFO - 0/5 [20.00%]: m_0 joined 2019-02-27 11:33:47,566 - INFO - 0/5 [20.00%]: m_1 joined 2019-02-27 11:33:47,566 - INFO - 0/5 [20.00%]: m_2 joined 2019-02-27 11:33:47,566 - INFO - 0/5 [20.00%]: m_3 joined 2019-02-27 11:33:47,566 - INFO - 0/5 [20.00%]: m_4 joined 2019-02-27 11:33:47,566 - INFO - 0/5 [20.00%]: c_0 joined 2019-02-27 11:33:47,566 - INFO - 0/5 [20.00%]: c_1 joined 2019-02-27 11:33:47,566 - INFO - 0/5 [20.00%]: c_2 joined 2019-02-27 11:33:47,566 - INFO - 0/5 [20.00%]: c_3 joined 2019-02-27 11:33:47,567 - INFO - 0/5 [20.00%]: c_4 joined 2019-02-27 11:33:47,568 - INFO - 0/5 [20.00%]: nGisiWgNZq6ITZM5 joined 2019-02-27 11:33:47,568 - INFO - 0/5 [20.00%]: jtgUe52RvEJgwBuN joined 2019-02-27 11:33:47,568 - INFO - 0/5 [20.00%]: 0 Negotiations/4 _entities 2019-02-27 11:33:47,570 - INFO - 0/5 [20.00%]: m_0 requested negmas.sao.SAOMechanism[None] with ['c_0', 'm_0'] (ID 5f68800e-a09e-49e9-9094-27ccd9d850f5) 2019-02-27 11:33:47,571 - INFO - 0/5 [20.00%]: m_0-b2b74473-ea51-4163-bfd8-8a73d4d95a46 request was accepted 2019-02-27 11:33:47,572 - INFO - 0/5 [20.00%]: m_1 requested negmas.sao.SAOMechanism[None] with ['c_0', 'm_1'] (ID 5e48fa65-2952-4f87-9cf7-677d528452b3) 2019-02-27 11:33:47,574 - INFO - 0/5 [20.00%]: m_1-330bf13e-d489-4e44-883c-f0a910d8fd0a request was accepted 2019-02-27 11:33:47,575 - INFO - 0/5 [20.00%]: m_2 requested negmas.sao.SAOMechanism[None] with ['c_0', 'm_2'] (ID 17aef600-20c5-415f-8e58-d7f44d7183a5) 2019-02-27 11:33:47,575 - INFO - 0/5 [20.00%]: m_2-3e017d97-5d6b-4404-acec-89b56f648c32 request was accepted 2019-02-27 11:33:47,576 - INFO - 0/5 [20.00%]: m_3 requested negmas.sao.SAOMechanism[None] with ['c_0', 'm_3'] (ID b7fcf9f5-20cd-48f6-b224-0b5eae1e16b3) 2019-02-27 11:33:47,577 - INFO - 0/5 [20.00%]: m_3-552642da-2001-4c04-b664-9c84d03bb7f8 request was accepted 2019-02-27 11:33:47,578 - INFO - 0/5 [20.00%]: m_4 requested negmas.sao.SAOMechanism[None] with ['c_0', 'm_4'] (ID 74f74d79-b4aa-4ddc-b655-505c9afa35ee) 2019-02-27 11:33:47,579 - INFO - 0/5 [20.00%]: m_4-f942a03d-e2a1-46a3-8c5a-0f0aab311383 request was accepted 2019-02-27 11:33:47,580 - INFO - 0/5 [20.00%]: m_0 requested negmas.sao.SAOMechanism[None] with ['c_0', 'm_0'] (ID 3b743e35-618f-434e-bc8a-0bff517343d9) 2019-02-27 11:33:47,580 - INFO - 0/5 [20.00%]: m_0-b2b74473-ea51-4163-bfd8-8a73d4d95a46 request was accepted 2019-02-27 11:33:47,581 - INFO - 0/5 [20.00%]: m_1 requested negmas.sao.SAOMechanism[None] with ['c_0', 'm_1'] (ID 0d07d1e0-2e21-487d-91b2-5be2da93f39e) 2019-02-27 11:33:47,581 - INFO - 0/5 [20.00%]: m_1-330bf13e-d489-4e44-883c-f0a910d8fd0a request was accepted 2019-02-27 11:33:47,582 - INFO - 0/5 [20.00%]: m_2 requested negmas.sao.SAOMechanism[None] with ['c_0', 'm_2'] (ID ff28e847-4254-44a8-981b-6817e96f8070) 2019-02-27 11:33:47,583 - INFO - 0/5 [20.00%]: m_2-3e017d97-5d6b-4404-acec-89b56f648c32 request was accepted 2019-02-27 11:33:47,584 - INFO - 0/5 [20.00%]: m_3 requested negmas.sao.SAOMechanism[None] with ['c_0', 'm_3'] (ID 25ae23a9-c9f7-4f22-8792-70defaf04dd1) 2019-02-27 11:33:47,585 - INFO - 0/5 [20.00%]: m_3-552642da-2001-4c04-b664-9c84d03bb7f8 request was accepted 2019-02-27 11:33:47,586 - INFO - 0/5 [20.00%]: m_4 requested negmas.sao.SAOMechanism[None] with ['c_0', 'm_4'] (ID 1cefb1c8-485f-4d03-a203-1e0777a9e917) 2019-02-27 11:33:47,586 - INFO - 0/5 [20.00%]: m_4-f942a03d-e2a1-46a3-8c5a-0f0aab311383 request was accepted 2019-02-27 11:33:47,587 - INFO - 0/5 [20.00%]: m_0 requested negmas.sao.SAOMechanism[None] with ['c_1', 'm_0'] (ID eea02780-141e-496b-9c67-fd9992f6a11c) 2019-02-27 11:33:47,588 - INFO - 0/5 [20.00%]: m_0-b2b74473-ea51-4163-bfd8-8a73d4d95a46 request was accepted 2019-02-27 11:33:47,589 - INFO - 0/5 [20.00%]: m_1 requested negmas.sao.SAOMechanism[None] with ['c_1', 'm_1'] (ID 01fc943a-00d3-4347-9005-6462a121cbcd) 2019-02-27 11:33:47,590 - INFO - 0/5 [20.00%]: m_1-330bf13e-d489-4e44-883c-f0a910d8fd0a request was accepted 2019-02-27 11:33:47,591 - INFO - 0/5 [20.00%]: m_2 requested negmas.sao.SAOMechanism[None] with ['c_1', 'm_2'] (ID 5c4e5571-337b-46a0-9ac5-c9c8f186e510) 2019-02-27 11:33:47,591 - INFO - 0/5 [20.00%]: m_2-3e017d97-5d6b-4404-acec-89b56f648c32 request was accepted 2019-02-27 11:33:47,592 - INFO - 0/5 [20.00%]: m_3 requested negmas.sao.SAOMechanism[None] with ['c_1', 'm_3'] (ID a85fa79f-ad21-46d8-bffa-e7b76f28670b) 2019-02-27 11:33:47,593 - INFO - 0/5 [20.00%]: m_3-552642da-2001-4c04-b664-9c84d03bb7f8 request was accepted 2019-02-27 11:33:47,594 - INFO - 0/5 [20.00%]: m_4 requested negmas.sao.SAOMechanism[None] with ['c_1', 'm_4'] (ID f70890fa-5347-4d75-8a7a-a49971c5d0ea) 2019-02-27 11:33:47,594 - INFO - 0/5 [20.00%]: m_4-f942a03d-e2a1-46a3-8c5a-0f0aab311383 request was accepted 2019-02-27 11:33:47,596 - INFO - 0/5 [20.00%]: m_0 requested negmas.sao.SAOMechanism[None] with ['c_1', 'm_0'] (ID 8099eb61-a865-411c-a97e-01f4d0b51a11) 2019-02-27 11:33:47,596 - INFO - 0/5 [20.00%]: m_0-b2b74473-ea51-4163-bfd8-8a73d4d95a46 request was accepted 2019-02-27 11:33:47,597 - INFO - 0/5 [20.00%]: m_1 requested negmas.sao.SAOMechanism[None] with ['c_1', 'm_1'] (ID 7de7cc3d-ca82-4e0d-8761-6db9776066e8) 2019-02-27 11:33:47,598 - INFO - 0/5 [20.00%]: m_1-330bf13e-d489-4e44-883c-f0a910d8fd0a request was accepted 2019-02-27 11:33:47,599 - INFO - 0/5 [20.00%]: m_2 requested negmas.sao.SAOMechanism[None] with ['c_1', 'm_2'] (ID b0805e06-24be-40ff-9edc-f3a926aadd29) 2019-02-27 11:33:47,599 - INFO - 0/5 [20.00%]: m_2-3e017d97-5d6b-4404-acec-89b56f648c32 request was accepted 2019-02-27 11:33:47,600 - INFO - 0/5 [20.00%]: m_3 requested negmas.sao.SAOMechanism[None] with ['c_1', 'm_3'] (ID f0f7440d-9899-4729-8a49-05ee0ff74f87) 2019-02-27 11:33:47,601 - INFO - 0/5 [20.00%]: m_3-552642da-2001-4c04-b664-9c84d03bb7f8 request was accepted 2019-02-27 11:33:47,602 - INFO - 0/5 [20.00%]: m_4 requested negmas.sao.SAOMechanism[None] with ['c_1', 'm_4'] (ID 93fd617b-5579-488e-b438-a117db7521e2) 2019-02-27 11:33:47,602 - INFO - 0/5 [20.00%]: m_4-f942a03d-e2a1-46a3-8c5a-0f0aab311383 request was accepted 2019-02-27 11:33:47,604 - INFO - 0/5 [20.00%]: m_0 requested negmas.sao.SAOMechanism[None] with ['c_2', 'm_0'] (ID 8954cc6e-cfcd-4d64-8efd-86aeb9fcd635) 2019-02-27 11:33:47,604 - INFO - 0/5 [20.00%]: m_0-b2b74473-ea51-4163-bfd8-8a73d4d95a46 request was accepted 2019-02-27 11:33:47,605 - INFO - 0/5 [20.00%]: m_1 requested negmas.sao.SAOMechanism[None] with ['c_2', 'm_1'] (ID 2b9ec4c1-e3d8-40f7-afd9-bcac19e4ea3b) 2019-02-27 11:33:47,606 - INFO - 0/5 [20.00%]: m_1-330bf13e-d489-4e44-883c-f0a910d8fd0a request was accepted 2019-02-27 11:33:47,607 - INFO - 0/5 [20.00%]: m_2 requested negmas.sao.SAOMechanism[None] with ['c_2', 'm_2'] (ID a9bbfc99-167e-423f-8174-ea536f076f14) 2019-02-27 11:33:47,608 - INFO - 0/5 [20.00%]: m_2-3e017d97-5d6b-4404-acec-89b56f648c32 request was accepted 2019-02-27 11:33:47,609 - INFO - 0/5 [20.00%]: m_3 requested negmas.sao.SAOMechanism[None] with ['c_2', 'm_3'] (ID b263f360-86fa-45c6-ab47-aac810fc1551) 2019-02-27 11:33:47,609 - INFO - 0/5 [20.00%]: m_3-552642da-2001-4c04-b664-9c84d03bb7f8 request was accepted 2019-02-27 11:33:47,610 - INFO - 0/5 [20.00%]: m_4 requested negmas.sao.SAOMechanism[None] with ['c_2', 'm_4'] (ID 5a8968b7-f804-4be7-b8bd-bb87f40e39c1) 2019-02-27 11:33:47,611 - INFO - 0/5 [20.00%]: m_4-f942a03d-e2a1-46a3-8c5a-0f0aab311383 request was accepted 2019-02-27 11:33:47,612 - INFO - 0/5 [20.00%]: m_0 requested negmas.sao.SAOMechanism[None] with ['c_2', 'm_0'] (ID 9217716f-3e9b-432b-8bd3-35678589b0ce) 2019-02-27 11:33:47,612 - INFO - 0/5 [20.00%]: m_0-b2b74473-ea51-4163-bfd8-8a73d4d95a46 request was accepted 2019-02-27 11:33:47,614 - INFO - 0/5 [20.00%]: m_1 requested negmas.sao.SAOMechanism[None] with ['c_2', 'm_1'] (ID 067953bc-48e8-4c84-8cd7-fc95bfe2de6e) 2019-02-27 11:33:47,615 - INFO - 0/5 [20.00%]: m_1-330bf13e-d489-4e44-883c-f0a910d8fd0a request was accepted 2019-02-27 11:33:47,616 - INFO - 0/5 [20.00%]: m_2 requested negmas.sao.SAOMechanism[None] with ['c_2', 'm_2'] (ID 51501269-339a-4f76-8b0d-1742e0055abf) 2019-02-27 11:33:47,619 - INFO - 0/5 [20.00%]: m_2-3e017d97-5d6b-4404-acec-89b56f648c32 request was accepted 2019-02-27 11:33:47,622 - INFO - 0/5 [20.00%]: m_3 requested negmas.sao.SAOMechanism[None] with ['c_2', 'm_3'] (ID ffe3d7d5-738e-41a5-b02f-49edc0ee150d) 2019-02-27 11:33:47,623 - INFO - 0/5 [20.00%]: m_3-552642da-2001-4c04-b664-9c84d03bb7f8 request was accepted 2019-02-27 11:33:47,625 - INFO - 0/5 [20.00%]: m_4 requested negmas.sao.SAOMechanism[None] with ['c_2', 'm_4'] (ID 703c9aba-dbda-46ca-b4b9-f56416e7b721) 2019-02-27 11:33:47,626 - INFO - 0/5 [20.00%]: m_4-f942a03d-e2a1-46a3-8c5a-0f0aab311383 request was accepted 2019-02-27 11:33:47,630 - INFO - 0/5 [20.00%]: m_0 requested negmas.sao.SAOMechanism[None] with ['c_3', 'm_0'] (ID 0e1372f3-ec35-4907-b222-7fc8437b2ee8) 2019-02-27 11:33:47,632 - INFO - 0/5 [20.00%]: m_0-b2b74473-ea51-4163-bfd8-8a73d4d95a46 request was accepted 2019-02-27 11:33:47,635 - INFO - 0/5 [20.00%]: m_1 requested negmas.sao.SAOMechanism[None] with ['c_3', 'm_1'] (ID b9ecfb33-b6cf-4048-a67a-e984fd7c0c5c) 2019-02-27 11:33:47,635 - INFO - 0/5 [20.00%]: m_1-330bf13e-d489-4e44-883c-f0a910d8fd0a request was accepted 2019-02-27 11:33:47,637 - INFO - 0/5 [20.00%]: m_2 requested negmas.sao.SAOMechanism[None] with ['c_3', 'm_2'] (ID 59e5104a-2faa-4e5e-9768-04003baea594) 2019-02-27 11:33:47,637 - INFO - 0/5 [20.00%]: m_2-3e017d97-5d6b-4404-acec-89b56f648c32 request was accepted 2019-02-27 11:33:47,639 - INFO - 0/5 [20.00%]: m_3 requested negmas.sao.SAOMechanism[None] with ['c_3', 'm_3'] (ID 30e38d3b-6c08-4a6b-8fe5-891169e17e11) 2019-02-27 11:33:47,640 - INFO - 0/5 [20.00%]: m_3-552642da-2001-4c04-b664-9c84d03bb7f8 request was accepted 2019-02-27 11:33:47,641 - INFO - 0/5 [20.00%]: m_4 requested negmas.sao.SAOMechanism[None] with ['c_3', 'm_4'] (ID 3f08ba16-b8a8-4c94-81b9-41cdcd92f229) 2019-02-27 11:33:47,642 - INFO - 0/5 [20.00%]: m_4-f942a03d-e2a1-46a3-8c5a-0f0aab311383 request was accepted 2019-02-27 11:33:47,643 - INFO - 0/5 [20.00%]: m_0 requested negmas.sao.SAOMechanism[None] with ['c_3', 'm_0'] (ID 7b4daabf-0af8-4a85-805a-d23423c46c48) 2019-02-27 11:33:47,644 - INFO - 0/5 [20.00%]: m_0-b2b74473-ea51-4163-bfd8-8a73d4d95a46 request was accepted 2019-02-27 11:33:47,645 - INFO - 0/5 [20.00%]: m_1 requested negmas.sao.SAOMechanism[None] with ['c_3', 'm_1'] (ID 051fecc9-f8d1-41ca-b51a-1d906c78cd2b) 2019-02-27 11:33:47,646 - INFO - 0/5 [20.00%]: m_1-330bf13e-d489-4e44-883c-f0a910d8fd0a request was accepted 2019-02-27 11:33:47,646 - INFO - 0/5 [20.00%]: m_2 requested negmas.sao.SAOMechanism[None] with ['c_3', 'm_2'] (ID ef559cac-83ca-48ad-93c0-d3b387eee34d) 2019-02-27 11:33:47,647 - INFO - 0/5 [20.00%]: m_2-3e017d97-5d6b-4404-acec-89b56f648c32 request was accepted 2019-02-27 11:33:47,648 - INFO - 0/5 [20.00%]: m_3 requested negmas.sao.SAOMechanism[None] with ['c_3', 'm_3'] (ID 36a6ffab-08dc-4883-ad68-31891473689e) 2019-02-27 11:33:47,649 - INFO - 0/5 [20.00%]: m_3-552642da-2001-4c04-b664-9c84d03bb7f8 request was accepted 2019-02-27 11:33:47,650 - INFO - 0/5 [20.00%]: m_4 requested negmas.sao.SAOMechanism[None] with ['c_3', 'm_4'] (ID a2c5e206-2924-475c-97d4-fd2545f3ef69) 2019-02-27 11:33:47,651 - INFO - 0/5 [20.00%]: m_4-f942a03d-e2a1-46a3-8c5a-0f0aab311383 request was accepted 2019-02-27 11:33:47,652 - INFO - 0/5 [20.00%]: m_0 requested negmas.sao.SAOMechanism[None] with ['c_4', 'm_0'] (ID 74db9f0b-f355-49eb-a6c6-9cc3050b54dd) 2019-02-27 11:33:47,653 - INFO - 0/5 [20.00%]: m_0-b2b74473-ea51-4163-bfd8-8a73d4d95a46 request was accepted 2019-02-27 11:33:47,654 - INFO - 0/5 [20.00%]: m_1 requested negmas.sao.SAOMechanism[None] with ['c_4', 'm_1'] (ID fa273499-b936-4456-b8a9-cb458a5885bf) 2019-02-27 11:33:47,654 - INFO - 0/5 [20.00%]: m_1-330bf13e-d489-4e44-883c-f0a910d8fd0a request was accepted 2019-02-27 11:33:47,655 - INFO - 0/5 [20.00%]: m_2 requested negmas.sao.SAOMechanism[None] with ['c_4', 'm_2'] (ID 63292051-f0bf-4908-b4dd-7c10ad3a3c3a) 2019-02-27 11:33:47,656 - INFO - 0/5 [20.00%]: m_2-3e017d97-5d6b-4404-acec-89b56f648c32 request was accepted 2019-02-27 11:33:47,657 - INFO - 0/5 [20.00%]: m_3 requested negmas.sao.SAOMechanism[None] with ['c_4', 'm_3'] (ID 9d4100bb-4bb9-4857-aae8-c9c9946d5f39) 2019-02-27 11:33:47,657 - INFO - 0/5 [20.00%]: m_3-552642da-2001-4c04-b664-9c84d03bb7f8 request was accepted 2019-02-27 11:33:47,658 - INFO - 0/5 [20.00%]: m_4 requested negmas.sao.SAOMechanism[None] with ['c_4', 'm_4'] (ID bf6c389c-0951-4b62-9f53-376ba74ea595) 2019-02-27 11:33:47,659 - INFO - 0/5 [20.00%]: m_4-f942a03d-e2a1-46a3-8c5a-0f0aab311383 request was accepted 2019-02-27 11:33:47,660 - INFO - 0/5 [20.00%]: m_0 requested negmas.sao.SAOMechanism[None] with ['c_4', 'm_0'] (ID 3881fd1d-bd3a-4bf0-a53d-3a09b847b6cf) 2019-02-27 11:33:47,661 - INFO - 0/5 [20.00%]: m_0-b2b74473-ea51-4163-bfd8-8a73d4d95a46 request was accepted 2019-02-27 11:33:47,662 - INFO - 0/5 [20.00%]: m_1 requested negmas.sao.SAOMechanism[None] with ['c_4', 'm_1'] (ID 11864280-e658-465d-999a-5a53e6893755) 2019-02-27 11:33:47,662 - INFO - 0/5 [20.00%]: m_1-330bf13e-d489-4e44-883c-f0a910d8fd0a request was accepted 2019-02-27 11:33:47,663 - INFO - 0/5 [20.00%]: m_2 requested negmas.sao.SAOMechanism[None] with ['c_4', 'm_2'] (ID 5cc085c7-6f9d-42ac-8df4-3bf88684547e) 2019-02-27 11:33:47,664 - INFO - 0/5 [20.00%]: m_2-3e017d97-5d6b-4404-acec-89b56f648c32 request was accepted 2019-02-27 11:33:47,665 - INFO - 0/5 [20.00%]: m_3 requested negmas.sao.SAOMechanism[None] with ['c_4', 'm_3'] (ID 07799b33-858e-4acb-8b42-9bdf3f07415b) 2019-02-27 11:33:47,666 - INFO - 0/5 [20.00%]: m_3-552642da-2001-4c04-b664-9c84d03bb7f8 request was accepted 2019-02-27 11:33:47,667 - INFO - 0/5 [20.00%]: m_4 requested negmas.sao.SAOMechanism[None] with ['c_4', 'm_4'] (ID 935c00df-6cb2-4f0a-9758-af2ea876707f) 2019-02-27 11:33:47,669 - INFO - 0/5 [20.00%]: m_4-f942a03d-e2a1-46a3-8c5a-0f0aab311383 request was accepted 2019-02-27 11:33:47,669 - DEBUG - 0/5 [20.00%]: Factory 3972f90f-1ef1-4320-b2ed-b7cc1e3fe76a: money=0, storage={}, loans=0.0 2019-02-27 11:33:47,669 - DEBUG - 0/5 [20.00%]: Factory 9c12276a-e377-43ff-9942-ebebbaca5f0f: money=0, storage={}, loans=0.0 2019-02-27 11:33:47,669 - DEBUG - 0/5 [20.00%]: Factory 9fb5bd99-8a77-455c-a292-13a61f3d1277: money=0, storage={}, loans=0.0 2019-02-27 11:33:47,670 - DEBUG - 0/5 [20.00%]: Factory 6444729f-608f-470a-924f-06aa20c714c4: money=0, storage={}, loans=0.0 2019-02-27 11:33:47,670 - DEBUG - 0/5 [20.00%]: Factory a55763d3-8c50-4b3a-baef-01f9098fbe92: money=0, storage={}, loans=0.0 2019-02-27 11:33:47,670 - DEBUG - 0/5 [20.00%]: Factory a8759689-b82f-46c9-9316-c8184a6eb865: money=0.0, storage={}, loans=0.0 2019-02-27 11:33:47,670 - DEBUG - 0/5 [20.00%]: Factory 56cc3bd8-8f94-4f34-aad8-9e7c25c2a662: money=0.0, storage={}, loans=0.0 2019-02-27 11:33:47,670 - DEBUG - 0/5 [20.00%]: Factory bef7fbff-b1d6-41dc-91d1-b2f6e58392a2: money=0.0, storage={}, loans=0.0 2019-02-27 11:33:47,670 - DEBUG - 0/5 [20.00%]: Factory 7fb015ca-deb5-4a63-8735-0c2ad68edd7d: money=0.0, storage={}, loans=0.0 2019-02-27 11:33:47,670 - DEBUG - 0/5 [20.00%]: Factory 6a59c2fb-0af9-445c-8278-8278d53edb14: money=0.0, storage={}, loans=0.0 2019-02-27 11:33:47,672 - INFO - 1/5 [40.00%]: 50 Negotiations/4 _entities 2019-02-27 11:33:48,089 - DEBUG - 1/5 [40.00%]: Contract [signed]: ['c_2', 'm_4'] > {'time': 1, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_2-9d36542d-3adc-45c3-a83d-bf3254872e52: buy 0 (t: 1, u: (0, 2.0), q: (1, 4))', 'partners': "['c_2-9d36542d-3adc-45c3-a83d-bf3254872e52', 'm_4-f942a03d-e2a1-46a3-8c5a-0f0aab311383']", 'seller': 'm_4-f942a03d-e2a1-46a3-8c5a-0f0aab311383', 'buyer': 'c_2-9d36542d-3adc-45c3-a83d-bf3254872e52'} 2019-02-27 11:33:48,090 - DEBUG - 1/5 [40.00%]: Contract [signed]: ['c_1', 'm_1'] > {'time': 2, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_1-33983822-6cfc-4241-a062-02dde1227de6: buy 0 (t: 2, u: (0, 2.0), q: (1, 3))', 'partners': "['c_1-33983822-6cfc-4241-a062-02dde1227de6', 'm_1-330bf13e-d489-4e44-883c-f0a910d8fd0a']", 'seller': 'm_1-330bf13e-d489-4e44-883c-f0a910d8fd0a', 'buyer': 'c_1-33983822-6cfc-4241-a062-02dde1227de6'} 2019-02-27 11:33:48,090 - DEBUG - 1/5 [40.00%]: Contract [cancelled]: ['c_1', 'm_3'] > {'time': 2, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_1-33983822-6cfc-4241-a062-02dde1227de6: buy 0 (t: 2, u: (0, 2.0), q: (1, 3))', 'partners': "['c_1-33983822-6cfc-4241-a062-02dde1227de6', 'm_3-552642da-2001-4c04-b664-9c84d03bb7f8']", 'seller': 'm_3-552642da-2001-4c04-b664-9c84d03bb7f8', 'buyer': 'c_1-33983822-6cfc-4241-a062-02dde1227de6'} 2019-02-27 11:33:48,091 - DEBUG - 1/5 [40.00%]: Contract [signed]: ['c_3', 'm_0'] > {'time': 1, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_3-2ad64379-0773-4b5b-9536-5bc7a9ef116d: buy 0 (t: 1, u: (0, 2.0), q: (1, 4))', 'partners': "['c_3-2ad64379-0773-4b5b-9536-5bc7a9ef116d', 'm_0-b2b74473-ea51-4163-bfd8-8a73d4d95a46']", 'seller': 'm_0-b2b74473-ea51-4163-bfd8-8a73d4d95a46', 'buyer': 'c_3-2ad64379-0773-4b5b-9536-5bc7a9ef116d'} 2019-02-27 11:33:48,091 - DEBUG - 1/5 [40.00%]: Contract [signed]: ['c_1', 'm_4'] > {'time': 1, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_1-33983822-6cfc-4241-a062-02dde1227de6: buy 0 (t: 1, u: (0, 2.0), q: (1, 4))', 'partners': "['c_1-33983822-6cfc-4241-a062-02dde1227de6', 'm_4-f942a03d-e2a1-46a3-8c5a-0f0aab311383']", 'seller': 'm_4-f942a03d-e2a1-46a3-8c5a-0f0aab311383', 'buyer': 'c_1-33983822-6cfc-4241-a062-02dde1227de6'} 2019-02-27 11:33:48,092 - DEBUG - 1/5 [40.00%]: Contract [signed]: ['c_2', 'm_3'] > {'time': 2, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_2-9d36542d-3adc-45c3-a83d-bf3254872e52: buy 0 (t: 2, u: (0, 2.0), q: (1, 4))', 'partners': "['c_2-9d36542d-3adc-45c3-a83d-bf3254872e52', 'm_3-552642da-2001-4c04-b664-9c84d03bb7f8']", 'seller': 'm_3-552642da-2001-4c04-b664-9c84d03bb7f8', 'buyer': 'c_2-9d36542d-3adc-45c3-a83d-bf3254872e52'} 2019-02-27 11:33:48,092 - DEBUG - 1/5 [40.00%]: Contract [signed]: ['c_4', 'm_4'] > {'time': 2, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_4-58a433ab-e5bb-4c9f-9bbc-29117626f303: buy 0 (t: 2, u: (0, 2.0), q: (1, 4))', 'partners': "['c_4-58a433ab-e5bb-4c9f-9bbc-29117626f303', 'm_4-f942a03d-e2a1-46a3-8c5a-0f0aab311383']", 'seller': 'm_4-f942a03d-e2a1-46a3-8c5a-0f0aab311383', 'buyer': 'c_4-58a433ab-e5bb-4c9f-9bbc-29117626f303'} 2019-02-27 11:33:48,093 - DEBUG - 1/5 [40.00%]: Contract [cancelled]: ['c_4', 'm_0'] > {'time': 2, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_4-58a433ab-e5bb-4c9f-9bbc-29117626f303: buy 0 (t: 2, u: (0, 2.0), q: (1, 4))', 'partners': "['c_4-58a433ab-e5bb-4c9f-9bbc-29117626f303', 'm_0-b2b74473-ea51-4163-bfd8-8a73d4d95a46']", 'seller': 'm_0-b2b74473-ea51-4163-bfd8-8a73d4d95a46', 'buyer': 'c_4-58a433ab-e5bb-4c9f-9bbc-29117626f303'} 2019-02-27 11:33:48,093 - DEBUG - 1/5 [40.00%]: Contract [cancelled]: ['c_2', 'm_0'] > {'time': 1, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_2-9d36542d-3adc-45c3-a83d-bf3254872e52: buy 0 (t: 1, u: (0, 2.0), q: (1, 4))', 'partners': "['c_2-9d36542d-3adc-45c3-a83d-bf3254872e52', 'm_0-b2b74473-ea51-4163-bfd8-8a73d4d95a46']", 'seller': 'm_0-b2b74473-ea51-4163-bfd8-8a73d4d95a46', 'buyer': 'c_2-9d36542d-3adc-45c3-a83d-bf3254872e52'} 2019-02-27 11:33:48,093 - DEBUG - 1/5 [40.00%]: Contract [cancelled]: ['c_1', 'm_1'] > {'time': 1, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_1-33983822-6cfc-4241-a062-02dde1227de6: buy 0 (t: 1, u: (0, 2.0), q: (1, 4))', 'partners': "['c_1-33983822-6cfc-4241-a062-02dde1227de6', 'm_1-330bf13e-d489-4e44-883c-f0a910d8fd0a']", 'seller': 'm_1-330bf13e-d489-4e44-883c-f0a910d8fd0a', 'buyer': 'c_1-33983822-6cfc-4241-a062-02dde1227de6'} 2019-02-27 11:33:48,094 - DEBUG - 1/5 [40.00%]: Contract [cancelled]: ['c_3', 'm_4'] > {'time': 1, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_3-2ad64379-0773-4b5b-9536-5bc7a9ef116d: buy 0 (t: 1, u: (0, 2.0), q: (1, 4))', 'partners': "['c_3-2ad64379-0773-4b5b-9536-5bc7a9ef116d', 'm_4-f942a03d-e2a1-46a3-8c5a-0f0aab311383']", 'seller': 'm_4-f942a03d-e2a1-46a3-8c5a-0f0aab311383', 'buyer': 'c_3-2ad64379-0773-4b5b-9536-5bc7a9ef116d'} 2019-02-27 11:33:48,094 - DEBUG - 1/5 [40.00%]: Contract [signed]: ['c_0', 'm_0'] > {'time': 2, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_0-26d2ab4a-d500-4d36-af88-647bcb3b39b4: buy 0 (t: 2, u: (0, 2.0), q: (1, 3))', 'partners': "['c_0-26d2ab4a-d500-4d36-af88-647bcb3b39b4', 'm_0-b2b74473-ea51-4163-bfd8-8a73d4d95a46']", 'seller': 'm_0-b2b74473-ea51-4163-bfd8-8a73d4d95a46', 'buyer': 'c_0-26d2ab4a-d500-4d36-af88-647bcb3b39b4'} 2019-02-27 11:33:48,094 - DEBUG - 1/5 [40.00%]: Contract [cancelled]: ['c_4', 'm_2'] > {'time': 2, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_4-58a433ab-e5bb-4c9f-9bbc-29117626f303: buy 0 (t: 2, u: (0, 2.0), q: (1, 4))', 'partners': "['c_4-58a433ab-e5bb-4c9f-9bbc-29117626f303', 'm_2-3e017d97-5d6b-4404-acec-89b56f648c32']", 'seller': 'm_2-3e017d97-5d6b-4404-acec-89b56f648c32', 'buyer': 'c_4-58a433ab-e5bb-4c9f-9bbc-29117626f303'} 2019-02-27 11:33:48,095 - DEBUG - 1/5 [40.00%]: Contract [signed]: ['c_0', 'm_2'] > {'time': 1, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_0-26d2ab4a-d500-4d36-af88-647bcb3b39b4: buy 0 (t: 1, u: (0, 2.0), q: (1, 4))', 'partners': "['c_0-26d2ab4a-d500-4d36-af88-647bcb3b39b4', 'm_2-3e017d97-5d6b-4404-acec-89b56f648c32']", 'seller': 'm_2-3e017d97-5d6b-4404-acec-89b56f648c32', 'buyer': 'c_0-26d2ab4a-d500-4d36-af88-647bcb3b39b4'} 2019-02-27 11:33:48,095 - DEBUG - 1/5 [40.00%]: Contract [cancelled]: ['c_2', 'm_2'] > {'time': 2, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_2-9d36542d-3adc-45c3-a83d-bf3254872e52: buy 0 (t: 2, u: (0, 2.0), q: (1, 4))', 'partners': "['c_2-9d36542d-3adc-45c3-a83d-bf3254872e52', 'm_2-3e017d97-5d6b-4404-acec-89b56f648c32']", 'seller': 'm_2-3e017d97-5d6b-4404-acec-89b56f648c32', 'buyer': 'c_2-9d36542d-3adc-45c3-a83d-bf3254872e52'} 2019-02-27 11:33:48,095 - DEBUG - 1/5 [40.00%]: Contract [cancelled]: ['c_0', 'm_0'] > {'time': 1, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_0-26d2ab4a-d500-4d36-af88-647bcb3b39b4: buy 0 (t: 1, u: (0, 2.0), q: (1, 4))', 'partners': "['c_0-26d2ab4a-d500-4d36-af88-647bcb3b39b4', 'm_0-b2b74473-ea51-4163-bfd8-8a73d4d95a46']", 'seller': 'm_0-b2b74473-ea51-4163-bfd8-8a73d4d95a46', 'buyer': 'c_0-26d2ab4a-d500-4d36-af88-647bcb3b39b4'} 2019-02-27 11:33:48,096 - DEBUG - 1/5 [40.00%]: Contract [cancelled]: ['c_1', 'm_2'] > {'time': 2, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_1-33983822-6cfc-4241-a062-02dde1227de6: buy 0 (t: 2, u: (0, 2.0), q: (1, 3))', 'partners': "['c_1-33983822-6cfc-4241-a062-02dde1227de6', 'm_2-3e017d97-5d6b-4404-acec-89b56f648c32']", 'seller': 'm_2-3e017d97-5d6b-4404-acec-89b56f648c32', 'buyer': 'c_1-33983822-6cfc-4241-a062-02dde1227de6'} 2019-02-27 11:33:48,096 - DEBUG - 1/5 [40.00%]: Contract [signed]: ['c_4', 'm_3'] > {'time': 1, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_4-58a433ab-e5bb-4c9f-9bbc-29117626f303: buy 0 (t: 1, u: (0, 2.0), q: (1, 3))', 'partners': "['c_4-58a433ab-e5bb-4c9f-9bbc-29117626f303', 'm_3-552642da-2001-4c04-b664-9c84d03bb7f8']", 'seller': 'm_3-552642da-2001-4c04-b664-9c84d03bb7f8', 'buyer': 'c_4-58a433ab-e5bb-4c9f-9bbc-29117626f303'} 2019-02-27 11:33:48,096 - DEBUG - 1/5 [40.00%]: Contract [cancelled]: ['c_2', 'm_1'] > {'time': 1, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_2-9d36542d-3adc-45c3-a83d-bf3254872e52: buy 0 (t: 1, u: (0, 2.0), q: (1, 4))', 'partners': "['c_2-9d36542d-3adc-45c3-a83d-bf3254872e52', 'm_1-330bf13e-d489-4e44-883c-f0a910d8fd0a']", 'seller': 'm_1-330bf13e-d489-4e44-883c-f0a910d8fd0a', 'buyer': 'c_2-9d36542d-3adc-45c3-a83d-bf3254872e52'} 2019-02-27 11:33:48,096 - DEBUG - 1/5 [40.00%]: Contract [cancelled]: ['c_3', 'm_3'] > {'time': 1, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_3-2ad64379-0773-4b5b-9536-5bc7a9ef116d: buy 0 (t: 1, u: (0, 2.0), q: (1, 4))', 'partners': "['c_3-2ad64379-0773-4b5b-9536-5bc7a9ef116d', 'm_3-552642da-2001-4c04-b664-9c84d03bb7f8']", 'seller': 'm_3-552642da-2001-4c04-b664-9c84d03bb7f8', 'buyer': 'c_3-2ad64379-0773-4b5b-9536-5bc7a9ef116d'} 2019-02-27 11:33:48,097 - DEBUG - 1/5 [40.00%]: Contract [cancelled]: ['c_1', 'm_4'] > {'time': 2, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_1-33983822-6cfc-4241-a062-02dde1227de6: buy 0 (t: 2, u: (0, 2.0), q: (1, 3))', 'partners': "['c_1-33983822-6cfc-4241-a062-02dde1227de6', 'm_4-f942a03d-e2a1-46a3-8c5a-0f0aab311383']", 'seller': 'm_4-f942a03d-e2a1-46a3-8c5a-0f0aab311383', 'buyer': 'c_1-33983822-6cfc-4241-a062-02dde1227de6'} 2019-02-27 11:33:48,097 - DEBUG - 1/5 [40.00%]: Contract [signed]: ['c_3', 'm_2'] > {'time': 2, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_3-2ad64379-0773-4b5b-9536-5bc7a9ef116d: buy 0 (t: 2, u: (0, 2.0), q: (1, 3))', 'partners': "['c_3-2ad64379-0773-4b5b-9536-5bc7a9ef116d', 'm_2-3e017d97-5d6b-4404-acec-89b56f648c32']", 'seller': 'm_2-3e017d97-5d6b-4404-acec-89b56f648c32', 'buyer': 'c_3-2ad64379-0773-4b5b-9536-5bc7a9ef116d'} 2019-02-27 11:33:48,098 - DEBUG - 1/5 [40.00%]: Contract [cancelled]: ['c_0', 'm_3'] > {'time': 2, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_0-26d2ab4a-d500-4d36-af88-647bcb3b39b4: buy 0 (t: 2, u: (0, 2.0), q: (1, 3))', 'partners': "['c_0-26d2ab4a-d500-4d36-af88-647bcb3b39b4', 'm_3-552642da-2001-4c04-b664-9c84d03bb7f8']", 'seller': 'm_3-552642da-2001-4c04-b664-9c84d03bb7f8', 'buyer': 'c_0-26d2ab4a-d500-4d36-af88-647bcb3b39b4'} 2019-02-27 11:33:48,098 - DEBUG - 1/5 [40.00%]: Contract [cancelled]: ['c_0', 'm_4'] > {'time': 2, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_0-26d2ab4a-d500-4d36-af88-647bcb3b39b4: buy 0 (t: 2, u: (0, 2.0), q: (1, 3))', 'partners': "['c_0-26d2ab4a-d500-4d36-af88-647bcb3b39b4', 'm_4-f942a03d-e2a1-46a3-8c5a-0f0aab311383']", 'seller': 'm_4-f942a03d-e2a1-46a3-8c5a-0f0aab311383', 'buyer': 'c_0-26d2ab4a-d500-4d36-af88-647bcb3b39b4'} 2019-02-27 11:33:48,098 - DEBUG - 1/5 [40.00%]: Contract [cancelled]: ['c_2', 'm_4'] > {'time': 2, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_2-9d36542d-3adc-45c3-a83d-bf3254872e52: buy 0 (t: 2, u: (0, 2.0), q: (1, 4))', 'partners': "['c_2-9d36542d-3adc-45c3-a83d-bf3254872e52', 'm_4-f942a03d-e2a1-46a3-8c5a-0f0aab311383']", 'seller': 'm_4-f942a03d-e2a1-46a3-8c5a-0f0aab311383', 'buyer': 'c_2-9d36542d-3adc-45c3-a83d-bf3254872e52'} 2019-02-27 11:33:48,099 - DEBUG - 1/5 [40.00%]: Contract [cancelled]: ['c_3', 'm_4'] > {'time': 2, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_3-2ad64379-0773-4b5b-9536-5bc7a9ef116d: buy 0 (t: 2, u: (0, 2.0), q: (1, 3))', 'partners': "['c_3-2ad64379-0773-4b5b-9536-5bc7a9ef116d', 'm_4-f942a03d-e2a1-46a3-8c5a-0f0aab311383']", 'seller': 'm_4-f942a03d-e2a1-46a3-8c5a-0f0aab311383', 'buyer': 'c_3-2ad64379-0773-4b5b-9536-5bc7a9ef116d'} 2019-02-27 11:33:48,099 - DEBUG - 1/5 [40.00%]: Contract [cancelled]: ['c_4', 'm_4'] > {'time': 1, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_4-58a433ab-e5bb-4c9f-9bbc-29117626f303: buy 0 (t: 1, u: (0, 2.0), q: (1, 3))', 'partners': "['c_4-58a433ab-e5bb-4c9f-9bbc-29117626f303', 'm_4-f942a03d-e2a1-46a3-8c5a-0f0aab311383']", 'seller': 'm_4-f942a03d-e2a1-46a3-8c5a-0f0aab311383', 'buyer': 'c_4-58a433ab-e5bb-4c9f-9bbc-29117626f303'} 2019-02-27 11:33:48,099 - DEBUG - 1/5 [40.00%]: Contract [cancelled]: ['c_3', 'm_0'] > {'time': 2, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_3-2ad64379-0773-4b5b-9536-5bc7a9ef116d: buy 0 (t: 2, u: (0, 2.0), q: (1, 3))', 'partners': "['c_3-2ad64379-0773-4b5b-9536-5bc7a9ef116d', 'm_0-b2b74473-ea51-4163-bfd8-8a73d4d95a46']", 'seller': 'm_0-b2b74473-ea51-4163-bfd8-8a73d4d95a46', 'buyer': 'c_3-2ad64379-0773-4b5b-9536-5bc7a9ef116d'} 2019-02-27 11:33:48,100 - DEBUG - 1/5 [40.00%]: Contract [cancelled]: ['c_0', 'm_3'] > {'time': 1, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_0-26d2ab4a-d500-4d36-af88-647bcb3b39b4: buy 0 (t: 1, u: (0, 2.0), q: (1, 4))', 'partners': "['c_0-26d2ab4a-d500-4d36-af88-647bcb3b39b4', 'm_3-552642da-2001-4c04-b664-9c84d03bb7f8']", 'seller': 'm_3-552642da-2001-4c04-b664-9c84d03bb7f8', 'buyer': 'c_0-26d2ab4a-d500-4d36-af88-647bcb3b39b4'} 2019-02-27 11:33:48,100 - DEBUG - 1/5 [40.00%]: Contract [cancelled]: ['c_3', 'm_1'] > {'time': 1, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_3-2ad64379-0773-4b5b-9536-5bc7a9ef116d: buy 0 (t: 1, u: (0, 2.0), q: (1, 4))', 'partners': "['c_3-2ad64379-0773-4b5b-9536-5bc7a9ef116d', 'm_1-330bf13e-d489-4e44-883c-f0a910d8fd0a']", 'seller': 'm_1-330bf13e-d489-4e44-883c-f0a910d8fd0a', 'buyer': 'c_3-2ad64379-0773-4b5b-9536-5bc7a9ef116d'} 2019-02-27 11:33:48,100 - DEBUG - 1/5 [40.00%]: Contract [cancelled]: ['c_1', 'm_0'] > {'time': 1, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_1-33983822-6cfc-4241-a062-02dde1227de6: buy 0 (t: 1, u: (0, 2.0), q: (1, 4))', 'partners': "['c_1-33983822-6cfc-4241-a062-02dde1227de6', 'm_0-b2b74473-ea51-4163-bfd8-8a73d4d95a46']", 'seller': 'm_0-b2b74473-ea51-4163-bfd8-8a73d4d95a46', 'buyer': 'c_1-33983822-6cfc-4241-a062-02dde1227de6'} 2019-02-27 11:33:48,101 - DEBUG - 1/5 [40.00%]: Contract [cancelled]: ['c_1', 'm_3'] > {'time': 1, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_1-33983822-6cfc-4241-a062-02dde1227de6: buy 0 (t: 1, u: (0, 2.0), q: (1, 4))', 'partners': "['c_1-33983822-6cfc-4241-a062-02dde1227de6', 'm_3-552642da-2001-4c04-b664-9c84d03bb7f8']", 'seller': 'm_3-552642da-2001-4c04-b664-9c84d03bb7f8', 'buyer': 'c_1-33983822-6cfc-4241-a062-02dde1227de6'} 2019-02-27 11:33:48,101 - DEBUG - 1/5 [40.00%]: Contract [cancelled]: ['c_4', 'm_1'] > {'time': 2, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_4-58a433ab-e5bb-4c9f-9bbc-29117626f303: buy 0 (t: 2, u: (0, 2.0), q: (1, 4))', 'partners': "['c_4-58a433ab-e5bb-4c9f-9bbc-29117626f303', 'm_1-330bf13e-d489-4e44-883c-f0a910d8fd0a']", 'seller': 'm_1-330bf13e-d489-4e44-883c-f0a910d8fd0a', 'buyer': 'c_4-58a433ab-e5bb-4c9f-9bbc-29117626f303'} 2019-02-27 11:33:48,101 - DEBUG - 1/5 [40.00%]: Contract [cancelled]: ['c_2', 'm_2'] > {'time': 1, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_2-9d36542d-3adc-45c3-a83d-bf3254872e52: buy 0 (t: 1, u: (0, 2.0), q: (1, 4))', 'partners': "['c_2-9d36542d-3adc-45c3-a83d-bf3254872e52', 'm_2-3e017d97-5d6b-4404-acec-89b56f648c32']", 'seller': 'm_2-3e017d97-5d6b-4404-acec-89b56f648c32', 'buyer': 'c_2-9d36542d-3adc-45c3-a83d-bf3254872e52'} 2019-02-27 11:33:48,101 - DEBUG - 1/5 [40.00%]: Contract [cancelled]: ['c_4', 'm_3'] > {'time': 2, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_4-58a433ab-e5bb-4c9f-9bbc-29117626f303: buy 0 (t: 2, u: (0, 2.0), q: (1, 4))', 'partners': "['c_4-58a433ab-e5bb-4c9f-9bbc-29117626f303', 'm_3-552642da-2001-4c04-b664-9c84d03bb7f8']", 'seller': 'm_3-552642da-2001-4c04-b664-9c84d03bb7f8', 'buyer': 'c_4-58a433ab-e5bb-4c9f-9bbc-29117626f303'} 2019-02-27 11:33:48,102 - DEBUG - 1/5 [40.00%]: Contract [cancelled]: ['c_3', 'm_3'] > {'time': 2, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_3-2ad64379-0773-4b5b-9536-5bc7a9ef116d: buy 0 (t: 2, u: (0, 2.0), q: (1, 3))', 'partners': "['c_3-2ad64379-0773-4b5b-9536-5bc7a9ef116d', 'm_3-552642da-2001-4c04-b664-9c84d03bb7f8']", 'seller': 'm_3-552642da-2001-4c04-b664-9c84d03bb7f8', 'buyer': 'c_3-2ad64379-0773-4b5b-9536-5bc7a9ef116d'} 2019-02-27 11:33:48,102 - DEBUG - 1/5 [40.00%]: Contract [cancelled]: ['c_0', 'm_4'] > {'time': 1, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_0-26d2ab4a-d500-4d36-af88-647bcb3b39b4: buy 0 (t: 1, u: (0, 2.0), q: (1, 4))', 'partners': "['c_0-26d2ab4a-d500-4d36-af88-647bcb3b39b4', 'm_4-f942a03d-e2a1-46a3-8c5a-0f0aab311383']", 'seller': 'm_4-f942a03d-e2a1-46a3-8c5a-0f0aab311383', 'buyer': 'c_0-26d2ab4a-d500-4d36-af88-647bcb3b39b4'} 2019-02-27 11:33:48,102 - DEBUG - 1/5 [40.00%]: Contract [cancelled]: ['c_3', 'm_2'] > {'time': 1, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_3-2ad64379-0773-4b5b-9536-5bc7a9ef116d: buy 0 (t: 1, u: (0, 2.0), q: (1, 4))', 'partners': "['c_3-2ad64379-0773-4b5b-9536-5bc7a9ef116d', 'm_2-3e017d97-5d6b-4404-acec-89b56f648c32']", 'seller': 'm_2-3e017d97-5d6b-4404-acec-89b56f648c32', 'buyer': 'c_3-2ad64379-0773-4b5b-9536-5bc7a9ef116d'} 2019-02-27 11:33:48,103 - DEBUG - 1/5 [40.00%]: Contract [cancelled]: ['c_0', 'm_1'] > {'time': 1, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_0-26d2ab4a-d500-4d36-af88-647bcb3b39b4: buy 0 (t: 1, u: (0, 2.0), q: (1, 4))', 'partners': "['c_0-26d2ab4a-d500-4d36-af88-647bcb3b39b4', 'm_1-330bf13e-d489-4e44-883c-f0a910d8fd0a']", 'seller': 'm_1-330bf13e-d489-4e44-883c-f0a910d8fd0a', 'buyer': 'c_0-26d2ab4a-d500-4d36-af88-647bcb3b39b4'} 2019-02-27 11:33:48,103 - DEBUG - 1/5 [40.00%]: Contract [cancelled]: ['c_1', 'm_0'] > {'time': 2, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_1-33983822-6cfc-4241-a062-02dde1227de6: buy 0 (t: 2, u: (0, 2.0), q: (1, 3))', 'partners': "['c_1-33983822-6cfc-4241-a062-02dde1227de6', 'm_0-b2b74473-ea51-4163-bfd8-8a73d4d95a46']", 'seller': 'm_0-b2b74473-ea51-4163-bfd8-8a73d4d95a46', 'buyer': 'c_1-33983822-6cfc-4241-a062-02dde1227de6'} 2019-02-27 11:33:48,103 - DEBUG - 1/5 [40.00%]: Contract [cancelled]: ['c_3', 'm_1'] > {'time': 2, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_3-2ad64379-0773-4b5b-9536-5bc7a9ef116d: buy 0 (t: 2, u: (0, 2.0), q: (1, 3))', 'partners': "['c_3-2ad64379-0773-4b5b-9536-5bc7a9ef116d', 'm_1-330bf13e-d489-4e44-883c-f0a910d8fd0a']", 'seller': 'm_1-330bf13e-d489-4e44-883c-f0a910d8fd0a', 'buyer': 'c_3-2ad64379-0773-4b5b-9536-5bc7a9ef116d'} 2019-02-27 11:33:48,104 - DEBUG - 1/5 [40.00%]: Contract [cancelled]: ['c_4', 'm_2'] > {'time': 1, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_4-58a433ab-e5bb-4c9f-9bbc-29117626f303: buy 0 (t: 1, u: (0, 2.0), q: (1, 3))', 'partners': "['c_4-58a433ab-e5bb-4c9f-9bbc-29117626f303', 'm_2-3e017d97-5d6b-4404-acec-89b56f648c32']", 'seller': 'm_2-3e017d97-5d6b-4404-acec-89b56f648c32', 'buyer': 'c_4-58a433ab-e5bb-4c9f-9bbc-29117626f303'} 2019-02-27 11:33:48,104 - DEBUG - 1/5 [40.00%]: Contract [cancelled]: ['c_4', 'm_1'] > {'time': 1, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_4-58a433ab-e5bb-4c9f-9bbc-29117626f303: buy 0 (t: 1, u: (0, 2.0), q: (1, 3))', 'partners': "['c_4-58a433ab-e5bb-4c9f-9bbc-29117626f303', 'm_1-330bf13e-d489-4e44-883c-f0a910d8fd0a']", 'seller': 'm_1-330bf13e-d489-4e44-883c-f0a910d8fd0a', 'buyer': 'c_4-58a433ab-e5bb-4c9f-9bbc-29117626f303'} 2019-02-27 11:33:48,104 - DEBUG - 1/5 [40.00%]: Contract [cancelled]: ['c_4', 'm_0'] > {'time': 1, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_4-58a433ab-e5bb-4c9f-9bbc-29117626f303: buy 0 (t: 1, u: (0, 2.0), q: (1, 3))', 'partners': "['c_4-58a433ab-e5bb-4c9f-9bbc-29117626f303', 'm_0-b2b74473-ea51-4163-bfd8-8a73d4d95a46']", 'seller': 'm_0-b2b74473-ea51-4163-bfd8-8a73d4d95a46', 'buyer': 'c_4-58a433ab-e5bb-4c9f-9bbc-29117626f303'} 2019-02-27 11:33:48,105 - DEBUG - 1/5 [40.00%]: Contract [cancelled]: ['c_2', 'm_3'] > {'time': 1, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_2-9d36542d-3adc-45c3-a83d-bf3254872e52: buy 0 (t: 1, u: (0, 2.0), q: (1, 4))', 'partners': "['c_2-9d36542d-3adc-45c3-a83d-bf3254872e52', 'm_3-552642da-2001-4c04-b664-9c84d03bb7f8']", 'seller': 'm_3-552642da-2001-4c04-b664-9c84d03bb7f8', 'buyer': 'c_2-9d36542d-3adc-45c3-a83d-bf3254872e52'} 2019-02-27 11:33:48,105 - DEBUG - 1/5 [40.00%]: Contract [cancelled]: ['c_0', 'm_2'] > {'time': 2, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_0-26d2ab4a-d500-4d36-af88-647bcb3b39b4: buy 0 (t: 2, u: (0, 2.0), q: (1, 3))', 'partners': "['c_0-26d2ab4a-d500-4d36-af88-647bcb3b39b4', 'm_2-3e017d97-5d6b-4404-acec-89b56f648c32']", 'seller': 'm_2-3e017d97-5d6b-4404-acec-89b56f648c32', 'buyer': 'c_0-26d2ab4a-d500-4d36-af88-647bcb3b39b4'} 2019-02-27 11:33:48,105 - DEBUG - 1/5 [40.00%]: Contract [cancelled]: ['c_1', 'm_2'] > {'time': 1, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_1-33983822-6cfc-4241-a062-02dde1227de6: buy 0 (t: 1, u: (0, 2.0), q: (1, 4))', 'partners': "['c_1-33983822-6cfc-4241-a062-02dde1227de6', 'm_2-3e017d97-5d6b-4404-acec-89b56f648c32']", 'seller': 'm_2-3e017d97-5d6b-4404-acec-89b56f648c32', 'buyer': 'c_1-33983822-6cfc-4241-a062-02dde1227de6'} 2019-02-27 11:33:48,106 - DEBUG - 1/5 [40.00%]: Contract [cancelled]: ['c_2', 'm_0'] > {'time': 2, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_2-9d36542d-3adc-45c3-a83d-bf3254872e52: buy 0 (t: 2, u: (0, 2.0), q: (1, 4))', 'partners': "['c_2-9d36542d-3adc-45c3-a83d-bf3254872e52', 'm_0-b2b74473-ea51-4163-bfd8-8a73d4d95a46']", 'seller': 'm_0-b2b74473-ea51-4163-bfd8-8a73d4d95a46', 'buyer': 'c_2-9d36542d-3adc-45c3-a83d-bf3254872e52'} 2019-02-27 11:33:48,106 - DEBUG - 1/5 [40.00%]: Contract [cancelled]: ['c_2', 'm_1'] > {'time': 2, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_2-9d36542d-3adc-45c3-a83d-bf3254872e52: buy 0 (t: 2, u: (0, 2.0), q: (1, 4))', 'partners': "['c_2-9d36542d-3adc-45c3-a83d-bf3254872e52', 'm_1-330bf13e-d489-4e44-883c-f0a910d8fd0a']", 'seller': 'm_1-330bf13e-d489-4e44-883c-f0a910d8fd0a', 'buyer': 'c_2-9d36542d-3adc-45c3-a83d-bf3254872e52'} 2019-02-27 11:33:48,106 - DEBUG - 1/5 [40.00%]: Contract [cancelled]: ['c_0', 'm_1'] > {'time': 2, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_0-26d2ab4a-d500-4d36-af88-647bcb3b39b4: buy 0 (t: 2, u: (0, 2.0), q: (1, 3))', 'partners': "['c_0-26d2ab4a-d500-4d36-af88-647bcb3b39b4', 'm_1-330bf13e-d489-4e44-883c-f0a910d8fd0a']", 'seller': 'm_1-330bf13e-d489-4e44-883c-f0a910d8fd0a', 'buyer': 'c_0-26d2ab4a-d500-4d36-af88-647bcb3b39b4'} 2019-02-27 11:33:48,107 - INFO - 1/5 [40.00%]: m_0 requested negmas.sao.SAOMechanism[None] with ['c_0', 'm_0'] (ID c0c480a0-1fe3-40e9-81c7-9c20ae04a7bd) 2019-02-27 11:33:48,108 - INFO - 1/5 [40.00%]: m_0-b2b74473-ea51-4163-bfd8-8a73d4d95a46 request was accepted 2019-02-27 11:33:48,109 - INFO - 1/5 [40.00%]: m_1 requested negmas.sao.SAOMechanism[None] with ['c_0', 'm_1'] (ID 3dd3f580-6c2e-4b0a-af64-d6642165ec2a) 2019-02-27 11:33:48,109 - INFO - 1/5 [40.00%]: m_1-330bf13e-d489-4e44-883c-f0a910d8fd0a request was accepted 2019-02-27 11:33:48,110 - INFO - 1/5 [40.00%]: m_2 requested negmas.sao.SAOMechanism[None] with ['c_0', 'm_2'] (ID 71d6626c-ccea-4bc1-8351-847fa79a3c22) 2019-02-27 11:33:48,111 - INFO - 1/5 [40.00%]: m_2-3e017d97-5d6b-4404-acec-89b56f648c32 request was accepted 2019-02-27 11:33:48,112 - INFO - 1/5 [40.00%]: m_3 requested negmas.sao.SAOMechanism[None] with ['c_0', 'm_3'] (ID d7919c77-2e7f-48bd-bab8-d9d2e857a225) 2019-02-27 11:33:48,112 - INFO - 1/5 [40.00%]: m_3-552642da-2001-4c04-b664-9c84d03bb7f8 request was accepted 2019-02-27 11:33:48,113 - INFO - 1/5 [40.00%]: m_4 requested negmas.sao.SAOMechanism[None] with ['c_0', 'm_4'] (ID 145ed356-6b3f-4362-a46e-b5058f973a63) 2019-02-27 11:33:48,114 - INFO - 1/5 [40.00%]: m_4-f942a03d-e2a1-46a3-8c5a-0f0aab311383 request was accepted 2019-02-27 11:33:48,115 - INFO - 1/5 [40.00%]: m_0 requested negmas.sao.SAOMechanism[None] with ['c_1', 'm_0'] (ID 4dcc49c7-5558-46c9-a115-81e0dfbe6ceb) 2019-02-27 11:33:48,115 - INFO - 1/5 [40.00%]: m_0-b2b74473-ea51-4163-bfd8-8a73d4d95a46 request was accepted 2019-02-27 11:33:48,116 - INFO - 1/5 [40.00%]: m_1 requested negmas.sao.SAOMechanism[None] with ['c_1', 'm_1'] (ID c79f6049-073b-4bd7-a8f8-5e6433fa0066) 2019-02-27 11:33:48,117 - INFO - 1/5 [40.00%]: m_1-330bf13e-d489-4e44-883c-f0a910d8fd0a request was accepted 2019-02-27 11:33:48,118 - INFO - 1/5 [40.00%]: m_2 requested negmas.sao.SAOMechanism[None] with ['c_1', 'm_2'] (ID 28faad74-3185-4e71-9fad-1503b2f516b7) 2019-02-27 11:33:48,119 - INFO - 1/5 [40.00%]: m_2-3e017d97-5d6b-4404-acec-89b56f648c32 request was accepted 2019-02-27 11:33:48,119 - INFO - 1/5 [40.00%]: m_3 requested negmas.sao.SAOMechanism[None] with ['c_1', 'm_3'] (ID 9f619d35-fbf9-4a6b-98f6-f7f5c965b238) 2019-02-27 11:33:48,120 - INFO - 1/5 [40.00%]: m_3-552642da-2001-4c04-b664-9c84d03bb7f8 request was accepted 2019-02-27 11:33:48,121 - INFO - 1/5 [40.00%]: m_4 requested negmas.sao.SAOMechanism[None] with ['c_1', 'm_4'] (ID e8dfd030-1679-4fad-927b-e4542b790e9d) 2019-02-27 11:33:48,121 - INFO - 1/5 [40.00%]: m_4-f942a03d-e2a1-46a3-8c5a-0f0aab311383 request was accepted 2019-02-27 11:33:48,123 - INFO - 1/5 [40.00%]: m_0 requested negmas.sao.SAOMechanism[None] with ['c_2', 'm_0'] (ID bb4b22d8-24aa-47f8-882d-8b87cc7ff5be) 2019-02-27 11:33:48,123 - INFO - 1/5 [40.00%]: m_0-b2b74473-ea51-4163-bfd8-8a73d4d95a46 request was accepted 2019-02-27 11:33:48,124 - INFO - 1/5 [40.00%]: m_1 requested negmas.sao.SAOMechanism[None] with ['c_2', 'm_1'] (ID 2c3112d8-71bb-4610-82db-fd8afc3809ef) 2019-02-27 11:33:48,125 - INFO - 1/5 [40.00%]: m_1-330bf13e-d489-4e44-883c-f0a910d8fd0a request was accepted 2019-02-27 11:33:48,126 - INFO - 1/5 [40.00%]: m_2 requested negmas.sao.SAOMechanism[None] with ['c_2', 'm_2'] (ID db519b29-6e7e-42e5-b5c5-aefa0d26640c) 2019-02-27 11:33:48,126 - INFO - 1/5 [40.00%]: m_2-3e017d97-5d6b-4404-acec-89b56f648c32 request was accepted 2019-02-27 11:33:48,127 - INFO - 1/5 [40.00%]: m_3 requested negmas.sao.SAOMechanism[None] with ['c_2', 'm_3'] (ID 8699841c-e39e-4e2a-bc7d-ed7937fadc59) 2019-02-27 11:33:48,128 - INFO - 1/5 [40.00%]: m_3-552642da-2001-4c04-b664-9c84d03bb7f8 request was accepted 2019-02-27 11:33:48,129 - INFO - 1/5 [40.00%]: m_4 requested negmas.sao.SAOMechanism[None] with ['c_2', 'm_4'] (ID 4266735f-ddda-4980-8bcc-d2e3fc69cdd6) 2019-02-27 11:33:48,129 - INFO - 1/5 [40.00%]: m_4-f942a03d-e2a1-46a3-8c5a-0f0aab311383 request was accepted 2019-02-27 11:33:48,130 - INFO - 1/5 [40.00%]: m_0 requested negmas.sao.SAOMechanism[None] with ['c_3', 'm_0'] (ID 5cd637ca-db14-4dee-b0de-1505cc650414) 2019-02-27 11:33:48,131 - INFO - 1/5 [40.00%]: m_0-b2b74473-ea51-4163-bfd8-8a73d4d95a46 request was accepted 2019-02-27 11:33:48,132 - INFO - 1/5 [40.00%]: m_1 requested negmas.sao.SAOMechanism[None] with ['c_3', 'm_1'] (ID 9461b361-f0e1-4be3-9c3e-64fdf6cf28ce) 2019-02-27 11:33:48,133 - INFO - 1/5 [40.00%]: m_1-330bf13e-d489-4e44-883c-f0a910d8fd0a request was accepted 2019-02-27 11:33:48,134 - INFO - 1/5 [40.00%]: m_2 requested negmas.sao.SAOMechanism[None] with ['c_3', 'm_2'] (ID 8dbc5b6a-8712-4b14-989e-88057b803d6c) 2019-02-27 11:33:48,134 - INFO - 1/5 [40.00%]: m_2-3e017d97-5d6b-4404-acec-89b56f648c32 request was accepted 2019-02-27 11:33:48,135 - INFO - 1/5 [40.00%]: m_3 requested negmas.sao.SAOMechanism[None] with ['c_3', 'm_3'] (ID 28b0e958-9b8f-48f8-a752-895cd00b1ff0) 2019-02-27 11:33:48,136 - INFO - 1/5 [40.00%]: m_3-552642da-2001-4c04-b664-9c84d03bb7f8 request was accepted 2019-02-27 11:33:48,136 - INFO - 1/5 [40.00%]: m_4 requested negmas.sao.SAOMechanism[None] with ['c_3', 'm_4'] (ID fd44cae6-d010-4318-a5d9-e3c04daa7e14) 2019-02-27 11:33:48,137 - INFO - 1/5 [40.00%]: m_4-f942a03d-e2a1-46a3-8c5a-0f0aab311383 request was accepted 2019-02-27 11:33:48,138 - INFO - 1/5 [40.00%]: m_0 requested negmas.sao.SAOMechanism[None] with ['c_4', 'm_0'] (ID 72bbf591-1976-42e4-b501-f51e295d0384) 2019-02-27 11:33:48,138 - INFO - 1/5 [40.00%]: m_0-b2b74473-ea51-4163-bfd8-8a73d4d95a46 request was accepted 2019-02-27 11:33:48,139 - INFO - 1/5 [40.00%]: m_1 requested negmas.sao.SAOMechanism[None] with ['c_4', 'm_1'] (ID 7c443319-b067-4b69-8a04-691f174a8571) 2019-02-27 11:33:48,140 - INFO - 1/5 [40.00%]: m_1-330bf13e-d489-4e44-883c-f0a910d8fd0a request was accepted 2019-02-27 11:33:48,141 - INFO - 1/5 [40.00%]: m_2 requested negmas.sao.SAOMechanism[None] with ['c_4', 'm_2'] (ID 6dbb050e-1e58-4bed-bffe-66f73d8ca7b3) 2019-02-27 11:33:48,141 - INFO - 1/5 [40.00%]: m_2-3e017d97-5d6b-4404-acec-89b56f648c32 request was accepted 2019-02-27 11:33:48,142 - INFO - 1/5 [40.00%]: m_3 requested negmas.sao.SAOMechanism[None] with ['c_4', 'm_3'] (ID 02c78be4-94be-4d27-834c-2782da2b77c1) 2019-02-27 11:33:48,143 - INFO - 1/5 [40.00%]: m_3-552642da-2001-4c04-b664-9c84d03bb7f8 request was accepted 2019-02-27 11:33:48,144 - INFO - 1/5 [40.00%]: m_4 requested negmas.sao.SAOMechanism[None] with ['c_4', 'm_4'] (ID 7f654114-e34c-482b-abc9-ab4bbff26c83) 2019-02-27 11:33:48,144 - INFO - 1/5 [40.00%]: m_4-f942a03d-e2a1-46a3-8c5a-0f0aab311383 request was accepted 2019-02-27 11:33:48,144 - INFO - 1/5 [40.00%]: Executing c_1-33983822-6cfc-4241-a062-02dde1227de6, m_4-f942a03d-e2a1-46a3-8c5a-0f0aab311383 agreed on {'time': 1, 'quantity': 4, 'unit_price': 0.5} 2019-02-27 11:33:48,144 - DEBUG - 1/5 [40.00%]: Moved 4 units of p0 from m_4 to c_1 for 2.0 dollars 2019-02-27 11:33:48,144 - INFO - 1/5 [40.00%]: Executing c_3-2ad64379-0773-4b5b-9536-5bc7a9ef116d, m_0-b2b74473-ea51-4163-bfd8-8a73d4d95a46 agreed on {'time': 1, 'quantity': 4, 'unit_price': 0.5} 2019-02-27 11:33:48,144 - DEBUG - 1/5 [40.00%]: Moved 4 units of p0 from m_0 to c_3 for 2.0 dollars 2019-02-27 11:33:48,145 - INFO - 1/5 [40.00%]: Executing c_2-9d36542d-3adc-45c3-a83d-bf3254872e52, m_4-f942a03d-e2a1-46a3-8c5a-0f0aab311383 agreed on {'time': 1, 'quantity': 4, 'unit_price': 0.5} 2019-02-27 11:33:48,145 - DEBUG - 1/5 [40.00%]: Moved 4 units of p0 from m_4 to c_2 for 2.0 dollars 2019-02-27 11:33:48,145 - INFO - 1/5 [40.00%]: Executing c_4-58a433ab-e5bb-4c9f-9bbc-29117626f303, m_3-552642da-2001-4c04-b664-9c84d03bb7f8 agreed on {'time': 1, 'quantity': 3, 'unit_price': 0.5} 2019-02-27 11:33:48,145 - DEBUG - 1/5 [40.00%]: Moved 3 units of p0 from m_3 to c_4 for 1.5 dollars 2019-02-27 11:33:48,145 - INFO - 1/5 [40.00%]: Executing c_0-26d2ab4a-d500-4d36-af88-647bcb3b39b4, m_2-3e017d97-5d6b-4404-acec-89b56f648c32 agreed on {'time': 1, 'quantity': 4, 'unit_price': 0.5} 2019-02-27 11:33:48,145 - DEBUG - 1/5 [40.00%]: Moved 4 units of p0 from m_2 to c_0 for 2.0 dollars 2019-02-27 11:33:48,145 - DEBUG - 1/5 [40.00%]: Factory 3972f90f-1ef1-4320-b2ed-b7cc1e3fe76a: money=-2.0, storage={}, loans=0.0 2019-02-27 11:33:48,145 - DEBUG - 1/5 [40.00%]: Factory 9c12276a-e377-43ff-9942-ebebbaca5f0f: money=-2.0, storage={}, loans=0.0 2019-02-27 11:33:48,145 - DEBUG - 1/5 [40.00%]: Factory 9fb5bd99-8a77-455c-a292-13a61f3d1277: money=-2.0, storage={}, loans=0.0 2019-02-27 11:33:48,145 - DEBUG - 1/5 [40.00%]: Factory 6444729f-608f-470a-924f-06aa20c714c4: money=-2.0, storage={}, loans=0.0 2019-02-27 11:33:48,145 - DEBUG - 1/5 [40.00%]: Factory a55763d3-8c50-4b3a-baef-01f9098fbe92: money=-1.5, storage={}, loans=0.0 2019-02-27 11:33:48,145 - DEBUG - 1/5 [40.00%]: Factory a8759689-b82f-46c9-9316-c8184a6eb865: money=2.0, storage={0: -4}, loans=0.0 2019-02-27 11:33:48,145 - DEBUG - 1/5 [40.00%]: Factory 56cc3bd8-8f94-4f34-aad8-9e7c25c2a662: money=0.0, storage={}, loans=0.0 2019-02-27 11:33:48,145 - DEBUG - 1/5 [40.00%]: Factory bef7fbff-b1d6-41dc-91d1-b2f6e58392a2: money=2.0, storage={0: -4}, loans=0.0 2019-02-27 11:33:48,145 - DEBUG - 1/5 [40.00%]: Factory 7fb015ca-deb5-4a63-8735-0c2ad68edd7d: money=1.5, storage={0: -3}, loans=0.0 2019-02-27 11:33:48,145 - DEBUG - 1/5 [40.00%]: Factory 6a59c2fb-0af9-445c-8278-8278d53edb14: money=4.0, storage={0: -8}, loans=0.0 2019-02-27 11:33:48,145 - INFO - 2/5 [60.00%]: 25 Negotiations/4 _entities 2019-02-27 11:33:48,354 - DEBUG - 2/5 [60.00%]: Contract [signed]: ['c_2', 'm_2'] > {'time': 3, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_2-9d36542d-3adc-45c3-a83d-bf3254872e52: buy 0 (t: 3, u: (0, 2.0), q: (1, 4))', 'partners': "['c_2-9d36542d-3adc-45c3-a83d-bf3254872e52', 'm_2-3e017d97-5d6b-4404-acec-89b56f648c32']", 'seller': 'm_2-3e017d97-5d6b-4404-acec-89b56f648c32', 'buyer': 'c_2-9d36542d-3adc-45c3-a83d-bf3254872e52'} 2019-02-27 11:33:48,354 - DEBUG - 2/5 [60.00%]: Contract [cancelled]: ['c_2', 'm_0'] > {'time': 3, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_2-9d36542d-3adc-45c3-a83d-bf3254872e52: buy 0 (t: 3, u: (0, 2.0), q: (1, 4))', 'partners': "['c_2-9d36542d-3adc-45c3-a83d-bf3254872e52', 'm_0-b2b74473-ea51-4163-bfd8-8a73d4d95a46']", 'seller': 'm_0-b2b74473-ea51-4163-bfd8-8a73d4d95a46', 'buyer': 'c_2-9d36542d-3adc-45c3-a83d-bf3254872e52'} 2019-02-27 11:33:48,354 - DEBUG - 2/5 [60.00%]: Contract [signed]: ['c_4', 'm_2'] > {'time': 3, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_4-58a433ab-e5bb-4c9f-9bbc-29117626f303: buy 0 (t: 3, u: (0, 2.0), q: (1, 3))', 'partners': "['c_4-58a433ab-e5bb-4c9f-9bbc-29117626f303', 'm_2-3e017d97-5d6b-4404-acec-89b56f648c32']", 'seller': 'm_2-3e017d97-5d6b-4404-acec-89b56f648c32', 'buyer': 'c_4-58a433ab-e5bb-4c9f-9bbc-29117626f303'} 2019-02-27 11:33:48,355 - DEBUG - 2/5 [60.00%]: Contract [cancelled]: ['c_2', 'm_3'] > {'time': 3, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_2-9d36542d-3adc-45c3-a83d-bf3254872e52: buy 0 (t: 3, u: (0, 2.0), q: (1, 4))', 'partners': "['c_2-9d36542d-3adc-45c3-a83d-bf3254872e52', 'm_3-552642da-2001-4c04-b664-9c84d03bb7f8']", 'seller': 'm_3-552642da-2001-4c04-b664-9c84d03bb7f8', 'buyer': 'c_2-9d36542d-3adc-45c3-a83d-bf3254872e52'} 2019-02-27 11:33:48,355 - DEBUG - 2/5 [60.00%]: Contract [signed]: ['c_1', 'm_2'] > {'time': 3, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_1-33983822-6cfc-4241-a062-02dde1227de6: buy 0 (t: 3, u: (0, 2.0), q: (1, 3))', 'partners': "['c_1-33983822-6cfc-4241-a062-02dde1227de6', 'm_2-3e017d97-5d6b-4404-acec-89b56f648c32']", 'seller': 'm_2-3e017d97-5d6b-4404-acec-89b56f648c32', 'buyer': 'c_1-33983822-6cfc-4241-a062-02dde1227de6'} 2019-02-27 11:33:48,355 - DEBUG - 2/5 [60.00%]: Contract [signed]: ['c_0', 'm_1'] > {'time': 3, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_0-26d2ab4a-d500-4d36-af88-647bcb3b39b4: buy 0 (t: 3, u: (0, 2.0), q: (1, 3))', 'partners': "['c_0-26d2ab4a-d500-4d36-af88-647bcb3b39b4', 'm_1-330bf13e-d489-4e44-883c-f0a910d8fd0a']", 'seller': 'm_1-330bf13e-d489-4e44-883c-f0a910d8fd0a', 'buyer': 'c_0-26d2ab4a-d500-4d36-af88-647bcb3b39b4'} 2019-02-27 11:33:48,356 - DEBUG - 2/5 [60.00%]: Contract [signed]: ['c_3', 'm_3'] > {'time': 3, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_3-2ad64379-0773-4b5b-9536-5bc7a9ef116d: buy 0 (t: 3, u: (0, 2.0), q: (1, 3))', 'partners': "['c_3-2ad64379-0773-4b5b-9536-5bc7a9ef116d', 'm_3-552642da-2001-4c04-b664-9c84d03bb7f8']", 'seller': 'm_3-552642da-2001-4c04-b664-9c84d03bb7f8', 'buyer': 'c_3-2ad64379-0773-4b5b-9536-5bc7a9ef116d'} 2019-02-27 11:33:48,356 - DEBUG - 2/5 [60.00%]: Contract [cancelled]: ['c_1', 'm_3'] > {'time': 3, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_1-33983822-6cfc-4241-a062-02dde1227de6: buy 0 (t: 3, u: (0, 2.0), q: (1, 3))', 'partners': "['c_1-33983822-6cfc-4241-a062-02dde1227de6', 'm_3-552642da-2001-4c04-b664-9c84d03bb7f8']", 'seller': 'm_3-552642da-2001-4c04-b664-9c84d03bb7f8', 'buyer': 'c_1-33983822-6cfc-4241-a062-02dde1227de6'} 2019-02-27 11:33:48,356 - DEBUG - 2/5 [60.00%]: Contract [cancelled]: ['c_4', 'm_3'] > {'time': 3, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_4-58a433ab-e5bb-4c9f-9bbc-29117626f303: buy 0 (t: 3, u: (0, 2.0), q: (1, 3))', 'partners': "['c_4-58a433ab-e5bb-4c9f-9bbc-29117626f303', 'm_3-552642da-2001-4c04-b664-9c84d03bb7f8']", 'seller': 'm_3-552642da-2001-4c04-b664-9c84d03bb7f8', 'buyer': 'c_4-58a433ab-e5bb-4c9f-9bbc-29117626f303'} 2019-02-27 11:33:48,357 - DEBUG - 2/5 [60.00%]: Contract [cancelled]: ['c_0', 'm_0'] > {'time': 3, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_0-26d2ab4a-d500-4d36-af88-647bcb3b39b4: buy 0 (t: 3, u: (0, 2.0), q: (1, 3))', 'partners': "['c_0-26d2ab4a-d500-4d36-af88-647bcb3b39b4', 'm_0-b2b74473-ea51-4163-bfd8-8a73d4d95a46']", 'seller': 'm_0-b2b74473-ea51-4163-bfd8-8a73d4d95a46', 'buyer': 'c_0-26d2ab4a-d500-4d36-af88-647bcb3b39b4'} 2019-02-27 11:33:48,357 - DEBUG - 2/5 [60.00%]: Contract [cancelled]: ['c_3', 'm_0'] > {'time': 3, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_3-2ad64379-0773-4b5b-9536-5bc7a9ef116d: buy 0 (t: 3, u: (0, 2.0), q: (1, 3))', 'partners': "['c_3-2ad64379-0773-4b5b-9536-5bc7a9ef116d', 'm_0-b2b74473-ea51-4163-bfd8-8a73d4d95a46']", 'seller': 'm_0-b2b74473-ea51-4163-bfd8-8a73d4d95a46', 'buyer': 'c_3-2ad64379-0773-4b5b-9536-5bc7a9ef116d'} 2019-02-27 11:33:48,357 - DEBUG - 2/5 [60.00%]: Contract [cancelled]: ['c_4', 'm_4'] > {'time': 3, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_4-58a433ab-e5bb-4c9f-9bbc-29117626f303: buy 0 (t: 3, u: (0, 2.0), q: (1, 3))', 'partners': "['c_4-58a433ab-e5bb-4c9f-9bbc-29117626f303', 'm_4-f942a03d-e2a1-46a3-8c5a-0f0aab311383']", 'seller': 'm_4-f942a03d-e2a1-46a3-8c5a-0f0aab311383', 'buyer': 'c_4-58a433ab-e5bb-4c9f-9bbc-29117626f303'} 2019-02-27 11:33:48,358 - DEBUG - 2/5 [60.00%]: Contract [cancelled]: ['c_4', 'm_1'] > {'time': 3, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_4-58a433ab-e5bb-4c9f-9bbc-29117626f303: buy 0 (t: 3, u: (0, 2.0), q: (1, 3))', 'partners': "['c_4-58a433ab-e5bb-4c9f-9bbc-29117626f303', 'm_1-330bf13e-d489-4e44-883c-f0a910d8fd0a']", 'seller': 'm_1-330bf13e-d489-4e44-883c-f0a910d8fd0a', 'buyer': 'c_4-58a433ab-e5bb-4c9f-9bbc-29117626f303'} 2019-02-27 11:33:48,358 - DEBUG - 2/5 [60.00%]: Contract [cancelled]: ['c_2', 'm_4'] > {'time': 3, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_2-9d36542d-3adc-45c3-a83d-bf3254872e52: buy 0 (t: 3, u: (0, 2.0), q: (1, 4))', 'partners': "['c_2-9d36542d-3adc-45c3-a83d-bf3254872e52', 'm_4-f942a03d-e2a1-46a3-8c5a-0f0aab311383']", 'seller': 'm_4-f942a03d-e2a1-46a3-8c5a-0f0aab311383', 'buyer': 'c_2-9d36542d-3adc-45c3-a83d-bf3254872e52'} 2019-02-27 11:33:48,358 - DEBUG - 2/5 [60.00%]: Contract [cancelled]: ['c_0', 'm_2'] > {'time': 3, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_0-26d2ab4a-d500-4d36-af88-647bcb3b39b4: buy 0 (t: 3, u: (0, 2.0), q: (1, 3))', 'partners': "['c_0-26d2ab4a-d500-4d36-af88-647bcb3b39b4', 'm_2-3e017d97-5d6b-4404-acec-89b56f648c32']", 'seller': 'm_2-3e017d97-5d6b-4404-acec-89b56f648c32', 'buyer': 'c_0-26d2ab4a-d500-4d36-af88-647bcb3b39b4'} 2019-02-27 11:33:48,359 - DEBUG - 2/5 [60.00%]: Contract [cancelled]: ['c_1', 'm_4'] > {'time': 3, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_1-33983822-6cfc-4241-a062-02dde1227de6: buy 0 (t: 3, u: (0, 2.0), q: (1, 3))', 'partners': "['c_1-33983822-6cfc-4241-a062-02dde1227de6', 'm_4-f942a03d-e2a1-46a3-8c5a-0f0aab311383']", 'seller': 'm_4-f942a03d-e2a1-46a3-8c5a-0f0aab311383', 'buyer': 'c_1-33983822-6cfc-4241-a062-02dde1227de6'} 2019-02-27 11:33:48,359 - DEBUG - 2/5 [60.00%]: Contract [cancelled]: ['c_0', 'm_4'] > {'time': 3, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_0-26d2ab4a-d500-4d36-af88-647bcb3b39b4: buy 0 (t: 3, u: (0, 2.0), q: (1, 3))', 'partners': "['c_0-26d2ab4a-d500-4d36-af88-647bcb3b39b4', 'm_4-f942a03d-e2a1-46a3-8c5a-0f0aab311383']", 'seller': 'm_4-f942a03d-e2a1-46a3-8c5a-0f0aab311383', 'buyer': 'c_0-26d2ab4a-d500-4d36-af88-647bcb3b39b4'} 2019-02-27 11:33:48,359 - DEBUG - 2/5 [60.00%]: Contract [cancelled]: ['c_1', 'm_0'] > {'time': 3, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_1-33983822-6cfc-4241-a062-02dde1227de6: buy 0 (t: 3, u: (0, 2.0), q: (1, 3))', 'partners': "['c_1-33983822-6cfc-4241-a062-02dde1227de6', 'm_0-b2b74473-ea51-4163-bfd8-8a73d4d95a46']", 'seller': 'm_0-b2b74473-ea51-4163-bfd8-8a73d4d95a46', 'buyer': 'c_1-33983822-6cfc-4241-a062-02dde1227de6'} 2019-02-27 11:33:48,360 - DEBUG - 2/5 [60.00%]: Contract [cancelled]: ['c_3', 'm_2'] > {'time': 3, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_3-2ad64379-0773-4b5b-9536-5bc7a9ef116d: buy 0 (t: 3, u: (0, 2.0), q: (1, 3))', 'partners': "['c_3-2ad64379-0773-4b5b-9536-5bc7a9ef116d', 'm_2-3e017d97-5d6b-4404-acec-89b56f648c32']", 'seller': 'm_2-3e017d97-5d6b-4404-acec-89b56f648c32', 'buyer': 'c_3-2ad64379-0773-4b5b-9536-5bc7a9ef116d'} 2019-02-27 11:33:48,360 - DEBUG - 2/5 [60.00%]: Contract [cancelled]: ['c_4', 'm_0'] > {'time': 3, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_4-58a433ab-e5bb-4c9f-9bbc-29117626f303: buy 0 (t: 3, u: (0, 2.0), q: (1, 3))', 'partners': "['c_4-58a433ab-e5bb-4c9f-9bbc-29117626f303', 'm_0-b2b74473-ea51-4163-bfd8-8a73d4d95a46']", 'seller': 'm_0-b2b74473-ea51-4163-bfd8-8a73d4d95a46', 'buyer': 'c_4-58a433ab-e5bb-4c9f-9bbc-29117626f303'} 2019-02-27 11:33:48,360 - DEBUG - 2/5 [60.00%]: Contract [cancelled]: ['c_1', 'm_1'] > {'time': 3, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_1-33983822-6cfc-4241-a062-02dde1227de6: buy 0 (t: 3, u: (0, 2.0), q: (1, 3))', 'partners': "['c_1-33983822-6cfc-4241-a062-02dde1227de6', 'm_1-330bf13e-d489-4e44-883c-f0a910d8fd0a']", 'seller': 'm_1-330bf13e-d489-4e44-883c-f0a910d8fd0a', 'buyer': 'c_1-33983822-6cfc-4241-a062-02dde1227de6'} 2019-02-27 11:33:48,361 - DEBUG - 2/5 [60.00%]: Contract [cancelled]: ['c_3', 'm_1'] > {'time': 3, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_3-2ad64379-0773-4b5b-9536-5bc7a9ef116d: buy 0 (t: 3, u: (0, 2.0), q: (1, 3))', 'partners': "['c_3-2ad64379-0773-4b5b-9536-5bc7a9ef116d', 'm_1-330bf13e-d489-4e44-883c-f0a910d8fd0a']", 'seller': 'm_1-330bf13e-d489-4e44-883c-f0a910d8fd0a', 'buyer': 'c_3-2ad64379-0773-4b5b-9536-5bc7a9ef116d'} 2019-02-27 11:33:48,361 - DEBUG - 2/5 [60.00%]: Contract [cancelled]: ['c_3', 'm_4'] > {'time': 3, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_3-2ad64379-0773-4b5b-9536-5bc7a9ef116d: buy 0 (t: 3, u: (0, 2.0), q: (1, 3))', 'partners': "['c_3-2ad64379-0773-4b5b-9536-5bc7a9ef116d', 'm_4-f942a03d-e2a1-46a3-8c5a-0f0aab311383']", 'seller': 'm_4-f942a03d-e2a1-46a3-8c5a-0f0aab311383', 'buyer': 'c_3-2ad64379-0773-4b5b-9536-5bc7a9ef116d'} 2019-02-27 11:33:48,361 - DEBUG - 2/5 [60.00%]: Contract [cancelled]: ['c_0', 'm_3'] > {'time': 3, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_0-26d2ab4a-d500-4d36-af88-647bcb3b39b4: buy 0 (t: 3, u: (0, 2.0), q: (1, 3))', 'partners': "['c_0-26d2ab4a-d500-4d36-af88-647bcb3b39b4', 'm_3-552642da-2001-4c04-b664-9c84d03bb7f8']", 'seller': 'm_3-552642da-2001-4c04-b664-9c84d03bb7f8', 'buyer': 'c_0-26d2ab4a-d500-4d36-af88-647bcb3b39b4'} 2019-02-27 11:33:48,362 - DEBUG - 2/5 [60.00%]: Contract [cancelled]: ['c_2', 'm_1'] > {'time': 3, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_2-9d36542d-3adc-45c3-a83d-bf3254872e52: buy 0 (t: 3, u: (0, 2.0), q: (1, 4))', 'partners': "['c_2-9d36542d-3adc-45c3-a83d-bf3254872e52', 'm_1-330bf13e-d489-4e44-883c-f0a910d8fd0a']", 'seller': 'm_1-330bf13e-d489-4e44-883c-f0a910d8fd0a', 'buyer': 'c_2-9d36542d-3adc-45c3-a83d-bf3254872e52'} 2019-02-27 11:33:48,362 - INFO - 2/5 [60.00%]: m_0 requested negmas.sao.SAOMechanism[None] with ['c_0', 'm_0'] (ID 7cba2cff-dfc6-473b-b468-88bc921e75d7) 2019-02-27 11:33:48,363 - INFO - 2/5 [60.00%]: m_0-b2b74473-ea51-4163-bfd8-8a73d4d95a46 request was accepted 2019-02-27 11:33:48,364 - INFO - 2/5 [60.00%]: m_1 requested negmas.sao.SAOMechanism[None] with ['c_0', 'm_1'] (ID 074fef8a-75fe-4bd3-9251-b8159d0623ee) 2019-02-27 11:33:48,364 - INFO - 2/5 [60.00%]: m_1-330bf13e-d489-4e44-883c-f0a910d8fd0a request was accepted 2019-02-27 11:33:48,366 - INFO - 2/5 [60.00%]: m_2 requested negmas.sao.SAOMechanism[None] with ['c_0', 'm_2'] (ID 61d3d6f5-108d-440a-b5a3-50318fb5fc55) 2019-02-27 11:33:48,366 - INFO - 2/5 [60.00%]: m_2-3e017d97-5d6b-4404-acec-89b56f648c32 request was accepted 2019-02-27 11:33:48,367 - INFO - 2/5 [60.00%]: m_3 requested negmas.sao.SAOMechanism[None] with ['c_0', 'm_3'] (ID 6c909600-64ca-4e5d-aebb-c13e1e0f60b6) 2019-02-27 11:33:48,368 - INFO - 2/5 [60.00%]: m_3-552642da-2001-4c04-b664-9c84d03bb7f8 request was accepted 2019-02-27 11:33:48,368 - INFO - 2/5 [60.00%]: m_4 requested negmas.sao.SAOMechanism[None] with ['c_0', 'm_4'] (ID 7b48f581-6723-4e9d-90dc-c7dbd25d6420) 2019-02-27 11:33:48,369 - INFO - 2/5 [60.00%]: m_4-f942a03d-e2a1-46a3-8c5a-0f0aab311383 request was accepted 2019-02-27 11:33:48,370 - INFO - 2/5 [60.00%]: m_0 requested negmas.sao.SAOMechanism[None] with ['c_1', 'm_0'] (ID cc60fcf2-49d7-4a96-8722-c842757909a5) 2019-02-27 11:33:48,371 - INFO - 2/5 [60.00%]: m_0-b2b74473-ea51-4163-bfd8-8a73d4d95a46 request was accepted 2019-02-27 11:33:48,371 - INFO - 2/5 [60.00%]: m_1 requested negmas.sao.SAOMechanism[None] with ['c_1', 'm_1'] (ID e037fe11-dc66-4009-8fe9-12391f24503a) 2019-02-27 11:33:48,372 - INFO - 2/5 [60.00%]: m_1-330bf13e-d489-4e44-883c-f0a910d8fd0a request was accepted 2019-02-27 11:33:48,373 - INFO - 2/5 [60.00%]: m_2 requested negmas.sao.SAOMechanism[None] with ['c_1', 'm_2'] (ID ce724de6-28e8-4e05-8f75-e3c8e56866d7) 2019-02-27 11:33:48,373 - INFO - 2/5 [60.00%]: m_2-3e017d97-5d6b-4404-acec-89b56f648c32 request was accepted 2019-02-27 11:33:48,374 - INFO - 2/5 [60.00%]: m_3 requested negmas.sao.SAOMechanism[None] with ['c_1', 'm_3'] (ID 2f414e9b-a467-46bc-bf98-55e347563386) 2019-02-27 11:33:48,375 - INFO - 2/5 [60.00%]: m_3-552642da-2001-4c04-b664-9c84d03bb7f8 request was accepted 2019-02-27 11:33:48,376 - INFO - 2/5 [60.00%]: m_4 requested negmas.sao.SAOMechanism[None] with ['c_1', 'm_4'] (ID 19e9c278-3ae3-41a2-82bb-b013d76aceb8) 2019-02-27 11:33:48,376 - INFO - 2/5 [60.00%]: m_4-f942a03d-e2a1-46a3-8c5a-0f0aab311383 request was accepted 2019-02-27 11:33:48,378 - INFO - 2/5 [60.00%]: m_0 requested negmas.sao.SAOMechanism[None] with ['c_2', 'm_0'] (ID 329f8009-0e71-4e8c-98a8-c0173156afe9) 2019-02-27 11:33:48,378 - INFO - 2/5 [60.00%]: m_0-b2b74473-ea51-4163-bfd8-8a73d4d95a46 request was accepted 2019-02-27 11:33:48,379 - INFO - 2/5 [60.00%]: m_1 requested negmas.sao.SAOMechanism[None] with ['c_2', 'm_1'] (ID 5f2846b2-6327-4ed0-a9cf-445ded49516a) 2019-02-27 11:33:48,380 - INFO - 2/5 [60.00%]: m_1-330bf13e-d489-4e44-883c-f0a910d8fd0a request was accepted 2019-02-27 11:33:48,383 - INFO - 2/5 [60.00%]: m_2 requested negmas.sao.SAOMechanism[None] with ['c_2', 'm_2'] (ID 0bae84ad-9a5a-4bfa-a864-c754e7854d63) 2019-02-27 11:33:48,383 - INFO - 2/5 [60.00%]: m_2-3e017d97-5d6b-4404-acec-89b56f648c32 request was accepted 2019-02-27 11:33:48,384 - INFO - 2/5 [60.00%]: m_3 requested negmas.sao.SAOMechanism[None] with ['c_2', 'm_3'] (ID e94f514d-cd44-4308-a970-f9e5e1b3f292) 2019-02-27 11:33:48,385 - INFO - 2/5 [60.00%]: m_3-552642da-2001-4c04-b664-9c84d03bb7f8 request was accepted 2019-02-27 11:33:48,386 - INFO - 2/5 [60.00%]: m_4 requested negmas.sao.SAOMechanism[None] with ['c_2', 'm_4'] (ID 69736a7c-3c9b-4289-a82a-4b988d150561) 2019-02-27 11:33:48,387 - INFO - 2/5 [60.00%]: m_4-f942a03d-e2a1-46a3-8c5a-0f0aab311383 request was accepted 2019-02-27 11:33:48,388 - INFO - 2/5 [60.00%]: m_0 requested negmas.sao.SAOMechanism[None] with ['c_3', 'm_0'] (ID 9d161356-8135-4158-8a26-484762033e59) 2019-02-27 11:33:48,389 - INFO - 2/5 [60.00%]: m_0-b2b74473-ea51-4163-bfd8-8a73d4d95a46 request was accepted 2019-02-27 11:33:48,390 - INFO - 2/5 [60.00%]: m_1 requested negmas.sao.SAOMechanism[None] with ['c_3', 'm_1'] (ID a080c1f4-dbf5-4d59-8bc2-35334510dae9) 2019-02-27 11:33:48,391 - INFO - 2/5 [60.00%]: m_1-330bf13e-d489-4e44-883c-f0a910d8fd0a request was accepted 2019-02-27 11:33:48,392 - INFO - 2/5 [60.00%]: m_2 requested negmas.sao.SAOMechanism[None] with ['c_3', 'm_2'] (ID 240cdfbb-69ce-4515-93dd-72f690280913) 2019-02-27 11:33:48,392 - INFO - 2/5 [60.00%]: m_2-3e017d97-5d6b-4404-acec-89b56f648c32 request was accepted 2019-02-27 11:33:48,393 - INFO - 2/5 [60.00%]: m_3 requested negmas.sao.SAOMechanism[None] with ['c_3', 'm_3'] (ID 09d70884-8de2-4a6b-a0d2-debae3ca2666) 2019-02-27 11:33:48,394 - INFO - 2/5 [60.00%]: m_3-552642da-2001-4c04-b664-9c84d03bb7f8 request was accepted 2019-02-27 11:33:48,395 - INFO - 2/5 [60.00%]: m_4 requested negmas.sao.SAOMechanism[None] with ['c_3', 'm_4'] (ID aa75669e-0e31-415b-b5a5-93af61db760e) 2019-02-27 11:33:48,396 - INFO - 2/5 [60.00%]: m_4-f942a03d-e2a1-46a3-8c5a-0f0aab311383 request was accepted 2019-02-27 11:33:48,397 - INFO - 2/5 [60.00%]: m_0 requested negmas.sao.SAOMechanism[None] with ['c_4', 'm_0'] (ID 3f99a53f-77d9-4b80-bee3-3a775531c6f9) 2019-02-27 11:33:48,397 - INFO - 2/5 [60.00%]: m_0-b2b74473-ea51-4163-bfd8-8a73d4d95a46 request was accepted 2019-02-27 11:33:48,398 - INFO - 2/5 [60.00%]: m_1 requested negmas.sao.SAOMechanism[None] with ['c_4', 'm_1'] (ID c8f42d20-235a-4497-96e7-9bd66c8c8edf) 2019-02-27 11:33:48,399 - INFO - 2/5 [60.00%]: m_1-330bf13e-d489-4e44-883c-f0a910d8fd0a request was accepted 2019-02-27 11:33:48,400 - INFO - 2/5 [60.00%]: m_2 requested negmas.sao.SAOMechanism[None] with ['c_4', 'm_2'] (ID ee78f522-ecf7-4f1b-9417-1877578c5535) 2019-02-27 11:33:48,400 - INFO - 2/5 [60.00%]: m_2-3e017d97-5d6b-4404-acec-89b56f648c32 request was accepted 2019-02-27 11:33:48,401 - INFO - 2/5 [60.00%]: m_3 requested negmas.sao.SAOMechanism[None] with ['c_4', 'm_3'] (ID 44220581-0567-428c-87b2-04ad2675c2ef) 2019-02-27 11:33:48,402 - INFO - 2/5 [60.00%]: m_3-552642da-2001-4c04-b664-9c84d03bb7f8 request was accepted 2019-02-27 11:33:48,403 - INFO - 2/5 [60.00%]: m_4 requested negmas.sao.SAOMechanism[None] with ['c_4', 'm_4'] (ID 31cfa134-7e9f-4191-a441-ef80b5ce8208) 2019-02-27 11:33:48,403 - INFO - 2/5 [60.00%]: m_4-f942a03d-e2a1-46a3-8c5a-0f0aab311383 request was accepted 2019-02-27 11:33:48,403 - INFO - 2/5 [60.00%]: Executing c_0-26d2ab4a-d500-4d36-af88-647bcb3b39b4, m_0-b2b74473-ea51-4163-bfd8-8a73d4d95a46 agreed on {'time': 2, 'quantity': 3, 'unit_price': 0.5} 2019-02-27 11:33:48,403 - DEBUG - 2/5 [60.00%]: Moved 3 units of p0 from m_0 to c_0 for 1.5 dollars 2019-02-27 11:33:48,404 - INFO - 2/5 [60.00%]: Executing c_4-58a433ab-e5bb-4c9f-9bbc-29117626f303, m_4-f942a03d-e2a1-46a3-8c5a-0f0aab311383 agreed on {'time': 2, 'quantity': 4, 'unit_price': 0.5} 2019-02-27 11:33:48,404 - DEBUG - 2/5 [60.00%]: Moved 4 units of p0 from m_4 to c_4 for 2.0 dollars 2019-02-27 11:33:48,404 - INFO - 2/5 [60.00%]: Executing c_2-9d36542d-3adc-45c3-a83d-bf3254872e52, m_3-552642da-2001-4c04-b664-9c84d03bb7f8 agreed on {'time': 2, 'quantity': 4, 'unit_price': 0.5} 2019-02-27 11:33:48,404 - DEBUG - 2/5 [60.00%]: Moved 4 units of p0 from m_3 to c_2 for 2.0 dollars 2019-02-27 11:33:48,404 - INFO - 2/5 [60.00%]: Executing c_3-2ad64379-0773-4b5b-9536-5bc7a9ef116d, m_2-3e017d97-5d6b-4404-acec-89b56f648c32 agreed on {'time': 2, 'quantity': 3, 'unit_price': 0.5} 2019-02-27 11:33:48,404 - DEBUG - 2/5 [60.00%]: Moved 3 units of p0 from m_2 to c_3 for 1.5 dollars 2019-02-27 11:33:48,404 - INFO - 2/5 [60.00%]: Executing c_1-33983822-6cfc-4241-a062-02dde1227de6, m_1-330bf13e-d489-4e44-883c-f0a910d8fd0a agreed on {'time': 2, 'quantity': 3, 'unit_price': 0.5} 2019-02-27 11:33:48,404 - DEBUG - 2/5 [60.00%]: Moved 3 units of p0 from m_1 to c_1 for 1.5 dollars 2019-02-27 11:33:48,404 - DEBUG - 2/5 [60.00%]: Factory 3972f90f-1ef1-4320-b2ed-b7cc1e3fe76a: money=-3.5, storage={}, loans=0.0 2019-02-27 11:33:48,404 - DEBUG - 2/5 [60.00%]: Factory 9c12276a-e377-43ff-9942-ebebbaca5f0f: money=-3.5, storage={}, loans=0.0 2019-02-27 11:33:48,404 - DEBUG - 2/5 [60.00%]: Factory 9fb5bd99-8a77-455c-a292-13a61f3d1277: money=-4.0, storage={}, loans=0.0 2019-02-27 11:33:48,404 - DEBUG - 2/5 [60.00%]: Factory 6444729f-608f-470a-924f-06aa20c714c4: money=-3.5, storage={}, loans=0.0 2019-02-27 11:33:48,404 - DEBUG - 2/5 [60.00%]: Factory a55763d3-8c50-4b3a-baef-01f9098fbe92: money=-3.5, storage={}, loans=0.0 2019-02-27 11:33:48,405 - DEBUG - 2/5 [60.00%]: Factory a8759689-b82f-46c9-9316-c8184a6eb865: money=3.5, storage={0: -7}, loans=0.0 2019-02-27 11:33:48,405 - DEBUG - 2/5 [60.00%]: Factory 56cc3bd8-8f94-4f34-aad8-9e7c25c2a662: money=1.5, storage={0: -3}, loans=0.0 2019-02-27 11:33:48,405 - DEBUG - 2/5 [60.00%]: Factory bef7fbff-b1d6-41dc-91d1-b2f6e58392a2: money=3.5, storage={0: -7}, loans=0.0 2019-02-27 11:33:48,405 - DEBUG - 2/5 [60.00%]: Factory 7fb015ca-deb5-4a63-8735-0c2ad68edd7d: money=3.5, storage={0: -7}, loans=0.0 2019-02-27 11:33:48,405 - DEBUG - 2/5 [60.00%]: Factory 6a59c2fb-0af9-445c-8278-8278d53edb14: money=6.0, storage={0: -12}, loans=0.0 2019-02-27 11:33:48,405 - INFO - 3/5 [80.00%]: 25 Negotiations/4 _entities 2019-02-27 11:33:48,612 - DEBUG - 3/5 [80.00%]: Contract [cancelled]: ['c_0', 'm_0'] > {'time': 4, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_0-26d2ab4a-d500-4d36-af88-647bcb3b39b4: buy 0 (t: 4, u: (0, 2.0), q: (1, 3))', 'partners': "['c_0-26d2ab4a-d500-4d36-af88-647bcb3b39b4', 'm_0-b2b74473-ea51-4163-bfd8-8a73d4d95a46']", 'seller': 'm_0-b2b74473-ea51-4163-bfd8-8a73d4d95a46', 'buyer': 'c_0-26d2ab4a-d500-4d36-af88-647bcb3b39b4'} 2019-02-27 11:33:48,612 - DEBUG - 3/5 [80.00%]: Contract [cancelled]: ['c_4', 'm_3'] > {'time': 4, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_4-58a433ab-e5bb-4c9f-9bbc-29117626f303: buy 0 (t: 4, u: (0, 2.0), q: (1, 3))', 'partners': "['c_4-58a433ab-e5bb-4c9f-9bbc-29117626f303', 'm_3-552642da-2001-4c04-b664-9c84d03bb7f8']", 'seller': 'm_3-552642da-2001-4c04-b664-9c84d03bb7f8', 'buyer': 'c_4-58a433ab-e5bb-4c9f-9bbc-29117626f303'} 2019-02-27 11:33:48,612 - DEBUG - 3/5 [80.00%]: Contract [cancelled]: ['c_3', 'm_2'] > {'time': 4, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_3-2ad64379-0773-4b5b-9536-5bc7a9ef116d: buy 0 (t: 4, u: (0, 2.0), q: (1, 4))', 'partners': "['c_3-2ad64379-0773-4b5b-9536-5bc7a9ef116d', 'm_2-3e017d97-5d6b-4404-acec-89b56f648c32']", 'seller': 'm_2-3e017d97-5d6b-4404-acec-89b56f648c32', 'buyer': 'c_3-2ad64379-0773-4b5b-9536-5bc7a9ef116d'} 2019-02-27 11:33:48,613 - DEBUG - 3/5 [80.00%]: Contract [cancelled]: ['c_4', 'm_4'] > {'time': 4, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_4-58a433ab-e5bb-4c9f-9bbc-29117626f303: buy 0 (t: 4, u: (0, 2.0), q: (1, 3))', 'partners': "['c_4-58a433ab-e5bb-4c9f-9bbc-29117626f303', 'm_4-f942a03d-e2a1-46a3-8c5a-0f0aab311383']", 'seller': 'm_4-f942a03d-e2a1-46a3-8c5a-0f0aab311383', 'buyer': 'c_4-58a433ab-e5bb-4c9f-9bbc-29117626f303'} 2019-02-27 11:33:48,613 - DEBUG - 3/5 [80.00%]: Contract [cancelled]: ['c_4', 'm_1'] > {'time': 4, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_4-58a433ab-e5bb-4c9f-9bbc-29117626f303: buy 0 (t: 4, u: (0, 2.0), q: (1, 3))', 'partners': "['c_4-58a433ab-e5bb-4c9f-9bbc-29117626f303', 'm_1-330bf13e-d489-4e44-883c-f0a910d8fd0a']", 'seller': 'm_1-330bf13e-d489-4e44-883c-f0a910d8fd0a', 'buyer': 'c_4-58a433ab-e5bb-4c9f-9bbc-29117626f303'} 2019-02-27 11:33:48,613 - DEBUG - 3/5 [80.00%]: Contract [cancelled]: ['c_4', 'm_2'] > {'time': 4, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_4-58a433ab-e5bb-4c9f-9bbc-29117626f303: buy 0 (t: 4, u: (0, 2.0), q: (1, 3))', 'partners': "['c_4-58a433ab-e5bb-4c9f-9bbc-29117626f303', 'm_2-3e017d97-5d6b-4404-acec-89b56f648c32']", 'seller': 'm_2-3e017d97-5d6b-4404-acec-89b56f648c32', 'buyer': 'c_4-58a433ab-e5bb-4c9f-9bbc-29117626f303'} 2019-02-27 11:33:48,614 - DEBUG - 3/5 [80.00%]: Contract [cancelled]: ['c_3', 'm_3'] > {'time': 4, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_3-2ad64379-0773-4b5b-9536-5bc7a9ef116d: buy 0 (t: 4, u: (0, 2.0), q: (1, 4))', 'partners': "['c_3-2ad64379-0773-4b5b-9536-5bc7a9ef116d', 'm_3-552642da-2001-4c04-b664-9c84d03bb7f8']", 'seller': 'm_3-552642da-2001-4c04-b664-9c84d03bb7f8', 'buyer': 'c_3-2ad64379-0773-4b5b-9536-5bc7a9ef116d'} 2019-02-27 11:33:48,614 - DEBUG - 3/5 [80.00%]: Contract [cancelled]: ['c_1', 'm_4'] > {'time': 4, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_1-33983822-6cfc-4241-a062-02dde1227de6: buy 0 (t: 4, u: (0, 2.0), q: (1, 3))', 'partners': "['c_1-33983822-6cfc-4241-a062-02dde1227de6', 'm_4-f942a03d-e2a1-46a3-8c5a-0f0aab311383']", 'seller': 'm_4-f942a03d-e2a1-46a3-8c5a-0f0aab311383', 'buyer': 'c_1-33983822-6cfc-4241-a062-02dde1227de6'} 2019-02-27 11:33:48,614 - DEBUG - 3/5 [80.00%]: Contract [cancelled]: ['c_3', 'm_4'] > {'time': 4, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_3-2ad64379-0773-4b5b-9536-5bc7a9ef116d: buy 0 (t: 4, u: (0, 2.0), q: (1, 4))', 'partners': "['c_3-2ad64379-0773-4b5b-9536-5bc7a9ef116d', 'm_4-f942a03d-e2a1-46a3-8c5a-0f0aab311383']", 'seller': 'm_4-f942a03d-e2a1-46a3-8c5a-0f0aab311383', 'buyer': 'c_3-2ad64379-0773-4b5b-9536-5bc7a9ef116d'} 2019-02-27 11:33:48,614 - DEBUG - 3/5 [80.00%]: Contract [cancelled]: ['c_2', 'm_2'] > {'time': 4, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_2-9d36542d-3adc-45c3-a83d-bf3254872e52: buy 0 (t: 4, u: (0, 2.0), q: (1, 4))', 'partners': "['c_2-9d36542d-3adc-45c3-a83d-bf3254872e52', 'm_2-3e017d97-5d6b-4404-acec-89b56f648c32']", 'seller': 'm_2-3e017d97-5d6b-4404-acec-89b56f648c32', 'buyer': 'c_2-9d36542d-3adc-45c3-a83d-bf3254872e52'} 2019-02-27 11:33:48,615 - DEBUG - 3/5 [80.00%]: Contract [cancelled]: ['c_1', 'm_3'] > {'time': 4, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_1-33983822-6cfc-4241-a062-02dde1227de6: buy 0 (t: 4, u: (0, 2.0), q: (1, 3))', 'partners': "['c_1-33983822-6cfc-4241-a062-02dde1227de6', 'm_3-552642da-2001-4c04-b664-9c84d03bb7f8']", 'seller': 'm_3-552642da-2001-4c04-b664-9c84d03bb7f8', 'buyer': 'c_1-33983822-6cfc-4241-a062-02dde1227de6'} 2019-02-27 11:33:48,615 - DEBUG - 3/5 [80.00%]: Contract [cancelled]: ['c_1', 'm_1'] > {'time': 4, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_1-33983822-6cfc-4241-a062-02dde1227de6: buy 0 (t: 4, u: (0, 2.0), q: (1, 3))', 'partners': "['c_1-33983822-6cfc-4241-a062-02dde1227de6', 'm_1-330bf13e-d489-4e44-883c-f0a910d8fd0a']", 'seller': 'm_1-330bf13e-d489-4e44-883c-f0a910d8fd0a', 'buyer': 'c_1-33983822-6cfc-4241-a062-02dde1227de6'} 2019-02-27 11:33:48,615 - DEBUG - 3/5 [80.00%]: Contract [cancelled]: ['c_2', 'm_4'] > {'time': 4, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_2-9d36542d-3adc-45c3-a83d-bf3254872e52: buy 0 (t: 4, u: (0, 2.0), q: (1, 4))', 'partners': "['c_2-9d36542d-3adc-45c3-a83d-bf3254872e52', 'm_4-f942a03d-e2a1-46a3-8c5a-0f0aab311383']", 'seller': 'm_4-f942a03d-e2a1-46a3-8c5a-0f0aab311383', 'buyer': 'c_2-9d36542d-3adc-45c3-a83d-bf3254872e52'} 2019-02-27 11:33:48,616 - DEBUG - 3/5 [80.00%]: Contract [cancelled]: ['c_1', 'm_2'] > {'time': 4, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_1-33983822-6cfc-4241-a062-02dde1227de6: buy 0 (t: 4, u: (0, 2.0), q: (1, 3))', 'partners': "['c_1-33983822-6cfc-4241-a062-02dde1227de6', 'm_2-3e017d97-5d6b-4404-acec-89b56f648c32']", 'seller': 'm_2-3e017d97-5d6b-4404-acec-89b56f648c32', 'buyer': 'c_1-33983822-6cfc-4241-a062-02dde1227de6'} 2019-02-27 11:33:48,616 - DEBUG - 3/5 [80.00%]: Contract [cancelled]: ['c_3', 'm_1'] > {'time': 4, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_3-2ad64379-0773-4b5b-9536-5bc7a9ef116d: buy 0 (t: 4, u: (0, 2.0), q: (1, 4))', 'partners': "['c_3-2ad64379-0773-4b5b-9536-5bc7a9ef116d', 'm_1-330bf13e-d489-4e44-883c-f0a910d8fd0a']", 'seller': 'm_1-330bf13e-d489-4e44-883c-f0a910d8fd0a', 'buyer': 'c_3-2ad64379-0773-4b5b-9536-5bc7a9ef116d'} 2019-02-27 11:33:48,616 - DEBUG - 3/5 [80.00%]: Contract [cancelled]: ['c_2', 'm_0'] > {'time': 4, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_2-9d36542d-3adc-45c3-a83d-bf3254872e52: buy 0 (t: 4, u: (0, 2.0), q: (1, 4))', 'partners': "['c_2-9d36542d-3adc-45c3-a83d-bf3254872e52', 'm_0-b2b74473-ea51-4163-bfd8-8a73d4d95a46']", 'seller': 'm_0-b2b74473-ea51-4163-bfd8-8a73d4d95a46', 'buyer': 'c_2-9d36542d-3adc-45c3-a83d-bf3254872e52'} 2019-02-27 11:33:48,617 - DEBUG - 3/5 [80.00%]: Contract [cancelled]: ['c_0', 'm_1'] > {'time': 4, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_0-26d2ab4a-d500-4d36-af88-647bcb3b39b4: buy 0 (t: 4, u: (0, 2.0), q: (1, 3))', 'partners': "['c_0-26d2ab4a-d500-4d36-af88-647bcb3b39b4', 'm_1-330bf13e-d489-4e44-883c-f0a910d8fd0a']", 'seller': 'm_1-330bf13e-d489-4e44-883c-f0a910d8fd0a', 'buyer': 'c_0-26d2ab4a-d500-4d36-af88-647bcb3b39b4'} 2019-02-27 11:33:48,617 - DEBUG - 3/5 [80.00%]: Contract [cancelled]: ['c_3', 'm_0'] > {'time': 4, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_3-2ad64379-0773-4b5b-9536-5bc7a9ef116d: buy 0 (t: 4, u: (0, 2.0), q: (1, 4))', 'partners': "['c_3-2ad64379-0773-4b5b-9536-5bc7a9ef116d', 'm_0-b2b74473-ea51-4163-bfd8-8a73d4d95a46']", 'seller': 'm_0-b2b74473-ea51-4163-bfd8-8a73d4d95a46', 'buyer': 'c_3-2ad64379-0773-4b5b-9536-5bc7a9ef116d'} 2019-02-27 11:33:48,617 - DEBUG - 3/5 [80.00%]: Contract [cancelled]: ['c_0', 'm_2'] > {'time': 4, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_0-26d2ab4a-d500-4d36-af88-647bcb3b39b4: buy 0 (t: 4, u: (0, 2.0), q: (1, 3))', 'partners': "['c_0-26d2ab4a-d500-4d36-af88-647bcb3b39b4', 'm_2-3e017d97-5d6b-4404-acec-89b56f648c32']", 'seller': 'm_2-3e017d97-5d6b-4404-acec-89b56f648c32', 'buyer': 'c_0-26d2ab4a-d500-4d36-af88-647bcb3b39b4'} 2019-02-27 11:33:48,618 - DEBUG - 3/5 [80.00%]: Contract [cancelled]: ['c_0', 'm_3'] > {'time': 4, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_0-26d2ab4a-d500-4d36-af88-647bcb3b39b4: buy 0 (t: 4, u: (0, 2.0), q: (1, 3))', 'partners': "['c_0-26d2ab4a-d500-4d36-af88-647bcb3b39b4', 'm_3-552642da-2001-4c04-b664-9c84d03bb7f8']", 'seller': 'm_3-552642da-2001-4c04-b664-9c84d03bb7f8', 'buyer': 'c_0-26d2ab4a-d500-4d36-af88-647bcb3b39b4'} 2019-02-27 11:33:48,618 - DEBUG - 3/5 [80.00%]: Contract [cancelled]: ['c_1', 'm_0'] > {'time': 4, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_1-33983822-6cfc-4241-a062-02dde1227de6: buy 0 (t: 4, u: (0, 2.0), q: (1, 3))', 'partners': "['c_1-33983822-6cfc-4241-a062-02dde1227de6', 'm_0-b2b74473-ea51-4163-bfd8-8a73d4d95a46']", 'seller': 'm_0-b2b74473-ea51-4163-bfd8-8a73d4d95a46', 'buyer': 'c_1-33983822-6cfc-4241-a062-02dde1227de6'} 2019-02-27 11:33:48,618 - DEBUG - 3/5 [80.00%]: Contract [cancelled]: ['c_4', 'm_0'] > {'time': 4, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_4-58a433ab-e5bb-4c9f-9bbc-29117626f303: buy 0 (t: 4, u: (0, 2.0), q: (1, 3))', 'partners': "['c_4-58a433ab-e5bb-4c9f-9bbc-29117626f303', 'm_0-b2b74473-ea51-4163-bfd8-8a73d4d95a46']", 'seller': 'm_0-b2b74473-ea51-4163-bfd8-8a73d4d95a46', 'buyer': 'c_4-58a433ab-e5bb-4c9f-9bbc-29117626f303'} 2019-02-27 11:33:48,618 - DEBUG - 3/5 [80.00%]: Contract [cancelled]: ['c_0', 'm_4'] > {'time': 4, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_0-26d2ab4a-d500-4d36-af88-647bcb3b39b4: buy 0 (t: 4, u: (0, 2.0), q: (1, 3))', 'partners': "['c_0-26d2ab4a-d500-4d36-af88-647bcb3b39b4', 'm_4-f942a03d-e2a1-46a3-8c5a-0f0aab311383']", 'seller': 'm_4-f942a03d-e2a1-46a3-8c5a-0f0aab311383', 'buyer': 'c_0-26d2ab4a-d500-4d36-af88-647bcb3b39b4'} 2019-02-27 11:33:48,619 - DEBUG - 3/5 [80.00%]: Contract [cancelled]: ['c_2', 'm_3'] > {'time': 4, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_2-9d36542d-3adc-45c3-a83d-bf3254872e52: buy 0 (t: 4, u: (0, 2.0), q: (1, 4))', 'partners': "['c_2-9d36542d-3adc-45c3-a83d-bf3254872e52', 'm_3-552642da-2001-4c04-b664-9c84d03bb7f8']", 'seller': 'm_3-552642da-2001-4c04-b664-9c84d03bb7f8', 'buyer': 'c_2-9d36542d-3adc-45c3-a83d-bf3254872e52'} 2019-02-27 11:33:48,619 - DEBUG - 3/5 [80.00%]: Contract [cancelled]: ['c_2', 'm_1'] > {'time': 4, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_2-9d36542d-3adc-45c3-a83d-bf3254872e52: buy 0 (t: 4, u: (0, 2.0), q: (1, 4))', 'partners': "['c_2-9d36542d-3adc-45c3-a83d-bf3254872e52', 'm_1-330bf13e-d489-4e44-883c-f0a910d8fd0a']", 'seller': 'm_1-330bf13e-d489-4e44-883c-f0a910d8fd0a', 'buyer': 'c_2-9d36542d-3adc-45c3-a83d-bf3254872e52'} 2019-02-27 11:33:48,620 - INFO - 3/5 [80.00%]: Executing c_0-26d2ab4a-d500-4d36-af88-647bcb3b39b4, m_1-330bf13e-d489-4e44-883c-f0a910d8fd0a agreed on {'time': 3, 'quantity': 3, 'unit_price': 0.5} 2019-02-27 11:33:48,620 - DEBUG - 3/5 [80.00%]: Moved 3 units of p0 from m_1 to c_0 for 1.5 dollars 2019-02-27 11:33:48,620 - INFO - 3/5 [80.00%]: Executing c_2-9d36542d-3adc-45c3-a83d-bf3254872e52, m_2-3e017d97-5d6b-4404-acec-89b56f648c32 agreed on {'time': 3, 'quantity': 4, 'unit_price': 0.5} 2019-02-27 11:33:48,620 - DEBUG - 3/5 [80.00%]: Moved 4 units of p0 from m_2 to c_2 for 2.0 dollars 2019-02-27 11:33:48,620 - INFO - 3/5 [80.00%]: Executing c_1-33983822-6cfc-4241-a062-02dde1227de6, m_2-3e017d97-5d6b-4404-acec-89b56f648c32 agreed on {'time': 3, 'quantity': 3, 'unit_price': 0.5} 2019-02-27 11:33:48,620 - DEBUG - 3/5 [80.00%]: Moved 3 units of p0 from m_2 to c_1 for 1.5 dollars 2019-02-27 11:33:48,620 - INFO - 3/5 [80.00%]: Executing c_4-58a433ab-e5bb-4c9f-9bbc-29117626f303, m_2-3e017d97-5d6b-4404-acec-89b56f648c32 agreed on {'time': 3, 'quantity': 3, 'unit_price': 0.5} 2019-02-27 11:33:48,620 - DEBUG - 3/5 [80.00%]: Moved 3 units of p0 from m_2 to c_4 for 1.5 dollars 2019-02-27 11:33:48,620 - INFO - 3/5 [80.00%]: Executing c_3-2ad64379-0773-4b5b-9536-5bc7a9ef116d, m_3-552642da-2001-4c04-b664-9c84d03bb7f8 agreed on {'time': 3, 'quantity': 3, 'unit_price': 0.5} 2019-02-27 11:33:48,620 - DEBUG - 3/5 [80.00%]: Moved 3 units of p0 from m_3 to c_3 for 1.5 dollars 2019-02-27 11:33:48,620 - DEBUG - 3/5 [80.00%]: Factory 3972f90f-1ef1-4320-b2ed-b7cc1e3fe76a: money=-5.0, storage={0: 4}, loans=0.0 2019-02-27 11:33:48,620 - DEBUG - 3/5 [80.00%]: Factory 9c12276a-e377-43ff-9942-ebebbaca5f0f: money=-5.0, storage={0: 4}, loans=0.0 2019-02-27 11:33:48,620 - DEBUG - 3/5 [80.00%]: Factory 9fb5bd99-8a77-455c-a292-13a61f3d1277: money=-6.0, storage={0: 4}, loans=0.0 2019-02-27 11:33:48,620 - DEBUG - 3/5 [80.00%]: Factory 6444729f-608f-470a-924f-06aa20c714c4: money=-5.0, storage={0: 4}, loans=0.0 2019-02-27 11:33:48,620 - DEBUG - 3/5 [80.00%]: Factory a55763d3-8c50-4b3a-baef-01f9098fbe92: money=-5.0, storage={0: 3}, loans=0.0 2019-02-27 11:33:48,621 - DEBUG - 3/5 [80.00%]: Factory a8759689-b82f-46c9-9316-c8184a6eb865: money=3.5, storage={0: -7}, loans=0.0 2019-02-27 11:33:48,621 - DEBUG - 3/5 [80.00%]: Factory 56cc3bd8-8f94-4f34-aad8-9e7c25c2a662: money=3.0, storage={0: -6}, loans=0.0 2019-02-27 11:33:48,621 - DEBUG - 3/5 [80.00%]: Factory bef7fbff-b1d6-41dc-91d1-b2f6e58392a2: money=8.5, storage={0: -17}, loans=0.0 2019-02-27 11:33:48,621 - DEBUG - 3/5 [80.00%]: Factory 7fb015ca-deb5-4a63-8735-0c2ad68edd7d: money=5.0, storage={0: -10}, loans=0.0 2019-02-27 11:33:48,621 - DEBUG - 3/5 [80.00%]: Factory 6a59c2fb-0af9-445c-8278-8278d53edb14: money=6.0, storage={0: -12}, loans=0.0 2019-02-27 11:33:48,621 - INFO - 4/5 [100.00%]: 0 Negotiations/4 _entities 2019-02-27 11:33:48,621 - DEBUG - 4/5 [100.00%]: Factory 3972f90f-1ef1-4320-b2ed-b7cc1e3fe76a: money=-5.0, storage={0: 7}, loans=0.0 2019-02-27 11:33:48,621 - DEBUG - 4/5 [100.00%]: Factory 9c12276a-e377-43ff-9942-ebebbaca5f0f: money=-5.0, storage={0: 7}, loans=0.0 2019-02-27 11:33:48,621 - DEBUG - 4/5 [100.00%]: Factory 9fb5bd99-8a77-455c-a292-13a61f3d1277: money=-6.0, storage={0: 8}, loans=0.0 2019-02-27 11:33:48,621 - DEBUG - 4/5 [100.00%]: Factory 6444729f-608f-470a-924f-06aa20c714c4: money=-5.0, storage={0: 7}, loans=0.0 2019-02-27 11:33:48,622 - DEBUG - 4/5 [100.00%]: Factory a55763d3-8c50-4b3a-baef-01f9098fbe92: money=-5.0, storage={0: 7}, loans=0.0 2019-02-27 11:33:48,622 - DEBUG - 4/5 [100.00%]: Factory a8759689-b82f-46c9-9316-c8184a6eb865: money=3.5, storage={0: -7}, loans=0.0 2019-02-27 11:33:48,622 - DEBUG - 4/5 [100.00%]: Factory 56cc3bd8-8f94-4f34-aad8-9e7c25c2a662: money=3.0, storage={0: -6}, loans=0.0 2019-02-27 11:33:48,622 - DEBUG - 4/5 [100.00%]: Factory bef7fbff-b1d6-41dc-91d1-b2f6e58392a2: money=8.5, storage={0: -17}, loans=0.0 2019-02-27 11:33:48,622 - DEBUG - 4/5 [100.00%]: Factory 7fb015ca-deb5-4a63-8735-0c2ad68edd7d: money=5.0, storage={0: -10}, loans=0.0 2019-02-27 11:33:48,622 - DEBUG - 4/5 [100.00%]: Factory 6a59c2fb-0af9-445c-8278-8278d53edb14: money=6.0, storage={0: -12}, loans=0.0 2019-02-27 11:33:48,625 - INFO - 0/10 [10.00%]: SCMLWorld/20190227-113348mf3lw: World Created 2019-02-27 11:33:48,625 - INFO - 0/10 [10.00%]: m_0 joined 2019-02-27 11:33:48,625 - INFO - 0/10 [10.00%]: m_1 joined 2019-02-27 11:33:48,625 - INFO - 0/10 [10.00%]: m_2 joined 2019-02-27 11:33:48,625 - INFO - 0/10 [10.00%]: m_3 joined 2019-02-27 11:33:48,625 - INFO - 0/10 [10.00%]: m_4 joined 2019-02-27 11:33:48,625 - INFO - 0/10 [10.00%]: c_0 joined 2019-02-27 11:33:48,625 - INFO - 0/10 [10.00%]: c_1 joined 2019-02-27 11:33:48,625 - INFO - 0/10 [10.00%]: c_2 joined 2019-02-27 11:33:48,625 - INFO - 0/10 [10.00%]: c_3 joined 2019-02-27 11:33:48,625 - INFO - 0/10 [10.00%]: c_4 joined 2019-02-27 11:33:48,626 - INFO - 0/10 [10.00%]: k8JMRQcYue8AUSTH joined 2019-02-27 11:33:48,626 - INFO - 0/10 [10.00%]: IQazPOi4JWgWFnQx joined 2019-02-27 11:33:48,626 - INFO - 0/10 [10.00%]: 0 Negotiations/4 _entities 2019-02-27 11:33:48,627 - INFO - 0/10 [10.00%]: m_0 requested negmas.sao.SAOMechanism[None] with ['c_3', 'm_0'] (ID d046dc71-8922-4b9e-9134-5a8e7f33eacd) 2019-02-27 11:33:48,629 - INFO - 0/10 [10.00%]: m_0-61b223a2-ea24-4bfc-9bf3-aa85fa8a955a request was accepted 2019-02-27 11:33:48,632 - INFO - 0/10 [10.00%]: m_1 requested negmas.sao.SAOMechanism[None] with ['c_3', 'm_1'] (ID dfed905a-da62-49c5-ab07-a2a36b484dea) 2019-02-27 11:33:48,634 - INFO - 0/10 [10.00%]: m_1-b789f15d-3508-464a-8717-8ba1da159754 request was accepted 2019-02-27 11:33:48,635 - INFO - 0/10 [10.00%]: m_2 requested negmas.sao.SAOMechanism[None] with ['c_3', 'm_2'] (ID f604f137-1827-4132-ac06-4a5487be4fea) 2019-02-27 11:33:48,636 - INFO - 0/10 [10.00%]: m_2-f4d60475-9842-4006-8513-ca39a2379160 request was accepted 2019-02-27 11:33:48,637 - INFO - 0/10 [10.00%]: m_3 requested negmas.sao.SAOMechanism[None] with ['c_3', 'm_3'] (ID 2304199f-ecbe-4cdb-a3ad-daee600a74ac) 2019-02-27 11:33:48,637 - INFO - 0/10 [10.00%]: m_3-418c12ae-b8cd-4e28-a9a8-b998b4ef7df6 request was accepted 2019-02-27 11:33:48,639 - INFO - 0/10 [10.00%]: m_4 requested negmas.sao.SAOMechanism[None] with ['c_3', 'm_4'] (ID caa2e5e1-330d-4918-96a2-2c51462bbb2e) 2019-02-27 11:33:48,639 - INFO - 0/10 [10.00%]: m_4-4f6b8ebc-32b0-44d5-88d6-88b3cec0b489 request was accepted 2019-02-27 11:33:48,640 - INFO - 0/10 [10.00%]: m_0 requested negmas.sao.SAOMechanism[None] with ['c_3', 'm_0'] (ID c38f6408-2701-4c44-b929-4ea27924afa9) 2019-02-27 11:33:48,641 - INFO - 0/10 [10.00%]: m_0-61b223a2-ea24-4bfc-9bf3-aa85fa8a955a request was accepted 2019-02-27 11:33:48,642 - INFO - 0/10 [10.00%]: m_1 requested negmas.sao.SAOMechanism[None] with ['c_3', 'm_1'] (ID 6a403198-27b6-4b5c-b055-737548dbda67) 2019-02-27 11:33:48,642 - INFO - 0/10 [10.00%]: m_1-b789f15d-3508-464a-8717-8ba1da159754 request was accepted 2019-02-27 11:33:48,643 - INFO - 0/10 [10.00%]: m_2 requested negmas.sao.SAOMechanism[None] with ['c_3', 'm_2'] (ID cd7a2aca-7fd0-4079-8965-7a2bc1570068) 2019-02-27 11:33:48,644 - INFO - 0/10 [10.00%]: m_2-f4d60475-9842-4006-8513-ca39a2379160 request was accepted 2019-02-27 11:33:48,645 - INFO - 0/10 [10.00%]: m_3 requested negmas.sao.SAOMechanism[None] with ['c_3', 'm_3'] (ID d22e2008-e922-464b-9e8a-c36a14c72d5a) 2019-02-27 11:33:48,645 - INFO - 0/10 [10.00%]: m_3-418c12ae-b8cd-4e28-a9a8-b998b4ef7df6 request was accepted 2019-02-27 11:33:48,646 - INFO - 0/10 [10.00%]: m_4 requested negmas.sao.SAOMechanism[None] with ['c_3', 'm_4'] (ID 6b3e94e6-9629-4ff1-ae20-fcf9dfd5000d) 2019-02-27 11:33:48,647 - INFO - 0/10 [10.00%]: m_4-4f6b8ebc-32b0-44d5-88d6-88b3cec0b489 request was accepted 2019-02-27 11:33:48,648 - INFO - 0/10 [10.00%]: m_0 requested negmas.sao.SAOMechanism[None] with ['c_3', 'm_0'] (ID b7e115ed-a310-42a0-b9d9-1fa748afcfd9) 2019-02-27 11:33:48,648 - INFO - 0/10 [10.00%]: m_0-61b223a2-ea24-4bfc-9bf3-aa85fa8a955a request was accepted 2019-02-27 11:33:48,649 - INFO - 0/10 [10.00%]: m_1 requested negmas.sao.SAOMechanism[None] with ['c_3', 'm_1'] (ID 162b8812-9e49-4508-9a8c-8214f3f2425c) 2019-02-27 11:33:48,650 - INFO - 0/10 [10.00%]: m_1-b789f15d-3508-464a-8717-8ba1da159754 request was accepted 2019-02-27 11:33:48,651 - INFO - 0/10 [10.00%]: m_2 requested negmas.sao.SAOMechanism[None] with ['c_3', 'm_2'] (ID 21364d17-6033-4fde-98ac-c34af98abf6e) 2019-02-27 11:33:48,652 - INFO - 0/10 [10.00%]: m_2-f4d60475-9842-4006-8513-ca39a2379160 request was accepted 2019-02-27 11:33:48,653 - INFO - 0/10 [10.00%]: m_3 requested negmas.sao.SAOMechanism[None] with ['c_3', 'm_3'] (ID 25ce104e-195a-49f6-a0c2-930a9bf50f04) 2019-02-27 11:33:48,653 - INFO - 0/10 [10.00%]: m_3-418c12ae-b8cd-4e28-a9a8-b998b4ef7df6 request was accepted 2019-02-27 11:33:48,654 - INFO - 0/10 [10.00%]: m_4 requested negmas.sao.SAOMechanism[None] with ['c_3', 'm_4'] (ID 7d23c6e2-eef0-4906-b480-4da0262f0c78) 2019-02-27 11:33:48,655 - INFO - 0/10 [10.00%]: m_4-4f6b8ebc-32b0-44d5-88d6-88b3cec0b489 request was accepted 2019-02-27 11:33:48,656 - INFO - 0/10 [10.00%]: m_0 requested negmas.sao.SAOMechanism[None] with ['c_3', 'm_0'] (ID abd4d2ff-3107-4223-a0cb-aff4b7771e31) 2019-02-27 11:33:48,656 - INFO - 0/10 [10.00%]: m_0-61b223a2-ea24-4bfc-9bf3-aa85fa8a955a request was accepted 2019-02-27 11:33:48,657 - INFO - 0/10 [10.00%]: m_1 requested negmas.sao.SAOMechanism[None] with ['c_3', 'm_1'] (ID 544761d4-00b1-4aa0-a5e3-7586f2a6bca6) 2019-02-27 11:33:48,658 - INFO - 0/10 [10.00%]: m_1-b789f15d-3508-464a-8717-8ba1da159754 request was accepted 2019-02-27 11:33:48,659 - INFO - 0/10 [10.00%]: m_2 requested negmas.sao.SAOMechanism[None] with ['c_3', 'm_2'] (ID c471aebc-6283-421f-a7da-227d521da601) 2019-02-27 11:33:48,660 - INFO - 0/10 [10.00%]: m_2-f4d60475-9842-4006-8513-ca39a2379160 request was accepted 2019-02-27 11:33:48,661 - INFO - 0/10 [10.00%]: m_3 requested negmas.sao.SAOMechanism[None] with ['c_3', 'm_3'] (ID c2dc8a56-8466-4edd-af5b-17e3504f6c1c) 2019-02-27 11:33:48,661 - INFO - 0/10 [10.00%]: m_3-418c12ae-b8cd-4e28-a9a8-b998b4ef7df6 request was accepted 2019-02-27 11:33:48,662 - INFO - 0/10 [10.00%]: m_4 requested negmas.sao.SAOMechanism[None] with ['c_3', 'm_4'] (ID fbb29752-4b2a-4664-877e-832b169de477) 2019-02-27 11:33:48,663 - INFO - 0/10 [10.00%]: m_4-4f6b8ebc-32b0-44d5-88d6-88b3cec0b489 request was accepted 2019-02-27 11:33:48,664 - INFO - 0/10 [10.00%]: m_0 requested negmas.sao.SAOMechanism[None] with ['c_2', 'm_0'] (ID 52010d1b-adfc-4314-bc54-f5660a205e84) 2019-02-27 11:33:48,665 - INFO - 0/10 [10.00%]: m_0-61b223a2-ea24-4bfc-9bf3-aa85fa8a955a request was accepted 2019-02-27 11:33:48,666 - INFO - 0/10 [10.00%]: m_1 requested negmas.sao.SAOMechanism[None] with ['c_2', 'm_1'] (ID fa6ba3df-14c9-4ffb-82b6-720787d13e52) 2019-02-27 11:33:48,667 - INFO - 0/10 [10.00%]: m_1-b789f15d-3508-464a-8717-8ba1da159754 request was accepted 2019-02-27 11:33:48,668 - INFO - 0/10 [10.00%]: m_2 requested negmas.sao.SAOMechanism[None] with ['c_2', 'm_2'] (ID 9772cb82-9ed0-4675-97b5-7634d9e50c24) 2019-02-27 11:33:48,668 - INFO - 0/10 [10.00%]: m_2-f4d60475-9842-4006-8513-ca39a2379160 request was accepted 2019-02-27 11:33:48,669 - INFO - 0/10 [10.00%]: m_3 requested negmas.sao.SAOMechanism[None] with ['c_2', 'm_3'] (ID b5f54632-98b0-4d95-949e-b09981bfa275) 2019-02-27 11:33:48,670 - INFO - 0/10 [10.00%]: m_3-418c12ae-b8cd-4e28-a9a8-b998b4ef7df6 request was accepted 2019-02-27 11:33:48,670 - INFO - 0/10 [10.00%]: m_4 requested negmas.sao.SAOMechanism[None] with ['c_2', 'm_4'] (ID 9a15cbc6-3822-414c-b711-42dcfd99c9a0) 2019-02-27 11:33:48,671 - INFO - 0/10 [10.00%]: m_4-4f6b8ebc-32b0-44d5-88d6-88b3cec0b489 request was accepted 2019-02-27 11:33:48,672 - INFO - 0/10 [10.00%]: m_0 requested negmas.sao.SAOMechanism[None] with ['c_2', 'm_0'] (ID 1bdf3ab0-a0bb-4426-97f7-9563828fecd7) 2019-02-27 11:33:48,673 - INFO - 0/10 [10.00%]: m_0-61b223a2-ea24-4bfc-9bf3-aa85fa8a955a request was accepted 2019-02-27 11:33:48,674 - INFO - 0/10 [10.00%]: m_1 requested negmas.sao.SAOMechanism[None] with ['c_2', 'm_1'] (ID 1c1bbe16-9595-455a-882d-d8682229490f) 2019-02-27 11:33:48,675 - INFO - 0/10 [10.00%]: m_1-b789f15d-3508-464a-8717-8ba1da159754 request was accepted 2019-02-27 11:33:48,676 - INFO - 0/10 [10.00%]: m_2 requested negmas.sao.SAOMechanism[None] with ['c_2', 'm_2'] (ID f6c55413-6099-45be-afc8-a095ed5c9fa9) 2019-02-27 11:33:48,676 - INFO - 0/10 [10.00%]: m_2-f4d60475-9842-4006-8513-ca39a2379160 request was accepted 2019-02-27 11:33:48,677 - INFO - 0/10 [10.00%]: m_3 requested negmas.sao.SAOMechanism[None] with ['c_2', 'm_3'] (ID ddd121e5-2068-4bc5-ae93-d0e6a3b73e5c) 2019-02-27 11:33:48,678 - INFO - 0/10 [10.00%]: m_3-418c12ae-b8cd-4e28-a9a8-b998b4ef7df6 request was accepted 2019-02-27 11:33:48,679 - INFO - 0/10 [10.00%]: m_4 requested negmas.sao.SAOMechanism[None] with ['c_2', 'm_4'] (ID e7ba03a1-2f8f-4419-ae60-8562f65511fb) 2019-02-27 11:33:48,680 - INFO - 0/10 [10.00%]: m_4-4f6b8ebc-32b0-44d5-88d6-88b3cec0b489 request was accepted 2019-02-27 11:33:48,684 - INFO - 0/10 [10.00%]: m_0 requested negmas.sao.SAOMechanism[None] with ['c_2', 'm_0'] (ID a217ce7e-93a7-4237-aa0d-86da62653647) 2019-02-27 11:33:48,685 - INFO - 0/10 [10.00%]: m_0-61b223a2-ea24-4bfc-9bf3-aa85fa8a955a request was accepted 2019-02-27 11:33:48,688 - INFO - 0/10 [10.00%]: m_1 requested negmas.sao.SAOMechanism[None] with ['c_2', 'm_1'] (ID 4a6612a4-2b0e-4149-b93c-6aedb139453a) 2019-02-27 11:33:48,689 - INFO - 0/10 [10.00%]: m_1-b789f15d-3508-464a-8717-8ba1da159754 request was accepted 2019-02-27 11:33:48,691 - INFO - 0/10 [10.00%]: m_2 requested negmas.sao.SAOMechanism[None] with ['c_2', 'm_2'] (ID ab5c3bc1-a995-49e2-aaff-7148f9c052c2) 2019-02-27 11:33:48,691 - INFO - 0/10 [10.00%]: m_2-f4d60475-9842-4006-8513-ca39a2379160 request was accepted 2019-02-27 11:33:48,692 - INFO - 0/10 [10.00%]: m_3 requested negmas.sao.SAOMechanism[None] with ['c_2', 'm_3'] (ID e2585261-4e7e-43d3-8619-22054d803faf) 2019-02-27 11:33:48,693 - INFO - 0/10 [10.00%]: m_3-418c12ae-b8cd-4e28-a9a8-b998b4ef7df6 request was accepted 2019-02-27 11:33:48,694 - INFO - 0/10 [10.00%]: m_4 requested negmas.sao.SAOMechanism[None] with ['c_2', 'm_4'] (ID 602f57f4-0aab-4303-b827-dfa859ac8c01) 2019-02-27 11:33:48,695 - INFO - 0/10 [10.00%]: m_4-4f6b8ebc-32b0-44d5-88d6-88b3cec0b489 request was accepted 2019-02-27 11:33:48,696 - INFO - 0/10 [10.00%]: m_0 requested negmas.sao.SAOMechanism[None] with ['c_2', 'm_0'] (ID 75c390eb-444e-416e-b671-44bac9998f1d) 2019-02-27 11:33:48,696 - INFO - 0/10 [10.00%]: m_0-61b223a2-ea24-4bfc-9bf3-aa85fa8a955a request was accepted 2019-02-27 11:33:48,697 - INFO - 0/10 [10.00%]: m_1 requested negmas.sao.SAOMechanism[None] with ['c_2', 'm_1'] (ID b4e05d27-8136-4b08-ba25-895748def5b3) 2019-02-27 11:33:48,698 - INFO - 0/10 [10.00%]: m_1-b789f15d-3508-464a-8717-8ba1da159754 request was accepted 2019-02-27 11:33:48,699 - INFO - 0/10 [10.00%]: m_2 requested negmas.sao.SAOMechanism[None] with ['c_2', 'm_2'] (ID b9707326-bb69-40be-95f9-6caeef2d0aec) 2019-02-27 11:33:48,699 - INFO - 0/10 [10.00%]: m_2-f4d60475-9842-4006-8513-ca39a2379160 request was accepted 2019-02-27 11:33:48,700 - INFO - 0/10 [10.00%]: m_3 requested negmas.sao.SAOMechanism[None] with ['c_2', 'm_3'] (ID ec8739d5-e587-4f00-a6ce-3137179078ce) 2019-02-27 11:33:48,701 - INFO - 0/10 [10.00%]: m_3-418c12ae-b8cd-4e28-a9a8-b998b4ef7df6 request was accepted 2019-02-27 11:33:48,701 - INFO - 0/10 [10.00%]: m_4 requested negmas.sao.SAOMechanism[None] with ['c_2', 'm_4'] (ID d36e9887-146b-4f0a-a651-ab668d8bf44a) 2019-02-27 11:33:48,702 - INFO - 0/10 [10.00%]: m_4-4f6b8ebc-32b0-44d5-88d6-88b3cec0b489 request was accepted 2019-02-27 11:33:48,703 - INFO - 0/10 [10.00%]: m_0 requested negmas.sao.SAOMechanism[None] with ['c_1', 'm_0'] (ID 7630ac35-08e2-454c-b34f-447321629501) 2019-02-27 11:33:48,704 - INFO - 0/10 [10.00%]: m_0-61b223a2-ea24-4bfc-9bf3-aa85fa8a955a request was accepted 2019-02-27 11:33:48,705 - INFO - 0/10 [10.00%]: m_1 requested negmas.sao.SAOMechanism[None] with ['c_1', 'm_1'] (ID 21bbea82-3982-4f81-89c9-89f1703e205b) 2019-02-27 11:33:48,705 - INFO - 0/10 [10.00%]: m_1-b789f15d-3508-464a-8717-8ba1da159754 request was accepted 2019-02-27 11:33:48,706 - INFO - 0/10 [10.00%]: m_2 requested negmas.sao.SAOMechanism[None] with ['c_1', 'm_2'] (ID 4b361aaf-0fb1-4504-a7e4-a54c5411b2ba) 2019-02-27 11:33:48,707 - INFO - 0/10 [10.00%]: m_2-f4d60475-9842-4006-8513-ca39a2379160 request was accepted 2019-02-27 11:33:48,708 - INFO - 0/10 [10.00%]: m_3 requested negmas.sao.SAOMechanism[None] with ['c_1', 'm_3'] (ID 4aba86ff-1625-4d00-ac28-ee2d024f5289) 2019-02-27 11:33:48,708 - INFO - 0/10 [10.00%]: m_3-418c12ae-b8cd-4e28-a9a8-b998b4ef7df6 request was accepted 2019-02-27 11:33:48,709 - INFO - 0/10 [10.00%]: m_4 requested negmas.sao.SAOMechanism[None] with ['c_1', 'm_4'] (ID 0cc9b89f-dba6-45ef-86d8-28423c6da4c2) 2019-02-27 11:33:48,709 - INFO - 0/10 [10.00%]: m_4-4f6b8ebc-32b0-44d5-88d6-88b3cec0b489 request was accepted 2019-02-27 11:33:48,711 - INFO - 0/10 [10.00%]: m_0 requested negmas.sao.SAOMechanism[None] with ['c_1', 'm_0'] (ID a9cd0ce9-67d6-42ca-970e-1ed2507b3f91) 2019-02-27 11:33:48,711 - INFO - 0/10 [10.00%]: m_0-61b223a2-ea24-4bfc-9bf3-aa85fa8a955a request was accepted 2019-02-27 11:33:48,712 - INFO - 0/10 [10.00%]: m_1 requested negmas.sao.SAOMechanism[None] with ['c_1', 'm_1'] (ID 4afb31c8-3875-460b-b389-7bad01720155) 2019-02-27 11:33:48,713 - INFO - 0/10 [10.00%]: m_1-b789f15d-3508-464a-8717-8ba1da159754 request was accepted 2019-02-27 11:33:48,713 - INFO - 0/10 [10.00%]: m_2 requested negmas.sao.SAOMechanism[None] with ['c_1', 'm_2'] (ID 649eba51-d460-476a-927c-a45882595b82) 2019-02-27 11:33:48,714 - INFO - 0/10 [10.00%]: m_2-f4d60475-9842-4006-8513-ca39a2379160 request was accepted 2019-02-27 11:33:48,715 - INFO - 0/10 [10.00%]: m_3 requested negmas.sao.SAOMechanism[None] with ['c_1', 'm_3'] (ID fa9b9f48-2a17-4762-8462-76c10c233d92) 2019-02-27 11:33:48,716 - INFO - 0/10 [10.00%]: m_3-418c12ae-b8cd-4e28-a9a8-b998b4ef7df6 request was accepted 2019-02-27 11:33:48,716 - INFO - 0/10 [10.00%]: m_4 requested negmas.sao.SAOMechanism[None] with ['c_1', 'm_4'] (ID 937ce6c3-8541-4d1c-913f-31add3a28f5e) 2019-02-27 11:33:48,717 - INFO - 0/10 [10.00%]: m_4-4f6b8ebc-32b0-44d5-88d6-88b3cec0b489 request was accepted 2019-02-27 11:33:48,718 - INFO - 0/10 [10.00%]: m_0 requested negmas.sao.SAOMechanism[None] with ['c_1', 'm_0'] (ID 9fbdbd64-ad9f-4256-9b5e-2d6a7751647d) 2019-02-27 11:33:48,719 - INFO - 0/10 [10.00%]: m_0-61b223a2-ea24-4bfc-9bf3-aa85fa8a955a request was accepted 2019-02-27 11:33:48,720 - INFO - 0/10 [10.00%]: m_1 requested negmas.sao.SAOMechanism[None] with ['c_1', 'm_1'] (ID 755ed949-a1d6-4028-9585-63253c05fadb) 2019-02-27 11:33:48,720 - INFO - 0/10 [10.00%]: m_1-b789f15d-3508-464a-8717-8ba1da159754 request was accepted 2019-02-27 11:33:48,721 - INFO - 0/10 [10.00%]: m_2 requested negmas.sao.SAOMechanism[None] with ['c_1', 'm_2'] (ID 3f5c415b-0332-41c0-814a-84b5a87130c9) 2019-02-27 11:33:48,722 - INFO - 0/10 [10.00%]: m_2-f4d60475-9842-4006-8513-ca39a2379160 request was accepted 2019-02-27 11:33:48,723 - INFO - 0/10 [10.00%]: m_3 requested negmas.sao.SAOMechanism[None] with ['c_1', 'm_3'] (ID ff5b3320-3076-49a3-aa61-f8b3ea5c5e8a) 2019-02-27 11:33:48,723 - INFO - 0/10 [10.00%]: m_3-418c12ae-b8cd-4e28-a9a8-b998b4ef7df6 request was accepted 2019-02-27 11:33:48,724 - INFO - 0/10 [10.00%]: m_4 requested negmas.sao.SAOMechanism[None] with ['c_1', 'm_4'] (ID 188c3ab4-f644-484a-b5fe-11ffc4f7e044) 2019-02-27 11:33:48,725 - INFO - 0/10 [10.00%]: m_4-4f6b8ebc-32b0-44d5-88d6-88b3cec0b489 request was accepted 2019-02-27 11:33:48,726 - INFO - 0/10 [10.00%]: m_0 requested negmas.sao.SAOMechanism[None] with ['c_1', 'm_0'] (ID 3db57ef1-ebbc-484e-83f8-28d8ef6256db) 2019-02-27 11:33:48,727 - INFO - 0/10 [10.00%]: m_0-61b223a2-ea24-4bfc-9bf3-aa85fa8a955a request was accepted 2019-02-27 11:33:48,727 - INFO - 0/10 [10.00%]: m_1 requested negmas.sao.SAOMechanism[None] with ['c_1', 'm_1'] (ID 02b14aab-c26a-425d-a27f-6c40e807c4af) 2019-02-27 11:33:48,728 - INFO - 0/10 [10.00%]: m_1-b789f15d-3508-464a-8717-8ba1da159754 request was accepted 2019-02-27 11:33:48,730 - INFO - 0/10 [10.00%]: m_2 requested negmas.sao.SAOMechanism[None] with ['c_1', 'm_2'] (ID 4fee8aad-b0ea-45c6-9690-2d4b827704db) 2019-02-27 11:33:48,731 - INFO - 0/10 [10.00%]: m_2-f4d60475-9842-4006-8513-ca39a2379160 request was accepted 2019-02-27 11:33:48,733 - INFO - 0/10 [10.00%]: m_3 requested negmas.sao.SAOMechanism[None] with ['c_1', 'm_3'] (ID a6a20b07-8629-4360-8c00-404d49bf641d) 2019-02-27 11:33:48,734 - INFO - 0/10 [10.00%]: m_3-418c12ae-b8cd-4e28-a9a8-b998b4ef7df6 request was accepted 2019-02-27 11:33:48,735 - INFO - 0/10 [10.00%]: m_4 requested negmas.sao.SAOMechanism[None] with ['c_1', 'm_4'] (ID 352ef926-93ad-44b0-8f7c-5da1accec111) 2019-02-27 11:33:48,736 - INFO - 0/10 [10.00%]: m_4-4f6b8ebc-32b0-44d5-88d6-88b3cec0b489 request was accepted 2019-02-27 11:33:48,738 - INFO - 0/10 [10.00%]: m_0 requested negmas.sao.SAOMechanism[None] with ['c_0', 'm_0'] (ID ca47f1b3-0e8c-4398-9d9d-3ef614e021e0) 2019-02-27 11:33:48,738 - INFO - 0/10 [10.00%]: m_0-61b223a2-ea24-4bfc-9bf3-aa85fa8a955a request was accepted 2019-02-27 11:33:48,741 - INFO - 0/10 [10.00%]: m_1 requested negmas.sao.SAOMechanism[None] with ['c_0', 'm_1'] (ID 3f09cb8d-88c9-4b01-9f20-fed85547c265) 2019-02-27 11:33:48,741 - INFO - 0/10 [10.00%]: m_1-b789f15d-3508-464a-8717-8ba1da159754 request was accepted 2019-02-27 11:33:48,743 - INFO - 0/10 [10.00%]: m_2 requested negmas.sao.SAOMechanism[None] with ['c_0', 'm_2'] (ID 5226fd27-01d9-40ce-8cde-0e0fdd24cb9a) 2019-02-27 11:33:48,744 - INFO - 0/10 [10.00%]: m_2-f4d60475-9842-4006-8513-ca39a2379160 request was accepted 2019-02-27 11:33:48,745 - INFO - 0/10 [10.00%]: m_3 requested negmas.sao.SAOMechanism[None] with ['c_0', 'm_3'] (ID aa003727-2cf5-4ef8-9b1e-4fe74e914a7b) 2019-02-27 11:33:48,745 - INFO - 0/10 [10.00%]: m_3-418c12ae-b8cd-4e28-a9a8-b998b4ef7df6 request was accepted 2019-02-27 11:33:48,746 - INFO - 0/10 [10.00%]: m_4 requested negmas.sao.SAOMechanism[None] with ['c_0', 'm_4'] (ID c381ecf7-6288-4434-912d-734eedb1e42c) 2019-02-27 11:33:48,747 - INFO - 0/10 [10.00%]: m_4-4f6b8ebc-32b0-44d5-88d6-88b3cec0b489 request was accepted 2019-02-27 11:33:48,748 - INFO - 0/10 [10.00%]: m_0 requested negmas.sao.SAOMechanism[None] with ['c_0', 'm_0'] (ID 1cbd694d-cc25-492b-9fcd-aed0c77de1e1) 2019-02-27 11:33:48,749 - INFO - 0/10 [10.00%]: m_0-61b223a2-ea24-4bfc-9bf3-aa85fa8a955a request was accepted 2019-02-27 11:33:48,750 - INFO - 0/10 [10.00%]: m_1 requested negmas.sao.SAOMechanism[None] with ['c_0', 'm_1'] (ID 82148aa3-c29f-40a1-80f1-f2d5e0333754) 2019-02-27 11:33:48,751 - INFO - 0/10 [10.00%]: m_1-b789f15d-3508-464a-8717-8ba1da159754 request was accepted 2019-02-27 11:33:48,752 - INFO - 0/10 [10.00%]: m_2 requested negmas.sao.SAOMechanism[None] with ['c_0', 'm_2'] (ID 8b735641-0049-42a5-9ff7-c430b7e3aedf) 2019-02-27 11:33:48,752 - INFO - 0/10 [10.00%]: m_2-f4d60475-9842-4006-8513-ca39a2379160 request was accepted 2019-02-27 11:33:48,754 - INFO - 0/10 [10.00%]: m_3 requested negmas.sao.SAOMechanism[None] with ['c_0', 'm_3'] (ID 8a01d112-0756-4a75-ad5c-619bec3a56ae) 2019-02-27 11:33:48,754 - INFO - 0/10 [10.00%]: m_3-418c12ae-b8cd-4e28-a9a8-b998b4ef7df6 request was accepted 2019-02-27 11:33:48,755 - INFO - 0/10 [10.00%]: m_4 requested negmas.sao.SAOMechanism[None] with ['c_0', 'm_4'] (ID ea80024f-0c69-406a-8480-59a3576d2e55) 2019-02-27 11:33:48,756 - INFO - 0/10 [10.00%]: m_4-4f6b8ebc-32b0-44d5-88d6-88b3cec0b489 request was accepted 2019-02-27 11:33:48,757 - INFO - 0/10 [10.00%]: m_0 requested negmas.sao.SAOMechanism[None] with ['c_0', 'm_0'] (ID e899e615-3427-494a-a344-d303e73ab182) 2019-02-27 11:33:48,758 - INFO - 0/10 [10.00%]: m_0-61b223a2-ea24-4bfc-9bf3-aa85fa8a955a request was accepted 2019-02-27 11:33:48,759 - INFO - 0/10 [10.00%]: m_1 requested negmas.sao.SAOMechanism[None] with ['c_0', 'm_1'] (ID 8cad764d-9ae4-43b1-9ccd-302f0bbbe0a0) 2019-02-27 11:33:48,759 - INFO - 0/10 [10.00%]: m_1-b789f15d-3508-464a-8717-8ba1da159754 request was accepted 2019-02-27 11:33:48,760 - INFO - 0/10 [10.00%]: m_2 requested negmas.sao.SAOMechanism[None] with ['c_0', 'm_2'] (ID c8f03b7b-5e29-49d5-9801-1f48a89b1f07) 2019-02-27 11:33:48,761 - INFO - 0/10 [10.00%]: m_2-f4d60475-9842-4006-8513-ca39a2379160 request was accepted 2019-02-27 11:33:48,762 - INFO - 0/10 [10.00%]: m_3 requested negmas.sao.SAOMechanism[None] with ['c_0', 'm_3'] (ID 06b702d8-2762-4b6f-9d5b-19406531400f) 2019-02-27 11:33:48,762 - INFO - 0/10 [10.00%]: m_3-418c12ae-b8cd-4e28-a9a8-b998b4ef7df6 request was accepted 2019-02-27 11:33:48,763 - INFO - 0/10 [10.00%]: m_4 requested negmas.sao.SAOMechanism[None] with ['c_0', 'm_4'] (ID 3c041bff-6eea-4f24-bd09-36f13606b1b1) 2019-02-27 11:33:48,764 - INFO - 0/10 [10.00%]: m_4-4f6b8ebc-32b0-44d5-88d6-88b3cec0b489 request was accepted 2019-02-27 11:33:48,765 - INFO - 0/10 [10.00%]: m_0 requested negmas.sao.SAOMechanism[None] with ['c_0', 'm_0'] (ID 21cb0c3a-00e1-4c36-a8b5-e82d231ee6cf) 2019-02-27 11:33:48,766 - INFO - 0/10 [10.00%]: m_0-61b223a2-ea24-4bfc-9bf3-aa85fa8a955a request was accepted 2019-02-27 11:33:48,767 - INFO - 0/10 [10.00%]: m_1 requested negmas.sao.SAOMechanism[None] with ['c_0', 'm_1'] (ID 2c26f106-3732-4e32-89c1-fa0f2bfdbe67) 2019-02-27 11:33:48,767 - INFO - 0/10 [10.00%]: m_1-b789f15d-3508-464a-8717-8ba1da159754 request was accepted 2019-02-27 11:33:48,768 - INFO - 0/10 [10.00%]: m_2 requested negmas.sao.SAOMechanism[None] with ['c_0', 'm_2'] (ID 9c384110-5270-4d83-a036-b7f9c0d6e2f1) 2019-02-27 11:33:48,769 - INFO - 0/10 [10.00%]: m_2-f4d60475-9842-4006-8513-ca39a2379160 request was accepted 2019-02-27 11:33:48,770 - INFO - 0/10 [10.00%]: m_3 requested negmas.sao.SAOMechanism[None] with ['c_0', 'm_3'] (ID 54a73a3d-4a1c-4578-90f2-8e0ab10e5aed) 2019-02-27 11:33:48,770 - INFO - 0/10 [10.00%]: m_3-418c12ae-b8cd-4e28-a9a8-b998b4ef7df6 request was accepted 2019-02-27 11:33:48,771 - INFO - 0/10 [10.00%]: m_4 requested negmas.sao.SAOMechanism[None] with ['c_0', 'm_4'] (ID 4d0839e1-d64a-47fe-9cf4-a49c662d5d82) 2019-02-27 11:33:48,772 - INFO - 0/10 [10.00%]: m_4-4f6b8ebc-32b0-44d5-88d6-88b3cec0b489 request was accepted 2019-02-27 11:33:48,773 - INFO - 0/10 [10.00%]: m_0 requested negmas.sao.SAOMechanism[None] with ['c_4', 'm_0'] (ID 9f5be0bc-7c0c-4e81-aefe-283443b3d07c) 2019-02-27 11:33:48,774 - INFO - 0/10 [10.00%]: m_0-61b223a2-ea24-4bfc-9bf3-aa85fa8a955a request was accepted 2019-02-27 11:33:48,775 - INFO - 0/10 [10.00%]: m_1 requested negmas.sao.SAOMechanism[None] with ['c_4', 'm_1'] (ID a24c43cf-7fbf-43ab-b7c8-fd5704532e5f) 2019-02-27 11:33:48,776 - INFO - 0/10 [10.00%]: m_1-b789f15d-3508-464a-8717-8ba1da159754 request was accepted 2019-02-27 11:33:48,777 - INFO - 0/10 [10.00%]: m_2 requested negmas.sao.SAOMechanism[None] with ['c_4', 'm_2'] (ID df8a75c9-48a9-479d-a07d-418c67232616) 2019-02-27 11:33:48,777 - INFO - 0/10 [10.00%]: m_2-f4d60475-9842-4006-8513-ca39a2379160 request was accepted 2019-02-27 11:33:48,778 - INFO - 0/10 [10.00%]: m_3 requested negmas.sao.SAOMechanism[None] with ['c_4', 'm_3'] (ID 82cd77c2-d1f7-4cc6-a564-2911f2871242) 2019-02-27 11:33:48,779 - INFO - 0/10 [10.00%]: m_3-418c12ae-b8cd-4e28-a9a8-b998b4ef7df6 request was accepted 2019-02-27 11:33:48,780 - INFO - 0/10 [10.00%]: m_4 requested negmas.sao.SAOMechanism[None] with ['c_4', 'm_4'] (ID c546f64b-23c3-4860-9a8e-9ef48b47ea15) 2019-02-27 11:33:48,780 - INFO - 0/10 [10.00%]: m_4-4f6b8ebc-32b0-44d5-88d6-88b3cec0b489 request was accepted 2019-02-27 11:33:48,781 - INFO - 0/10 [10.00%]: m_0 requested negmas.sao.SAOMechanism[None] with ['c_4', 'm_0'] (ID 0ef1f46f-f56b-4159-9fd4-958e62e1649a) 2019-02-27 11:33:48,782 - INFO - 0/10 [10.00%]: m_0-61b223a2-ea24-4bfc-9bf3-aa85fa8a955a request was accepted 2019-02-27 11:33:48,783 - INFO - 0/10 [10.00%]: m_1 requested negmas.sao.SAOMechanism[None] with ['c_4', 'm_1'] (ID 3713e8a2-f28b-4729-9602-e374c95a21f7) 2019-02-27 11:33:48,784 - INFO - 0/10 [10.00%]: m_1-b789f15d-3508-464a-8717-8ba1da159754 request was accepted 2019-02-27 11:33:48,784 - INFO - 0/10 [10.00%]: m_2 requested negmas.sao.SAOMechanism[None] with ['c_4', 'm_2'] (ID 098dbbc1-00fc-4154-8bbf-5ef3bd000d3a) 2019-02-27 11:33:48,785 - INFO - 0/10 [10.00%]: m_2-f4d60475-9842-4006-8513-ca39a2379160 request was accepted 2019-02-27 11:33:48,786 - INFO - 0/10 [10.00%]: m_3 requested negmas.sao.SAOMechanism[None] with ['c_4', 'm_3'] (ID c2a6bf05-298a-46ba-a903-e601a1e10654) 2019-02-27 11:33:48,786 - INFO - 0/10 [10.00%]: m_3-418c12ae-b8cd-4e28-a9a8-b998b4ef7df6 request was accepted 2019-02-27 11:33:48,787 - INFO - 0/10 [10.00%]: m_4 requested negmas.sao.SAOMechanism[None] with ['c_4', 'm_4'] (ID 2e413c3e-ab6f-40e0-ac85-806b598c0487) 2019-02-27 11:33:48,788 - INFO - 0/10 [10.00%]: m_4-4f6b8ebc-32b0-44d5-88d6-88b3cec0b489 request was accepted 2019-02-27 11:33:48,789 - INFO - 0/10 [10.00%]: m_0 requested negmas.sao.SAOMechanism[None] with ['c_4', 'm_0'] (ID fbfcabe6-8296-4289-a794-c99dcfa9a21d) 2019-02-27 11:33:48,790 - INFO - 0/10 [10.00%]: m_0-61b223a2-ea24-4bfc-9bf3-aa85fa8a955a request was accepted 2019-02-27 11:33:48,791 - INFO - 0/10 [10.00%]: m_1 requested negmas.sao.SAOMechanism[None] with ['c_4', 'm_1'] (ID ec994847-1d6b-4094-9dde-35a564cbe56a) 2019-02-27 11:33:48,791 - INFO - 0/10 [10.00%]: m_1-b789f15d-3508-464a-8717-8ba1da159754 request was accepted 2019-02-27 11:33:48,792 - INFO - 0/10 [10.00%]: m_2 requested negmas.sao.SAOMechanism[None] with ['c_4', 'm_2'] (ID 893153d5-e695-4a7c-8779-26c93199a9de) 2019-02-27 11:33:48,793 - INFO - 0/10 [10.00%]: m_2-f4d60475-9842-4006-8513-ca39a2379160 request was accepted 2019-02-27 11:33:48,794 - INFO - 0/10 [10.00%]: m_3 requested negmas.sao.SAOMechanism[None] with ['c_4', 'm_3'] (ID 971986cf-f3b3-4b7f-863b-950d9ff75f04) 2019-02-27 11:33:48,794 - INFO - 0/10 [10.00%]: m_3-418c12ae-b8cd-4e28-a9a8-b998b4ef7df6 request was accepted 2019-02-27 11:33:48,795 - INFO - 0/10 [10.00%]: m_4 requested negmas.sao.SAOMechanism[None] with ['c_4', 'm_4'] (ID fb82eddf-2694-4e43-ae22-ae712c41540d) 2019-02-27 11:33:48,796 - INFO - 0/10 [10.00%]: m_4-4f6b8ebc-32b0-44d5-88d6-88b3cec0b489 request was accepted 2019-02-27 11:33:48,797 - INFO - 0/10 [10.00%]: m_0 requested negmas.sao.SAOMechanism[None] with ['c_4', 'm_0'] (ID 6edbc14b-7001-4f2e-b448-443a99bbd756) 2019-02-27 11:33:48,798 - INFO - 0/10 [10.00%]: m_0-61b223a2-ea24-4bfc-9bf3-aa85fa8a955a request was accepted 2019-02-27 11:33:48,799 - INFO - 0/10 [10.00%]: m_1 requested negmas.sao.SAOMechanism[None] with ['c_4', 'm_1'] (ID d0831d6d-a19a-450e-9cea-c8f8a2d9e544) 2019-02-27 11:33:48,799 - INFO - 0/10 [10.00%]: m_1-b789f15d-3508-464a-8717-8ba1da159754 request was accepted 2019-02-27 11:33:48,800 - INFO - 0/10 [10.00%]: m_2 requested negmas.sao.SAOMechanism[None] with ['c_4', 'm_2'] (ID ba30b07a-9bd0-4b55-ab2f-cf2149765faf) 2019-02-27 11:33:48,801 - INFO - 0/10 [10.00%]: m_2-f4d60475-9842-4006-8513-ca39a2379160 request was accepted 2019-02-27 11:33:48,801 - INFO - 0/10 [10.00%]: m_3 requested negmas.sao.SAOMechanism[None] with ['c_4', 'm_3'] (ID a23f41f3-bcf1-4ec4-b349-45a0896a3727) 2019-02-27 11:33:48,802 - INFO - 0/10 [10.00%]: m_3-418c12ae-b8cd-4e28-a9a8-b998b4ef7df6 request was accepted 2019-02-27 11:33:48,803 - INFO - 0/10 [10.00%]: m_4 requested negmas.sao.SAOMechanism[None] with ['c_4', 'm_4'] (ID 0e2a4c97-0307-4de1-80c6-7f934cf0742f) 2019-02-27 11:33:48,803 - INFO - 0/10 [10.00%]: m_4-4f6b8ebc-32b0-44d5-88d6-88b3cec0b489 request was accepted 2019-02-27 11:33:48,803 - DEBUG - 0/10 [10.00%]: Factory 95e75c6e-fd73-4d10-bb63-7e6fd5ed934d: money=0, storage={}, loans=0.0 2019-02-27 11:33:48,804 - DEBUG - 0/10 [10.00%]: Factory 1d03dc99-48cd-4b69-81d8-4faf95f470b1: money=0, storage={}, loans=0.0 2019-02-27 11:33:48,804 - DEBUG - 0/10 [10.00%]: Factory 3988d198-d05c-4a8a-93c9-8a88363a07d6: money=0, storage={}, loans=0.0 2019-02-27 11:33:48,804 - DEBUG - 0/10 [10.00%]: Factory bad2c634-f9b5-4ae3-8b59-626ce7e171fb: money=0, storage={}, loans=0.0 2019-02-27 11:33:48,804 - DEBUG - 0/10 [10.00%]: Factory ee428c0e-e853-4495-8bbd-24302264a757: money=0, storage={}, loans=0.0 2019-02-27 11:33:48,804 - DEBUG - 0/10 [10.00%]: Factory cb5ab840-9bd8-41f9-866a-ca43e56e74c6: money=0.0, storage={}, loans=0.0 2019-02-27 11:33:48,804 - DEBUG - 0/10 [10.00%]: Factory b5cdcb3a-a4bd-478d-9795-d361eb70cf32: money=0.0, storage={}, loans=0.0 2019-02-27 11:33:48,804 - DEBUG - 0/10 [10.00%]: Factory cb4aedd6-68a2-450a-8d92-117fcb5ae311: money=0.0, storage={}, loans=0.0 2019-02-27 11:33:48,804 - DEBUG - 0/10 [10.00%]: Factory 986a8ca5-1b97-449f-b316-450edc5ed050: money=0.0, storage={}, loans=0.0 2019-02-27 11:33:48,804 - DEBUG - 0/10 [10.00%]: Factory d70b6918-35dd-4eab-924c-7a13f3ad3feb: money=0.0, storage={}, loans=0.0 2019-02-27 11:33:48,805 - INFO - 1/10 [20.00%]: 100 Negotiations/4 _entities 2019-02-27 11:33:49,675 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_3', 'm_2'] > {'time': 3, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_3-0230100d-3633-49be-bb01-4928b35e59bc: buy 0 (t: 3, u: (0, 2.0), q: (1, 4))', 'partners': "['c_3-0230100d-3633-49be-bb01-4928b35e59bc', 'm_2-f4d60475-9842-4006-8513-ca39a2379160']", 'seller': 'm_2-f4d60475-9842-4006-8513-ca39a2379160', 'buyer': 'c_3-0230100d-3633-49be-bb01-4928b35e59bc'} 2019-02-27 11:33:49,675 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_1', 'm_2'] > {'time': 1, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_1-68b3b84c-c42b-4582-9119-917484eb77ef: buy 0 (t: 1, u: (0, 2.0), q: (1, 3))', 'partners': "['c_1-68b3b84c-c42b-4582-9119-917484eb77ef', 'm_2-f4d60475-9842-4006-8513-ca39a2379160']", 'seller': 'm_2-f4d60475-9842-4006-8513-ca39a2379160', 'buyer': 'c_1-68b3b84c-c42b-4582-9119-917484eb77ef'} 2019-02-27 11:33:49,675 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_2', 'm_4'] > {'time': 3, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_2-c1142518-c4d8-4f80-9889-693a093ef989: buy 0 (t: 3, u: (0, 2.0), q: (1, 4))', 'partners': "['c_2-c1142518-c4d8-4f80-9889-693a093ef989', 'm_4-4f6b8ebc-32b0-44d5-88d6-88b3cec0b489']", 'seller': 'm_4-4f6b8ebc-32b0-44d5-88d6-88b3cec0b489', 'buyer': 'c_2-c1142518-c4d8-4f80-9889-693a093ef989'} 2019-02-27 11:33:49,676 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_3', 'm_4'] > {'time': 1, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_3-0230100d-3633-49be-bb01-4928b35e59bc: buy 0 (t: 1, u: (0, 2.0), q: (1, 4))', 'partners': "['c_3-0230100d-3633-49be-bb01-4928b35e59bc', 'm_4-4f6b8ebc-32b0-44d5-88d6-88b3cec0b489']", 'seller': 'm_4-4f6b8ebc-32b0-44d5-88d6-88b3cec0b489', 'buyer': 'c_3-0230100d-3633-49be-bb01-4928b35e59bc'} 2019-02-27 11:33:49,676 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_1', 'm_0'] > {'time': 3, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_1-68b3b84c-c42b-4582-9119-917484eb77ef: buy 0 (t: 3, u: (0, 2.0), q: (1, 4))', 'partners': "['c_1-68b3b84c-c42b-4582-9119-917484eb77ef', 'm_0-61b223a2-ea24-4bfc-9bf3-aa85fa8a955a']", 'seller': 'm_0-61b223a2-ea24-4bfc-9bf3-aa85fa8a955a', 'buyer': 'c_1-68b3b84c-c42b-4582-9119-917484eb77ef'} 2019-02-27 11:33:49,676 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_4', 'm_2'] > {'time': 4, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_4-76d9311e-d5f6-4e91-bb83-72994095e2c6: buy 0 (t: 4, u: (0, 2.0), q: (1, 3))', 'partners': "['c_4-76d9311e-d5f6-4e91-bb83-72994095e2c6', 'm_2-f4d60475-9842-4006-8513-ca39a2379160']", 'seller': 'm_2-f4d60475-9842-4006-8513-ca39a2379160', 'buyer': 'c_4-76d9311e-d5f6-4e91-bb83-72994095e2c6'} 2019-02-27 11:33:49,677 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_1', 'm_2'] > {'time': 3, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_1-68b3b84c-c42b-4582-9119-917484eb77ef: buy 0 (t: 3, u: (0, 2.0), q: (1, 4))', 'partners': "['c_1-68b3b84c-c42b-4582-9119-917484eb77ef', 'm_2-f4d60475-9842-4006-8513-ca39a2379160']", 'seller': 'm_2-f4d60475-9842-4006-8513-ca39a2379160', 'buyer': 'c_1-68b3b84c-c42b-4582-9119-917484eb77ef'} 2019-02-27 11:33:49,677 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_1', 'm_3'] > {'time': 4, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_1-68b3b84c-c42b-4582-9119-917484eb77ef: buy 0 (t: 4, u: (0, 2.0), q: (1, 3))', 'partners': "['c_1-68b3b84c-c42b-4582-9119-917484eb77ef', 'm_3-418c12ae-b8cd-4e28-a9a8-b998b4ef7df6']", 'seller': 'm_3-418c12ae-b8cd-4e28-a9a8-b998b4ef7df6', 'buyer': 'c_1-68b3b84c-c42b-4582-9119-917484eb77ef'} 2019-02-27 11:33:49,677 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_4', 'm_3'] > {'time': 3, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_4-76d9311e-d5f6-4e91-bb83-72994095e2c6: buy 0 (t: 3, u: (0, 2.0), q: (1, 4))', 'partners': "['c_4-76d9311e-d5f6-4e91-bb83-72994095e2c6', 'm_3-418c12ae-b8cd-4e28-a9a8-b998b4ef7df6']", 'seller': 'm_3-418c12ae-b8cd-4e28-a9a8-b998b4ef7df6', 'buyer': 'c_4-76d9311e-d5f6-4e91-bb83-72994095e2c6'} 2019-02-27 11:33:49,678 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_0', 'm_3'] > {'time': 4, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_0-b6f40f78-35c5-4b76-9f90-53a459a66882: buy 0 (t: 4, u: (0, 2.0), q: (1, 4))', 'partners': "['c_0-b6f40f78-35c5-4b76-9f90-53a459a66882', 'm_3-418c12ae-b8cd-4e28-a9a8-b998b4ef7df6']", 'seller': 'm_3-418c12ae-b8cd-4e28-a9a8-b998b4ef7df6', 'buyer': 'c_0-b6f40f78-35c5-4b76-9f90-53a459a66882'} 2019-02-27 11:33:49,678 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_0', 'm_2'] > {'time': 1, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_0-b6f40f78-35c5-4b76-9f90-53a459a66882: buy 0 (t: 1, u: (0, 2.0), q: (1, 3))', 'partners': "['c_0-b6f40f78-35c5-4b76-9f90-53a459a66882', 'm_2-f4d60475-9842-4006-8513-ca39a2379160']", 'seller': 'm_2-f4d60475-9842-4006-8513-ca39a2379160', 'buyer': 'c_0-b6f40f78-35c5-4b76-9f90-53a459a66882'} 2019-02-27 11:33:49,679 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_3', 'm_0'] > {'time': 2, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_3-0230100d-3633-49be-bb01-4928b35e59bc: buy 0 (t: 2, u: (0, 2.0), q: (1, 3))', 'partners': "['c_3-0230100d-3633-49be-bb01-4928b35e59bc', 'm_0-61b223a2-ea24-4bfc-9bf3-aa85fa8a955a']", 'seller': 'm_0-61b223a2-ea24-4bfc-9bf3-aa85fa8a955a', 'buyer': 'c_3-0230100d-3633-49be-bb01-4928b35e59bc'} 2019-02-27 11:33:49,679 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_1', 'm_4'] > {'time': 1, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_1-68b3b84c-c42b-4582-9119-917484eb77ef: buy 0 (t: 1, u: (0, 2.0), q: (1, 3))', 'partners': "['c_1-68b3b84c-c42b-4582-9119-917484eb77ef', 'm_4-4f6b8ebc-32b0-44d5-88d6-88b3cec0b489']", 'seller': 'm_4-4f6b8ebc-32b0-44d5-88d6-88b3cec0b489', 'buyer': 'c_1-68b3b84c-c42b-4582-9119-917484eb77ef'} 2019-02-27 11:33:49,679 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_2', 'm_1'] > {'time': 3, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_2-c1142518-c4d8-4f80-9889-693a093ef989: buy 0 (t: 3, u: (0, 2.0), q: (1, 4))', 'partners': "['c_2-c1142518-c4d8-4f80-9889-693a093ef989', 'm_1-b789f15d-3508-464a-8717-8ba1da159754']", 'seller': 'm_1-b789f15d-3508-464a-8717-8ba1da159754', 'buyer': 'c_2-c1142518-c4d8-4f80-9889-693a093ef989'} 2019-02-27 11:33:49,680 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_4', 'm_0'] > {'time': 1, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_4-76d9311e-d5f6-4e91-bb83-72994095e2c6: buy 0 (t: 1, u: (0, 2.0), q: (1, 4))', 'partners': "['c_4-76d9311e-d5f6-4e91-bb83-72994095e2c6', 'm_0-61b223a2-ea24-4bfc-9bf3-aa85fa8a955a']", 'seller': 'm_0-61b223a2-ea24-4bfc-9bf3-aa85fa8a955a', 'buyer': 'c_4-76d9311e-d5f6-4e91-bb83-72994095e2c6'} 2019-02-27 11:33:49,680 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_0', 'm_3'] > {'time': 3, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_0-b6f40f78-35c5-4b76-9f90-53a459a66882: buy 0 (t: 3, u: (0, 2.0), q: (1, 3))', 'partners': "['c_0-b6f40f78-35c5-4b76-9f90-53a459a66882', 'm_3-418c12ae-b8cd-4e28-a9a8-b998b4ef7df6']", 'seller': 'm_3-418c12ae-b8cd-4e28-a9a8-b998b4ef7df6', 'buyer': 'c_0-b6f40f78-35c5-4b76-9f90-53a459a66882'} 2019-02-27 11:33:49,680 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_0', 'm_3'] > {'time': 2, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_0-b6f40f78-35c5-4b76-9f90-53a459a66882: buy 0 (t: 2, u: (0, 2.0), q: (1, 4))', 'partners': "['c_0-b6f40f78-35c5-4b76-9f90-53a459a66882', 'm_3-418c12ae-b8cd-4e28-a9a8-b998b4ef7df6']", 'seller': 'm_3-418c12ae-b8cd-4e28-a9a8-b998b4ef7df6', 'buyer': 'c_0-b6f40f78-35c5-4b76-9f90-53a459a66882'} 2019-02-27 11:33:49,681 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_1', 'm_2'] > {'time': 4, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_1-68b3b84c-c42b-4582-9119-917484eb77ef: buy 0 (t: 4, u: (0, 2.0), q: (1, 3))', 'partners': "['c_1-68b3b84c-c42b-4582-9119-917484eb77ef', 'm_2-f4d60475-9842-4006-8513-ca39a2379160']", 'seller': 'm_2-f4d60475-9842-4006-8513-ca39a2379160', 'buyer': 'c_1-68b3b84c-c42b-4582-9119-917484eb77ef'} 2019-02-27 11:33:49,681 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_1', 'm_1'] > {'time': 1, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_1-68b3b84c-c42b-4582-9119-917484eb77ef: buy 0 (t: 1, u: (0, 2.0), q: (1, 3))', 'partners': "['c_1-68b3b84c-c42b-4582-9119-917484eb77ef', 'm_1-b789f15d-3508-464a-8717-8ba1da159754']", 'seller': 'm_1-b789f15d-3508-464a-8717-8ba1da159754', 'buyer': 'c_1-68b3b84c-c42b-4582-9119-917484eb77ef'} 2019-02-27 11:33:49,681 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_4', 'm_0'] > {'time': 4, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_4-76d9311e-d5f6-4e91-bb83-72994095e2c6: buy 0 (t: 4, u: (0, 2.0), q: (1, 3))', 'partners': "['c_4-76d9311e-d5f6-4e91-bb83-72994095e2c6', 'm_0-61b223a2-ea24-4bfc-9bf3-aa85fa8a955a']", 'seller': 'm_0-61b223a2-ea24-4bfc-9bf3-aa85fa8a955a', 'buyer': 'c_4-76d9311e-d5f6-4e91-bb83-72994095e2c6'} 2019-02-27 11:33:49,681 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_0', 'm_4'] > {'time': 4, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_0-b6f40f78-35c5-4b76-9f90-53a459a66882: buy 0 (t: 4, u: (0, 2.0), q: (1, 4))', 'partners': "['c_0-b6f40f78-35c5-4b76-9f90-53a459a66882', 'm_4-4f6b8ebc-32b0-44d5-88d6-88b3cec0b489']", 'seller': 'm_4-4f6b8ebc-32b0-44d5-88d6-88b3cec0b489', 'buyer': 'c_0-b6f40f78-35c5-4b76-9f90-53a459a66882'} 2019-02-27 11:33:49,682 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_1', 'm_2'] > {'time': 2, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_1-68b3b84c-c42b-4582-9119-917484eb77ef: buy 0 (t: 2, u: (0, 2.0), q: (1, 3))', 'partners': "['c_1-68b3b84c-c42b-4582-9119-917484eb77ef', 'm_2-f4d60475-9842-4006-8513-ca39a2379160']", 'seller': 'm_2-f4d60475-9842-4006-8513-ca39a2379160', 'buyer': 'c_1-68b3b84c-c42b-4582-9119-917484eb77ef'} 2019-02-27 11:33:49,682 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_4', 'm_2'] > {'time': 2, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_4-76d9311e-d5f6-4e91-bb83-72994095e2c6: buy 0 (t: 2, u: (0, 2.0), q: (1, 3))', 'partners': "['c_4-76d9311e-d5f6-4e91-bb83-72994095e2c6', 'm_2-f4d60475-9842-4006-8513-ca39a2379160']", 'seller': 'm_2-f4d60475-9842-4006-8513-ca39a2379160', 'buyer': 'c_4-76d9311e-d5f6-4e91-bb83-72994095e2c6'} 2019-02-27 11:33:49,682 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_0', 'm_0'] > {'time': 2, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_0-b6f40f78-35c5-4b76-9f90-53a459a66882: buy 0 (t: 2, u: (0, 2.0), q: (1, 4))', 'partners': "['c_0-b6f40f78-35c5-4b76-9f90-53a459a66882', 'm_0-61b223a2-ea24-4bfc-9bf3-aa85fa8a955a']", 'seller': 'm_0-61b223a2-ea24-4bfc-9bf3-aa85fa8a955a', 'buyer': 'c_0-b6f40f78-35c5-4b76-9f90-53a459a66882'} 2019-02-27 11:33:49,683 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_1', 'm_3'] > {'time': 3, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_1-68b3b84c-c42b-4582-9119-917484eb77ef: buy 0 (t: 3, u: (0, 2.0), q: (1, 4))', 'partners': "['c_1-68b3b84c-c42b-4582-9119-917484eb77ef', 'm_3-418c12ae-b8cd-4e28-a9a8-b998b4ef7df6']", 'seller': 'm_3-418c12ae-b8cd-4e28-a9a8-b998b4ef7df6', 'buyer': 'c_1-68b3b84c-c42b-4582-9119-917484eb77ef'} 2019-02-27 11:33:49,683 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_4', 'm_3'] > {'time': 2, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_4-76d9311e-d5f6-4e91-bb83-72994095e2c6: buy 0 (t: 2, u: (0, 2.0), q: (1, 3))', 'partners': "['c_4-76d9311e-d5f6-4e91-bb83-72994095e2c6', 'm_3-418c12ae-b8cd-4e28-a9a8-b998b4ef7df6']", 'seller': 'm_3-418c12ae-b8cd-4e28-a9a8-b998b4ef7df6', 'buyer': 'c_4-76d9311e-d5f6-4e91-bb83-72994095e2c6'} 2019-02-27 11:33:49,683 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_2', 'm_4'] > {'time': 2, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_2-c1142518-c4d8-4f80-9889-693a093ef989: buy 0 (t: 2, u: (0, 2.0), q: (1, 4))', 'partners': "['c_2-c1142518-c4d8-4f80-9889-693a093ef989', 'm_4-4f6b8ebc-32b0-44d5-88d6-88b3cec0b489']", 'seller': 'm_4-4f6b8ebc-32b0-44d5-88d6-88b3cec0b489', 'buyer': 'c_2-c1142518-c4d8-4f80-9889-693a093ef989'} 2019-02-27 11:33:49,684 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_0', 'm_1'] > {'time': 3, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_0-b6f40f78-35c5-4b76-9f90-53a459a66882: buy 0 (t: 3, u: (0, 2.0), q: (1, 3))', 'partners': "['c_0-b6f40f78-35c5-4b76-9f90-53a459a66882', 'm_1-b789f15d-3508-464a-8717-8ba1da159754']", 'seller': 'm_1-b789f15d-3508-464a-8717-8ba1da159754', 'buyer': 'c_0-b6f40f78-35c5-4b76-9f90-53a459a66882'} 2019-02-27 11:33:49,684 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_0', 'm_2'] > {'time': 3, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_0-b6f40f78-35c5-4b76-9f90-53a459a66882: buy 0 (t: 3, u: (0, 2.0), q: (1, 3))', 'partners': "['c_0-b6f40f78-35c5-4b76-9f90-53a459a66882', 'm_2-f4d60475-9842-4006-8513-ca39a2379160']", 'seller': 'm_2-f4d60475-9842-4006-8513-ca39a2379160', 'buyer': 'c_0-b6f40f78-35c5-4b76-9f90-53a459a66882'} 2019-02-27 11:33:49,684 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_3', 'm_4'] > {'time': 4, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_3-0230100d-3633-49be-bb01-4928b35e59bc: buy 0 (t: 4, u: (0, 2.0), q: (1, 4))', 'partners': "['c_3-0230100d-3633-49be-bb01-4928b35e59bc', 'm_4-4f6b8ebc-32b0-44d5-88d6-88b3cec0b489']", 'seller': 'm_4-4f6b8ebc-32b0-44d5-88d6-88b3cec0b489', 'buyer': 'c_3-0230100d-3633-49be-bb01-4928b35e59bc'} 2019-02-27 11:33:49,685 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_2', 'm_3'] > {'time': 3, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_2-c1142518-c4d8-4f80-9889-693a093ef989: buy 0 (t: 3, u: (0, 2.0), q: (1, 4))', 'partners': "['c_2-c1142518-c4d8-4f80-9889-693a093ef989', 'm_3-418c12ae-b8cd-4e28-a9a8-b998b4ef7df6']", 'seller': 'm_3-418c12ae-b8cd-4e28-a9a8-b998b4ef7df6', 'buyer': 'c_2-c1142518-c4d8-4f80-9889-693a093ef989'} 2019-02-27 11:33:49,685 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_4', 'm_4'] > {'time': 2, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_4-76d9311e-d5f6-4e91-bb83-72994095e2c6: buy 0 (t: 2, u: (0, 2.0), q: (1, 3))', 'partners': "['c_4-76d9311e-d5f6-4e91-bb83-72994095e2c6', 'm_4-4f6b8ebc-32b0-44d5-88d6-88b3cec0b489']", 'seller': 'm_4-4f6b8ebc-32b0-44d5-88d6-88b3cec0b489', 'buyer': 'c_4-76d9311e-d5f6-4e91-bb83-72994095e2c6'} 2019-02-27 11:33:49,685 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_3', 'm_3'] > {'time': 2, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_3-0230100d-3633-49be-bb01-4928b35e59bc: buy 0 (t: 2, u: (0, 2.0), q: (1, 3))', 'partners': "['c_3-0230100d-3633-49be-bb01-4928b35e59bc', 'm_3-418c12ae-b8cd-4e28-a9a8-b998b4ef7df6']", 'seller': 'm_3-418c12ae-b8cd-4e28-a9a8-b998b4ef7df6', 'buyer': 'c_3-0230100d-3633-49be-bb01-4928b35e59bc'} 2019-02-27 11:33:49,685 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_2', 'm_0'] > {'time': 2, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_2-c1142518-c4d8-4f80-9889-693a093ef989: buy 0 (t: 2, u: (0, 2.0), q: (1, 4))', 'partners': "['c_2-c1142518-c4d8-4f80-9889-693a093ef989', 'm_0-61b223a2-ea24-4bfc-9bf3-aa85fa8a955a']", 'seller': 'm_0-61b223a2-ea24-4bfc-9bf3-aa85fa8a955a', 'buyer': 'c_2-c1142518-c4d8-4f80-9889-693a093ef989'} 2019-02-27 11:33:49,686 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_4', 'm_0'] > {'time': 2, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_4-76d9311e-d5f6-4e91-bb83-72994095e2c6: buy 0 (t: 2, u: (0, 2.0), q: (1, 3))', 'partners': "['c_4-76d9311e-d5f6-4e91-bb83-72994095e2c6', 'm_0-61b223a2-ea24-4bfc-9bf3-aa85fa8a955a']", 'seller': 'm_0-61b223a2-ea24-4bfc-9bf3-aa85fa8a955a', 'buyer': 'c_4-76d9311e-d5f6-4e91-bb83-72994095e2c6'} 2019-02-27 11:33:49,686 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_2', 'm_2'] > {'time': 4, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_2-c1142518-c4d8-4f80-9889-693a093ef989: buy 0 (t: 4, u: (0, 2.0), q: (1, 3))', 'partners': "['c_2-c1142518-c4d8-4f80-9889-693a093ef989', 'm_2-f4d60475-9842-4006-8513-ca39a2379160']", 'seller': 'm_2-f4d60475-9842-4006-8513-ca39a2379160', 'buyer': 'c_2-c1142518-c4d8-4f80-9889-693a093ef989'} 2019-02-27 11:33:49,686 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_3', 'm_1'] > {'time': 4, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_3-0230100d-3633-49be-bb01-4928b35e59bc: buy 0 (t: 4, u: (0, 2.0), q: (1, 4))', 'partners': "['c_3-0230100d-3633-49be-bb01-4928b35e59bc', 'm_1-b789f15d-3508-464a-8717-8ba1da159754']", 'seller': 'm_1-b789f15d-3508-464a-8717-8ba1da159754', 'buyer': 'c_3-0230100d-3633-49be-bb01-4928b35e59bc'} 2019-02-27 11:33:49,687 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_3', 'm_3'] > {'time': 4, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_3-0230100d-3633-49be-bb01-4928b35e59bc: buy 0 (t: 4, u: (0, 2.0), q: (1, 4))', 'partners': "['c_3-0230100d-3633-49be-bb01-4928b35e59bc', 'm_3-418c12ae-b8cd-4e28-a9a8-b998b4ef7df6']", 'seller': 'm_3-418c12ae-b8cd-4e28-a9a8-b998b4ef7df6', 'buyer': 'c_3-0230100d-3633-49be-bb01-4928b35e59bc'} 2019-02-27 11:33:49,687 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_3', 'm_2'] > {'time': 4, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_3-0230100d-3633-49be-bb01-4928b35e59bc: buy 0 (t: 4, u: (0, 2.0), q: (1, 4))', 'partners': "['c_3-0230100d-3633-49be-bb01-4928b35e59bc', 'm_2-f4d60475-9842-4006-8513-ca39a2379160']", 'seller': 'm_2-f4d60475-9842-4006-8513-ca39a2379160', 'buyer': 'c_3-0230100d-3633-49be-bb01-4928b35e59bc'} 2019-02-27 11:33:49,687 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_4', 'm_2'] > {'time': 1, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_4-76d9311e-d5f6-4e91-bb83-72994095e2c6: buy 0 (t: 1, u: (0, 2.0), q: (1, 4))', 'partners': "['c_4-76d9311e-d5f6-4e91-bb83-72994095e2c6', 'm_2-f4d60475-9842-4006-8513-ca39a2379160']", 'seller': 'm_2-f4d60475-9842-4006-8513-ca39a2379160', 'buyer': 'c_4-76d9311e-d5f6-4e91-bb83-72994095e2c6'} 2019-02-27 11:33:49,688 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_1', 'm_4'] > {'time': 4, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_1-68b3b84c-c42b-4582-9119-917484eb77ef: buy 0 (t: 4, u: (0, 2.0), q: (1, 3))', 'partners': "['c_1-68b3b84c-c42b-4582-9119-917484eb77ef', 'm_4-4f6b8ebc-32b0-44d5-88d6-88b3cec0b489']", 'seller': 'm_4-4f6b8ebc-32b0-44d5-88d6-88b3cec0b489', 'buyer': 'c_1-68b3b84c-c42b-4582-9119-917484eb77ef'} 2019-02-27 11:33:49,688 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_2', 'm_3'] > {'time': 4, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_2-c1142518-c4d8-4f80-9889-693a093ef989: buy 0 (t: 4, u: (0, 2.0), q: (1, 3))', 'partners': "['c_2-c1142518-c4d8-4f80-9889-693a093ef989', 'm_3-418c12ae-b8cd-4e28-a9a8-b998b4ef7df6']", 'seller': 'm_3-418c12ae-b8cd-4e28-a9a8-b998b4ef7df6', 'buyer': 'c_2-c1142518-c4d8-4f80-9889-693a093ef989'} 2019-02-27 11:33:49,688 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_0', 'm_4'] > {'time': 3, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_0-b6f40f78-35c5-4b76-9f90-53a459a66882: buy 0 (t: 3, u: (0, 2.0), q: (1, 3))', 'partners': "['c_0-b6f40f78-35c5-4b76-9f90-53a459a66882', 'm_4-4f6b8ebc-32b0-44d5-88d6-88b3cec0b489']", 'seller': 'm_4-4f6b8ebc-32b0-44d5-88d6-88b3cec0b489', 'buyer': 'c_0-b6f40f78-35c5-4b76-9f90-53a459a66882'} 2019-02-27 11:33:49,688 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_1', 'm_4'] > {'time': 2, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_1-68b3b84c-c42b-4582-9119-917484eb77ef: buy 0 (t: 2, u: (0, 2.0), q: (1, 3))', 'partners': "['c_1-68b3b84c-c42b-4582-9119-917484eb77ef', 'm_4-4f6b8ebc-32b0-44d5-88d6-88b3cec0b489']", 'seller': 'm_4-4f6b8ebc-32b0-44d5-88d6-88b3cec0b489', 'buyer': 'c_1-68b3b84c-c42b-4582-9119-917484eb77ef'} 2019-02-27 11:33:49,689 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_1', 'm_0'] > {'time': 2, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_1-68b3b84c-c42b-4582-9119-917484eb77ef: buy 0 (t: 2, u: (0, 2.0), q: (1, 3))', 'partners': "['c_1-68b3b84c-c42b-4582-9119-917484eb77ef', 'm_0-61b223a2-ea24-4bfc-9bf3-aa85fa8a955a']", 'seller': 'm_0-61b223a2-ea24-4bfc-9bf3-aa85fa8a955a', 'buyer': 'c_1-68b3b84c-c42b-4582-9119-917484eb77ef'} 2019-02-27 11:33:49,689 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_0', 'm_2'] > {'time': 2, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_0-b6f40f78-35c5-4b76-9f90-53a459a66882: buy 0 (t: 2, u: (0, 2.0), q: (1, 4))', 'partners': "['c_0-b6f40f78-35c5-4b76-9f90-53a459a66882', 'm_2-f4d60475-9842-4006-8513-ca39a2379160']", 'seller': 'm_2-f4d60475-9842-4006-8513-ca39a2379160', 'buyer': 'c_0-b6f40f78-35c5-4b76-9f90-53a459a66882'} 2019-02-27 11:33:49,689 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_0', 'm_4'] > {'time': 1, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_0-b6f40f78-35c5-4b76-9f90-53a459a66882: buy 0 (t: 1, u: (0, 2.0), q: (1, 3))', 'partners': "['c_0-b6f40f78-35c5-4b76-9f90-53a459a66882', 'm_4-4f6b8ebc-32b0-44d5-88d6-88b3cec0b489']", 'seller': 'm_4-4f6b8ebc-32b0-44d5-88d6-88b3cec0b489', 'buyer': 'c_0-b6f40f78-35c5-4b76-9f90-53a459a66882'} 2019-02-27 11:33:49,690 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_4', 'm_3'] > {'time': 1, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_4-76d9311e-d5f6-4e91-bb83-72994095e2c6: buy 0 (t: 1, u: (0, 2.0), q: (1, 4))', 'partners': "['c_4-76d9311e-d5f6-4e91-bb83-72994095e2c6', 'm_3-418c12ae-b8cd-4e28-a9a8-b998b4ef7df6']", 'seller': 'm_3-418c12ae-b8cd-4e28-a9a8-b998b4ef7df6', 'buyer': 'c_4-76d9311e-d5f6-4e91-bb83-72994095e2c6'} 2019-02-27 11:33:49,690 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_4', 'm_0'] > {'time': 3, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_4-76d9311e-d5f6-4e91-bb83-72994095e2c6: buy 0 (t: 3, u: (0, 2.0), q: (1, 4))', 'partners': "['c_4-76d9311e-d5f6-4e91-bb83-72994095e2c6', 'm_0-61b223a2-ea24-4bfc-9bf3-aa85fa8a955a']", 'seller': 'm_0-61b223a2-ea24-4bfc-9bf3-aa85fa8a955a', 'buyer': 'c_4-76d9311e-d5f6-4e91-bb83-72994095e2c6'} 2019-02-27 11:33:49,690 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_2', 'm_2'] > {'time': 1, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_2-c1142518-c4d8-4f80-9889-693a093ef989: buy 0 (t: 1, u: (0, 2.0), q: (1, 3))', 'partners': "['c_2-c1142518-c4d8-4f80-9889-693a093ef989', 'm_2-f4d60475-9842-4006-8513-ca39a2379160']", 'seller': 'm_2-f4d60475-9842-4006-8513-ca39a2379160', 'buyer': 'c_2-c1142518-c4d8-4f80-9889-693a093ef989'} 2019-02-27 11:33:49,690 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_0', 'm_2'] > {'time': 4, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_0-b6f40f78-35c5-4b76-9f90-53a459a66882: buy 0 (t: 4, u: (0, 2.0), q: (1, 4))', 'partners': "['c_0-b6f40f78-35c5-4b76-9f90-53a459a66882', 'm_2-f4d60475-9842-4006-8513-ca39a2379160']", 'seller': 'm_2-f4d60475-9842-4006-8513-ca39a2379160', 'buyer': 'c_0-b6f40f78-35c5-4b76-9f90-53a459a66882'} 2019-02-27 11:33:49,691 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_1', 'm_3'] > {'time': 2, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_1-68b3b84c-c42b-4582-9119-917484eb77ef: buy 0 (t: 2, u: (0, 2.0), q: (1, 3))', 'partners': "['c_1-68b3b84c-c42b-4582-9119-917484eb77ef', 'm_3-418c12ae-b8cd-4e28-a9a8-b998b4ef7df6']", 'seller': 'm_3-418c12ae-b8cd-4e28-a9a8-b998b4ef7df6', 'buyer': 'c_1-68b3b84c-c42b-4582-9119-917484eb77ef'} 2019-02-27 11:33:49,691 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_0', 'm_0'] > {'time': 4, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_0-b6f40f78-35c5-4b76-9f90-53a459a66882: buy 0 (t: 4, u: (0, 2.0), q: (1, 4))', 'partners': "['c_0-b6f40f78-35c5-4b76-9f90-53a459a66882', 'm_0-61b223a2-ea24-4bfc-9bf3-aa85fa8a955a']", 'seller': 'm_0-61b223a2-ea24-4bfc-9bf3-aa85fa8a955a', 'buyer': 'c_0-b6f40f78-35c5-4b76-9f90-53a459a66882'} 2019-02-27 11:33:49,691 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_3', 'm_2'] > {'time': 1, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_3-0230100d-3633-49be-bb01-4928b35e59bc: buy 0 (t: 1, u: (0, 2.0), q: (1, 4))', 'partners': "['c_3-0230100d-3633-49be-bb01-4928b35e59bc', 'm_2-f4d60475-9842-4006-8513-ca39a2379160']", 'seller': 'm_2-f4d60475-9842-4006-8513-ca39a2379160', 'buyer': 'c_3-0230100d-3633-49be-bb01-4928b35e59bc'} 2019-02-27 11:33:49,692 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_2', 'm_1'] > {'time': 2, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_2-c1142518-c4d8-4f80-9889-693a093ef989: buy 0 (t: 2, u: (0, 2.0), q: (1, 4))', 'partners': "['c_2-c1142518-c4d8-4f80-9889-693a093ef989', 'm_1-b789f15d-3508-464a-8717-8ba1da159754']", 'seller': 'm_1-b789f15d-3508-464a-8717-8ba1da159754', 'buyer': 'c_2-c1142518-c4d8-4f80-9889-693a093ef989'} 2019-02-27 11:33:49,692 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_3', 'm_0'] > {'time': 1, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_3-0230100d-3633-49be-bb01-4928b35e59bc: buy 0 (t: 1, u: (0, 2.0), q: (1, 4))', 'partners': "['c_3-0230100d-3633-49be-bb01-4928b35e59bc', 'm_0-61b223a2-ea24-4bfc-9bf3-aa85fa8a955a']", 'seller': 'm_0-61b223a2-ea24-4bfc-9bf3-aa85fa8a955a', 'buyer': 'c_3-0230100d-3633-49be-bb01-4928b35e59bc'} 2019-02-27 11:33:49,692 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_3', 'm_1'] > {'time': 2, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_3-0230100d-3633-49be-bb01-4928b35e59bc: buy 0 (t: 2, u: (0, 2.0), q: (1, 3))', 'partners': "['c_3-0230100d-3633-49be-bb01-4928b35e59bc', 'm_1-b789f15d-3508-464a-8717-8ba1da159754']", 'seller': 'm_1-b789f15d-3508-464a-8717-8ba1da159754', 'buyer': 'c_3-0230100d-3633-49be-bb01-4928b35e59bc'} 2019-02-27 11:33:49,693 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_2', 'm_0'] > {'time': 4, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_2-c1142518-c4d8-4f80-9889-693a093ef989: buy 0 (t: 4, u: (0, 2.0), q: (1, 3))', 'partners': "['c_2-c1142518-c4d8-4f80-9889-693a093ef989', 'm_0-61b223a2-ea24-4bfc-9bf3-aa85fa8a955a']", 'seller': 'm_0-61b223a2-ea24-4bfc-9bf3-aa85fa8a955a', 'buyer': 'c_2-c1142518-c4d8-4f80-9889-693a093ef989'} 2019-02-27 11:33:49,693 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_1', 'm_3'] > {'time': 1, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_1-68b3b84c-c42b-4582-9119-917484eb77ef: buy 0 (t: 1, u: (0, 2.0), q: (1, 3))', 'partners': "['c_1-68b3b84c-c42b-4582-9119-917484eb77ef', 'm_3-418c12ae-b8cd-4e28-a9a8-b998b4ef7df6']", 'seller': 'm_3-418c12ae-b8cd-4e28-a9a8-b998b4ef7df6', 'buyer': 'c_1-68b3b84c-c42b-4582-9119-917484eb77ef'} 2019-02-27 11:33:49,693 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_0', 'm_0'] > {'time': 3, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_0-b6f40f78-35c5-4b76-9f90-53a459a66882: buy 0 (t: 3, u: (0, 2.0), q: (1, 3))', 'partners': "['c_0-b6f40f78-35c5-4b76-9f90-53a459a66882', 'm_0-61b223a2-ea24-4bfc-9bf3-aa85fa8a955a']", 'seller': 'm_0-61b223a2-ea24-4bfc-9bf3-aa85fa8a955a', 'buyer': 'c_0-b6f40f78-35c5-4b76-9f90-53a459a66882'} 2019-02-27 11:33:49,694 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_4', 'm_3'] > {'time': 4, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_4-76d9311e-d5f6-4e91-bb83-72994095e2c6: buy 0 (t: 4, u: (0, 2.0), q: (1, 3))', 'partners': "['c_4-76d9311e-d5f6-4e91-bb83-72994095e2c6', 'm_3-418c12ae-b8cd-4e28-a9a8-b998b4ef7df6']", 'seller': 'm_3-418c12ae-b8cd-4e28-a9a8-b998b4ef7df6', 'buyer': 'c_4-76d9311e-d5f6-4e91-bb83-72994095e2c6'} 2019-02-27 11:33:49,694 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_1', 'm_1'] > {'time': 4, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_1-68b3b84c-c42b-4582-9119-917484eb77ef: buy 0 (t: 4, u: (0, 2.0), q: (1, 3))', 'partners': "['c_1-68b3b84c-c42b-4582-9119-917484eb77ef', 'm_1-b789f15d-3508-464a-8717-8ba1da159754']", 'seller': 'm_1-b789f15d-3508-464a-8717-8ba1da159754', 'buyer': 'c_1-68b3b84c-c42b-4582-9119-917484eb77ef'} 2019-02-27 11:33:49,694 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_0', 'm_3'] > {'time': 1, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_0-b6f40f78-35c5-4b76-9f90-53a459a66882: buy 0 (t: 1, u: (0, 2.0), q: (1, 3))', 'partners': "['c_0-b6f40f78-35c5-4b76-9f90-53a459a66882', 'm_3-418c12ae-b8cd-4e28-a9a8-b998b4ef7df6']", 'seller': 'm_3-418c12ae-b8cd-4e28-a9a8-b998b4ef7df6', 'buyer': 'c_0-b6f40f78-35c5-4b76-9f90-53a459a66882'} 2019-02-27 11:33:49,695 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_2', 'm_3'] > {'time': 2, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_2-c1142518-c4d8-4f80-9889-693a093ef989: buy 0 (t: 2, u: (0, 2.0), q: (1, 4))', 'partners': "['c_2-c1142518-c4d8-4f80-9889-693a093ef989', 'm_3-418c12ae-b8cd-4e28-a9a8-b998b4ef7df6']", 'seller': 'm_3-418c12ae-b8cd-4e28-a9a8-b998b4ef7df6', 'buyer': 'c_2-c1142518-c4d8-4f80-9889-693a093ef989'} 2019-02-27 11:33:49,695 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_0', 'm_4'] > {'time': 2, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_0-b6f40f78-35c5-4b76-9f90-53a459a66882: buy 0 (t: 2, u: (0, 2.0), q: (1, 4))', 'partners': "['c_0-b6f40f78-35c5-4b76-9f90-53a459a66882', 'm_4-4f6b8ebc-32b0-44d5-88d6-88b3cec0b489']", 'seller': 'm_4-4f6b8ebc-32b0-44d5-88d6-88b3cec0b489', 'buyer': 'c_0-b6f40f78-35c5-4b76-9f90-53a459a66882'} 2019-02-27 11:33:49,696 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_4', 'm_1'] > {'time': 1, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_4-76d9311e-d5f6-4e91-bb83-72994095e2c6: buy 0 (t: 1, u: (0, 2.0), q: (1, 4))', 'partners': "['c_4-76d9311e-d5f6-4e91-bb83-72994095e2c6', 'm_1-b789f15d-3508-464a-8717-8ba1da159754']", 'seller': 'm_1-b789f15d-3508-464a-8717-8ba1da159754', 'buyer': 'c_4-76d9311e-d5f6-4e91-bb83-72994095e2c6'} 2019-02-27 11:33:49,697 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_1', 'm_1'] > {'time': 3, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_1-68b3b84c-c42b-4582-9119-917484eb77ef: buy 0 (t: 3, u: (0, 2.0), q: (1, 4))', 'partners': "['c_1-68b3b84c-c42b-4582-9119-917484eb77ef', 'm_1-b789f15d-3508-464a-8717-8ba1da159754']", 'seller': 'm_1-b789f15d-3508-464a-8717-8ba1da159754', 'buyer': 'c_1-68b3b84c-c42b-4582-9119-917484eb77ef'} 2019-02-27 11:33:49,698 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_4', 'm_1'] > {'time': 2, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_4-76d9311e-d5f6-4e91-bb83-72994095e2c6: buy 0 (t: 2, u: (0, 2.0), q: (1, 3))', 'partners': "['c_4-76d9311e-d5f6-4e91-bb83-72994095e2c6', 'm_1-b789f15d-3508-464a-8717-8ba1da159754']", 'seller': 'm_1-b789f15d-3508-464a-8717-8ba1da159754', 'buyer': 'c_4-76d9311e-d5f6-4e91-bb83-72994095e2c6'} 2019-02-27 11:33:49,698 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_2', 'm_4'] > {'time': 4, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_2-c1142518-c4d8-4f80-9889-693a093ef989: buy 0 (t: 4, u: (0, 2.0), q: (1, 3))', 'partners': "['c_2-c1142518-c4d8-4f80-9889-693a093ef989', 'm_4-4f6b8ebc-32b0-44d5-88d6-88b3cec0b489']", 'seller': 'm_4-4f6b8ebc-32b0-44d5-88d6-88b3cec0b489', 'buyer': 'c_2-c1142518-c4d8-4f80-9889-693a093ef989'} 2019-02-27 11:33:49,698 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_2', 'm_3'] > {'time': 1, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_2-c1142518-c4d8-4f80-9889-693a093ef989: buy 0 (t: 1, u: (0, 2.0), q: (1, 3))', 'partners': "['c_2-c1142518-c4d8-4f80-9889-693a093ef989', 'm_3-418c12ae-b8cd-4e28-a9a8-b998b4ef7df6']", 'seller': 'm_3-418c12ae-b8cd-4e28-a9a8-b998b4ef7df6', 'buyer': 'c_2-c1142518-c4d8-4f80-9889-693a093ef989'} 2019-02-27 11:33:49,699 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_3', 'm_4'] > {'time': 2, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_3-0230100d-3633-49be-bb01-4928b35e59bc: buy 0 (t: 2, u: (0, 2.0), q: (1, 3))', 'partners': "['c_3-0230100d-3633-49be-bb01-4928b35e59bc', 'm_4-4f6b8ebc-32b0-44d5-88d6-88b3cec0b489']", 'seller': 'm_4-4f6b8ebc-32b0-44d5-88d6-88b3cec0b489', 'buyer': 'c_3-0230100d-3633-49be-bb01-4928b35e59bc'} 2019-02-27 11:33:49,699 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_4', 'm_1'] > {'time': 4, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_4-76d9311e-d5f6-4e91-bb83-72994095e2c6: buy 0 (t: 4, u: (0, 2.0), q: (1, 3))', 'partners': "['c_4-76d9311e-d5f6-4e91-bb83-72994095e2c6', 'm_1-b789f15d-3508-464a-8717-8ba1da159754']", 'seller': 'm_1-b789f15d-3508-464a-8717-8ba1da159754', 'buyer': 'c_4-76d9311e-d5f6-4e91-bb83-72994095e2c6'} 2019-02-27 11:33:49,699 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_1', 'm_4'] > {'time': 3, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_1-68b3b84c-c42b-4582-9119-917484eb77ef: buy 0 (t: 3, u: (0, 2.0), q: (1, 4))', 'partners': "['c_1-68b3b84c-c42b-4582-9119-917484eb77ef', 'm_4-4f6b8ebc-32b0-44d5-88d6-88b3cec0b489']", 'seller': 'm_4-4f6b8ebc-32b0-44d5-88d6-88b3cec0b489', 'buyer': 'c_1-68b3b84c-c42b-4582-9119-917484eb77ef'} 2019-02-27 11:33:49,700 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_2', 'm_4'] > {'time': 1, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_2-c1142518-c4d8-4f80-9889-693a093ef989: buy 0 (t: 1, u: (0, 2.0), q: (1, 3))', 'partners': "['c_2-c1142518-c4d8-4f80-9889-693a093ef989', 'm_4-4f6b8ebc-32b0-44d5-88d6-88b3cec0b489']", 'seller': 'm_4-4f6b8ebc-32b0-44d5-88d6-88b3cec0b489', 'buyer': 'c_2-c1142518-c4d8-4f80-9889-693a093ef989'} 2019-02-27 11:33:49,700 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_2', 'm_0'] > {'time': 3, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_2-c1142518-c4d8-4f80-9889-693a093ef989: buy 0 (t: 3, u: (0, 2.0), q: (1, 4))', 'partners': "['c_2-c1142518-c4d8-4f80-9889-693a093ef989', 'm_0-61b223a2-ea24-4bfc-9bf3-aa85fa8a955a']", 'seller': 'm_0-61b223a2-ea24-4bfc-9bf3-aa85fa8a955a', 'buyer': 'c_2-c1142518-c4d8-4f80-9889-693a093ef989'} 2019-02-27 11:33:49,700 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_1', 'm_1'] > {'time': 2, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_1-68b3b84c-c42b-4582-9119-917484eb77ef: buy 0 (t: 2, u: (0, 2.0), q: (1, 3))', 'partners': "['c_1-68b3b84c-c42b-4582-9119-917484eb77ef', 'm_1-b789f15d-3508-464a-8717-8ba1da159754']", 'seller': 'm_1-b789f15d-3508-464a-8717-8ba1da159754', 'buyer': 'c_1-68b3b84c-c42b-4582-9119-917484eb77ef'} 2019-02-27 11:33:49,700 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_4', 'm_2'] > {'time': 3, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_4-76d9311e-d5f6-4e91-bb83-72994095e2c6: buy 0 (t: 3, u: (0, 2.0), q: (1, 4))', 'partners': "['c_4-76d9311e-d5f6-4e91-bb83-72994095e2c6', 'm_2-f4d60475-9842-4006-8513-ca39a2379160']", 'seller': 'm_2-f4d60475-9842-4006-8513-ca39a2379160', 'buyer': 'c_4-76d9311e-d5f6-4e91-bb83-72994095e2c6'} 2019-02-27 11:33:49,701 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_4', 'm_4'] > {'time': 1, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_4-76d9311e-d5f6-4e91-bb83-72994095e2c6: buy 0 (t: 1, u: (0, 2.0), q: (1, 4))', 'partners': "['c_4-76d9311e-d5f6-4e91-bb83-72994095e2c6', 'm_4-4f6b8ebc-32b0-44d5-88d6-88b3cec0b489']", 'seller': 'm_4-4f6b8ebc-32b0-44d5-88d6-88b3cec0b489', 'buyer': 'c_4-76d9311e-d5f6-4e91-bb83-72994095e2c6'} 2019-02-27 11:33:49,701 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_2', 'm_1'] > {'time': 1, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_2-c1142518-c4d8-4f80-9889-693a093ef989: buy 0 (t: 1, u: (0, 2.0), q: (1, 3))', 'partners': "['c_2-c1142518-c4d8-4f80-9889-693a093ef989', 'm_1-b789f15d-3508-464a-8717-8ba1da159754']", 'seller': 'm_1-b789f15d-3508-464a-8717-8ba1da159754', 'buyer': 'c_2-c1142518-c4d8-4f80-9889-693a093ef989'} 2019-02-27 11:33:49,701 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_0', 'm_0'] > {'time': 1, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_0-b6f40f78-35c5-4b76-9f90-53a459a66882: buy 0 (t: 1, u: (0, 2.0), q: (1, 3))', 'partners': "['c_0-b6f40f78-35c5-4b76-9f90-53a459a66882', 'm_0-61b223a2-ea24-4bfc-9bf3-aa85fa8a955a']", 'seller': 'm_0-61b223a2-ea24-4bfc-9bf3-aa85fa8a955a', 'buyer': 'c_0-b6f40f78-35c5-4b76-9f90-53a459a66882'} 2019-02-27 11:33:49,702 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_2', 'm_0'] > {'time': 1, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_2-c1142518-c4d8-4f80-9889-693a093ef989: buy 0 (t: 1, u: (0, 2.0), q: (1, 3))', 'partners': "['c_2-c1142518-c4d8-4f80-9889-693a093ef989', 'm_0-61b223a2-ea24-4bfc-9bf3-aa85fa8a955a']", 'seller': 'm_0-61b223a2-ea24-4bfc-9bf3-aa85fa8a955a', 'buyer': 'c_2-c1142518-c4d8-4f80-9889-693a093ef989'} 2019-02-27 11:33:49,702 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_2', 'm_2'] > {'time': 3, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_2-c1142518-c4d8-4f80-9889-693a093ef989: buy 0 (t: 3, u: (0, 2.0), q: (1, 4))', 'partners': "['c_2-c1142518-c4d8-4f80-9889-693a093ef989', 'm_2-f4d60475-9842-4006-8513-ca39a2379160']", 'seller': 'm_2-f4d60475-9842-4006-8513-ca39a2379160', 'buyer': 'c_2-c1142518-c4d8-4f80-9889-693a093ef989'} 2019-02-27 11:33:49,702 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_0', 'm_1'] > {'time': 4, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_0-b6f40f78-35c5-4b76-9f90-53a459a66882: buy 0 (t: 4, u: (0, 2.0), q: (1, 4))', 'partners': "['c_0-b6f40f78-35c5-4b76-9f90-53a459a66882', 'm_1-b789f15d-3508-464a-8717-8ba1da159754']", 'seller': 'm_1-b789f15d-3508-464a-8717-8ba1da159754', 'buyer': 'c_0-b6f40f78-35c5-4b76-9f90-53a459a66882'} 2019-02-27 11:33:49,703 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_2', 'm_1'] > {'time': 4, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_2-c1142518-c4d8-4f80-9889-693a093ef989: buy 0 (t: 4, u: (0, 2.0), q: (1, 3))', 'partners': "['c_2-c1142518-c4d8-4f80-9889-693a093ef989', 'm_1-b789f15d-3508-464a-8717-8ba1da159754']", 'seller': 'm_1-b789f15d-3508-464a-8717-8ba1da159754', 'buyer': 'c_2-c1142518-c4d8-4f80-9889-693a093ef989'} 2019-02-27 11:33:49,703 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_4', 'm_4'] > {'time': 4, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_4-76d9311e-d5f6-4e91-bb83-72994095e2c6: buy 0 (t: 4, u: (0, 2.0), q: (1, 3))', 'partners': "['c_4-76d9311e-d5f6-4e91-bb83-72994095e2c6', 'm_4-4f6b8ebc-32b0-44d5-88d6-88b3cec0b489']", 'seller': 'm_4-4f6b8ebc-32b0-44d5-88d6-88b3cec0b489', 'buyer': 'c_4-76d9311e-d5f6-4e91-bb83-72994095e2c6'} 2019-02-27 11:33:49,703 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_3', 'm_3'] > {'time': 3, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_3-0230100d-3633-49be-bb01-4928b35e59bc: buy 0 (t: 3, u: (0, 2.0), q: (1, 4))', 'partners': "['c_3-0230100d-3633-49be-bb01-4928b35e59bc', 'm_3-418c12ae-b8cd-4e28-a9a8-b998b4ef7df6']", 'seller': 'm_3-418c12ae-b8cd-4e28-a9a8-b998b4ef7df6', 'buyer': 'c_3-0230100d-3633-49be-bb01-4928b35e59bc'} 2019-02-27 11:33:49,704 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_3', 'm_0'] > {'time': 4, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_3-0230100d-3633-49be-bb01-4928b35e59bc: buy 0 (t: 4, u: (0, 2.0), q: (1, 4))', 'partners': "['c_3-0230100d-3633-49be-bb01-4928b35e59bc', 'm_0-61b223a2-ea24-4bfc-9bf3-aa85fa8a955a']", 'seller': 'm_0-61b223a2-ea24-4bfc-9bf3-aa85fa8a955a', 'buyer': 'c_3-0230100d-3633-49be-bb01-4928b35e59bc'} 2019-02-27 11:33:49,704 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_2', 'm_2'] > {'time': 2, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_2-c1142518-c4d8-4f80-9889-693a093ef989: buy 0 (t: 2, u: (0, 2.0), q: (1, 4))', 'partners': "['c_2-c1142518-c4d8-4f80-9889-693a093ef989', 'm_2-f4d60475-9842-4006-8513-ca39a2379160']", 'seller': 'm_2-f4d60475-9842-4006-8513-ca39a2379160', 'buyer': 'c_2-c1142518-c4d8-4f80-9889-693a093ef989'} 2019-02-27 11:33:49,704 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_3', 'm_1'] > {'time': 1, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_3-0230100d-3633-49be-bb01-4928b35e59bc: buy 0 (t: 1, u: (0, 2.0), q: (1, 4))', 'partners': "['c_3-0230100d-3633-49be-bb01-4928b35e59bc', 'm_1-b789f15d-3508-464a-8717-8ba1da159754']", 'seller': 'm_1-b789f15d-3508-464a-8717-8ba1da159754', 'buyer': 'c_3-0230100d-3633-49be-bb01-4928b35e59bc'} 2019-02-27 11:33:49,705 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_4', 'm_4'] > {'time': 3, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_4-76d9311e-d5f6-4e91-bb83-72994095e2c6: buy 0 (t: 3, u: (0, 2.0), q: (1, 4))', 'partners': "['c_4-76d9311e-d5f6-4e91-bb83-72994095e2c6', 'm_4-4f6b8ebc-32b0-44d5-88d6-88b3cec0b489']", 'seller': 'm_4-4f6b8ebc-32b0-44d5-88d6-88b3cec0b489', 'buyer': 'c_4-76d9311e-d5f6-4e91-bb83-72994095e2c6'} 2019-02-27 11:33:49,705 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_1', 'm_0'] > {'time': 1, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_1-68b3b84c-c42b-4582-9119-917484eb77ef: buy 0 (t: 1, u: (0, 2.0), q: (1, 3))', 'partners': "['c_1-68b3b84c-c42b-4582-9119-917484eb77ef', 'm_0-61b223a2-ea24-4bfc-9bf3-aa85fa8a955a']", 'seller': 'm_0-61b223a2-ea24-4bfc-9bf3-aa85fa8a955a', 'buyer': 'c_1-68b3b84c-c42b-4582-9119-917484eb77ef'} 2019-02-27 11:33:49,706 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_1', 'm_0'] > {'time': 4, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_1-68b3b84c-c42b-4582-9119-917484eb77ef: buy 0 (t: 4, u: (0, 2.0), q: (1, 3))', 'partners': "['c_1-68b3b84c-c42b-4582-9119-917484eb77ef', 'm_0-61b223a2-ea24-4bfc-9bf3-aa85fa8a955a']", 'seller': 'm_0-61b223a2-ea24-4bfc-9bf3-aa85fa8a955a', 'buyer': 'c_1-68b3b84c-c42b-4582-9119-917484eb77ef'} 2019-02-27 11:33:49,706 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_0', 'm_1'] > {'time': 2, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_0-b6f40f78-35c5-4b76-9f90-53a459a66882: buy 0 (t: 2, u: (0, 2.0), q: (1, 4))', 'partners': "['c_0-b6f40f78-35c5-4b76-9f90-53a459a66882', 'm_1-b789f15d-3508-464a-8717-8ba1da159754']", 'seller': 'm_1-b789f15d-3508-464a-8717-8ba1da159754', 'buyer': 'c_0-b6f40f78-35c5-4b76-9f90-53a459a66882'} 2019-02-27 11:33:49,706 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_3', 'm_3'] > {'time': 1, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_3-0230100d-3633-49be-bb01-4928b35e59bc: buy 0 (t: 1, u: (0, 2.0), q: (1, 4))', 'partners': "['c_3-0230100d-3633-49be-bb01-4928b35e59bc', 'm_3-418c12ae-b8cd-4e28-a9a8-b998b4ef7df6']", 'seller': 'm_3-418c12ae-b8cd-4e28-a9a8-b998b4ef7df6', 'buyer': 'c_3-0230100d-3633-49be-bb01-4928b35e59bc'} 2019-02-27 11:33:49,707 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_3', 'm_0'] > {'time': 3, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_3-0230100d-3633-49be-bb01-4928b35e59bc: buy 0 (t: 3, u: (0, 2.0), q: (1, 4))', 'partners': "['c_3-0230100d-3633-49be-bb01-4928b35e59bc', 'm_0-61b223a2-ea24-4bfc-9bf3-aa85fa8a955a']", 'seller': 'm_0-61b223a2-ea24-4bfc-9bf3-aa85fa8a955a', 'buyer': 'c_3-0230100d-3633-49be-bb01-4928b35e59bc'} 2019-02-27 11:33:49,707 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_3', 'm_4'] > {'time': 3, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_3-0230100d-3633-49be-bb01-4928b35e59bc: buy 0 (t: 3, u: (0, 2.0), q: (1, 4))', 'partners': "['c_3-0230100d-3633-49be-bb01-4928b35e59bc', 'm_4-4f6b8ebc-32b0-44d5-88d6-88b3cec0b489']", 'seller': 'm_4-4f6b8ebc-32b0-44d5-88d6-88b3cec0b489', 'buyer': 'c_3-0230100d-3633-49be-bb01-4928b35e59bc'} 2019-02-27 11:33:49,708 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_3', 'm_1'] > {'time': 3, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_3-0230100d-3633-49be-bb01-4928b35e59bc: buy 0 (t: 3, u: (0, 2.0), q: (1, 4))', 'partners': "['c_3-0230100d-3633-49be-bb01-4928b35e59bc', 'm_1-b789f15d-3508-464a-8717-8ba1da159754']", 'seller': 'm_1-b789f15d-3508-464a-8717-8ba1da159754', 'buyer': 'c_3-0230100d-3633-49be-bb01-4928b35e59bc'} 2019-02-27 11:33:49,708 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_3', 'm_2'] > {'time': 2, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_3-0230100d-3633-49be-bb01-4928b35e59bc: buy 0 (t: 2, u: (0, 2.0), q: (1, 3))', 'partners': "['c_3-0230100d-3633-49be-bb01-4928b35e59bc', 'm_2-f4d60475-9842-4006-8513-ca39a2379160']", 'seller': 'm_2-f4d60475-9842-4006-8513-ca39a2379160', 'buyer': 'c_3-0230100d-3633-49be-bb01-4928b35e59bc'} 2019-02-27 11:33:49,709 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_0', 'm_1'] > {'time': 1, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_0-b6f40f78-35c5-4b76-9f90-53a459a66882: buy 0 (t: 1, u: (0, 2.0), q: (1, 3))', 'partners': "['c_0-b6f40f78-35c5-4b76-9f90-53a459a66882', 'm_1-b789f15d-3508-464a-8717-8ba1da159754']", 'seller': 'm_1-b789f15d-3508-464a-8717-8ba1da159754', 'buyer': 'c_0-b6f40f78-35c5-4b76-9f90-53a459a66882'} 2019-02-27 11:33:49,709 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_4', 'm_1'] > {'time': 3, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_4-76d9311e-d5f6-4e91-bb83-72994095e2c6: buy 0 (t: 3, u: (0, 2.0), q: (1, 4))', 'partners': "['c_4-76d9311e-d5f6-4e91-bb83-72994095e2c6', 'm_1-b789f15d-3508-464a-8717-8ba1da159754']", 'seller': 'm_1-b789f15d-3508-464a-8717-8ba1da159754', 'buyer': 'c_4-76d9311e-d5f6-4e91-bb83-72994095e2c6'} 2019-02-27 11:33:49,713 - INFO - 1/10 [20.00%]: m_0 requested negmas.sao.SAOMechanism[None] with ['c_3', 'm_0'] (ID 3dc8dea9-ce42-407b-9ee6-c83822cf68ba) 2019-02-27 11:33:49,713 - INFO - 1/10 [20.00%]: m_0-61b223a2-ea24-4bfc-9bf3-aa85fa8a955a request was accepted 2019-02-27 11:33:49,714 - INFO - 1/10 [20.00%]: m_1 requested negmas.sao.SAOMechanism[None] with ['c_3', 'm_1'] (ID d52865c5-6f63-4d88-94d5-5d1f56c393e8) 2019-02-27 11:33:49,715 - INFO - 1/10 [20.00%]: m_1-b789f15d-3508-464a-8717-8ba1da159754 request was accepted 2019-02-27 11:33:49,716 - INFO - 1/10 [20.00%]: m_2 requested negmas.sao.SAOMechanism[None] with ['c_3', 'm_2'] (ID fac762b4-4fab-4e6a-a1d4-da10fb70c08c) 2019-02-27 11:33:49,716 - INFO - 1/10 [20.00%]: m_2-f4d60475-9842-4006-8513-ca39a2379160 request was accepted 2019-02-27 11:33:49,717 - INFO - 1/10 [20.00%]: m_3 requested negmas.sao.SAOMechanism[None] with ['c_3', 'm_3'] (ID eebd3f29-4187-4eb6-a05f-0c5961c24040) 2019-02-27 11:33:49,718 - INFO - 1/10 [20.00%]: m_3-418c12ae-b8cd-4e28-a9a8-b998b4ef7df6 request was accepted 2019-02-27 11:33:49,719 - INFO - 1/10 [20.00%]: m_4 requested negmas.sao.SAOMechanism[None] with ['c_3', 'm_4'] (ID 37dc0933-b0e1-4105-8960-b17cd60256da) 2019-02-27 11:33:49,720 - INFO - 1/10 [20.00%]: m_4-4f6b8ebc-32b0-44d5-88d6-88b3cec0b489 request was accepted 2019-02-27 11:33:49,723 - INFO - 1/10 [20.00%]: m_0 requested negmas.sao.SAOMechanism[None] with ['c_2', 'm_0'] (ID 6193d5c5-444f-4aec-99b1-56cc48b1a8ac) 2019-02-27 11:33:49,723 - INFO - 1/10 [20.00%]: m_0-61b223a2-ea24-4bfc-9bf3-aa85fa8a955a request was accepted 2019-02-27 11:33:49,725 - INFO - 1/10 [20.00%]: m_1 requested negmas.sao.SAOMechanism[None] with ['c_2', 'm_1'] (ID eae07dec-3754-4a6b-a8a6-be49bc2c1fe5) 2019-02-27 11:33:49,725 - INFO - 1/10 [20.00%]: m_1-b789f15d-3508-464a-8717-8ba1da159754 request was accepted 2019-02-27 11:33:49,728 - INFO - 1/10 [20.00%]: m_2 requested negmas.sao.SAOMechanism[None] with ['c_2', 'm_2'] (ID cfa5ef07-24e0-4847-8294-9f3095cc69b7) 2019-02-27 11:33:49,728 - INFO - 1/10 [20.00%]: m_2-f4d60475-9842-4006-8513-ca39a2379160 request was accepted 2019-02-27 11:33:49,729 - INFO - 1/10 [20.00%]: m_3 requested negmas.sao.SAOMechanism[None] with ['c_2', 'm_3'] (ID 1d7320c4-d7b4-49a6-9b0b-f9e59e94a9be) 2019-02-27 11:33:49,730 - INFO - 1/10 [20.00%]: m_3-418c12ae-b8cd-4e28-a9a8-b998b4ef7df6 request was accepted 2019-02-27 11:33:49,732 - INFO - 1/10 [20.00%]: m_4 requested negmas.sao.SAOMechanism[None] with ['c_2', 'm_4'] (ID 8e7e0d05-d5b1-4bd6-a4c7-1ea0caebe829) 2019-02-27 11:33:49,733 - INFO - 1/10 [20.00%]: m_4-4f6b8ebc-32b0-44d5-88d6-88b3cec0b489 request was accepted 2019-02-27 11:33:49,736 - INFO - 1/10 [20.00%]: m_0 requested negmas.sao.SAOMechanism[None] with ['c_1', 'm_0'] (ID 1352e077-4c29-46ae-8e51-b5ef9be60ea4) 2019-02-27 11:33:49,737 - INFO - 1/10 [20.00%]: m_0-61b223a2-ea24-4bfc-9bf3-aa85fa8a955a request was accepted 2019-02-27 11:33:49,738 - INFO - 1/10 [20.00%]: m_1 requested negmas.sao.SAOMechanism[None] with ['c_1', 'm_1'] (ID e1a460a2-fd93-4c46-b806-fece24d32aa6) 2019-02-27 11:33:49,739 - INFO - 1/10 [20.00%]: m_1-b789f15d-3508-464a-8717-8ba1da159754 request was accepted 2019-02-27 11:33:49,740 - INFO - 1/10 [20.00%]: m_2 requested negmas.sao.SAOMechanism[None] with ['c_1', 'm_2'] (ID 520682d3-4a3d-4ef2-a2a3-12e6efaed15d) 2019-02-27 11:33:49,741 - INFO - 1/10 [20.00%]: m_2-f4d60475-9842-4006-8513-ca39a2379160 request was accepted 2019-02-27 11:33:49,742 - INFO - 1/10 [20.00%]: m_3 requested negmas.sao.SAOMechanism[None] with ['c_1', 'm_3'] (ID ce8d82e7-1fab-49cf-995e-2e2609b48221) 2019-02-27 11:33:49,744 - INFO - 1/10 [20.00%]: m_3-418c12ae-b8cd-4e28-a9a8-b998b4ef7df6 request was accepted 2019-02-27 11:33:49,746 - INFO - 1/10 [20.00%]: m_4 requested negmas.sao.SAOMechanism[None] with ['c_1', 'm_4'] (ID 8cb1397c-b147-4400-bda0-b009ec755e5b) 2019-02-27 11:33:49,747 - INFO - 1/10 [20.00%]: m_4-4f6b8ebc-32b0-44d5-88d6-88b3cec0b489 request was accepted 2019-02-27 11:33:49,751 - INFO - 1/10 [20.00%]: m_0 requested negmas.sao.SAOMechanism[None] with ['c_0', 'm_0'] (ID 78760edf-ee4c-454a-ad81-352e8d5aa099) 2019-02-27 11:33:49,751 - INFO - 1/10 [20.00%]: m_0-61b223a2-ea24-4bfc-9bf3-aa85fa8a955a request was accepted 2019-02-27 11:33:49,752 - INFO - 1/10 [20.00%]: m_1 requested negmas.sao.SAOMechanism[None] with ['c_0', 'm_1'] (ID 2fbbcbab-98f6-4a1f-82b6-e0a3e37dbee8) 2019-02-27 11:33:49,753 - INFO - 1/10 [20.00%]: m_1-b789f15d-3508-464a-8717-8ba1da159754 request was accepted 2019-02-27 11:33:49,755 - INFO - 1/10 [20.00%]: m_2 requested negmas.sao.SAOMechanism[None] with ['c_0', 'm_2'] (ID ab697512-ec81-4213-a411-9485f8004b7b) 2019-02-27 11:33:49,756 - INFO - 1/10 [20.00%]: m_2-f4d60475-9842-4006-8513-ca39a2379160 request was accepted 2019-02-27 11:33:49,757 - INFO - 1/10 [20.00%]: m_3 requested negmas.sao.SAOMechanism[None] with ['c_0', 'm_3'] (ID 781be6fb-9d3e-43ab-8700-c423e7d8b330) 2019-02-27 11:33:49,758 - INFO - 1/10 [20.00%]: m_3-418c12ae-b8cd-4e28-a9a8-b998b4ef7df6 request was accepted 2019-02-27 11:33:49,759 - INFO - 1/10 [20.00%]: m_4 requested negmas.sao.SAOMechanism[None] with ['c_0', 'm_4'] (ID 34f265c3-f221-4333-9665-ad4171147d60) 2019-02-27 11:33:49,760 - INFO - 1/10 [20.00%]: m_4-4f6b8ebc-32b0-44d5-88d6-88b3cec0b489 request was accepted 2019-02-27 11:33:49,763 - INFO - 1/10 [20.00%]: m_0 requested negmas.sao.SAOMechanism[None] with ['c_4', 'm_0'] (ID 32bce4be-a53d-4c99-bb7a-279ecc29775e) 2019-02-27 11:33:49,764 - INFO - 1/10 [20.00%]: m_0-61b223a2-ea24-4bfc-9bf3-aa85fa8a955a request was accepted 2019-02-27 11:33:49,765 - INFO - 1/10 [20.00%]: m_1 requested negmas.sao.SAOMechanism[None] with ['c_4', 'm_1'] (ID e6ae86d0-8620-4a12-a468-e07b66a0d007) 2019-02-27 11:33:49,766 - INFO - 1/10 [20.00%]: m_1-b789f15d-3508-464a-8717-8ba1da159754 request was accepted 2019-02-27 11:33:49,767 - INFO - 1/10 [20.00%]: m_2 requested negmas.sao.SAOMechanism[None] with ['c_4', 'm_2'] (ID cf5873cf-2c20-4578-9906-3ecc7fd06a73) 2019-02-27 11:33:49,769 - INFO - 1/10 [20.00%]: m_2-f4d60475-9842-4006-8513-ca39a2379160 request was accepted 2019-02-27 11:33:49,770 - INFO - 1/10 [20.00%]: m_3 requested negmas.sao.SAOMechanism[None] with ['c_4', 'm_3'] (ID d62826ab-b7c7-436d-906f-9a1eee28d81f) 2019-02-27 11:33:49,771 - INFO - 1/10 [20.00%]: m_3-418c12ae-b8cd-4e28-a9a8-b998b4ef7df6 request was accepted 2019-02-27 11:33:49,772 - INFO - 1/10 [20.00%]: m_4 requested negmas.sao.SAOMechanism[None] with ['c_4', 'm_4'] (ID a70af081-fbfb-48a4-8fb9-d1be76c2948d) 2019-02-27 11:33:49,773 - INFO - 1/10 [20.00%]: m_4-4f6b8ebc-32b0-44d5-88d6-88b3cec0b489 request was accepted 2019-02-27 11:33:49,773 - DEBUG - 1/10 [20.00%]: Factory 95e75c6e-fd73-4d10-bb63-7e6fd5ed934d: money=0, storage={}, loans=0.0 2019-02-27 11:33:49,773 - DEBUG - 1/10 [20.00%]: Factory 1d03dc99-48cd-4b69-81d8-4faf95f470b1: money=0, storage={}, loans=0.0 2019-02-27 11:33:49,773 - DEBUG - 1/10 [20.00%]: Factory 3988d198-d05c-4a8a-93c9-8a88363a07d6: money=0, storage={}, loans=0.0 2019-02-27 11:33:49,773 - DEBUG - 1/10 [20.00%]: Factory bad2c634-f9b5-4ae3-8b59-626ce7e171fb: money=0, storage={}, loans=0.0 2019-02-27 11:33:49,773 - DEBUG - 1/10 [20.00%]: Factory ee428c0e-e853-4495-8bbd-24302264a757: money=0, storage={}, loans=0.0 2019-02-27 11:33:49,773 - DEBUG - 1/10 [20.00%]: Factory cb5ab840-9bd8-41f9-866a-ca43e56e74c6: money=0.0, storage={}, loans=0.0 2019-02-27 11:33:49,773 - DEBUG - 1/10 [20.00%]: Factory b5cdcb3a-a4bd-478d-9795-d361eb70cf32: money=0.0, storage={}, loans=0.0 2019-02-27 11:33:49,773 - DEBUG - 1/10 [20.00%]: Factory cb4aedd6-68a2-450a-8d92-117fcb5ae311: money=0.0, storage={}, loans=0.0 2019-02-27 11:33:49,773 - DEBUG - 1/10 [20.00%]: Factory 986a8ca5-1b97-449f-b316-450edc5ed050: money=0.0, storage={}, loans=0.0 2019-02-27 11:33:49,774 - DEBUG - 1/10 [20.00%]: Factory d70b6918-35dd-4eab-924c-7a13f3ad3feb: money=0.0, storage={}, loans=0.0 2019-02-27 11:33:49,774 - INFO - 2/10 [30.00%]: 25 Negotiations/4 _entities 2019-02-27 11:33:50,071 - DEBUG - 2/10 [30.00%]: Contract [to be signed at 3]: ['c_2', 'm_3'] > {'time': 5, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_2-c1142518-c4d8-4f80-9889-693a093ef989: buy 0 (t: 5, u: (0, 2.0), q: (1, 4))', 'partners': "['c_2-c1142518-c4d8-4f80-9889-693a093ef989', 'm_3-418c12ae-b8cd-4e28-a9a8-b998b4ef7df6']", 'seller': 'm_3-418c12ae-b8cd-4e28-a9a8-b998b4ef7df6', 'buyer': 'c_2-c1142518-c4d8-4f80-9889-693a093ef989'} 2019-02-27 11:33:50,072 - DEBUG - 2/10 [30.00%]: Contract [to be signed at 3]: ['c_1', 'm_4'] > {'time': 5, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_1-68b3b84c-c42b-4582-9119-917484eb77ef: buy 0 (t: 5, u: (0, 2.0), q: (1, 4))', 'partners': "['c_1-68b3b84c-c42b-4582-9119-917484eb77ef', 'm_4-4f6b8ebc-32b0-44d5-88d6-88b3cec0b489']", 'seller': 'm_4-4f6b8ebc-32b0-44d5-88d6-88b3cec0b489', 'buyer': 'c_1-68b3b84c-c42b-4582-9119-917484eb77ef'} 2019-02-27 11:33:50,072 - DEBUG - 2/10 [30.00%]: Contract [to be signed at 3]: ['c_4', 'm_1'] > {'time': 5, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_4-76d9311e-d5f6-4e91-bb83-72994095e2c6: buy 0 (t: 5, u: (0, 2.0), q: (1, 4))', 'partners': "['c_4-76d9311e-d5f6-4e91-bb83-72994095e2c6', 'm_1-b789f15d-3508-464a-8717-8ba1da159754']", 'seller': 'm_1-b789f15d-3508-464a-8717-8ba1da159754', 'buyer': 'c_4-76d9311e-d5f6-4e91-bb83-72994095e2c6'} 2019-02-27 11:33:50,072 - DEBUG - 2/10 [30.00%]: Contract [to be signed at 3]: ['c_2', 'm_2'] > {'time': 5, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_2-c1142518-c4d8-4f80-9889-693a093ef989: buy 0 (t: 5, u: (0, 2.0), q: (1, 4))', 'partners': "['c_2-c1142518-c4d8-4f80-9889-693a093ef989', 'm_2-f4d60475-9842-4006-8513-ca39a2379160']", 'seller': 'm_2-f4d60475-9842-4006-8513-ca39a2379160', 'buyer': 'c_2-c1142518-c4d8-4f80-9889-693a093ef989'} 2019-02-27 11:33:50,073 - DEBUG - 2/10 [30.00%]: Contract [to be signed at 3]: ['c_4', 'm_4'] > {'time': 5, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_4-76d9311e-d5f6-4e91-bb83-72994095e2c6: buy 0 (t: 5, u: (0, 2.0), q: (1, 4))', 'partners': "['c_4-76d9311e-d5f6-4e91-bb83-72994095e2c6', 'm_4-4f6b8ebc-32b0-44d5-88d6-88b3cec0b489']", 'seller': 'm_4-4f6b8ebc-32b0-44d5-88d6-88b3cec0b489', 'buyer': 'c_4-76d9311e-d5f6-4e91-bb83-72994095e2c6'} 2019-02-27 11:33:50,073 - DEBUG - 2/10 [30.00%]: Contract [to be signed at 3]: ['c_3', 'm_0'] > {'time': 5, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_3-0230100d-3633-49be-bb01-4928b35e59bc: buy 0 (t: 5, u: (0, 2.0), q: (1, 3))', 'partners': "['c_3-0230100d-3633-49be-bb01-4928b35e59bc', 'm_0-61b223a2-ea24-4bfc-9bf3-aa85fa8a955a']", 'seller': 'm_0-61b223a2-ea24-4bfc-9bf3-aa85fa8a955a', 'buyer': 'c_3-0230100d-3633-49be-bb01-4928b35e59bc'} 2019-02-27 11:33:50,074 - DEBUG - 2/10 [30.00%]: Contract [to be signed at 3]: ['c_0', 'm_0'] > {'time': 5, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_0-b6f40f78-35c5-4b76-9f90-53a459a66882: buy 0 (t: 5, u: (0, 2.0), q: (1, 4))', 'partners': "['c_0-b6f40f78-35c5-4b76-9f90-53a459a66882', 'm_0-61b223a2-ea24-4bfc-9bf3-aa85fa8a955a']", 'seller': 'm_0-61b223a2-ea24-4bfc-9bf3-aa85fa8a955a', 'buyer': 'c_0-b6f40f78-35c5-4b76-9f90-53a459a66882'} 2019-02-27 11:33:50,074 - DEBUG - 2/10 [30.00%]: Contract [to be signed at 3]: ['c_4', 'm_0'] > {'time': 5, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_4-76d9311e-d5f6-4e91-bb83-72994095e2c6: buy 0 (t: 5, u: (0, 2.0), q: (1, 4))', 'partners': "['c_4-76d9311e-d5f6-4e91-bb83-72994095e2c6', 'm_0-61b223a2-ea24-4bfc-9bf3-aa85fa8a955a']", 'seller': 'm_0-61b223a2-ea24-4bfc-9bf3-aa85fa8a955a', 'buyer': 'c_4-76d9311e-d5f6-4e91-bb83-72994095e2c6'} 2019-02-27 11:33:50,074 - DEBUG - 2/10 [30.00%]: Contract [to be signed at 3]: ['c_0', 'm_3'] > {'time': 5, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_0-b6f40f78-35c5-4b76-9f90-53a459a66882: buy 0 (t: 5, u: (0, 2.0), q: (1, 4))', 'partners': "['c_0-b6f40f78-35c5-4b76-9f90-53a459a66882', 'm_3-418c12ae-b8cd-4e28-a9a8-b998b4ef7df6']", 'seller': 'm_3-418c12ae-b8cd-4e28-a9a8-b998b4ef7df6', 'buyer': 'c_0-b6f40f78-35c5-4b76-9f90-53a459a66882'} 2019-02-27 11:33:50,075 - DEBUG - 2/10 [30.00%]: Contract [to be signed at 3]: ['c_2', 'm_0'] > {'time': 5, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_2-c1142518-c4d8-4f80-9889-693a093ef989: buy 0 (t: 5, u: (0, 2.0), q: (1, 4))', 'partners': "['c_2-c1142518-c4d8-4f80-9889-693a093ef989', 'm_0-61b223a2-ea24-4bfc-9bf3-aa85fa8a955a']", 'seller': 'm_0-61b223a2-ea24-4bfc-9bf3-aa85fa8a955a', 'buyer': 'c_2-c1142518-c4d8-4f80-9889-693a093ef989'} 2019-02-27 11:33:50,075 - DEBUG - 2/10 [30.00%]: Contract [to be signed at 3]: ['c_3', 'm_1'] > {'time': 5, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_3-0230100d-3633-49be-bb01-4928b35e59bc: buy 0 (t: 5, u: (0, 2.0), q: (1, 3))', 'partners': "['c_3-0230100d-3633-49be-bb01-4928b35e59bc', 'm_1-b789f15d-3508-464a-8717-8ba1da159754']", 'seller': 'm_1-b789f15d-3508-464a-8717-8ba1da159754', 'buyer': 'c_3-0230100d-3633-49be-bb01-4928b35e59bc'} 2019-02-27 11:33:50,075 - DEBUG - 2/10 [30.00%]: Contract [to be signed at 3]: ['c_4', 'm_3'] > {'time': 5, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_4-76d9311e-d5f6-4e91-bb83-72994095e2c6: buy 0 (t: 5, u: (0, 2.0), q: (1, 4))', 'partners': "['c_4-76d9311e-d5f6-4e91-bb83-72994095e2c6', 'm_3-418c12ae-b8cd-4e28-a9a8-b998b4ef7df6']", 'seller': 'm_3-418c12ae-b8cd-4e28-a9a8-b998b4ef7df6', 'buyer': 'c_4-76d9311e-d5f6-4e91-bb83-72994095e2c6'} 2019-02-27 11:33:50,076 - DEBUG - 2/10 [30.00%]: Contract [to be signed at 3]: ['c_1', 'm_2'] > {'time': 5, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_1-68b3b84c-c42b-4582-9119-917484eb77ef: buy 0 (t: 5, u: (0, 2.0), q: (1, 4))', 'partners': "['c_1-68b3b84c-c42b-4582-9119-917484eb77ef', 'm_2-f4d60475-9842-4006-8513-ca39a2379160']", 'seller': 'm_2-f4d60475-9842-4006-8513-ca39a2379160', 'buyer': 'c_1-68b3b84c-c42b-4582-9119-917484eb77ef'} 2019-02-27 11:33:50,076 - DEBUG - 2/10 [30.00%]: Contract [to be signed at 3]: ['c_0', 'm_1'] > {'time': 5, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_0-b6f40f78-35c5-4b76-9f90-53a459a66882: buy 0 (t: 5, u: (0, 2.0), q: (1, 4))', 'partners': "['c_0-b6f40f78-35c5-4b76-9f90-53a459a66882', 'm_1-b789f15d-3508-464a-8717-8ba1da159754']", 'seller': 'm_1-b789f15d-3508-464a-8717-8ba1da159754', 'buyer': 'c_0-b6f40f78-35c5-4b76-9f90-53a459a66882'} 2019-02-27 11:33:50,076 - DEBUG - 2/10 [30.00%]: Contract [to be signed at 3]: ['c_1', 'm_3'] > {'time': 5, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_1-68b3b84c-c42b-4582-9119-917484eb77ef: buy 0 (t: 5, u: (0, 2.0), q: (1, 4))', 'partners': "['c_1-68b3b84c-c42b-4582-9119-917484eb77ef', 'm_3-418c12ae-b8cd-4e28-a9a8-b998b4ef7df6']", 'seller': 'm_3-418c12ae-b8cd-4e28-a9a8-b998b4ef7df6', 'buyer': 'c_1-68b3b84c-c42b-4582-9119-917484eb77ef'} 2019-02-27 11:33:50,076 - DEBUG - 2/10 [30.00%]: Contract [to be signed at 3]: ['c_3', 'm_3'] > {'time': 5, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_3-0230100d-3633-49be-bb01-4928b35e59bc: buy 0 (t: 5, u: (0, 2.0), q: (1, 3))', 'partners': "['c_3-0230100d-3633-49be-bb01-4928b35e59bc', 'm_3-418c12ae-b8cd-4e28-a9a8-b998b4ef7df6']", 'seller': 'm_3-418c12ae-b8cd-4e28-a9a8-b998b4ef7df6', 'buyer': 'c_3-0230100d-3633-49be-bb01-4928b35e59bc'} 2019-02-27 11:33:50,077 - DEBUG - 2/10 [30.00%]: Contract [to be signed at 3]: ['c_4', 'm_2'] > {'time': 5, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_4-76d9311e-d5f6-4e91-bb83-72994095e2c6: buy 0 (t: 5, u: (0, 2.0), q: (1, 4))', 'partners': "['c_4-76d9311e-d5f6-4e91-bb83-72994095e2c6', 'm_2-f4d60475-9842-4006-8513-ca39a2379160']", 'seller': 'm_2-f4d60475-9842-4006-8513-ca39a2379160', 'buyer': 'c_4-76d9311e-d5f6-4e91-bb83-72994095e2c6'} 2019-02-27 11:33:50,077 - DEBUG - 2/10 [30.00%]: Contract [to be signed at 3]: ['c_1', 'm_0'] > {'time': 5, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_1-68b3b84c-c42b-4582-9119-917484eb77ef: buy 0 (t: 5, u: (0, 2.0), q: (1, 4))', 'partners': "['c_1-68b3b84c-c42b-4582-9119-917484eb77ef', 'm_0-61b223a2-ea24-4bfc-9bf3-aa85fa8a955a']", 'seller': 'm_0-61b223a2-ea24-4bfc-9bf3-aa85fa8a955a', 'buyer': 'c_1-68b3b84c-c42b-4582-9119-917484eb77ef'} 2019-02-27 11:33:50,077 - DEBUG - 2/10 [30.00%]: Contract [to be signed at 3]: ['c_2', 'm_1'] > {'time': 5, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_2-c1142518-c4d8-4f80-9889-693a093ef989: buy 0 (t: 5, u: (0, 2.0), q: (1, 4))', 'partners': "['c_2-c1142518-c4d8-4f80-9889-693a093ef989', 'm_1-b789f15d-3508-464a-8717-8ba1da159754']", 'seller': 'm_1-b789f15d-3508-464a-8717-8ba1da159754', 'buyer': 'c_2-c1142518-c4d8-4f80-9889-693a093ef989'} 2019-02-27 11:33:50,078 - DEBUG - 2/10 [30.00%]: Contract [to be signed at 3]: ['c_3', 'm_2'] > {'time': 5, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_3-0230100d-3633-49be-bb01-4928b35e59bc: buy 0 (t: 5, u: (0, 2.0), q: (1, 3))', 'partners': "['c_3-0230100d-3633-49be-bb01-4928b35e59bc', 'm_2-f4d60475-9842-4006-8513-ca39a2379160']", 'seller': 'm_2-f4d60475-9842-4006-8513-ca39a2379160', 'buyer': 'c_3-0230100d-3633-49be-bb01-4928b35e59bc'} 2019-02-27 11:33:50,078 - DEBUG - 2/10 [30.00%]: Contract [to be signed at 3]: ['c_3', 'm_4'] > {'time': 5, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_3-0230100d-3633-49be-bb01-4928b35e59bc: buy 0 (t: 5, u: (0, 2.0), q: (1, 3))', 'partners': "['c_3-0230100d-3633-49be-bb01-4928b35e59bc', 'm_4-4f6b8ebc-32b0-44d5-88d6-88b3cec0b489']", 'seller': 'm_4-4f6b8ebc-32b0-44d5-88d6-88b3cec0b489', 'buyer': 'c_3-0230100d-3633-49be-bb01-4928b35e59bc'} 2019-02-27 11:33:50,078 - DEBUG - 2/10 [30.00%]: Contract [to be signed at 3]: ['c_0', 'm_4'] > {'time': 5, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_0-b6f40f78-35c5-4b76-9f90-53a459a66882: buy 0 (t: 5, u: (0, 2.0), q: (1, 4))', 'partners': "['c_0-b6f40f78-35c5-4b76-9f90-53a459a66882', 'm_4-4f6b8ebc-32b0-44d5-88d6-88b3cec0b489']", 'seller': 'm_4-4f6b8ebc-32b0-44d5-88d6-88b3cec0b489', 'buyer': 'c_0-b6f40f78-35c5-4b76-9f90-53a459a66882'} 2019-02-27 11:33:50,078 - DEBUG - 2/10 [30.00%]: Contract [to be signed at 3]: ['c_2', 'm_4'] > {'time': 5, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_2-c1142518-c4d8-4f80-9889-693a093ef989: buy 0 (t: 5, u: (0, 2.0), q: (1, 4))', 'partners': "['c_2-c1142518-c4d8-4f80-9889-693a093ef989', 'm_4-4f6b8ebc-32b0-44d5-88d6-88b3cec0b489']", 'seller': 'm_4-4f6b8ebc-32b0-44d5-88d6-88b3cec0b489', 'buyer': 'c_2-c1142518-c4d8-4f80-9889-693a093ef989'} 2019-02-27 11:33:50,079 - DEBUG - 2/10 [30.00%]: Contract [to be signed at 3]: ['c_0', 'm_2'] > {'time': 5, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_0-b6f40f78-35c5-4b76-9f90-53a459a66882: buy 0 (t: 5, u: (0, 2.0), q: (1, 4))', 'partners': "['c_0-b6f40f78-35c5-4b76-9f90-53a459a66882', 'm_2-f4d60475-9842-4006-8513-ca39a2379160']", 'seller': 'm_2-f4d60475-9842-4006-8513-ca39a2379160', 'buyer': 'c_0-b6f40f78-35c5-4b76-9f90-53a459a66882'} 2019-02-27 11:33:50,079 - DEBUG - 2/10 [30.00%]: Contract [to be signed at 3]: ['c_1', 'm_1'] > {'time': 5, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_1-68b3b84c-c42b-4582-9119-917484eb77ef: buy 0 (t: 5, u: (0, 2.0), q: (1, 4))', 'partners': "['c_1-68b3b84c-c42b-4582-9119-917484eb77ef', 'm_1-b789f15d-3508-464a-8717-8ba1da159754']", 'seller': 'm_1-b789f15d-3508-464a-8717-8ba1da159754', 'buyer': 'c_1-68b3b84c-c42b-4582-9119-917484eb77ef'} 2019-02-27 11:33:50,082 - INFO - 2/10 [30.00%]: m_0 requested negmas.sao.SAOMechanism[None] with ['c_3', 'm_0'] (ID e27f1053-adca-4c33-b641-d63a39654196) 2019-02-27 11:33:50,082 - INFO - 2/10 [30.00%]: m_0-61b223a2-ea24-4bfc-9bf3-aa85fa8a955a request was accepted 2019-02-27 11:33:50,083 - INFO - 2/10 [30.00%]: m_1 requested negmas.sao.SAOMechanism[None] with ['c_3', 'm_1'] (ID 99dd5bb7-c289-4afd-9eb6-62e3764d2b77) 2019-02-27 11:33:50,084 - INFO - 2/10 [30.00%]: m_1-b789f15d-3508-464a-8717-8ba1da159754 request was accepted 2019-02-27 11:33:50,085 - INFO - 2/10 [30.00%]: m_2 requested negmas.sao.SAOMechanism[None] with ['c_3', 'm_2'] (ID 433f58c0-d659-4cbf-ae2c-8bdf4f123cf8) 2019-02-27 11:33:50,086 - INFO - 2/10 [30.00%]: m_2-f4d60475-9842-4006-8513-ca39a2379160 request was accepted 2019-02-27 11:33:50,087 - INFO - 2/10 [30.00%]: m_3 requested negmas.sao.SAOMechanism[None] with ['c_3', 'm_3'] (ID c3677209-8165-4465-986b-fcf370662237) 2019-02-27 11:33:50,087 - INFO - 2/10 [30.00%]: m_3-418c12ae-b8cd-4e28-a9a8-b998b4ef7df6 request was accepted 2019-02-27 11:33:50,088 - INFO - 2/10 [30.00%]: m_4 requested negmas.sao.SAOMechanism[None] with ['c_3', 'm_4'] (ID 8b3d9669-56e0-41d0-8a22-76d3b58d4dd2) 2019-02-27 11:33:50,089 - INFO - 2/10 [30.00%]: m_4-4f6b8ebc-32b0-44d5-88d6-88b3cec0b489 request was accepted 2019-02-27 11:33:50,091 - INFO - 2/10 [30.00%]: m_0 requested negmas.sao.SAOMechanism[None] with ['c_2', 'm_0'] (ID dde8b89c-63a0-47ac-aab8-d8c9cef949d1) 2019-02-27 11:33:50,092 - INFO - 2/10 [30.00%]: m_0-61b223a2-ea24-4bfc-9bf3-aa85fa8a955a request was accepted 2019-02-27 11:33:50,093 - INFO - 2/10 [30.00%]: m_1 requested negmas.sao.SAOMechanism[None] with ['c_2', 'm_1'] (ID 9060760a-af90-4594-bff1-61138eb5a261) 2019-02-27 11:33:50,094 - INFO - 2/10 [30.00%]: m_1-b789f15d-3508-464a-8717-8ba1da159754 request was accepted 2019-02-27 11:33:50,095 - INFO - 2/10 [30.00%]: m_2 requested negmas.sao.SAOMechanism[None] with ['c_2', 'm_2'] (ID 52599900-9f23-4cfd-8de9-d2b58e8d515c) 2019-02-27 11:33:50,095 - INFO - 2/10 [30.00%]: m_2-f4d60475-9842-4006-8513-ca39a2379160 request was accepted 2019-02-27 11:33:50,096 - INFO - 2/10 [30.00%]: m_3 requested negmas.sao.SAOMechanism[None] with ['c_2', 'm_3'] (ID 3e46d727-49b2-4e6b-a87d-a4b5e04380c1) 2019-02-27 11:33:50,097 - INFO - 2/10 [30.00%]: m_3-418c12ae-b8cd-4e28-a9a8-b998b4ef7df6 request was accepted 2019-02-27 11:33:50,098 - INFO - 2/10 [30.00%]: m_4 requested negmas.sao.SAOMechanism[None] with ['c_2', 'm_4'] (ID 4bf54ae7-7f2f-4beb-b6a4-347d88b847f4) 2019-02-27 11:33:50,099 - INFO - 2/10 [30.00%]: m_4-4f6b8ebc-32b0-44d5-88d6-88b3cec0b489 request was accepted 2019-02-27 11:33:50,101 - INFO - 2/10 [30.00%]: m_0 requested negmas.sao.SAOMechanism[None] with ['c_1', 'm_0'] (ID 4c68ffe9-e71c-4993-a033-971615715d07) 2019-02-27 11:33:50,102 - INFO - 2/10 [30.00%]: m_0-61b223a2-ea24-4bfc-9bf3-aa85fa8a955a request was accepted 2019-02-27 11:33:50,103 - INFO - 2/10 [30.00%]: m_1 requested negmas.sao.SAOMechanism[None] with ['c_1', 'm_1'] (ID d5ebbcce-6afe-4df4-8fd7-a8bd7d94583d) 2019-02-27 11:33:50,104 - INFO - 2/10 [30.00%]: m_1-b789f15d-3508-464a-8717-8ba1da159754 request was accepted 2019-02-27 11:33:50,106 - INFO - 2/10 [30.00%]: m_2 requested negmas.sao.SAOMechanism[None] with ['c_1', 'm_2'] (ID d135f5c9-9eff-475f-8195-ddeefc2a83ac) 2019-02-27 11:33:50,107 - INFO - 2/10 [30.00%]: m_2-f4d60475-9842-4006-8513-ca39a2379160 request was accepted 2019-02-27 11:33:50,109 - INFO - 2/10 [30.00%]: m_3 requested negmas.sao.SAOMechanism[None] with ['c_1', 'm_3'] (ID b2bc6192-fafb-4de7-aa59-5ec06883cc42) 2019-02-27 11:33:50,109 - INFO - 2/10 [30.00%]: m_3-418c12ae-b8cd-4e28-a9a8-b998b4ef7df6 request was accepted 2019-02-27 11:33:50,111 - INFO - 2/10 [30.00%]: m_4 requested negmas.sao.SAOMechanism[None] with ['c_1', 'm_4'] (ID fd1ab407-761e-4e80-b1bd-05ea776cd843) 2019-02-27 11:33:50,111 - INFO - 2/10 [30.00%]: m_4-4f6b8ebc-32b0-44d5-88d6-88b3cec0b489 request was accepted 2019-02-27 11:33:50,113 - INFO - 2/10 [30.00%]: m_0 requested negmas.sao.SAOMechanism[None] with ['c_0', 'm_0'] (ID f6e5c072-5962-4ed1-9bd8-b525b9f2a4d5) 2019-02-27 11:33:50,114 - INFO - 2/10 [30.00%]: m_0-61b223a2-ea24-4bfc-9bf3-aa85fa8a955a request was accepted 2019-02-27 11:33:50,115 - INFO - 2/10 [30.00%]: m_1 requested negmas.sao.SAOMechanism[None] with ['c_0', 'm_1'] (ID 4b31ba31-4cfe-48db-8ed9-9ebce1afe306) 2019-02-27 11:33:50,116 - INFO - 2/10 [30.00%]: m_1-b789f15d-3508-464a-8717-8ba1da159754 request was accepted 2019-02-27 11:33:50,117 - INFO - 2/10 [30.00%]: m_2 requested negmas.sao.SAOMechanism[None] with ['c_0', 'm_2'] (ID 2e762762-c5ef-4a5a-b790-edf6b372b4e3) 2019-02-27 11:33:50,117 - INFO - 2/10 [30.00%]: m_2-f4d60475-9842-4006-8513-ca39a2379160 request was accepted 2019-02-27 11:33:50,119 - INFO - 2/10 [30.00%]: m_3 requested negmas.sao.SAOMechanism[None] with ['c_0', 'm_3'] (ID 017c8f9c-33ad-478c-a9d2-e37a26a29eef) 2019-02-27 11:33:50,121 - INFO - 2/10 [30.00%]: m_3-418c12ae-b8cd-4e28-a9a8-b998b4ef7df6 request was accepted 2019-02-27 11:33:50,123 - INFO - 2/10 [30.00%]: m_4 requested negmas.sao.SAOMechanism[None] with ['c_0', 'm_4'] (ID 79e0ce4a-8dd1-4f6a-bbb3-6d04178daec9) 2019-02-27 11:33:50,124 - INFO - 2/10 [30.00%]: m_4-4f6b8ebc-32b0-44d5-88d6-88b3cec0b489 request was accepted 2019-02-27 11:33:50,125 - INFO - 2/10 [30.00%]: m_0 requested negmas.sao.SAOMechanism[None] with ['c_4', 'm_0'] (ID 8c10b3f1-dae3-435a-8f8d-d6a7dcc3d354) 2019-02-27 11:33:50,126 - INFO - 2/10 [30.00%]: m_0-61b223a2-ea24-4bfc-9bf3-aa85fa8a955a request was accepted 2019-02-27 11:33:50,127 - INFO - 2/10 [30.00%]: m_1 requested negmas.sao.SAOMechanism[None] with ['c_4', 'm_1'] (ID 4050601a-34b0-490e-9f03-b05be505cc81) 2019-02-27 11:33:50,127 - INFO - 2/10 [30.00%]: m_1-b789f15d-3508-464a-8717-8ba1da159754 request was accepted 2019-02-27 11:33:50,129 - INFO - 2/10 [30.00%]: m_2 requested negmas.sao.SAOMechanism[None] with ['c_4', 'm_2'] (ID 88865f22-13b1-4206-9c09-200f55c2012d) 2019-02-27 11:33:50,130 - INFO - 2/10 [30.00%]: m_2-f4d60475-9842-4006-8513-ca39a2379160 request was accepted 2019-02-27 11:33:50,131 - INFO - 2/10 [30.00%]: m_3 requested negmas.sao.SAOMechanism[None] with ['c_4', 'm_3'] (ID aa2b28e8-5cf8-493d-84eb-f28907ae18ce) 2019-02-27 11:33:50,131 - INFO - 2/10 [30.00%]: m_3-418c12ae-b8cd-4e28-a9a8-b998b4ef7df6 request was accepted 2019-02-27 11:33:50,132 - INFO - 2/10 [30.00%]: m_4 requested negmas.sao.SAOMechanism[None] with ['c_4', 'm_4'] (ID 06aba44c-be4b-41e8-9040-249ade1a2333) 2019-02-27 11:33:50,133 - INFO - 2/10 [30.00%]: m_4-4f6b8ebc-32b0-44d5-88d6-88b3cec0b489 request was accepted 2019-02-27 11:33:50,133 - INFO - 2/10 [30.00%]: Executing c_3-0230100d-3633-49be-bb01-4928b35e59bc, m_3-418c12ae-b8cd-4e28-a9a8-b998b4ef7df6 agreed on {'time': 2, 'quantity': 3, 'unit_price': 0.5} 2019-02-27 11:33:50,133 - DEBUG - 2/10 [30.00%]: Moved 3 units of p0 from m_3 to c_3 for 1.5 dollars 2019-02-27 11:33:50,133 - INFO - 2/10 [30.00%]: Executing c_1-68b3b84c-c42b-4582-9119-917484eb77ef, m_4-4f6b8ebc-32b0-44d5-88d6-88b3cec0b489 agreed on {'time': 2, 'quantity': 3, 'unit_price': 0.5} 2019-02-27 11:33:50,133 - DEBUG - 2/10 [30.00%]: Moved 3 units of p0 from m_4 to c_1 for 1.5 dollars 2019-02-27 11:33:50,133 - INFO - 2/10 [30.00%]: Executing c_4-76d9311e-d5f6-4e91-bb83-72994095e2c6, m_0-61b223a2-ea24-4bfc-9bf3-aa85fa8a955a agreed on {'time': 2, 'quantity': 3, 'unit_price': 0.5} 2019-02-27 11:33:50,134 - DEBUG - 2/10 [30.00%]: Moved 3 units of p0 from m_0 to c_4 for 1.5 dollars 2019-02-27 11:33:50,134 - INFO - 2/10 [30.00%]: Executing c_2-c1142518-c4d8-4f80-9889-693a093ef989, m_3-418c12ae-b8cd-4e28-a9a8-b998b4ef7df6 agreed on {'time': 2, 'quantity': 4, 'unit_price': 0.5} 2019-02-27 11:33:50,134 - DEBUG - 2/10 [30.00%]: Moved 4 units of p0 from m_3 to c_2 for 2.0 dollars 2019-02-27 11:33:50,134 - INFO - 2/10 [30.00%]: Executing c_0-b6f40f78-35c5-4b76-9f90-53a459a66882, m_1-b789f15d-3508-464a-8717-8ba1da159754 agreed on {'time': 2, 'quantity': 4, 'unit_price': 0.5} 2019-02-27 11:33:50,134 - DEBUG - 2/10 [30.00%]: Moved 4 units of p0 from m_1 to c_0 for 2.0 dollars 2019-02-27 11:33:50,134 - DEBUG - 2/10 [30.00%]: Factory 95e75c6e-fd73-4d10-bb63-7e6fd5ed934d: money=-2.0, storage={}, loans=0.0 2019-02-27 11:33:50,134 - DEBUG - 2/10 [30.00%]: Factory 1d03dc99-48cd-4b69-81d8-4faf95f470b1: money=-1.5, storage={}, loans=0.0 2019-02-27 11:33:50,134 - DEBUG - 2/10 [30.00%]: Factory 3988d198-d05c-4a8a-93c9-8a88363a07d6: money=-2.0, storage={}, loans=0.0 2019-02-27 11:33:50,134 - DEBUG - 2/10 [30.00%]: Factory bad2c634-f9b5-4ae3-8b59-626ce7e171fb: money=-1.5, storage={}, loans=0.0 2019-02-27 11:33:50,134 - DEBUG - 2/10 [30.00%]: Factory ee428c0e-e853-4495-8bbd-24302264a757: money=-1.5, storage={}, loans=0.0 2019-02-27 11:33:50,134 - DEBUG - 2/10 [30.00%]: Factory cb5ab840-9bd8-41f9-866a-ca43e56e74c6: money=1.5, storage={0: -3}, loans=0.0 2019-02-27 11:33:50,134 - DEBUG - 2/10 [30.00%]: Factory b5cdcb3a-a4bd-478d-9795-d361eb70cf32: money=2.0, storage={0: -4}, loans=0.0 2019-02-27 11:33:50,134 - DEBUG - 2/10 [30.00%]: Factory cb4aedd6-68a2-450a-8d92-117fcb5ae311: money=0.0, storage={}, loans=0.0 2019-02-27 11:33:50,134 - DEBUG - 2/10 [30.00%]: Factory 986a8ca5-1b97-449f-b316-450edc5ed050: money=3.5, storage={0: -7}, loans=0.0 2019-02-27 11:33:50,134 - DEBUG - 2/10 [30.00%]: Factory d70b6918-35dd-4eab-924c-7a13f3ad3feb: money=1.5, storage={0: -3}, loans=0.0 2019-02-27 11:33:50,134 - INFO - 3/10 [40.00%]: 25 Negotiations/4 _entities 2019-02-27 11:33:50,366 - DEBUG - 3/10 [40.00%]: Contract [to be signed at 4]: ['c_0', 'm_0'] > {'time': 6, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_0-b6f40f78-35c5-4b76-9f90-53a459a66882: buy 0 (t: 6, u: (0, 2.0), q: (1, 4))', 'partners': "['c_0-b6f40f78-35c5-4b76-9f90-53a459a66882', 'm_0-61b223a2-ea24-4bfc-9bf3-aa85fa8a955a']", 'seller': 'm_0-61b223a2-ea24-4bfc-9bf3-aa85fa8a955a', 'buyer': 'c_0-b6f40f78-35c5-4b76-9f90-53a459a66882'} 2019-02-27 11:33:50,366 - DEBUG - 3/10 [40.00%]: Contract [to be signed at 4]: ['c_0', 'm_4'] > {'time': 6, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_0-b6f40f78-35c5-4b76-9f90-53a459a66882: buy 0 (t: 6, u: (0, 2.0), q: (1, 4))', 'partners': "['c_0-b6f40f78-35c5-4b76-9f90-53a459a66882', 'm_4-4f6b8ebc-32b0-44d5-88d6-88b3cec0b489']", 'seller': 'm_4-4f6b8ebc-32b0-44d5-88d6-88b3cec0b489', 'buyer': 'c_0-b6f40f78-35c5-4b76-9f90-53a459a66882'} 2019-02-27 11:33:50,367 - DEBUG - 3/10 [40.00%]: Contract [to be signed at 4]: ['c_2', 'm_2'] > {'time': 6, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_2-c1142518-c4d8-4f80-9889-693a093ef989: buy 0 (t: 6, u: (0, 2.0), q: (1, 4))', 'partners': "['c_2-c1142518-c4d8-4f80-9889-693a093ef989', 'm_2-f4d60475-9842-4006-8513-ca39a2379160']", 'seller': 'm_2-f4d60475-9842-4006-8513-ca39a2379160', 'buyer': 'c_2-c1142518-c4d8-4f80-9889-693a093ef989'} 2019-02-27 11:33:50,367 - DEBUG - 3/10 [40.00%]: Contract [to be signed at 4]: ['c_3', 'm_4'] > {'time': 6, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_3-0230100d-3633-49be-bb01-4928b35e59bc: buy 0 (t: 6, u: (0, 2.0), q: (1, 4))', 'partners': "['c_3-0230100d-3633-49be-bb01-4928b35e59bc', 'm_4-4f6b8ebc-32b0-44d5-88d6-88b3cec0b489']", 'seller': 'm_4-4f6b8ebc-32b0-44d5-88d6-88b3cec0b489', 'buyer': 'c_3-0230100d-3633-49be-bb01-4928b35e59bc'} 2019-02-27 11:33:50,367 - DEBUG - 3/10 [40.00%]: Contract [to be signed at 4]: ['c_0', 'm_1'] > {'time': 6, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_0-b6f40f78-35c5-4b76-9f90-53a459a66882: buy 0 (t: 6, u: (0, 2.0), q: (1, 4))', 'partners': "['c_0-b6f40f78-35c5-4b76-9f90-53a459a66882', 'm_1-b789f15d-3508-464a-8717-8ba1da159754']", 'seller': 'm_1-b789f15d-3508-464a-8717-8ba1da159754', 'buyer': 'c_0-b6f40f78-35c5-4b76-9f90-53a459a66882'} 2019-02-27 11:33:50,368 - DEBUG - 3/10 [40.00%]: Contract [to be signed at 4]: ['c_4', 'm_2'] > {'time': 6, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_4-76d9311e-d5f6-4e91-bb83-72994095e2c6: buy 0 (t: 6, u: (0, 2.0), q: (1, 4))', 'partners': "['c_4-76d9311e-d5f6-4e91-bb83-72994095e2c6', 'm_2-f4d60475-9842-4006-8513-ca39a2379160']", 'seller': 'm_2-f4d60475-9842-4006-8513-ca39a2379160', 'buyer': 'c_4-76d9311e-d5f6-4e91-bb83-72994095e2c6'} 2019-02-27 11:33:50,368 - DEBUG - 3/10 [40.00%]: Contract [to be signed at 4]: ['c_3', 'm_2'] > {'time': 6, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_3-0230100d-3633-49be-bb01-4928b35e59bc: buy 0 (t: 6, u: (0, 2.0), q: (1, 4))', 'partners': "['c_3-0230100d-3633-49be-bb01-4928b35e59bc', 'm_2-f4d60475-9842-4006-8513-ca39a2379160']", 'seller': 'm_2-f4d60475-9842-4006-8513-ca39a2379160', 'buyer': 'c_3-0230100d-3633-49be-bb01-4928b35e59bc'} 2019-02-27 11:33:50,368 - DEBUG - 3/10 [40.00%]: Contract [to be signed at 4]: ['c_2', 'm_3'] > {'time': 6, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_2-c1142518-c4d8-4f80-9889-693a093ef989: buy 0 (t: 6, u: (0, 2.0), q: (1, 4))', 'partners': "['c_2-c1142518-c4d8-4f80-9889-693a093ef989', 'm_3-418c12ae-b8cd-4e28-a9a8-b998b4ef7df6']", 'seller': 'm_3-418c12ae-b8cd-4e28-a9a8-b998b4ef7df6', 'buyer': 'c_2-c1142518-c4d8-4f80-9889-693a093ef989'} 2019-02-27 11:33:50,369 - DEBUG - 3/10 [40.00%]: Contract [to be signed at 4]: ['c_4', 'm_1'] > {'time': 6, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_4-76d9311e-d5f6-4e91-bb83-72994095e2c6: buy 0 (t: 6, u: (0, 2.0), q: (1, 4))', 'partners': "['c_4-76d9311e-d5f6-4e91-bb83-72994095e2c6', 'm_1-b789f15d-3508-464a-8717-8ba1da159754']", 'seller': 'm_1-b789f15d-3508-464a-8717-8ba1da159754', 'buyer': 'c_4-76d9311e-d5f6-4e91-bb83-72994095e2c6'} 2019-02-27 11:33:50,369 - DEBUG - 3/10 [40.00%]: Contract [to be signed at 4]: ['c_2', 'm_0'] > {'time': 6, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_2-c1142518-c4d8-4f80-9889-693a093ef989: buy 0 (t: 6, u: (0, 2.0), q: (1, 4))', 'partners': "['c_2-c1142518-c4d8-4f80-9889-693a093ef989', 'm_0-61b223a2-ea24-4bfc-9bf3-aa85fa8a955a']", 'seller': 'm_0-61b223a2-ea24-4bfc-9bf3-aa85fa8a955a', 'buyer': 'c_2-c1142518-c4d8-4f80-9889-693a093ef989'} 2019-02-27 11:33:50,369 - DEBUG - 3/10 [40.00%]: Contract [to be signed at 4]: ['c_0', 'm_3'] > {'time': 6, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_0-b6f40f78-35c5-4b76-9f90-53a459a66882: buy 0 (t: 6, u: (0, 2.0), q: (1, 4))', 'partners': "['c_0-b6f40f78-35c5-4b76-9f90-53a459a66882', 'm_3-418c12ae-b8cd-4e28-a9a8-b998b4ef7df6']", 'seller': 'm_3-418c12ae-b8cd-4e28-a9a8-b998b4ef7df6', 'buyer': 'c_0-b6f40f78-35c5-4b76-9f90-53a459a66882'} 2019-02-27 11:33:50,369 - DEBUG - 3/10 [40.00%]: Contract [to be signed at 4]: ['c_3', 'm_3'] > {'time': 6, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_3-0230100d-3633-49be-bb01-4928b35e59bc: buy 0 (t: 6, u: (0, 2.0), q: (1, 4))', 'partners': "['c_3-0230100d-3633-49be-bb01-4928b35e59bc', 'm_3-418c12ae-b8cd-4e28-a9a8-b998b4ef7df6']", 'seller': 'm_3-418c12ae-b8cd-4e28-a9a8-b998b4ef7df6', 'buyer': 'c_3-0230100d-3633-49be-bb01-4928b35e59bc'} 2019-02-27 11:33:50,370 - DEBUG - 3/10 [40.00%]: Contract [to be signed at 4]: ['c_2', 'm_1'] > {'time': 6, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_2-c1142518-c4d8-4f80-9889-693a093ef989: buy 0 (t: 6, u: (0, 2.0), q: (1, 4))', 'partners': "['c_2-c1142518-c4d8-4f80-9889-693a093ef989', 'm_1-b789f15d-3508-464a-8717-8ba1da159754']", 'seller': 'm_1-b789f15d-3508-464a-8717-8ba1da159754', 'buyer': 'c_2-c1142518-c4d8-4f80-9889-693a093ef989'} 2019-02-27 11:33:50,370 - DEBUG - 3/10 [40.00%]: Contract [to be signed at 4]: ['c_0', 'm_2'] > {'time': 6, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_0-b6f40f78-35c5-4b76-9f90-53a459a66882: buy 0 (t: 6, u: (0, 2.0), q: (1, 4))', 'partners': "['c_0-b6f40f78-35c5-4b76-9f90-53a459a66882', 'm_2-f4d60475-9842-4006-8513-ca39a2379160']", 'seller': 'm_2-f4d60475-9842-4006-8513-ca39a2379160', 'buyer': 'c_0-b6f40f78-35c5-4b76-9f90-53a459a66882'} 2019-02-27 11:33:50,370 - DEBUG - 3/10 [40.00%]: Contract [to be signed at 4]: ['c_1', 'm_0'] > {'time': 6, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_1-68b3b84c-c42b-4582-9119-917484eb77ef: buy 0 (t: 6, u: (0, 2.0), q: (1, 3))', 'partners': "['c_1-68b3b84c-c42b-4582-9119-917484eb77ef', 'm_0-61b223a2-ea24-4bfc-9bf3-aa85fa8a955a']", 'seller': 'm_0-61b223a2-ea24-4bfc-9bf3-aa85fa8a955a', 'buyer': 'c_1-68b3b84c-c42b-4582-9119-917484eb77ef'} 2019-02-27 11:33:50,371 - DEBUG - 3/10 [40.00%]: Contract [to be signed at 4]: ['c_4', 'm_0'] > {'time': 6, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_4-76d9311e-d5f6-4e91-bb83-72994095e2c6: buy 0 (t: 6, u: (0, 2.0), q: (1, 4))', 'partners': "['c_4-76d9311e-d5f6-4e91-bb83-72994095e2c6', 'm_0-61b223a2-ea24-4bfc-9bf3-aa85fa8a955a']", 'seller': 'm_0-61b223a2-ea24-4bfc-9bf3-aa85fa8a955a', 'buyer': 'c_4-76d9311e-d5f6-4e91-bb83-72994095e2c6'} 2019-02-27 11:33:50,371 - DEBUG - 3/10 [40.00%]: Contract [to be signed at 4]: ['c_1', 'm_3'] > {'time': 6, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_1-68b3b84c-c42b-4582-9119-917484eb77ef: buy 0 (t: 6, u: (0, 2.0), q: (1, 3))', 'partners': "['c_1-68b3b84c-c42b-4582-9119-917484eb77ef', 'm_3-418c12ae-b8cd-4e28-a9a8-b998b4ef7df6']", 'seller': 'm_3-418c12ae-b8cd-4e28-a9a8-b998b4ef7df6', 'buyer': 'c_1-68b3b84c-c42b-4582-9119-917484eb77ef'} 2019-02-27 11:33:50,371 - DEBUG - 3/10 [40.00%]: Contract [to be signed at 4]: ['c_1', 'm_2'] > {'time': 6, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_1-68b3b84c-c42b-4582-9119-917484eb77ef: buy 0 (t: 6, u: (0, 2.0), q: (1, 3))', 'partners': "['c_1-68b3b84c-c42b-4582-9119-917484eb77ef', 'm_2-f4d60475-9842-4006-8513-ca39a2379160']", 'seller': 'm_2-f4d60475-9842-4006-8513-ca39a2379160', 'buyer': 'c_1-68b3b84c-c42b-4582-9119-917484eb77ef'} 2019-02-27 11:33:50,371 - DEBUG - 3/10 [40.00%]: Contract [to be signed at 4]: ['c_1', 'm_1'] > {'time': 6, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_1-68b3b84c-c42b-4582-9119-917484eb77ef: buy 0 (t: 6, u: (0, 2.0), q: (1, 3))', 'partners': "['c_1-68b3b84c-c42b-4582-9119-917484eb77ef', 'm_1-b789f15d-3508-464a-8717-8ba1da159754']", 'seller': 'm_1-b789f15d-3508-464a-8717-8ba1da159754', 'buyer': 'c_1-68b3b84c-c42b-4582-9119-917484eb77ef'} 2019-02-27 11:33:50,372 - DEBUG - 3/10 [40.00%]: Contract [to be signed at 4]: ['c_3', 'm_1'] > {'time': 6, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_3-0230100d-3633-49be-bb01-4928b35e59bc: buy 0 (t: 6, u: (0, 2.0), q: (1, 4))', 'partners': "['c_3-0230100d-3633-49be-bb01-4928b35e59bc', 'm_1-b789f15d-3508-464a-8717-8ba1da159754']", 'seller': 'm_1-b789f15d-3508-464a-8717-8ba1da159754', 'buyer': 'c_3-0230100d-3633-49be-bb01-4928b35e59bc'} 2019-02-27 11:33:50,372 - DEBUG - 3/10 [40.00%]: Contract [to be signed at 4]: ['c_4', 'm_4'] > {'time': 6, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_4-76d9311e-d5f6-4e91-bb83-72994095e2c6: buy 0 (t: 6, u: (0, 2.0), q: (1, 4))', 'partners': "['c_4-76d9311e-d5f6-4e91-bb83-72994095e2c6', 'm_4-4f6b8ebc-32b0-44d5-88d6-88b3cec0b489']", 'seller': 'm_4-4f6b8ebc-32b0-44d5-88d6-88b3cec0b489', 'buyer': 'c_4-76d9311e-d5f6-4e91-bb83-72994095e2c6'} 2019-02-27 11:33:50,372 - DEBUG - 3/10 [40.00%]: Contract [to be signed at 4]: ['c_2', 'm_4'] > {'time': 6, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_2-c1142518-c4d8-4f80-9889-693a093ef989: buy 0 (t: 6, u: (0, 2.0), q: (1, 4))', 'partners': "['c_2-c1142518-c4d8-4f80-9889-693a093ef989', 'm_4-4f6b8ebc-32b0-44d5-88d6-88b3cec0b489']", 'seller': 'm_4-4f6b8ebc-32b0-44d5-88d6-88b3cec0b489', 'buyer': 'c_2-c1142518-c4d8-4f80-9889-693a093ef989'} 2019-02-27 11:33:50,373 - DEBUG - 3/10 [40.00%]: Contract [to be signed at 4]: ['c_3', 'm_0'] > {'time': 6, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_3-0230100d-3633-49be-bb01-4928b35e59bc: buy 0 (t: 6, u: (0, 2.0), q: (1, 4))', 'partners': "['c_3-0230100d-3633-49be-bb01-4928b35e59bc', 'm_0-61b223a2-ea24-4bfc-9bf3-aa85fa8a955a']", 'seller': 'm_0-61b223a2-ea24-4bfc-9bf3-aa85fa8a955a', 'buyer': 'c_3-0230100d-3633-49be-bb01-4928b35e59bc'} 2019-02-27 11:33:50,373 - DEBUG - 3/10 [40.00%]: Contract [to be signed at 4]: ['c_4', 'm_3'] > {'time': 6, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_4-76d9311e-d5f6-4e91-bb83-72994095e2c6: buy 0 (t: 6, u: (0, 2.0), q: (1, 4))', 'partners': "['c_4-76d9311e-d5f6-4e91-bb83-72994095e2c6', 'm_3-418c12ae-b8cd-4e28-a9a8-b998b4ef7df6']", 'seller': 'm_3-418c12ae-b8cd-4e28-a9a8-b998b4ef7df6', 'buyer': 'c_4-76d9311e-d5f6-4e91-bb83-72994095e2c6'} 2019-02-27 11:33:50,373 - DEBUG - 3/10 [40.00%]: Contract [to be signed at 4]: ['c_1', 'm_4'] > {'time': 6, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_1-68b3b84c-c42b-4582-9119-917484eb77ef: buy 0 (t: 6, u: (0, 2.0), q: (1, 3))', 'partners': "['c_1-68b3b84c-c42b-4582-9119-917484eb77ef', 'm_4-4f6b8ebc-32b0-44d5-88d6-88b3cec0b489']", 'seller': 'm_4-4f6b8ebc-32b0-44d5-88d6-88b3cec0b489', 'buyer': 'c_1-68b3b84c-c42b-4582-9119-917484eb77ef'} 2019-02-27 11:33:50,375 - INFO - 3/10 [40.00%]: m_0 requested negmas.sao.SAOMechanism[None] with ['c_3', 'm_0'] (ID b0b9e9ca-48bc-4d84-979d-1ec194cf80ec) 2019-02-27 11:33:50,376 - INFO - 3/10 [40.00%]: m_0-61b223a2-ea24-4bfc-9bf3-aa85fa8a955a request was accepted 2019-02-27 11:33:50,377 - INFO - 3/10 [40.00%]: m_1 requested negmas.sao.SAOMechanism[None] with ['c_3', 'm_1'] (ID cbe47110-b774-4b4e-aeed-325027c3f42a) 2019-02-27 11:33:50,377 - INFO - 3/10 [40.00%]: m_1-b789f15d-3508-464a-8717-8ba1da159754 request was accepted 2019-02-27 11:33:50,379 - INFO - 3/10 [40.00%]: m_2 requested negmas.sao.SAOMechanism[None] with ['c_3', 'm_2'] (ID 0ffd99ee-6016-4cf5-a0ac-cf7010889275) 2019-02-27 11:33:50,379 - INFO - 3/10 [40.00%]: m_2-f4d60475-9842-4006-8513-ca39a2379160 request was accepted 2019-02-27 11:33:50,380 - INFO - 3/10 [40.00%]: m_3 requested negmas.sao.SAOMechanism[None] with ['c_3', 'm_3'] (ID 47bdb157-1d7d-44d1-a4c8-5d4fdf784542) 2019-02-27 11:33:50,381 - INFO - 3/10 [40.00%]: m_3-418c12ae-b8cd-4e28-a9a8-b998b4ef7df6 request was accepted 2019-02-27 11:33:50,383 - INFO - 3/10 [40.00%]: m_4 requested negmas.sao.SAOMechanism[None] with ['c_3', 'm_4'] (ID eafdd3e3-ba5c-41f3-a4be-cc366e3b701b) 2019-02-27 11:33:50,384 - INFO - 3/10 [40.00%]: m_4-4f6b8ebc-32b0-44d5-88d6-88b3cec0b489 request was accepted 2019-02-27 11:33:50,385 - INFO - 3/10 [40.00%]: m_0 requested negmas.sao.SAOMechanism[None] with ['c_2', 'm_0'] (ID d4a77f12-c913-4f21-abc0-ab54f2056d57) 2019-02-27 11:33:50,385 - INFO - 3/10 [40.00%]: m_0-61b223a2-ea24-4bfc-9bf3-aa85fa8a955a request was accepted 2019-02-27 11:33:50,386 - INFO - 3/10 [40.00%]: m_1 requested negmas.sao.SAOMechanism[None] with ['c_2', 'm_1'] (ID 9684f086-1d19-494d-8e41-493553036ca6) 2019-02-27 11:33:50,387 - INFO - 3/10 [40.00%]: m_1-b789f15d-3508-464a-8717-8ba1da159754 request was accepted 2019-02-27 11:33:50,388 - INFO - 3/10 [40.00%]: m_2 requested negmas.sao.SAOMechanism[None] with ['c_2', 'm_2'] (ID 275bcf9f-0615-4d68-b7b7-36e149161102) 2019-02-27 11:33:50,388 - INFO - 3/10 [40.00%]: m_2-f4d60475-9842-4006-8513-ca39a2379160 request was accepted 2019-02-27 11:33:50,389 - INFO - 3/10 [40.00%]: m_3 requested negmas.sao.SAOMechanism[None] with ['c_2', 'm_3'] (ID f45c6ed7-7332-4a12-a9a0-4626ecf489cd) 2019-02-27 11:33:50,390 - INFO - 3/10 [40.00%]: m_3-418c12ae-b8cd-4e28-a9a8-b998b4ef7df6 request was accepted 2019-02-27 11:33:50,392 - INFO - 3/10 [40.00%]: m_4 requested negmas.sao.SAOMechanism[None] with ['c_2', 'm_4'] (ID 6cb444ab-82cd-40f5-91e4-400e0b4343ff) 2019-02-27 11:33:50,394 - INFO - 3/10 [40.00%]: m_4-4f6b8ebc-32b0-44d5-88d6-88b3cec0b489 request was accepted 2019-02-27 11:33:50,396 - INFO - 3/10 [40.00%]: m_0 requested negmas.sao.SAOMechanism[None] with ['c_1', 'm_0'] (ID 0dd8c0eb-54c6-410d-afc8-98c8bb2c46f9) 2019-02-27 11:33:50,397 - INFO - 3/10 [40.00%]: m_0-61b223a2-ea24-4bfc-9bf3-aa85fa8a955a request was accepted 2019-02-27 11:33:50,398 - INFO - 3/10 [40.00%]: m_1 requested negmas.sao.SAOMechanism[None] with ['c_1', 'm_1'] (ID 7d395181-fac4-46e1-ac35-eac09970b625) 2019-02-27 11:33:50,399 - INFO - 3/10 [40.00%]: m_1-b789f15d-3508-464a-8717-8ba1da159754 request was accepted 2019-02-27 11:33:50,402 - INFO - 3/10 [40.00%]: m_2 requested negmas.sao.SAOMechanism[None] with ['c_1', 'm_2'] (ID 9a9ae701-f4b8-4193-a862-56192c9d322e) 2019-02-27 11:33:50,403 - INFO - 3/10 [40.00%]: m_2-f4d60475-9842-4006-8513-ca39a2379160 request was accepted 2019-02-27 11:33:50,405 - INFO - 3/10 [40.00%]: m_3 requested negmas.sao.SAOMechanism[None] with ['c_1', 'm_3'] (ID 685acecf-8121-4e49-8a81-97c3f560e46f) 2019-02-27 11:33:50,406 - INFO - 3/10 [40.00%]: m_3-418c12ae-b8cd-4e28-a9a8-b998b4ef7df6 request was accepted 2019-02-27 11:33:50,407 - INFO - 3/10 [40.00%]: m_4 requested negmas.sao.SAOMechanism[None] with ['c_1', 'm_4'] (ID d4a17416-5e9c-4486-9ac7-b22383265641) 2019-02-27 11:33:50,408 - INFO - 3/10 [40.00%]: m_4-4f6b8ebc-32b0-44d5-88d6-88b3cec0b489 request was accepted 2019-02-27 11:33:50,409 - INFO - 3/10 [40.00%]: m_0 requested negmas.sao.SAOMechanism[None] with ['c_0', 'm_0'] (ID 32766c6b-d9bd-46b0-9939-d66842e4145b) 2019-02-27 11:33:50,410 - INFO - 3/10 [40.00%]: m_0-61b223a2-ea24-4bfc-9bf3-aa85fa8a955a request was accepted 2019-02-27 11:33:50,411 - INFO - 3/10 [40.00%]: m_1 requested negmas.sao.SAOMechanism[None] with ['c_0', 'm_1'] (ID 6c2e5bae-b9d0-44e0-99c1-3af0a7ea9206) 2019-02-27 11:33:50,412 - INFO - 3/10 [40.00%]: m_1-b789f15d-3508-464a-8717-8ba1da159754 request was accepted 2019-02-27 11:33:50,413 - INFO - 3/10 [40.00%]: m_2 requested negmas.sao.SAOMechanism[None] with ['c_0', 'm_2'] (ID dcdb42e1-f92c-4736-b980-fee2c1ea04e0) 2019-02-27 11:33:50,414 - INFO - 3/10 [40.00%]: m_2-f4d60475-9842-4006-8513-ca39a2379160 request was accepted 2019-02-27 11:33:50,416 - INFO - 3/10 [40.00%]: m_3 requested negmas.sao.SAOMechanism[None] with ['c_0', 'm_3'] (ID 24661364-c6cf-43b1-9900-ac3494805a96) 2019-02-27 11:33:50,416 - INFO - 3/10 [40.00%]: m_3-418c12ae-b8cd-4e28-a9a8-b998b4ef7df6 request was accepted 2019-02-27 11:33:50,417 - INFO - 3/10 [40.00%]: m_4 requested negmas.sao.SAOMechanism[None] with ['c_0', 'm_4'] (ID 4209236d-1071-4d41-b1d1-95aca614705e) 2019-02-27 11:33:50,418 - INFO - 3/10 [40.00%]: m_4-4f6b8ebc-32b0-44d5-88d6-88b3cec0b489 request was accepted 2019-02-27 11:33:50,419 - INFO - 3/10 [40.00%]: m_0 requested negmas.sao.SAOMechanism[None] with ['c_4', 'm_0'] (ID d1ca6bd9-71ec-4596-90e4-8752fd169ce1) 2019-02-27 11:33:50,420 - INFO - 3/10 [40.00%]: m_0-61b223a2-ea24-4bfc-9bf3-aa85fa8a955a request was accepted 2019-02-27 11:33:50,421 - INFO - 3/10 [40.00%]: m_1 requested negmas.sao.SAOMechanism[None] with ['c_4', 'm_1'] (ID ecf0532d-ff4f-4b09-bb7a-de2770c645a0) 2019-02-27 11:33:50,422 - INFO - 3/10 [40.00%]: m_1-b789f15d-3508-464a-8717-8ba1da159754 request was accepted 2019-02-27 11:33:50,423 - INFO - 3/10 [40.00%]: m_2 requested negmas.sao.SAOMechanism[None] with ['c_4', 'm_2'] (ID d40e8a02-3236-4ded-89e4-def6bc771c51) 2019-02-27 11:33:50,423 - INFO - 3/10 [40.00%]: m_2-f4d60475-9842-4006-8513-ca39a2379160 request was accepted 2019-02-27 11:33:50,424 - INFO - 3/10 [40.00%]: m_3 requested negmas.sao.SAOMechanism[None] with ['c_4', 'm_3'] (ID 1afe049b-e9bd-4baa-9164-29a151c549bf) 2019-02-27 11:33:50,425 - INFO - 3/10 [40.00%]: m_3-418c12ae-b8cd-4e28-a9a8-b998b4ef7df6 request was accepted 2019-02-27 11:33:50,426 - INFO - 3/10 [40.00%]: m_4 requested negmas.sao.SAOMechanism[None] with ['c_4', 'm_4'] (ID c32bf445-1374-4fc9-a9ee-b202e421be21) 2019-02-27 11:33:50,426 - INFO - 3/10 [40.00%]: m_4-4f6b8ebc-32b0-44d5-88d6-88b3cec0b489 request was accepted 2019-02-27 11:33:50,426 - INFO - 3/10 [40.00%]: Executing c_4-76d9311e-d5f6-4e91-bb83-72994095e2c6, m_1-b789f15d-3508-464a-8717-8ba1da159754 agreed on {'time': 3, 'quantity': 4, 'unit_price': 0.5} 2019-02-27 11:33:50,426 - DEBUG - 3/10 [40.00%]: Moved 4 units of p0 from m_1 to c_4 for 2.0 dollars 2019-02-27 11:33:50,427 - INFO - 3/10 [40.00%]: Executing c_3-0230100d-3633-49be-bb01-4928b35e59bc, m_2-f4d60475-9842-4006-8513-ca39a2379160 agreed on {'time': 3, 'quantity': 4, 'unit_price': 0.5} 2019-02-27 11:33:50,427 - DEBUG - 3/10 [40.00%]: Moved 4 units of p0 from m_2 to c_3 for 2.0 dollars 2019-02-27 11:33:50,427 - INFO - 3/10 [40.00%]: Executing c_0-b6f40f78-35c5-4b76-9f90-53a459a66882, m_2-f4d60475-9842-4006-8513-ca39a2379160 agreed on {'time': 3, 'quantity': 3, 'unit_price': 0.5} 2019-02-27 11:33:50,427 - DEBUG - 3/10 [40.00%]: Moved 3 units of p0 from m_2 to c_0 for 1.5 dollars 2019-02-27 11:33:50,427 - INFO - 3/10 [40.00%]: Executing c_1-68b3b84c-c42b-4582-9119-917484eb77ef, m_0-61b223a2-ea24-4bfc-9bf3-aa85fa8a955a agreed on {'time': 3, 'quantity': 4, 'unit_price': 0.5} 2019-02-27 11:33:50,427 - DEBUG - 3/10 [40.00%]: Moved 4 units of p0 from m_0 to c_1 for 2.0 dollars 2019-02-27 11:33:50,427 - INFO - 3/10 [40.00%]: Executing c_2-c1142518-c4d8-4f80-9889-693a093ef989, m_4-4f6b8ebc-32b0-44d5-88d6-88b3cec0b489 agreed on {'time': 3, 'quantity': 4, 'unit_price': 0.5} 2019-02-27 11:33:50,427 - DEBUG - 3/10 [40.00%]: Moved 4 units of p0 from m_4 to c_2 for 2.0 dollars 2019-02-27 11:33:50,427 - DEBUG - 3/10 [40.00%]: Factory 95e75c6e-fd73-4d10-bb63-7e6fd5ed934d: money=-3.5, storage={}, loans=0.0 2019-02-27 11:33:50,427 - DEBUG - 3/10 [40.00%]: Factory 1d03dc99-48cd-4b69-81d8-4faf95f470b1: money=-3.5, storage={}, loans=0.0 2019-02-27 11:33:50,427 - DEBUG - 3/10 [40.00%]: Factory 3988d198-d05c-4a8a-93c9-8a88363a07d6: money=-4.0, storage={}, loans=0.0 2019-02-27 11:33:50,427 - DEBUG - 3/10 [40.00%]: Factory bad2c634-f9b5-4ae3-8b59-626ce7e171fb: money=-3.5, storage={}, loans=0.0 2019-02-27 11:33:50,427 - DEBUG - 3/10 [40.00%]: Factory ee428c0e-e853-4495-8bbd-24302264a757: money=-3.5, storage={}, loans=0.0 2019-02-27 11:33:50,427 - DEBUG - 3/10 [40.00%]: Factory cb5ab840-9bd8-41f9-866a-ca43e56e74c6: money=3.5, storage={0: -7}, loans=0.0 2019-02-27 11:33:50,427 - DEBUG - 3/10 [40.00%]: Factory b5cdcb3a-a4bd-478d-9795-d361eb70cf32: money=4.0, storage={0: -8}, loans=0.0 2019-02-27 11:33:50,427 - DEBUG - 3/10 [40.00%]: Factory cb4aedd6-68a2-450a-8d92-117fcb5ae311: money=3.5, storage={0: -7}, loans=0.0 2019-02-27 11:33:50,427 - DEBUG - 3/10 [40.00%]: Factory 986a8ca5-1b97-449f-b316-450edc5ed050: money=3.5, storage={0: -7}, loans=0.0 2019-02-27 11:33:50,427 - DEBUG - 3/10 [40.00%]: Factory d70b6918-35dd-4eab-924c-7a13f3ad3feb: money=3.5, storage={0: -7}, loans=0.0 2019-02-27 11:33:50,428 - INFO - 4/10 [50.00%]: 25 Negotiations/4 _entities 2019-02-27 11:33:50,668 - DEBUG - 4/10 [50.00%]: Contract [to be signed at 5]: ['c_1', 'm_2'] > {'time': 7, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_1-68b3b84c-c42b-4582-9119-917484eb77ef: buy 0 (t: 7, u: (0, 2.0), q: (1, 3))', 'partners': "['c_1-68b3b84c-c42b-4582-9119-917484eb77ef', 'm_2-f4d60475-9842-4006-8513-ca39a2379160']", 'seller': 'm_2-f4d60475-9842-4006-8513-ca39a2379160', 'buyer': 'c_1-68b3b84c-c42b-4582-9119-917484eb77ef'} 2019-02-27 11:33:50,668 - DEBUG - 4/10 [50.00%]: Contract [to be signed at 5]: ['c_3', 'm_4'] > {'time': 7, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_3-0230100d-3633-49be-bb01-4928b35e59bc: buy 0 (t: 7, u: (0, 2.0), q: (1, 3))', 'partners': "['c_3-0230100d-3633-49be-bb01-4928b35e59bc', 'm_4-4f6b8ebc-32b0-44d5-88d6-88b3cec0b489']", 'seller': 'm_4-4f6b8ebc-32b0-44d5-88d6-88b3cec0b489', 'buyer': 'c_3-0230100d-3633-49be-bb01-4928b35e59bc'} 2019-02-27 11:33:50,669 - DEBUG - 4/10 [50.00%]: Contract [to be signed at 5]: ['c_2', 'm_0'] > {'time': 7, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_2-c1142518-c4d8-4f80-9889-693a093ef989: buy 0 (t: 7, u: (0, 2.0), q: (1, 3))', 'partners': "['c_2-c1142518-c4d8-4f80-9889-693a093ef989', 'm_0-61b223a2-ea24-4bfc-9bf3-aa85fa8a955a']", 'seller': 'm_0-61b223a2-ea24-4bfc-9bf3-aa85fa8a955a', 'buyer': 'c_2-c1142518-c4d8-4f80-9889-693a093ef989'} 2019-02-27 11:33:50,669 - DEBUG - 4/10 [50.00%]: Contract [to be signed at 5]: ['c_0', 'm_2'] > {'time': 7, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_0-b6f40f78-35c5-4b76-9f90-53a459a66882: buy 0 (t: 7, u: (0, 2.0), q: (1, 3))', 'partners': "['c_0-b6f40f78-35c5-4b76-9f90-53a459a66882', 'm_2-f4d60475-9842-4006-8513-ca39a2379160']", 'seller': 'm_2-f4d60475-9842-4006-8513-ca39a2379160', 'buyer': 'c_0-b6f40f78-35c5-4b76-9f90-53a459a66882'} 2019-02-27 11:33:50,669 - DEBUG - 4/10 [50.00%]: Contract [to be signed at 5]: ['c_0', 'm_0'] > {'time': 7, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_0-b6f40f78-35c5-4b76-9f90-53a459a66882: buy 0 (t: 7, u: (0, 2.0), q: (1, 3))', 'partners': "['c_0-b6f40f78-35c5-4b76-9f90-53a459a66882', 'm_0-61b223a2-ea24-4bfc-9bf3-aa85fa8a955a']", 'seller': 'm_0-61b223a2-ea24-4bfc-9bf3-aa85fa8a955a', 'buyer': 'c_0-b6f40f78-35c5-4b76-9f90-53a459a66882'} 2019-02-27 11:33:50,669 - DEBUG - 4/10 [50.00%]: Contract [to be signed at 5]: ['c_3', 'm_0'] > {'time': 7, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_3-0230100d-3633-49be-bb01-4928b35e59bc: buy 0 (t: 7, u: (0, 2.0), q: (1, 3))', 'partners': "['c_3-0230100d-3633-49be-bb01-4928b35e59bc', 'm_0-61b223a2-ea24-4bfc-9bf3-aa85fa8a955a']", 'seller': 'm_0-61b223a2-ea24-4bfc-9bf3-aa85fa8a955a', 'buyer': 'c_3-0230100d-3633-49be-bb01-4928b35e59bc'} 2019-02-27 11:33:50,670 - DEBUG - 4/10 [50.00%]: Contract [to be signed at 5]: ['c_4', 'm_3'] > {'time': 7, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_4-76d9311e-d5f6-4e91-bb83-72994095e2c6: buy 0 (t: 7, u: (0, 2.0), q: (1, 3))', 'partners': "['c_4-76d9311e-d5f6-4e91-bb83-72994095e2c6', 'm_3-418c12ae-b8cd-4e28-a9a8-b998b4ef7df6']", 'seller': 'm_3-418c12ae-b8cd-4e28-a9a8-b998b4ef7df6', 'buyer': 'c_4-76d9311e-d5f6-4e91-bb83-72994095e2c6'} 2019-02-27 11:33:50,670 - DEBUG - 4/10 [50.00%]: Contract [to be signed at 5]: ['c_1', 'm_4'] > {'time': 7, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_1-68b3b84c-c42b-4582-9119-917484eb77ef: buy 0 (t: 7, u: (0, 2.0), q: (1, 3))', 'partners': "['c_1-68b3b84c-c42b-4582-9119-917484eb77ef', 'm_4-4f6b8ebc-32b0-44d5-88d6-88b3cec0b489']", 'seller': 'm_4-4f6b8ebc-32b0-44d5-88d6-88b3cec0b489', 'buyer': 'c_1-68b3b84c-c42b-4582-9119-917484eb77ef'} 2019-02-27 11:33:50,670 - DEBUG - 4/10 [50.00%]: Contract [to be signed at 5]: ['c_4', 'm_4'] > {'time': 7, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_4-76d9311e-d5f6-4e91-bb83-72994095e2c6: buy 0 (t: 7, u: (0, 2.0), q: (1, 3))', 'partners': "['c_4-76d9311e-d5f6-4e91-bb83-72994095e2c6', 'm_4-4f6b8ebc-32b0-44d5-88d6-88b3cec0b489']", 'seller': 'm_4-4f6b8ebc-32b0-44d5-88d6-88b3cec0b489', 'buyer': 'c_4-76d9311e-d5f6-4e91-bb83-72994095e2c6'} 2019-02-27 11:33:50,671 - DEBUG - 4/10 [50.00%]: Contract [to be signed at 5]: ['c_2', 'm_1'] > {'time': 7, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_2-c1142518-c4d8-4f80-9889-693a093ef989: buy 0 (t: 7, u: (0, 2.0), q: (1, 3))', 'partners': "['c_2-c1142518-c4d8-4f80-9889-693a093ef989', 'm_1-b789f15d-3508-464a-8717-8ba1da159754']", 'seller': 'm_1-b789f15d-3508-464a-8717-8ba1da159754', 'buyer': 'c_2-c1142518-c4d8-4f80-9889-693a093ef989'} 2019-02-27 11:33:50,671 - DEBUG - 4/10 [50.00%]: Contract [to be signed at 5]: ['c_2', 'm_4'] > {'time': 7, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_2-c1142518-c4d8-4f80-9889-693a093ef989: buy 0 (t: 7, u: (0, 2.0), q: (1, 3))', 'partners': "['c_2-c1142518-c4d8-4f80-9889-693a093ef989', 'm_4-4f6b8ebc-32b0-44d5-88d6-88b3cec0b489']", 'seller': 'm_4-4f6b8ebc-32b0-44d5-88d6-88b3cec0b489', 'buyer': 'c_2-c1142518-c4d8-4f80-9889-693a093ef989'} 2019-02-27 11:33:50,671 - DEBUG - 4/10 [50.00%]: Contract [to be signed at 5]: ['c_3', 'm_1'] > {'time': 7, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_3-0230100d-3633-49be-bb01-4928b35e59bc: buy 0 (t: 7, u: (0, 2.0), q: (1, 3))', 'partners': "['c_3-0230100d-3633-49be-bb01-4928b35e59bc', 'm_1-b789f15d-3508-464a-8717-8ba1da159754']", 'seller': 'm_1-b789f15d-3508-464a-8717-8ba1da159754', 'buyer': 'c_3-0230100d-3633-49be-bb01-4928b35e59bc'} 2019-02-27 11:33:50,671 - DEBUG - 4/10 [50.00%]: Contract [to be signed at 5]: ['c_2', 'm_3'] > {'time': 7, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_2-c1142518-c4d8-4f80-9889-693a093ef989: buy 0 (t: 7, u: (0, 2.0), q: (1, 3))', 'partners': "['c_2-c1142518-c4d8-4f80-9889-693a093ef989', 'm_3-418c12ae-b8cd-4e28-a9a8-b998b4ef7df6']", 'seller': 'm_3-418c12ae-b8cd-4e28-a9a8-b998b4ef7df6', 'buyer': 'c_2-c1142518-c4d8-4f80-9889-693a093ef989'} 2019-02-27 11:33:50,672 - DEBUG - 4/10 [50.00%]: Contract [to be signed at 5]: ['c_0', 'm_4'] > {'time': 7, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_0-b6f40f78-35c5-4b76-9f90-53a459a66882: buy 0 (t: 7, u: (0, 2.0), q: (1, 3))', 'partners': "['c_0-b6f40f78-35c5-4b76-9f90-53a459a66882', 'm_4-4f6b8ebc-32b0-44d5-88d6-88b3cec0b489']", 'seller': 'm_4-4f6b8ebc-32b0-44d5-88d6-88b3cec0b489', 'buyer': 'c_0-b6f40f78-35c5-4b76-9f90-53a459a66882'} 2019-02-27 11:33:50,672 - DEBUG - 4/10 [50.00%]: Contract [to be signed at 5]: ['c_4', 'm_0'] > {'time': 7, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_4-76d9311e-d5f6-4e91-bb83-72994095e2c6: buy 0 (t: 7, u: (0, 2.0), q: (1, 3))', 'partners': "['c_4-76d9311e-d5f6-4e91-bb83-72994095e2c6', 'm_0-61b223a2-ea24-4bfc-9bf3-aa85fa8a955a']", 'seller': 'm_0-61b223a2-ea24-4bfc-9bf3-aa85fa8a955a', 'buyer': 'c_4-76d9311e-d5f6-4e91-bb83-72994095e2c6'} 2019-02-27 11:33:50,672 - DEBUG - 4/10 [50.00%]: Contract [to be signed at 5]: ['c_0', 'm_3'] > {'time': 7, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_0-b6f40f78-35c5-4b76-9f90-53a459a66882: buy 0 (t: 7, u: (0, 2.0), q: (1, 3))', 'partners': "['c_0-b6f40f78-35c5-4b76-9f90-53a459a66882', 'm_3-418c12ae-b8cd-4e28-a9a8-b998b4ef7df6']", 'seller': 'm_3-418c12ae-b8cd-4e28-a9a8-b998b4ef7df6', 'buyer': 'c_0-b6f40f78-35c5-4b76-9f90-53a459a66882'} 2019-02-27 11:33:50,673 - DEBUG - 4/10 [50.00%]: Contract [to be signed at 5]: ['c_2', 'm_2'] > {'time': 7, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_2-c1142518-c4d8-4f80-9889-693a093ef989: buy 0 (t: 7, u: (0, 2.0), q: (1, 3))', 'partners': "['c_2-c1142518-c4d8-4f80-9889-693a093ef989', 'm_2-f4d60475-9842-4006-8513-ca39a2379160']", 'seller': 'm_2-f4d60475-9842-4006-8513-ca39a2379160', 'buyer': 'c_2-c1142518-c4d8-4f80-9889-693a093ef989'} 2019-02-27 11:33:50,673 - DEBUG - 4/10 [50.00%]: Contract [to be signed at 5]: ['c_1', 'm_0'] > {'time': 7, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_1-68b3b84c-c42b-4582-9119-917484eb77ef: buy 0 (t: 7, u: (0, 2.0), q: (1, 3))', 'partners': "['c_1-68b3b84c-c42b-4582-9119-917484eb77ef', 'm_0-61b223a2-ea24-4bfc-9bf3-aa85fa8a955a']", 'seller': 'm_0-61b223a2-ea24-4bfc-9bf3-aa85fa8a955a', 'buyer': 'c_1-68b3b84c-c42b-4582-9119-917484eb77ef'} 2019-02-27 11:33:50,674 - DEBUG - 4/10 [50.00%]: Contract [to be signed at 5]: ['c_3', 'm_3'] > {'time': 7, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_3-0230100d-3633-49be-bb01-4928b35e59bc: buy 0 (t: 7, u: (0, 2.0), q: (1, 3))', 'partners': "['c_3-0230100d-3633-49be-bb01-4928b35e59bc', 'm_3-418c12ae-b8cd-4e28-a9a8-b998b4ef7df6']", 'seller': 'm_3-418c12ae-b8cd-4e28-a9a8-b998b4ef7df6', 'buyer': 'c_3-0230100d-3633-49be-bb01-4928b35e59bc'} 2019-02-27 11:33:50,674 - DEBUG - 4/10 [50.00%]: Contract [to be signed at 5]: ['c_3', 'm_2'] > {'time': 7, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_3-0230100d-3633-49be-bb01-4928b35e59bc: buy 0 (t: 7, u: (0, 2.0), q: (1, 3))', 'partners': "['c_3-0230100d-3633-49be-bb01-4928b35e59bc', 'm_2-f4d60475-9842-4006-8513-ca39a2379160']", 'seller': 'm_2-f4d60475-9842-4006-8513-ca39a2379160', 'buyer': 'c_3-0230100d-3633-49be-bb01-4928b35e59bc'} 2019-02-27 11:33:50,674 - DEBUG - 4/10 [50.00%]: Contract [to be signed at 5]: ['c_0', 'm_1'] > {'time': 7, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_0-b6f40f78-35c5-4b76-9f90-53a459a66882: buy 0 (t: 7, u: (0, 2.0), q: (1, 3))', 'partners': "['c_0-b6f40f78-35c5-4b76-9f90-53a459a66882', 'm_1-b789f15d-3508-464a-8717-8ba1da159754']", 'seller': 'm_1-b789f15d-3508-464a-8717-8ba1da159754', 'buyer': 'c_0-b6f40f78-35c5-4b76-9f90-53a459a66882'} 2019-02-27 11:33:50,675 - DEBUG - 4/10 [50.00%]: Contract [to be signed at 5]: ['c_4', 'm_1'] > {'time': 7, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_4-76d9311e-d5f6-4e91-bb83-72994095e2c6: buy 0 (t: 7, u: (0, 2.0), q: (1, 3))', 'partners': "['c_4-76d9311e-d5f6-4e91-bb83-72994095e2c6', 'm_1-b789f15d-3508-464a-8717-8ba1da159754']", 'seller': 'm_1-b789f15d-3508-464a-8717-8ba1da159754', 'buyer': 'c_4-76d9311e-d5f6-4e91-bb83-72994095e2c6'} 2019-02-27 11:33:50,675 - DEBUG - 4/10 [50.00%]: Contract [to be signed at 5]: ['c_1', 'm_3'] > {'time': 7, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_1-68b3b84c-c42b-4582-9119-917484eb77ef: buy 0 (t: 7, u: (0, 2.0), q: (1, 3))', 'partners': "['c_1-68b3b84c-c42b-4582-9119-917484eb77ef', 'm_3-418c12ae-b8cd-4e28-a9a8-b998b4ef7df6']", 'seller': 'm_3-418c12ae-b8cd-4e28-a9a8-b998b4ef7df6', 'buyer': 'c_1-68b3b84c-c42b-4582-9119-917484eb77ef'} 2019-02-27 11:33:50,676 - DEBUG - 4/10 [50.00%]: Contract [to be signed at 5]: ['c_1', 'm_1'] > {'time': 7, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_1-68b3b84c-c42b-4582-9119-917484eb77ef: buy 0 (t: 7, u: (0, 2.0), q: (1, 3))', 'partners': "['c_1-68b3b84c-c42b-4582-9119-917484eb77ef', 'm_1-b789f15d-3508-464a-8717-8ba1da159754']", 'seller': 'm_1-b789f15d-3508-464a-8717-8ba1da159754', 'buyer': 'c_1-68b3b84c-c42b-4582-9119-917484eb77ef'} 2019-02-27 11:33:50,676 - DEBUG - 4/10 [50.00%]: Contract [to be signed at 5]: ['c_4', 'm_2'] > {'time': 7, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_4-76d9311e-d5f6-4e91-bb83-72994095e2c6: buy 0 (t: 7, u: (0, 2.0), q: (1, 3))', 'partners': "['c_4-76d9311e-d5f6-4e91-bb83-72994095e2c6', 'm_2-f4d60475-9842-4006-8513-ca39a2379160']", 'seller': 'm_2-f4d60475-9842-4006-8513-ca39a2379160', 'buyer': 'c_4-76d9311e-d5f6-4e91-bb83-72994095e2c6'} 2019-02-27 11:33:50,678 - INFO - 4/10 [50.00%]: m_0 requested negmas.sao.SAOMechanism[None] with ['c_3', 'm_0'] (ID 3e254eb9-e514-4a5b-8800-1ddd4e8e7eb7) 2019-02-27 11:33:50,678 - INFO - 4/10 [50.00%]: m_0-61b223a2-ea24-4bfc-9bf3-aa85fa8a955a request was accepted 2019-02-27 11:33:50,679 - INFO - 4/10 [50.00%]: m_1 requested negmas.sao.SAOMechanism[None] with ['c_3', 'm_1'] (ID 3d2db178-0683-4816-9418-bfa565ef03f2) 2019-02-27 11:33:50,680 - INFO - 4/10 [50.00%]: m_1-b789f15d-3508-464a-8717-8ba1da159754 request was accepted 2019-02-27 11:33:50,681 - INFO - 4/10 [50.00%]: m_2 requested negmas.sao.SAOMechanism[None] with ['c_3', 'm_2'] (ID f278d2a2-7b68-4c98-855e-56cc09d80ec6) 2019-02-27 11:33:50,681 - INFO - 4/10 [50.00%]: m_2-f4d60475-9842-4006-8513-ca39a2379160 request was accepted 2019-02-27 11:33:50,682 - INFO - 4/10 [50.00%]: m_3 requested negmas.sao.SAOMechanism[None] with ['c_3', 'm_3'] (ID a9618b14-2469-42e2-8b78-1ecde06bd667) 2019-02-27 11:33:50,684 - INFO - 4/10 [50.00%]: m_3-418c12ae-b8cd-4e28-a9a8-b998b4ef7df6 request was accepted 2019-02-27 11:33:50,685 - INFO - 4/10 [50.00%]: m_4 requested negmas.sao.SAOMechanism[None] with ['c_3', 'm_4'] (ID c9d5a4d5-62ee-40ad-9d3e-269d82243324) 2019-02-27 11:33:50,686 - INFO - 4/10 [50.00%]: m_4-4f6b8ebc-32b0-44d5-88d6-88b3cec0b489 request was accepted 2019-02-27 11:33:50,688 - INFO - 4/10 [50.00%]: m_0 requested negmas.sao.SAOMechanism[None] with ['c_2', 'm_0'] (ID 8bcac924-e2f7-4eef-b501-0a744fd0b3dd) 2019-02-27 11:33:50,688 - INFO - 4/10 [50.00%]: m_0-61b223a2-ea24-4bfc-9bf3-aa85fa8a955a request was accepted 2019-02-27 11:33:50,689 - INFO - 4/10 [50.00%]: m_1 requested negmas.sao.SAOMechanism[None] with ['c_2', 'm_1'] (ID 93570d17-4ff9-4016-bab1-e37a8fba198c) 2019-02-27 11:33:50,690 - INFO - 4/10 [50.00%]: m_1-b789f15d-3508-464a-8717-8ba1da159754 request was accepted 2019-02-27 11:33:50,691 - INFO - 4/10 [50.00%]: m_2 requested negmas.sao.SAOMechanism[None] with ['c_2', 'm_2'] (ID 3c64dacc-b5ef-4761-b1e1-639691ef877e) 2019-02-27 11:33:50,692 - INFO - 4/10 [50.00%]: m_2-f4d60475-9842-4006-8513-ca39a2379160 request was accepted 2019-02-27 11:33:50,694 - INFO - 4/10 [50.00%]: m_3 requested negmas.sao.SAOMechanism[None] with ['c_2', 'm_3'] (ID d663c307-dd5c-4664-8c55-110697ff507e) 2019-02-27 11:33:50,695 - INFO - 4/10 [50.00%]: m_3-418c12ae-b8cd-4e28-a9a8-b998b4ef7df6 request was accepted 2019-02-27 11:33:50,697 - INFO - 4/10 [50.00%]: m_4 requested negmas.sao.SAOMechanism[None] with ['c_2', 'm_4'] (ID dea26bb7-4bbc-4d77-b170-f45b16adc6f0) 2019-02-27 11:33:50,697 - INFO - 4/10 [50.00%]: m_4-4f6b8ebc-32b0-44d5-88d6-88b3cec0b489 request was accepted 2019-02-27 11:33:50,700 - INFO - 4/10 [50.00%]: m_0 requested negmas.sao.SAOMechanism[None] with ['c_1', 'm_0'] (ID 618ed79c-a19c-41db-9c97-a9d601cc3302) 2019-02-27 11:33:50,701 - INFO - 4/10 [50.00%]: m_0-61b223a2-ea24-4bfc-9bf3-aa85fa8a955a request was accepted 2019-02-27 11:33:50,702 - INFO - 4/10 [50.00%]: m_1 requested negmas.sao.SAOMechanism[None] with ['c_1', 'm_1'] (ID 6742c863-bec7-47be-ae49-cd0c64616605) 2019-02-27 11:33:50,702 - INFO - 4/10 [50.00%]: m_1-b789f15d-3508-464a-8717-8ba1da159754 request was accepted 2019-02-27 11:33:50,703 - INFO - 4/10 [50.00%]: m_2 requested negmas.sao.SAOMechanism[None] with ['c_1', 'm_2'] (ID b5445f07-ba0c-454f-bdb9-3f99632fc3e1) 2019-02-27 11:33:50,704 - INFO - 4/10 [50.00%]: m_2-f4d60475-9842-4006-8513-ca39a2379160 request was accepted 2019-02-27 11:33:50,705 - INFO - 4/10 [50.00%]: m_3 requested negmas.sao.SAOMechanism[None] with ['c_1', 'm_3'] (ID 58548e98-6c6f-4e6e-a2ca-a700dc0d3c28) 2019-02-27 11:33:50,706 - INFO - 4/10 [50.00%]: m_3-418c12ae-b8cd-4e28-a9a8-b998b4ef7df6 request was accepted 2019-02-27 11:33:50,707 - INFO - 4/10 [50.00%]: m_4 requested negmas.sao.SAOMechanism[None] with ['c_1', 'm_4'] (ID 9ac6fbe7-ba6d-4f24-9525-7aa2a89bdf92) 2019-02-27 11:33:50,708 - INFO - 4/10 [50.00%]: m_4-4f6b8ebc-32b0-44d5-88d6-88b3cec0b489 request was accepted 2019-02-27 11:33:50,710 - INFO - 4/10 [50.00%]: m_0 requested negmas.sao.SAOMechanism[None] with ['c_0', 'm_0'] (ID 1866e42a-cd95-418c-87f4-7b3c1e3a77ed) 2019-02-27 11:33:50,711 - INFO - 4/10 [50.00%]: m_0-61b223a2-ea24-4bfc-9bf3-aa85fa8a955a request was accepted 2019-02-27 11:33:50,712 - INFO - 4/10 [50.00%]: m_1 requested negmas.sao.SAOMechanism[None] with ['c_0', 'm_1'] (ID 2dca4e56-3bf1-4a81-8d90-8138983060fc) 2019-02-27 11:33:50,713 - INFO - 4/10 [50.00%]: m_1-b789f15d-3508-464a-8717-8ba1da159754 request was accepted 2019-02-27 11:33:50,714 - INFO - 4/10 [50.00%]: m_2 requested negmas.sao.SAOMechanism[None] with ['c_0', 'm_2'] (ID 7b985bfe-c385-4b97-a3d8-aa3e150ae21e) 2019-02-27 11:33:50,714 - INFO - 4/10 [50.00%]: m_2-f4d60475-9842-4006-8513-ca39a2379160 request was accepted 2019-02-27 11:33:50,716 - INFO - 4/10 [50.00%]: m_3 requested negmas.sao.SAOMechanism[None] with ['c_0', 'm_3'] (ID 51906af0-b492-47ad-b5ac-fa1b59ea4bf2) 2019-02-27 11:33:50,716 - INFO - 4/10 [50.00%]: m_3-418c12ae-b8cd-4e28-a9a8-b998b4ef7df6 request was accepted 2019-02-27 11:33:50,717 - INFO - 4/10 [50.00%]: m_4 requested negmas.sao.SAOMechanism[None] with ['c_0', 'm_4'] (ID 2e5f6263-00ac-4c4c-89f7-b9c3a6eb9874) 2019-02-27 11:33:50,718 - INFO - 4/10 [50.00%]: m_4-4f6b8ebc-32b0-44d5-88d6-88b3cec0b489 request was accepted 2019-02-27 11:33:50,719 - INFO - 4/10 [50.00%]: m_0 requested negmas.sao.SAOMechanism[None] with ['c_4', 'm_0'] (ID cf476966-b006-4b66-9189-582b4d69f19b) 2019-02-27 11:33:50,720 - INFO - 4/10 [50.00%]: m_0-61b223a2-ea24-4bfc-9bf3-aa85fa8a955a request was accepted 2019-02-27 11:33:50,721 - INFO - 4/10 [50.00%]: m_1 requested negmas.sao.SAOMechanism[None] with ['c_4', 'm_1'] (ID 06c524d8-6220-4c22-a96d-31ba03119549) 2019-02-27 11:33:50,721 - INFO - 4/10 [50.00%]: m_1-b789f15d-3508-464a-8717-8ba1da159754 request was accepted 2019-02-27 11:33:50,722 - INFO - 4/10 [50.00%]: m_2 requested negmas.sao.SAOMechanism[None] with ['c_4', 'm_2'] (ID 0d18e488-fed8-4331-8897-35df20f6d7be) 2019-02-27 11:33:50,723 - INFO - 4/10 [50.00%]: m_2-f4d60475-9842-4006-8513-ca39a2379160 request was accepted 2019-02-27 11:33:50,724 - INFO - 4/10 [50.00%]: m_3 requested negmas.sao.SAOMechanism[None] with ['c_4', 'm_3'] (ID ef052942-139b-4c5b-ae32-ffdbd096a455) 2019-02-27 11:33:50,725 - INFO - 4/10 [50.00%]: m_3-418c12ae-b8cd-4e28-a9a8-b998b4ef7df6 request was accepted 2019-02-27 11:33:50,726 - INFO - 4/10 [50.00%]: m_4 requested negmas.sao.SAOMechanism[None] with ['c_4', 'm_4'] (ID fc6e0de6-faf7-4871-911d-978b7c2357b2) 2019-02-27 11:33:50,726 - INFO - 4/10 [50.00%]: m_4-4f6b8ebc-32b0-44d5-88d6-88b3cec0b489 request was accepted 2019-02-27 11:33:50,726 - INFO - 4/10 [50.00%]: Executing c_1-68b3b84c-c42b-4582-9119-917484eb77ef, m_1-b789f15d-3508-464a-8717-8ba1da159754 agreed on {'time': 4, 'quantity': 3, 'unit_price': 0.5} 2019-02-27 11:33:50,726 - DEBUG - 4/10 [50.00%]: Moved 3 units of p0 from m_1 to c_1 for 1.5 dollars 2019-02-27 11:33:50,726 - INFO - 4/10 [50.00%]: Executing c_0-b6f40f78-35c5-4b76-9f90-53a459a66882, m_1-b789f15d-3508-464a-8717-8ba1da159754 agreed on {'time': 4, 'quantity': 4, 'unit_price': 0.5} 2019-02-27 11:33:50,727 - DEBUG - 4/10 [50.00%]: Moved 4 units of p0 from m_1 to c_0 for 2.0 dollars 2019-02-27 11:33:50,727 - INFO - 4/10 [50.00%]: Executing c_4-76d9311e-d5f6-4e91-bb83-72994095e2c6, m_2-f4d60475-9842-4006-8513-ca39a2379160 agreed on {'time': 4, 'quantity': 3, 'unit_price': 0.5} 2019-02-27 11:33:50,727 - DEBUG - 4/10 [50.00%]: Moved 3 units of p0 from m_2 to c_4 for 1.5 dollars 2019-02-27 11:33:50,727 - INFO - 4/10 [50.00%]: Executing c_2-c1142518-c4d8-4f80-9889-693a093ef989, m_4-4f6b8ebc-32b0-44d5-88d6-88b3cec0b489 agreed on {'time': 4, 'quantity': 3, 'unit_price': 0.5} 2019-02-27 11:33:50,727 - DEBUG - 4/10 [50.00%]: Moved 3 units of p0 from m_4 to c_2 for 1.5 dollars 2019-02-27 11:33:50,727 - INFO - 4/10 [50.00%]: Executing c_3-0230100d-3633-49be-bb01-4928b35e59bc, m_4-4f6b8ebc-32b0-44d5-88d6-88b3cec0b489 agreed on {'time': 4, 'quantity': 4, 'unit_price': 0.5} 2019-02-27 11:33:50,727 - DEBUG - 4/10 [50.00%]: Moved 4 units of p0 from m_4 to c_3 for 2.0 dollars 2019-02-27 11:33:50,727 - DEBUG - 4/10 [50.00%]: Factory 95e75c6e-fd73-4d10-bb63-7e6fd5ed934d: money=-5.5, storage={0: 4}, loans=0.0 2019-02-27 11:33:50,727 - DEBUG - 4/10 [50.00%]: Factory 1d03dc99-48cd-4b69-81d8-4faf95f470b1: money=-5.0, storage={0: 3}, loans=0.0 2019-02-27 11:33:50,727 - DEBUG - 4/10 [50.00%]: Factory 3988d198-d05c-4a8a-93c9-8a88363a07d6: money=-5.5, storage={0: 4}, loans=0.0 2019-02-27 11:33:50,727 - DEBUG - 4/10 [50.00%]: Factory bad2c634-f9b5-4ae3-8b59-626ce7e171fb: money=-5.5, storage={0: 3}, loans=0.0 2019-02-27 11:33:50,727 - DEBUG - 4/10 [50.00%]: Factory ee428c0e-e853-4495-8bbd-24302264a757: money=-5.0, storage={0: 3}, loans=0.0 2019-02-27 11:33:50,727 - DEBUG - 4/10 [50.00%]: Factory cb5ab840-9bd8-41f9-866a-ca43e56e74c6: money=3.5, storage={0: -7}, loans=0.0 2019-02-27 11:33:50,727 - DEBUG - 4/10 [50.00%]: Factory b5cdcb3a-a4bd-478d-9795-d361eb70cf32: money=7.5, storage={0: -15}, loans=0.0 2019-02-27 11:33:50,727 - DEBUG - 4/10 [50.00%]: Factory cb4aedd6-68a2-450a-8d92-117fcb5ae311: money=5.0, storage={0: -10}, loans=0.0 2019-02-27 11:33:50,727 - DEBUG - 4/10 [50.00%]: Factory 986a8ca5-1b97-449f-b316-450edc5ed050: money=3.5, storage={0: -7}, loans=0.0 2019-02-27 11:33:50,727 - DEBUG - 4/10 [50.00%]: Factory d70b6918-35dd-4eab-924c-7a13f3ad3feb: money=7.0, storage={0: -14}, loans=0.0 2019-02-27 11:33:50,727 - INFO - 5/10 [60.00%]: 25 Negotiations/4 _entities 2019-02-27 11:33:50,952 - DEBUG - 5/10 [60.00%]: Contract [to be signed at 6]: ['c_3', 'm_4'] > {'time': 8, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_3-0230100d-3633-49be-bb01-4928b35e59bc: buy 0 (t: 8, u: (0, 2.0), q: (1, 3))', 'partners': "['c_3-0230100d-3633-49be-bb01-4928b35e59bc', 'm_4-4f6b8ebc-32b0-44d5-88d6-88b3cec0b489']", 'seller': 'm_4-4f6b8ebc-32b0-44d5-88d6-88b3cec0b489', 'buyer': 'c_3-0230100d-3633-49be-bb01-4928b35e59bc'} 2019-02-27 11:33:50,953 - DEBUG - 5/10 [60.00%]: Contract [to be signed at 6]: ['c_3', 'm_3'] > {'time': 8, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_3-0230100d-3633-49be-bb01-4928b35e59bc: buy 0 (t: 8, u: (0, 2.0), q: (1, 3))', 'partners': "['c_3-0230100d-3633-49be-bb01-4928b35e59bc', 'm_3-418c12ae-b8cd-4e28-a9a8-b998b4ef7df6']", 'seller': 'm_3-418c12ae-b8cd-4e28-a9a8-b998b4ef7df6', 'buyer': 'c_3-0230100d-3633-49be-bb01-4928b35e59bc'} 2019-02-27 11:33:50,953 - DEBUG - 5/10 [60.00%]: Contract [to be signed at 6]: ['c_4', 'm_4'] > {'time': 8, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_4-76d9311e-d5f6-4e91-bb83-72994095e2c6: buy 0 (t: 8, u: (0, 2.0), q: (1, 3))', 'partners': "['c_4-76d9311e-d5f6-4e91-bb83-72994095e2c6', 'm_4-4f6b8ebc-32b0-44d5-88d6-88b3cec0b489']", 'seller': 'm_4-4f6b8ebc-32b0-44d5-88d6-88b3cec0b489', 'buyer': 'c_4-76d9311e-d5f6-4e91-bb83-72994095e2c6'} 2019-02-27 11:33:50,954 - DEBUG - 5/10 [60.00%]: Contract [to be signed at 6]: ['c_2', 'm_0'] > {'time': 8, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_2-c1142518-c4d8-4f80-9889-693a093ef989: buy 0 (t: 8, u: (0, 2.0), q: (1, 3))', 'partners': "['c_2-c1142518-c4d8-4f80-9889-693a093ef989', 'm_0-61b223a2-ea24-4bfc-9bf3-aa85fa8a955a']", 'seller': 'm_0-61b223a2-ea24-4bfc-9bf3-aa85fa8a955a', 'buyer': 'c_2-c1142518-c4d8-4f80-9889-693a093ef989'} 2019-02-27 11:33:50,954 - DEBUG - 5/10 [60.00%]: Contract [to be signed at 6]: ['c_0', 'm_2'] > {'time': 8, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_0-b6f40f78-35c5-4b76-9f90-53a459a66882: buy 0 (t: 8, u: (0, 2.0), q: (1, 4))', 'partners': "['c_0-b6f40f78-35c5-4b76-9f90-53a459a66882', 'm_2-f4d60475-9842-4006-8513-ca39a2379160']", 'seller': 'm_2-f4d60475-9842-4006-8513-ca39a2379160', 'buyer': 'c_0-b6f40f78-35c5-4b76-9f90-53a459a66882'} 2019-02-27 11:33:50,954 - DEBUG - 5/10 [60.00%]: Contract [to be signed at 6]: ['c_0', 'm_4'] > {'time': 8, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_0-b6f40f78-35c5-4b76-9f90-53a459a66882: buy 0 (t: 8, u: (0, 2.0), q: (1, 4))', 'partners': "['c_0-b6f40f78-35c5-4b76-9f90-53a459a66882', 'm_4-4f6b8ebc-32b0-44d5-88d6-88b3cec0b489']", 'seller': 'm_4-4f6b8ebc-32b0-44d5-88d6-88b3cec0b489', 'buyer': 'c_0-b6f40f78-35c5-4b76-9f90-53a459a66882'} 2019-02-27 11:33:50,955 - DEBUG - 5/10 [60.00%]: Contract [to be signed at 6]: ['c_2', 'm_4'] > {'time': 8, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_2-c1142518-c4d8-4f80-9889-693a093ef989: buy 0 (t: 8, u: (0, 2.0), q: (1, 3))', 'partners': "['c_2-c1142518-c4d8-4f80-9889-693a093ef989', 'm_4-4f6b8ebc-32b0-44d5-88d6-88b3cec0b489']", 'seller': 'm_4-4f6b8ebc-32b0-44d5-88d6-88b3cec0b489', 'buyer': 'c_2-c1142518-c4d8-4f80-9889-693a093ef989'} 2019-02-27 11:33:50,955 - DEBUG - 5/10 [60.00%]: Contract [to be signed at 6]: ['c_2', 'm_2'] > {'time': 8, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_2-c1142518-c4d8-4f80-9889-693a093ef989: buy 0 (t: 8, u: (0, 2.0), q: (1, 3))', 'partners': "['c_2-c1142518-c4d8-4f80-9889-693a093ef989', 'm_2-f4d60475-9842-4006-8513-ca39a2379160']", 'seller': 'm_2-f4d60475-9842-4006-8513-ca39a2379160', 'buyer': 'c_2-c1142518-c4d8-4f80-9889-693a093ef989'} 2019-02-27 11:33:50,955 - DEBUG - 5/10 [60.00%]: Contract [to be signed at 6]: ['c_3', 'm_0'] > {'time': 8, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_3-0230100d-3633-49be-bb01-4928b35e59bc: buy 0 (t: 8, u: (0, 2.0), q: (1, 3))', 'partners': "['c_3-0230100d-3633-49be-bb01-4928b35e59bc', 'm_0-61b223a2-ea24-4bfc-9bf3-aa85fa8a955a']", 'seller': 'm_0-61b223a2-ea24-4bfc-9bf3-aa85fa8a955a', 'buyer': 'c_3-0230100d-3633-49be-bb01-4928b35e59bc'} 2019-02-27 11:33:50,956 - DEBUG - 5/10 [60.00%]: Contract [to be signed at 6]: ['c_0', 'm_1'] > {'time': 8, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_0-b6f40f78-35c5-4b76-9f90-53a459a66882: buy 0 (t: 8, u: (0, 2.0), q: (1, 4))', 'partners': "['c_0-b6f40f78-35c5-4b76-9f90-53a459a66882', 'm_1-b789f15d-3508-464a-8717-8ba1da159754']", 'seller': 'm_1-b789f15d-3508-464a-8717-8ba1da159754', 'buyer': 'c_0-b6f40f78-35c5-4b76-9f90-53a459a66882'} 2019-02-27 11:33:50,956 - DEBUG - 5/10 [60.00%]: Contract [to be signed at 6]: ['c_4', 'm_1'] > {'time': 8, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_4-76d9311e-d5f6-4e91-bb83-72994095e2c6: buy 0 (t: 8, u: (0, 2.0), q: (1, 3))', 'partners': "['c_4-76d9311e-d5f6-4e91-bb83-72994095e2c6', 'm_1-b789f15d-3508-464a-8717-8ba1da159754']", 'seller': 'm_1-b789f15d-3508-464a-8717-8ba1da159754', 'buyer': 'c_4-76d9311e-d5f6-4e91-bb83-72994095e2c6'} 2019-02-27 11:33:50,956 - DEBUG - 5/10 [60.00%]: Contract [to be signed at 6]: ['c_1', 'm_4'] > {'time': 8, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_1-68b3b84c-c42b-4582-9119-917484eb77ef: buy 0 (t: 8, u: (0, 2.0), q: (1, 3))', 'partners': "['c_1-68b3b84c-c42b-4582-9119-917484eb77ef', 'm_4-4f6b8ebc-32b0-44d5-88d6-88b3cec0b489']", 'seller': 'm_4-4f6b8ebc-32b0-44d5-88d6-88b3cec0b489', 'buyer': 'c_1-68b3b84c-c42b-4582-9119-917484eb77ef'} 2019-02-27 11:33:50,956 - DEBUG - 5/10 [60.00%]: Contract [to be signed at 6]: ['c_1', 'm_1'] > {'time': 8, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_1-68b3b84c-c42b-4582-9119-917484eb77ef: buy 0 (t: 8, u: (0, 2.0), q: (1, 3))', 'partners': "['c_1-68b3b84c-c42b-4582-9119-917484eb77ef', 'm_1-b789f15d-3508-464a-8717-8ba1da159754']", 'seller': 'm_1-b789f15d-3508-464a-8717-8ba1da159754', 'buyer': 'c_1-68b3b84c-c42b-4582-9119-917484eb77ef'} 2019-02-27 11:33:50,957 - DEBUG - 5/10 [60.00%]: Contract [to be signed at 6]: ['c_2', 'm_1'] > {'time': 8, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_2-c1142518-c4d8-4f80-9889-693a093ef989: buy 0 (t: 8, u: (0, 2.0), q: (1, 3))', 'partners': "['c_2-c1142518-c4d8-4f80-9889-693a093ef989', 'm_1-b789f15d-3508-464a-8717-8ba1da159754']", 'seller': 'm_1-b789f15d-3508-464a-8717-8ba1da159754', 'buyer': 'c_2-c1142518-c4d8-4f80-9889-693a093ef989'} 2019-02-27 11:33:50,957 - DEBUG - 5/10 [60.00%]: Contract [to be signed at 6]: ['c_4', 'm_2'] > {'time': 8, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_4-76d9311e-d5f6-4e91-bb83-72994095e2c6: buy 0 (t: 8, u: (0, 2.0), q: (1, 3))', 'partners': "['c_4-76d9311e-d5f6-4e91-bb83-72994095e2c6', 'm_2-f4d60475-9842-4006-8513-ca39a2379160']", 'seller': 'm_2-f4d60475-9842-4006-8513-ca39a2379160', 'buyer': 'c_4-76d9311e-d5f6-4e91-bb83-72994095e2c6'} 2019-02-27 11:33:50,957 - DEBUG - 5/10 [60.00%]: Contract [to be signed at 6]: ['c_2', 'm_3'] > {'time': 8, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_2-c1142518-c4d8-4f80-9889-693a093ef989: buy 0 (t: 8, u: (0, 2.0), q: (1, 3))', 'partners': "['c_2-c1142518-c4d8-4f80-9889-693a093ef989', 'm_3-418c12ae-b8cd-4e28-a9a8-b998b4ef7df6']", 'seller': 'm_3-418c12ae-b8cd-4e28-a9a8-b998b4ef7df6', 'buyer': 'c_2-c1142518-c4d8-4f80-9889-693a093ef989'} 2019-02-27 11:33:50,958 - DEBUG - 5/10 [60.00%]: Contract [to be signed at 6]: ['c_1', 'm_2'] > {'time': 8, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_1-68b3b84c-c42b-4582-9119-917484eb77ef: buy 0 (t: 8, u: (0, 2.0), q: (1, 3))', 'partners': "['c_1-68b3b84c-c42b-4582-9119-917484eb77ef', 'm_2-f4d60475-9842-4006-8513-ca39a2379160']", 'seller': 'm_2-f4d60475-9842-4006-8513-ca39a2379160', 'buyer': 'c_1-68b3b84c-c42b-4582-9119-917484eb77ef'} 2019-02-27 11:33:50,958 - DEBUG - 5/10 [60.00%]: Contract [to be signed at 6]: ['c_0', 'm_3'] > {'time': 8, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_0-b6f40f78-35c5-4b76-9f90-53a459a66882: buy 0 (t: 8, u: (0, 2.0), q: (1, 4))', 'partners': "['c_0-b6f40f78-35c5-4b76-9f90-53a459a66882', 'm_3-418c12ae-b8cd-4e28-a9a8-b998b4ef7df6']", 'seller': 'm_3-418c12ae-b8cd-4e28-a9a8-b998b4ef7df6', 'buyer': 'c_0-b6f40f78-35c5-4b76-9f90-53a459a66882'} 2019-02-27 11:33:50,958 - DEBUG - 5/10 [60.00%]: Contract [to be signed at 6]: ['c_1', 'm_3'] > {'time': 8, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_1-68b3b84c-c42b-4582-9119-917484eb77ef: buy 0 (t: 8, u: (0, 2.0), q: (1, 3))', 'partners': "['c_1-68b3b84c-c42b-4582-9119-917484eb77ef', 'm_3-418c12ae-b8cd-4e28-a9a8-b998b4ef7df6']", 'seller': 'm_3-418c12ae-b8cd-4e28-a9a8-b998b4ef7df6', 'buyer': 'c_1-68b3b84c-c42b-4582-9119-917484eb77ef'} 2019-02-27 11:33:50,958 - DEBUG - 5/10 [60.00%]: Contract [to be signed at 6]: ['c_1', 'm_0'] > {'time': 8, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_1-68b3b84c-c42b-4582-9119-917484eb77ef: buy 0 (t: 8, u: (0, 2.0), q: (1, 3))', 'partners': "['c_1-68b3b84c-c42b-4582-9119-917484eb77ef', 'm_0-61b223a2-ea24-4bfc-9bf3-aa85fa8a955a']", 'seller': 'm_0-61b223a2-ea24-4bfc-9bf3-aa85fa8a955a', 'buyer': 'c_1-68b3b84c-c42b-4582-9119-917484eb77ef'} 2019-02-27 11:33:50,959 - DEBUG - 5/10 [60.00%]: Contract [to be signed at 6]: ['c_3', 'm_1'] > {'time': 8, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_3-0230100d-3633-49be-bb01-4928b35e59bc: buy 0 (t: 8, u: (0, 2.0), q: (1, 3))', 'partners': "['c_3-0230100d-3633-49be-bb01-4928b35e59bc', 'm_1-b789f15d-3508-464a-8717-8ba1da159754']", 'seller': 'm_1-b789f15d-3508-464a-8717-8ba1da159754', 'buyer': 'c_3-0230100d-3633-49be-bb01-4928b35e59bc'} 2019-02-27 11:33:50,959 - DEBUG - 5/10 [60.00%]: Contract [to be signed at 6]: ['c_0', 'm_0'] > {'time': 8, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_0-b6f40f78-35c5-4b76-9f90-53a459a66882: buy 0 (t: 8, u: (0, 2.0), q: (1, 4))', 'partners': "['c_0-b6f40f78-35c5-4b76-9f90-53a459a66882', 'm_0-61b223a2-ea24-4bfc-9bf3-aa85fa8a955a']", 'seller': 'm_0-61b223a2-ea24-4bfc-9bf3-aa85fa8a955a', 'buyer': 'c_0-b6f40f78-35c5-4b76-9f90-53a459a66882'} 2019-02-27 11:33:50,960 - DEBUG - 5/10 [60.00%]: Contract [to be signed at 6]: ['c_3', 'm_2'] > {'time': 8, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_3-0230100d-3633-49be-bb01-4928b35e59bc: buy 0 (t: 8, u: (0, 2.0), q: (1, 3))', 'partners': "['c_3-0230100d-3633-49be-bb01-4928b35e59bc', 'm_2-f4d60475-9842-4006-8513-ca39a2379160']", 'seller': 'm_2-f4d60475-9842-4006-8513-ca39a2379160', 'buyer': 'c_3-0230100d-3633-49be-bb01-4928b35e59bc'} 2019-02-27 11:33:50,960 - DEBUG - 5/10 [60.00%]: Contract [to be signed at 6]: ['c_4', 'm_0'] > {'time': 8, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_4-76d9311e-d5f6-4e91-bb83-72994095e2c6: buy 0 (t: 8, u: (0, 2.0), q: (1, 3))', 'partners': "['c_4-76d9311e-d5f6-4e91-bb83-72994095e2c6', 'm_0-61b223a2-ea24-4bfc-9bf3-aa85fa8a955a']", 'seller': 'm_0-61b223a2-ea24-4bfc-9bf3-aa85fa8a955a', 'buyer': 'c_4-76d9311e-d5f6-4e91-bb83-72994095e2c6'} 2019-02-27 11:33:50,960 - DEBUG - 5/10 [60.00%]: Contract [to be signed at 6]: ['c_4', 'm_3'] > {'time': 8, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_4-76d9311e-d5f6-4e91-bb83-72994095e2c6: buy 0 (t: 8, u: (0, 2.0), q: (1, 3))', 'partners': "['c_4-76d9311e-d5f6-4e91-bb83-72994095e2c6', 'm_3-418c12ae-b8cd-4e28-a9a8-b998b4ef7df6']", 'seller': 'm_3-418c12ae-b8cd-4e28-a9a8-b998b4ef7df6', 'buyer': 'c_4-76d9311e-d5f6-4e91-bb83-72994095e2c6'} 2019-02-27 11:33:50,963 - INFO - 5/10 [60.00%]: m_0 requested negmas.sao.SAOMechanism[None] with ['c_3', 'm_0'] (ID dc12f45d-eb4c-4fbd-94e7-95ca99497604) 2019-02-27 11:33:50,963 - INFO - 5/10 [60.00%]: m_0-61b223a2-ea24-4bfc-9bf3-aa85fa8a955a request was accepted 2019-02-27 11:33:50,965 - INFO - 5/10 [60.00%]: m_1 requested negmas.sao.SAOMechanism[None] with ['c_3', 'm_1'] (ID 06e8ef89-5c75-4dc1-8966-79573b131548) 2019-02-27 11:33:50,965 - INFO - 5/10 [60.00%]: m_1-b789f15d-3508-464a-8717-8ba1da159754 request was accepted 2019-02-27 11:33:50,966 - INFO - 5/10 [60.00%]: m_2 requested negmas.sao.SAOMechanism[None] with ['c_3', 'm_2'] (ID 0d5f8490-c271-4fa4-bcaa-dad60947895b) 2019-02-27 11:33:50,967 - INFO - 5/10 [60.00%]: m_2-f4d60475-9842-4006-8513-ca39a2379160 request was accepted 2019-02-27 11:33:50,968 - INFO - 5/10 [60.00%]: m_3 requested negmas.sao.SAOMechanism[None] with ['c_3', 'm_3'] (ID 78eb187d-2dba-4a4f-93b1-583b91d9b704) 2019-02-27 11:33:50,969 - INFO - 5/10 [60.00%]: m_3-418c12ae-b8cd-4e28-a9a8-b998b4ef7df6 request was accepted 2019-02-27 11:33:50,970 - INFO - 5/10 [60.00%]: m_4 requested negmas.sao.SAOMechanism[None] with ['c_3', 'm_4'] (ID b789bf7e-1238-4eb3-b05f-c6585d86927d) 2019-02-27 11:33:50,970 - INFO - 5/10 [60.00%]: m_4-4f6b8ebc-32b0-44d5-88d6-88b3cec0b489 request was accepted 2019-02-27 11:33:50,972 - INFO - 5/10 [60.00%]: m_0 requested negmas.sao.SAOMechanism[None] with ['c_2', 'm_0'] (ID a7ee7222-8c02-4f31-a741-0ef8ba6926cf) 2019-02-27 11:33:50,972 - INFO - 5/10 [60.00%]: m_0-61b223a2-ea24-4bfc-9bf3-aa85fa8a955a request was accepted 2019-02-27 11:33:50,973 - INFO - 5/10 [60.00%]: m_1 requested negmas.sao.SAOMechanism[None] with ['c_2', 'm_1'] (ID 73610720-688e-409f-9737-4b70b2a2388e) 2019-02-27 11:33:50,974 - INFO - 5/10 [60.00%]: m_1-b789f15d-3508-464a-8717-8ba1da159754 request was accepted 2019-02-27 11:33:50,975 - INFO - 5/10 [60.00%]: m_2 requested negmas.sao.SAOMechanism[None] with ['c_2', 'm_2'] (ID e6e233f2-d497-4184-bb01-c5f9dbe32554) 2019-02-27 11:33:50,975 - INFO - 5/10 [60.00%]: m_2-f4d60475-9842-4006-8513-ca39a2379160 request was accepted 2019-02-27 11:33:50,976 - INFO - 5/10 [60.00%]: m_3 requested negmas.sao.SAOMechanism[None] with ['c_2', 'm_3'] (ID b770e1ce-a414-423d-aecf-c00d2fa60233) 2019-02-27 11:33:50,977 - INFO - 5/10 [60.00%]: m_3-418c12ae-b8cd-4e28-a9a8-b998b4ef7df6 request was accepted 2019-02-27 11:33:50,978 - INFO - 5/10 [60.00%]: m_4 requested negmas.sao.SAOMechanism[None] with ['c_2', 'm_4'] (ID 13d51666-8788-4a77-9cf6-58ee19753415) 2019-02-27 11:33:50,978 - INFO - 5/10 [60.00%]: m_4-4f6b8ebc-32b0-44d5-88d6-88b3cec0b489 request was accepted 2019-02-27 11:33:50,980 - INFO - 5/10 [60.00%]: m_0 requested negmas.sao.SAOMechanism[None] with ['c_1', 'm_0'] (ID 1b6ad65d-4ba8-4288-a99c-d6263a9e0682) 2019-02-27 11:33:50,980 - INFO - 5/10 [60.00%]: m_0-61b223a2-ea24-4bfc-9bf3-aa85fa8a955a request was accepted 2019-02-27 11:33:50,982 - INFO - 5/10 [60.00%]: m_1 requested negmas.sao.SAOMechanism[None] with ['c_1', 'm_1'] (ID eb21c7cc-a494-434b-8fce-77b7d9aae8fb) 2019-02-27 11:33:50,982 - INFO - 5/10 [60.00%]: m_1-b789f15d-3508-464a-8717-8ba1da159754 request was accepted 2019-02-27 11:33:50,983 - INFO - 5/10 [60.00%]: m_2 requested negmas.sao.SAOMechanism[None] with ['c_1', 'm_2'] (ID a6c31383-9f34-4712-92ff-5b288b58ccff) 2019-02-27 11:33:50,984 - INFO - 5/10 [60.00%]: m_2-f4d60475-9842-4006-8513-ca39a2379160 request was accepted 2019-02-27 11:33:50,985 - INFO - 5/10 [60.00%]: m_3 requested negmas.sao.SAOMechanism[None] with ['c_1', 'm_3'] (ID 0215ff18-3ad1-4372-b52d-7f8cf25798f0) 2019-02-27 11:33:50,986 - INFO - 5/10 [60.00%]: m_3-418c12ae-b8cd-4e28-a9a8-b998b4ef7df6 request was accepted 2019-02-27 11:33:50,987 - INFO - 5/10 [60.00%]: m_4 requested negmas.sao.SAOMechanism[None] with ['c_1', 'm_4'] (ID 1ec86133-89ec-4350-8d2d-0a03397c14c8) 2019-02-27 11:33:50,987 - INFO - 5/10 [60.00%]: m_4-4f6b8ebc-32b0-44d5-88d6-88b3cec0b489 request was accepted 2019-02-27 11:33:50,989 - INFO - 5/10 [60.00%]: m_0 requested negmas.sao.SAOMechanism[None] with ['c_0', 'm_0'] (ID 8fdffb98-c795-475f-96ec-3ca338855b63) 2019-02-27 11:33:50,989 - INFO - 5/10 [60.00%]: m_0-61b223a2-ea24-4bfc-9bf3-aa85fa8a955a request was accepted 2019-02-27 11:33:50,990 - INFO - 5/10 [60.00%]: m_1 requested negmas.sao.SAOMechanism[None] with ['c_0', 'm_1'] (ID 0cb0a756-c385-4bb5-8030-adfb49cfc65c) 2019-02-27 11:33:50,991 - INFO - 5/10 [60.00%]: m_1-b789f15d-3508-464a-8717-8ba1da159754 request was accepted 2019-02-27 11:33:50,992 - INFO - 5/10 [60.00%]: m_2 requested negmas.sao.SAOMechanism[None] with ['c_0', 'm_2'] (ID 87c311ba-c80c-4288-8193-ff15d003fae5) 2019-02-27 11:33:50,992 - INFO - 5/10 [60.00%]: m_2-f4d60475-9842-4006-8513-ca39a2379160 request was accepted 2019-02-27 11:33:50,993 - INFO - 5/10 [60.00%]: m_3 requested negmas.sao.SAOMechanism[None] with ['c_0', 'm_3'] (ID fd6e2f35-803d-4a38-b4a4-d4df943df8f2) 2019-02-27 11:33:50,994 - INFO - 5/10 [60.00%]: m_3-418c12ae-b8cd-4e28-a9a8-b998b4ef7df6 request was accepted 2019-02-27 11:33:50,995 - INFO - 5/10 [60.00%]: m_4 requested negmas.sao.SAOMechanism[None] with ['c_0', 'm_4'] (ID a2199c83-e696-4193-9201-433bc08e8d53) 2019-02-27 11:33:50,995 - INFO - 5/10 [60.00%]: m_4-4f6b8ebc-32b0-44d5-88d6-88b3cec0b489 request was accepted 2019-02-27 11:33:50,997 - INFO - 5/10 [60.00%]: m_0 requested negmas.sao.SAOMechanism[None] with ['c_4', 'm_0'] (ID 9255cec8-398b-46a4-b76e-459adc739367) 2019-02-27 11:33:50,997 - INFO - 5/10 [60.00%]: m_0-61b223a2-ea24-4bfc-9bf3-aa85fa8a955a request was accepted 2019-02-27 11:33:50,999 - INFO - 5/10 [60.00%]: m_1 requested negmas.sao.SAOMechanism[None] with ['c_4', 'm_1'] (ID f7c56bf0-6291-4565-866a-e2d9ac411dbe) 2019-02-27 11:33:50,999 - INFO - 5/10 [60.00%]: m_1-b789f15d-3508-464a-8717-8ba1da159754 request was accepted 2019-02-27 11:33:51,000 - INFO - 5/10 [60.00%]: m_2 requested negmas.sao.SAOMechanism[None] with ['c_4', 'm_2'] (ID 4c6b97fa-e379-432d-a011-50acc96f26d3) 2019-02-27 11:33:51,001 - INFO - 5/10 [60.00%]: m_2-f4d60475-9842-4006-8513-ca39a2379160 request was accepted 2019-02-27 11:33:51,002 - INFO - 5/10 [60.00%]: m_3 requested negmas.sao.SAOMechanism[None] with ['c_4', 'm_3'] (ID 8c03f4ea-4c74-4190-b5d4-8f62204c31f6) 2019-02-27 11:33:51,002 - INFO - 5/10 [60.00%]: m_3-418c12ae-b8cd-4e28-a9a8-b998b4ef7df6 request was accepted 2019-02-27 11:33:51,003 - INFO - 5/10 [60.00%]: m_4 requested negmas.sao.SAOMechanism[None] with ['c_4', 'm_4'] (ID ec8580d8-fc53-4b59-8508-01107b835750) 2019-02-27 11:33:51,004 - INFO - 5/10 [60.00%]: m_4-4f6b8ebc-32b0-44d5-88d6-88b3cec0b489 request was accepted 2019-02-27 11:33:51,004 - INFO - 5/10 [60.00%]: Executing c_0-b6f40f78-35c5-4b76-9f90-53a459a66882, m_0-61b223a2-ea24-4bfc-9bf3-aa85fa8a955a agreed on {'time': 5, 'quantity': 4, 'unit_price': 0.5} 2019-02-27 11:33:51,004 - DEBUG - 5/10 [60.00%]: Moved 4 units of p0 from m_0 to c_0 for 2.0 dollars 2019-02-27 11:33:51,004 - INFO - 5/10 [60.00%]: Executing c_1-68b3b84c-c42b-4582-9119-917484eb77ef, m_4-4f6b8ebc-32b0-44d5-88d6-88b3cec0b489 agreed on {'time': 5, 'quantity': 4, 'unit_price': 0.5} 2019-02-27 11:33:51,004 - DEBUG - 5/10 [60.00%]: Moved 4 units of p0 from m_4 to c_1 for 2.0 dollars 2019-02-27 11:33:51,004 - INFO - 5/10 [60.00%]: Executing c_2-c1142518-c4d8-4f80-9889-693a093ef989, m_2-f4d60475-9842-4006-8513-ca39a2379160 agreed on {'time': 5, 'quantity': 4, 'unit_price': 0.5} 2019-02-27 11:33:51,004 - DEBUG - 5/10 [60.00%]: Moved 4 units of p0 from m_2 to c_2 for 2.0 dollars 2019-02-27 11:33:51,004 - INFO - 5/10 [60.00%]: Executing c_3-0230100d-3633-49be-bb01-4928b35e59bc, m_3-418c12ae-b8cd-4e28-a9a8-b998b4ef7df6 agreed on {'time': 5, 'quantity': 3, 'unit_price': 0.5} 2019-02-27 11:33:51,004 - DEBUG - 5/10 [60.00%]: Moved 3 units of p0 from m_3 to c_3 for 1.5 dollars 2019-02-27 11:33:51,005 - INFO - 5/10 [60.00%]: Executing c_4-76d9311e-d5f6-4e91-bb83-72994095e2c6, m_1-b789f15d-3508-464a-8717-8ba1da159754 agreed on {'time': 5, 'quantity': 4, 'unit_price': 0.5} 2019-02-27 11:33:51,005 - DEBUG - 5/10 [60.00%]: Moved 4 units of p0 from m_1 to c_4 for 2.0 dollars 2019-02-27 11:33:51,005 - DEBUG - 5/10 [60.00%]: Factory 95e75c6e-fd73-4d10-bb63-7e6fd5ed934d: money=-7.5, storage={0: 7}, loans=0.0 2019-02-27 11:33:51,005 - DEBUG - 5/10 [60.00%]: Factory 1d03dc99-48cd-4b69-81d8-4faf95f470b1: money=-7.0, storage={0: 7}, loans=0.0 2019-02-27 11:33:51,005 - DEBUG - 5/10 [60.00%]: Factory 3988d198-d05c-4a8a-93c9-8a88363a07d6: money=-7.5, storage={0: 8}, loans=0.0 2019-02-27 11:33:51,005 - DEBUG - 5/10 [60.00%]: Factory bad2c634-f9b5-4ae3-8b59-626ce7e171fb: money=-7.0, storage={0: 7}, loans=0.0 2019-02-27 11:33:51,005 - DEBUG - 5/10 [60.00%]: Factory ee428c0e-e853-4495-8bbd-24302264a757: money=-7.0, storage={0: 7}, loans=0.0 2019-02-27 11:33:51,005 - DEBUG - 5/10 [60.00%]: Factory cb5ab840-9bd8-41f9-866a-ca43e56e74c6: money=5.5, storage={0: -11}, loans=0.0 2019-02-27 11:33:51,005 - DEBUG - 5/10 [60.00%]: Factory b5cdcb3a-a4bd-478d-9795-d361eb70cf32: money=9.5, storage={0: -19}, loans=0.0 2019-02-27 11:33:51,006 - DEBUG - 5/10 [60.00%]: Factory cb4aedd6-68a2-450a-8d92-117fcb5ae311: money=7.0, storage={0: -14}, loans=0.0 2019-02-27 11:33:51,006 - DEBUG - 5/10 [60.00%]: Factory 986a8ca5-1b97-449f-b316-450edc5ed050: money=5.0, storage={0: -10}, loans=0.0 2019-02-27 11:33:51,006 - DEBUG - 5/10 [60.00%]: Factory d70b6918-35dd-4eab-924c-7a13f3ad3feb: money=9.0, storage={0: -18}, loans=0.0 2019-02-27 11:33:51,006 - INFO - 6/10 [70.00%]: 25 Negotiations/4 _entities 2019-02-27 11:33:51,219 - DEBUG - 6/10 [70.00%]: Contract [to be signed at 7]: ['c_3', 'm_0'] > {'time': 9, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_3-0230100d-3633-49be-bb01-4928b35e59bc: buy 0 (t: 9, u: (0, 2.0), q: (1, 4))', 'partners': "['c_3-0230100d-3633-49be-bb01-4928b35e59bc', 'm_0-61b223a2-ea24-4bfc-9bf3-aa85fa8a955a']", 'seller': 'm_0-61b223a2-ea24-4bfc-9bf3-aa85fa8a955a', 'buyer': 'c_3-0230100d-3633-49be-bb01-4928b35e59bc'} 2019-02-27 11:33:51,220 - DEBUG - 6/10 [70.00%]: Contract [to be signed at 7]: ['c_0', 'm_0'] > {'time': 9, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_0-b6f40f78-35c5-4b76-9f90-53a459a66882: buy 0 (t: 9, u: (0, 2.0), q: (1, 3))', 'partners': "['c_0-b6f40f78-35c5-4b76-9f90-53a459a66882', 'm_0-61b223a2-ea24-4bfc-9bf3-aa85fa8a955a']", 'seller': 'm_0-61b223a2-ea24-4bfc-9bf3-aa85fa8a955a', 'buyer': 'c_0-b6f40f78-35c5-4b76-9f90-53a459a66882'} 2019-02-27 11:33:51,220 - DEBUG - 6/10 [70.00%]: Contract [to be signed at 7]: ['c_0', 'm_3'] > {'time': 9, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_0-b6f40f78-35c5-4b76-9f90-53a459a66882: buy 0 (t: 9, u: (0, 2.0), q: (1, 3))', 'partners': "['c_0-b6f40f78-35c5-4b76-9f90-53a459a66882', 'm_3-418c12ae-b8cd-4e28-a9a8-b998b4ef7df6']", 'seller': 'm_3-418c12ae-b8cd-4e28-a9a8-b998b4ef7df6', 'buyer': 'c_0-b6f40f78-35c5-4b76-9f90-53a459a66882'} 2019-02-27 11:33:51,221 - DEBUG - 6/10 [70.00%]: Contract [to be signed at 7]: ['c_1', 'm_1'] > {'time': 9, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_1-68b3b84c-c42b-4582-9119-917484eb77ef: buy 0 (t: 9, u: (0, 2.0), q: (1, 4))', 'partners': "['c_1-68b3b84c-c42b-4582-9119-917484eb77ef', 'm_1-b789f15d-3508-464a-8717-8ba1da159754']", 'seller': 'm_1-b789f15d-3508-464a-8717-8ba1da159754', 'buyer': 'c_1-68b3b84c-c42b-4582-9119-917484eb77ef'} 2019-02-27 11:33:51,221 - DEBUG - 6/10 [70.00%]: Contract [to be signed at 7]: ['c_4', 'm_3'] > {'time': 9, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_4-76d9311e-d5f6-4e91-bb83-72994095e2c6: buy 0 (t: 9, u: (0, 2.0), q: (1, 4))', 'partners': "['c_4-76d9311e-d5f6-4e91-bb83-72994095e2c6', 'm_3-418c12ae-b8cd-4e28-a9a8-b998b4ef7df6']", 'seller': 'm_3-418c12ae-b8cd-4e28-a9a8-b998b4ef7df6', 'buyer': 'c_4-76d9311e-d5f6-4e91-bb83-72994095e2c6'} 2019-02-27 11:33:51,221 - DEBUG - 6/10 [70.00%]: Contract [to be signed at 7]: ['c_4', 'm_2'] > {'time': 9, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_4-76d9311e-d5f6-4e91-bb83-72994095e2c6: buy 0 (t: 9, u: (0, 2.0), q: (1, 4))', 'partners': "['c_4-76d9311e-d5f6-4e91-bb83-72994095e2c6', 'm_2-f4d60475-9842-4006-8513-ca39a2379160']", 'seller': 'm_2-f4d60475-9842-4006-8513-ca39a2379160', 'buyer': 'c_4-76d9311e-d5f6-4e91-bb83-72994095e2c6'} 2019-02-27 11:33:51,222 - DEBUG - 6/10 [70.00%]: Contract [to be signed at 7]: ['c_2', 'm_3'] > {'time': 9, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_2-c1142518-c4d8-4f80-9889-693a093ef989: buy 0 (t: 9, u: (0, 2.0), q: (1, 3))', 'partners': "['c_2-c1142518-c4d8-4f80-9889-693a093ef989', 'm_3-418c12ae-b8cd-4e28-a9a8-b998b4ef7df6']", 'seller': 'm_3-418c12ae-b8cd-4e28-a9a8-b998b4ef7df6', 'buyer': 'c_2-c1142518-c4d8-4f80-9889-693a093ef989'} 2019-02-27 11:33:51,222 - DEBUG - 6/10 [70.00%]: Contract [to be signed at 7]: ['c_4', 'm_4'] > {'time': 9, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_4-76d9311e-d5f6-4e91-bb83-72994095e2c6: buy 0 (t: 9, u: (0, 2.0), q: (1, 4))', 'partners': "['c_4-76d9311e-d5f6-4e91-bb83-72994095e2c6', 'm_4-4f6b8ebc-32b0-44d5-88d6-88b3cec0b489']", 'seller': 'm_4-4f6b8ebc-32b0-44d5-88d6-88b3cec0b489', 'buyer': 'c_4-76d9311e-d5f6-4e91-bb83-72994095e2c6'} 2019-02-27 11:33:51,222 - DEBUG - 6/10 [70.00%]: Contract [to be signed at 7]: ['c_3', 'm_1'] > {'time': 9, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_3-0230100d-3633-49be-bb01-4928b35e59bc: buy 0 (t: 9, u: (0, 2.0), q: (1, 4))', 'partners': "['c_3-0230100d-3633-49be-bb01-4928b35e59bc', 'm_1-b789f15d-3508-464a-8717-8ba1da159754']", 'seller': 'm_1-b789f15d-3508-464a-8717-8ba1da159754', 'buyer': 'c_3-0230100d-3633-49be-bb01-4928b35e59bc'} 2019-02-27 11:33:51,223 - DEBUG - 6/10 [70.00%]: Contract [to be signed at 7]: ['c_3', 'm_4'] > {'time': 9, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_3-0230100d-3633-49be-bb01-4928b35e59bc: buy 0 (t: 9, u: (0, 2.0), q: (1, 4))', 'partners': "['c_3-0230100d-3633-49be-bb01-4928b35e59bc', 'm_4-4f6b8ebc-32b0-44d5-88d6-88b3cec0b489']", 'seller': 'm_4-4f6b8ebc-32b0-44d5-88d6-88b3cec0b489', 'buyer': 'c_3-0230100d-3633-49be-bb01-4928b35e59bc'} 2019-02-27 11:33:51,223 - DEBUG - 6/10 [70.00%]: Contract [to be signed at 7]: ['c_3', 'm_3'] > {'time': 9, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_3-0230100d-3633-49be-bb01-4928b35e59bc: buy 0 (t: 9, u: (0, 2.0), q: (1, 4))', 'partners': "['c_3-0230100d-3633-49be-bb01-4928b35e59bc', 'm_3-418c12ae-b8cd-4e28-a9a8-b998b4ef7df6']", 'seller': 'm_3-418c12ae-b8cd-4e28-a9a8-b998b4ef7df6', 'buyer': 'c_3-0230100d-3633-49be-bb01-4928b35e59bc'} 2019-02-27 11:33:51,223 - DEBUG - 6/10 [70.00%]: Contract [to be signed at 7]: ['c_0', 'm_1'] > {'time': 9, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_0-b6f40f78-35c5-4b76-9f90-53a459a66882: buy 0 (t: 9, u: (0, 2.0), q: (1, 3))', 'partners': "['c_0-b6f40f78-35c5-4b76-9f90-53a459a66882', 'm_1-b789f15d-3508-464a-8717-8ba1da159754']", 'seller': 'm_1-b789f15d-3508-464a-8717-8ba1da159754', 'buyer': 'c_0-b6f40f78-35c5-4b76-9f90-53a459a66882'} 2019-02-27 11:33:51,224 - DEBUG - 6/10 [70.00%]: Contract [to be signed at 7]: ['c_4', 'm_1'] > {'time': 9, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_4-76d9311e-d5f6-4e91-bb83-72994095e2c6: buy 0 (t: 9, u: (0, 2.0), q: (1, 4))', 'partners': "['c_4-76d9311e-d5f6-4e91-bb83-72994095e2c6', 'm_1-b789f15d-3508-464a-8717-8ba1da159754']", 'seller': 'm_1-b789f15d-3508-464a-8717-8ba1da159754', 'buyer': 'c_4-76d9311e-d5f6-4e91-bb83-72994095e2c6'} 2019-02-27 11:33:51,224 - DEBUG - 6/10 [70.00%]: Contract [to be signed at 7]: ['c_3', 'm_2'] > {'time': 9, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_3-0230100d-3633-49be-bb01-4928b35e59bc: buy 0 (t: 9, u: (0, 2.0), q: (1, 4))', 'partners': "['c_3-0230100d-3633-49be-bb01-4928b35e59bc', 'm_2-f4d60475-9842-4006-8513-ca39a2379160']", 'seller': 'm_2-f4d60475-9842-4006-8513-ca39a2379160', 'buyer': 'c_3-0230100d-3633-49be-bb01-4928b35e59bc'} 2019-02-27 11:33:51,224 - DEBUG - 6/10 [70.00%]: Contract [to be signed at 7]: ['c_2', 'm_4'] > {'time': 9, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_2-c1142518-c4d8-4f80-9889-693a093ef989: buy 0 (t: 9, u: (0, 2.0), q: (1, 3))', 'partners': "['c_2-c1142518-c4d8-4f80-9889-693a093ef989', 'm_4-4f6b8ebc-32b0-44d5-88d6-88b3cec0b489']", 'seller': 'm_4-4f6b8ebc-32b0-44d5-88d6-88b3cec0b489', 'buyer': 'c_2-c1142518-c4d8-4f80-9889-693a093ef989'} 2019-02-27 11:33:51,224 - DEBUG - 6/10 [70.00%]: Contract [to be signed at 7]: ['c_1', 'm_3'] > {'time': 9, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_1-68b3b84c-c42b-4582-9119-917484eb77ef: buy 0 (t: 9, u: (0, 2.0), q: (1, 4))', 'partners': "['c_1-68b3b84c-c42b-4582-9119-917484eb77ef', 'm_3-418c12ae-b8cd-4e28-a9a8-b998b4ef7df6']", 'seller': 'm_3-418c12ae-b8cd-4e28-a9a8-b998b4ef7df6', 'buyer': 'c_1-68b3b84c-c42b-4582-9119-917484eb77ef'} 2019-02-27 11:33:51,225 - DEBUG - 6/10 [70.00%]: Contract [to be signed at 7]: ['c_1', 'm_2'] > {'time': 9, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_1-68b3b84c-c42b-4582-9119-917484eb77ef: buy 0 (t: 9, u: (0, 2.0), q: (1, 4))', 'partners': "['c_1-68b3b84c-c42b-4582-9119-917484eb77ef', 'm_2-f4d60475-9842-4006-8513-ca39a2379160']", 'seller': 'm_2-f4d60475-9842-4006-8513-ca39a2379160', 'buyer': 'c_1-68b3b84c-c42b-4582-9119-917484eb77ef'} 2019-02-27 11:33:51,225 - DEBUG - 6/10 [70.00%]: Contract [to be signed at 7]: ['c_1', 'm_4'] > {'time': 9, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_1-68b3b84c-c42b-4582-9119-917484eb77ef: buy 0 (t: 9, u: (0, 2.0), q: (1, 4))', 'partners': "['c_1-68b3b84c-c42b-4582-9119-917484eb77ef', 'm_4-4f6b8ebc-32b0-44d5-88d6-88b3cec0b489']", 'seller': 'm_4-4f6b8ebc-32b0-44d5-88d6-88b3cec0b489', 'buyer': 'c_1-68b3b84c-c42b-4582-9119-917484eb77ef'} 2019-02-27 11:33:51,225 - DEBUG - 6/10 [70.00%]: Contract [to be signed at 7]: ['c_1', 'm_0'] > {'time': 9, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_1-68b3b84c-c42b-4582-9119-917484eb77ef: buy 0 (t: 9, u: (0, 2.0), q: (1, 4))', 'partners': "['c_1-68b3b84c-c42b-4582-9119-917484eb77ef', 'm_0-61b223a2-ea24-4bfc-9bf3-aa85fa8a955a']", 'seller': 'm_0-61b223a2-ea24-4bfc-9bf3-aa85fa8a955a', 'buyer': 'c_1-68b3b84c-c42b-4582-9119-917484eb77ef'} 2019-02-27 11:33:51,225 - DEBUG - 6/10 [70.00%]: Contract [to be signed at 7]: ['c_2', 'm_0'] > {'time': 9, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_2-c1142518-c4d8-4f80-9889-693a093ef989: buy 0 (t: 9, u: (0, 2.0), q: (1, 3))', 'partners': "['c_2-c1142518-c4d8-4f80-9889-693a093ef989', 'm_0-61b223a2-ea24-4bfc-9bf3-aa85fa8a955a']", 'seller': 'm_0-61b223a2-ea24-4bfc-9bf3-aa85fa8a955a', 'buyer': 'c_2-c1142518-c4d8-4f80-9889-693a093ef989'} 2019-02-27 11:33:51,226 - DEBUG - 6/10 [70.00%]: Contract [to be signed at 7]: ['c_4', 'm_0'] > {'time': 9, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_4-76d9311e-d5f6-4e91-bb83-72994095e2c6: buy 0 (t: 9, u: (0, 2.0), q: (1, 4))', 'partners': "['c_4-76d9311e-d5f6-4e91-bb83-72994095e2c6', 'm_0-61b223a2-ea24-4bfc-9bf3-aa85fa8a955a']", 'seller': 'm_0-61b223a2-ea24-4bfc-9bf3-aa85fa8a955a', 'buyer': 'c_4-76d9311e-d5f6-4e91-bb83-72994095e2c6'} 2019-02-27 11:33:51,226 - DEBUG - 6/10 [70.00%]: Contract [to be signed at 7]: ['c_0', 'm_4'] > {'time': 9, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_0-b6f40f78-35c5-4b76-9f90-53a459a66882: buy 0 (t: 9, u: (0, 2.0), q: (1, 3))', 'partners': "['c_0-b6f40f78-35c5-4b76-9f90-53a459a66882', 'm_4-4f6b8ebc-32b0-44d5-88d6-88b3cec0b489']", 'seller': 'm_4-4f6b8ebc-32b0-44d5-88d6-88b3cec0b489', 'buyer': 'c_0-b6f40f78-35c5-4b76-9f90-53a459a66882'} 2019-02-27 11:33:51,226 - DEBUG - 6/10 [70.00%]: Contract [to be signed at 7]: ['c_2', 'm_2'] > {'time': 9, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_2-c1142518-c4d8-4f80-9889-693a093ef989: buy 0 (t: 9, u: (0, 2.0), q: (1, 3))', 'partners': "['c_2-c1142518-c4d8-4f80-9889-693a093ef989', 'm_2-f4d60475-9842-4006-8513-ca39a2379160']", 'seller': 'm_2-f4d60475-9842-4006-8513-ca39a2379160', 'buyer': 'c_2-c1142518-c4d8-4f80-9889-693a093ef989'} 2019-02-27 11:33:51,227 - DEBUG - 6/10 [70.00%]: Contract [to be signed at 7]: ['c_0', 'm_2'] > {'time': 9, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_0-b6f40f78-35c5-4b76-9f90-53a459a66882: buy 0 (t: 9, u: (0, 2.0), q: (1, 3))', 'partners': "['c_0-b6f40f78-35c5-4b76-9f90-53a459a66882', 'm_2-f4d60475-9842-4006-8513-ca39a2379160']", 'seller': 'm_2-f4d60475-9842-4006-8513-ca39a2379160', 'buyer': 'c_0-b6f40f78-35c5-4b76-9f90-53a459a66882'} 2019-02-27 11:33:51,227 - DEBUG - 6/10 [70.00%]: Contract [to be signed at 7]: ['c_2', 'm_1'] > {'time': 9, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_2-c1142518-c4d8-4f80-9889-693a093ef989: buy 0 (t: 9, u: (0, 2.0), q: (1, 3))', 'partners': "['c_2-c1142518-c4d8-4f80-9889-693a093ef989', 'm_1-b789f15d-3508-464a-8717-8ba1da159754']", 'seller': 'm_1-b789f15d-3508-464a-8717-8ba1da159754', 'buyer': 'c_2-c1142518-c4d8-4f80-9889-693a093ef989'} 2019-02-27 11:33:51,229 - INFO - 6/10 [70.00%]: Executing c_3-0230100d-3633-49be-bb01-4928b35e59bc, m_1-b789f15d-3508-464a-8717-8ba1da159754 agreed on {'time': 6, 'quantity': 4, 'unit_price': 0.5} 2019-02-27 11:33:51,229 - DEBUG - 6/10 [70.00%]: Moved 4 units of p0 from m_1 to c_3 for 2.0 dollars 2019-02-27 11:33:51,229 - INFO - 6/10 [70.00%]: Executing c_0-b6f40f78-35c5-4b76-9f90-53a459a66882, m_2-f4d60475-9842-4006-8513-ca39a2379160 agreed on {'time': 6, 'quantity': 4, 'unit_price': 0.5} 2019-02-27 11:33:51,229 - DEBUG - 6/10 [70.00%]: Moved 4 units of p0 from m_2 to c_0 for 2.0 dollars 2019-02-27 11:33:51,229 - INFO - 6/10 [70.00%]: Executing c_2-c1142518-c4d8-4f80-9889-693a093ef989, m_1-b789f15d-3508-464a-8717-8ba1da159754 agreed on {'time': 6, 'quantity': 4, 'unit_price': 0.5} 2019-02-27 11:33:51,229 - DEBUG - 6/10 [70.00%]: Moved 4 units of p0 from m_1 to c_2 for 2.0 dollars 2019-02-27 11:33:51,229 - INFO - 6/10 [70.00%]: Executing c_1-68b3b84c-c42b-4582-9119-917484eb77ef, m_2-f4d60475-9842-4006-8513-ca39a2379160 agreed on {'time': 6, 'quantity': 3, 'unit_price': 0.5} 2019-02-27 11:33:51,229 - DEBUG - 6/10 [70.00%]: Moved 3 units of p0 from m_2 to c_1 for 1.5 dollars 2019-02-27 11:33:51,229 - INFO - 6/10 [70.00%]: Executing c_4-76d9311e-d5f6-4e91-bb83-72994095e2c6, m_4-4f6b8ebc-32b0-44d5-88d6-88b3cec0b489 agreed on {'time': 6, 'quantity': 4, 'unit_price': 0.5} 2019-02-27 11:33:51,229 - DEBUG - 6/10 [70.00%]: Moved 4 units of p0 from m_4 to c_4 for 2.0 dollars 2019-02-27 11:33:51,229 - DEBUG - 6/10 [70.00%]: Factory 95e75c6e-fd73-4d10-bb63-7e6fd5ed934d: money=-9.5, storage={0: 11}, loans=0.0 2019-02-27 11:33:51,230 - DEBUG - 6/10 [70.00%]: Factory 1d03dc99-48cd-4b69-81d8-4faf95f470b1: money=-8.5, storage={0: 10}, loans=0.0 2019-02-27 11:33:51,230 - DEBUG - 6/10 [70.00%]: Factory 3988d198-d05c-4a8a-93c9-8a88363a07d6: money=-9.5, storage={0: 11}, loans=0.0 2019-02-27 11:33:51,230 - DEBUG - 6/10 [70.00%]: Factory bad2c634-f9b5-4ae3-8b59-626ce7e171fb: money=-9.0, storage={0: 11}, loans=0.0 2019-02-27 11:33:51,230 - DEBUG - 6/10 [70.00%]: Factory ee428c0e-e853-4495-8bbd-24302264a757: money=-9.0, storage={0: 10}, loans=0.0 2019-02-27 11:33:51,230 - DEBUG - 6/10 [70.00%]: Factory cb5ab840-9bd8-41f9-866a-ca43e56e74c6: money=5.5, storage={0: -11}, loans=0.0 2019-02-27 11:33:51,230 - DEBUG - 6/10 [70.00%]: Factory b5cdcb3a-a4bd-478d-9795-d361eb70cf32: money=13.5, storage={0: -27}, loans=0.0 2019-02-27 11:33:51,230 - DEBUG - 6/10 [70.00%]: Factory cb4aedd6-68a2-450a-8d92-117fcb5ae311: money=10.5, storage={0: -21}, loans=0.0 2019-02-27 11:33:51,230 - DEBUG - 6/10 [70.00%]: Factory 986a8ca5-1b97-449f-b316-450edc5ed050: money=5.0, storage={0: -10}, loans=0.0 2019-02-27 11:33:51,230 - DEBUG - 6/10 [70.00%]: Factory d70b6918-35dd-4eab-924c-7a13f3ad3feb: money=11.0, storage={0: -22}, loans=0.0 2019-02-27 11:33:51,230 - INFO - 7/10 [80.00%]: 0 Negotiations/4 _entities 2019-02-27 11:33:51,231 - INFO - 7/10 [80.00%]: Executing c_2-c1142518-c4d8-4f80-9889-693a093ef989, m_4-4f6b8ebc-32b0-44d5-88d6-88b3cec0b489 agreed on {'time': 7, 'quantity': 3, 'unit_price': 0.5} 2019-02-27 11:33:51,231 - DEBUG - 7/10 [80.00%]: Moved 3 units of p0 from m_4 to c_2 for 1.5 dollars 2019-02-27 11:33:51,231 - INFO - 7/10 [80.00%]: Executing c_3-0230100d-3633-49be-bb01-4928b35e59bc, m_3-418c12ae-b8cd-4e28-a9a8-b998b4ef7df6 agreed on {'time': 7, 'quantity': 3, 'unit_price': 0.5} 2019-02-27 11:33:51,231 - DEBUG - 7/10 [80.00%]: Moved 3 units of p0 from m_3 to c_3 for 1.5 dollars 2019-02-27 11:33:51,231 - INFO - 7/10 [80.00%]: Executing c_1-68b3b84c-c42b-4582-9119-917484eb77ef, m_0-61b223a2-ea24-4bfc-9bf3-aa85fa8a955a agreed on {'time': 7, 'quantity': 3, 'unit_price': 0.5} 2019-02-27 11:33:51,232 - DEBUG - 7/10 [80.00%]: Moved 3 units of p0 from m_0 to c_1 for 1.5 dollars 2019-02-27 11:33:51,232 - INFO - 7/10 [80.00%]: Executing c_0-b6f40f78-35c5-4b76-9f90-53a459a66882, m_4-4f6b8ebc-32b0-44d5-88d6-88b3cec0b489 agreed on {'time': 7, 'quantity': 3, 'unit_price': 0.5} 2019-02-27 11:33:51,232 - DEBUG - 7/10 [80.00%]: Moved 3 units of p0 from m_4 to c_0 for 1.5 dollars 2019-02-27 11:33:51,232 - INFO - 7/10 [80.00%]: Executing c_4-76d9311e-d5f6-4e91-bb83-72994095e2c6, m_0-61b223a2-ea24-4bfc-9bf3-aa85fa8a955a agreed on {'time': 7, 'quantity': 3, 'unit_price': 0.5} 2019-02-27 11:33:51,232 - DEBUG - 7/10 [80.00%]: Moved 3 units of p0 from m_0 to c_4 for 1.5 dollars 2019-02-27 11:33:51,232 - DEBUG - 7/10 [80.00%]: Factory 95e75c6e-fd73-4d10-bb63-7e6fd5ed934d: money=-11.0, storage={0: 15}, loans=0.0 2019-02-27 11:33:51,232 - DEBUG - 7/10 [80.00%]: Factory 1d03dc99-48cd-4b69-81d8-4faf95f470b1: money=-10.0, storage={0: 14}, loans=0.0 2019-02-27 11:33:51,232 - DEBUG - 7/10 [80.00%]: Factory 3988d198-d05c-4a8a-93c9-8a88363a07d6: money=-11.0, storage={0: 15}, loans=0.0 2019-02-27 11:33:51,232 - DEBUG - 7/10 [80.00%]: Factory bad2c634-f9b5-4ae3-8b59-626ce7e171fb: money=-10.5, storage={0: 14}, loans=0.0 2019-02-27 11:33:51,232 - DEBUG - 7/10 [80.00%]: Factory ee428c0e-e853-4495-8bbd-24302264a757: money=-10.5, storage={0: 14}, loans=0.0 2019-02-27 11:33:51,232 - DEBUG - 7/10 [80.00%]: Factory cb5ab840-9bd8-41f9-866a-ca43e56e74c6: money=8.5, storage={0: -17}, loans=0.0 2019-02-27 11:33:51,232 - DEBUG - 7/10 [80.00%]: Factory b5cdcb3a-a4bd-478d-9795-d361eb70cf32: money=13.5, storage={0: -27}, loans=0.0 2019-02-27 11:33:51,232 - DEBUG - 7/10 [80.00%]: Factory cb4aedd6-68a2-450a-8d92-117fcb5ae311: money=10.5, storage={0: -21}, loans=0.0 2019-02-27 11:33:51,232 - DEBUG - 7/10 [80.00%]: Factory 986a8ca5-1b97-449f-b316-450edc5ed050: money=6.5, storage={0: -13}, loans=0.0 2019-02-27 11:33:51,232 - DEBUG - 7/10 [80.00%]: Factory d70b6918-35dd-4eab-924c-7a13f3ad3feb: money=14.0, storage={0: -28}, loans=0.0 2019-02-27 11:33:51,232 - INFO - 8/10 [90.00%]: 0 Negotiations/4 _entities 2019-02-27 11:33:51,233 - INFO - 8/10 [90.00%]: Executing c_3-0230100d-3633-49be-bb01-4928b35e59bc, m_4-4f6b8ebc-32b0-44d5-88d6-88b3cec0b489 agreed on {'time': 8, 'quantity': 3, 'unit_price': 0.5} 2019-02-27 11:33:51,233 - DEBUG - 8/10 [90.00%]: Moved 3 units of p0 from m_4 to c_3 for 1.5 dollars 2019-02-27 11:33:51,233 - INFO - 8/10 [90.00%]: Executing c_2-c1142518-c4d8-4f80-9889-693a093ef989, m_4-4f6b8ebc-32b0-44d5-88d6-88b3cec0b489 agreed on {'time': 8, 'quantity': 3, 'unit_price': 0.5} 2019-02-27 11:33:51,233 - DEBUG - 8/10 [90.00%]: Moved 3 units of p0 from m_4 to c_2 for 1.5 dollars 2019-02-27 11:33:51,233 - INFO - 8/10 [90.00%]: Executing c_0-b6f40f78-35c5-4b76-9f90-53a459a66882, m_1-b789f15d-3508-464a-8717-8ba1da159754 agreed on {'time': 8, 'quantity': 4, 'unit_price': 0.5} 2019-02-27 11:33:51,233 - DEBUG - 8/10 [90.00%]: Moved 4 units of p0 from m_1 to c_0 for 2.0 dollars 2019-02-27 11:33:51,233 - INFO - 8/10 [90.00%]: Executing c_4-76d9311e-d5f6-4e91-bb83-72994095e2c6, m_3-418c12ae-b8cd-4e28-a9a8-b998b4ef7df6 agreed on {'time': 8, 'quantity': 3, 'unit_price': 0.5} 2019-02-27 11:33:51,234 - DEBUG - 8/10 [90.00%]: Moved 3 units of p0 from m_3 to c_4 for 1.5 dollars 2019-02-27 11:33:51,234 - INFO - 8/10 [90.00%]: Executing c_1-68b3b84c-c42b-4582-9119-917484eb77ef, m_1-b789f15d-3508-464a-8717-8ba1da159754 agreed on {'time': 8, 'quantity': 3, 'unit_price': 0.5} 2019-02-27 11:33:51,234 - DEBUG - 8/10 [90.00%]: Moved 3 units of p0 from m_1 to c_1 for 1.5 dollars 2019-02-27 11:33:51,234 - DEBUG - 8/10 [90.00%]: Factory 95e75c6e-fd73-4d10-bb63-7e6fd5ed934d: money=-13.0, storage={0: 19}, loans=0.0 2019-02-27 11:33:51,234 - DEBUG - 8/10 [90.00%]: Factory 1d03dc99-48cd-4b69-81d8-4faf95f470b1: money=-11.5, storage={0: 17}, loans=0.0 2019-02-27 11:33:51,234 - DEBUG - 8/10 [90.00%]: Factory 3988d198-d05c-4a8a-93c9-8a88363a07d6: money=-12.5, storage={0: 19}, loans=0.0 2019-02-27 11:33:51,234 - DEBUG - 8/10 [90.00%]: Factory bad2c634-f9b5-4ae3-8b59-626ce7e171fb: money=-12.0, storage={0: 18}, loans=0.0 2019-02-27 11:33:51,234 - DEBUG - 8/10 [90.00%]: Factory ee428c0e-e853-4495-8bbd-24302264a757: money=-12.0, storage={0: 18}, loans=0.0 2019-02-27 11:33:51,234 - DEBUG - 8/10 [90.00%]: Factory cb5ab840-9bd8-41f9-866a-ca43e56e74c6: money=8.5, storage={0: -17}, loans=0.0 2019-02-27 11:33:51,234 - DEBUG - 8/10 [90.00%]: Factory b5cdcb3a-a4bd-478d-9795-d361eb70cf32: money=17.0, storage={0: -34}, loans=0.0 2019-02-27 11:33:51,234 - DEBUG - 8/10 [90.00%]: Factory cb4aedd6-68a2-450a-8d92-117fcb5ae311: money=10.5, storage={0: -21}, loans=0.0 2019-02-27 11:33:51,234 - DEBUG - 8/10 [90.00%]: Factory 986a8ca5-1b97-449f-b316-450edc5ed050: money=8.0, storage={0: -16}, loans=0.0 2019-02-27 11:33:51,234 - DEBUG - 8/10 [90.00%]: Factory d70b6918-35dd-4eab-924c-7a13f3ad3feb: money=17.0, storage={0: -34}, loans=0.0 2019-02-27 11:33:51,234 - INFO - 9/10 [100.00%]: 0 Negotiations/4 _entities 2019-02-27 11:33:51,235 - DEBUG - 9/10 [100.00%]: Factory 95e75c6e-fd73-4d10-bb63-7e6fd5ed934d: money=-13.0, storage={0: 22}, loans=0.0 2019-02-27 11:33:51,235 - DEBUG - 9/10 [100.00%]: Factory 1d03dc99-48cd-4b69-81d8-4faf95f470b1: money=-11.5, storage={0: 20}, loans=0.0 2019-02-27 11:33:51,235 - DEBUG - 9/10 [100.00%]: Factory 3988d198-d05c-4a8a-93c9-8a88363a07d6: money=-12.5, storage={0: 22}, loans=0.0 2019-02-27 11:33:51,235 - DEBUG - 9/10 [100.00%]: Factory bad2c634-f9b5-4ae3-8b59-626ce7e171fb: money=-12.0, storage={0: 21}, loans=0.0 2019-02-27 11:33:51,235 - DEBUG - 9/10 [100.00%]: Factory ee428c0e-e853-4495-8bbd-24302264a757: money=-12.0, storage={0: 21}, loans=0.0 2019-02-27 11:33:51,235 - DEBUG - 9/10 [100.00%]: Factory cb5ab840-9bd8-41f9-866a-ca43e56e74c6: money=8.5, storage={0: -17}, loans=0.0 2019-02-27 11:33:51,235 - DEBUG - 9/10 [100.00%]: Factory b5cdcb3a-a4bd-478d-9795-d361eb70cf32: money=17.0, storage={0: -34}, loans=0.0 2019-02-27 11:33:51,235 - DEBUG - 9/10 [100.00%]: Factory cb4aedd6-68a2-450a-8d92-117fcb5ae311: money=10.5, storage={0: -21}, loans=0.0 2019-02-27 11:33:51,235 - DEBUG - 9/10 [100.00%]: Factory 986a8ca5-1b97-449f-b316-450edc5ed050: money=8.0, storage={0: -16}, loans=0.0 2019-02-27 11:33:51,235 - DEBUG - 9/10 [100.00%]: Factory d70b6918-35dd-4eab-924c-7a13f3ad3feb: money=17.0, storage={0: -34}, loans=0.0 PK!wZ88#negmas/logs/log_20190227-113406.txt2019-02-27 11:34:08,616 - INFO - 0/10 [10.00%]: SCMLWorld/20190227-113408EwL56: World Created 2019-02-27 11:34:08,616 - INFO - 0/10 [10.00%]: m_0 joined 2019-02-27 11:34:08,617 - INFO - 0/10 [10.00%]: m_1 joined 2019-02-27 11:34:08,617 - INFO - 0/10 [10.00%]: m_2 joined 2019-02-27 11:34:08,617 - INFO - 0/10 [10.00%]: m_3 joined 2019-02-27 11:34:08,617 - INFO - 0/10 [10.00%]: m_4 joined 2019-02-27 11:34:08,617 - INFO - 0/10 [10.00%]: c_0 joined 2019-02-27 11:34:08,617 - INFO - 0/10 [10.00%]: c_1 joined 2019-02-27 11:34:08,617 - INFO - 0/10 [10.00%]: c_2 joined 2019-02-27 11:34:08,617 - INFO - 0/10 [10.00%]: c_3 joined 2019-02-27 11:34:08,617 - INFO - 0/10 [10.00%]: c_4 joined 2019-02-27 11:34:08,618 - INFO - 0/10 [10.00%]: nGisiWgNZq6ITZM5 joined 2019-02-27 11:34:08,618 - INFO - 0/10 [10.00%]: jtgUe52RvEJgwBuN joined 2019-02-27 11:34:08,618 - INFO - 0/10 [10.00%]: 0 Negotiations/4 _entities 2019-02-27 11:34:08,621 - INFO - 0/10 [10.00%]: m_0 requested negmas.sao.SAOMechanism[None] with ['c_1', 'm_0'] (ID 87983d4f-9a58-481a-8f08-ff5a16e7c4ef) 2019-02-27 11:34:08,623 - INFO - 0/10 [10.00%]: m_0-6a7c0ac4-5a18-4feb-bcc1-a5a67aa1e7c5 request was accepted 2019-02-27 11:34:08,624 - INFO - 0/10 [10.00%]: m_1 requested negmas.sao.SAOMechanism[None] with ['c_1', 'm_1'] (ID f71fe54a-2031-4d75-b705-4bad86a46fcd) 2019-02-27 11:34:08,625 - INFO - 0/10 [10.00%]: m_1-02672ede-8506-42d2-9911-04211fcde6e5 request was accepted 2019-02-27 11:34:08,626 - INFO - 0/10 [10.00%]: m_2 requested negmas.sao.SAOMechanism[None] with ['c_1', 'm_2'] (ID 7a050107-8b73-4239-b655-4fa67afe7106) 2019-02-27 11:34:08,626 - INFO - 0/10 [10.00%]: m_2-577afd33-5aed-4647-8f4a-17a41dca4d54 request was accepted 2019-02-27 11:34:08,627 - INFO - 0/10 [10.00%]: m_3 requested negmas.sao.SAOMechanism[None] with ['c_1', 'm_3'] (ID 4c7f7506-cf98-4927-9f7b-38aa5cb68f4a) 2019-02-27 11:34:08,628 - INFO - 0/10 [10.00%]: m_3-dcea5638-aed1-4f6b-bf21-1a67e1bdefbd request was accepted 2019-02-27 11:34:08,629 - INFO - 0/10 [10.00%]: m_4 requested negmas.sao.SAOMechanism[None] with ['c_1', 'm_4'] (ID 69d052c2-c9c8-4b01-bb26-d343feda8899) 2019-02-27 11:34:08,630 - INFO - 0/10 [10.00%]: m_4-eebf8ea6-43d6-4114-96fb-76507f40ec73 request was accepted 2019-02-27 11:34:08,632 - INFO - 0/10 [10.00%]: m_0 requested negmas.sao.SAOMechanism[None] with ['c_1', 'm_0'] (ID 6dbc539f-064f-4f2b-90b7-b38b127925f8) 2019-02-27 11:34:08,634 - INFO - 0/10 [10.00%]: m_0-6a7c0ac4-5a18-4feb-bcc1-a5a67aa1e7c5 request was accepted 2019-02-27 11:34:08,635 - INFO - 0/10 [10.00%]: m_1 requested negmas.sao.SAOMechanism[None] with ['c_1', 'm_1'] (ID 442b899d-7ab6-4cf6-9436-0018f6736261) 2019-02-27 11:34:08,636 - INFO - 0/10 [10.00%]: m_1-02672ede-8506-42d2-9911-04211fcde6e5 request was accepted 2019-02-27 11:34:08,637 - INFO - 0/10 [10.00%]: m_2 requested negmas.sao.SAOMechanism[None] with ['c_1', 'm_2'] (ID a90a1f09-3c15-45f7-bb76-f7fe5b0c908d) 2019-02-27 11:34:08,637 - INFO - 0/10 [10.00%]: m_2-577afd33-5aed-4647-8f4a-17a41dca4d54 request was accepted 2019-02-27 11:34:08,638 - INFO - 0/10 [10.00%]: m_3 requested negmas.sao.SAOMechanism[None] with ['c_1', 'm_3'] (ID 25fca749-5060-4b10-8353-03d7c712402c) 2019-02-27 11:34:08,639 - INFO - 0/10 [10.00%]: m_3-dcea5638-aed1-4f6b-bf21-1a67e1bdefbd request was accepted 2019-02-27 11:34:08,640 - INFO - 0/10 [10.00%]: m_4 requested negmas.sao.SAOMechanism[None] with ['c_1', 'm_4'] (ID bdc508ab-81d9-45a4-99fc-ed73962e5d23) 2019-02-27 11:34:08,640 - INFO - 0/10 [10.00%]: m_4-eebf8ea6-43d6-4114-96fb-76507f40ec73 request was accepted 2019-02-27 11:34:08,642 - INFO - 0/10 [10.00%]: m_0 requested negmas.sao.SAOMechanism[None] with ['c_1', 'm_0'] (ID 643d4b1c-d7a0-46bc-9766-d00b5ad1dc07) 2019-02-27 11:34:08,642 - INFO - 0/10 [10.00%]: m_0-6a7c0ac4-5a18-4feb-bcc1-a5a67aa1e7c5 request was accepted 2019-02-27 11:34:08,643 - INFO - 0/10 [10.00%]: m_1 requested negmas.sao.SAOMechanism[None] with ['c_1', 'm_1'] (ID c59bce81-8ff7-4bf7-9de0-b2b2da1d89e7) 2019-02-27 11:34:08,644 - INFO - 0/10 [10.00%]: m_1-02672ede-8506-42d2-9911-04211fcde6e5 request was accepted 2019-02-27 11:34:08,645 - INFO - 0/10 [10.00%]: m_2 requested negmas.sao.SAOMechanism[None] with ['c_1', 'm_2'] (ID 8bac0586-13eb-4022-9df9-5d98ecb3f041) 2019-02-27 11:34:08,645 - INFO - 0/10 [10.00%]: m_2-577afd33-5aed-4647-8f4a-17a41dca4d54 request was accepted 2019-02-27 11:34:08,646 - INFO - 0/10 [10.00%]: m_3 requested negmas.sao.SAOMechanism[None] with ['c_1', 'm_3'] (ID c1ff37a7-4667-431d-84f0-f2ec13304c45) 2019-02-27 11:34:08,647 - INFO - 0/10 [10.00%]: m_3-dcea5638-aed1-4f6b-bf21-1a67e1bdefbd request was accepted 2019-02-27 11:34:08,648 - INFO - 0/10 [10.00%]: m_4 requested negmas.sao.SAOMechanism[None] with ['c_1', 'm_4'] (ID 3dd9221a-df90-4dd6-8d27-d49db4e7c40a) 2019-02-27 11:34:08,649 - INFO - 0/10 [10.00%]: m_4-eebf8ea6-43d6-4114-96fb-76507f40ec73 request was accepted 2019-02-27 11:34:08,650 - INFO - 0/10 [10.00%]: m_0 requested negmas.sao.SAOMechanism[None] with ['c_1', 'm_0'] (ID 0f4d559c-df20-498c-8ec4-66b7b5f15ffc) 2019-02-27 11:34:08,650 - INFO - 0/10 [10.00%]: m_0-6a7c0ac4-5a18-4feb-bcc1-a5a67aa1e7c5 request was accepted 2019-02-27 11:34:08,651 - INFO - 0/10 [10.00%]: m_1 requested negmas.sao.SAOMechanism[None] with ['c_1', 'm_1'] (ID 8bd26bbc-3584-4513-8887-d83f5d599966) 2019-02-27 11:34:08,652 - INFO - 0/10 [10.00%]: m_1-02672ede-8506-42d2-9911-04211fcde6e5 request was accepted 2019-02-27 11:34:08,653 - INFO - 0/10 [10.00%]: m_2 requested negmas.sao.SAOMechanism[None] with ['c_1', 'm_2'] (ID d69bbd12-a7cd-4f46-9d3c-9b765700b6b7) 2019-02-27 11:34:08,654 - INFO - 0/10 [10.00%]: m_2-577afd33-5aed-4647-8f4a-17a41dca4d54 request was accepted 2019-02-27 11:34:08,654 - INFO - 0/10 [10.00%]: m_3 requested negmas.sao.SAOMechanism[None] with ['c_1', 'm_3'] (ID 9ef5abfc-4a97-4a08-8bd5-b1129790e187) 2019-02-27 11:34:08,655 - INFO - 0/10 [10.00%]: m_3-dcea5638-aed1-4f6b-bf21-1a67e1bdefbd request was accepted 2019-02-27 11:34:08,656 - INFO - 0/10 [10.00%]: m_4 requested negmas.sao.SAOMechanism[None] with ['c_1', 'm_4'] (ID 9ee673d9-9843-45f0-b94f-dab8aafbaabf) 2019-02-27 11:34:08,657 - INFO - 0/10 [10.00%]: m_4-eebf8ea6-43d6-4114-96fb-76507f40ec73 request was accepted 2019-02-27 11:34:08,659 - INFO - 0/10 [10.00%]: m_0 requested negmas.sao.SAOMechanism[None] with ['c_3', 'm_0'] (ID 4698f8c8-1a0b-4d2d-a217-e10092481537) 2019-02-27 11:34:08,659 - INFO - 0/10 [10.00%]: m_0-6a7c0ac4-5a18-4feb-bcc1-a5a67aa1e7c5 request was accepted 2019-02-27 11:34:08,660 - INFO - 0/10 [10.00%]: m_1 requested negmas.sao.SAOMechanism[None] with ['c_3', 'm_1'] (ID 4d591afa-04a2-40a7-8b3f-660409ae47db) 2019-02-27 11:34:08,661 - INFO - 0/10 [10.00%]: m_1-02672ede-8506-42d2-9911-04211fcde6e5 request was accepted 2019-02-27 11:34:08,662 - INFO - 0/10 [10.00%]: m_2 requested negmas.sao.SAOMechanism[None] with ['c_3', 'm_2'] (ID d58542b4-f351-4f06-97a1-f451f6afa64f) 2019-02-27 11:34:08,662 - INFO - 0/10 [10.00%]: m_2-577afd33-5aed-4647-8f4a-17a41dca4d54 request was accepted 2019-02-27 11:34:08,663 - INFO - 0/10 [10.00%]: m_3 requested negmas.sao.SAOMechanism[None] with ['c_3', 'm_3'] (ID aa11c08e-269d-48e6-a282-008674da822e) 2019-02-27 11:34:08,664 - INFO - 0/10 [10.00%]: m_3-dcea5638-aed1-4f6b-bf21-1a67e1bdefbd request was accepted 2019-02-27 11:34:08,665 - INFO - 0/10 [10.00%]: m_4 requested negmas.sao.SAOMechanism[None] with ['c_3', 'm_4'] (ID 5e83c943-4ab0-4924-b509-483b55af0562) 2019-02-27 11:34:08,666 - INFO - 0/10 [10.00%]: m_4-eebf8ea6-43d6-4114-96fb-76507f40ec73 request was accepted 2019-02-27 11:34:08,667 - INFO - 0/10 [10.00%]: m_0 requested negmas.sao.SAOMechanism[None] with ['c_3', 'm_0'] (ID e3266671-b9b6-4a4b-8e43-16fd47ec63e1) 2019-02-27 11:34:08,668 - INFO - 0/10 [10.00%]: m_0-6a7c0ac4-5a18-4feb-bcc1-a5a67aa1e7c5 request was accepted 2019-02-27 11:34:08,669 - INFO - 0/10 [10.00%]: m_1 requested negmas.sao.SAOMechanism[None] with ['c_3', 'm_1'] (ID afa6b3ba-0f52-468e-b22b-ac41906adf46) 2019-02-27 11:34:08,672 - INFO - 0/10 [10.00%]: m_1-02672ede-8506-42d2-9911-04211fcde6e5 request was accepted 2019-02-27 11:34:08,675 - INFO - 0/10 [10.00%]: m_2 requested negmas.sao.SAOMechanism[None] with ['c_3', 'm_2'] (ID 37e5f8e0-3fdb-43f6-bbb1-5adbe4990be9) 2019-02-27 11:34:08,677 - INFO - 0/10 [10.00%]: m_2-577afd33-5aed-4647-8f4a-17a41dca4d54 request was accepted 2019-02-27 11:34:08,680 - INFO - 0/10 [10.00%]: m_3 requested negmas.sao.SAOMechanism[None] with ['c_3', 'm_3'] (ID 33332268-4f81-4c32-aeeb-7e1ff272ce3d) 2019-02-27 11:34:08,681 - INFO - 0/10 [10.00%]: m_3-dcea5638-aed1-4f6b-bf21-1a67e1bdefbd request was accepted 2019-02-27 11:34:08,683 - INFO - 0/10 [10.00%]: m_4 requested negmas.sao.SAOMechanism[None] with ['c_3', 'm_4'] (ID 64e49bb1-d7b5-41a1-b322-98d46d2890f4) 2019-02-27 11:34:08,684 - INFO - 0/10 [10.00%]: m_4-eebf8ea6-43d6-4114-96fb-76507f40ec73 request was accepted 2019-02-27 11:34:08,685 - INFO - 0/10 [10.00%]: m_0 requested negmas.sao.SAOMechanism[None] with ['c_3', 'm_0'] (ID 106a5e0e-f6a0-4d22-a5b1-51a6c5b6c0b9) 2019-02-27 11:34:08,686 - INFO - 0/10 [10.00%]: m_0-6a7c0ac4-5a18-4feb-bcc1-a5a67aa1e7c5 request was accepted 2019-02-27 11:34:08,689 - INFO - 0/10 [10.00%]: m_1 requested negmas.sao.SAOMechanism[None] with ['c_3', 'm_1'] (ID 4bad71d2-6ac7-429c-85b8-f53435c3b95a) 2019-02-27 11:34:08,690 - INFO - 0/10 [10.00%]: m_1-02672ede-8506-42d2-9911-04211fcde6e5 request was accepted 2019-02-27 11:34:08,691 - INFO - 0/10 [10.00%]: m_2 requested negmas.sao.SAOMechanism[None] with ['c_3', 'm_2'] (ID 9d9e0cb3-0468-457c-ad0f-44e83d42ed9b) 2019-02-27 11:34:08,691 - INFO - 0/10 [10.00%]: m_2-577afd33-5aed-4647-8f4a-17a41dca4d54 request was accepted 2019-02-27 11:34:08,692 - INFO - 0/10 [10.00%]: m_3 requested negmas.sao.SAOMechanism[None] with ['c_3', 'm_3'] (ID b8d0beef-fcbb-48a3-9b73-6bce4436a454) 2019-02-27 11:34:08,693 - INFO - 0/10 [10.00%]: m_3-dcea5638-aed1-4f6b-bf21-1a67e1bdefbd request was accepted 2019-02-27 11:34:08,694 - INFO - 0/10 [10.00%]: m_4 requested negmas.sao.SAOMechanism[None] with ['c_3', 'm_4'] (ID 625f9526-8dd1-4a5c-a721-71d4af77428c) 2019-02-27 11:34:08,695 - INFO - 0/10 [10.00%]: m_4-eebf8ea6-43d6-4114-96fb-76507f40ec73 request was accepted 2019-02-27 11:34:08,696 - INFO - 0/10 [10.00%]: m_0 requested negmas.sao.SAOMechanism[None] with ['c_3', 'm_0'] (ID 4803556c-2660-4d65-92d7-75a20c84e685) 2019-02-27 11:34:08,697 - INFO - 0/10 [10.00%]: m_0-6a7c0ac4-5a18-4feb-bcc1-a5a67aa1e7c5 request was accepted 2019-02-27 11:34:08,699 - INFO - 0/10 [10.00%]: m_1 requested negmas.sao.SAOMechanism[None] with ['c_3', 'm_1'] (ID c0879c65-6102-480a-9730-b9ebb863a3ae) 2019-02-27 11:34:08,699 - INFO - 0/10 [10.00%]: m_1-02672ede-8506-42d2-9911-04211fcde6e5 request was accepted 2019-02-27 11:34:08,701 - INFO - 0/10 [10.00%]: m_2 requested negmas.sao.SAOMechanism[None] with ['c_3', 'm_2'] (ID bfed199a-695b-44c6-89b3-772f11eb7797) 2019-02-27 11:34:08,701 - INFO - 0/10 [10.00%]: m_2-577afd33-5aed-4647-8f4a-17a41dca4d54 request was accepted 2019-02-27 11:34:08,702 - INFO - 0/10 [10.00%]: m_3 requested negmas.sao.SAOMechanism[None] with ['c_3', 'm_3'] (ID 2a51b360-3f2e-4054-a0a6-7b0c7d4ab748) 2019-02-27 11:34:08,703 - INFO - 0/10 [10.00%]: m_3-dcea5638-aed1-4f6b-bf21-1a67e1bdefbd request was accepted 2019-02-27 11:34:08,704 - INFO - 0/10 [10.00%]: m_4 requested negmas.sao.SAOMechanism[None] with ['c_3', 'm_4'] (ID 889a80d0-cb37-4c32-b455-3da0fef9dc86) 2019-02-27 11:34:08,704 - INFO - 0/10 [10.00%]: m_4-eebf8ea6-43d6-4114-96fb-76507f40ec73 request was accepted 2019-02-27 11:34:08,706 - INFO - 0/10 [10.00%]: m_0 requested negmas.sao.SAOMechanism[None] with ['c_0', 'm_0'] (ID 5f820607-6968-450c-bfea-3abe56bbc408) 2019-02-27 11:34:08,706 - INFO - 0/10 [10.00%]: m_0-6a7c0ac4-5a18-4feb-bcc1-a5a67aa1e7c5 request was accepted 2019-02-27 11:34:08,707 - INFO - 0/10 [10.00%]: m_1 requested negmas.sao.SAOMechanism[None] with ['c_0', 'm_1'] (ID 04373b6e-6d23-4653-a563-0b77edfc5fcb) 2019-02-27 11:34:08,708 - INFO - 0/10 [10.00%]: m_1-02672ede-8506-42d2-9911-04211fcde6e5 request was accepted 2019-02-27 11:34:08,708 - INFO - 0/10 [10.00%]: m_2 requested negmas.sao.SAOMechanism[None] with ['c_0', 'm_2'] (ID 9adb2b17-48b0-4c7c-ba86-c35835fa57dc) 2019-02-27 11:34:08,709 - INFO - 0/10 [10.00%]: m_2-577afd33-5aed-4647-8f4a-17a41dca4d54 request was accepted 2019-02-27 11:34:08,710 - INFO - 0/10 [10.00%]: m_3 requested negmas.sao.SAOMechanism[None] with ['c_0', 'm_3'] (ID d0d3f9be-93f9-4b6f-9d6f-ecd3d50104be) 2019-02-27 11:34:08,710 - INFO - 0/10 [10.00%]: m_3-dcea5638-aed1-4f6b-bf21-1a67e1bdefbd request was accepted 2019-02-27 11:34:08,711 - INFO - 0/10 [10.00%]: m_4 requested negmas.sao.SAOMechanism[None] with ['c_0', 'm_4'] (ID 8d6b1124-cc59-4819-84c0-2c6ad5bae91f) 2019-02-27 11:34:08,712 - INFO - 0/10 [10.00%]: m_4-eebf8ea6-43d6-4114-96fb-76507f40ec73 request was accepted 2019-02-27 11:34:08,713 - INFO - 0/10 [10.00%]: m_0 requested negmas.sao.SAOMechanism[None] with ['c_0', 'm_0'] (ID f2dc6183-a1d2-4ee7-a0a6-dfb698367b8b) 2019-02-27 11:34:08,714 - INFO - 0/10 [10.00%]: m_0-6a7c0ac4-5a18-4feb-bcc1-a5a67aa1e7c5 request was accepted 2019-02-27 11:34:08,715 - INFO - 0/10 [10.00%]: m_1 requested negmas.sao.SAOMechanism[None] with ['c_0', 'm_1'] (ID 31e1a36b-ac46-4f0b-940b-4b94f3a6f6c5) 2019-02-27 11:34:08,715 - INFO - 0/10 [10.00%]: m_1-02672ede-8506-42d2-9911-04211fcde6e5 request was accepted 2019-02-27 11:34:08,716 - INFO - 0/10 [10.00%]: m_2 requested negmas.sao.SAOMechanism[None] with ['c_0', 'm_2'] (ID b55da4e9-e73f-4023-bb65-11bb2fe542b1) 2019-02-27 11:34:08,717 - INFO - 0/10 [10.00%]: m_2-577afd33-5aed-4647-8f4a-17a41dca4d54 request was accepted 2019-02-27 11:34:08,718 - INFO - 0/10 [10.00%]: m_3 requested negmas.sao.SAOMechanism[None] with ['c_0', 'm_3'] (ID 82799f93-594a-4c18-842b-ab02e8028ad0) 2019-02-27 11:34:08,718 - INFO - 0/10 [10.00%]: m_3-dcea5638-aed1-4f6b-bf21-1a67e1bdefbd request was accepted 2019-02-27 11:34:08,720 - INFO - 0/10 [10.00%]: m_4 requested negmas.sao.SAOMechanism[None] with ['c_0', 'm_4'] (ID b509da98-f654-4568-9d83-aac46cb18265) 2019-02-27 11:34:08,721 - INFO - 0/10 [10.00%]: m_4-eebf8ea6-43d6-4114-96fb-76507f40ec73 request was accepted 2019-02-27 11:34:08,723 - INFO - 0/10 [10.00%]: m_0 requested negmas.sao.SAOMechanism[None] with ['c_0', 'm_0'] (ID 54065d46-25cc-4db9-b358-818a395c19fb) 2019-02-27 11:34:08,723 - INFO - 0/10 [10.00%]: m_0-6a7c0ac4-5a18-4feb-bcc1-a5a67aa1e7c5 request was accepted 2019-02-27 11:34:08,724 - INFO - 0/10 [10.00%]: m_1 requested negmas.sao.SAOMechanism[None] with ['c_0', 'm_1'] (ID 222c5c66-1843-45e9-b20e-a1c37b5e9227) 2019-02-27 11:34:08,725 - INFO - 0/10 [10.00%]: m_1-02672ede-8506-42d2-9911-04211fcde6e5 request was accepted 2019-02-27 11:34:08,726 - INFO - 0/10 [10.00%]: m_2 requested negmas.sao.SAOMechanism[None] with ['c_0', 'm_2'] (ID 3253406b-f229-4409-8a45-41334bd98783) 2019-02-27 11:34:08,726 - INFO - 0/10 [10.00%]: m_2-577afd33-5aed-4647-8f4a-17a41dca4d54 request was accepted 2019-02-27 11:34:08,727 - INFO - 0/10 [10.00%]: m_3 requested negmas.sao.SAOMechanism[None] with ['c_0', 'm_3'] (ID 2b1d250c-a345-4271-a93c-d718530e0e03) 2019-02-27 11:34:08,728 - INFO - 0/10 [10.00%]: m_3-dcea5638-aed1-4f6b-bf21-1a67e1bdefbd request was accepted 2019-02-27 11:34:08,729 - INFO - 0/10 [10.00%]: m_4 requested negmas.sao.SAOMechanism[None] with ['c_0', 'm_4'] (ID db81a2bf-95f9-4d96-9bfb-5285bc758e4d) 2019-02-27 11:34:08,730 - INFO - 0/10 [10.00%]: m_4-eebf8ea6-43d6-4114-96fb-76507f40ec73 request was accepted 2019-02-27 11:34:08,732 - INFO - 0/10 [10.00%]: m_0 requested negmas.sao.SAOMechanism[None] with ['c_0', 'm_0'] (ID 27a14314-c2a7-4f02-b0d4-7faa3bb9e1a9) 2019-02-27 11:34:08,732 - INFO - 0/10 [10.00%]: m_0-6a7c0ac4-5a18-4feb-bcc1-a5a67aa1e7c5 request was accepted 2019-02-27 11:34:08,733 - INFO - 0/10 [10.00%]: m_1 requested negmas.sao.SAOMechanism[None] with ['c_0', 'm_1'] (ID b89801be-6aa5-44bf-8e96-6b66e7b599d1) 2019-02-27 11:34:08,734 - INFO - 0/10 [10.00%]: m_1-02672ede-8506-42d2-9911-04211fcde6e5 request was accepted 2019-02-27 11:34:08,735 - INFO - 0/10 [10.00%]: m_2 requested negmas.sao.SAOMechanism[None] with ['c_0', 'm_2'] (ID 44984931-8a21-444c-804d-934228e379e3) 2019-02-27 11:34:08,735 - INFO - 0/10 [10.00%]: m_2-577afd33-5aed-4647-8f4a-17a41dca4d54 request was accepted 2019-02-27 11:34:08,736 - INFO - 0/10 [10.00%]: m_3 requested negmas.sao.SAOMechanism[None] with ['c_0', 'm_3'] (ID 56faab92-8b12-46e7-b72a-a5b17f61e7fa) 2019-02-27 11:34:08,737 - INFO - 0/10 [10.00%]: m_3-dcea5638-aed1-4f6b-bf21-1a67e1bdefbd request was accepted 2019-02-27 11:34:08,738 - INFO - 0/10 [10.00%]: m_4 requested negmas.sao.SAOMechanism[None] with ['c_0', 'm_4'] (ID 6b856241-d265-403e-920b-21b9593df5d7) 2019-02-27 11:34:08,738 - INFO - 0/10 [10.00%]: m_4-eebf8ea6-43d6-4114-96fb-76507f40ec73 request was accepted 2019-02-27 11:34:08,740 - INFO - 0/10 [10.00%]: m_0 requested negmas.sao.SAOMechanism[None] with ['c_2', 'm_0'] (ID 706d3dc4-e712-46bf-841c-a4f815604fcd) 2019-02-27 11:34:08,740 - INFO - 0/10 [10.00%]: m_0-6a7c0ac4-5a18-4feb-bcc1-a5a67aa1e7c5 request was accepted 2019-02-27 11:34:08,741 - INFO - 0/10 [10.00%]: m_1 requested negmas.sao.SAOMechanism[None] with ['c_2', 'm_1'] (ID 0e394cf9-9c2d-4fc9-8a39-8f7f0fd0625e) 2019-02-27 11:34:08,742 - INFO - 0/10 [10.00%]: m_1-02672ede-8506-42d2-9911-04211fcde6e5 request was accepted 2019-02-27 11:34:08,743 - INFO - 0/10 [10.00%]: m_2 requested negmas.sao.SAOMechanism[None] with ['c_2', 'm_2'] (ID 2663f4d0-e8b8-4e41-812e-bec1a0547f0f) 2019-02-27 11:34:08,743 - INFO - 0/10 [10.00%]: m_2-577afd33-5aed-4647-8f4a-17a41dca4d54 request was accepted 2019-02-27 11:34:08,744 - INFO - 0/10 [10.00%]: m_3 requested negmas.sao.SAOMechanism[None] with ['c_2', 'm_3'] (ID e1b929ab-9008-40de-8921-c1460f438b17) 2019-02-27 11:34:08,745 - INFO - 0/10 [10.00%]: m_3-dcea5638-aed1-4f6b-bf21-1a67e1bdefbd request was accepted 2019-02-27 11:34:08,746 - INFO - 0/10 [10.00%]: m_4 requested negmas.sao.SAOMechanism[None] with ['c_2', 'm_4'] (ID c9a1b9a1-c6c7-4f57-ae43-c4ee8a72e17c) 2019-02-27 11:34:08,746 - INFO - 0/10 [10.00%]: m_4-eebf8ea6-43d6-4114-96fb-76507f40ec73 request was accepted 2019-02-27 11:34:08,748 - INFO - 0/10 [10.00%]: m_0 requested negmas.sao.SAOMechanism[None] with ['c_2', 'm_0'] (ID 5ecd4052-4c33-4602-b5a8-fd196f445636) 2019-02-27 11:34:08,748 - INFO - 0/10 [10.00%]: m_0-6a7c0ac4-5a18-4feb-bcc1-a5a67aa1e7c5 request was accepted 2019-02-27 11:34:08,749 - INFO - 0/10 [10.00%]: m_1 requested negmas.sao.SAOMechanism[None] with ['c_2', 'm_1'] (ID e1bbe590-c4a8-4fcb-af70-7aaa906598ca) 2019-02-27 11:34:08,750 - INFO - 0/10 [10.00%]: m_1-02672ede-8506-42d2-9911-04211fcde6e5 request was accepted 2019-02-27 11:34:08,751 - INFO - 0/10 [10.00%]: m_2 requested negmas.sao.SAOMechanism[None] with ['c_2', 'm_2'] (ID eeee4766-66ef-463a-a472-9d77bef61a4e) 2019-02-27 11:34:08,752 - INFO - 0/10 [10.00%]: m_2-577afd33-5aed-4647-8f4a-17a41dca4d54 request was accepted 2019-02-27 11:34:08,753 - INFO - 0/10 [10.00%]: m_3 requested negmas.sao.SAOMechanism[None] with ['c_2', 'm_3'] (ID e2a70f44-5b7a-4603-9eb0-a0c6ef02aaff) 2019-02-27 11:34:08,753 - INFO - 0/10 [10.00%]: m_3-dcea5638-aed1-4f6b-bf21-1a67e1bdefbd request was accepted 2019-02-27 11:34:08,754 - INFO - 0/10 [10.00%]: m_4 requested negmas.sao.SAOMechanism[None] with ['c_2', 'm_4'] (ID c36152f2-800e-422d-84ad-968b7b876654) 2019-02-27 11:34:08,754 - INFO - 0/10 [10.00%]: m_4-eebf8ea6-43d6-4114-96fb-76507f40ec73 request was accepted 2019-02-27 11:34:08,756 - INFO - 0/10 [10.00%]: m_0 requested negmas.sao.SAOMechanism[None] with ['c_2', 'm_0'] (ID cbbaa1c7-cddb-45ae-9bbc-93bbfef7aed8) 2019-02-27 11:34:08,756 - INFO - 0/10 [10.00%]: m_0-6a7c0ac4-5a18-4feb-bcc1-a5a67aa1e7c5 request was accepted 2019-02-27 11:34:08,757 - INFO - 0/10 [10.00%]: m_1 requested negmas.sao.SAOMechanism[None] with ['c_2', 'm_1'] (ID bb525f31-d73c-4944-b49e-4a3e20ad1052) 2019-02-27 11:34:08,758 - INFO - 0/10 [10.00%]: m_1-02672ede-8506-42d2-9911-04211fcde6e5 request was accepted 2019-02-27 11:34:08,759 - INFO - 0/10 [10.00%]: m_2 requested negmas.sao.SAOMechanism[None] with ['c_2', 'm_2'] (ID 46fbe551-4cd4-4ac6-a08b-dfd7269d7f11) 2019-02-27 11:34:08,760 - INFO - 0/10 [10.00%]: m_2-577afd33-5aed-4647-8f4a-17a41dca4d54 request was accepted 2019-02-27 11:34:08,761 - INFO - 0/10 [10.00%]: m_3 requested negmas.sao.SAOMechanism[None] with ['c_2', 'm_3'] (ID 1dd5f480-ae51-4c7d-8f93-bd50ef107ca8) 2019-02-27 11:34:08,761 - INFO - 0/10 [10.00%]: m_3-dcea5638-aed1-4f6b-bf21-1a67e1bdefbd request was accepted 2019-02-27 11:34:08,762 - INFO - 0/10 [10.00%]: m_4 requested negmas.sao.SAOMechanism[None] with ['c_2', 'm_4'] (ID 0cf3e655-9df7-4752-a723-f10e5017dbd6) 2019-02-27 11:34:08,763 - INFO - 0/10 [10.00%]: m_4-eebf8ea6-43d6-4114-96fb-76507f40ec73 request was accepted 2019-02-27 11:34:08,764 - INFO - 0/10 [10.00%]: m_0 requested negmas.sao.SAOMechanism[None] with ['c_2', 'm_0'] (ID e8b6705f-81c3-446a-a4fa-8eae9cf16192) 2019-02-27 11:34:08,765 - INFO - 0/10 [10.00%]: m_0-6a7c0ac4-5a18-4feb-bcc1-a5a67aa1e7c5 request was accepted 2019-02-27 11:34:08,766 - INFO - 0/10 [10.00%]: m_1 requested negmas.sao.SAOMechanism[None] with ['c_2', 'm_1'] (ID 01971568-598b-4b00-a504-306fd464920a) 2019-02-27 11:34:08,766 - INFO - 0/10 [10.00%]: m_1-02672ede-8506-42d2-9911-04211fcde6e5 request was accepted 2019-02-27 11:34:08,767 - INFO - 0/10 [10.00%]: m_2 requested negmas.sao.SAOMechanism[None] with ['c_2', 'm_2'] (ID 93bd2d47-d9a4-456c-a0a7-c9c92110d9e5) 2019-02-27 11:34:08,768 - INFO - 0/10 [10.00%]: m_2-577afd33-5aed-4647-8f4a-17a41dca4d54 request was accepted 2019-02-27 11:34:08,769 - INFO - 0/10 [10.00%]: m_3 requested negmas.sao.SAOMechanism[None] with ['c_2', 'm_3'] (ID ac0369f7-e02f-4d87-a2aa-a9c0cbbadb82) 2019-02-27 11:34:08,770 - INFO - 0/10 [10.00%]: m_3-dcea5638-aed1-4f6b-bf21-1a67e1bdefbd request was accepted 2019-02-27 11:34:08,771 - INFO - 0/10 [10.00%]: m_4 requested negmas.sao.SAOMechanism[None] with ['c_2', 'm_4'] (ID 9bb01b0d-96f6-49ad-879c-a96cbc848358) 2019-02-27 11:34:08,771 - INFO - 0/10 [10.00%]: m_4-eebf8ea6-43d6-4114-96fb-76507f40ec73 request was accepted 2019-02-27 11:34:08,773 - INFO - 0/10 [10.00%]: m_0 requested negmas.sao.SAOMechanism[None] with ['c_4', 'm_0'] (ID 47fcea46-2fd0-40fd-bc79-7ff11aed300b) 2019-02-27 11:34:08,773 - INFO - 0/10 [10.00%]: m_0-6a7c0ac4-5a18-4feb-bcc1-a5a67aa1e7c5 request was accepted 2019-02-27 11:34:08,775 - INFO - 0/10 [10.00%]: m_1 requested negmas.sao.SAOMechanism[None] with ['c_4', 'm_1'] (ID 429ea35d-3f34-48a4-bf7a-72502d4d96a7) 2019-02-27 11:34:08,775 - INFO - 0/10 [10.00%]: m_1-02672ede-8506-42d2-9911-04211fcde6e5 request was accepted 2019-02-27 11:34:08,776 - INFO - 0/10 [10.00%]: m_2 requested negmas.sao.SAOMechanism[None] with ['c_4', 'm_2'] (ID 8ae827f9-0fc6-480f-8146-ecdd0289d127) 2019-02-27 11:34:08,777 - INFO - 0/10 [10.00%]: m_2-577afd33-5aed-4647-8f4a-17a41dca4d54 request was accepted 2019-02-27 11:34:08,778 - INFO - 0/10 [10.00%]: m_3 requested negmas.sao.SAOMechanism[None] with ['c_4', 'm_3'] (ID 25fc907b-778a-4500-8a40-589182668563) 2019-02-27 11:34:08,779 - INFO - 0/10 [10.00%]: m_3-dcea5638-aed1-4f6b-bf21-1a67e1bdefbd request was accepted 2019-02-27 11:34:08,780 - INFO - 0/10 [10.00%]: m_4 requested negmas.sao.SAOMechanism[None] with ['c_4', 'm_4'] (ID 06359b50-ba09-49dc-8b8e-e68a2741c51e) 2019-02-27 11:34:08,780 - INFO - 0/10 [10.00%]: m_4-eebf8ea6-43d6-4114-96fb-76507f40ec73 request was accepted 2019-02-27 11:34:08,782 - INFO - 0/10 [10.00%]: m_0 requested negmas.sao.SAOMechanism[None] with ['c_4', 'm_0'] (ID 5ce1f8c1-0efa-4d9b-a87a-208b74ceffb8) 2019-02-27 11:34:08,782 - INFO - 0/10 [10.00%]: m_0-6a7c0ac4-5a18-4feb-bcc1-a5a67aa1e7c5 request was accepted 2019-02-27 11:34:08,783 - INFO - 0/10 [10.00%]: m_1 requested negmas.sao.SAOMechanism[None] with ['c_4', 'm_1'] (ID 9b888dad-a5fe-47fc-aab3-5adfe9cc77c9) 2019-02-27 11:34:08,784 - INFO - 0/10 [10.00%]: m_1-02672ede-8506-42d2-9911-04211fcde6e5 request was accepted 2019-02-27 11:34:08,785 - INFO - 0/10 [10.00%]: m_2 requested negmas.sao.SAOMechanism[None] with ['c_4', 'm_2'] (ID 6a8707f2-7000-4643-adc6-7467eefe1cda) 2019-02-27 11:34:08,785 - INFO - 0/10 [10.00%]: m_2-577afd33-5aed-4647-8f4a-17a41dca4d54 request was accepted 2019-02-27 11:34:08,786 - INFO - 0/10 [10.00%]: m_3 requested negmas.sao.SAOMechanism[None] with ['c_4', 'm_3'] (ID 39339442-5387-4360-b9d0-d7e2788a0ca8) 2019-02-27 11:34:08,787 - INFO - 0/10 [10.00%]: m_3-dcea5638-aed1-4f6b-bf21-1a67e1bdefbd request was accepted 2019-02-27 11:34:08,788 - INFO - 0/10 [10.00%]: m_4 requested negmas.sao.SAOMechanism[None] with ['c_4', 'm_4'] (ID 55bf718f-4d2e-4c0f-b2cd-f3a4c15ed477) 2019-02-27 11:34:08,788 - INFO - 0/10 [10.00%]: m_4-eebf8ea6-43d6-4114-96fb-76507f40ec73 request was accepted 2019-02-27 11:34:08,790 - INFO - 0/10 [10.00%]: m_0 requested negmas.sao.SAOMechanism[None] with ['c_4', 'm_0'] (ID 8714131f-0c36-431e-a6a5-20656bc1e9e3) 2019-02-27 11:34:08,790 - INFO - 0/10 [10.00%]: m_0-6a7c0ac4-5a18-4feb-bcc1-a5a67aa1e7c5 request was accepted 2019-02-27 11:34:08,791 - INFO - 0/10 [10.00%]: m_1 requested negmas.sao.SAOMechanism[None] with ['c_4', 'm_1'] (ID fc43a655-1cf1-4002-8208-5b5217473b69) 2019-02-27 11:34:08,792 - INFO - 0/10 [10.00%]: m_1-02672ede-8506-42d2-9911-04211fcde6e5 request was accepted 2019-02-27 11:34:08,793 - INFO - 0/10 [10.00%]: m_2 requested negmas.sao.SAOMechanism[None] with ['c_4', 'm_2'] (ID b72aec0b-0741-4624-a07c-492e7cc29eb1) 2019-02-27 11:34:08,793 - INFO - 0/10 [10.00%]: m_2-577afd33-5aed-4647-8f4a-17a41dca4d54 request was accepted 2019-02-27 11:34:08,795 - INFO - 0/10 [10.00%]: m_3 requested negmas.sao.SAOMechanism[None] with ['c_4', 'm_3'] (ID b08c4a46-4806-49c0-b16f-e7f8d42ebe48) 2019-02-27 11:34:08,795 - INFO - 0/10 [10.00%]: m_3-dcea5638-aed1-4f6b-bf21-1a67e1bdefbd request was accepted 2019-02-27 11:34:08,796 - INFO - 0/10 [10.00%]: m_4 requested negmas.sao.SAOMechanism[None] with ['c_4', 'm_4'] (ID 8a94a60e-245f-45a6-8d33-7c61842d11e5) 2019-02-27 11:34:08,797 - INFO - 0/10 [10.00%]: m_4-eebf8ea6-43d6-4114-96fb-76507f40ec73 request was accepted 2019-02-27 11:34:08,798 - INFO - 0/10 [10.00%]: m_0 requested negmas.sao.SAOMechanism[None] with ['c_4', 'm_0'] (ID bc531ea3-7a16-4791-93aa-054ed2e315da) 2019-02-27 11:34:08,799 - INFO - 0/10 [10.00%]: m_0-6a7c0ac4-5a18-4feb-bcc1-a5a67aa1e7c5 request was accepted 2019-02-27 11:34:08,800 - INFO - 0/10 [10.00%]: m_1 requested negmas.sao.SAOMechanism[None] with ['c_4', 'm_1'] (ID 0e6bc040-8ff9-4794-8f85-156973b83da6) 2019-02-27 11:34:08,800 - INFO - 0/10 [10.00%]: m_1-02672ede-8506-42d2-9911-04211fcde6e5 request was accepted 2019-02-27 11:34:08,801 - INFO - 0/10 [10.00%]: m_2 requested negmas.sao.SAOMechanism[None] with ['c_4', 'm_2'] (ID a3e16393-abc4-40ab-9d80-e6949985baac) 2019-02-27 11:34:08,802 - INFO - 0/10 [10.00%]: m_2-577afd33-5aed-4647-8f4a-17a41dca4d54 request was accepted 2019-02-27 11:34:08,803 - INFO - 0/10 [10.00%]: m_3 requested negmas.sao.SAOMechanism[None] with ['c_4', 'm_3'] (ID ff4505a2-dd37-4601-90d0-6869072f29f8) 2019-02-27 11:34:08,803 - INFO - 0/10 [10.00%]: m_3-dcea5638-aed1-4f6b-bf21-1a67e1bdefbd request was accepted 2019-02-27 11:34:08,804 - INFO - 0/10 [10.00%]: m_4 requested negmas.sao.SAOMechanism[None] with ['c_4', 'm_4'] (ID 5bd9a22d-705c-49c5-88d6-ef6d87cbb070) 2019-02-27 11:34:08,805 - INFO - 0/10 [10.00%]: m_4-eebf8ea6-43d6-4114-96fb-76507f40ec73 request was accepted 2019-02-27 11:34:08,805 - DEBUG - 0/10 [10.00%]: Factory 567c17c8-8bbd-4ebb-828c-d4860fd379b7: money=0, storage={}, loans=0.0 2019-02-27 11:34:08,805 - DEBUG - 0/10 [10.00%]: Factory a0f4927d-1f5c-4f74-a2f7-aa8e774a27e3: money=0, storage={}, loans=0.0 2019-02-27 11:34:08,805 - DEBUG - 0/10 [10.00%]: Factory 8a8fa7a0-f90e-4d14-959d-34b2b489efe1: money=0, storage={}, loans=0.0 2019-02-27 11:34:08,805 - DEBUG - 0/10 [10.00%]: Factory c01b5ced-1ecd-491f-8503-d6b05067d41d: money=0, storage={}, loans=0.0 2019-02-27 11:34:08,805 - DEBUG - 0/10 [10.00%]: Factory e4a66fab-f4f6-483a-bc31-5cab325cfe7f: money=0, storage={}, loans=0.0 2019-02-27 11:34:08,805 - DEBUG - 0/10 [10.00%]: Factory ae788129-5389-405f-91bb-1dd70ada97a8: money=0.0, storage={}, loans=0.0 2019-02-27 11:34:08,805 - DEBUG - 0/10 [10.00%]: Factory ebf908e4-19c8-4171-ac89-c0ddba170b2f: money=0.0, storage={}, loans=0.0 2019-02-27 11:34:08,805 - DEBUG - 0/10 [10.00%]: Factory b3b8170f-8fca-486f-848a-69d82e617f52: money=0.0, storage={}, loans=0.0 2019-02-27 11:34:08,805 - DEBUG - 0/10 [10.00%]: Factory f5f00bb2-9f63-41d3-bbb2-270d5bc7268e: money=0.0, storage={}, loans=0.0 2019-02-27 11:34:08,805 - DEBUG - 0/10 [10.00%]: Factory 0f562fc9-74f3-4758-8c55-6045859782f5: money=0.0, storage={}, loans=0.0 2019-02-27 11:34:08,806 - INFO - 1/10 [20.00%]: 100 Negotiations/4 _entities 2019-02-27 11:34:09,673 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_1', 'm_3'] > {'time': 4, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_1-83f7bb54-0275-47dc-8c43-bd0e2b2744d4: buy 0 (t: 4, u: (0, 2.0), q: (1, 4))', 'partners': "['c_1-83f7bb54-0275-47dc-8c43-bd0e2b2744d4', 'm_3-dcea5638-aed1-4f6b-bf21-1a67e1bdefbd']", 'seller': 'm_3-dcea5638-aed1-4f6b-bf21-1a67e1bdefbd', 'buyer': 'c_1-83f7bb54-0275-47dc-8c43-bd0e2b2744d4'} 2019-02-27 11:34:09,674 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_1', 'm_4'] > {'time': 2, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_1-83f7bb54-0275-47dc-8c43-bd0e2b2744d4: buy 0 (t: 2, u: (0, 2.0), q: (1, 4))', 'partners': "['c_1-83f7bb54-0275-47dc-8c43-bd0e2b2744d4', 'm_4-eebf8ea6-43d6-4114-96fb-76507f40ec73']", 'seller': 'm_4-eebf8ea6-43d6-4114-96fb-76507f40ec73', 'buyer': 'c_1-83f7bb54-0275-47dc-8c43-bd0e2b2744d4'} 2019-02-27 11:34:09,674 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_4', 'm_3'] > {'time': 4, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_4-1729ce33-b911-41f1-b325-edaff5f0cdff: buy 0 (t: 4, u: (0, 2.0), q: (1, 3))', 'partners': "['c_4-1729ce33-b911-41f1-b325-edaff5f0cdff', 'm_3-dcea5638-aed1-4f6b-bf21-1a67e1bdefbd']", 'seller': 'm_3-dcea5638-aed1-4f6b-bf21-1a67e1bdefbd', 'buyer': 'c_4-1729ce33-b911-41f1-b325-edaff5f0cdff'} 2019-02-27 11:34:09,674 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_3', 'm_2'] > {'time': 1, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_3-b37498e8-6619-4aec-b3a3-dd95bbefbb6d: buy 0 (t: 1, u: (0, 2.0), q: (1, 4))', 'partners': "['c_3-b37498e8-6619-4aec-b3a3-dd95bbefbb6d', 'm_2-577afd33-5aed-4647-8f4a-17a41dca4d54']", 'seller': 'm_2-577afd33-5aed-4647-8f4a-17a41dca4d54', 'buyer': 'c_3-b37498e8-6619-4aec-b3a3-dd95bbefbb6d'} 2019-02-27 11:34:09,675 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_1', 'm_2'] > {'time': 3, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_1-83f7bb54-0275-47dc-8c43-bd0e2b2744d4: buy 0 (t: 3, u: (0, 2.0), q: (1, 4))', 'partners': "['c_1-83f7bb54-0275-47dc-8c43-bd0e2b2744d4', 'm_2-577afd33-5aed-4647-8f4a-17a41dca4d54']", 'seller': 'm_2-577afd33-5aed-4647-8f4a-17a41dca4d54', 'buyer': 'c_1-83f7bb54-0275-47dc-8c43-bd0e2b2744d4'} 2019-02-27 11:34:09,675 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_4', 'm_3'] > {'time': 2, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_4-1729ce33-b911-41f1-b325-edaff5f0cdff: buy 0 (t: 2, u: (0, 2.0), q: (1, 3))', 'partners': "['c_4-1729ce33-b911-41f1-b325-edaff5f0cdff', 'm_3-dcea5638-aed1-4f6b-bf21-1a67e1bdefbd']", 'seller': 'm_3-dcea5638-aed1-4f6b-bf21-1a67e1bdefbd', 'buyer': 'c_4-1729ce33-b911-41f1-b325-edaff5f0cdff'} 2019-02-27 11:34:09,675 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_0', 'm_4'] > {'time': 4, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_0-849400ab-19ff-42fa-bf65-10ef2f795a6f: buy 0 (t: 4, u: (0, 2.0), q: (1, 3))', 'partners': "['c_0-849400ab-19ff-42fa-bf65-10ef2f795a6f', 'm_4-eebf8ea6-43d6-4114-96fb-76507f40ec73']", 'seller': 'm_4-eebf8ea6-43d6-4114-96fb-76507f40ec73', 'buyer': 'c_0-849400ab-19ff-42fa-bf65-10ef2f795a6f'} 2019-02-27 11:34:09,676 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_4', 'm_2'] > {'time': 4, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_4-1729ce33-b911-41f1-b325-edaff5f0cdff: buy 0 (t: 4, u: (0, 2.0), q: (1, 3))', 'partners': "['c_4-1729ce33-b911-41f1-b325-edaff5f0cdff', 'm_2-577afd33-5aed-4647-8f4a-17a41dca4d54']", 'seller': 'm_2-577afd33-5aed-4647-8f4a-17a41dca4d54', 'buyer': 'c_4-1729ce33-b911-41f1-b325-edaff5f0cdff'} 2019-02-27 11:34:09,676 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_3', 'm_3'] > {'time': 4, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_3-b37498e8-6619-4aec-b3a3-dd95bbefbb6d: buy 0 (t: 4, u: (0, 2.0), q: (1, 4))', 'partners': "['c_3-b37498e8-6619-4aec-b3a3-dd95bbefbb6d', 'm_3-dcea5638-aed1-4f6b-bf21-1a67e1bdefbd']", 'seller': 'm_3-dcea5638-aed1-4f6b-bf21-1a67e1bdefbd', 'buyer': 'c_3-b37498e8-6619-4aec-b3a3-dd95bbefbb6d'} 2019-02-27 11:34:09,677 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_0', 'm_3'] > {'time': 1, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_0-849400ab-19ff-42fa-bf65-10ef2f795a6f: buy 0 (t: 1, u: (0, 2.0), q: (1, 3))', 'partners': "['c_0-849400ab-19ff-42fa-bf65-10ef2f795a6f', 'm_3-dcea5638-aed1-4f6b-bf21-1a67e1bdefbd']", 'seller': 'm_3-dcea5638-aed1-4f6b-bf21-1a67e1bdefbd', 'buyer': 'c_0-849400ab-19ff-42fa-bf65-10ef2f795a6f'} 2019-02-27 11:34:09,677 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_3', 'm_2'] > {'time': 3, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_3-b37498e8-6619-4aec-b3a3-dd95bbefbb6d: buy 0 (t: 3, u: (0, 2.0), q: (1, 3))', 'partners': "['c_3-b37498e8-6619-4aec-b3a3-dd95bbefbb6d', 'm_2-577afd33-5aed-4647-8f4a-17a41dca4d54']", 'seller': 'm_2-577afd33-5aed-4647-8f4a-17a41dca4d54', 'buyer': 'c_3-b37498e8-6619-4aec-b3a3-dd95bbefbb6d'} 2019-02-27 11:34:09,677 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_3', 'm_4'] > {'time': 2, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_3-b37498e8-6619-4aec-b3a3-dd95bbefbb6d: buy 0 (t: 2, u: (0, 2.0), q: (1, 4))', 'partners': "['c_3-b37498e8-6619-4aec-b3a3-dd95bbefbb6d', 'm_4-eebf8ea6-43d6-4114-96fb-76507f40ec73']", 'seller': 'm_4-eebf8ea6-43d6-4114-96fb-76507f40ec73', 'buyer': 'c_3-b37498e8-6619-4aec-b3a3-dd95bbefbb6d'} 2019-02-27 11:34:09,678 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_3', 'm_2'] > {'time': 2, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_3-b37498e8-6619-4aec-b3a3-dd95bbefbb6d: buy 0 (t: 2, u: (0, 2.0), q: (1, 4))', 'partners': "['c_3-b37498e8-6619-4aec-b3a3-dd95bbefbb6d', 'm_2-577afd33-5aed-4647-8f4a-17a41dca4d54']", 'seller': 'm_2-577afd33-5aed-4647-8f4a-17a41dca4d54', 'buyer': 'c_3-b37498e8-6619-4aec-b3a3-dd95bbefbb6d'} 2019-02-27 11:34:09,678 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_4', 'm_1'] > {'time': 2, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_4-1729ce33-b911-41f1-b325-edaff5f0cdff: buy 0 (t: 2, u: (0, 2.0), q: (1, 3))', 'partners': "['c_4-1729ce33-b911-41f1-b325-edaff5f0cdff', 'm_1-02672ede-8506-42d2-9911-04211fcde6e5']", 'seller': 'm_1-02672ede-8506-42d2-9911-04211fcde6e5', 'buyer': 'c_4-1729ce33-b911-41f1-b325-edaff5f0cdff'} 2019-02-27 11:34:09,678 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_2', 'm_3'] > {'time': 2, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_2-04df9282-7b04-48c4-a56c-066f6691dd4e: buy 0 (t: 2, u: (0, 2.0), q: (1, 3))', 'partners': "['c_2-04df9282-7b04-48c4-a56c-066f6691dd4e', 'm_3-dcea5638-aed1-4f6b-bf21-1a67e1bdefbd']", 'seller': 'm_3-dcea5638-aed1-4f6b-bf21-1a67e1bdefbd', 'buyer': 'c_2-04df9282-7b04-48c4-a56c-066f6691dd4e'} 2019-02-27 11:34:09,678 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_0', 'm_2'] > {'time': 4, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_0-849400ab-19ff-42fa-bf65-10ef2f795a6f: buy 0 (t: 4, u: (0, 2.0), q: (1, 3))', 'partners': "['c_0-849400ab-19ff-42fa-bf65-10ef2f795a6f', 'm_2-577afd33-5aed-4647-8f4a-17a41dca4d54']", 'seller': 'm_2-577afd33-5aed-4647-8f4a-17a41dca4d54', 'buyer': 'c_0-849400ab-19ff-42fa-bf65-10ef2f795a6f'} 2019-02-27 11:34:09,679 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_1', 'm_4'] > {'time': 1, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_1-83f7bb54-0275-47dc-8c43-bd0e2b2744d4: buy 0 (t: 1, u: (0, 2.0), q: (1, 4))', 'partners': "['c_1-83f7bb54-0275-47dc-8c43-bd0e2b2744d4', 'm_4-eebf8ea6-43d6-4114-96fb-76507f40ec73']", 'seller': 'm_4-eebf8ea6-43d6-4114-96fb-76507f40ec73', 'buyer': 'c_1-83f7bb54-0275-47dc-8c43-bd0e2b2744d4'} 2019-02-27 11:34:09,679 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_1', 'm_2'] > {'time': 1, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_1-83f7bb54-0275-47dc-8c43-bd0e2b2744d4: buy 0 (t: 1, u: (0, 2.0), q: (1, 4))', 'partners': "['c_1-83f7bb54-0275-47dc-8c43-bd0e2b2744d4', 'm_2-577afd33-5aed-4647-8f4a-17a41dca4d54']", 'seller': 'm_2-577afd33-5aed-4647-8f4a-17a41dca4d54', 'buyer': 'c_1-83f7bb54-0275-47dc-8c43-bd0e2b2744d4'} 2019-02-27 11:34:09,679 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_0', 'm_0'] > {'time': 3, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_0-849400ab-19ff-42fa-bf65-10ef2f795a6f: buy 0 (t: 3, u: (0, 2.0), q: (1, 3))', 'partners': "['c_0-849400ab-19ff-42fa-bf65-10ef2f795a6f', 'm_0-6a7c0ac4-5a18-4feb-bcc1-a5a67aa1e7c5']", 'seller': 'm_0-6a7c0ac4-5a18-4feb-bcc1-a5a67aa1e7c5', 'buyer': 'c_0-849400ab-19ff-42fa-bf65-10ef2f795a6f'} 2019-02-27 11:34:09,680 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_1', 'm_2'] > {'time': 2, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_1-83f7bb54-0275-47dc-8c43-bd0e2b2744d4: buy 0 (t: 2, u: (0, 2.0), q: (1, 4))', 'partners': "['c_1-83f7bb54-0275-47dc-8c43-bd0e2b2744d4', 'm_2-577afd33-5aed-4647-8f4a-17a41dca4d54']", 'seller': 'm_2-577afd33-5aed-4647-8f4a-17a41dca4d54', 'buyer': 'c_1-83f7bb54-0275-47dc-8c43-bd0e2b2744d4'} 2019-02-27 11:34:09,680 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_4', 'm_0'] > {'time': 3, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_4-1729ce33-b911-41f1-b325-edaff5f0cdff: buy 0 (t: 3, u: (0, 2.0), q: (1, 4))', 'partners': "['c_4-1729ce33-b911-41f1-b325-edaff5f0cdff', 'm_0-6a7c0ac4-5a18-4feb-bcc1-a5a67aa1e7c5']", 'seller': 'm_0-6a7c0ac4-5a18-4feb-bcc1-a5a67aa1e7c5', 'buyer': 'c_4-1729ce33-b911-41f1-b325-edaff5f0cdff'} 2019-02-27 11:34:09,680 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_1', 'm_0'] > {'time': 2, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_1-83f7bb54-0275-47dc-8c43-bd0e2b2744d4: buy 0 (t: 2, u: (0, 2.0), q: (1, 4))', 'partners': "['c_1-83f7bb54-0275-47dc-8c43-bd0e2b2744d4', 'm_0-6a7c0ac4-5a18-4feb-bcc1-a5a67aa1e7c5']", 'seller': 'm_0-6a7c0ac4-5a18-4feb-bcc1-a5a67aa1e7c5', 'buyer': 'c_1-83f7bb54-0275-47dc-8c43-bd0e2b2744d4'} 2019-02-27 11:34:09,680 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_0', 'm_2'] > {'time': 1, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_0-849400ab-19ff-42fa-bf65-10ef2f795a6f: buy 0 (t: 1, u: (0, 2.0), q: (1, 3))', 'partners': "['c_0-849400ab-19ff-42fa-bf65-10ef2f795a6f', 'm_2-577afd33-5aed-4647-8f4a-17a41dca4d54']", 'seller': 'm_2-577afd33-5aed-4647-8f4a-17a41dca4d54', 'buyer': 'c_0-849400ab-19ff-42fa-bf65-10ef2f795a6f'} 2019-02-27 11:34:09,681 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_4', 'm_1'] > {'time': 4, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_4-1729ce33-b911-41f1-b325-edaff5f0cdff: buy 0 (t: 4, u: (0, 2.0), q: (1, 3))', 'partners': "['c_4-1729ce33-b911-41f1-b325-edaff5f0cdff', 'm_1-02672ede-8506-42d2-9911-04211fcde6e5']", 'seller': 'm_1-02672ede-8506-42d2-9911-04211fcde6e5', 'buyer': 'c_4-1729ce33-b911-41f1-b325-edaff5f0cdff'} 2019-02-27 11:34:09,681 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_0', 'm_3'] > {'time': 2, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_0-849400ab-19ff-42fa-bf65-10ef2f795a6f: buy 0 (t: 2, u: (0, 2.0), q: (1, 3))', 'partners': "['c_0-849400ab-19ff-42fa-bf65-10ef2f795a6f', 'm_3-dcea5638-aed1-4f6b-bf21-1a67e1bdefbd']", 'seller': 'm_3-dcea5638-aed1-4f6b-bf21-1a67e1bdefbd', 'buyer': 'c_0-849400ab-19ff-42fa-bf65-10ef2f795a6f'} 2019-02-27 11:34:09,681 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_1', 'm_0'] > {'time': 3, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_1-83f7bb54-0275-47dc-8c43-bd0e2b2744d4: buy 0 (t: 3, u: (0, 2.0), q: (1, 4))', 'partners': "['c_1-83f7bb54-0275-47dc-8c43-bd0e2b2744d4', 'm_0-6a7c0ac4-5a18-4feb-bcc1-a5a67aa1e7c5']", 'seller': 'm_0-6a7c0ac4-5a18-4feb-bcc1-a5a67aa1e7c5', 'buyer': 'c_1-83f7bb54-0275-47dc-8c43-bd0e2b2744d4'} 2019-02-27 11:34:09,682 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_3', 'm_3'] > {'time': 3, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_3-b37498e8-6619-4aec-b3a3-dd95bbefbb6d: buy 0 (t: 3, u: (0, 2.0), q: (1, 3))', 'partners': "['c_3-b37498e8-6619-4aec-b3a3-dd95bbefbb6d', 'm_3-dcea5638-aed1-4f6b-bf21-1a67e1bdefbd']", 'seller': 'm_3-dcea5638-aed1-4f6b-bf21-1a67e1bdefbd', 'buyer': 'c_3-b37498e8-6619-4aec-b3a3-dd95bbefbb6d'} 2019-02-27 11:34:09,682 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_4', 'm_1'] > {'time': 1, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_4-1729ce33-b911-41f1-b325-edaff5f0cdff: buy 0 (t: 1, u: (0, 2.0), q: (1, 3))', 'partners': "['c_4-1729ce33-b911-41f1-b325-edaff5f0cdff', 'm_1-02672ede-8506-42d2-9911-04211fcde6e5']", 'seller': 'm_1-02672ede-8506-42d2-9911-04211fcde6e5', 'buyer': 'c_4-1729ce33-b911-41f1-b325-edaff5f0cdff'} 2019-02-27 11:34:09,682 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_0', 'm_2'] > {'time': 3, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_0-849400ab-19ff-42fa-bf65-10ef2f795a6f: buy 0 (t: 3, u: (0, 2.0), q: (1, 3))', 'partners': "['c_0-849400ab-19ff-42fa-bf65-10ef2f795a6f', 'm_2-577afd33-5aed-4647-8f4a-17a41dca4d54']", 'seller': 'm_2-577afd33-5aed-4647-8f4a-17a41dca4d54', 'buyer': 'c_0-849400ab-19ff-42fa-bf65-10ef2f795a6f'} 2019-02-27 11:34:09,683 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_2', 'm_1'] > {'time': 1, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_2-04df9282-7b04-48c4-a56c-066f6691dd4e: buy 0 (t: 1, u: (0, 2.0), q: (1, 4))', 'partners': "['c_2-04df9282-7b04-48c4-a56c-066f6691dd4e', 'm_1-02672ede-8506-42d2-9911-04211fcde6e5']", 'seller': 'm_1-02672ede-8506-42d2-9911-04211fcde6e5', 'buyer': 'c_2-04df9282-7b04-48c4-a56c-066f6691dd4e'} 2019-02-27 11:34:09,683 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_0', 'm_0'] > {'time': 2, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_0-849400ab-19ff-42fa-bf65-10ef2f795a6f: buy 0 (t: 2, u: (0, 2.0), q: (1, 3))', 'partners': "['c_0-849400ab-19ff-42fa-bf65-10ef2f795a6f', 'm_0-6a7c0ac4-5a18-4feb-bcc1-a5a67aa1e7c5']", 'seller': 'm_0-6a7c0ac4-5a18-4feb-bcc1-a5a67aa1e7c5', 'buyer': 'c_0-849400ab-19ff-42fa-bf65-10ef2f795a6f'} 2019-02-27 11:34:09,683 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_3', 'm_0'] > {'time': 1, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_3-b37498e8-6619-4aec-b3a3-dd95bbefbb6d: buy 0 (t: 1, u: (0, 2.0), q: (1, 4))', 'partners': "['c_3-b37498e8-6619-4aec-b3a3-dd95bbefbb6d', 'm_0-6a7c0ac4-5a18-4feb-bcc1-a5a67aa1e7c5']", 'seller': 'm_0-6a7c0ac4-5a18-4feb-bcc1-a5a67aa1e7c5', 'buyer': 'c_3-b37498e8-6619-4aec-b3a3-dd95bbefbb6d'} 2019-02-27 11:34:09,684 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_3', 'm_1'] > {'time': 2, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_3-b37498e8-6619-4aec-b3a3-dd95bbefbb6d: buy 0 (t: 2, u: (0, 2.0), q: (1, 4))', 'partners': "['c_3-b37498e8-6619-4aec-b3a3-dd95bbefbb6d', 'm_1-02672ede-8506-42d2-9911-04211fcde6e5']", 'seller': 'm_1-02672ede-8506-42d2-9911-04211fcde6e5', 'buyer': 'c_3-b37498e8-6619-4aec-b3a3-dd95bbefbb6d'} 2019-02-27 11:34:09,684 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_3', 'm_4'] > {'time': 1, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_3-b37498e8-6619-4aec-b3a3-dd95bbefbb6d: buy 0 (t: 1, u: (0, 2.0), q: (1, 4))', 'partners': "['c_3-b37498e8-6619-4aec-b3a3-dd95bbefbb6d', 'm_4-eebf8ea6-43d6-4114-96fb-76507f40ec73']", 'seller': 'm_4-eebf8ea6-43d6-4114-96fb-76507f40ec73', 'buyer': 'c_3-b37498e8-6619-4aec-b3a3-dd95bbefbb6d'} 2019-02-27 11:34:09,684 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_0', 'm_4'] > {'time': 2, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_0-849400ab-19ff-42fa-bf65-10ef2f795a6f: buy 0 (t: 2, u: (0, 2.0), q: (1, 3))', 'partners': "['c_0-849400ab-19ff-42fa-bf65-10ef2f795a6f', 'm_4-eebf8ea6-43d6-4114-96fb-76507f40ec73']", 'seller': 'm_4-eebf8ea6-43d6-4114-96fb-76507f40ec73', 'buyer': 'c_0-849400ab-19ff-42fa-bf65-10ef2f795a6f'} 2019-02-27 11:34:09,684 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_0', 'm_1'] > {'time': 1, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_0-849400ab-19ff-42fa-bf65-10ef2f795a6f: buy 0 (t: 1, u: (0, 2.0), q: (1, 3))', 'partners': "['c_0-849400ab-19ff-42fa-bf65-10ef2f795a6f', 'm_1-02672ede-8506-42d2-9911-04211fcde6e5']", 'seller': 'm_1-02672ede-8506-42d2-9911-04211fcde6e5', 'buyer': 'c_0-849400ab-19ff-42fa-bf65-10ef2f795a6f'} 2019-02-27 11:34:09,685 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_0', 'm_1'] > {'time': 2, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_0-849400ab-19ff-42fa-bf65-10ef2f795a6f: buy 0 (t: 2, u: (0, 2.0), q: (1, 3))', 'partners': "['c_0-849400ab-19ff-42fa-bf65-10ef2f795a6f', 'm_1-02672ede-8506-42d2-9911-04211fcde6e5']", 'seller': 'm_1-02672ede-8506-42d2-9911-04211fcde6e5', 'buyer': 'c_0-849400ab-19ff-42fa-bf65-10ef2f795a6f'} 2019-02-27 11:34:09,685 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_3', 'm_2'] > {'time': 4, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_3-b37498e8-6619-4aec-b3a3-dd95bbefbb6d: buy 0 (t: 4, u: (0, 2.0), q: (1, 4))', 'partners': "['c_3-b37498e8-6619-4aec-b3a3-dd95bbefbb6d', 'm_2-577afd33-5aed-4647-8f4a-17a41dca4d54']", 'seller': 'm_2-577afd33-5aed-4647-8f4a-17a41dca4d54', 'buyer': 'c_3-b37498e8-6619-4aec-b3a3-dd95bbefbb6d'} 2019-02-27 11:34:09,685 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_3', 'm_1'] > {'time': 4, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_3-b37498e8-6619-4aec-b3a3-dd95bbefbb6d: buy 0 (t: 4, u: (0, 2.0), q: (1, 4))', 'partners': "['c_3-b37498e8-6619-4aec-b3a3-dd95bbefbb6d', 'm_1-02672ede-8506-42d2-9911-04211fcde6e5']", 'seller': 'm_1-02672ede-8506-42d2-9911-04211fcde6e5', 'buyer': 'c_3-b37498e8-6619-4aec-b3a3-dd95bbefbb6d'} 2019-02-27 11:34:09,686 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_0', 'm_0'] > {'time': 1, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_0-849400ab-19ff-42fa-bf65-10ef2f795a6f: buy 0 (t: 1, u: (0, 2.0), q: (1, 3))', 'partners': "['c_0-849400ab-19ff-42fa-bf65-10ef2f795a6f', 'm_0-6a7c0ac4-5a18-4feb-bcc1-a5a67aa1e7c5']", 'seller': 'm_0-6a7c0ac4-5a18-4feb-bcc1-a5a67aa1e7c5', 'buyer': 'c_0-849400ab-19ff-42fa-bf65-10ef2f795a6f'} 2019-02-27 11:34:09,686 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_1', 'm_0'] > {'time': 1, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_1-83f7bb54-0275-47dc-8c43-bd0e2b2744d4: buy 0 (t: 1, u: (0, 2.0), q: (1, 4))', 'partners': "['c_1-83f7bb54-0275-47dc-8c43-bd0e2b2744d4', 'm_0-6a7c0ac4-5a18-4feb-bcc1-a5a67aa1e7c5']", 'seller': 'm_0-6a7c0ac4-5a18-4feb-bcc1-a5a67aa1e7c5', 'buyer': 'c_1-83f7bb54-0275-47dc-8c43-bd0e2b2744d4'} 2019-02-27 11:34:09,686 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_4', 'm_4'] > {'time': 2, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_4-1729ce33-b911-41f1-b325-edaff5f0cdff: buy 0 (t: 2, u: (0, 2.0), q: (1, 3))', 'partners': "['c_4-1729ce33-b911-41f1-b325-edaff5f0cdff', 'm_4-eebf8ea6-43d6-4114-96fb-76507f40ec73']", 'seller': 'm_4-eebf8ea6-43d6-4114-96fb-76507f40ec73', 'buyer': 'c_4-1729ce33-b911-41f1-b325-edaff5f0cdff'} 2019-02-27 11:34:09,687 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_1', 'm_4'] > {'time': 3, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_1-83f7bb54-0275-47dc-8c43-bd0e2b2744d4: buy 0 (t: 3, u: (0, 2.0), q: (1, 4))', 'partners': "['c_1-83f7bb54-0275-47dc-8c43-bd0e2b2744d4', 'm_4-eebf8ea6-43d6-4114-96fb-76507f40ec73']", 'seller': 'm_4-eebf8ea6-43d6-4114-96fb-76507f40ec73', 'buyer': 'c_1-83f7bb54-0275-47dc-8c43-bd0e2b2744d4'} 2019-02-27 11:34:09,687 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_4', 'm_2'] > {'time': 1, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_4-1729ce33-b911-41f1-b325-edaff5f0cdff: buy 0 (t: 1, u: (0, 2.0), q: (1, 3))', 'partners': "['c_4-1729ce33-b911-41f1-b325-edaff5f0cdff', 'm_2-577afd33-5aed-4647-8f4a-17a41dca4d54']", 'seller': 'm_2-577afd33-5aed-4647-8f4a-17a41dca4d54', 'buyer': 'c_4-1729ce33-b911-41f1-b325-edaff5f0cdff'} 2019-02-27 11:34:09,687 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_3', 'm_1'] > {'time': 1, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_3-b37498e8-6619-4aec-b3a3-dd95bbefbb6d: buy 0 (t: 1, u: (0, 2.0), q: (1, 4))', 'partners': "['c_3-b37498e8-6619-4aec-b3a3-dd95bbefbb6d', 'm_1-02672ede-8506-42d2-9911-04211fcde6e5']", 'seller': 'm_1-02672ede-8506-42d2-9911-04211fcde6e5', 'buyer': 'c_3-b37498e8-6619-4aec-b3a3-dd95bbefbb6d'} 2019-02-27 11:34:09,688 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_1', 'm_3'] > {'time': 2, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_1-83f7bb54-0275-47dc-8c43-bd0e2b2744d4: buy 0 (t: 2, u: (0, 2.0), q: (1, 4))', 'partners': "['c_1-83f7bb54-0275-47dc-8c43-bd0e2b2744d4', 'm_3-dcea5638-aed1-4f6b-bf21-1a67e1bdefbd']", 'seller': 'm_3-dcea5638-aed1-4f6b-bf21-1a67e1bdefbd', 'buyer': 'c_1-83f7bb54-0275-47dc-8c43-bd0e2b2744d4'} 2019-02-27 11:34:09,688 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_1', 'm_1'] > {'time': 4, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_1-83f7bb54-0275-47dc-8c43-bd0e2b2744d4: buy 0 (t: 4, u: (0, 2.0), q: (1, 4))', 'partners': "['c_1-83f7bb54-0275-47dc-8c43-bd0e2b2744d4', 'm_1-02672ede-8506-42d2-9911-04211fcde6e5']", 'seller': 'm_1-02672ede-8506-42d2-9911-04211fcde6e5', 'buyer': 'c_1-83f7bb54-0275-47dc-8c43-bd0e2b2744d4'} 2019-02-27 11:34:09,688 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_1', 'm_0'] > {'time': 4, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_1-83f7bb54-0275-47dc-8c43-bd0e2b2744d4: buy 0 (t: 4, u: (0, 2.0), q: (1, 4))', 'partners': "['c_1-83f7bb54-0275-47dc-8c43-bd0e2b2744d4', 'm_0-6a7c0ac4-5a18-4feb-bcc1-a5a67aa1e7c5']", 'seller': 'm_0-6a7c0ac4-5a18-4feb-bcc1-a5a67aa1e7c5', 'buyer': 'c_1-83f7bb54-0275-47dc-8c43-bd0e2b2744d4'} 2019-02-27 11:34:09,688 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_2', 'm_0'] > {'time': 4, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_2-04df9282-7b04-48c4-a56c-066f6691dd4e: buy 0 (t: 4, u: (0, 2.0), q: (1, 4))', 'partners': "['c_2-04df9282-7b04-48c4-a56c-066f6691dd4e', 'm_0-6a7c0ac4-5a18-4feb-bcc1-a5a67aa1e7c5']", 'seller': 'm_0-6a7c0ac4-5a18-4feb-bcc1-a5a67aa1e7c5', 'buyer': 'c_2-04df9282-7b04-48c4-a56c-066f6691dd4e'} 2019-02-27 11:34:09,689 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_4', 'm_4'] > {'time': 4, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_4-1729ce33-b911-41f1-b325-edaff5f0cdff: buy 0 (t: 4, u: (0, 2.0), q: (1, 3))', 'partners': "['c_4-1729ce33-b911-41f1-b325-edaff5f0cdff', 'm_4-eebf8ea6-43d6-4114-96fb-76507f40ec73']", 'seller': 'm_4-eebf8ea6-43d6-4114-96fb-76507f40ec73', 'buyer': 'c_4-1729ce33-b911-41f1-b325-edaff5f0cdff'} 2019-02-27 11:34:09,689 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_3', 'm_0'] > {'time': 4, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_3-b37498e8-6619-4aec-b3a3-dd95bbefbb6d: buy 0 (t: 4, u: (0, 2.0), q: (1, 4))', 'partners': "['c_3-b37498e8-6619-4aec-b3a3-dd95bbefbb6d', 'm_0-6a7c0ac4-5a18-4feb-bcc1-a5a67aa1e7c5']", 'seller': 'm_0-6a7c0ac4-5a18-4feb-bcc1-a5a67aa1e7c5', 'buyer': 'c_3-b37498e8-6619-4aec-b3a3-dd95bbefbb6d'} 2019-02-27 11:34:09,689 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_0', 'm_1'] > {'time': 3, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_0-849400ab-19ff-42fa-bf65-10ef2f795a6f: buy 0 (t: 3, u: (0, 2.0), q: (1, 3))', 'partners': "['c_0-849400ab-19ff-42fa-bf65-10ef2f795a6f', 'm_1-02672ede-8506-42d2-9911-04211fcde6e5']", 'seller': 'm_1-02672ede-8506-42d2-9911-04211fcde6e5', 'buyer': 'c_0-849400ab-19ff-42fa-bf65-10ef2f795a6f'} 2019-02-27 11:34:09,690 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_0', 'm_1'] > {'time': 4, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_0-849400ab-19ff-42fa-bf65-10ef2f795a6f: buy 0 (t: 4, u: (0, 2.0), q: (1, 3))', 'partners': "['c_0-849400ab-19ff-42fa-bf65-10ef2f795a6f', 'm_1-02672ede-8506-42d2-9911-04211fcde6e5']", 'seller': 'm_1-02672ede-8506-42d2-9911-04211fcde6e5', 'buyer': 'c_0-849400ab-19ff-42fa-bf65-10ef2f795a6f'} 2019-02-27 11:34:09,690 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_2', 'm_2'] > {'time': 3, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_2-04df9282-7b04-48c4-a56c-066f6691dd4e: buy 0 (t: 3, u: (0, 2.0), q: (1, 4))', 'partners': "['c_2-04df9282-7b04-48c4-a56c-066f6691dd4e', 'm_2-577afd33-5aed-4647-8f4a-17a41dca4d54']", 'seller': 'm_2-577afd33-5aed-4647-8f4a-17a41dca4d54', 'buyer': 'c_2-04df9282-7b04-48c4-a56c-066f6691dd4e'} 2019-02-27 11:34:09,690 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_0', 'm_4'] > {'time': 1, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_0-849400ab-19ff-42fa-bf65-10ef2f795a6f: buy 0 (t: 1, u: (0, 2.0), q: (1, 3))', 'partners': "['c_0-849400ab-19ff-42fa-bf65-10ef2f795a6f', 'm_4-eebf8ea6-43d6-4114-96fb-76507f40ec73']", 'seller': 'm_4-eebf8ea6-43d6-4114-96fb-76507f40ec73', 'buyer': 'c_0-849400ab-19ff-42fa-bf65-10ef2f795a6f'} 2019-02-27 11:34:09,690 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_2', 'm_0'] > {'time': 3, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_2-04df9282-7b04-48c4-a56c-066f6691dd4e: buy 0 (t: 3, u: (0, 2.0), q: (1, 4))', 'partners': "['c_2-04df9282-7b04-48c4-a56c-066f6691dd4e', 'm_0-6a7c0ac4-5a18-4feb-bcc1-a5a67aa1e7c5']", 'seller': 'm_0-6a7c0ac4-5a18-4feb-bcc1-a5a67aa1e7c5', 'buyer': 'c_2-04df9282-7b04-48c4-a56c-066f6691dd4e'} 2019-02-27 11:34:09,691 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_2', 'm_2'] > {'time': 2, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_2-04df9282-7b04-48c4-a56c-066f6691dd4e: buy 0 (t: 2, u: (0, 2.0), q: (1, 3))', 'partners': "['c_2-04df9282-7b04-48c4-a56c-066f6691dd4e', 'm_2-577afd33-5aed-4647-8f4a-17a41dca4d54']", 'seller': 'm_2-577afd33-5aed-4647-8f4a-17a41dca4d54', 'buyer': 'c_2-04df9282-7b04-48c4-a56c-066f6691dd4e'} 2019-02-27 11:34:09,691 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_2', 'm_2'] > {'time': 1, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_2-04df9282-7b04-48c4-a56c-066f6691dd4e: buy 0 (t: 1, u: (0, 2.0), q: (1, 4))', 'partners': "['c_2-04df9282-7b04-48c4-a56c-066f6691dd4e', 'm_2-577afd33-5aed-4647-8f4a-17a41dca4d54']", 'seller': 'm_2-577afd33-5aed-4647-8f4a-17a41dca4d54', 'buyer': 'c_2-04df9282-7b04-48c4-a56c-066f6691dd4e'} 2019-02-27 11:34:09,691 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_0', 'm_3'] > {'time': 3, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_0-849400ab-19ff-42fa-bf65-10ef2f795a6f: buy 0 (t: 3, u: (0, 2.0), q: (1, 3))', 'partners': "['c_0-849400ab-19ff-42fa-bf65-10ef2f795a6f', 'm_3-dcea5638-aed1-4f6b-bf21-1a67e1bdefbd']", 'seller': 'm_3-dcea5638-aed1-4f6b-bf21-1a67e1bdefbd', 'buyer': 'c_0-849400ab-19ff-42fa-bf65-10ef2f795a6f'} 2019-02-27 11:34:09,692 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_2', 'm_0'] > {'time': 2, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_2-04df9282-7b04-48c4-a56c-066f6691dd4e: buy 0 (t: 2, u: (0, 2.0), q: (1, 3))', 'partners': "['c_2-04df9282-7b04-48c4-a56c-066f6691dd4e', 'm_0-6a7c0ac4-5a18-4feb-bcc1-a5a67aa1e7c5']", 'seller': 'm_0-6a7c0ac4-5a18-4feb-bcc1-a5a67aa1e7c5', 'buyer': 'c_2-04df9282-7b04-48c4-a56c-066f6691dd4e'} 2019-02-27 11:34:09,692 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_2', 'm_3'] > {'time': 4, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_2-04df9282-7b04-48c4-a56c-066f6691dd4e: buy 0 (t: 4, u: (0, 2.0), q: (1, 4))', 'partners': "['c_2-04df9282-7b04-48c4-a56c-066f6691dd4e', 'm_3-dcea5638-aed1-4f6b-bf21-1a67e1bdefbd']", 'seller': 'm_3-dcea5638-aed1-4f6b-bf21-1a67e1bdefbd', 'buyer': 'c_2-04df9282-7b04-48c4-a56c-066f6691dd4e'} 2019-02-27 11:34:09,692 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_4', 'm_3'] > {'time': 3, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_4-1729ce33-b911-41f1-b325-edaff5f0cdff: buy 0 (t: 3, u: (0, 2.0), q: (1, 4))', 'partners': "['c_4-1729ce33-b911-41f1-b325-edaff5f0cdff', 'm_3-dcea5638-aed1-4f6b-bf21-1a67e1bdefbd']", 'seller': 'm_3-dcea5638-aed1-4f6b-bf21-1a67e1bdefbd', 'buyer': 'c_4-1729ce33-b911-41f1-b325-edaff5f0cdff'} 2019-02-27 11:34:09,693 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_0', 'm_3'] > {'time': 4, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_0-849400ab-19ff-42fa-bf65-10ef2f795a6f: buy 0 (t: 4, u: (0, 2.0), q: (1, 3))', 'partners': "['c_0-849400ab-19ff-42fa-bf65-10ef2f795a6f', 'm_3-dcea5638-aed1-4f6b-bf21-1a67e1bdefbd']", 'seller': 'm_3-dcea5638-aed1-4f6b-bf21-1a67e1bdefbd', 'buyer': 'c_0-849400ab-19ff-42fa-bf65-10ef2f795a6f'} 2019-02-27 11:34:09,693 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_4', 'm_4'] > {'time': 1, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_4-1729ce33-b911-41f1-b325-edaff5f0cdff: buy 0 (t: 1, u: (0, 2.0), q: (1, 3))', 'partners': "['c_4-1729ce33-b911-41f1-b325-edaff5f0cdff', 'm_4-eebf8ea6-43d6-4114-96fb-76507f40ec73']", 'seller': 'm_4-eebf8ea6-43d6-4114-96fb-76507f40ec73', 'buyer': 'c_4-1729ce33-b911-41f1-b325-edaff5f0cdff'} 2019-02-27 11:34:09,693 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_3', 'm_3'] > {'time': 2, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_3-b37498e8-6619-4aec-b3a3-dd95bbefbb6d: buy 0 (t: 2, u: (0, 2.0), q: (1, 4))', 'partners': "['c_3-b37498e8-6619-4aec-b3a3-dd95bbefbb6d', 'm_3-dcea5638-aed1-4f6b-bf21-1a67e1bdefbd']", 'seller': 'm_3-dcea5638-aed1-4f6b-bf21-1a67e1bdefbd', 'buyer': 'c_3-b37498e8-6619-4aec-b3a3-dd95bbefbb6d'} 2019-02-27 11:34:09,694 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_1', 'm_3'] > {'time': 3, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_1-83f7bb54-0275-47dc-8c43-bd0e2b2744d4: buy 0 (t: 3, u: (0, 2.0), q: (1, 4))', 'partners': "['c_1-83f7bb54-0275-47dc-8c43-bd0e2b2744d4', 'm_3-dcea5638-aed1-4f6b-bf21-1a67e1bdefbd']", 'seller': 'm_3-dcea5638-aed1-4f6b-bf21-1a67e1bdefbd', 'buyer': 'c_1-83f7bb54-0275-47dc-8c43-bd0e2b2744d4'} 2019-02-27 11:34:09,694 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_1', 'm_1'] > {'time': 1, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_1-83f7bb54-0275-47dc-8c43-bd0e2b2744d4: buy 0 (t: 1, u: (0, 2.0), q: (1, 4))', 'partners': "['c_1-83f7bb54-0275-47dc-8c43-bd0e2b2744d4', 'm_1-02672ede-8506-42d2-9911-04211fcde6e5']", 'seller': 'm_1-02672ede-8506-42d2-9911-04211fcde6e5', 'buyer': 'c_1-83f7bb54-0275-47dc-8c43-bd0e2b2744d4'} 2019-02-27 11:34:09,694 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_4', 'm_3'] > {'time': 1, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_4-1729ce33-b911-41f1-b325-edaff5f0cdff: buy 0 (t: 1, u: (0, 2.0), q: (1, 3))', 'partners': "['c_4-1729ce33-b911-41f1-b325-edaff5f0cdff', 'm_3-dcea5638-aed1-4f6b-bf21-1a67e1bdefbd']", 'seller': 'm_3-dcea5638-aed1-4f6b-bf21-1a67e1bdefbd', 'buyer': 'c_4-1729ce33-b911-41f1-b325-edaff5f0cdff'} 2019-02-27 11:34:09,695 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_4', 'm_0'] > {'time': 1, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_4-1729ce33-b911-41f1-b325-edaff5f0cdff: buy 0 (t: 1, u: (0, 2.0), q: (1, 3))', 'partners': "['c_4-1729ce33-b911-41f1-b325-edaff5f0cdff', 'm_0-6a7c0ac4-5a18-4feb-bcc1-a5a67aa1e7c5']", 'seller': 'm_0-6a7c0ac4-5a18-4feb-bcc1-a5a67aa1e7c5', 'buyer': 'c_4-1729ce33-b911-41f1-b325-edaff5f0cdff'} 2019-02-27 11:34:09,695 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_2', 'm_1'] > {'time': 3, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_2-04df9282-7b04-48c4-a56c-066f6691dd4e: buy 0 (t: 3, u: (0, 2.0), q: (1, 4))', 'partners': "['c_2-04df9282-7b04-48c4-a56c-066f6691dd4e', 'm_1-02672ede-8506-42d2-9911-04211fcde6e5']", 'seller': 'm_1-02672ede-8506-42d2-9911-04211fcde6e5', 'buyer': 'c_2-04df9282-7b04-48c4-a56c-066f6691dd4e'} 2019-02-27 11:34:09,695 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_0', 'm_0'] > {'time': 4, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_0-849400ab-19ff-42fa-bf65-10ef2f795a6f: buy 0 (t: 4, u: (0, 2.0), q: (1, 3))', 'partners': "['c_0-849400ab-19ff-42fa-bf65-10ef2f795a6f', 'm_0-6a7c0ac4-5a18-4feb-bcc1-a5a67aa1e7c5']", 'seller': 'm_0-6a7c0ac4-5a18-4feb-bcc1-a5a67aa1e7c5', 'buyer': 'c_0-849400ab-19ff-42fa-bf65-10ef2f795a6f'} 2019-02-27 11:34:09,695 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_4', 'm_4'] > {'time': 3, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_4-1729ce33-b911-41f1-b325-edaff5f0cdff: buy 0 (t: 3, u: (0, 2.0), q: (1, 4))', 'partners': "['c_4-1729ce33-b911-41f1-b325-edaff5f0cdff', 'm_4-eebf8ea6-43d6-4114-96fb-76507f40ec73']", 'seller': 'm_4-eebf8ea6-43d6-4114-96fb-76507f40ec73', 'buyer': 'c_4-1729ce33-b911-41f1-b325-edaff5f0cdff'} 2019-02-27 11:34:09,696 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_2', 'm_4'] > {'time': 4, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_2-04df9282-7b04-48c4-a56c-066f6691dd4e: buy 0 (t: 4, u: (0, 2.0), q: (1, 4))', 'partners': "['c_2-04df9282-7b04-48c4-a56c-066f6691dd4e', 'm_4-eebf8ea6-43d6-4114-96fb-76507f40ec73']", 'seller': 'm_4-eebf8ea6-43d6-4114-96fb-76507f40ec73', 'buyer': 'c_2-04df9282-7b04-48c4-a56c-066f6691dd4e'} 2019-02-27 11:34:09,696 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_1', 'm_1'] > {'time': 2, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_1-83f7bb54-0275-47dc-8c43-bd0e2b2744d4: buy 0 (t: 2, u: (0, 2.0), q: (1, 4))', 'partners': "['c_1-83f7bb54-0275-47dc-8c43-bd0e2b2744d4', 'm_1-02672ede-8506-42d2-9911-04211fcde6e5']", 'seller': 'm_1-02672ede-8506-42d2-9911-04211fcde6e5', 'buyer': 'c_1-83f7bb54-0275-47dc-8c43-bd0e2b2744d4'} 2019-02-27 11:34:09,696 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_2', 'm_1'] > {'time': 2, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_2-04df9282-7b04-48c4-a56c-066f6691dd4e: buy 0 (t: 2, u: (0, 2.0), q: (1, 3))', 'partners': "['c_2-04df9282-7b04-48c4-a56c-066f6691dd4e', 'm_1-02672ede-8506-42d2-9911-04211fcde6e5']", 'seller': 'm_1-02672ede-8506-42d2-9911-04211fcde6e5', 'buyer': 'c_2-04df9282-7b04-48c4-a56c-066f6691dd4e'} 2019-02-27 11:34:09,697 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_0', 'm_2'] > {'time': 2, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_0-849400ab-19ff-42fa-bf65-10ef2f795a6f: buy 0 (t: 2, u: (0, 2.0), q: (1, 3))', 'partners': "['c_0-849400ab-19ff-42fa-bf65-10ef2f795a6f', 'm_2-577afd33-5aed-4647-8f4a-17a41dca4d54']", 'seller': 'm_2-577afd33-5aed-4647-8f4a-17a41dca4d54', 'buyer': 'c_0-849400ab-19ff-42fa-bf65-10ef2f795a6f'} 2019-02-27 11:34:09,697 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_2', 'm_1'] > {'time': 4, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_2-04df9282-7b04-48c4-a56c-066f6691dd4e: buy 0 (t: 4, u: (0, 2.0), q: (1, 4))', 'partners': "['c_2-04df9282-7b04-48c4-a56c-066f6691dd4e', 'm_1-02672ede-8506-42d2-9911-04211fcde6e5']", 'seller': 'm_1-02672ede-8506-42d2-9911-04211fcde6e5', 'buyer': 'c_2-04df9282-7b04-48c4-a56c-066f6691dd4e'} 2019-02-27 11:34:09,697 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_4', 'm_2'] > {'time': 3, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_4-1729ce33-b911-41f1-b325-edaff5f0cdff: buy 0 (t: 3, u: (0, 2.0), q: (1, 4))', 'partners': "['c_4-1729ce33-b911-41f1-b325-edaff5f0cdff', 'm_2-577afd33-5aed-4647-8f4a-17a41dca4d54']", 'seller': 'm_2-577afd33-5aed-4647-8f4a-17a41dca4d54', 'buyer': 'c_4-1729ce33-b911-41f1-b325-edaff5f0cdff'} 2019-02-27 11:34:09,697 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_4', 'm_0'] > {'time': 2, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_4-1729ce33-b911-41f1-b325-edaff5f0cdff: buy 0 (t: 2, u: (0, 2.0), q: (1, 3))', 'partners': "['c_4-1729ce33-b911-41f1-b325-edaff5f0cdff', 'm_0-6a7c0ac4-5a18-4feb-bcc1-a5a67aa1e7c5']", 'seller': 'm_0-6a7c0ac4-5a18-4feb-bcc1-a5a67aa1e7c5', 'buyer': 'c_4-1729ce33-b911-41f1-b325-edaff5f0cdff'} 2019-02-27 11:34:09,698 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_3', 'm_0'] > {'time': 3, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_3-b37498e8-6619-4aec-b3a3-dd95bbefbb6d: buy 0 (t: 3, u: (0, 2.0), q: (1, 3))', 'partners': "['c_3-b37498e8-6619-4aec-b3a3-dd95bbefbb6d', 'm_0-6a7c0ac4-5a18-4feb-bcc1-a5a67aa1e7c5']", 'seller': 'm_0-6a7c0ac4-5a18-4feb-bcc1-a5a67aa1e7c5', 'buyer': 'c_3-b37498e8-6619-4aec-b3a3-dd95bbefbb6d'} 2019-02-27 11:34:09,698 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_2', 'm_3'] > {'time': 1, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_2-04df9282-7b04-48c4-a56c-066f6691dd4e: buy 0 (t: 1, u: (0, 2.0), q: (1, 4))', 'partners': "['c_2-04df9282-7b04-48c4-a56c-066f6691dd4e', 'm_3-dcea5638-aed1-4f6b-bf21-1a67e1bdefbd']", 'seller': 'm_3-dcea5638-aed1-4f6b-bf21-1a67e1bdefbd', 'buyer': 'c_2-04df9282-7b04-48c4-a56c-066f6691dd4e'} 2019-02-27 11:34:09,698 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_3', 'm_4'] > {'time': 4, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_3-b37498e8-6619-4aec-b3a3-dd95bbefbb6d: buy 0 (t: 4, u: (0, 2.0), q: (1, 4))', 'partners': "['c_3-b37498e8-6619-4aec-b3a3-dd95bbefbb6d', 'm_4-eebf8ea6-43d6-4114-96fb-76507f40ec73']", 'seller': 'm_4-eebf8ea6-43d6-4114-96fb-76507f40ec73', 'buyer': 'c_3-b37498e8-6619-4aec-b3a3-dd95bbefbb6d'} 2019-02-27 11:34:09,699 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_1', 'm_4'] > {'time': 4, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_1-83f7bb54-0275-47dc-8c43-bd0e2b2744d4: buy 0 (t: 4, u: (0, 2.0), q: (1, 4))', 'partners': "['c_1-83f7bb54-0275-47dc-8c43-bd0e2b2744d4', 'm_4-eebf8ea6-43d6-4114-96fb-76507f40ec73']", 'seller': 'm_4-eebf8ea6-43d6-4114-96fb-76507f40ec73', 'buyer': 'c_1-83f7bb54-0275-47dc-8c43-bd0e2b2744d4'} 2019-02-27 11:34:09,699 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_1', 'm_3'] > {'time': 1, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_1-83f7bb54-0275-47dc-8c43-bd0e2b2744d4: buy 0 (t: 1, u: (0, 2.0), q: (1, 4))', 'partners': "['c_1-83f7bb54-0275-47dc-8c43-bd0e2b2744d4', 'm_3-dcea5638-aed1-4f6b-bf21-1a67e1bdefbd']", 'seller': 'm_3-dcea5638-aed1-4f6b-bf21-1a67e1bdefbd', 'buyer': 'c_1-83f7bb54-0275-47dc-8c43-bd0e2b2744d4'} 2019-02-27 11:34:09,699 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_2', 'm_2'] > {'time': 4, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_2-04df9282-7b04-48c4-a56c-066f6691dd4e: buy 0 (t: 4, u: (0, 2.0), q: (1, 4))', 'partners': "['c_2-04df9282-7b04-48c4-a56c-066f6691dd4e', 'm_2-577afd33-5aed-4647-8f4a-17a41dca4d54']", 'seller': 'm_2-577afd33-5aed-4647-8f4a-17a41dca4d54', 'buyer': 'c_2-04df9282-7b04-48c4-a56c-066f6691dd4e'} 2019-02-27 11:34:09,700 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_3', 'm_3'] > {'time': 1, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_3-b37498e8-6619-4aec-b3a3-dd95bbefbb6d: buy 0 (t: 1, u: (0, 2.0), q: (1, 4))', 'partners': "['c_3-b37498e8-6619-4aec-b3a3-dd95bbefbb6d', 'm_3-dcea5638-aed1-4f6b-bf21-1a67e1bdefbd']", 'seller': 'm_3-dcea5638-aed1-4f6b-bf21-1a67e1bdefbd', 'buyer': 'c_3-b37498e8-6619-4aec-b3a3-dd95bbefbb6d'} 2019-02-27 11:34:09,700 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_4', 'm_0'] > {'time': 4, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_4-1729ce33-b911-41f1-b325-edaff5f0cdff: buy 0 (t: 4, u: (0, 2.0), q: (1, 3))', 'partners': "['c_4-1729ce33-b911-41f1-b325-edaff5f0cdff', 'm_0-6a7c0ac4-5a18-4feb-bcc1-a5a67aa1e7c5']", 'seller': 'm_0-6a7c0ac4-5a18-4feb-bcc1-a5a67aa1e7c5', 'buyer': 'c_4-1729ce33-b911-41f1-b325-edaff5f0cdff'} 2019-02-27 11:34:09,700 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_3', 'm_4'] > {'time': 3, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_3-b37498e8-6619-4aec-b3a3-dd95bbefbb6d: buy 0 (t: 3, u: (0, 2.0), q: (1, 3))', 'partners': "['c_3-b37498e8-6619-4aec-b3a3-dd95bbefbb6d', 'm_4-eebf8ea6-43d6-4114-96fb-76507f40ec73']", 'seller': 'm_4-eebf8ea6-43d6-4114-96fb-76507f40ec73', 'buyer': 'c_3-b37498e8-6619-4aec-b3a3-dd95bbefbb6d'} 2019-02-27 11:34:09,700 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_4', 'm_2'] > {'time': 2, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_4-1729ce33-b911-41f1-b325-edaff5f0cdff: buy 0 (t: 2, u: (0, 2.0), q: (1, 3))', 'partners': "['c_4-1729ce33-b911-41f1-b325-edaff5f0cdff', 'm_2-577afd33-5aed-4647-8f4a-17a41dca4d54']", 'seller': 'm_2-577afd33-5aed-4647-8f4a-17a41dca4d54', 'buyer': 'c_4-1729ce33-b911-41f1-b325-edaff5f0cdff'} 2019-02-27 11:34:09,701 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_2', 'm_4'] > {'time': 1, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_2-04df9282-7b04-48c4-a56c-066f6691dd4e: buy 0 (t: 1, u: (0, 2.0), q: (1, 4))', 'partners': "['c_2-04df9282-7b04-48c4-a56c-066f6691dd4e', 'm_4-eebf8ea6-43d6-4114-96fb-76507f40ec73']", 'seller': 'm_4-eebf8ea6-43d6-4114-96fb-76507f40ec73', 'buyer': 'c_2-04df9282-7b04-48c4-a56c-066f6691dd4e'} 2019-02-27 11:34:09,701 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_2', 'm_0'] > {'time': 1, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_2-04df9282-7b04-48c4-a56c-066f6691dd4e: buy 0 (t: 1, u: (0, 2.0), q: (1, 4))', 'partners': "['c_2-04df9282-7b04-48c4-a56c-066f6691dd4e', 'm_0-6a7c0ac4-5a18-4feb-bcc1-a5a67aa1e7c5']", 'seller': 'm_0-6a7c0ac4-5a18-4feb-bcc1-a5a67aa1e7c5', 'buyer': 'c_2-04df9282-7b04-48c4-a56c-066f6691dd4e'} 2019-02-27 11:34:09,701 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_1', 'm_2'] > {'time': 4, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_1-83f7bb54-0275-47dc-8c43-bd0e2b2744d4: buy 0 (t: 4, u: (0, 2.0), q: (1, 4))', 'partners': "['c_1-83f7bb54-0275-47dc-8c43-bd0e2b2744d4', 'm_2-577afd33-5aed-4647-8f4a-17a41dca4d54']", 'seller': 'm_2-577afd33-5aed-4647-8f4a-17a41dca4d54', 'buyer': 'c_1-83f7bb54-0275-47dc-8c43-bd0e2b2744d4'} 2019-02-27 11:34:09,702 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_2', 'm_3'] > {'time': 3, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_2-04df9282-7b04-48c4-a56c-066f6691dd4e: buy 0 (t: 3, u: (0, 2.0), q: (1, 4))', 'partners': "['c_2-04df9282-7b04-48c4-a56c-066f6691dd4e', 'm_3-dcea5638-aed1-4f6b-bf21-1a67e1bdefbd']", 'seller': 'm_3-dcea5638-aed1-4f6b-bf21-1a67e1bdefbd', 'buyer': 'c_2-04df9282-7b04-48c4-a56c-066f6691dd4e'} 2019-02-27 11:34:09,702 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_2', 'm_4'] > {'time': 3, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_2-04df9282-7b04-48c4-a56c-066f6691dd4e: buy 0 (t: 3, u: (0, 2.0), q: (1, 4))', 'partners': "['c_2-04df9282-7b04-48c4-a56c-066f6691dd4e', 'm_4-eebf8ea6-43d6-4114-96fb-76507f40ec73']", 'seller': 'm_4-eebf8ea6-43d6-4114-96fb-76507f40ec73', 'buyer': 'c_2-04df9282-7b04-48c4-a56c-066f6691dd4e'} 2019-02-27 11:34:09,702 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_2', 'm_4'] > {'time': 2, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_2-04df9282-7b04-48c4-a56c-066f6691dd4e: buy 0 (t: 2, u: (0, 2.0), q: (1, 3))', 'partners': "['c_2-04df9282-7b04-48c4-a56c-066f6691dd4e', 'm_4-eebf8ea6-43d6-4114-96fb-76507f40ec73']", 'seller': 'm_4-eebf8ea6-43d6-4114-96fb-76507f40ec73', 'buyer': 'c_2-04df9282-7b04-48c4-a56c-066f6691dd4e'} 2019-02-27 11:34:09,703 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_1', 'm_1'] > {'time': 3, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_1-83f7bb54-0275-47dc-8c43-bd0e2b2744d4: buy 0 (t: 3, u: (0, 2.0), q: (1, 4))', 'partners': "['c_1-83f7bb54-0275-47dc-8c43-bd0e2b2744d4', 'm_1-02672ede-8506-42d2-9911-04211fcde6e5']", 'seller': 'm_1-02672ede-8506-42d2-9911-04211fcde6e5', 'buyer': 'c_1-83f7bb54-0275-47dc-8c43-bd0e2b2744d4'} 2019-02-27 11:34:09,703 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_3', 'm_1'] > {'time': 3, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_3-b37498e8-6619-4aec-b3a3-dd95bbefbb6d: buy 0 (t: 3, u: (0, 2.0), q: (1, 3))', 'partners': "['c_3-b37498e8-6619-4aec-b3a3-dd95bbefbb6d', 'm_1-02672ede-8506-42d2-9911-04211fcde6e5']", 'seller': 'm_1-02672ede-8506-42d2-9911-04211fcde6e5', 'buyer': 'c_3-b37498e8-6619-4aec-b3a3-dd95bbefbb6d'} 2019-02-27 11:34:09,703 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_3', 'm_0'] > {'time': 2, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_3-b37498e8-6619-4aec-b3a3-dd95bbefbb6d: buy 0 (t: 2, u: (0, 2.0), q: (1, 4))', 'partners': "['c_3-b37498e8-6619-4aec-b3a3-dd95bbefbb6d', 'm_0-6a7c0ac4-5a18-4feb-bcc1-a5a67aa1e7c5']", 'seller': 'm_0-6a7c0ac4-5a18-4feb-bcc1-a5a67aa1e7c5', 'buyer': 'c_3-b37498e8-6619-4aec-b3a3-dd95bbefbb6d'} 2019-02-27 11:34:09,704 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_4', 'm_1'] > {'time': 3, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_4-1729ce33-b911-41f1-b325-edaff5f0cdff: buy 0 (t: 3, u: (0, 2.0), q: (1, 4))', 'partners': "['c_4-1729ce33-b911-41f1-b325-edaff5f0cdff', 'm_1-02672ede-8506-42d2-9911-04211fcde6e5']", 'seller': 'm_1-02672ede-8506-42d2-9911-04211fcde6e5', 'buyer': 'c_4-1729ce33-b911-41f1-b325-edaff5f0cdff'} 2019-02-27 11:34:09,704 - DEBUG - 1/10 [20.00%]: Contract [to be signed at 2]: ['c_0', 'm_4'] > {'time': 3, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_0-849400ab-19ff-42fa-bf65-10ef2f795a6f: buy 0 (t: 3, u: (0, 2.0), q: (1, 3))', 'partners': "['c_0-849400ab-19ff-42fa-bf65-10ef2f795a6f', 'm_4-eebf8ea6-43d6-4114-96fb-76507f40ec73']", 'seller': 'm_4-eebf8ea6-43d6-4114-96fb-76507f40ec73', 'buyer': 'c_0-849400ab-19ff-42fa-bf65-10ef2f795a6f'} 2019-02-27 11:34:09,706 - INFO - 1/10 [20.00%]: m_0 requested negmas.sao.SAOMechanism[None] with ['c_1', 'm_0'] (ID 97093394-6859-46bb-9882-e0fac9a986b1) 2019-02-27 11:34:09,707 - INFO - 1/10 [20.00%]: m_0-6a7c0ac4-5a18-4feb-bcc1-a5a67aa1e7c5 request was accepted 2019-02-27 11:34:09,707 - INFO - 1/10 [20.00%]: m_1 requested negmas.sao.SAOMechanism[None] with ['c_1', 'm_1'] (ID 38426163-95b0-45d1-a9f2-de37b3d15e89) 2019-02-27 11:34:09,708 - INFO - 1/10 [20.00%]: m_1-02672ede-8506-42d2-9911-04211fcde6e5 request was accepted 2019-02-27 11:34:09,709 - INFO - 1/10 [20.00%]: m_2 requested negmas.sao.SAOMechanism[None] with ['c_1', 'm_2'] (ID 5fa50d4c-02d8-4f6f-b374-0d03b9e2b01f) 2019-02-27 11:34:09,709 - INFO - 1/10 [20.00%]: m_2-577afd33-5aed-4647-8f4a-17a41dca4d54 request was accepted 2019-02-27 11:34:09,710 - INFO - 1/10 [20.00%]: m_3 requested negmas.sao.SAOMechanism[None] with ['c_1', 'm_3'] (ID c04c4980-88b6-49b3-8b3d-dca9f095a806) 2019-02-27 11:34:09,711 - INFO - 1/10 [20.00%]: m_3-dcea5638-aed1-4f6b-bf21-1a67e1bdefbd request was accepted 2019-02-27 11:34:09,712 - INFO - 1/10 [20.00%]: m_4 requested negmas.sao.SAOMechanism[None] with ['c_1', 'm_4'] (ID 453d51fe-a217-4838-8209-c8a819121832) 2019-02-27 11:34:09,712 - INFO - 1/10 [20.00%]: m_4-eebf8ea6-43d6-4114-96fb-76507f40ec73 request was accepted 2019-02-27 11:34:09,714 - INFO - 1/10 [20.00%]: m_0 requested negmas.sao.SAOMechanism[None] with ['c_3', 'm_0'] (ID e6c9e862-87a0-49ab-8d1b-3ecaa9962e3f) 2019-02-27 11:34:09,715 - INFO - 1/10 [20.00%]: m_0-6a7c0ac4-5a18-4feb-bcc1-a5a67aa1e7c5 request was accepted 2019-02-27 11:34:09,716 - INFO - 1/10 [20.00%]: m_1 requested negmas.sao.SAOMechanism[None] with ['c_3', 'm_1'] (ID 126bb74c-a68a-4f11-b7a3-c9eb3bcbf5a5) 2019-02-27 11:34:09,717 - INFO - 1/10 [20.00%]: m_1-02672ede-8506-42d2-9911-04211fcde6e5 request was accepted 2019-02-27 11:34:09,718 - INFO - 1/10 [20.00%]: m_2 requested negmas.sao.SAOMechanism[None] with ['c_3', 'm_2'] (ID 6061bf11-a60e-4984-b19b-78c89429bc78) 2019-02-27 11:34:09,719 - INFO - 1/10 [20.00%]: m_2-577afd33-5aed-4647-8f4a-17a41dca4d54 request was accepted 2019-02-27 11:34:09,720 - INFO - 1/10 [20.00%]: m_3 requested negmas.sao.SAOMechanism[None] with ['c_3', 'm_3'] (ID 113041a2-123a-4082-9f42-ee9c5476619a) 2019-02-27 11:34:09,720 - INFO - 1/10 [20.00%]: m_3-dcea5638-aed1-4f6b-bf21-1a67e1bdefbd request was accepted 2019-02-27 11:34:09,721 - INFO - 1/10 [20.00%]: m_4 requested negmas.sao.SAOMechanism[None] with ['c_3', 'm_4'] (ID c8bcd0f3-d301-4818-860a-f5422fefcd5d) 2019-02-27 11:34:09,722 - INFO - 1/10 [20.00%]: m_4-eebf8ea6-43d6-4114-96fb-76507f40ec73 request was accepted 2019-02-27 11:34:09,724 - INFO - 1/10 [20.00%]: m_0 requested negmas.sao.SAOMechanism[None] with ['c_0', 'm_0'] (ID 4de88e4b-dd42-47d1-b567-ae56f9a6facc) 2019-02-27 11:34:09,724 - INFO - 1/10 [20.00%]: m_0-6a7c0ac4-5a18-4feb-bcc1-a5a67aa1e7c5 request was accepted 2019-02-27 11:34:09,725 - INFO - 1/10 [20.00%]: m_1 requested negmas.sao.SAOMechanism[None] with ['c_0', 'm_1'] (ID 2f9708b5-f1a9-449a-bb09-c9090c1ee149) 2019-02-27 11:34:09,726 - INFO - 1/10 [20.00%]: m_1-02672ede-8506-42d2-9911-04211fcde6e5 request was accepted 2019-02-27 11:34:09,727 - INFO - 1/10 [20.00%]: m_2 requested negmas.sao.SAOMechanism[None] with ['c_0', 'm_2'] (ID f3c58741-0939-4ef6-8fb0-ed6e5f3fc7bd) 2019-02-27 11:34:09,727 - INFO - 1/10 [20.00%]: m_2-577afd33-5aed-4647-8f4a-17a41dca4d54 request was accepted 2019-02-27 11:34:09,728 - INFO - 1/10 [20.00%]: m_3 requested negmas.sao.SAOMechanism[None] with ['c_0', 'm_3'] (ID fff32fe6-ca72-4f92-9c9d-7703a3db340b) 2019-02-27 11:34:09,729 - INFO - 1/10 [20.00%]: m_3-dcea5638-aed1-4f6b-bf21-1a67e1bdefbd request was accepted 2019-02-27 11:34:09,730 - INFO - 1/10 [20.00%]: m_4 requested negmas.sao.SAOMechanism[None] with ['c_0', 'm_4'] (ID 8f61be5f-08c5-4bb9-8b29-2975f14b34ef) 2019-02-27 11:34:09,731 - INFO - 1/10 [20.00%]: m_4-eebf8ea6-43d6-4114-96fb-76507f40ec73 request was accepted 2019-02-27 11:34:09,733 - INFO - 1/10 [20.00%]: m_0 requested negmas.sao.SAOMechanism[None] with ['c_2', 'm_0'] (ID 15ebb8cd-baf8-43f4-9f1b-59348e42336b) 2019-02-27 11:34:09,733 - INFO - 1/10 [20.00%]: m_0-6a7c0ac4-5a18-4feb-bcc1-a5a67aa1e7c5 request was accepted 2019-02-27 11:34:09,734 - INFO - 1/10 [20.00%]: m_1 requested negmas.sao.SAOMechanism[None] with ['c_2', 'm_1'] (ID 2782902a-fdcb-4acb-b861-22734bd6069a) 2019-02-27 11:34:09,735 - INFO - 1/10 [20.00%]: m_1-02672ede-8506-42d2-9911-04211fcde6e5 request was accepted 2019-02-27 11:34:09,736 - INFO - 1/10 [20.00%]: m_2 requested negmas.sao.SAOMechanism[None] with ['c_2', 'm_2'] (ID 3d47da7e-4c7b-4611-9f77-7323b66754dc) 2019-02-27 11:34:09,737 - INFO - 1/10 [20.00%]: m_2-577afd33-5aed-4647-8f4a-17a41dca4d54 request was accepted 2019-02-27 11:34:09,738 - INFO - 1/10 [20.00%]: m_3 requested negmas.sao.SAOMechanism[None] with ['c_2', 'm_3'] (ID efa3153c-a1af-4fa1-92a3-d948c66b9800) 2019-02-27 11:34:09,739 - INFO - 1/10 [20.00%]: m_3-dcea5638-aed1-4f6b-bf21-1a67e1bdefbd request was accepted 2019-02-27 11:34:09,741 - INFO - 1/10 [20.00%]: m_4 requested negmas.sao.SAOMechanism[None] with ['c_2', 'm_4'] (ID c2c4f121-7627-41d0-a39f-82887c61b50d) 2019-02-27 11:34:09,742 - INFO - 1/10 [20.00%]: m_4-eebf8ea6-43d6-4114-96fb-76507f40ec73 request was accepted 2019-02-27 11:34:09,744 - INFO - 1/10 [20.00%]: m_0 requested negmas.sao.SAOMechanism[None] with ['c_4', 'm_0'] (ID fcda2eb8-aec1-4914-bb51-26019fb1e400) 2019-02-27 11:34:09,744 - INFO - 1/10 [20.00%]: m_0-6a7c0ac4-5a18-4feb-bcc1-a5a67aa1e7c5 request was accepted 2019-02-27 11:34:09,746 - INFO - 1/10 [20.00%]: m_1 requested negmas.sao.SAOMechanism[None] with ['c_4', 'm_1'] (ID 21cdbb2a-843a-4d68-b342-9a10dd58adfd) 2019-02-27 11:34:09,746 - INFO - 1/10 [20.00%]: m_1-02672ede-8506-42d2-9911-04211fcde6e5 request was accepted 2019-02-27 11:34:09,748 - INFO - 1/10 [20.00%]: m_2 requested negmas.sao.SAOMechanism[None] with ['c_4', 'm_2'] (ID dd427c18-a9e6-478c-b60a-21fa57355bfc) 2019-02-27 11:34:09,749 - INFO - 1/10 [20.00%]: m_2-577afd33-5aed-4647-8f4a-17a41dca4d54 request was accepted 2019-02-27 11:34:09,750 - INFO - 1/10 [20.00%]: m_3 requested negmas.sao.SAOMechanism[None] with ['c_4', 'm_3'] (ID 6a571855-08a0-4918-92de-0a0ed5926a2e) 2019-02-27 11:34:09,751 - INFO - 1/10 [20.00%]: m_3-dcea5638-aed1-4f6b-bf21-1a67e1bdefbd request was accepted 2019-02-27 11:34:09,752 - INFO - 1/10 [20.00%]: m_4 requested negmas.sao.SAOMechanism[None] with ['c_4', 'm_4'] (ID 910df86f-776c-4dd5-8c89-d3843bd21831) 2019-02-27 11:34:09,752 - INFO - 1/10 [20.00%]: m_4-eebf8ea6-43d6-4114-96fb-76507f40ec73 request was accepted 2019-02-27 11:34:09,752 - DEBUG - 1/10 [20.00%]: Factory 567c17c8-8bbd-4ebb-828c-d4860fd379b7: money=0, storage={}, loans=0.0 2019-02-27 11:34:09,753 - DEBUG - 1/10 [20.00%]: Factory a0f4927d-1f5c-4f74-a2f7-aa8e774a27e3: money=0, storage={}, loans=0.0 2019-02-27 11:34:09,753 - DEBUG - 1/10 [20.00%]: Factory 8a8fa7a0-f90e-4d14-959d-34b2b489efe1: money=0, storage={}, loans=0.0 2019-02-27 11:34:09,753 - DEBUG - 1/10 [20.00%]: Factory c01b5ced-1ecd-491f-8503-d6b05067d41d: money=0, storage={}, loans=0.0 2019-02-27 11:34:09,753 - DEBUG - 1/10 [20.00%]: Factory e4a66fab-f4f6-483a-bc31-5cab325cfe7f: money=0, storage={}, loans=0.0 2019-02-27 11:34:09,753 - DEBUG - 1/10 [20.00%]: Factory ae788129-5389-405f-91bb-1dd70ada97a8: money=0.0, storage={}, loans=0.0 2019-02-27 11:34:09,753 - DEBUG - 1/10 [20.00%]: Factory ebf908e4-19c8-4171-ac89-c0ddba170b2f: money=0.0, storage={}, loans=0.0 2019-02-27 11:34:09,753 - DEBUG - 1/10 [20.00%]: Factory b3b8170f-8fca-486f-848a-69d82e617f52: money=0.0, storage={}, loans=0.0 2019-02-27 11:34:09,753 - DEBUG - 1/10 [20.00%]: Factory f5f00bb2-9f63-41d3-bbb2-270d5bc7268e: money=0.0, storage={}, loans=0.0 2019-02-27 11:34:09,753 - DEBUG - 1/10 [20.00%]: Factory 0f562fc9-74f3-4758-8c55-6045859782f5: money=0.0, storage={}, loans=0.0 2019-02-27 11:34:09,754 - INFO - 2/10 [30.00%]: 25 Negotiations/4 _entities 2019-02-27 11:34:09,964 - DEBUG - 2/10 [30.00%]: Contract [to be signed at 3]: ['c_1', 'm_2'] > {'time': 5, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_1-83f7bb54-0275-47dc-8c43-bd0e2b2744d4: buy 0 (t: 5, u: (0, 2.0), q: (1, 3))', 'partners': "['c_1-83f7bb54-0275-47dc-8c43-bd0e2b2744d4', 'm_2-577afd33-5aed-4647-8f4a-17a41dca4d54']", 'seller': 'm_2-577afd33-5aed-4647-8f4a-17a41dca4d54', 'buyer': 'c_1-83f7bb54-0275-47dc-8c43-bd0e2b2744d4'} 2019-02-27 11:34:09,964 - DEBUG - 2/10 [30.00%]: Contract [to be signed at 3]: ['c_0', 'm_4'] > {'time': 5, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_0-849400ab-19ff-42fa-bf65-10ef2f795a6f: buy 0 (t: 5, u: (0, 2.0), q: (1, 4))', 'partners': "['c_0-849400ab-19ff-42fa-bf65-10ef2f795a6f', 'm_4-eebf8ea6-43d6-4114-96fb-76507f40ec73']", 'seller': 'm_4-eebf8ea6-43d6-4114-96fb-76507f40ec73', 'buyer': 'c_0-849400ab-19ff-42fa-bf65-10ef2f795a6f'} 2019-02-27 11:34:09,965 - DEBUG - 2/10 [30.00%]: Contract [to be signed at 3]: ['c_3', 'm_0'] > {'time': 5, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_3-b37498e8-6619-4aec-b3a3-dd95bbefbb6d: buy 0 (t: 5, u: (0, 2.0), q: (1, 3))', 'partners': "['c_3-b37498e8-6619-4aec-b3a3-dd95bbefbb6d', 'm_0-6a7c0ac4-5a18-4feb-bcc1-a5a67aa1e7c5']", 'seller': 'm_0-6a7c0ac4-5a18-4feb-bcc1-a5a67aa1e7c5', 'buyer': 'c_3-b37498e8-6619-4aec-b3a3-dd95bbefbb6d'} 2019-02-27 11:34:09,965 - DEBUG - 2/10 [30.00%]: Contract [to be signed at 3]: ['c_0', 'm_1'] > {'time': 5, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_0-849400ab-19ff-42fa-bf65-10ef2f795a6f: buy 0 (t: 5, u: (0, 2.0), q: (1, 4))', 'partners': "['c_0-849400ab-19ff-42fa-bf65-10ef2f795a6f', 'm_1-02672ede-8506-42d2-9911-04211fcde6e5']", 'seller': 'm_1-02672ede-8506-42d2-9911-04211fcde6e5', 'buyer': 'c_0-849400ab-19ff-42fa-bf65-10ef2f795a6f'} 2019-02-27 11:34:09,965 - DEBUG - 2/10 [30.00%]: Contract [to be signed at 3]: ['c_4', 'm_3'] > {'time': 5, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_4-1729ce33-b911-41f1-b325-edaff5f0cdff: buy 0 (t: 5, u: (0, 2.0), q: (1, 3))', 'partners': "['c_4-1729ce33-b911-41f1-b325-edaff5f0cdff', 'm_3-dcea5638-aed1-4f6b-bf21-1a67e1bdefbd']", 'seller': 'm_3-dcea5638-aed1-4f6b-bf21-1a67e1bdefbd', 'buyer': 'c_4-1729ce33-b911-41f1-b325-edaff5f0cdff'} 2019-02-27 11:34:09,966 - DEBUG - 2/10 [30.00%]: Contract [to be signed at 3]: ['c_2', 'm_1'] > {'time': 5, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_2-04df9282-7b04-48c4-a56c-066f6691dd4e: buy 0 (t: 5, u: (0, 2.0), q: (1, 3))', 'partners': "['c_2-04df9282-7b04-48c4-a56c-066f6691dd4e', 'm_1-02672ede-8506-42d2-9911-04211fcde6e5']", 'seller': 'm_1-02672ede-8506-42d2-9911-04211fcde6e5', 'buyer': 'c_2-04df9282-7b04-48c4-a56c-066f6691dd4e'} 2019-02-27 11:34:09,966 - DEBUG - 2/10 [30.00%]: Contract [to be signed at 3]: ['c_4', 'm_4'] > {'time': 5, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_4-1729ce33-b911-41f1-b325-edaff5f0cdff: buy 0 (t: 5, u: (0, 2.0), q: (1, 3))', 'partners': "['c_4-1729ce33-b911-41f1-b325-edaff5f0cdff', 'm_4-eebf8ea6-43d6-4114-96fb-76507f40ec73']", 'seller': 'm_4-eebf8ea6-43d6-4114-96fb-76507f40ec73', 'buyer': 'c_4-1729ce33-b911-41f1-b325-edaff5f0cdff'} 2019-02-27 11:34:09,966 - DEBUG - 2/10 [30.00%]: Contract [to be signed at 3]: ['c_3', 'm_4'] > {'time': 5, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_3-b37498e8-6619-4aec-b3a3-dd95bbefbb6d: buy 0 (t: 5, u: (0, 2.0), q: (1, 3))', 'partners': "['c_3-b37498e8-6619-4aec-b3a3-dd95bbefbb6d', 'm_4-eebf8ea6-43d6-4114-96fb-76507f40ec73']", 'seller': 'm_4-eebf8ea6-43d6-4114-96fb-76507f40ec73', 'buyer': 'c_3-b37498e8-6619-4aec-b3a3-dd95bbefbb6d'} 2019-02-27 11:34:09,966 - DEBUG - 2/10 [30.00%]: Contract [to be signed at 3]: ['c_1', 'm_0'] > {'time': 5, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_1-83f7bb54-0275-47dc-8c43-bd0e2b2744d4: buy 0 (t: 5, u: (0, 2.0), q: (1, 3))', 'partners': "['c_1-83f7bb54-0275-47dc-8c43-bd0e2b2744d4', 'm_0-6a7c0ac4-5a18-4feb-bcc1-a5a67aa1e7c5']", 'seller': 'm_0-6a7c0ac4-5a18-4feb-bcc1-a5a67aa1e7c5', 'buyer': 'c_1-83f7bb54-0275-47dc-8c43-bd0e2b2744d4'} 2019-02-27 11:34:09,967 - DEBUG - 2/10 [30.00%]: Contract [to be signed at 3]: ['c_2', 'm_2'] > {'time': 5, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_2-04df9282-7b04-48c4-a56c-066f6691dd4e: buy 0 (t: 5, u: (0, 2.0), q: (1, 3))', 'partners': "['c_2-04df9282-7b04-48c4-a56c-066f6691dd4e', 'm_2-577afd33-5aed-4647-8f4a-17a41dca4d54']", 'seller': 'm_2-577afd33-5aed-4647-8f4a-17a41dca4d54', 'buyer': 'c_2-04df9282-7b04-48c4-a56c-066f6691dd4e'} 2019-02-27 11:34:09,967 - DEBUG - 2/10 [30.00%]: Contract [to be signed at 3]: ['c_0', 'm_2'] > {'time': 5, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_0-849400ab-19ff-42fa-bf65-10ef2f795a6f: buy 0 (t: 5, u: (0, 2.0), q: (1, 4))', 'partners': "['c_0-849400ab-19ff-42fa-bf65-10ef2f795a6f', 'm_2-577afd33-5aed-4647-8f4a-17a41dca4d54']", 'seller': 'm_2-577afd33-5aed-4647-8f4a-17a41dca4d54', 'buyer': 'c_0-849400ab-19ff-42fa-bf65-10ef2f795a6f'} 2019-02-27 11:34:09,967 - DEBUG - 2/10 [30.00%]: Contract [to be signed at 3]: ['c_2', 'm_4'] > {'time': 5, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_2-04df9282-7b04-48c4-a56c-066f6691dd4e: buy 0 (t: 5, u: (0, 2.0), q: (1, 3))', 'partners': "['c_2-04df9282-7b04-48c4-a56c-066f6691dd4e', 'm_4-eebf8ea6-43d6-4114-96fb-76507f40ec73']", 'seller': 'm_4-eebf8ea6-43d6-4114-96fb-76507f40ec73', 'buyer': 'c_2-04df9282-7b04-48c4-a56c-066f6691dd4e'} 2019-02-27 11:34:09,968 - DEBUG - 2/10 [30.00%]: Contract [to be signed at 3]: ['c_0', 'm_3'] > {'time': 5, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_0-849400ab-19ff-42fa-bf65-10ef2f795a6f: buy 0 (t: 5, u: (0, 2.0), q: (1, 4))', 'partners': "['c_0-849400ab-19ff-42fa-bf65-10ef2f795a6f', 'm_3-dcea5638-aed1-4f6b-bf21-1a67e1bdefbd']", 'seller': 'm_3-dcea5638-aed1-4f6b-bf21-1a67e1bdefbd', 'buyer': 'c_0-849400ab-19ff-42fa-bf65-10ef2f795a6f'} 2019-02-27 11:34:09,968 - DEBUG - 2/10 [30.00%]: Contract [to be signed at 3]: ['c_1', 'm_4'] > {'time': 5, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_1-83f7bb54-0275-47dc-8c43-bd0e2b2744d4: buy 0 (t: 5, u: (0, 2.0), q: (1, 3))', 'partners': "['c_1-83f7bb54-0275-47dc-8c43-bd0e2b2744d4', 'm_4-eebf8ea6-43d6-4114-96fb-76507f40ec73']", 'seller': 'm_4-eebf8ea6-43d6-4114-96fb-76507f40ec73', 'buyer': 'c_1-83f7bb54-0275-47dc-8c43-bd0e2b2744d4'} 2019-02-27 11:34:09,968 - DEBUG - 2/10 [30.00%]: Contract [to be signed at 3]: ['c_3', 'm_1'] > {'time': 5, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_3-b37498e8-6619-4aec-b3a3-dd95bbefbb6d: buy 0 (t: 5, u: (0, 2.0), q: (1, 3))', 'partners': "['c_3-b37498e8-6619-4aec-b3a3-dd95bbefbb6d', 'm_1-02672ede-8506-42d2-9911-04211fcde6e5']", 'seller': 'm_1-02672ede-8506-42d2-9911-04211fcde6e5', 'buyer': 'c_3-b37498e8-6619-4aec-b3a3-dd95bbefbb6d'} 2019-02-27 11:34:09,969 - DEBUG - 2/10 [30.00%]: Contract [to be signed at 3]: ['c_2', 'm_3'] > {'time': 5, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_2-04df9282-7b04-48c4-a56c-066f6691dd4e: buy 0 (t: 5, u: (0, 2.0), q: (1, 3))', 'partners': "['c_2-04df9282-7b04-48c4-a56c-066f6691dd4e', 'm_3-dcea5638-aed1-4f6b-bf21-1a67e1bdefbd']", 'seller': 'm_3-dcea5638-aed1-4f6b-bf21-1a67e1bdefbd', 'buyer': 'c_2-04df9282-7b04-48c4-a56c-066f6691dd4e'} 2019-02-27 11:34:09,969 - DEBUG - 2/10 [30.00%]: Contract [to be signed at 3]: ['c_0', 'm_0'] > {'time': 5, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_0-849400ab-19ff-42fa-bf65-10ef2f795a6f: buy 0 (t: 5, u: (0, 2.0), q: (1, 4))', 'partners': "['c_0-849400ab-19ff-42fa-bf65-10ef2f795a6f', 'm_0-6a7c0ac4-5a18-4feb-bcc1-a5a67aa1e7c5']", 'seller': 'm_0-6a7c0ac4-5a18-4feb-bcc1-a5a67aa1e7c5', 'buyer': 'c_0-849400ab-19ff-42fa-bf65-10ef2f795a6f'} 2019-02-27 11:34:09,969 - DEBUG - 2/10 [30.00%]: Contract [to be signed at 3]: ['c_4', 'm_1'] > {'time': 5, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_4-1729ce33-b911-41f1-b325-edaff5f0cdff: buy 0 (t: 5, u: (0, 2.0), q: (1, 3))', 'partners': "['c_4-1729ce33-b911-41f1-b325-edaff5f0cdff', 'm_1-02672ede-8506-42d2-9911-04211fcde6e5']", 'seller': 'm_1-02672ede-8506-42d2-9911-04211fcde6e5', 'buyer': 'c_4-1729ce33-b911-41f1-b325-edaff5f0cdff'} 2019-02-27 11:34:09,970 - DEBUG - 2/10 [30.00%]: Contract [to be signed at 3]: ['c_1', 'm_1'] > {'time': 5, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_1-83f7bb54-0275-47dc-8c43-bd0e2b2744d4: buy 0 (t: 5, u: (0, 2.0), q: (1, 3))', 'partners': "['c_1-83f7bb54-0275-47dc-8c43-bd0e2b2744d4', 'm_1-02672ede-8506-42d2-9911-04211fcde6e5']", 'seller': 'm_1-02672ede-8506-42d2-9911-04211fcde6e5', 'buyer': 'c_1-83f7bb54-0275-47dc-8c43-bd0e2b2744d4'} 2019-02-27 11:34:09,970 - DEBUG - 2/10 [30.00%]: Contract [to be signed at 3]: ['c_4', 'm_0'] > {'time': 5, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_4-1729ce33-b911-41f1-b325-edaff5f0cdff: buy 0 (t: 5, u: (0, 2.0), q: (1, 3))', 'partners': "['c_4-1729ce33-b911-41f1-b325-edaff5f0cdff', 'm_0-6a7c0ac4-5a18-4feb-bcc1-a5a67aa1e7c5']", 'seller': 'm_0-6a7c0ac4-5a18-4feb-bcc1-a5a67aa1e7c5', 'buyer': 'c_4-1729ce33-b911-41f1-b325-edaff5f0cdff'} 2019-02-27 11:34:09,970 - DEBUG - 2/10 [30.00%]: Contract [to be signed at 3]: ['c_3', 'm_2'] > {'time': 5, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_3-b37498e8-6619-4aec-b3a3-dd95bbefbb6d: buy 0 (t: 5, u: (0, 2.0), q: (1, 3))', 'partners': "['c_3-b37498e8-6619-4aec-b3a3-dd95bbefbb6d', 'm_2-577afd33-5aed-4647-8f4a-17a41dca4d54']", 'seller': 'm_2-577afd33-5aed-4647-8f4a-17a41dca4d54', 'buyer': 'c_3-b37498e8-6619-4aec-b3a3-dd95bbefbb6d'} 2019-02-27 11:34:09,971 - DEBUG - 2/10 [30.00%]: Contract [to be signed at 3]: ['c_4', 'm_2'] > {'time': 5, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_4-1729ce33-b911-41f1-b325-edaff5f0cdff: buy 0 (t: 5, u: (0, 2.0), q: (1, 3))', 'partners': "['c_4-1729ce33-b911-41f1-b325-edaff5f0cdff', 'm_2-577afd33-5aed-4647-8f4a-17a41dca4d54']", 'seller': 'm_2-577afd33-5aed-4647-8f4a-17a41dca4d54', 'buyer': 'c_4-1729ce33-b911-41f1-b325-edaff5f0cdff'} 2019-02-27 11:34:09,971 - DEBUG - 2/10 [30.00%]: Contract [to be signed at 3]: ['c_1', 'm_3'] > {'time': 5, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_1-83f7bb54-0275-47dc-8c43-bd0e2b2744d4: buy 0 (t: 5, u: (0, 2.0), q: (1, 3))', 'partners': "['c_1-83f7bb54-0275-47dc-8c43-bd0e2b2744d4', 'm_3-dcea5638-aed1-4f6b-bf21-1a67e1bdefbd']", 'seller': 'm_3-dcea5638-aed1-4f6b-bf21-1a67e1bdefbd', 'buyer': 'c_1-83f7bb54-0275-47dc-8c43-bd0e2b2744d4'} 2019-02-27 11:34:09,971 - DEBUG - 2/10 [30.00%]: Contract [to be signed at 3]: ['c_3', 'm_3'] > {'time': 5, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_3-b37498e8-6619-4aec-b3a3-dd95bbefbb6d: buy 0 (t: 5, u: (0, 2.0), q: (1, 3))', 'partners': "['c_3-b37498e8-6619-4aec-b3a3-dd95bbefbb6d', 'm_3-dcea5638-aed1-4f6b-bf21-1a67e1bdefbd']", 'seller': 'm_3-dcea5638-aed1-4f6b-bf21-1a67e1bdefbd', 'buyer': 'c_3-b37498e8-6619-4aec-b3a3-dd95bbefbb6d'} 2019-02-27 11:34:09,971 - DEBUG - 2/10 [30.00%]: Contract [to be signed at 3]: ['c_2', 'm_0'] > {'time': 5, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_2-04df9282-7b04-48c4-a56c-066f6691dd4e: buy 0 (t: 5, u: (0, 2.0), q: (1, 3))', 'partners': "['c_2-04df9282-7b04-48c4-a56c-066f6691dd4e', 'm_0-6a7c0ac4-5a18-4feb-bcc1-a5a67aa1e7c5']", 'seller': 'm_0-6a7c0ac4-5a18-4feb-bcc1-a5a67aa1e7c5', 'buyer': 'c_2-04df9282-7b04-48c4-a56c-066f6691dd4e'} 2019-02-27 11:34:09,974 - INFO - 2/10 [30.00%]: m_0 requested negmas.sao.SAOMechanism[None] with ['c_1', 'm_0'] (ID 2892f1c8-4891-4690-907e-3e1400298f1f) 2019-02-27 11:34:09,974 - INFO - 2/10 [30.00%]: m_0-6a7c0ac4-5a18-4feb-bcc1-a5a67aa1e7c5 request was accepted 2019-02-27 11:34:09,975 - INFO - 2/10 [30.00%]: m_1 requested negmas.sao.SAOMechanism[None] with ['c_1', 'm_1'] (ID e65481dc-f14d-4ac4-b8c1-05e85f78d881) 2019-02-27 11:34:09,976 - INFO - 2/10 [30.00%]: m_1-02672ede-8506-42d2-9911-04211fcde6e5 request was accepted 2019-02-27 11:34:09,977 - INFO - 2/10 [30.00%]: m_2 requested negmas.sao.SAOMechanism[None] with ['c_1', 'm_2'] (ID 0acf45fa-b260-452f-b520-49f0d78f7677) 2019-02-27 11:34:09,977 - INFO - 2/10 [30.00%]: m_2-577afd33-5aed-4647-8f4a-17a41dca4d54 request was accepted 2019-02-27 11:34:09,978 - INFO - 2/10 [30.00%]: m_3 requested negmas.sao.SAOMechanism[None] with ['c_1', 'm_3'] (ID 3a310eb9-8add-40e8-a51e-9be4c9da921f) 2019-02-27 11:34:09,979 - INFO - 2/10 [30.00%]: m_3-dcea5638-aed1-4f6b-bf21-1a67e1bdefbd request was accepted 2019-02-27 11:34:09,980 - INFO - 2/10 [30.00%]: m_4 requested negmas.sao.SAOMechanism[None] with ['c_1', 'm_4'] (ID f43d6756-87ab-4faf-967e-47781ec51180) 2019-02-27 11:34:09,980 - INFO - 2/10 [30.00%]: m_4-eebf8ea6-43d6-4114-96fb-76507f40ec73 request was accepted 2019-02-27 11:34:09,982 - INFO - 2/10 [30.00%]: m_0 requested negmas.sao.SAOMechanism[None] with ['c_3', 'm_0'] (ID 47490949-0b7e-4812-9d61-e526f72ca195) 2019-02-27 11:34:09,983 - INFO - 2/10 [30.00%]: m_0-6a7c0ac4-5a18-4feb-bcc1-a5a67aa1e7c5 request was accepted 2019-02-27 11:34:09,984 - INFO - 2/10 [30.00%]: m_1 requested negmas.sao.SAOMechanism[None] with ['c_3', 'm_1'] (ID f9a32897-36c3-40e4-8600-0c80a4d1de41) 2019-02-27 11:34:09,984 - INFO - 2/10 [30.00%]: m_1-02672ede-8506-42d2-9911-04211fcde6e5 request was accepted 2019-02-27 11:34:09,985 - INFO - 2/10 [30.00%]: m_2 requested negmas.sao.SAOMechanism[None] with ['c_3', 'm_2'] (ID e3375fc5-8292-4b37-ba59-d2e5e655cd87) 2019-02-27 11:34:09,986 - INFO - 2/10 [30.00%]: m_2-577afd33-5aed-4647-8f4a-17a41dca4d54 request was accepted 2019-02-27 11:34:09,987 - INFO - 2/10 [30.00%]: m_3 requested negmas.sao.SAOMechanism[None] with ['c_3', 'm_3'] (ID 7d59e1ed-06b7-4f5c-91bf-b948111cc4c7) 2019-02-27 11:34:09,987 - INFO - 2/10 [30.00%]: m_3-dcea5638-aed1-4f6b-bf21-1a67e1bdefbd request was accepted 2019-02-27 11:34:09,988 - INFO - 2/10 [30.00%]: m_4 requested negmas.sao.SAOMechanism[None] with ['c_3', 'm_4'] (ID aa9cc685-c9ef-4c6b-921a-d26b3dd2d364) 2019-02-27 11:34:09,989 - INFO - 2/10 [30.00%]: m_4-eebf8ea6-43d6-4114-96fb-76507f40ec73 request was accepted 2019-02-27 11:34:09,990 - INFO - 2/10 [30.00%]: m_0 requested negmas.sao.SAOMechanism[None] with ['c_0', 'm_0'] (ID 6efe0665-f246-4092-8476-0f36f612700f) 2019-02-27 11:34:09,991 - INFO - 2/10 [30.00%]: m_0-6a7c0ac4-5a18-4feb-bcc1-a5a67aa1e7c5 request was accepted 2019-02-27 11:34:09,992 - INFO - 2/10 [30.00%]: m_1 requested negmas.sao.SAOMechanism[None] with ['c_0', 'm_1'] (ID a5e9ed43-b3d5-4125-974c-afd33017bc4e) 2019-02-27 11:34:09,992 - INFO - 2/10 [30.00%]: m_1-02672ede-8506-42d2-9911-04211fcde6e5 request was accepted 2019-02-27 11:34:09,994 - INFO - 2/10 [30.00%]: m_2 requested negmas.sao.SAOMechanism[None] with ['c_0', 'm_2'] (ID c1536182-7340-4df3-a237-08d3521684c8) 2019-02-27 11:34:09,994 - INFO - 2/10 [30.00%]: m_2-577afd33-5aed-4647-8f4a-17a41dca4d54 request was accepted 2019-02-27 11:34:09,995 - INFO - 2/10 [30.00%]: m_3 requested negmas.sao.SAOMechanism[None] with ['c_0', 'm_3'] (ID 043f7b80-e97f-4b57-9adc-e20aa8fbdfaa) 2019-02-27 11:34:09,996 - INFO - 2/10 [30.00%]: m_3-dcea5638-aed1-4f6b-bf21-1a67e1bdefbd request was accepted 2019-02-27 11:34:09,997 - INFO - 2/10 [30.00%]: m_4 requested negmas.sao.SAOMechanism[None] with ['c_0', 'm_4'] (ID e495536e-da58-4e0b-8e1f-05906bb0abb3) 2019-02-27 11:34:09,998 - INFO - 2/10 [30.00%]: m_4-eebf8ea6-43d6-4114-96fb-76507f40ec73 request was accepted 2019-02-27 11:34:10,001 - INFO - 2/10 [30.00%]: m_0 requested negmas.sao.SAOMechanism[None] with ['c_2', 'm_0'] (ID 30907e94-16ba-4e79-ba23-73d78346fd32) 2019-02-27 11:34:10,002 - INFO - 2/10 [30.00%]: m_0-6a7c0ac4-5a18-4feb-bcc1-a5a67aa1e7c5 request was accepted 2019-02-27 11:34:10,003 - INFO - 2/10 [30.00%]: m_1 requested negmas.sao.SAOMechanism[None] with ['c_2', 'm_1'] (ID 6b146bc9-f311-4d16-8a57-1c083b55d4c1) 2019-02-27 11:34:10,003 - INFO - 2/10 [30.00%]: m_1-02672ede-8506-42d2-9911-04211fcde6e5 request was accepted 2019-02-27 11:34:10,004 - INFO - 2/10 [30.00%]: m_2 requested negmas.sao.SAOMechanism[None] with ['c_2', 'm_2'] (ID f82a009b-5cb1-448a-b81a-0d4af4347773) 2019-02-27 11:34:10,005 - INFO - 2/10 [30.00%]: m_2-577afd33-5aed-4647-8f4a-17a41dca4d54 request was accepted 2019-02-27 11:34:10,006 - INFO - 2/10 [30.00%]: m_3 requested negmas.sao.SAOMechanism[None] with ['c_2', 'm_3'] (ID fb6af349-730a-4465-9f91-8c5ed94b3990) 2019-02-27 11:34:10,007 - INFO - 2/10 [30.00%]: m_3-dcea5638-aed1-4f6b-bf21-1a67e1bdefbd request was accepted 2019-02-27 11:34:10,008 - INFO - 2/10 [30.00%]: m_4 requested negmas.sao.SAOMechanism[None] with ['c_2', 'm_4'] (ID 17e90bca-c6f5-4aa8-af8f-4100eec3c84f) 2019-02-27 11:34:10,009 - INFO - 2/10 [30.00%]: m_4-eebf8ea6-43d6-4114-96fb-76507f40ec73 request was accepted 2019-02-27 11:34:10,010 - INFO - 2/10 [30.00%]: m_0 requested negmas.sao.SAOMechanism[None] with ['c_4', 'm_0'] (ID cfa2a9ef-9eb9-45bc-9065-72c5d3831e4f) 2019-02-27 11:34:10,011 - INFO - 2/10 [30.00%]: m_0-6a7c0ac4-5a18-4feb-bcc1-a5a67aa1e7c5 request was accepted 2019-02-27 11:34:10,012 - INFO - 2/10 [30.00%]: m_1 requested negmas.sao.SAOMechanism[None] with ['c_4', 'm_1'] (ID 61037685-2ca8-4877-bcb0-cc05437c9b13) 2019-02-27 11:34:10,012 - INFO - 2/10 [30.00%]: m_1-02672ede-8506-42d2-9911-04211fcde6e5 request was accepted 2019-02-27 11:34:10,014 - INFO - 2/10 [30.00%]: m_2 requested negmas.sao.SAOMechanism[None] with ['c_4', 'm_2'] (ID 98fc5e96-2ccb-4de8-9dd8-ea7520cf608e) 2019-02-27 11:34:10,015 - INFO - 2/10 [30.00%]: m_2-577afd33-5aed-4647-8f4a-17a41dca4d54 request was accepted 2019-02-27 11:34:10,016 - INFO - 2/10 [30.00%]: m_3 requested negmas.sao.SAOMechanism[None] with ['c_4', 'm_3'] (ID 468f2445-0dd0-48a8-a918-b83aed24bf8c) 2019-02-27 11:34:10,017 - INFO - 2/10 [30.00%]: m_3-dcea5638-aed1-4f6b-bf21-1a67e1bdefbd request was accepted 2019-02-27 11:34:10,018 - INFO - 2/10 [30.00%]: m_4 requested negmas.sao.SAOMechanism[None] with ['c_4', 'm_4'] (ID 27109998-f3fd-49b0-bc94-d662b00ab962) 2019-02-27 11:34:10,019 - INFO - 2/10 [30.00%]: m_4-eebf8ea6-43d6-4114-96fb-76507f40ec73 request was accepted 2019-02-27 11:34:10,019 - INFO - 2/10 [30.00%]: Executing c_2-04df9282-7b04-48c4-a56c-066f6691dd4e, m_1-02672ede-8506-42d2-9911-04211fcde6e5 agreed on {'time': 2, 'quantity': 3, 'unit_price': 0.5} 2019-02-27 11:34:10,019 - DEBUG - 2/10 [30.00%]: Moved 3 units of p0 from m_1 to c_2 for 1.5 dollars 2019-02-27 11:34:10,019 - INFO - 2/10 [30.00%]: Executing c_3-b37498e8-6619-4aec-b3a3-dd95bbefbb6d, m_1-02672ede-8506-42d2-9911-04211fcde6e5 agreed on {'time': 2, 'quantity': 4, 'unit_price': 0.5} 2019-02-27 11:34:10,019 - DEBUG - 2/10 [30.00%]: Moved 4 units of p0 from m_1 to c_3 for 2.0 dollars 2019-02-27 11:34:10,019 - INFO - 2/10 [30.00%]: Executing c_4-1729ce33-b911-41f1-b325-edaff5f0cdff, m_4-eebf8ea6-43d6-4114-96fb-76507f40ec73 agreed on {'time': 2, 'quantity': 3, 'unit_price': 0.5} 2019-02-27 11:34:10,019 - DEBUG - 2/10 [30.00%]: Moved 3 units of p0 from m_4 to c_4 for 1.5 dollars 2019-02-27 11:34:10,019 - INFO - 2/10 [30.00%]: Executing c_1-83f7bb54-0275-47dc-8c43-bd0e2b2744d4, m_4-eebf8ea6-43d6-4114-96fb-76507f40ec73 agreed on {'time': 2, 'quantity': 4, 'unit_price': 0.5} 2019-02-27 11:34:10,019 - DEBUG - 2/10 [30.00%]: Moved 4 units of p0 from m_4 to c_1 for 2.0 dollars 2019-02-27 11:34:10,019 - INFO - 2/10 [30.00%]: Executing c_0-849400ab-19ff-42fa-bf65-10ef2f795a6f, m_4-eebf8ea6-43d6-4114-96fb-76507f40ec73 agreed on {'time': 2, 'quantity': 3, 'unit_price': 0.5} 2019-02-27 11:34:10,019 - DEBUG - 2/10 [30.00%]: Moved 3 units of p0 from m_4 to c_0 for 1.5 dollars 2019-02-27 11:34:10,019 - DEBUG - 2/10 [30.00%]: Factory 567c17c8-8bbd-4ebb-828c-d4860fd379b7: money=-1.5, storage={}, loans=0.0 2019-02-27 11:34:10,020 - DEBUG - 2/10 [30.00%]: Factory a0f4927d-1f5c-4f74-a2f7-aa8e774a27e3: money=-2.0, storage={}, loans=0.0 2019-02-27 11:34:10,020 - DEBUG - 2/10 [30.00%]: Factory 8a8fa7a0-f90e-4d14-959d-34b2b489efe1: money=-1.5, storage={}, loans=0.0 2019-02-27 11:34:10,020 - DEBUG - 2/10 [30.00%]: Factory c01b5ced-1ecd-491f-8503-d6b05067d41d: money=-2.0, storage={}, loans=0.0 2019-02-27 11:34:10,020 - DEBUG - 2/10 [30.00%]: Factory e4a66fab-f4f6-483a-bc31-5cab325cfe7f: money=-1.5, storage={}, loans=0.0 2019-02-27 11:34:10,020 - DEBUG - 2/10 [30.00%]: Factory ae788129-5389-405f-91bb-1dd70ada97a8: money=0.0, storage={}, loans=0.0 2019-02-27 11:34:10,020 - DEBUG - 2/10 [30.00%]: Factory ebf908e4-19c8-4171-ac89-c0ddba170b2f: money=3.5, storage={0: -7}, loans=0.0 2019-02-27 11:34:10,020 - DEBUG - 2/10 [30.00%]: Factory b3b8170f-8fca-486f-848a-69d82e617f52: money=0.0, storage={}, loans=0.0 2019-02-27 11:34:10,020 - DEBUG - 2/10 [30.00%]: Factory f5f00bb2-9f63-41d3-bbb2-270d5bc7268e: money=0.0, storage={}, loans=0.0 2019-02-27 11:34:10,020 - DEBUG - 2/10 [30.00%]: Factory 0f562fc9-74f3-4758-8c55-6045859782f5: money=5.0, storage={0: -10}, loans=0.0 2019-02-27 11:34:10,020 - INFO - 3/10 [40.00%]: 25 Negotiations/4 _entities 2019-02-27 11:34:10,229 - DEBUG - 3/10 [40.00%]: Contract [to be signed at 4]: ['c_4', 'm_1'] > {'time': 6, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_4-1729ce33-b911-41f1-b325-edaff5f0cdff: buy 0 (t: 6, u: (0, 2.0), q: (1, 4))', 'partners': "['c_4-1729ce33-b911-41f1-b325-edaff5f0cdff', 'm_1-02672ede-8506-42d2-9911-04211fcde6e5']", 'seller': 'm_1-02672ede-8506-42d2-9911-04211fcde6e5', 'buyer': 'c_4-1729ce33-b911-41f1-b325-edaff5f0cdff'} 2019-02-27 11:34:10,229 - DEBUG - 3/10 [40.00%]: Contract [to be signed at 4]: ['c_2', 'm_0'] > {'time': 6, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_2-04df9282-7b04-48c4-a56c-066f6691dd4e: buy 0 (t: 6, u: (0, 2.0), q: (1, 4))', 'partners': "['c_2-04df9282-7b04-48c4-a56c-066f6691dd4e', 'm_0-6a7c0ac4-5a18-4feb-bcc1-a5a67aa1e7c5']", 'seller': 'm_0-6a7c0ac4-5a18-4feb-bcc1-a5a67aa1e7c5', 'buyer': 'c_2-04df9282-7b04-48c4-a56c-066f6691dd4e'} 2019-02-27 11:34:10,229 - DEBUG - 3/10 [40.00%]: Contract [to be signed at 4]: ['c_4', 'm_3'] > {'time': 6, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_4-1729ce33-b911-41f1-b325-edaff5f0cdff: buy 0 (t: 6, u: (0, 2.0), q: (1, 4))', 'partners': "['c_4-1729ce33-b911-41f1-b325-edaff5f0cdff', 'm_3-dcea5638-aed1-4f6b-bf21-1a67e1bdefbd']", 'seller': 'm_3-dcea5638-aed1-4f6b-bf21-1a67e1bdefbd', 'buyer': 'c_4-1729ce33-b911-41f1-b325-edaff5f0cdff'} 2019-02-27 11:34:10,230 - DEBUG - 3/10 [40.00%]: Contract [to be signed at 4]: ['c_3', 'm_3'] > {'time': 6, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_3-b37498e8-6619-4aec-b3a3-dd95bbefbb6d: buy 0 (t: 6, u: (0, 2.0), q: (1, 3))', 'partners': "['c_3-b37498e8-6619-4aec-b3a3-dd95bbefbb6d', 'm_3-dcea5638-aed1-4f6b-bf21-1a67e1bdefbd']", 'seller': 'm_3-dcea5638-aed1-4f6b-bf21-1a67e1bdefbd', 'buyer': 'c_3-b37498e8-6619-4aec-b3a3-dd95bbefbb6d'} 2019-02-27 11:34:10,230 - DEBUG - 3/10 [40.00%]: Contract [to be signed at 4]: ['c_3', 'm_0'] > {'time': 6, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_3-b37498e8-6619-4aec-b3a3-dd95bbefbb6d: buy 0 (t: 6, u: (0, 2.0), q: (1, 3))', 'partners': "['c_3-b37498e8-6619-4aec-b3a3-dd95bbefbb6d', 'm_0-6a7c0ac4-5a18-4feb-bcc1-a5a67aa1e7c5']", 'seller': 'm_0-6a7c0ac4-5a18-4feb-bcc1-a5a67aa1e7c5', 'buyer': 'c_3-b37498e8-6619-4aec-b3a3-dd95bbefbb6d'} 2019-02-27 11:34:10,230 - DEBUG - 3/10 [40.00%]: Contract [to be signed at 4]: ['c_0', 'm_3'] > {'time': 6, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_0-849400ab-19ff-42fa-bf65-10ef2f795a6f: buy 0 (t: 6, u: (0, 2.0), q: (1, 4))', 'partners': "['c_0-849400ab-19ff-42fa-bf65-10ef2f795a6f', 'm_3-dcea5638-aed1-4f6b-bf21-1a67e1bdefbd']", 'seller': 'm_3-dcea5638-aed1-4f6b-bf21-1a67e1bdefbd', 'buyer': 'c_0-849400ab-19ff-42fa-bf65-10ef2f795a6f'} 2019-02-27 11:34:10,231 - DEBUG - 3/10 [40.00%]: Contract [to be signed at 4]: ['c_2', 'm_2'] > {'time': 6, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_2-04df9282-7b04-48c4-a56c-066f6691dd4e: buy 0 (t: 6, u: (0, 2.0), q: (1, 4))', 'partners': "['c_2-04df9282-7b04-48c4-a56c-066f6691dd4e', 'm_2-577afd33-5aed-4647-8f4a-17a41dca4d54']", 'seller': 'm_2-577afd33-5aed-4647-8f4a-17a41dca4d54', 'buyer': 'c_2-04df9282-7b04-48c4-a56c-066f6691dd4e'} 2019-02-27 11:34:10,231 - DEBUG - 3/10 [40.00%]: Contract [to be signed at 4]: ['c_2', 'm_3'] > {'time': 6, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_2-04df9282-7b04-48c4-a56c-066f6691dd4e: buy 0 (t: 6, u: (0, 2.0), q: (1, 4))', 'partners': "['c_2-04df9282-7b04-48c4-a56c-066f6691dd4e', 'm_3-dcea5638-aed1-4f6b-bf21-1a67e1bdefbd']", 'seller': 'm_3-dcea5638-aed1-4f6b-bf21-1a67e1bdefbd', 'buyer': 'c_2-04df9282-7b04-48c4-a56c-066f6691dd4e'} 2019-02-27 11:34:10,231 - DEBUG - 3/10 [40.00%]: Contract [to be signed at 4]: ['c_3', 'm_4'] > {'time': 6, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_3-b37498e8-6619-4aec-b3a3-dd95bbefbb6d: buy 0 (t: 6, u: (0, 2.0), q: (1, 3))', 'partners': "['c_3-b37498e8-6619-4aec-b3a3-dd95bbefbb6d', 'm_4-eebf8ea6-43d6-4114-96fb-76507f40ec73']", 'seller': 'm_4-eebf8ea6-43d6-4114-96fb-76507f40ec73', 'buyer': 'c_3-b37498e8-6619-4aec-b3a3-dd95bbefbb6d'} 2019-02-27 11:34:10,232 - DEBUG - 3/10 [40.00%]: Contract [to be signed at 4]: ['c_0', 'm_0'] > {'time': 6, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_0-849400ab-19ff-42fa-bf65-10ef2f795a6f: buy 0 (t: 6, u: (0, 2.0), q: (1, 4))', 'partners': "['c_0-849400ab-19ff-42fa-bf65-10ef2f795a6f', 'm_0-6a7c0ac4-5a18-4feb-bcc1-a5a67aa1e7c5']", 'seller': 'm_0-6a7c0ac4-5a18-4feb-bcc1-a5a67aa1e7c5', 'buyer': 'c_0-849400ab-19ff-42fa-bf65-10ef2f795a6f'} 2019-02-27 11:34:10,232 - DEBUG - 3/10 [40.00%]: Contract [to be signed at 4]: ['c_3', 'm_1'] > {'time': 6, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_3-b37498e8-6619-4aec-b3a3-dd95bbefbb6d: buy 0 (t: 6, u: (0, 2.0), q: (1, 3))', 'partners': "['c_3-b37498e8-6619-4aec-b3a3-dd95bbefbb6d', 'm_1-02672ede-8506-42d2-9911-04211fcde6e5']", 'seller': 'm_1-02672ede-8506-42d2-9911-04211fcde6e5', 'buyer': 'c_3-b37498e8-6619-4aec-b3a3-dd95bbefbb6d'} 2019-02-27 11:34:10,232 - DEBUG - 3/10 [40.00%]: Contract [to be signed at 4]: ['c_1', 'm_0'] > {'time': 6, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_1-83f7bb54-0275-47dc-8c43-bd0e2b2744d4: buy 0 (t: 6, u: (0, 2.0), q: (1, 4))', 'partners': "['c_1-83f7bb54-0275-47dc-8c43-bd0e2b2744d4', 'm_0-6a7c0ac4-5a18-4feb-bcc1-a5a67aa1e7c5']", 'seller': 'm_0-6a7c0ac4-5a18-4feb-bcc1-a5a67aa1e7c5', 'buyer': 'c_1-83f7bb54-0275-47dc-8c43-bd0e2b2744d4'} 2019-02-27 11:34:10,233 - DEBUG - 3/10 [40.00%]: Contract [to be signed at 4]: ['c_0', 'm_4'] > {'time': 6, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_0-849400ab-19ff-42fa-bf65-10ef2f795a6f: buy 0 (t: 6, u: (0, 2.0), q: (1, 4))', 'partners': "['c_0-849400ab-19ff-42fa-bf65-10ef2f795a6f', 'm_4-eebf8ea6-43d6-4114-96fb-76507f40ec73']", 'seller': 'm_4-eebf8ea6-43d6-4114-96fb-76507f40ec73', 'buyer': 'c_0-849400ab-19ff-42fa-bf65-10ef2f795a6f'} 2019-02-27 11:34:10,233 - DEBUG - 3/10 [40.00%]: Contract [to be signed at 4]: ['c_1', 'm_3'] > {'time': 6, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_1-83f7bb54-0275-47dc-8c43-bd0e2b2744d4: buy 0 (t: 6, u: (0, 2.0), q: (1, 4))', 'partners': "['c_1-83f7bb54-0275-47dc-8c43-bd0e2b2744d4', 'm_3-dcea5638-aed1-4f6b-bf21-1a67e1bdefbd']", 'seller': 'm_3-dcea5638-aed1-4f6b-bf21-1a67e1bdefbd', 'buyer': 'c_1-83f7bb54-0275-47dc-8c43-bd0e2b2744d4'} 2019-02-27 11:34:10,233 - DEBUG - 3/10 [40.00%]: Contract [to be signed at 4]: ['c_4', 'm_4'] > {'time': 6, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_4-1729ce33-b911-41f1-b325-edaff5f0cdff: buy 0 (t: 6, u: (0, 2.0), q: (1, 4))', 'partners': "['c_4-1729ce33-b911-41f1-b325-edaff5f0cdff', 'm_4-eebf8ea6-43d6-4114-96fb-76507f40ec73']", 'seller': 'm_4-eebf8ea6-43d6-4114-96fb-76507f40ec73', 'buyer': 'c_4-1729ce33-b911-41f1-b325-edaff5f0cdff'} 2019-02-27 11:34:10,233 - DEBUG - 3/10 [40.00%]: Contract [to be signed at 4]: ['c_0', 'm_1'] > {'time': 6, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_0-849400ab-19ff-42fa-bf65-10ef2f795a6f: buy 0 (t: 6, u: (0, 2.0), q: (1, 4))', 'partners': "['c_0-849400ab-19ff-42fa-bf65-10ef2f795a6f', 'm_1-02672ede-8506-42d2-9911-04211fcde6e5']", 'seller': 'm_1-02672ede-8506-42d2-9911-04211fcde6e5', 'buyer': 'c_0-849400ab-19ff-42fa-bf65-10ef2f795a6f'} 2019-02-27 11:34:10,234 - DEBUG - 3/10 [40.00%]: Contract [to be signed at 4]: ['c_1', 'm_4'] > {'time': 6, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_1-83f7bb54-0275-47dc-8c43-bd0e2b2744d4: buy 0 (t: 6, u: (0, 2.0), q: (1, 4))', 'partners': "['c_1-83f7bb54-0275-47dc-8c43-bd0e2b2744d4', 'm_4-eebf8ea6-43d6-4114-96fb-76507f40ec73']", 'seller': 'm_4-eebf8ea6-43d6-4114-96fb-76507f40ec73', 'buyer': 'c_1-83f7bb54-0275-47dc-8c43-bd0e2b2744d4'} 2019-02-27 11:34:10,234 - DEBUG - 3/10 [40.00%]: Contract [to be signed at 4]: ['c_3', 'm_2'] > {'time': 6, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_3-b37498e8-6619-4aec-b3a3-dd95bbefbb6d: buy 0 (t: 6, u: (0, 2.0), q: (1, 3))', 'partners': "['c_3-b37498e8-6619-4aec-b3a3-dd95bbefbb6d', 'm_2-577afd33-5aed-4647-8f4a-17a41dca4d54']", 'seller': 'm_2-577afd33-5aed-4647-8f4a-17a41dca4d54', 'buyer': 'c_3-b37498e8-6619-4aec-b3a3-dd95bbefbb6d'} 2019-02-27 11:34:10,235 - DEBUG - 3/10 [40.00%]: Contract [to be signed at 4]: ['c_0', 'm_2'] > {'time': 6, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_0-849400ab-19ff-42fa-bf65-10ef2f795a6f: buy 0 (t: 6, u: (0, 2.0), q: (1, 4))', 'partners': "['c_0-849400ab-19ff-42fa-bf65-10ef2f795a6f', 'm_2-577afd33-5aed-4647-8f4a-17a41dca4d54']", 'seller': 'm_2-577afd33-5aed-4647-8f4a-17a41dca4d54', 'buyer': 'c_0-849400ab-19ff-42fa-bf65-10ef2f795a6f'} 2019-02-27 11:34:10,235 - DEBUG - 3/10 [40.00%]: Contract [to be signed at 4]: ['c_4', 'm_2'] > {'time': 6, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_4-1729ce33-b911-41f1-b325-edaff5f0cdff: buy 0 (t: 6, u: (0, 2.0), q: (1, 4))', 'partners': "['c_4-1729ce33-b911-41f1-b325-edaff5f0cdff', 'm_2-577afd33-5aed-4647-8f4a-17a41dca4d54']", 'seller': 'm_2-577afd33-5aed-4647-8f4a-17a41dca4d54', 'buyer': 'c_4-1729ce33-b911-41f1-b325-edaff5f0cdff'} 2019-02-27 11:34:10,235 - DEBUG - 3/10 [40.00%]: Contract [to be signed at 4]: ['c_1', 'm_1'] > {'time': 6, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_1-83f7bb54-0275-47dc-8c43-bd0e2b2744d4: buy 0 (t: 6, u: (0, 2.0), q: (1, 4))', 'partners': "['c_1-83f7bb54-0275-47dc-8c43-bd0e2b2744d4', 'm_1-02672ede-8506-42d2-9911-04211fcde6e5']", 'seller': 'm_1-02672ede-8506-42d2-9911-04211fcde6e5', 'buyer': 'c_1-83f7bb54-0275-47dc-8c43-bd0e2b2744d4'} 2019-02-27 11:34:10,235 - DEBUG - 3/10 [40.00%]: Contract [to be signed at 4]: ['c_1', 'm_2'] > {'time': 6, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_1-83f7bb54-0275-47dc-8c43-bd0e2b2744d4: buy 0 (t: 6, u: (0, 2.0), q: (1, 4))', 'partners': "['c_1-83f7bb54-0275-47dc-8c43-bd0e2b2744d4', 'm_2-577afd33-5aed-4647-8f4a-17a41dca4d54']", 'seller': 'm_2-577afd33-5aed-4647-8f4a-17a41dca4d54', 'buyer': 'c_1-83f7bb54-0275-47dc-8c43-bd0e2b2744d4'} 2019-02-27 11:34:10,236 - DEBUG - 3/10 [40.00%]: Contract [to be signed at 4]: ['c_4', 'm_0'] > {'time': 6, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_4-1729ce33-b911-41f1-b325-edaff5f0cdff: buy 0 (t: 6, u: (0, 2.0), q: (1, 4))', 'partners': "['c_4-1729ce33-b911-41f1-b325-edaff5f0cdff', 'm_0-6a7c0ac4-5a18-4feb-bcc1-a5a67aa1e7c5']", 'seller': 'm_0-6a7c0ac4-5a18-4feb-bcc1-a5a67aa1e7c5', 'buyer': 'c_4-1729ce33-b911-41f1-b325-edaff5f0cdff'} 2019-02-27 11:34:10,236 - DEBUG - 3/10 [40.00%]: Contract [to be signed at 4]: ['c_2', 'm_4'] > {'time': 6, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_2-04df9282-7b04-48c4-a56c-066f6691dd4e: buy 0 (t: 6, u: (0, 2.0), q: (1, 4))', 'partners': "['c_2-04df9282-7b04-48c4-a56c-066f6691dd4e', 'm_4-eebf8ea6-43d6-4114-96fb-76507f40ec73']", 'seller': 'm_4-eebf8ea6-43d6-4114-96fb-76507f40ec73', 'buyer': 'c_2-04df9282-7b04-48c4-a56c-066f6691dd4e'} 2019-02-27 11:34:10,236 - DEBUG - 3/10 [40.00%]: Contract [to be signed at 4]: ['c_2', 'm_1'] > {'time': 6, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_2-04df9282-7b04-48c4-a56c-066f6691dd4e: buy 0 (t: 6, u: (0, 2.0), q: (1, 4))', 'partners': "['c_2-04df9282-7b04-48c4-a56c-066f6691dd4e', 'm_1-02672ede-8506-42d2-9911-04211fcde6e5']", 'seller': 'm_1-02672ede-8506-42d2-9911-04211fcde6e5', 'buyer': 'c_2-04df9282-7b04-48c4-a56c-066f6691dd4e'} 2019-02-27 11:34:10,238 - INFO - 3/10 [40.00%]: m_0 requested negmas.sao.SAOMechanism[None] with ['c_1', 'm_0'] (ID 1f78677a-1438-4523-9145-d5caf4caa31b) 2019-02-27 11:34:10,238 - INFO - 3/10 [40.00%]: m_0-6a7c0ac4-5a18-4feb-bcc1-a5a67aa1e7c5 request was accepted 2019-02-27 11:34:10,240 - INFO - 3/10 [40.00%]: m_1 requested negmas.sao.SAOMechanism[None] with ['c_1', 'm_1'] (ID 0120cd38-9435-430e-a768-da762634a54c) 2019-02-27 11:34:10,240 - INFO - 3/10 [40.00%]: m_1-02672ede-8506-42d2-9911-04211fcde6e5 request was accepted 2019-02-27 11:34:10,241 - INFO - 3/10 [40.00%]: m_2 requested negmas.sao.SAOMechanism[None] with ['c_1', 'm_2'] (ID 34b43df2-f862-4641-b244-32217caaf876) 2019-02-27 11:34:10,242 - INFO - 3/10 [40.00%]: m_2-577afd33-5aed-4647-8f4a-17a41dca4d54 request was accepted 2019-02-27 11:34:10,243 - INFO - 3/10 [40.00%]: m_3 requested negmas.sao.SAOMechanism[None] with ['c_1', 'm_3'] (ID f77a1951-8ae5-4226-b5a7-785b56439500) 2019-02-27 11:34:10,243 - INFO - 3/10 [40.00%]: m_3-dcea5638-aed1-4f6b-bf21-1a67e1bdefbd request was accepted 2019-02-27 11:34:10,245 - INFO - 3/10 [40.00%]: m_4 requested negmas.sao.SAOMechanism[None] with ['c_1', 'm_4'] (ID e2dce63b-8f1b-4224-9c0d-13c9113cf616) 2019-02-27 11:34:10,245 - INFO - 3/10 [40.00%]: m_4-eebf8ea6-43d6-4114-96fb-76507f40ec73 request was accepted 2019-02-27 11:34:10,248 - INFO - 3/10 [40.00%]: m_0 requested negmas.sao.SAOMechanism[None] with ['c_3', 'm_0'] (ID f639f5d4-9e23-4b8c-9b1a-a74db19f35e2) 2019-02-27 11:34:10,249 - INFO - 3/10 [40.00%]: m_0-6a7c0ac4-5a18-4feb-bcc1-a5a67aa1e7c5 request was accepted 2019-02-27 11:34:10,250 - INFO - 3/10 [40.00%]: m_1 requested negmas.sao.SAOMechanism[None] with ['c_3', 'm_1'] (ID 0c51e52a-7fe1-4292-a35e-6239e8c5dc29) 2019-02-27 11:34:10,251 - INFO - 3/10 [40.00%]: m_1-02672ede-8506-42d2-9911-04211fcde6e5 request was accepted 2019-02-27 11:34:10,252 - INFO - 3/10 [40.00%]: m_2 requested negmas.sao.SAOMechanism[None] with ['c_3', 'm_2'] (ID 2df1fad9-17d3-4d26-b638-1a2d038c76af) 2019-02-27 11:34:10,252 - INFO - 3/10 [40.00%]: m_2-577afd33-5aed-4647-8f4a-17a41dca4d54 request was accepted 2019-02-27 11:34:10,253 - INFO - 3/10 [40.00%]: m_3 requested negmas.sao.SAOMechanism[None] with ['c_3', 'm_3'] (ID b98dc1cf-2379-4658-9225-e5edc4d2b97f) 2019-02-27 11:34:10,254 - INFO - 3/10 [40.00%]: m_3-dcea5638-aed1-4f6b-bf21-1a67e1bdefbd request was accepted 2019-02-27 11:34:10,255 - INFO - 3/10 [40.00%]: m_4 requested negmas.sao.SAOMechanism[None] with ['c_3', 'm_4'] (ID 05e2bdc0-ba4c-47c3-b7df-f7871b29ce9c) 2019-02-27 11:34:10,255 - INFO - 3/10 [40.00%]: m_4-eebf8ea6-43d6-4114-96fb-76507f40ec73 request was accepted 2019-02-27 11:34:10,257 - INFO - 3/10 [40.00%]: m_0 requested negmas.sao.SAOMechanism[None] with ['c_0', 'm_0'] (ID b170a1f3-979d-468d-b634-08a259a731df) 2019-02-27 11:34:10,257 - INFO - 3/10 [40.00%]: m_0-6a7c0ac4-5a18-4feb-bcc1-a5a67aa1e7c5 request was accepted 2019-02-27 11:34:10,258 - INFO - 3/10 [40.00%]: m_1 requested negmas.sao.SAOMechanism[None] with ['c_0', 'm_1'] (ID 1243b1c9-d616-4e6c-8ad7-844525fda673) 2019-02-27 11:34:10,259 - INFO - 3/10 [40.00%]: m_1-02672ede-8506-42d2-9911-04211fcde6e5 request was accepted 2019-02-27 11:34:10,260 - INFO - 3/10 [40.00%]: m_2 requested negmas.sao.SAOMechanism[None] with ['c_0', 'm_2'] (ID bf63fa48-90b2-48d8-a5e7-7a530966e0af) 2019-02-27 11:34:10,260 - INFO - 3/10 [40.00%]: m_2-577afd33-5aed-4647-8f4a-17a41dca4d54 request was accepted 2019-02-27 11:34:10,262 - INFO - 3/10 [40.00%]: m_3 requested negmas.sao.SAOMechanism[None] with ['c_0', 'm_3'] (ID 52d1a930-3fac-4a19-b547-ced7dc3f7f3d) 2019-02-27 11:34:10,262 - INFO - 3/10 [40.00%]: m_3-dcea5638-aed1-4f6b-bf21-1a67e1bdefbd request was accepted 2019-02-27 11:34:10,263 - INFO - 3/10 [40.00%]: m_4 requested negmas.sao.SAOMechanism[None] with ['c_0', 'm_4'] (ID 597db8fa-c3e8-49bf-b9f5-09d6aee43757) 2019-02-27 11:34:10,265 - INFO - 3/10 [40.00%]: m_4-eebf8ea6-43d6-4114-96fb-76507f40ec73 request was accepted 2019-02-27 11:34:10,266 - INFO - 3/10 [40.00%]: m_0 requested negmas.sao.SAOMechanism[None] with ['c_2', 'm_0'] (ID 4331f441-ceb0-4830-a87c-7bd859b0260b) 2019-02-27 11:34:10,267 - INFO - 3/10 [40.00%]: m_0-6a7c0ac4-5a18-4feb-bcc1-a5a67aa1e7c5 request was accepted 2019-02-27 11:34:10,268 - INFO - 3/10 [40.00%]: m_1 requested negmas.sao.SAOMechanism[None] with ['c_2', 'm_1'] (ID f2a45539-9078-4fe9-97d1-083bf01294a5) 2019-02-27 11:34:10,269 - INFO - 3/10 [40.00%]: m_1-02672ede-8506-42d2-9911-04211fcde6e5 request was accepted 2019-02-27 11:34:10,270 - INFO - 3/10 [40.00%]: m_2 requested negmas.sao.SAOMechanism[None] with ['c_2', 'm_2'] (ID d2ab3eca-13c0-4011-bad7-199718c83e43) 2019-02-27 11:34:10,270 - INFO - 3/10 [40.00%]: m_2-577afd33-5aed-4647-8f4a-17a41dca4d54 request was accepted 2019-02-27 11:34:10,271 - INFO - 3/10 [40.00%]: m_3 requested negmas.sao.SAOMechanism[None] with ['c_2', 'm_3'] (ID 156491d7-1150-4c3c-87f8-96aefb9f4b71) 2019-02-27 11:34:10,272 - INFO - 3/10 [40.00%]: m_3-dcea5638-aed1-4f6b-bf21-1a67e1bdefbd request was accepted 2019-02-27 11:34:10,273 - INFO - 3/10 [40.00%]: m_4 requested negmas.sao.SAOMechanism[None] with ['c_2', 'm_4'] (ID c9a0de12-280b-4af5-9dfb-c368c0398750) 2019-02-27 11:34:10,273 - INFO - 3/10 [40.00%]: m_4-eebf8ea6-43d6-4114-96fb-76507f40ec73 request was accepted 2019-02-27 11:34:10,275 - INFO - 3/10 [40.00%]: m_0 requested negmas.sao.SAOMechanism[None] with ['c_4', 'm_0'] (ID e80c35b1-ec61-4f93-8953-2b5b2bee2349) 2019-02-27 11:34:10,276 - INFO - 3/10 [40.00%]: m_0-6a7c0ac4-5a18-4feb-bcc1-a5a67aa1e7c5 request was accepted 2019-02-27 11:34:10,277 - INFO - 3/10 [40.00%]: m_1 requested negmas.sao.SAOMechanism[None] with ['c_4', 'm_1'] (ID 37e74686-8440-4041-9465-e61b3b62a2dc) 2019-02-27 11:34:10,277 - INFO - 3/10 [40.00%]: m_1-02672ede-8506-42d2-9911-04211fcde6e5 request was accepted 2019-02-27 11:34:10,278 - INFO - 3/10 [40.00%]: m_2 requested negmas.sao.SAOMechanism[None] with ['c_4', 'm_2'] (ID 1e3ca41a-0386-42b1-b3f5-276754c8fe08) 2019-02-27 11:34:10,279 - INFO - 3/10 [40.00%]: m_2-577afd33-5aed-4647-8f4a-17a41dca4d54 request was accepted 2019-02-27 11:34:10,280 - INFO - 3/10 [40.00%]: m_3 requested negmas.sao.SAOMechanism[None] with ['c_4', 'm_3'] (ID 47ef3b77-ed94-42fe-97e8-352b222de1d4) 2019-02-27 11:34:10,281 - INFO - 3/10 [40.00%]: m_3-dcea5638-aed1-4f6b-bf21-1a67e1bdefbd request was accepted 2019-02-27 11:34:10,282 - INFO - 3/10 [40.00%]: m_4 requested negmas.sao.SAOMechanism[None] with ['c_4', 'm_4'] (ID 10fea878-a335-4384-aa74-59b9ca329ffd) 2019-02-27 11:34:10,282 - INFO - 3/10 [40.00%]: m_4-eebf8ea6-43d6-4114-96fb-76507f40ec73 request was accepted 2019-02-27 11:34:10,282 - INFO - 3/10 [40.00%]: Executing c_3-b37498e8-6619-4aec-b3a3-dd95bbefbb6d, m_4-eebf8ea6-43d6-4114-96fb-76507f40ec73 agreed on {'time': 3, 'quantity': 3, 'unit_price': 0.5} 2019-02-27 11:34:10,282 - DEBUG - 3/10 [40.00%]: Moved 3 units of p0 from m_4 to c_3 for 1.5 dollars 2019-02-27 11:34:10,282 - INFO - 3/10 [40.00%]: Executing c_1-83f7bb54-0275-47dc-8c43-bd0e2b2744d4, m_2-577afd33-5aed-4647-8f4a-17a41dca4d54 agreed on {'time': 3, 'quantity': 4, 'unit_price': 0.5} 2019-02-27 11:34:10,282 - DEBUG - 3/10 [40.00%]: Moved 4 units of p0 from m_2 to c_1 for 2.0 dollars 2019-02-27 11:34:10,283 - INFO - 3/10 [40.00%]: Executing c_4-1729ce33-b911-41f1-b325-edaff5f0cdff, m_4-eebf8ea6-43d6-4114-96fb-76507f40ec73 agreed on {'time': 3, 'quantity': 4, 'unit_price': 0.5} 2019-02-27 11:34:10,283 - DEBUG - 3/10 [40.00%]: Moved 4 units of p0 from m_4 to c_4 for 2.0 dollars 2019-02-27 11:34:10,283 - INFO - 3/10 [40.00%]: Executing c_2-04df9282-7b04-48c4-a56c-066f6691dd4e, m_3-dcea5638-aed1-4f6b-bf21-1a67e1bdefbd agreed on {'time': 3, 'quantity': 4, 'unit_price': 0.5} 2019-02-27 11:34:10,283 - DEBUG - 3/10 [40.00%]: Moved 4 units of p0 from m_3 to c_2 for 2.0 dollars 2019-02-27 11:34:10,283 - INFO - 3/10 [40.00%]: Executing c_0-849400ab-19ff-42fa-bf65-10ef2f795a6f, m_0-6a7c0ac4-5a18-4feb-bcc1-a5a67aa1e7c5 agreed on {'time': 3, 'quantity': 3, 'unit_price': 0.5} 2019-02-27 11:34:10,283 - DEBUG - 3/10 [40.00%]: Moved 3 units of p0 from m_0 to c_0 for 1.5 dollars 2019-02-27 11:34:10,283 - DEBUG - 3/10 [40.00%]: Factory 567c17c8-8bbd-4ebb-828c-d4860fd379b7: money=-3.0, storage={}, loans=0.0 2019-02-27 11:34:10,283 - DEBUG - 3/10 [40.00%]: Factory a0f4927d-1f5c-4f74-a2f7-aa8e774a27e3: money=-4.0, storage={}, loans=0.0 2019-02-27 11:34:10,283 - DEBUG - 3/10 [40.00%]: Factory 8a8fa7a0-f90e-4d14-959d-34b2b489efe1: money=-3.5, storage={}, loans=0.0 2019-02-27 11:34:10,283 - DEBUG - 3/10 [40.00%]: Factory c01b5ced-1ecd-491f-8503-d6b05067d41d: money=-3.5, storage={}, loans=0.0 2019-02-27 11:34:10,283 - DEBUG - 3/10 [40.00%]: Factory e4a66fab-f4f6-483a-bc31-5cab325cfe7f: money=-3.5, storage={}, loans=0.0 2019-02-27 11:34:10,283 - DEBUG - 3/10 [40.00%]: Factory ae788129-5389-405f-91bb-1dd70ada97a8: money=1.5, storage={0: -3}, loans=0.0 2019-02-27 11:34:10,283 - DEBUG - 3/10 [40.00%]: Factory ebf908e4-19c8-4171-ac89-c0ddba170b2f: money=3.5, storage={0: -7}, loans=0.0 2019-02-27 11:34:10,283 - DEBUG - 3/10 [40.00%]: Factory b3b8170f-8fca-486f-848a-69d82e617f52: money=2.0, storage={0: -4}, loans=0.0 2019-02-27 11:34:10,283 - DEBUG - 3/10 [40.00%]: Factory f5f00bb2-9f63-41d3-bbb2-270d5bc7268e: money=2.0, storage={0: -4}, loans=0.0 2019-02-27 11:34:10,283 - DEBUG - 3/10 [40.00%]: Factory 0f562fc9-74f3-4758-8c55-6045859782f5: money=8.5, storage={0: -17}, loans=0.0 2019-02-27 11:34:10,283 - INFO - 4/10 [50.00%]: 25 Negotiations/4 _entities 2019-02-27 11:34:10,542 - DEBUG - 4/10 [50.00%]: Contract [to be signed at 5]: ['c_3', 'm_3'] > {'time': 7, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_3-b37498e8-6619-4aec-b3a3-dd95bbefbb6d: buy 0 (t: 7, u: (0, 2.0), q: (1, 3))', 'partners': "['c_3-b37498e8-6619-4aec-b3a3-dd95bbefbb6d', 'm_3-dcea5638-aed1-4f6b-bf21-1a67e1bdefbd']", 'seller': 'm_3-dcea5638-aed1-4f6b-bf21-1a67e1bdefbd', 'buyer': 'c_3-b37498e8-6619-4aec-b3a3-dd95bbefbb6d'} 2019-02-27 11:34:10,543 - DEBUG - 4/10 [50.00%]: Contract [to be signed at 5]: ['c_0', 'm_4'] > {'time': 7, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_0-849400ab-19ff-42fa-bf65-10ef2f795a6f: buy 0 (t: 7, u: (0, 2.0), q: (1, 4))', 'partners': "['c_0-849400ab-19ff-42fa-bf65-10ef2f795a6f', 'm_4-eebf8ea6-43d6-4114-96fb-76507f40ec73']", 'seller': 'm_4-eebf8ea6-43d6-4114-96fb-76507f40ec73', 'buyer': 'c_0-849400ab-19ff-42fa-bf65-10ef2f795a6f'} 2019-02-27 11:34:10,543 - DEBUG - 4/10 [50.00%]: Contract [to be signed at 5]: ['c_0', 'm_2'] > {'time': 7, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_0-849400ab-19ff-42fa-bf65-10ef2f795a6f: buy 0 (t: 7, u: (0, 2.0), q: (1, 4))', 'partners': "['c_0-849400ab-19ff-42fa-bf65-10ef2f795a6f', 'm_2-577afd33-5aed-4647-8f4a-17a41dca4d54']", 'seller': 'm_2-577afd33-5aed-4647-8f4a-17a41dca4d54', 'buyer': 'c_0-849400ab-19ff-42fa-bf65-10ef2f795a6f'} 2019-02-27 11:34:10,544 - DEBUG - 4/10 [50.00%]: Contract [to be signed at 5]: ['c_1', 'm_2'] > {'time': 7, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_1-83f7bb54-0275-47dc-8c43-bd0e2b2744d4: buy 0 (t: 7, u: (0, 2.0), q: (1, 4))', 'partners': "['c_1-83f7bb54-0275-47dc-8c43-bd0e2b2744d4', 'm_2-577afd33-5aed-4647-8f4a-17a41dca4d54']", 'seller': 'm_2-577afd33-5aed-4647-8f4a-17a41dca4d54', 'buyer': 'c_1-83f7bb54-0275-47dc-8c43-bd0e2b2744d4'} 2019-02-27 11:34:10,544 - DEBUG - 4/10 [50.00%]: Contract [to be signed at 5]: ['c_4', 'm_2'] > {'time': 7, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_4-1729ce33-b911-41f1-b325-edaff5f0cdff: buy 0 (t: 7, u: (0, 2.0), q: (1, 4))', 'partners': "['c_4-1729ce33-b911-41f1-b325-edaff5f0cdff', 'm_2-577afd33-5aed-4647-8f4a-17a41dca4d54']", 'seller': 'm_2-577afd33-5aed-4647-8f4a-17a41dca4d54', 'buyer': 'c_4-1729ce33-b911-41f1-b325-edaff5f0cdff'} 2019-02-27 11:34:10,545 - DEBUG - 4/10 [50.00%]: Contract [to be signed at 5]: ['c_0', 'm_0'] > {'time': 7, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_0-849400ab-19ff-42fa-bf65-10ef2f795a6f: buy 0 (t: 7, u: (0, 2.0), q: (1, 4))', 'partners': "['c_0-849400ab-19ff-42fa-bf65-10ef2f795a6f', 'm_0-6a7c0ac4-5a18-4feb-bcc1-a5a67aa1e7c5']", 'seller': 'm_0-6a7c0ac4-5a18-4feb-bcc1-a5a67aa1e7c5', 'buyer': 'c_0-849400ab-19ff-42fa-bf65-10ef2f795a6f'} 2019-02-27 11:34:10,545 - DEBUG - 4/10 [50.00%]: Contract [to be signed at 5]: ['c_3', 'm_4'] > {'time': 7, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_3-b37498e8-6619-4aec-b3a3-dd95bbefbb6d: buy 0 (t: 7, u: (0, 2.0), q: (1, 3))', 'partners': "['c_3-b37498e8-6619-4aec-b3a3-dd95bbefbb6d', 'm_4-eebf8ea6-43d6-4114-96fb-76507f40ec73']", 'seller': 'm_4-eebf8ea6-43d6-4114-96fb-76507f40ec73', 'buyer': 'c_3-b37498e8-6619-4aec-b3a3-dd95bbefbb6d'} 2019-02-27 11:34:10,546 - DEBUG - 4/10 [50.00%]: Contract [to be signed at 5]: ['c_2', 'm_3'] > {'time': 7, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_2-04df9282-7b04-48c4-a56c-066f6691dd4e: buy 0 (t: 7, u: (0, 2.0), q: (1, 4))', 'partners': "['c_2-04df9282-7b04-48c4-a56c-066f6691dd4e', 'm_3-dcea5638-aed1-4f6b-bf21-1a67e1bdefbd']", 'seller': 'm_3-dcea5638-aed1-4f6b-bf21-1a67e1bdefbd', 'buyer': 'c_2-04df9282-7b04-48c4-a56c-066f6691dd4e'} 2019-02-27 11:34:10,546 - DEBUG - 4/10 [50.00%]: Contract [to be signed at 5]: ['c_1', 'm_0'] > {'time': 7, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_1-83f7bb54-0275-47dc-8c43-bd0e2b2744d4: buy 0 (t: 7, u: (0, 2.0), q: (1, 4))', 'partners': "['c_1-83f7bb54-0275-47dc-8c43-bd0e2b2744d4', 'm_0-6a7c0ac4-5a18-4feb-bcc1-a5a67aa1e7c5']", 'seller': 'm_0-6a7c0ac4-5a18-4feb-bcc1-a5a67aa1e7c5', 'buyer': 'c_1-83f7bb54-0275-47dc-8c43-bd0e2b2744d4'} 2019-02-27 11:34:10,547 - DEBUG - 4/10 [50.00%]: Contract [to be signed at 5]: ['c_2', 'm_1'] > {'time': 7, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_2-04df9282-7b04-48c4-a56c-066f6691dd4e: buy 0 (t: 7, u: (0, 2.0), q: (1, 4))', 'partners': "['c_2-04df9282-7b04-48c4-a56c-066f6691dd4e', 'm_1-02672ede-8506-42d2-9911-04211fcde6e5']", 'seller': 'm_1-02672ede-8506-42d2-9911-04211fcde6e5', 'buyer': 'c_2-04df9282-7b04-48c4-a56c-066f6691dd4e'} 2019-02-27 11:34:10,549 - DEBUG - 4/10 [50.00%]: Contract [to be signed at 5]: ['c_3', 'm_2'] > {'time': 7, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_3-b37498e8-6619-4aec-b3a3-dd95bbefbb6d: buy 0 (t: 7, u: (0, 2.0), q: (1, 3))', 'partners': "['c_3-b37498e8-6619-4aec-b3a3-dd95bbefbb6d', 'm_2-577afd33-5aed-4647-8f4a-17a41dca4d54']", 'seller': 'm_2-577afd33-5aed-4647-8f4a-17a41dca4d54', 'buyer': 'c_3-b37498e8-6619-4aec-b3a3-dd95bbefbb6d'} 2019-02-27 11:34:10,550 - DEBUG - 4/10 [50.00%]: Contract [to be signed at 5]: ['c_1', 'm_4'] > {'time': 7, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_1-83f7bb54-0275-47dc-8c43-bd0e2b2744d4: buy 0 (t: 7, u: (0, 2.0), q: (1, 4))', 'partners': "['c_1-83f7bb54-0275-47dc-8c43-bd0e2b2744d4', 'm_4-eebf8ea6-43d6-4114-96fb-76507f40ec73']", 'seller': 'm_4-eebf8ea6-43d6-4114-96fb-76507f40ec73', 'buyer': 'c_1-83f7bb54-0275-47dc-8c43-bd0e2b2744d4'} 2019-02-27 11:34:10,550 - DEBUG - 4/10 [50.00%]: Contract [to be signed at 5]: ['c_1', 'm_1'] > {'time': 7, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_1-83f7bb54-0275-47dc-8c43-bd0e2b2744d4: buy 0 (t: 7, u: (0, 2.0), q: (1, 4))', 'partners': "['c_1-83f7bb54-0275-47dc-8c43-bd0e2b2744d4', 'm_1-02672ede-8506-42d2-9911-04211fcde6e5']", 'seller': 'm_1-02672ede-8506-42d2-9911-04211fcde6e5', 'buyer': 'c_1-83f7bb54-0275-47dc-8c43-bd0e2b2744d4'} 2019-02-27 11:34:10,550 - DEBUG - 4/10 [50.00%]: Contract [to be signed at 5]: ['c_2', 'm_4'] > {'time': 7, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_2-04df9282-7b04-48c4-a56c-066f6691dd4e: buy 0 (t: 7, u: (0, 2.0), q: (1, 4))', 'partners': "['c_2-04df9282-7b04-48c4-a56c-066f6691dd4e', 'm_4-eebf8ea6-43d6-4114-96fb-76507f40ec73']", 'seller': 'm_4-eebf8ea6-43d6-4114-96fb-76507f40ec73', 'buyer': 'c_2-04df9282-7b04-48c4-a56c-066f6691dd4e'} 2019-02-27 11:34:10,551 - DEBUG - 4/10 [50.00%]: Contract [to be signed at 5]: ['c_0', 'm_1'] > {'time': 7, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_0-849400ab-19ff-42fa-bf65-10ef2f795a6f: buy 0 (t: 7, u: (0, 2.0), q: (1, 4))', 'partners': "['c_0-849400ab-19ff-42fa-bf65-10ef2f795a6f', 'm_1-02672ede-8506-42d2-9911-04211fcde6e5']", 'seller': 'm_1-02672ede-8506-42d2-9911-04211fcde6e5', 'buyer': 'c_0-849400ab-19ff-42fa-bf65-10ef2f795a6f'} 2019-02-27 11:34:10,551 - DEBUG - 4/10 [50.00%]: Contract [to be signed at 5]: ['c_4', 'm_1'] > {'time': 7, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_4-1729ce33-b911-41f1-b325-edaff5f0cdff: buy 0 (t: 7, u: (0, 2.0), q: (1, 4))', 'partners': "['c_4-1729ce33-b911-41f1-b325-edaff5f0cdff', 'm_1-02672ede-8506-42d2-9911-04211fcde6e5']", 'seller': 'm_1-02672ede-8506-42d2-9911-04211fcde6e5', 'buyer': 'c_4-1729ce33-b911-41f1-b325-edaff5f0cdff'} 2019-02-27 11:34:10,552 - DEBUG - 4/10 [50.00%]: Contract [to be signed at 5]: ['c_4', 'm_0'] > {'time': 7, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_4-1729ce33-b911-41f1-b325-edaff5f0cdff: buy 0 (t: 7, u: (0, 2.0), q: (1, 4))', 'partners': "['c_4-1729ce33-b911-41f1-b325-edaff5f0cdff', 'm_0-6a7c0ac4-5a18-4feb-bcc1-a5a67aa1e7c5']", 'seller': 'm_0-6a7c0ac4-5a18-4feb-bcc1-a5a67aa1e7c5', 'buyer': 'c_4-1729ce33-b911-41f1-b325-edaff5f0cdff'} 2019-02-27 11:34:10,553 - DEBUG - 4/10 [50.00%]: Contract [to be signed at 5]: ['c_0', 'm_3'] > {'time': 7, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_0-849400ab-19ff-42fa-bf65-10ef2f795a6f: buy 0 (t: 7, u: (0, 2.0), q: (1, 4))', 'partners': "['c_0-849400ab-19ff-42fa-bf65-10ef2f795a6f', 'm_3-dcea5638-aed1-4f6b-bf21-1a67e1bdefbd']", 'seller': 'm_3-dcea5638-aed1-4f6b-bf21-1a67e1bdefbd', 'buyer': 'c_0-849400ab-19ff-42fa-bf65-10ef2f795a6f'} 2019-02-27 11:34:10,553 - DEBUG - 4/10 [50.00%]: Contract [to be signed at 5]: ['c_3', 'm_1'] > {'time': 7, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_3-b37498e8-6619-4aec-b3a3-dd95bbefbb6d: buy 0 (t: 7, u: (0, 2.0), q: (1, 3))', 'partners': "['c_3-b37498e8-6619-4aec-b3a3-dd95bbefbb6d', 'm_1-02672ede-8506-42d2-9911-04211fcde6e5']", 'seller': 'm_1-02672ede-8506-42d2-9911-04211fcde6e5', 'buyer': 'c_3-b37498e8-6619-4aec-b3a3-dd95bbefbb6d'} 2019-02-27 11:34:10,553 - DEBUG - 4/10 [50.00%]: Contract [to be signed at 5]: ['c_4', 'm_3'] > {'time': 7, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_4-1729ce33-b911-41f1-b325-edaff5f0cdff: buy 0 (t: 7, u: (0, 2.0), q: (1, 4))', 'partners': "['c_4-1729ce33-b911-41f1-b325-edaff5f0cdff', 'm_3-dcea5638-aed1-4f6b-bf21-1a67e1bdefbd']", 'seller': 'm_3-dcea5638-aed1-4f6b-bf21-1a67e1bdefbd', 'buyer': 'c_4-1729ce33-b911-41f1-b325-edaff5f0cdff'} 2019-02-27 11:34:10,554 - DEBUG - 4/10 [50.00%]: Contract [to be signed at 5]: ['c_3', 'm_0'] > {'time': 7, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_3-b37498e8-6619-4aec-b3a3-dd95bbefbb6d: buy 0 (t: 7, u: (0, 2.0), q: (1, 3))', 'partners': "['c_3-b37498e8-6619-4aec-b3a3-dd95bbefbb6d', 'm_0-6a7c0ac4-5a18-4feb-bcc1-a5a67aa1e7c5']", 'seller': 'm_0-6a7c0ac4-5a18-4feb-bcc1-a5a67aa1e7c5', 'buyer': 'c_3-b37498e8-6619-4aec-b3a3-dd95bbefbb6d'} 2019-02-27 11:34:10,554 - DEBUG - 4/10 [50.00%]: Contract [to be signed at 5]: ['c_1', 'm_3'] > {'time': 7, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_1-83f7bb54-0275-47dc-8c43-bd0e2b2744d4: buy 0 (t: 7, u: (0, 2.0), q: (1, 4))', 'partners': "['c_1-83f7bb54-0275-47dc-8c43-bd0e2b2744d4', 'm_3-dcea5638-aed1-4f6b-bf21-1a67e1bdefbd']", 'seller': 'm_3-dcea5638-aed1-4f6b-bf21-1a67e1bdefbd', 'buyer': 'c_1-83f7bb54-0275-47dc-8c43-bd0e2b2744d4'} 2019-02-27 11:34:10,554 - DEBUG - 4/10 [50.00%]: Contract [to be signed at 5]: ['c_2', 'm_2'] > {'time': 7, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_2-04df9282-7b04-48c4-a56c-066f6691dd4e: buy 0 (t: 7, u: (0, 2.0), q: (1, 4))', 'partners': "['c_2-04df9282-7b04-48c4-a56c-066f6691dd4e', 'm_2-577afd33-5aed-4647-8f4a-17a41dca4d54']", 'seller': 'm_2-577afd33-5aed-4647-8f4a-17a41dca4d54', 'buyer': 'c_2-04df9282-7b04-48c4-a56c-066f6691dd4e'} 2019-02-27 11:34:10,555 - DEBUG - 4/10 [50.00%]: Contract [to be signed at 5]: ['c_2', 'm_0'] > {'time': 7, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_2-04df9282-7b04-48c4-a56c-066f6691dd4e: buy 0 (t: 7, u: (0, 2.0), q: (1, 4))', 'partners': "['c_2-04df9282-7b04-48c4-a56c-066f6691dd4e', 'm_0-6a7c0ac4-5a18-4feb-bcc1-a5a67aa1e7c5']", 'seller': 'm_0-6a7c0ac4-5a18-4feb-bcc1-a5a67aa1e7c5', 'buyer': 'c_2-04df9282-7b04-48c4-a56c-066f6691dd4e'} 2019-02-27 11:34:10,555 - DEBUG - 4/10 [50.00%]: Contract [to be signed at 5]: ['c_4', 'm_4'] > {'time': 7, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_4-1729ce33-b911-41f1-b325-edaff5f0cdff: buy 0 (t: 7, u: (0, 2.0), q: (1, 4))', 'partners': "['c_4-1729ce33-b911-41f1-b325-edaff5f0cdff', 'm_4-eebf8ea6-43d6-4114-96fb-76507f40ec73']", 'seller': 'm_4-eebf8ea6-43d6-4114-96fb-76507f40ec73', 'buyer': 'c_4-1729ce33-b911-41f1-b325-edaff5f0cdff'} 2019-02-27 11:34:10,557 - INFO - 4/10 [50.00%]: m_0 requested negmas.sao.SAOMechanism[None] with ['c_1', 'm_0'] (ID 6bd3d3f6-ba17-4ec4-a85d-dc65cd9a0d03) 2019-02-27 11:34:10,557 - INFO - 4/10 [50.00%]: m_0-6a7c0ac4-5a18-4feb-bcc1-a5a67aa1e7c5 request was accepted 2019-02-27 11:34:10,559 - INFO - 4/10 [50.00%]: m_1 requested negmas.sao.SAOMechanism[None] with ['c_1', 'm_1'] (ID 26d221de-8c89-479c-9efa-5dd2ccef1709) 2019-02-27 11:34:10,559 - INFO - 4/10 [50.00%]: m_1-02672ede-8506-42d2-9911-04211fcde6e5 request was accepted 2019-02-27 11:34:10,561 - INFO - 4/10 [50.00%]: m_2 requested negmas.sao.SAOMechanism[None] with ['c_1', 'm_2'] (ID 715e5971-05d5-43dc-99b3-921433f8bdba) 2019-02-27 11:34:10,562 - INFO - 4/10 [50.00%]: m_2-577afd33-5aed-4647-8f4a-17a41dca4d54 request was accepted 2019-02-27 11:34:10,563 - INFO - 4/10 [50.00%]: m_3 requested negmas.sao.SAOMechanism[None] with ['c_1', 'm_3'] (ID 3006a216-3125-433f-9c3a-4fa5f8cbb449) 2019-02-27 11:34:10,563 - INFO - 4/10 [50.00%]: m_3-dcea5638-aed1-4f6b-bf21-1a67e1bdefbd request was accepted 2019-02-27 11:34:10,565 - INFO - 4/10 [50.00%]: m_4 requested negmas.sao.SAOMechanism[None] with ['c_1', 'm_4'] (ID 95e98281-e769-4e27-806f-5377278e806d) 2019-02-27 11:34:10,565 - INFO - 4/10 [50.00%]: m_4-eebf8ea6-43d6-4114-96fb-76507f40ec73 request was accepted 2019-02-27 11:34:10,567 - INFO - 4/10 [50.00%]: m_0 requested negmas.sao.SAOMechanism[None] with ['c_3', 'm_0'] (ID c1735a10-a880-48d2-9083-67fbd1911f81) 2019-02-27 11:34:10,569 - INFO - 4/10 [50.00%]: m_0-6a7c0ac4-5a18-4feb-bcc1-a5a67aa1e7c5 request was accepted 2019-02-27 11:34:10,571 - INFO - 4/10 [50.00%]: m_1 requested negmas.sao.SAOMechanism[None] with ['c_3', 'm_1'] (ID 2d164a2e-4497-45e3-b167-bd929e2798fc) 2019-02-27 11:34:10,572 - INFO - 4/10 [50.00%]: m_1-02672ede-8506-42d2-9911-04211fcde6e5 request was accepted 2019-02-27 11:34:10,573 - INFO - 4/10 [50.00%]: m_2 requested negmas.sao.SAOMechanism[None] with ['c_3', 'm_2'] (ID d7943af8-dac2-41ea-ae8c-8998b34dad91) 2019-02-27 11:34:10,574 - INFO - 4/10 [50.00%]: m_2-577afd33-5aed-4647-8f4a-17a41dca4d54 request was accepted 2019-02-27 11:34:10,575 - INFO - 4/10 [50.00%]: m_3 requested negmas.sao.SAOMechanism[None] with ['c_3', 'm_3'] (ID 34d3301f-c39c-43a2-8eb1-c9998e36617d) 2019-02-27 11:34:10,575 - INFO - 4/10 [50.00%]: m_3-dcea5638-aed1-4f6b-bf21-1a67e1bdefbd request was accepted 2019-02-27 11:34:10,577 - INFO - 4/10 [50.00%]: m_4 requested negmas.sao.SAOMechanism[None] with ['c_3', 'm_4'] (ID 8cc2b22a-c861-4c27-8e0a-4843f16fcbff) 2019-02-27 11:34:10,577 - INFO - 4/10 [50.00%]: m_4-eebf8ea6-43d6-4114-96fb-76507f40ec73 request was accepted 2019-02-27 11:34:10,579 - INFO - 4/10 [50.00%]: m_0 requested negmas.sao.SAOMechanism[None] with ['c_0', 'm_0'] (ID 853ab68e-262d-4175-9da4-56693eb0416a) 2019-02-27 11:34:10,580 - INFO - 4/10 [50.00%]: m_0-6a7c0ac4-5a18-4feb-bcc1-a5a67aa1e7c5 request was accepted 2019-02-27 11:34:10,581 - INFO - 4/10 [50.00%]: m_1 requested negmas.sao.SAOMechanism[None] with ['c_0', 'm_1'] (ID 3d4c2699-6b79-412d-8848-2b3086e82726) 2019-02-27 11:34:10,581 - INFO - 4/10 [50.00%]: m_1-02672ede-8506-42d2-9911-04211fcde6e5 request was accepted 2019-02-27 11:34:10,582 - INFO - 4/10 [50.00%]: m_2 requested negmas.sao.SAOMechanism[None] with ['c_0', 'm_2'] (ID ef099a8a-ef2d-41fb-9b77-04837897cc43) 2019-02-27 11:34:10,583 - INFO - 4/10 [50.00%]: m_2-577afd33-5aed-4647-8f4a-17a41dca4d54 request was accepted 2019-02-27 11:34:10,585 - INFO - 4/10 [50.00%]: m_3 requested negmas.sao.SAOMechanism[None] with ['c_0', 'm_3'] (ID eb2d04cb-1687-458f-b286-a0a179797ddd) 2019-02-27 11:34:10,585 - INFO - 4/10 [50.00%]: m_3-dcea5638-aed1-4f6b-bf21-1a67e1bdefbd request was accepted 2019-02-27 11:34:10,586 - INFO - 4/10 [50.00%]: m_4 requested negmas.sao.SAOMechanism[None] with ['c_0', 'm_4'] (ID da2ac157-1c36-4140-a764-077d54b73f16) 2019-02-27 11:34:10,587 - INFO - 4/10 [50.00%]: m_4-eebf8ea6-43d6-4114-96fb-76507f40ec73 request was accepted 2019-02-27 11:34:10,588 - INFO - 4/10 [50.00%]: m_0 requested negmas.sao.SAOMechanism[None] with ['c_2', 'm_0'] (ID 722cb694-2127-4276-aa59-b4578e299d7e) 2019-02-27 11:34:10,590 - INFO - 4/10 [50.00%]: m_0-6a7c0ac4-5a18-4feb-bcc1-a5a67aa1e7c5 request was accepted 2019-02-27 11:34:10,591 - INFO - 4/10 [50.00%]: m_1 requested negmas.sao.SAOMechanism[None] with ['c_2', 'm_1'] (ID f5d85b96-5d21-441c-a2a7-9b27f9c56211) 2019-02-27 11:34:10,592 - INFO - 4/10 [50.00%]: m_1-02672ede-8506-42d2-9911-04211fcde6e5 request was accepted 2019-02-27 11:34:10,594 - INFO - 4/10 [50.00%]: m_2 requested negmas.sao.SAOMechanism[None] with ['c_2', 'm_2'] (ID dabe4c2f-b68c-4429-9d8e-b9c834e508c4) 2019-02-27 11:34:10,595 - INFO - 4/10 [50.00%]: m_2-577afd33-5aed-4647-8f4a-17a41dca4d54 request was accepted 2019-02-27 11:34:10,596 - INFO - 4/10 [50.00%]: m_3 requested negmas.sao.SAOMechanism[None] with ['c_2', 'm_3'] (ID e713f190-5a45-4a78-8ea2-ccf8afb1516a) 2019-02-27 11:34:10,597 - INFO - 4/10 [50.00%]: m_3-dcea5638-aed1-4f6b-bf21-1a67e1bdefbd request was accepted 2019-02-27 11:34:10,598 - INFO - 4/10 [50.00%]: m_4 requested negmas.sao.SAOMechanism[None] with ['c_2', 'm_4'] (ID 2042e46e-777d-42c1-bbfa-1cc76b75d43f) 2019-02-27 11:34:10,599 - INFO - 4/10 [50.00%]: m_4-eebf8ea6-43d6-4114-96fb-76507f40ec73 request was accepted 2019-02-27 11:34:10,601 - INFO - 4/10 [50.00%]: m_0 requested negmas.sao.SAOMechanism[None] with ['c_4', 'm_0'] (ID 5817f782-c2a3-4fd2-a793-3d0b1f564b13) 2019-02-27 11:34:10,602 - INFO - 4/10 [50.00%]: m_0-6a7c0ac4-5a18-4feb-bcc1-a5a67aa1e7c5 request was accepted 2019-02-27 11:34:10,604 - INFO - 4/10 [50.00%]: m_1 requested negmas.sao.SAOMechanism[None] with ['c_4', 'm_1'] (ID a06a1a85-94df-4a59-b9ea-20fa7af663cd) 2019-02-27 11:34:10,604 - INFO - 4/10 [50.00%]: m_1-02672ede-8506-42d2-9911-04211fcde6e5 request was accepted 2019-02-27 11:34:10,606 - INFO - 4/10 [50.00%]: m_2 requested negmas.sao.SAOMechanism[None] with ['c_4', 'm_2'] (ID 17a33b70-3fc9-4e34-8d38-e4b887f51515) 2019-02-27 11:34:10,606 - INFO - 4/10 [50.00%]: m_2-577afd33-5aed-4647-8f4a-17a41dca4d54 request was accepted 2019-02-27 11:34:10,607 - INFO - 4/10 [50.00%]: m_3 requested negmas.sao.SAOMechanism[None] with ['c_4', 'm_3'] (ID ce50b033-86f4-43e5-9e3e-292b1600e920) 2019-02-27 11:34:10,608 - INFO - 4/10 [50.00%]: m_3-dcea5638-aed1-4f6b-bf21-1a67e1bdefbd request was accepted 2019-02-27 11:34:10,609 - INFO - 4/10 [50.00%]: m_4 requested negmas.sao.SAOMechanism[None] with ['c_4', 'm_4'] (ID fd7c6213-2b6e-4015-ac65-b1539e733e92) 2019-02-27 11:34:10,610 - INFO - 4/10 [50.00%]: m_4-eebf8ea6-43d6-4114-96fb-76507f40ec73 request was accepted 2019-02-27 11:34:10,610 - INFO - 4/10 [50.00%]: Executing c_0-849400ab-19ff-42fa-bf65-10ef2f795a6f, m_4-eebf8ea6-43d6-4114-96fb-76507f40ec73 agreed on {'time': 4, 'quantity': 3, 'unit_price': 0.5} 2019-02-27 11:34:10,610 - DEBUG - 4/10 [50.00%]: Moved 3 units of p0 from m_4 to c_0 for 1.5 dollars 2019-02-27 11:34:10,610 - INFO - 4/10 [50.00%]: Executing c_1-83f7bb54-0275-47dc-8c43-bd0e2b2744d4, m_1-02672ede-8506-42d2-9911-04211fcde6e5 agreed on {'time': 4, 'quantity': 4, 'unit_price': 0.5} 2019-02-27 11:34:10,610 - DEBUG - 4/10 [50.00%]: Moved 4 units of p0 from m_1 to c_1 for 2.0 dollars 2019-02-27 11:34:10,610 - INFO - 4/10 [50.00%]: Executing c_2-04df9282-7b04-48c4-a56c-066f6691dd4e, m_0-6a7c0ac4-5a18-4feb-bcc1-a5a67aa1e7c5 agreed on {'time': 4, 'quantity': 4, 'unit_price': 0.5} 2019-02-27 11:34:10,610 - DEBUG - 4/10 [50.00%]: Moved 4 units of p0 from m_0 to c_2 for 2.0 dollars 2019-02-27 11:34:10,610 - INFO - 4/10 [50.00%]: Executing c_3-b37498e8-6619-4aec-b3a3-dd95bbefbb6d, m_1-02672ede-8506-42d2-9911-04211fcde6e5 agreed on {'time': 4, 'quantity': 4, 'unit_price': 0.5} 2019-02-27 11:34:10,610 - DEBUG - 4/10 [50.00%]: Moved 4 units of p0 from m_1 to c_3 for 2.0 dollars 2019-02-27 11:34:10,610 - INFO - 4/10 [50.00%]: Executing c_4-1729ce33-b911-41f1-b325-edaff5f0cdff, m_1-02672ede-8506-42d2-9911-04211fcde6e5 agreed on {'time': 4, 'quantity': 3, 'unit_price': 0.5} 2019-02-27 11:34:10,610 - DEBUG - 4/10 [50.00%]: Moved 3 units of p0 from m_1 to c_4 for 1.5 dollars 2019-02-27 11:34:10,610 - DEBUG - 4/10 [50.00%]: Factory 567c17c8-8bbd-4ebb-828c-d4860fd379b7: money=-4.5, storage={0: 3}, loans=0.0 2019-02-27 11:34:10,610 - DEBUG - 4/10 [50.00%]: Factory a0f4927d-1f5c-4f74-a2f7-aa8e774a27e3: money=-6.0, storage={0: 4}, loans=0.0 2019-02-27 11:34:10,610 - DEBUG - 4/10 [50.00%]: Factory 8a8fa7a0-f90e-4d14-959d-34b2b489efe1: money=-5.5, storage={0: 3}, loans=0.0 2019-02-27 11:34:10,611 - DEBUG - 4/10 [50.00%]: Factory c01b5ced-1ecd-491f-8503-d6b05067d41d: money=-5.5, storage={0: 4}, loans=0.0 2019-02-27 11:34:10,611 - DEBUG - 4/10 [50.00%]: Factory e4a66fab-f4f6-483a-bc31-5cab325cfe7f: money=-5.0, storage={0: 3}, loans=0.0 2019-02-27 11:34:10,611 - DEBUG - 4/10 [50.00%]: Factory ae788129-5389-405f-91bb-1dd70ada97a8: money=3.5, storage={0: -7}, loans=0.0 2019-02-27 11:34:10,611 - DEBUG - 4/10 [50.00%]: Factory ebf908e4-19c8-4171-ac89-c0ddba170b2f: money=9.0, storage={0: -18}, loans=0.0 2019-02-27 11:34:10,611 - DEBUG - 4/10 [50.00%]: Factory b3b8170f-8fca-486f-848a-69d82e617f52: money=2.0, storage={0: -4}, loans=0.0 2019-02-27 11:34:10,611 - DEBUG - 4/10 [50.00%]: Factory f5f00bb2-9f63-41d3-bbb2-270d5bc7268e: money=2.0, storage={0: -4}, loans=0.0 2019-02-27 11:34:10,611 - DEBUG - 4/10 [50.00%]: Factory 0f562fc9-74f3-4758-8c55-6045859782f5: money=10.0, storage={0: -20}, loans=0.0 2019-02-27 11:34:10,611 - INFO - 5/10 [60.00%]: 25 Negotiations/4 _entities 2019-02-27 11:34:10,845 - DEBUG - 5/10 [60.00%]: Contract [to be signed at 6]: ['c_2', 'm_1'] > {'time': 8, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_2-04df9282-7b04-48c4-a56c-066f6691dd4e: buy 0 (t: 8, u: (0, 2.0), q: (1, 3))', 'partners': "['c_2-04df9282-7b04-48c4-a56c-066f6691dd4e', 'm_1-02672ede-8506-42d2-9911-04211fcde6e5']", 'seller': 'm_1-02672ede-8506-42d2-9911-04211fcde6e5', 'buyer': 'c_2-04df9282-7b04-48c4-a56c-066f6691dd4e'} 2019-02-27 11:34:10,845 - DEBUG - 5/10 [60.00%]: Contract [to be signed at 6]: ['c_4', 'm_1'] > {'time': 8, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_4-1729ce33-b911-41f1-b325-edaff5f0cdff: buy 0 (t: 8, u: (0, 2.0), q: (1, 4))', 'partners': "['c_4-1729ce33-b911-41f1-b325-edaff5f0cdff', 'm_1-02672ede-8506-42d2-9911-04211fcde6e5']", 'seller': 'm_1-02672ede-8506-42d2-9911-04211fcde6e5', 'buyer': 'c_4-1729ce33-b911-41f1-b325-edaff5f0cdff'} 2019-02-27 11:34:10,845 - DEBUG - 5/10 [60.00%]: Contract [to be signed at 6]: ['c_0', 'm_3'] > {'time': 8, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_0-849400ab-19ff-42fa-bf65-10ef2f795a6f: buy 0 (t: 8, u: (0, 2.0), q: (1, 4))', 'partners': "['c_0-849400ab-19ff-42fa-bf65-10ef2f795a6f', 'm_3-dcea5638-aed1-4f6b-bf21-1a67e1bdefbd']", 'seller': 'm_3-dcea5638-aed1-4f6b-bf21-1a67e1bdefbd', 'buyer': 'c_0-849400ab-19ff-42fa-bf65-10ef2f795a6f'} 2019-02-27 11:34:10,846 - DEBUG - 5/10 [60.00%]: Contract [to be signed at 6]: ['c_4', 'm_0'] > {'time': 8, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_4-1729ce33-b911-41f1-b325-edaff5f0cdff: buy 0 (t: 8, u: (0, 2.0), q: (1, 4))', 'partners': "['c_4-1729ce33-b911-41f1-b325-edaff5f0cdff', 'm_0-6a7c0ac4-5a18-4feb-bcc1-a5a67aa1e7c5']", 'seller': 'm_0-6a7c0ac4-5a18-4feb-bcc1-a5a67aa1e7c5', 'buyer': 'c_4-1729ce33-b911-41f1-b325-edaff5f0cdff'} 2019-02-27 11:34:10,846 - DEBUG - 5/10 [60.00%]: Contract [to be signed at 6]: ['c_1', 'm_2'] > {'time': 8, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_1-83f7bb54-0275-47dc-8c43-bd0e2b2744d4: buy 0 (t: 8, u: (0, 2.0), q: (1, 4))', 'partners': "['c_1-83f7bb54-0275-47dc-8c43-bd0e2b2744d4', 'm_2-577afd33-5aed-4647-8f4a-17a41dca4d54']", 'seller': 'm_2-577afd33-5aed-4647-8f4a-17a41dca4d54', 'buyer': 'c_1-83f7bb54-0275-47dc-8c43-bd0e2b2744d4'} 2019-02-27 11:34:10,846 - DEBUG - 5/10 [60.00%]: Contract [to be signed at 6]: ['c_2', 'm_0'] > {'time': 8, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_2-04df9282-7b04-48c4-a56c-066f6691dd4e: buy 0 (t: 8, u: (0, 2.0), q: (1, 3))', 'partners': "['c_2-04df9282-7b04-48c4-a56c-066f6691dd4e', 'm_0-6a7c0ac4-5a18-4feb-bcc1-a5a67aa1e7c5']", 'seller': 'm_0-6a7c0ac4-5a18-4feb-bcc1-a5a67aa1e7c5', 'buyer': 'c_2-04df9282-7b04-48c4-a56c-066f6691dd4e'} 2019-02-27 11:34:10,846 - DEBUG - 5/10 [60.00%]: Contract [to be signed at 6]: ['c_2', 'm_2'] > {'time': 8, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_2-04df9282-7b04-48c4-a56c-066f6691dd4e: buy 0 (t: 8, u: (0, 2.0), q: (1, 3))', 'partners': "['c_2-04df9282-7b04-48c4-a56c-066f6691dd4e', 'm_2-577afd33-5aed-4647-8f4a-17a41dca4d54']", 'seller': 'm_2-577afd33-5aed-4647-8f4a-17a41dca4d54', 'buyer': 'c_2-04df9282-7b04-48c4-a56c-066f6691dd4e'} 2019-02-27 11:34:10,847 - DEBUG - 5/10 [60.00%]: Contract [to be signed at 6]: ['c_2', 'm_3'] > {'time': 8, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_2-04df9282-7b04-48c4-a56c-066f6691dd4e: buy 0 (t: 8, u: (0, 2.0), q: (1, 3))', 'partners': "['c_2-04df9282-7b04-48c4-a56c-066f6691dd4e', 'm_3-dcea5638-aed1-4f6b-bf21-1a67e1bdefbd']", 'seller': 'm_3-dcea5638-aed1-4f6b-bf21-1a67e1bdefbd', 'buyer': 'c_2-04df9282-7b04-48c4-a56c-066f6691dd4e'} 2019-02-27 11:34:10,847 - DEBUG - 5/10 [60.00%]: Contract [to be signed at 6]: ['c_4', 'm_2'] > {'time': 8, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_4-1729ce33-b911-41f1-b325-edaff5f0cdff: buy 0 (t: 8, u: (0, 2.0), q: (1, 4))', 'partners': "['c_4-1729ce33-b911-41f1-b325-edaff5f0cdff', 'm_2-577afd33-5aed-4647-8f4a-17a41dca4d54']", 'seller': 'm_2-577afd33-5aed-4647-8f4a-17a41dca4d54', 'buyer': 'c_4-1729ce33-b911-41f1-b325-edaff5f0cdff'} 2019-02-27 11:34:10,848 - DEBUG - 5/10 [60.00%]: Contract [to be signed at 6]: ['c_0', 'm_1'] > {'time': 8, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_0-849400ab-19ff-42fa-bf65-10ef2f795a6f: buy 0 (t: 8, u: (0, 2.0), q: (1, 4))', 'partners': "['c_0-849400ab-19ff-42fa-bf65-10ef2f795a6f', 'm_1-02672ede-8506-42d2-9911-04211fcde6e5']", 'seller': 'm_1-02672ede-8506-42d2-9911-04211fcde6e5', 'buyer': 'c_0-849400ab-19ff-42fa-bf65-10ef2f795a6f'} 2019-02-27 11:34:10,848 - DEBUG - 5/10 [60.00%]: Contract [to be signed at 6]: ['c_3', 'm_1'] > {'time': 8, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_3-b37498e8-6619-4aec-b3a3-dd95bbefbb6d: buy 0 (t: 8, u: (0, 2.0), q: (1, 4))', 'partners': "['c_3-b37498e8-6619-4aec-b3a3-dd95bbefbb6d', 'm_1-02672ede-8506-42d2-9911-04211fcde6e5']", 'seller': 'm_1-02672ede-8506-42d2-9911-04211fcde6e5', 'buyer': 'c_3-b37498e8-6619-4aec-b3a3-dd95bbefbb6d'} 2019-02-27 11:34:10,849 - DEBUG - 5/10 [60.00%]: Contract [to be signed at 6]: ['c_1', 'm_0'] > {'time': 8, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_1-83f7bb54-0275-47dc-8c43-bd0e2b2744d4: buy 0 (t: 8, u: (0, 2.0), q: (1, 4))', 'partners': "['c_1-83f7bb54-0275-47dc-8c43-bd0e2b2744d4', 'm_0-6a7c0ac4-5a18-4feb-bcc1-a5a67aa1e7c5']", 'seller': 'm_0-6a7c0ac4-5a18-4feb-bcc1-a5a67aa1e7c5', 'buyer': 'c_1-83f7bb54-0275-47dc-8c43-bd0e2b2744d4'} 2019-02-27 11:34:10,849 - DEBUG - 5/10 [60.00%]: Contract [to be signed at 6]: ['c_1', 'm_1'] > {'time': 8, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_1-83f7bb54-0275-47dc-8c43-bd0e2b2744d4: buy 0 (t: 8, u: (0, 2.0), q: (1, 4))', 'partners': "['c_1-83f7bb54-0275-47dc-8c43-bd0e2b2744d4', 'm_1-02672ede-8506-42d2-9911-04211fcde6e5']", 'seller': 'm_1-02672ede-8506-42d2-9911-04211fcde6e5', 'buyer': 'c_1-83f7bb54-0275-47dc-8c43-bd0e2b2744d4'} 2019-02-27 11:34:10,850 - DEBUG - 5/10 [60.00%]: Contract [to be signed at 6]: ['c_4', 'm_3'] > {'time': 8, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_4-1729ce33-b911-41f1-b325-edaff5f0cdff: buy 0 (t: 8, u: (0, 2.0), q: (1, 4))', 'partners': "['c_4-1729ce33-b911-41f1-b325-edaff5f0cdff', 'm_3-dcea5638-aed1-4f6b-bf21-1a67e1bdefbd']", 'seller': 'm_3-dcea5638-aed1-4f6b-bf21-1a67e1bdefbd', 'buyer': 'c_4-1729ce33-b911-41f1-b325-edaff5f0cdff'} 2019-02-27 11:34:10,851 - DEBUG - 5/10 [60.00%]: Contract [to be signed at 6]: ['c_0', 'm_0'] > {'time': 8, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_0-849400ab-19ff-42fa-bf65-10ef2f795a6f: buy 0 (t: 8, u: (0, 2.0), q: (1, 4))', 'partners': "['c_0-849400ab-19ff-42fa-bf65-10ef2f795a6f', 'm_0-6a7c0ac4-5a18-4feb-bcc1-a5a67aa1e7c5']", 'seller': 'm_0-6a7c0ac4-5a18-4feb-bcc1-a5a67aa1e7c5', 'buyer': 'c_0-849400ab-19ff-42fa-bf65-10ef2f795a6f'} 2019-02-27 11:34:10,852 - DEBUG - 5/10 [60.00%]: Contract [to be signed at 6]: ['c_1', 'm_4'] > {'time': 8, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_1-83f7bb54-0275-47dc-8c43-bd0e2b2744d4: buy 0 (t: 8, u: (0, 2.0), q: (1, 4))', 'partners': "['c_1-83f7bb54-0275-47dc-8c43-bd0e2b2744d4', 'm_4-eebf8ea6-43d6-4114-96fb-76507f40ec73']", 'seller': 'm_4-eebf8ea6-43d6-4114-96fb-76507f40ec73', 'buyer': 'c_1-83f7bb54-0275-47dc-8c43-bd0e2b2744d4'} 2019-02-27 11:34:10,852 - DEBUG - 5/10 [60.00%]: Contract [to be signed at 6]: ['c_0', 'm_4'] > {'time': 8, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_0-849400ab-19ff-42fa-bf65-10ef2f795a6f: buy 0 (t: 8, u: (0, 2.0), q: (1, 4))', 'partners': "['c_0-849400ab-19ff-42fa-bf65-10ef2f795a6f', 'm_4-eebf8ea6-43d6-4114-96fb-76507f40ec73']", 'seller': 'm_4-eebf8ea6-43d6-4114-96fb-76507f40ec73', 'buyer': 'c_0-849400ab-19ff-42fa-bf65-10ef2f795a6f'} 2019-02-27 11:34:10,852 - DEBUG - 5/10 [60.00%]: Contract [to be signed at 6]: ['c_3', 'm_2'] > {'time': 8, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_3-b37498e8-6619-4aec-b3a3-dd95bbefbb6d: buy 0 (t: 8, u: (0, 2.0), q: (1, 4))', 'partners': "['c_3-b37498e8-6619-4aec-b3a3-dd95bbefbb6d', 'm_2-577afd33-5aed-4647-8f4a-17a41dca4d54']", 'seller': 'm_2-577afd33-5aed-4647-8f4a-17a41dca4d54', 'buyer': 'c_3-b37498e8-6619-4aec-b3a3-dd95bbefbb6d'} 2019-02-27 11:34:10,853 - DEBUG - 5/10 [60.00%]: Contract [to be signed at 6]: ['c_4', 'm_4'] > {'time': 8, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_4-1729ce33-b911-41f1-b325-edaff5f0cdff: buy 0 (t: 8, u: (0, 2.0), q: (1, 4))', 'partners': "['c_4-1729ce33-b911-41f1-b325-edaff5f0cdff', 'm_4-eebf8ea6-43d6-4114-96fb-76507f40ec73']", 'seller': 'm_4-eebf8ea6-43d6-4114-96fb-76507f40ec73', 'buyer': 'c_4-1729ce33-b911-41f1-b325-edaff5f0cdff'} 2019-02-27 11:34:10,853 - DEBUG - 5/10 [60.00%]: Contract [to be signed at 6]: ['c_3', 'm_3'] > {'time': 8, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_3-b37498e8-6619-4aec-b3a3-dd95bbefbb6d: buy 0 (t: 8, u: (0, 2.0), q: (1, 4))', 'partners': "['c_3-b37498e8-6619-4aec-b3a3-dd95bbefbb6d', 'm_3-dcea5638-aed1-4f6b-bf21-1a67e1bdefbd']", 'seller': 'm_3-dcea5638-aed1-4f6b-bf21-1a67e1bdefbd', 'buyer': 'c_3-b37498e8-6619-4aec-b3a3-dd95bbefbb6d'} 2019-02-27 11:34:10,853 - DEBUG - 5/10 [60.00%]: Contract [to be signed at 6]: ['c_0', 'm_2'] > {'time': 8, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_0-849400ab-19ff-42fa-bf65-10ef2f795a6f: buy 0 (t: 8, u: (0, 2.0), q: (1, 4))', 'partners': "['c_0-849400ab-19ff-42fa-bf65-10ef2f795a6f', 'm_2-577afd33-5aed-4647-8f4a-17a41dca4d54']", 'seller': 'm_2-577afd33-5aed-4647-8f4a-17a41dca4d54', 'buyer': 'c_0-849400ab-19ff-42fa-bf65-10ef2f795a6f'} 2019-02-27 11:34:10,854 - DEBUG - 5/10 [60.00%]: Contract [to be signed at 6]: ['c_1', 'm_3'] > {'time': 8, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_1-83f7bb54-0275-47dc-8c43-bd0e2b2744d4: buy 0 (t: 8, u: (0, 2.0), q: (1, 4))', 'partners': "['c_1-83f7bb54-0275-47dc-8c43-bd0e2b2744d4', 'm_3-dcea5638-aed1-4f6b-bf21-1a67e1bdefbd']", 'seller': 'm_3-dcea5638-aed1-4f6b-bf21-1a67e1bdefbd', 'buyer': 'c_1-83f7bb54-0275-47dc-8c43-bd0e2b2744d4'} 2019-02-27 11:34:10,854 - DEBUG - 5/10 [60.00%]: Contract [to be signed at 6]: ['c_3', 'm_4'] > {'time': 8, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_3-b37498e8-6619-4aec-b3a3-dd95bbefbb6d: buy 0 (t: 8, u: (0, 2.0), q: (1, 4))', 'partners': "['c_3-b37498e8-6619-4aec-b3a3-dd95bbefbb6d', 'm_4-eebf8ea6-43d6-4114-96fb-76507f40ec73']", 'seller': 'm_4-eebf8ea6-43d6-4114-96fb-76507f40ec73', 'buyer': 'c_3-b37498e8-6619-4aec-b3a3-dd95bbefbb6d'} 2019-02-27 11:34:10,854 - DEBUG - 5/10 [60.00%]: Contract [to be signed at 6]: ['c_2', 'm_4'] > {'time': 8, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_2-04df9282-7b04-48c4-a56c-066f6691dd4e: buy 0 (t: 8, u: (0, 2.0), q: (1, 3))', 'partners': "['c_2-04df9282-7b04-48c4-a56c-066f6691dd4e', 'm_4-eebf8ea6-43d6-4114-96fb-76507f40ec73']", 'seller': 'm_4-eebf8ea6-43d6-4114-96fb-76507f40ec73', 'buyer': 'c_2-04df9282-7b04-48c4-a56c-066f6691dd4e'} 2019-02-27 11:34:10,855 - DEBUG - 5/10 [60.00%]: Contract [to be signed at 6]: ['c_3', 'm_0'] > {'time': 8, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_3-b37498e8-6619-4aec-b3a3-dd95bbefbb6d: buy 0 (t: 8, u: (0, 2.0), q: (1, 4))', 'partners': "['c_3-b37498e8-6619-4aec-b3a3-dd95bbefbb6d', 'm_0-6a7c0ac4-5a18-4feb-bcc1-a5a67aa1e7c5']", 'seller': 'm_0-6a7c0ac4-5a18-4feb-bcc1-a5a67aa1e7c5', 'buyer': 'c_3-b37498e8-6619-4aec-b3a3-dd95bbefbb6d'} 2019-02-27 11:34:10,856 - INFO - 5/10 [60.00%]: m_0 requested negmas.sao.SAOMechanism[None] with ['c_1', 'm_0'] (ID 38e7318e-628f-44ac-a639-168038a8e7c2) 2019-02-27 11:34:10,857 - INFO - 5/10 [60.00%]: m_0-6a7c0ac4-5a18-4feb-bcc1-a5a67aa1e7c5 request was accepted 2019-02-27 11:34:10,858 - INFO - 5/10 [60.00%]: m_1 requested negmas.sao.SAOMechanism[None] with ['c_1', 'm_1'] (ID e261740c-688f-4330-b3fd-514963ac1e98) 2019-02-27 11:34:10,858 - INFO - 5/10 [60.00%]: m_1-02672ede-8506-42d2-9911-04211fcde6e5 request was accepted 2019-02-27 11:34:10,859 - INFO - 5/10 [60.00%]: m_2 requested negmas.sao.SAOMechanism[None] with ['c_1', 'm_2'] (ID 490fcb8a-3013-482b-baeb-b6c501a2b9cf) 2019-02-27 11:34:10,860 - INFO - 5/10 [60.00%]: m_2-577afd33-5aed-4647-8f4a-17a41dca4d54 request was accepted 2019-02-27 11:34:10,861 - INFO - 5/10 [60.00%]: m_3 requested negmas.sao.SAOMechanism[None] with ['c_1', 'm_3'] (ID 34a614c0-0c51-4f15-b7bf-e00a8314398a) 2019-02-27 11:34:10,861 - INFO - 5/10 [60.00%]: m_3-dcea5638-aed1-4f6b-bf21-1a67e1bdefbd request was accepted 2019-02-27 11:34:10,862 - INFO - 5/10 [60.00%]: m_4 requested negmas.sao.SAOMechanism[None] with ['c_1', 'm_4'] (ID c5328638-c54f-4578-922c-62419e284afe) 2019-02-27 11:34:10,862 - INFO - 5/10 [60.00%]: m_4-eebf8ea6-43d6-4114-96fb-76507f40ec73 request was accepted 2019-02-27 11:34:10,865 - INFO - 5/10 [60.00%]: m_0 requested negmas.sao.SAOMechanism[None] with ['c_3', 'm_0'] (ID 445b5c44-11e7-4169-a9b6-39afda793259) 2019-02-27 11:34:10,865 - INFO - 5/10 [60.00%]: m_0-6a7c0ac4-5a18-4feb-bcc1-a5a67aa1e7c5 request was accepted 2019-02-27 11:34:10,867 - INFO - 5/10 [60.00%]: m_1 requested negmas.sao.SAOMechanism[None] with ['c_3', 'm_1'] (ID 577e4509-3538-4216-8bc3-258ed933d3f0) 2019-02-27 11:34:10,868 - INFO - 5/10 [60.00%]: m_1-02672ede-8506-42d2-9911-04211fcde6e5 request was accepted 2019-02-27 11:34:10,869 - INFO - 5/10 [60.00%]: m_2 requested negmas.sao.SAOMechanism[None] with ['c_3', 'm_2'] (ID d02a8595-a754-4cea-bdf3-e3eeecea4e55) 2019-02-27 11:34:10,869 - INFO - 5/10 [60.00%]: m_2-577afd33-5aed-4647-8f4a-17a41dca4d54 request was accepted 2019-02-27 11:34:10,870 - INFO - 5/10 [60.00%]: m_3 requested negmas.sao.SAOMechanism[None] with ['c_3', 'm_3'] (ID 10476b8b-cf9b-42d0-9d30-5b9e34e222c7) 2019-02-27 11:34:10,871 - INFO - 5/10 [60.00%]: m_3-dcea5638-aed1-4f6b-bf21-1a67e1bdefbd request was accepted 2019-02-27 11:34:10,872 - INFO - 5/10 [60.00%]: m_4 requested negmas.sao.SAOMechanism[None] with ['c_3', 'm_4'] (ID 5094e635-03b6-4788-b26b-6b4a3e2c7283) 2019-02-27 11:34:10,873 - INFO - 5/10 [60.00%]: m_4-eebf8ea6-43d6-4114-96fb-76507f40ec73 request was accepted 2019-02-27 11:34:10,874 - INFO - 5/10 [60.00%]: m_0 requested negmas.sao.SAOMechanism[None] with ['c_0', 'm_0'] (ID 63da1d1c-a38c-4cbf-8459-b6715cd105c0) 2019-02-27 11:34:10,875 - INFO - 5/10 [60.00%]: m_0-6a7c0ac4-5a18-4feb-bcc1-a5a67aa1e7c5 request was accepted 2019-02-27 11:34:10,876 - INFO - 5/10 [60.00%]: m_1 requested negmas.sao.SAOMechanism[None] with ['c_0', 'm_1'] (ID c4cb444e-aae7-4d43-baaf-c173affe873e) 2019-02-27 11:34:10,876 - INFO - 5/10 [60.00%]: m_1-02672ede-8506-42d2-9911-04211fcde6e5 request was accepted 2019-02-27 11:34:10,877 - INFO - 5/10 [60.00%]: m_2 requested negmas.sao.SAOMechanism[None] with ['c_0', 'm_2'] (ID e5454f98-98aa-4179-b439-76699bf426a0) 2019-02-27 11:34:10,878 - INFO - 5/10 [60.00%]: m_2-577afd33-5aed-4647-8f4a-17a41dca4d54 request was accepted 2019-02-27 11:34:10,879 - INFO - 5/10 [60.00%]: m_3 requested negmas.sao.SAOMechanism[None] with ['c_0', 'm_3'] (ID 9077da33-4436-4a00-8ec9-75256858055c) 2019-02-27 11:34:10,879 - INFO - 5/10 [60.00%]: m_3-dcea5638-aed1-4f6b-bf21-1a67e1bdefbd request was accepted 2019-02-27 11:34:10,880 - INFO - 5/10 [60.00%]: m_4 requested negmas.sao.SAOMechanism[None] with ['c_0', 'm_4'] (ID e69b9487-a2b5-4dfd-8f29-f1993948b9b7) 2019-02-27 11:34:10,881 - INFO - 5/10 [60.00%]: m_4-eebf8ea6-43d6-4114-96fb-76507f40ec73 request was accepted 2019-02-27 11:34:10,883 - INFO - 5/10 [60.00%]: m_0 requested negmas.sao.SAOMechanism[None] with ['c_2', 'm_0'] (ID 3ac7db99-06e3-46e1-9385-e5ee73eed019) 2019-02-27 11:34:10,883 - INFO - 5/10 [60.00%]: m_0-6a7c0ac4-5a18-4feb-bcc1-a5a67aa1e7c5 request was accepted 2019-02-27 11:34:10,884 - INFO - 5/10 [60.00%]: m_1 requested negmas.sao.SAOMechanism[None] with ['c_2', 'm_1'] (ID d6cbecaf-0848-414a-8205-ad75f03af07f) 2019-02-27 11:34:10,885 - INFO - 5/10 [60.00%]: m_1-02672ede-8506-42d2-9911-04211fcde6e5 request was accepted 2019-02-27 11:34:10,886 - INFO - 5/10 [60.00%]: m_2 requested negmas.sao.SAOMechanism[None] with ['c_2', 'm_2'] (ID 6f0a7840-56b9-45a3-ac35-7ff21dc10128) 2019-02-27 11:34:10,886 - INFO - 5/10 [60.00%]: m_2-577afd33-5aed-4647-8f4a-17a41dca4d54 request was accepted 2019-02-27 11:34:10,887 - INFO - 5/10 [60.00%]: m_3 requested negmas.sao.SAOMechanism[None] with ['c_2', 'm_3'] (ID 5aafae8a-7693-433f-8568-5b632f666ec3) 2019-02-27 11:34:10,888 - INFO - 5/10 [60.00%]: m_3-dcea5638-aed1-4f6b-bf21-1a67e1bdefbd request was accepted 2019-02-27 11:34:10,889 - INFO - 5/10 [60.00%]: m_4 requested negmas.sao.SAOMechanism[None] with ['c_2', 'm_4'] (ID 9d1b90ac-b7ae-4049-9540-588c238c1d40) 2019-02-27 11:34:10,889 - INFO - 5/10 [60.00%]: m_4-eebf8ea6-43d6-4114-96fb-76507f40ec73 request was accepted 2019-02-27 11:34:10,891 - INFO - 5/10 [60.00%]: m_0 requested negmas.sao.SAOMechanism[None] with ['c_4', 'm_0'] (ID 71820251-e3b3-40a8-a969-adc49beff0f9) 2019-02-27 11:34:10,891 - INFO - 5/10 [60.00%]: m_0-6a7c0ac4-5a18-4feb-bcc1-a5a67aa1e7c5 request was accepted 2019-02-27 11:34:10,893 - INFO - 5/10 [60.00%]: m_1 requested negmas.sao.SAOMechanism[None] with ['c_4', 'm_1'] (ID 2d4e43c7-7a66-4089-8e09-1126a250474f) 2019-02-27 11:34:10,893 - INFO - 5/10 [60.00%]: m_1-02672ede-8506-42d2-9911-04211fcde6e5 request was accepted 2019-02-27 11:34:10,895 - INFO - 5/10 [60.00%]: m_2 requested negmas.sao.SAOMechanism[None] with ['c_4', 'm_2'] (ID 01253073-1565-400d-a707-9a8cc0982fa8) 2019-02-27 11:34:10,895 - INFO - 5/10 [60.00%]: m_2-577afd33-5aed-4647-8f4a-17a41dca4d54 request was accepted 2019-02-27 11:34:10,896 - INFO - 5/10 [60.00%]: m_3 requested negmas.sao.SAOMechanism[None] with ['c_4', 'm_3'] (ID 0dab47ee-afe8-435a-baae-94037850b4ea) 2019-02-27 11:34:10,897 - INFO - 5/10 [60.00%]: m_3-dcea5638-aed1-4f6b-bf21-1a67e1bdefbd request was accepted 2019-02-27 11:34:10,898 - INFO - 5/10 [60.00%]: m_4 requested negmas.sao.SAOMechanism[None] with ['c_4', 'm_4'] (ID 74e0c5e8-1a59-4962-ab33-44b7ac4064e8) 2019-02-27 11:34:10,899 - INFO - 5/10 [60.00%]: m_4-eebf8ea6-43d6-4114-96fb-76507f40ec73 request was accepted 2019-02-27 11:34:10,899 - INFO - 5/10 [60.00%]: Executing c_1-83f7bb54-0275-47dc-8c43-bd0e2b2744d4, m_3-dcea5638-aed1-4f6b-bf21-1a67e1bdefbd agreed on {'time': 5, 'quantity': 3, 'unit_price': 0.5} 2019-02-27 11:34:10,899 - DEBUG - 5/10 [60.00%]: Moved 3 units of p0 from m_3 to c_1 for 1.5 dollars 2019-02-27 11:34:10,899 - INFO - 5/10 [60.00%]: Executing c_0-849400ab-19ff-42fa-bf65-10ef2f795a6f, m_3-dcea5638-aed1-4f6b-bf21-1a67e1bdefbd agreed on {'time': 5, 'quantity': 4, 'unit_price': 0.5} 2019-02-27 11:34:10,899 - DEBUG - 5/10 [60.00%]: Moved 4 units of p0 from m_3 to c_0 for 2.0 dollars 2019-02-27 11:34:10,899 - INFO - 5/10 [60.00%]: Executing c_2-04df9282-7b04-48c4-a56c-066f6691dd4e, m_4-eebf8ea6-43d6-4114-96fb-76507f40ec73 agreed on {'time': 5, 'quantity': 3, 'unit_price': 0.5} 2019-02-27 11:34:10,899 - DEBUG - 5/10 [60.00%]: Moved 3 units of p0 from m_4 to c_2 for 1.5 dollars 2019-02-27 11:34:10,899 - INFO - 5/10 [60.00%]: Executing c_4-1729ce33-b911-41f1-b325-edaff5f0cdff, m_1-02672ede-8506-42d2-9911-04211fcde6e5 agreed on {'time': 5, 'quantity': 3, 'unit_price': 0.5} 2019-02-27 11:34:10,899 - DEBUG - 5/10 [60.00%]: Moved 3 units of p0 from m_1 to c_4 for 1.5 dollars 2019-02-27 11:34:10,899 - INFO - 5/10 [60.00%]: Executing c_3-b37498e8-6619-4aec-b3a3-dd95bbefbb6d, m_0-6a7c0ac4-5a18-4feb-bcc1-a5a67aa1e7c5 agreed on {'time': 5, 'quantity': 3, 'unit_price': 0.5} 2019-02-27 11:34:10,899 - DEBUG - 5/10 [60.00%]: Moved 3 units of p0 from m_0 to c_3 for 1.5 dollars 2019-02-27 11:34:10,899 - DEBUG - 5/10 [60.00%]: Factory 567c17c8-8bbd-4ebb-828c-d4860fd379b7: money=-6.5, storage={0: 6}, loans=0.0 2019-02-27 11:34:10,899 - DEBUG - 5/10 [60.00%]: Factory a0f4927d-1f5c-4f74-a2f7-aa8e774a27e3: money=-7.5, storage={0: 8}, loans=0.0 2019-02-27 11:34:10,900 - DEBUG - 5/10 [60.00%]: Factory 8a8fa7a0-f90e-4d14-959d-34b2b489efe1: money=-7.0, storage={0: 7}, loans=0.0 2019-02-27 11:34:10,900 - DEBUG - 5/10 [60.00%]: Factory c01b5ced-1ecd-491f-8503-d6b05067d41d: money=-7.0, storage={0: 7}, loans=0.0 2019-02-27 11:34:10,900 - DEBUG - 5/10 [60.00%]: Factory e4a66fab-f4f6-483a-bc31-5cab325cfe7f: money=-6.5, storage={0: 7}, loans=0.0 2019-02-27 11:34:10,900 - DEBUG - 5/10 [60.00%]: Factory ae788129-5389-405f-91bb-1dd70ada97a8: money=5.0, storage={0: -10}, loans=0.0 2019-02-27 11:34:10,900 - DEBUG - 5/10 [60.00%]: Factory ebf908e4-19c8-4171-ac89-c0ddba170b2f: money=10.5, storage={0: -21}, loans=0.0 2019-02-27 11:34:10,900 - DEBUG - 5/10 [60.00%]: Factory b3b8170f-8fca-486f-848a-69d82e617f52: money=2.0, storage={0: -4}, loans=0.0 2019-02-27 11:34:10,900 - DEBUG - 5/10 [60.00%]: Factory f5f00bb2-9f63-41d3-bbb2-270d5bc7268e: money=5.5, storage={0: -11}, loans=0.0 2019-02-27 11:34:10,900 - DEBUG - 5/10 [60.00%]: Factory 0f562fc9-74f3-4758-8c55-6045859782f5: money=11.5, storage={0: -23}, loans=0.0 2019-02-27 11:34:10,900 - INFO - 6/10 [70.00%]: 25 Negotiations/4 _entities 2019-02-27 11:34:11,136 - DEBUG - 6/10 [70.00%]: Contract [to be signed at 7]: ['c_0', 'm_4'] > {'time': 9, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_0-849400ab-19ff-42fa-bf65-10ef2f795a6f: buy 0 (t: 9, u: (0, 2.0), q: (1, 4))', 'partners': "['c_0-849400ab-19ff-42fa-bf65-10ef2f795a6f', 'm_4-eebf8ea6-43d6-4114-96fb-76507f40ec73']", 'seller': 'm_4-eebf8ea6-43d6-4114-96fb-76507f40ec73', 'buyer': 'c_0-849400ab-19ff-42fa-bf65-10ef2f795a6f'} 2019-02-27 11:34:11,136 - DEBUG - 6/10 [70.00%]: Contract [to be signed at 7]: ['c_0', 'm_3'] > {'time': 9, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_0-849400ab-19ff-42fa-bf65-10ef2f795a6f: buy 0 (t: 9, u: (0, 2.0), q: (1, 4))', 'partners': "['c_0-849400ab-19ff-42fa-bf65-10ef2f795a6f', 'm_3-dcea5638-aed1-4f6b-bf21-1a67e1bdefbd']", 'seller': 'm_3-dcea5638-aed1-4f6b-bf21-1a67e1bdefbd', 'buyer': 'c_0-849400ab-19ff-42fa-bf65-10ef2f795a6f'} 2019-02-27 11:34:11,137 - DEBUG - 6/10 [70.00%]: Contract [to be signed at 7]: ['c_4', 'm_4'] > {'time': 9, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_4-1729ce33-b911-41f1-b325-edaff5f0cdff: buy 0 (t: 9, u: (0, 2.0), q: (1, 4))', 'partners': "['c_4-1729ce33-b911-41f1-b325-edaff5f0cdff', 'm_4-eebf8ea6-43d6-4114-96fb-76507f40ec73']", 'seller': 'm_4-eebf8ea6-43d6-4114-96fb-76507f40ec73', 'buyer': 'c_4-1729ce33-b911-41f1-b325-edaff5f0cdff'} 2019-02-27 11:34:11,137 - DEBUG - 6/10 [70.00%]: Contract [to be signed at 7]: ['c_1', 'm_3'] > {'time': 9, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_1-83f7bb54-0275-47dc-8c43-bd0e2b2744d4: buy 0 (t: 9, u: (0, 2.0), q: (1, 3))', 'partners': "['c_1-83f7bb54-0275-47dc-8c43-bd0e2b2744d4', 'm_3-dcea5638-aed1-4f6b-bf21-1a67e1bdefbd']", 'seller': 'm_3-dcea5638-aed1-4f6b-bf21-1a67e1bdefbd', 'buyer': 'c_1-83f7bb54-0275-47dc-8c43-bd0e2b2744d4'} 2019-02-27 11:34:11,137 - DEBUG - 6/10 [70.00%]: Contract [to be signed at 7]: ['c_2', 'm_3'] > {'time': 9, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_2-04df9282-7b04-48c4-a56c-066f6691dd4e: buy 0 (t: 9, u: (0, 2.0), q: (1, 3))', 'partners': "['c_2-04df9282-7b04-48c4-a56c-066f6691dd4e', 'm_3-dcea5638-aed1-4f6b-bf21-1a67e1bdefbd']", 'seller': 'm_3-dcea5638-aed1-4f6b-bf21-1a67e1bdefbd', 'buyer': 'c_2-04df9282-7b04-48c4-a56c-066f6691dd4e'} 2019-02-27 11:34:11,138 - DEBUG - 6/10 [70.00%]: Contract [to be signed at 7]: ['c_2', 'm_2'] > {'time': 9, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_2-04df9282-7b04-48c4-a56c-066f6691dd4e: buy 0 (t: 9, u: (0, 2.0), q: (1, 3))', 'partners': "['c_2-04df9282-7b04-48c4-a56c-066f6691dd4e', 'm_2-577afd33-5aed-4647-8f4a-17a41dca4d54']", 'seller': 'm_2-577afd33-5aed-4647-8f4a-17a41dca4d54', 'buyer': 'c_2-04df9282-7b04-48c4-a56c-066f6691dd4e'} 2019-02-27 11:34:11,138 - DEBUG - 6/10 [70.00%]: Contract [to be signed at 7]: ['c_0', 'm_2'] > {'time': 9, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_0-849400ab-19ff-42fa-bf65-10ef2f795a6f: buy 0 (t: 9, u: (0, 2.0), q: (1, 4))', 'partners': "['c_0-849400ab-19ff-42fa-bf65-10ef2f795a6f', 'm_2-577afd33-5aed-4647-8f4a-17a41dca4d54']", 'seller': 'm_2-577afd33-5aed-4647-8f4a-17a41dca4d54', 'buyer': 'c_0-849400ab-19ff-42fa-bf65-10ef2f795a6f'} 2019-02-27 11:34:11,138 - DEBUG - 6/10 [70.00%]: Contract [to be signed at 7]: ['c_3', 'm_2'] > {'time': 9, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_3-b37498e8-6619-4aec-b3a3-dd95bbefbb6d: buy 0 (t: 9, u: (0, 2.0), q: (1, 4))', 'partners': "['c_3-b37498e8-6619-4aec-b3a3-dd95bbefbb6d', 'm_2-577afd33-5aed-4647-8f4a-17a41dca4d54']", 'seller': 'm_2-577afd33-5aed-4647-8f4a-17a41dca4d54', 'buyer': 'c_3-b37498e8-6619-4aec-b3a3-dd95bbefbb6d'} 2019-02-27 11:34:11,139 - DEBUG - 6/10 [70.00%]: Contract [to be signed at 7]: ['c_0', 'm_1'] > {'time': 9, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_0-849400ab-19ff-42fa-bf65-10ef2f795a6f: buy 0 (t: 9, u: (0, 2.0), q: (1, 4))', 'partners': "['c_0-849400ab-19ff-42fa-bf65-10ef2f795a6f', 'm_1-02672ede-8506-42d2-9911-04211fcde6e5']", 'seller': 'm_1-02672ede-8506-42d2-9911-04211fcde6e5', 'buyer': 'c_0-849400ab-19ff-42fa-bf65-10ef2f795a6f'} 2019-02-27 11:34:11,140 - DEBUG - 6/10 [70.00%]: Contract [to be signed at 7]: ['c_3', 'm_4'] > {'time': 9, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_3-b37498e8-6619-4aec-b3a3-dd95bbefbb6d: buy 0 (t: 9, u: (0, 2.0), q: (1, 4))', 'partners': "['c_3-b37498e8-6619-4aec-b3a3-dd95bbefbb6d', 'm_4-eebf8ea6-43d6-4114-96fb-76507f40ec73']", 'seller': 'm_4-eebf8ea6-43d6-4114-96fb-76507f40ec73', 'buyer': 'c_3-b37498e8-6619-4aec-b3a3-dd95bbefbb6d'} 2019-02-27 11:34:11,140 - DEBUG - 6/10 [70.00%]: Contract [to be signed at 7]: ['c_0', 'm_0'] > {'time': 9, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_0-849400ab-19ff-42fa-bf65-10ef2f795a6f: buy 0 (t: 9, u: (0, 2.0), q: (1, 4))', 'partners': "['c_0-849400ab-19ff-42fa-bf65-10ef2f795a6f', 'm_0-6a7c0ac4-5a18-4feb-bcc1-a5a67aa1e7c5']", 'seller': 'm_0-6a7c0ac4-5a18-4feb-bcc1-a5a67aa1e7c5', 'buyer': 'c_0-849400ab-19ff-42fa-bf65-10ef2f795a6f'} 2019-02-27 11:34:11,140 - DEBUG - 6/10 [70.00%]: Contract [to be signed at 7]: ['c_1', 'm_1'] > {'time': 9, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_1-83f7bb54-0275-47dc-8c43-bd0e2b2744d4: buy 0 (t: 9, u: (0, 2.0), q: (1, 3))', 'partners': "['c_1-83f7bb54-0275-47dc-8c43-bd0e2b2744d4', 'm_1-02672ede-8506-42d2-9911-04211fcde6e5']", 'seller': 'm_1-02672ede-8506-42d2-9911-04211fcde6e5', 'buyer': 'c_1-83f7bb54-0275-47dc-8c43-bd0e2b2744d4'} 2019-02-27 11:34:11,140 - DEBUG - 6/10 [70.00%]: Contract [to be signed at 7]: ['c_1', 'm_2'] > {'time': 9, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_1-83f7bb54-0275-47dc-8c43-bd0e2b2744d4: buy 0 (t: 9, u: (0, 2.0), q: (1, 3))', 'partners': "['c_1-83f7bb54-0275-47dc-8c43-bd0e2b2744d4', 'm_2-577afd33-5aed-4647-8f4a-17a41dca4d54']", 'seller': 'm_2-577afd33-5aed-4647-8f4a-17a41dca4d54', 'buyer': 'c_1-83f7bb54-0275-47dc-8c43-bd0e2b2744d4'} 2019-02-27 11:34:11,141 - DEBUG - 6/10 [70.00%]: Contract [to be signed at 7]: ['c_4', 'm_0'] > {'time': 9, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_4-1729ce33-b911-41f1-b325-edaff5f0cdff: buy 0 (t: 9, u: (0, 2.0), q: (1, 4))', 'partners': "['c_4-1729ce33-b911-41f1-b325-edaff5f0cdff', 'm_0-6a7c0ac4-5a18-4feb-bcc1-a5a67aa1e7c5']", 'seller': 'm_0-6a7c0ac4-5a18-4feb-bcc1-a5a67aa1e7c5', 'buyer': 'c_4-1729ce33-b911-41f1-b325-edaff5f0cdff'} 2019-02-27 11:34:11,141 - DEBUG - 6/10 [70.00%]: Contract [to be signed at 7]: ['c_2', 'm_0'] > {'time': 9, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_2-04df9282-7b04-48c4-a56c-066f6691dd4e: buy 0 (t: 9, u: (0, 2.0), q: (1, 3))', 'partners': "['c_2-04df9282-7b04-48c4-a56c-066f6691dd4e', 'm_0-6a7c0ac4-5a18-4feb-bcc1-a5a67aa1e7c5']", 'seller': 'm_0-6a7c0ac4-5a18-4feb-bcc1-a5a67aa1e7c5', 'buyer': 'c_2-04df9282-7b04-48c4-a56c-066f6691dd4e'} 2019-02-27 11:34:11,141 - DEBUG - 6/10 [70.00%]: Contract [to be signed at 7]: ['c_2', 'm_4'] > {'time': 9, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_2-04df9282-7b04-48c4-a56c-066f6691dd4e: buy 0 (t: 9, u: (0, 2.0), q: (1, 3))', 'partners': "['c_2-04df9282-7b04-48c4-a56c-066f6691dd4e', 'm_4-eebf8ea6-43d6-4114-96fb-76507f40ec73']", 'seller': 'm_4-eebf8ea6-43d6-4114-96fb-76507f40ec73', 'buyer': 'c_2-04df9282-7b04-48c4-a56c-066f6691dd4e'} 2019-02-27 11:34:11,142 - DEBUG - 6/10 [70.00%]: Contract [to be signed at 7]: ['c_3', 'm_3'] > {'time': 9, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_3-b37498e8-6619-4aec-b3a3-dd95bbefbb6d: buy 0 (t: 9, u: (0, 2.0), q: (1, 4))', 'partners': "['c_3-b37498e8-6619-4aec-b3a3-dd95bbefbb6d', 'm_3-dcea5638-aed1-4f6b-bf21-1a67e1bdefbd']", 'seller': 'm_3-dcea5638-aed1-4f6b-bf21-1a67e1bdefbd', 'buyer': 'c_3-b37498e8-6619-4aec-b3a3-dd95bbefbb6d'} 2019-02-27 11:34:11,188 - DEBUG - 6/10 [70.00%]: Contract [to be signed at 7]: ['c_2', 'm_1'] > {'time': 9, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_2-04df9282-7b04-48c4-a56c-066f6691dd4e: buy 0 (t: 9, u: (0, 2.0), q: (1, 3))', 'partners': "['c_2-04df9282-7b04-48c4-a56c-066f6691dd4e', 'm_1-02672ede-8506-42d2-9911-04211fcde6e5']", 'seller': 'm_1-02672ede-8506-42d2-9911-04211fcde6e5', 'buyer': 'c_2-04df9282-7b04-48c4-a56c-066f6691dd4e'} 2019-02-27 11:34:11,188 - DEBUG - 6/10 [70.00%]: Contract [to be signed at 7]: ['c_3', 'm_1'] > {'time': 9, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_3-b37498e8-6619-4aec-b3a3-dd95bbefbb6d: buy 0 (t: 9, u: (0, 2.0), q: (1, 4))', 'partners': "['c_3-b37498e8-6619-4aec-b3a3-dd95bbefbb6d', 'm_1-02672ede-8506-42d2-9911-04211fcde6e5']", 'seller': 'm_1-02672ede-8506-42d2-9911-04211fcde6e5', 'buyer': 'c_3-b37498e8-6619-4aec-b3a3-dd95bbefbb6d'} 2019-02-27 11:34:11,189 - DEBUG - 6/10 [70.00%]: Contract [to be signed at 7]: ['c_1', 'm_4'] > {'time': 9, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_1-83f7bb54-0275-47dc-8c43-bd0e2b2744d4: buy 0 (t: 9, u: (0, 2.0), q: (1, 3))', 'partners': "['c_1-83f7bb54-0275-47dc-8c43-bd0e2b2744d4', 'm_4-eebf8ea6-43d6-4114-96fb-76507f40ec73']", 'seller': 'm_4-eebf8ea6-43d6-4114-96fb-76507f40ec73', 'buyer': 'c_1-83f7bb54-0275-47dc-8c43-bd0e2b2744d4'} 2019-02-27 11:34:11,189 - DEBUG - 6/10 [70.00%]: Contract [to be signed at 7]: ['c_4', 'm_2'] > {'time': 9, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_4-1729ce33-b911-41f1-b325-edaff5f0cdff: buy 0 (t: 9, u: (0, 2.0), q: (1, 4))', 'partners': "['c_4-1729ce33-b911-41f1-b325-edaff5f0cdff', 'm_2-577afd33-5aed-4647-8f4a-17a41dca4d54']", 'seller': 'm_2-577afd33-5aed-4647-8f4a-17a41dca4d54', 'buyer': 'c_4-1729ce33-b911-41f1-b325-edaff5f0cdff'} 2019-02-27 11:34:11,189 - DEBUG - 6/10 [70.00%]: Contract [to be signed at 7]: ['c_1', 'm_0'] > {'time': 9, 'quantity': 3, 'unit_price': 0.5} on annotation {'cfp': 'c_1-83f7bb54-0275-47dc-8c43-bd0e2b2744d4: buy 0 (t: 9, u: (0, 2.0), q: (1, 3))', 'partners': "['c_1-83f7bb54-0275-47dc-8c43-bd0e2b2744d4', 'm_0-6a7c0ac4-5a18-4feb-bcc1-a5a67aa1e7c5']", 'seller': 'm_0-6a7c0ac4-5a18-4feb-bcc1-a5a67aa1e7c5', 'buyer': 'c_1-83f7bb54-0275-47dc-8c43-bd0e2b2744d4'} 2019-02-27 11:34:11,190 - DEBUG - 6/10 [70.00%]: Contract [to be signed at 7]: ['c_3', 'm_0'] > {'time': 9, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_3-b37498e8-6619-4aec-b3a3-dd95bbefbb6d: buy 0 (t: 9, u: (0, 2.0), q: (1, 4))', 'partners': "['c_3-b37498e8-6619-4aec-b3a3-dd95bbefbb6d', 'm_0-6a7c0ac4-5a18-4feb-bcc1-a5a67aa1e7c5']", 'seller': 'm_0-6a7c0ac4-5a18-4feb-bcc1-a5a67aa1e7c5', 'buyer': 'c_3-b37498e8-6619-4aec-b3a3-dd95bbefbb6d'} 2019-02-27 11:34:11,190 - DEBUG - 6/10 [70.00%]: Contract [to be signed at 7]: ['c_4', 'm_3'] > {'time': 9, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_4-1729ce33-b911-41f1-b325-edaff5f0cdff: buy 0 (t: 9, u: (0, 2.0), q: (1, 4))', 'partners': "['c_4-1729ce33-b911-41f1-b325-edaff5f0cdff', 'm_3-dcea5638-aed1-4f6b-bf21-1a67e1bdefbd']", 'seller': 'm_3-dcea5638-aed1-4f6b-bf21-1a67e1bdefbd', 'buyer': 'c_4-1729ce33-b911-41f1-b325-edaff5f0cdff'} 2019-02-27 11:34:11,191 - DEBUG - 6/10 [70.00%]: Contract [to be signed at 7]: ['c_4', 'm_1'] > {'time': 9, 'quantity': 4, 'unit_price': 0.5} on annotation {'cfp': 'c_4-1729ce33-b911-41f1-b325-edaff5f0cdff: buy 0 (t: 9, u: (0, 2.0), q: (1, 4))', 'partners': "['c_4-1729ce33-b911-41f1-b325-edaff5f0cdff', 'm_1-02672ede-8506-42d2-9911-04211fcde6e5']", 'seller': 'm_1-02672ede-8506-42d2-9911-04211fcde6e5', 'buyer': 'c_4-1729ce33-b911-41f1-b325-edaff5f0cdff'} 2019-02-27 11:34:11,193 - INFO - 6/10 [70.00%]: Executing c_2-04df9282-7b04-48c4-a56c-066f6691dd4e, m_3-dcea5638-aed1-4f6b-bf21-1a67e1bdefbd agreed on {'time': 6, 'quantity': 4, 'unit_price': 0.5} 2019-02-27 11:34:11,193 - DEBUG - 6/10 [70.00%]: Moved 4 units of p0 from m_3 to c_2 for 2.0 dollars 2019-02-27 11:34:11,193 - INFO - 6/10 [70.00%]: Executing c_1-83f7bb54-0275-47dc-8c43-bd0e2b2744d4, m_1-02672ede-8506-42d2-9911-04211fcde6e5 agreed on {'time': 6, 'quantity': 4, 'unit_price': 0.5} 2019-02-27 11:34:11,193 - DEBUG - 6/10 [70.00%]: Moved 4 units of p0 from m_1 to c_1 for 2.0 dollars 2019-02-27 11:34:11,193 - INFO - 6/10 [70.00%]: Executing c_4-1729ce33-b911-41f1-b325-edaff5f0cdff, m_2-577afd33-5aed-4647-8f4a-17a41dca4d54 agreed on {'time': 6, 'quantity': 4, 'unit_price': 0.5} 2019-02-27 11:34:11,193 - DEBUG - 6/10 [70.00%]: Moved 4 units of p0 from m_2 to c_4 for 2.0 dollars 2019-02-27 11:34:11,193 - INFO - 6/10 [70.00%]: Executing c_3-b37498e8-6619-4aec-b3a3-dd95bbefbb6d, m_4-eebf8ea6-43d6-4114-96fb-76507f40ec73 agreed on {'time': 6, 'quantity': 3, 'unit_price': 0.5} 2019-02-27 11:34:11,193 - DEBUG - 6/10 [70.00%]: Moved 3 units of p0 from m_4 to c_3 for 1.5 dollars 2019-02-27 11:34:11,193 - INFO - 6/10 [70.00%]: Executing c_0-849400ab-19ff-42fa-bf65-10ef2f795a6f, m_1-02672ede-8506-42d2-9911-04211fcde6e5 agreed on {'time': 6, 'quantity': 4, 'unit_price': 0.5} 2019-02-27 11:34:11,193 - DEBUG - 6/10 [70.00%]: Moved 4 units of p0 from m_1 to c_0 for 2.0 dollars 2019-02-27 11:34:11,193 - DEBUG - 6/10 [70.00%]: Factory 567c17c8-8bbd-4ebb-828c-d4860fd379b7: money=-8.5, storage={0: 9}, loans=0.0 2019-02-27 11:34:11,193 - DEBUG - 6/10 [70.00%]: Factory a0f4927d-1f5c-4f74-a2f7-aa8e774a27e3: money=-9.5, storage={0: 12}, loans=0.0 2019-02-27 11:34:11,193 - DEBUG - 6/10 [70.00%]: Factory 8a8fa7a0-f90e-4d14-959d-34b2b489efe1: money=-9.0, storage={0: 11}, loans=0.0 2019-02-27 11:34:11,193 - DEBUG - 6/10 [70.00%]: Factory c01b5ced-1ecd-491f-8503-d6b05067d41d: money=-8.5, storage={0: 11}, loans=0.0 2019-02-27 11:34:11,194 - DEBUG - 6/10 [70.00%]: Factory e4a66fab-f4f6-483a-bc31-5cab325cfe7f: money=-8.5, storage={0: 10}, loans=0.0 2019-02-27 11:34:11,194 - DEBUG - 6/10 [70.00%]: Factory ae788129-5389-405f-91bb-1dd70ada97a8: money=5.0, storage={0: -10}, loans=0.0 2019-02-27 11:34:11,194 - DEBUG - 6/10 [70.00%]: Factory ebf908e4-19c8-4171-ac89-c0ddba170b2f: money=14.5, storage={0: -29}, loans=0.0 2019-02-27 11:34:11,194 - DEBUG - 6/10 [70.00%]: Factory b3b8170f-8fca-486f-848a-69d82e617f52: money=4.0, storage={0: -8}, loans=0.0 2019-02-27 11:34:11,194 - DEBUG - 6/10 [70.00%]: Factory f5f00bb2-9f63-41d3-bbb2-270d5bc7268e: money=7.5, storage={0: -15}, loans=0.0 2019-02-27 11:34:11,194 - DEBUG - 6/10 [70.00%]: Factory 0f562fc9-74f3-4758-8c55-6045859782f5: money=13.0, storage={0: -26}, loans=0.0 2019-02-27 11:34:11,194 - INFO - 7/10 [80.00%]: 0 Negotiations/4 _entities 2019-02-27 11:34:11,195 - INFO - 7/10 [80.00%]: Executing c_2-04df9282-7b04-48c4-a56c-066f6691dd4e, m_3-dcea5638-aed1-4f6b-bf21-1a67e1bdefbd agreed on {'time': 7, 'quantity': 4, 'unit_price': 0.5} 2019-02-27 11:34:11,196 - DEBUG - 7/10 [80.00%]: Moved 4 units of p0 from m_3 to c_2 for 2.0 dollars 2019-02-27 11:34:11,196 - INFO - 7/10 [80.00%]: Executing c_4-1729ce33-b911-41f1-b325-edaff5f0cdff, m_0-6a7c0ac4-5a18-4feb-bcc1-a5a67aa1e7c5 agreed on {'time': 7, 'quantity': 4, 'unit_price': 0.5} 2019-02-27 11:34:11,196 - DEBUG - 7/10 [80.00%]: Moved 4 units of p0 from m_0 to c_4 for 2.0 dollars 2019-02-27 11:34:11,196 - INFO - 7/10 [80.00%]: Executing c_0-849400ab-19ff-42fa-bf65-10ef2f795a6f, m_1-02672ede-8506-42d2-9911-04211fcde6e5 agreed on {'time': 7, 'quantity': 4, 'unit_price': 0.5} 2019-02-27 11:34:11,196 - DEBUG - 7/10 [80.00%]: Moved 4 units of p0 from m_1 to c_0 for 2.0 dollars 2019-02-27 11:34:11,196 - INFO - 7/10 [80.00%]: Executing c_3-b37498e8-6619-4aec-b3a3-dd95bbefbb6d, m_3-dcea5638-aed1-4f6b-bf21-1a67e1bdefbd agreed on {'time': 7, 'quantity': 3, 'unit_price': 0.5} 2019-02-27 11:34:11,196 - DEBUG - 7/10 [80.00%]: Moved 3 units of p0 from m_3 to c_3 for 1.5 dollars 2019-02-27 11:34:11,196 - INFO - 7/10 [80.00%]: Executing c_1-83f7bb54-0275-47dc-8c43-bd0e2b2744d4, m_3-dcea5638-aed1-4f6b-bf21-1a67e1bdefbd agreed on {'time': 7, 'quantity': 4, 'unit_price': 0.5} 2019-02-27 11:34:11,196 - DEBUG - 7/10 [80.00%]: Moved 4 units of p0 from m_3 to c_1 for 2.0 dollars 2019-02-27 11:34:11,196 - DEBUG - 7/10 [80.00%]: Factory 567c17c8-8bbd-4ebb-828c-d4860fd379b7: money=-10.5, storage={0: 13}, loans=0.0 2019-02-27 11:34:11,196 - DEBUG - 7/10 [80.00%]: Factory a0f4927d-1f5c-4f74-a2f7-aa8e774a27e3: money=-11.5, storage={0: 15}, loans=0.0 2019-02-27 11:34:11,196 - DEBUG - 7/10 [80.00%]: Factory 8a8fa7a0-f90e-4d14-959d-34b2b489efe1: money=-11.0, storage={0: 14}, loans=0.0 2019-02-27 11:34:11,197 - DEBUG - 7/10 [80.00%]: Factory c01b5ced-1ecd-491f-8503-d6b05067d41d: money=-10.0, storage={0: 14}, loans=0.0 2019-02-27 11:34:11,197 - DEBUG - 7/10 [80.00%]: Factory e4a66fab-f4f6-483a-bc31-5cab325cfe7f: money=-10.5, storage={0: 13}, loans=0.0 2019-02-27 11:34:11,197 - DEBUG - 7/10 [80.00%]: Factory ae788129-5389-405f-91bb-1dd70ada97a8: money=7.0, storage={0: -14}, loans=0.0 2019-02-27 11:34:11,197 - DEBUG - 7/10 [80.00%]: Factory ebf908e4-19c8-4171-ac89-c0ddba170b2f: money=16.5, storage={0: -33}, loans=0.0 2019-02-27 11:34:11,197 - DEBUG - 7/10 [80.00%]: Factory b3b8170f-8fca-486f-848a-69d82e617f52: money=4.0, storage={0: -8}, loans=0.0 2019-02-27 11:34:11,197 - DEBUG - 7/10 [80.00%]: Factory f5f00bb2-9f63-41d3-bbb2-270d5bc7268e: money=13.0, storage={0: -26}, loans=0.0 2019-02-27 11:34:11,197 - DEBUG - 7/10 [80.00%]: Factory 0f562fc9-74f3-4758-8c55-6045859782f5: money=13.0, storage={0: -26}, loans=0.0 2019-02-27 11:34:11,197 - INFO - 8/10 [90.00%]: 0 Negotiations/4 _entities 2019-02-27 11:34:11,198 - INFO - 8/10 [90.00%]: Executing c_0-849400ab-19ff-42fa-bf65-10ef2f795a6f, m_4-eebf8ea6-43d6-4114-96fb-76507f40ec73 agreed on {'time': 8, 'quantity': 4, 'unit_price': 0.5} 2019-02-27 11:34:11,198 - DEBUG - 8/10 [90.00%]: Moved 4 units of p0 from m_4 to c_0 for 2.0 dollars 2019-02-27 11:34:11,198 - INFO - 8/10 [90.00%]: Executing c_2-04df9282-7b04-48c4-a56c-066f6691dd4e, m_1-02672ede-8506-42d2-9911-04211fcde6e5 agreed on {'time': 8, 'quantity': 3, 'unit_price': 0.5} 2019-02-27 11:34:11,198 - DEBUG - 8/10 [90.00%]: Moved 3 units of p0 from m_1 to c_2 for 1.5 dollars 2019-02-27 11:34:11,198 - INFO - 8/10 [90.00%]: Executing c_1-83f7bb54-0275-47dc-8c43-bd0e2b2744d4, m_1-02672ede-8506-42d2-9911-04211fcde6e5 agreed on {'time': 8, 'quantity': 4, 'unit_price': 0.5} 2019-02-27 11:34:11,198 - DEBUG - 8/10 [90.00%]: Moved 4 units of p0 from m_1 to c_1 for 2.0 dollars 2019-02-27 11:34:11,198 - INFO - 8/10 [90.00%]: Executing c_4-1729ce33-b911-41f1-b325-edaff5f0cdff, m_4-eebf8ea6-43d6-4114-96fb-76507f40ec73 agreed on {'time': 8, 'quantity': 4, 'unit_price': 0.5} 2019-02-27 11:34:11,199 - DEBUG - 8/10 [90.00%]: Moved 4 units of p0 from m_4 to c_4 for 2.0 dollars 2019-02-27 11:34:11,199 - INFO - 8/10 [90.00%]: Executing c_3-b37498e8-6619-4aec-b3a3-dd95bbefbb6d, m_3-dcea5638-aed1-4f6b-bf21-1a67e1bdefbd agreed on {'time': 8, 'quantity': 4, 'unit_price': 0.5} 2019-02-27 11:34:11,199 - DEBUG - 8/10 [90.00%]: Moved 4 units of p0 from m_3 to c_3 for 2.0 dollars 2019-02-27 11:34:11,199 - DEBUG - 8/10 [90.00%]: Factory 567c17c8-8bbd-4ebb-828c-d4860fd379b7: money=-12.5, storage={0: 17}, loans=0.0 2019-02-27 11:34:11,199 - DEBUG - 8/10 [90.00%]: Factory a0f4927d-1f5c-4f74-a2f7-aa8e774a27e3: money=-13.5, storage={0: 19}, loans=0.0 2019-02-27 11:34:11,199 - DEBUG - 8/10 [90.00%]: Factory 8a8fa7a0-f90e-4d14-959d-34b2b489efe1: money=-12.5, storage={0: 18}, loans=0.0 2019-02-27 11:34:11,199 - DEBUG - 8/10 [90.00%]: Factory c01b5ced-1ecd-491f-8503-d6b05067d41d: money=-12.0, storage={0: 17}, loans=0.0 2019-02-27 11:34:11,199 - DEBUG - 8/10 [90.00%]: Factory e4a66fab-f4f6-483a-bc31-5cab325cfe7f: money=-12.5, storage={0: 17}, loans=0.0 2019-02-27 11:34:11,199 - DEBUG - 8/10 [90.00%]: Factory ae788129-5389-405f-91bb-1dd70ada97a8: money=7.0, storage={0: -14}, loans=0.0 2019-02-27 11:34:11,199 - DEBUG - 8/10 [90.00%]: Factory ebf908e4-19c8-4171-ac89-c0ddba170b2f: money=20.0, storage={0: -40}, loans=0.0 2019-02-27 11:34:11,199 - DEBUG - 8/10 [90.00%]: Factory b3b8170f-8fca-486f-848a-69d82e617f52: money=4.0, storage={0: -8}, loans=0.0 2019-02-27 11:34:11,199 - DEBUG - 8/10 [90.00%]: Factory f5f00bb2-9f63-41d3-bbb2-270d5bc7268e: money=15.0, storage={0: -30}, loans=0.0 2019-02-27 11:34:11,199 - DEBUG - 8/10 [90.00%]: Factory 0f562fc9-74f3-4758-8c55-6045859782f5: money=17.0, storage={0: -34}, loans=0.0 2019-02-27 11:34:11,199 - INFO - 9/10 [100.00%]: 0 Negotiations/4 _entities 2019-02-27 11:34:11,200 - DEBUG - 9/10 [100.00%]: Factory 567c17c8-8bbd-4ebb-828c-d4860fd379b7: money=-12.5, storage={0: 21}, loans=0.0 2019-02-27 11:34:11,200 - DEBUG - 9/10 [100.00%]: Factory a0f4927d-1f5c-4f74-a2f7-aa8e774a27e3: money=-13.5, storage={0: 23}, loans=0.0 2019-02-27 11:34:11,200 - DEBUG - 9/10 [100.00%]: Factory 8a8fa7a0-f90e-4d14-959d-34b2b489efe1: money=-12.5, storage={0: 22}, loans=0.0 2019-02-27 11:34:11,200 - DEBUG - 9/10 [100.00%]: Factory c01b5ced-1ecd-491f-8503-d6b05067d41d: money=-12.0, storage={0: 20}, loans=0.0 2019-02-27 11:34:11,200 - DEBUG - 9/10 [100.00%]: Factory e4a66fab-f4f6-483a-bc31-5cab325cfe7f: money=-12.5, storage={0: 21}, loans=0.0 2019-02-27 11:34:11,200 - DEBUG - 9/10 [100.00%]: Factory ae788129-5389-405f-91bb-1dd70ada97a8: money=7.0, storage={0: -14}, loans=0.0 2019-02-27 11:34:11,200 - DEBUG - 9/10 [100.00%]: Factory ebf908e4-19c8-4171-ac89-c0ddba170b2f: money=20.0, storage={0: -40}, loans=0.0 2019-02-27 11:34:11,200 - DEBUG - 9/10 [100.00%]: Factory b3b8170f-8fca-486f-848a-69d82e617f52: money=4.0, storage={0: -8}, loans=0.0 2019-02-27 11:34:11,200 - DEBUG - 9/10 [100.00%]: Factory f5f00bb2-9f63-41d3-bbb2-270d5bc7268e: money=15.0, storage={0: -30}, loans=0.0 2019-02-27 11:34:11,200 - DEBUG - 9/10 [100.00%]: Factory 0f562fc9-74f3-4758-8c55-6045859782f5: money=17.0, storage={0: -34}, loans=0.0 PK! y}#negmas/logs/log_20190227-113533.txt2019-02-27 11:35:34,704 - INFO - 0/10 [10.00%]: DummyWorld/20190227-113534EwL56: World Created 2019-02-27 11:35:34,704 - INFO - 0/10 [10.00%]: A1 joined 2019-02-27 11:35:34,704 - INFO - 0/10 [10.00%]: A2 joined 2019-02-27 11:35:34,704 - INFO - 0/10 [10.00%]: 0 Negotiations/1 _entities 2019-02-27 11:35:34,705 - INFO - 1/10 [20.00%]: 0 Negotiations/1 _entities 2019-02-27 11:35:34,705 - INFO - 2/10 [30.00%]: 0 Negotiations/1 _entities 2019-02-27 11:35:34,705 - INFO - 2/10 [30.00%]: A1 requested None[None] with ['A2', 'A1'] (ID b40ad5b8-e75b-440d-b8a4-0147c87223f6) 2019-02-27 11:35:34,707 - INFO - 2/10 [30.00%]: A1 request was accepted 2019-02-27 11:35:34,707 - INFO - 3/10 [40.00%]: 1 Negotiations/1 _entities 2019-02-27 11:35:34,724 - DEBUG - 3/10 [40.00%]: Contract [signed]: ['A2', 'A1'] > {'nGisiWgNZq6ITZM5': 0} on annotation 2019-02-27 11:35:34,724 - INFO - 4/10 [50.00%]: 0 Negotiations/1 _entities 2019-02-27 11:35:34,724 - INFO - 4/10 [50.00%]: A2 requested None[None] with ['A1', 'A2'] (ID 8788990c-f0b6-4500-bf5a-40a62ac3d9e2) 2019-02-27 11:35:34,725 - INFO - 4/10 [50.00%]: A2 request was accepted 2019-02-27 11:35:34,725 - INFO - 5/10 [60.00%]: 1 Negotiations/1 _entities 2019-02-27 11:35:34,742 - DEBUG - 5/10 [60.00%]: Contract [signed]: ['A1', 'A2'] > {'pslm0lcNQqEefRWi': 0} on annotation 2019-02-27 11:35:34,742 - INFO - 6/10 [70.00%]: 0 Negotiations/1 _entities 2019-02-27 11:35:34,742 - INFO - 7/10 [80.00%]: 0 Negotiations/1 _entities 2019-02-27 11:35:34,742 - INFO - 8/10 [90.00%]: 0 Negotiations/1 _entities 2019-02-27 11:35:34,742 - INFO - 9/10 [100.00%]: 0 Negotiations/1 _entities 2019-02-27 11:35:34,744 - INFO - 0/10000 [0.14%]: DummyWorld/20190227-113534qeoeP: World Created 2019-02-27 11:35:34,744 - INFO - 0/10 [10.00%]: DummyWorld/20190227-113534UE156: World Created 2019-02-27 11:35:34,749 - INFO - 0/10000 [0.14%]: DummyWorld/20190227-113534hM6CQ: World Created 2019-02-27 11:35:34,749 - INFO - 0/10 [10.00%]: DummyWorld/20190227-113534qjJSa: World Created PK!Lu湐negmas/mechanisms.py"""Provides interfaces for defining negotiation mechanisms. """ import itertools import math import pprint import time import uuid from abc import abstractmethod, ABC from collections import defaultdict from typing import Tuple, List, Optional, Any, Iterable, Union, Dict, Set, Type import pandas as pd from dataclasses import dataclass from negmas.utilities import UtilityFunction, MappingUtilityFunction, pareto_frontier from negmas.outcomes import outcome_is_valid, Issue, Outcome, enumerate_outcomes from negmas.common import ( AgentMechanismInterface, MechanismState, register_all_mechanisms, NamedObject, ) from negmas.common import NegotiatorInfo from negmas.events import * from negmas.generics import ikeys from negmas.helpers import snake_case from negmas.negotiators import Negotiator __all__ = ["Mechanism", "Protocol", "MechanismRoundResult"] @dataclass class MechanismRoundResult: broken: bool = False """True only if END_NEGOTIATION was selected by one agent""" timedout: bool = False """True if a timeout occurred. Usually not used""" agreement: Optional["Outcome"] = None """The agreement if any""" error: bool = False """True if an error occurred in the mechanism""" error_details: str = "" """Error message""" # noinspection PyAttributeOutsideInit class Mechanism(NamedObject, EventSource, ABC): """ Base class for all negotiation Mechanisms. Override the `round` function of this class to implement a round of your mechanism """ all: Dict[str, "Mechanism"] = {} register_all_mechanisms(all) def __init__( self, issues: List["Issue"] = None, outcomes: Union[int, List["Outcome"]] = None, n_steps: int = None, time_limit: float = None, step_time_limit: float = None, max_n_agents: int = None, dynamic_entry=False, cache_outcomes=True, max_n_outcomes: int = 1000000, keep_issue_names=True, annotation: Optional[Dict[str, Any]] = None, state_factory=MechanismState, enable_callbacks=False, name=None, ): """ Args: issues: List of issues to use (optional as you can pass `outcomes`) outcomes: List of outcomes (optional as you can pass `issues`). If an int then it is the number of outcomes n_steps: Number of rounds allowed (None means infinity) time_limit: Number of real seconds allowed (None means infinity) max_n_agents: Maximum allowed number of agents dynamic_entry: Allow agents to enter/leave negotiations between rounds cache_outcomes: If true, a list of all possible outcomes will be cached max_n_outcomes: The maximum allowed number of outcomes in the cached set keep_issue_names: If True, dicts with issue names will be used for outcomes otherwise tuples annotation: Arbitrary annotation state_factory: A callable that receives an arbitrary set of key-value pairs and return a MechanismState descendant object name: Name of the mechanism session. Should be unique. If not given, it will be generated. """ super().__init__(name=name) # parameters fixed for all runs if issues is None: if outcomes is None: raise ValueError( "Not issues or outcomes are given to this mechanism. Cannot be constructed" ) else: if isinstance(outcomes, int): outcomes = [(_,) for _ in range(outcomes)] else: outcomes = list(outcomes) n_issues = len(outcomes[0]) issues = [] issue_names = ikeys(outcomes[0]) for issue in range(n_issues): vals = list(set([_[issue] for _ in outcomes])) issues.append(vals) __issues = [ Issue(_, name=name_) for _, name_ in zip(issues, issue_names) ] else: __issues = list(issues) if outcomes is None and cache_outcomes: try: if len(__issues) == 0: outcomes = [] else: n_outcomes = 1 for issue in __issues: if issue.is_continuous(): break n_outcomes *= issue.cardinality() if n_outcomes > max_n_outcomes: break else: outcomes = enumerate_outcomes( __issues, keep_issue_names=keep_issue_names ) except ValueError: pass elif outcomes is not None: issue_names = [_.name for _ in issues] assert (keep_issue_names and isinstance(outcomes[0], dict)) or ( not keep_issue_names and isinstance(outcomes[0], tuple) ), ( f"Either you request to keep issue" f" names but use tuple outcomes or " f"vice versa (names={keep_issue_names}" f", type={type(outcomes[0])})" ) if keep_issue_names: for i, outcome in enumerate(outcomes): assert list(outcome.keys()) == issue_names else: for i, outcome in enumerate(outcomes): assert len(outcome) == len(issue_names) __outcomes = outcomes # we have now __issues is a List[Issue] and __outcomes is Optional[List[Outcome]] # create a couple of ways to access outcomes by indices effeciently self.outcome_index = lambda x: None self.outcome_indices = [] if __outcomes is not None and cache_outcomes: self.outcome_indices = range(len(__outcomes)) try: _outcome_index = dict(zip(__outcomes, self.outcome_indices)) self.outcome_index = lambda x: _outcome_index[x] except: self.outcome_index = lambda x: __outcomes.index(x) self.id = str(uuid.uuid4()) self.ami = AgentMechanismInterface( id=self.id, n_outcomes=None if outcomes is None else len(outcomes), issues=__issues, outcomes=__outcomes, time_limit=time_limit, n_steps=n_steps, step_time_limit=step_time_limit, dynamic_entry=dynamic_entry, max_n_agents=max_n_agents, annotation=annotation, ) self._history = [] # if self.ami.issues is not None: # self.ami.issues = tuple(self.ami.issues) # if self.ami.outcomes is not None: # self.ami.outcomes = tuple(self.ami.outcomes) self._state_factory = state_factory Mechanism.all[self.id] = self self._requirements = {} self._negotiators = [] self._roles = [] self._start_time = None self._started = False self._step = 0 self._n_accepting_agents = 0 self._broken = False self._agreement = None self._timedout = False self._running = False self._error = False self._error_details = "" self.__discrete_outcomes: List[Outcome] = None self._enable_callbacks = enable_callbacks self.agents_of_role = defaultdict(list) self.role_of_agent = {} @classmethod def get_info(cls, id: str) -> AgentMechanismInterface: """Returns the mechanism information which contains its static config plus methods to access current state""" return cls.all[id].ami @property def participants(self) -> List[NegotiatorInfo]: """Returns a list of all participant names""" return [ NegotiatorInfo(name=_.name, id=_.id, type=snake_case(_.__class__.__name__)) for _ in self.negotiators ] def is_valid(self, outcome: "Outcome"): """Checks whether the outcome is valid given the issues""" if self.ami.issues is None or len(self.ami.issues) == 0: raise ValueError("I do not have any issues to check") return outcome_is_valid(outcome, self.ami.issues) def discrete_outcomes( self, n_max: int = None, astype: Type["Outcome"] = dict ) -> List["Outcome"]: """ A discrete set of outcomes that spans the outcome space Args: n_max: The maximum number of outcomes to return. If None, all outcomes will be returned for discrete issues and *100* if any of the issues was continuous astype: A type to cast the resulting outcomes to. Returns: List[Outcome]: List of `n` or less outcomes """ if self.outcomes is not None: return self.outcomes if self.__discrete_outcomes is None: if all(issue.is_discrete() for issue in self.issues): self.__discrete_outcomes = Issue.sample( issues=self.issues, n_outcomes=n_max, astype=astype, with_replacement=False, fail_if_not_enough=False, ) else: self.__discrete_outcomes = Issue.sample( issues=self.issues, n_outcomes=n_max if n_max is not None else 100, astype=astype, with_replacement=False, fail_if_not_enough=False, ) return self.__discrete_outcomes def random_outcomes( self, n: int = 1, astype: Type[Outcome] = dict ) -> List["Outcome"]: """Returns random offers""" if self.ami.issues is None or len(self.ami.issues) == 0: raise ValueError("I do not have any issues to generate offers from") return Issue.sample( issues=self.issues, n_outcomes=n, astype=astype, with_replacement=False, fail_if_not_enough=False, ) @property def time(self) -> Optional[float]: """Elapsed time since mechanism started in seconds. None if the mechanism did not start running""" if self._start_time is None: return 0.0 return time.monotonic() - self._start_time @property def remaining_time(self) -> Optional[float]: """Returns remaining time in seconds. None if no time limit is given.""" if self.ami.time_limit is None: return None limit = self.ami.time_limit - (time.monotonic() - self._start_time) if limit < 0.0: return 0.0 return limit @property def relative_time(self) -> Optional[float]: """Returns a number between ``0`` and ``1`` indicating elapsed relative time or steps.""" if self.ami.time_limit is None and self.ami.n_steps is None: return None relative_step = ( (self._step + 1) / self.ami.n_steps if self.ami.n_steps is not None else -1.0 ) relative_time = ( self.time / self.ami.time_limit if self.ami.time_limit is not None else -1.0 ) return max([relative_step, relative_time]) @property def remaining_steps(self) -> Optional[int]: """Returns the remaining number of steps until the end of the mechanism run. None if unlimited""" if self.ami.n_steps is None: return None return self.ami.n_steps - self._step 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.ami, state=self.state, ufun=ufun, role=role): self._negotiators.append(negotiator) self._roles.append(role) self.role_of_agent[negotiator.uuid] = role self.agents_of_role[role].append(negotiator) return True return None def remove(self, agent: "Negotiator", **kwargs) -> Optional[bool]: """Remove the agent from the negotiation. Args: agent: Returns: * True if the agent was removed. * False if the agent was not in the negotiation already. * None if the agent cannot be removed. """ try: indx = self._negotiators.index(agent) except ValueError: return False if not self.can_leave(agent): return None self._negotiators = self._negotiators[0:indx] + self._negotiators[indx + 1 :] if self._enable_callbacks: agent.on_leave(self.ami, **kwargs) return True def add_requirements(self, requirements: dict) -> None: """Adds requirements.""" requirements = { k: set(v) if isinstance(v, list) else v for k, v in requirements.items() } if hasattr(self, "_requirements"): self._requirements.update(requirements) else: self._requirements = requirements def remove_requirements(self, requirements: Iterable) -> None: """Adds requirements.""" for r in requirements: if r in self._requirements.keys(): self._requirements.pop(r, None) @property def negotiators(self): return self._negotiators @property def requirements(self): """A dictionary specifying the requirements that must be in the capabilities of any agent to join the mechanism. """ return self._requirements @requirements.setter def requirements( self, requirements: Dict[ str, Union[ Tuple[Union[int, float, str], Union[int, float, str]], List, Set, Union[int, float, str], ], ], ): self._requirements = { k: set(v) if isinstance(v, list) else v for k, v in requirements.items() } @property def agreement(self): return self._agreement def is_satisfying(self, capabilities: dict) -> bool: """Checks if the given capabilities are satisfying mechanism requirements. Args: capabilities: capabilities to check Returns: bool are the requirements satisfied by the capabilities. Remarks: - Requirements are also a dict with the following meanings: - tuple: Min and max acceptable values - list/set: Any value in the iterable is acceptable - Single value: The capability must match this value - Capabilities can also have the same three possibilities. """ requirements = self.requirements for r, v in requirements.items(): if v is None: if r not in capabilities.keys(): return False else: continue if r not in capabilities.keys(): return False if capabilities[r] is None: continue c = capabilities[r] if isinstance(c, tuple): # c is range if isinstance(v, tuple): # both ranges match = v[0] <= c[0] <= v[1] or v[0] <= c[1] <= v[1] else: # c is range and cutoff_utility is not a range match = ( any(c[0] <= _ <= c[1] for _ in v) if isinstance(v, set) else c[0] <= v <= c[1] ) elif isinstance(c, list) or isinstance(c, set): # c is list if isinstance(v, tuple): # c is a list and cutoff_utility is a range match = any(v[0] <= _ <= v[1] for _ in c) else: # c is a list and cutoff_utility is not a range match = any(_ in v for _ in c) if isinstance(v, set) else v in c else: # c is a single value if isinstance(v, tuple): # c is a singlton and cutoff_utility is a range match = v[0] <= c <= v[1] else: # c is a singlton and cutoff_utility is not a range match = c in v if isinstance(v, set) else c == v if not match: return False return True def can_participate(self, agent: "Negotiator") -> bool: """Checks if the agent can participate in this type of negotiation in general. Args: agent: Returns: bool: True if it can Remarks: The only reason this may return `False` is if the mechanism requires some requirements that are not within the capabilities of the agent. When evaluating compatibility, the agent is considered incapable of participation if any of the following conditions hold: * A mechanism requirement is not in the capabilities of the agent * A mechanism requirement is in the capabilities of the agent by the values required for it is not in the values announced by the agent. An agent that lists a `None` value for a capability is announcing that it can work with all its values. On the other hand, a mechanism that lists a requirement as None announces that it accepts any value for this requirement as long as it exist in the agent """ return self.is_satisfying(agent.capabilities) @property def n_outcomes(self): return self.ami.n_outcomes @property def issues(self): return self.ami.issues @property def completed(self): return self.agreement is not None or self._broken @property def outcomes(self): return self.ami.outcomes @property def n_steps(self): return self.ami.n_steps @property def time_limit(self): return self.ami.time_limit @property def running(self): return self._running @property def dynamic_entry(self): return self.ami.dynamic_entry @property def max_n_agents(self): return self.ami.max_n_agents @max_n_agents.setter def max_n_agents(self, n: int): self.ami.max_n_agents = n def can_accept_more_agents(self) -> bool: """Whether the mechanism can **currently** accept more negotiators.""" return ( True if self.ami.max_n_agents is None or self._negotiators is None else len(self._negotiators) < self.ami.max_n_agents ) def can_leave(self, agent: "Negotiator") -> bool: """Can the agent leave now?""" return ( True if self.ami.dynamic_entry else not self.ami.state.running and agent in self._negotiators ) def can_enter(self, agent: "Negotiator") -> bool: """Whether the agent can enter the negotiation now.""" return self.can_accept_more_agents() and self.can_participate(agent) def __iter__(self): return self def __next__(self) -> MechanismState: result = self.step() if not self._running: raise StopIteration return result def step(self) -> MechanismState: """Runs a single step of the mechanism. Returns: MechanismState: The state of the negotiation *after* the round is conducted Remarks: - Every call yields the results of one round (see `round()`) - If the mechanism was yet to start, it will start it and runs one round - There is another function (`run()`) that runs the whole mechanism in blocking mode """ if self.time_limit is not None and self.time > self.time_limit: self._agreement, self._broken, self._timedout = None, False, True self._history.append(self.state) return self.state if len(self._negotiators) < 2: if self.ami.dynamic_entry: self._history.append(self.state) return self.state else: self.ami.state.running = False self._agreement, self._broken, self._timedout = None, False, False self._history.append(self.state) self.on_negotiation_end() return self.state if self._broken or self._timedout or self._agreement is not None: self._history.append(self.state) return self.state if not self._running: self._running = True self._step = 0 self._start_time = time.monotonic() self._started = True if self.on_negotiation_start() is False: self._agreement, self._broken, self._timedout = None, False, False self._history.append(self.state) return self.state if self._enable_callbacks: for a in self.negotiators: a.on_negotiation_start(state=self.state) self.announce(Event(type="negotiation_start", data=None)) else: remaining_steps, remaining_time = self.remaining_steps, self.remaining_time if (remaining_steps is not None and remaining_steps <= 0) or ( remaining_time is not None and remaining_time <= 0.0 ): self._running = False self._agreement, self._broken, self._timedout = None, False, True self._history.append(self.state) self.on_negotiation_end() return self.state if self._enable_callbacks: for agent in self._negotiators: agent.on_round_start(state=self.state) step_start = time.perf_counter() result = self.round() step_time = time.perf_counter() - step_start self._error, self._error_details = result.error, result.error_details if self._error: self.on_mechanism_error() if ( self.ami.step_time_limit is not None and step_time > self.ami.step_time_limit ): self._broken, self._timedout, self._agreement = False, True, None else: self._broken, self._timedout, self._agreement = ( result.broken, result.timedout, result.agreement, ) if (self._agreement is not None) or self._broken or self._timedout: self._running = False self._step += 1 if self._enable_callbacks: for agent in self._negotiators: agent.on_round_end(state=self.state) if not self._running: self.on_negotiation_end() self._history.append(self.state) return self.state def run(self, timeout=None) -> MechanismState: if timeout is None: for _ in self: pass else: start_time = time.perf_counter() for _ in self: if time.perf_counter() - start_time > timeout: self._running, self._timedout = False, True self.on_negotiation_end() break return self.state def on_mechanism_error(self) -> None: """ Called when there is a mechanism error Remarks: - When overriding this function you **MUST** call the base class version """ if self._enable_callbacks: for a in self.negotiators: a.on_mechanism_error(state=self.state) def on_negotiation_end(self) -> None: """ Called at the end of each negotiation Remarks: - When overriding this function you **MUST** call the base class version """ if self._enable_callbacks: for a in self.negotiators: a.on_negotiation_end(state=self.state) self.announce( Event( type="negotiation_end", data={ "agreement": self.agreement, "state": self.state, "annotation": self.ami.annotation, }, ) ) def on_negotiation_start(self) -> bool: """Called before starting the negotiation. If it returns False then negotiation will end immediately""" return True @property def history(self): return self._history @property def state(self): """Returns the current state. Override `extra_state` if you want to keep extra state""" current_state = self.extra_state() if current_state is None: current_state = {} else: current_state = dict(current_state) current_state.update( { "running": self._running, "step": self._step, "time": self.time, "relative_time": self.relative_time, "broken": self._broken, "timedout": self._timedout, "started": self._started, "agreement": self._agreement, "n_negotiators": len(self.negotiators), "has_error": self._error, "error_details": self._error_details, } ) return self._state_factory(**current_state) def pareto_frontier( self, n_max=None, sort_by_welfare=True ) -> Tuple[List[Tuple[float]], List["Outcome"]]: ufuns = self._get_ufuns() if any(_ is None for _ in ufuns): return [], [] frontier, indices = pareto_frontier( ufuns=ufuns, n_discretization=None, sort_by_welfare=sort_by_welfare, outcomes=self.discrete_outcomes(n_max=n_max), ) return frontier, [self.discrete_outcomes(n_max=n_max)[_] for _ in indices] def __str__(self): d = self.__dict__.copy() return pprint.pformat(d) __repr__ = __str__ def _get_ufuns(self): ufuns = [] for a in self.negotiators: ufuns.append(a.utility_function) return ufuns def plot(self, plot_utils=True, plot_outcomes=True): import matplotlib.pyplot as plt import matplotlib.gridspec as gridspec if len(self.negotiators) > 2: print("Cannot visualize negotiations with more than 2 negotiators") else: # has_front = int(len(self.outcomes[0]) <2) has_front = 1 n_agents = len(self.negotiators) history = pd.DataFrame(data=[_.__dict__ for _ in self.history]) # history['time'] = [_.time for _ in self.history] # history['relative_time'] = [_.relative_time for _ in self.history] # history['step'] = [_.step for _ in self.history] history = history.loc[~history.current_offer.isnull(), :] ufuns = self._get_ufuns() outcomes = self.outcomes utils = [tuple(f(o) for f in ufuns) for o in outcomes] agent_names = [a.name for a in self.negotiators] history["offer_index"] = [outcomes.index(_) for _ in history.current_offer] frontier, frontier_outcome = self.pareto_frontier(sort_by_welfare=True) frontier_outcome_indices = [outcomes.index(_) for _ in frontier_outcome] if plot_utils: fig_util = plt.figure() if plot_outcomes: fig_outcome = plt.figure() gs_util = gridspec.GridSpec(n_agents, has_front + 1) if plot_utils else None gs_outcome = ( gridspec.GridSpec(n_agents, has_front + 1) if plot_outcomes else None ) axs_util, axs_outcome = [], [] for a in range(n_agents): if a == 0: if plot_utils: axs_util.append(fig_util.add_subplot(gs_util[a, has_front])) if plot_outcomes: axs_outcome.append( fig_outcome.add_subplot(gs_outcome[a, has_front]) ) else: if plot_utils: axs_util.append( fig_util.add_subplot( gs_util[a, has_front], sharex=axs_util[0] ) ) if plot_outcomes: axs_outcome.append( fig_outcome.add_subplot( gs_outcome[a, has_front], sharex=axs_outcome[0] ) ) if plot_utils: axs_util[-1].set_ylabel(agent_names[a]) if plot_outcomes: axs_outcome[-1].set_ylabel(agent_names[a]) for a, (au, ao) in enumerate( zip( itertools.chain(axs_util, itertools.repeat(None)), itertools.chain(axs_outcome, itertools.repeat(None)), ) ): if au is None and ao is None: break h = history.loc[ history.current_proposer == self.negotiators[a].id, ["relative_time", "offer_index", "current_offer"], ] h["utility"] = h["current_offer"].apply(ufuns[a]) if plot_outcomes: ao.plot(h.relative_time, h["offer_index"]) if plot_utils: au.plot(h.relative_time, h.utility) au.set_ylim(0.0, 1.0) if has_front: if plot_utils: axu = fig_util.add_subplot(gs_util[:, 0]) axu.scatter( [_[0] for _ in utils], [_[1] for _ in utils], label="outcomes", color="gray", marker="s", s=20, ) if plot_outcomes: axo = fig_outcome.add_subplot(gs_outcome[:, 0]) clrs = ("blue", "green") if plot_utils: for a in range(n_agents): h = history.loc[ history.current_proposer == self.negotiators[a].id, ["relative_time", "offer_index", "current_offer"], ] h["u0"] = h["current_offer"].apply(ufuns[0]) h["u1"] = h["current_offer"].apply(ufuns[1]) axu.scatter( h.u0, h.u1, color=clrs[a], label=f"{agent_names[a]}" ) if plot_outcomes: steps = sorted(history.step.unique().tolist()) aoffers = [[], []] for step in steps[::2]: offrs = [] for a in range(n_agents): a_offer = history.loc[ (history.current_proposer == agent_names[a]) & ((history.step == step) | (history.step == step + 1)), "offer_index", ] if len(a_offer) > 0: offrs.append(a_offer.values[-1]) if len(offrs) == 2: aoffers[0].append(offrs[0]) aoffers[1].append(offrs[1]) axo.scatter(aoffers[0], aoffers[1], color=clrs[0], label=f"offers") if self.state.agreement is not None: if plot_utils: axu.scatter( [ufuns[0](self.state.agreement)], [ufuns[1](self.state.agreement)], color="black", marker="*", s=120, label="SCMLAgreement", ) if plot_outcomes: axo.scatter( [outcomes.index(self.state.agreement)], [outcomes.index(self.state.agreement)], color="black", marker="*", s=120, label="SCMLAgreement", ) if plot_utils: f1, f2 = [_[0] for _ in frontier], [_[1] for _ in frontier] axu.scatter(f1, f2, label="frontier", color="red", marker="x") axu.legend() axu.set_xlabel(agent_names[0] + " utility") axu.set_ylabel(agent_names[1] + " utility") if self.agreement is not None: pareto_distance = 1e9 cu = (ufuns[0](self.agreement), ufuns[1](self.agreement)) for pu in frontier: dist = math.sqrt( (pu[0] - cu[0]) ** 2 + (pu[1] - cu[1]) ** 2 ) if dist < pareto_distance: pareto_distance = dist axu.text( 0, 0.95, f"Pareto-distance={pareto_distance:5.2}", verticalalignment="top", transform=axu.transAxes, ) if plot_outcomes: axo.scatter( frontier_outcome_indices, frontier_outcome_indices, color="red", marker="x", label="frontier", ) axo.legend() axo.set_xlabel(agent_names[0]) axo.set_ylabel(agent_names[1]) if plot_utils: fig_util.show() if plot_outcomes: fig_outcome.show() @abstractmethod def round(self) -> MechanismRoundResult: """ Implements a single step of the mechanism. Override this! Returns: MechanismRoundResult giving whether the negotiation was broken or timedout and the agreement if any. """ raise NotImplementedError( "You must inherit from Mechanism and override its round() function" ) def extra_state(self) -> Optional[Dict[str, Any]]: """Returns any extra state information to be kept in the `state` and `history` properties""" return None Protocol = Mechanism """An alias for `Mechanism`""" PK!+dOOnegmas/negotiators.py"""This module defines the interfaces to all negotiation agents (negotiators) in the platform. """ import functools import math from abc import ABC from copy import copy from typing import Optional, Tuple, Union, Type from typing import TYPE_CHECKING, Dict, Any, Callable from negmas.common import * from negmas.events import Notifiable, Notification from negmas.helpers import get_class from negmas.utilities import make_discounted_ufun if TYPE_CHECKING: from negmas.outcomes import Outcome from negmas.utilities import UtilityValue, UtilityFunction __all__ = ["Negotiator", "AspirationMixin", "Controller"] # Most abstract kind of agent class Negotiator(NamedObject, Notifiable, ABC): r"""Abstract negotiation agent. Base class for all negotiators Args: name: Negotiator name. If not given it is assigned by the system (unique 16 characters). Returns: bool: True if participating in the given negotiation (or any negotiation if it was None) Remarks: """ def __init__( self, name: str = None, ufun: Optional["UtilityFunction"] = None, parent: "Controller" = None, ) -> None: super().__init__(name=name) self.__parent = parent self._capabilities = {"enter": True, "leave": True} self.add_capabilities({"evaluate": True, "compare": True}) self._mechanism_id = None self._ami = None self._initial_state = None self.utility_function = ufun self._init_utility = ufun self._role = None def __getattribute__(self, item): if item in ("id", "name") or item.startswith("_"): return super().__getattribute__(item) parent = super().__getattribute__("__dict__").get("_Negotiator__parent", None) if parent is None: return super().__getattribute__(item) attr = getattr(parent, item, None) if attr is None: return super().__getattribute__(item) if isinstance(attr, Callable): return functools.partial( attr, negotiator_id=super().__getattribute__("__dict__")[ "_NamedObject__uuid" ], ) return super().__getattribute__(item) def before_death(self, cntxt: Dict[str, Any]) -> bool: """Called whenever the parent is about to kill this negotiator. It should return False if the negotiator does not with to be killed but the controller can still force-kill it""" def _dissociate(self): self._mechanism_id = None self._ami = None self.utility_function = self._init_utility self._role = None def isin(self, negotiation_id: Optional[str]) -> bool: """Is that agent participating in the given negotiation? Tests if the agent is participating in the given negotiation. Args: negotiation_id (Optional[str]): The negotiation ID tested. If None, it means ANY negotiation Returns: bool: True if participating in the given negotiation (or any negotiation if it was None) """ return self._mechanism_id == negotiation_id @property def reserved_value(self): """Reserved value is what the agent gets if no agreement is reached in the negotiation.""" if self.utility_function is None: return None if self.utility_function.reserved_value is not None: return self.utility_function.reserved_value return self.utility_function(None) @property def capabilities(self) -> Dict[str, Any]: """Agent capabilities""" return self._capabilities def add_capabilities(self, capabilities: dict) -> None: """Adds named capabilities to the agent. Args: capabilities: The capabilities to be added as a dict Returns: None Remarks: It is the responsibility of the caller to be really capable of added capabilities. """ if hasattr(self, "_capabilities"): self._capabilities.update(capabilities) else: self._capabilities = capabilities # CALL BACKS def join( self, ami: AgentMechanismInterface, state: MechanismState, *, ufun: Optional["UtilityFunction"] = None, role: str = "agent", ) -> bool: """ Called by the mechanism when the agent is about to enter a negotiation. It can prevent the agent from entering Args: ami (AgentMechanismInterface): The negotiation. state (MechanismState): The current state of the negotiation ufun (UtilityFunction): The ufun function to use before any discounting. role (str): role of the agent. Returns: bool indicating whether or not the agent accepts to enter. If False is returned it will not enter the negotiation """ if self._mechanism_id is not None: return False self._role = role self._mechanism_id = ami.id self._ami = ami self._initial_state = state if ufun is not None: self.utility_function = ufun if self.utility_function: self.utility_function.ami = ami return True def on_negotiation_start(self, state: MechanismState) -> None: """ A call back called at each negotiation start Args: state: `MechanismState` giving current state of the negotiation. Remarks: - The default behavior is to do nothing. - Override this to hook some action. """ def on_round_start(self, state: MechanismState) -> None: """A call back called at each negotiation round start Args: state: `MechanismState` giving current state of the negotiation. Remarks: - The default behavior is to do nothing. - Override this to hook some action. """ def on_mechanism_error(self, state: MechanismState) -> None: """ A call back called whenever an error happens in the mechanism. The error and its explanation are accessible in `state` Args: state: `MechanismState` giving current state of the negotiation. Remarks: - The default behavior is to do nothing. - Override this to hook some action """ def on_round_end(self, state: MechanismState) -> None: """ A call back called at each negotiation round end Args: state: `MechanismState` giving current state of the negotiation. Remarks: - The default behavior is to do nothing. - Override this to hook some action """ def on_leave(self, state: MechanismState) -> None: """A call back called after leaving a negotiation. Args: state: `MechanismState` giving current state of the negotiation. Remarks: - **MUST** call the baseclass `on_leave` using `super`() if you are going to override this. - The default behavior is to do nothing. - Override this to hook some action """ self._dissociate() def on_negotiation_end(self, state: MechanismState) -> None: """ A call back called at each negotiation end Args: state: `MechanismState` or one of its descendants giving the state at which the negotiation ended. Remarks: - The default behavior is to do nothing. - Override this to hook some action """ def on_notification(self, notification: Notification, notifier: str): if notifier != self._mechanism_id: raise ValueError(f"Notification is coming from unknown {notifier}") if notification.type == "negotiation_start": self.on_negotiation_start(state=notification.data) elif notification.type == "round_start": self.on_round_start(state=notification.data) elif notification.type == "round_end": self.on_round_end(state=notification.data) elif notification.type == "negotiation_end": self.on_negotiation_end(state=notification.data) def __str__(self): return f"{self.name}" def compare(self, first: "Outcome", second: "Outcome") -> Optional["UtilityValue"]: """ Compares two offers using the `ufun` Args: first: First outcome to be compared second: Second outcome to be compared Returns: UtilityValue: An estimate of the differences between the two outcomes. It can be a real number between -1, 1 or a probability distribution over the same range. """ if self.utility_function is None: return None return self.utility_function.compare(first, second) class Java: implements = ["jnegmas.negotiators.Negotiator"] class AspirationMixin: """Adds aspiration level calculation. This Mixin MUST be used with a `Negotiator` class.""" def aspiration_init( self, max_aspiration: float, aspiration_type: Union[str, int, float], above_reserved_value=True, ): """ Args: max_aspiration: aspiration_type: above_reserved_value: """ self.add_capabilities({"aspiration": True}) self.max_aspiration = max_aspiration self.aspiration_type = aspiration_type self.e = 1.0 if isinstance(aspiration_type, int): self.e = float(aspiration_type) elif isinstance(aspiration_type, float): self.e = aspiration_type elif aspiration_type == "boulware": self.e = 4.0 elif aspiration_type == "linear": self.e = 1.0 elif aspiration_type == "conceder": self.e = 0.25 else: raise ValueError(f"Unknown aspiration type {aspiration_type}") self.above_reserved = above_reserved_value def aspiration(self, t: float) -> float: """ The aspiration level Args: t: relative time (a number between zero and one) Returns: aspiration level """ if t is None: raise ValueError( f"Aspiration negotiators cannot be used in negotiations with no time or #steps limit!!" ) if self.e < 1e-7: return 0.0 pmin = ( self.reserved_value if self.above_reserved and self.reserved_value is not None else 0.0 ) return pmin + (self.max_aspiration - pmin) * (1.0 - math.pow(t, self.e)) class Controller(NamedObject): """Controls the behavior of multiple negotiators in multiple negotiations The controller class MUST implement all methods of the negotiator class it is controlling with one added argument negotiator_id (str) which represents ID of the negotiator on which the method is being invoked. """ def __init__( self, default_negotiator_type: Union[str, Type[Negotiator]] = None, default_negotiator_params: Dict[str, Any] = None, name: str = None, ): super().__init__(name=name) self._negotiators: Dict[str, Tuple["Negotiator", Dict[str, Any]]] = {} if default_negotiator_params is None: default_negotiator_params = {} if isinstance(default_negotiator_type, str): default_negotiator_type = get_class(default_negotiator_type) self.__default_negotiator_type = default_negotiator_type self.__default_negotiator_params = default_negotiator_params def create_negotiator( self, negotiator_type: Union[str, Type[Negotiator]] = None, name: str = None, cntxt: Dict[str, None] = None, **kwargs, ) -> Negotiator: """ Creates a negotiator passing it the context Args: negotiator_type: Type of the negotiator to be created name: negotiator name cntxt: The context to be associated with this negotiator. It will not be passed to the negotiator constructor. **kwargs: any key-value pairs to be passed to the negotiator constructor Returns: Negotiator: The negotiator to be controlled """ if negotiator_type is None: negotiator_type = self.__default_negotiator_type elif isinstance(negotiator_type, str): negotiator_type = get_class(negotiator_type) if negotiator_type is None: raise ValueError( "No negotiator type is passed and no default negotiator type is defined for this " "controller" ) new_negotiator = negotiator_type( name=name, parent=self, **self.__default_negotiator_params, **kwargs ) if new_negotiator is not None: self._negotiators[new_negotiator.id] = (new_negotiator, cntxt) return new_negotiator def call(self, negotiator: Negotiator, method: str, *args, **kwargs): """ Calls the given method on the given negotiator safely without causing recursion. The controller MUST use this function to access any callable on the negotiator Args: negotiator: method: *args: **kwargs: Returns: """ negotiator._Negotiator__parent = None result = getattr(negotiator, method)(*args, **kwargs) negotiator._Negotiator__parent = self return result def kill_negotiator(self, negotiator_id: str, force: bool = False) -> None: """ Kills the negotiator sending it an `before_death` message. Args: negotiator_id: The ID of the negotiator to kill. force: Whether to kill the negotiator in case it refused to die. Remarks: - Killing a negotiator amounts to nothing more than removing it form the list of negotiators maintained by the controller. """ negotiator, cntxt = self._negotiators.get(negotiator_id, (None, None)) if negotiator is None: return response = negotiator.on_kill(cntxt=cntxt) if response or force: self._negotiators.pop(negotiator_id, None) def join( self, negotiator_id: str, ami: AgentMechanismInterface, state: MechanismState, *, ufun: Optional["UtilityFunction"] = None, role: str = "agent", ) -> bool: """ Called by the mechanism when the agent is about to enter a negotiation. It can prevent the agent from entering Args: negotiator_id: The negotiator ID ami (AgentMechanismInterface): The negotiation. state (MechanismState): The current state of the negotiation ufun (UtilityFunction): The ufun function to use before any discounting. role (str): role of the agent. Returns: bool indicating whether or not the agent accepts to enter.If False is returned it will not enter the negotiation. """ negotiator, cntxt = self._negotiators.get(negotiator_id, (None, None)) if negotiator is None: raise ValueError(f"Unknown negotiator {negotiator_id}") return self.call(negotiator, "join", ami=ami, state=state, ufun=ufun, role=role) def on_negotiation_start(self, negotiator_id: str, state: MechanismState) -> None: """ A call back called at each negotiation start Args: negotiator_id: The negotiator ID state: `MechanismState` giving current state of the negotiation. Remarks: - The default behavior is to do nothing. - Override this to hook some action. """ negotiator, cntxt = self._negotiators.get(negotiator_id, (None, None)) if negotiator is None: raise ValueError(f"Unknown negotiator {negotiator_id}") return self.call(negotiator, "on_negotiation_start", state=state) def on_round_start(self, negotiator_id: str, state: MechanismState) -> None: """A call back called at each negotiation round start Args: negotiator_id: The negotiator ID state: `MechanismState` giving current state of the negotiation. Remarks: - The default behavior is to do nothing. - Override this to hook some action. """ negotiator, cntxt = self._negotiators.get(negotiator_id, (None, None)) if negotiator is None: raise ValueError(f"Unknown negotiator {negotiator_id}") return self.call(negotiator, "on_round_start", state=state) def on_mechanism_error(self, negotiator_id: str, state: MechanismState) -> None: """ A call back called whenever an error happens in the mechanism. The error and its explanation are accessible in `state` Args: negotiator_id: The negotiator ID state: `MechanismState` giving current state of the negotiation. Remarks: - The default behavior is to do nothing. - Override this to hook some action """ negotiator, cntxt = self._negotiators.get(negotiator_id, (None, None)) if negotiator is None: raise ValueError(f"Unknown negotiator {negotiator_id}") return self.call(negotiator, "on_mechanism_error", state=state) def on_round_end(self, negotiator_id: str, state: MechanismState) -> None: """ A call back called at each negotiation round end Args: negotiator_id: The negotiator ID state: `MechanismState` giving current state of the negotiation. Remarks: - The default behavior is to do nothing. - Override this to hook some action """ negotiator, cntxt = self._negotiators.get(negotiator_id, (None, None)) if negotiator is None: raise ValueError(f"Unknown negotiator {negotiator_id}") return self.call(negotiator, "on_round_end", state=state) def on_leave(self, negotiator_id: str, state: MechanismState) -> None: """A call back called after leaving a negotiation. Args: negotiator_id: The negotiator ID state: `MechanismState` giving current state of the negotiation. Remarks: - **MUST** call the baseclass `on_leave` using `super`() if you are going to override this. - The default behavior is to do nothing. - Override this to hook some action """ negotiator, cntxt = self._negotiators.get(negotiator_id, (None, None)) if negotiator is None: raise ValueError(f"Unknown negotiator {negotiator_id}") return self.call(negotiator, "on_leave", state=state) def on_negotiation_end(self, negotiator_id: str, state: MechanismState) -> None: """ A call back called at each negotiation end Args: negotiator_id: The negotiator ID state: `MechanismState` or one of its descendants giving the state at which the negotiation ended. Remarks: - The default behavior is to do nothing. - Override this to hook some action """ negotiator, cntxt = self._negotiators.get(negotiator_id, (None, None)) if negotiator is None: raise ValueError(f"Unknown negotiator {negotiator_id}") return self.call(negotiator, "on_negotiation_end", state=state) def on_notification( self, negotiator_id: str, notification: Notification, notifier: str ): negotiator, cntxt = self._negotiators.get(negotiator_id, (None, None)) if negotiator is None: raise ValueError(f"Unknown negotiator {negotiator_id}") return self.call( negotiator, "on_notification", notification=notification, notifier=notifier ) def __str__(self): return f"{self.name}" PK!tnegmas/outcomes.py"""Defines basic concept related to outcomes Outcomes in this package are always assumed to be multi-issue outcomes where single-issue outcomes can be implemented as the special case with a single issue. - Both Continuous and discrete issues are supported. All issue will have names. If none is given, a random name will be used. It is HIGHLY recommended to always name your issues. - Outcomes are dictionaries with issue names as keys and issue values as values. Examples: Different ways to create issues: >>> issues = [Issue((0.5, 2.0), 'price'), Issue(['2018.10.'+ str(_) for _ in range(1, 4)], 'date') ... , Issue(20, 'count')] >>> for _ in issues: print(_) price: (0.5, 2.0) date: ['2018.10.1', '2018.10.2', '2018.10.3'] count: 20 Outcome example compatible with the given set of issues: >>> a = {'price': 1.2, 'date': '2018.10.04', 'count': 4} """ import itertools import math import random import xml.etree.ElementTree as ET from enum import Enum from functools import reduce from operator import mul from typing import ( Optional, Collection, List, Generator, Iterable, Sequence, Union, Type, ) from typing import Tuple, Mapping, Dict, Any import numpy as np import pkg_resources from dataclasses import dataclass, fields from .java import PYTHON_CLASS_IDENTIFIER from .common import NamedObject from .generics import * from .helpers import unique_name LARGE_NUMBER = 100 __all__ = [ "Outcome", "OutcomeType", "OutcomeRange", "ResponseType", "Issue", "Issues", "outcome_is_valid", "outcome_is_complete", "outcome_range_is_valid", "outcome_range_is_complete", "outcome_in_range", "enumerate_outcomes", "sample_outcomes", "outcome_as_dict", "outcome_as_tuple", "num_outcomes", ] class ResponseType(Enum): """Possible answers to offers during negotiation.""" ACCEPT_OFFER = 0 REJECT_OFFER = 1 END_NEGOTIATION = 2 NO_RESPONSE = 3 class Issue(NamedObject): """Encodes an Issue. Args: values: Possible values for the issue name: Name of the issue. If not given, a random name will be generated Examples: >>> print(Issue(['to be', 'not to be'], name='THE problem')) THE problem: ['to be', 'not to be'] >>> print(Issue(3, name='Cars')) Cars: 3 >>> print(Issue((0.0, 1.0), name='required accuracy')) required accuracy: (0.0, 1.0) >>> a = Issue((0.0, 1.0), name='required accuracy') >>> a.is_continuous() True >>> a.is_discrete() False Remarks: - Issues can be initialized by either an iterable of strings, an integer or a tuple of two real values with the following meanings: - ``iterable of strings``: This is an issue that can any value within the given set of values (strings) - ``int``: This is an issue that takes any value from 0 to the given value -1 (int) - ``float``: This is an issue that can take any real value between the given limits (min, max) """ def __init__( self, values: Union[List[str], int, Tuple[float, float]], name: Optional[str] = None, ) -> None: super().__init__(name=name) # if isinstance(values, int) and values <= LARGE_NUMBER: # values = list(range(values)) if isinstance(values, tuple): values = (float(values[0]), float(values[1])) self.values = values @classmethod def to_xml_str(cls, issues: List["Issue"], enumerate_integer: bool = True) -> str: """Converts the list of issues into a well-formed xml string Examples: >>> issues = [Issue(values=10, name='i1'), Issue(values=['a', 'b', 'c'], name='i2'), ... Issue(values=(2.5, 3.5), name='i3')] >>> s = Issue.to_xml_str(issues) >>> print(s.strip()) >>> issues2, _ = Issue.from_xml_str(s) >>> print([_.__class__.__name__ for _ in issues2]) ['Issue', 'Issue', 'Issue'] >>> print(len(issues2)) 3 >>> print([str(_) for _ in issues2]) ["i1: ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9']", "i2: ['a', 'b', 'c']", 'i3: (2.5, 3.5)'] >>> print([_.values for _ in issues2]) [['0', '1', '2', '3', '4', '5', '6', '7', '8', '9'], ['a', 'b', 'c'], (2.5, 3.5)] """ output = ( f'\n\n' f'\n' ) for indx, issue in enumerate(issues): if isinstance(issue.values, int): if enumerate_integer: output += f' \n' for i, v in enumerate(range(issue.values)): output += f' \n \n' output += " \n" else: output += ( f' \n' ) elif isinstance(issue.values, tuple): output += ( f' \n' f' \n \n' ) else: output += f' \n' for i, v in enumerate(issue.values): output += f' \n \n' output += " \n" output += f"\n\n" return output @classmethod def to_genius( cls, issues: Iterable["Issue"], file_name: str, enumerate_integer: bool = True ) -> None: """Exports a the domain issues to a GENIUS XML file. Args: issues: The issues to be exported file_name (str): File name to export to Returns: A List[Issue] or Dict[Issue] Examples: >>> issues, _ = Issue.from_genius(file_name = pkg_resources.resource_filename('negmas' ... , resource_name='tests/data/Laptop/Laptop-C-domain.xml')) >>> Issue.to_genius(issues=issues, file_name = pkg_resources.resource_filename('negmas' ... , resource_name='tests/data/LaptopConv/Laptop-C-domain.xml')) >>> issues2, _ = Issue.from_genius(file_name = pkg_resources.resource_filename('negmas' ... , resource_name='tests/data/LaptopConv/Laptop-C-domain.xml')) >>> print('\\n'.join([' '.join(list(issue.all)) for issue in issues])) Dell Macintosh HP 60 Gb 80 Gb 120 Gb 19'' LCD 20'' LCD 23'' LCD >>> print('\\n'.join([' '.join(list(issue.all)) for issue in issues2])) Dell Macintosh HP 60 Gb 80 Gb 120 Gb 19'' LCD 20'' LCD 23'' LCD - Forcing Single outcome >>> issues, _ = Issue.from_genius(file_name = pkg_resources.resource_filename('negmas' ... , resource_name='tests/data/Laptop/Laptop-C-domain.xml') ... , force_single_issue=True, keep_value_names=False, keep_issue_names=False) >>> print(list(issues[0].all)) [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26] >>> Issue.to_genius(issues=issues, enumerate_integer=True ... , file_name = pkg_resources.resource_filename('negmas' ... , resource_name='tests/data/LaptopConv/Laptop-C-domain.xml')) >>> issues3, _ = Issue.from_genius(file_name=pkg_resources.resource_filename('negmas' ... , resource_name='tests/data/LaptopConv/Laptop-C-domain.xml')) >>> print([list(issue.all) for issue in issues3]) [['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12', '13', '14', '15', '16', '17', '18', '19', '20', '21', '22', '23', '24', '25', '26']] Remarks: See ``from_xml_str`` for all the parameters """ with open(file_name, "w") as f: f.write( cls.to_xml_str(issues=list(issues), enumerate_integer=enumerate_integer) ) @classmethod def from_xml_str( cls, xml_str: str, force_single_issue=False, keep_value_names=True, keep_issue_names=True, safe_parsing=True, n_discretization: Optional[int] = None, max_n_outcomes: int = 1e6, ): """Exports a list/dict of issues from a GENIUS XML file. Args: xml_str (str): The string containing GENIUS style XML domain issue definitions force_single_issue (bool): Tries to generate a MappingUtility function with a single issue which is the product of all issues in the input keep_value_names (bool): Keep names of values keep_issue_names (bool): Keep names of issues safe_parsing (bool): Turn on extra checks n_discretization (Optional[int]): If not None, real valued issues are discretized with the given number of values max_n_outcomes (int): Maximum number of outcomes allowed (effective only if force_single_issue is True) Returns: - List[Issue] The issues (note that issue names will be stored in the name attribute of each issue if keep_issue_names) - List[dict] A list of agent information dicts each contains 'agent', 'class', 'utility_file_name' Examples: >>> domain_file_name = pkg_resources.resource_filename('negmas' ... , resource_name='tests/data/Laptop/Laptop-C-domain.xml') >>> issues, _ = Issue.from_xml_str(open(domain_file_name, 'r').read() ... , force_single_issue=True, keep_value_names=False, keep_issue_names=False) >>> issue = issues[0] >>> print(issue.cardinality()) 27 >>> print(list(issue.all)) [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26] >>> issues, _ = Issue.from_xml_str(open(domain_file_name, 'r').read() ... , force_single_issue=True, keep_value_names=False, keep_issue_names=True) >>> print(issues[0].name) Laptop-Harddisk-External Monitor >>> print(len(issues)) 1 >>> print(list(issues[0].all)) [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26] >>> issues, _ = Issue.from_xml_str(open(domain_file_name, 'r').read() ... , force_single_issue=True, keep_value_names=True, keep_issue_names=False) >>> issue = issues[0] >>> print(issue.cardinality()) 27 >>> print('\\n'.join(list(issue.all)[:5])) Dell+60 Gb+19'' LCD Dell+60 Gb+20'' LCD Dell+60 Gb+23'' LCD Dell+80 Gb+19'' LCD Dell+80 Gb+20'' LCD >>> issues, _ = Issue.from_xml_str(open(domain_file_name, 'r').read() ... , force_single_issue=False, keep_issue_names=False, keep_value_names=True) >>> type(issues) >>> str(issues[0]) "0: ['Dell', 'Macintosh', 'HP']" >>> print([_.cardinality() for _ in issues]) [3, 3, 3] >>> print('\\n'.join([' '.join(list(issue.all)) for issue in issues])) Dell Macintosh HP 60 Gb 80 Gb 120 Gb 19'' LCD 20'' LCD 23'' LCD >>> issues, _ = Issue.from_xml_str(open(domain_file_name, 'r').read() ... , force_single_issue=False, keep_issue_names=True, keep_value_names=True) >>> len(issues) 3 >>> str(issues[0]) "Laptop: ['Dell', 'Macintosh', 'HP']" >>> print([_.cardinality() for _ in issues]) [3, 3, 3] >>> print('\\n'.join([' '.join(list(issue.all)) for issue in issues])) Dell Macintosh HP 60 Gb 80 Gb 120 Gb 19'' LCD 20'' LCD 23'' LCD >>> issues, _ = Issue.from_xml_str(open(domain_file_name, 'r').read() ... , force_single_issue=False, keep_issue_names=False, keep_value_names=False) >>> len(issues) 3 >>> type(issues) >>> str(issues[0]).split(': ')[-1] '3' >>> print([_.cardinality() for _ in issues]) [3, 3, 3] >>> domain_file_name = pkg_resources.resource_filename('negmas' ... , resource_name='tests/data/fuzzyagent/single_issue_domain.xml') >>> issues, _ = Issue.from_xml_str(open(domain_file_name, 'r').read() ... , force_single_issue=False, keep_issue_names=False, keep_value_names=False) >>> len(issues) 1 >>> type(issues) >>> str(issues[0]).split(': ')[-1] '(10.0, 40.0)' >>> print([_.cardinality() for _ in issues]) [-1] """ root = ET.fromstring(xml_str) if safe_parsing and root.tag != "negotiation_template": raise ValueError(f"Root tag is {root.tag}: negotiation_template") utility_space = None agents = [] for child in root: if child.tag == "utility_space": utility_space = child for _ in utility_space: if _.tag == "objective": utility_space = _ break elif child.tag == "agent": agents.append(child.attrib) if utility_space is None: if safe_parsing: raise ValueError(f"No objective child was found in the root") utility_space = root weights = {} issues = {} issue_info = {} all_discrete = True for child in utility_space: if child.tag == "issue": indx = int(child.attrib["index"]) - 1 myname = child.attrib["name"] issue_key = myname if keep_issue_names else indx issue_info[issue_key] = {"name": myname, "index": indx} info = {"type": "discrete", "etype": "discrete", "vtype": "discrete"} for a in ("type", "etype", "vtype"): info[a] = child.attrib.get(a, info[a]) mytype = info["type"] if mytype == "discrete": issues[issue_key] = [] for item in child: if item.tag == "item": item_indx = int(item.attrib["index"]) - 1 item_name = item.attrib.get("value", None) item_key = ( item_name if keep_value_names and item_name is not None else item_indx ) if ( item_key not in issues[issue_key] ): # ignore repeated items issues[issue_key].append(item_key) if not keep_value_names: issues[issue_key] = len(issues[issue_key]) elif mytype in ("integer", "real"): lower, upper = ( child.attrib.get("lowerbound", None), child.attrib.get("upperbound", None), ) for rng_child in child: if rng_child.tag == "range": lower, upper = ( rng_child.attrib.get("lowerbound", lower), rng_child.attrib.get("upperbound", upper), ) if mytype == "integer": lower, upper = int(lower), int(upper) if keep_value_names: issues[issue_key] = list(range(lower, upper + 1)) else: issues[issue_key] = upper - lower + 1 else: if n_discretization is None: all_discrete = False issues[issue_key] = (float(lower), float(upper)) else: issues[issue_key] = n_discretization else: # I should add the real-valued issues code here raise ValueError(f"Unknown type: {mytype}") else: raise ValueError(f"Unknown child for objective: {child.tag}") for key, value in zip(ikeys(issues), ivalues(issues)): issues[key] = Issue( values=value, name=issue_info[key]["name"] if keep_issue_names else str(issue_info[key]["index"]), ) issues = list(issues.values()) if force_single_issue: issue_name_ = ( "-".join([_.name for _ in issues]) if keep_issue_names else "0" ) if all_discrete or n_discretization is not None: n_outcomes = None if max_n_outcomes is not None: n_items = [len(list(_.alli(n=n_discretization))) for _ in issues] n_outcomes = reduce(mul, n_items, 1) if n_outcomes > max_n_outcomes: return None, None if keep_value_names: if len(issues) > 1: all_values = itertools.product( *[ [str(_) for _ in issue.alli(n=n_discretization)] for issue_key, issue in zip(range(len(issues)), issues) ] ) all_values = list( map(lambda items: "+".join(items), all_values) ) else: all_values = [ str(_) for _ in issues[0].alli(n=n_discretization) ] issues = [Issue(values=all_values, name=issue_name_)] else: if n_outcomes is None: n_items = [_.cardinality() for _ in issues] n_outcomes = reduce(mul, n_items, 1) issues = [Issue(values=n_outcomes, name=issue_name_)] else: return None, None return issues, agents @classmethod def from_genius( cls, file_name: str, force_single_issue=False, keep_value_names=True, keep_issue_names=True, safe_parsing=True, n_discretization: Optional[int] = None, max_n_outcomes: int = 1e6, ): """Imports a the domain issues from a GENIUS XML file. Args: file_name (str): File name to import from Returns: A List[Issue] or Dict[Issue] Examples: >>> issues, _ = Issue.from_genius(file_name = pkg_resources.resource_filename('negmas' ... , resource_name='tests/data/Laptop/Laptop-C-domain.xml')) >>> print([_.name for _ in issues]) ['Laptop', 'Harddisk', 'External Monitor'] Remarks: See ``from_xml_str`` for all the parameters """ with open(file_name, "r", encoding="utf-8") as f: xml_str = f.read() return cls.from_xml_str( xml_str=xml_str, force_single_issue=force_single_issue, keep_value_names=keep_value_names, keep_issue_names=keep_issue_names, safe_parsing=safe_parsing, n_discretization=n_discretization, max_n_outcomes=max_n_outcomes, ) @staticmethod def n_outcomes(issues: Iterable["Issue"]) -> int: """Returns the total number of outcomes in a set of issues. `-1` indicates infinity""" n = 1 for issue in issues: n *= issue.cardinality() if n < 0: return -1 return n @staticmethod def generate( issues: Sequence[Union[int, List[str], Tuple[float, float]]], counts: Optional[Sequence[int]] = None, names: Optional[Sequence[str]] = None, ) -> List["Issue"]: """Generates a set of issues with given parameters. Each is optionally repeated Args: issues: The parameters of the issues counts: The number of times to repeat each of the `issues` names: The names to assign to the issues. If None, then string representations of integers starting from zero will be used. Returns: List['Issue']: The list of issues with given conditions """ one_each = counts is None int_names = names is None result = [] nxt = 0 for i, issue in enumerate(issues): count = 1 if one_each else counts[i] # type: ignore for j in range(count): name = str(nxt) if int_names else names[i] # type: ignore # if count > 1: # name = name + f' {j}' nxt += 1 result.append(Issue(values=issue, name=name)) return result @property def type(self) -> str: """The type of the issue. Returns: str: either 'continuous' or 'discrete' """ if isinstance(self.values, tuple) and isinstance(self.values[0], float): return "continuous" elif isinstance(self.values, int) or isinstance(self.values, list): return "discrete" raise ValueError( "Unknown type. Note that a Tuple[int, int] is not allowed as a range." ) def is_continuous(self) -> bool: """Test whether the issue is a continuous issue Returns: bool: continuous or not """ return self.type.startswith("c") def is_discrete(self) -> bool: """Test whether the issue is a discrete issue Returns: bool: discrete or not """ return self.type.startswith("d") @property def all(self) -> Generator: """A generator that generates all possible values. Remarks: - This function returns a generator for the case when the number of values is very large. - If you need a list then use something like: >>> from negmas.outcomes import Issue >>> list(Issue(5).all) [0, 1, 2, 3, 4] """ if self.is_continuous(): raise ValueError("Cannot return all possibilities of a continuous issue") if isinstance(self.values, int): yield from range(self.values) else: yield from self.values # type: ignore def alli(self, n: Optional[int] = 10) -> Generator: """A generator that generates all possible values or samples n values for real Issues. Remarks: - This function returns a generator for the case when the number of values is very large. - If you need a list then use something like: >>> from negmas.outcomes import Issue >>> list(Issue(5).all) [0, 1, 2, 3, 4] """ if self.is_continuous(): if n is None: raise ValueError("Real valued issue with no discretization value") yield from np.linspace( self.values[0], self.values[1], num=n, endpoint=True ).tolist() if isinstance(self.values, int): yield from range(self.values) else: yield from self.values # type: ignore def cardinality(self) -> int: """The number of possible outcomes for the issue. A negative number means infinite""" if isinstance(self.values, int): return self.values elif self.is_continuous(): return -1 return len(self.values) # type: ignore def rand(self) -> Union[int, float, str]: """Picks a random valid value.""" if isinstance(self.values, int): return random.randint(0, self.values - 1) elif self.is_continuous(): return ( random.random() * (self.values[1] - self.values[0]) + self.values[0] ) # type: ignore return random.choice(self.values) # type: ignore def rand_outcomes( self, n: int, with_replacement=False, fail_if_not_enough=False ) -> Iterable["Outcome"]: """Picks a random valid value.""" if isinstance(self.values, int): if n > self.values and not with_replacement: if fail_if_not_enough: raise ValueError( f"Cannot sample {n} outcomes out of {self.values} without replacement" ) else: return [_ for _ in range(self.values)] if with_replacement: return np.random.randint(low=0, high=self.values, size=n).tolist() else: return random.shuffle([_ for _ in range(self.values)])[:n] elif self.is_continuous(): if with_replacement: return ( np.random.rand(n) * (self.values[1] - self.values[0]) + self.values[0] ).tolist() else: return np.linspace( self.values[0], self.values[1], num=n, endpoint=True ).tolist() if n > len(self.values) and not with_replacement: if fail_if_not_enough: raise ValueError( f"Cannot sample {n} outcomes out of {self.values} without replacement" ) else: return self.values return np.random.choice( np.asarray(self.values, dtype=type(self.values[0])), size=n, replace=with_replacement, ).tolist() rand_valid = rand def rand_invalid(self) -> Union[int, float, str]: """Pick a random *invalid* value""" if isinstance(self.values, int): return random.randint(self.values + 1, 2 * self.values) elif self.is_continuous(): return ( random.random() * (self.values[1]) + self.values[1] + 1e-3 ) # type: ignore pick = ( unique_name("") + str(random.choice(self.values)) + unique_name("") ) # type: ignore return pick @classmethod def enumerate( cls, issues: Collection["Issue"], max_n_outcomes: int = None, astype: Type = dict, ) -> List["Outcome"]: n = num_outcomes(issues) if n is None: return cls.sample(issues=issues, n_outcomes=max_n_outcomes, astype=astype) values = enumerate_outcomes(issues, keep_issue_names=False) if n > max_n_outcomes: values = random.sample(values, max_n_outcomes) outcomes = [] for value in values: if astype == tuple: outcomes.append(tuple(value)) elif astype == dict: outcomes.append(dict(zip((i.name for i in issues), value))) else: outcomes.append(astype(**dict(zip((i.name for i in issues), value)))) return outcomes @classmethod def sample( cls, issues: Collection["Issue"], n_outcomes: int, astype: Type = dict, with_replacement: bool = True, fail_if_not_enough=True, ) -> List["Outcome"]: """ Samples some outcomes from the issue space defined by the list of issues Args: issues: List of issues to sample from n_outcomes: The number of outcomes required astype: The type of the outcomes. It can be `tuple`, `dict` or any `OutcomeType` with_replacement: Whether sampling is with replacement (allowing repetition) fail_if_not_enough: IF given then an exception is raised if not enough outcomes are available Returns: a list of outcomes Examples: >>> from negmas import Issue, OutcomeType >>> issues = [Issue(name='price', values=(0.0, 3.0)), Issue(name='quantity', values=10)] Sampling outcomes as tuples >>> samples = Issue.sample(issues=issues, n_outcomes=10, astype=tuple) >>> len(samples) == 10 True >>> type(samples[0]) == tuple True Sampling outcomes as dicts >>> samples = Issue.sample(issues=issues, n_outcomes=10, astype=dict) >>> len(samples) == 10 True >>> type(samples[0]) == dict True >>> list(samples[0].keys()) ['price', 'quantity'] >>> @dataclass ... class MyOutcome(OutcomeType): ... price: float = 0.0 ... quantity: int = 0 Sampling outcomes as an arbitrary class >>> samples = Issue.sample(issues=issues, n_outcomes=10, astype=MyOutcome) >>> len(samples) == 10 True >>> type(samples[0]) == MyOutcome True >>> list(samples[0].keys()) ['price', 'quantity'] """ n_total = num_outcomes(issues) if ( n_total is not None and n_outcomes is not None and n_total < n_outcomes and fail_if_not_enough and not with_replacement ): raise ValueError( f"Cannot sample {n_outcomes} from a total of possible {n_total} outcomes" ) if n_total is not None and n_outcomes is None: values = enumerate_outcomes(issues=issues, keep_issue_names=False) elif n_total is None and n_outcomes is None: raise ValueError( f"Cannot sample unknown number of outcomes from continuous outcome spaces" ) else: samples = [] for issue in issues: samples.append( issue.rand_outcomes( n=n_outcomes, with_replacement=True, fail_if_not_enough=True ) ) values = [] for i in range(n_outcomes): values.append([s[i] for s in samples]) if not with_replacement: tmp_values = [] for value in values: tmp_values.append(tuple(value)) tmp_values = set(tmp_values) remaining = n_outcomes - len(tmp_values) n_max_trials, i = 10, 0 while remaining < 0 and i < n_max_trials: tmp_values = tmp_values.union( set( cls.sample( issues=issues, n_outcomes=remaining, astype=tuple, with_replacement=True, fail_if_not_enough=False, ) ) ) i += 1 values = list(tmp_values) outcomes = [] for value in values: if astype == tuple: outcomes.append(tuple(value)) elif astype == dict: outcomes.append(dict(zip((i.name for i in issues), value))) else: outcomes.append(astype(**dict(zip((i.name for i in issues), value)))) return outcomes @property def outcome_range(self) -> "OutcomeRange": """An outcome range that represents the full space of the issues""" outcome_range = {} if self.is_continuous(): outcome_range[self.name] = self.values else: outcome_range[self.name] = self.all return outcome_range def __str__(self): return f"{self.name}: {self.values}" __repr__ = __str__ def __hash__(self): return hash(str(self)) def __eq__(self, other): return self.values == other.values and self.name == other.name def __copy__(self): return Issue(name=self.name, values=self.values) def __deepcopy__(self, memodict={}): if isinstance(self.values, list): return Issue(name=self.name, values=[_ for _ in self.values]) return Issue(name=self.name, values=self.values) @classmethod def from_java(cls, d: Dict[str, Any], class_name: str) -> "Issue": if class_name.endswith("ListIssue"): return Issue(name=d.get("name", None), values=d["values"]) if class_name.endswith("RangeIssue"): return Issue(name=d.get("name", None), values=(d["min"], d["max"])) raise ValueError( f"Unknown issue type: {class_name} with dict {d} received from Java" ) def to_java(self): if self.values is None: return None if isinstance(self.values, tuple): if isinstance(self.values[0], int): return { "name": self.name, "min": int(self.values[0]), "max": int(self.values[0]), PYTHON_CLASS_IDENTIFIER: "negmas.outcomes.IntRangeIssue", } else: return { "name": self.name, "min": float(self.values[0]), "max": float(self.values[0]), PYTHON_CLASS_IDENTIFIER: "negmas.outcomes.DoubleRangeIssue", } if isinstance(self.values, Iterable): if isinstance(self.values[0], int): return { "name": self.name, "values": [int(_) for _ in self.values], PYTHON_CLASS_IDENTIFIER: "negmas.outcomes.IntListIssue", } elif isinstance(self.values[0], str): return { "name": self.name, "values": [str(_) for _ in self.values], PYTHON_CLASS_IDENTIFIER: "negmas.outcomes.StringListIssue", } return { "name": self.name, "values": [float(_) for _ in self.values], PYTHON_CLASS_IDENTIFIER: "negmas.outcomes.DoubleListIssue", } class Issues(object): """Encodes a set of Issues. Args: name-value pairs Remarks: - Issues can be initialized by either an iterable of strings, an integer or a tuple of two real values with the following meanings: - ``iterable of strings``: This is an issue that can any value within the given set of values (strings) - ``int``: This is an issue that takes any value from 0 to the given value -1 (int) - ``float``: This is an issue that can take any real value between the given limits (min, max) """ def __init__(self, **kwargs) -> None: self.issues = [Issue(name=k, values=v) for k, v in kwargs.items()] @classmethod def from_issue_collection(cls, issues: Iterable[Issue], name: str = None): out = Issues(name=name) out.issues = issues return out @classmethod def from_single_issue(cls, issue: Issue, name: str = None): return Issues.from_issue_collection([issue], name=name) def n_outcomes(self) -> int: """Returns the total number of outcomes in a set of issues. `-1` indicates infinity""" n = 1 for issue in self.issues: n *= issue.cardinality() if n < 0: return -1 return n @property def types(self) -> List[str]: """The type of the issue. Returns: str: either 'continuous' or 'discrete' """ types_ = [] for issue in self.issues: types_.append(issue.type) return types_ def is_infinite(self) -> bool: """Test whether any issue is continuous (infinite outcome space) Returns: bool: continuous or not """ return any(_.startswith("c") for _ in self.types) def is_finite(self) -> bool: """Test whether all issues are discrete (finite outcome space) Returns: bool: discrete or not """ return all(_.startswith("d") for _ in self.types) @property def all(self) -> Generator: """A generator that generates all possible values. Remarks: - This function returns a generator for the case when the number of values is very large. - If you need a list then use something like: """ if self.is_infinite(): raise ValueError("Cannot return all possibilities of a continuous issues") yield from itertools.product(_.all for _ in self.issues) def cardinality(self) -> int: """The number of possible outcomes for the issue. A negative number means infinite""" return self.n_outcomes() def rand(self) -> Dict[str, Union[int, float, str]]: """Picks a random valid value.""" return {_.name: _.rand() for _ in self.issues} rand_valid = rand def rand_invalid(self) -> Dict[str, Union[int, float, str]]: """Pick a random *invalid* value""" return {_.name: _.rand_invalid() for _ in self.issues} @property def outcome_range(self) -> "OutcomeRange": """An outcome range that represents the full space of the issues""" outcome_range = {} for issue in self.issues: if issue.is_continuous(): outcome_range[issue.name] = issue.values else: outcome_range[issue.name] = issue.all return outcome_range def __str__(self): return "\n".join([str(_) for _ in self.issues]) @dataclass class OutcomeType: """A helper class allowing for definition of types that behave as outcomes (either in the form of dict or tuple). This class is intended to be used when a simple tuple or dict is not enough for describing an outcome (e.g. to use editor features like auto-completion of members). You simply define your class as a dataclass and add your fields to it then inherit from OutcomeType. As we do nothing in the __init__ function, that is compatible with python dataclasses. Examples: >>> from negmas import OutcomeType, Issue >>> @dataclass ... class MyOutcome(OutcomeType): ... price: float = 0.0 ... quantity: int = 0 You can use MyOutcome as an outcome directly or convert it to a tuple/dict for other functions >>> outcome = MyOutcome(price=2.0, quantity=3) >>> outcome.price 2.0 >>> outcome['price'] 2.0 >>> outcome.astuple() (2.0, 3) >>> outcome.asdict() {'price': 2.0, 'quantity': 3} You can also use outputs from issues to initialize your class >>> issues = [Issue(name='price', values=(0.0, 3.0)), Issue(name='quantity', values=10)] >>> sample = Issue.sample(issues=issues, n_outcomes=1)[0] >>> outcome = MyOutcome(**sample) >>> outcome.price == outcome['price'] True """ def __getitem__(self, item): """Makes the outcome type behave like a dict""" return self.__dict__[item] def keys(self) -> List[str]: return tuple(_.name for _ in fields(self)) def values(self) -> List[str]: return tuple(self.__dict__[_.name] for _ in fields(self)) def astuple(self): """Converts the outcome to a tuple where the order of items is the same as they are defined as fields""" return tuple(self.__dict__[_.name] for _ in fields(self)) def asdict(self): """Converts the outcome to a dict containing all fields""" return {_.name: self.__dict__[_.name] for _ in fields(self)} def get(self, name, default: Any = None): """Acts like dict.get""" try: return getattr(self, name, default) except: return default Outcome = Union[ OutcomeType, Tuple[Union[int, float, str, list]], Dict[Union[int, str], Union[int, float, str, list]], ] """An outcome is either a tuple of values or a dict with name/value pairs.""" Outcomes = List["Outcome"] OutcomeRanges = List["OutcomeRange"] OutcomeRange = Mapping[ Union[int, str], Union[ int, float, str, List[int], List[float], List[str], Tuple[int, int], Tuple[float, float], List[Tuple[Union[int, float], Union[int, float]]], ], ] def num_outcomes(issues: Collection[Issue]) -> Optional[int]: n = 1 for issue in issues: c = issue.cardinality() if c < 0: return None n *= c return n def enumerate_outcomes( issues: Iterable[Issue], keep_issue_names=True ) -> Optional[Union[List["Outcome"], Dict[str, "Outcome"]]]: """Enumerates all outcomes of this set of issues if possible Args: issues: keep_issue_names: Returns: List """ try: outcomes = list(itertools.product(*[_.all for _ in issues])) except: return None if keep_issue_names: issue_names = [_.name for _ in issues] for i, outcome in enumerate(outcomes): outcomes[i] = dict(zip(issue_names, outcome)) return outcomes def sample_outcomes( issues: Iterable[Issue], n_outcomes: Optional[int] = None, keep_issue_names=True, min_per_dim=5, expansion_policy=None, ) -> Optional[List[Optional["Outcome"]]]: """Discretizes the issue space and returns either a predefined number of outcomes or uniform samples Args: issues: The issues describing the issue space to be discretized n_outcomes: If None then exactly `min_per_dim` bins will be used for every continuous dimension and all outcomes will be returned keep_issue_names: min_per_dim: expansion_policy: None or 'repeat' or 'null' or 'no'. If repeat, then some of the outcomes will be repeated if None or 'no' then no expansion will happen if the total number of outcomes is less than n_outcomes. If 'null' then expansion will be with None values Returns: List Examples: enumberate the whole space >>> issues = [Issue(values=(0, 1), name='Price'), Issue(values=['a', 'b'], name='Name')] >>> sample_outcomes(issues=issues) [{'Price': 0.0, 'Name': 'a'}, {'Price': 0.0, 'Name': 'b'}, {'Price': 0.25, 'Name': 'a'}, {'Price': 0.25, 'Name': 'b'}, {'Price': 0.5, 'Name': 'a'}, {'Price': 0.5, 'Name': 'b'}, {'Price': 0.75, 'Name': 'a'}, {'Price': 0.75, 'Name': 'b'}, {'Price': 1.0, 'Name': 'a'}, {'Price': 1.0, 'Name': 'b'}] enumerate with sampling for very large space (we have 10 outcomes in the discretized space) >>> issues = [Issue(values=(0, 1), name='Price'), Issue(values=['a', 'b'], name='Name')] >>> sampled=sample_outcomes(issues=issues, n_outcomes=5) >>> len(sampled) 5 >>> len(set(tuple(_.values()) for _ in sampled)) 5 """ issues = [_ for _ in issues] continuous = [] indx = [] discrete = [] n_disc = 0 for i, issue in enumerate(issues): if issue.is_continuous(): continuous.append(issue) indx.append(i) else: discrete.append(issue) n_disc += issue.cardinality() if len(continuous) > 0: if n_outcomes is not None: n_per_issue = max(min_per_dim, (n_outcomes - n_disc) / len(continuous)) else: n_per_issue = min_per_dim for i, issue in enumerate(continuous): issues[indx[i]] = Issue( name=issue.name, values=list( np.linspace( issue.values[0], issue.values[1], num=n_per_issue, endpoint=True ).tolist() ), ) cardinality = 1 for issue in issues: cardinality *= issue.cardinality() if cardinality == n_outcomes or n_outcomes is None: return list(enumerate_outcomes(issues, keep_issue_names=keep_issue_names)) if cardinality < n_outcomes: outcomes = list(enumerate_outcomes(issues, keep_issue_names=keep_issue_names)) if expansion_policy == "no" or expansion_policy is None: return outcomes elif expansion_policy == "null": return outcomes + [None] * (n_outcomes - cardinality) elif expansion_policy == "repeat": n_reps = n_outcomes // cardinality n_rem = n_outcomes % cardinality if n_reps > 1: for _ in n_reps: outcomes += outcomes if n_rem > 0: outcomes += outcomes[:n_rem] return outcomes return list( random.sample( enumerate_outcomes(issues, keep_issue_names=keep_issue_names), n_outcomes ) ) def _is_single(x): """Checks whether a value is a single value which is defined as either a string or not an Iterable.""" return isinstance(x, str) or isinstance(x, int) or isinstance(x, float) def outcome_is_valid(outcome: Outcome, issues: Collection[Issue]) -> bool: """Test validity of an outcome given a set of issues. Examples: >>> issues = [Issue((0.5, 2.0), 'price'), Issue(['2018.10.'+ str(_) for _ in range(1, 4)], 'date')\ , Issue(20, 'count')] >>> for _ in issues: print(_) price: (0.5, 2.0) date: ['2018.10.1', '2018.10.2', '2018.10.3'] count: 20 >>> print([outcome_is_valid({'price':3.0}, issues), outcome_is_valid({'date': '2018.10.4'}, issues)\ , outcome_is_valid({'count': 21}, issues)]) [False, False, False] >>> valid_incomplete = {'price': 1.9} >>> print(outcome_is_valid(valid_incomplete, issues)) True >>> print(outcome_is_complete(valid_incomplete, issues)) False >>> valid_incomplete.update({'date': '2018.10.2', 'count': 5}) >>> print(outcome_is_complete(valid_incomplete, issues)) True Args: outcome: outcome tested which can contain values for a partial set of issue values issues: issues Returns: Union[bool, Tuple[bool, str]]: If return_problem is True then a second return value contains a string with reason of failure """ for issue in issues: for key in ikeys(outcome): if issue.name == str(key): break else: continue value = iget(outcome, key) if isinstance(issue.values, int) and ( isinstance(value, str) or not 0 <= value < issue.values ): return False elif isinstance(issue.values, tuple) and ( isinstance(value, str) or not issue.values[0] < value < issue.values[1] ): return False elif isinstance(issue.values, list) and value not in issue.values: return False return True def outcome_is_complete(outcome: Outcome, issues: Collection[Issue]) -> bool: """Tests that the outcome is valid and complete. Examples: >>> issues = [Issue((0.5, 2.0), 'price'), Issue(['2018.10.'+ str(_) for _ in range(1, 4)], 'date')\ , Issue(20, 'count')] >>> for _ in issues: print(_) price: (0.5, 2.0) date: ['2018.10.1', '2018.10.2', '2018.10.3'] count: 20 >>> print([outcome_is_complete({'price':3.0}, issues), outcome_is_complete({'date': '2018.10.4'}, issues)\ , outcome_is_complete({'count': 21}, issues)]) [False, False, False] >>> valid_incomplete = {'price': 1.9} >>> print(outcome_is_complete(valid_incomplete, issues)) False >>> valid_incomplete.update({'date': '2018.10.2', 'count': 5}) >>> print(outcome_is_complete(valid_incomplete, issues)) True >>> invalid = {'price': 2000, 'date': '2018.10.2', 'count': 5} >>> print(outcome_is_complete(invalid, issues)) False >>> invalid = {'unknown': 2000, 'date': '2018.10.2', 'count': 5} >>> print(outcome_is_complete(invalid, issues)) False Args: outcome: outcome tested which much contain valid values all issues if it is to be considered complete. issues: issues Returns: Union[bool, Tuple[bool, str]]: If return_problem is True then a second return value contains a string with reason of failure """ if len(outcome) != len(issues): return False valid = outcome_is_valid(outcome, issues) if not valid: return False for issue in issues: if issue.name not in outcome.keys(): return False return True def outcome_range_is_valid( outcome_range: OutcomeRange, issues: Optional[Collection[Issue]] = None ) -> Union[bool, Tuple[bool, str]]: """Tests whether the outcome range is valid for the set of issues. Args: outcome_range: issues: Example: >>> try: ... outcome_range_is_valid({'price': (0, 10)}) ... except NotImplementedError: ... print('Not implemented') Not implemented Returns: """ # TODO implement this function raise NotImplementedError() def outcome_range_is_complete( outcome_range: OutcomeRange, issues: Optional[Collection[Issue]] = None ) -> Union[bool, Tuple[bool, str]]: """Tests whether the outcome range is valid and complete for the set of issues Args: outcome_range: issues: Example: >>> try: ... outcome_range_is_complete({'price': (0, 10)}) ... except NotImplementedError: ... print('Not implemented') Not implemented Returns: """ # TODO implement this function raise NotImplementedError() ################################# # Outcome space implementation # ################################# def outcome_in_range( outcome: Outcome, outcome_range: OutcomeRange, *, strict=False, fail_incomplete=False, ) -> bool: """ Tests that the outcome is contained within the given range of outcomes. An outcome range defines a value or a range of values for each issue. Args: outcome: Outcome being tested outcome_range: Outcome range being tested against strict: Whether to enforce that all issues in the outcome must be mentioned in the outcome_range fail_incomplete: If True then outcomes that do not sepcify a value for all keys in the outcome_range will be considered not falling within it. If False then these outcomes will be considered falling within the range given that the values for the issues mentioned in the outcome satisfy the range constraints. Examples: >>> outcome_range = {'price': (0.0, 2.0), 'distance': [0.3, 0.4], 'type': ['a', 'b'], 'area': 3} >>> outcome_range_2 = {'price': [(0.0, 1.0), (1.5, 2.0)], 'area': [(3, 4), (7, 9)]} >>> outcome_in_range({'price':3.0}, outcome_range) False >>> outcome_in_range({'date': '2018.10.4'}, outcome_range) True >>> outcome_in_range({'date': '2018.10.4'}, outcome_range, strict=True) False >>> outcome_in_range({'area': 3}, outcome_range, fail_incomplete=True) False >>> outcome_in_range({'area': 3}, outcome_range) True >>> outcome_in_range({'type': 'c'}, outcome_range) False >>> outcome_in_range({'type': 'a'}, outcome_range) True >>> outcome_in_range({'date': '2018.10.4'}, outcome_range_2) True >>> outcome_in_range({'area': 3.1}, outcome_range_2) True >>> outcome_in_range({'area': 3}, outcome_range_2) False >>> outcome_in_range({'area': 5}, outcome_range_2) False >>> outcome_in_range({'price': 0.4}, outcome_range_2) True >>> outcome_in_range({'price': 0.4}, outcome_range_2, fail_incomplete=True) False >>> outcome_in_range({'price': 1.2}, outcome_range_2) False >>> outcome_in_range({'price': 0.4, 'area': 3.9}, outcome_range_2) True >>> outcome_in_range({'price': 0.4, 'area': 10}, outcome_range_2) False >>> outcome_in_range({'price': 1.2, 'area': 10}, outcome_range_2) False >>> outcome_in_range({'price': 1.2, 'area': 4}, outcome_range_2) False >>> outcome_in_range({'type': 'a'}, outcome_range_2) True >>> outcome_in_range({'type': 'a'}, outcome_range_2, strict=True) False >>> outcome_range = {'price': 10} >>> outcome_in_range({'price': 10}, outcome_range) True >>> outcome_in_range({'price': 11}, outcome_range) False Returns: bool: Success or failure Remarks: Outcome ranges specify regions in an outcome space. They can have any of the following conditions: - A key/issue not mentioned in the outcome range does not add any constraints meaning that **All** values are acceptable except if strict == True. If strict == True then *NO* value will be accepted for issues not in the outcome_range. - A key/issue with the value None in the outcome range means **All** values on this issue are acceptable. This is the same as having this key/issue removed from the outcome space - A key/issue withe the value [] (empty list) accepts *NO* outcomes - A key/issue with a single value means that it is the only one acceptable - A key/issue with a single 2-items tuple (min, max) means that any value within that range is acceptable. - A key/issue with a list of values means an output is acceptable if it falls within the condition specified by any of the values in the list (list == union). Each such value can be a single value, a 2-items tuple or another list. Notice that lists of lists can always be combined into a single list of values """ if ( fail_incomplete and len(set(ikeys(outcome_range)).difference(ikeys(outcome))) > 0 ): return False for key, value in ienumerate(outcome): if key not in ikeys(outcome_range): if strict: return False continue values = iget(outcome_range, key, None) if values is None: return False if _is_single(values) and value != values: return False if isinstance(values, tuple) and not values[0] < value < values[1]: return False if isinstance(values, list): for constraint in values: if _is_single(constraint): if value == constraint: break elif isinstance(constraint, list): if value in constraint: break elif isinstance(constraint, tuple): if constraint[0] < value < constraint[1]: break else: return False continue return True # # def _make_iterable( # v: Union[list, tuple, int, str, float] # ) -> Union[list, tuple]: # """Ensures the output is an Iterable if it was a single value. # # >>> [_make_iterable(1), _make_iterable('1'), _make_iterable(1.0), _make_iterable([1])] # [{1}, {'1'}, {1.0}, {1}] # # """ # if _is_single(v): # return {v} # # return set(v) # # # def _intersect_tuples(v1: tuple, v2: tuple) -> tuple: # """Finds intersection between two tuples. # # Examples: # # >>> print(_intersect_tuples((0.0, 1.0), (1.1, 2.0))) # (0.0, 0.0) # >>> _intersect_tuples((0.0, 1.0), (1.0, 2.0)) # (1.0, 1.0) # >>> _intersect_tuples((0.0, 1.0), (0.5, 2.0)) # (0.5, 1.0) # # """ # if not (v1[0] <= v2[0] <= v1[1] or v2[0] <= v1[0] <= v2[1]): # return (v1[0], v1[0]) # # return max((v1[0], v2[0])), min((v1[1], v2[1])) # # # def _union_tuples(v1: tuple, v2: tuple) -> Union[tuple, List[tuple]]: # """The union of two tuples. # # Examples: # # >>> _union_tuples((0.0, 1.0), (0.0, 1.0)) # (0.0, 1.0) # >>> _union_tuples((0.0, 1.0), (0.5, 1.0)) # (0.0, 1.0) # >>> _union_tuples((0.0, 1.0), (0.5, 2.0)) # (0.0, 2.0) # >>> _union_tuples((0.0, 1.0), (1.0, 2.0)) # [(0.0, 1.0), (1.0, 2.0)] # >>> _union_tuples((0.0, 1.0), (2.0, 3.0)) # [(0.0, 1.0), (2.0, 3.0)] # # """ # if v1[0] == v2[0] and v1[1] == v2[1]: # return v1 # # if not (v1[0] < v2[0] < v1[1] or v2[0] < v1[0] < v2[1]): # return [v1, v2] # # return min((v1[0], v2[0])), max((v1[1], v2[1])) # # # def _subtract_tuples(v1: tuple, v2: tuple) -> Union[tuple, List[tuple]]: # """The difference between first and second tuple (v1 - v2) # # Examples: # # >>> _subtract_tuples((0.0, 1.0), (-1.0, 0.0)) # (0.0, 1.0) # >>> _subtract_tuples((0.0, 1.0), (-1.0, 0.5)) # (0.5, 1.0) # >>> _subtract_tuples((0.0, 1.0), (0.2, 0.5)) # [(0.0, 0.2), (0.5, 1.0)] # >>> _subtract_tuples((0.0, 1.0), (0.5, 1.5)) # (0.0, 0.5) # >>> _subtract_tuples((0.0, 1.0), (1.5, 2.0)) # (0.0, 1.0) # # """ # v = _intersect_tuples(v1, v2) # if v[0] == v[1]: # return v1 # # if v[0] <= v1[0] and v[1] <= v1[1]: # return (v[1], v1[1]) # # if v[0] > v1[0] and v[1] < v1[1]: # return [(v1[0], v[0]), (v[1], v1[1])] # # return (v1[0], v[0]) # # # def _apply_on_lists( # v1: Union[set, list], v2: Union[set, list], op: str # ) -> set: # """Applies a set operation on lists. # # Examples: # # >>> _apply_on_lists([1, 2, 3], [2, 4 ,5], 'intersection') # {2} # >>> _apply_on_lists([1, 2, 3], [2, 4 ,5], 'union') # {1, 2, 3, 4, 5} # >>> _apply_on_lists([1, 2, 3], [2, 4 ,5], 'subtract') # {1, 3} # # """ # v1, v2 = set(v1), set(v2) # if op.startswith('i'): # return v1.intersection(v2) # # elif op.startswith('u'): # return v1.union(v2) # # elif op.startswith('s'): # return v1.difference(v2) # raise ValueError() # # # def _intersect_list_tuple(lst: list, tpl: tuple) -> list: # """Intersection between a list and tuple. # # Examples: # # >>> _intersect_list_tuple([1, 2, 3], (2.5, 4.0)) # [3] # >>> _intersect_list_tuple([1, 2, 3], (6.0, 7.0)) # [] # >>> _intersect_list_tuple([1, 2, 3], (0.0, 3.0)) # [1, 2, 3] # >>> _intersect_list_tuple([], (0.0, 3.0)) # [] # # """ # result = [] # for _ in lst: # if tpl[0] <= _ <= tpl[1]: # result.append(_) # return result # # # def _union_list_tuple( # lst: list, tpl: tuple # ) -> Union[tuple, List[Union[tuple, list]]]: # """Finds the union between a list and a tuple. # # Examples: # # >>> _union_list_tuple([1, 2, 3], (2.5, 4.0)) # [(2.5, 4.0), [1, 2, 3]] # >>> _union_list_tuple([1, 2, 3], (6.0, 7.0)) # [(6.0, 7.0), [1, 2, 3]] # >>> _union_list_tuple([1, 2, 3], (0.0, 3.0)) # (0.0, 3.0) # >>> _union_list_tuple([], (0.0, 3.0)) # (0.0, 3.0) # # """ # for _ in lst: # if not (tpl[0] <= _ <= tpl[1]): # return [tpl, lst] # # return tpl # def range_intersection(r1: OutcomeRange, r2: OutcomeRange) -> OutcomeRange: # """A new outcome range at the intersection of given outcome ranges # # Examples: # >>> r1 = {'price': (0.0, 1.0), 'cost':[1, 2, 3, 4, 5] # ... , 'delivery': ['yes', 'no'], 'honor':'yes'} # >>> r2 = {'price': (0.5, 2.0), 'cost':[4, 5, 6] # ... , 'delivery': ['yes'], 'honor':'yes'} # >>> r3 = {'price': (0.5, 2.0), 'cost':[4, 5, 6] # ... , 'delivery': ['yes'], 'honor':'no'} # >>> r4 = {'price': (0.5, 2.0), 'cost':[4, 5, 6] # ... , 'delivery': 'yes', 'honor':'yes'} # >>> r5 = {'price': [1.0, 3.0], 'cost':[4, 5, 6] # ... , 'delivery': 'yes', 'honor':None} # >>> r6 = {'price': [1.0, 3.0], 'cost':[4, 5, 6] # ... , 'delivery': 'yes', 'honor':[]} # >>> r7 = {'price': 9.0, 'cost':[4, 5, 6] # ... , 'delivery': 'yes', 'honor':None} # >>> r8 = {'price': 0.5, 'cost':[9] # ... , 'delivery': 'no', 'honor':None} # >>> r9 = {'price': 0.5} # >>> range_intersection(r1, r2) # {'price': (0.5, 1.0), 'cost': [4, 5], 'delivery': 'yes', 'honor': 'yes'} # >>> range_intersection(r1, r3) # {'price': (0.5, 1.0), 'cost': [4, 5], 'delivery': 'yes', 'honor': []} # >>> range_intersection(r1, r4) # {'price': (0.5, 1.0), 'cost': [4, 5], 'delivery': 'yes', 'honor': 'yes'} # >>> range_intersection(r1, r5) # {'price': 1.0, 'cost': [4, 5], 'delivery': 'yes', 'honor': 'yes'} # >>> range_intersection(r1, r6) # {'price': 1.0, 'cost': [4, 5], 'delivery': 'yes', 'honor': []} # >>> range_intersection(r1, r7) # {'price': [], 'cost': [4, 5], 'delivery': 'yes', 'honor': 'yes'} # >>> range_intersection(r1, r8) # {'price': 0.5, 'cost': [], 'delivery': 'no', 'honor': 'yes'} # >>> range_intersection(r1, r9) # {'price': 0.5, 'cost': [1, 2, 3, 4, 5], 'delivery': ['yes', 'no'], 'honor': 'yes'} # # """ # r = {} # r1 = range_simplify(r1, compress=False) # r2 = range_simplify(r2, compress=False) # for k, v1 in r1.items(): # if k not in r2.keys(): # r[k] = copy.copy(v1) # continue # v2 = r2[k] # if v1 is None: # r[k] = copy.copy(v2) # continue # if v2 is None: # r[k] = copy.copy(v1) # continue # v1 = copy.copy(_make_iterable(v1)) # v2 = copy.copy(_make_iterable(v2)) # if isinstance(v1, tuple) and isinstance(v2, tuple): # r[k] = _intersect_tuples(v1, v2) # elif isinstance(v1, tuple) and not isinstance(v2, tuple): # r[k] = _intersect_list_tuple(lst=v2, tpl=v1) # elif not isinstance(v1, tuple) and isinstance(v2, tuple): # r[k] = _intersect_list_tuple(lst=v1, tpl=v2) # else: # r[k] = set(v1).intersection(v2) # if isinstance(r[k], list) and len(r[k]) == 1: # r[k] = r[k][0] # return r # # # def range_simplify(r: OutcomeRange, compress: bool=False) -> OutcomeRange: # """Simplifies an outcome range. # # Args: # # r: The outcome range # compress: If true the dimensions that are not constrained are removed. # # Examples: # # >>> range_simplify({'a': [5], 'b': [4, 1, 3, 2], 'c': (1.0, 1.0)}) # {'a': 5, 'b': [4, 1, 3, 2], 'c': 1.0} # # >>> range_simplify({'a': [5], 'b': [4, 1, 3, 2], 'c': [(0.0, 2.0), (1.5, 3.0) # ... , 4, 2, [1, 2, 3], [1], (0.5, 0.5)]}) # {'a': 5, 'b': [1, 2, 3, 4], 'c': [(0.0, 3.0), [1, 2, 3, 4]] # # # """ # # def _simplify_value(cutoff_utility): # """Puts the value in the most compressed form. """ # # if _is_single(cutoff_utility): # return cutoff_utility # if isinstance(cutoff_utility, tuple) and cutoff_utility[0] == cutoff_utility[1]: # return cutoff_utility[0] # if isinstance(cutoff_utility, list) and len(cutoff_utility) == 1: # return cutoff_utility # if isinstance(cutoff_utility, list): # combined_list = [] # tuples = [] # for item in cutoff_utility: # if _is_single(item): # combined_list.append(item) # elif isinstance(item, tuple): # tuples.append(item) # elif isinstance(item, list): # combined_list += item # else: # raise ValueError('not a single, tuple or list!!! cannot understand') # if len(tuples) > 1: # results = _union_tuples(tuples[0], tuples[1]) # for i in range(2, len(tuples)): # results = _union_tuples(results, tuples[i]) # tuples = results # if isinstance(tuples, tuple): # tuples = [tuples] # cutoff_utility = tuples + sorted(list(set(combined_list))) # if len(cutoff_utility) == 1: # cutoff_utility = cutoff_utility[0] # return cutoff_utility # # keys = sorted(r.keys()) # return {k: _simplify_value(r[k]) for k in keys} # # # def range_equal(r1: OutcomeRange, r2: OutcomeRange) -> OutcomeRange: # """Tests if the two outcomes are equal # # Examples: # >>> range_equal({'a': 5, 'b': [1, 2, 3, 4], 'c': (1.0, 2.0)}, # ... {'a': [5], 'b': [4, 1, 3, 2], 'c': (1.0, 2.0)}) # # """ # # def range_union(r1: OutcomeRange, r2: OutcomeRange) -> OutcomeRange: # """A new outcome range covering the union of input outcome ranges. # # Examples: # >>> r1 = {'price': (0.0, 1.0), 'cost':[1, 2, 3, 4, 5] # ... , 'delivery': ['yes', 'no'], 'honor':'yes'} # >>> r2 = {'price': (0.5, 2.0), 'cost':[4, 5, 6] # ... , 'delivery': ['yes'], 'honor':'yes'} # >>> r3 = {'price': (0.5, 2.0), 'cost':[4, 5, 6] # ... , 'delivery': ['yes'], 'honor':'no'} # >>> r4 = {'price': (0.5, 2.0), 'cost':[4, 5, 6] # ... , 'delivery': 'yes', 'honor':'yes'} # >>> r5 = {'price': [1.0, 3.0], 'cost':[4, 5, 6] # ... , 'delivery': 'yes', 'honor':None} # >>> r6 = {'price': [1.0, 3.0], 'cost':[4, 5, 6] # ... , 'delivery': 'yes', 'honor':[]} # >>> r7 = {'price': 9.0, 'cost':[4, 5, 6] # ... , 'delivery': 'yes', 'honor':None} # >>> r8 = {'price': 0.5, 'cost':[9] # ... , 'delivery': 'no', 'honor':None} # >>> r9 = {'price': 0.5} # >>> range_union(r1, r2) # {'honor': 'yes', 'cost': [1, 2, 3, 4, 5, 6], 'price': (0.0, 2.0), 'delivery': ['yes', 'no']} # >>> range_union(r1, r3) # {'honor': ['yes', 'no'], 'cost': [1, 2, 3, 4, 5, 6], 'price': (0.0, 2.0), 'delivery': ['yes', 'no']} # >>> range_union(r1, r4) # {'honor': 'yes', 'cost': [1, 2, 3, 4, 5, 6], 'price': (0.0, 2.0), 'delivery': ['yes', 'no']} # >>> range_union(r1, r5) # {'honor': None, 'cost': [1, 2, 3, 4, 5, 6], 'price': [(0.0, 1.0), [3]], 'delivery': ['yes', 'no']} # >>> range_union(r1, r6) # {'honor': 'yes', 'cost': [1, 2, 3, 4, 5, 6], 'price': [(0.0, 1.0), [3]], 'delivery': ['yes', 'no']} # >>> range_union(r1, r7) # {'honor': None, 'cost': [1, 2, 3, 4, 5, 9], 'price': [(0.0, 1.0), [9.0]], 'delivery': ['yes', 'no']} # >>> range_union(r1, r8) # {'honor': None, 'cost': [1, 2, 3, 4, 5, 6], 'price': (0.0, 1.0), 'delivery': ['yes', 'no']} # >>> range_union(r1, r9) # {'honor': None, 'cost': None, 'price': (0.0, 1.0), 'delivery': None} # # """ # r = {} # all_k = list(set(r1.keys()).union(r2.keys())) # for k in all_k: # if k not in r1.keys(): # r[k] = None # continue # if k not in r2.keys(): # r[k] = None # continue # v1, v2 = r1[k], r2[k] # if v1 is None or v2 is None: # r[k] = None # continue # v1 = _make_iterable(v1) # v2 = _make_iterable(v2) # if isinstance(v1, tuple) and isinstance(v2, tuple): # r[k] = _union_tuples(v1, v2) # elif isinstance(v1, tuple) and not isinstance(v2, tuple): # r[k] = _union_list_tuple(lst=v2, tpl=v1) # elif not isinstance(v1, tuple) and isinstance(v2, tuple): # r[k] = _union_list_tuple(lst=v1, tpl=v2) # else: # r[k] = _apply_on_lists(v1, v2, 'union') # return r # # def range_subtract(r1: OutcomeRange, r2: OutcomeRange, parent1: OutcomeRange=None, parent2: OutcomeRange=None) -> OutcomeRange: # r = {} # # for k, v1 in r1.items(): # if k not in r2.keys(): # r[k] = [] # continue # v2 = r2[k] # if v1 is None: # if parent1 is None: # raise RuntimeError('No parent is defined, cannot invert') # r[k] = range_invert({k: v2}, {k: parent1.get(k, None)}) # continue # v1 = _make_iterable(v1) # v2 = _make_iterable(v2) # if isinstance(v1, tuple) and isinstance(v2, tuple): # r[k] = _subtract_tuples(v1, v2) # elif isinstance(v1, tuple) and not isinstance(v2, tuple): # r[k] = _subtract_list_tuple(lst=v2, tpl=v1) # elif not isinstance(v1, tuple) and isinstance(v2, tuple): # r[k] = _subtract_list_tuple(lst=v1, tpl=v2) # else: # r[k] = _apply_on_lists(v1, v2, 'subtract') # return r # # # def range_invert(r1: OutcomeRange, issues=Iterable[Issue], resolution=1e-6) -> OutcomeRange: # r = {} # # for k, v1 in r1.items(): # if v1 is None: # r[k] = [] # continue # # TODO complete this # # return r # # # def _dim_cardinality(x: Any, recursing=False) -> Union[int, float]: # if isinstance(x, str): # return 1 # if isinstance(x, int) and not recursing: # return x # if isinstance(x, tuple): # if x[0] != x[1]: # return math.inf # else: # return 1 # if isinstance(x, Iterable): # return sum([_dim_cardinality(_, recursing=True) for _ in x]) # return 1 # # # def _all_values(x: Any, recursing=False): # if isinstance(x, str): # yield x # raise StopIteration # if isinstance(x, int) and not recursing: # yield from range(x) # raise StopIteration # if isinstance(x, tuple): # raise RuntimeError('Cannot iterate over ranges (tuples)') # if isinstance(x, Iterable): # yield from x # raise StopIteration SingleValue = Union[int, float, str] EPSILON = 1e-9 # class SingleIssueSpace(NamedObject): # """Encodes the space of values for a single issue. # # Examples: # # You can define a complex issue space combining ranges and sets of values: # >>> everything = SingleIssueSpace(ranges= (20.0, 30.0), count = 10, name='everything') # >>> print(everything) # everything: (20.0, 30.0) and {0, 1, 2, 3, 4, 5, 6, 7, 8, 9} # # You can create child issue spaces that belong to it as needed # >>> i1 = SingleIssueSpace(ranges= (20.0, 25.0), values = [1, 2, 3, 4, 5], name='i1', parent=everything) # >>> i2 = SingleIssueSpace(ranges= (20.0, 25.0), name='i2', parent=everything) # >>> i3 = SingleIssueSpace(values = [1, 2, 3, 4, 5], name='i3', parent=everything) # >>> i4 = SingleIssueSpace(values = [6, 7, 8, 9], ranges = (25.0, 29.0), name='i3', parent=everything) # # You can make complex spaces by combining them arbitrary using arithmetic operators # >>> print(everything - ((i2 + i3) )) # (everything-(i2+i3)): (25.0, 30.0) and {0, 6, 7, 8, 9} # >>> print(-(i2 + i4)) # -(i2+i3): (29.0, 30.0) and {0, 1, 2, 3, 4, 5} # # You can also use logical operators # >>> print(everything % ((i2 | i3) )) # (everything-(i2+i3)): (25.0, 30.0) and {0, 6, 7, 8, 9} # >>> print(~(i2 | i4)) # -(i2+i3): (29.0, 30.0) and {0, 1, 2, 3, 4, 5} # # # See the documentation of arithmetic operators to find more examples # # """ # __slots__ = ['ranges', 'values', 'parent', 'everything'] # # def __init__( # self, # ranges: Union[Tuple[Any, Any], Iterable[Tuple[Any, Any]]] = None, # values: Iterable[SingleValue] = None, # count: int = None, # parent: 'SingleIssueSpace' = None, # everything=False, # name: str = None, # ): # super().__init__(name=name) # self.parent = parent # self.everything = everything # if everything: # self.ranges = self.values = None # else: # if ranges is None: # ranges = [] # if values is None: # values = [] # if isinstance(ranges, tuple): # ranges = [ranges] # self.ranges = list(ranges) # self.values = set(values) # if count is not None: # self.values = self.values.union(range(count)) # self.simplify() # # @property # def n_outcomes(self) -> Union[int, float]: # """Returns the total number of outcomes in a set of issues. `math.inf` indicates infinity # # Examples: # # >>> from negmas import SingleIssueSpace # >>> SingleIssueSpace(ranges=(0.0, 1.0), values=[2.0, 3.0, 4.0]).n_outcomes # inf # >>> SingleIssueSpace(values=[2.0, 3.0, 4.0]).n_outcomes # 3 # >>> SingleIssueSpace(count=10).n_outcomes # 10 # >>> SingleIssueSpace(count=10, values=[20, 30, 40]).n_outcomes # 13 # >>> SingleIssueSpace(count=10, values=[20, 30, 40, 40, 40]).n_outcomes # 13 # >>> SingleIssueSpace(count=10, values=[1, 2, 4]).n_outcomes # 10 # # # """ # if self.everything: # return self.parent.n_outcomes if self.parent is not None else math.inf # # if len(self.ranges) > 0: # return math.inf # # return len(self.values) # # @property # def cardinalities(self) -> Dict[str, Union[int, float]]: # """The cardinality of that issue space with its name. Useful when creating complex OutcomeSpaces # # Examples: # # >>> from negmas import SingleIssueSpace # >>> SingleIssueSpace(name='issue', ranges=(0.0, 1.0), values=[2.0, 3.0, 4.0]).cardinalities # {'issue': inf} # >>> SingleIssueSpace(name='issue', values=[2.0, 3.0, 4.0]).cardinalities # {'issue': 3} # >>> SingleIssueSpace(name='issue', count=10).cardinalities # {'issue': 10} # >>> SingleIssueSpace(name='issue', count=10, values=[20, 30, 40]).cardinalities # {'issue': 13} # >>> SingleIssueSpace(name='issue', count=10, values=[20, 30, 40, 40, 40]).cardinalities # {'issue': 13} # >>> SingleIssueSpace(name='issue', count=10, values=[1, 2, 4]).cardinalities # {'issue': 10} # # """ # return {self.name: self.cardinality} # # @property # def type(self) -> str: # """The type of the issue. # # Returns: # str: either 'continuous' or 'discrete' # # Examples: # # >>> from negmas import SingleIssueSpace # >>> SingleIssueSpace(name='issue', ranges=(0.0, 1.0), values=[2.0, 3.0, 4.0]).type # 'continuous' # >>> SingleIssueSpace(name='issue', values=[2.0, 3.0, 4.0]).type # 'discrete' # >>> SingleIssueSpace(name='issue', count=10).type # 'discrete' # >>> SingleIssueSpace(name='issue', count=10, values=[20, 30, 40]).type # 'discrete' # # """ # if self.everything: # return self.parent.type if self.parent is not None else ( # 'continuous' if len(self.ranges) > 0 else 'discrete' # ) # # return 'continuous' if len(self.ranges) > 0 else 'discrete' # # @property # def infinite(self) -> bool: # """Test whether any issue is continuous (infinite outcome space) # # Returns: # bool: continuous (== infinite) or not # # Examples: # # >>> from negmas import SingleIssueSpace # >>> SingleIssueSpace(name='issue', ranges=(0.0, 1.0), values=[2.0, 3.0, 4.0]).infinite # True # >>> SingleIssueSpace(name='issue', values=[2.0, 3.0, 4.0]).infinite # False # >>> SingleIssueSpace(name='issue', count=10).infinite # False # >>> SingleIssueSpace(name='issue', count=10, values=[20, 30, 40]).infinite # False # # """ # if self.everything: # return self.parent.infinite if self.parent is not None else len( # self.ranges # ) > 0 # # return len(self.ranges) > 0 # # @property # def finite(self) -> bool: # """Test whether all issues are discrete (finite outcome space) # # Returns: # bool: discrete or not # # Examples: # # >>> from negmas import SingleIssueSpace # >>> SingleIssueSpace(name='issue', ranges=(0.0, 1.0), values=[2.0, 3.0, 4.0]).finite # False # >>> SingleIssueSpace(name='issue', values=[2.0, 3.0, 4.0]).finite # True # >>> SingleIssueSpace(name='issue', count=10).finite # True # >>> SingleIssueSpace(name='issue', count=10, values=[20, 30, 40]).finite # True # # """ # return not self.infinite # # @property # def all(self) -> Generator: # """A generator that generates all possible values. # # Remarks: # - This function returns a generator for the case when the number of values is very large. # - If you need a list then use something like: # # # Examples: # # >>> from negmas import SingleIssueSpace # >>> try: # ... list(SingleIssueSpace(name='issue', ranges=(0.0, 1.0), values=[2.0, 3.0, 4.0]).all) # ... except ValueError: # ... print('failed') # failed # >>> list(SingleIssueSpace(name='issue', values=[2.0, 3.0, 4.0]).all) # [2.0, 3.0, 4.0] # >>> list(SingleIssueSpace(name='issue', count=10).all) # [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] # >>> parent = SingleIssueSpace(name='issue', count=10) # >>> list(SingleIssueSpace(name='issue', count=3, parent=parent).all) # [0, 1, 2] # >>> list(SingleIssueSpace(name='issue', parent=parent).all) # [] # >>> list(SingleIssueSpace(name='issue', everything=True, parent=parent).all) # [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] # # """ # if self.infinite: # raise ValueError( # 'Cannot return all possibilities of a continuous issues' # ) # # if self.everything: # yield from self.parent.all # # else: # yield from self.values # # def __contains__(self, item: SingleValue) -> bool: # """Tests if an outcome is within this issue space. # # # Examples: # # >>> prices = SingleIssueSpace(name='price', ranges = [(0.0, 10.0), (20.0, 30.0)], values=[2.0, 3.0, 44]) # >>> [_ in prices for _ in (0.0, 0.5, 1.0, 15.0, 20.0, 22.0, 40, 44.0)] # [False, True, True, False, False, True, False, True] # # """ # if self.everything: # return item in self.parent # # for r in self.ranges: # if r[0] < item < r[1]: # return True # # return item in self.values # # def _in_ranges(self, v: SingleValue): # """Checks if a value is within the ranges.""" # for r in self.ranges: # if r[0] < v < r[1]: # return True # # return False # # def _compress_ranges(self) -> None: # """Combines ranges and removes empty ones.""" # self.ranges = sorted( # [_ for _ in self.ranges if _[0] != _[1]], key=lambda x: x[0] # ) # if len(self.ranges) > 1: # ranges = _union_tuples(self.ranges[0], self.ranges[1]) # for i in range(2, len(self.ranges)): # if isinstance(ranges, tuple): # ranges = _union_tuples(ranges, self.ranges[i]) # else: # last_union = _union_tuples(ranges[-1], self.ranges[i]) # if isinstance(last_union, tuple): # last_union = [last_union] # ranges = ranges[:-1] + last_union # if isinstance(ranges, tuple): # ranges = [ranges] # self.ranges = ranges # # def simplify(self) -> None: # """Simplifies internal representation. # # Examples: # # >>> print(SingleIssueSpace(count=8, ranges= [(22.0, 34.0), (25, 41), (5.0, 7.0)] # ... , values= [12, 11, 10, 13, 50], name='i2')) # i2: [(5.0, 7.0), (22.0, 41)] and {0, 1, 2, 3, 4, 5, 7, 10, 11, 12, 13, 50} # >>> print(SingleIssueSpace(ranges=[(0.0, 1.0), (2.0, 3.0)], values={10.0, 11.0}, name='issue 1')) # issue 1: [(0.0, 1.0), (2.0, 3.0)] and {10.0, 11.0} # >>> print(SingleIssueSpace(ranges=[(0.0, 1.0), (0.5, 3.0)], values={10.0, 11.0}, name='issue 2')) # issue 2: (0.0, 3.0) and {10.0, 11.0} # >>> print(SingleIssueSpace(ranges=[(0.0, 1.0), (0.5, 3.0)], values={0.1, 0.9}, name='issue 3')) # issue 3: (0.0, 3.0) # >>> print(SingleIssueSpace(ranges=[(0.0, 1.0), (1.0, 2.0)], values={0.3, 1.0, 2.5}, name='issue 4')) # issue 4: (0.0, 2.0) and {2.5} # """ # if self.everything: # return # # self._compress_ranges() # self.values = set(_ for _ in self.values if not self._in_ranges(_)) # if len(self.ranges) > 1: # comp = [] # for i in range(len(self.ranges) - 1): # if self.ranges[i][1] == self.ranges[i + 1][0] and self.ranges[ # i # ][ # 1 # ] in self.values: # self.values.remove(self.ranges[i][1]) # comp.append(i) # for i in comp: # self.ranges = self.ranges[0:i] + [ # (self.ranges[i][0], self.ranges[i + 1][1]) # ] + self.ranges[ # i + 2: # ] # # @property # def ancestors(self) -> List['SingleIssueSpace']: # """Returns all the ancestors of this issue space # # Examples: # # >>> from negmas import SingleIssueSpace # >>> i1 = SingleIssueSpace(count=10, name='i1') # >>> i1.ancestors # [] # >>> i2 = SingleIssueSpace(count=10, name='i2') # >>> i2.ancestors # [] # >>> i_1 = SingleIssueSpace(count=10, name='i_1', parent=i1) # >>> [_.name for _ in i_1.ancestors] # ['i1'] # >>> i_12 = SingleIssueSpace(count=10, name='i_12', parent=i_1) # >>> [_.name for _ in i_12.ancestors] # ['i_1', 'i1'] # >>> i_123 = SingleIssueSpace(count=10, name='i_123', parent=i_12) # >>> [_.name for _ in i_123.ancestors] # ['i_12', 'i_1', 'i1'] # >>> i_2 = SingleIssueSpace(count=10, name='i_2', parent=i2) # >>> [_.name for _ in i_2.ancestors] # ['i2'] # # # """ # if self.parent is None: # return [] # # return [self.parent] + self.parent.ancestors # # def __add__(self, other: Union[SingleValue, 'SingleIssueSpace']): # """Finds the union of two outcome spaces. # # Examples: # # >>> from negmas import SingleIssueSpace # >>> i1 = SingleIssueSpace(count=10, ranges= [(20.0, 30.0), (40, 50.0)], values= [50], name='i1') # >>> i2 = SingleIssueSpace(count=8, ranges= [(22.0, 34.0), (25, 41), (5.0, 7.0)] # ... , values= [12, 11, 10, 13, 50], name='i2') # >>> print(i1 + i2) # (i1+i2): [(5.0, 7.0), (20.0, 50.0)] and {0, 1, 2, 3, 4, 5, 7, 8, 9, 10, 11, 12, 13, 50} # >>> print(i1 + 144) # (i1+144): [(20.0, 30.0), (40, 50.0)] and {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 144, 50} # # """ # if self.everything: # return self.parent + other # # if _is_single(other): # result = SingleIssueSpace( # ranges=self.ranges, # values=self.values, # count=None, # parent=self.parent, # name=f'({self.name}+{other})', # ) # result.values.add(other) # else: # result = SingleIssueSpace( # ranges=self.ranges, # values=self.values, # count=None, # parent=self.parent, # name=f'({self.name}+{other.name})', # ) # result.values = self.values.union(other.values) # result.ranges += other.ranges # result.simplify() # return result # # def __mul__(self, other: Union[SingleValue, 'SingleIssueSpace']): # """Finds the intersection of two outcome spaces. # # Examples: # # >>> from negmas import SingleIssueSpace # >>> i1 = SingleIssueSpace(count=10, ranges= [(20.0, 30.0), (40, 50.0)], values= [50], name='i1') # >>> i2 = SingleIssueSpace(count=8, ranges= [(22.0, 34.0), (25, 41), (5.0, 7.0)] # ... , values= [12, 11, 10, 13, 50], name='i2') # >>> print(i1 * i2) # (i1*i2): [(22.0, 30.0), (40, 41)] and {0, 1, 2, 3, 4, 5, 7, 50} # >>> print(i1 * 144) # (144*i1): set() # >>> print(i1 * 21.2) # (21.2*i1): {21.2} # # """ # if self.everything: # return self.parent * other # # if _is_single(other): # if other in self: # return SingleIssueSpace( # ranges=None, # values=[other], # count=None, # parent=self.parent, # name=f'({other}*{self.name})', # ) # # else: # return SingleIssueSpace( # ranges=None, # values=None, # count=None, # parent=self.parent, # name=f'({other}*{self.name})', # ) # # result = SingleIssueSpace( # ranges=None, # values=None, # count=None, # parent=self.parent, # name=f'({self.name}*{other.name})', # ) # result.values = self.values.intersection(other.values) # for r1 in self.ranges: # for r2 in other.ranges: # intersection = _intersect_tuples(r1, r2) # result.ranges.append(intersection) # result.simplify() # return result # # def __sub__(self, other: Union[SingleValue, 'SingleIssueSpace']): # """An outcome space containing this outcome space minus the intersection with other. # # # Examples: # # >>> from negmas import SingleIssueSpace # >>> i1 = SingleIssueSpace(count=10, ranges= [(20.0, 30.0), (40, 50.0)], values= [50], name='i1') # >>> i2 = SingleIssueSpace(count=8, ranges= [(22.0, 34.0), (25, 41), (5.0, 7.0)] # ... , values= [12, 11, 10, 13, 50], name='i2') # >>> print(i1 - i2) # (i1-i2): [(20.0, 22.0), (41, 50.0)] and {8, 9, 6} # >>> print(i1 - 144) # (i1-144): [(20.0, 30.0), (40, 50.0)] and {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 50} # >>> print(i1 - 21.2) # (i1-21.2): [(20.0, 21.2), (21.2, 30.0), (40, 50.0)] and {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 50} # # # # """ # if self.everything: # return self.parent - other # # if _is_single(other): # ranges = [] # for r in self.ranges: # if r[0] < other < r[1]: # ranges.append((r[0], other)) # ranges.append((other, r[1])) # else: # ranges.append(r) # values = self.values.copy() # if other in values: # values.remove(other) # return SingleIssueSpace( # ranges=ranges, # values=values, # count=None, # parent=self.parent, # name=f'({self.name}-{other})', # ) # # result = SingleIssueSpace( # ranges=None, # values=None, # count=None, # parent=self.parent, # name=f'({self.name}-{other.name})', # ) # result.values = self.values.difference(other.values) # other *= self # for r1 in self.ranges: # survived = r1 # for r2 in other.ranges: # if isinstance(survived, tuple): # survived = _subtract_tuples(survived, r2) # else: # survived = [_subtract_tuples(_, r2) for _ in survived] # if isinstance(survived, tuple): # survived = [survived] # result.ranges += survived # result.simplify() # return result # # @property # def empty(self): # """Checks if this is an empty SingleIssueSpace. # # Examples: # # >>> from negmas import SingleIssueSpace # >>> SingleIssueSpace().empty # True # >>> SingleIssueSpace(everything=True).empty # True # >>> i1 = SingleIssueSpace(count=10) # >>> i1.empty # False # >>> SingleIssueSpace(everything=True, parent=i1).empty # False # # """ # if self.everything: # if self.parent is None: # return True # # return self.parent.empty # # return len(self.ranges) == 0 and len(self.values) == 0 # # def __neg__(self) -> 'SingleIssueSpace': # """The inverse of this outcome space. Assumes that a parent outcome space is defined. # # Examples: # >>> from negmas import SingleIssueSpace # >>> i1 = SingleIssueSpace(count=10, ranges= [(20.0, 30.0), (40, 50.0)], values= [50], name='i1') # >>> i2 = SingleIssueSpace(count=8, ranges= [(22.0, 34.0), (25, 41), (5.0, 7.0)] # ... , values= [12, 11, 10, 13, 50], name='i2') # >>> try: # ... print(-i2) # ... except RuntimeError: # ... print('cannot inverse without a parent') # cannot inverse without a parent # >>> i2 = SingleIssueSpace(count=8, ranges= [(22.0, 34.0), (25, 41), (5.0, 7.0)] # ... , values= [12, 11, 10, 13, 50], parent=i1, name='i2') # >>> print(-i2) # -i2: [(20.0, 22.0), (41, 50.0)] and {8, 9, 6} # # # """ # if self.everything: # return self.parent if self.parent is not None else SingleIssueSpace( # ranges=None, # values=None, # count=None, # parent=None, # name=f'-{self.name}', # ) # # if self.empty: # return self.parent if self.parent is not None else SingleIssueSpace( # ranges=None, # values=None, # count=None, # parent=None, # everything=True, # name=f'-{self.name}', # ) # # if self.parent is None: # raise RuntimeError( # 'Cannot find the inverse of an issue space that has no parent' # ) # # result = self.parent - self # result.rename(f'-{self.name}') # return result # # def rand(self) -> Optional[SingleValue]: # """Picks a random valid value. # # Examples: # # >>> from negmas import SingleIssueSpace # >>> i1 = SingleIssueSpace(count=10, ranges= [(20.0, 30.0), (40, 50.0)], values= [50], name='i1') # >>> samples = [i1.rand() for _ in range(10)] # >>> [_ in i1 for _ in samples] # [True, True, True, True, True, True, True, True, True, True] # # """ # if self.everything: # if self.parent is None: # return None # # return self.parent.rand() # # if self.empty: # return None # # if len(self.ranges) == 0: # return random.sample(self.values) # # sizes = [_[1] - _[0] for _ in self.ranges] # total_size = sum(sizes) # v = random.random() * total_size # total = 0.0 # for s, r in zip(sizes, self.ranges): # total += s # if v > total: # return r[0] + v - total # # return self.ranges[-1][1] - EPSILON # # rand_valid = rand # # def rand_invalid(self) -> Optional[SingleValue]: # """Pick a random *invalid* value # # Examples: # # >>> from negmas import SingleIssueSpace # >>> i1 = SingleIssueSpace(count=10, ranges= [(20.0, 30.0), (40, 50.0)], values= [50], name='i1') # >>> samples = [i1.rand_invalid() for _ in range(10)] # >>> [_ in i1 for _ in samples] # [False, False, False, False, False, False, False, False, False, False] # # # """ # if self.everything: # if self.parent is None: # return None # # return self.parent.rand_invalid() # # if self.empty: # return 'anything' # # if len(self.ranges) == 0: # if isinstance(random.sample(self.values), str): # return unique_name('', add_time=False) # # mx = max(self.values) # return random.randint(mx + 1, 2 * mx) # # mx = self.ranges[0][1] # mn = self.ranges[0][0] # for r in self.ranges: # mx = max([mx, r[1]]) # mn = min([mn, r[1]]) # return random.random() * (mx - mn) + mx # # def __str__(self): # """Returns a string representation. # # Examples: # # >>> i1 = SingleIssueSpace(ranges=(0.0, 1.0), values=[2.0, 3.0, 4.0], name='issue 1') # >>> print(i1) # issue 1: (0.0, 1.0) and {2.0, 3.0, 4.0} # >>> print(SingleIssueSpace(ranges=(0.0, 1.0), name='issue 2')) # issue 2: (0.0, 1.0) # >>> print(SingleIssueSpace(ranges=(0.0, 1.0), name='issue 3', parent=i1)) # issue 3 (parent: issue 1): (0.0, 1.0) # >>> print(SingleIssueSpace(parent=i1, name='issue 4')) # issue 4 (parent: issue 1): set() # >>> print(SingleIssueSpace(parent=i1, everything=True, name='issue 4')) # issue 4 (parent: issue 1): everything # >>> print(SingleIssueSpace(values={0.0, 1.0}, name='issue 5')) # issue 5: {0.0, 1.0} # >>> print(SingleIssueSpace(ranges=[(0.0, 1.0), (2.0, 3.0)], values={10.0, 11.0}, name='issue 6')) # issue 6: [(0.0, 1.0), (2.0, 3.0)] and {10.0, 11.0} # >>> print(SingleIssueSpace(ranges=[(0.0, 1.0), (0.5, 3.0)], values={10.0, 11.0}, name='issue 6')) # issue 6: (0.0, 3.0) and {10.0, 11.0} # >>> print(SingleIssueSpace(ranges=[(0.0, 1.0), (0.5, 3.0)], values={0.1, 0.9}, name='issue 6')) # issue 6: (0.0, 3.0) # # """ # if self.everything: # base = f'everything' # elif len(self.ranges) == 0: # base = f'{self.values}' # elif len(self.values) == 0: # if len(self.ranges) == 1: # base = f'{self.ranges[0]}' # else: # base = f'{self.ranges}' # else: # if len(self.ranges) == 1: # base = f'{self.ranges[0]} and {self.values}' # else: # base = f'{self.ranges} and {self.values}' # if self.parent is not None: # parent = f' (parent: {self.parent.name})' # else: # parent = '' # return f'{self.name}{parent}: {base}' # # def __and__(self, other): # return self * other # # def __or__(self, other): # return self + other # # def __xor__(self, other): # return self + other - (self * other) # # def __invert__(self): # return -self # # def __mod__(self, other): # return self - other # # cardinality = n_outcomes # dimensionality = 1 # n_dims = 1 # contains = __contains__ # union = __add__ # instersection = __mul__ # difference = __sub__ # class OutcomeSpace(object): # """An arbitrary constraint on outcomes. # # Overrides standard operators so it can be used something like the following: # # # # """ # __slots__ = ('_parent', '_range') # def __init__(self, parent: Optional['OutcomeSpace']=None, **kwargs) -> None: # super().__init__() # self._parent = parent # self._range = copy.deepcopy(kwargs) # # @property # def n_augmented_outcomes(self) -> Union[int, float]: # """Returns the total number of outcomes in a set of issues. `-1` indicates infinity""" # # n = 1 # for dim in self._range.values(): # n *= _dim_cardinality(dim) # if math.isinf(n): # return math.inf # return n # # cardinality = n_augmented_outcomes # # @property # def n_dims(self): # return len(self._range) # # dimensionality = n_dims # # @property # def cardinalities(self) -> Dict[str, Union[int, float]]: # """The cardinality of all dimensions""" # return {k: _dim_cardinality(cutoff_utility) for k, cutoff_utility in self._range} # # @property # def types(self) -> Dict[str, str]: # """The type of the issue. # # Returns: # str: either 'continuous' or 'discrete' # # """ # return {k: 'continuous' if math.isinf(_dim_cardinality(cutoff_utility)) else 'discrete' for k, cutoff_utility in self._range} # # def is_infinite(self) -> bool: # """Test whether any issue is continuous (infinite outcome space) # # Returns: # bool: continuous or not # # """ # return any(math.isinf(_) for _ in self.cardinalities) # # def is_finite(self) -> bool: # """Test whether all issues are discrete (finite outcome space) # # Returns: # bool: discrete or not # # """ # return not self.is_infinite() # # @property # def all(self) -> Generator: # """A generator that generates all possible values. # # Remarks: # - This function returns a generator for the case when the number of values is very large. # - If you need a list then use something like: # # # """ # if self.is_infinite(): # raise ValueError('Cannot return all possibilities of a continuous issues') # if len(self._range) == 0: # raise StopIteration # yield from itertools.product(_all_values for _ in self._range) # # def __contains__(self, item: Union[Outcome, OutcomeRange, 'OutcomeSpace']): # """Tests if an outcome, outcome range, or another outcome space is within this outcome space.""" # return outcome_in_range(item, self._range) # # def __add__(self, other: Union[Outcome, OutcomeRange, 'OutcomeSpace']): # """Finds the union of two outcome spaces.""" # r = OutcomeSpace(parent=self._parent) # r._range = range_union(self._range, other._range) # return r # # def __mul__(self, other: Union[Outcome, OutcomeRange, 'OutcomeSpace']): # """Finds the intersection of two outcome spaces.""" # r = OutcomeSpace(parent=self._parent) # r._range = range_intersection(self._range, other._range) # return r # # def __sub__(self, other: Union[Outcome, OutcomeRange, 'OutcomeSpace']): # """An outcome space containing this outcome space minus the intersection with other.""" # # def __neg__(self): # """The inverse of this outcome space. Assumes that a parent outcome space is defined.""" # # def rand(self) -> Dict[str, Union[int, float, str]]: # """Picks a random valid value.""" # # rand_valid = rand # # def rand_invalid(self) -> Dict[str, Union[int, float, str]]: # """Pick a random *invalid* value""" def outcome_as_dict(outcome: Outcome, issue_names: List[str] = None): """Converts the outcome to a dict no matter what was its type""" if outcome is None: return None if isinstance(outcome, dict): return outcome if isinstance(outcome, OutcomeType): return outcome.asdict() if issue_names is not None: return dict(zip(issue_names, outcome)) return dict(zip((str(_) for _ in range(len(outcome))), outcome)) def outcome_as_tuple(outcome: Outcome): """Converts the outcome to a tuple no matter what was its type""" if outcome is None: return None if isinstance(outcome, tuple): return outcome if isinstance(outcome, OutcomeType): return outcome.astuple() if isinstance(outcome, dict): return list(outcome.values()) raise ValueError(f"Unknown type for outcome {type(outcome)}") PK!Kxd negmas/sao.py""" Implements Stacked Alternating Offers (SAO) mechanism and basic negotiators. """ import random import time from abc import abstractmethod from dataclasses import dataclass from typing import Dict, Any, Callable, Type from typing import Sequence, Optional, List, Tuple, Iterable, Union import numpy as np from negmas.common import * from negmas.common import _ShadowAgentMechanismInterface from negmas.events import Notification from negmas.java import ( JavaCallerMixin, to_java, from_java, java_link, to_dict, JNegmasGateway, python_identifier, ) from negmas.mechanisms import MechanismRoundResult, Mechanism from negmas.negotiators import Negotiator, AspirationMixin, Controller from negmas.outcomes import ( sample_outcomes, Outcome, outcome_is_valid, ResponseType, outcome_as_dict, ) from negmas.utilities import ( MappingUtilityFunction, normalize, UtilityFunction, UtilityValue, JavaUtilityFunction, ) __all__ = [ "SAOState", "SAOMechanism", "SAOProtocol", "SAONegotiator", "RandomNegotiator", "LimitedOutcomesNegotiator", "LimitedOutcomesAcceptor", "AspirationNegotiator", "ToughNegotiator", "OnlyBestNegotiator", "SimpleTitForTatNegotiator", "NiceNegotiator", "SAOController", "JavaSAONegotiator", ] @dataclass class SAOResponse: """A response to an offer given by an agent in the alternating offers protocol""" response: ResponseType = ResponseType.NO_RESPONSE outcome: Optional["Outcome"] = None @dataclass class SAOState(MechanismState): current_offer: Optional["Outcome"] = None current_proposer: Optional[str] = None n_acceptances: int = 0 @dataclass class SAOAMI(AgentMechanismInterface): end_on_no_response: bool = True publish_proposer: bool = True publish_n_acceptances: bool = False class SAOMechanism(Mechanism): def __init__( self, issues=None, outcomes=None, n_steps=None, time_limit=None, step_time_limit=None, max_n_agents=None, dynamic_entry=True, keep_issue_names=True, cache_outcomes=True, max_n_outcomes: int = 1000000, annotation: Optional[Dict[str, Any]] = None, end_on_no_response=True, publish_proposer=True, publish_n_acceptances=False, enable_callbacks=False, name: Optional[str] = None, ): super().__init__( issues=issues, outcomes=outcomes, n_steps=n_steps, time_limit=time_limit, step_time_limit=step_time_limit, max_n_agents=max_n_agents, dynamic_entry=dynamic_entry, keep_issue_names=keep_issue_names, cache_outcomes=cache_outcomes, max_n_outcomes=max_n_outcomes, annotation=annotation, state_factory=SAOState, enable_callbacks=enable_callbacks, name=name, ) self._current_offer = None self._current_proposer = None self._n_accepting = 0 self._first_proposer = 0 self._avoid_ultimatum = n_steps is not None self.end_negotiation_on_refusal_to_propose = end_on_no_response self.publish_proposer = publish_proposer self.publish_n_acceptances = publish_n_acceptances def join( self, ami: AgentMechanismInterface, state: MechanismState, *, ufun: Optional["UtilityFunction"] = None, role: str = "agent", ) -> bool: if not super().join(ami, state, ufun=ufun, role=role): return False if not self.ami.dynamic_entry and not any( [a.capabilities.get("propose", False) for a in self.negotiators] ): self._current_proposer = None self._current_offer = None self._n_accepting = 0 return False return True def extra_state(self): return SAOState( current_offer=self._current_offer, current_proposer=self._current_proposer.id if self._current_proposer and self.publish_proposer else None, n_acceptances=self._n_accepting if self.publish_n_acceptances else 0, ) def round(self) -> MechanismRoundResult: """implements a round of the Stacked Alternating Offers Protocol. """ negotiators: List[SAONegotiator] = self.negotiators n_negotiators = len(negotiators) # if this is the first step which means that there is no _current_offer if self.ami.state.step == 0: assert self._current_offer is None assert self._current_proposer is None # choose a random negotiator and set it as the current negotiator self._first_proposer = random.randint(0, n_negotiators - 1) if self._avoid_ultimatum: # if we are trying to avoid an ultimatum, we take an offer from everyone and ignore them but one. # this way, the agent cannot know its order. For example, if we have two agents and 3 steps, this will # be the situation after each step: # # Case 1: Assume that it ignored the offer from agent 1 # Step, Agent 0 calls received , Agent 1 calls received , relative time during last call # 0 , counter(None)->offer1* , counter(None) -> offer0 , 0/3 # 1 , counter(offer2)->offer3 , counter(offer1) -> offer2 , 1/3 # 2 , counter(offer4)->offer5 , counter(offer3) -> offer4 , 2/3 # 3 , , counter(offer5)->offer6 , 3/3 # # Case 2: Assume that it ignored the offer from agent 0 # Step, Agent 0 calls received , Agent 1 calls received , relative time during last call # 0 , counter(None)->offer1 , counter(None) -> offer0* , 0/3 # 1 , counter(offer0)->offer2 , counter(offer2) -> offer3 , 1/3 # 2 , counter(offer3)->offer4 , counter(offer4) -> offer5 , 2/3 # 3 , counter(offer5)->offer6 , , 3/3 # # in both cases, the agent cannot know whether its last offer going to be passed to the other agent # (the ultimatum scenario) or not. responses = [] for neg in negotiators: if not neg.capabilities.get("propose", False): continue strt = time.perf_counter() resp = neg.counter(state=self.state, offer=None) if ( self.ami.step_time_limit is not None and time.perf_counter() - strt > self.ami.step_time_limit ): return MechanismRoundResult( broken=False, timedout=True, agreement=None ) if self._enable_callbacks: for other in self.negotiators: if other is not neg: other.on_partner_response( state=self.state, agent_id=neg.id, outcome=None, response=resp, ) if ( resp.response == ResponseType.END_NEGOTIATION or resp.response == ResponseType.NO_RESPONSE or ( resp.outcome is None and neg.capabilities.get("propose", False) ) ): return MechanismRoundResult( broken=True, timedout=False, agreement=None ) responses.append(resp) if len(responses) < 1: if not self.dynamic_entry: return MechanismRoundResult( broken=True, timedout=False, agreement=None, error=True, error_details="No proposers and no dynamic entry", ) else: return MechanismRoundResult( broken=False, timedout=False, agreement=None ) resp = ( responses[self._first_proposer] if len(responses) > self._first_proposer else responses[0] ) neg = ( negotiators[self._first_proposer] if len(negotiators) > self._first_proposer else negotiators[0] ) else: # when there is no risk of ultimatum (n_steps is not known), we just take one first offer. neg = negotiators[self._first_proposer] strt = time.perf_counter() resp = neg.counter(state=self.state, offer=None) if ( self.ami.step_time_limit is not None and time.perf_counter() - strt > self.ami.step_time_limit ): return MechanismRoundResult( broken=False, timedout=True, agreement=None ) if self._enable_callbacks: for other in self.negotiators: if other is not neg: other.on_partner_response( state=self.state, agent_id=neg.id, outcome=None, response=resp, ) if ( resp.response == ResponseType.END_NEGOTIATION or resp.response == ResponseType.NO_RESPONSE or resp.outcome is None ): return MechanismRoundResult( broken=True, timedout=False, agreement=None ) self._n_accepting = 1 self._current_offer = resp.outcome self._current_proposer = neg return MechanismRoundResult(broken=False, timedout=False, agreement=None) # this is not the first round. A round will get n_negotiators steps ordered_negotiators = [ negotiators[(_ + self._first_proposer + 1) % n_negotiators] for _ in range(n_negotiators) ] for neg in ordered_negotiators: strt = time.perf_counter() resp = neg.counter(state=self.state, offer=self._current_offer) if ( self.ami.step_time_limit is not None and time.perf_counter() - strt > self.ami.step_time_limit ): return MechanismRoundResult(broken=False, timedout=True, agreement=None) if self._enable_callbacks: for other in self.negotiators: if other is not neg: other.on_partner_response( state=self.state, agent_id=neg.id, outcome=self._current_offer, response=resp, ) if resp.response == ResponseType.NO_RESPONSE: continue if resp.response == ResponseType.END_NEGOTIATION: return MechanismRoundResult(broken=True, timedout=False, agreement=None) if resp.response == ResponseType.ACCEPT_OFFER: self._n_accepting += 1 if self._n_accepting == n_negotiators: return MechanismRoundResult( broken=False, timedout=False, agreement=self._current_offer ) if resp.response == ResponseType.REJECT_OFFER: proposal = resp.outcome if proposal is None: if self.end_negotiation_on_refusal_to_propose: return MechanismRoundResult( broken=True, timedout=False, agreement=None ) elif self._enable_callbacks: for other in self.negotiators: if other is not neg: other.on_partner_refused_to_propose( agent_id=neg, state=self.state ) continue else: self._current_offer = proposal self._current_proposer = neg self._n_accepting = 1 if self._enable_callbacks: for other in self.negotiators: if other is neg: continue other.on_partner_proposal( agent_id=neg.id, offer=proposal, state=self.state ) return MechanismRoundResult( broken=False, timedout=False, agreement=None ) # we can arrive here only if all agents either refused to response or to offer. if not self.ami.dynamic_entry: raise RuntimeError( "No negotiators can propose. I cannot run a meaningful negotiation" ) return MechanismRoundResult( broken=False, timedout=False, agreement=None, error=True, error_details="No negotiators can propose in a static_entry" " negotiation!!", ) class RandomResponseMixin(object): def init_ranodm_response( self, p_acceptance: float = 0.15, p_rejection: float = 0.25, p_ending: float = 0.1, ) -> None: """Constructor Args: p_acceptance (float): probability of accepting offers p_rejection (float): probability of rejecting offers p_ending (float): probability of ending negotiation Returns: None Remarks: - If the summation of acceptance, rejection and ending probabilities is less than 1.0 then with the remaining probability a NO_RESPONSE is returned from respond() """ if not hasattr(self, "add_capabilities"): raise ValueError( f"self.__class__.__name__ is just a mixin for class Negotiator. You must inherit from Negotiator or" f" one of its descendents before inheriting from self.__class__.__name__" ) self.add_capabilities({"respond": True}) self.p_acceptance = p_acceptance self.p_rejection = p_rejection self.p_ending = p_ending self.wheel: List[Tuple[float, ResponseType]] = [(0.0, ResponseType.NO_RESPONSE)] if self.p_acceptance > 0.0: self.wheel = [ (self.wheel[-1][0] + self.p_acceptance, ResponseType.ACCEPT_OFFER) ] if self.p_rejection > 0.0: self.wheel.append( (self.wheel[-1][0] + self.p_rejection, ResponseType.REJECT_OFFER) ) if self.p_ending > 0.0: self.wheel.append( (self.wheel[-1][0] + self.p_ending, ResponseType.REJECT_OFFER) ) if self.wheel[-1][0] > 1.0: raise ValueError("Probabilities of acceptance+rejection+ending>1") self.wheel = self.wheel[1:] # noinspection PyUnusedLocal,PyUnusedLocal def respond(self, state: MechanismState, offer: "Outcome") -> "ResponseType": r = random.random() for w in self.wheel: if w[0] >= r: return w[1] return ResponseType.NO_RESPONSE # noinspection PyAttributeOutsideInit class RandomProposalMixin(object): """The simplest possible agent. It just generates random offers and respond randomly to offers. """ def init_random_proposal(self: Negotiator): self.add_capabilities( { "propose": True, "propose-with-value": False, "max-proposals": None, # indicates infinity } ) def propose(self, state: MechanismState) -> Optional["Outcome"]: if ( hasattr(self, "_offerable_outcomes") and self._offerable_outcomes is not None ): return random.sample(self._offerable_outcomes, 1)[0] return self._ami.random_outcomes(1, astype=dict)[0] class LimitedOutcomesAcceptorMixin(object): """An agent the accepts a limited set of outcomes. The agent accepts any of the given outcomes with the given probabilities. """ 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=0.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 respond(self, state: MechanismState, offer: "Outcome") -> "ResponseType": """Respond to an offer. Args: offer (Outcome): offer being tested Returns: ResponseType: The response to the offer """ ami = self._ami r = random.random() if r < self.p_no_response: return ResponseType.NO_RESPONSE if r < self.p_ending: return ResponseType.END_NEGOTIATION if self.acceptable_outcomes is None: if ( outcome_is_valid(offer, ami.issues) and random.random() < self.acceptance_probabilities ): return ResponseType.ACCEPT_OFFER else: return ResponseType.REJECT_OFFER try: indx = self.acceptable_outcomes.index(offer) except ValueError: return ResponseType.REJECT_OFFER prob = self.acceptance_probabilities[indx] if indx < 0 or not outcome_is_valid(offer, ami.issues): return ResponseType.REJECT_OFFER if random.random() < prob: return ResponseType.ACCEPT_OFFER return ResponseType.REJECT_OFFER class LimitedOutcomesProposerMixin(object): """An agent the accepts a limited set of outcomes. The agent proposes randomly from the given set of outcomes. Args: proposable_outcomes (Optional[Outcomes]): the set of prooposable outcomes. If None then it is assumed to be all the outcomes of the negotiation """ def init_limited_outcomes_proposer( self: Negotiator, proposable_outcomes: Optional[List["Outcome"]] = None ) -> None: self.add_capabilities( { "propose": True, "propose-with-value": False, "max-proposals": None, # indicates infinity } ) self._offerable_outcomes = proposable_outcomes if proposable_outcomes is not None: self._offerable_outcomes = list(proposable_outcomes) def propose(self, state: MechanismState) -> Optional["Outcome"]: if self._offerable_outcomes is None: return self._ami.random_outcomes(1)[0] else: return random.sample(self._offerable_outcomes, 1)[0] class LimitedOutcomesMixin(LimitedOutcomesAcceptorMixin, LimitedOutcomesProposerMixin): """An agent the accepts a limited set of outcomes. The agent accepts any of the given outcomes with the given probabilities. """ def init_limited_outcomes( self, outcomes: Optional[Union[int, Iterable["Outcome"]]] = None, acceptable_outcomes: Optional[Iterable["Outcome"]] = None, acceptance_probabilities: Optional[Union[float, List[float]]] = None, proposable_outcomes: Optional[Iterable["Outcome"]] = None, p_ending=0.0, p_no_response=0.0, ) -> None: """Constructor Args: acceptable_outcomes (Optional[Outcomes]): the set of acceptable outcomes. If None then it is assumed to be all the outcomes of the negotiation. acceptance_probabilities (Sequence[Float]): probability of accepting each acceptable outcome. If None then it is assumed to be unity. proposable_outcomes (Optional[Outcomes]): the set of outcomes from which the agent is allowed to propose. If None, then it is the same as acceptable outcomes with nonzero probability p_no_response (float): probability of refusing to respond to offers p_ending (float): probability of ending negotiation Returns: None """ self.init_limited_outcomes_acceptor( outcomes=outcomes, acceptable_outcomes=acceptable_outcomes, acceptance_probabilities=acceptance_probabilities, p_ending=p_ending, p_no_response=p_no_response, ) if proposable_outcomes is None and self.acceptable_outcomes is not None: if not isinstance(self.acceptance_probabilities, float): proposable_outcomes = [ _ for _, p in zip( self.acceptable_outcomes, self.acceptance_probabilities ) if p > 1e-9 ] self.init_limited_outcomes_proposer(proposable_outcomes=proposable_outcomes) class SAONegotiator(Negotiator): def __init__( self, assume_normalized=True, ufun: Optional[UtilityFunction] = None, name: Optional[str] = None, rational_proposal=True, parent: Controller = None, ): super().__init__(name=name, ufun=ufun, parent=parent) self.assume_normalized = assume_normalized self.__end_negotiation = False self.my_last_proposal: Optional["Outcome"] = None self.my_last_proposal_utility: float = None self.rational_proposal = rational_proposal self.add_capabilities({"respond": True, "propose": True, "max-proposals": 1}) def on_notification(self, notification: Notification, notifier: str): if notification.type == "end_negotiation": self.__end_negotiation = True def propose_(self, state: MechanismState) -> Optional["Outcome"]: if not self._capabilities["propose"] or self.__end_negotiation: return None proposal = self.propose(state=state) # never return a proposal that is less than the reserved value if self.rational_proposal and self.reserved_value is not None: utility = None if proposal is not None and self.utility_function is not None: utility = self.utility_function(proposal) if utility is not None and utility < self.reserved_value: return None if utility is not None: self.my_last_proposal = proposal self.my_last_proposal_utility = utility return proposal def respond_(self, state: MechanismState, offer: "Outcome") -> "ResponseType": """Respond to an offer. Args: state: `MechanismState` giving current state of the negotiation. offer (Outcome): offer being tested Returns: ResponseType: The response to the offer Remarks: - The default implementation never ends the negotiation except if an earler end_negotiation notification is sent to the negotiator - The default implementation asks the negotiator to `propose`() and accepts the `offer` if its utility was at least as good as the offer that it would have proposed (and above the reserved value). """ if self.__end_negotiation: return ResponseType.END_NEGOTIATION return self.respond(state=state, offer=offer) def counter( self, state: MechanismState, offer: Optional["Outcome"] ) -> "SAOResponse": """ Called to counter an offer Args: state: `MechanismState` giving current state of the negotiation. offer: The offer to be countered. None means no offer and the agent is requested to propose an offer Returns: Tuple[ResponseType, Outcome]: The response to the given offer with a counter offer if the response is REJECT """ if self.__end_negotiation: return SAOResponse(ResponseType.END_NEGOTIATION, None) if offer is None: return SAOResponse(ResponseType.REJECT_OFFER, self.propose_(state=state)) response = self.respond_(state=state, offer=offer) if response != ResponseType.REJECT_OFFER: return SAOResponse(response, None) return SAOResponse(response, self.propose_(state=state)) def respond(self, state: MechanismState, offer: "Outcome") -> "ResponseType": """Respond to an offer. Args: state: `MechanismState` giving current state of the negotiation. offer (Outcome): offer being tested Returns: ResponseType: The response to the offer Remarks: - The default implementation never ends the negotiation - The default implementation asks the negotiator to `propose`() and accepts the `offer` if its utility was at least as good as the offer that it would have proposed (and above the reserved value). """ if self.utility_function is None: return ResponseType.REJECT_OFFER if self.utility_function(offer) < self.reserved_value: return ResponseType.REJECT_OFFER utility = None if self.my_last_proposal_utility is not None: utility = self.my_last_proposal_utility if utility is None: myoffer = self.propose_(state=state) if myoffer is None: return ResponseType.NO_RESPONSE utility = self.utility_function(myoffer) if utility is not None and self.utility_function(offer) >= utility: return ResponseType.ACCEPT_OFFER return ResponseType.REJECT_OFFER # CALLBACK def on_partner_proposal( self, state: MechanismState, agent_id: str, offer: "Outcome" ) -> None: """ A callback called by the mechanism when a partner proposes something Args: state: `MechanismState` giving the state of the negotiation when the offer was porposed. agent_id: The ID of the agent who proposed offer: The proposal. Returns: None """ def on_partner_refused_to_propose( self, state: MechanismState, agent_id: str ) -> None: """ A callback called by the mechanism when a partner refuses to propose Args: state: `MechanismState` giving the state of the negotiation when the partner refused to offer. agent_id: The ID of the agent who refused to propose Returns: None """ def on_partner_response( self, state: MechanismState, agent_id: str, outcome: "Outcome", response: "SAOResponse", ) -> None: """ A callback called by the mechanism when a partner responds to some offer Args: state: `MechanismState` giving the state of the negotiation when the partner responded. agent_id: The ID of the agent who responded outcome: The proposal being responded to. response: The response Returns: None """ @abstractmethod def propose(self, state: MechanismState) -> Optional["Outcome"]: """Propose a set of offers Args: state: `MechanismState` giving current state of the negotiation. Returns: The outcome being proposed or None to refuse to propose Remarks: - This function guarantees that no agents can propose something with a utility value """ class Java: implements = ["jnegmas.sao.SAONegotiator"] class RandomNegotiator(Negotiator, RandomResponseMixin, RandomProposalMixin): """A negotiation agent that responds randomly in a single negotiation.""" 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, ) # noinspection PyCallByClass class LimitedOutcomesNegotiator(LimitedOutcomesMixin, SAONegotiator): """A negotiation agent that uses a fixed set of outcomes in a single negotiation.""" def __init__( self, name: str = None, parent: Controller = None, outcomes: Optional[Union[int, Iterable["Outcome"]]] = None, acceptable_outcomes: Optional[List["Outcome"]] = None, acceptance_probabilities: Optional[Union[float, List[float]]] = None, p_ending=0.0, p_no_response=0.0, ) -> None: super().__init__(name=name, parent=parent) self.init_limited_outcomes( p_ending=p_ending, p_no_response=p_no_response, acceptable_outcomes=acceptable_outcomes, acceptance_probabilities=acceptance_probabilities, outcomes=outcomes, ) # noinspection PyCallByClass class LimitedOutcomesAcceptor(SAONegotiator, LimitedOutcomesAcceptorMixin): """A negotiation agent that uses a fixed set of outcomes in a single negotiation.""" def respond(self, state: MechanismState, offer: "Outcome") -> "ResponseType": return LimitedOutcomesAcceptorMixin.respond(self, state=state, offer=offer) def __init__( self, name: str = None, parent: Controller = None, outcomes: Optional[Union[int, Iterable["Outcome"]]] = None, acceptable_outcomes: Optional[List["Outcome"]] = None, acceptance_probabilities: Optional[List[float]] = None, p_ending=0.0, p_no_response=0.0, ) -> None: SAONegotiator.__init__(self, name=name, parent=parent) self.init_limited_outcomes_acceptor( p_ending=p_ending, p_no_response=p_no_response, acceptable_outcomes=acceptable_outcomes, acceptance_probabilities=acceptance_probabilities, outcomes=outcomes, ) self.add_capabilities({"propose": False}) def propose(self, state: MechanismState) -> Optional["Outcome"]: return None class AspirationNegotiator(SAONegotiator, AspirationMixin): def __init__( self, name=None, ufun=None, parent: Controller = None, max_aspiration=0.95, aspiration_type="boulware", dynamic_ufun=True, randomize_offer=False, can_propose=True, assume_normalized=False, ): super().__init__( name=name, assume_normalized=assume_normalized, parent=parent, ufun=ufun ) self.aspiration_init( max_aspiration=max_aspiration, aspiration_type=aspiration_type ) self.ordered_outcomes = [] self.dynamic_ufun = dynamic_ufun self.randomize_offer = randomize_offer self._max_aspiration = self.max_aspiration self.ufun_max = None self.ufun_min = None self.__ufun_modified = False self.add_capabilities( { "respond": True, "propose": can_propose, "propose-with-value": False, "max-proposals": None, # indicates infinity } ) @property def eu(self) -> Callable[["Outcome"], Optional["UtilityValue"]]: """ The utility function in the given negotiation taking opponent model into account. Remarks: - If no utility_function is internally stored, `eu` still returns a valid callable that returns None for everything. """ if hasattr(self, "opponent_model"): return lambda x: self.utility_function( x ) * self.opponent_model.probability_of_acceptance(x) else: return self.utility_function def _update_ordered_outcomes(self): outcomes = self._ami.discrete_outcomes() self.ordered_outcomes = sorted( [(self.utility_function(outcome), outcome) for outcome in outcomes], key=lambda x: x[0], reverse=True, ) if not self.assume_normalized: self.ufun_max = self.ordered_outcomes[0][0] self.ufun_min = self.ordered_outcomes[-1][0] if self.reserved_value is not None and self.ufun_min < self.reserved_value: self.ufun_min = self.reserved_value def on_notification(self, notification: Notification, notifier: str): super().on_notification(notification, notifier) if notification.type == "ufun_modified": if self.dynamic_ufun: self.__ufun_modified = True self._update_ordered_outcomes() def join( self, ami: AgentMechanismInterface, state: MechanismState, *, ufun: Optional["UtilityFunction"] = None, role: str = "agent", ) -> bool: if not super().join(ami, state, ufun=ufun, role=role): return False self.__ufun_modified = False self._update_ordered_outcomes() return True def respond(self, state: MechanismState, offer: "Outcome") -> "ResponseType": if self.utility_function is None: return ResponseType.REJECT_OFFER u = self.utility_function(offer) if u is None: return ResponseType.REJECT_OFFER asp = ( self.aspiration(state.relative_time) * (self.ufun_max - self.ufun_min) + self.ufun_min ) if u >= asp and u >= self.reserved_value: return ResponseType.ACCEPT_OFFER if asp < self.reserved_value: return ResponseType.END_NEGOTIATION return ResponseType.REJECT_OFFER def propose(self, state: MechanismState) -> Optional["Outcome"]: asp = ( self.aspiration(state.relative_time) * (self.ufun_max - self.ufun_min) + self.ufun_min ) if asp < self.reserved_value: return None for i, (u, o) in enumerate(self.ordered_outcomes): if u is None: continue if u < asp: if u < self.reserved_value: return None if i == 0: return self.ordered_outcomes[i][1] if self.randomize_offer: return random.sample(self.ordered_outcomes[:i], 1)[0][1] return self.ordered_outcomes[i - 1][1] if self.randomize_offer: return random.sample(self.ordered_outcomes, 1)[0][1] return self.ordered_outcomes[-1][1] class NiceNegotiator(SAONegotiator, RandomProposalMixin): def __init__(self, *args, **kwargs): SAONegotiator.__init__(self, *args, **kwargs) self.init_random_proposal() def respond(self, state: MechanismState, offer: "Outcome") -> "ResponseType": return ResponseType.ACCEPT_OFFER def propose(self, state: MechanismState) -> Optional["Outcome"]: return RandomProposalMixin.propose(self=self, state=state) class ToughNegotiator(SAONegotiator): def __init__( self, name=None, parent: Controller = None, dynamic_ufun=True, can_propose=True ): super().__init__(name=name, parent=parent) self.best_outcome = None self.dynamic_ufun = dynamic_ufun self._offerable_outcomes = None self.add_capabilities( { "respond": True, "propose": can_propose, "propose-with-value": False, "max-proposals": None, # indicates infinity } ) @property def eu(self) -> Callable[["Outcome"], Optional["UtilityValue"]]: """ The utility function in the given negotiation taking opponent model into account. Remarks: - If no utility_function is internally stored, `eu` still returns a valid callable that returns None for everything. """ if hasattr(self, "opponent_model"): return lambda x: self.utility_function( x ) * self.opponent_model.probability_of_acceptance(x) else: return self.utility_function def join( self, ami: AgentMechanismInterface, state: MechanismState, *, ufun: Optional["UtilityFunction"] = None, role: str = "agent", ) -> bool: if not super().join(ami, state, ufun=ufun, role=role): return False outcomes = ( self._ami.outcomes if self._offerable_outcomes is None else self._offerable_outcomes ) if self.utility_function is None: return True self.best_outcome = max( [(self.utility_function(outcome), outcome) for outcome in outcomes] )[1] return True def respond(self, state: MechanismState, offer: "Outcome") -> "ResponseType": if self.dynamic_ufun: outcomes = ( self._ami.outcomes if self._offerable_outcomes is None else self._offerable_outcomes ) if self.utility_function is None: return ResponseType.REJECT_OFFER self.best_outcome = max( [(self.utility_function(outcome), outcome) for outcome in outcomes] )[1] if offer == self.best_outcome: return ResponseType.ACCEPT_OFFER return ResponseType.REJECT_OFFER def propose(self, state: MechanismState) -> Optional["Outcome"]: if not self._capabilities["propose"]: return None if self.dynamic_ufun: outcomes = ( self._ami.outcomes if self._offerable_outcomes is None else self._offerable_outcomes ) self.best_outcome = max( [(self.eu(outcome), outcome) for outcome in outcomes] )[1] return self.best_outcome class OnlyBestNegotiator(SAONegotiator): def __init__( self, name=None, parent: Controller = None, dynamic_ufun=True, min_utility=0.95, top_fraction=0.05, best_first=False, probabilisic_offering=True, can_propose=True, ): super().__init__(name=name, parent=parent) self._offerable_outcomes = None self.best_outcome = [] self.dynamic_ufun = dynamic_ufun self.top_fraction = top_fraction self.min_utility = min_utility self.best_first = best_first self.probabilisit_offering = probabilisic_offering self.ordered_outcomes = [] self.acceptable_outcomes = [] self.wheel = np.array([]) self.offered = set([]) self.add_capabilities( { "respond": True, "propose": can_propose, "propose-with-value": False, "max-proposals": None, # indicates infinity } ) @property def eu(self) -> Callable[["Outcome"], Optional["UtilityValue"]]: """ The utility function in the given negotiation taking opponent model into account. Remarks: - If no utility_function is internally stored, `eu` still returns a valid callable that returns None for everything. """ if hasattr(self, "opponent_model"): return lambda x: self.utility_function( x ) * self.opponent_model.probability_of_acceptance(x) else: return self.utility_function def acceptable(self): outcomes = ( self._ami.outcomes if self._offerable_outcomes is None else self._offerable_outcomes ) eu_outcome = [(self.eu(outcome), outcome) for outcome in outcomes] self.ordered_outcomes = sorted(eu_outcome, key=lambda x: x[0], reverse=True) if self.min_utility is None: selected, selected_utils = [], [] else: util_limit = self.min_utility * self.ordered_outcomes[0][0] selected, selected_utils = [], [] for u, o in self.ordered_outcomes: if u >= util_limit: selected.append(o) selected_utils.append(u) else: break if self.top_fraction is not None: frac_limit = max( 1, int(round(self.top_fraction * len(self.ordered_outcomes))) ) else: frac_limit = len(outcomes) if frac_limit >= len(selected) > 0: sum = np.asarray(selected_utils).sum() if sum > 0.0: selected_utils /= sum selected_utils = np.cumsum(selected_utils) else: selected_utils = np.linspace(0.0, 1.0, len(selected_utils)) return selected, selected_utils if frac_limit > 0: n_sel = len(selected) fsel = [_[1] for _ in self.ordered_outcomes[n_sel:frac_limit]] futil = [_[0] for _ in self.ordered_outcomes[n_sel:frac_limit]] selected_utils = selected_utils + futil sum = np.asarray(selected_utils).sum() if sum > 0.0: selected_utils /= sum selected_utils = np.cumsum(selected_utils) else: selected_utils = np.linspace(0.0, 1.0, len(selected_utils)) return selected + fsel, selected_utils return [], [] def join( self, ami: AgentMechanismInterface, state: MechanismState, *, ufun: Optional["UtilityFunction"] = None, role: str = "agent", ) -> bool: if not super().join(ami, state, ufun=ufun, role=role): return False self.acceptable_outcomes, self.wheel = self.acceptable() return True def respond(self, state: MechanismState, offer: "Outcome") -> "ResponseType": if self.dynamic_ufun: self.acceptable_outcomes, self.wheel = self.acceptable() if offer in self.acceptable_outcomes: return ResponseType.ACCEPT_OFFER return ResponseType.REJECT_OFFER def propose(self, state: MechanismState) -> Optional["Outcome"]: if not self._capabilities["propose"]: return None if self.dynamic_ufun: self.acceptable_outcomes, self.wheel = self.acceptable() if self.best_first: for o in self.acceptable_outcomes: if o not in self.offered: self.offered.add(o) return o if len(self.acceptable_outcomes) > 0: if self.probabilisit_offering: r = random.random() for o, w in zip(self.acceptable_outcomes, self.wheel): if w > r: return o return random.sample(self.acceptable_outcomes, 1)[0] return random.sample(self.acceptable_outcomes, 1)[0] return None class SimpleTitForTatNegotiator(SAONegotiator): """Implements a generalized tit-for-tat strategy""" def __init__( self, name: str = None, parent: Controller = None, ufun: Optional["UtilityFunction"] = None, kindness=0.0, randomize_offer=False, initial_concession: Union[float, str] = "min", ): super().__init__(name=name, ufun=ufun, parent=parent) self._offerable_outcomes = None self.received_utilities = [] self.proposed_utility = None self.kindness = kindness self.ordered_outcomes = None self.initial_concession = initial_concession self.randomize_offer = randomize_offer def join( self, ami: AgentMechanismInterface, state: MechanismState, *, ufun: Optional["UtilityFunction"] = None, role: str = "agent", ) -> bool: if not super().join(ami, state, ufun=ufun, role=role): return False outcomes = ( self._ami.outcomes if self._offerable_outcomes is None else self._offerable_outcomes ) if outcomes is None: outcomes = sample_outcomes(self._ami.issues, keep_issue_names=True) if self.utility_function is None: return True self.ordered_outcomes = sorted( [(self.utility_function(outcome), outcome) for outcome in outcomes], key=lambda x: x[0], reverse=True, ) return True def respond(self, state: MechanismState, offer: "Outcome") -> "ResponseType": my_offer = self.propose(state=state) if self.utility_function is None: return ResponseType.REJECT_OFFER u = self.utility_function(offer) if len(self.received_utilities) < 2: self.received_utilities.append(u) else: self.received_utilities[-1] = u if u >= self.utility_function(my_offer): return ResponseType.ACCEPT_OFFER return ResponseType.REJECT_OFFER def _outcome_at_utility(self, asp: float, n: int) -> List["Outcome"]: for i, (u, o) in enumerate(self.ordered_outcomes): if u is None: continue if u < asp: if i == 0: return [self.ordered_outcomes[0][1]] * n if self.randomize_offer: if n < i: return [random.sample(self.ordered_outcomes, 1)[0][1]] * n else: return [_[1] for _ in self.ordered_outcomes[:i]] else: return [self.ordered_outcomes[i][1]] * n def propose(self, state: MechanismState) -> Optional["Outcome"]: if len(self.received_utilities) < 2 or self.proposed_utility is None: if len(self.received_utilities) < 1: return self.ordered_outcomes[0][1] if ( isinstance(self.initial_concession, str) and self.initial_concession == "min" ): asp = None for u, o in self.ordered_outcomes: if u is None: continue if asp is not None and u < asp: break asp = u if asp is None: return self.ordered_outcomes[0][1] else: asp = self.ordered_outcomes[0][0] * (1 - self.initial_concession) return self._outcome_at_utility(asp=asp, n=1)[0] opponent_concession = self.received_utilities[1] - self.received_utilities[0] asp = self.proposed_utility - opponent_concession * (1 + self.kindness) return self._outcome_at_utility(asp=asp, n=1)[0] def _to_java_response(response: ResponseType) -> int: if response == ResponseType.ACCEPT_OFFER: return 0 if response == ResponseType.REJECT_OFFER: return 1 if response == ResponseType.END_NEGOTIATION: return 2 if response == ResponseType.NO_RESPONSE: return 3 raise ValueError(f"Unknown response{response}") def _from_java_response(response: int) -> ResponseType: if response == 0: return ResponseType.ACCEPT_OFFER if response == 1: return ResponseType.REJECT_OFFER if response == 2: return ResponseType.END_NEGOTIATION if response == 3: return ResponseType.NO_RESPONSE raise ValueError( f"Unknown response type {response} returned from the Java underlying negotiator" ) class JavaSAONegotiator(SAONegotiator, JavaCallerMixin): def __init__( self, java_object, java_class_name: Optional[str], auto_load_java: bool = False, outcome_type: Type = dict, ): if java_class_name is not None or java_object is not None: self.init_java_bridge( java_object=java_object, java_class_name=java_class_name, auto_load_java=auto_load_java, python_shadow_object=None, ) if java_object is None: self._java_object.fromMap(to_java(self)) d = { python_identifier(k): v for k, v in JNegmasGateway.gateway.entry_point.toMap( self._java_object ).items() } ufun = d.get("utility_function", None) ufun = JavaUtilityFunction(ufun, None) if ufun is not None else None super().__init__( name=d.get("name", None), assume_normalized=d.get("assume_normalized", False), ufun=ufun, rational_proposal=d.get("rational_proposal", True), parent=d.get("parent", None), ) self._outcome_type = outcome_type self.add_capabilities( { "respond": True, "propose": True, "propose-with-value": False, "max-proposals": None, # indicates infinity } ) def on_partner_proposal( self, state: MechanismState, agent_id: str, offer: "Outcome" ) -> None: self._java_object.onPartnerProposal(to_java(state), agent_id, to_java(offer)) def on_partner_refused_to_propose( self, state: MechanismState, agent_id: str ) -> None: self._java_object.onPartnerRefusedToPropose(to_java(state), agent_id) def on_partner_response( self, state: MechanismState, agent_id: str, outcome: "Outcome", response: "SAOResponse", ) -> None: self._java_object.onPartnerResponse( to_java(state), agent_id, to_java(outcome), self._to_java_response(response) ) def isin(self, negotiation_id: Optional[str]) -> bool: return self._java_object.isIn(negotiation_id) def join( self, ami: AgentMechanismInterface, state: MechanismState, *, ufun: Optional["UtilityFunction"] = None, role: str = "agent", ) -> bool: return self._java_object.join( java_link(_ShadowAgentMechanismInterface(ami)), to_java(state), ufun, role ) def on_negotiation_start(self, state: MechanismState) -> None: self._java_object.onNegotiationStart(to_java(state)) def on_round_start(self, state: MechanismState) -> None: super().on_round_start(state) def on_mechanism_error(self, state: MechanismState) -> None: super().on_mechanism_error(state) def on_round_end(self, state: MechanismState) -> None: super().on_round_end(state) def on_leave(self, state: MechanismState) -> None: super().on_leave(state) def on_negotiation_end(self, state: MechanismState) -> None: super().on_negotiation_end(state) @classmethod def from_dict( cls, java_object, *args, parent: Controller = None ) -> "JavaSAONegotiator": """Creates a Java negotiator from an object returned from the JVM implementing PySAONegotiator""" ufun = java_object.getUtilityFunction() if ufun is not None: ufun = JavaUtilityFunction.from_dict(java_object=ufun) return JavaCallerMixin.from_dict( java_object, name=java_object.getName(), assume_normalized=java_object.getAssumeNormalized(), rational_proposal=java_object.getRationalProposal(), parent=parent, ufun=ufun, ) def on_notification(self, notification: Notification, notifier: str): super().on_notification(notification=notification, notifier=notifier) jnotification = {"type": notification.type, "data": to_java(notification.data)} self._java_object.on_notification(jnotification, notifier) def respond(self, state: MechanismState, offer: "Outcome"): return _from_java_response( self._java_object.respond(to_java(state), outcome_as_dict(offer)) ) def propose(self, state: MechanismState) -> Optional["Outcome"]: outcome = from_java(self._java_object.propose(to_java(state))) if outcome is None: return None if self._outcome_type == dict: return outcome if self._outcome_type == tuple: return tuple(outcome.values()) return self._outcome_type(outcome) # class Java: # implements = ['jnegmas.sao.SAONegotiator'] class _ShadowSAONegotiator: """A python shadow to a java negotiator""" class Java: implements = ["jnegmas.sao.SAONegotiator"] def to_java(self): return to_dict(self.shadow) def __init__(self, negotiator: SAONegotiator): self.shadow = negotiator def respond(self, state, outcome): return _to_java_response( self.shadow.respond(from_java(state), from_java(outcome)) ) def propose(self, state): return to_java(self.shadow.propose(from_java(state))) def isIn(self, negotiation_id): return to_java(self.shadow.isin(negotiation_id=negotiation_id)) def join(self, ami, state, ufun, role): return to_java( self.shadow.join( ami=from_java(ami), state=from_java(state), ufun=JavaUtilityFunction(ufun, None) if ufun is not None else None, role=role, ) ) def onNegotiationStart(self, state): return to_java(self.shadow.on_negotiation_start(from_java(state))) def onNegotiationEnd(self, state): return to_java(self.shadow.on_negotiation_end(from_java(state))) def onMechanismError(self, state): return to_java(self.shadow.on_mechanism_error(from_java(state))) def onRoundStart(self, state): return to_java(self.shadow.on_round_start(from_java(state))) def onRoundEnd(self, state): return to_java(self.shadow.on_round_end(from_java(state))) def onLeave(self, state): return to_java(self.shadow.on_leave(from_java(state))) def onPartnerProposal(self, state, agent_id, offer): return to_java( self.shadow.on_partner_proposal( state=from_java(state), agent_id=agent_id, offer=from_java(offer) ) ) def onPartnerRefusedToPropose(self, state, agent_id): return to_java( self.shadow.on_partner_refused_to_propose( state=from_java(state), agent_id=agent_id ) ) def onPartnerResponse(self, state, agent_id, offer, response: int, counter_offer): return to_java( self.shadow.on_partner_response( state=from_java(state), agent_id=agent_id, outcome=from_java(offer), response=SAOResponse( response=ResponseType(response), outcome=from_java(counter_offer) ), ) ) def onNotification(self, notification, notifier): return to_java(self.shadow.on_notification(from_java(notification), notifier)) def setUtilityFunction(self, ufun): self.shadow.utility_function = ( ufun if ufun is None else JavaUtilityFunction(ufun, None) ) def getUtilityFunction(self): return to_java(self.shadow.utility_function) def getID(self): return self.shadow.id def setID(self): return self.shadow.id class SAOController(Controller): def propose_( self, negotiator_id: str, state: MechanismState ) -> Optional["Outcome"]: negotiator, cntxt = self._negotiators.get(negotiator_id, (None, None)) if negotiator is None: raise ValueError(f"Unknown negotiator {negotiator_id}") return self.call(negotiator, "propose", state=state) def respond_( self, negotiator_id: str, state: MechanismState, offer: "Outcome" ) -> "ResponseType": negotiator, cntxt = self._negotiators.get(negotiator_id, (None, None)) if negotiator is None: raise ValueError(f"Unknown negotiator {negotiator_id}") return self.call(negotiator, "respond", state=state, offer=offer) SAOProtocol = SAOMechanism """An alias for `SAOMechanism object""" PK!0Ynegmas/scripts/__init__.py"""Command line scripts""" PK!sj)V)Vnegmas/scripts/app.py#!/usr/bin/env python """The NegMAS universal command line tool""" import json import os import traceback import urllib.request from functools import partial from math import factorial from pathlib import Path from pprint import pformat from time import perf_counter import click import pandas as pd import progressbar import yaml from tabulate import tabulate import negmas from negmas import save_stats from negmas.apps.scml import * from negmas.helpers import humanize_time, unique_name from negmas.java import init_jnegmas_bridge, jnegmas_bridge_is_running try: # disable a warning in yaml 1b1 version yaml.warnings({"YAMLLoadWarning": False}) except: pass n_completed = 0 n_total = 0 JNEGMAS_JAR_NAME = "jnegmas-0.2.3-all.jar" GENIUS_JAR_NAME = "genius-8.0.4-bridge.jar" def print_progress(_, i, n) -> None: """Prints the progress of a tournament""" global n_completed, n_total n_completed = i + 1 n_total = n print( f"{n_completed:04} of {n:04} worlds completed ({n_completed / n:0.2%})", flush=True, ) def print_world_progress(world) -> None: """Prints the progress of a world""" step = world.current_step + 1 s = ( f"World# {n_completed:04}: {step:04} of {world.n_steps:04} " f"steps completed ({step / world.n_steps:0.2f}) " ) if n_total > 0: s += f"TOTAL: ({n_completed + step / world.n_steps / n_total:0.2f})" print(s, flush=True) click.option = partial(click.option, show_default=True) @click.group() def cli(): pass @cli.command(help="Run a tournament between candidate agent types") @click.option( "--name", "-n", default="random", help='The name of the tournament. The special value "random" will result in a random name', ) @click.option("--steps", "-s", default=100, help="Number of steps.") @click.option( "--ttype", "--tournament-type", "--tournament", default="anac2019collusion", help="The config to use. Default is ANAC 2019. Options supported are anac2019std, anac2019collusion, " "anac2019sabotage", ) @click.option( "--timeout", "-t", default=0, help="Timeout after the given number of seconds (0 for infinite)", ) @click.option( "--configs", default=5, help="Number of unique configurations to generate." ) @click.option("--runs", default=2, help="Number of runs for each configuration") @click.option( "--max-runs", default=-1, help="Maximum total number of runs. Zero or negative numbers mean no limit", ) @click.option( "--competitors", default="negmas.apps.scml.DoNothingFactoryManager;negmas.apps.scml.GreedyFactoryManager", help="A semicolon (;) separated list of agent types to use for the competition.", ) @click.option( "--factories", default=5, help="Minimum numbers of factories to have per level." ) @click.option( "--jcompetitors", "--java-competitors", default="", help="A semicolon (;) separated list of agent types to use for the competition.", ) @click.option( "--parallel/--serial", default=True, help="Run a parallel/serial tournament on a single machine", ) @click.option( "--distributed/--single-machine", default=False, help="Run a distributed tournament using dask", ) @click.option( "--log", "-l", default="~/negmas/logs/tournaments", help="Default location to save logs (A folder will be created under it)", ) @click.option( "--verbosity", default=1, help="verbosity level (from 0 == silent to 1 == world progress)", ) @click.option("--configs-only/--run", default=False, help="configs_only") @click.option( "--reveal-names/--hidden-names", default=True, help="Reveal agent names (should be used only for " "debugging)", ) @click.option( "--ip", default="127.0.0.1", help="The IP address for a dask scheduler to run the distributed tournament." " Effective only if --distributed", ) @click.option( "--port", default=8786, help="The IP port number a dask scheduler to run the distributed tournament." " Effective only if --distributed", ) @click.option( "--compact/--debug", default=True, help="If True, effort is exerted to reduce the memory footprint which" "includes reducing logs dramatically.", ) def tournament( name, steps, parallel, distributed, ttype, timeout, log, verbosity, configs_only, reveal_names, ip, port, runs, configs, max_runs, competitors, jcompetitors, compact, factories, ): if timeout <= 0: timeout = None if name == "random": name = None if max_runs <= 0: max_runs = None if not compact: if not reveal_names: print( "You are running the tournament with --debug. Will reveal agent types in their names" ) reveal_names = True verbosity = max(1, verbosity) worlds_per_config = ( None if max_runs is None else int(round(max_runs / (configs * runs))) ) parallelism = "distributed" if distributed else "parallel" if parallel else "serial" all_competitors = competitors.split(";") for i, cp in enumerate(all_competitors): if "." not in cp: all_competitors[i] = "negmas.apps.scml.factory_managers." + cp all_competitors_params = [dict() for _ in range(len(all_competitors))] if jcompetitors is not None and len(jcompetitors) > 0: jcompetitor_params = [{"java_class_name": _} for _ in jcompetitors.split(";")] for jp in jcompetitor_params: if "." not in jp["java_class_name"]: jp["java_class_name"] = ( "jnegmas.apps.scml.factory_managers." + jp["java_class_name"] ) jcompetitors = ["negmas.apps.scml.JavaFactoryManager"] * len(jcompetitor_params) all_competitors += jcompetitors all_competitors_params += jcompetitor_params print("You are using some Java agents. The tournament MUST run serially") parallelism = "serial" if not jnegmas_bridge_is_running(): print( "Error: You are using java competitors but jnegmas bridge is not running\n\nTo correct this issue" " run the following command IN A DIFFERENT TERMINAL because it will block:\n\n" "$ negmas jnegmas" ) exit(1) prog_callback = print_world_progress if verbosity > 1 and not distributed else None recommended = ( runs * configs * factorial(len(all_competitors) * (1 if "std" in ttype else 3)) ) if worlds_per_config is not None and worlds_per_config < 1: print( f"You need at least {(configs * runs)} runs even with a single permutation of managers." f".\n\nSet --max-runs to at least {(configs * runs)} (Recommended {recommended})" ) return if max_runs is not None and max_runs < recommended: print( f"You are running {max_runs} worlds only but it is recommended to set {max_runs} to at least " f"{recommended}. Will continue" ) if worlds_per_config is None: n_agents_per_competitor = 1 if ttype == "anac2019std" else 3 n_worlds = ( factorial(n_agents_per_competitor * len(all_competitors)) * runs * configs ) if n_worlds > 100: print( f"You are running the maximum possible number of permutations for each configuration. This is roughly" f" {n_worlds} simulations (each for {steps} steps). That will take a VERY long time." f"\n\nYou can reduce the number of simulations by setting --configs (currently {configs}) or --runs" f" (currently {runs}) to a lower value. If you are running a collusion competition, you can reduce" f" the number of simulations " f"{factorial(n_agents_per_competitor * len(all_competitors))/factorial(len(all_competitors))} times " f"by running a standard competition (--ttype=anac2019std)." f"\nFinally, you can limit the maximum number of worlds to run by setting --max-runs=integer." ) if ttype == "anac2019collusion": n_new = factorial(len(all_competitors)) * runs * configs print( f"If you use --ttype=anac2019std (standard competition), the number of simulations will be {n_new}" ) if ( not input(f"Are you sure you want to run {n_worlds} simulations?") .lower() .startswith("y") ): exit(0) if len(jcompetitors) > 0: print("You are using java-competitors. The tournament will be run serially") parallelism = "serial" start = perf_counter() if ttype.lower() == "anac2019std": results = anac2019_std( competitors=all_competitors, competitor_params=all_competitors_params, agent_names_reveal_type=reveal_names, tournament_path=log, total_timeout=timeout, parallelism=parallelism, scheduler_ip=ip, scheduler_port=port, world_progress_callback=prog_callback, name=name, verbose=verbosity > 0, n_runs_per_world=runs, n_configs=configs, max_worlds_per_config=worlds_per_config, configs_only=configs_only, n_steps=steps, compact=compact, ) elif ttype.lower() in ("anac2019collusion", "anac2019"): results = anac2019_collusion( competitors=all_competitors, competitor_params=all_competitors_params, agent_names_reveal_type=reveal_names, tournament_path=log, total_timeout=timeout, parallelism=parallelism, scheduler_ip=ip, scheduler_port=port, world_progress_callback=prog_callback, name=name, verbose=verbosity > 0, n_runs_per_world=runs, n_configs=configs, max_worlds_per_config=worlds_per_config, configs_only=configs_only, n_steps=steps, compact=compact, ) else: print(f"{ttype.lower()} tournament type is not supported") exit(1) if configs_only: print(f"Saved all configs to {str(results)}") print(f"Finished in {humanize_time(perf_counter() - start)} [config-only]") return print(tabulate(results.total_scores, headers="keys", tablefmt="psql")) print(f"Finished in {humanize_time(perf_counter() - start)} [{parallelism}]") @cli.command(help="Run an SCML world simulation") @click.option("--steps", default=100, help="Number of steps.") @click.option( "--levels", default=3, help="Number of intermediate production levels (processes). " "-1 means a single product and no factories.", ) @click.option("--neg-speedup", default=21, help="Negotiation Speedup.") @click.option( "--negotiator", default="negmas.sao.AspirationNegotiator", help="Negotiator type to use for builtin agents.", ) @click.option( "--min-consumption", default=3, help="The minimum number of units consumed by each consumer at every " "time-step.", ) @click.option( "--max-consumption", default=5, help="The maximum number of units consumed by each consumer at every " "time-step.", ) @click.option( "--agents", default=5, help="Number of agents (miners/negmas.consumers) per production level", ) @click.option("--horizon", default=20, help="Consumption horizon.") @click.option("--transport", default=0, help="Transportation Delay.") @click.option("--time", default=60 * 90, help="Total time limit.") @click.option("--neg-time", default=60 * 4, help="Time limit per single negotiation") @click.option("--neg-steps", default=20, help="Number of rounds per single negotiation") @click.option( "--sign", default=1, help="The default delay between contract conclusion and signing", ) @click.option( "--guaranteed", default=False, help="Whether to only sign contracts that are guaranteed not to cause " "breaches", ) @click.option("--lines", default=10, help="The number of lines per factory") @click.option( "--retrials", default=5, help="The number of times an agent re-tries on failed negotiations", ) @click.option( "--use-consumer", default=True, help="Use internal consumer object in factory managers", ) @click.option( "--max-insurance", default=100, help="Use insurance against partner in factory managers up to this " "premium", ) @click.option( "--riskiness", default=0.0, help="How risky is the default factory manager" ) @click.option( "--log", default="~/negmas/logs", help="Default location to save logs (A folder will be created under it)", ) @click.option( "--compact/--debug", default=True, help="If True, effort is exerted to reduce the memory footprint which" "includes reducing logs dramatically.", ) def scml( steps, levels, neg_speedup, negotiator, agents, horizon, min_consumption, max_consumption, transport, time, neg_time, neg_steps, sign, guaranteed, lines, retrials, use_consumer, max_insurance, riskiness, log, compact, ): params = { "steps": steps, "levels": levels, "neg_speedup": neg_speedup, "negotiator": negotiator, "agents": agents, "horizon": horizon, "min_consumption": min_consumption, "max_consumption": max_consumption, "transport": transport, "time": time, "neg_time": neg_time, "neg_steps": neg_steps, "sign": sign, "guaranteed": guaranteed, "lines": lines, "retrials": retrials, "use_consumer": use_consumer, "max_insurance": max_insurance, "riskiness": riskiness, } neg_speedup = neg_speedup if neg_speedup is not None and neg_speedup > 0 else None if min_consumption == max_consumption: consumption = min_consumption else: consumption = (min_consumption, max_consumption) customer_kwargs = {"negotiator_type": negotiator, "consumption_horizon": horizon} miner_kwargs = {"negotiator_type": negotiator, "n_retrials": retrials} factory_kwargs = { "negotiator_type": negotiator, "n_retrials": retrials, "sign_only_guaranteed_contracts": guaranteed, "use_consumer": use_consumer, "riskiness": riskiness, "max_insurance_premium": max_insurance, } if log.startswith("~/"): log_dir = Path.home() / log[2:] else: log_dir = Path(log) log_dir = log_dir / unique_name(base="scml", add_time=True, rand_digits=0) log_dir = log_dir.absolute() os.makedirs(log_dir, exist_ok=True) log_file_name = str(log_dir / "log.txt") exception = None world = SCMLWorld.chain_world( log_file_name=log_file_name, n_steps=steps, negotiation_speed=neg_speedup, n_intermediate_levels=levels, n_miners=agents, n_consumers=agents, n_factories_per_level=agents, consumption=consumption, consumer_kwargs=customer_kwargs, miner_kwargs=miner_kwargs, default_manager_params=factory_kwargs, transportation_delay=transport, time_limit=time, neg_time_limit=neg_time, neg_n_steps=neg_steps, default_signing_delay=sign, n_lines_per_factory=lines, compact=compact, agent_names_reveal_type=True, ) failed = False strt = perf_counter() try: for i in progressbar.progressbar(range(world.n_steps), max_value=world.n_steps): elapsed = perf_counter() - strt if world.time_limit is not None and elapsed >= world.time_limit: break if not world.step(): break except Exception: exception = traceback.format_exc() failed = True elapsed = perf_counter() - strt def print_and_log(s): world.logdebug(s) print(s) world.logdebug(f"{pformat(world.stats, compact=True)}") world.logdebug( f"=================================================\n" f"steps: {steps}, horizon: {horizon}, time: {time}, levels: {levels}, agents_per_level: " f"{agents}, lines: {lines}, guaranteed: {guaranteed}, negotiator: {negotiator}\n" f"consumption: {consumption}" f", transport_to: {transport}, sign: {sign}, speedup: {neg_speedup}, neg_steps: {neg_steps}" f", retrials: {retrials}" f", neg_time: {neg_time}\n" f"==================================================" ) save_stats(world=world, log_dir=log_dir, params=params) if len(world.saved_contracts) > 0: data = pd.DataFrame(world.saved_contracts) data = data.sort_values(["delivery_time"]) data = data.loc[ data.signed_at >= 0, [ "seller_type", "buyer_type", "seller_name", "buyer_name", "delivery_time", "unit_price", "quantity", "product_name", "n_neg_steps", "signed_at", ], ] data.columns = [ "seller_type", "buyer_type", "seller", "buyer", "t", "price", "q", "product", "steps", "signed", ] print_and_log(tabulate(data, headers="keys", tablefmt="psql")) n_executed = sum(world.stats["n_contracts_executed"]) n_negs = sum(world.stats["n_negotiations"]) n_contracts = len(world.saved_contracts) winners = [ f"{_.name} gaining {world.a2f[_.id].balance / world.a2f[_.id].initial_balance - 1.0:0.0%}" for _ in world.winners ] print_and_log( f"{n_contracts} contracts :-) [N. Negotiations: {n_negs}, Agreement Rate: " f"{world.agreement_rate:0.0%}]" ) print_and_log( f"Cancelled: {world.cancellation_rate:0.0%}, Executed: {world.contract_execution_fraction:0.0%}" f", Breached: {world.breach_rate:0.0%}, N. Executed: {n_executed}, Business size: " f"{world.business_size}\n" f"Winners: {winners}\n" f"Running Time {humanize_time(elapsed)}" ) else: print_and_log("No contracts! :-(") print_and_log(f"Running Time {humanize_time(elapsed)}") if failed: print(exception) world.logdebug(exception) print(f"FAILED at step {world.current_step} of {world.n_steps}\n") @cli.command(help="Start the bridge to genius (to use GeniusNegotiator)") @click.option( "--path", "-p", default="auto", help='Path to genius-8.0.4.jar with embedded NegLoader. Use "auto" to ' "read the path from ~/negmas/config.json" "\n\tConfig key is genius_bridge_jar" "\nYou can download this jar from: " "http://www.yasserm.com/scml/genius-8.0.4-bridge.jar", ) @click.option( "--port", "-r", default=0, help="Port to run the NegLoader on. Pass 0 for the default value", ) @click.option( "--force/--no-force", default=False, help="Force trial even if an earlier instance exists", ) def genius(path, port, force): negmas.init_genius_bridge( path=path if path != "auto" else None, port=port, force=force ) @cli.command(help="Start the bridge to JNegMAS (to use Java agents in worlds)") @click.option( "--path", "-p", default="auto", help='Path to jnegmas*.jar with. Use "auto" to ' "read the path from ~/negmas/config.json." "\n\tConfig key is jnegmas_jar" "\nYou can download the latest version of this jar from: " "http://www.yasserm.com/scml/jnegmas-all.jar", ) @click.option( "--port", "-r", default=0, help="Port to run the jnegmas on. Pass 0 for the default value", ) def jnegmas(path, port): init_jnegmas_bridge(path=path if path != "auto" else None, port=port) input( "Press C^c to quit. You may also need to kill any remaining java processes manually" ) def download_and_set(key, url, file_name): """ Downloads a file and sets the corresponding key in ~/negmas/config.json Args: key: Key name in config.json url: URL to download from file_name: file name Returns: """ config_path = Path.home() / "negmas" jar_path = config_path / "files" jar_path.mkdir(parents=True, exist_ok=True) jar_path = jar_path / file_name urllib.request.urlretrieve(url, jar_path) config = {} config_file = config_path / "config.json" if config_file.exists(): with open(config_file, "r") as f: config = json.load(f) config[key] = str(jar_path) with open(config_file, "w") as f: json.dump(config, fp=f, sort_keys=True, indent=4) @cli.command(help="Downloads jnegmas and updates your settings") def jnegmas_setup(): url = f"http://www.yasserm.com/scml/{JNEGMAS_JAR_NAME}" print(f"Downloading: {url}", end="", flush=True) download_and_set(key="jnegmas_jar", url=url, file_name="jnegmas.jar") print(" done successfully") @cli.command(help="Downloads the genius bridge and updates your settings") def genius_setup(): url = f"http://www.yasserm.com/scml/{GENIUS_JAR_NAME}" print(f"Downloading: {url}", end="", flush=True) download_and_set(key="genius_bridge_jar", url=url, file_name="jnegmas.jar") print(" done successfully") @cli.command(help="Prints NegMAS version") def version(): print(negmas.__version__) if __name__ == "__main__": cli() PK!bRRnegmas/situated.py"""This module defines the base classes for worlds within which multiple agents engage in situated negotiations The `Agent` class encapsulates the managing entity that creates negotiators to engage in negotiations within a world `Simulation` in order to maximize its own total utility. Remarks: -------- - When immediate_negotiations is true, negotiations start in the same step they are registered in (they may also end in that step) and `negotiation_speed_multiple` steps of it are conducted. That entails that requesting a negotiation may result in new contracts in the same time-step only of `immediate_negotiations` is true. Simulation steps: ----------------- #. prepare custom stats (call `_pre_step_stats`) #. sign contracts that are to be signed at this step calling `on_contract_signed` as needed #. step all existing negotiations `negotiation_speed_multiple` times handling any failed negotiations and creating contracts for any resulting agreements #. run all `Entity` objects registered (i.e. all agents) in the predefined `simulation_order`. #. execute contracts that are executable at this time-step handling any breaches #. allow custom simulation steps to run (call `_simulation_step`) #. remove any negotiations that are completed! #. update basic stats #. update custom stats (call `_post_step_stats`) """ import copy import logging import os import random import re import time import uuid from abc import ABC, abstractmethod from collections import defaultdict, namedtuple from enum import Enum from pathlib import Path from typing import Dict, Sized from typing import ( Optional, List, Any, Tuple, Callable, Union, Iterable, Set, Iterator, Collection, ) import numpy as np import pandas as pd import yaml from dataclasses import dataclass, field from negmas.common import AgentMechanismInterface, MechanismState from negmas.common import NamedObject from negmas.events import Event, EventSource, EventSink, Notifier from negmas.helpers import ( ConfigReader, instantiate, get_class, unique_name, snake_case, dump, create_loggers, ) from negmas.mechanisms import Mechanism from negmas.negotiators import Negotiator from negmas.outcomes import OutcomeType, Issue __all__ = [ "Action", # An action that an `Agent` can execute in the `World`. "Contract", # A agreement definition which encapsulates an agreement with partners and extra information "Breach", # A breach in executing a contract "BreachProcessing", "Agent", # Negotiator capable of engaging in multiple negotiations "BulletinBoard", "World", "Entity", "AgentWorldInterface", # the interface though which an agent can interact with the world "NegotiationInfo", "RenegotiationRequest", "save_stats", ] PROTOCOL_CLASS_NAME_FIELD = "__mechanism_class_name" try: # disable a warning in yaml 1b1 version yaml.warnings({"YAMLLoadWarning": False}) except: pass @dataclass class Action: """An action that an `Agent` can execute in a `World` through the `Simulator`.""" type: str """Action name.""" params: dict """Any extra parameters to be passed for the action.""" def __str__(self): return f"{self.type}: {self.params}" Signature = namedtuple("Signature", ["id", "signature"]) """A signature with the name of signature and her signature""" @dataclass class Contract(OutcomeType): """A agreement definition which encapsulates an agreement with partners and extra information""" partners: List[str] = field(default_factory=list) """The partners""" agreement: OutcomeType = None """The actual agreement of the negotiation in the form of an `Outcome` in the `Issue` space defined by `issues`""" annotation: Dict[str, Any] = field(default_factory=dict) """Misc. information to be kept with the agreement.""" issues: List[Issue] = field(default_factory=list) """Issues of the negotiations from which this agreement was concluded. It may be empty""" signed_at: Optional[int] = None """The time-step at which the contract was signed""" concluded_at: Optional[int] = None """The time-step at which the contract was concluded (but it is still not binding until signed)""" nullified_at: Optional[int] = None """The time-step at which the contract was nullified after being signed. That can happen if a partner declares bankruptcy""" to_be_signed_at: Optional[int] = None """The time-step at which the contract should be signed""" signatures: List[Signature] = field(default_factory=list) """A list of signatures giving agent name, signature""" mechanism_state: Optional[MechanismState] = None """The mechanism state at the contract conclusion""" id: str = field(default_factory=lambda: str(uuid.uuid4()), init=True) """Object name""" def __str__(self): return f'{", ".join(self.partners)} agreed on {str(self.agreement)}' def __hash__(self): """The hash depends only on the name""" return self.id.__hash__() class Java: implements = ["jnegmas.situated.Contract"] @dataclass class Breach: contract: Contract """The agreement being breached""" perpetrator: str """ID of the agent committing the breach""" type: str """The type of the breach. Can be one of: `refusal`, `product`, `money`, `penalty`.""" victims: List[str] = field(default_factory=list) """Specific victims of the breach. If not given all partners in the agreement (except perpetrator) are considered victims""" level: float = 1.0 """Breach level defaulting to full breach (a number between 0 and 1)""" step: int = -1 """The simulation step at which the breach occurred""" id: str = field(default_factory=lambda: str(uuid.uuid4()), init=True) """Object name""" def __hash__(self): """The hash depends only on the name""" return self.id.__hash__() def __str__(self): return f"Breach ({self.level} {self.type}) by {self.perpetrator} on {self.contract.id} at {self.step}" def as_dict(self): return { "contract": str(self.contract), "contract_id": self.contract.id, "type": self.type, "level": self.level, "id": self.id, "perpetrator": self.perpetrator, "perpetrator_type": self.perpetrator.__class__.__name__, "victims": [_ for _ in self.victims], "step": self.step, "resolved": None, } class Java: implements = ["jnegmas.situated.Breach"] class BreachProcessing(Enum): """The way breaches are to be handled""" NONE = 0 """The breach should always be reported in the breach list and no re-negotiation is allowed.""" VICTIM_THEN_PERPETRATOR = 1 """The victim is asked to set the re-negotiation agenda then the perpetrator.""" META_NEGOTIATION = 2 """A meta negotiation is instantiated between victim and perpetrator to set re-negotiation issues.""" @dataclass class RenegotiationRequest: """A request for renegotiation. The issues can be any or all of the following: immediate_delivery: int immediate_unit_price: float later_quantity: int later_unit_price: int later_penalty: float later_time: int """ publisher: "Agent" issues: List[Issue] annotation: Dict[str, Any] = field(default_factory=dict) class Java: implements = ["jnegmas.situated.RenegotiationRequest"] class Entity(NamedObject): """Defines an entity that is a part of the world but does not participate in the simulation""" def __init__(self, name: str = None): super().__init__(name=name) @property def type_name(self): """Returns the name of the type of this entity""" return snake_case(self.__class__.__name__) @property def short_type_name(self): """Returns a short name of the type of this entity""" long_name = self.type_name name = ( long_name.split(".")[-1] .lower() .replace("factory_manager", "") .replace("manager", "") ) name = ( name.replace("factory", "") .replace("agent", "") .replace("miner", "") .replace("consumer", "") ) if long_name.startswith("jnegmas"): name = f"j-{name}" name = name.strip("_") return name class BulletinBoard(Entity, EventSource, ConfigReader): """The bulletin-board which carries all public information. It consists of sections each with a dictionary of records. """ def __getstate__(self): return self.name, self._data def __setstate__(self, state): name, self._data = state super().__init__(name=name) def __init__(self, name: str = None): """ Constructor Args: name: BulletinBoard name """ super().__init__(name=name) self._data: Dict[str, Dict[str, Any]] = {} def add_section(self, name: str) -> None: """ Adds a section to the bulletin Board Args: name: Section name Returns: """ self._data[name] = {} def query( self, section: Optional[Union[str, List[str]]], query: Any, query_keys=False ) -> Optional[Dict[str, Any]]: """ Returns all records in the given section/sections of the bulletin-board that satisfy the query Args: section: Either a section name, a list of sections or None specifying ALL public sections (see remarks) query: The query which is USUALLY a dict with conditions on it when querying values and a RegExp when querying keys query_keys: Whether the query is to be applied to the keys or values. Returns: - A dictionary with key:value pairs giving all records that satisfied the given requirements. Remarks: - A public section is a section with a name that does not start with an underscore - If a set of sections is given, and two records in different sections had the same key, only one of them will be returned - Key queries use regular expressions and match from the beginning using the standard re.match function """ if section is None: return self.query( section=[_ for _ in self._data.keys() if not _.startswith("_")], query=query, query_keys=query_keys, ) if isinstance(section, Iterable) and not isinstance(section, str): results = [ self.query(section=_, query=query, query_keys=query_keys) for _ in section ] if len(results) == 0: return dict() final: Dict[str, Any] = {} for _ in results: final.update(_) return final sec = self._data.get(section, None) if sec is None: return {} if query is None: return copy.deepcopy(sec) if query_keys: return {k: v for k, v in sec.items() if re.match(str(query), k) is not None} return {k: v for k, v in sec.items() if BulletinBoard.satisfies(v, query)} @classmethod def satisfies(cls, value: Any, query: Any) -> bool: method = getattr(value, "satisfies", None) if method is not None and isinstance(method, Callable): return method(query) if isinstance(value, dict) and isinstance(query, dict): for k, v in query.items(): if value.get(k, None) != v: return False else: raise ValueError( f"Cannot check satisfaction of {type(query)} against value {type(value)}" ) return True def read(self, section: str, key: str) -> Any: """ Reads the value associated with given key Args: section: section name key: key Returns: Content of that key in the bulletin-board """ sec = self._data.get(section, None) if sec is None: return None return sec.get(key, None) def record(self, section: str, value: Any, key: Optional[str] = None) -> None: """ Records data in the given section of the bulletin-board Args: section: section name (can contain subsections separated by '/') key: The key value: The value """ if key is None: try: skey = str(hash(value)) except: skey = str(uuid.uuid4()) else: skey = key self._data[section][skey] = value self.announce( Event("new_record", data={"section": section, "key": skey, "value": value}) ) def remove( self, section: Optional[Union[List[str], str]], *, query: Optional[Any] = None, key: str = None, query_keys: bool = False, value: Any = None, ) -> bool: """ Removes a value or a set of values from the bulletin Board Args: section: The section query: the query to use to select what to remove key: the key to remove (no need to give a full query) query_keys: Whether to apply the query (if given) to keys or values value: Value to be removed Returns: bool: Success of failure """ if section is None: return self.remove( section=[_ for _ in self._data.keys() if not _.startswith("_")], query=query, key=key, query_keys=query_keys, ) if isinstance(section, Iterable) and not isinstance(section, str): return all( self.remove(section=_, query=query, key=key, query_keys=query_keys) for _ in section ) sec = self._data.get(section, None) if sec is None: return False if value is not None: for k, v in sec.items(): if v == value: key = k break if key is not None: try: self.announce( Event( "will_remove_record", data={"section": sec, "key": key, "value": sec[key]}, ) ) sec.pop(key, None) return True except KeyError: return False if query is None: return False if query_keys: keys = [k for k, v in sec.items() if re.match(str(query), k) is not None] else: keys = [k for k, v in sec.items() if v.satisfies(query)] if len(keys) == 0: return False for k in keys: self.announce( Event( "will_remove_record", data={"section": sec, "key": k, "value": sec[k]}, ) ) sec.pop(k, None) return True @property def data(self): """This property is intended for use only by the world manager. No other agent is allowed to use it""" return self._data def safe_min(a, b): """Returns min(a, b) assuming None is less than anything.""" if a is None: return b if b is None: return a return min(a, b) @dataclass class NegotiationInfo: """Saves information about a negotiation""" mechanism: Optional[Mechanism] partners: List["Agent"] annotation: Dict[str, Any] issues: List["Issue"] requested_at: int rejectors: Optional[List["Agent"]] = None class MechanismFactory: """A mechanism creation class. It can invite agents to join a mechanism and then run it.""" def __init__( self, world: "World", mechanism_name: str, mechanism_params: Dict[str, Any], issues: List["Issue"], req_id: str, caller: "Agent", partners: List["Agent"], roles: Optional[List[str]] = None, annotation: Dict[str, Any] = None, neg_n_steps: int = None, neg_time_limit: int = None, neg_step_time_limit=None, ): self.mechanism_name, self.mechanism_params = mechanism_name, mechanism_params self.caller = caller self.partners = partners self.roles = roles self.annotation = annotation self.neg_n_steps = neg_n_steps self.neg_time_limit = neg_time_limit self.neg_step_time_limit = neg_step_time_limit self.world = world self.req_id = req_id self.issues = issues self.mechanism = None def _create_negotiation_session( self, mechanism: Mechanism, responses: Iterator[Tuple[Negotiator, str]], partners: List["Agent"], ) -> Mechanism: if self.neg_n_steps is not None: mechanism.ami.n_steps = self.neg_n_steps if self.neg_time_limit is not None: mechanism.ami.time_limit = self.neg_time_limit if self.neg_step_time_limit is not None: mechanism.ami.step_time_limit = self.neg_step_time_limit for partner in partners: mechanism.register_listener(event_type="negotiation_end", listener=partner) for _negotiator, _role in responses: mechanism.add(negotiator=_negotiator, role=_role) return mechanism def _start_negotiation( self, mechanism_name, mechanism_params, roles, caller, partners, annotation, issues, req_id, ) -> Optional[NegotiationInfo]: """Tries to prepare the negotiation to start by asking everyone to join""" mechanisms = self.world.mechanisms if issues is None: caller.on_neg_request_rejected_(req_id=req_id, by=None) return None if ( mechanisms is not None and mechanism_name is not None and mechanism_name not in mechanisms.keys() ): caller.on_neg_request_rejected_(req_id=req_id, by=None) return None if mechanisms is not None and mechanism_name is not None: mechanism_name = mechanisms[mechanism_name].pop( PROTOCOL_CLASS_NAME_FIELD, mechanism_name ) if mechanism_params is None: mechanism_params = {} if mechanisms and mechanisms.get(mechanism_name, None) is not None: mechanism_params.update(mechanisms[mechanism_name]) # mechanism_params = {k: v for k, v in mechanism_params.items() if k != PROTOCOL_CLASS_NAME_FIELD} mechanism_params["n_steps"] = self.neg_n_steps mechanism_params["time_limit"] = self.neg_time_limit mechanism_params["step_time_limit"] = self.neg_step_time_limit mechanism_params["issues"] = issues mechanism_params["annotation"] = annotation mechanism_params["name"] = "-".join(_.id for _ in partners) if mechanism_name is None: if mechanisms is not None and len(mechanisms) == 1: mechanism_name = list(mechanisms.keys())[0] else: mechanism_name = "negmas.sao.SAOMechanism" try: mechanism = instantiate(class_name=mechanism_name, **mechanism_params) except: mechanism = None self.world.logerror( f"Failed to create {mechanism_name} with params {mechanism_params}" ) self.mechanism = mechanism if mechanism is None: return None if roles is None: roles = [None] * len(partners) partner_names = [p.id for p in partners] responses = [ partner.respond_to_negotiation_request_( initiator=caller.id, partners=partner_names, issues=issues, annotation=annotation, role=role, mechanism=mechanism.ami, req_id=req_id if partner == caller else None, ) for role, partner in zip(roles, partners) ] if not all(responses): rejectors = [p for p, response in zip(partners, responses) if not response] caller.on_neg_request_rejected_(req_id=req_id, by=[_.id for _ in rejectors]) self.world.loginfo(f"{caller.id} request was rejected by {rejectors}") return NegotiationInfo( mechanism=None, partners=partners, annotation=annotation, issues=issues, rejectors=rejectors, requested_at=self.world.current_step, ) mechanism = self._create_negotiation_session( mechanism=mechanism, responses=zip(responses, roles), partners=partners ) neg_info = NegotiationInfo( mechanism=mechanism, partners=partners, annotation=annotation, issues=issues, requested_at=self.world.current_step, ) caller.on_neg_request_accepted_(req_id=req_id, mechanism=mechanism.ami) self.world.loginfo(f"{caller.id} request was accepted") return neg_info def init(self) -> Optional[NegotiationInfo]: return self._start_negotiation( mechanism_name=self.mechanism_name, mechanism_params=self.mechanism_params, roles=self.roles, caller=self.caller, partners=self.partners, annotation=self.annotation, issues=self.issues, req_id=self.req_id, ) class AgentWorldInterface: """Agent World Interface class""" def __getstate__(self): return self._world, self.agent.id def __setstate__(self, state): self._world, agent_id = state self.agent = self._world.agents[agent_id] def __init__(self, world: "World", agent: "Agent"): self._world, self.agent = world, agent def execute( self, action: Action, callback: Callable[[Action, bool], Any] = None ) -> bool: """Executes an action in the world simulation""" return self._world.execute(action=action, agent=self.agent, callback=callback) @property def state(self) -> Any: """Returns the private state of the agent in that world""" return self._world.get_private_state(self.agent) @property def relative_time(self) -> float: """Relative time of the simulation going from 0 to 1""" return self._world.relative_time @property def current_step(self) -> int: """Current simulation step""" return self._world.current_step @property def n_steps(self) -> int: """Number of steps in a simulation""" return self._world.n_steps @property def default_signing_delay(self) -> int: return self._world.default_signing_delay def request_negotiation_about( self, issues: List[Issue], partners: List[str], req_id: str, roles: List[str] = None, annotation: Optional[Dict[str, Any]] = None, mechanism_name: str = None, mechanism_params: Dict[str, Any] = None, ) -> bool: """ Requests to start a negotiation with some other agents Args: req_id: issues: Negotiation issues annotation: Extra information to be passed to the `partners` when asking them to join the negotiation partners: A list of partners to participate in the negotiation roles: The roles of different partners. If None then each role for each partner will be None mechanism_name: Name of the mechanism to use. It must be one of the mechanism_names that are supported by the `World` or None which means that the `World` should select the mechanism. If None, then `roles` and `my_role` must also be None mechanism_params: A dict of parameters used to initialize the mechanism object Returns: List["Agent"] the list of partners who rejected the negotiation if any. If None then the negotiation was accepted. If empty then the negotiation was not started from the world manager Remarks: - The function will create a request ID that will be used in callbacks `on_neg_request_accepted` and `on_neg_request_rejected` """ partner_agents = [self._world.agents[_] for _ in partners] return self._world.request_negotiation_about( req_id=req_id, caller=self.agent, partners=partner_agents, roles=roles, issues=issues, annotation=annotation, mechanism_name=mechanism_name, mechanism_params=mechanism_params, ) def loginfo(self, msg: str) -> None: """ Logs an INFO message Args: msg: The message to log Returns: """ self._world.loginfo(msg) def logwarning(self, msg: str) -> None: """ Logs a WARNING message Args: msg: The message to log Returns: """ self._world.logwarning(msg) def logdebug(self, msg: str) -> None: """ Logs a WARNING message Args: msg: The message to log Returns: """ self._world.logdebug(msg) def logerror(self, msg: str) -> None: """ Logs a WARNING message Args: msg: The message to log Returns: """ self._world.logerror(msg) def bb_query( self, section: Optional[Union[str, List[str]]], query: Any, query_keys=False ) -> Optional[Dict[str, Any]]: """ Returns all records in the given section/sections of the bulletin-board that satisfy the query Args: section: Either a section name, a list of sections or None specifying ALL public sections (see remarks) query: The query which is USUALLY a dict with conditions on it when querying values and a RegExp when querying keys query_keys: Whether the query is to be applied to the keys or values. Returns: - A dictionary with key:value pairs giving all records that satisfied the given requirements. Remarks: - A public section is a section with a name that does not start with an underscore - If a set of sections is given, and two records in different sections had the same key, only one of them will be returned - Key queries use regular expressions and match from the beginning using the standard re.match function """ return self._world.bulletin_board.query( section=section, query=query, query_keys=query_keys ) def bb_read(self, section: str, key: str) -> Optional[Any]: """ Reads the value associated with given key from the bulletin board Args: section: section name key: key Returns: Content of that key in the bulletin-board """ return self._world.bulletin_board.read(section=section, key=key) def bb_record(self, section: str, value: Any, key: Optional[str] = None) -> None: """ Records data in the given section of the bulletin board Args: section: section name (can contain subsections separated by '/') key: The key value: The value """ return self._world.bulletin_board.record(section=section, value=value, key=key) def bb_remove( self, section: Optional[Union[List[str], str]], *, query: Optional[Any] = None, key: str = None, query_keys: bool = False, value: Any = None, ) -> bool: """ Removes a value or a set of values from the bulletin Board Args: section: The section query: the query to use to select what to remove key: the key to remove (no need to give a full query) query_keys: Whether to apply the query (if given) to keys or values value: Value to be removed Returns: bool: Success of failure """ return self._world.bulletin_board.remove( section=section, query=query, key=key, query_keys=query_keys, value=value ) class Java: implements = ["jnegmas.situated.AgentWorldInterface"] class World(EventSink, EventSource, ConfigReader, ABC): """Base world class encapsulating a world that runs a simulation with several agents interacting within some dynamically changing environment. A world maintains its own session. """ def __getstate__(self): state = self.__dict__.copy() if "logger" in state.keys(): state.pop("logger", None) return state def __setstate__(self, state): self.__dict__ = state self.logger = create_loggers( file_name=self.log_file_name, module_name=None, screen_level=self.log_screen_level if self.log_to_screen else None, file_level=self.log_file_level, app_wide_log_file=True, ) def __init__( self, bulletin_board: BulletinBoard = None, n_steps=10000, time_limit=60 * 60, negotiation_speed=None, neg_n_steps=100, neg_time_limit=3 * 60, neg_step_time_limit=60, default_signing_delay=0, breach_processing=BreachProcessing.VICTIM_THEN_PERPETRATOR, log_file_name="", log_to_screen: bool = False, log_file_level=logging.DEBUG, log_screen_level=logging.ERROR, mechanisms: Dict[str, Dict[str, Any]] = None, awi_type: str = "negmas.situated.AgentWorldInterface", start_negotiations_immediately: bool = False, save_signed_contracts: bool = True, save_cancelled_contracts: bool = True, save_negotiations: bool = True, save_resolved_breaches: bool = True, save_unresolved_breaches: bool = True, name=None, ): """ Args: bulletin_board: n_steps: Total simulation time in steps time_limit: Real-time limit on the simulation negotiation_speed: The number of negotiation steps per simulation step. None means infinite neg_n_steps: Maximum number of steps allowed for a negotiation. neg_step_time_limit: Time limit for single step of the negotiation protocol. neg_time_limit: Real-time limit on each single negotiation name: Name of the simulator """ super().__init__() self.log_file_name = log_file_name self.log_file_level = log_file_level self.log_screen_level = log_screen_level self.log_to_screen = log_to_screen self.logger = create_loggers( file_name=log_file_name, module_name=None, screen_level=log_screen_level if log_to_screen else None, file_level=log_file_level, app_wide_log_file=True, ) self.bulletin_board: BulletinBoard = bulletin_board self.set_bulletin_board(bulletin_board=bulletin_board) self._negotiations: Dict[str, NegotiationInfo] = {} self.unsigned_contracts: Dict[int, Set[Contract]] = defaultdict(set) self.breach_processing = breach_processing self.n_steps = n_steps self.save_signed_contracts = save_signed_contracts self.save_cancelled_contracts = save_cancelled_contracts self.save_negotiations = save_negotiations self.save_resolved_breaches = save_resolved_breaches self.save_unresolved_breaches = save_unresolved_breaches self.current_step = 0 self.negotiation_speed = negotiation_speed self.default_signing_delay = default_signing_delay self.time_limit = time_limit self.neg_n_steps = neg_n_steps self.neg_time_limit = neg_time_limit self.neg_step_time_limit = neg_step_time_limit self._entities: Dict[int, Set[Entity]] = defaultdict(set) self._negotiations: Dict[str, NegotiationInfo] = {} self._start_time = -1 if isinstance(mechanisms, Collection) and not isinstance(mechanisms, dict): mechanisms = dict(zip(mechanisms, [dict()] * len(mechanisms))) self.mechanisms: Optional[Dict[str, Dict[str, Any]]] = mechanisms self.awi_type = get_class(awi_type, scope=globals()) self.name = ( name if name is not None else unique_name(base=self.__class__.__name__, add_time=True, rand_digits=5) ) self._stats: Dict[str, List[Any]] = defaultdict(list) self.__n_negotiations = 0 self.__n_contracts_signed = 0 self.__n_contracts_concluded = 0 self.__n_contracts_cancelled = 0 self._saved_contracts: Dict[str, Dict[str, Any]] = {} self._saved_negotiations: Dict[str, Dict[str, Any]] = {} self._saved_breaches: Dict[str, Dict[str, Any]] = {} self.agents: Dict[str, Agent] = {} self.immediate_negotiations = start_negotiations_immediately self.loginfo(f"{self.name}: World Created") def loginfo(self, s: str) -> None: """logs info-level information Args: s (str): The string to log """ self.logger.info(f"{self._log_header()}: " + s.strip()) def logdebug(self, s) -> None: """logs debug-level information Args: s (str): The string to log """ self.logger.debug(f"{self._log_header()}: " + s.strip()) def logwarning(self, s) -> None: """logs warning-level information Args: s (str): The string to log """ self.logger.warning(f"{self._log_header()}: " + s.strip()) def logerror(self, s) -> None: """logs error-level information Args: s (str): The string to log """ self.logger.error(f"{self._log_header()}: " + s.strip()) def set_bulletin_board(self, bulletin_board): self.bulletin_board = ( bulletin_board if bulletin_board is not None else BulletinBoard() ) self.bulletin_board.add_section("breaches") self.bulletin_board.add_section("stats") self.bulletin_board.add_section("settings") @property def time(self) -> Optional[float]: """Elapsed time since mechanism started in seconds. None if the mechanism did not start running""" if self._start_time is None: return None return time.monotonic() - self._start_time @property def remaining_time(self) -> Optional[float]: """Returns remaining time in seconds. None if no time limit is given.""" if self.time_limit is None: return None limit = self.time_limit - (time.monotonic() - self._start_time) if limit < 0.0: return 0.0 return limit @property def relative_time(self) -> float: """Returns a number between ``0`` and ``1`` indicating elapsed relative time or steps.""" if self.time_limit is None and self.n_steps is None: return 0.0 relative_step = ( (self.current_step + 1) / self.n_steps if self.n_steps is not None else np.nan ) relative_time = ( self.time / self.time_limit if self.time_limit is not None else np.nan ) return max([relative_step, relative_time]) @property def remaining_steps(self) -> Optional[int]: """Returns the remaining number of steps until the end of the mechanism run. None if unlimited""" if self.n_steps is None: return None return self.n_steps - self.current_step def _register_breach(self, breach: Breach) -> None: # we do not report breachs with no victims if breach.victims is None or len(breach.victims) < 1: return self.bulletin_board.record( section="breaches", key=breach.id, value=self._breach_record(breach) ) @property def saved_negotiations(self) -> List[Dict[str, Any]]: return list(self._saved_negotiations.values()) @property def stats(self) -> Dict[str, Any]: return self._stats def step(self) -> bool: """A single simulation step""" if self.current_step >= self.n_steps: self.logerror( f"Asked to step after the simulation ({self.n_steps}). Will just ignore this" ) return False self.loginfo( f"{len(self._negotiations)} Negotiations/{len(self._entities)} _entities" ) def _run_negotiations(n_steps: Optional[int] = None): """ Runs all bending negotiations """ mechanisms = list( (k, _.mechanism) for k, _ in self._negotiations.items() if _ is not None ) current_step = 0 while len(mechanisms) > 0: random.shuffle(mechanisms) for puuid, mechanism in mechanisms: result = mechanism.step() agreement, is_broken = result.agreement, result.broken if agreement is not None or is_broken: # or not mechanism.running: negotiation = self._negotiations.get(puuid, None) if agreement is None: self._register_failed_negotiation( mechanism.ami, negotiation ) else: self._register_contract(mechanism.ami, negotiation) if negotiation: self._negotiations.pop(mechanism.uuid, None) mechanisms = list( (k, _.mechanism) for k, _ in self._negotiations.items() if _ is not None ) current_step += 1 if n_steps is not None and current_step >= n_steps: break # initialize stats # ---------------- n_new_contract_executions = 0 n_new_breaches = 0 n_cancelled = 0 activity_level = 0 self._pre_step_stats() self._stats["n_registered_negotiations_before"].append(len(self._negotiations)) # sign contacts that are to be signed in this step # ------------------------------------------------ # this is done first to allow these contracts to be executed immediately unsigned = self.unsigned_contracts.get(self.current_step, None) signed = [] cancelled = [] if unsigned: for contract in unsigned: rejectors = self._sign_contract(contract=contract) if rejectors is not None and len(rejectors) == 0: signed.append(contract) else: cancelled.append(contract) for contract in signed: self.on_contract_signed(contract=contract) for contract in cancelled: self.on_contract_cancelled(contract=contract) # run all negotiations before the simulation step if that is the meeting strategy # -------------------------------------------------------------------------------- if self.negotiation_speed is None: _run_negotiations() # Step all entities in the world once: # ------------------------------------ # note that entities are simulated in the partial-order specified by their priority value tasks: List[Entity] = [] for priority in sorted(self._entities.keys()): tasks += [_ for _ in self._entities[priority]] for task in tasks: task.step_() # execute contracts that are executable at this step # -------------------------------------------------- current_contracts = [ _ for _ in self._get_executable_contracts() if _.nullified_at is None ] if len(current_contracts) > 0: # remove expired contracts executed = set() current_contracts = self._contract_execution_order(current_contracts) breached_contracts = [] something_executed = True while something_executed: something_executed = False for contract in current_contracts: contract_breaches = self._execute_contract(contract) if len(contract_breaches) < 1: self._saved_contracts[contract.id]["executed"] = True self._saved_contracts[contract.id]["breaches"] = "" executed.add(contract) n_new_contract_executions += 1 activity_level += self._contract_size(contract) # something_executed = True # @todo I am disabling this for now as this approach may result in multiple loans else: self._saved_contracts[contract.id]["executed"] = False self._saved_contracts[contract.id]["breaches"] = "; ".join( str(_) for _ in current_contracts ) breached_contracts.append((contract, contract_breaches)) for b in contract_breaches: self._saved_breaches[b.id] = b.as_dict() current_contracts = [_[0] for _ in breached_contracts] for contract, contract_breaches in breached_contracts: resolution = self._process_breach(contract, list(contract_breaches)) n_new_breaches += 1 - int(resolution is not None) self._complete_contract_execution( contract, list(contract_breaches), resolution ) self._delete_executed_contracts() # note that all contracts even breached ones are to be deleted # World Simulation Step: # ---------------------- # The world manager should execute a single step of simulation in this function. It may lead to new negotiations self._simulation_step() # do one step of all negotiations if that is specified as the meeting strategy if self.negotiation_speed is not None: _run_negotiations(n_steps=self.negotiation_speed) # remove all negotiations that are completed # ------------------------------------------ completed = list( k for k, _ in self._negotiations.items() if _ is not None and _.mechanism.completed ) for key in completed: self._negotiations.pop(key, None) # update stats # ------------ n_total_contracts = n_new_contract_executions + n_new_breaches self._stats["n_contracts_executed"].append(n_new_contract_executions) self._stats["n_contracts_cancelled"].append(self.__n_contracts_cancelled) self._stats["n_breaches"].append(n_new_breaches) self._stats["breach_level"].append( n_new_breaches / n_total_contracts if n_total_contracts > 0 else np.nan ) self._stats["n_contracts_signed"].append(self.__n_contracts_signed) self._stats["n_contracts_concluded"].append(self.__n_contracts_concluded) self._stats["n_negotiations"].append(self.__n_negotiations) self._stats["n_registered_negotiations_after"].append(len(self._negotiations)) self._stats["activity_level"].append(activity_level) self._post_step_stats() self.__n_negotiations = 0 self.__n_contracts_signed = 0 self.__n_contracts_concluded = 0 self.__n_contracts_cancelled = 0 self.current_step += 1 # always indicate that the simulation is to continue return True @property def saved_breaches(self) -> List[Dict[str, Any]]: return list(self._saved_breaches.values()) @property def resolved_breaches(self) -> List[Dict[str, Any]]: return list(_ for _ in self._saved_breaches.values() if _["resolved"]) @property def unresolved_breaches(self) -> List[Dict[str, Any]]: return list(_ for _ in self._saved_breaches.values() if not _["resolved"]) def run(self): """Runs the simulation until it ends""" self._start_time = time.monotonic() for _ in range(self.n_steps): if ( self.time_limit is not None and (time.monotonic() - self._start_time) >= self.time_limit ): break if not self.step(): break def register(self, x: "Entity", simulation_priority: int = 0): """ Registers an entity in the world so it can be looked up by name. Should not be called directly Args: x: The entity to be registered simulation_priority: The simulation periority. Entities with lower periorities will be stepped first during Returns: """ # super().register(x) # If we inherit from session, we can do that but it is not needed as we do not do string # based resolution now if hasattr(x, "_world"): x._world = self if hasattr(x, "step_"): self._entities[simulation_priority].add(x) def join(self, x: "Agent", simulation_priority: int = 0): """Add an agent to the world. Args: x: The agent to be registered simulation_priority: The simulation periority. Entities with lower periorities will be stepped first during Returns: """ self.loginfo(f"{x.name} joined") self.register(x, simulation_priority=simulation_priority) self.agents[x.id] = x x.awi = self.awi_type(self, x) def _register_negotiation( self, mechanism_name, mechanism_params, roles, caller, partners, annotation, issues, req_id, run_to_completion=False, ) -> Optional[NegotiationInfo]: """Registers a negotiation and returns the list of rejectors if any or None""" factory = MechanismFactory( world=self, mechanism_name=mechanism_name, mechanism_params=mechanism_params, issues=issues, req_id=req_id, caller=caller, partners=partners, roles=roles, annotation=annotation, neg_n_steps=self.neg_n_steps, neg_time_limit=self.neg_time_limit, neg_step_time_limit=self.neg_step_time_limit, ) neg = factory.init() if neg is None: return None if neg.mechanism is None: return neg self.__n_negotiations += 1 if run_to_completion: pass else: self._negotiations[neg.mechanism.uuid] = neg if self.immediate_negotiations: mechanism = neg.mechanism puuid = mechanism.uuid result = mechanism.step() agreement, is_broken = result.agreement, result.broken if agreement is not None or is_broken: # or not mechanism.running: negotiation = self._negotiations.get(puuid, None) if agreement is None: self._register_failed_negotiation(mechanism.ami, negotiation) else: self._register_contract(mechanism.ami, negotiation) if negotiation: self._negotiations.pop(mechanism.uuid, None) # self.loginfo( # f'{caller.id} request was accepted') return neg def request_negotiation_about( self, req_id: str, caller: "Agent", issues: List[Issue], partners: List["Agent"], roles: List[str] = None, annotation: Optional[Dict[str, Any]] = None, mechanism_name: str = None, mechanism_params: Dict[str, Any] = None, ) -> bool: """ Requests to start a negotiation with some other agents Args: req_id: An ID For the request that is unique to the caller caller: The agent requesting the negotiation partners: The list of partners that the agent wants to negotiate with. Roles will be determined by these agents. issues: Negotiation issues annotation: Extra information to be passed to the `partners` when asking them to join the negotiation partners: A list of partners to participate in the negotiation roles: The roles of different partners. If None then each role for each partner will be None mechanism_name: Name of the mechanism to use. It must be one of the mechanism_names that are supported by the `World` or None which means that the `World` should select the mechanism. If None, then `roles` and `my_role` must also be None mechanism_params: A dict of parameters used to initialize the mechanism object Returns: None. The caller will be informed by a callback function `on_neg_request_accepted` or `on_neg_request_rejected` about the status of the negotiation. """ self.loginfo( f"{caller.name} requested " f"{mechanism_name}[{mechanism_params}] with {[_.name for _ in partners]} (ID {req_id})" ) neg = self._register_negotiation( mechanism_name=mechanism_name, mechanism_params=mechanism_params, roles=roles, caller=caller, partners=partners, annotation=annotation, issues=issues, req_id=req_id, run_to_completion=False, ) success = neg is not None and neg.mechanism is not None return success def run_negotiation( self, caller: "Agent", issues: Collection[Issue], partners: Collection["Agent"], roles: Collection[str] = None, annotation: Optional[Dict[str, Any]] = None, mechanism_name: str = None, mechanism_params: Dict[str, Any] = None, ) -> Optional[Tuple[Contract, AgentMechanismInterface]]: """ Requests to start a negotiation with some other agents Args: caller: The agent requesting the negotiation partners: The list of partners that the agent wants to negotiate with. Roles will be determined by these agents. issues: Negotiation issues annotation: Extra information to be passed to the `partners` when asking them to join the negotiation partners: A list of partners to participate in the negotiation roles: The roles of different partners. If None then each role for each partner will be None mechanism_name: Name of the mechanism to use. It must be one of the mechanism_names that are supported by the `World` or None which means that the `World` should select the mechanism. If None, then `roles` and `my_role` must also be None mechanism_params: A dict of parameters used to initialize the mechanism object Returns: Contract: The agreed upon contract if negotiation was successful otherwise, None. """ self.loginfo( f"{caller.name} requested immediate negotiation " f"{mechanism_name}[{mechanism_params}] with {[_.name for _ in partners]}" ) neg = self._register_negotiation( mechanism_name=mechanism_name, mechanism_params=mechanism_params, roles=roles, caller=caller, partners=partners, annotation=annotation, issues=issues, req_id=None, run_to_completion=True, ) if neg and neg.mechanism: mechanism = neg.mechanism mechanism.run() if mechanism.agreement is None: contract = None self._register_failed_negotiation( mechanism=mechanism.ami, negotiation=neg ) else: contract = self._register_contract( mechanism=mechanism.ami, negotiation=neg, force_signature_now=True ) return contract, mechanism.ami return None def _log_header(self): if self.time is None: return f"{self.name} (not started)" return f"{self.current_step}/{self.n_steps} [{self.relative_time:0.2%}]" def _register_contract( self, mechanism, negotiation, force_signature_now=False ) -> Optional[Contract]: partners = negotiation.partners if self.save_negotiations: _stats = { "final_status": "failed", "partners": [_.id for _ in partners], "partner_types": [_.__class__.__name__ for _ in partners], "ended_at": self.current_step, "requested_at": negotiation.requested_at, "mechanism_type": mechanism.__class__.__name__, } _stats.update(mechanism.state.__dict__) self._saved_negotiations[mechanism.id] = _stats if mechanism.state.agreement is None or negotiation is None: return None signed_at = None if force_signature_now: signing_delay = 0 else: signing_delay = mechanism.state.agreement.get( "signing_delay", self.default_signing_delay ) contract = Contract( partners=list(_.id for _ in partners), annotation=negotiation.annotation, issues=negotiation.issues, agreement=mechanism.state.agreement, concluded_at=self.current_step, to_be_signed_at=self.current_step + signing_delay, signed_at=signed_at, mechanism_state=mechanism.state, ) if not force_signature_now: self.on_contract_concluded( contract, to_be_signed_at=self.current_step + signing_delay ) for partner in partners: partner.on_negotiation_success_(contract=contract, mechanism=mechanism) if signing_delay == 0: rejectors = self._sign_contract(contract) signed = rejectors is not None and len(rejectors) == 0 if signed and not force_signature_now: self.on_contract_signed(contract=contract) sign_status = ( "signed" if signed else f"cancelled by {rejectors if rejectors is not None else 'error!!'}" ) else: sign_status = f"to be signed at {contract.to_be_signed_at}" self.on_contract_cancelled(contract=contract) if negotiation.annotation is not None: annot_ = dict( zip( negotiation.annotation.keys(), (str(_) for _ in negotiation.annotation.values()), ) ) else: annot_ = "" self.logdebug( f'Contract<{"immediate-signature-forced" if force_signature_now else ""}> [{sign_status}]: {[_.name for _ in partners]}' f" > {str(mechanism.state.agreement)} on annotation {annot_}" ) return contract def _register_failed_negotiation(self, mechanism, negotiation) -> None: partners = negotiation.partners mechanism_state = mechanism.state annotation = negotiation.annotation if self.save_negotiations: _stats = { "final_status": "failed", "partners": [_.id for _ in partners], "partner_types": [_.__class__.__name__ for _ in partners], "ended_at": self.current_step, "requested_at": negotiation.requested_at, "mechanism_type": mechanism.__class__.__name__, } _stats.update(mechanism.state.__dict__) self._saved_negotiations[mechanism.id] = _stats for partner in partners: partner.on_negotiation_failure_( partners=[_.id for _ in partners], annotation=annotation, mechanism=mechanism, state=mechanism_state, ) self.logdebug( f"Negotiation failure between {[_.name for _ in partners]}" f" on annotation {negotiation.annotation} " ) def _sign_contract(self, contract: Contract) -> Optional[List[str]]: """Called to sign a contract and returns whether or not it was signed""" # if self._contract_finalization_time(contract) >= self.n_steps or \ # self._contract_execution_time(contract) < self.current_step: # return None partners = [self.agents[_] for _ in contract.partners] signatures = list( zip( partners, (partner.sign_contract(contract=contract) for partner in partners), ) ) rejectors = [partner for partner, signature in signatures if signature is None] if len(rejectors) == 0: contract.signatures = [ Signature(id=a.id, signature=s) for a, s in signatures ] contract.signed_at = self.current_step for partner in partners: partner.on_contract_signed_(contract=contract) else: # if self.save_cancelled_contracts: record = self._contract_record(contract) record["signed"] = False record["executed"] = None record["breaches"] = "" self._saved_contracts[contract.id] = record # else: # self._saved_contracts.pop(contract.id, None) for partner in partners: partner.on_contract_cancelled_( contract=contract, rejectors=[_.id for _ in rejectors] ) return [_.id for _ in rejectors] def on_contract_signed(self, contract: Contract) -> None: """Called to add a contract to the existing set of contract after it is signed Args: contract: The contract to add Remarks: - By default this function just adds the contract to the set of contracts maintaned by the world. - You should ALWAYS call this function when overriding it. """ self.__n_contracts_signed += 1 self.unsigned_contracts[self.current_step].remove(contract) record = self._contract_record(contract) if self.save_signed_contracts: record["signed"] = True record["executed"] = None record["breaches"] = "" self._saved_contracts[contract.id] = record else: self._saved_contracts.pop(contract.id, None) def on_contract_cancelled(self, contract): """Called whenever a concluded contract is not signed (cancelled) Args: contract: The contract to add Remarks: - By default this function just adds the contract to the set of contracts maintaned by the world. - You should ALWAYS call this function when overriding it. """ self.__n_contracts_cancelled += 1 unsigned = self.unsigned_contracts.get(self.current_step, None) if unsigned is None: return try: unsigned.remove(contract) except KeyError: pass @property def saved_contracts(self) -> List[Dict[str, Any]]: return list(self._saved_contracts.values()) @property def signed_contracts(self) -> List[Dict[str, Any]]: return list(_ for _ in self._saved_contracts.values() if _["signed"]) @property def cancelled_contracts(self) -> List[Dict[str, Any]]: return list(_ for _ in self._saved_contracts.values() if not _["signed"]) def on_contract_concluded(self, contract: Contract, to_be_signed_at: int) -> None: """Called to add a contract to the existing set of contract after it is signed Args: contract: The contract to add to_be_signed_at: The timestep at which the contract is to be signed Remarks: - By default this function just adds the contract to the set of contracts maintaned by the world. - You should ALWAYS call this function when overriding it. """ self.__n_contracts_concluded += 1 self.unsigned_contracts[to_be_signed_at].add(contract) # self.saved_contracts.append(self._contract_record(contract)) def save_config(self, file_name: str): """ Saves the config of the world as a yaml file Args: file_name: Name of file to save the config to Returns: """ with open(file_name, "w") as file: yaml.safe_dump(self.__dict__, file) @abstractmethod def _delete_executed_contracts(self) -> None: """Called after processing executable contracts at every simulation step to delete processed contracts""" @abstractmethod def _get_executable_contracts(self) -> Collection[Contract]: """Called at every time-step to get the contracts that are `executable` at this point of the simulation""" @abstractmethod def _post_step_stats(self): """Called at the end of the simulation step to update all stats""" pass @abstractmethod def _pre_step_stats(self): """Called at the beginning of the simulation step to prepare stats or update them""" pass @abstractmethod def _contract_execution_order( self, contracts: Collection[Contract] ) -> Collection[Contract]: """Orders the contracts in a specific time-step that are about to be executed""" @abstractmethod def _contract_record(self, contract: Contract) -> Dict[str, Any]: """Converts a contract to a record suitable for permanent storage""" @abstractmethod def _breach_record(self, breach: Breach) -> Dict[str, Any]: """Converts a breach to a record suitable for storage during the simulation""" @abstractmethod def _execute_contract(self, contract: Contract) -> Set[Breach]: """ Tries to execute the contract Args: contract: Returns: Set[Breach]: The set of breaches committed if any. If there are no breaches return an empty set Remarks: - You must call super() implementation of this method before doing anything """ self.loginfo(f"Executing {str(contract)}") return set() @abstractmethod def _complete_contract_execution( self, contract: Contract, breaches: List[Breach], resolution: Contract ) -> None: """ Called after breach resolution is completed for contracts for which some potential breaches occurred. Args: contract: The contract considered. breaches: The list of potential breaches that was generated by `_execute_contract`. resolution: The agreed upon resolution Returns: """ def _process_breach( self, contract: Contract, breaches: List[Breach], force_immediate_signing=True ) -> Optional[Contract]: new_contract = None # calculate total breach level total_breach_levels = defaultdict(int) for breach in breaches: total_breach_levels[breach.perpetrator] += breach.level # give agents the chance to set renegotiation agenda in ascending order of their total breach levels for agent_name, _ in sorted( zip(total_breach_levels.keys(), total_breach_levels.values()), key=lambda x: x[1], ): agent = self.agents[agent_name] agenda = agent.set_renegotiation_agenda( contract=contract, breaches=breaches ) if agenda is None: continue negotiators = [] for partner in contract.partners: negotiator = self.agents[partner].respond_to_renegotiation_request( contract=contract, breaches=breaches, agenda=agenda ) if negotiator is None: break negotiators.append(negotiator) else: # everyone accepted this renegotiation results = self.run_negotiation( caller=agent, issues=agenda.issues, partners=[self.agents[_] for _ in contract.partners], ) if results is not None: new_contract, mechanism = results self._register_contract( mechanism=mechanism, negotiation=None, force_signature_now=force_immediate_signing, ) break if new_contract is not None: for breach in breaches: if self.save_resolved_breaches: self._saved_breaches[breach.id]["resolved"] = True else: self._saved_breaches.pop(breach.id, None) return new_contract for breach in breaches: if self.save_unresolved_breaches: self._saved_breaches[breach.id]["resolved"] = False else: self._saved_breaches.pop(breach.id, None) self._register_breach(breach) return None @abstractmethod def execute( self, action: Action, agent: "Agent", callback: Callable = None ) -> bool: """Executes the given action by the given agent""" @abstractmethod def get_private_state(self, agent: "Agent") -> dict: """Reads the private state of the given agent""" @abstractmethod def _simulation_step(self): """A single step of the simulation if any""" @abstractmethod def _contract_finalization_time(self, contract: Contract) -> int: """ Returns the time at which the given contract will complete execution Args: contract: Returns: """ @abstractmethod def _contract_execution_time(self, contract: Contract) -> int: """ Returns the time at which the given contract will start execution Args: contract: Returns: """ @abstractmethod def _contract_size(self, contract: Contract) -> float: """ Returns an estimation of the **activity level** associated with this contract. Higher is better Args: contract: Returns: """ RunningNegotiationInfo = namedtuple( "RunningNegotiationInfo", ["negotiator", "annotation", "uuid", "extra"] ) """Keeps track of running negotiations for an agent""" NegotiationRequestInfo = namedtuple( "NegotiationRequestInfo", ["partners", "issues", "annotation", "uuid", "negotiator", "extra"], ) """Keeps track to negotiation requests that an agent sent""" class Agent(Entity, EventSink, ConfigReader, Notifier, ABC): """Base class for all agents that can run within a `World` and engage in situated negotiations""" def __getstate__(self): return self.name, self.awi def __setstate__(self, state): name, awi = state super().__init__(name=name) self._awi = awi def __init__(self, name: str = None): super().__init__(name=name) self._running_negotiations: Dict[str, RunningNegotiationInfo] = {} self._requested_negotiations: Dict[str, NegotiationRequestInfo] = {} self.contracts: List[Contract] = [] self._unsigned_contracts: Set[Contract] = set() self._awi: AgentWorldInterface = None @property def unsigned_contracts(self) -> List[Contract]: """ All contracts that are not yet signed. """ return list(self._unsigned_contracts) @property def requested_negotiations(self) -> List[NegotiationRequestInfo]: """The negotiations currently requested by the agent. Returns: A list of negotiation request information objects (`NegotiationRequestInfo`) """ return list(self._requested_negotiations.values()) @property def running_negotiations(self) -> List[RunningNegotiationInfo]: """The negotiations currently requested by the agent. Returns: A list of negotiation information objects (`RunningNegotiationInfo`) """ return list(self._running_negotiations.values()) @property def awi(self) -> AgentWorldInterface: """Gets the Agent-world interface.""" return self._awi @awi.setter def awi(self, awi: AgentWorldInterface): """Sets the Agent-world interface. Should only be called by the world.""" self._awi = awi def _add_negotiation_request_info( self, issues: List[Issue], partners: List[str], annotation: Optional[Dict[str, Any]], negotiator: Optional[Negotiator], extra: Optional[Dict[str, Any]], ) -> str: """ Creates a new `NegotiationRequestInfo` record and returns its ID Args: issues: negotiation issues partners: partners annotation: annotation negotiator: the negotiator to use extra: any extra information Returns: A unique identifier for this negotiation info structure """ req_id = str(uuid.uuid4()) self._requested_negotiations[req_id] = NegotiationRequestInfo( issues=issues, partners=partners, annotation=annotation, negotiator=negotiator, extra=extra, uuid=req_id, ) return req_id def _request_negotiation( self, issues: List[Issue], partners: List[str], roles: List[str] = None, annotation: Optional[Dict[str, Any]] = None, mechanism_name: str = None, mechanism_params: Dict[str, Any] = None, negotiator: Negotiator = None, extra: Optional[Dict[str, Any]] = None, ) -> bool: """ Requests to start a negotiation with some other agents Args: issues: Negotiation issues annotation: Extra information to be passed to the `partners` when asking them to join the negotiation partners: A list of partners to participate in the negotiation roles: The roles of different partners. If None then each role for each partner will be None mechanism_name: Name of the mechanism to use. It must be one of the mechanism_names that are supported by the `World` or None which means that the `World` should select the mechanism. If None, then `roles` and `my_role` must also be None mechanism_params: A dict of parameters used to initialize the mechanism object negotiator: My negotiator to use in this negotiation. Can be none extra: Any extra information I would like to keep to myself for this negotiation Returns: List["Agent"] the list of partners who rejected the negotiation if any. If None then the negotiation was accepted. If empty then the negotiation was not started from the world manager Remarks: - The function will create a request ID that will be used in callbacks `on_neg_request_accepted` and `on_neg_request_rejected`. - This function is a private function as the name implies and should not be called directly in any world. - World designers extending this class for their worlds, should define a way to start negotiations that calls this function. The simplest way is to just define a `request_negotiation` function that calls this private version directly with the same parameters. """ req_id = self._add_negotiation_request_info( issues=issues, partners=partners, annotation=annotation, negotiator=negotiator, extra=extra, ) return self.awi.request_negotiation_about( issues=issues, partners=partners, req_id=req_id, roles=roles, annotation=annotation, mechanism_name=mechanism_name, mechanism_params=mechanism_params, ) def init_(self): """Called to initialize the agent **after** the world is initialized. the AWI is accessible at this point.""" self.init() def step_(self): """Called at every time-step. This function is called directly by the world.""" self.step() def on_event(self, event: Event, sender: EventSource): if not isinstance(sender, Mechanism) and not isinstance(sender, Mechanism): raise ValueError( f"Sender of the negotiation end event is of type {sender.__class__.__name__} " f"not Mechanism!!" ) if event.type == "negotiation_end": # will be sent by the World once a negotiation in which this agent is involved is completed l mechanism_id = sender.id self._running_negotiations.pop(mechanism_id, None) # ------------------------------------------------------------------ # EVENT CALLBACKS (Called by the `World` when certain events happen) # ------------------------------------------------------------------ def on_neg_request_rejected_(self, req_id: str, by: Optional[List[str]]): """Called when a requested negotiation is rejected Args: req_id: The request ID passed to _request_negotiation by: A list of agents that refused to participate or None if the failure was for another reason """ self.on_neg_request_rejected(req_id, by) self._requested_negotiations.pop(req_id, None) def on_neg_request_accepted_(self, req_id: str, mechanism: AgentMechanismInterface): """Called when a requested negotiation is accepted""" self.on_neg_request_accepted(req_id, mechanism) neg = self._requested_negotiations[req_id].negotiator annotation = self._requested_negotiations[req_id].annotation self._running_negotiations[mechanism.id] = RunningNegotiationInfo( extra=self._requested_negotiations[req_id].extra, negotiator=neg, annotation=annotation, uuid=req_id, ) self._requested_negotiations.pop(req_id, None) def on_negotiation_failure_( self, partners: List[str], annotation: Dict[str, Any], mechanism: AgentMechanismInterface, state: MechanismState, ) -> None: """Called whenever a negotiation ends without agreement""" self.on_negotiation_failure(partners, annotation, mechanism, state) self._running_negotiations.pop(mechanism.id, None) def on_negotiation_success_( self, contract: Contract, mechanism: AgentMechanismInterface ) -> None: """Called whenever a negotiation ends with agreement""" self.on_negotiation_success(contract, mechanism) self._unsigned_contracts.add(contract) self._running_negotiations.pop(mechanism.id, None) def on_contract_signed_(self, contract: Contract) -> None: """Called whenever a contract is signed by all partners""" self.on_contract_signed(contract) if contract in self._unsigned_contracts: self._unsigned_contracts.remove(contract) self.contracts.append(contract) def on_contract_cancelled_(self, contract: Contract, rejectors: List[str]) -> None: """Called whenever at least a partner did not sign the contract""" self.on_contract_cancelled(contract, rejectors) if contract in self._unsigned_contracts: self._unsigned_contracts.remove(contract) def respond_to_negotiation_request_( self, initiator: str, partners: List[str], issues: List[Issue], annotation: Dict[str, Any], mechanism: AgentMechanismInterface, role: Optional[str], req_id: Optional[str], ) -> Optional[Negotiator]: """Called when a negotiation request is received""" if req_id is not None: info = self._requested_negotiations.get(req_id, None) if info and info.negotiator is not None: return info.negotiator return self._respond_to_negotiation_request( initiator=initiator, partners=partners, issues=issues, annotation=annotation, mechanism=mechanism, role=role, req_id=req_id, ) def __str__(self): return f"{self.name}" __repr__ = __str__ @abstractmethod def step(self): """Called by the simulator at every simulation step""" @abstractmethod def init(self): """Called to initialize the agent **after** the world is initialized. the AWI is accessible at this point.""" @abstractmethod def _respond_to_negotiation_request( self, initiator: str, partners: List[str], issues: List[Issue], annotation: Dict[str, Any], mechanism: AgentMechanismInterface, role: Optional[str], req_id: Optional[str], ) -> Optional[Negotiator]: """ Called by the mechanism to ask for joining a negotiation. The agent can refuse by returning a None Args: initiator: The ID of the agent that initiated the negotiation request partners: The partner list (will include this agent) issues: The list of issues annotation: Any annotation specific to this negotiation. mechanism: The mechanism that started the negotiation role: The role of this agent in the negotiation req_id: The req_id passed to the AWI when starting the negotiation (only to the initiator). Returns: None to refuse the negotiation or a `Negotiator` object appropriate to the given mechanism to accept it. Remarks: - It is expected that world designers will introduce a better way to respond and override this function to call it """ @abstractmethod def on_neg_request_rejected(self, req_id: str, by: Optional[List[str]]): """Called when a requested negotiation is rejected Args: req_id: The request ID passed to _request_negotiation by: A list of agents that refused to participate or None if the failure was for another reason """ @abstractmethod def on_neg_request_accepted(self, req_id: str, mechanism: AgentMechanismInterface): """Called when a requested negotiation is accepted""" @abstractmethod def on_negotiation_failure( self, partners: List[str], annotation: Dict[str, Any], mechanism: AgentMechanismInterface, state: MechanismState, ) -> None: """Called whenever a negotiation ends without agreement""" @abstractmethod def on_negotiation_success( self, contract: Contract, mechanism: AgentMechanismInterface ) -> None: """Called whenever a negotiation ends with agreement""" @abstractmethod def on_contract_signed(self, contract: Contract) -> None: """Called whenever a contract is signed by all partners""" @abstractmethod def on_contract_cancelled(self, contract: Contract, rejectors: List[str]) -> None: """Called whenever at least a partner did not sign the contract""" @abstractmethod def set_renegotiation_agenda( self, contract: Contract, breaches: List[Breach] ) -> Optional[RenegotiationRequest]: """ Received by partners in ascending order of their total breach levels in order to set the renegotiation agenda when contract execution fails Args: contract: The contract being breached breaches: All breaches on `contract` Returns: Renegotiation agenda (issues to negotiate about to avoid reporting the breaches). """ @abstractmethod def respond_to_renegotiation_request( self, contract: Contract, breaches: List[Breach], agenda: RenegotiationRequest ) -> Optional[Negotiator]: """ Called to respond to a renegotiation request Args: agenda: contract: breaches: Returns: """ @abstractmethod def sign_contract(self, contract: Contract) -> Optional[str]: """Called after the signing delay from contract conclusion to sign the contract. Contracts become binding only after they are signed.""" return self.id def save_stats(world: World, log_dir: str, params: Dict[str, Any] = None): """ Saves the statistics of a world run. Args: world: log_dir: params: Returns: """ log_dir = Path(log_dir) os.makedirs(log_dir, exist_ok=True) dump(params, log_dir / "params") dump(world.stats, log_dir / "stats") try: data = pd.DataFrame.from_dict(world.stats) data.to_csv(str(log_dir / "stats.csv"), index_label="index") except: pass if world.save_negotiations: if len(world.saved_negotiations) > 0: data = pd.DataFrame(world.saved_negotiations) data.to_csv(str(log_dir / "negotiations.csv"), index_label="index") else: with open(log_dir / "negotiations.csv", "w") as f: f.write("") if world.save_resolved_breaches or world.save_unresolved_breaches: if len(world.saved_breaches) > 0: data = pd.DataFrame(world.saved_breaches) data.to_csv(str(log_dir / "breaches.csv"), index_label="index") else: with open(log_dir / "breaches.csv", "w") as f: f.write("") if world.save_signed_contracts: if len(world.signed_contracts) > 0: data = pd.DataFrame(world.signed_contracts) data = data.sort_values(["delivery_time"]) data = data.loc[ :, [ "seller_type", "buyer_type", "seller_name", "buyer_name", "delivery_time", "unit_price", "quantity", "product_name", "n_neg_steps", "signed_at", "concluded_at", "cfp", ], ] data.to_csv(str(log_dir / "signed_contracts.csv"), index_label="index") else: with open(log_dir / "signed_contracts.csv", "w") as f: f.write("") if world.save_cancelled_contracts: if len(world.cancelled_contracts) > 0: data = pd.DataFrame(world.cancelled_contracts) data = data.sort_values(["delivery_time"]) data = data.loc[ :, [ "seller_type", "buyer_type", "seller_name", "buyer_name", "delivery_time", "unit_price", "quantity", "product_name", "n_neg_steps", "signed_at", "concluded_at", "cfp", ], ] data.to_csv(str(log_dir / "cancelled_contracts.csv"), index_label="index") else: with open(log_dir / "cancelled_contracts.csv", "w") as f: f.write("") if world.save_signed_contracts or world.save_cancelled_contracts: if len(world.saved_contracts) > 0: data = pd.DataFrame(world.saved_contracts) data = data.sort_values(["delivery_time"]) data.to_csv(str(log_dir / "contracts_full_info.csv"), index_label="index") data = data.loc[ :, [ "seller_type", "buyer_type", "seller_name", "buyer_name", "delivery_time", "unit_price", "quantity", "product_name", "n_neg_steps", "signed_at", "concluded_at", "cfp", ], ] if world.save_signed_contracts and world.save_cancelled_contracts: data.to_csv(str(log_dir / "all_contracts.csv"), index_label="index") else: with open(log_dir / "contracts_full_info.csv", "w") as f: f.write("") if world.save_signed_contracts and world.save_cancelled_contracts: with open(log_dir / "all_contracts.csv", "w") as f: f.write("") PK!4cnegmas/tests/__init__.py"""Tests package""" PK!qqnegmas/tests/config/scml.json{ "initial_wallet_balance": 1e6, "n_steps": 1000000, "time_limit": 3000, "neg_n_steps": 100, "neg_time_limit": 180, "minimum_balance": 0.0, "interest_rate": null, "max_allowed_breach_level": null, "breach_processing": 1, "meeting_strategy": 1, "products": [ { "name": "silicon", "catalog_price": 1.0 }, { "name": "iron", "catalog_price": 0.5 }, { "name": "copper", "catalog_price": 0.25 }, { "name": "plastic", "catalog_price": 0.3 }, { "name": "minerals", "catalog_price": 6.0 }, { "name": "cpu", "catalog_price": null }, { "name": "ram", "catalog_price": null }, { "name": "timer", "catalog_price": null }, { "name": "gpu", "catalog_price": null }, { "name": "rom", "catalog_price": null }, { "name": "motherboard", "catalog_price": null }, { "name": "monitor", "catalog_price": null }, { "name": "keyboard", "catalog_price": null }, { "name": "mouse", "catalog_price": null }, { "name": "case", "catalog_price": null }, { "name": "pc", "catalog_price": null }, { "name": "phone", "catalog_price": null }, { "name": "tablet", "catalog_price": null } ], "processes": [ { "name": "make_cpu_1", "inputs": [ [ "silicon", 3, 0.0 ], [ "copper", 4, 0.0 ] ], "outputs": [ [ "cpu", 1, 1.0 ] ] }, { "name": "make_cpu_2", "inputs": [ [ "silicon", 5, 0.0 ], [ "copper", 2, 0.0 ] ], "outputs": [ [ "cpu", 1, 1.0 ] ] }, { "name": "make_ram_1", "inputs": [ [ "silicon", 2, 0.0 ], [ "copper", 5, 0.0 ], [ "iron", 1, 0.0 ] ], "outputs": [ [ "ram", 1, 1.0 ] ] }, { "name": "make_ram_2", "inputs": [ [ "silicon", 3, 0.0 ], [ "copper", 3, 0.0 ], [ "iron", 2, 0.0 ] ], "outputs": [ [ "ram", 1, 1.0 ] ] }, { "name": "make_rom_1", "inputs": [ [ "silicon", 2, 0.0 ], [ "copper", 5, 0.0 ], [ "iron", 2, 0.0 ] ], "outputs": [ [ "rom", 1, 1.0 ] ] }, { "name": "make_rom_2", "inputs": [ [ "silicon", 3, 0.0 ], [ "copper", 3, 0.0 ], [ "iron", 3, 0.0 ] ], "outputs": [ [ "rom", 1, 1.0 ] ] }, { "name": "make_monitor_1", "inputs": [ [ "silicon", 3, 0.0 ], [ "copper", 3, 0.0 ], [ "iron", 2, 0.0 ], [ "minerals", 1, 0.0 ], [ "ram", 1, 0.0 ] ], "outputs": [ [ "ram", 1, 1.0 ] ] }, { "name": "make_monitor_2", "inputs": [ [ "silicon", 5, 0.0 ], [ "copper", 1, 0.0 ], [ "minerals", 1, 0.0 ], [ "ram", 1, 0.0 ] ], "outputs": [ [ "ram", 1, 1.0 ] ] } ], "factories": [ { "max_storage": 10000, "lines": { "l1": { "name": "l1", "profiles": { "make_cpu1": { "n_steps": 5, "cost": 10 }, "make_cpu2": { "n_steps": 4, "cost": 12 } } } } } ], "consumers": [ ], "raw_material_generators": [ ], "factory_managers": null } PK!:+ negmas/tests/config/scml.yamlmax_allowed_breach_level = null PK!5>33.negmas/tests/data/10issues/10issues-domain.xml PK!%negmas/tests/data/10issues/pareto.xml 0.67824775, 1.0 0.6797583, 0.9322034 0.7583082, 0.91638416 0.7854985, 0.85423726 0.82477343, 0.82146895 0.826284, 0.7536723 0.918429, 0.7457627 0.9199396, 0.6779661 0.99848944, 0.66214687 1.0, 0.5943503PK!,!>(negmas/tests/data/10issues/profile-1.xml PK!iKا(negmas/tests/data/10issues/profile-2.xml PK!>nś8negmas/tests/data/AMPOvsCity/ampo_vs_city_ampo_space.xml PK!((8negmas/tests/data/AMPOvsCity/ampo_vs_city_city_space.xml PK!y? ? 6negmas/tests/data/AMPOvsCity/ampo_vs_city_template.xml PK!Y;I,negmas/tests/data/Laptop/Laptop-C-domain.xml PK!JJ+negmas/tests/data/Laptop/Laptop-C-prof1.xml PK!GG+negmas/tests/data/Laptop/Laptop-C-prof2.xml PK!yz&NN2negmas/tests/data/Laptop1Issue/Laptop-C-domain.xml PK!urr1negmas/tests/data/Laptop1Issue/Laptop-C-prof1.xml PK!)lss1negmas/tests/data/Laptop1Issue/Laptop-C-prof2.xml PK!sHg[ [ 0negmas/tests/data/LaptopConv/Laptop-C-domain.xml PK!V$j: : /negmas/tests/data/LaptopConv/Laptop-C-prof1.xml PK! !~; ; /negmas/tests/data/LaptopConv/Laptop-C-prof2.xml PK!fl l 2negmas/tests/data/LaptopConv1D/Laptop-C-domain.xml PK!b|KK1negmas/tests/data/LaptopConv1D/Laptop-C-prof1.xml PK!ȒLL1negmas/tests/data/LaptopConv1D/Laptop-C-prof2.xml PK!) n.negmas/tests/data/fuzzyagent/buyer_utility.xml PK!E9`/negmas/tests/data/fuzzyagent/seller_utility.xml PK!G0114negmas/tests/data/fuzzyagent/single_issue_domain.xml PK!sM_ _ Bnegmas/tests/data/scenarios/anac/y2010/EnglandZimbabwe/England.xml PK!iQnegmas/tests/data/scenarios/anac/y2010/EnglandZimbabwe/EnglandZimbabwe_domain.xml PK!G] ] Cnegmas/tests/data/scenarios/anac/y2010/EnglandZimbabwe/Zimbabwe.xml PK!QJJNnegmas/tests/data/scenarios/anac/y2010/ItexvsCypress/ItexvsCypress_Cypress.xml PK!+҂GGKnegmas/tests/data/scenarios/anac/y2010/ItexvsCypress/ItexvsCypress_Itex.xml PK!:UMnegmas/tests/data/scenarios/anac/y2010/ItexvsCypress/ItexvsCypress_domain.xml PK!Z X  =negmas/tests/data/scenarios/anac/y2010/Travel/travel_chox.xml PK!ɸ ?negmas/tests/data/scenarios/anac/y2010/Travel/travel_domain.xml PK!A7>negmas/tests/data/scenarios/anac/y2010/Travel/travel_fanny.xml PK!5>33Dnegmas/tests/data/scenarios/other/S-1NIKFRT-1/S-1NIKFRT-1-domain.xml PK!K /KK8negmas/tests/data/scenarios/other/S-1NIKFRT-1/pareto.xml 0.6061776, 1.0 0.8108108, 0.95596594 0.91795367, 0.90767044 1.0, 0.7698864PK!Ő;negmas/tests/data/scenarios/other/S-1NIKFRT-1/profile-1.xml PK!Ty;negmas/tests/data/scenarios/other/S-1NIKFRT-1/profile-2.xml PK!MW\$$negmas/tests/fixtures.pyfrom pytest import fixture from negmas.outcomes import Issue @fixture() def bissue(): return Issue(["be", "not b"], name="binary") @fixture() def hamlet(): return Issue(["val {}".format(_) for _ in range(5)], name="THE problem") @fixture() def uissue(): return Issue(["val {}".format(_) for _ in range(5)]) @fixture() def cissue(): return Issue((0.0, 1.0), name="c") @fixture() def dissue(): return Issue(10, name="d") @fixture() def sissue(): return Issue(["val {}".format(_) for _ in range(5)], name="s") @fixture() def issues(cissue, dissue, sissue): return [cissue, dissue, sissue] @fixture() def int_issues(): return Issue.generate([5], [10]) @fixture() def valid_outcome_dict(issues): outcome = {} for issue in issues: outcome[issue.name] = issue.rand() return outcome @fixture() def invalid_outcome_dict(issues): outcome = {} for issue in issues: outcome[issue.name] = issue.rand_invalid() return outcome @fixture() def valid_outcome_list(int_issues): outcome = [] for issue in int_issues: outcome.append(issue.rand()) return outcome @fixture() def invalid_outcome_list(int_issues): outcome = [] for issue in int_issues: outcome.append(issue.rand_invalid()) return outcome PK!g@B@B!negmas/tests/scml/test_factory.pyimport copy import itertools import sys from collections import defaultdict import numpy as np import pytest from pytest import fixture, mark from negmas.apps.scml import ( ManufacturingProfile, Product, Process, InputOutput, Job, RunningCommandInfo, ) from negmas.apps.scml.simulators import ( SlowFactorySimulator, FastFactorySimulator, storage_as_array, ) from negmas.apps.scml.world import Factory from negmas.apps.scml.common import NO_PRODUCTION n_lines = 5 n_levels = 4 n_products = 5 n_processes = 3 initial_wallet = 100.0 n_steps = 100 max_storage = sys.maxsize initial_storage = dict( zip(range(n_products * n_levels), range(10, 10 * (n_products * n_levels), 10)) ) @fixture(scope="module") def products(): return [ Product( id=i + l * n_levels, production_level=l, name=f"{l}_{i}", catalog_price=(i + 1) * (l + 1), expires_in=None, ) for i in range(n_products) for l in range(n_levels) ] @fixture(scope="module") def processes(): return [ Process( id=i + l * n_levels, production_level=l, name=f"p{l}_{i}", inputs={ InputOutput(product=i + (l - 1) * n_levels, quantity=3, step=0.0), InputOutput(product=i + (l - 1) * n_levels, quantity=2, step=0.0), }, outputs={ InputOutput(product=i + l * n_levels, quantity=1, step=1.0), InputOutput(product=i + l * n_levels, quantity=2, step=1.0), }, historical_cost=1 + i + l * n_levels, ) for i in range(n_processes) for l in range(1, n_levels) ] @fixture(scope="module") def profiles(processes): return [ ManufacturingProfile( n_steps=i + 1, cost=10 * (i + 1), initial_pause_cost=1, running_pause_cost=2, resumption_cost=3, cancellation_cost=4, line=l, process=p, ) for i, (p, l) in enumerate(zip(processes, itertools.cycle(range(n_lines)))) ] @fixture(scope="module") def n_profiles(profiles): return len(profiles) @fixture def empty_factory(profiles): return Factory( id="factory", profiles=profiles, initial_wallet=initial_wallet, initial_storage={}, max_storage=max_storage, ) @fixture def factory_with_storage(profiles): return Factory( id="factory", profiles=profiles, initial_storage=copy.deepcopy(initial_storage), initial_wallet=initial_wallet, max_storage=max_storage, ) @fixture def slow_simulator(profiles, products): return SlowFactorySimulator( initial_wallet=initial_wallet, initial_storage=initial_storage, n_steps=n_steps, n_products=len(products), profiles=profiles, max_storage=max_storage, ) def test_can_init_factory(empty_factory): assert empty_factory._n_lines == n_lines def test_schedule_and_job(factory_with_storage): profile_ind = 0 factory = factory_with_storage t = 10 line = factory.profiles[profile_ind].line job = Job( profile=profile_ind, time=t, line=line, action="run", contract=None, override=True, ) factory.schedule(job=job) assert len(factory._jobs) == 1 assert factory._jobs[(t, factory.profiles[profile_ind].line)] == job assert factory._wallet == initial_wallet assert len(factory._storage) == len(initial_storage) assert factory._storage == initial_storage profile = factory.profiles[profile_ind] # nothing happens before job time for _ in range(t): infos = factory.step() assert all(info.is_empty for info in infos) assert all(command.action == "none" for command in factory._commands) # the command is executed in job time for _ in range(profile.n_steps): infos = factory.step() assert not any(info.failed for info in infos) assert all( command.action == "none" for i, command in enumerate(factory._commands) if i != line ) if _ == 0: assert isinstance(infos[line].started, RunningCommandInfo) assert infos[line].started.beg == factory._next_step - 1 assert infos[line].started.end == profile.n_steps + factory._next_step - 1 if _ == profile.n_steps - 1: assert isinstance(infos[line].finished, RunningCommandInfo) if 0 < _ < profile.n_steps - 1: assert isinstance(infos[line].continuing, RunningCommandInfo) assert not infos[line].finished and not infos[line].started # nothing happens after job time for _ in range(t): infos = factory.step() assert all(info.no_production for info in infos) assert all(command.action == "none" for command in factory._commands) @mark.parametrize("wallet", [initial_wallet, 0], ids=["has_money", "no_money"]) def test_schedule_and_job_with_failures(empty_factory, wallet): profile_ind = 0 factory = empty_factory factory._wallet = wallet t = 10 line = factory.profiles[profile_ind].line job = Job( profile=profile_ind, time=t, line=line, action="run", contract=None, override=True, ) factory.schedule(job=job) assert len(factory._jobs) == 1 assert factory._jobs[(t, factory.profiles[profile_ind].line)] == job assert factory._wallet == wallet assert len(factory._storage) == 0 profile = factory.profiles[profile_ind] # nothing happens before job time for _ in range(t): infos = factory.step() assert all(info.is_empty for info in infos) assert all(command.action == "none" for command in factory._commands) # the command is executed in job time infos = factory.step() assert not any(info.failed for i, info in enumerate(infos) if i != line) assert infos[line].failed assert len(infos[line].failure.missing_inputs) > 0 if wallet < profile.cost: assert infos[line].failure.missing_money == profile.cost - wallet # nothing happens after job time for _ in range(2 * t): infos = factory.step() assert all(info.no_production for info in infos) assert all(command.action == "none" for command in factory._commands) def test_slow_factory_simulator_can_be_initialized(slow_simulator): assert slow_simulator is not None def do_simulator_run(simulator, profiles, t, at, profile_ind, override): profile = profiles[profile_ind] line = profile.line cost = profile.cost length = profile.n_steps total_inputs = sum(_.quantity for _ in profile.process.inputs) if at >= t else 0 total_outputs = ( sum(_.quantity for _ in profile.process.outputs) if at >= t + profile.n_steps else 0 ) job = Job( profile=profile_ind, time=t, line=line, action="run", contract=None, override=False, ) simulator.schedule(job=job, override=override) assert simulator.wallet_at(at) == ( initial_wallet if at < t else initial_wallet - cost ) assert ( simulator.total_storage_at(at) == sum(initial_storage.values()) - total_inputs + total_outputs ) assert ( simulator.line_schedules_at(at)[_] == NO_PRODUCTION for _ in range(n_lines) if _ != line ) if at < t or at >= t + length: assert simulator.line_schedules_at(at)[line] == NO_PRODUCTION # @todo correct the slow simulator @mark.parametrize( "profile_ind,t,at_,override,simulator_type", [ # (0, 10, 'after', True, 'slow'), (0, 10, 'after', False, 'slow'), (0, 10, 'before', True, 'slow'), # (0, 10, 'before', False, 'slow') # , (0, 10, 'just before', True, 'slow'), (0, 10, 'just before', False, 'slow'), # (0, 10, 'just after', True, 'slow') # , (0, 10, 'just after', False, 'slow') # , (0, 10, 'at', True, 'slow'), (0, 10, 'at', False, 'slow'), (0, 10, 'middle', True, 'slow'), # (0, 10, 'middle', False, 'slow') # , (1, 10, 'after', True, 'slow'), (1, 10, 'after', False, 'slow'), (1, 10, 'before', True, 'slow') # , (1, 10, 'before', False, 'slow') # , (1, 10, 'just before', True, 'slow'), (1, 10, 'just before', False, 'slow'), # (1, 10, 'just after', True, 'slow') # , (1, 10, 'just after', False, 'slow') # , (1, 10, 'at', True, 'slow'), (1, 10, 'at', False, 'slow'), (1, 10, 'middle', True, 'slow'), # (1, 10, 'middle', False, 'slow') # , (2, 10, 'after', True, 'slow'), (2, 10, 'after', False, 'slow'), (2, 10, 'before', True, 'slow') # , (2, 10, 'before', False, 'slow') # , (2, 10, 'just before', True, 'slow'), (2, 10, 'just before', False, 'slow'), # (2, 10, 'just after', True, 'slow') # , (2, 10, 'just after', False, 'slow') # , (2, 10, 'at', True, 'slow'), (2, 10, 'at', False, 'slow'), (2, 10, 'middle', True, 'slow'), # (2, 10, 'middle', False, 'slow') # , (3, 10, 'after', True, 'slow'), (3, 10, 'after', False, 'slow'), (3, 10, 'before', True, 'slow') # , (3, 10, 'before', False, 'slow') # , (3, 10, 'just before', True, 'slow'), (3, 10, 'just before', False, 'slow'), # (3, 10, 'just after', True, 'slow') # , (3, 10, 'just after', False, 'slow') # , (3, 10, 'at', True, 'slow'), (3, 10, 'at', False, 'slow'), (3, 10, 'middle', True, 'slow'), # (3, 10, 'middle', False, 'slow'), (0, 0, "after", True, "fast"), (0, 0, "after", False, "fast"), (0, 0, "before", True, "fast"), (0, 0, "before", False, "fast"), (0, 0, "just before", True, "fast"), (0, 0, "just before", False, "fast"), (0, 0, "just after", True, "fast"), (0, 0, "just after", False, "fast"), (0, 0, "at", True, "fast"), (0, 0, "at", False, "fast"), (0, 0, "middle", True, "fast"), (0, 0, "middle", False, "fast"), (1, 0, "after", True, "fast"), (1, 0, "after", False, "fast"), (1, 0, "before", True, "fast"), (1, 0, "before", False, "fast"), (1, 0, "just before", True, "fast"), (1, 0, "just before", False, "fast"), (1, 0, "just after", True, "fast"), (1, 0, "just after", False, "fast"), (1, 0, "at", True, "fast"), (1, 0, "at", False, "fast"), (1, 0, "middle", True, "fast"), (1, 0, "middle", False, "fast"), (2, 0, "after", True, "fast"), (2, 0, "after", False, "fast"), (2, 0, "before", True, "fast"), (2, 0, "before", False, "fast"), (2, 0, "just before", True, "fast"), (2, 0, "just before", False, "fast"), (2, 0, "just after", True, "fast"), (2, 0, "just after", False, "fast"), (2, 0, "at", True, "fast"), (2, 0, "at", False, "fast"), (2, 0, "middle", True, "fast"), (2, 0, "middle", False, "fast"), (3, 0, "after", True, "fast"), (3, 0, "after", False, "fast"), (3, 0, "before", True, "fast"), (3, 0, "before", False, "fast"), (3, 0, "just before", True, "fast"), (3, 0, "just before", False, "fast"), (3, 0, "just after", True, "fast"), (3, 0, "just after", False, "fast"), (3, 0, "at", True, "fast"), (3, 0, "at", False, "fast"), (3, 0, "middle", True, "fast"), (3, 0, "middle", False, "fast"), (0, 10, "after", True, "fast"), (0, 10, "after", False, "fast"), (0, 10, "before", True, "fast"), (0, 10, "before", False, "fast"), (0, 10, "just before", True, "fast"), (0, 10, "just before", False, "fast"), (0, 10, "just after", True, "fast"), (0, 10, "just after", False, "fast"), (0, 10, "at", True, "fast"), (0, 10, "at", False, "fast"), (0, 10, "middle", True, "fast"), (0, 10, "middle", False, "fast"), (1, 10, "after", True, "fast"), (1, 10, "after", False, "fast"), (1, 10, "before", True, "fast"), (1, 10, "before", False, "fast"), (1, 10, "just before", True, "fast"), (1, 10, "just before", False, "fast"), (1, 10, "just after", True, "fast"), (1, 10, "just after", False, "fast"), (1, 10, "at", True, "fast"), (1, 10, "at", False, "fast"), (1, 10, "middle", True, "fast"), (1, 10, "middle", False, "fast"), (2, 10, "after", True, "fast"), (2, 10, "after", False, "fast"), (2, 10, "before", True, "fast"), (2, 10, "before", False, "fast"), (2, 10, "just before", True, "fast"), (2, 10, "just before", False, "fast"), (2, 10, "just after", True, "fast"), (2, 10, "just after", False, "fast"), (2, 10, "at", True, "fast"), (2, 10, "at", False, "fast"), (2, 10, "middle", True, "fast"), (2, 10, "middle", False, "fast"), (3, 10, "after", True, "fast"), (3, 10, "after", False, "fast"), (3, 10, "before", True, "fast"), (3, 10, "before", False, "fast"), (3, 10, "just before", True, "fast"), (3, 10, "just before", False, "fast"), (3, 10, "just after", True, "fast"), (3, 10, "just after", False, "fast"), (3, 10, "at", True, "fast"), (3, 10, "at", False, "fast"), (3, 10, "middle", True, "fast"), (3, 10, "middle", False, "fast"), (0, 0, "after", True, "fast"), (0, 0, "after", False, "fast"), (0, 0, "before", True, "fast"), (0, 0, "before", False, "fast"), (0, 0, "just before", True, "fast"), (0, 0, "just before", False, "fast"), (0, 0, "just after", True, "fast"), (0, 0, "just after", False, "fast"), (0, 0, "at", True, "fast"), (0, 0, "at", False, "fast"), (0, 0, "middle", True, "fast"), (0, 0, "middle", False, "fast"), (1, 0, "after", True, "fast"), (1, 0, "after", False, "fast"), (1, 0, "before", True, "fast"), (1, 0, "before", False, "fast"), (1, 0, "just before", True, "fast"), (1, 0, "just before", False, "fast"), (1, 0, "just after", True, "fast"), (1, 0, "just after", False, "fast"), (1, 0, "at", True, "fast"), (1, 0, "at", False, "fast"), (1, 0, "middle", True, "fast"), (1, 0, "middle", False, "fast"), (2, 0, "after", True, "fast"), (2, 0, "after", False, "fast"), (2, 0, "before", True, "fast"), (2, 0, "before", False, "fast"), (2, 0, "just before", True, "fast"), (2, 0, "just before", False, "fast"), (2, 0, "just after", True, "fast"), (2, 0, "just after", False, "fast"), (2, 0, "at", True, "fast"), (2, 0, "at", False, "fast"), (2, 0, "middle", True, "fast"), (2, 0, "middle", False, "fast"), (3, 0, "after", True, "fast"), (3, 0, "after", False, "fast"), (3, 0, "before", True, "fast"), (3, 0, "before", False, "fast"), (3, 0, "just before", True, "fast"), (3, 0, "just before", False, "fast"), (3, 0, "just after", True, "fast"), (3, 0, "just after", False, "fast"), (3, 0, "at", True, "fast"), (3, 0, "at", False, "fast"), (3, 0, "middle", True, "fast"), (3, 0, "middle", False, "fast"), ], ) def test_slow_factory_simulator_with_jobs( products, profiles, profile_ind, t, at_, override, simulator_type ): simulator_type = ( SlowFactorySimulator if simulator_type == "slow" else FastFactorySimulator ) simulator = simulator_type( initial_wallet=initial_wallet, initial_storage=initial_storage, n_steps=n_steps, n_products=len(products), profiles=profiles, max_storage=max_storage, ) profile = profiles[profile_ind] length = profile.n_steps if at_ == "before": if t - 5 < 0: return at = t - 5 elif at_ == "after": if t + length + 3 > n_steps: return at = t + length + 3 elif at_ == "at": at = t elif at_ == "just before": if t - 1 < 0: return at = t - 1 elif at_ == "just after": at = t + length elif at_ == "middle": if length == 1: return at = (t + length) // 2 else: raise ValueError(f"Unknown option {at_}") do_simulator_run(simulator, profiles, t, at, profile_ind, override) if __name__ == "__main__": pytest.main(args=[__file__]) PK!- oPoP#negmas/tests/scml/test_scheduler.pyimport copy import itertools import math from collections import defaultdict import pytest from pytest import fixture import numpy as np from negmas import Contract from negmas.apps.scml import ( Product, Process, InputOutput, ManufacturingProfile, SCMLAgreement, CFP, GreedyScheduler, ManufacturingProfileCompiled, ProductManufacturingInfo, ) from negmas.apps.scml.simulators import SlowFactorySimulator from negmas.apps.scml.world import Factory n_lines = 5 n_levels = 4 n_products = 5 n_processes = 3 initial_wallet = 100.0 n_steps = 100 max_storage = None initial_storage = dict( zip(range(n_products * n_levels), range(10, 10 * (n_products * n_levels), 10)) ) @fixture(scope="module") def products(): return [ Product( id=i + l * n_levels, production_level=l, name=f"{l}_{i}", catalog_price=(i + 1) * (l + 1), expires_in=None, ) for i in range(n_products) for l in range(n_levels) ] @fixture(scope="module") def processes(): return [ Process( id=i + l * n_levels, production_level=l, name=f"p{l}_{i}", inputs={ InputOutput(product=i + (l - 1) * n_levels, quantity=3, step=0.0), InputOutput(product=i + (l - 1) * n_levels, quantity=2, step=0.0), }, outputs={ InputOutput(product=i + l * n_levels, quantity=1, step=1.0), InputOutput(product=i + l * n_levels, quantity=2, step=1.0), }, historical_cost=1 + i + l * n_levels, ) for i in range(n_processes) for l in range(1, n_levels) ] @fixture(scope="module") def profiles(processes): return [ ManufacturingProfile( n_steps=i + 1, cost=10 * (i + 1), initial_pause_cost=1, running_pause_cost=2, resumption_cost=3, cancellation_cost=4, line=l, process=p, ) for i, (p, l) in enumerate(zip(processes, itertools.cycle(range(n_lines)))) ] @fixture(scope="module") def n_profiles(profiles): return len(profiles) @fixture def empty_factory(profiles): return Factory( id="factory", profiles=profiles, initial_wallet=initial_wallet, initial_storage={}, max_storage=max_storage, ) @fixture def factory_with_storage(profiles): return Factory( id="factory", profiles=profiles, initial_storage=copy.deepcopy(initial_storage), initial_wallet=initial_wallet, max_storage=max_storage, ) @fixture def slow_simulator(profiles, products): return SlowFactorySimulator( initial_wallet=initial_wallet, initial_storage=initial_storage, n_steps=n_steps, n_products=len(products), profiles=profiles, max_storage=max_storage, ) # class TestGreedyScheduler: # manager_name = 'test' # products = [Product(name=f'pr{i}', catalog_price=i + 1, id=i, production_level=i # , expires_in=0) for i in range(5)] # processes = [Process(id=0, name='p0', inputs={InputOutput(0, quantity=2, step=0.0), # InputOutput(1, quantity=3, step=0.0)} # , outputs={InputOutput(2, quantity=1, step=1.0)} # , historical_cost=1, production_level=1) # , Process(id=1, name='p1', inputs={InputOutput(2, quantity=3, step=0.0)} # , outputs={InputOutput(3, quantity=1, step=1.0)} # , historical_cost=1, production_level=2) # , Process(id=2, name='p2', inputs={InputOutput(2, quantity=3, step=0.0)} # , outputs={InputOutput(3, quantity=2, step=1.0)} # , historical_cost=3, production_level=2) # , Process(id=3, name='p3', inputs={InputOutput(3, quantity=3, step=0.0)} # , outputs={InputOutput(4, quantity=1, step=1.0)} # , historical_cost=3, production_level=3) # ] # @classmethod # def setup_class(cls): # cls.manager_name = 'test' # cls.products = [Product(name=f'pr{i}', catalog_price=i + 1, id=i, production_level=i # , expires_in=0) for i in range(5)] # cls.processes = [Process(id=0, name='p0', inputs={InputOutput(0, quantity=2, step=0.0), # InputOutput(1, quantity=3, step=0.0)} # , outputs={InputOutput(2, quantity=1, step=1.0)} # , historical_cost=1, production_level=1) # , Process(id=1, name='p1', inputs={InputOutput(2, quantity=3, step=0.0)} # , outputs={InputOutput(3, quantity=1, step=1.0)} # , historical_cost=1, production_level=2) # , Process(id=2, name='p2', inputs={InputOutput(2, quantity=3, step=0.0)} # , outputs={InputOutput(3, quantity=2, step=1.0)} # , historical_cost=3, production_level=2) # , Process(id=3, name='p3', inputs={InputOutput(3, quantity=3, step=0.0)} # , outputs={InputOutput(4, quantity=1, step=1.0)} # , historical_cost=3, production_level=3) # ] # # @classmethod # def create_profiles(cls, n_lines): # profiles = [] # for l in range(n_lines): # profiles.extend([ManufacturingProfile(n_steps=1, cost=10, cancellation_cost=5 # , initial_pause_cost=0, running_pause_cost=0, resumption_cost=0, line=l, # process=cls.processes[0]) # , ManufacturingProfile(n_steps=5, cost=5, cancellation_cost=2 # , initial_pause_cost=0, running_pause_cost=0, resumption_cost=0, line=l, # process=cls.processes[0]) # , ManufacturingProfile(n_steps=3, cost=3, cancellation_cost=0 # , initial_pause_cost=0, running_pause_cost=0, resumption_cost=0, line=l, # process=cls.processes[1]) # , ManufacturingProfile(n_steps=2, cost=5, cancellation_cost=0 # , initial_pause_cost=0, running_pause_cost=0, resumption_cost=0, line=l, # process=cls.processes[1])]) # return profiles # # @classmethod # def create_factory(cls, n_lines, initial_balance, storage): # profiles = cls.create_profiles(n_lines) # return Factory(id='factory', profiles=profiles, initial_storage=storage # , initial_wallet=initial_balance, max_storage=max_storage) # # @classmethod # def create_scheduler(cls, n_lines, n_steps, strategy, initial_balance, storage): # if storage is None: # storage = {} # factory = cls.create_factory(n_lines, initial_balance, storage) # profiles = factory.profiles # processes = cls.processes # p2i = dict(zip(processes, range(len(processes)))) # compiled_profiles = [ManufacturingProfileCompiled.from_manufacturing_profile(p, process2ind=p2i) # for p in profiles] # scheduler = GreedyScheduler(manager_id=cls.manager_name, awi=None, horizon=None, max_insurance_premium=None # , add_catalog_prices=True, strategy=strategy) # simulator = SlowFactorySimulator(initial_wallet=initial_balance, initial_storage=storage # , n_steps=n_steps, n_products=len(cls.products), profiles=compiled_profiles # , max_storage=max_storage) # producing = defaultdict(list) # for index, profile in enumerate(profiles): # process = profile.process # for outpt in process.outputs: # step = int(math.ceil(outpt.step * profile.n_steps)) # producing[outpt.product].append(ProductManufacturingInfo(profile=index # , quantity=outpt.quantity # , step=step)) # # scheduler.init(simulator=simulator, products=cls.products, processes=cls.processes # , profiles=compiled_profiles, producing=producing) # return scheduler # # @classmethod # def buy_contract(cls, t, u, q, p): # return Contract(agreement=SCMLAgreement(time=t, unit_price=u, quantity=q) # , annotation={'cfp': CFP(is_buy=True, product=p, time=t, unit_price=u, quantity=q # , publisher=cls.manager_name) # , 'buyer': cls.manager_name, 'seller': 'anyone'}) # # @classmethod # def sell_contract(cls, t, u, q, p): # return Contract(agreement=SCMLAgreement(time=t, unit_price=u, quantity=q) # , annotation={'cfp': CFP(is_buy=True, product=p, time=t, unit_price=u, quantity=q # , publisher='anyone') # , 'buyer': 'anyone', 'seller': cls.manager_name}) # # def test_initialization(self): # scheduler = self.create_scheduler(n_lines=3, n_steps=5, strategy='earliest', initial_balance=1000 # , storage={}) # assert len(scheduler.products) == len(self.products) # # def test_scheduling_a_buy_contract(self): # t = 2 # initial = 1000 # unit_price, quantity = 2, 1 # total = unit_price * quantity # storage = {0: 10, 1: 10, 2: 0} # contract = self.buy_contract(p=0, t=t, u=unit_price, q=quantity) # scheduler = self.create_scheduler(n_lines=1, n_steps=t * 2, storage=storage, strategy='earliest' # , initial_balance=initial) # schedule = scheduler.schedule([contract]) # final = schedule.final_balance # assert schedule.valid # assert final == initial - total # # factory = scheduler.factory_state # # assert len(factory.predicted_balance) == t + 1 # # assert max(abs(factory.predicted_storage[0, :t] - 10)) == 0 # # assert max(abs(factory.predicted_storage[0, t:] - 11)) == 0 # # assert max(abs(factory.predicted_storage[1, :t] - 10)) == 0 # # assert max(abs(factory.predicted_storage[2:].flatten())) == 0 # # assert max(abs(factory.predicted_balance[:t] - initial)) == 0 # # assert max(abs(factory.predicted_balance[t:] - initial + total)) == 0 # # @todo test the case where end != None # # def test_scheduling_a_sell_contract_no_needs(self): # t, n_steps = 3, 20 # initial = 1000 # unit_price, quantity = 2, 1 # total = unit_price * quantity # storage = {0: 10, 1: 10, 2: 0} # contract = self.sell_contract(p=0, t=t, u=unit_price, q=quantity) # scheduler = self.create_scheduler(n_lines=1, n_steps=t * 2, storage=storage, strategy='earliest') # scheduler.schedule([contract]) # factory = scheduler.factory_state # # assert max(abs(factory.predicted_storage[0, :t] - 10)) == 0 # assert max(abs(factory.predicted_storage[0, t:] - 9)) == 0 # assert max(abs(factory.predicted_storage[1, :t] - 10)) == 0 # assert max(abs(factory.predicted_storage[2:].flatten())) == 0 # assert max(abs(factory.predicted_balance[:t] - 1000)) == 0 # assert max(abs(factory.predicted_balance[t:] - 1002)) == 0 # # @pytest.mark.parametrize('product_id,t,quantity,valid' # , [(0, 12, 1, False), (2, 12, 1, True), (2, 12, 2, True), (2, 12, 50, False)] # , ids=['cannot be produced', 'producing 1 item', 'producing 2 items', 'time is not enough']) # def test_scheduling_a_sell_contract_with_needs_early(self, product_id, t, quantity, valid): # products, processes, profiles = self.products, self.processes, self.profiles # n_steps = 20 # initial = 1000 # unit_price = 2 # total = unit_price * quantity # process, profile = self.processes[0], self.profiles[0] # storage = {0: 0, 1: 0, 2: 0} # contract = self.sell_contract(p=product_id, t=t, u=unit_price, q=quantity) # scheduler = self.create_scheduler(n_lines=1, n_steps=n_steps, storage=storage, strategy='earliest') # info = scheduler.schedule([contract]) # factory = scheduler.factory_state # # total_cost = sum(self.products[i.product].catalog_price * i.quantity for i in process.inputs) # total_cost += profile.cost # selling_price = contract.agreement['unit_price'] * contract.agreement['quantity'] # production_time = profile.n_steps * contract.agreement['quantity'] // list(process.outputs)[0].quantity # # assert info.valid == valid # if valid: # assert len(info.needs) == 2 * quantity # assert 2 in (info.needs[0].quantity_to_buy, info.needs[1].quantity_to_buy) # assert 3 in (info.needs[0].quantity_to_buy, info.needs[1].quantity_to_buy) # if quantity > 1: # assert 2 in (info.needs[2].quantity_to_buy, info.needs[3].quantity_to_buy) # assert 3 in (info.needs[2].quantity_to_buy, info.needs[3].quantity_to_buy) # # expected_balance = np.array([initial - total_cost] * profile.n_steps + # [initial - quantity * total_cost] * (contract.agreement['time'] # - profile.n_steps) + # [initial - quantity * total_cost + selling_price]) # expected_storage = np.array([[-2] * profile.n_steps + [-2 * quantity] * (t + 1 - profile.n_steps), # [-3] * profile.n_steps + [-3 * quantity] * (t + 1 - profile.n_steps), # [0] * profile.n_steps + [1] * profile.n_steps + # [quantity] * (t - 2 * profile.n_steps) + [0], # [0] * (t + 1), # [0] * (t + 1)]) # expected_total_storage = expected_storage.sum(axis=0) # expected_line_schedule = np.array([0] * profile.n_steps * quantity + [-1] * (t + 1 # - quantity * profile.n_steps)) # else: # expected_line_schedule = scheduler.managed_factory.schedule[ # list(scheduler.managed_factory.lines.values())[0]][: t + 1] # expected_storage = scheduler.managed_factory.predicted_storage[:, : t + 1] # expected_balance = scheduler.managed_factory.predicted_balance[: t + 1] # expected_total_storage = scheduler.managed_factory.predicted_total_storage[: t + 1] # # line_schedule = factory.schedule[list(factory.lines.values())[0]] # assert np.all(factory.predicted_storage == expected_storage) # assert np.all(factory.predicted_total_storage == expected_total_storage) # assert np.all(line_schedule == expected_line_schedule) # assert np.all(factory.predicted_balance == expected_balance) # # # @pytest.mark.parametrize('product_id,t,quantity,valid' # , [(0, 12, 1, False), (2, 12, 1, True), (2, 12, 2, True), (2, 12, 50, False)] # , ids=['cannot be produced', 'producing 1 item', 'producing 2 items', 'time is not enough']) # def test_scheduling_a_sell_contract_with_needs_late(self, product_id, t, quantity, valid): # products, processes, profiles = self.products, self.processes, self.profiles # n_steps = 20 # initial = 1000 # unit_price = 2 # total = unit_price * quantity # process, profile = self.processes[0], self.profiles[0] # storage = {0: 0, 1: 0, 2: 0} # contract = self.sell_contract(p=product_id, t=t, u=unit_price, q=quantity) # scheduler = self.create_scheduler(n_lines=1, n_steps=n_steps, storage=storage, strategy='latest') # info = scheduler.schedule([contract]) # factory = scheduler.factory_state # # total_cost = sum(self.products[i.product].catalog_price * i.quantity for i in process.inputs) # total_cost += profile.cost # selling_price = contract.agreement['unit_price'] * contract.agreement['quantity'] # production_time = profile.n_steps * contract.agreement['quantity'] // list(process.outputs)[0].quantity # # assert info.valid == valid # if valid: # assert len(info.needs) == 2 * quantity # assert 2 in (info.needs[0].quantity_to_buy, info.needs[1].quantity_to_buy) # assert 3 in (info.needs[0].quantity_to_buy, info.needs[1].quantity_to_buy) # if quantity > 1: # assert 2 in (info.needs[2].quantity_to_buy, info.needs[3].quantity_to_buy) # assert 3 in (info.needs[2].quantity_to_buy, info.needs[3].quantity_to_buy) # # def _expected_balance(n_steps=profile.n_steps, total=t + 1): # s = initial * np.ones(total) # s[total - 1] += selling_price # for q in range(quantity): # s[-n_steps * (q + 1) - 1:] -= total_cost # return s.tolist() # # def _expected_storage(n_needed, n_steps=profile.n_steps, total=t + 1): # s = np.zeros(total) # for q in range(quantity): # s[-n_steps * (q + 1) - 1:] -= n_needed # return s.tolist() # # def _expected_output(total=t + 1, n_steps=profile.n_steps): # s = np.zeros(total) # for q in range(quantity): # s[-n_steps * q - 1:] += 1 # s[-1] = 0 # return s.tolist() # # def _expected_line(total=t + 1, n_steps=profile.n_steps): # s = -1 * np.ones(total) # for q in range(quantity): # s[-n_steps * (q + 1) - 1:-1] = 0 # return s.tolist() # # expected_balance = _expected_balance() # expected_storage = np.array([_expected_storage(2), _expected_storage(3), _expected_output() # , [0] * (t + 1), [0] * (t + 1)]) # expected_total_storage = expected_storage.sum(axis=0) # expected_line_schedule = _expected_line() # # # print(f'q={quantity}') # # pprint([str(_) for _ in info.needs]) # # print('expected') # # pprint(expected_line_schedule) # # print('real') # # pprint({k.id: v for k, v in factory.schedule.items()}) # # print('expected') # # pprint(expected_balance) # # print('real') # # pprint(factory.predicted_balance) # # print('expected') # # pprint(expected_storage) # # print('real') # # pprint(factory.predicted_storage) # # # # print(f'total_cost: {total_cost}, selling_price: {selling_price}, production_time: {production_time}') # else: # expected_line_schedule = scheduler.managed_factory.schedule[ # list(scheduler.managed_factory.lines.values())[0]][: t + 1] # expected_storage = scheduler.managed_factory.predicted_storage[:, : t + 1] # expected_balance = scheduler.managed_factory.predicted_balance[: t + 1] # expected_total_storage = scheduler.managed_factory.predicted_total_storage[: t + 1] # # line_schedule = factory.schedule[list(factory.lines.values())[0]] # assert np.all(factory.predicted_storage == expected_storage) # assert np.all(factory.predicted_total_storage == expected_total_storage) # assert np.all(line_schedule == expected_line_schedule) # assert np.all(factory.predicted_balance == expected_balance) PK!nn!negmas/tests/test_SAOMechanism.pyimport random from pytest import mark from negmas import SAOMechanism, AspirationNegotiator, MappingUtilityFunction def test_on_negotiation_start(): mechanism = SAOMechanism(outcomes=10) assert mechanism.on_negotiation_start() @mark.parametrize(["n_negotaitors"], [(2,), (3,)]) def test_round_n_agents(n_negotaitors): n_outcomes = 5 mechanism = SAOMechanism(outcomes=n_outcomes, n_steps=3) ufuns = MappingUtilityFunction.generate_random(n_negotaitors, outcomes=n_outcomes) for i in range(n_negotaitors): mechanism.add(AspirationNegotiator(name=f"agent{i}"), ufun=ufuns[i]) assert mechanism.state.step == 0 mechanism.step() assert mechanism.state.step == 1 assert 0 <= mechanism._first_proposer < n_negotaitors assert ( mechanism._current_proposer.name == mechanism.negotiators[mechanism._first_proposer].name ) assert mechanism._current_offer is not None @mark.parametrize(["n_negotaitors"], [(2,), (3,)]) def test_mechanism_can_run(n_negotaitors): n_outcomes = 5 mechanism = SAOMechanism(outcomes=n_outcomes, n_steps=3) ufuns = MappingUtilityFunction.generate_random(n_negotaitors, outcomes=n_outcomes) for i in range(n_negotaitors): mechanism.add(AspirationNegotiator(name=f"agent{i}"), ufun=ufuns[i]) assert mechanism.state.step == 0 mechanism.step() mechanism.run() PK!ECkk negmas/tests/test_basic_agent.pyimport pytest from negmas import Negotiator if __name__ == "__main__": pytest.main(args=[__file__]) PK!/BBnegmas/tests/test_genius.pyimport pathlib import numpy as np import pkg_resources import pytest from negmas import ( GeniusNegotiator, load_genius_domain, load_genius_domain_from_folder, genius_bridge_is_running, ) dom_folder = pathlib.Path( pkg_resources.resource_filename( "negmas", resource_name="tests/data/scenarios/anac/y2010/Travel" ) ) dom = dom_folder / "travel_domain.xml" util1 = dom_folder / "travel_chox.xml" util2 = dom_folder / "travel_fanny.xml" @pytest.fixture(scope="module") def init_genius(): pass @pytest.mark.skipif( condition=not genius_bridge_is_running(), reason="No Genius Bridge, skipping genius-agent tests", ) def test_genius_agent(init_genius): p, _, issues = load_genius_domain_from_folder( dom_folder, agent_factories=[ lambda: GeniusNegotiator( java_class_name="agents.anac.y2015.Atlas3.Atlas3", domain_file_name=dom, utility_file_name=util1, ), lambda: GeniusNegotiator( java_class_name="agents.anac.y2015.AgentX.AgentX", domain_file_name=dom, utility_file_name=util2, ), ], keep_issue_names=True, keep_value_names=True, time_limit=20, ) assert len(p.negotiators) > 1 issue_list = [f"{k}:{v}" for k, v in enumerate(issues)] assert issue_list == [ "0:Atmosphere: ['Cultural heritage', 'Local traditions', 'Political stability', 'Security (personal)'" ", 'Liveliness', 'Turistic activities', 'Hospitality']", "1:Amusement: ['Nightlife and entertainment', 'Nightclubs', 'Excursion', 'Casinos', 'Zoo', 'Festivals'" ", 'Amusement park']", "2:Culinary: ['Local cuisine', 'Lunch facilities', 'International cuisine', 'Cooking workshops']", "3:Shopping: ['Shopping malls', 'Markets', 'Streets', 'Small boutiques']", "4:Culture: ['Museum', 'Music hall', 'Theater', 'Art gallery', 'Cinema', 'Congress center']", "5:Sport: ['Bike tours', 'Hiking', 'Indoor activities', 'Outdoor activities', 'Adventure']", "6:Environment: ['Parks and Gardens', 'Square', 'Historical places', 'See, river, etc.', 'Monuments'" ", 'Special streets', 'Palace', 'Landscape and nature']", ] atlas3, agentx = p.negotiators[0], p.negotiators[1] p.run() # print(f'{len(p.history)} bids exchanged') u1 = np.array([float(atlas3.utility_function(s.current_offer)) for s in p.history]) u2 = np.array([float(agentx.utility_function(s.current_offer)) for s in p.history]) welfare = u1 + u2 # print( # f'Negotiator 1: {u1.mean()}({u1.std()})[{u1.min()}, {u1.max()}]\nNegotiator 2: {u2.mean()}({u2.std()})[{u1.min()}, {u1.max()}]' # f'\nWelfare: {welfare.mean()}({welfare.std()})[{welfare.min()}, {welfare.max()}]') # print(p.state) assert len(u1) > 0 @pytest.mark.skipif( condition=not genius_bridge_is_running(), reason="No Genius Bridge, skipping genius-agent tests", ) def test_genius_agent_step_limit(init_genius): p, _, issues = load_genius_domain_from_folder( dom_folder, agent_factories=[ lambda: GeniusNegotiator( java_class_name="agents.anac.y2015.Atlas3.Atlas3", domain_file_name=dom, utility_file_name=util1, ), lambda: GeniusNegotiator( java_class_name="agents.anac.y2015.AgentX.AgentX", domain_file_name=dom, utility_file_name=util2, ), ], keep_issue_names=True, keep_value_names=True, n_steps=20, time_limit=None, ) issue_list = [f"{k}:{v}" for k, v in enumerate(issues)] assert issue_list == [ "0:Atmosphere: ['Cultural heritage', 'Local traditions', 'Political stability', 'Security (personal)', 'Liveliness', 'Turistic activities', 'Hospitality']", "1:Amusement: ['Nightlife and entertainment', 'Nightclubs', 'Excursion', 'Casinos', 'Zoo', 'Festivals', 'Amusement park']", "2:Culinary: ['Local cuisine', 'Lunch facilities', 'International cuisine', 'Cooking workshops']", "3:Shopping: ['Shopping malls', 'Markets', 'Streets', 'Small boutiques']", "4:Culture: ['Museum', 'Music hall', 'Theater', 'Art gallery', 'Cinema', 'Congress center']", "5:Sport: ['Bike tours', 'Hiking', 'Indoor activities', 'Outdoor activities', 'Adventure']", "6:Environment: ['Parks and Gardens', 'Square', 'Historical places', 'See, river, etc.', 'Monuments', 'Special streets', 'Palace', 'Landscape and nature']", ] atlas3, agentx = p.negotiators[0], p.negotiators[1] p.run() # print(f'{len(p.history)} bids exchanged') u1 = np.array([float(atlas3.utility_function(s.current_offer)) for s in p.history]) u2 = np.array([float(agentx.utility_function(s.current_offer)) for s in p.history]) welfare = u1 + u2 # print( # f'Negotiator 1: {u1.mean()}({u1.std()})[{u1.min()}, {u1.max()}]\nNegotiator 2: {u2.mean()}({u2.std()})[{u1.min()}, {u1.max()}]' # f'\nWelfare: {welfare.mean()}({welfare.std()})[{welfare.min()}, {welfare.max()}]') # print(p.state) @pytest.mark.skipif( condition=not genius_bridge_is_running(), reason="No Genius Bridge, skipping genius-agent tests", ) def test_genius_agent_step_long_session(init_genius): a1 = GeniusNegotiator( java_class_name="agents.anac.y2015.Atlas3.Atlas3", domain_file_name=dom, utility_file_name=util1, ) a2 = GeniusNegotiator( java_class_name="agents.anac.y2015.Atlas3.Atlas3", domain_file_name=dom, utility_file_name=util2, ) p, _, issues = load_genius_domain( dom, keep_issue_names=True, keep_value_names=True, n_steps=20, time_limit=None ) issue_list = [f"{k}:{v}" for k, v in enumerate(issues)] assert issue_list == [ "0:Atmosphere: ['Cultural heritage', 'Local traditions', 'Political stability', 'Security (personal)', 'Liveliness', 'Turistic activities', 'Hospitality']", "1:Amusement: ['Nightlife and entertainment', 'Nightclubs', 'Excursion', 'Casinos', 'Zoo', 'Festivals', 'Amusement park']", "2:Culinary: ['Local cuisine', 'Lunch facilities', 'International cuisine', 'Cooking workshops']", "3:Shopping: ['Shopping malls', 'Markets', 'Streets', 'Small boutiques']", "4:Culture: ['Museum', 'Music hall', 'Theater', 'Art gallery', 'Cinema', 'Congress center']", "5:Sport: ['Bike tours', 'Hiking', 'Indoor activities', 'Outdoor activities', 'Adventure']", "6:Environment: ['Parks and Gardens', 'Square', 'Historical places', 'See, river, etc.', 'Monuments', 'Special streets', 'Palace', 'Landscape and nature']", ] p.add(a1) p.add(a2) p.run() # print(f'{len(p.history)} bids exchanged') u1 = np.array([float(a1.utility_function(s.current_offer)) for s in p.history]) u2 = np.array([float(a2.utility_function(s.current_offer)) for s in p.history]) welfare = u1 + u2 # print( # f'Negotiator 1: {u1.mean()}({u1.std()})[{u1.min()}, {u1.max()}]\nNegotiator 2: {u2.mean()}({u2.std()})[{u1.min()}, {u1.max()}]' # f'\nWelfare: {welfare.mean()}({welfare.std()})[{welfare.min()}, {welfare.max()}]') # print(p.state) assert len(u1) > 4 @pytest.mark.skipif( condition=not genius_bridge_is_running(), reason="No Genius Bridge, skipping genius-agent tests", ) def test_genius_agent_same_utility(init_genius): from negmas import GeniusNegotiator, load_genius_domain dom = dom_folder / "travel_domain.xml" util1 = dom_folder / "travel_chox.xml" util2 = util1 a1 = GeniusNegotiator( java_class_name="agents.anac.y2015.Atlas3.Atlas3", domain_file_name=dom, utility_file_name=util1, ) a2 = GeniusNegotiator( java_class_name="agents.anac.y2015.AgentX.AgentX", domain_file_name=dom, utility_file_name=util2, ) p, _, issues = load_genius_domain( dom, keep_issue_names=True, keep_value_names=True, time_limit=30 ) issue_list = [f"{k}:{v}" for k, v in enumerate(issues)] assert issue_list == [ "0:Atmosphere: ['Cultural heritage', 'Local traditions', 'Political stability', 'Security (personal)'" ", 'Liveliness', 'Turistic activities', 'Hospitality']", "1:Amusement: ['Nightlife and entertainment', 'Nightclubs', 'Excursion', 'Casinos', 'Zoo'" ", 'Festivals', 'Amusement park']", "2:Culinary: ['Local cuisine', 'Lunch facilities', 'International cuisine', 'Cooking workshops']", "3:Shopping: ['Shopping malls', 'Markets', 'Streets', 'Small boutiques']", "4:Culture: ['Museum', 'Music hall', 'Theater', 'Art gallery', 'Cinema', 'Congress center']", "5:Sport: ['Bike tours', 'Hiking', 'Indoor activities', 'Outdoor activities', 'Adventure']", "6:Environment: ['Parks and Gardens', 'Square', 'Historical places', 'See, river, etc.'" ", 'Monuments', 'Special streets', 'Palace', 'Landscape and nature']", ] p.add(a1) p.add(a2) p.run() u1 = np.array([float(a1.utility_function(s.current_offer)) for s in p.history]) u2 = np.array([float(a2.utility_function(s.current_offer)) for s in p.history]) welfare = u1 + u2 assert len(u1) == 2 assert welfare[0] == welfare[1] == 2.0 assert p.state.agreement is not None assert p.state.broken is False class TestGeniusAgentSessions: def prepare( self, utils=(1, 1), single_issue=True, keep_issue_names=True, keep_value_names=True, ): from negmas import convert_genius_domain_from_folder src = pkg_resources.resource_filename( "negmas", resource_name="tests/data/Laptop" ) dst = pkg_resources.resource_filename( "negmas", resource_name="tests/data/LaptopConv1D" ) if single_issue: assert convert_genius_domain_from_folder( src_folder_name=src, dst_folder_name=dst, force_single_issue=True, cache_and_discretize_outcomes=True, n_discretization=10, ) base_folder = dst else: base_folder = src neg, agent_info, issues = load_genius_domain_from_folder( base_folder, keep_issue_names=keep_issue_names, keep_value_names=keep_value_names, ) # atlas = GeniusNegotiator.random_negotiator( atlas = GeniusNegotiator( java_class_name="agents.anac.y2015.Atlas3.Atlas3", domain_file_name=base_folder + "/Laptop-C-domain.xml", utility_file_name=base_folder + f"/Laptop-C-prof{utils[0]}.xml", keep_issue_names=keep_issue_names, keep_value_names=keep_value_names, ) # agentx = GeniusNegotiator.random_negotiator( agentx = GeniusNegotiator( java_class_name="agents.anac.y2015.AgentX.AgentX", domain_file_name=base_folder + "/Laptop-C-domain.xml", utility_file_name=base_folder + f"/Laptop-C-prof{utils[1]}.xml", keep_issue_names=keep_issue_names, keep_value_names=keep_value_names, ) neg.add(atlas) neg.add(agentx) return neg @pytest.mark.skipif( condition=not genius_bridge_is_running(), reason="No Genius Bridge, skipping genius-agent tests", ) def test_genius_agents_can_run_on_converted_single_issue_ufun1(self, init_genius): neg = self.prepare(utils=(1, 1), single_issue=True) assert neg.pareto_frontier(sort_by_welfare=True)[0] == [(1.0, 1.0)] state = neg.run() # pprint(neg.history) assert neg.agreement is not None # assert len(neg.history) <= 3 assert neg.agreement == { "Laptop-Harddisk-External Monitor": "HP+60 Gb+19'' LCD" } @pytest.mark.skipif( condition=not genius_bridge_is_running(), reason="No Genius Bridge, skipping genius-agent tests", ) def test_genius_agents_can_run_on_converted_single_issue_ufun2(self, init_genius): neg = self.prepare(utils=(2, 2), single_issue=True) assert neg.pareto_frontier(sort_by_welfare=True)[0] == [(1.0, 1.0)] state = neg.run() assert neg.agreement is not None assert len(neg.history) <= 3 assert neg.agreement == { "Laptop-Harddisk-External Monitor": "Macintosh+80 Gb+19'' LCD" } @pytest.mark.skipif( condition=not genius_bridge_is_running(), reason="No Genius Bridge, skipping genius-agent tests", ) def test_genius_agents_can_run_on_converted_single_issue(self, init_genius): neg = self.prepare(utils=(1, 2), single_issue=True) assert neg.pareto_frontier(sort_by_welfare=True)[0] == [ (0.7715533992081258, 0.8450562871935449), (0.5775524426410947, 1.0), (1.0, 0.5136317604069089), (0.8059990434329689, 0.6685754732133642), ] state = neg.run() # assert len(neg.history) >= 2 assert neg.agreement is not None @pytest.mark.skipif( condition=not genius_bridge_is_running(), reason="No Genius Bridge, skipping genius-agent tests", ) def test_genius_agents_can_run_on_converted_multiple_issues(self, init_genius): neg = self.prepare(utils=(1, 1), single_issue=False) frontier = neg.pareto_frontier(sort_by_welfare=True)[0] true_frontier = [(1.0, 1.0)] assert len(frontier) == len(true_frontier) for a, b in zip(frontier, true_frontier): assert abs(a[0] - b[0]) < 1e-5 and abs(a[1] - b[1]) < 1e-5 state = neg.run() assert len(neg.history) < 3 assert neg.agreement is not None assert neg.agreement == { "Laptop": "HP", "Harddisk": "60 Gb", "External Monitor": "19'' LCD", } @pytest.mark.skipif( condition=not genius_bridge_is_running(), reason="No Genius Bridge, skipping genius-agent tests", ) def test_genius_agents_can_run_on_converted_multiple_issues_no_names( self, init_genius ): neg = self.prepare(utils=(1, 1), single_issue=False, keep_issue_names=False) frontier = neg.pareto_frontier(sort_by_welfare=True)[0] true_frontier = [(1.0, 1.0)] assert len(frontier) == len(true_frontier) for a, b in zip(frontier, true_frontier): assert abs(a[0] - b[0]) < 1e-5 and abs(a[1] - b[1]) < 1e-5 state = neg.run() assert len(neg.history) < 3 assert neg.agreement is not None assert neg.agreement == ("HP", "60 Gb", "19'' LCD") @pytest.mark.skipif( condition=not genius_bridge_is_running(), reason="No Genius Bridge, skipping genius-agent tests", ) def test_genius_agent_example(self, init_genius): agent_name1 = "agents.anac.y2015.Atlas3.Atlas3" agent_name2 = "agents.anac.y2015.Atlas3.Atlas3" single_issue = False keep_issue_names, keep_value_names = False, False utils = (1, 1) from negmas import convert_genius_domain_from_folder src = pkg_resources.resource_filename( "negmas", resource_name="tests/data/Laptop" ) dst = pkg_resources.resource_filename( "negmas", resource_name="tests/data/LaptopConv1D" ) if single_issue: assert convert_genius_domain_from_folder( src_folder_name=src, dst_folder_name=dst, force_single_issue=True, cache_and_discretize_outcomes=True, n_discretization=10, ) base_folder = dst else: base_folder = src neg, agent_info, issues = load_genius_domain_from_folder( base_folder, keep_issue_names=keep_issue_names, keep_value_names=keep_value_names, ) # atlas = GeniusNegotiator.random_negotiator( atlas = GeniusNegotiator( java_class_name=agent_name1, domain_file_name=base_folder + "/Laptop-C-domain.xml", utility_file_name=base_folder + f"/Laptop-C-prof{utils[0]}.xml", keep_issue_names=keep_issue_names, keep_value_names=keep_value_names, ) agentx = GeniusNegotiator( java_class_name=agent_name2, domain_file_name=base_folder + "/Laptop-C-domain.xml", utility_file_name=base_folder + f"/Laptop-C-prof{utils[1]}.xml", keep_issue_names=keep_issue_names, keep_value_names=keep_value_names, ) neg.add(atlas) neg.add(agentx) # print(agent_name1, agent_name2, neg.run(timeout=1)) if __name__ == "__main__": pytest.main(args=[__file__]) PK! negmas/tests/test_helpers.pyimport sys from enum import Enum import pytest from negmas.helpers import create_loggers, unique_name, is_nonzero_file, ConfigReader from negmas.helpers import pretty_string def test_create_loggers_with_default_params(capsys): log = create_loggers() log.info("Test info") _, captured = capsys.readouterr() assert captured == "" def disabled_test_create_loggers_with_file_params(capsys, tmpdir): file_name = tmpdir.join("log.txt") log = create_loggers( file_name=file_name, module_wide_log_file=True, app_wide_log_file=False ) log.info("Test info") # _, captured = capsys.readouterr() # assert captured == '' # with open(file_name, 'r') as f: # flog = f.read() # assert flog.endswith('INFO - Test info\n') log.warning("Test message") # _, captured = capsys.readouterr() # assert captured.endswith('WARNING - Test message\n') # with open(file_name, 'r') as f: # flog = f.read() # assert flog.endswith('WARNING - Test message\n') def test_unique_name_defaults(): a = unique_name("") assert len(a) == 8 + 1 + 6 + 8 def test_unique_name_no_time(): assert len(unique_name("", add_time=False)) == 8 def test_unique_name_with_path(tmpdir): a = unique_name(str(tmpdir)) assert a.startswith(str(tmpdir)) def test_is_nonzero_file(tmpdir): f_name = unique_name("") f = tmpdir / f_name assert is_nonzero_file(str(f)) is False with open(f, "w") as tst_file: tst_file.write("") assert is_nonzero_file(str(f)) is False with open(f, "w") as tst_file: tst_file.write("test") assert is_nonzero_file(str(f)) is True def test_pretty_string(capsys): assert pretty_string("Test with no components") == "Test with no components" assert pretty_string(4) == "4" assert pretty_string(2.5) == "2.5" assert pretty_string([1, 2, 3]) == "[\n 1\n 2\n 3\n]" assert pretty_string((1, 2, 3)) == "[\n 1\n 2\n 3\n]" assert pretty_string({"a": 1, "b": 2}) == "{\n a:1\n b:2\n}" assert pretty_string([1, 2, 3], compact=True) == "[ 1 2 3]" assert pretty_string((1, 2, 3), compact=True) == "[ 1 2 3]" assert pretty_string({"a": 1, "b": 2}, compact=True) == '{ "a":1 "b":2}' def test_config_reader(): class A(ConfigReader): def __init__(self, a, b): self.a = a self.b = b test, children = A.from_config( config={"a": 10, "b": [1, 2, 3]}, ignore_children=False, scope=locals() ) assert isinstance(test, A) assert test.a == 10 assert test.b == [1, 2, 3] def test_config_reader_with_enum(): class E(Enum): E1 = 1 E2 = 2 class A(ConfigReader): def __init__(self, a, b, e: E): self.a = a self.b = b self.e = e test, children = A.from_config( config={"a": 10, "b": [1, 2, 3], "e:E": 1}, ignore_children=False, scope=locals(), ) assert isinstance(test, A) assert test.a == 10 assert test.b == [1, 2, 3] assert test.e == E.E1 def test_config_reader_ignoring_children(): class A(ConfigReader): def __init__(self, a, b): self.a = a self.b = b test = A.from_config(config={"a": 10, "b": [1, 2, 3]}, scope=locals()) assert isinstance(test, A) assert test.a == 10 assert test.b == [1, 2, 3] class B(ConfigReader): def __init__(self, bb, bbdefault=5): self.bb = bb self.bbdefaults = bbdefault class Other(ConfigReader): def __init__(self, o): self.o = o class C(ConfigReader): def __init__(self, cc, b: B = None, others=None): self.cc = cc self.b = B self.others = others def set_others(self, others): self.others = others class A(ConfigReader): def __init__(self, a, b=None, c=None): self.a = a self.b = b self.c = c def test_config_reader_with_subobjects(): test = A.from_config( config={ "a": 10, "b": {"bb": 20}, "c": { "cc": 5, "b": {"bb": 20}, "others": [{"o": 1}, {"o": 2}, None, {"o": 3}], }, }, scope=globals(), ) assert isinstance(test, A) assert test.a == 10 assert isinstance(test.b, B) assert isinstance(test.c, C) assert isinstance(test.c.others, list) assert isinstance(test.c.others[0], Other) assert len(test.c.others) == 4 assert test.c.others[2] is None if __name__ == "__main__": pytest.main(args=[__file__]) PK!5 negmas/tests/test_inout.pyfrom os import walk import os import pkg_resources import pytest from negmas import load_genius_domain_from_folder, AspirationNegotiator @pytest.fixture def scenarios_folder(): return pkg_resources.resource_filename( "negmas", resource_name="tests/data/scenarios" ) def test_importing_file_without_exceptions(scenarios_folder): folder_name = scenarios_folder + "/other/S-1NIKFRT-1" domain = load_genius_domain_from_folder(folder_name, n_discretization=10) # print(domain) def test_convert_dir_keep_names(tmpdir): from negmas import convert_genius_domain_from_folder dst = tmpdir.mkdir("sub") src = pkg_resources.resource_filename("negmas", resource_name="tests/data/Laptop") dst = pkg_resources.resource_filename( "negmas", resource_name="tests/data/LaptopConv" ) assert convert_genius_domain_from_folder( src_folder_name=src, dst_folder_name=dst, force_single_issue=True, cache_and_discretize_outcomes=True, n_discretization=10, keep_issue_names=True, keep_value_names=True, normalize_utilities=True, ) mechanism, agent_info, issues = load_genius_domain_from_folder(dst) assert len(issues) == 1 for k, v in enumerate(issues): assert ( f"{k}:{v}" == """0:Laptop-Harddisk-External Monitor: ["Dell+60 Gb+19'' LCD", "Dell+60 Gb+20'' LCD", "Dell+60 Gb+23'' LCD", "Dell+80 Gb+19'' LCD", "Dell+80 Gb+20'' LCD", "Dell+80 Gb+23'' LCD", "Dell+120 Gb+19'' LCD", "Dell+120 Gb+20'' LCD", "Dell+120 Gb+23'' LCD", "Macintosh+60 Gb+19'' LCD", "Macintosh+60 Gb+20'' LCD", "Macintosh+60 Gb+23'' LCD", "Macintosh+80 Gb+19'' LCD", "Macintosh+80 Gb+20'' LCD", "Macintosh+80 Gb+23'' LCD", "Macintosh+120 Gb+19'' LCD", "Macintosh+120 Gb+20'' LCD", "Macintosh+120 Gb+23'' LCD", "HP+60 Gb+19'' LCD", "HP+60 Gb+20'' LCD", "HP+60 Gb+23'' LCD", "HP+80 Gb+19'' LCD", "HP+80 Gb+20'' LCD", "HP+80 Gb+23'' LCD", "HP+120 Gb+19'' LCD", "HP+120 Gb+20'' LCD", "HP+120 Gb+23'' LCD"]""" ) def test_convert_dir_no_names(tmpdir): from negmas import convert_genius_domain_from_folder dst = tmpdir.mkdir("sub") src = pkg_resources.resource_filename("negmas", resource_name="tests/data/Laptop") dst = pkg_resources.resource_filename( "negmas", resource_name="tests/data/LaptopConv" ) assert convert_genius_domain_from_folder( src_folder_name=src, dst_folder_name=dst, force_single_issue=True, cache_and_discretize_outcomes=True, n_discretization=10, keep_issue_names=False, keep_value_names=False, normalize_utilities=True, ) mechanism, agent_info, issues = load_genius_domain_from_folder(dst) assert len(issues) == 1 for k, v in enumerate(issues): assert ( f"{k}:{v}" == """0:0: ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12', '13', '14', '15', '16', '17', '18', '19', '20', '21', '22', '23', '24', '25', '26']""" ) def test_simple_run_with_aspiration_agents(): file_name = pkg_resources.resource_filename( "negmas", resource_name="tests/data/Laptop" ) assert os.path.exists(file_name) mechanism, agents, issues = load_genius_domain_from_folder( file_name, n_steps=100, time_limit=30, force_single_issue=True, keep_issue_names=False, keep_value_names=False, agent_factories=AspirationNegotiator, ) assert mechanism is not None state = mechanism.run() PK!]] negmas/tests/test_integration.pyfrom random import seed # seed(0) import pytest from pprint import pprint import time from negmas import UtilityDistribution as U import negmas start = time.monotonic() import os from negmas import HyperRectangleUtilityFunction from negmas import LimitedOutcomesNegotiator from negmas import SAOMechanism print(f"Import took {time.monotonic()-start}") 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 # print(f'Took {time.monotonic()-start}') if __name__ == "__main__": pytest.main(args=[__file__]) PK!T0qf negmas/tests/test_issue.pyfrom pytest import fixture import pytest from .fixtures import * from negmas import Issue def test_type(hamlet, cissue, dissue): assert cissue.type == "continuous", "Continuous type passes" assert dissue.type == "discrete", "int passes" assert hamlet.type == "discrete", "string list passes" hamlet.values = (1, 2) with pytest.raises(ValueError): print(hamlet.type) def test_is_continuous(cissue, dissue, hamlet): assert cissue.is_continuous() is True, "Continuous type passes" assert dissue.is_continuous() is False, "string list passes" assert hamlet.is_continuous() is False, "int passes" def test_is_discrete(cissue, dissue, hamlet): assert cissue.is_discrete() is False, "Continuous type passes" assert dissue.is_discrete() is True, "string list passes" assert hamlet.is_discrete() is True, "int passes" def test_string_conversion(uissue, hamlet): assert str(uissue).endswith(": ['val 0', 'val 1', 'val 2', 'val 3', 'val 4']") assert str(hamlet) == "THE problem: ['val 0', 'val 1', 'val 2', 'val 3', 'val 4']" def test_cartinatlity(cissue, dissue, hamlet): assert cissue.cardinality() == -1 assert hamlet.cardinality() == 5 assert dissue.cardinality() == 10 def test_n_outcomes(cissue, dissue, hamlet): assert Issue.n_outcomes([cissue, dissue, hamlet]) == -1 assert Issue.n_outcomes([dissue, hamlet]) == 50 assert Issue.n_outcomes([dissue]) == 10 assert Issue.n_outcomes([]) == 1 def test_rand(cissue, dissue, hamlet, bissue): for _ in range(100): assert 0.0 <= cissue.rand() < 1.0 assert 0 <= dissue.rand() < 10 assert hamlet.rand() in hamlet.values assert bissue.rand() in bissue.values def test_rand_invalid(cissue, dissue, hamlet, bissue): for _ in range(100): assert not 0.0 <= cissue.rand_invalid() < 1.0 assert not 0 <= dissue.rand_invalid() < 10 assert hamlet.rand_invalid() not in hamlet.values assert bissue.rand_invalid() not in bissue.values def test_possibilities(cissue, dissue, hamlet, bissue): with pytest.raises(ValueError): _ = list(cissue.all) assert len(list(dissue.all)) == 10 assert len(list(hamlet.all)) == 5 assert len(list(bissue.all)) == 2 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 test_issue_generation_multiples(): issues_ = Issue.generate([5], [10]) assert len(issues_) == 10 for i, issue in enumerate(issues_): assert issue.name.startswith(str(i)) assert issue.values == 5 if __name__ == "__main__": pytest.main(args=[__file__]) PK!> negmas/tests/test_negotiators.pyfrom typing import List import numpy as np import pytest from negmas import ( ToughNegotiator, SAOMechanism, AspirationNegotiator, OnlyBestNegotiator, SAOController, ) from negmas.utilities import RandomUtilityFunction 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_proposer == a1.id] a2offers = [s.current_offer for s in neg.history if s.current_proposer == 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_proposer == a1.id] a2offers = [s.current_offer for s in neg.history if s.current_proposer == 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_controller(): n_sessions = 5 c = SAOController( default_negotiator_type="negmas.sao.AspirationNegotiator", default_negotiator_params={"aspiration_type": "conceder"}, ) sessions = [SAOMechanism(outcomes=10, n_steps=10) for _ in range(n_sessions)] for session in sessions: session.add( AspirationNegotiator(aspiration_type="conceder"), ufun=RandomUtilityFunction(outcomes=session.outcomes), ) session.add( c.create_negotiator(), ufun=RandomUtilityFunction(outcomes=session.outcomes) ) completed: List[int] = [] while len(completed) < n_sessions: for i, session in enumerate(sessions): if i in completed: continue state = session.step() if state.broken or state.timedout or state.agreement is not None: completed.append(i) # we are just asserting that the controller runs if __name__ == "__main__": pytest.main(args=[__file__]) PK!@K  negmas/tests/test_outcomes.pyimport pytest import random from .fixtures import * from negmas import Issues, outcome_is_valid, outcome_in_range def test_dict_outcomes(issues, valid_outcome_dict, invalid_outcome_dict): assert outcome_is_valid(valid_outcome_dict, issues) assert not outcome_is_valid(invalid_outcome_dict, issues) def test_list_outcomes(int_issues, valid_outcome_list, invalid_outcome_list): assert outcome_is_valid(valid_outcome_list, int_issues) assert not outcome_is_valid(invalid_outcome_list, int_issues) def test_outcome_in_verious_ranges(): or1 = {"price": (0.0, 2.0), "distance": [0.3, 0.4], "type": ["a", "b"], "area": 3} or2 = {"price": [(0.0, 1.0), (1.5, 2.0)], "area": [(3, 4), (7, 9)]} assert outcome_in_range({"date": "2018.10.4"}, or1) assert not outcome_in_range({"date": "2018.10.4"}, or1, strict=True) assert outcome_in_range({"area": 3}, or1) assert not outcome_in_range({"type": "c"}, or1) assert outcome_in_range({"type": "a"}, or1) assert not outcome_in_range({"date": "2018.10.4"}, or2, strict=True) assert not outcome_in_range({"area": 3}, or2) assert outcome_in_range({"area": 3.0001}, or2) assert not outcome_in_range({"area": 5}, or2) assert outcome_in_range({"price": 0.4}, or2) assert not outcome_in_range({"price": 1.2}, or2) assert not outcome_in_range({"price": 0.4, "area": 4}, or2) assert not outcome_in_range({"price": 0.4, "area": 10}, or2) assert not outcome_in_range({"price": 1.2, "area": 10}, or2) assert not outcome_in_range({"price": 1.2, "area": 4}, or2) assert outcome_in_range({"type": "a"}, or2) or1 = {"price": 10} assert outcome_in_range({"price": 10}, or1) assert not outcome_in_range({"price": 11}, or1) 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: 10" 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.n_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_outcome_constraint(): r1 = { "price": [(0.0, 1.0), (3.0, 4.0)], "quantity": [1, 2, 4, 5], "delivery": "yes", } notr1 = {"price": [(3.01, 3.99), (4.01, 10.0)], "quantity": 3, "delivery": "no"} r2 = {"price": (3.01, 10.0), "quantity": [2, 3], "delivery": ["yes", "no"]} # r = OutcomeSpace(r1) if __name__ == "__main__": pytest.main(args=[__file__]) PK!׶**negmas/tests/test_protocols.pyfrom pprint import pprint from typing import Iterable import pytest import random from negmas import * random.seed(0) class MyMechanism(Mechanism): def __init__(self, dynamic_entry=True): super().__init__(outcomes=20, n_steps=10, dynamic_entry=dynamic_entry) self.current = 0 def round(self) -> MechanismRoundResult: # r = random.random() # if r > 1.0 / self.n_steps: # return None, False, None self.current += 1 if self.current < 6: return MechanismRoundResult(agreement=None) return MechanismRoundResult(agreement=self.random_outcomes(1)[0]) @pytest.fixture def mechanism(): return MyMechanism() @pytest.fixture def static_mechanism(): return MyMechanism(dynamic_entry=False) @pytest.fixture def dynamic_mechanism(): return MyMechanism(dynamic_entry=True) def test_set_requirements(mechanism): c = {"a": True, "b": [1, 2], "c": [1], "d": [1, 2], "e": False, "f": None} d = {"g": True} mechanism.requirements = c # print(mechanism.requirements) for k, v in c.items(): if isinstance(v, Iterable): assert [a == b for a, b in zip(mechanism.requirements[k], v)] else: assert mechanism.requirements[k] == v mechanism.add_requirements(d) for k, v in c.items(): if isinstance(v, Iterable): assert [a == b for a, b in zip(mechanism.requirements[k], v)] else: assert mechanism.requirements[k] == v for k, v in d.items(): if isinstance(v, Iterable): assert [a == b for a, b in zip(mechanism.requirements[k], v)] else: assert mechanism.requirements[k] == v def test_can_work_with_no_requirements(mechanism): assert mechanism.can_participate(RandomNegotiator(outcomes=mechanism.outcomes)) def test_can_check_compatibility(mechanism): c = {"a": True, "b": [1, 2, 3], "c": 1, "d": None, "f": 3} assert mechanism.is_satisfying(c) mechanism.add_requirements({"a": False}) assert not mechanism.is_satisfying(c) mechanism.add_requirements({"a": True}) assert mechanism.is_satisfying(c) mechanism.add_requirements({"g": False}) assert not mechanism.is_satisfying(c) mechanism.requirements = c assert mechanism.is_satisfying(c) mechanism.add_requirements({"g": False}) assert not mechanism.is_satisfying(c) mechanism.remove_requirements(["a", "g"]) assert mechanism.is_satisfying(c) mechanism.requirements = c assert mechanism.is_satisfying(c) mechanism.add_requirements({"a": not c["a"]}) assert not mechanism.is_satisfying(c) mechanism.add_requirements({"a": None}) assert mechanism.is_satisfying(c) mechanism.add_requirements({"a": not c["a"]}) assert not mechanism.is_satisfying(c) mechanism.add_requirements({"a": [True, False]}) assert mechanism.is_satisfying(c) class HasCapabilities(object): capabilities = c assert mechanism.can_participate(HasCapabilities()) def test_different_capability_types(mechanism): c = { "bvalue": True, "svalue": "abc", "ivalue": 1, "irange": (1, 5), "frange": (1.0, 5.0), "ilist": [1, 2, 9], } mechanism.requirements = c # single value assert mechanism.is_satisfying({**c, "bvalue": True}) assert not mechanism.is_satisfying({**c, "bvalue": False}) assert mechanism.is_satisfying({**c, "bvalue": [True, False]}) assert mechanism.is_satisfying({**c, "svalue": "abc"}) assert mechanism.is_satisfying({**c, "svalue": ["abc", "cde"]}) assert not mechanism.is_satisfying({**c, "svalue": "ab"}) assert not mechanism.is_satisfying({**c, "svalue": ["cc", "ab"]}) assert mechanism.is_satisfying({**c, "ivalue": 1}) assert not mechanism.is_satisfying({**c, "ivalue": 5}) # range assert not mechanism.is_satisfying({**c, "irange": [-1, 0]}) assert not mechanism.is_satisfying({**c, "irange": -1}) assert not mechanism.is_satisfying({**c, "irange": 0}) assert not mechanism.is_satisfying({**c, "irange": (-1, 0)}) assert mechanism.is_satisfying({**c, "irange": (0, 1)}) assert mechanism.is_satisfying({**c, "irange": [0, 1]}) assert mechanism.is_satisfying({**c, "irange": 1}) assert mechanism.is_satisfying({**c, "irange": (0, 2)}) assert mechanism.is_satisfying({**c, "irange": (2, 4)}) assert mechanism.is_satisfying({**c, "irange": (4, 5)}) assert mechanism.is_satisfying({**c, "irange": (4, 6)}) assert not mechanism.is_satisfying({**c, "irange": (6, 7)}) assert not mechanism.is_satisfying({**c, "frange": (-1, 0)}) assert mechanism.is_satisfying({**c, "frange": (0, 1)}) assert mechanism.is_satisfying({**c, "frange": (0, 2)}) assert mechanism.is_satisfying({**c, "frange": (2, 4)}) assert mechanism.is_satisfying({**c, "frange": (4, 5)}) assert mechanism.is_satisfying({**c, "frange": (4, 6)}) assert not mechanism.is_satisfying({**c, "frange": (6, 7)}) # list assert not mechanism.is_satisfying({**c, "ilist": (-1, 0)}) assert mechanism.is_satisfying({**c, "ilist": (0, 1)}) assert mechanism.is_satisfying({**c, "ilist": (3, 10)}) assert not mechanism.is_satisfying({**c, "ilist": [-1, 0]}) assert mechanism.is_satisfying({**c, "ilist": [0, 1]}) assert not mechanism.is_satisfying({**c, "ilist": [3, 10]}) assert not mechanism.is_satisfying({**c, "ilist": 0}) assert mechanism.is_satisfying({**c, "ilist": 9}) def test_can_accept_more_agents(mechanism): mechanism.max_n_agents = 2 assert mechanism.can_accept_more_agents() is True mechanism.add(RandomNegotiator(mechanism.outcomes), ufun=lambda x: 5.0) assert mechanism.can_accept_more_agents() is True mechanism.add(RandomNegotiator(mechanism.outcomes), ufun=lambda x: 5.0) assert mechanism.can_accept_more_agents() is False def test_dynamic_entry(static_mechanism: Mechanism): a = RandomNegotiator(static_mechanism.outcomes) assert static_mechanism.can_enter(a) assert not static_mechanism.can_leave(a) static_mechanism.add(a, ufun=lambda x: 5.0) static_mechanism.add( RandomNegotiator(static_mechanism.outcomes), ufun=lambda x: 5.0 ) def test_mechanism_fails_on_less_than_two_agents(static_mechanism): assert not static_mechanism.run().started static_mechanism.add( RandomNegotiator(static_mechanism.outcomes), ufun=lambda x: 5.0 ) assert not static_mechanism.run().started static_mechanism.add( RandomNegotiator(static_mechanism.outcomes), ufun=lambda x: 5.0 ) static_mechanism.run() assert len(static_mechanism.history) > 0 and static_mechanism.state.broken is False def test_mechanism_fails_on_less_than_two_agents_dynamic(dynamic_mechanism): assert not dynamic_mechanism.run().broken dynamic_mechanism.add( RandomNegotiator(dynamic_mechanism.outcomes), ufun=lambda x: 5.0 ) assert not dynamic_mechanism.run().broken dynamic_mechanism.add( RandomNegotiator(dynamic_mechanism.outcomes), ufun=lambda x: 5.0 ) dynamic_mechanism.run() assert ( len(dynamic_mechanism.history) > 0 and dynamic_mechanism.state.broken is False ) def test_mechanisms_get_some_rounds(): lengths = [] for _ in range(10): p = MyMechanism(dynamic_entry=False) p.add(RandomNegotiator(outcomes=10), ufun=lambda x: 5.0) p.add(RandomNegotiator(outcomes=10), ufun=lambda x: 5.0) p.run() lengths.append(len(p.history)) assert not all(_ < 2 for _ in lengths) # def test_alternating_offers_mechanism(): # 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 = LimitedOutcomesNegotiator(acceptable_outcomes=to_be_offered, outcomes=10) # a2 = LimitedOutcomesAcceptor(acceptable_outcomes=to_be_accepted, outcomes=10) # p.add(a1, ufun=MappingUtilityFunction(lambda x: x[0]+1.0)) # p.add(a2, ufun=MappingUtilityFunction(lambda x: x[0] + 1.0)) # p.run() # 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 offer' # assert p.agreement is None or p.agreement in to_be_accepted, 'acceptor accepted the correct offer' # assert all([_ in to_be_offered for _ in a1offers]) 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, outcomes=10) a2 = LimitedOutcomesAcceptor(acceptable_outcomes=to_be_accepted, outcomes=10) 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_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( outcomes=n_outcomes, 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_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( outcomes=n_outcomes, acceptable_outcomes=accepted, acceptance_probabilities=[1.0] * len(accepted), ) acceptor = LimitedOutcomesAcceptor( outcomes=n_outcomes, 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 if __name__ == "__main__": pytest.main(args=[__file__]) PK!|--negmas/tests/test_scml.pyimport copy from pprint import pprint from typing import List, Dict import numpy as np import pkg_resources import pytest from negmas.apps.scml import * from negmas.apps.scml import ( InputOutput, Job, FactoryStatusUpdate, GreedyScheduler, ProductionFailure, ) from negmas.situated import Contract # def test_can_create_a_random_scml_world(): # world = SCMLWorld.random() # assert len(world.products) > 0 # assert len(world.processes) > 0 # assert len(world.stats['market_size']) == 0 # winners = [_.name for _ in world.winners] # assert len(winners) == len(world.factory_managers) # for x in ('n_contract_executions', 'n_breaches', 'n_cfps_on_board', 'n_cfps'): # assert len(world.stats[x]) == 0 # def test_can_run_a_random_small_scml_world(): # world = SCMLWorld.random_small(log_file_name='', n_steps=200) # world.run() # print('') # for key in sorted(world.stats.keys()): # print(f'{key}:{world.stats[key]}') # winners = [_.name for _ in world.winners] # print('Winners: ', winners) # print('Losers: ', [_.name for _ in world.factory_managers if _.name not in winners]) # data = pd.DataFrame(data=world.saved_contracts).loc[:, ["buyer", "seller", "product", "quantity", "delivery_time" # , "unit_price", "penalty", "signing_delay", "concluded_at", "signed_at", "issues", "cfp"]] # data.to_csv(f'{logdir()}/contracts.csv') # # # def test_can_run_a_random_small_scml_world_with_delayed_signing(): # world = SCMLWorld.random_small(log_file_name='', n_steps=20, default_signing_delay=1) # world.run() # print('') # for key in sorted(world.stats.keys()): # print(f'{key}:{world.stats[key]}') # winners = [_.name for _ in world.winners] # print('Winners: ', winners) # print('Losers: ', [_.name for _ in world.factory_managers if _.name not in winners]) # data = pd.DataFrame(data=world.saved_contracts).loc[:, ["buyer", "seller", "product", "quantity", "delivery_time" # , "unit_price", "penalty", "signing_delay", "concluded_at", "signed_at", "issues", "cfp"]] # data.to_csv(f'{logdir()}/contracts.csv') # # # def test_can_run_a_random_small_scml_world_with_money_resolution(): # world = SCMLWorld.random_small(log_file_name='', n_steps=20, money_resolution=1) # world.run() # print('') # for key in sorted(world.stats.keys()): # print(f'{key}:{world.stats[key]}') # winners = [_.name for _ in world.winners] # print('Winners: ', winners) # print('Losers: ', [_.name for _ in world.factory_managers if _.name not in winners]) # data = pd.DataFrame(data=world.saved_contracts).loc[:, ["buyer", "seller", "product", "quantity", "delivery_time" # , "unit_price", "penalty", "signing_delay", "concluded_at", "signed_at", "issues", "cfp"]] # data.to_csv(f'{logdir()}/contracts.csv') def logdir(): return pkg_resources.resource_filename("negmas", resource_name="tests") def test_can_run_a_random_tiny_scml_world(): world = SCMLWorld.chain_world( log_file_name="", n_steps=5, n_factories_per_level=1, consumer_kwargs={ "negotiator_type": "negmas.sao.NiceNegotiator", "consumption_horizon": 2, } # , factory_kwargs={'max_insurance_premium': 100} , miner_kwargs={"negotiator_type": "negmas.sao.NiceNegotiator"}, ) world.run() # print('') # for key in sorted(world.stats.keys()): # print(f'{key}:{world.stats[key]}') winners = [_.name for _ in world.winners] # print('Winners: ', winners) # print('Losers: ', [_.name for _ in world.factory_managers if _.name not in winners]) # if len(world.saved_contracts) > 0: # data = pd.DataFrame(data=world.saved_contracts).loc[:, ["buyer", "seller", "product", "quantity", "delivery_time" # , "unit_price", "penalty", "signing_delay", "concluded_at", "signed_at", "issues", "cfp"]] # data.to_csv(f'{logdir()}/contracts.csv') def test_can_run_a_random_tiny_scml_world_no_immediate(): world = SCMLWorld.chain_world(log_file_name="", n_steps=5) world.run() def test_can_run_a_random_tiny_scml_world_with_insurance(): world = SCMLWorld.chain_world( log_file_name="", n_steps=5 # , factory_kwargs={'max_insurance_premium': 1e6} , consumer_kwargs={"negotiator_type": "negmas.sao.NiceNegotiator"}, miner_kwargs={"negotiator_type": "negmas.sao.NiceNegotiator"}, ) world.run() # @settings(max_examples=50) # @given(horizon=st.sampled_from([None, 10, 50, 100, 500]), # immediate=st.booleans(), # signing_delay=st.integers(0, 3), # n_factory_levels=st.integers(1, 5), # n_factories_per_level=st.integers(1, 5) # ) # def test_can_run_a_random_tiny_scml_world_with_n_factories(horizon, immediate, signing_delay # , n_factory_levels, n_factories_per_level): # n_steps = 500 # world = SCMLWorld.tiny(n_intermediate_levels=n_factory_levels - 1, log_file_name='', n_steps=n_steps # , n_factories_per_level=n_factories_per_level # , default_signing_delay=signing_delay # , consumer_kwargs={'immediate_cfp_update': immediate, 'consumption_horizon': horizon # , 'negotiator_type': 'NiceNegotiator'} # , miner_kwargs={'negotiator_type': 'NiceNegotiator' # , 'use_immediate_negotiations': immediate} # , factory_kwargs={'max_insurance_premium': -1 # , 'use_immediate_negotiations': immediate} # ) # world.run() # print('') # for key in sorted(world.stats.keys()): # print(f'{key}:{world.stats[key]}') # winners = [_.name for _ in world.winners] # print('Winners: ', winners) # print('Losers: ', [_.name for _ in world.factory_managers if _.name not in winners]) # # assert sum(world.stats['n_contracts_concluded']) > 0 # # assert sum(world.stats['n_contracts_signed']) > 0 # # assert len(winners) < len(world.factory_managers) def test_can_run_a_random_tiny_scml_world_with_linear_production(): horizon = None signing_delay = 0 n_factory_levels = 0 n_factories_per_level = 2 n_steps = 10 world = SCMLWorld.chain_world( n_intermediate_levels=n_factory_levels - 1, log_file_name="", n_steps=n_steps, n_factories_per_level=n_factories_per_level, default_signing_delay=signing_delay, consumer_kwargs={ "consumption_horizon": horizon, "negotiator_type": "negmas.sao.NiceNegotiator", }, miner_kwargs={"negotiator_type": "negmas.sao.NiceNegotiator"}, ) world.run() assert sum(world.stats["n_contracts_concluded"]) > 0 def test_can_run_a_random_tiny_scml_world_with_no_factory(): n_steps = 10 world = SCMLWorld.chain_world( n_intermediate_levels=-1, log_file_name="", n_steps=n_steps, negotiation_speed=None, ) world.run() # print('') # for key in sorted(world.stats.keys()): # print(f'{key}:{world.stats[key]}') assert world.stats["n_negotiations"][0] >= n_steps - 1, ( "at least n negotiations occur where n is the number of " "steps - 1" ) assert world.stats["n_negotiations"][2:] == [0] * ( len(world.stats["n_negotiations"]) - 2 ), ("All negotiations " "happen in steps 0, 1") assert sum(world.stats["n_contracts_concluded"]) >= sum( world.stats["n_contracts_signed"] ), "some contracts signed" assert sum(world.stats["n_breaches"]) == 0, "No breaches" assert sum(world.stats["market_size"]) == 0, "No change in the market size" # data = pd.DataFrame(data=world.saved_contracts).loc[:, ["buyer", "seller", "product", "quantity", "delivery_time" # , "unit_price", "penalty", "signing_delay", "concluded_at", "signed_at", "issues", "cfp"]] # data.to_csv(f'{logdir()}/contracts.csv') def test_can_run_a_random_tiny_scml_world_with_no_factory_finite_horizon(): n_steps = 5 horizon = n_steps // 2 world = SCMLWorld.chain_world( n_intermediate_levels=-1, log_file_name="", n_steps=n_steps, consumer_kwargs={"consumption_horizon": horizon}, ) world.run() # print('') # for key in sorted(world.stats.keys()): # print(f'{key}:{world.stats[key]}') # assert world.stats['n_negotiations'][0] >= horizon - 1, "at least n negotiations occur where n is the number of " \ # "horizon - 1" assert sum(world.stats["n_contracts_concluded"]) >= sum( world.stats["n_contracts_signed"] ), "all contracts signed" assert sum(world.stats["n_breaches"]) == 0, "No breaches" assert sum(world.stats["market_size"]) == 0, "No change in the market size" # data = pd.DataFrame(data=world.saved_contracts).loc[:, ["buyer", "seller", "product", "quantity", "delivery_time" # , "unit_price", "penalty", "signing_delay", "concluded_at", "signed_at", "issues", "cfp"]] # data.to_csv(f'{logdir()}/contracts.csv') def test_can_run_a_random_tiny_scml_world_with_no_factory_with_delay(): n_steps = 10 world = SCMLWorld.chain_world( n_intermediate_levels=-1, log_file_name="", n_steps=n_steps, default_signing_delay=1, ) world.run() # print('') # for key in sorted(world.stats.keys()): # print(f'{key}:{world.stats[key]}') assert world.stats["n_negotiations"][0] >= n_steps - 1, ( "at least n negotiations occur where n is the number of " "steps - 1" ) # assert world.stats['n_negotiations'][1:] == [0] * (len(world.stats['n_negotiations']) - 1), "All negotiations " \ # "happen in step 0" assert sum(world.stats["n_contracts_concluded"]) >= sum( world.stats["n_contracts_signed"] ), "all contracts signed" assert sum(world.stats["n_breaches"]) == 0, "No breaches" assert sum(world.stats["market_size"]) == 0, "No change in the market size" # data = pd.DataFrame(data=world.saved_contracts).loc[:, ["buyer", "seller", "product", "quantity", "delivery_time" # , "unit_price", "penalty", "signing_delay", "concluded_at", "signed_at", "issues", "cfp"]] # data.to_csv(f'{logdir()}/contracts.csv') def test_can_run_a_random_tiny_scml_world_with_no_factory_with_delay_no_immediate_neg(): n_steps = 10 horizon = 4 world = SCMLWorld.chain_world( n_intermediate_levels=-1, log_file_name="", n_steps=n_steps, default_signing_delay=1, consumer_kwargs={"immediate_cfp_update": False, "consumption_horizon": horizon}, ) world.run() # print('') # for key in sorted(world.stats.keys()): # print(f'{key}:{world.stats[key]}') # assert world.stats['n_negotiations'][0] >= horizon - 1, "at least n negotiations occur where n is the number of " \ # "horizon - 1" assert sum(world.stats["n_contracts_concluded"]) >= world.stats[ "n_contracts_concluded" ][-1] + sum(world.stats["n_contracts_signed"]), "some contracts signed" assert sum(world.stats["n_breaches"]) == 0, "No breaches" assert sum(world.stats["market_size"]) == 0, "No change in the market size" if __name__ == "__main__": pytest.main(args=[__file__]) PK!nnegmas/tests/test_situated.pyfrom typing import ( List, Optional, Tuple, Dict, Any, Union, Callable, Set, Iterable, Collection, ) import pytest from negmas import ( Issue, AspirationNegotiator, LinearUtilityAggregationFunction, Mechanism, Negotiator, SAOMechanism, Mechanism, Negotiator, RenegotiationRequest, AgentMechanismInterface, MechanismState, ) from negmas.helpers import ConfigReader from negmas.situated import World, Agent, Action, Breach, Contract results = [] # will keep results not to use printing class DummyWorld(World): def _complete_contract_execution( self, contract: Contract, breaches: List[Breach], resolved: bool ) -> None: pass def _contract_finalization_time(self, contract: Contract) -> int: return self.current_step + 1 def _contract_execution_time(self, contract: Contract) -> int: return self.current_step def _contract_size(self, contract: Contract) -> float: return 0.0 def __init__(self, n_steps=10000, negotiation_speed=None): super().__init__(n_steps=n_steps, negotiation_speed=negotiation_speed) self.the_agents = [] def join(self, x: "Agent", simulation_priority: int = 0): super().join(x=x, simulation_priority=simulation_priority) self.the_agents.append(x) def _delete_executed_contracts(self) -> None: pass def _get_executable_contracts(self) -> Collection[Contract]: return [] def _post_step_stats(self): pass def _pre_step_stats(self): pass def _contract_execution_order( self, contracts: Collection[Contract] ) -> Collection[Contract]: return contracts def _contract_record(self, contract: Contract) -> Dict[str, Any]: return contract.__dict__ def _execute_contract(self, contract: Contract) -> Set[Breach]: return set() def _process_breach( self, contract: Contract, breaches: List[Breach], force_immediate_signing=True ) -> Optional[Contract]: return None def _breach_record(self, breach: Breach): return breach.__dict__ def execute( self, action: Action, agent: "Agent", callback: Callable = None ) -> bool: return True def get_private_state(self, agent: "Agent") -> Any: s = {"partners": [_ for _ in self.the_agents if _ is not agent]} return s def _simulation_step(self): pass class DummyAgent(Agent): def init(self): pass def _respond_to_negotiation_request( self, initiator: str, partners: List[str], issues: List[Issue], annotation: Dict[str, Any], mechanism: AgentMechanismInterface, role: Optional[str], req_id: Optional[str], ) -> Optional[Negotiator]: negotiator = AspirationNegotiator( ufun=LinearUtilityAggregationFunction( issue_utilities=[lambda x: 1.0 - x / 10.0] ) ) return negotiator def on_neg_request_rejected(self, req_id: str, by: Optional[List[str]]): pass def on_neg_request_accepted(self, req_id: str, mechanism: AgentMechanismInterface): pass def on_negotiation_failure( self, partners: List[str], annotation: Dict[str, Any], mechanism: AgentMechanismInterface, state: MechanismState, ) -> None: pass def on_negotiation_success( self, contract: Contract, mechanism: AgentMechanismInterface ) -> None: pass def on_contract_signed(self, contract: Contract) -> None: pass def on_contract_cancelled(self, contract: Contract, rejectors: List[str]) -> None: pass def sign_contract(self, contract: Contract) -> Optional[str]: pass def set_renegotiation_agenda( self, contract: Contract, breaches: List[Breach] ) -> Optional[RenegotiationRequest]: return None def respond_to_renegotiation_request( self, contract: Contract, breaches: List[Breach], agenda: RenegotiationRequest ) -> Optional[Negotiator]: return None def __init__(self, name=None): super().__init__(name=name) self.id = name self.current_step = 0 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 test_world_runs_with_some_negs(capsys): global results results = [] world = DummyWorld(n_steps=10) world.join(DummyAgent("A1")) world.join(DummyAgent("A2")) world.run() assert "A1: step 1" in results, "first step logged" assert "A2: step 1" in results, "first step logged" assert "A1 started negotiation with A2" in results, "negotiation started" assert f"A1: step {world.n_steps-1}" in results, "last step logged" assert f"A2: step {world.n_steps-1}" in results, "last step logged" assert len(world._saved_contracts) == 2 assert sum(world.stats["n_negotiations"]) == 2 def test_config_reader_with_a_world(): world = DummyWorld() assert world.bulletin_board is not None assert world.n_steps == 10000 world = DummyWorld.from_config(scope=globals(), config={"n_steps": 10}) assert world.bulletin_board is not None assert world.n_steps == 10 def test_config_reader_with_a_world_with_enum(): from negmas.situated import BulletinBoard, World world = DummyWorld() assert world.bulletin_board is not None assert world.n_steps == 10000 world = DummyWorld.from_config( scope=globals(), config={"n_steps": 10, "negotiation_speed": 2} ) assert world.bulletin_board is not None assert world.n_steps == 10 assert world.negotiation_speed == 2 if __name__ == "__main__": pytest.main(args=[__file__]) PK!Wnegmas/tests/test_utilities.pyimport pytest from negmas import * 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 test_linear_utility(): buyer_utility = LinearUtilityAggregationFunction( { "cost": lambda x: -x, "number of items": lambda x: 0.5 * x, "delivery": {"delivered": 10.0, "not delivered": -2.0}, } ) assert ( buyer_utility({"cost": 1.0, "number of items": 3, "delivery": "not delivered"}) == -1.0 + 1.5 - 2.0 ) def test_hypervolume_utility(): f = HyperRectangleUtilityFunction( outcome_ranges=[ None, {0: (1.0, 2.0), 1: (1.0, 2.0)}, {0: (1.4, 2.0), 2: (2.0, 3.0)}, ], utilities=[5.0, 2.0, lambda x: 2 * x[2] + x[0]], ) f_ignore_input = HyperRectangleUtilityFunction( outcome_ranges=[ None, {0: (1.0, 2.0), 1: (1.0, 2.0)}, {0: (1.4, 2.0), 2: (2.0, 3.0)}, ], utilities=[5.0, 2.0, lambda x: 2 * x[2] + x[0]], ignore_issues_not_in_input=True, ) f_ignore_failing = HyperRectangleUtilityFunction( outcome_ranges=[ None, {0: (1.0, 2.0), 1: (1.0, 2.0)}, {0: (1.4, 2.0), 2: (2.0, 3.0)}, ], utilities=[5.0, 2.0, lambda x: 2 * x[2] + x[0]], ignore_failing_range_utilities=True, ) f_ignore_both = HyperRectangleUtilityFunction( outcome_ranges=[ None, {0: (1.0, 2.0), 1: (1.0, 2.0)}, {0: (1.4, 2.0), 2: (2.0, 3.0)}, ], utilities=[5.0, 2.0, lambda x: 2 * x[2] + x[0]], ignore_failing_range_utilities=True, ignore_issues_not_in_input=True, ) g = HyperRectangleUtilityFunction( outcome_ranges=[{0: (1.0, 2.0), 1: (1.0, 2.0)}, {0: (1.4, 2.0), 2: (2.0, 3.0)}], utilities=[2.0, lambda x: 2 * x[2] + x[0]], ) g_ignore_input = HyperRectangleUtilityFunction( outcome_ranges=[{0: (1.0, 2.0), 1: (1.0, 2.0)}, {0: (1.4, 2.0), 2: (2.0, 3.0)}], utilities=[2.0, lambda x: 2 * x[2] + x[0]], ignore_issues_not_in_input=True, ) g_ignore_failing = HyperRectangleUtilityFunction( outcome_ranges=[{0: (1.0, 2.0), 1: (1.0, 2.0)}, {0: (1.4, 2.0), 2: (2.0, 3.0)}], utilities=[2.0, lambda x: 2 * x[2] + x[0]], ignore_failing_range_utilities=True, ) g_ignore_both = HyperRectangleUtilityFunction( outcome_ranges=[{0: (1.0, 2.0), 1: (1.0, 2.0)}, {0: (1.4, 2.0), 2: (2.0, 3.0)}], utilities=[2.0, lambda x: 2 * x[2] + x[0]], ignore_failing_range_utilities=True, ignore_issues_not_in_input=True, ) funs = [ g, g_ignore_input, g_ignore_failing, g_ignore_both, f, f_ignore_input, f_ignore_failing, f_ignore_both, ] outcomes = [ [1.5, 1.5, 2.5], # belongs to all volumes [1.5, 1.5, 1.0], # belongs to first {0: 1.5, 2: 2.5}, {0: 11.5, 1: 11.5, 2: 12.5}, [1.5], {2: 2.5}, ] expected = [ [8.5, 8.5, 8.5, 8.5, 13.5, 13.5, 13.5, 13.5], [2.0, 2.0, 2.0, 2.0, 7.0, 7.0, 7.0, 7.0], [None, 6.5, None, 6.5, None, 11.5, None, 11.5], [0.0, 0.0, 0.0, 0.0, 5.0, 5.0, 5.0, 5.0], [None, 0.0, None, 0.0, None, 5.0, None, 5.0], [None, 0.0, None, 0.0, None, 5.0, None, 5.0], ] for outcome, expectation in zip(outcomes, expected): utilities = [f(outcome) for f in funs] for i, (u, e) in enumerate(zip(utilities, expectation)): # print(i, utilities, outcome) assert u == e if __name__ == "__main__": pytest.main(args=[__file__]) PK!G9o9onegmas/tournaments.py""" Tournament generation and management. """ import concurrent.futures as futures import copy import itertools import math import pathlib import time import traceback import warnings from dataclasses import dataclass, field from os import PathLike from pathlib import Path from typing import Optional, List, Callable, Union, Type, Sequence, Dict, Any, Tuple import numpy as np import pandas as pd import yaml from typing_extensions import Protocol from negmas.helpers import ( get_class, unique_name, import_by_name, get_full_type_name, humanize_time, dump, ) from .situated import Agent, World, save_stats __all__ = [ "tournament", "WorldGenerator", "WorldRunResults", "TournamentResults", "run_world", "process_world_run", ] PROTOCOL_CLASS_NAME_FIELD = "__mechanism_class_name" try: # disable a warning in yaml 1b1 version yaml.warnings({"YAMLLoadWarning": False}) except: pass class WorldGenerator(Protocol): """A callback-protocol specifying the signature of a world generator function that can be passed to `tournament` Args: kwargs: key-value pairs of arguments. See Also: `tournament` """ def __call__(self, **kwargs) -> World: ... class ConfigGenerator(Protocol): """A callback-protocol specifying the signature of a config generator function that can be passed to `tournament` Args: n_competitors: Number of competitor types n_agents_per_competitor: Number of agents to instantiate for each competitor agent_names_reveal_type: whether agent names contain their types (used for debugging purposes). kwargs: key-value pairs of arguments. See Also: `tournament` `ConfigAssigner` """ def __call__( self, n_competitors: int, n_agents_per_competitor: int, agent_names_reveal_type: bool = False, compact: bool = False, **kwargs, ) -> Dict[str, Any]: ... class ConfigAssigner(Protocol): """A callback-protocol specifying the signature of a function that can be used to assign competitors to a config generated using a `ConfigGenerator` Args: config: The dict returned from the `ConfigGenerator` max_n_worlds: Maximum allowed number of worlds to generate from this config n_agents_per_competitor: Number of agents to instantiate for each competitor competitors: A list of `Agent` types that can be used to create the competitors params: A list of parameters to pass to the agent types See Also: `ConfigGenerator` `tournament` """ def __call__( self, config: Dict[str, Any], max_n_worlds: int, n_agents_per_competitor: int = 1, competitors: Sequence[Type[Agent]] = (), params: Sequence[Dict[str, Any]] = (), ) -> List[Dict[str, Any]]: ... @dataclass class WorldRunResults: """Results of a world run""" world_name: str """World name""" log_file_name: str """Log file name""" names: List[str] = field(default_factory=list, init=False) """Agent names""" scores: List[float] = field(default_factory=list, init=False) """Agent scores""" types: List[str] = field(default_factory=list, init=False) """Agent type names""" @dataclass class TournamentResults: scores: pd.DataFrame total_scores: pd.DataFrame winners: List[str] """Winner type name(s) which may be a list""" winners_scores: np.array """Winner score (accumulated)""" ttest: pd.DataFrame def run_world(world_params: dict, dry_run: bool = False, save_world_stats: bool = True): """Runs a world and returns stats. This function is designed to be used with distributed systems like dask. Args: world_params: World info dict. See remarks for its parameters dry_run: If true, the world will not be run. Only configs will be saved save_world_stats: If true, saves individual world stats Remarks: The `world_params` dict should have the following members: - name: world name [Defaults to random] - log_file_name: file name to store the world log [Defaults to random] - __dir_name: directory to store the world stats [Defaults to random] - __world_generator: full name of the world generator function (including its module) [Required] - __score_calculator: full name of the score calculator function [Required] - __tournament_name: name of the tournament [Defaults to random] - others: values of all other keys are passed to the world generator as kwargs """ world_generator = world_params.get("__world_generator", None) score_calculator = world_params.get("__score_calculator", None) tournament_name = world_params.get("__tournament_name", unique_name(base="")) assert world_generator and score_calculator, ( f"Cannot run without specifying both a world generator and a score " f"calculator" ) world_generator = import_by_name(world_generator) score_calculator = import_by_name(score_calculator) default_name = unique_name(base="") world_params["name"] = world_params.get("name", default_name) world_name = world_params["name"] default_dir = ( Path(f"~") / "negmas" / "tournaments" / tournament_name / world_name ).absolute() world_params["log_file_name"] = world_params.get( "log_file_name", str(default_dir / "log.txt") ) world_params["__dir_name"] = world_params.get("__dir_name", str(default_dir)) # delete the parameters not used by _run_world for k in ("__world_generator", "__tournament_name", "__score_calculator"): if k in world_params.keys(): world_params.pop(k, None) return _run_world( world_params=world_params, world_generator=world_generator, score_calculator=score_calculator, dry_run=dry_run, save_world_stats=save_world_stats, ) def _run_world( world_params: dict, world_generator: WorldGenerator, score_calculator: Callable[[World, bool], WorldRunResults], world_progress_callback: Callable[[Optional[World]], None] = None, dry_run: bool = False, save_world_stats: bool = True, ) -> Tuple[WorldRunResults, str]: """Runs a world and returns stats Args: world_params: World info dict. See remarks for its parameters world_generator: World generator function. score_calculator: Score calculator function. world_progress_callback: world progress callback dry_run: If true, the world is not run. Its config is saved instead. save_world_stats: If true, saves individual world stats Returns: A tuple with the list of `WorldRunResults` for all the worlds generated using this config and the directory in which these results are stored Remarks: - The `world_params` dict should have the following members: - name: world name - log_file_name: file name to store the world log - __dir_name: directory to store the world stats - others: values of all other keys are passed to the world generator as kwargs """ world_params = world_params.copy() dir_name = world_params["__dir_name"] world_params.pop("__dir_name", None) world = world_generator(**world_params) if dry_run: world.save_config(dir_name) scores = score_calculator(world, True) return scores, dir_name if world_progress_callback is None: world.run() else: _start_time = time.monotonic() for _ in range(world.n_steps): if ( world.time_limit is not None and (time.monotonic() - _start_time) >= world.time_limit ): break if not world.step(): break world_progress_callback(world) if save_world_stats: save_stats(world=world, log_dir=dir_name) scores = score_calculator(world, False) return scores, dir_name def process_world_run( results: WorldRunResults, tournament_name: str, dir_name: str, save_world_stats: bool = True, ) -> pd.DataFrame: """ Generates a dataframe with the results of this world run Args: results: Results of the world run tournament_name: tournament name dir_name: directory name to store the stats. save_world_stats: It True, it will be assumed that world stats are saved Returns: A pandas DataFrame with agent_name, agent_type, score, log_file, world, and stats_folder columns """ log_file, world_name_ = results.log_file_name, results.world_name if save_world_stats and log_file is not None and pathlib.Path(log_file).exists(): with open(log_file, "a") as f: f.write( f"\nPART of TOURNAMENT {tournament_name}. This world run completed successfully\n" ) scores = [] for name_, type_, score in zip(results.names, results.types, results.scores): scores.append( { "agent_name": name_, "agent_type": type_, "score": score, "log_file": log_file, "world": world_name_, "stats_folder": dir_name, } ) return pd.DataFrame(data=scores) def _run_dask( scheduler_ip, scheduler_port, verbose, world_infos, world_generator, tournament_progress_callback, n_worlds, name, score_calculator, dry_run, save_world_stats, ) -> List[pd.DataFrame]: """Runs the tournament on dask""" import distributed scores = [] if scheduler_ip is None and scheduler_port is None: address = None else: if scheduler_ip is None: scheduler_ip = "127.0.0.1" if scheduler_port is None: scheduler_port = "8786" address = f"{scheduler_ip}:{scheduler_port}" if verbose: print(f"Will use DASK on {address}") client = distributed.Client(address=address, set_as_default=True) future_results = [] for world_info in world_infos: future_results.append( client.submit( _run_world, world_info, world_generator, score_calculator, None, dry_run, save_world_stats, ) ) print(f"Submitted all processes to DASK ({len(world_infos)})") _strt = time.perf_counter() for i, (future, result) in enumerate( distributed.as_completed(future_results, with_results=True, raise_errors=False) ): try: score_, dir_name = result if tournament_progress_callback is not None: tournament_progress_callback(score_, i, n_worlds) scores.append( process_world_run(score_, tournament_name=name, dir_name=str(dir_name)), save_world_stats=save_world_stats, ) if verbose: _duration = time.perf_counter() - _strt print( f"{i + 1:003} of {n_worlds:003} [{100 * (i + 1) / n_worlds:0.3}%] completed in " f"{humanize_time(_duration)} [ETA {humanize_time(_duration * n_worlds / (i + 1))}]" ) except Exception as e: if tournament_progress_callback is not None: tournament_progress_callback(None, i, n_worlds) print(traceback.format_exc()) print(e) client.shutdown() return scores def tournament( competitors: Sequence[Union[str, Type[Agent]]], config_generator: ConfigGenerator, config_assigner: ConfigAssigner, world_generator: WorldGenerator, score_calculator: Callable[[World, bool], WorldRunResults], competitor_params: Optional[Sequence[Dict[str, Any]]] = None, agent_names_reveal_type=False, n_agents_per_competitor=1, n_configs: int = 10, max_worlds_per_config: int = 100, n_runs_per_world: int = 5, max_n_configs: int = None, n_runs_per_config: int = None, tournament_path: str = "./logs/tournaments", total_timeout: Optional[int] = None, parallelism="parallel", scheduler_ip: Optional[str] = None, scheduler_port: Optional[str] = None, tournament_progress_callback: Callable[ [Optional[WorldRunResults], int, int], None ] = None, world_progress_callback: Callable[[Optional[World]], None] = None, name: str = None, verbose: bool = False, configs_only: bool = False, compact: bool = False, **kwargs, ) -> Union[TournamentResults, PathLike]: """ Runs a tournament Args: name: Tournament name config_generator: Used to generate unique configs that will be used to evaluate competitors config_assigner: Used to generate assignments of competitors to the configs created by the `config_generator` world_generator: A functions to generate worlds for the tournament that follows the assignments made by the `config_assigner` score_calculator: A function for calculating the score of all agents in a world *After it finishes running*. The second parameter is a boolean specifying whether this is a dry_run. For dry runs, scores are not expected but names and types should exist in the returned `WorldRunResults`. competitors: A list of class names for the competitors competitor_params: A list of competitor parameters (used to initialize the competitors). agent_names_reveal_type: If true then the type of an agent should be readable in its name (most likely at its beginning). n_configs: The number of different world configs (up to competitor assignment) to be generated. max_worlds_per_config: The maximum number of worlds to run per config. If None, then all possible assignments of competitors within each config will be tried (all permutations). n_runs_per_world: Number of runs per world. All of these world runs will have identical competitor assignment and identical world configuration. n_agents_per_competitor: The number of agents of each competing type to be instantiated in the world. max_n_configs: [Depricated] The number of configs to use (it is replaced by separately setting `n_config` and `max_worlds_per_config` ) n_runs_per_config: [Depricated] The number of runs (simulation) for every config. It is replaced by `n_runs_per_world` total_timeout: Total timeout for the complete process tournament_path: Path at which to store all results. A scores.csv file will keep the scores and logs folder will keep detailed logs parallelism: Type of parallelism. Can be 'serial' for serial, 'parallel' for parallel and 'distributed' for distributed! scheduler_port: Port of the dask scheduler if parallelism is dask, dist, or distributed scheduler_ip: IP Address of the dask scheduler if parallelism is dask, dist, or distributed world_progress_callback: A function to be called after every step of every world run (only allowed for serial and parallel evaluation and should be used with cautious). tournament_progress_callback: A function to be called with `WorldRunResults` after each world finished processing verbose: Verbosity configs_only: If true, a config file for each compact: If true, compact logs will be created and effort will be made to reduce the memory footprint kwargs: Arguments to pass to the `config_generator` function Returns: `TournamentResults` The results of the tournament or a `PathLike` giving the location where configs were saved """ if max_n_configs is not None or n_runs_per_config is not None: n_runs_per_world = ( n_runs_per_config if n_runs_per_config is not None else n_runs_per_world ) n_configs = max(1, int(math.log2(max_n_configs))) max_worlds_per_config = int(0.5 + max_n_configs / n_configs) warnings.warn( f"max_n_configs and n_runs_per_config are deprecated and will be removed in future versions. " f"Use n_configs, max_worlds_per_config n_runs_per_world instead." f"\nWill use the following settings: n_configs ({n_configs})" f", max_worlds_per_config ({max_worlds_per_config})" f", and n_runs_per_world ({n_runs_per_world})." ) if n_runs_per_world is None or n_configs is None: raise ValueError( f"Values for n_configs ({n_configs})" f", and n_runs_per_world ({n_runs_per_world}) must be given or possible to calculate " f"from max_n_configs ({max_n_configs}) and n_runs_per_config ({n_runs_per_config})" ) dask_options = ("dist", "distributed", "dask", "d") multiprocessing_options = ("local", "parallel", "par", "p") serial_options = ("none", "serial", "s") if parallelism is None: parallelism = "serial" assert ( total_timeout is None or parallelism not in dask_options ), f"Cannot use {parallelism} with a total-timeout" assert world_progress_callback is None or parallelism not in dask_options, ( f"Cannot use {parallelism} with a " f"world callback" ) if name is None: name = unique_name("", add_time=True, rand_digits=0) competitors = list(competitors) if tournament_path.startswith("~"): tournament_path = Path.home() / ("/".join(tournament_path.split("/")[1:])) tournament_path = (pathlib.Path(tournament_path) / name).absolute() tournament_path.mkdir(parents=True, exist_ok=True) if verbose: print(f"Results of Tournament {name} will be saved to {str(tournament_path)}") if competitor_params is None: competitor_params = [dict() for _ in range(len(competitors))] params = { "competitors": [ get_class(_).__name__ if not isinstance(_, str) else _ for _ in competitors ], "params": competitor_params, "n_agents_per_competitor": n_agents_per_competitor, "tournament_path": str(tournament_path), "total_timeout": total_timeout, "parallelism": parallelism, "scheduler_ip": scheduler_ip, "scheduler_port": scheduler_port, "name": name, "n_configs": n_configs, "n_world_per_config": max_worlds_per_config, "n_runs_per_world": n_runs_per_world, "n_worlds": None, } params.update(kwargs) dump(params, tournament_path / "params") configs = [ config_generator( n_competitors=len(competitors), n_agents_per_competitor=n_agents_per_competitor, agent_names_reveal_type=agent_names_reveal_type, compact=compact, **kwargs, ) for _ in range(n_configs) ] dump(configs, tournament_path / "base_configs") if verbose: print( f"Will run {len(configs)} different base world configurations ({parallelism})", flush=True, ) assigned = list( itertools.chain( *[ config_assigner( config=c, max_n_worlds=max_worlds_per_config, n_agents_per_competitor=n_agents_per_competitor, competitors=competitors, params=competitor_params, ) for c in configs ] ) ) params["n_worlds"] = len(assigned) * n_runs_per_world dump(params, tournament_path / "params") dump(assigned, tournament_path / "assigned_configs") if verbose: print( f"Will run {len(assigned)} different factory/manager assignments ({parallelism})", flush=True, ) assigned = list(itertools.chain(*([assigned] * n_runs_per_world))) for config in assigned: dir_name = tournament_path / config["world_params"]["name"] config.update( {"log_file_name": str(dir_name / "log.txt"), "__dir_name": str(dir_name)} ) config["world_params"].update({"log_file_name": str(dir_name / "log.txt")}) saved_configs = [ { k: copy.copy(v) if k != "competitors" else [get_full_type_name(c) if not isinstance(c, str) else c for c in v] for k, v in _.items() } for _ in assigned ] score_calculator_name = ( get_full_type_name(score_calculator) if not isinstance(score_calculator, str) else score_calculator ) world_generator_name = ( get_full_type_name(world_generator) if not isinstance(world_generator, str) else world_generator ) for d in saved_configs: d["__score_calculator"] = score_calculator_name d["__world_generator"] = world_generator_name d["__tournament_name"] = name config_path = tournament_path / "configs" config_path.mkdir(exist_ok=True, parents=True) for i, conf in enumerate(saved_configs): f_name = config_path / f"{i:06}" dump(conf, f_name) scores_list = [] scores_file = str(tournament_path / "scores.csv") n_world_configs = len(assigned) if verbose: print( f"Will run {n_world_configs} total world simulations ({parallelism})", flush=True, ) if parallelism in serial_options: strt = time.perf_counter() for i, world_params in enumerate(assigned): if total_timeout is not None and time.perf_counter() - strt > total_timeout: break try: score_, _ = _run_world( world_params=world_params, world_generator=world_generator, world_progress_callback=world_progress_callback, score_calculator=score_calculator, dry_run=configs_only, save_world_stats=not compact, ) if tournament_progress_callback is not None: tournament_progress_callback(score_, i, n_world_configs) scores_list.append( process_world_run( score_, tournament_name=name, dir_name=str(world_params["__dir_name"]), save_world_stats=not compact, ) ) if verbose: _duration = time.perf_counter() - strt print( f"{i + 1:003} of {n_world_configs:003} [{(i + 1) / n_world_configs:.02%}] " f'{"saved" if configs_only else "completed"} ' f"in {humanize_time(_duration)}" f" [ETA {humanize_time(_duration * n_world_configs / (i + 1))}]" ) except Exception as e: if tournament_progress_callback is not None: tournament_progress_callback(None, i, n_world_configs) print(traceback.format_exc()) print(e) elif parallelism in multiprocessing_options: executor = futures.ProcessPoolExecutor(max_workers=None) future_results = [] for world_params in assigned: future_results.append( executor.submit( _run_world, world_params, world_generator, score_calculator, world_progress_callback, configs_only, not compact, ) ) if verbose: print(f"Submitted all processes ({len(assigned)})") _strt = time.perf_counter() for i, future in enumerate( futures.as_completed(future_results, timeout=total_timeout) ): try: score_, dir_name = future.result() if tournament_progress_callback is not None: tournament_progress_callback(score_, i, n_world_configs) scores_list.append( process_world_run( score_, tournament_name=name, dir_name=str(dir_name), save_world_stats=not compact, ) ) if verbose: _duration = time.perf_counter() - _strt print( f"{i + 1:003} of {n_world_configs:003} [{100 * (i + 1) / n_world_configs:0.3}%] " f'{"saved" if configs_only else "completed"} in ' f"{humanize_time(_duration)}" f" [ETA {humanize_time(_duration * n_world_configs / (i + 1))}]" ) except futures.TimeoutError: if tournament_progress_callback is not None: tournament_progress_callback(None, i, n_world_configs) print("Tournament timed-out") break except Exception as e: if tournament_progress_callback is not None: tournament_progress_callback(None, i, n_world_configs) print(traceback.format_exc()) print(e) elif parallelism in dask_options: scores_list = _run_dask( scheduler_ip, scheduler_port, verbose, assigned, world_generator, tournament_progress_callback, n_world_configs, name, score_calculator, configs_only, not compact, ) if configs_only: return config_path if verbose: print(f"Finding winners") if len(scores_list) < 1: return TournamentResults( scores=pd.DataFrame(), total_scores=pd.DataFrame(), winners=[], winners_scores=np.array([]), ttest=pd.DataFrame(), ) scores: pd.DataFrame = pd.concat(scores_list, ignore_index=True) scores = pd.DataFrame(data=scores) scores.to_csv(scores_file, index_label="index") scores = scores.loc[~scores["agent_type"].isnull(), :] scores = scores.loc[scores["agent_type"].str.len() > 0, :] total_scores = ( scores.groupby(["agent_type"])["score"] .mean() .sort_values(ascending=False) .reset_index() ) winner_table = total_scores.loc[ total_scores["score"] == total_scores["score"].max(), : ] winners = winner_table["agent_type"].values.tolist() winner_scores = winner_table["score"].values types = list(scores["agent_type"].unique()) ttest_results = [] for i, t1 in enumerate(types): for j, t2 in enumerate(types[i + 1 :]): from scipy.stats import ttest_ind t, p = ttest_ind( scores[scores["agent_type"] == t1].score, scores[scores["agent_type"] == t2].score, ) ttest_results.append({"a": t1, "b": t2, "t": t, "p": p}) if verbose: print( f"Tournament completed successfully\nWinners: {list(zip(winners, winner_scores))}" ) scores.to_csv(str(tournament_path / "scores.csv"), index_label="index") total_scores.to_csv(str(tournament_path / "total_scores.csv"), index_label="index") winner_table.to_csv(str(tournament_path / "winners.csv"), index_label="index") ttest_results = pd.DataFrame(data=ttest_results) ttest_results.to_csv(str(tournament_path / "ttest.csv"), index_label="index") return TournamentResults( scores=scores, total_scores=total_scores, winners=winners, winners_scores=winner_scores, ttest=ttest_results, ) PK!NVnegmas/utilities.pyr"""Models basic types of utility functions. Utility functions are at the core of negotiation. Agents engage in negotiations with the goal of maximizing some utility function. In most cases, these utility functions are assumed to be known a-periori and static for the duration of a single negotiations. Notes: We try to allow for applications that do not necessary have these two assumptions in the following ways: * A utility_function *value* (\ `UtilityValue`\ ) can always represent represent a utility_function distribution over all possible utility_function values (\ `UtilityDistribution`\ ) or a `KnownUtilityValue` which is a real number. * The base class of all utility_function *functions* is `UtilityFunction` and is assumed to map outcomes (\ `Outcome` objects) to the aforementioned generic utility *values* (\ `UtilityValue` objects). * Utility functions can be constructed using any `Callable` which makes it possible to construct them so that they change depending on the context or the progression of the negotiation. """ import itertools import pprint import random import xml.etree.ElementTree as ET from abc import ABC, abstractmethod from functools import reduce from operator import mul from typing import ( MutableMapping, Mapping, Union, Optional, Any, Sequence, Callable, Dict, List, Iterable, Tuple, Collection, ) from typing import TYPE_CHECKING import numpy as np import pkg_resources from negmas.common import NamedObject from negmas.common import AgentMechanismInterface from negmas.generics import GenericMapping, ienumerate, iget, ivalues from negmas.helpers import Distribution from negmas.helpers import snake_case, gmap, ikeys, Floats from negmas.java import JavaCallerMixin, to_java from negmas.outcomes import ( sample_outcomes, OutcomeRange, Outcome, outcome_in_range, Issue, outcome_is_valid, OutcomeType, outcome_as_dict, ) if TYPE_CHECKING: from negmas.outcomes import OutcomeRange, Outcome __all__ = [ "UtilityDistribution", "UtilityValue", "UtilityFunction", "ConstUFun", "LinDiscountedUFun", "ExpDiscountedUFun", "MappingUtilityFunction", "LinearUtilityAggregationFunction", "NonLinearUtilityAggregationFunction", "HyperRectangleUtilityFunction", "NonlinearHyperRectangleUtilityFunction", "ComplexWeightedUtilityFunction", "ComplexNonlinearUtilityFunction", "IPUtilityFunction", "pareto_frontier", "make_discounted_ufun", "normalize", "JavaUtilityFunction", "RandomUtilityFunction", ] # Helper Types just used to make type hinting more readable OutcomeUtilityMapping = Union[ Callable[[Union["Outcome", int, str, float]], "UtilityValue"], Mapping[Union[Sequence, Mapping, int, str, float], "UtilityValue"], ] OutcomeUtilityMappings = List[OutcomeUtilityMapping] """Maps from multi-issue or single-issue outcomes to Negotiator values.""" IssueUtilityFunctionMapping = Union[ # type: ignore Callable[["Issue"], "UtilityFunction"], # type: ignore Mapping["Issue", "UtilityFunction"], # type: ignore ] # type: ignore IssueUtilityFunctionMappings = List[IssueUtilityFunctionMapping] UtilityDistribution = Distribution class ExactUtilityValue(float): """Encapsulates a single offerable_outcomes utility_function value.""" UtilityValue = Union[UtilityDistribution, float] """Either a utility_function distribution or an exact offerable_outcomes utility_function value. `UtilityFunction`s always return a `UtilityValue` which makes it easier to implement algorithms relying on probabilistic modeling of utility_function values.""" class UtilityFunction(ABC, NamedObject): """The abstract base class for all utility functions. A utility function encapsulates a mapping from outcomes to UtilityValue(s). This is a generalization of standard utility functions that are expected to always return a real-value. This generalization is useful for modeling cases in which only partial knowledge of the utility function is available. Args: name (str): Name of the utility function. If None, a random name will be given. reserved_value(float): The value to return if the input offer to `apply` is None """ def __init__( self, name: Optional[str] = None, ami: AgentMechanismInterface = None, reserved_value: Optional[UtilityValue] = 0.0, ) -> None: super().__init__(name=name) self.reserved_value = reserved_value self.ami = ami @property def is_dynamic(self): """Whether the utility function can potentially depend on negotiation state (mechanism information). - If this property is `False`, the ufun can safely be assumed to be static (not dependent on negotiation state). - If this property is `True`, the ufun may depend on negotiation state but it may also not depend on it. """ return self.ami is None @classmethod def from_genius(cls, file_name: str, **kwargs): """Imports a utility function from a GENIUS XML file. Args: file_name (str): File name to import from Returns: A utility function object (depending on the input file) Examples: >>> from negmas import UtilityFunction >>> u, d = UtilityFunction.from_genius(file_name = pkg_resources.resource_filename('negmas' ... , resource_name='tests/data/Laptop/Laptop-C-prof1.xml')) >>> u.__class__.__name__ 'LinearUtilityAggregationFunction' >>> u.reserved_value 0.0 >>> d 1.0 Remarks: See ``from_xml_str`` for all the parameters """ with open(file_name, "r") as f: xml_str = f.read() return cls.from_xml_str(xml_str=xml_str, **kwargs) @classmethod def to_genius( cls, u: "UtilityFunction", issues: List[Issue], file_name: str, **kwargs ): """Exports a utility function from a GENIUS XML file. Args: file_name (str): File name to export to u: utility function issues: The issues being considered as defined in the domain Returns: None Examples: >>> from negmas import UtilityFunction >>> from negmas import load_genius_domain >>> _, _, issues = load_genius_domain(domain_file_name=pkg_resources.resource_filename('negmas' ... , resource_name='tests/data/Laptop/Laptop-C-domain.xml') ... , keep_issue_names=False) >>> u, discount = UtilityFunction.from_genius(file_name=pkg_resources.resource_filename('negmas' ... , resource_name='tests/data/Laptop/Laptop-C-prof1.xml') ... , keep_issue_names=False) >>> UtilityFunction.to_genius(u=u, issues=issues, discount_factor=discount ... , file_name = pkg_resources.resource_filename('negmas' ... , resource_name='tests/data/LaptopConv/Laptop-C-prof1.xml')) Remarks: See ``to_xml_str`` for all the parameters """ with open(file_name, "w") as f: f.write(cls.to_xml_str(u=u, issues=issues, **kwargs)) @classmethod def to_xml_str( cls, u: "UtilityFunction", issues: List[Issue], discount_factor=None ) -> str: """Exports a utility function to a well formatted string """ if issues is not None: n_issues = len(issues) else: n_issues = 0 output = ( f'\n' f'\n' ) output += u.xml(issues=issues) if "" not in output: output += "\n" if discount_factor is not None: output += f'\n' if u.reserved_value is not None and "\n' if "" not in output: output += "\n" return output @classmethod def from_xml_str( cls, xml_str: str, domain_issues: Optional[List[Issue]] = None, force_single_issue=False, keep_issue_names=True, keep_value_names=True, safe_parsing=True, normalize_utility=True, max_n_outcomes: int = 1e6, ignore_discount=False, ignore_reserved=False, ): """Imports a utility function from a GENIUS XML string. Args: xml_str (str): The string containing GENIUS style XML utility function definition domain_issues (List[Issue]): Optional issue space to confirm that the utility function is valid force_single_issue (bool): Tries to generate a MappingUtility function with a single issue which is the product of all issues in the input keep_issue_names (bool): Keep names of issues keep_value_names (bool): Keep names of values safe_parsing (bool): Turn on extra checks normalize_utility (bool): Normalize the output utilities to the range from 0 to 1 max_n_outcomes (int): Maximum number of outcomes allowed (effective only if force_single_issue is True) Returns: A utility function object (depending on the input file) Examples: >>> u, _ = UtilityFunction.from_xml_str(open(pkg_resources.resource_filename('negmas' ... , resource_name='tests/data/Laptop/Laptop-C-prof1.xml') ... , 'r').read(), force_single_issue=False ... , normalize_utility=True, keep_issue_names=False, keep_value_names=True) >>> assert abs(u(('Dell', '60 Gb', "19'' LCD")) - 0.599329436957658) < 0.1 >>> assert abs(u(('HP', '80 Gb', "20'' LCD")) - 0.6342209804130308) < 0.01 >>> assert abs(u(('HP', '60 Gb', "19'' LCD")) - 1.0) < 0.0001 >>> u, _ = UtilityFunction.from_xml_str(open(pkg_resources.resource_filename('negmas' ... , resource_name='tests/data/Laptop/Laptop-C-prof1.xml') ... , 'r').read() ... , force_single_issue=True, normalize_utility=False) >>> assert abs(u(("Dell+60 Gb+19'' LCD",)) - 21.987727736172488) < 0.000001 >>> assert abs(u(("HP+80 Gb+20'' LCD",)) - 22.68559475583014) < 0.000001 >>> u, _ = UtilityFunction.from_xml_str(open(pkg_resources.resource_filename('negmas' ... , resource_name='tests/data/Laptop/Laptop-C-prof1.xml') ... , 'r').read(), force_single_issue=True ... , keep_issue_names=False, keep_value_names=False, normalize_utility=False) >>> assert abs(u((0,)) - 21.987727736172488) < 0.000001 >>> u, _ = UtilityFunction.from_xml_str(open(pkg_resources.resource_filename('negmas' ... , resource_name='tests/data/Laptop/Laptop-C-prof1.xml') ... , 'r').read(), force_single_issue=False, normalize_utility=False) >>> assert abs(u({'Laptop': 'Dell', 'Harddisk': '60 Gb', 'External Monitor': "19'' LCD"}) - 21.987727736172488) < 0.000001 >>> assert abs(u({'Laptop': 'HP', 'Harddisk': '80 Gb', 'External Monitor': "20'' LCD"}) - 22.68559475583014) < 0.000001 >>> u, _ = UtilityFunction.from_xml_str(open(pkg_resources.resource_filename('negmas' ... , resource_name='tests/data/Laptop/Laptop-C-prof1.xml') ... , 'r').read() ... , force_single_issue=True, normalize_utility=True) >>> assert abs(u(("Dell+60 Gb+19'' LCD",)) - 0.599329436957658) < 0.1 >>> assert abs(u(("HP+80 Gb+20'' LCD",)) - 0.6342209804130308) < 0.01 >>> u, _ = UtilityFunction.from_xml_str(open(pkg_resources.resource_filename('negmas' ... , resource_name='tests/data/Laptop/Laptop-C-prof1.xml') ... , 'r').read(), force_single_issue=True ... , keep_issue_names=False, keep_value_names=False, normalize_utility=True) >>> assert abs(u((0,)) - 0.599329436957658) < 0.1 >>> u, _ = UtilityFunction.from_xml_str(open(pkg_resources.resource_filename('negmas' ... , resource_name='tests/data/Laptop/Laptop-C-prof1.xml') ... , 'r').read(), force_single_issue=False, normalize_utility=True) >>> assert abs(u({'Laptop': 'Dell', 'Harddisk': '60 Gb', 'External Monitor': "19'' LCD"}) - 0.599329436957658) < 0.1 >>> assert abs(u({'Laptop': 'HP', 'Harddisk': '80 Gb', 'External Monitor': "20'' LCD"}) - 0.6342209804130308) < 0.01 >>> assert abs(u({'Laptop': 'HP', 'Harddisk': '60 Gb', 'External Monitor': "19'' LCD"}) - 1.0) < 0.0001 """ root = ET.fromstring(xml_str) if safe_parsing and root.tag != "utility_space": raise ValueError(f"Root tag is {root.tag}: Expected utility_space") if domain_issues is not None: if isinstance(domain_issues, list): domain_issues: Dict[str, Issue] = dict( zip([_.name for _ in domain_issues], domain_issues) ) elif isinstance(domain_issues, Issue) and force_single_issue: domain_issues = dict(zip([domain_issues.name], [domain_issues])) objective = None reserved_value = 0.0 discount_factor = 0.0 for child in root: if child.tag == "objective": objective = child elif child.tag == "reservation": reserved_value = float(child.attrib["value"]) elif child.tag == "discount_factor": discount_factor = float(child.attrib["value"]) if objective is None: if safe_parsing: pass # raise ValueError(f'No objective child was found in the root') objective = root weights = {} issues = {} real_issues = {} issue_info = {} issue_keys = {} rects, rect_utils = [], [] def _get_hyperrects(ufun, max_utility, utiltype=float): utype = ufun.attrib.get("type", "none") uweight = float(ufun.attrib.get("weight", 1)) uagg = ufun.attrib.get("aggregation", "sum") if uagg != "sum": raise ValueError( f"Hypervolumes combined using {uagg} are not supported (only sum is supported)" ) total_util = utiltype(0) rects = [] rect_utils = [] if utype == "PlainUfun": for rect in ufun: util = utiltype(rect.attrib.get("utility", 0)) total_util += util if util > 0 else 0 ranges = {} rect_utils.append(util * uweight) for r in rect: key = issue_keys[int(r.attrib["index"]) - 1] ranges[key] = ( utiltype(r.attrib["min"]), utiltype(r.attrib["max"]), ) rects.append(ranges) else: raise ValueError(f"Unknown ufun type {utype}") total_util = total_util if max_utility is None else max_utility if normalize_utility: for i, u in enumerate(rect_utils): rect_utils[i] = u / total_util return rects, rect_utils for child in objective: if child.tag == "weight": indx = int(child.attrib["index"]) - 1 weights[indx] = float(child.attrib["value"]) elif child.tag == "utility_function" or child.tag == "utility": utility_tag = child max_utility = child.attrib.get("maxutility", None) if max_utility is not None: max_utility = float(max_utility) ufun_found = False for ufun in utility_tag: if ufun.tag == "ufun": ufun_found = True _r, _u = _get_hyperrects(ufun, max_utility) rects += _r rect_utils += _u if not ufun_found: raise ValueError( f"Cannot find ufun tag inside a utility_function tag" ) elif child.tag == "issue": indx = int(child.attrib["index"]) - 1 myname = child.attrib["name"] issue_key = myname if keep_issue_names else indx if domain_issues is not None and myname not in domain_issues.keys(): raise ValueError( f"Issue {myname} is not in the input issue names ({domain_issues.keys()})" ) issue_info[issue_key] = {"name": myname, "index": indx} issue_keys[indx] = issue_key info = {"type": "discrete", "etype": "discrete", "vtype": "discrete"} for a in ("type", "etype", "vtype"): info[a] = child.attrib.get(a, info[a]) mytype = info["type"] value_scale = None value_shift = None if mytype == "discrete": issues[issue_key] = {} if ( domain_issues is not None and domain_issues[myname].is_continuous() ): raise ValueError( f"Got a {mytype} issue but expected a continuous valued issue" ) # issues[indx]['items'] = {} elif mytype in ("integer", "real"): lower, upper = ( child.attrib.get("lowerbound", None), child.attrib.get("upperbound", None), ) for rng_child in child: if rng_child.tag == "range": lower, upper = ( rng_child.attrib.get("lowerbound", lower), rng_child.attrib.get("upperbound", upper), ) if mytype == "integer": issues[issue_key] = {} if ( domain_issues is not None and domain_issues[myname].is_continuous() ): raise ValueError( f"Got a {mytype} issue but expected a continuous valued issue" ) # issues[indx]['items'] = {} lower, upper = int(lower), int(upper) for i in range(lower, upper + 1): if domain_issues is not None and not outcome_is_valid( (i,), [domain_issues[myname]] ): raise ValueError( f"Value {i} is not in the domain issue values: " f"{domain_issues[myname].values}" ) issues[issue_key][i] = i if keep_value_names else i - lower else: lower, upper = float(lower), float(upper) if ( domain_issues is not None and not domain_issues[myname].is_continuous() ): n_steps = domain_issues[myname].cardinality() delta = (n_steps - 1) / (upper - lower) value_shift = -lower * delta value_scale = delta lower, upper = 0, n_steps - 1 issues[issue_key] = {} for i in range(lower, upper + 1): issues[issue_key][i] = ( str(i) if keep_value_names else i - lower ) else: real_issues[issue_key] = {} real_issues[issue_key]["range"] = (lower, upper) real_issues[issue_key]["key"] = issue_key else: raise ValueError(f"Unknown type: {mytype}") if mytype in "discrete" or "integer" or "real": found_values = False for item in child: if item.tag == "item": if mytype == "real": raise ValueError( f"cannot specify item utilities for real type" ) item_indx = int(item.attrib["index"]) - 1 item_name: str = item.attrib.get("value", None) if item_name is None: continue item_key = ( item_name if keep_value_names and item_name is not None else item_indx ) if domain_issues is not None: domain_all = list(domain_issues[myname].all) if len(domain_all) > 0 and isinstance( domain_all[0], int ): item_key = int(item_key) if len(domain_all) > 0 and isinstance( domain_all[0], int ): item_name = int(item_name) if item_name not in domain_all: raise ValueError( f"Value {item_name} is not in the domain issue values: " f"{domain_issues[myname].values}" ) if len(domain_all) > 0 and isinstance( domain_all[0], int ): item_name = str(item_name) if mytype == "integer": item_key = int(item_key) issues[issue_key][item_key] = float( item.attrib.get("evaluation", reserved_value) ) found_values = True elif item.tag == "evaluator": if item.attrib["ftype"] == "linear": offset = item.attrib.get( "offset", item.attrib.get("parameter0", 0.0) ) slope = item.attrib.get( "slope", item.attrib.get("parameter1", 1.0) ) offset, slope = float(offset), float(slope) if value_scale is None: fun = lambda x: offset + slope * float(x) else: fun = lambda x: offset + slope * ( value_scale * float(x) + value_shift ) elif item.attrib["ftype"] == "triangular": strt = item.attrib.get("parameter0", 0.0) end = item.attrib.get("parameter1", 1.0) middle = item.attrib.get("parameter2", 1.0) strt, end, middle = ( float(strt), float(end), float(middle), ) offset1, slope1 = strt, (middle - strt) offset2, slope2 = middle, (middle - end) if value_scale is None: fun = ( lambda x: offset1 + slope1 * float(x) if x < middle else offset2 + slope2 * float(x) ) else: fun = ( lambda x: offset1 + slope1 * (value_scale * float(x) + value_shift) if x < middle else offset2 + slope2 * (value_scale * float(x) + value_shift) ) else: raise ValueError( f'Unknown ftype {item.attrib["ftype"]}' ) if mytype == "real" and value_scale is None: real_issues[issue_key]["fun"] = fun else: for item_key, value in issues[issue_key].items(): issues[issue_key][item_key] = fun(value) found_values = True if not found_values and issue_key in issues.keys(): issues.pop(issue_key, None) else: """Here goes the code for real-valued issues""" # if not keep_issue_names: # issues = [issues[_] for _ in issues.keys()] # real_issues = [real_issues[_] for _ in sorted(real_issues.keys())] # for i, issue in enumerate(issues): # issues[i] = [issue[_] for _ in issue.keys()] if safe_parsing and ( len(weights) > 0 and len(weights) != len(issues) + len(real_issues) and len(weights) != len(issues) ): raise ValueError( f"Got {len(weights)} weights for {len(issues)} issues and {len(real_issues)} real issues" ) if force_single_issue and ( len(rects) > 0 or len(real_issues) > 1 or (len(real_issues) > 0 and len(issues) > 0) ): raise ValueError( f"Cannot force single issue with a hyper-volumes based function" ) # add utilities specified not as hyper-rectangles u = None if len(issues) > 0: if len(weights) > 0: for key, issue in zip(ikeys(issues), ivalues(issues)): try: w = weights[issue_info[key]["index"]] except: w = 1.0 for item_key in ikeys(issue): issue[item_key] *= w if force_single_issue: n_outcomes = None if max_n_outcomes is not None: n_items = [len(_) for _ in ivalues(issues)] n_outcomes = reduce(mul, n_items, 1) if n_outcomes > max_n_outcomes: return None, reserved_value, discount_factor if keep_value_names: names = itertools.product( *[ [ str(item_key).replace("&", "-") for item_key in ikeys(items) ] for issue_key, items in zip(ikeys(issues), ivalues(issues)) ] ) names = map(lambda items: ("+".join(items),), names) else: if n_outcomes is None: n_items = [len(_) for _ in ivalues(issues)] n_outcomes = reduce(mul, n_items, 1) names = [(_,) for _ in range(n_outcomes)] utils = itertools.product( *[ [item_utility for item_utility in ivalues(items)] for issue_key, items in zip(ikeys(issues), ivalues(issues)) ] ) utils = map(lambda vals: sum(vals), utils) if normalize_utility: utils = list(utils) umax, umin = max(utils), min(utils) if umax != umin: utils = [(_ - umin) / (umax - umin) for _ in utils] if keep_issue_names: u = MappingUtilityFunction(dict(zip(names, utils))) else: u = MappingUtilityFunction(dict(zip(names, utils))) else: utils = None if normalize_utility: utils = itertools.product( *[ [item_utility for item_utility in ivalues(items)] for issue_key, items in zip(ikeys(issues), ivalues(issues)) ] ) utils = list(map(lambda vals: sum(vals), utils)) umax, umin = max(utils), min(utils) factor = umax - umin if factor > 1e-8: offset = (umin / len(issues)) / factor else: offset = 0.0 factor = 1.0 for key, issue in ienumerate(issues): for item_key in ikeys(issue): issues[key][item_key] = ( issues[key][item_key] / factor - offset ) if len(issues) > 1: u = LinearUtilityAggregationFunction(issue_utilities=issues) else: first_key = list(ikeys(issues))[0] if utils is None: utils = ivalues(issues[first_key]) if keep_issue_names: u = MappingUtilityFunction( dict(zip([(_,) for _ in ikeys(issues[first_key])], utils)) ) else: u = MappingUtilityFunction( dict(zip([(_,) for _ in range(len(utils))], utils)) ) # add real_valued issues if len(real_issues) > 0: if len(weights) > 0: for key, issue in zip(ikeys(real_issues), ivalues(real_issues)): try: w = weights[issue_info[key]["index"]] except: w = 1.0 issue["fun_final"] = lambda x: w * issue["fun"](x) if normalize_utility: n_items_to_test = 10 utils = itertools.product( *[ [ issue["fun"](_) for _ in np.linspace( issue["range"][0], issue["range"][1], num=n_items_to_test, endpoint=True, ) ] for key, issue in zip(ikeys(real_issues), ivalues(real_issues)) ] ) utils = list(map(lambda vals: sum(vals), utils)) umax, umin = max(utils), min(utils) factor = umax - umin if factor > 1e-8: offset = (umin / len(real_issues)) / factor else: offset = 0.0 factor = 1.0 for key, issue in real_issues.items(): issue["fun_final"] = lambda x: w * issue["fun"](x) / factor - offset u_real = LinearUtilityAggregationFunction( issue_utilities={_["key"]: _["fun_final"] for _ in real_issues.values()} ) if u is None: u = u_real else: u = ComplexWeightedUtilityFunction( ufuns=[u, u_real], weights=[1.0, 1.0] ) # add hyper rectangles issues if len(rects) > 0: uhyper = HyperRectangleUtilityFunction( outcome_ranges=rects, utilities=rect_utils ) if u is None: u = uhyper else: u = ComplexWeightedUtilityFunction( ufuns=[u, uhyper], weights=[1.0, 1.0] ) if reserved_value is not None and not ignore_reserved and u is not None: u.reserved_value = reserved_value if ignore_discount: discount_factor = None return u, discount_factor @abstractmethod def __call__(self, offer: Outcome) -> Optional[UtilityValue]: """Calculate the utility_function value for a given outcome. Args: offer: The offer to be evaluated. Remarks: - You cannot return None from overriden apply() functions but raise an exception (ValueError) if it was not possible to calculate the UtilityValue. - Return A UtilityValue not a float for real-valued utilities for the benefit of inspection code. Returns: UtilityValue: The utility_function value which may be a distribution. If `None` it means the utility_function value cannot be calculated. """ if offer is None: return self.reserved_value return None @classmethod def approximate( cls, ufuns: List["UtilityFunction"], issues: Iterable["Issue"], n_outcomes: int, min_per_dim=5, force_single_issue=False, ) -> Tuple[List["MappingUtilityFunction"], List["Outcome"], List["Issue"]]: """ Args: cls: ufuns: issues: n_outcomes: min_per_dim: force_single_issue: Returns: """ issues = list(issues) outcomes = sample_outcomes( issues=issues, keep_issue_names=False, min_per_dim=min_per_dim, expansion_policy="null", n_outcomes=n_outcomes, ) if force_single_issue: output_outcomes = [(_,) for _ in range(n_outcomes)] output_issues = [Issue(values=len(output_outcomes))] else: output_outcomes = outcomes issue_values = [] for i in range(len(issues)): vals = np.unique(np.array([_[i] for _ in outcomes])).tolist() issue_values.append(vals) output_issues = [ Issue(name=issue.name, values=issue_vals) for issue, issue_vals in zip(issues, issue_values) ] utils = [] for ufun in ufuns: u = [ufun(o) for o in outcomes] utils.append(MappingUtilityFunction(mapping=dict(zip(output_outcomes, u)))) return utils, output_outcomes, output_issues def compare(self, o1, o2) -> "UtilityValue": """Compares the two outcomes and returns a measure of the difference between their utilities""" u1, u2 = self(o1), self(o2) if isinstance(u1, float) and isinstance(u2, float): return u1 - u2 raise NotImplementedError( "Should calculate the integration [(u1-u2) du1 du2] but not implemented yet." ) @abstractmethod def xml(self, issues: List[Issue]) -> str: """Converts the function into a well formed XML string preferrably in GENIUS format. If the output has with then discount factor and reserved value should also be included If the output has it will not be appended in `to_xml_str` """ @property def type(self) -> str: """Returns the utility_function type. Each class inheriting from this ``UtilityFunction`` class will have its own type. The default type is the empty string. Examples: >>> from negmas.utilities import * >>> print(LinearUtilityAggregationFunction({1:lambda x:x, 2:lambda x:x}).type) linear_aggregation >>> print(MappingUtilityFunction(lambda x: x).type) mapping >>> print(NonLinearUtilityAggregationFunction({1:lambda x:x}, f=lambda x: x).type) non_linear_aggregation Returns: str: utility_function type """ return snake_case( self.__class__.__name__.replace("Function", "").replace("Utility", "") ) @property def base_type(self) -> str: """Returns the utility_function base type ignoring discounting and similar wrappings.""" return self.type def eu(self, offer: "Outcome") -> Optional[float]: """Calculate the expected utility_function value. Args: offer: The offer to be evaluated. Returns: float: The expected utility_function for utility_priors and just utility_function for real-valued utilities. """ v = self(offer) return float(v) if v is not None else None @classmethod def generate_bilateral( cls, outcomes: Union[int, List[Outcome]], conflict_level: float = 0.5, conflict_delta=0.005, win_win=0.5, ) -> Tuple["UtilityFunction", "UtilityFunction"]: """Generates a couple of utility functions Args: n_outcomes (int): number of outcomes to use conflict_level: How conflicting are the two ufuns to generate. 1.0 means maximum conflict. conflict_delta: How variable is the conflict at different outcomes. zero_summness: How zero-sum like are the two ufuns. Examples: >>> u1, u2 = UtilityFunction.generate_bilateral(outcomes=10, conflict_level=0.0 ... , conflict_delta=0.0, win_win=0.0) >>> print(UtilityFunction.conflict_level(u1, u2, outcomes=10)) 0.0 >>> u1, u2 = UtilityFunction.generate_bilateral(outcomes=10, conflict_level=1.0 ... , conflict_delta=0.0, win_win=0.0) >>> print(UtilityFunction.conflict_level(u1, u2, outcomes=10)) 1.0 >>> u1, u2 = UtilityFunction.generate_bilateral(outcomes=10, conflict_level=0.5 ... , conflict_delta=0.0, win_win=1.0) >>> 0.0 <= UtilityFunction.conflict_level(u1, u2, outcomes=10) <= 1.0 True """ if isinstance(outcomes, int): outcomes = [(_,) for _ in range(outcomes)] n_outcomes = len(outcomes) u1 = np.random.random(n_outcomes) rand = np.random.random(n_outcomes) if conflict_level > 0.5: conflicting = 1.0 - u1 + conflict_delta * np.random.random(n_outcomes) u2 = conflicting * conflict_level + rand * (1 - conflict_level) elif conflict_level < 0.5: same = u1 + conflict_delta * np.random.random(n_outcomes) u2 = same * (1 - conflict_level) + rand * conflict_level else: u2 = rand # todo implement win_win correctly. Order the ufun then make outcomes with good outcome even better and vice # versa # u2 += u2 * win_win # u2 += np.random.random(n_outcomes) * conflict_delta u1 -= u1.min() u2 -= u2.min() u1 = u1 / u1.max() u2 = u2 / u2.max() if random.random() > 0.5: u1, u2 = u2, u1 return ( MappingUtilityFunction(dict(zip(outcomes, u1))), MappingUtilityFunction(dict(zip(outcomes, u2))), ) @classmethod def generate_random_bilateral( cls, outcomes: Union[int, List[Outcome]] ) -> Tuple["UtilityFunction", "UtilityFunction"]: """Generates a couple of utility functions Args: n_outcomes (int): number of outcomes to use conflict_level: How conflicting are the two ufuns to generate. 1.0 means maximum conflict. conflict_delta: How variable is the conflict at different outcomes. zero_summness: How zero-sum like are the two ufuns. """ if isinstance(outcomes, int): outcomes = [(_,) for _ in range(outcomes)] n_outcomes = len(outcomes) u1 = np.random.random(n_outcomes) u2 = np.random.random(n_outcomes) u1 -= u1.min() u2 -= u2.min() u1 /= u1.max() u2 /= u2.max() return ( MappingUtilityFunction(dict(zip(outcomes, u1))), MappingUtilityFunction(dict(zip(outcomes, u2))), ) @classmethod def generate_random( cls, n: int, outcomes: Union[int, List[Outcome]], normalized: bool = True ) -> List["UtilityFunction"]: """Generates a couple of utility functions Args: n: number of utility functions to generate outcomes: number of outcomes to use normalized: if true, the resulting ufuns will be normlized between zero and one. """ if isinstance(outcomes, int): outcomes = [(_,) for _ in range(outcomes)] n_outcomes = len(outcomes) ufuns = [] for _ in range(n): u1 = np.random.random(n_outcomes) if normalized: u1 -= u1.min() u1 /= u1.max() ufuns.append(MappingUtilityFunction(dict(zip(outcomes, u1)))) return ufuns @classmethod def conflict_level( cls, u1: "UtilityFunction", u2: "UtilityFunction", outcomes: Union[int, List["Outcome"]], max_tests: int = 10000, ) -> float: """ Finds the conflict level in these two ufuns Args: u1: u2: Examples: - A nonlinear strictly zero sum case >>> outcomes = [(_,) for _ in range(10)] >>> u1 = MappingUtilityFunction(dict(zip(outcomes, np.random.random(len(outcomes))))) >>> u2 = MappingUtilityFunction(dict(zip(outcomes, 1.0 - np.array(list(u1.mapping.values()))))) >>> print(UtilityFunction.conflict_level(u1=u1, u2=u2, outcomes=outcomes)) 1.0 - The same ufun >>> print(UtilityFunction.conflict_level(u1=u1, u2=u1, outcomes=outcomes)) 0.0 - A linear strictly zero sum case >>> outcomes = [(_,) for _ in range(10)] >>> u1 = MappingUtilityFunction(dict(zip(outcomes, np.linspace(0.0, 1.0, len(outcomes), endpoint=True)))) >>> u2 = MappingUtilityFunction(dict(zip(outcomes, np.linspace(1.0, 0.0, len(outcomes), endpoint=True)))) >>> print(UtilityFunction.conflict_level(u1=u1, u2=u2, outcomes=outcomes)) 1.0 """ if isinstance(outcomes, int): outcomes = [(_,) for _ in range(outcomes)] n_outcomes = len(outcomes) points = np.array([[u1(o), u2(o)] for o in outcomes]) order = np.random.permutation(np.array(range(n_outcomes))) p1, p2 = points[order, 0], points[order, 1] signs = [] trial = 0 for i in range(n_outcomes - 1): for j in range(i + 1, n_outcomes): if trial >= max_tests: break trial += 1 o11, o12 = p1[i], p1[j] o21, o22 = p2[i], p2[j] if o12 == o11 and o21 == o22: continue signs.append( int((o12 > o11 and o21 > o22) or (o12 < o11 and o21 < o22)) ) signs = np.array(signs) if len(signs) == 0: return None return signs.mean() @classmethod def winwin_level( cls, u1: "UtilityFunction", u2: "UtilityFunction", outcomes: Union[int, List["Outcome"]], max_tests: int = 10000, ) -> float: """ Finds the conflict level in these two ufuns Args: u1: u2: Examples: - A nonlinear same ufun case >>> outcomes = [(_,) for _ in range(10)] >>> u1 = MappingUtilityFunction(dict(zip(outcomes, np.linspace(1.0, 0.0, len(outcomes), endpoint=True)))) - A linear strictly zero sum case >>> outcomes = [(_,) for _ in range(10)] >>> u1 = MappingUtilityFunction(dict(zip(outcomes, np.linspace(0.0, 1.0, len(outcomes), endpoint=True)))) >>> u2 = MappingUtilityFunction(dict(zip(outcomes, np.linspace(1.0, 0.0, len(outcomes), endpoint=True)))) """ if isinstance(outcomes, int): outcomes = [(_,) for _ in range(outcomes)] n_outcomes = len(outcomes) points = np.array([[u1(o), u2(o)] for o in outcomes]) order = np.random.permutation(np.array(range(n_outcomes))) p1, p2 = points[order, 0], points[order, 1] signs = [] for trial, (i, j) in enumerate( zip(range(n_outcomes - 1), range(1, n_outcomes)) ): if trial >= max_tests: break o11, o12 = p1[i], p1[j] o21, o22 = p2[i], p2[j] if o11 == o12: if o21 == o22: continue else: win = abs(o22 - o21) elif o11 < o12: if o21 == o22: win = o12 - o11 else: win = (o12 - o11) + (o22 - o21) else: if o21 == o22: win = o11 - o12 else: win = (o11 - o12) + (o22 - o21) signs.append(win) signs = np.array(signs) if len(signs) == 0: return None return signs.mean() UtilityFunctions = List["UtilityFunction"] class ExpDiscountedUFun(UtilityFunction): """A discounted utility function based on some factor of the negotiation Args: ufun: The utility function that is being discounted beta: discount factor factor: str -> The name of the AgentMechanismInterface variable based on which discounting operate callable -> must receive a mechanism info object and returns a float representing the factor """ def __init__( self, ufun: UtilityFunction, ami: "AgentMechanismInterface", beta: Optional[float] = None, factor: Union[str, Callable[["AgentMechanismInterface"], float]] = "step", name=None, reserved_value: Optional[UtilityValue] = 0.0, dynamic_reservation=True, ): super().__init__(name=name, reserved_value=reserved_value, ami=ami) self.ufun = ufun self.beta = beta self.factor = factor self.dynamic_reservation = dynamic_reservation def __call__(self, offer: Outcome) -> Optional[UtilityValue]: if offer is None and not self.dynamic_reservation: return self.reserved_value u = self.ufun(offer) if not self.beta or self.beta == 1.0: return u if isinstance(self.factor, str): factor = getattr(self.ami, self.factor) else: factor = self.factor(self.ami) return (factor ** self.beta) * u def xml(self, issues: List[Issue]) -> str: output = self.ufun.xml(issues) output += "\n" factor = None if self.factor is not None: factor = str(self.factor) if self.beta is not None: output += f' The name of the AgentMechanismInterface variable based on which discounting operate callable -> must receive a mechanism info object and returns a float representing the factor power: A power to raise the total cost to before discounting it from the utility_function value """ def __init__( self, ufun: UtilityFunction, ami: "AgentMechanismInterface", cost: Optional[float] = None, factor: Union[str, Callable[["AgentMechanismInterface"], float]] = "step", power: float = 1.0, name=None, reserved_value: Optional[UtilityValue] = 0.0, dynamic_reservation=True, ): super().__init__(name=name, reserved_value=reserved_value, ami=ami) self.ufun = ufun self.cost = cost self.factor = factor self.power = power self.dynamic_reservation = dynamic_reservation def __call__(self, offer: Outcome) -> Optional[UtilityValue]: if offer is None and not self.dynamic_reservation: return self.reserved_value u = self.ufun(offer) if not self.cost or self.cost == 0.0: return u if isinstance(self.factor, str): factor = getattr(self.ami, self.factor) else: factor = self.factor(self.ami) return u - ((factor * self.cost) ** self.power) def xml(self, issues: List[Issue]) -> str: output = self.ufun.xml(issues) output += "\n" factor = None if self.factor is not None: factor = str(self.factor) if self.cost is not None: output += f' Optional[UtilityValue]: if offer is None: return self.reserved_value return self.value def xml(self, issues: List[Issue]) -> str: pass def __str__(self): return str(self.value) def make_discounted_ufun( ufun: "UtilityFunction", ami: "AgentMechanismInterface", cost_per_round: float = None, power_per_round: float = None, discount_per_round: float = None, cost_per_relative_time: float = None, power_per_relative_time: float = None, discount_per_relative_time: float = None, cost_per_real_time: float = None, power_per_real_time: float = None, discount_per_real_time: float = None, dynamic_reservation: bool = True, ): if cost_per_round is not None and cost_per_round > 0.0: ufun = LinDiscountedUFun( ufun=ufun, ami=ami, cost=cost_per_round, factor="step", power=power_per_round, dynamic_reservation=dynamic_reservation, ) if cost_per_relative_time is not None and cost_per_relative_time > 0.0: ufun = LinDiscountedUFun( ufun=ufun, ami=ami, cost=cost_per_relative_time, factor="relative_time", power=power_per_relative_time, dynamic_reservation=dynamic_reservation, ) if cost_per_real_time is not None and cost_per_real_time > 0.0: ufun = LinDiscountedUFun( ufun=ufun, ami=ami, cost=cost_per_real_time, factor="real_time", power=power_per_real_time, dynamic_reservation=dynamic_reservation, ) if discount_per_round is not None and discount_per_round > 0.0: ufun = ExpDiscountedUFun( ufun=ufun, ami=ami, beta=discount_per_round, factor="step", dynamic_reservation=dynamic_reservation, ) if discount_per_relative_time is not None and discount_per_relative_time > 0.0: ufun = ExpDiscountedUFun( ufun=ufun, ami=ami, beta=discount_per_relative_time, factor="relative_time", dynamic_reservation=dynamic_reservation, ) if discount_per_real_time is not None and discount_per_real_time > 0.0: ufun = ExpDiscountedUFun( ufun=ufun, ami=ami, beta=discount_per_real_time, factor="real_time", dynamic_reservation=dynamic_reservation, ) return ufun class LinearUtilityAggregationFunction(UtilityFunction): r"""A linear utility function for multi-issue negotiations. Models a linear utility function using predefined weights:\. Args: issue_utilities: utility functions for individual issues weights: weights for combining `issue_utilities` name: name of the utility function. If None a random name will be generated. Notes: The utility value is calculated as: .. math:: u = \sum_{i=0}^{n_{outcomes}-1} {w_i * u_i} Examples: >>> issues = [Issue((10.0, 20.0), 'price'), Issue(['delivered', 'not delivered'], 'delivery') ... , Issue(5, 'quality')] >>> print(list(map(str, issues))) ['price: (10.0, 20.0)', "delivery: ['delivered', 'not delivered']", 'quality: 5'] >>> f = LinearUtilityAggregationFunction({'price': lambda x: 2.0*x ... , 'delivery': {'delivered': 10, 'not delivered': -10} ... , 'quality': MappingUtilityFunction(lambda x: x-3)} ... , weights={'price': 1.0, 'delivery': 2.0, 'quality': 4.0}) >>> float(f({'quality': 2, 'price': 14.0, 'delivery': 'delivered'}) ... ) - (1.0*(2.0*14)+2.0*10+4.0*(2.0-3.0)) 0.0 >>> f = LinearUtilityAggregationFunction({'price': lambda x: 2.0*x ... , 'delivery': {'delivered': 10, 'not delivered': -10}} ... , weights={'price': 1.0, 'delivery': 2.0}) >>> float(f({'quality': 2, 'price': 14.0, 'delivery': 'delivered'})) - (1.0*(2.0*14)+2.0*10) 0.0 You can use lists instead of dictionaries for defining outcomes, weights and nonlinearity but that is less readable >>> f = LinearUtilityAggregationFunction([lambda x: 2.0*x ... , {'delivered': 10, 'not delivered': -10} ... , MappingUtilityFunction(lambda x: x-3)] ... , weights=[1.0, 2.0, 4.0]) >>> float(f((14.0, 'delivered', 2))) - (1.0*(2.0*14)+2.0*10+4.0*(2.0-3.0)) 0.0 Remarks: The mapping need not use all the issues in the output as the last example show. """ def __init__( self, issue_utilities: Union[ MutableMapping[Any, GenericMapping], Sequence[GenericMapping] ], weights: Optional[Union[Mapping[Any, float], Sequence[float]]] = None, name: Optional[str] = None, reserved_value: Optional[UtilityValue] = 0.0, ami: AgentMechanismInterface = None, ) -> None: super().__init__(name=name, reserved_value=reserved_value, ami=ami) self.issue_utilities = issue_utilities self.weights = weights if self.weights is None: self.weights = {} for k in ikeys(self.issue_utilities): self.weights[k] = 1.0 for k, v in ienumerate(self.issue_utilities): self.issue_utilities[k] = ( v if isinstance(v, UtilityFunction) else MappingUtilityFunction(v) ) def __call__(self, offer: Optional["Outcome"]) -> Optional[UtilityValue]: if offer is None: return self.reserved_value u = ExactUtilityValue(0.0) for k in ikeys(self.issue_utilities): v = iget(offer, k) current_utility = gmap(iget(self.issue_utilities, k), v) if current_utility is None: return None w = iget(self.weights, k) # type: ignore if w is None: return None try: u += w * current_utility except FloatingPointError: continue return u def xml(self, issues: List[Issue]) -> str: """ Generates an XML string representing the utility function Args: issues: Examples: >>> issues = [Issue(values=10, name='i1'), Issue(values=['delivered', 'not delivered'], name='i2') ... , Issue(values=4, name='i3')] >>> f = LinearUtilityAggregationFunction([lambda x: 2.0*x ... , {'delivered': 10, 'not delivered': -10} ... , MappingUtilityFunction(lambda x: x-3)] ... , weights=[1.0, 2.0, 4.0]) >>> print(f.xml(issues)) >>> print(f.xml({i:_ for i, _ in enumerate(issues)})) """ output = "" keys = list(ikeys(issues)) for i, k in enumerate(keys): issue_name = iget(issues, k).name output += f'\n' vals = iget(issues, k).all for indx, v in enumerate(vals): u = gmap(iget(self.issue_utilities, k), v) v_ = ( v if not (isinstance(v, tuple) or isinstance(v, list)) else "-".join([str(_) for _ in v]) ) output += ( f' \n' ) output += "\n" for i, k in enumerate(keys): output += ( f'\n\n' ) return output def __str__(self): return f"u: {self.issue_utilities}\n w: {self.weights}" class MappingUtilityFunction(UtilityFunction): """Outcome mapping utility function. This is the simplest possible utility function and it just maps a set of ``Outcome``s to a set of ``UtilityValue``(s). It is only usable with single-issue negotiations. It can be constructed with wither a mapping (e.g. a dirct) or a callable function. Args: mapping: Either a callable or a mapping from ``Outcome`` (dict) to ``UtilityValue``. default: value returned for outcomes causing exception (e.g. invalid outcomes). name: name of the utility function. If None a random name will be generated. Eamples: Single issue outcome case: >>> issue =Issue(values=['to be', 'not to be'], name='THE problem') >>> print(str(issue)) THE problem: ['to be', 'not to be'] >>> f = MappingUtilityFunction({'to be':10.0, 'not to be':0.0}) >>> print(list(map(f, ['to be', 'not to be']))) [10.0, 0.0] >>> f = MappingUtilityFunction(mapping={'to be':-10.0, 'not to be':10.0}) >>> print(list(map(f, ['to be', 'not to be']))) [-10.0, 10.0] >>> f = MappingUtilityFunction(lambda x: float(len(x))) >>> print(list(map(f, ['to be', 'not to be']))) [5.0, 9.0] Multi issue case: >>> issues = [Issue((10.0, 20.0), 'price'), Issue(['delivered', 'not delivered'], 'delivery') ... , Issue(5, 'quality')] >>> print(list(map(str, issues))) ['price: (10.0, 20.0)', "delivery: ['delivered', 'not delivered']", 'quality: 5'] >>> f = MappingUtilityFunction(lambda x: x['price'] if x['delivery'] == 'delivered' else -1.0) >>> g = MappingUtilityFunction(lambda x: x['price'] if x['delivery'] == 'delivered' else -1.0 ... , default=-1000 ) >>> f({'price': 16.0}) is None True >>> g({'price': 16.0}) -1000 >>> f({'price': 16.0, 'delivery': 'delivered'}) 16.0 >>> f({'price': 16.0, 'delivery': 'not delivered'}) -1.0 Remarks: - If the mapping used failed on the outcome (for example because it is not a valid outcome), then the ``default`` value given to the constructor (which defaults to None) will be returned. """ def __init__( self, mapping: OutcomeUtilityMapping, default=None, name: str = None, reserved_value: Optional[UtilityValue] = 0.0, ami: AgentMechanismInterface = None, ) -> None: super().__init__(name=name, reserved_value=reserved_value, ami=ami) self.mapping = mapping self.default = default def __call__(self, offer: Optional["Outcome"]) -> Optional[UtilityValue]: # noinspection PyBroadException if offer is None: return self.reserved_value try: if isinstance(offer, dict) and isinstance(self.mapping, dict): m = gmap(self.mapping, tuple(offer.values())) else: m = gmap(self.mapping, offer) except Exception: return self.default return m def xml(self, issues: List[Issue]) -> str: """ Examples: >>> issue =Issue(values=['to be', 'not to be'], name='THE problem') >>> print(str(issue)) THE problem: ['to be', 'not to be'] >>> f = MappingUtilityFunction({'to be':10.0, 'not to be':0.0}) >>> print(list(map(f, ['to be', 'not to be']))) [10.0, 0.0] >>> print(f.xml([issue])) """ if len(issues) > 1: raise ValueError( "Cannot call xml() on a mapping utility function with more than one issue" ) if issues is not None: issue_names = [_.name for _ in issues] key = issue_names[0] else: key = "0" output = f'\n' if isinstance(self.mapping, Callable): for i, k in enumerate(issues[key].all): if isinstance(k, tuple) or isinstance(k, list): k = "-".join([str(_) for _ in k]) output += ( f' \n' f" \n" ) else: for i, (k, v) in enumerate(ienumerate(self.mapping)): if isinstance(k, tuple) or isinstance(k, list): k = "-".join([str(_) for _ in k]) output += ( f' \n' f" \n" ) output += "\n" output += '\n\n' return output def __str__(self) -> str: return f"mapping: {self.mapping}\ndefault: {self.default}" class RandomUtilityFunction(MappingUtilityFunction): """A random utility function for a discrete outcome space""" def __init__(self, outcomes: List[Outcome]): if len(outcomes) < 1: raise ValueError("Cannot create a random utility function without outcomes") if isinstance(outcomes[0], tuple): pass else: outcomes = [tuple(o.keys()) for o in outcomes] super().__init__(mapping=dict(zip(outcomes, np.random.rand(len(outcomes))))) class NonLinearUtilityAggregationFunction(UtilityFunction): r"""A nonlinear utility function. Allows for the modeling of a single nonlinear utility function that combines the utilities of different issues. Args: issue_utilities: A set of mappings from issue values to utility functions. These are generic mappings so \ `Callable`\ (s) and \ `Mapping`\ (s) are both accepted f: A nonlinear function mapping from a dict of utility_function-per-issue to a float name: name of the utility function. If None a random name will be generated. Notes: The utility is calculated as: .. math:: u = f\\left(u_0\\left(i_0\\right), u_1\\left(i_1\\right), ..., u_n\\left(i_n\\right)\\right) where :math:`u_j()` is the utility function for issue :math:`j` and :math:`i_j` is value of issue :math:`j` in the evaluated outcome. Examples: >>> issues = [Issue((10.0, 20.0), 'price'), Issue(['delivered', 'not delivered'], 'delivery') ... , Issue(5, 'quality')] >>> print(list(map(str, issues))) ['price: (10.0, 20.0)', "delivery: ['delivered', 'not delivered']", 'quality: 5'] >>> g = NonLinearUtilityAggregationFunction({ 'price': lambda x: 2.0*x ... , 'delivery': {'delivered': 10, 'not delivered': -10} ... , 'quality': MappingUtilityFunction(lambda x: x-3)} ... , f=lambda u: u['price'] + 2.0 * u['quality']) >>> float(g({'quality': 2, 'price': 14.0, 'delivery': 'delivered'})) - ((2.0*14)+2.0*(2.0-3.0)) 0.0 >>> g = NonLinearUtilityAggregationFunction({'price' : lambda x: 2.0*x ... , 'delivery': {'delivered': 10, 'not delivered': -10}} ... , f=lambda u: 2.0 * u['price'] ) >>> float(g({'price': 14.0, 'delivery': 'delivered'})) - (2.0*(2.0*14)) 0.0 """ def xml(self, issues: List[Issue]) -> str: raise NotImplementedError(f"Cannot convert {self.__class__.__name__} to xml") def __init__( self, issue_utilities: MutableMapping[Any, GenericMapping], f: Callable[[Dict[Any, UtilityValue]], UtilityValue], name: Optional[str] = None, reserved_value: Optional[UtilityValue] = 0.0, ami: AgentMechanismInterface = None, ) -> None: super().__init__(name=name, reserved_value=reserved_value, ami=ami) self.issue_utilities = issue_utilities self.f = f def __call__(self, offer: Optional["Outcome"]) -> Optional[UtilityValue]: if offer is None: return self.reserved_value if self.issue_utilities is None: raise ValueError( "No issue utilities were set. Call set_params() or use the constructor" ) u = {} for k in ikeys(self.issue_utilities): v = iget(offer, k) u[k] = gmap(iget(self.issue_utilities, k), v) return self.f(u) class HyperRectangleUtilityFunction(UtilityFunction): """A utility function defined as a set of hyper-volumes. The utility function that is calulated by combining linearly a set of *probably nonlinear* functions applied in predefined hyper-volumes of the outcome space. Args: outcome_ranges: The outcome_ranges for which the `mappings` are defined mappings: The *possibly nonlinear* mapppings correponding to the outcome_ranges weights: The *optional* weights to use for combining the outputs of the `mappings` ignore_issues_not_in_input: If a hyper-volumne local function is defined for some issue that is not in the outcome being evaluated ignore it. ignore_failing_range_utilities: If a hyper-volume local function fails, just assume it did not exist for this outcome. name: name of the utility function. If None a random name will be generated. Examples: We will use the following issue space of cardinality :math:`10 \times 5 \times 4`: >>> issues = [Issue(10), Issue(5), Issue(4)] Now create the utility function with >>> f = HyperRectangleUtilityFunction(outcome_ranges=[ ... {0: (1.0, 2.0), 1: (1.0, 2.0)}, ... {0: (1.4, 2.0), 2: (2.0, 3.0)}] ... , utilities= [2.0, lambda x: 2 * x[2] + x[0]]) >>> g = HyperRectangleUtilityFunction(outcome_ranges=[ ... {0: (1.0, 2.0), 1: (1.0, 2.0)}, ... {0: (1.4, 2.0), 2: (2.0, 3.0)}] ... , utilities= [2.0, lambda x: 2 * x[2] + x[0]] ... , ignore_issues_not_in_input=True) >>> h = HyperRectangleUtilityFunction(outcome_ranges=[ ... {0: (1.0, 2.0), 1: (1.0, 2.0)}, ... {0: (1.4, 2.0), 2: (2.0, 3.0)}] ... , utilities= [2.0, lambda x: 2 * x[2] + x[0]] ... , ignore_failing_range_utilities=True) We can now calcualte the utility_function of some outcomes: * An outcome that belongs to the both outcome_ranges: >>> [f({0: 1.5,1: 1.5, 2: 2.5}), g({0: 1.5,1: 1.5, 2: 2.5}), h({0: 1.5,1: 1.5, 2: 2.5})] [8.5, 8.5, 8.5] * An outcome that belongs to the first hypervolume only: >>> [f({0: 1.5,1: 1.5, 2: 1.0}), g({0: 1.5,1: 1.5, 2: 1.0}), h({0: 1.5,1: 1.5, 2: 1.0})] [2.0, 2.0, 2.0] * An outcome that belongs to and has the first hypervolume only: >>> [f({0: 1.5}), g({0: 1.5}), h({0: 1.5})] [None, 0.0, None] * An outcome that belongs to the second hypervolume only: >>> [f({0: 1.5,2: 2.5}), g({0: 1.5,2: 2.5}), h({0: 1.5,2: 2.5})] [None, 6.5, None] * An outcome that has and belongs to the second hypervolume only: >>> [f({2: 2.5}), g({2: 2.5}), h({2: 2.5})] [None, 0.0, None] * An outcome that belongs to no outcome_ranges: >>> [f({0: 11.5,1: 11.5, 2: 12.5}), g({0: 11.5,1: 11.5, 2: 12.5}), h({0: 11.5,1: 11.5, 2: 12.5})] [0.0, 0.0, 0.0] Remarks: - The number of outcome_ranges, mappings, and weights must be the same - if no weights are given they are all assumed to equal unity - mappings can either by an `OutcomeUtilityMapping` or a constant. """ def xml(self, issues: List[Issue]) -> str: """Represents the function as XML Args: issues: Examples: >>> f = HyperRectangleUtilityFunction(outcome_ranges=[ ... {0: (1.0, 2.0), 1: (1.0, 2.0)}, ... {0: (1.4, 2.0), 2: (2.0, 3.0)}] ... , utilities= [2.0, 9.0 + 4.0]) >>> print(f.xml([Issue((0.0, 4.0), name='0'), Issue((0.0, 9.0), name='1') ... , Issue((0.0, 9.0), name='2')]).strip()) """ output = "" for i, issue in enumerate(ivalues(issues)): name = issue.name if isinstance(issue.values, tuple): output += ( f'\n' f' \n' f"" ) elif isinstance(issue.values, int): output += ( f'\n' ) else: output += ( f'\n' ) # todo find the real maxutility output += '\n \n' for rect, u, w in zip(self.outcome_ranges, self.mappings, self.weights): output += f' \n' for indx in ikeys(rect): values = iget(rect, indx, None) if values is None: continue if isinstance(values, float) or isinstance(values, int): mn, mx = values, values elif isinstance(values, tuple): mn, mx = values else: mn, mx = min(values), max(values) output += ( f' \n' ) output += f" \n" output += " \n" return output def __init__( self, outcome_ranges: Iterable[OutcomeRange], utilities: Union[Floats, OutcomeUtilityMappings], weights: Optional[Floats] = None, *, ignore_issues_not_in_input=False, ignore_failing_range_utilities=False, name: Optional[str] = None, reserved_value: Optional[UtilityValue] = 0.0, ami: AgentMechanismInterface = None, ) -> None: super().__init__(name=name, reserved_value=reserved_value, ami=ami) self.outcome_ranges = outcome_ranges self.mappings = utilities self.weights = weights self.ignore_issues_not_in_input = ignore_issues_not_in_input self.ignore_failing_range_utilities = ignore_failing_range_utilities self.adjust_params() def adjust_params(self): if self.weights is None: self.weights = [1.0] * len(self.outcome_ranges) def __call__(self, offer: Optional["Outcome"]) -> Optional[UtilityValue]: if offer is None: return self.reserved_value u = ExactUtilityValue(0.0) for weight, outcome_range, mapping in zip( self.weights, self.outcome_ranges, self.mappings ): # type: ignore # fail on any outcome_range that constrains issues not in the presented outcome if outcome_range is not None and set(ikeys(outcome_range)) - set( ikeys(offer) ) != set([]): if self.ignore_issues_not_in_input: continue return None elif outcome_range is None or outcome_in_range(offer, outcome_range): if isinstance(mapping, float): u += weight * mapping else: # fail if any outcome_range utility_function cannot be calculated from the input try: # noinspection PyTypeChecker u += weight * gmap(mapping, offer) except KeyError: if self.ignore_failing_range_utilities: continue return None return u class NonlinearHyperRectangleUtilityFunction(UtilityFunction): """A utility function defined as a set of outcome_ranges. Args: hypervolumes: see `HyperRectangleUtilityFunction` mappings: see `HyperRectangleUtilityFunction` f: A nonlinear function to combine the results of `mappings` name: name of the utility function. If None a random name will be generated """ def xml(self, issues: List[Issue]) -> str: raise NotImplementedError(f"Cannot convert {self.__class__.__name__} to xml") def __init__( self, hypervolumes: Iterable[OutcomeRange], mappings: OutcomeUtilityMappings, f: Callable[[List[UtilityValue]], UtilityValue], name: Optional[str] = None, reserved_value: Optional[UtilityValue] = 0.0, ami: AgentMechanismInterface = None, ) -> None: super().__init__(name=name, reserved_value=reserved_value, ami=ami) self.hypervolumes = hypervolumes self.mappings = mappings self.f = f def __call__(self, offer: Optional["Outcome"]) -> Optional[UtilityValue]: if offer is None: return self.reserved_value if not isinstance(self.hypervolumes, Iterable): raise ValueError( "Hypervolumes are not set. Call set_params() or pass them through the constructor." ) u = [] for hypervolume, mapping in zip(self.hypervolumes, self.mappings): if outcome_in_range(offer, hypervolume): u.append(gmap(mapping, offer)) return self.f(u) class ComplexWeightedUtilityFunction(UtilityFunction): """ A utility function composed of linear aggregation of other utility functions Args: ufuns: An iterable of utility functions weights: Weights used for combination name: Utility function name """ def __init__( self, ufuns: Iterable[UtilityFunction], weights: Optional[Iterable[float]] = None, name=None, reserved_value: Optional[UtilityValue] = 0.0, ami: AgentMechanismInterface = None, ): super().__init__(name=name, reserved_value=reserved_value, ami=ami) self.ufuns = list(ufuns) if weights is None: weights = [1.0] * len(self.ufuns) self.weights = list(weights) def __call__(self, offer: Outcome) -> Optional[UtilityValue]: """Calculate the utility_function value for a given outcome. Args: offer: The offer to be evaluated. Remarks: - You cannot return None from overriden apply() functions but raise an exception (ValueError) if it was not possible to calculate the UtilityValue. - Return A UtilityValue not a float for real-valued utilities for the benefit of inspection code. Returns: UtilityValue: The utility_function value which may be a distribution. If `None` it means the utility_function value cannot be calculated. """ if offer is None: return self.reserved_value u = ExactUtilityValue(0.0) failure = False for f, w in zip(self.ufuns, self.weights): util = f(offer) if util is not None: u += w * util else: failure = True return u if not failure else None def xml(self, issues: List[Issue]) -> str: output = "" # @todo implement weights. Here I assume they are always 1.0 for f, w in zip(self.ufuns, self.weights): output += f.xml(issues) return output class ComplexNonlinearUtilityFunction(UtilityFunction): """ A utility function composed of nonlinear aggregation of other utility functions Args: ufuns: An iterable of utility functions combination_function: The function used to combine results of ufuns name: Utility function name """ def __init__( self, ufuns: Iterable[UtilityFunction], combination_function=Callable[[Iterable[UtilityValue]], UtilityValue], name=None, reserved_value: Optional[UtilityValue] = 0.0, ami: AgentMechanismInterface = None, ): super().__init__(name=name, reserved_value=reserved_value, ami=ami) self.ufuns = list(ufuns) self.combination_function = combination_function def __call__(self, offer: Outcome) -> Optional[UtilityValue]: """Calculate the utility_function value for a given outcome. Args: offer: The offer to be evaluated. Remarks: - You cannot return None from overriden apply() functions but raise an exception (ValueError) if it was not possible to calculate the UtilityValue. - Return A UtilityValue not a float for real-valued utilities for the benefit of inspection code. Returns: UtilityValue: The utility_function value which may be a distribution. If `None` it means the utility_function value cannot be calculated. """ if offer is None: return self.reserved_value return self.combination_function([f(offer) for f in self.ufuns]) def xml(self, issues: List[Issue]) -> str: raise NotImplementedError(f"Cannot convert {self.__class__.__name__} to xml") class IPUtilityFunction(UtilityFunction): """Independent Probabilistic Utility Function. Args: outcomes: Iterable of outcomes distribs: distributions associated with the outcomes name: ufun name Examples: >>> f = IPUtilityFunction(outcomes=[('o1',), ('o2',)] ... , distributions=[UtilityDistribution(dtype='uniform', loc=0.0, scale=0.5) ... , UtilityDistribution(dtype='uniform', loc=0.1, scale=0.5)]) >>> f(('o1',)) U(0.0, 0.5) >>> f = IPUtilityFunction(outcomes=[{'cost': 10, 'dist': 20}, {'cost': 10, 'dist': 30}] ... , distributions=[UtilityDistribution(dtype='uniform', loc=0.0, scale=0.5) ... , UtilityDistribution(dtype='uniform', loc=0.1, scale=0.5)]) >>> f({'cost': 10, 'dist': 30}) U(0.1, 0.6) """ def __init__( self, outcomes: Iterable["Outcome"], distributions: Iterable["UtilityDistribution"] = None, issue_names: Iterable[str] = None, name=None, reserved_value: Optional[UtilityValue] = 0.0, ami: AgentMechanismInterface = None, ): super().__init__(name=name, reserved_value=reserved_value, ami=ami) outcomes, distributions = ( list(outcomes), (list(distributions) if distributions is not None else None), ) if len(outcomes) < 1: raise ValueError( "IPUtilityFunction cannot be initialized with zero outcomes" ) self.tupelized = False self.n_issues = len(outcomes[0]) if issue_names is None: self.issue_names = sorted(ikeys(outcomes[0])) else: self.issue_names = range(len(outcomes[0])) self.issue_keys = dict(zip(range(self.n_issues), self.issue_names)) if not isinstance(outcomes[0], tuple): outcomes = [ tuple(iget(_, key, None) for key in self.issue_names) for _ in outcomes ] self.tupelized = True if distributions is None: distributions = [ UtilityDistribution(dtype="uniform", loc=0.0, scale=1.0) for _ in range(len(outcomes)) ] self.distributions = dict(zip(outcomes, distributions)) def distribution(self, outcome: "Outcome") -> "UtilityValue": """ Returns the distributon associated with a specific outcome Args: outcome: Returns: """ return self.distributions[self.key(outcome)] @classmethod def from_ufun( cls, u: MappingUtilityFunction, range: Tuple[float, float] = (0.0, 1.0), uncertainty: float = 0.5, variability: float = 0.0, ) -> "IPUtilityFunction": """ Generates a distribution from which `u` may have been sampled Args: u: range: range of the utility_function values uncertainty: uncertainty level Examples: - No uncertainty >>> u = MappingUtilityFunction(mapping=dict(zip([('o1',), ('o2',)], [0.3, 0.7]))) >>> p = IPUtilityFunction.from_ufun(u, uncertainty=0.0) >>> print(p) {('o1',): U(0.3, 0.3), ('o2',): U(0.7, 0.7)} - Full uncertainty >>> u = MappingUtilityFunction(mapping=dict(zip([('o1',), ('o2',)], [0.3, 0.7]))) >>> p = IPUtilityFunction.from_ufun(u, uncertainty=1.0) >>> print(p) {('o1',): U(0.0, 1.0), ('o2',): U(0.0, 1.0)} - some uncertainty >>> u = MappingUtilityFunction(mapping=dict(zip([('o1',), ('o2',)], [0.3, 0.7]))) >>> p = IPUtilityFunction.from_ufun(u, uncertainty=0.1) >>> print([_.scale for _ in p.distributions.values()]) [0.1, 0.1] >>> for k, v in p.distributions.items(): ... assert v.loc <= u(k) Returns: a new IPUtilityFunction """ if isinstance(u.mapping, dict): return cls.from_mapping( u.mapping, range=range, uncertainty=uncertainty, variability=variability ) return cls.from_mapping( dict(zip(ikeys(u.mapping), ivalues(u.mapping))), range=range, uncertainty=uncertainty, variability=variability, ) @classmethod def from_mapping( cls, mapping: Dict["Outcome", float], range: Tuple[float, float] = (0.0, 1.0), uncertainty: float = 0.5, variability: float = 0.0, ) -> "IPUtilityFunction": """ Generates a distribution from which `u` may have been sampled Args: mapping: mapping from outcomes to float values range: range of the utility_function values uncertainty: uncertainty level Examples: - No uncertainty >>> mapping=dict(zip([('o1',), ('o2',)], [0.3, 0.7])) >>> p = IPUtilityFunction.from_mapping(mapping, uncertainty=0.0) >>> print(p) {('o1',): U(0.3, 0.3), ('o2',): U(0.7, 0.7)} - Full uncertainty >>> mapping=dict(zip([('o1',), ('o2',)], [0.3, 0.7])) >>> p = IPUtilityFunction.from_mapping(mapping, uncertainty=1.0) >>> print(p) {('o1',): U(0.0, 1.0), ('o2',): U(0.0, 1.0)} - some uncertainty >>> mapping=dict(zip([('o1',), ('o2',)], [0.3, 0.7])) >>> p = IPUtilityFunction.from_mapping(mapping, uncertainty=0.1) >>> print([_.scale for _ in p.distributions.values()]) [0.1, 0.1] >>> for k, v in p.distributions.items(): ... assert v.loc <= mapping[k] Returns: a new IPUtilityFunction """ outcomes = list(mapping.keys()) if isinstance(uncertainty, Iterable): uncertainties = uncertainty elif variability <= 0.0: uncertainties = [uncertainty] * len(outcomes) else: uncertainties = ( uncertainty + (np.random.rand(len(outcomes)) - 0.5) * variability * uncertainty ).tolist() return IPUtilityFunction( outcomes=outcomes, distributions=[ Distribution.around(value=mapping[o], uncertainty=u, range=range) for o, u in zip(outcomes, uncertainties) ], ) def __str__(self): return pprint.pformat(self.distributions) def sample(self) -> MappingUtilityFunction: """ Samples the utility_function distribution to create a mapping utility function Examples: >>> import random >>> f = IPUtilityFunction(outcomes=[('o1',), ('o2',)] ... , distributions=[UtilityDistribution(dtype='uniform', loc=0.0, scale=0.2) ... , UtilityDistribution(dtype='uniform', loc=0.4, scale=0.5)]) >>> u = f.sample() >>> assert u(('o1',)) <= 0.2 >>> assert 0.4 <= u(('o2',)) <= 0.9 Returns: MappingUtilityFunction """ return MappingUtilityFunction( mapping={o: d.sample(1)[0] for o, d in self.distributions.items()} ) def key(self, outcome: "Outcome"): """ Returns the key of the given outcome in self.distributions. Args: outcome: Returns: tuple Examples: >>> f = IPUtilityFunction(outcomes=[('o1',), ('o2',)] ... , distributions=[UtilityDistribution(dtype='uniform', loc=0.0, scale=0.5) ... , UtilityDistribution(dtype='uniform', loc=0.1, scale=0.5)]) >>> f.key({0:'o1'}) ('o1',) >>> f.key(('o1',)) ('o1',) >>> f.distributions {('o1',): U(0.0, 0.5), ('o2',): U(0.1, 0.6)} >>> f.distribution(('o1',)) U(0.0, 0.5) >>> f = IPUtilityFunction(outcomes=[{'cost': 10, 'dist': 20}, {'dist': 30, 'cost': 10}] ... , distributions=[UtilityDistribution(dtype='uniform', loc=0.0, scale=0.5) ... , UtilityDistribution(dtype='uniform', loc=0.1, scale=0.5)]) >>> f.key({'dist': 30, 'cost': 10}) (10, 30) >>> f.key({'cost': 10, 'dist': 30}) (10, 30) >>> f.distributions {(10, 20): U(0.0, 0.5), (10, 30): U(0.1, 0.6)} >>> f.distribution((10, 20.0)) U(0.0, 0.5) >>> f.distribution({'cost': 10, 'dist': 20}) U(0.0, 0.5) """ if isinstance(outcome, tuple): return outcome return tuple((outcome.get(_, None) for _ in self.issue_names)) def __call__(self, offer: Outcome) -> Optional[UtilityValue]: """Calculate the utility_function value for a given outcome. Args: offer: The offer to be evaluated. Remarks: - You cannot return None from overriden apply() functions but raise an exception (ValueError) if it was not possible to calculate the UtilityValue. - Return A UtilityValue not a float for real-valued utilities for the benefit of inspection code. Returns: UtilityValue: The utility_function value which may be a distribution. If `None` it means the utility_function value cannot be calculated. """ if offer is None: return self.reserved_value if self.tupelized and not isinstance(offer, tuple): offer = tuple(ivalues(offer)) return self.distributions[offer] def xml(self, issues: List[Issue]) -> str: raise NotImplementedError(f"Cannot convert {self.__class__.__name__} to xml") def _pareto_frontier( points, eps=-1e-18, sort_by_welfare=False ) -> Tuple[List[Tuple[float]], List[int]]: """Finds the pareto-frontier of a set of points Args: points: list of points eps: A (usually negative) small number to treat as zero during calculations sort_by_welfare: If True, the results are sorted descindingly by total welfare Returns: """ points = np.asarray(points) n = len(points) indices = np.array(range(n)) for j in range(points.shape[1]): order = points[:, 0].argsort()[-1::-1] points = points[order] indices = indices[order] frontier = [(indices[0], points[0, :])] for p in range(1, n): current = points[p, :] for i, (_, f) in enumerate(frontier): current_better, current_worse = current > f, current < f if np.all(current == f): break if not np.any(current_better) and np.any(current_worse): # current is dominated, break break if np.any(current_better): if not np.any(current_worse): # current dominates f, append it, remove f and scan for anything else dominated by current for j, (_, g) in enumerate(frontier[i + 1 :]): if np.all(current == g): frontier = frontier[:i] + frontier[i + 1 :] break if np.any(current > g) and not np.any(current < g): frontier = frontier[:j] + frontier[j + 1 :] else: frontier[i] = (indices[p], current) else: # neither current nor f dominate each other, append current only if it is not # dominated by anything in frontier for j, (_, g) in enumerate(frontier[i + 1 :]): if np.all(current == g) or ( np.any(g > current) and not np.any(current > g) ): break else: frontier.append((indices[p], current)) if sort_by_welfare: welfare = [np.sum(_[1]) for _ in frontier] indx = sorted(range(len(welfare)), key=lambda x: welfare[x], reverse=True) frontier = [frontier[_] for _ in indx] return [tuple(_[1]) for _ in frontier], [_[0] for _ in frontier] def pareto_frontier( ufuns: Iterable[UtilityFunction], outcomes: Iterable[Outcome] = None, issues: Iterable[Issue] = None, n_discretization: Optional[int] = 10, sort_by_welfare=False, ) -> Tuple[List[Tuple[float]], List[int]]: """Finds all pareto-optimal outcomes in the list Args: ufuns: The utility functions outcomes: the outcomes to be checked. If None then all possible outcomes from the issues will be checked issues: The set of issues (only used when outcomes is None) n_discretization: The number of items to discretize each real-dimension into sort_by_welfare: If True, the resutls are sorted descendingly by total welfare Returns: Two lists of the same length. First list gives the utilities at pareto frontier points and second list gives their indices """ ufuns = list(ufuns) if issues: issues = list(issues) if outcomes: outcomes = list(outcomes) # calculate all candidate outcomes if outcomes is None: if issues is None: return [], [] outcomes = itertools.product( *[issue.alli(n=n_discretization) for issue in issues] ) points = [[ufun(outcome) for ufun in ufuns] for outcome in outcomes] return _pareto_frontier(points, sort_by_welfare=sort_by_welfare) def normalize( ufun: UtilityFunction, outcomes: Collection[Outcome], rng: Tuple[float, float] = (0.0, 1.0), epsilon: float = 1e-6, infeasible_cutoff: Optional[float] = -1000.0, ) -> UtilityFunction: """Normalizes a utility function to the range [0, 1] Args: ufun: The utility function to normalize outcomes: A collection of outcomes to normalize for rng: range to normalize to. Default is [0, 1] epsilon: A small number specifying the resolution infeasible_cutoff: A value under which any utility is considered infeasible and is not used in normalization Returns: UtilityFunction: A utility function that is guaranteed to be normalized for the set of given outcomes """ u: List[float] u = [ufun(o) for o in outcomes] if infeasible_cutoff is not None: u = [float(_) for _ in u if _ is not None and float(_) >= infeasible_cutoff] else: u = [float(_) for _ in u if _ is not None] if len(u) == 0: return ufun mx, mn = max(u), min(u) if abs(mx - 1.0) < epsilon and abs(mn) < epsilon: return ufun if mx == mn: if -epsilon <= mn <= 1 + epsilon: return ufun else: r = ( float(ufun.reserved_value) / mn if ufun.reserved_value is not None and mn != 0.0 else 0.0 ) if infeasible_cutoff is not None: return ComplexNonlinearUtilityFunction( ufuns=[ufun], combination_function=lambda x: infeasible_cutoff if x[0] is None else x[0] if x[0] < infeasible_cutoff else 0.5 * x[0] / mn, ) else: return ComplexWeightedUtilityFunction( ufuns=[ufun], weights=[0.5 / mn], name=ufun.name + "-normalized", reserved_value=r, ami=ufun.ami, ) scale = (rng[1] - rng[0]) / (mx - mn) r = scale * (ufun.reserved_value - mn) if ufun.reserved_value else 0.0 if infeasible_cutoff is not None: return ComplexNonlinearUtilityFunction( ufuns=[ufun], combination_function=lambda x: infeasible_cutoff if x[0] is None else x[0] if x[0] < infeasible_cutoff else scale * (x[0] - mn) + rng[0], ) else: return ComplexWeightedUtilityFunction( ufuns=[ufun, ConstUFun(-mn + rng[0] / scale)], weights=[scale, scale], name=ufun.name + "-normalized", reserved_value=r, ami=ufun.ami, ) class JavaUtilityFunction(UtilityFunction, JavaCallerMixin): """A utility function implemented in Java""" def __init__(self, java_object, java_class_name: Optional[str], *args, **kwargs): super().__init__(*args, **kwargs) self.init_java_bridge( java_object=java_object, java_class_name=java_class_name, auto_load_java=False, ) if java_object is None: self._java_object.fromMap(to_java(self)) def __call__(self, offer: Outcome) -> Optional[UtilityValue]: return self._java_object.call(to_java(outcome_as_dict(offer))) def xml(self, issues: List[Issue]) -> str: return "Java UFun" PK!H@)1'negmas-0.2.8.dist-info/entry_points.txtN+I/N.,()KMM,PzPaĂL..PK!Wvnegmas-0.2.8.dist-info/LICENSENegMAS library (Negotiation oriented Multi-Agent System) Copyright (C) 2019 Yasser Mohammad This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.PK!HڽTUnegmas-0.2.8.dist-info/WHEEL A н#Z;/"d&F[xzw@Zpy3Fv]\fi4WZ^EgM_-]#0(q7PK!H@ %negmas-0.2.8.dist-info/METADATAZrIAfO$Y춙L\Kr- cN@}X]I9LfZE`?{.}! OBK0< .RX&Kq8 rɋ͈]x4E6̰k,S2A-E?[`0fQFa Z3^f<4ƿ:㯃fD[}0둮w=ƥYb~; =be:b2gdVV|,e!tjp,p9z+h\fV*R5}N؋2a~rcf_/w!҈df%7yL*7Y7Ixxg {S/4AόЦ_YF(apoeep0enJ}çNc#J&ǂNĭ-X<H{+rQ<\踐9%tLeXmrn~M!K-< )DR rX_Y/<`gdx1f $CUޮzOM6Cn?ކ\ۂS۽O:KO}LU 0pp 1L<vwax"O%OW#䛂>ߧ-qvb=ߗ2MصMv'f!k皋|'@wNrwg5W"z{%HJOټKg"#4.~q3SmO? THtxr(᥯f}f@ ^ B()2لz7OG&Vt`'sGڹv}\6 ry ՗/AHy ] Td7WmI% C kz!mi$'6+e*/ GCLti;Z ]A b_jӺA&P ]fqB&"YBTii)B2Qjit6CМg<[C,ʄ0*B'̣zb3|z[zDz/UkWk!} >ffhneA c g3%_oT#LL8Q|C_&YX aD&M՚0OGl@,ᨷTh%8Hx1 Gau@jX6sZ\"ƺH,.b%v+T]v~3W&7_]3xVy?cTc =J{p^)4ݪ@#Hz^zp()*kyۜg!J(^Ю[TCμZo=ޞCe* zJ0iA2_A'\t28Dm#HB*8- Ea iuۀ}ꠚB @ imE~2ñe0x;l8UXQ]~ Vln9ZFVu>Ȟ#ȇGyaTmdǷsQE"%Mi 1DbE[E .6YEH,:񴠫79A^m^Ri"./ z;eWh8ToF#/N Y "Zv<.t7--XJMymd+BQpl@mx,[#ZdzTGlivaRݵ7FUw"Gw:bFǠYkS*,+ZI Ju^nQH5^?A^M|X=u@JHa:PfiXpt=~s!Ϥ^Υeڡ5O /=/+rZMlg5vrk'5k)ЦjNg_LUFebGyͥGuw ǝ1a:)ڄmetYrk4"-:]R8?kZA=f G9@;9a2u>ԮU Z642K"h<;3pmClMUE f6{A A&ۚcyeYGt-~B~/jU@K`E5eZBN$zܥ:lAmkff} dЫ(Vx x޸h .F؝#N|andL] ؙzUNhR/2s@j6"BK{;~.6<ZMDd"3i&~dN ϋEUDQta{IaMM#f&b{;C\cEUHOA<rj@k,VHًw7/_x6zs$})ЗZ>{NWȌ.k-0lgrȅi&ɴ2;ܒţH܂ [7.kâ9nBt ! fU+W͋Hޕw͢5\6ѱq*S3ҭ:6%W~N=3h/EvӃ'{@9b] Z(MZXpv:#{HVD}AMYpjV8M{DCTگ0_0>'ame(y@ZJ7H [ ;+԰gFVs԰&=rn _AnXTf+dPĘFMp (2jr?A/#R|R 5@}[G &Mێ@ fya@W96vd{J8줕B_U^u*\[D];Ty֓c6X_ɮ:p^qȨ PthAyMw䱽`,I\m2;cg˽"ڼ#>(Wá`P݇qE"Nqؓ\Qj ͔8^B ?5dl2b]$2כۤ!{'տxx;3B}H~EKʭ䚑{UVvc*"J=!{=%ɲk=y@Mt-k-wWbPe]=1 KM ]O* ,CۛF0_L;~,8 ck5}j?pQPwo5qŪ^0^:'|plLN*Le>}J>X;"0+=#Y/:HcJ#&\>%h({һ ƿ2W&P=81`Pit>GQ+̪D3zHq D3l ;_xAQ8"'%sw)Rq{E􁈋vrT3` ܬ o[gL41qvV,&* r!+H%.%/R4js{!cU>Ԟ*'C|VsWR"=zÆ<Ʈxx7 V9h{uS>b/[ʗӣ,ď6\]'־@-T5rCi IA a_xp~!krXznaJGuW|WX{a} rt5ɽ.Y ܎Dʶ;I~QNgDyJ#]I͑v/*~*XET\::ڝ:dNIC2!S (E2{dN~!d % C_Wa[]/F~#_s Q+֘Q|pMyGW0~maZ%IxBe3l8ya#>ƛi"I:SoR;k`[ b.n:rmO~αkb?fU=>H"I^WꤕNԾR@Է9s$>p?[/OmeɈz2jA\( zXAɶЯP[ɏ?. B9C {dBVt\4l.L(D&\n_>E=ycjH-Y@tq.`% שLEݶ0t#gz(_Xc !3C{)fWH{o-c˜x @KDPlz8AlwvWe}T1p֘Hs HÌj>T]w ss,KU-hJb"- "Y7p657BޔgFFͿ29f-?{s5#dapx<.WHo2eKv8^œ$3Po hFo>?.Z#aV){ȾZ4<5!_o#旖IW} UV{ LbROGfۇGVQY#QoA'8C 7p!^iVB4kf24*Dˮ. &SW,w l szZ\Gxz !^Kgiא @5Gf w~@X^V}[~iqQ"LyP_F2R.@2K4jG~ϳ=L5, JZ  A mqVD["~XiM |E޼둒`/.dhsø,5;$mݛHU8Kw+}e f:Z{ pRNDrx=v_ }0IZ6V>pgg0\1*lsFvΰ)h9գ#Oќ C4_ԬO ɼ O*}Te.:#6:uO]. _"TTU]d^LV%EȷWo: N &'? U!Wii}f`kᯖzH+/nMD*t9wb5<\J[byn" `m?{5D h2=L^69i0t=T3s;zLH~~x^~ (nxd >iH$ ?oVxUhʃ颾|F^9MNlMo&*(x{{/d)paA~r19U!dzD9poc?1Wgx{O|C!3fuFm/l;ffz/Q;oÏ(1'˩ >x8^q VuQ~z*Ebv_g˯a&SF:h쎪8XVuv9Sv0Eg{U!.f18XR]ꮞt-b#4Yo}U+4꾛2oO' YTBw"S ;軗^hRFrGyGuWDn\nm厡Ro)!0v%)6Or+7 8vEwl@SOg0vnO # UlEC>cm>MG˄Ma"HK~m:&+v{H]`#~w-FХpJwU=oUOEϒRҍIR>Im\nj°d7 ?ȾgRl܈+ץ'==Qu>Ǽ/gj(-gD7IyXRiV/By6?oЯߧDAjؗ\dC8{u wq!١8~>>l\A,o/ӆ&0X@.G\)@ W"!ʨY5DI هG9Q/S>pgʲ>P\Z}+ڞ:ePkyV|KIs:A>%舮%6Xq;v;߷Z.]Y104m>K~~_|&0|saP=n nXpmɘrˍE~c$A<AF?*7!FJJWmٷ9 |b?'ŌmOv͎ͭ@CIC@ZdF~=HI QX?Mdn[tmklGP `WTЇ*(N=h$2rAX(:f͟u;cWy{Z{jvˡɘ/) . o/u׫M tڎk03r=DIt{;nQoa@Vm6u6ڧVuN053Ζ#9JfZ} z@R+7ӳ'^z`,#p̕ZZxw$;i>O~d!׈+p!|%aVJ~ǜ vPK!ޛ AUTHORS.rstPK! CONTRIBUTING.rstPK!&Q HISTORY.rstPK!Wv$LICENSEPK!ȇq (README.rstPK!y> Inegmas/__init__.pyPK!&DNNNnegmas/apps/__init__.pyPK!>dNnegmas/apps/scml/__init__.pyPK! //gnegmas/apps/scml/agent.pyPK!PJGC\C\~negmas/apps/scml/awi.pyPK!tcYv,v,negmas/apps/scml/bank.pyPK!)Q^? negmas/apps/scml/common.pyPK!=0|1|1negmas/apps/scml/consumers.pyPK!5[YY$'negmas/apps/scml/factory_managers.pyPK!)negmas/apps/scml/helpers.pyPK!v;//dnegmas/apps/scml/insurance.pyPK!+k~~negmas/apps/scml/miners.pyPK!n~r~r'negmas/apps/scml/schedulers.pyPK!>negmas/apps/scml/simulators.pyPK!ednegmas/apps/scml/utils.pyPK!Lx؆؆Bnegmas/apps/scml/world.pyPK!a))Q}negmas/common.pyPK!/negmas/events.pyPK!J2J20negmas/external/NegLoader.classPK!negmas/external/__init__.pyPK!nNu,negmas/external/jnegmas-1.0-SNAPSHOT-all.jarPK!d_GGLb negmas/external/negload.javaPK!pC negmas/generics.pyPK!Mwaa negmas/genius.pyPK!YQ& negmas/helpers.pyPK!rHrHT negmas/inout.pyPK!h=>^>^ negmas/java.pyPK!L  #]M negmas/logs/log_20190227-113253.txtPK!p |#  #nnnegmas/logs/log_20190227-113345.txtPK!wZ88#negmas/logs/log_20190227-113406.txtPK! y}#lnegmas/logs/log_20190227-113533.txtPK!Lu湐tnegmas/mechanisms.pyPK!+dOOnegmas/negotiators.pyPK!tTnegmas/outcomes.pyPK!Kxd negmas/sao.pyPK!0Y:negmas/scripts/__init__.pyPK!sj)V)Vnegmas/scripts/app.pyPK!bRR6negmas/situated.pyPK!4cnegmas/tests/__init__.pyPK!qqnegmas/tests/config/scml.jsonPK!:+ negmas/tests/config/scml.yamlPK!5>33.negmas/tests/data/10issues/10issues-domain.xmlPK!%unegmas/tests/data/10issues/pareto.xmlPK!,!>(negmas/tests/data/10issues/profile-1.xmlPK!iKا(negmas/tests/data/10issues/profile-2.xmlPK!>nś8negmas/tests/data/AMPOvsCity/ampo_vs_city_ampo_space.xmlPK!((8negmas/tests/data/AMPOvsCity/ampo_vs_city_city_space.xmlPK!y? ? 6'negmas/tests/data/AMPOvsCity/ampo_vs_city_template.xmlPK!Y;I,negmas/tests/data/Laptop/Laptop-C-domain.xmlPK!JJ+$negmas/tests/data/Laptop/Laptop-C-prof1.xmlPK!GG+*negmas/tests/data/Laptop/Laptop-C-prof2.xmlPK!yz&NN2#1negmas/tests/data/Laptop1Issue/Laptop-C-domain.xmlPK!urr13negmas/tests/data/Laptop1Issue/Laptop-C-prof1.xmlPK!)lss16negmas/tests/data/Laptop1Issue/Laptop-C-prof2.xmlPK!sHg[ [ 0D9negmas/tests/data/LaptopConv/Laptop-C-domain.xmlPK!V$j: : /Bnegmas/tests/data/LaptopConv/Laptop-C-prof1.xmlPK! !~; ; /tOnegmas/tests/data/LaptopConv/Laptop-C-prof2.xmlPK!fl l 2[negmas/tests/data/LaptopConv1D/Laptop-C-domain.xmlPK!b|KK1inegmas/tests/data/LaptopConv1D/Laptop-C-prof1.xmlPK!ȒLL1Rznegmas/tests/data/LaptopConv1D/Laptop-C-prof2.xmlPK!) n.negmas/tests/data/fuzzyagent/buyer_utility.xmlPK!E9`/܌negmas/tests/data/fuzzyagent/seller_utility.xmlPK!G0114Ȏnegmas/tests/data/fuzzyagent/single_issue_domain.xmlPK!sM_ _ BKnegmas/tests/data/scenarios/anac/y2010/EnglandZimbabwe/England.xmlPK!iQ negmas/tests/data/scenarios/anac/y2010/EnglandZimbabwe/EnglandZimbabwe_domain.xmlPK!G] ] C negmas/tests/data/scenarios/anac/y2010/EnglandZimbabwe/Zimbabwe.xmlPK!QJJNʯnegmas/tests/data/scenarios/anac/y2010/ItexvsCypress/ItexvsCypress_Cypress.xmlPK!+҂GGKnegmas/tests/data/scenarios/anac/y2010/ItexvsCypress/ItexvsCypress_Itex.xmlPK!:UM0negmas/tests/data/scenarios/anac/y2010/ItexvsCypress/ItexvsCypress_domain.xmlPK!Z X  =negmas/tests/data/scenarios/anac/y2010/Travel/travel_chox.xmlPK!ɸ ?negmas/tests/data/scenarios/anac/y2010/Travel/travel_domain.xmlPK!A7>negmas/tests/data/scenarios/anac/y2010/Travel/travel_fanny.xmlPK!5>33Dnegmas/tests/data/scenarios/other/S-1NIKFRT-1/S-1NIKFRT-1-domain.xmlPK!K /KK8negmas/tests/data/scenarios/other/S-1NIKFRT-1/pareto.xmlPK!Ő;6negmas/tests/data/scenarios/other/S-1NIKFRT-1/profile-1.xmlPK!Ty;?negmas/tests/data/scenarios/other/S-1NIKFRT-1/profile-2.xmlPK!MW\$$~#negmas/tests/fixtures.pyPK!g@B@B!(negmas/tests/scml/test_factory.pyPK!- oPoP#Wknegmas/tests/scml/test_scheduler.pyPK!nn!negmas/tests/test_SAOMechanism.pyPK!ECkk negmas/tests/test_basic_agent.pyPK!/BB]negmas/tests/test_genius.pyPK! negmas/tests/test_helpers.pyPK!5 rnegmas/tests/test_inout.pyPK!]] %negmas/tests/test_integration.pyPK!T0qf 7)negmas/tests/test_issue.pyPK!> F5negmas/tests/test_negotiators.pyPK!@K  @negmas/tests/test_outcomes.pyPK!׶**Lnegmas/tests/test_protocols.pyPK!|--wnegmas/tests/test_scml.pyPK!ntnegmas/tests/test_situated.pyPK!W|negmas/tests/test_utilities.pyPK!G9o9onegmas/tournaments.pyPK!NV"Anegmas/utilities.pyPK!H@)1' negmas-0.2.8.dist-info/entry_points.txtPK!Wv negmas-0.2.8.dist-info/LICENSEPK!HڽTU negmas-0.2.8.dist-info/WHEELPK!H@ %+ negmas-0.2.8.dist-info/METADATAPK!H L%a negmas-0.2.8.dist-info/RECORDPKhh j!