pgRouting

root/tags/release-1.0-beta/boost_wrapper.cpp

Revision 39, 5.5 kB (checked in by anton, 1 year ago)

1.0.0b tag added

Line 
1 /*
2  * Shortest path algorithm for PostgreSQL
3  *
4  * Copyright (c) 2005 Sylvain Pasche
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19  *
20  */
21
22 #include <boost/config.hpp>
23 #include <iostream>
24 #include <fstream>
25
26 #include <boost/graph/graph_traits.hpp>
27 #include <boost/graph/adjacency_list.hpp>
28 #include <boost/graph/dijkstra_shortest_paths.hpp>
29
30 #include "dijkstra.h"
31
32 using namespace std;
33 using namespace boost;
34
35 /*
36 //      FIXME: use this to avoid heap allocation ?
37
38 void* operator new(size_t size)
39 {
40 return palloc(size);
41 }
42
43 void operator delete(void *p)
44 {
45     pfree(p);
46 }
47
48 */
49
50 // Maximal number of nodes in the path (to avoid infinite loops)
51 #define MAX_NODES 1000000
52
53 struct Vertex
54 {
55     int id;
56     float8 cost;
57 };
58
59
60 int
61 boost_dijkstra(edge_t *edges, unsigned int count, int start_vertex, int end_vertex,
62                bool directed, bool has_reverse_cost,
63                path_element_t **path, int *path_count, char **err_msg)
64 {
65
66     // FIXME: use a template for the directedS parameters
67     typedef adjacency_list < listS, vecS, directedS, no_property, Vertex> graph_t;
68
69     typedef graph_traits < graph_t >::vertex_descriptor vertex_descriptor;
70     typedef graph_traits < graph_t >::edge_descriptor edge_descriptor;
71     typedef std::pair<int, int> Edge;
72
73     // FIXME: compute this value
74     const unsigned int num_nodes = ((directed && has_reverse_cost ? 2 : 1) * count) + 100;
75
76     graph_t graph(num_nodes);
77
78     property_map<graph_t, edge_weight_t>::type weightmap = get(edge_weight, graph);
79
80     for (std::size_t j = 0; j < count; ++j)
81     {
82         edge_descriptor e; bool inserted;
83         tie(e, inserted) = add_edge(edges[j].source, edges[j].target, graph);
84
85         graph[e].cost = edges[j].cost;
86         graph[e].id = edges[j].id;
87                                
88         if (!directed || (directed && has_reverse_cost))
89         {
90             tie(e, inserted) = add_edge(edges[j].target, edges[j].source, graph);
91             graph[e].id = edges[j].id;
92
93             if (has_reverse_cost)
94             {
95                 graph[e].cost = edges[j].reverse_cost;
96             }
97             else
98             {
99                 graph[e].cost = edges[j].cost;
100             }
101         }
102     }
103
104     std::vector<vertex_descriptor> predecessors(num_vertices(graph));
105
106     vertex_descriptor _source = vertex(start_vertex, graph);
107
108     if (_source < 0 /*|| _source >= num_nodes*/)
109     {
110         *err_msg = "Starting vertex not found";
111         return -1;
112     }
113
114     vertex_descriptor _target = vertex(end_vertex, graph);
115     if (_target < 0 /*|| _target >= num_nodes*/)
116     {
117         *err_msg = "Ending vertex not found";
118         return -1;
119     }
120
121     std::vector<float8> distances(num_vertices(graph));
122     dijkstra_shortest_paths(graph, _source,
123                             predecessor_map(&predecessors[0]).
124                             weight_map(get(&Vertex::cost, graph))
125                             .distance_map(&distances[0]));
126
127     vector<int> path_vect;
128     int max = MAX_NODES;
129     path_vect.push_back(_target);
130     while (_target != _source)
131     {
132         if (_target == predecessors[_target])
133         {
134             *err_msg = "No path found";
135             return 0;
136         }
137         _target = predecessors[_target];
138
139         path_vect.push_back(_target);
140         if (!max--)
141         {
142             *err_msg = "Overflow";
143             return -1;
144         }
145     }
146
147     *path = (path_element_t *) malloc(sizeof(path_element_t) * (path_vect.size() + 1));
148     *path_count = path_vect.size();
149
150     for(int i = path_vect.size() - 1, j = 0; i >= 0; i--, j++)
151     {
152         graph_traits < graph_t >::vertex_descriptor v_src;
153         graph_traits < graph_t >::vertex_descriptor v_targ;
154         graph_traits < graph_t >::edge_descriptor e;
155         graph_traits < graph_t >::out_edge_iterator out_i, out_end;
156
157         (*path)[j].vertex_id = path_vect.at(i);
158
159         (*path)[j].edge_id = -1;
160         (*path)[j].cost = distances[_target];
161        
162         if (i == 0)
163         {
164             continue;
165         }
166
167         v_src = path_vect.at(i);
168         v_targ = path_vect.at(i - 1);
169
170         for (tie(out_i, out_end) = out_edges(v_src, graph);
171              out_i != out_end; ++out_i)
172         {
173             graph_traits < graph_t >::vertex_descriptor v, targ;
174             e = *out_i;
175             v = source(e, graph);
176             targ = target(e, graph);
177                                                                
178             if (targ == v_targ)
179             {
180                 (*path)[j].edge_id = graph[*out_i].id;
181                 (*path)[j].cost = graph[*out_i].cost;
182                 break;
183             }
184         }
185     }
186
187     return EXIT_SUCCESS;
188 }
189
190 #if 0
191
192 // Testing function
193
194 #define NUM_EDGES 100
195 int main() {
196                
197     edge_t *e;
198
199     e = (edge_t *)malloc(NUM_EDGES * sizeof(edge_t));
200     if (!e)
201         return -1;
202
203     for (int i = 0; i < NUM_EDGES; i++)
204     {
205         e[i].id = i;
206         e[i].source = i;
207         e[i].target = (i + 1 > NUM_EDGES) ? 0 : i + 1;
208         e[i].cost = 1;
209     }
210
211     char *err_msg = NULL;
212     path_element_t *path;
213     int ret;
214     int path_count;
215
216     int final_edges = NUM_EDGES - 1;
217
218     ret = boost_dijkstra(e, NUM_EDGES, 0, final_edges, 1, 0, &path, &path_count, &err_msg);
219
220     if (ret < 0)
221     {
222         printf("Error: %s\n", err_msg);
223
224     } else {
225         printf("Path is :\n");
226         for (int i = 0; i < path_count; i++)
227         {
228             printf("Step %i vertex_id  %i \n", i, path[i].vertex_id);
229             printf("        edge_id    %i \n", path[i].edge_id);
230             printf("        cost       %f \n", path[i].cost);
231         }
232         free(path);
233     }
234     printf("\n");
235     free(e);
236 }
237 #endif
Note: See TracBrowser for help on using the browser.