-
Notifications
You must be signed in to change notification settings - Fork 48
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
adding multiple capacity vehicle capability #29
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,7 +2,7 @@ | |
#define NODE_OR_TOOLS_ADAPTORS_F1FF74E9681C_H | ||
|
||
#include <nan.h> | ||
|
||
#include <iostream> | ||
#include "types.h" | ||
|
||
// We adapt matrices and vectors for or-tools since it expects them to have specific signatures and types. | ||
|
@@ -134,11 +134,30 @@ template <typename Vector> inline auto makeVectorFromJsNumberArray(v8::Local<v8: | |
|
||
if (!num->IsNumber()) | ||
throw std::runtime_error{"Expected array element of types Number"}; | ||
|
||
//std::cout<<"hello"<<std::endl; | ||
vec.at(atIdx) = Nan::To<std::int32_t>(num).FromJust(); | ||
} | ||
|
||
return vec; | ||
} | ||
|
||
// our function for changing js array into vector of long long int | ||
|
||
template <typename Vector> inline auto makeVectorFromJsNumberArray1(v8::Local<v8::Array> array) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why is this function needed? |
||
const int64 len = array->Length(); | ||
|
||
Vector vec(len); | ||
|
||
for (int64 atIdx = 0; atIdx < len; ++atIdx) { | ||
auto num = Nan::Get(array, atIdx).ToLocalChecked(); | ||
|
||
if (!num->IsNumber()) | ||
throw std::runtime_error{"Expected array element of types Number"}; | ||
//std::cout<<"hello"<<std::endl; | ||
vec.at(atIdx) = Nan::To<int64_t>(num).FromJust(); | ||
} | ||
|
||
return vec; | ||
} | ||
|
||
#endif |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -10,33 +10,40 @@ | |
#include <utility> | ||
#include <vector> | ||
|
||
struct TSPWorker final : Nan::AsyncWorker { | ||
using Base = Nan::AsyncWorker; | ||
struct TSPWorker final { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why did you remove this and no longer initialize the base class below? The base class already stores the callback, there should be no need to store it here. |
||
|
||
TSPWorker(std::shared_ptr<const CostMatrix> costs_, Nan::Callback* callback, const RoutingModelParameters& modelParams_, | ||
const RoutingSearchParameters& searchParams_, std::int32_t numNodes, std::int32_t numVehicles, | ||
std::int32_t vehicleDepot) | ||
: Base(callback), costs{std::move(costs_)}, model{numNodes, numVehicles, NodeIndex{vehicleDepot}, modelParams_}, | ||
modelParams{modelParams_}, searchParams{searchParams_} {} | ||
: mCallback(callback), costs{std::move(costs_)}, model{numNodes, numVehicles, NodeIndex{vehicleDepot}, modelParams_}, | ||
modelParams{modelParams_}, searchParams{searchParams_} | ||
{ | ||
Execute(); | ||
} | ||
|
||
void Execute() override { | ||
void Execute() { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please inherit from the NAN AsyncWorker and keep the overrides here and below. |
||
auto costAdaptor = makeBinaryAdaptor(*costs); | ||
auto costEvaluator = makeCallback(costAdaptor); | ||
|
||
model.SetArcCostEvaluatorOfAllVehicles(costEvaluator); | ||
|
||
const auto* assignment = model.SolveWithParameters(searchParams); | ||
|
||
if (!assignment || (model.status() != RoutingModel::Status::ROUTING_SUCCESS)) | ||
SetErrorMessage("Unable to find a solution"); | ||
std::string jsError; | ||
if (!assignment || (model.status() != RoutingModel::Status::ROUTING_SUCCESS)) { | ||
jsError = "Unable to find a solution"; | ||
} | ||
|
||
model.AssignmentToRoutes(*assignment, &routes); | ||
|
||
if (routes.size() != 1) | ||
SetErrorMessage("Expected route for one vehicle"); | ||
if (routes.size() != 1) { | ||
jsError = "Expected route for one vehicle"; | ||
} | ||
|
||
HandleOKCallback(jsError); | ||
} | ||
|
||
void HandleOKCallback() override { | ||
void HandleOKCallback(std::string jsError) { | ||
Nan::HandleScope scope; | ||
|
||
const auto& route = routes.front(); | ||
|
@@ -47,9 +54,10 @@ struct TSPWorker final : Nan::AsyncWorker { | |
(void)Nan::Set(jsRoute, j, Nan::New<v8::Number>(route[j].value())); | ||
|
||
const auto argc = 2u; | ||
v8::Local<v8::Value> argv[argc] = {Nan::Null(), jsRoute}; | ||
v8::Local<v8::String> errorStr = v8::String::NewFromUtf8(v8::Isolate::GetCurrent(), jsError.c_str()); | ||
v8::Local<v8::Value> argv[argc] = {errorStr, jsRoute}; | ||
|
||
callback->Call(argc, argv); | ||
mCallback->Call(argc, argv); | ||
} | ||
|
||
std::shared_ptr<const CostMatrix> costs; // inc ref count to keep alive for async cb | ||
|
@@ -58,6 +66,7 @@ struct TSPWorker final : Nan::AsyncWorker { | |
RoutingModelParameters modelParams; | ||
RoutingSearchParameters searchParams; | ||
|
||
Nan::Callback* mCallback; | ||
// Stores solution until we can translate back to v8 objects | ||
std::vector<std::vector<NodeIndex>> routes; | ||
}; | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -25,7 +25,7 @@ struct VRPSearchParams { | |
std::int32_t numVehicles; | ||
std::int32_t depotNode; | ||
std::int32_t timeHorizon; | ||
std::int32_t vehicleCapacity; | ||
std::vector<int64> vehicleCapacity; // type changed to vector | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. remove comment |
||
|
||
RouteLocks routeLocks; | ||
|
||
|
@@ -40,8 +40,8 @@ inline auto makeTimeWindowsFrom2dArray(std::int32_t n, v8::Local<v8::Array> arra | |
if (n < 0) | ||
throw std::runtime_error{"Negative size"}; | ||
|
||
if (static_cast<std::int32_t>(array->Length()) != n) | ||
throw std::runtime_error{"Array dimension do not match size"}; | ||
// if (static_cast<std::int32_t>(array->Length()) != n) | ||
// throw std::runtime_error{"Array dimension do not match size"}; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why commented out? |
||
|
||
TimeWindows timeWindows(n); | ||
|
||
|
@@ -78,8 +78,8 @@ inline auto makeRouteLocksFrom2dArray(std::int32_t n, v8::Local<v8::Array> array | |
if (n < 0) | ||
throw std::runtime_error{"Negative size"}; | ||
|
||
if (static_cast<std::int32_t>(array->Length()) != n) | ||
throw std::runtime_error{"Array dimension do not match size"}; | ||
// if (static_cast<std::int32_t>(array->Length()) != n) | ||
// throw std::runtime_error{"Array dimension do not match size"}; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why commented out? |
||
|
||
// Note: use (n) for construction because RouteLocks is a weak alias to a std::vector. | ||
// Using vec(n) creates a vector of n items, using vec{n} creates a vector with a single element n. | ||
|
@@ -130,6 +130,13 @@ VRPSolverParams::VRPSolverParams(const Nan::FunctionCallbackInfo<v8::Value>& inf | |
auto timeWindowsVectorOk = !maybeTimeWindowsVector.IsEmpty() && maybeTimeWindowsVector.ToLocalChecked()->IsArray(); | ||
auto demandMatrixOk = !maybeDemandMatrix.IsEmpty() && maybeDemandMatrix.ToLocalChecked()->IsArray(); | ||
|
||
|
||
if(!numNodesOk ) throw std::runtime_error{"ERROR TYPE 1"}; | ||
else if(!costMatrixOk) throw std::runtime_error{"ERROR TYPE 2"}; | ||
else if(!durationMatrixOk) throw std::runtime_error{"ERROR TYPE 3"}; | ||
else if(!timeWindowsVectorOk) throw std::runtime_error{"ERROR TYPE 4"}; | ||
else if(!demandMatrixOk) throw std::runtime_error{"ERROR TYPE 5"}; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What's going on here? |
||
|
||
if (!numNodesOk || !costMatrixOk || !durationMatrixOk || !timeWindowsVectorOk || !demandMatrixOk) | ||
throw std::runtime_error{"SolverOptions expects" | ||
" 'numNodes' (Number)," | ||
|
@@ -170,7 +177,7 @@ VRPSearchParams::VRPSearchParams(const Nan::FunctionCallbackInfo<v8::Value>& inf | |
auto numVehiclesOk = !maybeNumVehicles.IsEmpty() && maybeNumVehicles.ToLocalChecked()->IsNumber(); | ||
auto depotNodeOk = !maybeDepotNode.IsEmpty() && maybeDepotNode.ToLocalChecked()->IsNumber(); | ||
auto timeHorizonOk = !maybeTimeHorizon.IsEmpty() && maybeTimeHorizon.ToLocalChecked()->IsNumber(); | ||
auto vehicleCapacityOk = !maybeVehicleCapacity.IsEmpty() && maybeVehicleCapacity.ToLocalChecked()->IsNumber(); | ||
auto vehicleCapacityOk = !maybeVehicleCapacity.IsEmpty() && maybeVehicleCapacity.ToLocalChecked()->IsArray(); // IsNumber() changed to IsArray() | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. remove comment |
||
auto routeLocksOk = !maybeRouteLocks.IsEmpty() && maybeRouteLocks.ToLocalChecked()->IsArray(); | ||
auto pickupsOk = !maybePickups.IsEmpty() && maybePickups.ToLocalChecked()->IsArray(); | ||
auto deliveriesOk = !maybeDeliveries.IsEmpty() && maybeDeliveries.ToLocalChecked()->IsArray(); | ||
|
@@ -192,7 +199,9 @@ VRPSearchParams::VRPSearchParams(const Nan::FunctionCallbackInfo<v8::Value>& inf | |
numVehicles = Nan::To<std::int32_t>(maybeNumVehicles.ToLocalChecked()).FromJust(); | ||
depotNode = Nan::To<std::int32_t>(maybeDepotNode.ToLocalChecked()).FromJust(); | ||
timeHorizon = Nan::To<std::int32_t>(maybeTimeHorizon.ToLocalChecked()).FromJust(); | ||
vehicleCapacity = Nan::To<std::int32_t>(maybeVehicleCapacity.ToLocalChecked()).FromJust(); | ||
//vehicleCapacity = Nan::To<std::int32_t>(maybeVehicleCapacity.ToLocalChecked()).FromJust(); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why commented out? |
||
|
||
|
||
|
||
auto routeLocksArray = maybeRouteLocks.ToLocalChecked().As<v8::Array>(); | ||
routeLocks = makeRouteLocksFrom2dArray(numVehicles, routeLocksArray); | ||
|
@@ -203,6 +212,10 @@ VRPSearchParams::VRPSearchParams(const Nan::FunctionCallbackInfo<v8::Value>& inf | |
auto deliveriesArray = maybeDeliveries.ToLocalChecked().As<v8::Array>(); | ||
deliveries = makeVectorFromJsNumberArray<Deliveries>(deliveriesArray); | ||
|
||
auto vehicleCapacityArray = maybeVehicleCapacity.ToLocalChecked().As<v8::Array>(); | ||
vehicleCapacity = makeVectorFromJsNumberArray1<std::vector<int64> >(vehicleCapacityArray); | ||
// new function call added to make vehicle capacity vector calls function in adapter.h | ||
|
||
callback = info[1].As<v8::Function>(); | ||
} | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -32,7 +32,7 @@ struct VRPWorker final : Nan::AsyncWorker { | |
std::int32_t numVehicles_, // | ||
std::int32_t vehicleDepot_, // | ||
std::int32_t timeHorizon_, // | ||
std::int32_t vehicleCapacity_, // | ||
std::vector<int64> vehicleCapacity_, // type changed to vector int64 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why the change from int32s to int64s? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. it was because the AddDimensionWithVehicleCapacity() takes long long integer array |
||
RouteLocks routeLocks_, // | ||
Pickups pickups_, // | ||
Deliveries deliveries_) // | ||
|
@@ -47,7 +47,7 @@ struct VRPWorker final : Nan::AsyncWorker { | |
numVehicles{numVehicles_}, | ||
vehicleDepot{vehicleDepot_}, | ||
timeHorizon{timeHorizon_}, | ||
vehicleCapacity{vehicleCapacity_}, | ||
vehicleCapacity{std::move(vehicleCapacity_)}, | ||
routeLocks{std::move(routeLocks_)}, | ||
pickups{std::move(pickups_)}, | ||
deliveries{std::move(deliveries_)}, | ||
|
@@ -120,14 +120,38 @@ struct VRPWorker final : Nan::AsyncWorker { | |
auto demandAdaptor = makeBinaryAdaptor(*demands); | ||
auto demandCallback = makeCallback(demandAdaptor); | ||
|
||
const static auto kDimensionCapacity = "capacity"; | ||
|
||
//std::vector<int64> vehicle_capacities | ||
// vehicle capacity call back | ||
|
||
model.AddDimension(demandCallback, /*slack=*/0, vehicleCapacity, /*fix_start_cumul_to_zero=*/true, kDimensionCapacity); | ||
//auto vehicleCapacityAdaptor = makeUnaryAdaptor(vehicleCapacity); | ||
// auto vehicleCapacityCallback = makeCallback(vehicleCapacityAdaptor); | ||
|
||
// if(model.status() != RoutingModel::Status::ROUTING_SUCCESS) | ||
// return SetErrorMessage("Unable to find a solution -2"); | ||
|
||
|
||
const static std::string& kDimensionCapacity = "capacity"; | ||
|
||
//function for handling different capacitated vehicles | ||
model.AddDimensionWithVehicleCapacity(demandCallback, /*slack=*/0, vehicleCapacity, /*fix_start_cumul_to_zero=*/true, kDimensionCapacity); | ||
const auto& capacityDimension = model.GetDimensionOrDie(kDimensionCapacity); | ||
|
||
// if(model.status() != RoutingModel::Status::ROUTING_SUCCESS) | ||
// return SetErrorMessage("Unable to find a solution -1"); | ||
//old | ||
//const static auto kDimensionCapacity = "capacity"; | ||
|
||
//model.AddDimension(demandCallback, /*slack=*/0, vehicleCapacity, /*fix_start_cumul_to_zero=*/true, kDimensionCapacity); | ||
// const auto& capacityDimension = model.GetDimensionOrDie(kDimensionCapacity); | ||
|
||
|
||
|
||
// Pickup and Deliveries | ||
|
||
auto* solver = model.solver(); | ||
// if(model.status() != RoutingModel::Status::ROUTING_SUCCESS) | ||
// return SetErrorMessage("Unable to find a solution 0"); | ||
|
||
for (std::int32_t atIdx = 0; atIdx < pickups.size(); ++atIdx) { | ||
const auto pickupIndex = model.NodeToIndex(pickups.at(atIdx)); | ||
|
@@ -144,14 +168,22 @@ struct VRPWorker final : Nan::AsyncWorker { | |
|
||
model.AddPickupAndDelivery(pickups.at(atIdx), deliveries.at(atIdx)); | ||
} | ||
// if(model.status() != RoutingModel::Status::ROUTING_SUCCESS) | ||
// return SetErrorMessage("Unable to find a solution 0"); | ||
|
||
// Done with modifications to the routing model | ||
|
||
model.CloseModel(); | ||
|
||
// if(model.status() != RoutingModel::Status::ROUTING_SUCCESS) | ||
// return SetErrorMessage("Unable to find a solution 1"); | ||
|
||
// Locking routes into place needs to happen after the model is closed and the underlying vars are established | ||
const auto validLocks = model.ApplyLocksToAllVehicles(routeLocks, /*close_routes=*/false); | ||
|
||
// if(model.status() != RoutingModel::Status::ROUTING_SUCCESS) | ||
// return SetErrorMessage("Unable to find a solution 2"); | ||
|
||
if (!validLocks) | ||
return SetErrorMessage("Invalid locks"); | ||
|
||
|
@@ -238,7 +270,7 @@ struct VRPWorker final : Nan::AsyncWorker { | |
std::int32_t numVehicles; | ||
std::int32_t vehicleDepot; | ||
std::int32_t timeHorizon; | ||
std::int32_t vehicleCapacity; | ||
std::vector<int64> vehicleCapacity; // changed type of vehicle capacity from int32_t to vector<int64> | ||
|
||
const RouteLocks routeLocks; | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The debug prints and the include above have to go before we can merge this