def __init__(self, args, capacity): self.capacity = capacity self.discount = args.gamma self.priority_weight = args.priority_weight self.priority_exponent = args.priority_exponent self.absolute_error_upper = args.absolute_error_upper self.t = 0 # Internal episode timestep counter self.tree = SegmentTree( capacity ) # Store experiences in a wrap-around cyclic buffer within a sum tree for querying priorities self.priority_weight_increase = (1 - args.priority_weight) / self.capacity
def test_segment_tree_lo_hi(): st = SegmentTree(4) assert (st.tree[1].lo, st.tree[1].hi) == (0, 3), "root creation test" assert (st.tree[3].lo, st.tree[3].hi) == (2, 3), "2nd creation test" assert (st.tree[5].lo, st.tree[5].hi) == (1, 1), "leaf creation test" assert len(list(filter(lambda x: x, st.tree))) == 7, "no more nodes" st = SegmentTree(7) assert (st.tree[1].lo, st.tree[1].hi) == (0, 6), "root creation test" assert (st.tree[3].lo, st.tree[3].hi) == (3, 6), "r 2nd creation test" assert (st.tree[5].lo, st.tree[5].hi) == (1, 2), "l 3nd creation test" assert (st.tree[10].lo, st.tree[10].hi) == (1, 1), "leaf creation test"
def main(): # Operation: O(logN) arr = [3, 1, 5, 3, 13, 7, 2, 7, 2] tree = SegmentTree(arr) # Time: O(N), Space: O(N) # Sum print ("Sum from 1 to 3", arr[1:4], tree.query(1, 3, 'sum')) print ("Sum from 4 to 7", arr[4:8], tree.query(4, 7, 'sum')) # Min print ("Min from 1 to 3", arr[1:4], tree.query(1, 3, 'min')) print ("Min from 4 to 7", arr[4:8], tree.query(4, 7, 'min')) # Max print ("Max from 1 to 3", arr[1:4], tree.query(1, 3, 'max')) print ("Max from 4 to 7", arr[4:8], tree.query(4, 7, 'max'))
def measure_of_union_of_rectangles(rectangle_list): X = [] Y = [] m = 0 for rectangle in rectangle_list: X.append( (rectangle.x.begin, 'begin', rectangle.y.begin, rectangle.y.end)) X.append((rectangle.x.end, 'end', rectangle.y.begin, rectangle.y.end)) Y.append((rectangle.y.begin, 'begin')) Y.append((rectangle.y.end, 'end')) # Prepare X X = sorted(X, key=lambda tup: tup[0]) X.insert(0, X[0]) # Prepare Segment Tree for Y Y = sorted(Y, key=lambda tup: tup[0]) st = SegmentTree(Y[0][0], Y[len(Y) - 1][0]) for i in xrange(1, len(X)): m = m + st.root.m * (X[i][0] - X[i - 1][0]) if X[i][1] == 'begin': st.root.insert(X[i][2], X[i][3]) else: st.root.delete(X[i][2], X[i][3]) return m
def contour_of_union_of_rectangles(rectangle_list): X = [] Y = [] for rectangle in rectangle_list: X.append( (rectangle.x.begin, 'begin', rectangle.y.begin, rectangle.y.end)) X.append((rectangle.x.end, 'end', rectangle.y.begin, rectangle.y.end)) Y.append((rectangle.y.begin, 'begin')) Y.append((rectangle.y.end, 'end')) # Prepare X X = sorted(X, key=lambda tup: tup[0]) # Prepare Segment Tree for Y Y = sorted(Y, key=lambda tup: tup[0]) st = SegmentTree(Y[0][0], Y[len(Y) - 1][0]) # A contains all vertical edges A = [] horizontal_edges = [] vertical_edges = [] for i in xrange(0, len(X)): if X[i][1] == 'begin': stack = [] st.root.contr(X[i][2], X[i][3], stack) accumulate_vertical_edges_and_endpoints(A, vertical_edges, X[i][0], stack) st.root.insert(X[i][2], X[i][3]) else: st.root.delete(X[i][2], X[i][3]) stack = [] st.root.contr(X[i][2], X[i][3], stack) accumulate_vertical_edges_and_endpoints(A, vertical_edges, X[i][0], stack) # Perform a lexicographic sort on A, first on ordinates, then on abscissa A.sort(key=lambda endpoint: (endpoint.y, endpoint.x)) # Pick out all the horizontal and vertical edges for k in range(len(A) / 2): # Report edges only when there is something there... if abs(A[2 * k].x - A[2 * k + 1].x) > 0: # Two consecutive endpoints at 2k and 2k + 1 give rise to one horizontal edge horizontal_edges.append( HorizontalEdge(A[2 * k].y, A[2 * k].x, A[2 * k + 1].x)) return vertical_edges, horizontal_edges
def test_simple_sums(self): targetArray = [1, 2, 3, 4] cases = [(0, 1), (0, 2), (0, 3), (1, 2), (1, 3)] good = [1, 3, 6, 2, 5] sTree = SegmentTree(targetArray, Operation(lambda x, y: x + y, 0)) for case, good_answer in zip(cases, good): with self.subTest(case=case): self.assertEqual(sTree.calculate(case[0], case[1]), good_answer)
def test_segment_tree_queries(): INTERFACE_SIZE = 10000 NUM_QUERIES = 100 st = SegmentTree(INTERFACE_SIZE) nv = Naive(INTERFACE_SIZE) for _ in range(NUM_QUERIES): left = random.randint(0, INTERFACE_SIZE - 1) right = random.randint(left, INTERFACE_SIZE - 1) if random.random() > 0.5: val = random.randint(1, 100) print(f'add {val}: {left} - {right}') st.add(left, right, val) nv.add(left, right, val) else: seg_ans = st.min_query(left, right) nai_ans = nv.min_query(left, right) assert seg_ans == nai_ans, f"{left} {right} correctness"
def test_segment_tree_prop(): st = SegmentTree(4) st.add(0, 1, 2) assert st.tree[2].delta == 2, "lazy update" assert len(list(filter(lambda x: x and x.delta == 0, st.tree))) == 6 st.add(3, 3, 1) assert st.tree[7].delta == 1, "lazy update leaf" assert len(list(filter(lambda x: x and x.delta == 0, st.tree))) == 5 st.add(1, 2, 3) assert st.tree[2].delta == 0, "lazy update intermedite" assert st.tree[5].delta == 5, "prop works"
class ReplayMemory: def __init__(self, max_memory=1000): self.max_memory = max_memory self.memory = SegmentTree(max_memory) self._count = 0 @property def count(self): return self._count def add_memory(self, state_input, best_action, reward, done, next_state_input, td): data = [state_input, best_action, reward, done, next_state_input] self.memory.add(td, data) if self._count <= self.max_memory: self._count += 1 def get_memory(self, batch_size): segment = self.memory.total / batch_size batch_tree_index = [] tds = [] batch = [] for i in range(batch_size): a = segment * i b = segment * (i + 1) segment = random.uniform(a, b) tree_index, td, data = self.memory.get(segment) batch_tree_index.append(tree_index) tds.append(td) batch.append(data) return batch_tree_index, tds, batch def update_memory(self, tree_indexes, tds): for i in range(len(tree_indexes)): self.memory.update(tree_indexes[i], tds[i])
def test_segment_tree_update(): st = SegmentTree(4) st.add(0, 1, 2) assert st.tree[2].min == 0, "laziness" st.add(1, 2, 3) assert st.tree[2].min == 2, "lazy update intermedite" assert st.tree[5].min == 0, "prop works"
class DyeWall: """ 染色墙 """ def __init__(self, data): self.data = data self._segment_tree = SegmentTree( self.data, merger=lambda x, y: len(set.union(x, y))) self._segment_tree.lazy_push_down = self._lazy_push_down def dye(self, i, j, color): self._dye(self._segment_tree.root, i, j, color) def _dye(self, node, l, r, color): if node.bound_l == l and node.bound_r == r: node.value = {color} node.lazy_tag += 1 return node mid = node.bound_l + (node.bound_r - node.bound_l) // 2 if r <= mid: node.left = self._dye(node.left, l, r, {color}) elif l >= mid + 1: node.right = self._dye(node.right, l, r, {color}) else: node.left = self._dye(node.left, l, mid, {color}) node.right = self._dye(node.right, mid + 1, r, {color}) node.value = self._merger(node.left.value, node.right.value) return node @staticmethod def _lazy_push_down(node): if node.bound_l == node.bound_r: return node.left.value = {node.color} node.left.lazy_tag += node.lazy_tag node.right.value = {node.color} node.right.lazy_tag += node.lazy_tag node.lazy_tag = 0 def query_color_numbers(self, i, j): return len(self._segment_tree.query(i, j))
def test_stress(self): n = 1000 epochs = 100 arr = np.zeros(n) tree = SegmentTree(0, n) tree.update(0, n, 0) for i in range(epochs): l, r = np.random.randint(0, n, 2) l, r = sorted([l, r]) r += 1 val = np.random.random() tree.update(l, r, val) arr[l: r] = val for i in range(n): self.assertEqual(arr[i], tree.query(i))
def perimeter_of_union_of_rectangles(rectangle_list): X = [] Y = [] p = 0 m_zero = 0 for rectangle in rectangle_list: X.append( (rectangle.x.begin, 'begin', rectangle.y.begin, rectangle.y.end)) X.append((rectangle.x.end, 'end', rectangle.y.begin, rectangle.y.end)) Y.append((rectangle.y.begin, 'begin')) Y.append((rectangle.y.end, 'end')) # Prepare X X = sorted(X, key=lambda tup: tup[0]) X.insert(0, X[0]) # Prepare Segment Tree for Y Y = sorted(Y, key=lambda tup: tup[0]) st = SegmentTree(Y[0][0], Y[len(Y) - 1][0]) for i in xrange(1, len(X)): alpha_star = st.root.alpha if X[i][1] == 'begin': st.root.insert(X[i][2], X[i][3]) else: st.root.delete(X[i][2], X[i][3]) m_star = st.root.m p = p + alpha_star * (X[i][0] - X[i - 1][0]) + abs(m_star - m_zero) m_zero = m_star return p
from segment_tree import SegmentTree a = [18, 17, 13, 19, 15, 11, 20] st = SegmentTree(a) assert st.rmq(1, 3) == 2 assert st.rmq(3, 4) == 4 assert st.rmq(0, 0) == 0 assert st.rmq(0, 1) == 1 assert st.rmq(0, 6) == 5 assert st.rmq(4, 6) == 5 st.update(5, 100) assert st.rmq(1, 3) == 2 assert st.rmq(3, 4) == 4 assert st.rmq(0, 0) == 0 assert st.rmq(0, 1) == 1 assert st.rmq(0, 6) == 2 assert st.rmq(4, 6) == 4 assert st.rmq(4, 5) == 4
from segment_tree import SegmentTree arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11] t = SegmentTree(arr) a = t.query(2, 9, "max") print("The maximum value of this range is : ", a) a = t.query(2, 9, "min") print("The minimum value of this range is : ", a) a = t.query(2, 7, "sum") print("The sum of this range is : ", a) t.update(2, 25) print("The updated array is : ", arr)
def __init__(self, max_memory=1000): self.max_memory = max_memory self.memory = SegmentTree(max_memory) self._count = 0
#autor: Manjarrez Hernandez Raul #carrera: Ingenieria en Sistemas Computacionales from segment_tree import SegmentTree """una matriz con algunos elementos aquí estamos ajustando nuestra matriz en el árbol de segmentos donde t es tomado como objeto del árbol de segmentos""" arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11] #t se utilizará para realizar operaciones en ese segmento t = SegmentTree(arr) #aquí estamos encontrando valor de número máximo en un rango a = t.query(0, 10, "max") print("El Valor Maximo del Rango es: ", a) #aquí estamos encontrando el valor de número mínimo en un rango a = t.query(4, 10, "min") print("El Valor Minimo del Rango es: ", a) #aquí estamos encontrando el valor de suma de un rango a = t.query(0, 3, "sum") print("La suma del Rango es: ", a) #aquí estamos actualizando el valor de un índice particular t.update(2, 57) #reemplazará el valor de índice '2' con 25 print("El Arreglo Actualizado es : ", arr)
class PrioritizedReplayMemory: def __init__(self, args, capacity): self.capacity = capacity self.discount = args.gamma self.priority_weight = args.priority_weight self.priority_exponent = args.priority_exponent self.absolute_error_upper = args.absolute_error_upper self.t = 0 # Internal episode timestep counter self.tree = SegmentTree( capacity ) # Store experiences in a wrap-around cyclic buffer within a sum tree for querying priorities self.priority_weight_increase = (1 - args.priority_weight) / self.capacity # Adds state and action at time t, reward and done at time t + 1 def append(self, state, action, reward, next_state, done): self.tree.append( Experience(state, action, reward, next_state, done), self.tree.max) # Store new transition with maximum priority self.t = 0 if done else self.t + 1 # Start new episodes with t = 0 def _get_sample_from_segment(self, segment, i): valid = False while not valid: sample = np.random.uniform( i * segment, (i + 1) * segment) # Uniformly sample an element from within a segment prob, idx, tree_idx = self.tree.find( sample ) # Retrieve sample from tree with un-normalised probability # Resample if transition straddled current index or probability 0 if prob != 0: valid = True # Note that conditions are valid but extra conservative around buffer index 0 experience = self.tree.get(idx) return prob, idx, tree_idx, experience def sample(self, batch_size): self.priority_weight = min( self.priority_weight + self.priority_weight_increase, 1) p_total = self.tree.total( ) # Retrieve sum of all priorities (used to create a normalised probability distribution) segment = p_total / batch_size # Batch size number of segments, based on sum over all probabilities batch = [ self._get_sample_from_segment(segment, i) for i in range(batch_size) ] # Get batch of valid samples probs, idxs, tree_idxs, experiences = zip(*batch) states = torch.from_numpy( np.vstack([exp.state for exp in experiences if exp is not None ])).to(device=device).to(dtype=torch.float32) actions = torch.from_numpy( np.vstack([exp.action for exp in experiences if exp is not None ])).to(device=device).to(dtype=torch.long) rewards = torch.from_numpy( np.vstack([exp.reward for exp in experiences if exp is not None ])).to(device=device).to(dtype=torch.float32) next_states = torch.from_numpy( np.vstack([ exp.next_state for exp in experiences if exp is not None ])).to(device=device).to(dtype=torch.float32) dones = torch.from_numpy( np.vstack([exp.done for exp in experiences if exp is not None ])).to(device=device).to(dtype=torch.float32) probs = np.array( probs, dtype=np.float32) / p_total # Calculate normalised probabilities capacity = self.capacity if self.tree.full else self.tree.index weights = ( capacity * probs )**-self.priority_weight # Compute importance-sampling weights w weights = torch.tensor( weights / weights.max(), dtype=torch.float32, device=device ) # Normalise by max importance-sampling weight from batch return tree_idxs, states, actions, rewards, next_states, dones, weights def update_priorities(self, idxs, priorities): # priorities = errors clipped_errors = np.minimum(priorities, self.absolute_error_upper) clipped_errors = np.power(clipped_errors, self.priority_exponent) for idx, priority in zip(idxs, clipped_errors): self.tree.update(idx, priority) def __len__(self): return len(self.tree)
def __init__(self, data): self.data = data self._segment_tree = SegmentTree( self.data, merger=lambda x, y: len(set.union(x, y))) self._segment_tree.lazy_push_down = self._lazy_push_down