Ejemplo n.º 1
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]))
Ejemplo n.º 2
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)
Ejemplo n.º 3
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)
Ejemplo n.º 4
0
 def __sub__(self, other):
     if isinstance(other, ExpiringGood):
         other = float(other)
     sum_time_structure = sum(self.time_structure)
     if sum_time_structure < - epsilon:
         raise NotEnoughGoods("AnAgent", "ExpiringGood", -sum_time_structure)
     for i in range(len(self.time_structure)):
         if other >= self.time_structure[i]:
             other -= self.time_structure[i]
             self.time_structure[i] = 0
         else:
             self.time_structure[i] -= other
             break
     return self
Ejemplo n.º 5
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, 'abcEconomics_receive_good', [good, quantity])
        return {good: quantity}
Ejemplo n.º 6
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.haves[good] = 0
        else:
            assert quantity >= 0.0
            available = self.haves[good]
            if available < quantity - epsilon:
                raise NotEnoughGoods(self.name, good, quantity - available)
            self.haves[good] -= quantity
Ejemplo n.º 7
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._inventory[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._inventory.haves[offer.good] += quantity
            self._inventory.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._inventory[offer.good]
            if quantity > available + epsilon + epsilon * max(
                    quantity, available):
                raise NotEnoughGoods(self.name, offer.good,
                                     quantity - available)
            if quantity > available:
                quantity = available
            self._inventory.haves[offer.good] -= quantity
            self._inventory.haves[offer.currency] += quantity * offer.price
        offer.final_quantity = quantity
        self.send(offer.sender, 'abcEconomics_receive_accept',
                  (offer.id, quantity))
        del self._polled_offers[offer.id]
        if offer.sell:
            return {offer.good: -quantity, offer.currency: money_amount}
        else:
            return {offer.good: quantity, offer.currency: -money_amount}
Ejemplo n.º 8
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._inventory[good]
        assert quantity > - epsilon, 'quantity %.30f is smaller than 0 - epsilon (%.30f)' % (quantity, - epsilon)
        if quantity < 0:
            quantity = 0
        if quantity > available + epsilon + epsilon * fmax(quantity, available):
            raise NotEnoughGoods(self.name, good, quantity - available)
        if quantity > available:
            quantity = available

        offer_id = self._offer_counter()
        self._inventory.reserve(good, quantity)
        offer = Offer(self.name,
                      receiver,
                      good,
                      quantity,
                      price,
                      currency,
                      True,
                      'new',
                      -2,
                      offer_id,
                      self.time,
                      -2)
        self.given_offers[offer_id] = offer
        self.send(receiver, 'abcEconomics_propose_sell', offer)
        return offer