c40856ff1d213e3bd707cebcdeffcf890b75eede
[mtp.git] / ksp.cc
1
2 ///////////////////////////////////////////////////////////////////////////
3 // START_IP_HEADER                                                       //
4 //                                                                       //
5 // This program is free software: you can redistribute it and/or modify  //
6 // it under the terms of the version 3 of the GNU General Public License //
7 // as published by the Free Software Foundation.                         //
8 //                                                                       //
9 // This program is distributed in the hope that it will be useful, but   //
10 // WITHOUT ANY WARRANTY; without even the implied warranty of            //
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU      //
12 // General Public License for more details.                              //
13 //                                                                       //
14 // You should have received a copy of the GNU General Public License     //
15 // along with this program. If not, see <http://www.gnu.org/licenses/>.  //
16 //                                                                       //
17 // Written by and Copyright (C) Francois Fleuret                         //
18 // Contact <francois.fleuret@idiap.ch> for comments & bug reports        //
19 //                                                                       //
20 // END_IP_HEADER                                                         //
21 ///////////////////////////////////////////////////////////////////////////
22
23 #define VERBOSE
24
25 #include <iostream>
26 #include <fstream>
27 #include <cmath>
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <float.h>
31
32 using namespace std;
33
34 typedef float scalar_t;
35
36 #ifdef DEBUG
37 #define ASSERT(x) if(!(x)) { \
38   std::cerr << "ASSERT FAILED IN " << __FILE__ << ":" << __LINE__ << endl; \
39   abort(); \
40 }
41 #else
42 #define ASSERT(x)
43 #endif
44
45 class Vertex;
46
47 class Edge {
48 public:
49   int occupied;
50   scalar_t length, fixed_length;
51   Vertex *terminal_vertex;
52   Edge *next, *pred;
53 };
54
55 class Vertex {
56 public:
57   // These are the leaving edges
58   Edge *first_edge;
59   scalar_t distance;
60
61   Vertex *pred_vertex;
62   Edge *pred_edge;
63
64   Vertex() { first_edge = 0; }
65
66   inline void add_edge(Edge *e) {
67     if(first_edge) { first_edge->pred = e; }
68     e->next = first_edge;
69     e->pred = 0;
70     first_edge = e;
71   }
72
73   inline void del_edge(Edge *e) {
74     if(e == first_edge) { first_edge = e->next; }
75     if(e->pred) { e->pred->next = e->next; }
76     if(e->next) { e->next->pred = e->pred; }
77   }
78 };
79
80 class Graph {
81 public:
82   int nb_vertices;
83   Edge *edge_heap;
84   Vertex *vertices;
85   Vertex *source, *sink;
86
87   Graph(int nb_vertices, int nb_edges, int *from, int *to, scalar_t *lengths,
88         int source, int sink);
89   ~Graph();
90
91   void initialize_fixed_lengths();
92   void update_fixed_length();
93   void find_shortest_path();
94   void find_best_paths();
95   void print();
96 };
97
98 void Graph::print() {
99   for(int n = 0; n < nb_vertices; n++) {
100     cout << "VERTEX [" << n << "] ";
101     for(Edge *e = vertices[n].first_edge; e; e = e->next) {
102       cout << " " << e->length;
103     }
104     cout << endl;
105   }
106 }
107
108 Graph::Graph(int nb_vrt, int nb_edges,
109              int *from, int *to, scalar_t *lengths,
110              int src, int snk) {
111   nb_vertices = nb_vrt;
112
113   edge_heap = new Edge[nb_edges];
114   vertices = new Vertex[nb_vertices];
115
116   source = &vertices[src];
117   sink = &vertices[snk];
118
119   for(int e = 0; e < nb_edges; e++) {
120     vertices[from[e]].add_edge(&edge_heap[e]);
121     edge_heap[e].occupied = 0;
122     edge_heap[e].length = lengths[e];
123     edge_heap[e].terminal_vertex = &vertices[to[e]];
124   }
125 }
126
127 Graph::~Graph() {
128   delete[] vertices;
129   delete[] edge_heap;
130 }
131
132 void Graph::initialize_fixed_lengths() {
133   scalar_t length_min = 0;
134   for(int n = 0; n < nb_vertices; n++) {
135     for(Edge *e = vertices[n].first_edge; e; e = e->next) {
136       length_min = min(e->length, length_min);
137     }
138   }
139   for(int n = 0; n < nb_vertices; n++) {
140     for(Edge *e = vertices[n].first_edge; e; e = e->next) {
141       e->fixed_length = e->length - length_min;
142     }
143   }
144 }
145
146 void Graph::update_fixed_length() {
147   for(int n = 0; n < nb_vertices; n++) {
148     scalar_t d = vertices[n].distance;
149     for(Edge *e = vertices[n].first_edge; e; e = e->next) {
150       e->fixed_length += d - e->terminal_vertex->distance;
151     }
152   }
153 }
154
155 void Graph::find_shortest_path() {
156   Vertex **front = new Vertex *[nb_vertices];
157   Vertex **new_front = new Vertex *[nb_vertices];
158   Vertex **tmp_front;
159   int tmp_front_size;
160   Vertex *v, *tv;
161   scalar_t d;
162
163 #ifdef DEBUG
164   for(int n = 0; n < nb_vertices; n++) {
165     for(Edge *e = vertices[n].first_edge; e; e = e->next) {
166       if(e->fixed_length < 0) {
167         cerr << "DEBUG error in find_shortest_path: Edge fixed lengths have to be positive."
168              << endl;
169         abort();
170       }
171     }
172   }
173 #endif
174
175   for(int v = 0; v < nb_vertices; v++) {
176     vertices[v].distance = FLT_MAX;
177     vertices[v].pred_vertex = 0;
178     vertices[v].pred_edge = 0;
179   }
180
181   int front_size = 0, new_front_size;
182   front[front_size++] = source;
183   source->distance = 0;
184
185   do {
186     new_front_size = 0;
187     for(int f = 0; f < front_size; f++) {
188       v = front[f];
189       for(Edge *e = v->first_edge; e; e = e->next) {
190         d = v->distance + e->fixed_length;
191         tv = e->terminal_vertex;
192         if(d < tv->distance) {
193           tv->distance = d;
194           tv->pred_vertex = v;
195           tv->pred_edge = e;
196           new_front[new_front_size++] = tv;
197         }
198       }
199     }
200
201     tmp_front = new_front;
202     new_front = front;
203     front = tmp_front;
204
205     tmp_front_size = new_front_size;
206     new_front_size = front_size;
207     front_size = tmp_front_size;
208     cout << "front_size = " << front_size << endl;
209   } while(front_size > 0);
210
211   delete[] front;
212   delete[] new_front;
213 }
214
215 void Graph::find_best_paths() {
216   scalar_t total_length;
217
218   initialize_fixed_lengths();
219
220   do {
221     print();
222
223     total_length = 0.0;
224     find_shortest_path();
225     update_fixed_length();
226
227     // Do we reach the sink?
228     if(sink->pred_edge) {
229
230 #ifdef VERBOSE
231       cout << "VERBOSE there is a path reaching the sink" << endl;
232 #endif
233
234       // If yes, compute the length of the best path
235       for(Vertex *v = sink; v->pred_edge; v = v->pred_vertex) {
236         total_length += v->pred_edge->length;
237       }
238
239 #ifdef VERBOSE
240       cout << "VERBOSE total_length " << total_length << endl;
241 #endif
242
243       // If that length is negative
244       if(total_length < 0.0) {
245         // Invert all the edges along the best path
246         for(Vertex *v = sink; v->pred_edge; v = v->pred_vertex) {
247           Edge *e = v->pred_edge;
248           e->terminal_vertex = v->pred_vertex;
249           e->occupied = 1 - e->occupied;
250           e->length = - e->length;
251           e->fixed_length = - e->fixed_length;
252           v->pred_vertex->del_edge(e);
253           v->add_edge(e);
254           cout << "INVERT!" << endl;
255         }
256       }
257     }
258   } while(total_length < 0.0);
259 }
260
261 //////////////////////////////////////////////////////////////////////
262
263 int main(int argc, char **argv) {
264
265   if(argc < 2) {
266     cerr << argv[0] << " <graph file>" << endl;
267     exit(EXIT_FAILURE);
268   }
269
270   ifstream *file = new ifstream(argv[1]);
271
272   int nb_edges, nb_vertices;
273   int source, sink;
274
275   if(file->good()) {
276
277     (*file) >> nb_vertices >> nb_edges;
278     (*file) >> source >> sink;
279
280     cout << "INPUT nb_edges " << nb_edges << endl;
281     cout << "INPUT nb_vertices " << nb_vertices << endl;
282     cout << "INPUT source " << source << endl;
283     cout << "INPUT sink " << sink << endl;
284
285     scalar_t *el = new scalar_t[nb_edges];
286     int *ea = new int[nb_edges];
287     int *eb = new int[nb_edges];
288
289     for(int e = 0; e < nb_edges; e++) {
290       (*file) >> ea[e] >> eb[e] >> el[e];
291       cout << "INPUT_EDGE " << ea[e] << " " << eb[e] << " " << el[e] << endl;
292     }
293
294     Graph graph(nb_vertices, nb_edges, ea, eb, el, source, sink);
295
296     graph.find_best_paths();
297
298     delete[] el;
299     delete[] ea;
300     delete[] eb;
301
302   } else {
303
304     cerr << "Can not open " << argv[1] << endl;
305
306     delete file;
307     exit(EXIT_FAILURE);
308
309   }
310
311   delete file;
312   exit(EXIT_SUCCESS);
313 }