def test_euler_tour_levels(self):

    def check_level(node, level):
      indices = [i for i, x in enumerate(tour) if x == node]
      for i in indices:
        self.assertEquals(level, levels[i])

    N = 100
    random.seed(1)
    values = [random.randint(0, 100) for i in range(N)]
    (left, right, root) = rangemaxq.build_cartesian(values)
    (tour, levels, represent) = rangemaxq.euler_tour(left, right, root)

    stack = [root]
    check_level(root, max(levels))

    while len(stack) > 0:
      node = stack.pop()
      level = levels[represent[node]]

      if left[node] >= 0:
        check_level(left[node], level - 1)
        stack.append(left[node])

      if right[node] >= 0:
        check_level(right[node], level - 1)
        stack.append(right[node])
  def test_euler_represent(self):
    N = 100
    random.seed(1)
    values = [random.randint(0, 100) for i in range(N)]
    (left, right, root) = rangemaxq.build_cartesian(values)
    (tour, levels, represent) = rangemaxq.euler_tour(left, right, root)

    self.assertEquals(len(values), len(represent))

    for i in range(len(values)):
      idx = tour.index(i)
      self.assertEquals(idx, represent[i])
  def test_euler_tour_parent_child(self):
    N = 100
    random.seed(1)
    values = [random.randint(0, 100) for i in range(N)]
    (left, right, root) = rangemaxq.build_cartesian(values)
    (tour, levels, represent) = rangemaxq.euler_tour(left, right, root)

    for i in range(len(tour) - 1):
      idx = tour[i]
      idxn = tour[i + 1]

      # Because of the constraint for RMQ3, the tour should not contain
      # the same element on two consecutive positions.
      self.assertNotEqual(idx, idxn)

      self.assertTrue(
        left[idx] == idxn or right[idx] == idxn or
        left[idxn] == idx or right[idxn] == idx,
        'Nodes %d and %d are not in a parent-child relationship.' % (idx, idxn))