PGROUTING  3.2
TSP_driver.cpp
Go to the documentation of this file.
1 /*PGR-GNU*****************************************************************
2 
3 FILE: TSP_driver.cpp
4 
5 Generated with Template by:
6 Copyright (c) 2015 pgRouting developers
8 
9 Function's developer:
10 Copyright (c) 2015 Celia Virginia Vergara Castillo
12 
13 ------
14 
15 This program is free software; you can redistribute it and/or modify
16 it under the terms of the GNU General Public License as published by
17 the Free Software Foundation; either version 2 of the License, or
18 (at your option) any later version.
19 
20 This program is distributed in the hope that it will be useful,
21 but WITHOUT ANY WARRANTY; without even the implied warranty of
22 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 GNU General Public License for more details.
24 
25 You should have received a copy of the GNU General Public License
26 along with this program; if not, write to the Free Software
27 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
28 
29  ********************************************************************PGR-GNU*/
30 
31 #include "drivers/tsp/TSP_driver.h"
32 
33 #include <string>
34 #include <sstream>
35 #include <vector>
36 #include <algorithm>
37 
38 #include "cpp_common/Dmatrix.h"
39 #include "tsp/pgr_tsp.hpp"
40 
41 #include "cpp_common/pgr_alloc.hpp"
42 #include "cpp_common/pgr_assert.h"
43 
44 void
46  Matrix_cell_t *distances,
47  size_t total_distances,
48  int64_t start_vid,
49  int64_t end_vid,
50 
51  double initial_temperature,
52  double final_temperature,
53  double cooling_factor,
54  int64_t tries_per_temperature,
55  int64_t max_changes_per_temperature,
56  int64_t max_consecutive_non_changes,
57  bool randomize,
58  double time_limit,
59 
60  General_path_element_t **return_tuples,
61  size_t *return_count,
62  char **log_msg,
63  char **notice_msg,
64  char **err_msg) {
65  std::ostringstream log;
66  std::ostringstream notice;
67  std::ostringstream err;
68 
69  try {
70  std::vector <Matrix_cell_t> data_costs(
71  distances,
72  distances + total_distances);
73 
74  pgrouting::tsp::Dmatrix costs(data_costs);
75 
76  if (!costs.has_no_infinity()) {
77  err << "An Infinity value was found on the Matrix";
78  *err_msg = pgr_msg(err.str().c_str());
79  return;
80  }
81 
82  if (!costs.is_symmetric()) {
83  err << "A Non symmetric Matrix was given as input";
84  *err_msg = pgr_msg(err.str().c_str());
85  return;
86  }
87 
88  double real_cost = -1;
89 
90  size_t idx_start = costs.has_id(start_vid) ?
91  costs.get_index(start_vid) : 0;
92 
93  size_t idx_end = costs.has_id(end_vid) ?
94  costs.get_index(end_vid) : 0;
95 
96  if (costs.has_id(start_vid)
97  && costs.has_id(end_vid)
98  && start_vid != end_vid) {
99  /* An ending vertex needs to be by the starting vertex */
100  real_cost = costs.distance(idx_start, idx_end);
101  costs.set(idx_start, idx_end, 0);
102  }
103 
104 
105  log << "Processing Information \n"
106  << "Initializing tsp class --->";
108 
109 
110  log << " tsp.greedyInitial --->";
111  tsp.greedyInitial(idx_start);
112 
113 
114 
115  log << " tsp.annealing --->";
116  tsp.annealing(
117  initial_temperature,
118  final_temperature,
119  cooling_factor,
120  tries_per_temperature,
121  max_changes_per_temperature,
122  max_consecutive_non_changes,
123  randomize,
124  time_limit);
125  log << " OK\n";
126  log << tsp.get_log();
127  log << tsp.get_stats();
128 
129  auto bestTour(tsp.get_tour());
130 
131  if (costs.has_id(start_vid)
132  && costs.has_id(end_vid)
133  && start_vid != end_vid) {
134  costs.set(idx_start, idx_end, real_cost);
135  }
136 
137 
138  log << "\nBest cost reached = " << costs.tourCost(bestTour);
139 
140  auto start_ptr = std::find(
141  bestTour.cities.begin(),
142  bestTour.cities.end(),
143  idx_start);
144 
145 
146  std::rotate(
147  bestTour.cities.begin(),
148  start_ptr,
149  bestTour.cities.end());
150 
151  if (costs.has_id(start_vid)
152  && costs.has_id(end_vid)
153  && start_vid != end_vid) {
154  if (*(bestTour.cities.begin() + 1) == idx_end) {
155  std::reverse(
156  bestTour.cities.begin() + 1,
157  bestTour.cities.end());
158  }
159  }
160 
161 
162  std::vector< General_path_element_t > result;
163  result.reserve(bestTour.cities.size() + 1);
164  pgassert(bestTour.cities.size() == costs.size());
165 
166  bestTour.cities.push_back(bestTour.cities.front());
167 
168  auto prev_id = bestTour.cities.front();
169  double agg_cost = 0;
170  for (const auto &id : bestTour.cities) {
171  if (id == prev_id) continue;
173  data.node = costs.get_id(prev_id);
174  data.edge = static_cast<int64_t>(prev_id);
175  data.cost = costs.distance(prev_id, id);
176  data.agg_cost = agg_cost;
177  result.push_back(data);
178  agg_cost += data.cost;
179  prev_id = id;
180  }
181 
182  /* inserting the returning to starting point */
183  {
185  data.node = costs.get_id(bestTour.cities.front());
186  data.edge = static_cast<int64_t>(bestTour.cities.front());
187  data.cost = costs.distance(prev_id, bestTour.cities.front());
188  agg_cost += data.cost;
189  data.agg_cost = agg_cost;
190  result.push_back(data);
191  }
192 
193  pgassert(result.size() == bestTour.cities.size());
194  *return_count = bestTour.size();
195  (*return_tuples) = pgr_alloc(result.size(), (*return_tuples));
196 
197  /* store the results */
198  int seq = 0;
199  for (const auto &row : result) {
200  (*return_tuples)[seq] = row;
201  ++seq;
202  }
203 
204  *log_msg = log.str().empty()?
205  *log_msg :
206  pgr_msg(log.str().c_str());
207  *notice_msg = notice.str().empty()?
208  *notice_msg :
209  pgr_msg(notice.str().c_str());
210  } catch (AssertFailedException &except) {
211  (*return_tuples) = pgr_free(*return_tuples);
212  (*return_count) = 0;
213  err << except.what();
214  *err_msg = pgr_msg(err.str().c_str());
215  *log_msg = pgr_msg(log.str().c_str());
216  } catch (std::exception &except) {
217  (*return_tuples) = pgr_free(*return_tuples);
218  (*return_count) = 0;
219  err << except.what();
220  *err_msg = pgr_msg(err.str().c_str());
221  *log_msg = pgr_msg(log.str().c_str());
222  } catch(...) {
223  (*return_tuples) = pgr_free(*return_tuples);
224  (*return_count) = 0;
225  err << "Caught unknown exception!";
226  *err_msg = pgr_msg(err.str().c_str());
227  *log_msg = pgr_msg(log.str().c_str());
228  }
229 }
pgr_alloc
T * pgr_alloc(std::size_t size, T *ptr)
allocates memory
Definition: pgr_alloc.hpp:66
General_path_element_t::edge
int64_t edge
Definition: general_path_element_t.h:42
pgrouting::tsp::Dmatrix::get_index
size_t get_index(int64_t id) const
original id -> idx
Definition: Dmatrix.cpp:93
pgr_tsp.hpp
pgrouting::tsp::Dmatrix::set
void set(size_t i, size_t j, double dist)
sets a special value for the distance(i,j)
Definition: Dmatrix.h:60
pgr_msg
char * pgr_msg(const std::string &msg)
Definition: pgr_alloc.cpp:30
AssertFailedException::what
virtual const char * what() const
Definition: pgr_assert.cpp:67
pgrouting::tsp::Dmatrix::tourCost
double tourCost(const Tour &tour) const
tour evaluation
Definition: Dmatrix.cpp:44
pgrouting::tsp::TSP
Definition: pgr_tsp.hpp:77
pgrouting::tsp::Dmatrix::is_symmetric
bool is_symmetric() const
Definition: Dmatrix.cpp:193
pgrouting::tsp::Dmatrix::has_no_infinity
bool has_no_infinity() const
Definition: Dmatrix.cpp:162
pgrouting::tsp::TSP::get_stats
std::string get_stats() const
Definition: pgr_tsp.hpp:106
pgassert
#define pgassert(expr)
Uses the standard assert syntax.
Definition: pgr_assert.h:94
pgrouting::tsp::Dmatrix::has_id
bool has_id(int64_t id) const
original id -> true
Definition: Dmatrix.cpp:79
TSP_driver.h
pgr_alloc.hpp
pgrouting::tsp::Dmatrix::size
size_t size() const
|idx|
Definition: Dmatrix.h:88
pgrouting::tsp::Dmatrix::get_id
int64_t get_id(size_t idx) const
idx -> original id
Definition: Dmatrix.cpp:101
pgrouting::tsp::TSP::annealing
void annealing(double initial_temperature, double final_temperature, double cooling_factor, int64_t tries_per_temperature, int64_t max_changes_per_temperature, int64_t max_consecutive_non_changes, bool randomize, double time_limit)
Definition: pgr_tsp.cpp:429
pgr_assert.h
An assert functionality that uses C++ throw().
General_path_element_t::node
int64_t node
Definition: general_path_element_t.h:41
pgrouting::tsp::TSP::greedyInitial
void greedyInitial(size_t idx_start=0)
Definition: pgr_tsp.cpp:143
General_path_element_t
Definition: general_path_element_t.h:37
pgrouting::tsp::TSP::get_log
std::string get_log() const
Definition: pgr_tsp.hpp:115
Dmatrix.h
pgr_free
T * pgr_free(T *ptr)
Definition: pgr_alloc.hpp:77
pgrouting::tsp::Dmatrix::distance
double distance(int64_t i, int64_t j) const
Definition: Dmatrix.h:108
do_pgr_tsp
void do_pgr_tsp(Matrix_cell_t *distances, size_t total_distances, int64_t start_vid, int64_t end_vid, double initial_temperature, double final_temperature, double cooling_factor, int64_t tries_per_temperature, int64_t max_changes_per_temperature, int64_t max_consecutive_non_changes, bool randomize, double time_limit, General_path_element_t **return_tuples, size_t *return_count, char **log_msg, char **notice_msg, char **err_msg)
Definition: TSP_driver.cpp:45
matrix_cell
Definition: matrix_cell_t.h:37
General_path_element_t::cost
double cost
Definition: general_path_element_t.h:43
pgrouting::tsp::TSP::get_tour
Tour get_tour() const
Definition: pgr_tsp.hpp:104
pgrouting::tsp::Dmatrix
Definition: Dmatrix.h:43
General_path_element_t::agg_cost
double agg_cost
Definition: general_path_element_t.h:44
AssertFailedException
Extends std::exception and is the exception that we throw if an assert fails.
Definition: pgr_assert.h:139