vrpRouting  0.3
base_matrix.cpp
Go to the documentation of this file.
1 /*PGR-GNU*****************************************************************
2 FILE: matrix.cpp
3 
4 Copyright (c) 2015 pgRouting developers
6 
7 Developer:
8 Copyright (c) 2015 Celia Virginia Vergara Castillo
9 
10 ------
11 
12 This program is free software; you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by
14 the Free Software Foundation; either version 2 of the License, or
15 (at your option) any later version.
16 
17 This program is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 GNU General Public License for more details.
21 
22 You should have received a copy of the GNU General Public License
23 along with this program; if not, write to the Free Software
24 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
25 
26  ********************************************************************PGR-GNU*/
29 #include "cpp_common/base_matrix.h"
30 
31 #include <string>
32 #include <sstream>
33 #include <algorithm>
34 #include <limits>
35 #include <vector>
36 #include <map>
37 #include <cmath>
38 #include <utility>
39 
41 #include "cpp_common/pgr_assert.h"
42 #include "c_types/matrix_cell_t.h"
44 
45 
46 namespace vrprouting {
47 namespace base {
48 
49 namespace detail {
50 double
51 get_distance(std::pair<Coordinate, Coordinate> p1 , std::pair<Coordinate, Coordinate> p2) {
52  auto dx = p1.first - p2.first;
53  auto dy = p1.second - p2.second;
54  return std::sqrt(dx * dx + dy * dy);
55 }
56 } // namespace detail
57 
84 void
85 Base_Matrix::set_ids(const std::vector<Matrix_cell_t> &data) {
86  pgassert(m_ids.empty());
87  Identifiers<Id> node_ids;
88  /*
89  * Cycle the information
90  */
91  for (const auto &cost : data) {
92  /*
93  * extract the original identifiers
94  */
95  node_ids += cost.from_vid;
96  node_ids += cost.to_vid;
97  }
98  /*
99  * Save the extracted information
100  */
101  m_ids.insert(m_ids.begin(), node_ids.begin(), node_ids.end());
102 }
103 
104 
125 bool
127  /*
128  * binary search the stored identifiers
129  */
130  auto pos = std::lower_bound(m_ids.cbegin(), m_ids.cend(), id);
131 
132  /*
133  * Return search results
134  */
135  return pos != m_ids.end() && *pos == id;
136 }
137 
138 
160 Idx
162  /*
163  * binary search the stored identifiers
164  */
165  auto pos = std::lower_bound(m_ids.begin(), m_ids.end(), id);
166  if (pos == m_ids.end()) {
167  std::ostringstream msg;
168  msg << *this << "\nNot found" << id;
169  pgassertwm(false, msg.str());
170  throw std::make_pair(std::string("(INTERNAL) Base_Matrix: Unable to find node on matrix"), msg.str());
171  }
172  pgassert(pos != m_ids.end());
173 
174  /*
175  * return the index found
176  */
177  return static_cast<Idx>(pos - m_ids.begin());
178 }
179 
201 Id
203  /*
204  * Go to the index in the identifiers vector
205  */
206 
207  if (index >= m_ids.size()) {
208  std::ostringstream msg;
209  msg << *this << "\nOut of range" << index;
210  pgassertwm(false, msg.str());
211  throw std::make_pair(std::string("(INTERNAL) Base_Matrix: The given index is out of range"), msg.str());
212  }
213  pgassert(index < m_ids.size());
214 
215  /*
216  * return the original id found
217  */
218  return static_cast<Id>(m_ids[index]);
219 }
220 
236  Matrix_cell_t *data_costs, size_t size_matrix,
237  const Identifiers<Id>& node_ids,
238  Multiplier multiplier) {
239  /*
240  * Sets the selected nodes identifiers
241  */
242  m_ids.insert(m_ids.begin(), node_ids.begin(), node_ids.end());
243 
244  /*
245  * Create matrix
246  */
247  m_time_matrix.resize(
248  m_ids.size(),
249  std::vector<TInterval>(
250  m_ids.size(),
251  /*
252  * Set initial values to infinity
253  */
254  (std::numeric_limits<TInterval>::max)()));
255 
256  Identifiers<Idx> inserted;
257  /*
258  * Cycle the matrix data
259  */
260  for (size_t i = 0; i < size_matrix; ++i) {
261  auto data = data_costs[i];
262  /*
263  * skip if row is not from selected nodes
264  */
265  if (!(has_id(data.from_vid) && has_id(data.to_vid))) continue;
266 
267  /*
268  * Save the information
269  */
270  m_time_matrix[get_index(data.from_vid)][get_index(data.to_vid)] =
271  static_cast<TInterval>(static_cast<Multiplier>(data.cost) * multiplier);
272 
273  /*
274  * If the opposite direction is infinity insert the same cost
275  */
276  if (m_time_matrix[get_index(data.to_vid)][get_index(data.from_vid)] == (std::numeric_limits<TInterval>::max)()) {
277  m_time_matrix[get_index(data.to_vid)][get_index(data.from_vid)] =
278  m_time_matrix[get_index(data.from_vid)][get_index(data.to_vid)];
279  }
280  }
281 
282  /*
283  * Set the diagonal values to 0
284  */
285  for (size_t i = 0; i < m_time_matrix.size(); ++i) {
286  m_time_matrix[i][i] = 0;
287  }
288 }
289 
305 Base_Matrix::Base_Matrix(Vroom_matrix_t *matrix_rows, size_t total_matrix_rows,
306  const Identifiers<Id> &location_ids, double scaling_factor) {
307  /*
308  * Sets the selected nodes identifiers
309  */
310  m_ids.insert(m_ids.begin(), location_ids.begin(), location_ids.end());
311 
312  /*
313  * Create matrix
314  */
315  m_time_matrix.resize(
316  m_ids.size(),
317  std::vector<TInterval>(m_ids.size(),
318  /*
319  * Set initial values to infinity
320  */
321  (std::numeric_limits<TInterval>::max)()));
322  m_cost_matrix.resize(
323  m_ids.size(),
324  std::vector<TravelCost>(m_ids.size(), (std::numeric_limits<TravelCost>::max)()));
325 
326  Identifiers<Idx> inserted;
327  /*
328  * Cycle the matrix data
329  */
330  for (size_t i = 0; i < total_matrix_rows; ++i) {
331  auto cell = matrix_rows[i];
332  /*
333  * skip if row is not from selected nodes
334  */
335  if (!(has_id(cell.start_id) && has_id(cell.end_id))) continue;
336 
337  /*
338  * Save the information. Scale the time matrix according to scaling_factor
339  */
340  m_time_matrix[get_index(cell.start_id)][get_index(cell.end_id)] =
341  static_cast<Duration>(std::round(cell.duration / scaling_factor));
342  m_cost_matrix[get_index(cell.start_id)][get_index(cell.end_id)] =
343  static_cast<Duration>(cell.cost);
344 
345  /*
346  * If the opposite direction is infinity insert the same cost
347  */
348  if (m_time_matrix[get_index(cell.end_id)][get_index(cell.start_id)] ==
349  (std::numeric_limits<TInterval>::max)()) {
350  m_time_matrix[get_index(cell.end_id)][get_index(cell.start_id)] =
351  m_time_matrix[get_index(cell.start_id)][get_index(cell.end_id)];
352  }
353  if (m_cost_matrix[get_index(cell.end_id)][get_index(cell.start_id)] ==
354  (std::numeric_limits<TravelCost>::max)()) {
355  m_cost_matrix[get_index(cell.end_id)][get_index(cell.start_id)] =
356  m_cost_matrix[get_index(cell.start_id)][get_index(cell.end_id)];
357  }
358  }
359 
360  /*
361  * Set the diagonal values to 0
362  */
363  for (size_t i = 0; i < m_time_matrix.size(); ++i) {
364  m_time_matrix[i][i] = 0;
365  m_cost_matrix[i][i] = 0;
366  }
367 }
368 
369 /*
370  * constructor for euclidean
371  */
372 Base_Matrix::Base_Matrix(const std::map<std::pair<Coordinate, Coordinate>, Id> &euclidean_data, Multiplier multiplier) {
373  m_ids.reserve(euclidean_data.size());
374  for (const auto &e : euclidean_data) {
375  m_ids.push_back(e.second);
376  }
377  m_time_matrix.resize(
378  m_ids.size(),
379  std::vector<TInterval>(
380  m_ids.size(),
381  (std::numeric_limits<TInterval>::max)()));
382 
383  for (const auto &from : euclidean_data) {
384  for (const auto &to : euclidean_data) {
385  auto from_id = get_index(from.second);
386  auto to_id = get_index(to.second);
387  m_time_matrix[from_id][to_id] =
388  static_cast<TInterval>(static_cast<Multiplier>(detail::get_distance(from.first, to.first)) * multiplier);
389  m_time_matrix[to_id][from_id] = m_time_matrix[from_id][to_id];
390  }
391  }
392 
393  for (size_t i = 0; i < m_time_matrix.size(); ++i) {
394  m_time_matrix[i][i] = 0;
395  }
396 }
397 
403 vroom::Matrix<vroom::Duration>
405  size_t matrix_size = m_ids.size();
406  vroom::Matrix<vroom::Cost> vroom_matrix(matrix_size);
407  for (size_t i = 0; i < matrix_size; i++) {
408  for (size_t j = 0; j < matrix_size; j++) {
409  vroom_matrix[i][j] = static_cast<vroom::Duration>(m_time_matrix[i][j]);
410  }
411  }
412  return vroom_matrix;
413 }
414 
420 vroom::Matrix<vroom::Cost>
422  size_t matrix_size = m_ids.size();
423  vroom::Matrix<vroom::Cost> vroom_matrix(matrix_size);
424  for (size_t i = 0; i < matrix_size; i++) {
425  for (size_t j = 0; j < matrix_size; j++) {
426  vroom_matrix[i][j] = static_cast<vroom::Cost>(m_cost_matrix[i][j]);
427  }
428  }
429  return vroom_matrix;
430 }
431 
458 bool
460  /*
461  * Cycle the matrix
462  */
463  for (const auto &row : m_time_matrix) {
464  for (const auto &val : row) {
465  /*
466  * found infinity?
467  *
468  * yes -> return false
469  */
470  if (val == (std::numeric_limits<TInterval>::max)()) return false;
471  }
472  }
473  /*
474  * return true
475  */
476  return true;
477 }
478 
486 bool
488  for (size_t i = 0; i < m_time_matrix.size(); ++i) {
489  for (size_t j = 0; j < m_time_matrix.size(); ++j) {
490  for (size_t k = 0; k < m_time_matrix.size(); ++k) {
491  if (m_time_matrix[i][k] > (m_time_matrix[i][j] + m_time_matrix[j][k])) {
492  return false;
493  }
494  }
495  }
496  }
497  return true;
498 }
499 
507 size_t
509  if (depth > m_time_matrix.size()) return depth;
510  for (auto & i : m_time_matrix) {
511  for (size_t j = 0; j < m_time_matrix.size(); ++j) {
512  for (size_t k = 0; k < m_time_matrix.size(); ++k) {
513  if (i[k] > (i[j] + m_time_matrix[j][k])) {
514  i[k] = i[j] + m_time_matrix[j][k];
515  return fix_triangle_inequality(++depth);
516  }
517  }
518  }
519  }
520  return depth;
521 }
522 
523 bool
525  for (size_t i = 0; i < m_time_matrix.size(); ++i) {
526  for (size_t j = 0; j < m_time_matrix.size(); ++j) {
527  if (0.000001 < std::fabs(m_time_matrix[i][j] - m_time_matrix[j][i])) {
528  std::ostringstream log;
529  log << "i \t" << i
530  << "j \t" << j
531  << "m_time_matrix[i][j] \t" << m_time_matrix[i][j]
532  << "m_time_matrix[j][i] \t" << m_time_matrix[j][i]
533  << "\n";
534  log << (*this);
535  pgassertwm(false, log.str());
536  return false;
537  }
538  }
539  }
540  return true;
541 }
542 
543 
567 std::ostream& operator<<(std::ostream &log, const Base_Matrix &matrix) {
568  /*
569  * print the identifiers
570  */
571  for (const auto id : matrix.m_ids) {
572  log << "\t" << id;
573  }
574  log << "\n";
575  size_t i = 0;
576 
577  /*
578  * Cycle the cells
579  */
580  for (const auto &row : matrix.m_time_matrix) {
581  size_t j = 0;
582  for (const auto cost : row) {
583  /*
584  * print the information
585  */
586  log << "Internal(" << i << "," << j << ")"
587  << "\tOriginal(" << matrix.m_ids[i] << "," << matrix.m_ids[j] << ")"
588  << "\t = " << cost
589  << "\n";
590  ++j;
591  }
592  ++i;
593  }
594  return log;
595 }
596 
597 
598 } // namespace base
599 } // namespace vrprouting
vrprouting::base::detail::get_distance
double get_distance(std::pair< Coordinate, Coordinate > p1, std::pair< Coordinate, Coordinate > p2)
Definition: base_matrix.cpp:51
vrprouting::base::Base_Matrix::get_original_id
Id get_original_id(Idx) const
original id -> idx
Definition: base_matrix.cpp:202
vrprouting::base::Base_Matrix::Base_Matrix
Base_Matrix()=default
Constructs an emtpy matrix.
vrprouting::base::Base_Matrix::get_index
Idx get_index(Id) const
original id -> idx
Definition: base_matrix.cpp:161
vrprouting::base::operator<<
std::ostream & operator<<(std::ostream &log, const Base_Matrix &matrix)
Definition: base_matrix.cpp:567
vrprouting::base::Base_Matrix::m_cost_matrix
std::vector< std::vector< TravelCost > > m_cost_matrix
the cost matrix for vroom
Definition: base_matrix.h:132
vrprouting::base::Base_Matrix::set_ids
void set_ids(const std::vector< Matrix_cell_t > &)
Traverses the matrix information to set the ids of the nodes.
Definition: base_matrix.cpp:85
pgassertwm
#define pgassertwm(expr, msg)
Adds a message to the assertion.
Definition: pgr_assert.h:118
vrprouting::base::Base_Matrix::get_vroom_duration_matrix
vroom::Matrix< vroom::Duration > get_vroom_duration_matrix() const
Get VROOM duration matrix from vrprouting Base Matrix.
Definition: base_matrix.cpp:404
pgassert
#define pgassert(expr)
Uses the standard assert syntax.
Definition: pgr_assert.h:95
Id
int64_t Id
Definition: typedefs.h:78
Identifiers::begin
const_iterator begin() const
Definition: identifiers.hpp:81
vroom_matrix_t.h
pgr_assert.h
An assert functionality that uses C++ throw().
vrprouting::base::Base_Matrix::has_no_infinity
bool has_no_infinity() const
does the matrix values not given by the user?
Definition: base_matrix.cpp:459
vrprouting::base::Base_Matrix::m_ids
std::vector< Id > m_ids
DATA.
Definition: base_matrix.h:120
vrprouting::base::Base_Matrix::fix_triangle_inequality
size_t fix_triangle_inequality(size_t depth=0)
Fix Triangle Inequality Theorem.
Definition: base_matrix.cpp:508
Vroom_matrix_t
Matrix's attributes.
Definition: vroom_matrix_t.h:46
Idx
uint64_t Idx
Definition: typedefs.h:79
Matrix_cell_t
traveling costs
Definition: matrix_cell_t.h:41
vrprouting::base::Base_Matrix::m_time_matrix
std::vector< std::vector< TInterval > > m_time_matrix
the actual time matrix
Definition: base_matrix.h:126
Identifiers::end
const_iterator end() const
Definition: identifiers.hpp:82
Duration
uint32_t Duration
Definition: typedefs.h:81
vrprouting::base::Base_Matrix
N x N matrix.
Definition: base_matrix.h:61
vrprouting::base::Base_Matrix::has_id
bool has_id(Id) const
has identifier
Definition: base_matrix.cpp:126
TInterval
int64_t TInterval
Definition: typedefs.h:72
Multiplier
double Multiplier
Definition: typedefs.h:77
base_matrix.h
vrprouting::base::Base_Matrix::is_symmetric
bool is_symmetric() const
is the matrix symetric?
Definition: base_matrix.cpp:524
vrprouting::base::Base_Matrix::get_vroom_cost_matrix
vroom::Matrix< vroom::Cost > get_vroom_cost_matrix() const
Get VROOM cost matrix from vrprouting Base Matrix.
Definition: base_matrix.cpp:421
identifiers.hpp
matrix_cell_t.h
Identifiers
Definition: identifiers.hpp:51
vrprouting::base::Base_Matrix::obeys_triangle_inequality
bool obeys_triangle_inequality() const
does the matrix obeys the triangle inequality?
Definition: base_matrix.cpp:487
vrprouting
Definition: base_matrix.cpp:46