void pr_advance_to_next_child__mut(Pr_TraverseState* state) {
  uint32_t next_slot = state->next_slot;
  Node** cur_slots = state->current->slots;
  ASSERT(!is_backwards(cur_slots[next_slot]), "At %s we are going backward instead of forward", 
         ((Node*)follow_edge(cur_slots[next_slot]))->name);
  Node* tmp_grand_pa = state->previous;

  state->previous = state->current;
  state->current = follow_edge(cur_slots[next_slot]);
  state->previous->slots[next_slot] = set_flags_on_edge(tmp_grand_pa, SET_TRAVERSE_FLAG|SET_BACK_FLAG|state->tag_token);
  state->next_slot = pr_next_untraversed_slot(state->current, state->tag_token, 0);
}
Bf_EdgeParams bf_backward_invert_edges__mut(Bf_TraverseState *state) {
  Bf_EdgeParams params = {0};
  Node *grand_pa = NULL;

  // Invariant : (grand_pa / NULL) <-- (parent)   (tail)
  while(1) {
    params = bf_get_node_edge_parameters(state->parent);
    ASSERT(state->parent->count <= state->tail->count, "While going backwards children always hold a higher gen than parents");
    ASSERT(is_backwards(state->parent->slots[params.inv_idx]), "There should always be a backward edge");
    grand_pa = follow_edge(state->parent->slots[params.inv_idx]);

    state->parent->count = params.min_gen ? params.min_gen : state->tail->count;
    ASSERT(state->parent->count >= state->next_tail_gen, "While going backwards we never go under the target generation");

    // we have found the closest ancestor of the node we are looking for
    if (state->parent->count == state->next_tail_gen) break;

    state->parent->slots[params.inv_idx] = state->tail;
    state->tail = state->parent;
    state->parent = grand_pa;
    ASSERT(state->parent, "We should not go past the root while going backwards");
  }
  // The edge params of the node where the traversal must change direction
  // Or the default value on a degenerate case : no need to backward to reach the next tail node
  return params;
}
uint32_t pr_next_untraversed_slot(Node *node, size_t tag_token, uint32_t start_slot) {
  uint32_t next_slot = start_slot;
  for(; next_slot < SLOT_COUNT; ++next_slot) {
    Node *child = follow_edge(node->slots[next_slot]);
    if (!child) continue;
    if (get_flags_on_edge(node->slots[next_slot], SET_TRAVERSE_FLAG)) continue;
    // the edge should not point to an already visited node
    if (pr_get_visit_tag_value(child) == tag_token) continue; 
    // Do not follow edges that loop back to itself
    if (child == node) continue; 
    break;
  }

  ASSERT(next_slot == SLOT_COUNT || follow_edge(node->slots[next_slot]), 
         "Untraversed null edge at %s slot %u", node->name, next_slot);
  return next_slot;
}
void bf_pivot_back_forward_edges__mut(Bf_TraverseState *state, Bf_EdgeParams params) {
  // degenerate case : no need to backward to reach the next tail node
  if (!params.min_gen) return;

  Node *grand_pa = follow_edge(state->parent->slots[params.inv_idx]);
  state->parent->slots[params.inv_idx] = state->tail;
  state->tail = state->parent->slots[params.min_idx];
  state->parent->slots[params.min_idx] = to_backwards_edge(grand_pa);
  ASSERT(state->tail->count == state->next_tail_gen, "The pivoted edge should have pointed to the next tail node");
}
Exemplo n.º 5
0
void turn_to_line(robot_state &state, float degrees_approx)
{
	std::cout << "Making " << degrees_approx << "* turn.\n";
	if (fabs(degrees_approx) < 5.f)	// the junction is straight, ascribe to numerical error
	{
		move(state, 1, 0);
		while (state.line_state == LINE_JUNCTION)
			update_sensor_values(state);
		delay(50);	// Just to make sure we're past the junction
	}
	else
	{
		float turn = degrees_approx < 0 ? 1 : -1;
		// Turn in desired direction until we are off the line
		move(state, -0.2, turn);
		while (state.line_state != LINE_NONE_DETECTED)
			update_sensor_values(state);
		std::cout << "Left previous line\n";
		// We've turned off the line -- now just a bit extra:
		//delay(100);
		// Go forward until we hit the new line.
		move(state, 1, 0);
		while (state.line_state == LINE_NONE_DETECTED)
			update_sensor_values(state);

		std::cout << "line acquired, using edge following to align...\n";
		// Now use edge following to acquire line
		while (state.line_state != LINE_STRAIGHT)
		{
			if (turn < 0)
				follow_edge(state, 3, false);
			else
				follow_edge(state, 0, true);
			update_sensor_values(state);
		}
		std::cout << "Realigned to line, resuming normal following\n";
	}
}
uint32_t bf_backward_prune_exhausted_branch__mut(Bf_TraverseState *state) {
  Bf_EdgeParams params = {0};
  // Invariant : the tail node has no forward edges
  while (!params.min_gen) {
    ASSERT(state->parent, "We should not go past the root while pruning backwards");
    params = bf_get_node_edge_parameters(state->parent);
    ASSERT(is_backwards(state->parent->slots[params.inv_idx]), "There should always be a backward edge");

    state->tail = state->parent;
    state->parent = follow_edge(state->parent->slots[params.inv_idx]);
  }
  // we reached a node with ancestors in the visit queue, recalculate generation after prune
  state->tail->count = params.min_gen;
  // we keep the invariant that between parent and tail there is no edge
  state->tail->slots[params.inv_idx] = NULL;
  ASSERT(state->tail->count >= state->next_tail_gen, "When we cannot prune further we should be at a higher generation");
  return state->tail->count;
}
GraphHandle restore_graph_from_buffer(PersistedGraph graph_buf) {
  GraphHandle new_graph = {0};
  new_graph.vertex_count = graph_buf.vertex_count;
  new_graph.root = calloc(new_graph.vertex_count, sizeof(Node));
  
  restore_graph_from_buffer_no_offset_adjust(graph_buf, new_graph);

  // now we need to adjust the edge pointers to the new offset
  size_t adjust = (size_t)new_graph.root - graph_buf.offset.as_int;
  for (uint32_t i=0; i<new_graph.vertex_count; ++i)
    for (uint32_t j=0; j<SLOT_COUNT; ++j) {
      size_t edge = (size_t)(new_graph.root[i].slots[j]);
      if (follow_edge((void*)edge) == 0) continue;
      edge += adjust;
      //LOG_TRACE("Move %p -> %p", new_graph.root[i].slots[j], (void*)edge);
      new_graph.root[i].slots[j] = (void*)edge;
    }
  return new_graph;
}
void dump_graph_dot_format(GraphHandle graph, const char* filepath) {
  FILE* dot_file = fopen(filepath, "w");
  LOG_INFO("Dumping graph to %s", filepath);
  ASSERT(dot_file, "Failed to open file");

  fprintf(dot_file, "digraph {\n");
  fprintf(dot_file, "  node  [ nodesep=1.5 ];\n");
  fprintf(dot_file, "  graph [ overlap=false; bgcolor=\"grey\" ];\n");
  fprintf(dot_file, "  edge  [ weight=0.5 ];\n");

  for(uint32_t i=0; i<graph.vertex_count; ++i) {
    Node* node = (Node*)(graph.root + i);
    LOG_TRACE("Printing %u : %s", i, node->name);

    if (i == 0 || i == graph.vertex_count-1)
      fprintf_node_dot_format(dot_file, node, "cyan");
    else if (is_leaf_node(node))
      fprintf_node_dot_format(dot_file, node, "gold");
    else if (is_leaf_node_ignore_back(node))
      fprintf_node_dot_format(dot_file, node, "orange");
    else
      fprintf_node_dot_format(dot_file, node, NULL);

    for(uint32_t slot=0; slot < SLOT_COUNT; ++slot) {
      Node* child = follow_edge(node->slots[slot]);
      if (child)
        if (is_backwards(node->slots[slot]))
          fprintf_edge_dot_format(dot_file, node, child, "red");
        else if (get_flags_on_edge(node->slots[slot], SET_TRAVERSE_FLAG))
          fprintf_edge_dot_format(dot_file, node, child, "blue");
        else if (get_flags_on_edge(node->slots[slot], SET_VISIT_FLAG))
          fprintf_edge_dot_format(dot_file, node, child, "green4");
        else
          fprintf_edge_dot_format(dot_file, node, child, NULL);
      else if (is_backwards(node->slots[slot]))
        fprintf_edge_dot_format(dot_file, node, NULL, "red");
    }
  }

  fprintf(dot_file, "}\n");
  fclose(dot_file);
}
void pr_backward_invert_edges__mut(Pr_TraverseState *state) {
  // Invariant : state.current MUST be rolled back
  while (state->next_slot == SLOT_COUNT && state->current != state->poison) {
    uint32_t back_slot = 0;
    Node** prev_slots = state->previous->slots;
    Node* tmp_last_cur = state->current;
    pr_rollback_node_to_init_state__mut(state->current, state->tag_token);

    for(; back_slot < SLOT_COUNT 
          && !get_flags_on_edge(prev_slots[back_slot], SET_BACK_FLAG);
        ++back_slot);
    ASSERT(get_flags_on_edge(prev_slots[back_slot], SET_TRAVERSE_FLAG), 
           "All back edge should have been traversed at : %s", state->previous->name);
    ASSERT(back_slot < SLOT_COUNT, "Could not find any back edge on %s", state->previous->name);

    state->current = state->previous;
    state->previous = follow_edge(prev_slots[back_slot]);
    state->current->slots[back_slot] = set_flags_on_edge(tmp_last_cur, SET_TRAVERSE_FLAG|state->tag_token);
    state->next_slot = pr_next_untraversed_slot(state->current, state->tag_token, back_slot+1);
  }
}