scml.std.agents =============== .. py:module:: scml.std.agents Submodules ---------- .. toctree:: :maxdepth: 1 /autoapi/scml/std/agents/aspiration/index /autoapi/scml/std/agents/greedy/index /autoapi/scml/std/agents/nothing/index /autoapi/scml/std/agents/rand/index Attributes ---------- .. autoapisummary:: scml.std.agents.StdDoNothingAgent scml.std.agents.__all__ Classes ------- .. autoapisummary:: scml.std.agents.SingleAgreementAspirationAgent scml.std.agents.GreedyStdAgent scml.std.agents.GreedySyncAgent scml.std.agents.GreedyOneShotAgent scml.std.agents.StdPlaceholder scml.std.agents.SyncRandomStdAgent scml.std.agents.SyncRandomOneShotAgent scml.std.agents.RandomStdAgent Package Contents ---------------- .. py:class:: SingleAgreementAspirationAgent(*args, **kwargs) Bases: :py:obj:`scml.oneshot.agent.OneShotSyncAgent` Uses a time-based strategy to accept a single agreement from the set it is considering. .. py:method:: before_step() Called at the beginning of every step. Remarks: - Use this for any proactive code that needs to be done every simulation step. .. py:method:: counter_all(offers, states) Calculate a response to all offers from all negotiators (negotiator ID is the key). :param offers: Maps negotiator IDs to offers :param states: Maps negotiator IDs to offers AT the time the offers were made. :returns: A dictionary mapping negotiator ID to an `SAOResponse`. The response per agent consist of a tuple. In case of acceptance or ending the negotiation the second item of the tuple should be None. In case of rejection, the second item should be the counter offer. Remarks: - The response type CANNOT be WAIT. - If the system determines that a loop is formed, the agent may receive this call for a subset of negotiations not all of them. .. py:method:: choose_agents(offers, outcome) Selects an appropriate way to distribute this outcome to agents with given IDs. .. py:method:: first_proposals() -> Dict[str, negmas.Outcome | None] Gets a set of proposals to use for initializing the negotiation. :returns: A dictionary mapping each negotiator (in self.negotiators dict) to an outcome to be used as the first proposal if the agent is to start a negotiation. .. py:class:: GreedyStdAgent(*args, concession_exponent=None, acc_price_slack=float('inf'), step_price_slack=None, opp_price_slack=None, opp_acc_price_slack=None, range_slack=None, future_threshold=0.9, production_target=0.75, **kwargs) Bases: :py:obj:`scml.std.agent.StdAgent` A greedy agent based on StdAgent :param concession_exponent: A real number controlling how fast does the agent concede on price. :param acc_price_slack: The allowed slack in price limits compared with best prices I got so far :param step_price_slack: The allowed slack in price limits compared with best prices I got this step :param opp_price_slack: The allowed slack in price limits compared with best prices I got so far from a given opponent in this step :param opp_acc_price_slack: The allowed slack in price limits compared with best prices I got so far from a given opponent so far :param range_slack: Always consider prices above (1-`range_slack`) of the best possible prices *good enough*. :param production_target: Fraction of production capacity to be secured in advance Remarks: - A `concession_exponent` greater than one makes the agent concede super linearly and vice versa .. py:attribute:: _e :value: None .. py:attribute:: _acc_price_slack .. py:attribute:: _step_price_slack :value: None .. py:attribute:: _opp_price_slack :value: None .. py:attribute:: _opp_acc_price_slack :value: None .. py:attribute:: _range_slack :value: None .. py:attribute:: _production_target :value: 0.75 .. py:attribute:: _future_threshold :value: 0.9 .. py:method:: init() Initialize the quantities and best prices received so far .. py:method:: before_step() Initialize the quantities and best prices received for next step .. py:method:: on_negotiation_success(contract, mechanism) Record sales/supplies secured .. py:method:: propose(negotiator_id: str, state, source=None) -> negmas.Outcome | None Proposes an offer to one of the partners. :param negotiator_id: ID of the negotiator (and partner) :param state: Mechanism state including current step :returns: an outcome to offer. .. py:method:: respond(negotiator_id, state, source=None) -> negmas.ResponseType Responds to an offer from one of the partners. :param negotiator_id: ID of the negotiator (and partner) :param state: Mechanism state including current step :returns: A response type which can either be reject, accept, or end negotiation. Remarks: default behavior is to accept only if the current offer is the same or has a higher utility compared with what the agent would have proposed in the given state and reject otherwise .. py:method:: best_offer(negotiator_id) .. py:method:: _future_needs(negotiator_id, t) .. py:method:: _needed(negotiator_id) .. py:method:: _is_selling(nmi) .. py:method:: _is_good_price(nmi, state, offer) Checks if a given price is good enough at this stage .. py:method:: _find_good_price(nmi, state, offer) Finds a good-enough price conceding linearly over time .. py:method:: _price_range(nmi, offer) Limits the price by the best price received .. py:method:: _th(step, n_steps) calculates a descending threshold (0 <= th <= 1) .. py:class:: GreedySyncAgent(*args, threshold=None, **kwargs) Bases: :py:obj:`scml.oneshot.agent.OneShotSyncAgent`, :py:obj:`GreedyOneShotAgent` A greedy agent based on OneShotSyncAgent .. py:attribute:: _threshold :value: None .. py:attribute:: ufun :type: scml.oneshot.ufun.OneShotUFun Returns the preferences if it is a `BaseUtilityFunction` else None .. py:method:: before_step() Called at the beginning of every step. Remarks: - Use this for any proactive code that needs to be done every simulation step. .. py:method:: first_proposals() Decide a first proposal on every negotiation. Returning None for a negotiation means ending it. .. py:method:: counter_all(offers, states) -> dict Respond to a set of offers given the negotiation state of each. .. py:method:: _needs() Returns both input and output needs .. py:method:: propose(negotiator_id, state) Proposes an offer to one of the partners. :param negotiator_id: ID of the negotiator (and partner) :param state: Mechanism state including current step :returns: an outcome to offer. .. py:method:: respond(negotiator_id, state, source='') Responds to an offer from one of the partners. :param negotiator_id: ID of the negotiator (and partner) :param state: Mechanism state including current step :returns: A response type which can either be reject, accept, or end negotiation. Remarks: default behavior is to accept only if the current offer is the same or has a higher utility compared with what the agent would have proposed in the given state and reject otherwise .. py:class:: GreedyOneShotAgent(*args, concession_exponent=None, acc_price_slack=float('inf'), step_price_slack=None, opp_price_slack=None, opp_acc_price_slack=None, range_slack=None, **kwargs) Bases: :py:obj:`scml.oneshot.agent.OneShotAgent` A greedy agent based on OneShotAgent :param concession_exponent: A real number controlling how fast does the agent concede on price. :param acc_price_slack: The allowed slack in price limits compared with best prices I got so far :param step_price_slack: The allowed slack in price limits compared with best prices I got this step :param opp_price_slack: The allowed slack in price limits compared with best prices I got so far from a given opponent in this step :param opp_acc_price_slack: The allowed slack in price limits compared with best prices I got so far from a given opponent so far :param range_slack: Always consider prices above (1-`range_slack`) of the best possible prices *good enough*. Remarks: - A `concession_exponent` greater than one makes the agent concede super linearly and vice versa .. py:attribute:: _e :value: None .. py:attribute:: _acc_price_slack .. py:attribute:: _step_price_slack :value: None .. py:attribute:: _opp_price_slack :value: None .. py:attribute:: _opp_acc_price_slack :value: None .. py:attribute:: _range_slack :value: None .. py:method:: init() Initialize the quantities and best prices received so far .. py:method:: before_step() Initialize the quantities and best prices received for next step .. py:method:: on_negotiation_success(contract, mechanism) Record sales/supplies secured .. py:method:: propose(negotiator_id: str, state, source=None) -> negmas.Outcome | None Proposes an offer to one of the partners. :param negotiator_id: ID of the negotiator (and partner) :param state: Mechanism state including current step :returns: an outcome to offer. .. py:method:: respond(negotiator_id, state, source=None) -> negmas.ResponseType Responds to an offer from one of the partners. :param negotiator_id: ID of the negotiator (and partner) :param state: Mechanism state including current step :returns: A response type which can either be reject, accept, or end negotiation. Remarks: default behavior is to accept only if the current offer is the same or has a higher utility compared with what the agent would have proposed in the given state and reject otherwise .. py:method:: best_offer(negotiator_id) .. py:method:: _needed(negotiator_id) .. py:method:: _is_selling(nmi) .. py:method:: _is_good_price(nmi, state, price) Checks if a given price is good enough at this stage .. py:method:: _find_good_price(nmi, state) Finds a good-enough price conceding linearly over time .. py:method:: _price_range(nmi) Limits the price by the best price received .. py:method:: _th(step, n_steps) calculates a descending threshold (0 <= th <= 1) .. py:data:: StdDoNothingAgent .. py:class:: StdPlaceholder(*args, **kwargs) Bases: :py:obj:`scml.std.policy.StdPolicy` An agent that always raises an exception if called to negotiate. It is useful as a placeholder (for example for RL and MARL exposition) .. py:method:: act(state) The main policy. Generates an action given a state .. py:class:: SyncRandomStdAgent(*args, today_target_productivity=0.3, future_target_productivity=0.3, today_concentration=0.25, future_concentration=0.75, today_concession_exp=2.0, future_concession_exp=4.0, future_min_price=0.25, prioritize_near_future: bool = False, prioritize_far_future: bool = False, pfuture=0.15, **kwargs) Bases: :py:obj:`scml.std.agent.StdSyncAgent` An agent that distributes its needs over its partners randomly. .. py:attribute:: ptoday :value: 0.85 .. py:attribute:: today_exp :value: 2.0 .. py:attribute:: future_exp :value: 4.0 .. py:attribute:: fmin :value: 0.25 .. py:attribute:: today_productivity :value: 0.3 .. py:attribute:: future_productivity :value: 0.3 .. py:attribute:: near :value: False .. py:attribute:: far :value: False .. py:attribute:: future_concentration :value: 0.75 .. py:attribute:: today_concentration :value: 0.25 .. py:method:: first_proposals() Gets a set of proposals to use for initializing the negotiation. :returns: A dictionary mapping each negotiator (in self.negotiators dict) to an outcome to be used as the first proposal if the agent is to start a negotiation. .. py:method:: counter_all(offers, states) Calculate a response to all offers from all negotiators (negotiator ID is the key). :param offers: Maps negotiator IDs to offers :param states: Maps negotiator IDs to offers AT the time the offers were made. :returns: A dictionary mapping negotiator ID to an `SAOResponse`. The response per agent consist of a tuple. In case of acceptance or ending the negotiation the second item of the tuple should be None. In case of rejection, the second item should be the counter offer. Remarks: - The response type CANNOT be WAIT. - If the system determines that a loop is formed, the agent may receive this call for a subset of negotiations not all of them. .. py:method:: distribute_todays_needs(partners=None) -> dict[str, int] Distributes my needs randomly over all my partners .. py:method:: estimate_future_needs() Estimates how much I need to buy and sell for each future step .. py:method:: distribute_future_offers(partners: list[str]) -> dict[str, negmas.Outcome | None] Distribute future offers over the given partners .. py:method:: is_supplier(negotiator_id) .. py:method:: is_consumer(negotiator_id) .. py:method:: best_price(partner_id) Best price for a negotiation today .. py:method:: good_price(partner_id, today: bool) A good price to use .. py:method:: buy_price(t: float, mn: float, mx: float, today: bool) -> float Return a good price to buy at .. py:method:: sell_price(t: float, mn: float, mx: float, today: bool) -> float Return a good price to sell at .. py:method:: good2buy(p: float, t: float, mn, mx, today: bool) Is p a good price to buy at? .. py:method:: good2sell(p: float, t: float, mn, mx, today: bool) Is p a good price to sell at? .. py:class:: SyncRandomOneShotAgent(*args, equal: bool = False, overordering_max: float = 0.2, overordering_min: float = 0.0, overordering_exp: float = 0.4, mismatch_exp: float = 4.0, mismatch_max: float = 0.3, **kwargs) Bases: :py:obj:`scml.oneshot.agent.OneShotSyncAgent` An agent that distributes its needs over its partners randomly. :param equal: If given, it tries to equally distribute its needs over as many of its suppliers/consumers as possible :param overordering_max: Maximum fraction of needs to over-order. For example, it the agent needs 5 items and this is 0.2, it will order 6 in the first negotiation step. :param overordering_min: Minimum fraction of needs to over-order. Used in the last negotiation step. :param overordering_exp: Controls how fast does the over-ordering quantity go from max to min. :param concession_exp: Controls how fast does the agent concedes on matching its needs exactly. :param mismatch_max: Maximum mismtach in quantity allowed between needs and accepted offers. If a fraction, it is will be this fraction of the production capacity (n_lines). .. py:attribute:: equal_distribution :value: False .. py:attribute:: overordering_max :value: 0.2 .. py:attribute:: overordering_min :value: 0.0 .. py:attribute:: overordering_exp :value: 0.4 .. py:attribute:: mismatch_exp :value: 4.0 .. py:attribute:: mismatch_max :value: 0.3 .. py:method:: init() Called once after the AWI is set. Remarks: - Use this for any proactive initialization code. .. py:method:: distribute_needs(t: float) -> dict[str, int] Distributes my needs randomly over all my partners .. py:method:: first_proposals() Gets a set of proposals to use for initializing the negotiation. :returns: A dictionary mapping each negotiator (in self.negotiators dict) to an outcome to be used as the first proposal if the agent is to start a negotiation. .. py:method:: counter_all(offers, states) Calculate a response to all offers from all negotiators (negotiator ID is the key). :param offers: Maps negotiator IDs to offers :param states: Maps negotiator IDs to offers AT the time the offers were made. :returns: A dictionary mapping negotiator ID to an `SAOResponse`. The response per agent consist of a tuple. In case of acceptance or ending the negotiation the second item of the tuple should be None. In case of rejection, the second item should be the counter offer. Remarks: - The response type CANNOT be WAIT. - If the system determines that a loop is formed, the agent may receive this call for a subset of negotiations not all of them. .. py:method:: _allowed_mismatch(r: float) .. py:method:: _overordering_fraction(t: float) .. py:method:: _step_and_price(best_price=False) Returns current step and a random (or max) price .. py:class:: RandomStdAgent(owner=None, ufun=None, name=None, p_accept=PROB_ACCEPTANCE, p_end=PROB_END) Bases: :py:obj:`scml.std.agent.StdAgent` A naive random agent .. py:method:: propose(negotiator_id: str, state: negmas.sao.SAOState) -> negmas.Outcome | None Proposes an offer to one of the partners. :param negotiator_id: ID of the negotiator (and partner) :param state: Mechanism state including current step :returns: an outcome to offer. .. py:method:: respond(negotiator_id, state, source=None) Responds to an offer from one of the partners. :param negotiator_id: ID of the negotiator (and partner) :param state: Mechanism state including current step :returns: A response type which can either be reject, accept, or end negotiation. Remarks: default behavior is to accept only if the current offer is the same or has a higher utility compared with what the agent would have proposed in the given state and reject otherwise .. py:data:: __all__