From a2f8554a6d7ead6af4df4552f23f7fb0dcf0bc8c Mon Sep 17 00:00:00 2001 From: "lperron@google.com" Date: Wed, 9 Jul 2014 11:09:30 +0000 Subject: [PATCH] ported examples --- examples/cpp/acp_challenge.cc | 2 +- examples/cpp/acp_challenge_routing.cc | 2 +- examples/cpp/costas_array.cc | 2 +- examples/cpp/cryptarithm.cc | 2 +- examples/cpp/cvrptw.cc | 2 +- examples/cpp/cvrptw_with_refueling.cc | 315 +++++++++++++++ examples/cpp/cvrptw_with_resources.cc | 301 ++++++++++++++ .../cvrptw_with_stop_times_and_resources.cc | 367 ++++++++++++++++++ examples/cpp/dimacs_assignment.cc | 2 +- examples/cpp/dobble_ls.cc | 2 +- examples/cpp/fap_model_printer.cc | 2 +- examples/cpp/fap_model_printer.h | 2 +- examples/cpp/fap_parser.cc | 2 +- examples/cpp/fap_parser.h | 2 +- examples/cpp/fap_utilities.cc | 2 +- examples/cpp/fap_utilities.h | 2 +- examples/cpp/flexible_jobshop.cc | 2 +- examples/cpp/flexible_jobshop.h | 2 +- examples/cpp/flow_api.cc | 2 +- examples/cpp/frequency_assignment_problem.cc | 2 +- examples/cpp/golomb.cc | 2 +- examples/cpp/integer_programming.cc | 2 +- examples/cpp/jobshop.cc | 2 +- examples/cpp/jobshop.h | 2 +- examples/cpp/jobshop_earlytardy.cc | 2 +- examples/cpp/jobshop_earlytardy.h | 2 +- examples/cpp/jobshop_ls.cc | 2 +- examples/cpp/jobshop_ls.h | 2 +- examples/cpp/linear_assignment_api.cc | 2 +- examples/cpp/linear_programming.cc | 2 +- .../cpp/linear_solver_protocol_buffers.cc | 30 +- examples/cpp/ls_api.cc | 2 +- examples/cpp/magic_square.cc | 2 +- examples/cpp/model_util.cc | 2 +- examples/cpp/mps_driver.cc | 2 +- examples/cpp/multidim_knapsack.cc | 9 +- examples/cpp/network_routing.cc | 2 +- examples/cpp/nqueens.cc | 2 +- examples/cpp/opb_reader.h | 2 +- examples/cpp/parse_dimacs_assignment.cc | 2 +- examples/cpp/parse_dimacs_assignment.h | 2 +- examples/cpp/pdptw.cc | 2 +- examples/cpp/print_dimacs_assignment.cc | 2 +- examples/cpp/print_dimacs_assignment.h | 2 +- examples/cpp/sat_cnf_reader.h | 2 +- examples/cpp/sat_runner.cc | 2 +- examples/cpp/solve.cc | 2 +- examples/cpp/sports_scheduling.cc | 2 +- ...trawberry_fields_with_column_generation.cc | 2 +- examples/cpp/tsp.cc | 2 +- 50 files changed, 1050 insertions(+), 62 deletions(-) create mode 100644 examples/cpp/cvrptw_with_refueling.cc create mode 100644 examples/cpp/cvrptw_with_resources.cc create mode 100644 examples/cpp/cvrptw_with_stop_times_and_resources.cc diff --git a/examples/cpp/acp_challenge.cc b/examples/cpp/acp_challenge.cc index 6b404c7e33..6af2ce1922 100644 --- a/examples/cpp/acp_challenge.cc +++ b/examples/cpp/acp_challenge.cc @@ -1,4 +1,4 @@ -// Copyright 2010-2013 Google +// Copyright 2010-2014 Google // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at diff --git a/examples/cpp/acp_challenge_routing.cc b/examples/cpp/acp_challenge_routing.cc index 19246d4183..f3ec6abf63 100644 --- a/examples/cpp/acp_challenge_routing.cc +++ b/examples/cpp/acp_challenge_routing.cc @@ -1,4 +1,4 @@ -// Copyright 2010-2013 Google +// Copyright 2010-2014 Google // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at diff --git a/examples/cpp/costas_array.cc b/examples/cpp/costas_array.cc index 2ccd99f31c..f3c866581d 100644 --- a/examples/cpp/costas_array.cc +++ b/examples/cpp/costas_array.cc @@ -1,4 +1,4 @@ -// Copyright 2010-2013 Google +// Copyright 2010-2014 Google // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at diff --git a/examples/cpp/cryptarithm.cc b/examples/cpp/cryptarithm.cc index a64cd10e8a..6e9c6591b7 100644 --- a/examples/cpp/cryptarithm.cc +++ b/examples/cpp/cryptarithm.cc @@ -1,4 +1,4 @@ -// Copyright 2010-2013 Google +// Copyright 2010-2014 Google // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at diff --git a/examples/cpp/cvrptw.cc b/examples/cpp/cvrptw.cc index 2cd9f06adf..0bfc56843e 100644 --- a/examples/cpp/cvrptw.cc +++ b/examples/cpp/cvrptw.cc @@ -1,4 +1,4 @@ -// Copyright 2010-2013 Google +// Copyright 2010-2014 Google // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at diff --git a/examples/cpp/cvrptw_with_refueling.cc b/examples/cpp/cvrptw_with_refueling.cc new file mode 100644 index 0000000000..383a9e09ba --- /dev/null +++ b/examples/cpp/cvrptw_with_refueling.cc @@ -0,0 +1,315 @@ +// Copyright 2010-2014 Google +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// Capacitated Vehicle Routing Problem with Time Windows and refueling +// constraints. +// This is an extension to the model in cvrptw.cc so refer to that file for +// more information on the common part of the model. The model implemented here +// takes into account refueling constraints using a specific dimension: vehicles +// must visit certain nodes (refueling nodes) before the quantity of fuel +// reaches zero. Fuel consumption is proportional to the distance traveled. + +#include "base/unique_ptr.h" +#include + +#include "base/callback.h" +#include "base/commandlineflags.h" +#include "base/commandlineflags.h" +#include "base/integral_types.h" +#include "base/logging.h" +#include "base/stringprintf.h" +#include "constraint_solver/routing.h" +#include "base/random.h" + +using operations_research::Assignment; +using operations_research::IntVar; +using operations_research::RoutingDimension; +using operations_research::RoutingModel; +using operations_research::Solver; +using operations_research::ACMRandom; +using operations_research::StringAppendF; +using operations_research::StringPrintf; +using operations_research::scoped_ptr; + + +DECLARE_string(routing_first_solution); +DECLARE_bool(routing_no_lns); +DEFINE_int32(vrp_orders, 100, "Nodes in the problem."); +DEFINE_int32(vrp_vehicles, 20, "Size of Traveling Salesman Problem instance."); +DEFINE_bool(vrp_use_deterministic_random_seed, false, + "Use deterministic random seeds."); + +const char* kTime = "Time"; +const char* kCapacity = "Capacity"; +const char* kFuel = "Fuel"; + +// Random seed generator. +int32 GetSeed() { + if (FLAGS_vrp_use_deterministic_random_seed) { + return ACMRandom::DeterministicSeed(); + } else { + return ACMRandom::HostnamePidTimeSeed(); + } +} + +// Returns true if node is a refueling node (based on node / refuel node ratio). +bool IsRefuelNode(int64 node) { + const int64 kRefuelNodeRatio = 10; + return (node % kRefuelNodeRatio == 0); +} + +// Location container, contains positions of orders and can be used to obtain +// Manhattan distances/times between locations. +class LocationContainer { + public: + explicit LocationContainer(int64 speed) + : randomizer_(GetSeed()), speed_(speed) { + CHECK_LT(0, speed_); + } + void AddLocation(int64 x, int64 y) { locations_.push_back(Location(x, y)); } + void AddRandomLocation(int64 x_max, int64 y_max) { + AddLocation(randomizer_.Uniform(x_max + 1), randomizer_.Uniform(y_max + 1)); + } + int64 ManhattanDistance(RoutingModel::NodeIndex from, + RoutingModel::NodeIndex to) const { + return locations_[from].DistanceTo(locations_[to]); + } + int64 NegManhattanDistance(RoutingModel::NodeIndex from, + RoutingModel::NodeIndex to) const { + return -ManhattanDistance(from, to); + } + int64 ManhattanTime(RoutingModel::NodeIndex from, + RoutingModel::NodeIndex to) const { + return ManhattanDistance(from, to) / speed_; + } + + private: + class Location { + public: + Location() : x_(0), y_(0) {} + Location(int64 x, int64 y) : x_(x), y_(y) {} + int64 DistanceTo(const Location& location) const { + return Abs(x_ - location.x_) + Abs(y_ - location.y_); + } + + private: + static int64 Abs(int64 value) { return std::max(value, -value); } + + int64 x_; + int64 y_; + }; + + ACMRandom randomizer_; + const int64 speed_; + ITIVector locations_; +}; + +// Random demand. +class RandomDemand { + public: + RandomDemand(int size, RoutingModel::NodeIndex depot) + : size_(size), depot_(depot) { + CHECK_LT(0, size_); + } + void Initialize() { + const int64 kDemandMax = 5; + const int64 kDemandMin = 1; + demand_.reset(new int64[size_]); + ACMRandom randomizer(GetSeed()); + for (int order = 0; order < size_; ++order) { + if (order == depot_) { + demand_[order] = 0; + } else { + demand_[order] = + kDemandMin + randomizer.Uniform(kDemandMax - kDemandMin + 1); + } + } + } + int64 Demand(RoutingModel::NodeIndex from, RoutingModel::NodeIndex to) const { + // Refuel nodes don't have a demand. + if (!IsRefuelNode(from.value())) { + return demand_[from.value()]; + } + return 0; + } + + private: + std::unique_ptr demand_; + const int size_; + const RoutingModel::NodeIndex depot_; +}; + +// Service time (proportional to demand) + transition time callback. +class ServiceTimePlusTransition { + public: + ServiceTimePlusTransition(int64 time_per_demand_unit, + RoutingModel::NodeEvaluator2* demand, + RoutingModel::NodeEvaluator2* transition_time) + : time_per_demand_unit_(time_per_demand_unit), + demand_(demand), + transition_time_(transition_time) {} + int64 Compute(RoutingModel::NodeIndex from, + RoutingModel::NodeIndex to) const { + return time_per_demand_unit_ * demand_->Run(from, to) + + transition_time_->Run(from, to); + } + + private: + const int64 time_per_demand_unit_; + std::unique_ptr demand_; + std::unique_ptr transition_time_; +}; + +// Route plan displayer. +// TODO(user): Move the display code to the routing library. +void DisplayPlan(const RoutingModel& routing, const Assignment& plan) { + // Display plan cost. + std::string plan_output = StringPrintf("Cost %lld\n", plan.ObjectiveValue()); + + // Display dropped orders. + std::string dropped; + for (int order = 1; order < routing.nodes(); ++order) { + if (plan.Value(routing.NextVar(order)) == order) { + if (dropped.empty()) { + StringAppendF(&dropped, " %d", order); + } else { + StringAppendF(&dropped, ", %d", order); + } + } + } + if (!dropped.empty()) { + plan_output += "Dropped orders:" + dropped + "\n"; + } + + // Display actual output for each vehicle. + const RoutingDimension& capacity_dimension = + routing.GetDimensionOrDie(kCapacity); + const RoutingDimension& time_dimension = routing.GetDimensionOrDie(kTime); + const RoutingDimension& fuel_dimension = routing.GetDimensionOrDie(kFuel); + for (int route_number = 0; route_number < routing.vehicles(); + ++route_number) { + int64 order = routing.Start(route_number); + StringAppendF(&plan_output, "Route %d: ", route_number); + if (routing.IsEnd(plan.Value(routing.NextVar(order)))) { + plan_output += "Empty\n"; + } else { + while (true) { + IntVar* const load_var = capacity_dimension.CumulVar(order); + IntVar* const time_var = time_dimension.CumulVar(order); + IntVar* const fuel_var = fuel_dimension.CumulVar(order); + StringAppendF(&plan_output, + "%lld Load(%lld) Time(%lld, %lld) Fuel(%lld, %lld) -> ", + order, plan.Value(load_var), plan.Min(time_var), + plan.Max(time_var), plan.Min(fuel_var), + plan.Max(fuel_var)); + if (routing.IsEnd(order)) break; + order = plan.Value(routing.NextVar(order)); + } + } + plan_output += "\n"; + } + LOG(INFO) << plan_output; +} + +int main(int argc, char** argv) { + google::ParseCommandLineFlags( &argc, &argv, true); + CHECK_LT(0, FLAGS_vrp_orders) << "Specify an instance size greater than 0."; + CHECK_LT(0, FLAGS_vrp_vehicles) << "Specify a non-null vehicle fleet size."; + // VRP of size FLAGS_vrp_size. + // Nodes are indexed from 0 to FLAGS_vrp_orders, the starts and ends of + // the routes are at node 0. + const RoutingModel::NodeIndex kDepot(0); + RoutingModel routing(FLAGS_vrp_orders + 1, FLAGS_vrp_vehicles); + routing.SetDepot(kDepot); + // Setting first solution heuristic (cheapest addition). + FLAGS_routing_first_solution = "PathCheapestArc"; + // Disabling Large Neighborhood Search, comment out to activate it. + FLAGS_routing_no_lns = true; + + // Setting up locations. + const int64 kXMax = 100000; + const int64 kYMax = 100000; + const int64 kSpeed = 10; + LocationContainer locations(kSpeed); + for (int location = 0; location <= FLAGS_vrp_orders; ++location) { + locations.AddRandomLocation(kXMax, kYMax); + } + + // Setting the cost function. + routing.SetArcCostEvaluatorOfAllVehicles( + NewPermanentCallback(&locations, &LocationContainer::ManhattanDistance)); + + // Adding capacity dimension constraints. + const int64 kVehicleCapacity = 40; + const int64 kNullCapacitySlack = 0; + RandomDemand demand(routing.nodes(), kDepot); + demand.Initialize(); + routing.AddDimension(NewPermanentCallback(&demand, &RandomDemand::Demand), + kNullCapacitySlack, kVehicleCapacity, + /*fix_start_cumul_to_zero=*/true, kCapacity); + + // Adding time dimension constraints. + const int64 kTimePerDemandUnit = 300; + const int64 kHorizon = 24 * 3600; + ServiceTimePlusTransition time( + kTimePerDemandUnit, NewPermanentCallback(&demand, &RandomDemand::Demand), + NewPermanentCallback(&locations, &LocationContainer::ManhattanTime)); + routing.AddDimension( + NewPermanentCallback(&time, &ServiceTimePlusTransition::Compute), + kHorizon, kHorizon, /*fix_start_cumul_to_zero=*/true, kTime); + const RoutingDimension& time_dimension = routing.GetDimensionOrDie(kTime); + // Adding time windows. + ACMRandom randomizer(GetSeed()); + const int64 kTWDuration = 5 * 3600; + for (int order = 1; order < routing.nodes(); ++order) { + if (!IsRefuelNode(order)) { + const int64 start = randomizer.Uniform(kHorizon - kTWDuration); + time_dimension.CumulVar(order)->SetRange(start, start + kTWDuration); + } + } + + // Adding fuel dimension. This dimension consumes a quantity equal to the + // distance traveled. Only refuel nodes can make the quantity of dimension + // increase by letting slack variable replenish the fuel. + const int64 kFuelCapacity = kXMax + kYMax; + routing.AddDimension( + NewPermanentCallback(&locations, + &LocationContainer::NegManhattanDistance), + kFuelCapacity, kFuelCapacity, /*fix_start_cumul_to_zero=*/false, kFuel); + const RoutingDimension& fuel_dimension = routing.GetDimensionOrDie(kFuel); + for (int order = 0; order < routing.Size(); ++order) { + // Only let slack free for refueling nodes. + if (!IsRefuelNode(order) || routing.IsStart(order)) { + fuel_dimension.SlackVar(order)->SetValue(0); + } + // Needed to instantiate fuel quantity at each node. + routing.AddVariableMinimizedByFinalizer(fuel_dimension.CumulVar(order)); + } + + // Adding penalty costs to allow skipping orders. + const int64 kPenalty = 100000; + const RoutingModel::NodeIndex kFirstNodeAfterDepot(1); + for (RoutingModel::NodeIndex order = kFirstNodeAfterDepot; + order < routing.nodes(); ++order) { + std::vector orders(1, order); + routing.AddDisjunction(orders, kPenalty); + } + + // Solve, returns a solution if any (owned by RoutingModel). + const Assignment* solution = routing.Solve(); + if (solution != NULL) { + DisplayPlan(routing, *solution); + } else { + LOG(INFO) << "No solution found."; + } + return 0; +} diff --git a/examples/cpp/cvrptw_with_resources.cc b/examples/cpp/cvrptw_with_resources.cc new file mode 100644 index 0000000000..9e685a9f8b --- /dev/null +++ b/examples/cpp/cvrptw_with_resources.cc @@ -0,0 +1,301 @@ +// Copyright 2010-2014 Google +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// Capacitated Vehicle Routing Problem with Time Windows and capacitated +// resources. +// This is an extension to the model in cvrptw.cc so refer to that file for +// more information on the common part of the model. The model implemented here +// limits the number of vehicles which can simultaneously leave or enter the +// depot due to limited resources (or capacity) available. +// TODO(user): The current model consumes resources even for vehicles with +// empty routes; fix this when we have an API on the cumulative constraints +// with variable demands. + +#include "base/unique_ptr.h" +#include + +#include "base/callback.h" +#include "base/commandlineflags.h" +#include "base/commandlineflags.h" +#include "base/integral_types.h" +#include "base/logging.h" +#include "base/stringprintf.h" +#include "constraint_solver/routing.h" +#include "base/random.h" + +using operations_research::Assignment; +using operations_research::IntervalVar; +using operations_research::IntVar; +using operations_research::RoutingDimension; +using operations_research::RoutingModel; +using operations_research::Solver; +using operations_research::ACMRandom; +using operations_research::StringAppendF; +using operations_research::StringPrintf; +using operations_research::scoped_ptr; + + +DECLARE_string(routing_first_solution); +DECLARE_bool(routing_no_lns); +DEFINE_int32(vrp_orders, 100, "Nodes in the problem."); +DEFINE_int32(vrp_vehicles, 20, "Size of Traveling Salesman Problem instance."); +DEFINE_bool(vrp_use_deterministic_random_seed, false, + "Use deterministic random seeds."); + +const char* kTime = "Time"; +const char* kCapacity = "Capacity"; + +// Random seed generator. +int32 GetSeed() { + if (FLAGS_vrp_use_deterministic_random_seed) { + return ACMRandom::DeterministicSeed(); + } else { + return ACMRandom::HostnamePidTimeSeed(); + } +} + +// Location container, contains positions of orders and can be used to obtain +// Manhattan distances/times between locations. +class LocationContainer { + public: + explicit LocationContainer(int64 speed) + : randomizer_(GetSeed()), speed_(speed) { + CHECK_LT(0, speed_); + } + void AddLocation(int64 x, int64 y) { locations_.push_back(Location(x, y)); } + void AddRandomLocation(int64 x_max, int64 y_max) { + AddLocation(randomizer_.Uniform(x_max + 1), randomizer_.Uniform(y_max + 1)); + } + int64 ManhattanDistance(RoutingModel::NodeIndex from, + RoutingModel::NodeIndex to) const { + return locations_[from].DistanceTo(locations_[to]); + } + int64 ManhattanTime(RoutingModel::NodeIndex from, + RoutingModel::NodeIndex to) const { + return ManhattanDistance(from, to) / speed_; + } + + private: + class Location { + public: + Location() : x_(0), y_(0) {} + Location(int64 x, int64 y) : x_(x), y_(y) {} + int64 DistanceTo(const Location& location) const { + return Abs(x_ - location.x_) + Abs(y_ - location.y_); + } + + private: + static int64 Abs(int64 value) { return std::max(value, -value); } + + int64 x_; + int64 y_; + }; + + ACMRandom randomizer_; + const int64 speed_; + ITIVector locations_; +}; + +// Random demand. +class RandomDemand { + public: + RandomDemand(int size, RoutingModel::NodeIndex depot) + : size_(size), depot_(depot) { + CHECK_LT(0, size_); + } + void Initialize() { + const int64 kDemandMax = 5; + const int64 kDemandMin = 1; + demand_.reset(new int64[size_]); + ACMRandom randomizer(GetSeed()); + for (int order = 0; order < size_; ++order) { + if (order == depot_) { + demand_[order] = 0; + } else { + demand_[order] = + kDemandMin + randomizer.Uniform(kDemandMax - kDemandMin + 1); + } + } + } + int64 Demand(RoutingModel::NodeIndex from, RoutingModel::NodeIndex to) const { + return demand_[from.value()]; + } + + private: + std::unique_ptr demand_; + const int size_; + const RoutingModel::NodeIndex depot_; +}; + +// Service time (proportional to demand) + transition time callback. +class ServiceTimePlusTransition { + public: + ServiceTimePlusTransition(int64 time_per_demand_unit, + RoutingModel::NodeEvaluator2* demand, + RoutingModel::NodeEvaluator2* transition_time) + : time_per_demand_unit_(time_per_demand_unit), + demand_(demand), + transition_time_(transition_time) {} + int64 Compute(RoutingModel::NodeIndex from, + RoutingModel::NodeIndex to) const { + return time_per_demand_unit_ * demand_->Run(from, to) + + transition_time_->Run(from, to); + } + + private: + const int64 time_per_demand_unit_; + std::unique_ptr demand_; + std::unique_ptr transition_time_; +}; + +// Route plan displayer. +// TODO(user): Move the display code to the routing library. +void DisplayPlan(const RoutingModel& routing, const Assignment& plan) { + // Display plan cost. + std::string plan_output = StringPrintf("Cost %lld\n", plan.ObjectiveValue()); + + // Display dropped orders. + std::string dropped; + for (int order = 1; order < routing.nodes(); ++order) { + if (plan.Value(routing.NextVar(order)) == order) { + if (dropped.empty()) { + StringAppendF(&dropped, " %d", order); + } else { + StringAppendF(&dropped, ", %d", order); + } + } + } + if (!dropped.empty()) { + plan_output += "Dropped orders:" + dropped + "\n"; + } + + // Display actual output for each vehicle. + const RoutingDimension& capacity_dimension = + routing.GetDimensionOrDie(kCapacity); + const RoutingDimension& time_dimension = routing.GetDimensionOrDie(kTime); + for (int route_number = 0; route_number < routing.vehicles(); + ++route_number) { + int64 order = routing.Start(route_number); + StringAppendF(&plan_output, "Route %d: ", route_number); + if (routing.IsEnd(plan.Value(routing.NextVar(order)))) { + plan_output += "Empty\n"; + } else { + while (true) { + IntVar* const load_var = capacity_dimension.CumulVar(order); + IntVar* const time_var = time_dimension.CumulVar(order); + StringAppendF(&plan_output, "%lld Load(%lld) Time(%lld, %lld) -> ", + order, plan.Value(load_var), plan.Min(time_var), + plan.Max(time_var)); + if (routing.IsEnd(order)) break; + order = plan.Value(routing.NextVar(order)); + } + } + } + LOG(INFO) << plan_output; +} + +int main(int argc, char** argv) { + google::ParseCommandLineFlags( &argc, &argv, true); + CHECK_LT(0, FLAGS_vrp_orders) << "Specify an instance size greater than 0."; + CHECK_LT(0, FLAGS_vrp_vehicles) << "Specify a non-null vehicle fleet size."; + // VRP of size FLAGS_vrp_size. + // Nodes are indexed from 0 to FLAGS_vrp_orders, the starts and ends of + // the routes are at node 0. + const RoutingModel::NodeIndex kDepot(0); + RoutingModel routing(FLAGS_vrp_orders + 1, FLAGS_vrp_vehicles); + routing.SetDepot(kDepot); + // Setting first solution heuristic (cheapest addition). + FLAGS_routing_first_solution = "PathCheapestArc"; + // Disabling Large Neighborhood Search, comment out to activate it. + FLAGS_routing_no_lns = true; + + // Setting up locations. + const int64 kXMax = 100000; + const int64 kYMax = 100000; + const int64 kSpeed = 10; + LocationContainer locations(kSpeed); + for (int location = 0; location <= FLAGS_vrp_orders; ++location) { + locations.AddRandomLocation(kXMax, kYMax); + } + + // Setting the cost function. + routing.SetArcCostEvaluatorOfAllVehicles( + NewPermanentCallback(&locations, &LocationContainer::ManhattanDistance)); + + // Adding capacity dimension constraints. + const int64 kVehicleCapacity = 40; + const int64 kNullCapacitySlack = 0; + RandomDemand demand(routing.nodes(), kDepot); + demand.Initialize(); + routing.AddDimension(NewPermanentCallback(&demand, &RandomDemand::Demand), + kNullCapacitySlack, kVehicleCapacity, + /*fix_start_cumul_to_zero=*/true, kCapacity); + + // Adding time dimension constraints. + const int64 kTimePerDemandUnit = 300; + const int64 kHorizon = 24 * 3600; + ServiceTimePlusTransition time( + kTimePerDemandUnit, NewPermanentCallback(&demand, &RandomDemand::Demand), + NewPermanentCallback(&locations, &LocationContainer::ManhattanTime)); + routing.AddDimension( + NewPermanentCallback(&time, &ServiceTimePlusTransition::Compute), + kHorizon, kHorizon, /*fix_start_cumul_to_zero=*/false, kTime); + + // Adding time windows. + ACMRandom randomizer(GetSeed()); + const int64 kTWDuration = 5 * 3600; + for (int order = 1; order < routing.nodes(); ++order) { + const int64 start = randomizer.Uniform(kHorizon - kTWDuration); + routing.CumulVar(order, kTime)->SetRange(start, start + kTWDuration); + } + + // Adding resource constraints at the depot (start and end location of + // routes). + std::vector start_end_times; + for (int i = 0; i < FLAGS_vrp_vehicles; ++i) { + start_end_times.push_back(routing.CumulVar(routing.End(i), kTime)); + start_end_times.push_back(routing.CumulVar(routing.Start(i), kTime)); + } + // Build corresponding time intervals. + const int64 kVehicleSetup = 180; + Solver* const solver = routing.solver(); + std::vector intervals; + solver->MakeFixedDurationIntervalVarArray(start_end_times, kVehicleSetup, + "depot_interval", &intervals); + // Constrain the number of maximum simultaneous intervals at depot. + const int64 kDepotCapacity = 5; + std::vector depot_usage(start_end_times.size(), 1); + solver->AddConstraint( + solver->MakeCumulative(intervals, depot_usage, kDepotCapacity, "depot")); + // Instantiate route start and end times to produce feasible times. + for (int i = 0; i < start_end_times.size(); ++i) { + routing.AddVariableMinimizedByFinalizer(start_end_times[i]); + } + + // Adding penalty costs to allow skipping orders. + const int64 kPenalty = 100000; + const RoutingModel::NodeIndex kFirstNodeAfterDepot(1); + for (RoutingModel::NodeIndex order = kFirstNodeAfterDepot; + order < routing.nodes(); ++order) { + std::vector orders(1, order); + routing.AddDisjunction(orders, kPenalty); + } + + // Solve, returns a solution if any (owned by RoutingModel). + const Assignment* solution = routing.Solve(); + if (solution != NULL) { + DisplayPlan(routing, *solution); + } else { + LOG(INFO) << "No solution found."; + } + return 0; +} diff --git a/examples/cpp/cvrptw_with_stop_times_and_resources.cc b/examples/cpp/cvrptw_with_stop_times_and_resources.cc new file mode 100644 index 0000000000..c6d752de9d --- /dev/null +++ b/examples/cpp/cvrptw_with_stop_times_and_resources.cc @@ -0,0 +1,367 @@ +// Copyright 2010-2014 Google +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// Capacitated Vehicle Routing Problem with Time Windows, fixed stop times and +// capacitated resources. A stop is defined as consecutive nodes at the same +// location. +// This is an extension to the model in cvrptw.cc so refer to that file for +// more information on the common part of the model. The model implemented here +// limits the number of vehicles which can simultaneously leave or enter a node +// to one. + +#include "base/unique_ptr.h" +#include + +#include "base/callback.h" +#include "base/commandlineflags.h" +#include "base/commandlineflags.h" +#include "base/integral_types.h" +#include "base/logging.h" +#include "base/stringprintf.h" +#include "base/join.h" +#include "constraint_solver/routing.h" +#include "base/random.h" + +using operations_research::Assignment; +using operations_research::IntervalVar; +using operations_research::IntExpr; +using operations_research::IntVar; +using operations_research::RoutingDimension; +using operations_research::RoutingModel; +using operations_research::Solver; +using operations_research::ACMRandom; +using operations_research::StrCat; +using operations_research::StringAppendF; +using operations_research::StringPrintf; +using operations_research::scoped_ptr; + + +DECLARE_string(routing_first_solution); +DECLARE_bool(routing_no_lns); +DEFINE_int32(vrp_stops, 25, "Stop locations in the problem."); +DEFINE_int32(vrp_orders_per_stop, 5, "Nodes for each stop."); +DEFINE_int32(vrp_vehicles, 20, "Size of Traveling Salesman Problem instance."); +DEFINE_bool(vrp_use_deterministic_random_seed, false, + "Use deterministic random seeds."); + +const char* kTime = "Time"; +const char* kCapacity = "Capacity"; + +// Random seed generator. +int32 GetSeed() { + if (FLAGS_vrp_use_deterministic_random_seed) { + return ACMRandom::DeterministicSeed(); + } else { + return ACMRandom::HostnamePidTimeSeed(); + } +} + +// Location container, contains positions of orders and can be used to obtain +// Manhattan distances/times between locations. +class LocationContainer { + public: + explicit LocationContainer(int64 speed) + : randomizer_(GetSeed()), speed_(speed) { + CHECK_LT(0, speed_); + } + void AddLocation(int64 x, int64 y) { locations_.push_back(Location(x, y)); } + void AddRandomLocation(int64 x_max, int64 y_max, int duplicates) { + const int64 x = randomizer_.Uniform(x_max + 1); + const int64 y = randomizer_.Uniform(y_max + 1); + for (int i = 0; i < duplicates; ++i) { + AddLocation(x, y); + } + } + int64 ManhattanDistance(RoutingModel::NodeIndex from, + RoutingModel::NodeIndex to) const { + return locations_[from].DistanceTo(locations_[to]); + } + int64 ManhattanTime(RoutingModel::NodeIndex from, + RoutingModel::NodeIndex to) const { + return ManhattanDistance(from, to) / speed_; + } + bool SameLocation(RoutingModel::NodeIndex node1, + RoutingModel::NodeIndex node2) const { + if (node1 < locations_.size() && node2 < locations_.size()) { + return locations_[node1].IsAtSameLocation(locations_[node2]); + } + return false; + } + int64 SameLocationFromIndex(int64 node1, int64 node2) const { + // The direct conversion from constraint model indices to routing model + // nodes is correct because the depot is node 0. + // TODO(user): Fetch proper indices from routing model. + return SameLocation(RoutingModel::NodeIndex(node1), + RoutingModel::NodeIndex(node2)); + } + + private: + class Location { + public: + Location() : x_(0), y_(0) {} + Location(int64 x, int64 y) : x_(x), y_(y) {} + int64 DistanceTo(const Location& location) const { + return Abs(x_ - location.x_) + Abs(y_ - location.y_); + } + bool IsAtSameLocation(const Location& location) const { + return x_ == location.x_ && y_ == location.y_; + } + + private: + static int64 Abs(int64 value) { return std::max(value, -value); } + + int64 x_; + int64 y_; + }; + + ACMRandom randomizer_; + const int64 speed_; + ITIVector locations_; +}; + +// Random demand. +class RandomDemand { + public: + RandomDemand(int size, RoutingModel::NodeIndex depot) + : size_(size), depot_(depot) { + CHECK_LT(0, size_); + } + void Initialize() { + const int64 kDemandMax = 5; + const int64 kDemandMin = 1; + demand_.reset(new int64[size_]); + ACMRandom randomizer(GetSeed()); + for (int order = 0; order < size_; ++order) { + if (order == depot_) { + demand_[order] = 0; + } else { + demand_[order] = + kDemandMin + randomizer.Uniform(kDemandMax - kDemandMin + 1); + } + } + } + int64 Demand(RoutingModel::NodeIndex from, RoutingModel::NodeIndex to) const { + return demand_[from.value()]; + } + + private: + std::unique_ptr demand_; + const int size_; + const RoutingModel::NodeIndex depot_; +}; + +// Stop service time + transition time callback. +class StopServiceTimePlusTransition { + public: + StopServiceTimePlusTransition(int64 stop_time, + const LocationContainer& location_container, + RoutingModel::NodeEvaluator2* transition_time) + : stop_time_(stop_time), + location_container_(location_container), + transition_time_(transition_time) {} + int64 Compute(RoutingModel::NodeIndex from, + RoutingModel::NodeIndex to) const { + return location_container_.SameLocation(from, to) ? 0 + : stop_time_ + transition_time_->Run(from, to); + } + + private: + const int64 stop_time_; + const LocationContainer& location_container_; + std::unique_ptr demand_; + std::unique_ptr transition_time_; +}; + +// Route plan displayer. +// TODO(user): Move the display code to the routing library. +void DisplayPlan(const RoutingModel& routing, const Assignment& plan) { + // Display plan cost. + std::string plan_output = StringPrintf("Cost %lld\n", plan.ObjectiveValue()); + + // Display dropped orders. + std::string dropped; + for (int order = 1; order < routing.nodes(); ++order) { + if (plan.Value(routing.NextVar(order)) == order) { + if (dropped.empty()) { + StringAppendF(&dropped, " %d", order); + } else { + StringAppendF(&dropped, ", %d", order); + } + } + } + if (!dropped.empty()) { + plan_output += "Dropped orders:" + dropped + "\n"; + } + LOG(INFO) << plan_output; + + // Display actual output for each vehicle. + const RoutingDimension& capacity_dimension = + routing.GetDimensionOrDie(kCapacity); + const RoutingDimension& time_dimension = routing.GetDimensionOrDie(kTime); + for (int route_number = 0; route_number < routing.vehicles(); + ++route_number) { + std::string route_output; + int64 order = routing.Start(route_number); + StringAppendF(&route_output, "Route %d: ", route_number); + if (routing.IsEnd(plan.Value(routing.NextVar(order)))) { + route_output += "Empty\n"; + } else { + while (true) { + IntVar* const load_var = capacity_dimension.CumulVar(order); + IntVar* const time_var = time_dimension.CumulVar(order); + StringAppendF(&route_output, " -> %lld Load(%lld) Time(%lld, %lld)", + order, plan.Value(load_var), plan.Min(time_var), + plan.Max(time_var)); + if (routing.IsEnd(order)) break; + order = plan.Value(routing.NextVar(order)); + } + } + LOG(INFO) << route_output; + } +} + +int main(int argc, char** argv) { + google::ParseCommandLineFlags( &argc, &argv, true); + CHECK_LT(0, FLAGS_vrp_stops) << "Specify an instance size greater than 0."; + CHECK_LT(0, FLAGS_vrp_orders_per_stop) + << "Specify an instance size greater than 0."; + CHECK_LT(0, FLAGS_vrp_vehicles) << "Specify a non-null vehicle fleet size."; + const int vrp_orders = FLAGS_vrp_stops * FLAGS_vrp_orders_per_stop; + // Nodes are indexed from 0 to vrp_orders, the starts and ends of the routes + // are at node 0. + const RoutingModel::NodeIndex kDepot(0); + RoutingModel routing(vrp_orders + 1, FLAGS_vrp_vehicles); + routing.SetDepot(kDepot); + // Setting first solution heuristic (cheapest addition). + FLAGS_routing_first_solution = "PathCheapestArc"; + // Disabling Large Neighborhood Search, comment out to activate it. + FLAGS_routing_no_lns = true; + + // Setting up locations. + const int64 kXMax = 100000; + const int64 kYMax = 100000; + const int64 kSpeed = 10; + LocationContainer locations(kSpeed); + for (int stop = 0; stop <= FLAGS_vrp_stops; ++stop) { + const int num_orders = stop == 0 ? 1 : FLAGS_vrp_orders_per_stop; + locations.AddRandomLocation(kXMax, kYMax, num_orders); + } + + // Setting the cost function. + routing.SetArcCostEvaluatorOfAllVehicles( + NewPermanentCallback(&locations, &LocationContainer::ManhattanDistance)); + + // Adding capacity dimension constraints. + const int64 kVehicleCapacity = 40; + const int64 kNullCapacitySlack = 0; + RandomDemand demand(routing.nodes(), kDepot); + demand.Initialize(); + routing.AddDimension(NewPermanentCallback(&demand, &RandomDemand::Demand), + kNullCapacitySlack, kVehicleCapacity, + /*fix_start_cumul_to_zero=*/true, kCapacity); + + // Adding time dimension constraints. + const int64 kStopTime = 300; + const int64 kHorizon = 24 * 3600; + StopServiceTimePlusTransition time( + kStopTime, + locations, + NewPermanentCallback(&locations, &LocationContainer::ManhattanTime)); + routing.AddDimension( + NewPermanentCallback(&time, &StopServiceTimePlusTransition::Compute), + kHorizon, kHorizon, /*fix_start_cumul_to_zero=*/false, kTime); + + // Adding time windows, for the sake of simplicty same for each stop. + ACMRandom randomizer(GetSeed()); + const int64 kTWDuration = 5 * 3600; + for (int stop = 0; stop < FLAGS_vrp_stops; ++stop) { + const int64 start = randomizer.Uniform(kHorizon - kTWDuration); + for (int stop_order = 0; + stop_order < FLAGS_vrp_orders_per_stop; + ++stop_order) { + const int order = stop * FLAGS_vrp_orders_per_stop + stop_order + 1; + routing.CumulVar(order, kTime)->SetRange(start, start + kTWDuration); + } + } + + // Adding resource constraints at order locations. + Solver* const solver = routing.solver(); + std::vector intervals; + for (int stop = 0; stop < FLAGS_vrp_stops; ++stop) { + std::vector stop_intervals; + for (int stop_order = 0; + stop_order < FLAGS_vrp_orders_per_stop; + ++stop_order) { + const int order = stop * FLAGS_vrp_orders_per_stop + stop_order + 1; + IntervalVar* const interval = + solver->MakeFixedDurationIntervalVar( + 0, kHorizon, kStopTime, true, StrCat("Order", order)); + intervals.push_back(interval); + stop_intervals.push_back(interval); + // Link order and interval. + IntVar* const order_start = routing.CumulVar(order, kTime); + solver->AddConstraint(solver->MakeIsEqualCt( + interval->SafeStartExpr(0), + order_start, + interval->PerformedExpr()->Var())); + // Make interval performed iff corresponding order has service time. + // An order has no service time iff it is at the same location as the + // next order on the route. + IntVar* const is_null_duration = + solver->MakeElement( + NewPermanentCallback(&locations, + &LocationContainer::SameLocationFromIndex, + order), + routing.NextVar(order))->Var(); + solver->AddConstraint(solver->MakeNonEquality(interval->PerformedExpr(), + is_null_duration)); + routing.AddIntervalToAssignment(interval); + // We are minimizing route durations by minimizing route ends; so we can + // maximize order starts to pack them together. + routing.AddVariableMaximizedByFinalizer(order_start); + } + // Only one order can happen at the same time at a given location. + std::vector location_usage(stop_intervals.size(), 1); + solver->AddConstraint( + solver->MakeCumulative( + stop_intervals, location_usage, 1, StrCat("Client", stop))); + } + // Minimizing route duration. + for (int vehicle = 0 ; vehicle < routing.vehicles(); ++vehicle) { + routing.AddVariableMinimizedByFinalizer( + routing.CumulVar(routing.End(vehicle), kTime)); + } + + // Adding penalty costs to allow skipping orders. + const int64 kPenalty = 100000; + const RoutingModel::NodeIndex kFirstNodeAfterDepot(1); + for (RoutingModel::NodeIndex order = kFirstNodeAfterDepot; + order < routing.nodes(); ++order) { + std::vector orders(1, order); + routing.AddDisjunction(orders, kPenalty); + } + + // Solve, returns a solution if any (owned by RoutingModel). + const Assignment* solution = routing.Solve(); + if (solution != NULL) { + DisplayPlan(routing, *solution); + LOG(INFO) << "Stop intervals:"; + for (IntervalVar* const interval : intervals) { + if (solution->PerformedValue(interval)) { + LOG(INFO) << interval->name() << ": " << solution->StartValue(interval); + } + } + } else { + LOG(INFO) << "No solution found."; + } + return 0; +} diff --git a/examples/cpp/dimacs_assignment.cc b/examples/cpp/dimacs_assignment.cc index 7ec1295dc0..e258b8f7d8 100644 --- a/examples/cpp/dimacs_assignment.cc +++ b/examples/cpp/dimacs_assignment.cc @@ -1,4 +1,4 @@ -// Copyright 2010-2013 Google +// Copyright 2010-2014 Google // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at diff --git a/examples/cpp/dobble_ls.cc b/examples/cpp/dobble_ls.cc index 1bbdf8e638..bcc7a66ac0 100644 --- a/examples/cpp/dobble_ls.cc +++ b/examples/cpp/dobble_ls.cc @@ -1,4 +1,4 @@ -// Copyright 2010-2013 Google +// Copyright 2010-2014 Google // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at diff --git a/examples/cpp/fap_model_printer.cc b/examples/cpp/fap_model_printer.cc index 5babbccde2..0be1c4bd3a 100644 --- a/examples/cpp/fap_model_printer.cc +++ b/examples/cpp/fap_model_printer.cc @@ -1,4 +1,4 @@ -// Copyright 2010-2013 Google +// Copyright 2010-2014 Google // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at diff --git a/examples/cpp/fap_model_printer.h b/examples/cpp/fap_model_printer.h index c8b0a02b13..877d8aec51 100644 --- a/examples/cpp/fap_model_printer.h +++ b/examples/cpp/fap_model_printer.h @@ -1,4 +1,4 @@ -// Copyright 2010-2013 Google +// Copyright 2010-2014 Google // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at diff --git a/examples/cpp/fap_parser.cc b/examples/cpp/fap_parser.cc index 462bedb66b..341668d583 100644 --- a/examples/cpp/fap_parser.cc +++ b/examples/cpp/fap_parser.cc @@ -1,4 +1,4 @@ -// Copyright 2010-2013 Google +// Copyright 2010-2014 Google // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at diff --git a/examples/cpp/fap_parser.h b/examples/cpp/fap_parser.h index fc3d85ee7c..bae8044c59 100644 --- a/examples/cpp/fap_parser.h +++ b/examples/cpp/fap_parser.h @@ -1,4 +1,4 @@ -// Copyright 2010-2013 Google +// Copyright 2010-2014 Google // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at diff --git a/examples/cpp/fap_utilities.cc b/examples/cpp/fap_utilities.cc index 1d7bff8694..60d2dc17ec 100644 --- a/examples/cpp/fap_utilities.cc +++ b/examples/cpp/fap_utilities.cc @@ -1,4 +1,4 @@ -// Copyright 2010-2013 Google +// Copyright 2010-2014 Google // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at diff --git a/examples/cpp/fap_utilities.h b/examples/cpp/fap_utilities.h index 2479e70b64..6168f320da 100644 --- a/examples/cpp/fap_utilities.h +++ b/examples/cpp/fap_utilities.h @@ -1,4 +1,4 @@ -// Copyright 2010-2013 Google +// Copyright 2010-2014 Google // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at diff --git a/examples/cpp/flexible_jobshop.cc b/examples/cpp/flexible_jobshop.cc index bcfb23f48e..0e0a0eea17 100644 --- a/examples/cpp/flexible_jobshop.cc +++ b/examples/cpp/flexible_jobshop.cc @@ -1,4 +1,4 @@ -// Copyright 2010-2013 Google +// Copyright 2010-2014 Google // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at diff --git a/examples/cpp/flexible_jobshop.h b/examples/cpp/flexible_jobshop.h index a1a219cdcf..a16f2cec47 100644 --- a/examples/cpp/flexible_jobshop.h +++ b/examples/cpp/flexible_jobshop.h @@ -1,4 +1,4 @@ -// Copyright 2010-2013 Google +// Copyright 2010-2014 Google // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at diff --git a/examples/cpp/flow_api.cc b/examples/cpp/flow_api.cc index ddeed9880f..813bfcbfbf 100644 --- a/examples/cpp/flow_api.cc +++ b/examples/cpp/flow_api.cc @@ -1,4 +1,4 @@ -// Copyright 2010-2013 Google +// Copyright 2010-2014 Google // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at diff --git a/examples/cpp/frequency_assignment_problem.cc b/examples/cpp/frequency_assignment_problem.cc index 6a54ae29a2..0a0788e393 100644 --- a/examples/cpp/frequency_assignment_problem.cc +++ b/examples/cpp/frequency_assignment_problem.cc @@ -1,4 +1,4 @@ -// Copyright 2010-2013 Google +// Copyright 2010-2014 Google // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at diff --git a/examples/cpp/golomb.cc b/examples/cpp/golomb.cc index 17cb8ef6bf..468cbae6f1 100644 --- a/examples/cpp/golomb.cc +++ b/examples/cpp/golomb.cc @@ -1,4 +1,4 @@ -// Copyright 2010-2013 Google +// Copyright 2010-2014 Google // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at diff --git a/examples/cpp/integer_programming.cc b/examples/cpp/integer_programming.cc index 66a2dd125c..0c93a8da66 100644 --- a/examples/cpp/integer_programming.cc +++ b/examples/cpp/integer_programming.cc @@ -1,4 +1,4 @@ -// Copyright 2010-2013 Google +// Copyright 2010-2014 Google // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at diff --git a/examples/cpp/jobshop.cc b/examples/cpp/jobshop.cc index 55e26e772c..e3214e5e39 100644 --- a/examples/cpp/jobshop.cc +++ b/examples/cpp/jobshop.cc @@ -1,4 +1,4 @@ -// Copyright 2010-2013 Google +// Copyright 2010-2014 Google // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at diff --git a/examples/cpp/jobshop.h b/examples/cpp/jobshop.h index 759437b111..3dbb6d4d07 100644 --- a/examples/cpp/jobshop.h +++ b/examples/cpp/jobshop.h @@ -1,4 +1,4 @@ -// Copyright 2010-2013 Google +// Copyright 2010-2014 Google // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at diff --git a/examples/cpp/jobshop_earlytardy.cc b/examples/cpp/jobshop_earlytardy.cc index 1fc02db29d..1b9c85bd7e 100644 --- a/examples/cpp/jobshop_earlytardy.cc +++ b/examples/cpp/jobshop_earlytardy.cc @@ -1,4 +1,4 @@ -// Copyright 2010-2013 Google +// Copyright 2010-2014 Google // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at diff --git a/examples/cpp/jobshop_earlytardy.h b/examples/cpp/jobshop_earlytardy.h index 6ed9425e62..5958e641db 100644 --- a/examples/cpp/jobshop_earlytardy.h +++ b/examples/cpp/jobshop_earlytardy.h @@ -1,4 +1,4 @@ -// Copyright 2010-2013 Google +// Copyright 2010-2014 Google // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at diff --git a/examples/cpp/jobshop_ls.cc b/examples/cpp/jobshop_ls.cc index 025da4f7a4..fa4add06a6 100644 --- a/examples/cpp/jobshop_ls.cc +++ b/examples/cpp/jobshop_ls.cc @@ -1,4 +1,4 @@ -// Copyright 2010-2013 Google +// Copyright 2010-2014 Google // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at diff --git a/examples/cpp/jobshop_ls.h b/examples/cpp/jobshop_ls.h index 474fa61679..6f15185cff 100644 --- a/examples/cpp/jobshop_ls.h +++ b/examples/cpp/jobshop_ls.h @@ -1,4 +1,4 @@ -// Copyright 2010-2013 Google +// Copyright 2010-2014 Google // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at diff --git a/examples/cpp/linear_assignment_api.cc b/examples/cpp/linear_assignment_api.cc index 5d803f01ac..da07804582 100644 --- a/examples/cpp/linear_assignment_api.cc +++ b/examples/cpp/linear_assignment_api.cc @@ -1,4 +1,4 @@ -// Copyright 2010-2013 Google +// Copyright 2010-2014 Google // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at diff --git a/examples/cpp/linear_programming.cc b/examples/cpp/linear_programming.cc index 9b78bf1775..32e8b15794 100644 --- a/examples/cpp/linear_programming.cc +++ b/examples/cpp/linear_programming.cc @@ -1,4 +1,4 @@ -// Copyright 2010-2013 Google +// Copyright 2010-2014 Google // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at diff --git a/examples/cpp/linear_solver_protocol_buffers.cc b/examples/cpp/linear_solver_protocol_buffers.cc index 855ed5919e..a4b95e4926 100644 --- a/examples/cpp/linear_solver_protocol_buffers.cc +++ b/examples/cpp/linear_solver_protocol_buffers.cc @@ -1,4 +1,4 @@ -// Copyright 2010-2013 Google +// Copyright 2010-2014 Google // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at @@ -63,16 +63,18 @@ void BuildLinearProgrammingMaxExample(MPSolver::OptimizationProblemType type) { new_proto::MPModelRequest model_request; model_request.mutable_model()->CopyFrom(model_proto); -#if defined(USE_GLPK) - if (type == MPSolver::GLPK_LINEAR_PROGRAMMING) { - model_request.set_solver_type(new_proto::MPModelRequest::GLPK_LINEAR_PROGRAMMING); + #if defined(USE_GLOP) + if (type == MPSolver::GLOP_LINEAR_PROGRAMMING) { + model_request.set_solver_type( + new_proto::MPModelRequest::GLOP_LINEAR_PROGRAMMING); } -#endif // USE_GLPK -#if defined(USE_CLP) + #endif // USE_GLOP + #if defined(USE_CLP) if (type == MPSolver::CLP_LINEAR_PROGRAMMING) { - model_request.set_solver_type(new_proto::MPModelRequest::CLP_LINEAR_PROGRAMMING); + model_request.set_solver_type( + new_proto::MPModelRequest::CLP_LINEAR_PROGRAMMING); } -#endif // USE_CLP + #endif // USE_CLP new_proto::MPSolutionResponse solution_response; MPSolver::SolveWithProto(model_request, &solution_response); @@ -88,14 +90,14 @@ void BuildLinearProgrammingMaxExample(MPSolver::OptimizationProblemType type) { } void RunAllExamples() { -#if defined(USE_GLPK) - LOG(INFO) << "----- Running Max Example with GLPK -----"; - BuildLinearProgrammingMaxExample(MPSolver::GLPK_LINEAR_PROGRAMMING); -#endif // USE_GLPK -#if defined(USE_CLP) + #if defined(USE_GLOP) + LOG(INFO) << "----- Running Max Example with GLOP -----"; + BuildLinearProgrammingMaxExample(MPSolver::GLOP_LINEAR_PROGRAMMING); + #endif // USE_GLOP + #if defined(USE_CLP) LOG(INFO) << "----- Running Max Example with Coin LP -----"; BuildLinearProgrammingMaxExample(MPSolver::CLP_LINEAR_PROGRAMMING); -#endif // USE_CLP + #endif // USE_CLP } } // namespace operations_research diff --git a/examples/cpp/ls_api.cc b/examples/cpp/ls_api.cc index c5a0fd44cf..333a353270 100644 --- a/examples/cpp/ls_api.cc +++ b/examples/cpp/ls_api.cc @@ -1,4 +1,4 @@ -// Copyright 2010-2013 Google +// Copyright 2010-2014 Google // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at diff --git a/examples/cpp/magic_square.cc b/examples/cpp/magic_square.cc index 9e893d436f..681626f8ca 100644 --- a/examples/cpp/magic_square.cc +++ b/examples/cpp/magic_square.cc @@ -1,4 +1,4 @@ -// Copyright 2010-2013 Google +// Copyright 2010-2014 Google // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at diff --git a/examples/cpp/model_util.cc b/examples/cpp/model_util.cc index 888182c0ae..f3d218d30a 100644 --- a/examples/cpp/model_util.cc +++ b/examples/cpp/model_util.cc @@ -1,4 +1,4 @@ -// Copyright 2010-2013 Google +// Copyright 2010-2014 Google // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at diff --git a/examples/cpp/mps_driver.cc b/examples/cpp/mps_driver.cc index 728a3077f6..76e15b892f 100644 --- a/examples/cpp/mps_driver.cc +++ b/examples/cpp/mps_driver.cc @@ -1,4 +1,4 @@ -// Copyright 2010-2013 Google +// Copyright 2010-2014 Google // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at diff --git a/examples/cpp/multidim_knapsack.cc b/examples/cpp/multidim_knapsack.cc index 29320b6a30..deed8f188a 100644 --- a/examples/cpp/multidim_knapsack.cc +++ b/examples/cpp/multidim_knapsack.cc @@ -1,4 +1,4 @@ -// Copyright 2010-2013 Google +// Copyright 2010-2014 Google // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at @@ -26,6 +26,7 @@ #include "base/filelinereader.h" #include "base/split.h" #include "constraint_solver/constraint_solver.h" +#include "constraint_solver/hybrid.h" DEFINE_string( data_file, "", @@ -171,7 +172,9 @@ class MultiDimKnapsackData { } break; } - case 6: { break; } + case 6: { + break; + } } } else { // 0 = init @@ -304,7 +307,7 @@ void SolveKnapsack(MultiDimKnapsackData* const data) { if (FLAGS_simplex_frequency > 0) { SearchMonitor* const simplex = - solver.MakeSimplexConstraint(FLAGS_simplex_frequency); + MakeSimplexConstraint(&solver, FLAGS_simplex_frequency); monitors.push_back(simplex); } diff --git a/examples/cpp/network_routing.cc b/examples/cpp/network_routing.cc index 038f89e468..2ab9c094cf 100644 --- a/examples/cpp/network_routing.cc +++ b/examples/cpp/network_routing.cc @@ -1,4 +1,4 @@ -// Copyright 2010-2013 Google +// Copyright 2010-2014 Google // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at diff --git a/examples/cpp/nqueens.cc b/examples/cpp/nqueens.cc index ed4ab43199..7177f6095f 100644 --- a/examples/cpp/nqueens.cc +++ b/examples/cpp/nqueens.cc @@ -1,4 +1,4 @@ -// Copyright 2010-2013 Google +// Copyright 2010-2014 Google // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at diff --git a/examples/cpp/opb_reader.h b/examples/cpp/opb_reader.h index 34c540cee4..d004c4692c 100644 --- a/examples/cpp/opb_reader.h +++ b/examples/cpp/opb_reader.h @@ -1,4 +1,4 @@ -// Copyright 2010-2013 Google +// Copyright 2010-2014 Google // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at diff --git a/examples/cpp/parse_dimacs_assignment.cc b/examples/cpp/parse_dimacs_assignment.cc index 1de452d179..73c6a8976f 100644 --- a/examples/cpp/parse_dimacs_assignment.cc +++ b/examples/cpp/parse_dimacs_assignment.cc @@ -1,4 +1,4 @@ -// Copyright 2010-2013 Google +// Copyright 2010-2014 Google // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at diff --git a/examples/cpp/parse_dimacs_assignment.h b/examples/cpp/parse_dimacs_assignment.h index ad72ed324d..ed19551cf7 100644 --- a/examples/cpp/parse_dimacs_assignment.h +++ b/examples/cpp/parse_dimacs_assignment.h @@ -1,4 +1,4 @@ -// Copyright 2010-2013 Google +// Copyright 2010-2014 Google // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at diff --git a/examples/cpp/pdptw.cc b/examples/cpp/pdptw.cc index edaa7ff44d..c1deff18d8 100644 --- a/examples/cpp/pdptw.cc +++ b/examples/cpp/pdptw.cc @@ -1,4 +1,4 @@ -// Copyright 2010-2013 Google +// Copyright 2010-2014 Google // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at diff --git a/examples/cpp/print_dimacs_assignment.cc b/examples/cpp/print_dimacs_assignment.cc index 4685f0683a..4098821e38 100644 --- a/examples/cpp/print_dimacs_assignment.cc +++ b/examples/cpp/print_dimacs_assignment.cc @@ -1,4 +1,4 @@ -// Copyright 2010-2013 Google +// Copyright 2010-2014 Google // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at diff --git a/examples/cpp/print_dimacs_assignment.h b/examples/cpp/print_dimacs_assignment.h index 91763bfd70..8105ca22c4 100644 --- a/examples/cpp/print_dimacs_assignment.h +++ b/examples/cpp/print_dimacs_assignment.h @@ -1,4 +1,4 @@ -// Copyright 2010-2013 Google +// Copyright 2010-2014 Google // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at diff --git a/examples/cpp/sat_cnf_reader.h b/examples/cpp/sat_cnf_reader.h index bc305c8cae..ea4491db07 100644 --- a/examples/cpp/sat_cnf_reader.h +++ b/examples/cpp/sat_cnf_reader.h @@ -1,4 +1,4 @@ -// Copyright 2010-2013 Google +// Copyright 2010-2014 Google // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at diff --git a/examples/cpp/sat_runner.cc b/examples/cpp/sat_runner.cc index cce31cb86e..cc1e3b4cd0 100644 --- a/examples/cpp/sat_runner.cc +++ b/examples/cpp/sat_runner.cc @@ -1,4 +1,4 @@ -// Copyright 2010-2013 Google +// Copyright 2010-2014 Google // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at diff --git a/examples/cpp/solve.cc b/examples/cpp/solve.cc index b63b97b96d..fbb3f9a8b7 100644 --- a/examples/cpp/solve.cc +++ b/examples/cpp/solve.cc @@ -1,4 +1,4 @@ -// Copyright 2010-2013 Google +// Copyright 2010-2014 Google // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at diff --git a/examples/cpp/sports_scheduling.cc b/examples/cpp/sports_scheduling.cc index 911864d2d0..3e00e57c58 100644 --- a/examples/cpp/sports_scheduling.cc +++ b/examples/cpp/sports_scheduling.cc @@ -1,4 +1,4 @@ -// Copyright 2010-2013 Google +// Copyright 2010-2014 Google // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at diff --git a/examples/cpp/strawberry_fields_with_column_generation.cc b/examples/cpp/strawberry_fields_with_column_generation.cc index 38992fcab7..97e779505e 100644 --- a/examples/cpp/strawberry_fields_with_column_generation.cc +++ b/examples/cpp/strawberry_fields_with_column_generation.cc @@ -1,4 +1,4 @@ -// Copyright 2010-2013 Google +// Copyright 2010-2014 Google // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at diff --git a/examples/cpp/tsp.cc b/examples/cpp/tsp.cc index 979c160b4c..649d7bd462 100644 --- a/examples/cpp/tsp.cc +++ b/examples/cpp/tsp.cc @@ -1,4 +1,4 @@ -// Copyright 2010-2013 Google +// Copyright 2010-2014 Google // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at