Exemplo n.º 1
0
def solve(par):
    n, m, X, Y, Z, A = par
    speed = []
    for i in range(n):
        speed.append(A[i % m])
        A[i % m] = (X * A[i % m] + Y * (i + 1)) % Z

    sumCount = RBTree()
    count = [1] * (n)

    for i in range(n):
        try:
            sumCount[speed[i]] += 0
        except KeyError:
            sumCount[speed[i]] = 0

        s = speed[i]
        while True:
            try:
                s, v = sumCount.prev_item(s)
                count[i] += v
            except KeyError:
                break
        sumCount[speed[i]] += count[i]

    return str(sum(count))
Exemplo n.º 2
0
def solve(par):
    n, m, X, Y, Z, A = par
    speed = []
    for i in range(n):
        speed.append(A[i % m])
        A[i % m] = (X * A[i % m] + Y * (i + 1)) % Z

    sumCount = RBTree()
    count = [1] * (n)
    
    for i in range(n):
        try:
            sumCount[speed[i]] += 0
        except KeyError:
            sumCount[speed[i]] = 0

        s = speed[i]
        while True:
            try:
                s, v = sumCount.prev_item(s)
                count[i] += v
            except KeyError:
                break
        sumCount[speed[i]] += count[i]
        
    return str(sum(count))
Exemplo n.º 3
0
    def __init__(self, expiredIn):
        self.messageQueue = RBTree()
        self.subscribers = RBTree()
        self.expiredIn = expiredIn
        self.idGenerator = IdGenerator()

        task.LoopingCall(self.purgeMessageQueue).start(1, False)
        task.LoopingCall(self.purgeSubscribers).start(1, False)
Exemplo n.º 4
0
 def __init__(self, reservoir_size, alpha):
     self.values = RBTree()
     self.counter = Atomic(0)
     self.next_scale_time = Atomic(0)
     self.alpha = alpha
     self.reservoir_size = reservoir_size
     self.lock = RLock()
     self.clear()
 def __init__(self):
     """
     Instantiate OrderBook object which uses RBTree as main data structure
     """
     self.bids = RBTree()
     self.asks = RBTree()
     # keep track of max and min for bid and ask orders respectively
     self.bid_max = -math.inf
     self.bid_min = math.inf
     self.ask_max = -math.inf
     self.ask_min = math.inf
Exemplo n.º 6
0
 def __init__(self, reservoir_size, alpha):
     self.values = RBTree()
     self.counter = Atomic(0)
     self.next_scale_time = Atomic(0)
     self.alpha = alpha
     self.reservoir_size = reservoir_size
     self.lock = RLock()
     self.clear()
Exemplo n.º 7
0
class ConsistHash(object):
    def __init__(self, size=0xffff):
        self.size = size # set consistent hash circul size
        self.rbt = RBTree()  # red black tree

    def insert_host(self, host):
        host_id = host.get_id(self.size)
        self.rbt.insert(host_id, host)

    def remove_host(self, host):
        host_id = host.get_id(self.size)
        self.rbt.remove(host_id)

    @staticmethod
    def _find_upper(root, elem):
        if root is None:
            return -1

        if elem == root.key:
            return root.key
        elif elem < root.key:
            maybe_max = find_upper(root.left, elem)
            if _not_exists(maybe_max):
                return root.key
            return maybe_max
        else:
            maybe_max = find_upper(root.right, elem)
            if _not_exists(maybe_max):
                return -1
            return maybe_max

    def find_host(self, id):
        id %= self.size
        idx = self._find_upper(self.rbt._root, id)
        if idx == -1:  # id larger than max id
            # assert tree is not empty
            return self.rbt.min_item()[1]
        return self.rbt.get_value(idx)
class OrderBook:
    def __init__(self):
        """
        Instantiate OrderBook object which uses RBTree as main data structure
        """
        self.bids = RBTree()
        self.asks = RBTree()
        # keep track of max and min for bid and ask orders respectively
        self.bid_max = -math.inf
        self.bid_min = math.inf
        self.ask_max = -math.inf
        self.ask_min = math.inf

    def __repr__(self):
        """
        Return a string representation of OrderBook object

        :return: a string describing OrderBook object
        :rtype: str
        """
        return ("Bids Representation: \n"
                "{}\n"
                "Asks Representation: \n"
                "{}\n"
                "Current best bid price is {}\n"
                "Current best ask price is {}\n"
                "Current bid-ask spread is {}".format(str(self.bids),
                                                      str(self.asks),
                                                      str(self.bid_max),
                                                      str(self.ask_min),
                                                      str(self.get_spread())))

    def __eq__(self, other):
        """
        Return True iff self and other have exactly the same bids and asks attributes

        :param other: Any object used for comparison
        :type other: Any
        :return: whether self and other are the same
        :rtype: bool
        """
        if not type(self) == type(other):
            return False
        return self.bids == other.bids and self.asks == other.asks

    def get_spread(self):
        """
        Calculate the spread from best bid and ask

        :return: current spread on OrderBook
        :rtype: float
        """
        return self.ask_min - self.bid_max

    def get_midpoint(self):
        """
        Calculate mid point price from best bid and ask

        :return: current mid point price
        :rtype: float
        """
        return (self.ask_min + self.bid_max) / 2

    def get_liquidity(self):
        """
        Calculate the liquidity for both bid and ask side. Total volume of liquidity quoted on bids and asks within 2x
        the spread from the best bid and the best ask, in units of the base currency.

        :return: current bid and ask liquidity
        :rtype: float, float
        """
        spread = self.get_spread()
        lower_bound_bid = self.bid_max - 2 * spread
        upper_bound_ask = self.ask_min + 2 * spread
        # get orders in the liquidity range using TreeSlice
        liquidity_bids_tree = self.bids[lower_bound_bid:self.bid_max + 1]
        liquidity_asks_tree = self.asks[self.ask_min:upper_bound_ask]
        bid_liquidity = sum(liquidity_bids_tree.values())
        ask_liquidity = sum(liquidity_asks_tree.values())
        return bid_liquidity, ask_liquidity

    def update_order(self, price, amount):
        """
        Update OrderBook by inserting a new price as key and amount as value to RBTree. If a price (key) already exists,
        update its corresponding amount (value) to new amount.

        :param price: price of a limit order
        :type price: float
        :param amount: amount of the limit order
        :type amount: float
        :return: None
        :rtype: NoneType
        """
        # bid order
        if amount > 0:
            # insert() method updates amount if price exists, add new Node with price and amount otherwise
            self.bids.insert(price, amount)
            # update max and min
            if price > self.bid_max:
                self.bid_max = price
            if price < self.bid_min:
                self.bid_min = price
        # ask order
        elif amount < 0:
            self.asks.insert(price, -amount)
            if price > self.ask_max:
                self.ask_max = price
            if price < self.ask_min:
                self.ask_min = price
        # amount is 0, all liquidity at price level consumed
        else:
            # remove the order from bids
            if price in self.bids:
                self.bids.pop(price)
                # update max and min by searching RBTree, time complexity O(log(n))
                if price == self.bid_max:
                    self.bid_max = self.bids.max_key()
                elif price == self.bid_min:
                    self.bid_min = self.bids.min_key()
            # remove the order from asks
            if price in self.asks:
                self.asks.pop(price)
                if price == self.ask_max:
                    self.ask_max = self.asks.max_key()
                elif price == self.ask_min:
                    self.ask_min = self.asks.min_key()
Exemplo n.º 9
0
class ExponentiallyDecayingSample(object):
    RESCALE_THRESHOLD = 60 * 60

    def __init__(self, reservoir_size, alpha):
        self.values = RBTree()
        self.counter = Atomic(0)
        self.next_scale_time = Atomic(0)
        self.alpha = alpha
        self.reservoir_size = reservoir_size
        self.lock = RLock()
        self.clear()

    def clear(self):
        with self.lock:
            self.values.clear()
            self.counter.value = 0
            self.next_scale_time.value = time() + self.RESCALE_THRESHOLD
            self.start_time = time()

    def size(self):
        count = self.counter.value
        if count < self.reservoir_size:
            return count
        return self.reservoir_size

    def __len__(self):
        return self.size()

    def snapshot(self):
        with self.lock:
            return Snapshot(list(self.values.values()))

    def weight(self, timestamp):
        return math.exp(self.alpha * timestamp)

    def rescale(self, now, next_time):
        if self.next_scale_time.compare_and_swap(next_time, now + self.RESCALE_THRESHOLD):
            with self.lock:
                old_start_time = self.start_time
                self.start_time = time()
                for key in list(self.values.keys()):
                    value = self.values.remove(key)
                self.values[key * math.exp(-self.alpha * (self.start_time - old_start_time))] = value

    def update(self, value, timestamp=None):
        if not timestamp:
            timestamp = time()
        with self.lock:
            try:
                priority = self.weight(timestamp - self.start_time) / random.random()
            except OverflowError:
                priority = sys.float_info.max
            new_count = self.counter.update(lambda v: v + 1)

            if math.isnan(priority):
                return

            if new_count <= self.reservoir_size:
                self.values[priority] = value
            else:
                first_priority = self.values.root.key
                if first_priority < priority:
                    if priority in self.values:
                        self.values[priority] = value
                        if not self.values.remove(first_priority):
                            first_priority = self.values.root()
Exemplo n.º 10
0
 def __init__(self, size=0xffff):
     self.size = size # set consistent hash circul size
     self.rbt = RBTree()  # red black tree
Exemplo n.º 11
0
            maybe_max = find_upper(root.right, elem)
            if _not_exists(maybe_max):
                return -1
            return maybe_max

    def find_host(self, id):
        id %= self.size
        idx = self._find_upper(self.rbt._root, id)
        if idx == -1:  # id larger than max id
            # assert tree is not empty
            return self.rbt.min_item()[1]
        return self.rbt.get_value(idx)


if __name__ == "__main__":
    rbt = RBTree()
    for i in range(0, 30, 2):
        rbt.insert(i, "{}".format(i))
    print(find_next(rbt._root, 3))
    print(find_next(rbt._root, 4))
    print(find_next(rbt._root, 5))
    print(find_next(rbt._root, 21))
    print(find_lower(rbt._root, 10)) # should be 10
    print(find_lower(rbt._root, 11)) # should be 10
    print(find_lower(rbt._root, 9)) # should be 8
    print(find_lower(rbt._root, 7)) # should be 6
    print(find_lower(rbt._root, 5)) # should be 4
    print(find_lower(rbt._root, 3)) # should be 2
    print(find_lower(rbt._root, 1)) # should be 0
    print(find_lower(rbt._root, 0)) # should be 0
    print(find_lower(rbt._root, -2)) # should be -1
Exemplo n.º 12
0
class Channel:
    """ Channel provides pub/sub service for a single channel"""
    def __init__(self, expiredIn):
        self.messageQueue = RBTree()
        self.subscribers = RBTree()
        self.expiredIn = expiredIn
        self.idGenerator = IdGenerator()

        task.LoopingCall(self.purgeMessageQueue).start(1, False)
        task.LoopingCall(self.purgeSubscribers).start(1, False)

    def subscriber_size(self):
        count = 0
        for s in self.subscribers.values():
            count += len(s)
        return count

    def publish(self, data, isAsync = True):
        """ Publish the data to the message queue. After messages
            are published, interested subscribers will be notified.
            @params isAsync: specify if the subscribers should be
                notified asynchronously or synchronously.
        """
        time = now()
        dataWithId = (self.idGenerator.generateId(), data)
        self.messageQueue.setdefault(time, []).append(dataWithId)
        self.notify(time, dataWithId, isAsync)

    def subscribe(self, onReceive, onTimeout,
                  timeFrom = 0, timeTo = sys.maxint,
                  minId = 0, timeoutSec = 0):
        """ subscribe messages within a specific time span.
            @params onReceive: if the interested messages are
                retrieved, onReceive will be invoked to notify
                the subscribers.
            @params onTimeout: if subscriber waits for more than
                `timeoutSec` seconds, onTimeout will be invoked.
            @params timeFrom: only retrieve messages after timestamp
                `timeFrom`; time is represented in unix time.
            @params timeTo: only retrieve messages before timestamp
                `timeTo`; time is represented in unix time.
            @params minId: this is HACK...
        """
        messages = self._flatten(self.messageQueue[timeFrom: timeTo], minId)
        messages = list(messages)

        if len(messages) != 0 or timeoutSec == 0:
            onReceive(messages)
            return

        waitUntil = now() + timeoutSec
        subscription = (timeFrom, timeTo, onReceive, onTimeout)

        self.subscribers.setdefault(waitUntil, []).append(subscription)

    def notify(self, time, data, isAsync = True):
        # purge expired subscribers
        self.purgeSubscribers()

        for time, bucket in self.subscribers.items():
            index = partition(bucket,
                              lambda sub: time < sub[0] or time > sub[1])

            data = [data]
            for i in range(index, len(bucket)):
                callback = bucket[i][2]
                if isAsync:
                    reactor.callLater(0, callback, data)
                else:
                    callback(data)

            del bucket[index:]

            if len(bucket) == 0:
                del self.subscribers[time]

    def purgeMessageQueue(self):
        expired = now() - self.expiredIn + 1
        del self.messageQueue[:expired]

    def purgeSubscribers(self):
        expired = now() + 1
        for data in self._flatten(self.subscribers[:expired], 0):
            data[3]()
        del self.subscribers[:expired]

    # --- Utilities ---
    def _flatten(self, buckets, minId):
        for bucket in buckets.values():
            for item in bucket:
                if item[0] >= minId:
                    yield item
Exemplo n.º 13
0
class ExponentiallyDecayingSample(object):
    RESCALE_THRESHOLD = 60 * 60

    def __init__(self, reservoir_size, alpha):
        self.values = RBTree()
        self.counter = Atomic(0)
        self.next_scale_time = Atomic(0)
        self.alpha = alpha
        self.reservoir_size = reservoir_size
        self.lock = RLock()
        self.clear()

    def clear(self):
        with self.lock:
            self.values.clear()
            self.counter.value = 0
            self.next_scale_time.value = time() + self.RESCALE_THRESHOLD
            self.start_time = time()

    def size(self):
        count = self.counter.value
        if count < self.reservoir_size:
            return count
        return self.reservoir_size

    def __len__(self):
        return self.size()

    def snapshot(self):
        with self.lock:
            return Snapshot(list(self.values.values()))

    def weight(self, timestamp):
        return math.exp(self.alpha * timestamp)

    def rescale(self, now, next_time):
        if self.next_scale_time.compare_and_swap(next_time,
                                                 now + self.RESCALE_THRESHOLD):
            with self.lock:
                old_start_time = self.start_time
                self.start_time = time()
                for key in list(self.values.keys()):
                    value = self.values.remove(key)
                self.values[key * math.exp(
                    -self.alpha * (self.start_time - old_start_time))] = value

    def update(self, value, timestamp=None):
        if not timestamp:
            timestamp = time()
        with self.lock:
            try:
                priority = self.weight(timestamp -
                                       self.start_time) / random.random()
            except OverflowError:
                priority = sys.float_info.max
            new_count = self.counter.update(lambda v: v + 1)

            if math.isnan(priority):
                return

            if new_count <= self.reservoir_size:
                self.values[priority] = value
            else:
                first_priority = self.values.root.key
                if first_priority < priority:
                    if priority in self.values:
                        self.values[priority] = value
                        if not self.values.remove(first_priority):
                            first_priority = self.values.root()