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=473d13ecb5a99bf6ec713fc9aca3500591ed3bbd;hb=20f94c6bff1541da8d0639966787dc8aaafea025;hpb=2c79f2f3d73d7dc7a8c799ad9386484a5a684ca4 diff --git a/mtp_graph.cc b/mtp_graph.cc index 473d13e..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; @@ -153,15 +153,13 @@ void MTPGraph::print(ostream *os) { void MTPGraph::print_dot(ostream *os) { (*os) << "digraph {" << endl; + (*os) << " rankdir=\"LR\";" << endl; (*os) << " node [shape=circle,width=0.75,fixedsize=true];" << endl; (*os) << " edge [color=gray,arrowhead=open]" << endl; (*os) << " " << _source->id << " [peripheries=2];" << endl; (*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) { @@ -187,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 @@ -204,64 +212,70 @@ void MTPGraph::force_positivized_lengths() { } int MTPGraph::is_dag() { - Vertex *v, *tv; + Vertex *v; Edge *e; // 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]; } - int front_size = _nb_vertices, nb_with_incoming; int iteration = 0; - int new_front_size, pred_front_size; + int front_size = _nb_vertices, pred_front_size; do { - iteration++; - nb_with_incoming = 0; - - // 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) { - tv = e->terminal_vertex; - tv->iteration = iteration; + e->terminal_vertex->last_change = iteration; } } - new_front_size = 0; - // We remove all the vertices without incoming edge - for(int f = 0; f < front_size; f++) { + pred_front_size = front_size; + front_size = 0; + + // We keep all the vertices with incoming nodes + for(int f = 0; f < pred_front_size; f++) { v = _front[f]; - if(v->iteration == iteration) { - _front[new_front_size++] = v; + if(v->last_change == iteration) { + _front[front_size++] = v; } } - pred_front_size = front_size; - front_size = new_front_size; + 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() { Vertex **tmp_front; - int tmp_front_size; Vertex *v, *tv; Edge *e; scalar_t d; +#ifdef DEBUG + if(is_dag()) { + cout << "find_shortest_path: DAG -> ok" << endl; + } else { + for(int e = 0; e < _nb_edges; e++) { + if(_edges[e].positivized_length < 0) abort(); + } + cout << "find_shortest_path: All positivized_length are positive -> ok" << endl; + } +#endif + 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; @@ -272,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]; @@ -282,21 +295,19 @@ 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; } } } } - tmp_front = _new_front; - _new_front = _front; - _front = tmp_front; + tmp_front = _new_front; _new_front = _front; _front = tmp_front; + + front_size = new_front_size; - tmp_front_size = new_front_size; - new_front_size = front_size; - front_size = tmp_front_size; + iteration++; } while(front_size > 0); } @@ -311,12 +322,9 @@ void MTPGraph::find_best_paths(scalar_t *lengths) { _edges[e].positivized_length = _edges[e].length; } - // Let's be a bit paranoid - ASSERT(is_dag()); - - // We use call find_shortest_path here to set properly the distance, - // so that we can make all the edge lengths positive at the first - // iteration. + // We call find_shortest_path here to set properly the distances to + // the source, so that we can make all the edge lengths positive at + // the first iteration. find_shortest_path(); do { @@ -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; }