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))
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 __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
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()
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()
def __init__(self, size=0xffff): self.size = size # set consistent hash circul size self.rbt = RBTree() # red black tree
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
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
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()