X-Git-Url: https://fleuret.org/cgi-bin/gitweb/gitweb.cgi?a=blobdiff_plain;f=mtp_graph.cc;h=cc816c95f899a16220fa09ed0ab3f151578d7329;hb=e9fbecf1c13c63a717c1b359c24287dbce23d4ed;hp=1dd6ff22a59b4c25c4e52650256f52ed82568b17;hpb=f72214033cc9a12fb40470a5122f3c4686cdc2d1;p=mtp.git diff --git a/mtp_graph.cc b/mtp_graph.cc index 1dd6ff2..cc816c9 100644 --- a/mtp_graph.cc +++ b/mtp_graph.cc @@ -20,158 +20,213 @@ #include #include +#include using namespace std; class Edge { public: int id, occupied; - scalar_t length, work_length; + scalar_t length, positivized_length; Vertex *origin_vertex, *terminal_vertex; - Edge *next, *pred; + + // These are the links in the origin_vertex leaving edge list + Edge *next_leaving_edge, *pred_leaving_edge; + + inline void revert(); }; class Vertex { public: - int id, iteration; - Edge *root_edge; + int id; + Edge *leaving_edges; scalar_t distance_from_source; - Vertex *pred_vertex; - Edge *pred_edge; + Edge *best_pred_edge_to_source; - Vertex() { root_edge = 0; } + int iteration; // Used in find_shortest_path to know if we already + // added this vertex to the front + Vertex(); + inline void add_edge(Edge *e); + inline void del_edge(Edge *e); +}; - inline void add_edge(Edge *e) { - e->next = root_edge; - e->pred = 0; - if(root_edge) { root_edge->pred = e; } - root_edge = e; - } +////////////////////////////////////////////////////////////////////// - inline void del_edge(Edge *e) { - if(e == root_edge) { root_edge = e->next; } - if(e->pred) { e->pred->next = e->next; } - if(e->next) { e->next->pred = e->pred; } - } -}; +void Edge::revert() { + length = - length; + positivized_length = 0; + origin_vertex->del_edge(this); + terminal_vertex->add_edge(this); + Vertex *t = terminal_vertex; + terminal_vertex = origin_vertex; + origin_vertex = t; +} -void MTPGraph::print() { - for(int k = 0; k < _nb_edges; k++) { - Edge *e = edges + k; - cout << e->origin_vertex->id - << " -> " - << e->terminal_vertex->id - << " " - << e->length; - if(e->occupied) { - cout << " *"; - } - cout << endl; - } +////////////////////////////////////////////////////////////////////// + +Vertex::Vertex() { + leaving_edges = 0; } -void MTPGraph::print_dot() { - cout << "digraph {" << endl; - cout << " node[shape=circle];" << endl; - for(int k = 0; k < _nb_edges; k++) { - Edge *e = edges + k; - if(e->occupied) { - cout << " " << e->origin_vertex->id << " -> " << e->terminal_vertex->id - << " [style=bold,color=black,label=\"" << -e->length << "\"];" << endl; - } else { - cout << " " << e->origin_vertex->id << " -> " << e->terminal_vertex->id - << " [color=gray,label=\"" << e->length << "\"];" << endl; - } - } - cout << "}" << endl; +void Vertex::add_edge(Edge *e) { + e->next_leaving_edge = leaving_edges; + e->pred_leaving_edge = 0; + if(leaving_edges) { leaving_edges->pred_leaving_edge = e; } + leaving_edges = e; +} + +void Vertex::del_edge(Edge *e) { + if(e == leaving_edges) { leaving_edges = e->next_leaving_edge; } + if(e->pred_leaving_edge) { e->pred_leaving_edge->next_leaving_edge = e->next_leaving_edge; } + if(e->next_leaving_edge) { e->next_leaving_edge->pred_leaving_edge = e->pred_leaving_edge; } +} + +////////////////////////////////////////////////////////////////////// + +Path::Path(int l) { + length = l; + nodes = new int[length]; } +Path::~Path() { + delete[] nodes; +} + +////////////////////////////////////////////////////////////////////// + MTPGraph::MTPGraph(int nb_vertices, int nb_edges, int *from, int *to, - int src, int snk) { + int source, int sink) { _nb_vertices = nb_vertices; _nb_edges = nb_edges; - edges = new Edge[_nb_edges]; - vertices = new Vertex[_nb_vertices]; + _edges = new Edge[_nb_edges]; + _vertices = new Vertex[_nb_vertices]; _front = new Vertex *[_nb_vertices]; _new_front = new Vertex *[_nb_vertices]; - _source = &vertices[src]; - _sink = &vertices[snk]; + _source = &_vertices[source]; + _sink = &_vertices[sink]; for(int v = 0; v < _nb_vertices; v++) { - vertices[v].id = v; + _vertices[v].id = v; } for(int e = 0; e < nb_edges; e++) { - vertices[from[e]].add_edge(&edges[e]); - edges[e].occupied = 0; - edges[e].id = e; - edges[e].origin_vertex = &vertices[from[e]]; - edges[e].terminal_vertex = &vertices[to[e]]; + _vertices[from[e]].add_edge(_edges + e); + _edges[e].occupied = 0; + _edges[e].id = e; + _edges[e].origin_vertex = _vertices + from[e]; + _edges[e].terminal_vertex = _vertices + to[e]; } + paths = 0; + nb_paths = 0; } MTPGraph::~MTPGraph() { - delete[] vertices; - delete[] edges; + delete[] _vertices; + delete[] _edges; delete[] _front; delete[] _new_front; + for(int p = 0; p < nb_paths; p++) delete paths[p]; + delete[] paths; +} + +////////////////////////////////////////////////////////////////////// + +void MTPGraph::print(ostream *os) { + for(int k = 0; k < _nb_edges; k++) { + Edge *e = _edges + k; + (*os) << e->origin_vertex->id + << " -> " + << e->terminal_vertex->id + << " " + << e->length; + if(e->occupied) { + (*os) << " *"; + } + (*os) << endl; + } +} + +void MTPGraph::print_dot(ostream *os) { + (*os) << "digraph {" << endl; + (*os) << " node[shape=circle];" << endl; + for(int k = 0; k < _nb_edges; k++) { + Edge *e = _edges + k; + // (*os) << " " << e->origin_vertex->id << " -> " << e->terminal_vertex->id + // << ";" + // << endl; + if(e->occupied) { + (*os) << " " << e->origin_vertex->id << " -> " << e->terminal_vertex->id + << " [style=bold,color=black,label=\"" << e->length << "\"];" << endl; + } else { + (*os) << " " << e->origin_vertex->id << " -> " << e->terminal_vertex->id + << " [color=gray,label=\"" << e->length << "\"];" << endl; + } + } + (*os) << "}" << endl; } -void MTPGraph::initialize_work_lengths() { +////////////////////////////////////////////////////////////////////// + +void MTPGraph::initialize_positivized_lengths_with_min() { scalar_t length_min = 0; for(int n = 0; n < _nb_vertices; n++) { - for(Edge *e = vertices[n].root_edge; e; e = e->next) { + for(Edge *e = _vertices[n].leaving_edges; e; e = e->next_leaving_edge) { length_min = min(e->length, length_min); } } for(int n = 0; n < _nb_vertices; n++) { - for(Edge *e = vertices[n].root_edge; e; e = e->next) { - e->work_length = e->length - length_min; + for(Edge *e = _vertices[n].leaving_edges; e; e = e->next_leaving_edge) { + e->positivized_length = e->length - length_min; } } } -void MTPGraph::update_work_lengths() { +void MTPGraph::update_positivized_lengths() { for(int k = 0; k < _nb_edges; k++) { - Edge *e = edges + k; - e->work_length += e->terminal_vertex->distance_from_source - e->terminal_vertex->distance_from_source; + Edge *e = _edges + k; + e->positivized_length += + e->origin_vertex->distance_from_source - e->terminal_vertex->distance_from_source; } } -void MTPGraph::force_positive_work_lengths() { +void MTPGraph::force_positivized_lengths() { #ifdef VERBOSE 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].root_edge; e; e = e->next) { - if(e->work_length < 0) { + for(Edge *e = _vertices[n].leaving_edges; e; e = e->next_leaving_edge) { + if(e->positivized_length < 0) { #ifdef VERBOSE - residual_error -= e->work_length; + residual_error -= e->positivized_length; + max_error = max(max_error, fabs(e->positivized_length)); #endif - e->work_length = 0.0; + e->positivized_length = 0.0; } } } #ifdef VERBOSE - cerr << "residual_error " << residual_error << endl; + cerr << "residual_error " << residual_error << " max_error " << residual_error << endl; #endif } +// This method does not change the edge occupation. It update +// distance_from_source and best_pred_edge_to_source. void MTPGraph::find_shortest_path(Vertex **_front, Vertex **_new_front) { Vertex **tmp_front; int tmp_front_size; Vertex *v, *tv; + Edge *e; scalar_t d; for(int v = 0; v < _nb_vertices; v++) { - vertices[v].distance_from_source = FLT_MAX; - vertices[v].pred_vertex = 0; - vertices[v].pred_edge = 0; - vertices[v].iteration = 0; + _vertices[v].distance_from_source = FLT_MAX; + _vertices[v].best_pred_edge_to_source = 0; + _vertices[v].iteration = 0; } int iteration = 0; @@ -183,15 +238,40 @@ void MTPGraph::find_shortest_path(Vertex **_front, Vertex **_new_front) { do { _new_front_size = 0; iteration++; + + // for(int k = 0; k < _nb_edges; k++) { + // Edge *e = _edges + k; + // d = e->origin_vertex->distance_from_source + e->positivized_length; + // if(d < e->terminal_vertex->distance_from_source) { + // e->terminal_vertex->distance_from_source = d; + // _new_front_size++; + // } + // } + + // for(int n = 0; n < _nb_vertices; n++) { + // v = &_vertices[n]; + // for(e = v->leaving_edges; e; e = e->next_leaving_edge) { + // d = v->distance_from_source + e->positivized_length; + // tv = e->terminal_vertex; + // if(d < tv->distance_from_source) { + // tv->distance_from_source = d; + // tv->best_pred_edge_to_source = e; + // if(tv->iteration < iteration) { + // _new_front[_new_front_size++] = tv; + // tv->iteration = iteration; + // } + // } + // } + // } + for(int f = 0; f < _front_size; f++) { v = _front[f]; - for(Edge *e = v->root_edge; e; e = e->next) { - d = v->distance_from_source + e->work_length; + for(e = v->leaving_edges; e; e = e->next_leaving_edge) { + d = v->distance_from_source + e->positivized_length; tv = e->terminal_vertex; if(d < tv->distance_from_source) { tv->distance_from_source = d; - tv->pred_vertex = v; - tv->pred_edge = e; + tv->best_pred_edge_to_source = e; if(tv->iteration < iteration) { _new_front[_new_front_size++] = tv; tv->iteration = iteration; @@ -208,53 +288,72 @@ void MTPGraph::find_shortest_path(Vertex **_front, Vertex **_new_front) { _new_front_size = _front_size; _front_size = tmp_front_size; } while(_front_size > 0); + +#ifdef DEBUG + scalar_t min_delta = 0, delta; + for(int k = 0; k < _nb_edges; k++) { + Edge *e = _edges + k; + // d = e->origin_vertex->distance_from_source + e->positivized_length; + // if(d > e->terminal_vertex->distance_from_source) { abort(); } + delta = e->positivized_length + + (e->origin_vertex->distance_from_source - e->terminal_vertex->distance_from_source); + min_delta = min(delta, min_delta); + } + cout << "min_delta = " << delta << endl; +#endif } -void MTPGraph::find_best_paths(scalar_t *lengths, int *result_edge_occupation) { +void MTPGraph::find_best_paths(scalar_t *lengths) { scalar_t total_length; + Vertex *v; + Edge *e; for(int e = 0; e < _nb_edges; e++) { - edges[e].length = lengths[e]; - edges[e].work_length = edges[e].length; + _edges[e].length = lengths[e]; + _edges[e].occupied = 0; + _edges[e].positivized_length = _edges[e].length; } -#warning - // find_shortest_path(_front, _new_front); - // update_work_lengths(); + cout << "********************************************************" << endl; + // print_dot(&cout); + + // We use one iteration of find_shortest_path simply to propagate + // the distance to make all the edge lengths positive. + find_shortest_path(_front, _new_front); + update_positivized_lengths(); - initialize_work_lengths(); + // #warning + // initialize_positivized_lengths_with_min(); do { - force_positive_work_lengths(); + force_positivized_lengths(); find_shortest_path(_front, _new_front); - update_work_lengths(); + update_positivized_lengths(); total_length = 0.0; // Do we reach the _sink? - if(_sink->pred_edge) { - + if(_sink->best_pred_edge_to_source) { // If yes, compute the length of the best path - for(Vertex *v = _sink; v->pred_vertex; v = v->pred_vertex) { - total_length += v->pred_edge->length; + v = _sink; + while(v->best_pred_edge_to_source) { + total_length += v->best_pred_edge_to_source->length; + v = v->best_pred_edge_to_source->origin_vertex; } - // If that length is negative if(total_length < 0.0) { #ifdef VERBOSE - cout << "Found a path of length " << total_length << endl; + cerr << "Found a path of length " << total_length << endl; #endif // Invert all the edges along the best path - for(Vertex *v = _sink; v->pred_edge; v = v->pred_vertex) { - Edge *e = v->pred_edge; + v = _sink; + while(v->best_pred_edge_to_source) { + e = v->best_pred_edge_to_source; + v = e->origin_vertex; + e->revert(); + // This is the only place where we change the occupations of + // edges e->occupied = 1 - e->occupied; - e->length = - e->length; - e->work_length = - e->work_length; - e->origin_vertex->del_edge(e); - e->terminal_vertex->add_edge(e); - Vertex *t = e->terminal_vertex; - e->terminal_vertex = e->origin_vertex; - e->origin_vertex = t; } } } @@ -262,44 +361,62 @@ void MTPGraph::find_best_paths(scalar_t *lengths, int *result_edge_occupation) { } while(total_length < 0.0); for(int k = 0; k < _nb_edges; k++) { - Edge *e = edges + k; - if(e->occupied) { - e->length = - e->length; - e->work_length = 0; - e->origin_vertex->del_edge(e); - e->terminal_vertex->add_edge(e); - Vertex *t = e->terminal_vertex; - e->terminal_vertex = e->origin_vertex; - e->origin_vertex = t; + Edge *e = _edges + k; + if(e->occupied) { e->revert(); } + } +} + +int MTPGraph::retrieve_one_path(Edge *e, int *nodes) { + Edge *f, *next = 0; + int l = 0; + + if(nodes) { nodes[l++] = e->origin_vertex->id; } + else l++; + + while(e->terminal_vertex != _sink) { + if(nodes) { nodes[l++] = e->terminal_vertex->id; } + else l++; + 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 << "Non-sink path end point?!" << endl; + abort(); + } + if(nb_choices > 1) { + cerr << "Non node-disjoint path, can not retrieve." << endl; + abort(); + } } + e = next; } - // for(Edge *e = _sink->root_edge; e; e = e->next) { - // if(e->occupied) { - // Edge *f = e; - // cout << "PATH " << _sink->id; - // while(f) { - // cout << " " << f->terminal_vertex->id; - // for(f = f->terminal_vertex->root_edge; f && !f->occupied; f = f->next); - // } - // cout << endl; - // } - // } + if(nodes) { nodes[l++] = e->terminal_vertex->id; } + else l++; - // int nb_occupied = 0; - // for(int e = 0; e < _nb_edges; e++) { - // for(int n = 0; n < _nb_vertices; n++) { - // Vertex *v = &vertices[n]; - // for(Edge *e = v->root_edge; e; e = e->next) { - // if(e->occupied) nb_occupied++; - // } - // } - // } + return l; +} - for(int n = 0; n < _nb_vertices; n++) { - Vertex *v = &vertices[n]; - for(Edge *e = v->root_edge; e; e = e->next) { - result_edge_occupation[e->id] = e->occupied; +void MTPGraph::retrieve_disjoint_paths() { + Edge *e; + + for(int p = 0; p < nb_paths; p++) delete paths[p]; + delete[] paths; + + nb_paths = 0; + for(e = _source->leaving_edges; e; e = e->next_leaving_edge) { + if(e->occupied) { nb_paths++; } + } + + paths = new Path *[nb_paths]; + + int p = 0; + for(e = _source->leaving_edges; e; e = e->next_leaving_edge) { + if(e->occupied) { + int l = retrieve_one_path(e, 0); + paths[p] = new Path(l); + retrieve_one_path(e, paths[p]->nodes); + p++; } } }