Esempio n. 1
0
 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
Esempio n. 2
0
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'))
Esempio n. 4
0
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
Esempio n. 5
0
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
Esempio n. 6
0
    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)
Esempio n. 7
0
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"
Esempio n. 8
0
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"
Esempio n. 9
0
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])
Esempio n. 10
0
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"
Esempio n. 11
0
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))
Esempio n. 12
0
 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))
Esempio n. 13
0
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
Esempio n. 14
0
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
Esempio n. 15
0
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) 
Esempio n. 16
0
 def __init__(self, max_memory=1000):
     self.max_memory = max_memory
     self.memory = SegmentTree(max_memory)
     self._count = 0
Esempio n. 17
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)
Esempio n. 18
0
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)
Esempio n. 19
0
 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