Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion R/clarke_wright.R
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@
#' * `site` - The site index (i.e. the index of the (1-indexed) `demand` vector)
#' associated to the run.
#' * `order` - Integer values providing the visiting order within each run.
#' * `load` - The departing load on site `site` in units of `demand` per particular run.
#' * `load` - The load after visiting site `site` in units of `demand` per particular run.
#'
#'
#' Unless a site demand exceeds the vehicle capacities it is always assigned
Expand Down
4 changes: 2 additions & 2 deletions src/Makefile.debug
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
debug: clarke_wright.cpp fleet.cpp cpp11.cpp distmat.cpp run.cpp router.cpp tsp_greedy.cpp
debug: clarke_wright.cpp fleet.cpp cpp11.cpp symmat.cpp run.cpp router.cpp tsp_greedy.cpp
g++ -std=gnu++17 -I. \
-fstack-protector-strong -fstack-clash-protection -Wformat -fcf-protection \
-Wdate-time -Wall -pedantic -Wformat-security -g -O0 -fdiagnostics-color=always \
-fsanitize=address,undefined \
clarke_wright.cpp fleet.cpp distmat.cpp run.cpp router.cpp tsp_greedy.cpp \
clarke_wright.cpp fleet.cpp symmat.cpp run.cpp router.cpp tsp_greedy.cpp \
-o debug
159 changes: 58 additions & 101 deletions src/clarke_wright.cpp
Original file line number Diff line number Diff line change
@@ -1,15 +1,17 @@
#include <iterator>
#include <vector>
#include <functional>
#include "router.h"
#include "symmat.h"
#include <cassert>

// selects demand with a given sign, and always returns positive values
std::tuple<std::vector<int>, std::vector<double>, distmat<double>>
select_demand(const std::vector<double> &demand, const distmat<double> &distm, int sign)
std::tuple<std::vector<int>, std::vector<double>, Distmat>
select_demand(const std::vector<double> &demand, const Distmat &distm, int sign)
{
std::vector<int> new_ind;
std::vector<double> new_demand;
distmat<double> new_distm;
Distmat new_distm;

new_ind.reserve(demand.size());
new_demand.reserve(demand.size());
Expand Down Expand Up @@ -37,7 +39,7 @@ select_demand(const std::vector<double> &demand, const distmat<double> &distm, i
new_distm = distm.sub(new_ind_dist);
}

return std::tuple<std::vector<int>, std::vector<double>, distmat<double>>(new_ind, new_demand, new_distm);
return std::tuple<std::vector<int>, std::vector<double>, Distmat>(new_ind, new_demand, new_distm);
}

tbls cpp_clarke_wright(
Expand All @@ -60,7 +62,7 @@ tbls cpp_clarke_wright(
}

auto fleet = std::make_shared<Fleet>(n_res, capacities, restricted_vehicles);
distmat<double> distm(distances);
Distmat distm(distances);

// we can have positive and negative demands
// positive = sites are sinks and origin is source
Expand All @@ -69,112 +71,55 @@ tbls cpp_clarke_wright(
// Strategy:
// Consider and solve positive and negative demands separately (we can use the same solver)
// Combine those solutions afterwards
/*
bool have_pos = false;
bool have_neg = false;

bool have_pos = false;
bool have_neg = false;

for (size_t i = 0; i < demand.size(); i++)
{
if (demand[i] > 0)
for (size_t i = 0; i < demand.size(); i++)
{
have_pos = true;
}
if (demand[i] < 0)
{
have_neg = true;
}
if (have_pos && have_neg)
{
break;
if (demand[i] > 0)
{
have_pos = true;
}
if (demand[i] < 0)
{
have_neg = true;
}
if (have_pos && have_neg)
{
break;
}
}
}

*/
/* Positive */
/*
std::vector<int> ind_pos;
std::vector<double> demand_pos;
distmat<double> distances_pos;

std::vector<int> ind_pos;
std::vector<double> demand_pos;
distmat<double> distances_pos;

if (have_pos)
{
std::tie(ind_pos, demand_pos, distances_pos) =
select_demand(demand, distm, 1);
}

Router runm_pos(
demand_pos,
std::make_unique<distmat<double>>(distances_pos),
fleet);

if (have_pos)
{
callback(runm_pos);
while (runm_pos.relink_best())
{
callback(runm_pos);
};
while (runm_pos.opt_vehicles())
{
};

if (!have_neg)
if (have_pos)
{
return (runm_pos.runs_as_tbls(demand_pos));
std::tie(ind_pos, demand_pos, distances_pos) =
select_demand(demand, distm, 1);
}
}

/* Negative */

std::vector<int> ind_neg;
std::vector<double> demand_neg;
distmat<double> distances_neg;

if (have_neg)
{
std::tie(ind_neg, demand_neg, distances_neg) =
select_demand(demand, distm, -1);
}

Router runm_neg(demand_neg,
std::make_unique<distmat<double>>(distances_neg),
fleet);

if (have_neg)
{
callback(runm_neg);
while (runm_neg.relink_best())
{
callback(runm_neg);
};

while (runm_neg.opt_vehicles())
{
};

if (!have_pos)
{
for (auto &dmnd : demand_neg)
{
dmnd = -dmnd;
}
return (runm_neg.runs_as_tbls(demand_neg));
}
}
*/

// if we have both, combine then and optimize again
Router runm_all(runm_pos, runm_neg, distm, ind_pos, ind_neg);
Router router(
std::make_shared<std::vector<double>>(demand),
std::make_unique<Distmat>(distm), fleet);

callback(runm_all);
while (runm_all.relink_best([](double l1, double l2)
{ return (std::max(l1, l2)); }))
callback(router);
while (router.relink_best())
{
callback(runm_all);
callback(router);
};
while (runm_all.opt_vehicles())
while (router.optimize_vehicles())
{
};
// router.optimize_runs_order();

return (runm_all.runs_as_tbls(demand));
return (router.runs_as_tbls());
}

#ifndef NDEBUG
Expand All @@ -183,10 +128,10 @@ int main()
{
tbls cols =
cpp_clarke_wright(
std::vector<double>{-3, -2, 1, 2},
std::vector<double>{5, 10, 5, 4, 5, 2, 12, 13, 10, 3},
std::vector<int>{100},
std::vector<double>{5},
std::vector<double>{14.14, 14.37, 7.86},
std::vector<double>{8.128214, 7.837354, 3.162988, 12.616152, 6.427298, 10.7306495},
std::vector<int>{2, 100},
std::vector<double>{33, 44},
std::vector<int>{},
std::vector<int>{});

Expand All @@ -203,4 +148,16 @@ int main()

return 0;
}
#endif
#endif


/*
> demand
[1] 14.148060 14.370754 7.861395
> pos
pos_x pos_y
1 0.000000 0.000000
2 6.608953 4.731766
3 2.834910 -7.306668
4 0.381919 3.139846
*/
34 changes: 14 additions & 20 deletions src/fleet.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,21 +9,16 @@ int Fleet::capacity(const int vehicle) const
return vehicle_caps[vehicle];
}

void Fleet::release_vehicle(const int vehicle)
void Fleet::release_vehicle(const VehicleTypeID vehicle)
{
if (vehicle_avail[vehicle] < INT_MAX)
{
vehicle_avail[vehicle] += 1;
}
}

void Fleet::reserve_vehicle(const int vehicle)
void Fleet::reserve_vehicle(const VehicleTypeID vehicle)
{
if (vehicle == -1)
{
throw std::runtime_error("blah.");
}

if (vehicle_avail[vehicle] <= 0)
{
throw std::runtime_error("No available vehicles of this type to pop.");
Expand All @@ -36,30 +31,29 @@ void Fleet::reserve_vehicle(const int vehicle)
}

template <typename ForwardIt>
bool Fleet::is_vehicle_restricted(const int vehicle, ForwardIt sites) const
bool Fleet::is_vehicle_restricted(const VehicleTypeID vehicle, ForwardIt sites) const
{
bool restricted = false;

for (const auto site : sites)
{
restricted = restricted ||
(this->restricted_vehicles[site].find(vehicle) !=
this->restricted_vehicles[site].end());
if (this->restricted_vehicles[site].find(vehicle) != this->restricted_vehicles[site].end())
{
return true;
}
}

return restricted;
return false;
}

template <typename ForwardIt>
int Fleet::find_fitting_vehicle(ForwardIt sites, const double max_load, bool max_load_soft) const
std::optional<VehicleTypeID> Fleet::find_fitting_vehicle(ForwardIt sites, const double max_load, bool max_load_soft) const
{
for (size_t vehicle = 0; vehicle < vehicle_caps.size(); vehicle++)
{
if (vehicle_avail[vehicle] >= 1 &&
max_load <= vehicle_caps[vehicle] &&
!is_vehicle_restricted(vehicle, sites))
{
return vehicle;
return (VehicleTypeID)vehicle;
}
}

Expand All @@ -71,13 +65,13 @@ int Fleet::find_fitting_vehicle(ForwardIt sites, const double max_load, bool max
if (vehicle_avail[vehicle] >= 1 &&
!is_vehicle_restricted(vehicle, sites))
{
return vehicle;
return (VehicleTypeID)vehicle;
}
}
}

return -1;
return std::nullopt;
}

template int Fleet::find_fitting_vehicle(union_view<int, std::unordered_set>, const double, bool) const;
template int Fleet::find_fitting_vehicle(std::unordered_set<int>, const double, bool) const;
template std::optional<VehicleTypeID> Fleet::find_fitting_vehicle(union_view<int, std::list>, const double, bool) const;
template std::optional<VehicleTypeID> Fleet::find_fitting_vehicle(std::list<int>, const double, bool) const;
18 changes: 12 additions & 6 deletions src/fleet.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,11 @@
#define FLEET_H

#include <vector>
#include <list>
#include <unordered_set>
#include <optional>

typedef int VehicleTypeID;

class Fleet
{
Expand All @@ -12,14 +16,16 @@ class Fleet
: vehicle_avail(vehicle_avail),
vehicle_caps(vehicle_caps),
restricted_vehicles(restricted_vehicles) {};
void reserve_vehicle(const int vehicle);
void release_vehicle(const int vehicle);
void reserve_vehicle(const VehicleTypeID vehicle);
void release_vehicle(const VehicleTypeID vehicle);

template <typename ForwardIt>
int find_fitting_vehicle(ForwardIt sites, const double max_load,
bool max_load_soft) const;
std::optional<VehicleTypeID> find_fitting_vehicle(
ForwardIt sites,
const double max_load,
bool max_load_soft) const;

int capacity(const int vehicle) const;
int capacity(const VehicleTypeID vehicle) const;

private:
// Number and capacity of particular vehicle types
Expand All @@ -30,7 +36,7 @@ class Fleet
std::vector<std::unordered_set<int>> restricted_vehicles;

template <typename ForwardIt>
bool is_vehicle_restricted(int vehicle, ForwardIt sites) const;
bool is_vehicle_restricted(const VehicleTypeID vehicle, ForwardIt sites) const;
};

#endif
9 changes: 5 additions & 4 deletions src/r_clarke_wright.cpp
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
#include <cpp11.hpp>
#include <iterator>
#include <vector>
#include "runmanager.h"
#include "router.h"
#include <functional>

using namespace cpp11;

Expand Down Expand Up @@ -38,7 +39,7 @@ tbls cpp_clarke_wright(
const std::vector<double> &capacities,
const std::vector<int> &restr_sites,
const std::vector<int> &restr_vehicles,
std::function<void(RunManager &)> callback = [](RunManager &) {});
std::function<void(Router &)> callback = [](Router &) {});

[[cpp11::register]]
cpp11::writable::list r_cpp_clarke_wright(
Expand Down Expand Up @@ -77,8 +78,8 @@ list cpp_clarke_wright_stepwise(
capacities,
restr_sites,
restr_vehicles,
[&steps, &demand](RunManager &runm)
{ steps.push_back(tbls_to_dfs(runm.runs_as_tbls(demand))); });
[&steps, &demand](Router &router)
{ steps.push_back(tbls_to_dfs(router.runs_as_tbls())); });

return steps;
}
Loading
Loading