PaGMO  1.1.5
tsp_vrplc.cpp
1 /*****************************************************************************
2  * Copyright (C) 2004-2014 The PaGMO development team, *
3  * Advanced Concepts Team (ACT), European Space Agency (ESA) *
4  * *
5  * https://github.com/esa/pagmo *
6  * *
7  * act@esa.int *
8  * *
9  * This program is free software; you can redistribute it and/or modify *
10  * it under the terms of the GNU General Public License as published by *
11  * the Free Software Foundation; either version 2 of the License, or *
12  * (at your option) any later version. *
13  * *
14  * This program is distributed in the hope that it will be useful, *
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
17  * GNU General Public License for more details. *
18  * *
19  * You should have received a copy of the GNU General Public License *
20  * along with this program; if not, write to the *
21  * Free Software Foundation, Inc., *
22  * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
23  *****************************************************************************/
24 
25 #include "tsp_vrplc.h"
26 #include "../population.h"
27 
28 namespace pagmo { namespace problem {
29 
31 
35  tsp_vrplc::tsp_vrplc() : base_tsp(3, 0, 0 , base_tsp::RANDOMKEYS), m_weights(), m_capacity(1.1)
36  {
37  std::vector<double> dumb(3,0);
38  m_weights = std::vector<std::vector<double> > (3,dumb);
39  m_weights[0][1] = 1;
40  m_weights[0][2] = 1;
41  m_weights[2][1] = 1;
42  m_weights[1][0] = 1;
43  m_weights[2][0] = 1;
44  m_weights[1][2] = 1;
45  }
46 
48 
54  tsp_vrplc::tsp_vrplc(const std::vector<std::vector<double> >& weights, const base_tsp::encoding_type& encoding, const double& capacity):
55  base_tsp(weights.size(),
56  compute_dimensions(weights.size(), encoding)[0],
57  compute_dimensions(weights.size(), encoding)[1],
58  encoding
59  ), m_weights(weights), m_capacity(capacity)
60  {
61  if (m_capacity <= 0)
62  {
63  pagmo_throw(value_error, "Maximum vehicle capacity needs to be strictly positive");
64  }
65  check_weights(m_weights);
66  }
67 
70  {
71  return base_ptr(new tsp_vrplc(*this));
72  }
73 
75 
83  void tsp_vrplc::check_weights(const std::vector<std::vector<double> > &matrix) const
84  {
85  decision_vector::size_type n_cols = matrix.size();
86 
87  for (decision_vector::size_type i = 0; i < n_cols; ++i) {
88  decision_vector::size_type n_rows = matrix.at(i).size();
89  // check if the matrix is square
90  if (n_rows != n_cols)
91  pagmo_throw(value_error, "adjacency matrix is not square");
92 
93  for (size_t j = 0; j < n_rows; ++j) {
94  if (i == j && matrix.at(i).at(j) != 0)
95  pagmo_throw(value_error, "main diagonal elements must all be zeros.");
96  if (i != j && !matrix.at(i).at(j)) // fully connected
97  pagmo_throw(value_error, "adjacency matrix contains zero values.");
98  if (i != j && (!matrix.at(i).at(j)) == matrix.at(i).at(j)) // fully connected
99  pagmo_throw(value_error, "adjacency matrix contains NaN values.");
100  }
101  }
102  }
103 
104  boost::array<int, 2> tsp_vrplc::compute_dimensions(decision_vector::size_type n_cities, base_tsp::encoding_type encoding)
105  {
106  boost::array<int,2> retval;
107  switch( encoding ) {
108  case FULL:
109  retval[0] = n_cities*(n_cities-1)+2;
110  retval[1] = (n_cities-1)*(n_cities-2);
111  break;
112  case RANDOMKEYS:
113  retval[0] = 0;
114  retval[1] = 0;
115  break;
116  case CITIES:
117  retval[0] = 1;
118  retval[1] = 0;
119  break;
120  }
121  return retval;
122  }
123 
124  void tsp_vrplc::objfun_impl(fitness_vector &f, const decision_vector& x) const
125  {
126  f[0] = 1;
127  double stl = 0;
128  decision_vector tour;
129  decision_vector::size_type n_cities = get_n_cities();
130  switch( get_encoding() ) {
131  case FULL:
132  {
133  tour = full2cities(x);
134  break;
135  }
136  case RANDOMKEYS:
137  {
138  tour = randomkeys2cities(x);
139  break;
140  }
141  case CITIES:
142  {
143  tour = x;
144  break;
145  }
146  }
147  for (decision_vector::size_type i=0; i<n_cities-1; ++i) {
148  stl += m_weights[tour[i]][tour[i+1]];
149  if(stl > m_capacity)
150  {
151  stl = 0;
152  f[0] += 1;
153  }
154  else
155  {
156  f[0] += (m_weights[tour[i]][tour[i+1]])/(n_cities*m_capacity);
157  }
158  }
159  return;
160  }
161 
163 
169  std::vector<std::vector<double> > tsp_vrplc::return_tours(const decision_vector& x) const
170  {
171  std::vector<std::vector<double> > tours;
172  double stl = 0;
173  decision_vector::size_type n_cities = get_n_cities();
174  std::vector<double> cur_tour;
175  for (decision_vector::size_type i=0; i<n_cities-1; ++i)
176  {
177  cur_tour.push_back(x[i]);
178  stl += m_weights[x[i]][x[i+1]];
179  if(stl > m_capacity)
180  {
181  stl = 0;
182  tours.push_back(cur_tour);
183  cur_tour.erase(cur_tour.begin(),cur_tour.end());
184  }
185  }
186  cur_tour.push_back(x[n_cities-1]);
187  tours.push_back(cur_tour);
188  return tours;
189  }
190 
191 
192  size_t tsp_vrplc::compute_idx(const size_t i, const size_t j, const size_t n) const
193  {
194  pagmo_assert( i!=j && i<n && j<n );
195  return i*(n-1) + j - (j>i? 1:0);
196  }
197 
198  void tsp_vrplc::compute_constraints_impl(constraint_vector &c, const decision_vector& x) const
199  {
200  decision_vector::size_type n_cities = get_n_cities();
201 
202  switch( get_encoding() )
203  {
204  case FULL:
205  {
206  // 1 - We set the equality constraints
207  for (size_t i = 0; i < n_cities; i++) {
208  c[i] = 0;
209  c[i+n_cities] = 0;
210  for (size_t j = 0; j < n_cities; j++)
211  {
212  if(i==j) continue; // ignoring main diagonal
213  decision_vector::size_type rows = compute_idx(i, j, n_cities);
214  decision_vector::size_type cols = compute_idx(j, i, n_cities);
215  c[i] += x[rows];
216  c[i+n_cities] += x[cols];
217  }
218  c[i] = c[i]-1;
219  c[i+n_cities] = c[i+n_cities]-1;
220  }
221 
222  //2 - We set the inequality constraints
223  //2.1 - First we compute the uj (see http://en.wikipedia.org/wiki/Travelling_salesman_problem#Integer_linear_programming_formulation)
224  // we start always out tour from the first city, without loosing generality
225  size_t next_city = 0,current_city = 0;
226  std::vector<int> u(n_cities);
227  for (size_t i = 0; i < n_cities; i++)
228  {
229  u[current_city] = i+1;
230  for (size_t j = 0; j < n_cities; j++)
231  {
232  if (current_city==j) continue;
233  if (x[compute_idx(current_city, j, n_cities)] == 1)
234  {
235  next_city = j;
236  break;
237  }
238  }
239  current_city = next_city;
240  }
241  int count=0;
242  for (size_t i = 1; i < n_cities; i++) {
243  for (size_t j = 1; j < n_cities; j++)
244  {
245  if (i==j) continue;
246  c[2*n_cities+count] = u[i]-u[j] + (n_cities+1) * x[compute_idx(i, j, n_cities)] - n_cities;
247  count++;
248  }
249  }
250  break;
251  }
252  case RANDOMKEYS:
253  break;
254  case CITIES:
255  {
256  std::vector<population::size_type> range(n_cities);
257  for (std::vector<population::size_type>::size_type i=0; i<range.size(); ++i)
258  {
259  range[i]=i;
260  }
261  c[0] = !std::is_permutation(x.begin(),x.end(),range.begin());
262  break;
263  }
264  }
265  return;
266  }
267 
269  double tsp_vrplc::distance(decision_vector::size_type i, decision_vector::size_type j) const
270  {
271  return m_weights[i][j];
272  }
273 
275 
278  const std::vector<std::vector<double> >& tsp_vrplc::get_weights() const
279  {
280  return m_weights;
281  }
282 
284 
287  const double& tsp_vrplc::get_capacity() const
288  {
289  return m_capacity;
290  }
291 
293  std::string tsp_vrplc::get_name() const
294  {
295  return "Vehicle Routing Problem with Limited Vehicle Capacity";
296  }
297 
299 
302  std::string tsp_vrplc::human_readable_extra() const
303  {
304  std::ostringstream oss;
305  oss << "\n\tNumber of cities: " << get_n_cities() << '\n';
306  oss << "\tEncoding: ";
307  switch( get_encoding() ) {
308  case FULL:
309  oss << "FULL" << '\n';
310  break;
311  case RANDOMKEYS:
312  oss << "RANDOMKEYS" << '\n';
313  break;
314  case CITIES:
315  oss << "CITIES" << '\n';
316  break;
317  }
318  oss << "\tMaximum vehicle capacity: " << m_capacity << std::endl;
319  oss << "\tWeight Matrix: \n";
320  for (decision_vector::size_type i=0; i<get_n_cities() ; ++i)
321  {
322  oss << "\t\t" << m_weights.at(i) << '\n';
323  if (i>5)
324  {
325  oss << "\t\t..." << '\n';
326  break;
327  }
328  }
329  return oss.str();
330  }
331 
332 
333 }} //namespaces
334 
335 BOOST_CLASS_EXPORT_IMPLEMENT(pagmo::problem::tsp_vrplc)
Root PaGMO namespace.
boost::shared_ptr< base > base_ptr
Alias for shared pointer to base problem.
Definition: problem/base.h:62
std::vector< double > decision_vector
Decision vector type.
Definition: types.h:40
A static Travelling Salesman Problem.
Definition: tsp_vrplc.h:47
std::vector< std::vector< double > > return_tours(const decision_vector &x) const
Returns the tours.
Definition: tsp_vrplc.cpp:169
base_ptr clone() const
Copy constructor for polymorphic objects (deep copy)
Definition: tsp_vrplc.cpp:69
pagmo::decision_vector full2cities(const pagmo::decision_vector &) const
From FULL to CITIES encoding.
Definition: base_tsp.cpp:74
std::string get_name() const
Returns the problem name.
Definition: tsp_vrplc.cpp:293
As a vector of doubles in [0,1].
Definition: base_tsp.h:69
decision_vector::size_type get_n_cities() const
Getter for m_n_cities.
Definition: base_tsp.cpp:193
const std::vector< std::vector< double > > & get_weights() const
Getter for m_weights.
Definition: tsp_vrplc.cpp:278
encoding_type
Mechanism used to encode the sequence of vertices to be visited.
Definition: base_tsp.h:68
double distance(decision_vector::size_type, decision_vector::size_type) const
Definition of the distance function.
Definition: tsp_vrplc.cpp:269
std::vector< double > fitness_vector
Fitness vector type.
Definition: types.h:42
std::vector< double > constraint_vector
Constraint vector type.
Definition: types.h:44
tsp_vrplc()
Default constructor.
Definition: tsp_vrplc.cpp:35
std::string human_readable_extra() const
Extra human readable info for the problem.
Definition: tsp_vrplc.cpp:302
const double & get_capacity() const
Getter for m_capacity.
Definition: tsp_vrplc.cpp:287
As a matrix with ones and zeros.
Definition: base_tsp.h:70
Base TSP (Travelling Salesman Problem).
Definition: base_tsp.h:64
As a sequence of cities ids.
Definition: base_tsp.h:71
pagmo::decision_vector randomkeys2cities(const pagmo::decision_vector &) const
From RANDOMKEYS to CITIES encoding.
Definition: base_tsp.cpp:127
encoding_type get_encoding() const
Getter for m_encoding.
Definition: base_tsp.cpp:184