Skip to content
This repository has been archived by the owner on Jan 23, 2024. It is now read-only.

Commit

Permalink
Merge pull request #96 from DavoudTaghawiNejad/tradecommit
Browse files Browse the repository at this point in the history
Tradecommit
  • Loading branch information
DavoudTaghawiNejad authored Sep 11, 2017
2 parents b2537e7 + 1c06264 commit bfa6a56
Show file tree
Hide file tree
Showing 31 changed files with 2,582 additions and 2,847 deletions.
16 changes: 14 additions & 2 deletions abce/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,9 @@ class Simulation(object):
**For easy debugging set processes to 1, this way only one agent
runs at a time and only one error message is displayed**
check_unchecked_msgs:
check every round that all messages have been received with get_massages or get_offers.
Example::
simulation = Simulation(name='ABCE',
Expand Down Expand Up @@ -150,14 +153,16 @@ class Simulation(object):
"""

def __init__(self, name='abce', random_seed=None,
trade_logging='off', processes=1):
trade_logging='off', processes=1, check_unchecked_msgs=False):
"""
"""
try:
name = simulation_name # noqa: F821
except NameError:
pass

self.check_unchecked_msgs = check_unchecked_msgs

self.num_of_agents_in_group = {}
self._messages = {}
self._resource_command_group = {}
Expand Down Expand Up @@ -386,6 +391,7 @@ def finalize(self):
print('')
print(str("time only simulation %6.2f" %
(time.time() - self.clock)))

self.database_queue.put('close')

while self._db.is_alive():
Expand Down Expand Up @@ -461,7 +467,10 @@ def build_agents(self, AgentClass, group_name, number=None,
agent_args={'group': group_name,
'trade_logging': self.trade_logging_mode,
'database': self.database_queue,
'random_seed': random.random()},
'random_seed': random.random(),
'agent_parameters': agent_parameters,
'simulation_parameters': parameters,
'check_unchecked_msgs': self.check_unchecked_msgs},
parameters=parameters,
agent_parameters=agent_parameters,
agent_params_from_sim=agent_params_from_sim)
Expand Down Expand Up @@ -503,6 +512,9 @@ def create_agent(self, AgentClass, group_name, parameters=None, agent_parameters
'trade_logging': self.trade_logging_mode,
'database': self.database_queue,
'random_seed': random.random(),
'agent_parameters': agent_parameters,
'simulation_parameters': parameters,
'check_unchecked_msgs': self.check_unchecked_msgs,
'start_round': self.time},
parameters=parameters,
agent_parameters=agent_parameters)
Expand Down
67 changes: 39 additions & 28 deletions abce/agent.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,6 @@
from .database import Database
from .trade import Trade
from .messaging import Messaging
from .expiringgood import ExpiringGood
from .inventory import Inventory


Expand Down Expand Up @@ -68,7 +67,7 @@ def selling(self):
...
def return_quantity_of_good(self):
return possession('good')
return['good']
...
Expand All @@ -87,7 +86,8 @@ def return_quantity_of_good(self):
"""
def __init__(self, id, group, trade_logging,
database, random_seed, num_managers, start_round=None):
database, random_seed, num_managers, agent_parameters, simulation_parameters,
check_unchecked_msgs, start_round=None):
""" Do not overwrite __init__ instead use a method called init instead.
init is called whenever the agent are build.
"""
Expand All @@ -109,11 +109,10 @@ def __init__(self, id, group, trade_logging,
self.num_managers = num_managers
self._out = [[] for _ in range(self.num_managers + 1)]

self._haves = Inventory(self.name)
self._inventory = Inventory(self.name)

# TODO make defaultdict; delete all key errors regarding self._haves as
# TODO make defaultdict; delete all key errors regarding self._inventory as
# defaultdict, does not have missing keys
self._haves['money'] = 0
self._msgs = {}

self.given_offers = OrderedDict()
Expand Down Expand Up @@ -153,6 +152,8 @@ def __init__(self, id, group, trade_logging,

self.log_this_round = True

self._check_every_round_for_lost_messages = check_unchecked_msgs

def init(self, parameters, agent_parameters):
""" This method is called when the agents are build.
It can be overwritten by the user, to initialize the agents.
Expand All @@ -172,26 +173,27 @@ def possession(self, good):
Example::
if self.possession('money') < 1:
if self['money'] < 1:
self.financial_crisis = True
if not(is_positive(self.possession('money')):
if not(is_positive(self['money']):
self.bancrupcy = True
"""
return self._haves.possession(good)
print("depreciated use self[good] or self.not_reserved[good]")
return self._inventory[good]

def possessions(self):
""" returns all possessions """
return self._haves.possessions()
return self._inventory.possessions()

def _offer_counter(self):
""" returns a unique number for an offer (containing the agent's name)
"""
self._offer_count += 1
return hash((self.name, self._offer_count))

def _advance_round(self, time):
def _check_for_lost_messages(self):
for offer in list(self.given_offers.values()):
if offer.made < self.round:
print("in agent %s this offers have not been retrieved:" %
Expand All @@ -203,15 +205,6 @@ def _advance_round(self, time):
'last round and not been retrieved in this'
'round get_offer(.)' % (self.group, self.id))

self._haves._advance_round()
self.contracts._advance_round(self.round)

if self.trade_logging > 0:
self.database_connection.put(
["trade_log", self._trade_log, self.round])

self._trade_log = defaultdict(int)

if sum([len(offers) for offers in list(self._open_offers_buy.values())]):
pprint(dict(self._open_offers_buy))
raise Exception('%s_%i: There are offers an agent send that have '
Expand All @@ -230,8 +223,15 @@ def _advance_round(self, time):
'have not been retrieved in this round '
'get_messages(.)' % (self.group, self.id))

def _advance_round(self, time):
self._inventory._advance_round()
self.contracts._advance_round(self.round)

if self._check_every_round_for_lost_messages:
self._check_for_lost_messages()

for ingredient, units, product in self._resources:
self._haves.create(product, self.possession(ingredient) * units)
self._inventory.create(product, self[ingredient] * units)

self.round = time
self.time = time
Expand All @@ -245,6 +245,12 @@ def _advance_round(self, time):
else:
self.log_this_round = False

if self.trade_logging > 0:
self.database_connection.put(
["trade_log", self._trade_log, self.round])

self._trade_log = defaultdict(int)

def create(self, good, quantity):
""" creates quantity of the good out of nothing
Expand All @@ -255,7 +261,7 @@ def create(self, good, quantity):
'good': is the name of the good
quantity: number
"""
self._haves.create(good, quantity)
self._inventory.create(good, quantity)

def create_timestructured(self, good, quantity):
""" creates quantity of the time structured good out of nothing.
Expand All @@ -281,13 +287,15 @@ def create_timestructured(self, good, quantity):
quantity:
an arry or number
"""
self._haves.create_timestructured(good, quantity)
self._inventory.create_timestructured(good, quantity)

def _declare_expiring(self, good, duration):
""" creates a good that has a limited duration
"""
self._haves[good] = ExpiringGood(duration)
self._haves._expiring_goods.append(good)
self._inventory._declare_expiring(good, duration)

def not_reserved(self, good):
return self._inventory.not_reserved(good)

def destroy(self, good, quantity=None):
""" destroys quantity of the good. If quantity is omitted destroys all
Expand All @@ -303,7 +311,7 @@ def destroy(self, good, quantity=None):
NotEnoughGoods: when goods are insufficient
"""
self._haves.destroy(good, quantity)
self._inventory.destroy(good, quantity)

def _execute(self, command, args, kwargs):
self._out = [[] for _ in range(self.num_managers + 1)]
Expand Down Expand Up @@ -339,7 +347,7 @@ def _register_resource(self, resource, units, product):
self._resources.append((resource, units, product))

def _register_perish(self, good):
self._haves._perishable.append(good)
self._inventory._perishable.append(good)

def _send(self, receiver_group, receiver_id, typ, msg):
""" sends a message to 'receiver_group', who can be an agent, a group or
Expand All @@ -352,4 +360,7 @@ def _send(self, receiver_group, receiver_id, typ, msg):
(receiver_group, receiver_id, (typ, msg)))

def __getitem__(self, good):
return self._haves[good]
return self._inventory.haves[good]

def __del__(self):
self._check_for_lost_messages()
20 changes: 10 additions & 10 deletions abce/agents/firmmultitechnologies.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ def produce_use_everything(self, production_function):
self.produce_use_everything(car_production_function)
"""
return self.produce(production_function, {inp: self.possession(inp) for inp in production_function['input']})
return self.produce(production_function, {inp: self[inp] for inp in production_function['input']})

def produce(self, production_function, input_goods):
""" Produces output goods given the specified amount of inputs.
Expand Down Expand Up @@ -80,24 +80,24 @@ def produce(self, production_function, input_goods):
"""
if production_function.use == 'all':
for good in list(input_goods.keys()):
if self._haves[good] < input_goods[good] - epsilon:
if self._inventory[good] < input_goods[good] - epsilon:
raise NotEnoughGoods(
self.name, good, (input_goods[good] - self._haves[good]))
self.name, good, (input_goods[good] - self._inventory[good]))

for good in input_goods:
self._haves[good] -= input_goods[good]
self._inventory.haves[good] -= input_goods[good]
else:
for good in list(production_function.use.keys()):
if self._haves[good] < input_goods[good] - epsilon:
if self._inventory[good] < input_goods[good] - epsilon:
raise NotEnoughGoods(
self.name, good, (input_goods[good] - self._haves[good]))
self.name, good, (input_goods[good] - self._inventory[good]))

for good, use in production_function.use.items():
self._haves[good] -= input_goods[good] * use
self._inventory.haves[good] -= input_goods[good] * use

output_dict = production_function.production(input_goods)
for good in list(output_dict.keys()):
self._haves[good] += output_dict[good]
self._inventory.haves[good] += output_dict[good]

return output_dict

Expand Down Expand Up @@ -473,9 +473,9 @@ def predict_net_value(self, production_function, input_goods, price_vector):
def sufficient_goods(self, input_goods):
""" checks whether the agent has all the goods in the vector input """
for good in input_goods:
if self._haves[good] < input_goods[good] - epsilon:
if self._inventory[good] < input_goods[good] - epsilon:
raise NotEnoughGoods(
self.name, good, input_goods[good] - self._haves[good])
self.name, good, input_goods[good] - self._inventory[good])


class ProductionFunction(object):
Expand Down
12 changes: 5 additions & 7 deletions abce/agents/household.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,7 @@
"""
The Household class extends the agent by giving him utility functions and the ability to consume goods.
"""
from __future__ import division
from __future__ import absolute_import
from builtins import object
from abce import NotEnoughGoods
import operator
from functools import reduce
from ..trade import get_epsilon
Expand Down Expand Up @@ -51,7 +49,7 @@ def consume_everything(self):
utility = self.consume_everything()
self.log('utility': {'u': utility})
"""
return self.consume({inp: self._haves[inp] for inp in list(self._utility_function.use.keys())})
return self.consume({inp: self._inventory[inp] for inp in list(self._utility_function.use.keys())})

def consume(self, input_goods):
""" consumes input_goods returns utility according to the agent's
Expand Down Expand Up @@ -83,12 +81,12 @@ def consume(self, input_goods):
"""
for good in list(self._utility_function.use.keys()):
if self._haves[good] < input_goods[good] - epsilon:
if self._inventory[good] < input_goods[good] - epsilon:
raise NotEnoughGoods(
self.name, good, (input_goods[good] - self._haves[good]))
self.name, good, (input_goods[good] - self._inventory[good]))

for good, use in self._utility_function.use.items():
self._haves[good] -= input_goods[good] * use
self._inventory.haves[good] -= input_goods[good] * use

return self._utility_function.formula(input_goods)

Expand Down
3 changes: 1 addition & 2 deletions abce/compile.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@
name='trade',
ext_modules=[
Extension('trade', ['trade.pyx']),
Extension('online_variance', ['online_variance.pyx']),
Extension('multicurrencytrade', ['multicurrencytrade.pyx'])],
Extension('online_variance', ['online_variance.pyx'])],
cmdclass={'build_ext': build_ext}
)
2 changes: 1 addition & 1 deletion abce/contracts/flexiblecontracting.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
from random import shuffle
from abce.trade import get_epsilon
from .contracts import Contracts
from .contract import Contract
from .contracting import Contract

epsilon = get_epsilon()

Expand Down
16 changes: 8 additions & 8 deletions abce/database.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,8 +61,8 @@ def log(self, action_name, data_to_log):
self.log('profit', profit)
self.log('employment_and_rent',
{'employment': self.possession('LAB'),
'rent': self.possession('CAP'),
{'employment': self['LAB'],
'rent': self['CAP'],
'composite': self.composite})
self.log(self.produce_use_everything())
Expand Down Expand Up @@ -105,7 +105,7 @@ def log_change(self, action_name, data_to_log):
Examples::
self.log_change('profit', {'money': self.possession('money')]})
self.log_change('profit', {'money': self['money']]})
self.log_change('inputs',
{'money': self.possessions(['money', 'gold', 'CAP', 'LAB')]})
"""
Expand Down Expand Up @@ -148,8 +148,8 @@ def observe_begin(self, action_name, data_to_observe):
... different method ...
self.log('employment_and_rent', {
'employment': self.possession('LAB'),
'rent': self.possession('CAP')})
'employment': self['LAB'],
'rent': self['CAP']})
"""
if self.log_this_round:
self._data_to_observe[action_name] = data_to_observe
Expand All @@ -172,8 +172,8 @@ def observe_end(self, action_name, data_to_observe):
... different method ...
self.log('employment_and_rent', {
'employment': self.possession('LAB'),
'rent':self.possession('CAP')})
'employment': self['LAB'],
'rent':self['CAP']})
"""
if self.log_this_round:
before = self._data_to_observe.pop(action_name)
Expand All @@ -190,7 +190,7 @@ def _common_log(self, variables, possessions, functions, lengths):
for var in variables:
ret[var] = self.__dict__[var]
for pos in possessions:
ret[pos] = self._haves[pos]
ret[pos] = self._inventory[pos]
for name, func in functions.items():
ret[name] = func(self)
for length in lengths:
Expand Down
Loading

0 comments on commit bfa6a56

Please sign in to comment.