Exemple #1
0
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)
    a2 = LimitedOutcomesAcceptor(acceptable_outcomes=to_be_accepted)
    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"
Exemple #2
0
    def ranking_error(
        self,
        gt: Union[List[float], Dict[Outcome, float], UtilityFunction],
        tolerance: float = 0.0,
    ) -> float:
        """
        Evaluates the utility function against gt counting differences in ranking only

        Args:

            gt: Ground truth ufun
            tolerance: a small tolerance when finding if the ranking is respected

        Returns:

            A value between zero and one indicating the ranking error
        """
        if isinstance(gt, list):
            gt = dict(zip(self.outcomes, gt))
        if not isinstance(gt, UtilityFunction):
            gt = MappingUtilityFunction(gt)
        rank = ranking(self, self.outcomes)
        return sum(
            int(float(gt(w1)) + tolerance < float(gt(w2)))
            for w1, w2 in zip(rank[:-1], rank[1:])) / (len(self.outcomes) - 1)
Exemple #3
0
def test_loops_are_broken(keep_order):
    """Tests that loops formed by concurrent negotiations are broken for syn controllers"""
    from negmas.mechanisms import Mechanism
    from negmas.sao import SAOSingleAgreementAspirationController

    a, b, c = (
        SAOSingleAgreementAspirationController(
            ufun=MappingUtilityFunction(lambda x: x["price"]), strict=False),
        SAOSingleAgreementAspirationController(
            ufun=MappingUtilityFunction(lambda x: x["price"]), strict=False),
        SAOSingleAgreementAspirationController(
            ufun=MappingUtilityFunction(lambda x: x["price"]), strict=False),
    )

    n1 = SAOMechanism(
        name="ab",
        issues=[Issue((0.0, 1.0), "price")],
        n_steps=50,
        outcome_type=dict,
    )
    n2 = SAOMechanism(
        name="ac",
        issues=[Issue((0.0, 1.0), "price")],
        n_steps=50,
        outcome_type=dict,
    )
    n3 = SAOMechanism(
        name="bc",
        issues=[Issue((0.0, 1.0), "price")],
        n_steps=50,
        outcome_type=dict,
    )

    n1.add(a.create_negotiator(name="a>b"))
    n1.add(b.create_negotiator(name="b>a"))
    n2.add(a.create_negotiator(name="a>c"))
    n2.add(c.create_negotiator(name="c>a"))
    n3.add(b.create_negotiator(name="b>c"))
    n3.add(c.create_negotiator(name="c>b"))
    negs = [n1, n2, n3]
    Mechanism.runall(negs, keep_order)

    agreements = [neg.state.agreement for neg in negs]
    assert sum(_ is not None for _ in agreements) > 0
Exemple #4
0
 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=MappingUtilityFunction(
         mapping=lambda x: 1.0 - x["i1"] / 10.0))
     return negotiator
def test_lap_ufun_full_ranking():
    issues = [Issue(5, "Price"), Issue(5, "Distance")]
    gt = {(o["Price"], o["Distance"]): 0.2 * o["Price"] - 0.45 * o["Distance"]
          for o in Issue.enumerate(issues, astype=dict)}
    full_ranking = [
        _[0] for _ in sorted(
            zip(gt.keys(), gt.values()), key=lambda x: x[1], reverse=True)
    ]
    for kind in ("error_sums", "errors"):
        ufun = RankingLAPUfunLearner(issues=issues, degree=1, kind=kind)
        ufun.fit(ranking_list=full_ranking)
        learned_ranking = [
            _[0] for _ in sorted(
                zip(ufun.uvals.keys(), ufun.uvals.values()),
                key=lambda x: x[1],
                reverse=True,
            )
        ]
        if kind == "error_sums":
            assert full_ranking == learned_ranking, f"Failed on {kind}"
            assert (ufun.ranking_error(gt=MappingUtilityFunction(
                lambda o: 0.2 * o[0] - 0.45 * o[1])) == 0.0)
Exemple #6
0
    def value_error(
        self, gt: Union[List[float], Dict[Outcome, float], UtilityFunction]
    ) -> Tuple[float, float]:
        """
        Finds the error in ufun values against gt (after normalization from 0-1)

        Args:
            gt: Ground truth

        Returns:

            Mean and std. dev of errors

        """
        if isinstance(gt, list):
            gt = dict(zip(self.outcomes, gt))
        if not isinstance(gt, UtilityFunction):
            gt = MappingUtilityFunction(gt)
        data = np.array([[float(gt(outcome)),
                          float(self(outcome))] for outcome in self.outcomes])
        mx, mn = data.max(axis=0), data.min(axis=0)
        data = (data - mn) / (mx - mn)
        err = (data[:, 0] - data[:, 1])**2
        return float(np.sqrt(np.mean(err))), float(np.std(err))
Exemple #7
0
    def init(self):
        """Called once after the agent-world interface is initialized"""

        # We assume the agent only takes one kind of input.
        if len(self.consuming.keys()) != 1:
            raise Exception('The agent is design to consume only one input')
        self.input_index = list(self.consuming.keys())[0]

        # We assume the agent only produced one kind of output.
        if len(self.producing.keys()) != 1:
            raise Exception('The agent is design to produce only one output')
        self.output_index = list(self.producing.keys())[0]

        self.production_cost = self.line_profiles[0][0].cost
        self.num_intermediate_products = len(self.awi.processes) - 1

        # Compute Expected Catalog Prices
        self.expected_catalog_prices[0] = 1.0
        for p in range(1, self.num_intermediate_products + 2):
            self.expected_catalog_prices[p] = 1.15 * (self.expected_catalog_prices[p - 1] + 2.5)

        # Initialize book keeping structures.
        for p in range(0, self.num_intermediate_products + 2):
            self.storage_history[p] = []
            self.contracted_buys_at_t[p], self.contracted_sales_at_t[p], self.executed_buys_at_t[p], self.executed_sales_at_t[p] = {}, {}, {}, {}
            self.signed_contracts_for_factory = {t: [] for t in range(0, self.awi.n_steps)}
            for t in range(0, self.awi.n_steps):
                self.contracted_buys_at_t[p][t] = 0
                self.contracted_sales_at_t[p][t] = 0
                self.executed_buys_at_t[p][t] = (0, 0)
                self.executed_sales_at_t[p][t] = (0, 0)

        # Initialize the negotiator that will negotiate for inputs
        self.input_negotiator_ufun = MappingUtilityFunction(mapping=lambda outcome: 1 - outcome['unit_price'], reserved_value=INVALID_UTILITY)

        # Initialize the negotiator that will negotiate for outputs
        self.output_negotiator_ufun = MappingUtilityFunction(
            mapping=lambda outcome: (math.exp(outcome['unit_price']) - 1.5) * outcome['quantity'] if outcome["unit_price"] > 0.0 else INVALID_UTILITY)

        # Set the time limit for posting CFPs.
        self.limit_post_cfps = self.awi.n_steps - 16

        # Set the time limit to sign CFPs to buy input
        self.limit_sign_time_input_product = self.awi.n_steps - 10

        # Initialize the brain of the agent. The brain takes in the input product, the output product, cost of production and num_intm_products.
        self.agent_brain = AgentBrain(game_length=self.awi.n_steps,
                                      input_product_index=self.input_index,
                                      output_product_index=self.output_index,
                                      production_cost=self.production_cost,
                                      num_intermediate_products=self.num_intermediate_products,
                                      verbose=self.verbose)

        # Register interest in all products.
        self.awi.unregister_interest([self.input_index, self.output_index])
        self.awi.register_interest([p for p in range(0, self.num_intermediate_products + 2)])

        if self.verbose:
            # Print some init info for informational purposes
            print(f'\n+++++++++++++++++++++++++++++++++++++++\n'
                  f'Starting game with a total of {self.awi.n_steps} steps\n'
                  f'\t Expected catalog prices = {self.expected_catalog_prices}\n'
                  f'\t There are {self.num_intermediate_products} intermediate products. \n'
                  f'\t SCML2020World processes = {self.awi.processes}\n'
                  f'\t My Cost = {self.line_profiles[0][0].cost}\n'
                  f'\t I, {self.id}, consume {self.input_index} and produce {self.output_index}\n'
                  f'\t Is the middle man active? {self.middle_man_active}\n'
                  f'+++++++++++++++++++++++++++++++++++++++\n')

            print(f'Parameters: '
                  f'\n\t hyper_parameter_optimization = {self.hyper_parameter_optimization}'
                  f'\n\t agent_aspiration_type = {self.agent_aspiration_type}'
                  f'\n\t limit_sign_storage = {self.limit_sign_storage}'
                  f'\n\t limit_number_sales_contracts_at_t = {self.limit_number_sales_contracts_at_t}'
                  f'\n\t limit_number_buys_contracts_at_t = {self.limit_number_buys_contracts_at_t}'
                  f'\n\t cfp_qtty_range_width = {self.cfp_qtty_range_width}'
                  f'\n ------------------------------------')

        # Which products will the middle man buy and sell?
        self.middle_man_products = {p for p in range(0, self.num_intermediate_products + 2) if p != self.input_index and p != self.output_index}
        if self.verbose:
            print(f'The middle man can buy and sell {self.middle_man_products}')
Exemple #8
0
        if self.ami:
            # the ami is not None, means, can use the factor defined by user!
            # return self.delta**(getattr(self.ami.state, self.factor) - 1) * sum(w * v for w, v in zip(self.weights, offer))
            return sum(w * v for w, v in zip(self.weights, offer))
        else:
            return sum(w * v for w, v in zip(self.weights, offer))

    def xml(self, issues: List[Issue]) -> str:
        output = ""
        keys = list(ikeys(issues))
        for i, k in enumerate(keys):
            issue_name = iget(issues, k).name
            output += f'<issue index="{i+1}" etype="discrete" type="discrete" vtype="discrete" name="{issue_name}">\n'
            vals = iget(issues, k).all
            for indx, u in enumerate(vals):
                output += (
                    f'    <item index="{indx+1}" value="{u}" evaluation="{u}" />\n'
                )
            output += "</issue>\n"
        for i, k in enumerate(keys):
            output += (
                f'<weight index="{i+1}" value="{iget(self.weights, k)}">\n</weight>\n'
            )
        return output

    def __str__(self):
        return f"w: {self.weights}, delta: {self.delta}, factor: {self.factor}"


MyOpponentUtilityFunction = MappingUtilityFunction(
    lambda x: random.random() * x[0])