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

Revision 39, 5.5 KB (checked in by anton, 3 years 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
32using namespace std;
33using namespace boost;
34
35/*
36//      FIXME: use this to avoid heap allocation ?
37
38void* operator new(size_t size)
39{
40return palloc(size);
41}
42
43void 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
53struct Vertex
54{
55    int id;
56    float8 cost;
57};
58
59
60int
61boost_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
195int 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.