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

Revision 39, 9.3 KB (checked in by anton, 3 years ago)

1.0.0b tag added

Line 
1/*
2 * Shooting* Shortest path algorithm for PostgreSQL
3 *
4 * Copyright (c) 2007 Anton A. Patrushev, Orkney, Inc.
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/vector_property_map.hpp>
29#include <shooting_star_search.hpp>
30
31#include "shooting_star.h"
32
33#include <math.h>    // for sqrt
34
35using namespace std;
36using namespace boost;
37
38// Maximal number of nodes in the path (to avoid infinite loops)
39#define MAX_NODES 1000000
40
41struct Edge
42{
43  int id;
44  int source;
45  int target;
46  float8 cost;
47  float8 distance;
48  float8 rank;
49  std::map< int, std::pair<float8, std::vector<int> >, std::less<int> > adjacent_edges;
50
51  std::vector< int > history;
52
53  default_color_type color;
54 
55  std::size_t index;
56
57  adjacency_list_traits<vecS, vecS, directedS>::edge_descriptor predecessor;
58};
59       
60struct Vertex
61{
62  int id;
63  float8 x;
64  float8 y;
65
66  default_color_type color;
67 
68  float8 cost;
69 
70};
71
72
73struct found_goal {}; // exception for termination
74
75// visitor that terminates when we find the goal
76template <class Edge>
77class shooting_star_goal_visitor : public boost::default_shooting_star_visitor
78{
79public:
80  shooting_star_goal_visitor(Edge goal) : m_goal(goal) {}
81
82  template <class Graph>
83  void examine_edge(Edge e, Graph& g) {
84    if(g[e].id == g[m_goal].id)
85      throw found_goal();
86  }
87  template <class Graph>
88  void finish_edge(Edge e, Graph& g) {}
89private:
90  Edge m_goal;
91};
92
93
94template <class Graph, class CostType>
95class distance_heuristic : public astar_heuristic<Graph, CostType>
96{
97public:
98  typedef typename graph_traits<Graph>::edge_descriptor Edge;
99  distance_heuristic(Graph& g, Edge goal):m_g(g), m_goal(goal){}
100  CostType operator()(Edge e)
101  {
102    CostType dx = m_g[target(m_goal, m_g)].x - m_g[target(e, m_g)].x;
103    CostType dy = m_g[target(m_goal, m_g)].y - m_g[target(e, m_g)].y;
104    //You can choose any heuristical function from below
105    //return ::max(dx, dy);
106    //return ::sqrt(dx * dx + dy * dy)/2;
107    //return 0;
108    return (::fabs(dx)+::fabs(dy))/2;
109  }
110private:
111  Graph& m_g;
112  Edge m_goal;
113};
114
115
116template <class G, class E>
117static void
118graph_add_edge(G &graph, int id, int source, int target,
119               float8 cost, float8 s_x, float8 s_y, float8 t_x, float8 t_y,
120               std::map< int, std::pair<float8, vector<int> >, std::less<int> > adjacent_edges)
121{
122
123  E e;
124  bool inserted;
125
126  if (cost < 0) // edges are not inserted in the graph if cost is negative
127    return;
128
129  tie(e, inserted) = add_edge(source, target, graph);
130
131  graph[e].cost = cost;
132  graph[e].id = id;
133
134//  put(edge_index, graph, graph[e], id);
135 
136  graph[e].source = source;
137  graph[e].target = target;
138 
139  graph[e].adjacent_edges = adjacent_edges;
140 
141  typedef typename graph_traits<G>::vertex_descriptor Vertex;
142  Vertex s = vertex(source, graph);
143  Vertex t = vertex(target, graph);
144
145  graph[s].id=source;
146  graph[t].id=target;
147
148  graph[s].x=s_x;
149  graph[s].y=s_y;
150  graph[t].x=t_x;
151  graph[t].y=t_y;
152
153}
154
155int
156boost_shooting_star(edge_shooting_star_t *edges_array, unsigned int count,
157            int source_edge_id, int target_edge_id,
158            bool directed, bool has_reverse_cost,
159            path_element_t **path, int *path_count, char **err_msg, int e_max_id)
160{
161
162  typedef adjacency_list<vecS, vecS, directedS, Vertex, Edge> graph_t;
163 
164  typedef graph_traits < graph_t >::vertex_descriptor vertex_descriptor;
165  typedef graph_traits < graph_t >::edge_descriptor edge_descriptor;
166
167  const unsigned int num_nodes = /*1*/count*2;
168 
169  int z;
170  int src, trg, offset;
171 
172  graph_t graph(num_nodes);
173
174  std::map< int, std::pair<float8, vector<int> >, std::less<int> > adjacent_edges;
175
176  std::map< int, int, std::less<int> > vertices;
177
178  offset = 0;
179 
180  for (std::size_t j = 0; j < count; ++j)
181  {
182    //Vertex ids renumbering moved here
183   
184    src = edges_array[j].source;
185    trg = edges_array[j].target;
186
187    if(vertices[src]==NULL)
188    //if (vertices.find(edges_array[j].source) == vertices.end())
189    {
190      vertices[src]=j+offset;
191      edges_array[j].source=j+offset;
192     
193    }
194    else
195    {
196      edges_array[j].source=vertices[src];
197    }
198
199    if(vertices[trg]==NULL)
200    //if (vertices.find(edges_array[j].target) == vertices.end())   
201    {
202      offset++;
203 
204      vertices[trg]=j+offset;
205      edges_array[j].target=j+offset;
206    }
207    else
208    {
209      edges_array[j].target=vertices[trg];
210    }
211   
212    adjacent_edges[edges_array[j].id].first = edges_array[j].to_cost;
213
214    for(z=0; z<MAX_RULE_LENGTH;++z)
215    {
216      if(edges_array[j].rule[z] > 0)
217      {
218        adjacent_edges[edges_array[j].id].second.push_back(edges_array[j].rule[z]);
219      }
220    }
221
222    if((j < count-1 && edges_array[j].id != edges_array[j+1].id)||(j==count-1))
223    {
224      graph_add_edge<graph_t, edge_descriptor>(graph,
225                                               edges_array[j].id, edges_array[j].source,
226                                               edges_array[j].target, edges_array[j].cost,
227                                               edges_array[j].s_x, edges_array[j].s_y,
228                                               edges_array[j].t_x, edges_array[j].t_y, adjacent_edges);
229
230      if (!directed || (directed && has_reverse_cost))
231      {
232        float8 cost;
233               
234        if (has_reverse_cost)
235        {
236          cost = edges_array[j].reverse_cost;
237        }
238        else
239        {
240          cost = edges_array[j].cost;
241        }
242
243        graph_add_edge<graph_t, edge_descriptor>(graph,
244                                               edges_array[j].id+e_max_id, edges_array[j].target,
245                                               edges_array[j].source, cost,
246                                               edges_array[j].s_x, edges_array[j].s_y,
247                                               edges_array[j].t_x, edges_array[j].t_y, adjacent_edges);
248      }
249
250    adjacent_edges.clear();
251   
252    }
253  }
254   
255  std::map< int, edge_descriptor, std::less<int> > predecessors;
256 
257  edge_descriptor source_edge;
258  edge_descriptor target_edge;
259 
260  bool source_found = false, target_found = false;
261 
262  graph_traits<graph_t>::edge_iterator ei, ei_end;
263  int index;   
264
265  index = 1;
266 
267  for(tie(ei, ei_end) = edges(graph); ei != ei_end; ++ei, ++index)
268    graph[*ei].index = index;   
269   
270  for(tie(ei, ei_end) = edges(graph); ei != ei_end; ++ei)
271  {
272    if(graph[*ei].id == source_edge_id)
273    {
274      source_edge = *ei;
275      source_found = true;
276      break;
277    }
278  }
279
280  if (!source_found)
281  {
282    *err_msg = "Source edge not found";
283    return -1;
284  }
285
286  for(tie(ei, ei_end) = edges(graph); ei != ei_end; ++ei)
287  {
288    if(graph[*ei].id == target_edge_id)
289    {
290      target_edge = *ei;
291      target_found = true;
292      break;
293    }
294  }
295
296  if (!target_found)
297  {
298    *err_msg = "Target edge not found";
299    return -1;
300  }
301
302  std::vector<float8> distances(num_edges(graph));
303 
304  std::vector<default_color_type> edge_colors(num_edges(graph), color_traits<default_color_type>::white());
305
306  property_map<graph_t, std::vector< int > Edge::*>::type history = get(&Edge::history, graph);
307
308  property_map<graph_t, std::size_t Edge::*>::type edge_index = get(&Edge::index, graph);
309
310  property_map<graph_t, float8 Edge::*>::type rank = get(&Edge::rank, graph);
311  property_map<graph_t, float8 Edge::*>::type distance = get(&Edge::distance, graph);
312
313  try
314  {
315    shooting_star_search
316      (graph, source_edge,
317       distance_heuristic<graph_t, float>(graph, target_edge),
318       weight_map(get(&Edge::cost, graph)).
319       weight_map2(get(&Edge::adjacent_edges, graph)).
320       vertex_color_map(get(&Vertex::color, graph)).
321       edge_color_map(get(&Edge::color, graph)).
322       visitor(shooting_star_goal_visitor<edge_descriptor>(target_edge)),
323       edge_index,
324       distance, rank,
325       history,
326       predecessors, e_max_id
327       );
328
329  }
330  catch(found_goal fg) {
331 
332    vector<edge_descriptor> path_vect;
333    int max = MAX_NODES;
334
335    path_vect.push_back(target_edge);
336   
337    while (target_edge != source_edge)
338      {
339        if ((target_edge == predecessors[graph[target_edge].id]) && (predecessors[graph[target_edge].id] != source_edge))
340        {
341          *err_msg = "No path found";
342          return -1;
343           
344        }
345 
346        target_edge = predecessors[graph[target_edge].id];
347
348        if(target_edge == predecessors[graph[target_edge].id] )
349          continue;
350
351        path_vect.push_back(target_edge);
352
353        if (!max--)
354          {
355            *err_msg = "Overflow";
356            return -1;
357          }
358      }
359
360    *path = (path_element_t *) malloc(sizeof(path_element_t) *
361                                      (path_vect.size() + 1));
362    *path_count = path_vect.size();
363
364    for(int i = path_vect.size() - 1, j = 0; i >= 0; i--, j++)
365    {
366      graph_traits < graph_t >::edge_descriptor e;
367
368      e = path_vect.at(i);
369
370      if(graph[e].id > e_max_id)
371        graph[e].id -= e_max_id;
372
373      (*path)[j].edge_id = graph[e].id;
374      (*path)[j].cost = graph[e].cost;
375      (*path)[j].vertex_id = source(e, graph);
376    }
377
378    return EXIT_SUCCESS;
379  }
380
381}
382
Note: See TracBrowser for help on using the browser.