AB-CE / abce

Agent-based computational Economics, the Python library that makes AB modelling easier
http://abce.readthedocs.io
181 stars 62 forks source link

Jupyter Tutorial: dealer not selling on round 0 #214

Closed pmartiner closed 2 years ago

pmartiner commented 2 years ago

Hi! I recently discovered abcEconomics and started to learn to use it by reading and running the jupyter tutorial on the website. However, I'm kind of stuck on the "Trade" section. The dealer, if I'm understanding correctly, should be selling after the consumer's offer on round 0, since they have drugs available, yet it seems, according to print_possessions(), that this is not happening. Why is that?

Here's what I'm getting (both by running my own notebook and the one on the repo):

from random import randrange

class NewKid(abce.Agent):
    def init(self, num_dealers):
        self.num_dealers = num_dealers
        self.create('money', 100)  # don't we all wish you'd this function in real live?

    def buy_drugs(self):
        drug_dealer_id = randrange(self.num_dealers)
        self.buy(('drug_dealer', drug_dealer_id), good='drugs', quantity=1, price=10)

    def print_possessions(self):
        print('    ' + self.group + str(dict(self.possessions())))

class DrugDealer(abce.Agent):
    def init(self):
        self.create('drugs', 1)

    def sell_to_customers(self):
        for offer in self.get_offers('drugs'):
            if offer.price >= 10 and self['drugs'] > 1:
                self.accept(offer)

    def print_possessions(self):
        print('    ' + self.group + str(dict(self.possessions())))

num_dealers = 1
num_customers = 1

simulation = abce.Simulation(name='school_yard', processes=1)

drug_dealers = simulation.build_agents(DrugDealer, 'drug_dealer', number=num_dealers)
customers = simulation.build_agents(NewKid, 'customer', number=num_customers, num_dealers=num_dealers)

kids = drug_dealers + customers

for r in range(2):
    print('Round', r)
    simulation.advance_round(r)
    print('Customer offers 10 dollar:')
    customers.buy_drugs()
    kids.print_possessions()
    print('Drug Dealer accepts or rejects the offer:')
    drug_dealers.sell_to_customers()
    kids.print_possessions()
    print()

Result:

Round 0
Customer offers 10 dollar:
    drug_dealer{'drugs': 1.0}
    customer{'money': 90.0}
Drug Dealer accepts or rejects the offer:
    drug_dealer{'drugs': 1.0}
    customer{'money': 100.0}

Round 1
Customer offers 10 dollar:
    drug_dealer{'drugs': 1.0}
    customer{'money': 90.0}
Drug Dealer accepts or rejects the offer:
    drug_dealer{'drugs': 1.0}
    customer{'money': 100.0}

Expected behavior:

Round 0
Customer offers 10 dollar:
    customer{'money': 90.0}
    drug_dealer{'drugs': 1.0}
Drug Dealer accepts or rejects the offer:
    customer{'money': 90.0, 'drugs': 1.0}
    drug_dealer{'drugs': 0, 'money': 10.0}

Round 1
Customer offers 10 dollar:
    customer{'money': 80.0, 'drugs': 1.0}
    drug_dealer{'drugs': 0, 'money': 10.0}
Drug Dealer accepts or rejects the offer:
    customer{'money': 90.0, 'drugs': 1.0}
    drug_dealer{'drugs': 0, 'money': 10.0}
rht commented 2 years ago

I got the expected result by changing this line:

            if offer.price >= 10 and self['drugs'] > 1:

where self['drugs'] > 1 is replaced with self['drugs'] >= 1

rht commented 2 years ago

I looked at the jupyter html, and found this to be the expected output:

Round0
Customer offers 10 dollar:
    drug_dealer{'drugs': 1.0}
    customer{'money': 90.0}
Drug Dealer accepts or rejects the offer:
    drug_dealer{'drugs': 1.0}
    customer{'money': 100.0}

Round1
Customer offers 10 dollar:
    drug_dealer{'drugs': 1.0}
    customer{'money': 90.0}
Drug Dealer accepts or rejects the offer:
    drug_dealer{'drugs': 1.0}
    customer{'money': 100.0}

which is in line with > 1 instead of >= 1. @DavoudTaghawiNejad which behavior do you intend to use?

pmartiner commented 2 years ago

That's true! I missed that >= 1. Thank you!

Maybe I misunderstood, but these line were the ones that led me to think the expected behavior was to trade (to have >=1), even if no supply remained:

When looking at round one one can see that after the customer offered 10 dollars, the 10 dollars are not available to him util the deal has either been accepted or rejected. After the drug dealer accepts the offer in the 0 round. The money is transfered to the drug dealer and the drugs to the customer.

In round 1, where the drug dealer runs out of drugs the 10 dollars go back to the customer.

rht commented 2 years ago

I see. Feel free to make a PR to update https://github.com/AB-CE/abce/blob/master/docs/jupyter_tutorial.html !

pmartiner commented 2 years ago

Will do! Thanks for the help!