root/trunk/core/src/boost_wrapper.cpp

Revision 178, 4.6 KB (checked in by anton, 2 years ago)

constant string conversion fixed

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
24#include <boost/graph/graph_traits.hpp>
25#include <boost/graph/adjacency_list.hpp>
26#include <boost/graph/dijkstra_shortest_paths.hpp>
27
28#include "dijkstra.h"
29
30using namespace std;
31using namespace boost;
32
33/*
34//      FIXME: use this to avoid heap allocation ?
35
36void* operator new(size_t size)
37{
38return palloc(size);
39}
40
41void operator delete(void *p)
42{
43    pfree(p);
44}
45
46*/
47
48// Maximal number of nodes in the path (to avoid infinite loops)
49#define MAX_NODES 100000000
50
51struct Vertex
52{
53    int id;
54    float8 cost;
55};
56
57
58int
59boost_dijkstra(edge_t *edges, unsigned int count, int start_vertex, int end_vertex,
60               bool directed, bool has_reverse_cost,
61               path_element_t **path, int *path_count, char **err_msg)
62{
63
64    // FIXME: use a template for the directedS parameters
65    typedef adjacency_list < listS, vecS, directedS, no_property, Vertex> graph_t;
66
67    typedef graph_traits < graph_t >::vertex_descriptor vertex_descriptor;
68    typedef graph_traits < graph_t >::edge_descriptor edge_descriptor;
69    typedef std::pair<int, int> Edge;
70
71    // FIXME: compute this value
72    const unsigned int num_nodes = ((directed && has_reverse_cost ? 2 : 1) * count) + 100;
73
74    graph_t graph(num_nodes);
75
76    property_map<graph_t, edge_weight_t>::type weightmap = get(edge_weight, graph);
77
78    for (std::size_t j = 0; j < count; ++j)
79    {
80        edge_descriptor e; bool inserted;
81        tie(e, inserted) = add_edge(edges[j].source, edges[j].target, graph);
82
83        graph[e].cost = edges[j].cost;
84        graph[e].id = edges[j].id;
85                               
86        if (!directed || (directed && has_reverse_cost))
87        {
88            tie(e, inserted) = add_edge(edges[j].target, edges[j].source, graph);
89            graph[e].id = edges[j].id;
90
91            if (has_reverse_cost)
92            {
93                graph[e].cost = edges[j].reverse_cost;
94            }
95            else
96            {
97                graph[e].cost = edges[j].cost;
98            }
99        }
100    }
101
102    std::vector<vertex_descriptor> predecessors(num_vertices(graph));
103
104    vertex_descriptor _source = vertex(start_vertex, graph);
105
106    if (_source < 0 /*|| _source >= num_nodes*/)
107    {
108        *err_msg = (char *) "Starting vertex not found";
109        return -1;
110    }
111
112    vertex_descriptor _target = vertex(end_vertex, graph);
113    if (_target < 0 /*|| _target >= num_nodes*/)
114    {
115        *err_msg = (char *) "Ending vertex not found";
116        return -1;
117    }
118
119    std::vector<float8> distances(num_vertices(graph));
120    // calling Boost function
121    dijkstra_shortest_paths(graph, _source,
122                            predecessor_map(&predecessors[0]).
123                            weight_map(get(&Vertex::cost, graph))
124                            .distance_map(&distances[0]));
125
126    vector<int> path_vect;
127    int max = MAX_NODES;
128    path_vect.push_back(_target);
129
130    while (_target != _source)
131    {
132        if (_target == predecessors[_target])
133        {
134            *err_msg = (char *) "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 = (char *) "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}
Note: See TracBrowser for help on using the browser.