root/branches/debug/core/src/shooting_star_boost_wrapper.cpp

Revision 144, 11.1 KB (checked in by anton, 3 years ago)

target edge added to found_goal exception

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 <cmath>    // for sqrt
34
35using namespace std;
36using namespace boost;
37
38struct Edge
39{
40  int id;
41  int source;
42  int target;
43  float8 cost;
44  float distance;
45  float rank;
46  std::map< int, vector< std::pair<float, std::vector<int> > >, std::less<int> > adjacent_edges;
47  default_color_type color;
48 
49  std::size_t index;
50};
51       
52struct Vertex
53{
54  int id;
55  float8 x;
56  float8 y;
57};
58
59// exception for termination
60template <class Edge>
61class found_goal
62{
63  public:
64    found_goal()
65    {
66    }
67    found_goal(Edge target) : target_edge(target)
68    {
69    }
70    found_goal(const found_goal &fg)
71    {
72    }
73    ~found_goal()
74    {
75    }
76    Edge get_target()
77    {
78      return target_edge;
79    }
80  private:
81    Edge target_edge;
82
83};
84
85// visitor that terminates when we find the goal
86template <class Edge>
87class shooting_star_goal_visitor : public boost::default_shooting_star_visitor
88{
89public:
90  shooting_star_goal_visitor(Edge goal, int max_id) : m_goal(goal)
91    {
92    }
93  shooting_star_goal_visitor(const shooting_star_goal_visitor &gv) : m_goal(gv.m_goal)
94    {
95    }
96  ~shooting_star_goal_visitor()
97    {
98    }
99
100  template <class Graph>
101  void examine_edge(Edge e, Graph& g, int e_max_id)
102  {
103    if( g[e].id == g[m_goal].id || g[e].id == g[m_goal].id + e_max_id)
104    {
105      throw found_goal<Edge>(e);
106    }
107  }
108  template <class Graph>
109  void finish_edge(Edge e, Graph& g) {}
110private:
111  Edge m_goal;
112  int e_max_id;
113};
114
115// Heuristic function
116template <class Graph, class CostType>
117class distance_heuristic
118{
119public:
120  typedef typename graph_traits<Graph>::edge_descriptor Edge;
121  distance_heuristic(Graph& g, Edge goal):m_g(g), m_goal(goal){}
122  CostType operator()(Edge e)
123  {
124    CostType dx = m_g[source(m_goal, m_g)].x - m_g[source(e, m_g)].x;
125    CostType dxt = m_g[target(m_goal, m_g)].x - m_g[target(e, m_g)].x;
126    CostType dy = m_g[source(m_goal, m_g)].y - m_g[source(e, m_g)].y;
127    CostType dyt = m_g[target(m_goal, m_g)].y - m_g[target(e, m_g)].y;
128    //You can choose any heuristical function from below
129    //return ::max(dx, dy);
130    //return ::sqrt(dx * dx + dy * dy)/2;
131    //return 0;
132    return (min(::fabs(dx),::fabs(dxt))+min(::fabs(dy),::fabs(dyt)))/2;
133  }
134private:
135  Graph& m_g;
136  Edge m_goal;
137};
138
139
140// Adds an edge to the graph
141// Also copies all attributes and adjacent edges
142template <class G, class E>
143static void
144graph_add_edge(G &graph, int index,
145               int id, int source, int target,
146               float8 cost, float8 s_x, float8 s_y, float8 t_x, float8 t_y,
147               std::map< int, vector< std::pair<float, vector<int> > >, std::less<int> > adjacent_edges)
148{
149
150  E e;
151  bool inserted;
152
153  if (cost < 0) // edges are inserted as unpassable if cost is negative
154    cost = MAX_COST;
155
156//  std::fstream myfile;
157//  myfile.open("/tmp/r_wrapper.log", std::ios::out|std::ios::app);
158 
159//  myfile<<"graph size is  "<< boost::num_edges(graph) << " edges\n" << std::flush;
160
161  tie(e, inserted) = add_edge(source, target, graph);
162
163  graph[e].cost = cost;
164  graph[e].id = id;
165 
166  graph[e].source = source;
167  graph[e].target = target;
168 
169  graph[e].adjacent_edges = adjacent_edges;
170
171  graph[e].rank = 0;
172  graph[e].distance = 0;
173 
174  graph[e].index = index;
175
176 
177  typedef typename graph_traits<G>::vertex_descriptor Vertex;
178  Vertex s = vertex(source, graph);
179  Vertex t = vertex(target, graph);
180
181  graph[s].id=source;
182  graph[t].id=target;
183
184  graph[s].x=s_x;
185  graph[s].y=s_y;
186  graph[t].x=t_x;
187  graph[t].y=t_y;
188
189//  myfile<<"edge "<< graph[e].id<<"("<<graph[e].source<<","<<graph[e].target<<"):"<<graph[e].cost<<" was inserted: " << inserted << "\n" << std::flush;
190//  myfile<<"(now  "<< boost::num_edges(graph) << " edges)\n" << std::flush;
191//  myfile.close();
192}
193
194// Main Shooting* function.
195// It renumbers vertices, fills the graph with edges,
196// calculates a route and return a result.
197int
198boost_shooting_star(edge_shooting_star_t *edges_array, unsigned int count,
199            int source_edge_id, int target_edge_id,
200            bool directed, bool has_reverse_cost,
201            path_element_t **path, int *path_count, char **err_msg, int e_max_id)
202{
203
204  typedef adjacency_list<vecS, vecS, directedS, Vertex, Edge> graph_t;
205
206  typedef graph_traits < graph_t >::vertex_descriptor vertex_descriptor;
207  typedef graph_traits < graph_t >::edge_descriptor edge_descriptor;
208
209  const unsigned int num_nodes = count*2;
210 
211  int z;
212  int src, trg, offset, rule_num;
213 
214  graph_t graph(num_nodes);
215
216  std::map< int, vector< std::pair<float, vector<int> > >, std::less<int> > adjacent_edges;
217
218  std::map< int, int, std::less<int> > vertices;
219 
220  vector<int> rule;
221
222  offset = 1;
223  rule_num = 0;
224
225  std::fstream myfile;
226  myfile.open("/tmp/r_wrapper.log", std::ios::out|std::ios::app);
227
228  myfile<<" Graph: "<<count<<"("<<num_nodes<<")\n"<<std::flush;
229
230  for (std::size_t j = 0; j < count; ++j)
231  {
232    //Vertex ids renumbering moved here
233    src = edges_array[j].source;
234    trg = edges_array[j].target;
235   
236    if(vertices[src]==0)
237    {
238      vertices[src]=j+offset;
239    }
240    edges_array[j].source=vertices[src];
241   
242    if(vertices[trg]==0)
243    {
244      offset++;     
245      vertices[trg]=j+offset;
246    }
247    edges_array[j].target=vertices[trg];
248   
249    for(z=0; z<MAX_RULE_LENGTH;++z)
250    {
251      if(edges_array[j].rule[z] > 0)
252      {
253        rule.push_back(edges_array[j].rule[z]);
254      }
255    }
256
257    if(edges_array[j].to_cost > 0)
258    {
259      adjacent_edges[edges_array[j].id].push_back(std::pair<float8, vector<int> > (edges_array[j].to_cost, rule) );
260      rule.clear();
261    }
262
263    if((j < count-1 && edges_array[j].id != edges_array[j+1].id)||(j==count-1))
264    {
265      graph_add_edge<graph_t, edge_descriptor>(graph, j,
266                                               edges_array[j].id, edges_array[j].source,
267                                               edges_array[j].target, edges_array[j].cost,
268                                               edges_array[j].s_x, edges_array[j].s_y,
269                                               edges_array[j].t_x, edges_array[j].t_y, adjacent_edges);
270   
271      // if the edge is not directed or if it is directed and has reverse cost
272      if (!directed || (directed && has_reverse_cost))
273      {
274        float8 cost;
275               
276        if (has_reverse_cost)
277        {
278          cost = edges_array[j].reverse_cost;
279        }
280        else
281        {
282          cost = edges_array[j].cost;
283        }
284
285
286      if(adjacent_edges[edges_array[j].id].size() > 0)
287      {
288        adjacent_edges[edges_array[j].id+e_max_id].assign( adjacent_edges[edges_array[j].id].begin(), adjacent_edges[edges_array[j].id].end() );
289        adjacent_edges.erase(edges_array[j].id);
290      }
291
292
293        graph_add_edge<graph_t, edge_descriptor>(graph, j,
294                                               edges_array[j].id+e_max_id, edges_array[j].target,
295                                               edges_array[j].source, cost,
296                                               edges_array[j].s_x, edges_array[j].s_y,
297                                               edges_array[j].t_x, edges_array[j].t_y, adjacent_edges);
298      }
299
300    adjacent_edges.clear();
301    rule_num = 0;
302    }
303    else
304    {
305      rule_num++;
306    }
307  }
308 
309 
310  edge_descriptor source_edge;
311  edge_descriptor target_edge;
312 
313  bool source_found = false, target_found = false;
314 
315  graph_traits<graph_t>::edge_iterator ei, ei_end;
316
317  for(tie(ei, ei_end) = edges(graph); ei != ei_end; ++ei)
318  {
319    if(graph[*ei].id == source_edge_id)
320    {
321      source_edge = *ei;
322      source_found = true;
323      break;
324    }
325
326  }
327
328  if (!source_found)
329  {
330    *err_msg = "Source edge not found";
331    myfile<<"Source not found\n"<<std::flush;
332    return -1;
333  }
334
335
336  for(tie(ei, ei_end) = edges(graph); ei != ei_end; ++ei)
337  {
338    if(graph[*ei].id == target_edge_id)
339    {
340      target_edge = *ei;
341      target_found = true;
342      break;
343    }
344  }
345
346
347  if (!target_found)
348  {
349    *err_msg = "Target edge not found";
350    myfile<<"Target not found\n"<<std::flush;
351    return -1;
352  }
353
354  myfile<<"\n e_max_id = "<<e_max_id<<"\n\n"<<std::flush;
355  property_map<graph_t, std::size_t Edge::*>::type edge_index = get(&Edge::index, graph);
356
357  std::map< int, edge_descriptor, std::less<int> > predecessors;
358 
359  property_map<graph_t, float Edge::*>::type rank = get(&Edge::rank, graph);
360  property_map<graph_t, float Edge::*>::type distance = get(&Edge::distance, graph);
361
362  try
363  {
364    //calling Shooting* search
365    shooting_star_search
366      (graph, source_edge,
367       distance_heuristic<graph_t, float>(graph, target_edge),
368       weight_map(get(&Edge::cost, graph)).
369       weight_map2(get(&Edge::adjacent_edges, graph)).
370       edge_color_map(get(&Edge::color, graph)).
371       visitor(shooting_star_goal_visitor<edge_descriptor>(target_edge, e_max_id)),
372       edge_index,
373       distance, rank,
374       predecessors, e_max_id
375       );
376
377  }
378  catch(found_goal<edge_descriptor> &fg)
379  {
380 
381//    myfile.open("/tmp/r_wrapper.log", std::ios::out|std::ios::app);
382   
383    myfile<<"\n*Path was found!*\n"<<std::flush;
384
385    vector<edge_descriptor> path_vect;
386    int max = MAX_NODES;
387   
388    target_edge = fg.get_target();
389
390    path_vect.push_back(target_edge);
391   
392    while (target_edge != source_edge)
393      {
394       
395                myfile<<"target_edge = "<<graph[target_edge].id<<", predecessors["<<graph[target_edge].id<<"] = "<<graph[predecessors[graph[target_edge].id]].id<<"\n"<<std::flush;
396
397        if ((target_edge == predecessors[graph[target_edge].id]) && (predecessors[graph[target_edge].id] != source_edge))
398        {
399          *err_msg = "No path found";
400          myfile<<"\nNo path found!\n"<<std::flush;
401          return -1;
402        }
403 
404        target_edge = predecessors[graph[target_edge].id];
405
406        path_vect.push_back(target_edge);
407
408        if (!max--)
409          {
410            *err_msg = "Overflow";
411          myfile<<"Overflow!\n"<<std::flush;
412            return -1;
413          }
414      }
415
416    *path = (path_element_t *) malloc(sizeof(path_element_t) *
417                                      (path_vect.size() + 1));
418    *path_count = path_vect.size();
419
420    for(int i = path_vect.size() - 1, j = 0; i >= 0; i--, j++)
421    {
422      graph_traits < graph_t >::edge_descriptor e;
423
424      e = path_vect.at(i);
425
426      if(graph[e].id > e_max_id)
427      {
428        graph[e].id -= e_max_id;       
429      }
430     
431      (*path)[j].edge_id = graph[e].id;
432      (*path)[j].cost = graph[e].cost;
433      (*path)[j].vertex_id = source(e, graph);
434    }
435
436    return EXIT_SUCCESS;
437  }
438
439  myfile<<"Nothing!\n"<<std::flush;
440
441  *err_msg = "Target edge was not reached";
442  return -1;
443
444}
445
Note: See TracBrowser for help on using the browser.