Getting Started =============== Running a negotiation --------------------- NegMAS has several built-in negotiation ``Mechanisms``, negotiation agents (``Negotiators``), and ``UtilityFunctions``. You can use these to run negotiations as follows. Imagine a buyer and a seller negotiating over the price of a single object. First, we make an issue “price” with 50 discrete values. Note here, it is possible to create multiple issues, but we will not include that here. If you are interested, see the `NegMAS documentation `__ for a tutorial. .. code:: ipython3 from negmas import make_issue, SAOMechanism, TimeBasedConcedingNegotiator from negmas.sao.negotiators import BoulwareTBNegotiator as Boulware from negmas.sao.negotiators import LinearTBNegotiator as Linear from negmas.preferences import LinearAdditiveUtilityFunction as UFun from negmas.preferences.value_fun import IdentityFun, AffineFun import matplotlib.pyplot as plt # create negotiation agenda (issues) issues = [make_issue(name="price", values=50)] # create the mechanism mechanism = SAOMechanism(issues=issues, n_steps=20) The negotiation protocol in NegMAS is handled by a ``Mechanism`` object. Here we instantiate a\ ``SAOMechanism`` which implements the `Stacked Alternating Offers Protocol `__. In this protocol, negotiators exchange offers until an offer is accepted by all negotiators (in this case 2), a negotiators leaves the table ending the negotiation or a time-out condition is met. In the example above, we use a limit on the number of rounds of ``20`` (a step of a mechanism is an executed round). Next, we define the utilities of the seller and the buyer. The utility function of the seller is defined by the ``IdentityFun`` which means that the higher the price, the higher the utility function. The buyer’s utility function is reversed. The last two lines make sure that utility is scaled between 0 and 1. .. code:: ipython3 seller_utility = UFun(values=[IdentityFun()], outcome_space=mechanism.outcome_space) buyer_utility = UFun( values=[AffineFun(slope=-1)], outcome_space=mechanism.outcome_space ) seller_utility = seller_utility.normalize() buyer_utility = buyer_utility.normalize() Then we add two agents with a boulware strategy. The negotiation ends with status overview. For example, you can see if the negotiation timed-out, what agreement was found, and how long the negotiation took. Moreover, we output the full negotiation history. For a more visual representation, we can plot the session. This shows the bidding curve, but also the proximity to e.g. the Nash point. .. code:: ipython3 # create and add agent A and B mechanism.add(Boulware(name="seller"), ufun=seller_utility) mechanism.add(Linear(name="buyer"), ufun=buyer_utility) # run the negotiation and show the results print(mechanism.run()) .. raw:: html
SAOState(
        running=False,
        waiting=False,
        started=True,
        step=16,
        time=0.003750874995603226,
        relative_time=0.8095238095238095,
        broken=False,
        timedout=False,
        agreement=(35,),
        results=None,
        n_negotiators=2,
        has_error=False,
        error_details='',
        erred_negotiator='',
        erred_agent='',
        threads={},
        last_thread='',
        current_offer=(35,),
        current_proposer='buyer-953acaf8-4227-4d51-a652-8626f799fa76',
        current_proposer_agent=None,
        n_acceptances=2,
        new_offers=[],
        new_offerer_agents=[None, None],
        last_negotiator='buyer',
        current_data=None,
        new_data=[]
    )
    
In this case, the negotiation ended with an agreement which is indicated by the ``agreement`` field of the `SAOState `__. We can see a trace of the negotiation giving the step number, agent-id and its offer using the ``extended_trace`` property of the mechanism (session): .. code:: ipython3 # negotiation history print(mechanism.extended_trace) .. raw:: html
[
        (0, 'seller-e3614ef9-6d24-442a-9332-b15342ffa1e4', (49,)),
        (0, 'buyer-953acaf8-4227-4d51-a652-8626f799fa76', (2,)),
        (1, 'seller-e3614ef9-6d24-442a-9332-b15342ffa1e4', (49,)),
        (1, 'buyer-953acaf8-4227-4d51-a652-8626f799fa76', (4,)),
        (2, 'seller-e3614ef9-6d24-442a-9332-b15342ffa1e4', (49,)),
        (2, 'buyer-953acaf8-4227-4d51-a652-8626f799fa76', (7,)),
        (3, 'seller-e3614ef9-6d24-442a-9332-b15342ffa1e4', (49,)),
        (3, 'buyer-953acaf8-4227-4d51-a652-8626f799fa76', (9,)),
        (4, 'seller-e3614ef9-6d24-442a-9332-b15342ffa1e4', (49,)),
        (4, 'buyer-953acaf8-4227-4d51-a652-8626f799fa76', (11,)),
        (5, 'seller-e3614ef9-6d24-442a-9332-b15342ffa1e4', (49,)),
        (5, 'buyer-953acaf8-4227-4d51-a652-8626f799fa76', (14,)),
        (6, 'seller-e3614ef9-6d24-442a-9332-b15342ffa1e4', (49,)),
        (6, 'buyer-953acaf8-4227-4d51-a652-8626f799fa76', (16,)),
        (7, 'seller-e3614ef9-6d24-442a-9332-b15342ffa1e4', (48,)),
        (7, 'buyer-953acaf8-4227-4d51-a652-8626f799fa76', (18,)),
        (8, 'seller-e3614ef9-6d24-442a-9332-b15342ffa1e4', (48,)),
        (8, 'buyer-953acaf8-4227-4d51-a652-8626f799fa76', (21,)),
        (9, 'seller-e3614ef9-6d24-442a-9332-b15342ffa1e4', (47,)),
        (9, 'buyer-953acaf8-4227-4d51-a652-8626f799fa76', (23,)),
        (10, 'seller-e3614ef9-6d24-442a-9332-b15342ffa1e4', (46,)),
        (10, 'buyer-953acaf8-4227-4d51-a652-8626f799fa76', (25,)),
        (11, 'seller-e3614ef9-6d24-442a-9332-b15342ffa1e4', (44,)),
        (11, 'buyer-953acaf8-4227-4d51-a652-8626f799fa76', (28,)),
        (12, 'seller-e3614ef9-6d24-442a-9332-b15342ffa1e4', (42,)),
        (12, 'buyer-953acaf8-4227-4d51-a652-8626f799fa76', (30,)),
        (13, 'seller-e3614ef9-6d24-442a-9332-b15342ffa1e4', (40,)),
        (13, 'buyer-953acaf8-4227-4d51-a652-8626f799fa76', (32,)),
        (14, 'seller-e3614ef9-6d24-442a-9332-b15342ffa1e4', (37,)),
        (14, 'buyer-953acaf8-4227-4d51-a652-8626f799fa76', (35,))
    ]
    
We can also plot the negotiation. .. code:: ipython3 mechanism.plot(mark_max_welfare_points=False) plt.show() .. image:: getting_started_files/getting_started_9_0.png The most commonly used method for visualizing a negotiation is to plot the utility of one negotiator on the x-axis and the utility of the other in the y-axis, offers of different negotiators are then displayed in different colors. The agreement is marked by a black star and important points like the `Nash Bargaining Solution `__, `Kalai/Egaliterian Bargaining Solution `__, `Kalai-Smorodonisky Bargaining Solution `__ and points with maximum welfare. This kind of figure is shown in the left-hand side of the previous graph and can be produced by calling ``plot()`` on the mechanism. Because our single-issue negotiation is a zero-sum game, all points have the same welfare of ``1.0`` and lie on a straight line. Another type of graph represents time (i.e. relative-time ranging from 0 to 1, real time, or step number) on the x-axis and represents the utility of one negotiator’s offer for itself with a bold color on the y-axis. The utility of the offers from this negotiators for all other negotiators are also shown using a lighter line with no marks. This kind of representation is useful in understanding clearly the change of each negotiator’s behavior over time (in terms of its own and its partners’ utilities). In the previous graph, we can clearly see the difference between the seller’s (upper right) and buyer’s (lower right) offering strategies. The ``plot`` function is very customizable and you can learn about all its parameters `here `__