X-Git-Url: https://www.fleuret.org/cgi-bin/gitweb/gitweb.cgi?p=mtp.git;a=blobdiff_plain;f=mtp_graph.cc;h=2cbb33848a3589007528a6e3b1098357dbf3d3df;hp=a03f60e050eeb8903e9828c14ea30c005e7c57eb;hb=HEAD;hpb=1f3de34727021a99f81b2a393653e6ef50af7f50 diff --git a/mtp_graph.cc b/mtp_graph.cc index a03f60e..2cbb338 100644 --- a/mtp_graph.cc +++ b/mtp_graph.cc @@ -241,7 +241,7 @@ void MTPGraph::force_positivized_lengths() { } } #ifdef VERBOSE - cerr << __FILE__ << ": residual_error " << residual_error << " max_error " << residual_error << endl; + cerr << __FILE__ << ": residual_error " << residual_error << " max_error " << max_error << endl; #endif } @@ -289,7 +289,7 @@ void MTPGraph::find_shortest_path() { _source->distance_from_source = 0; _source->decrease_distance_in_heap(_heap); - while(heap_size > 1) { + while(heap_size > 1) { // Get the closest to the source v = _heap[0]; @@ -379,7 +379,7 @@ void MTPGraph::find_best_paths(scalar_t *lengths) { } } -int MTPGraph::retrieve_one_path(Edge *e, Path *path) { +int MTPGraph::retrieve_one_path(Edge *e, Path *path, int *used_edges) { Edge *f, *next = 0; int l = 0, nb_occupied_next; @@ -396,7 +396,9 @@ int MTPGraph::retrieve_one_path(Edge *e, Path *path) { nb_occupied_next = 0; for(f = e->terminal_vertex->leaving_edge_list_root; f; f = f->next_leaving_edge) { - if(f->occupied) { nb_occupied_next++; next = f; } + if(f->occupied && !used_edges[f - _edges]) { + nb_occupied_next++; next = f; + } } #ifdef DEBUG @@ -404,13 +406,10 @@ int MTPGraph::retrieve_one_path(Edge *e, Path *path) { cerr << __FILE__ << ": retrieve_one_path: Non-sink end point." << endl; abort(); } - - else if(nb_occupied_next > 1) { - cerr << __FILE__ << ": retrieve_one_path: Non node-disjoint paths." << endl; - abort(); - } #endif + if(path) { used_edges[next - _edges] = 1; } + e = next; } @@ -424,23 +423,15 @@ int MTPGraph::retrieve_one_path(Edge *e, Path *path) { ////////////////////////////////////////////////////////////////////// -static int compare_vertices_on_distance(const void *v1, const void *v2) { - scalar_t delta = - (*((Vertex **) v1))->distance_from_source - - (*((Vertex **) v2))->distance_from_source; - if(delta < 0) return -1; - else if(delta > 0) return 1; - else return 0; -} - void MTPGraph::compute_dp_ordering() { Vertex *v; Edge *e; int ntv; - // This method computes for each node the length of the longest link - // from the source, and orders the node in _dp_order according to - // it. It aborts if the graph is not a DAG. + // This method orders the nodes by putting first the ones with no + // predecessors, then going on adding nodes whose predecessors have + // all been already added. Computing the distances from the source + // by visiting nodes in that order is equivalent to DP. int *nb_predecessors = new int[_nb_vertices]; @@ -464,12 +455,15 @@ void MTPGraph::compute_dp_ordering() { } } - scalar_t rank = 1; while(already_processed < front) { + // Here, nodes before already_processed can be ignored, nodes + // before front were set to 0 predecessors during the previous + // iteration. During this new iteration, we have to visit the + // successors of these ones only, since they are the only ones + // which may end up with no predecessors. new_front = front; while(already_processed < front) { v = *(already_processed++); - v->distance_from_source = rank; for(e = v->leaving_edge_list_root; e; e = e->next_leaving_edge) { ntv = int(e->terminal_vertex - _vertices); nb_predecessors[ntv]--; @@ -480,7 +474,6 @@ void MTPGraph::compute_dp_ordering() { } } front = new_front; - rank++; } if(already_processed < _dp_order + _nb_vertices) { @@ -489,9 +482,6 @@ void MTPGraph::compute_dp_ordering() { } delete[] nb_predecessors; - - for(int v = 0; v < _nb_vertices; v++) { _dp_order[v] = &_vertices[v]; } - qsort(_dp_order, _nb_vertices, sizeof(Vertex *), compare_vertices_on_distance); } ////////////////////////////////////////////////////////////////////// @@ -499,6 +489,7 @@ void MTPGraph::compute_dp_ordering() { void MTPGraph::retrieve_disjoint_paths() { Edge *e; int p, l; + int *used_edges; for(int p = 0; p < nb_paths; p++) delete paths[p]; delete[] paths; @@ -509,14 +500,21 @@ void MTPGraph::retrieve_disjoint_paths() { } paths = new Path *[nb_paths]; + used_edges = new int[_nb_edges]; + for(int e = 0; e < _nb_edges; e++) { + used_edges[e] = 0; + } p = 0; for(e = _source->leaving_edge_list_root; e; e = e->next_leaving_edge) { - if(e->occupied) { - l = retrieve_one_path(e, 0); + if(e->occupied && !used_edges[e - _edges]) { + l = retrieve_one_path(e, 0, used_edges); paths[p] = new Path(l); - retrieve_one_path(e, paths[p]); + retrieve_one_path(e, paths[p], used_edges); + used_edges[e - _edges] = 1; p++; } } + + delete[] used_edges; }