Source code for scml.scml2020.components.prediction

from abc import abstractmethod
from typing import Union, Iterable, List, Optional
import numpy as np

__all__ = [
    "TradePredictionStrategy",
    "FixedTradePredictionStrategy",
    "ExecutionRatePredictionStrategy",
    "FixedERPStrategy",
    "MeanERPStrategy",
]

from negmas import Contract, Breach


[docs]class TradePredictionStrategy: """A prediction strategy for expected inputs and outputs at every step Args: predicted_inputs: None for default, a number of an n_steps numbers giving predicted inputs predicted_outputs: None for default, a number of an n_steps numbers giving predicted outputs add_trade: If true, actual contracts will be just added to the expectations Provides: - `expected_inputs` : n_steps vector giving the predicted inputs at every time-step - `expected_outputs` : n_steps vector giving the predicted outputs at every time-step - `input_cost` : n_steps vector giving the predicted input cost at every time-step - `output_price` : n_steps vector giving the predicted output price at every time-step Remarks: - `Attributes` section describes the attributes that can be used to construct the component (passed to its `__init__` method). - `Provides` section describes the attributes (methods, properties, data-members) made available by this component directly. Note that everything provided by the bases of this components are also available to the agent (Check the `Bases` section above for all the bases of this component). - `Requires` section describes any requirements from the agent using this component. It defines a set of methods or properties/data-members that must exist in the agent that uses this component. These requirement are usually implemented as abstract methods in the component - `Abstract` section describes abstract methods that MUST be implemented by any descendant of this component. - `Hooks Into` section describes the methods this component overrides calling `super` () which allows other components to hook into the same method (by overriding it). Usually callbacks starting with `on_` are hooked into this way. - `Overrides` section describes the methods this component overrides without calling `super` effectively disallowing any other components after it in the MRO to call this method. Usually methods that do some action (i.e. not starting with `on_`) are overridden this way. """ def __init__( self, *args, predicted_outputs: Union[int, np.ndarray] = None, predicted_inputs: Union[int, np.ndarray] = None, add_trade=True, **kwargs ): super().__init__(*args, **kwargs) self.expected_outputs = predicted_outputs """Expected output quantity every step""" self.expected_inputs = predicted_inputs """Expected input quantity every step""" self.input_cost: np.ndarray = None """Expected unit price of the input""" self.output_price: np.ndarray = None """Expected unit price of the output""" self._add_trade = add_trade
[docs]class ExecutionRatePredictionStrategy: """ A prediction strategy for expected inputs and outputs at every step Provides: - `predict_quantity` : A method for predicting the quantity that will actually be executed from a contract Abstract: - `predict_quantity` : A method for predicting the quantity that will actually be executed from a contract Hooks Into: - `internal_state` Remarks: - `Attributes` section describes the attributes that can be used to construct the component (passed to its `__init__` method). - `Provides` section describes the attributes (methods, properties, data-members) made available by this component directly. Note that everything provided by the bases of this components are also available to the agent (Check the `Bases` section above for all the bases of this component). - `Requires` section describes any requirements from the agent using this component. It defines a set of methods or properties/data-members that must exist in the agent that uses this component. These requirement are usually implemented as abstract methods in the component - `Abstract` section describes abstract methods that MUST be implemented by any descendant of this component. - `Hooks Into` section describes the methods this component overrides calling `super` () which allows other components to hook into the same method (by overriding it). Usually callbacks starting with `on_` are hooked into this way. - `Overrides` section describes the methods this component overrides without calling `super` effectively disallowing any other components after it in the MRO to call this method. Usually methods that do some action (i.e. not starting with `on_`) are overridden this way. """
[docs] @abstractmethod def predict_quantity(self, contract: Contract): raise NotImplementedError("predict_quantity should be implemented by some other component.")
[docs]class FixedTradePredictionStrategy(TradePredictionStrategy): """ Predicts a fixed amount of trade both for the input and output products. Hooks Into: - `init` - `internal_state` - `on_contracts_finalized` Remarks: - `Attributes` section describes the attributes that can be used to construct the component (passed to its `__init__` method). - `Provides` section describes the attributes (methods, properties, data-members) made available by this component directly. Note that everything provided by the bases of this components are also available to the agent (Check the `Bases` section above for all the bases of this component). - `Requires` section describes any requirements from the agent using this component. It defines a set of methods or properties/data-members that must exist in the agent that uses this component. These requirement are usually implemented as abstract methods in the component - `Abstract` section describes abstract methods that MUST be implemented by any descendant of this component. - `Hooks Into` section describes the methods this component overrides calling `super` () which allows other components to hook into the same method (by overriding it). Usually callbacks starting with `on_` are hooked into this way. - `Overrides` section describes the methods this component overrides without calling `super` effectively disallowing any other components after it in the MRO to call this method. Usually methods that do some action (i.e. not starting with `on_`) are overridden this way. """
[docs] def init(self): self.input_cost = self.awi.catalog_prices[self.awi.my_input_product] * np.ones( self.awi.n_steps, dtype=int ) self.output_price = self.awi.catalog_prices[ self.awi.my_output_product ] * np.ones(self.awi.n_steps, dtype=int) inp = self.awi.my_input_product def adjust(x, demand): """Adjust the predicted demand/supply filling it with a default value or repeating as needed""" if x is None: x = max(1, self.awi.n_lines // 2) elif isinstance(x, Iterable): return np.array(x) predicted = int(x) * np.ones(self.awi.n_steps, dtype=int) if demand: predicted[: inp + 1] = 0 else: predicted[inp - self.awi.n_processes :] = 0 return predicted # adjust predicted demand and supply self.expected_outputs = adjust(self.expected_outputs, True) self.expected_inputs = adjust(self.expected_inputs, False) super().init()
@property def internal_state(self): state = super().internal_state state.update( { "expected_inputs": self.expected_inputs, "expected_outputs": self.expected_outputs, "input_cost": self.input_cost, "output_price": self.output_price, } ) return state
[docs] def on_contracts_finalized( self, signed: List[Contract], cancelled: List[Contract], rejectors: List[List[str]], ) -> None: super().on_contracts_finalized(signed, cancelled, rejectors) if not self._add_trade: return for contract in signed: t, q = contract.agreement["time"], contract.agreement["quantity"] if contract.annotation["seller"] == self.id: self.expected_outputs[t] += q else: self.expected_inputs[t] += q
[docs]class FixedERPStrategy(ExecutionRatePredictionStrategy): """Predicts that the there is a fixed execution rate that does not change for all partners Args: execution_fraction: The expected fraction of any contract's quantity to be executed Provides: - `predict_quantity` : A method for predicting the quantity that will actually be executed from a contract Hooks Into: - `internal_state` Remarks: - `Attributes` section describes the attributes that can be used to construct the component (passed to its `__init__` method). - `Provides` section describes the attributes (methods, properties, data-members) made available by this component directly. Note that everything provided by the bases of this components are also available to the agent (Check the `Bases` section above for all the bases of this component). - `Requires` section describes any requirements from the agent using this component. It defines a set of methods or properties/data-members that must exist in the agent that uses this component. These requirement are usually implemented as abstract methods in the component - `Abstract` section describes abstract methods that MUST be implemented by any descendant of this component. - `Hooks Into` section describes the methods this component overrides calling `super` () which allows other components to hook into the same method (by overriding it). Usually callbacks starting with `on_` are hooked into this way. - `Overrides` section describes the methods this component overrides without calling `super` effectively disallowing any other components after it in the MRO to call this method. Usually methods that do some action (i.e. not starting with `on_`) are overridden this way. """ def __init__(self, *args, execution_fraction=0.5, **kwargs): super().__init__(*args, **kwargs) self._execution_fraction = execution_fraction
[docs] def predict_quantity(self, contract: Contract): return contract.agreement["quantity"] * self._execution_fraction
[docs]class MeanERPStrategy(ExecutionRatePredictionStrategy): """ Predicts that the there is a fixed execution rate that does not change for all partners Args: execution_fraction: The expected fraction of any contract's quantity to be executed Provides: - `predict_quantity` : A method for predicting the quantity that will actually be executed from a contract Hooks Into: - `internal_state` - `init` - `on_contract_executed` - `on_contract_breached` Remarks: - `Attributes` section describes the attributes that can be used to construct the component (passed to its `__init__` method). - `Provides` section describes the attributes (methods, properties, data-members) made available by this component directly. Note that everything provided by the bases of this components are also available to the agent (Check the `Bases` section above for all the bases of this component). - `Requires` section describes any requirements from the agent using this component. It defines a set of methods or properties/data-members that must exist in the agent that uses this component. These requirement are usually implemented as abstract methods in the component - `Abstract` section describes abstract methods that MUST be implemented by any descendant of this component. - `Hooks Into` section describes the methods this component overrides calling `super` () which allows other components to hook into the same method (by overriding it). Usually callbacks starting with `on_` are hooked into this way. - `Overrides` section describes the methods this component overrides without calling `super` effectively disallowing any other components after it in the MRO to call this method. Usually methods that do some action (i.e. not starting with `on_`) are overridden this way. """ def __init__(self, *args, execution_fraction=0.5, **kwargs): super().__init__(*args, **kwargs) self._execution_fraction = execution_fraction self._total_quantity = None
[docs] def predict_quantity(self, contract: Contract): return contract.agreement["quantity"] * self._execution_fraction
[docs] def init(self): super().init() self._total_quantity = max(1, self.awi.n_steps * self.awi.n_lines // 10)
@property def internal_state(self): state = super().internal_state state.update({ "execution_fraction": self._execution_fraction }) return state
[docs] def on_contract_executed(self, contract: Contract) -> None: super().on_contract_executed(contract) old_total = self._total_quantity q = contract.agreement["quantity"] self._total_quantity += q self._execution_fraction = ( self._execution_fraction * old_total + q ) / self._total_quantity
[docs] def on_contract_breached( self, contract: Contract, breaches: List[Breach], resolution: Optional[Contract] ) -> None: super().on_contract_breached(contract, breaches, resolution) old_total = self._total_quantity q = contract.agreement["quantity"] * max(b.level for b in breaches) self._total_quantity += q self._execution_fraction = ( self._execution_fraction * old_total + q ) / self._total_quantity