Пример #1
0
    def produce(self, production_function, input_goods):
        """ Produces output goods given the specified amount of inputs.

        Transforms the Agent's goods specified in input goods
        according to a given production_function to output goods.
        Automatically changes the agent's belonging. Raises an
        exception, when the agent does not have sufficient resources.

        Args:
            production_function:
                A production_function produced with py:meth:`~abceagent.FirmMultiTechnologies..create_production_function`,
                py:meth:`~abceagent.FirmMultiTechnologies..create_cobb_douglas` or py:meth:`~abceagent.FirmMultiTechnologies..create_leontief`
            input goods {dictionary}:
                dictionary containing the amount of input good used for the production.

        Raises:
            NotEnoughGoods:
                This is raised when the goods are insufficient.

        Example::

            car = {'tire': 4, 'metal': 2000, 'plastic':  40}
            bike = {'tire': 2, 'metal': 400, 'plastic':  20}
            try:
                self.produce(car_production_function, car)
            except NotEnoughGoods:
                A.produce(bike_production_function, bike)
        """
        if production_function.use == 'all':
            for good in list(input_goods.keys()):
                if self._inventory[good] < input_goods[good] - epsilon:
                    raise NotEnoughGoods(
                        self.name, good,
                        (input_goods[good] - self._inventory[good]))

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

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

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

        return output_dict
Пример #2
0
 def reserve(self, good, quantity):
     self.reserved[good] += quantity
     if self.reserved[good] > self.haves[good]:
         self.reserved[good] += quantity
         raise NotEnoughGoods(
             self.name, good,
             quantity - (self.haves[good] - self.reserved[good]))
Пример #3
0
 def reserve(self, good, quantity):
     self._reserved[good] += quantity
     if self._reserved[good] > self.haves[good]:
         if isclose(self._reserved[good], self.haves[good]):
             self._reserved[good] = self.haves[good]
         else:
             self._reserved[good] -= quantity
             raise NotEnoughGoods(
                 self.name, good,
                 quantity - (self.haves[good] - self._reserved[good]))
Пример #4
0
    def pay_contract(self, contract):
        """ delivers on a contract """
        assert contract.pay_group == self.group and contract.pay_id == self.id
        money = contract.quantity * contract.price
        available = self._haves['money']
        if money > available + epsilon + epsilon * max(money, available):
            raise NotEnoughGoods(self.name, 'money', money - available)
        if money > available:
            money = available

        self._haves['money'] -= money
        self._send(contract.deliver_good_group,
                   contract.deliver_good_id, '_dp', contract)
Пример #5
0
    def deliver_contract(self, contract):
        """ delivers on a contract """
        assert contract.deliver_good_group == self.group and contract.deliver_good_id == self.id
        quantity = contract.quantity
        available = self._haves[contract.good]
        if quantity > available + epsilon + epsilon * max(quantity, available):
            raise NotEnoughGoods(self.name, contract.good,
                                 quantity - available)
        if quantity > available:
            quantity = available

        self._haves[contract.good] -= quantity
        self._send(contract.pay_group, contract.pay_id, '_dp', contract)
Пример #6
0
    def give(self, receiver, good, quantity, epsilon=epsilon):
        """ gives a good to another agent

        Args:
            receiver:
                The name of the receiving agent a tuple (group, id).
                e.G. ('firm', 15)
            good:
                the good to be transfered
            quantity:
                amount to be transfered

            epsilon (optional):
                if you have floating point errors, a quantity or prices is
                a fraction of number to high or low. You can increase the
                floating point tolerance. See troubleshooting -- floating point problems

        Raises:

            AssertionError, when good smaller than 0.

        Return:
            Dictionary, with the transfer, which can be used by self.log(...).

        Example::

            self.log('taxes', self.give('money': 0.05 * self['money'])

        """
        assert quantity > -epsilon, 'quantity %.30f is smaller than 0 - epsilon (%.30f)' % (
            quantity, -epsilon)
        if quantity < 0:
            quantity = 0
        available = self._inventory[good]
        if quantity > available + epsilon + epsilon * max(quantity, available):
            raise NotEnoughGoods(self.name, good, quantity - available)
        if quantity > available:
            quantity = available
        self._inventory.haves[good] -= quantity
        self.send(receiver, 'abce_receive_good', [good, quantity])
        return {good: quantity}
Пример #7
0
    def destroy(self, good, quantity=None):
        """ destroys quantity of the good. If quantity is omitted destroys all

        Args::

            'good':
                is the name of the good
            quantity (optional):
                number

        Raises::

            NotEnoughGoods: when goods are insufficient
        """
        if quantity is None:
            self._haves[good] = 0
        else:
            self._haves[good] -= quantity
            if self._haves[good] < 0:
                self._haves[good] = 0
                raise NotEnoughGoods(self.name, good,
                                     quantity - self._haves[good])
Пример #8
0
    def destroy(self, good, quantity=None):
        """ destroys quantity of the good. If quantity is omitted destroys all

        Use with care.

        Args::

            'good':
                is the name of the good
            quantity (optional):
                number

        Raises::

            NotEnoughGoods: when goods are insufficient
        """
        if quantity is None:
            self[good] = 0
        else:
            assert quantity >= 0.0
            available = self[good]
            if available < quantity - epsilon:
                raise NotEnoughGoods(self.name, good, quantity - available)
            self[good] -= quantity
Пример #9
0
    def accept(self, offer, quantity=-999, epsilon=epsilon):
        """ The buy or sell offer is accepted and cleared. If no quantity is
        given the offer is fully accepted; If a quantity is given the offer is
        partial accepted.

        Args:

            offer:
                the offer the other party made
            quantity:
                quantity to accept. If not given all is accepted

            epsilon (optional):
                if you have floating point errors, a quantity or prices is
                a fraction of number to high or low. You can increase the
                floating point tolerance. See troubleshooting -- floating point problems

        Return:
            Returns a dictionary with the good's quantity and the amount paid.
        """
        offer_quantity = offer.quantity
        if quantity == -999:
            quantity = offer_quantity
        assert quantity > - epsilon, 'quantity %.30f is smaller than 0 - epsilon (%.30f)' % (quantity, - epsilon)
        if quantity < 0:
            quantity = 0
        if quantity > offer_quantity + epsilon * max(quantity, offer_quantity):
            raise AssertionError('accepted more than offered %s: %.100f >= %.100f'
                                 % (offer.good, quantity, offer_quantity))
        if quantity > offer_quantity:
            quantity = offer_quantity

        if quantity == 0:
            self.reject(offer)
            return {offer.good: 0, offer.currency: 0}

        money_amount = quantity * offer.price
        if offer.sell:  # ord('s')
            assert money_amount > - epsilon, 'money = quantity * offer.price %.30f is smaller than 0 - epsilon (%.30f)' % (money_amount, - epsilon)
            if money_amount < 0:
                money_amount = 0

            available = self._haves[offer.currency]
            if money_amount > available + epsilon + epsilon * max(money_amount, available):
                raise NotEnoughGoods(self.name, offer.currency, money_amount - available)
            if money_amount > available:
                money_amount = available
            self._haves[offer.good] += quantity
            self._haves[offer.currency] -= quantity * offer.price
        else:
            assert quantity > - epsilon, 'quantity %.30f is smaller than 0 - epsilon (%.30f)' % (quantity, - epsilon)
            if quantity < 0:
                quantity = 0
            available = self._haves[offer.good]
            if quantity > available + epsilon + epsilon * max(quantity, available):
                raise NotEnoughGoods(self.name, offer.good, quantity - available)
            if quantity > available:
                quantity = available
            self._haves[offer.good] -= quantity
            self._haves[offer.currency] += quantity * offer.price
        offer.final_quantity = quantity
        self._send(offer.sender_group, offer.sender_id, '_p', (offer.id, quantity))
        del self._polled_offers[offer.id]
        if offer.sell:  # ord('s')
            return {offer.good: - quantity, offer.currency: money_amount}
        else:
            return {offer.good: quantity, offer.currency: - money_amount}
Пример #10
0
    def buy(self, receiver, good,
            quantity, price, currency='money', epsilon=epsilon):
        """ commits to sell the quantity of good at price

        The goods are not in haves or self.count(). When the offer is
        rejected it is automatically re-credited. When the offer is
        accepted the money amount is credited. (partial acceptance
        accordingly)

        Args:
            receiver:
                The name of the receiving agent a tuple (group, id).
                e.G. ('firm', 15)

            'good':
                name of the good

            quantity:
                maximum units disposed to buy at this price

            price:
                price per unit

            currency:
                is the currency of this transaction (defaults to 'money')

            epsilon (optional):
                if you have floating point errors, a quantity or prices is
                a fraction of number to high or low. You can increase the
                floating point tolerance. See troubleshooting -- floating point problems
        """
        assert price > - epsilon, 'price %.30f is smaller than 0 - epsilon (%.30f)' % (price, - epsilon)
        if price < 0:
            price = 0
        money_amount = quantity * price
        # makes sure the money_amount is between zero and maximum available, but
        # if its only a little bit above or below its set to the bounds
        available = self._haves[currency]
        assert money_amount > - epsilon, '%s (price * quantity) %.30f is smaller than 0 - epsilon (%.30f)' % (currency, money_amount, - epsilon)
        if money_amount < 0:
            money_amount = 0
        if money_amount > available + epsilon + epsilon * max(money_amount, available):
            raise NotEnoughGoods(self.name, currency, money_amount - available)
        if money_amount > available:
            money_amount = available

        offer_id = self._offer_counter()
        self._haves[currency] -= money_amount
        offer = Offer(self.group,
                      self.id,
                      receiver[0],
                      receiver[1],
                      good,
                      quantity,
                      price,
                      currency,
                      False,
                      'new',
                      -1,
                      offer_id,
                      self.round,
                      -1)
        self._send(receiver[0], receiver[1], '!b', offer)
        self.given_offers[offer_id] = offer
        return offer
Пример #11
0
    def sell(self, receiver,
             good, quantity, price, currency='money', epsilon=epsilon):
        """ commits to sell the quantity of good at price

        The good is not available for the agent. When the offer is
        rejected it is automatically re-credited. When the offer is
        accepted the money amount is credited. (partial acceptance
        accordingly)

        Args:
            receiver_group:
                group of the receiving agent

            receiver_id:
                number of the receiving agent

            'good':
                name of the good

            quantity:
                maximum units disposed to buy at this price

            price:
                price per unit

            currency:
                is the currency of this transaction (defaults to 'money')

            epsilon (optional):
                if you have floating point errors, a quantity or prices is
                a fraction of number to high or low. You can increase the
                floating point tolerance. See troubleshooting -- floating point problems

        Returns:
            A reference to the offer. The offer and the offer status can
            be accessed with `self.info(offer_reference)`.

        Example::

            def subround_1(self):
                self.offer = self.sell('household', 1, 'cookies', quantity=5, price=0.1)

            def subround_2(self):
                offer = self.info(self.offer)
                if offer.status == 'accepted':
                    print(offer.final_quantity , 'cookies have be bougth')
                else:
                    offer.status == 'rejected':
                    print('On diet')
        """
        assert price > - epsilon, 'price %.30f is smaller than 0 - epsilon (%.30f)' % (price, - epsilon)
        if price < 0:
            price = 0
        # makes sure the quantity is between zero and maximum available, but
        # if its only a little bit above or below its set to the bounds
        available = self._haves[good]
        assert quantity > - epsilon, 'quantity %.30f is smaller than 0 - epsilon (%.30f)' % (quantity, - epsilon)
        if quantity < 0:
            quantity = 0
        if quantity > available + epsilon + epsilon * max(quantity, available):
            raise NotEnoughGoods(self.name, good, quantity - available)
        if quantity > available:
            quantity = available

        offer_id = self._offer_counter()
        self._haves[good] -= quantity
        offer = Offer(self.group,
                      self.id,
                      receiver[0],
                      receiver[1],
                      good,
                      quantity,
                      price,
                      currency,
                      True,
                      'new',
                      -2,
                      offer_id,
                      self.round,
                      -2)
        self.given_offers[offer_id] = offer
        self._send(receiver[0], receiver[1], '!s', offer)
        return offer
Пример #12
0
 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:
             raise NotEnoughGoods(
                 self.name, good, input_goods[good] - self._haves[good])