26 #include <keplerian_toolbox/astro_constants.h>
27 #include <keplerian_toolbox/lambert_problem.h>
28 #include <keplerian_toolbox/core_functions/array3D_operations.h>
29 #include <keplerian_toolbox/core_functions/ic2par.h>
30 #include <keplerian_toolbox/epoch.h>
33 #include "../exceptions.h"
34 #include "../population.h"
38 namespace pagmo {
namespace problem {
51 const std::vector<kep_toolbox::planet::planet_ptr>& planets,
52 const std::vector<double>& values,
54 const std::vector<double>& epochs,
58 compute_dimensions(planets.size(), encoding)[0],
59 compute_dimensions(planets.size(), encoding)[1],
61 ), m_planets(planets), m_values(values), m_max_DV(max_DV), m_epochs(epochs), m_mu(planets[0]->get_mu_central_body()), m_DV(values.size() - 1)
63 if (planets.size() != values.size()){
64 pagmo_throw(value_error,
"Planet list must have the same size as values list");
66 if (planets.size() != epochs.size()){
67 pagmo_throw(value_error,
"Planet list must have the same size as times list");
69 if (planets.size() < 3 ){
70 pagmo_throw(value_error,
"Planet list must contain at least 3 elements");
73 for (
auto pl_ptr : m_planets)
75 if (pl_ptr->get_mu_central_body() != m_mu)
77 pagmo_throw(value_error,
"All planets in planet list must have the same gravity constant");
80 precompute_ephemerides();
94 double cum_p, ham_path_len;
95 decision_vector::size_type dumb1, dumb2;
115 ham_path_len = std::accumulate(m_DV.begin(), m_DV.end(), 0.0);
116 f[0] = -(cum_p + 1 - ham_path_len / (n_cities * m_max_DV * 10));
134 void tsp_ds::find_subsequence(
const decision_vector& tour,
double& retval_p,
double& retval_l, decision_vector::size_type& retval_it_l, decision_vector::size_type& retval_it_r,
const bool static_computations)
const
138 pagmo_throw(value_error,
"tour dimension must be equal to the number of planets");
143 decision_vector::size_type it_l = 0, it_r = 0;
144 bool cond_r =
true, cond_l =
true;
145 double cum_p = m_values[tour[0]];
146 double saved_length = m_max_DV;
150 retval_l = saved_length;
155 compute_DVs(tour, static_computations);
163 saved_length -= m_DV[it_r];
164 cum_p += m_values[tour[(it_r + 1)]];
168 if (saved_length < 0 || (it_l == it_r))
172 else if (cum_p > retval_p)
175 retval_l = saved_length;
179 else if (cum_p == retval_p)
181 if (saved_length > retval_l)
184 retval_l = saved_length;
190 if (it_r==n_cities-1)
203 saved_length += m_DV[it_l];
204 cum_p -= m_values[tour[it_l]];
207 if (saved_length > 0)
210 if (cum_p > retval_p)
213 retval_l = saved_length;
217 else if (cum_p == retval_p)
219 if (saved_length > retval_l)
222 retval_l = saved_length;
228 if (it_l == n_cities)
238 size_t tsp_ds::compute_idx(
const size_t i,
const size_t j,
const size_t n)
const
240 pagmo_assert( i!=j && i<n && j<n );
241 return i*(n-1) + j - (j>i? 1:0);
253 for (
size_t i = 0; i < n_cities; i++) {
256 for (
size_t j = 0; j < n_cities; j++) {
258 decision_vector::size_type rows = compute_idx(i, j, n_cities);
259 decision_vector::size_type cols = compute_idx(j, i, n_cities);
261 c[i+n_cities] += x[cols];
264 c[i+n_cities] = c[i+n_cities]-1;
270 size_t next_city = 0,current_city = 0;
271 std::vector<int> u(n_cities);
272 for (
size_t i = 0; i < n_cities; i++) {
273 u[current_city] = i+1;
274 for (
size_t j = 0; j < n_cities; j++)
276 if (current_city==j)
continue;
277 if (x[compute_idx(current_city, j, n_cities)] == 1)
283 current_city = next_city;
286 for (
size_t i = 1; i < n_cities; i++) {
287 for (
size_t j = 1; j < n_cities; j++)
290 c[2*n_cities+count] = u[i]-u[j] + (n_cities+1) * x[compute_idx(i, j, n_cities)] - n_cities;
300 std::vector<population::size_type> range(n_cities);
301 for (std::vector<population::size_type>::size_type i=0; i<range.size(); ++i)
305 c[0] = !std::is_permutation(x.begin(),x.end(),range.begin());
322 kep_toolbox::array6D elements1 = m_planets[i]->compute_elements();
323 kep_toolbox::array6D elements2 = m_planets[j]->compute_elements();
325 double a1 = elements1[0];
326 double i1 = elements1[2];
327 double W1 = elements1[3];
328 double e1 = elements1[1];
330 double a2 = elements2[0];
331 double i2 = elements2[2];
332 double W2 = elements2[3];
333 double e2 = elements2[1];
334 return three_impulses(a1,i1,W1,e1,a2,i2,W2,e2);
337 boost::array<int, 2> tsp_ds::compute_dimensions(decision_vector::size_type n_cities,
base_tsp::encoding_type encoding)
339 boost::array<int,2> retval;
342 retval[0] = n_cities*(n_cities-1)+2;
343 retval[1] = (n_cities-1)*(n_cities-2);
357 void tsp_ds::precompute_ephemerides()
const
359 kep_toolbox::array3D dumb0;
360 std::vector<kep_toolbox::array3D> dumb1(m_planets.size(),dumb0);
361 std::vector<std::vector<kep_toolbox::array3D> >dumb2(m_epochs.size(),dumb1);
365 kep_toolbox::array6D dumb3;
366 std::vector<kep_toolbox::array6D> dumb4(m_planets.size(),dumb3);
367 std::vector<std::vector<kep_toolbox::array6D> >dumb5(m_epochs.size(),dumb4);
370 for (
auto i = 0u; i < m_epochs.size(); ++i)
372 for (
auto j = 0u; j < m_planets.size(); ++j) {
375 m_planets[j]->eph(kep_toolbox::epoch(m_epochs[i], kep_toolbox::epoch::MJD2000), m_eph_r[i][j], m_eph_v[i][j]);
376 kep_toolbox::ic2par(m_eph_r[i][j], m_eph_v[i][j], m_mu, m_eph_el[i][j]);
380 std::cout << *m_planets[j] << std::endl;
381 std::cout <<
"At epoch: " << m_epochs[i] << std::endl;
382 std::cout <<
"planet idx: " << j << std::endl;
383 pagmo_throw(value_error,
"Ephemerides computations caused an error (planet above)");
390 void tsp_ds::compute_DVs(
const decision_vector& tour,
bool static_computations)
const
392 if (!static_computations)
396 m_DV[i] = distance_3_imp(tour[i], tour[(i + 1)], i);
401 m_DV[i] =
distance(tour[i], tour[(i + 1)]);
406 double tsp_ds::three_impulses(
double a1,
double i1,
double W1,
double e1,
double a2,
double i2,
double W2,
double e2)
const
409 double Vi,Vf, DV1,DV2;
412 double ra1 = a1 * (1. + e1);
414 double ra2 = a2 * (1. + e2);
416 double cosiREL = cos(i1) * cos(i2) + sin(i1) * sin(i2) * cos(W1) * cos(W2) + sin(i1) * sin(i2) * sin(W1) * sin(W2);
419 double rp2 = a2 * (1. - e2);
421 double rp1 = a1 * (1. - e1);
424 Vi = sqrt(m_mu * (2. / ra1 - 1. / a1));
425 Vf = sqrt(m_mu * (2. / ra1 - 2. / (rp2 + ra1)));
427 DV1 = sqrt(Vi * Vi + Vf * Vf - 2. * Vi * Vf * cosiREL);
429 DV2 = sqrt(m_mu) * abs(sqrt(2. / rp2 - 2. / (rp2 + ra1)) - sqrt(2. / rp2 - 2. / (rp2 + ra2)));
433 DV1 = sqrt(m_mu) * abs(sqrt(2. / rp1 - 2. / (rp1 + ra1)) - sqrt(2. / rp1 - 2. / (rp1 + ra2)));
434 Vi = sqrt(m_mu * (2. / ra2 - 2. / (rp1 + ra2)));
435 Vf = sqrt(m_mu * (2. / ra2 - 1. / a2));
437 DV2 = sqrt(abs(Vi * Vi + Vf * Vf - 2 * Vi * Vf * cosiREL));
452 double tsp_ds::distance_3_imp(
const decision_vector::size_type dep,
const decision_vector::size_type arr,
const size_t ep_idx)
const
455 return three_impulses(m_eph_el[ep_idx][dep][0], m_eph_el[ep_idx][dep][2], m_eph_el[ep_idx][dep][3], m_eph_el[ep_idx][dep][1], m_eph_el[ep_idx][arr][0], m_eph_el[ep_idx][arr][2], m_eph_el[ep_idx][arr][3], m_eph_el[ep_idx][arr][1]);
508 return "Debris Selection TSP (TSP-DS)";
517 std::ostringstream oss;
518 oss <<
"\n\tNumber of planets: " <<
get_n_cities() <<
'\n';
519 oss <<
"\tEncoding: ";
522 oss <<
"FULL" <<
'\n';
525 oss <<
"RANDOMKEYS" <<
'\n';
528 oss <<
"CITIES" <<
'\n';
531 oss <<
"\tObjects Names: " << std::endl <<
"\t\t[";
532 for (
auto i = 0u; i < m_planets.size(); ++i)
534 oss << m_planets[i]->get_name() <<
", ";
538 oss <<
"]" << std::endl <<
"\tEpochs: " << m_epochs <<
"\n";
539 oss <<
"\ttObjects Values: " << m_values << std::endl;
540 oss <<
"\tSpacecraft DV: " << m_max_DV <<
" [m/s]\n";
boost::shared_ptr< base > base_ptr
Alias for shared pointer to base problem.
std::vector< double > decision_vector
Decision vector type.
std::string human_readable_extra() const
Extra human readable info for the problem.
const decision_vector & get_epochs() const
Getter for m_times.
void find_subsequence(const decision_vector &, double &, double &, decision_vector::size_type &, decision_vector::size_type &, const bool=false) const
Given an hamiltonian path finds the best subtour.
const std::vector< double > & get_values() const
Getter for m_values.
pagmo::decision_vector full2cities(const pagmo::decision_vector &) const
From FULL to CITIES encoding.
As a vector of doubles in [0,1].
decision_vector::size_type get_n_cities() const
Getter for m_n_cities.
double get_max_DV() const
Getter for m_max_DV.
encoding_type
Mechanism used to encode the sequence of vertices to be visited.
std::vector< double > fitness_vector
Fitness vector type.
std::vector< double > constraint_vector
Constraint vector type.
std::string get_name() const
Getter for m_eph_el.
const std::vector< kep_toolbox::planet::planet_ptr > & get_planets() const
Getter for m_planets.
tsp_ds(const std::vector< kep_toolbox::planet::planet_ptr > &planets={kep_toolbox::planet::jpl_lp("venus").clone(), kep_toolbox::planet::jpl_lp("earth").clone(), kep_toolbox::planet::jpl_lp("mars").clone()}, const std::vector< double > &values={1., 1., 1.}, const double max_DV=30000, const std::vector< double > &epochs={1200, 1550, 1940}, const base_tsp::encoding_type &encoding=CITIES)
Constructor.
As a matrix with ones and zeros.
Base TSP (Travelling Salesman Problem).
The TSP - Debris Selection Problem.
As a sequence of cities ids.
pagmo::decision_vector randomkeys2cities(const pagmo::decision_vector &) const
From RANDOMKEYS to CITIES encoding.
encoding_type get_encoding() const
Getter for m_encoding.
double distance(decision_vector::size_type, decision_vector::size_type) const
Computation of the phaseless distance between two planets.
base_ptr clone() const
Copy constructor for polymorphic objects.