X-Git-Url: https://www.fleuret.org/cgi-bin/gitweb/gitweb.cgi?p=mtp.git;a=blobdiff_plain;f=mtp_graph.cc;h=6ce84c4d4c4622f8788ddf5ffd46bcdbf5fa13f1;hp=d3b921b791e6acfc2728702b0b593d0dc2cacdf0;hb=20f94c6bff1541da8d0639966787dc8aaafea025;hpb=abbaf6b4b4b8d10ee8e9054a3b8d262a2f242920 diff --git a/mtp_graph.cc b/mtp_graph.cc index d3b921b..6ce84c4 100644 --- a/mtp_graph.cc +++ b/mtp_graph.cc @@ -24,9 +24,7 @@ #include "mtp_graph.h" -#include #include -#include using namespace std; @@ -49,9 +47,11 @@ public: scalar_t distance_from_source; Edge *pred_edge_toward_source; - int iteration; // Used in find_shortest_path to know if we already - // added this vertex to the front + int last_change; // Used to mark which edges have already been + // processed in some methods + Vertex(); + inline void add_leaving_edge(Edge *e); inline void del_leaving_edge(Edge *e); }; @@ -60,7 +60,7 @@ public: void Edge::invert() { length = - length; - positivized_length = 0; + positivized_length = - positivized_length; origin_vertex->del_leaving_edge(this); terminal_vertex->add_leaving_edge(this); Vertex *t = terminal_vertex; @@ -160,9 +160,6 @@ void MTPGraph::print_dot(ostream *os) { (*os) << " " << _sink->id << " [peripheries=2];" << endl; for(int k = 0; k < _nb_edges; k++) { Edge *e = _edges + k; - // (*os) << " " << e->origin_vertex->id << " -> " << e->terminal_vertex->id - // << ";" - // << endl; (*os) << " " << e->origin_vertex->id << " -> " << e->terminal_vertex->id << " ["; if(e->occupied) { @@ -188,15 +185,25 @@ void MTPGraph::force_positivized_lengths() { scalar_t residual_error = 0.0; scalar_t max_error = 0.0; #endif - for(int n = 0; n < _nb_vertices; n++) { - for(Edge *e = _vertices[n].leaving_edges; e; e = e->next_leaving_edge) { - if(e->positivized_length < 0) { + for(int k = 0; k < _nb_edges; k++) { + Edge *e = _edges + k; + + if(e->positivized_length < 0) { + #ifdef VERBOSE + if((e->origin_vertex->last_change < 0 && e->terminal_vertex->last_change >= 0) || + (e->origin_vertex->last_change >= 0 && e->terminal_vertex->last_change < 0)) { + cout << "Inconsistent non-connexity (this should never happen)." << endl; + abort(); + } + if(e->origin_vertex->last_change >= 0 && + e->terminal_vertex->last_change >= 0 && + e->positivized_length < 0) { residual_error -= e->positivized_length; max_error = max(max_error, - e->positivized_length); -#endif - e->positivized_length = 0.0; } +#endif + e->positivized_length = 0.0; } } #ifdef VERBOSE @@ -210,7 +217,7 @@ int MTPGraph::is_dag() { // We put everybody in the front for(int k = 0; k < _nb_vertices; k++) { - _vertices[k].iteration = 0; + _vertices[k].last_change = -1; _front[k] = &_vertices[k]; } @@ -218,34 +225,34 @@ int MTPGraph::is_dag() { int front_size = _nb_vertices, pred_front_size; do { - iteration++; - - // We set the iteration field of all vertex with incoming edges to - // the current iteration value + // We set the last_change field of all the vertices with incoming + // edges to the current iteration value for(int f = 0; f < front_size; f++) { v = _front[f]; for(e = v->leaving_edges; e; e = e->next_leaving_edge) { - e->terminal_vertex->iteration = iteration; + e->terminal_vertex->last_change = iteration; } } pred_front_size = front_size; front_size = 0; - // We remove all the vertices without incoming edge + // We keep all the vertices with incoming nodes for(int f = 0; f < pred_front_size; f++) { v = _front[f]; - if(v->iteration == iteration) { + if(v->last_change == iteration) { _front[front_size++] = v; } } + + iteration++; } while(front_size < pred_front_size); return front_size == 0; } // This method does not change the edge occupation. It only set -// properly for every vertex the fields distance_from_source and +// properly, for every vertex, the fields distance_from_source and // pred_edge_toward_source. void MTPGraph::find_shortest_path() { @@ -268,7 +275,7 @@ void MTPGraph::find_shortest_path() { for(int k = 0; k < _nb_vertices; k++) { _vertices[k].distance_from_source = FLT_MAX; _vertices[k].pred_edge_toward_source = 0; - _vertices[k].iteration = 0; + _vertices[k].last_change = -1; } int iteration = 0; @@ -279,7 +286,6 @@ void MTPGraph::find_shortest_path() { do { new_front_size = 0; - iteration++; for(int f = 0; f < front_size; f++) { v = _front[f]; @@ -289,9 +295,9 @@ void MTPGraph::find_shortest_path() { if(d < tv->distance_from_source) { tv->distance_from_source = d; tv->pred_edge_toward_source = e; - if(tv->iteration < iteration) { + if(tv->last_change < iteration) { _new_front[new_front_size++] = tv; - tv->iteration = iteration; + tv->last_change = iteration; } } } @@ -300,6 +306,8 @@ void MTPGraph::find_shortest_path() { tmp_front = _new_front; _new_front = _front; _front = tmp_front; front_size = new_front_size; + + iteration++; } while(front_size > 0); } @@ -328,7 +336,8 @@ void MTPGraph::find_best_paths(scalar_t *lengths) { // Do we reach the sink? if(_sink->pred_edge_toward_source) { - // If yes, compute the length of the best path + // If yes, compute the length of the best path according to the + // original edge lengths v = _sink; while(v->pred_edge_toward_source) { total_length += v->pred_edge_toward_source->length; @@ -357,7 +366,7 @@ void MTPGraph::find_best_paths(scalar_t *lengths) { // Put back the graph in its original state (i.e. invert edges which // have been inverted in the process) for(int k = 0; k < _nb_edges; k++) { - Edge *e = _edges + k; + e = _edges + k; if(e->occupied) { e->invert(); } } } @@ -379,15 +388,19 @@ int MTPGraph::retrieve_one_path(Edge *e, Path *path) { int nb_choices = 0; for(f = e->terminal_vertex->leaving_edges; f; f = f->next_leaving_edge) { if(f->occupied) { nb_choices++; next = f; } - if(nb_choices == 0) { - cerr << "retrieve_one_path: Non-sink end point." << endl; - abort(); - } - if(nb_choices > 1) { - cerr << "retrieve_one_path: Non node-disjoint paths." << endl; - abort(); - } } + +#ifdef DEBUG + if(nb_choices == 0) { + cerr << "retrieve_one_path: Non-sink end point." << endl; + abort(); + } + if(nb_choices > 1) { + cerr << "retrieve_one_path: Non node-disjoint paths." << endl; + abort(); + } +#endif + e = next; }