constraint_solver: fixup

This commit is contained in:
Corentin Le Molgat
2022-06-22 10:37:50 +02:00
parent ec506600dc
commit e88481eeec
6 changed files with 113 additions and 124 deletions

View File

@@ -3359,35 +3359,29 @@ class PathState::NodeRange {
const CommittedNode* const first_node_;
};
// This checker enforces unary dimension requirements.
// A unary dimension requires that there is some valuation of
// node_capacity and demand such that for all paths,
// if arc A -> B is on a path of path_class p,
// then node_capacity[A] + demand[p][A] = node_capacity[B].
// Moreover, all node_capacities of a path must be inside interval
// path_capacity[path].
// Note that Intervals have two meanings:
// - for demand and node_capacity, those are values allowed for each associated
// decision variable.
// - for path_capacity, those are set of values that node_capacities of the path
// must respect.
// If the path capacity of a path is [kint64min, kint64max],
// then the unary dimension requirements are not enforced on this path.
class UnaryDimensionChecker {
// This checker enforces dimension requirements.
// A dimension requires that there is some valuation of
// cumul and demand such that for all paths:
// - cumul[A] is in interval node_capacity[A]
// - if arc A -> B is on a path of path_class p,
// then cumul[A] + demand[p](A, B) = cumul[B].
// - if A is on a path of class p, then
// cumul[A] must be inside interval path_capacity[path].
class DimensionChecker {
public:
struct Interval {
int64_t min;
int64_t max;
};
UnaryDimensionChecker(const PathState* path_state,
std::vector<Interval> path_capacity,
std::vector<int> path_class,
std::vector<std::function<Interval(int64_t)>>
min_max_demand_per_path_class,
std::vector<Interval> node_capacity);
DimensionChecker(const PathState* path_state,
std::vector<Interval> path_capacity,
std::vector<int> path_class,
std::vector<std::function<Interval(int64_t)>>
min_max_demand_per_path_class,
std::vector<Interval> node_capacity);
// Given the change made in PathState, checks that the unary dimension
// Given the change made in PathState, checks that the dimension
// constraint is still feasible.
bool Check() const;
@@ -3469,14 +3463,14 @@ LocalSearchFilter* MakePathStateFilter(Solver* solver,
const std::vector<IntVar*>& nexts);
// Make a filter that translates solver events to the input checker's interface.
// Since UnaryDimensionChecker has a PathState, the filter returned by this
// Since DimensionChecker has a PathState, the filter returned by this
// must be synchronized to the corresponding PathStateFilter:
// - Relax() must be called after the PathStateFilter's.
// - Accept() must be called after.
// - Synchronize() must be called before.
// - Revert() must be called before.
LocalSearchFilter* MakeUnaryDimensionFilter(
Solver* solver, std::unique_ptr<UnaryDimensionChecker> checker,
LocalSearchFilter* MakeDimensionFilter(
Solver* solver, std::unique_ptr<DimensionChecker> checker,
const std::string& dimension_name);
#endif // !defined(SWIG)

View File

@@ -2760,7 +2760,7 @@ class PathStateFilter : public LocalSearchFilter {
// Selection-based algorithm in O(n^2), to use for small change sets.
void MakeChainsFromChangedPathsAndArcsWithSelectionAlgorithm();
// From changed_paths_ and changed_arcs_, fill chains_ and paths_.
// Generic algorithm in O(sort(n)+n), to use for larger change sets.
// Generic algorithm in O(std::sort(n)+n), to use for larger change sets.
void MakeChainsFromChangedPathsAndArcsWithGenericAlgorithm();
const std::unique_ptr<PathState> path_state_;
@@ -3007,7 +3007,7 @@ LocalSearchFilter* MakePathStateFilter(Solver* solver,
}
namespace {
using Interval = UnaryDimensionChecker::Interval;
using Interval = DimensionChecker::Interval;
Interval Intersect(const Interval& i1, const Interval& i2) {
return {std::max(i1.min, i2.min), std::min(i1.max, i2.max)};
@@ -3032,7 +3032,7 @@ Interval Delta(const Interval& from, const Interval& to) {
}
} // namespace
UnaryDimensionChecker::UnaryDimensionChecker(
DimensionChecker::DimensionChecker(
const PathState* path_state, std::vector<Interval> path_capacity,
std::vector<int> path_class,
std::vector<std::function<Interval(int64_t)>> min_max_demand_per_path_class,
@@ -3057,7 +3057,7 @@ UnaryDimensionChecker::UnaryDimensionChecker(
FullCommit();
}
bool UnaryDimensionChecker::Check() const {
bool DimensionChecker::Check() const {
if (path_state_->IsInvalid()) return true;
for (const int path : path_state_->ChangedPaths()) {
const Interval path_capacity = path_capacity_[path];
@@ -3079,7 +3079,7 @@ bool UnaryDimensionChecker::Check() const {
chain_path == -1 ? -1 : path_class_[chain_path];
// Call the RIQ if the chain size is large enough;
// the optimal value was found with the associated benchmark in tests,
// in particular BM_UnaryDimensionChecker<ChangeSparsity::kSparse, *>.
// in particular BM_DimensionChecker<ChangeSparsity::kSparse, *>.
constexpr int kMinRangeSizeForRIQ = 4;
const bool chain_is_cached = chain_path_class == path_class;
if (last_index - first_index > kMinRangeSizeForRIQ && chain_is_cached &&
@@ -3116,7 +3116,7 @@ bool UnaryDimensionChecker::Check() const {
return true;
}
void UnaryDimensionChecker::Commit() {
void DimensionChecker::Commit() {
const int current_layer_size = backwards_demand_sums_riq_[0].size();
int change_size = path_state_->ChangedPaths().size();
for (const int path : path_state_->ChangedPaths()) {
@@ -3131,7 +3131,7 @@ void UnaryDimensionChecker::Commit() {
}
}
void UnaryDimensionChecker::IncrementalCommit() {
void DimensionChecker::IncrementalCommit() {
for (const int path : path_state_->ChangedPaths()) {
const int begin_index = backwards_demand_sums_riq_[0].size();
AppendPathDemandsToSums(path);
@@ -3139,7 +3139,7 @@ void UnaryDimensionChecker::IncrementalCommit() {
}
}
void UnaryDimensionChecker::FullCommit() {
void DimensionChecker::FullCommit() {
// Clear all structures.
previous_nontrivial_index_.clear();
for (auto& sums : backwards_demand_sums_riq_) sums.clear();
@@ -3152,7 +3152,7 @@ void UnaryDimensionChecker::FullCommit() {
}
}
void UnaryDimensionChecker::AppendPathDemandsToSums(int path) {
void DimensionChecker::AppendPathDemandsToSums(int path) {
const int path_class = path_class_[path];
// Compute sum of all demands for this path.
// TODO(user): backwards Nodes() iterator, to compute sum directly.
@@ -3183,7 +3183,7 @@ void UnaryDimensionChecker::AppendPathDemandsToSums(int path) {
}
}
void UnaryDimensionChecker::UpdateRIQStructure(int begin_index, int end_index) {
void DimensionChecker::UpdateRIQStructure(int begin_index, int end_index) {
// The max layer is the one used by
// GetMinMaxPartialDemandSum(begin_index, end_index - 1).
const int maximum_riq_exponent =
@@ -3210,8 +3210,7 @@ void UnaryDimensionChecker::UpdateRIQStructure(int begin_index, int end_index) {
// For instance, if this is only called when the range size is > 4
// and paths are <= 32 nodes long, then we only need layers 0, 2, 3, and 4.
// To compare, on a 512 < #nodes <= 1024 problem, this uses layers in [0, 10].
UnaryDimensionChecker::Interval
UnaryDimensionChecker::GetTightestBackwardsDemandSum(
DimensionChecker::Interval DimensionChecker::GetTightestBackwardsDemandSum(
int first_node_index, int last_node_index) const {
DCHECK_LE(0, first_node_index);
DCHECK_LT(first_node_index, last_node_index);
@@ -3228,8 +3227,8 @@ UnaryDimensionChecker::GetTightestBackwardsDemandSum(
return Intersect(i1, i2);
}
bool UnaryDimensionChecker::SubpathOnlyHasTrivialNodes(
int first_node_index, int last_node_index) const {
bool DimensionChecker::SubpathOnlyHasTrivialNodes(int first_node_index,
int last_node_index) const {
DCHECK_LE(0, first_node_index);
DCHECK_LT(first_node_index, last_node_index);
DCHECK_LT(last_node_index, previous_nontrivial_index_.size());
@@ -3238,13 +3237,13 @@ bool UnaryDimensionChecker::SubpathOnlyHasTrivialNodes(
namespace {
class UnaryDimensionFilter : public LocalSearchFilter {
class DimensionFilter : public LocalSearchFilter {
public:
std::string DebugString() const override { return name_; }
UnaryDimensionFilter(std::unique_ptr<UnaryDimensionChecker> checker,
const std::string& dimension_name)
DimensionFilter(std::unique_ptr<DimensionChecker> checker,
const std::string& dimension_name)
: checker_(std::move(checker)),
name_(absl::StrCat("UnaryDimensionFilter(", dimension_name, ")")) {}
name_(absl::StrCat("DimensionFilter(", dimension_name, ")")) {}
bool Accept(const Assignment* delta, const Assignment* deltadelta,
int64_t objective_min, int64_t objective_max) override {
@@ -3257,17 +3256,17 @@ class UnaryDimensionFilter : public LocalSearchFilter {
}
private:
std::unique_ptr<UnaryDimensionChecker> checker_;
std::unique_ptr<DimensionChecker> checker_;
const std::string name_;
};
} // namespace
LocalSearchFilter* MakeUnaryDimensionFilter(
Solver* solver, std::unique_ptr<UnaryDimensionChecker> checker,
LocalSearchFilter* MakeDimensionFilter(
Solver* solver, std::unique_ptr<DimensionChecker> checker,
const std::string& dimension_name) {
UnaryDimensionFilter* filter =
new UnaryDimensionFilter(std::move(checker), dimension_name);
DimensionFilter* filter =
new DimensionFilter(std::move(checker), dimension_name);
return solver->RevAlloc(filter);
}

View File

@@ -976,7 +976,7 @@ class ResourceAssignmentConstraint : public Constraint {
ResourceAssignmentOptimizer resource_assignment_optimizer(
&resource_group_, optimizer, mp_optimizer);
const auto transit = [&dimension](int64_t node, int64_t next) {
const auto transit = [&dimension](int64_t node, int64_t /*next*/) {
// TODO(user): Get rid of this max() by only allowing resources on
// dimensions with positive transits (model.AreVehicleTransitsPositive()).
// TODO(user): The transit lower bounds have not necessarily been
@@ -1103,7 +1103,7 @@ Constraint* MakeResourceConstraint(
// Evaluators
template <class A, class B>
static int64_t ReturnZero(A a, B b) {
static int64_t ReturnZero(A, B) {
return 0;
}
@@ -1271,7 +1271,7 @@ int RoutingModel::RegisterUnaryTransitVector(std::vector<int64_t> values) {
int RoutingModel::RegisterUnaryTransitCallback(TransitCallback1 callback) {
const int index = unary_transit_evaluators_.size();
unary_transit_evaluators_.push_back(std::move(callback));
return RegisterTransitCallback([this, index](int i, int j) {
return RegisterTransitCallback([this, index](int i, int /*j*/) {
return unary_transit_evaluators_[index](i);
});
}
@@ -1422,7 +1422,6 @@ bool RoutingModel::InitializeDimensionInternal(
const DimensionIndex dimension_index(dimensions_.size());
dimension_name_to_index_[dimension->name()] = dimension_index;
dimensions_.push_back(dimension);
dimension_cumuls_optimized_with_cumul_dependent_transits_.push_back(false);
dimension->Initialize(evaluator_indices, state_dependent_evaluator_indices,
slack_max);
solver_->AddConstraint(solver_->MakeDelayedPathCumul(
@@ -1851,7 +1850,7 @@ const RoutingModel::CostClassIndex RoutingModel::kCostClassIndexOfZeroCost =
CostClassIndex(0);
void RoutingModel::ComputeCostClasses(
const RoutingSearchParameters& parameters) {
const RoutingSearchParameters& /*parameters*/) {
// Create and reduce the cost classes.
cost_classes_.reserve(vehicles_);
cost_classes_.clear();
@@ -2525,7 +2524,7 @@ class RoutingModelInspector : public ModelVisitor {
RegisterInspectors();
}
~RoutingModelInspector() override {}
void EndVisitModel(const std::string& solver_name) override {
void EndVisitModel(const std::string& /*solver_name*/) override {
const std::vector<int> node_to_same_vehicle_component_id =
same_vehicle_components_.GetComponentIds();
model_->InitSameVehicleGroups(
@@ -2538,18 +2537,18 @@ class RoutingModelInspector : public ModelVisitor {
// TODO(user): Have a single annotated precedence graph.
}
void EndVisitConstraint(const std::string& type_name,
const Constraint* const constraint) override {
const Constraint* const /*constraint*/) override {
gtl::FindWithDefault(constraint_inspectors_, type_name, []() {})();
}
void VisitIntegerExpressionArgument(const std::string& type_name,
IntExpr* const expr) override {
gtl::FindWithDefault(expr_inspectors_, type_name,
[](const IntExpr* expr) {})(expr);
[](const IntExpr*) {})(expr);
}
void VisitIntegerArrayArgument(const std::string& arg_name,
const std::vector<int64_t>& values) override {
gtl::FindWithDefault(array_inspectors_, arg_name,
[](const std::vector<int64_t>& int_array) {})(values);
[](const std::vector<int64_t>&) {})(values);
}
private:
@@ -5113,8 +5112,6 @@ void RoutingModel::StoreDimensionCumulOptimizers(
const int num_dimensions = dimensions_.size();
local_optimizer_index_.resize(num_dimensions, -1);
global_optimizer_index_.resize(num_dimensions, -1);
dimension_local_optimizer_for_cumul_dependent_transits_.resize(
num_dimensions);
if (parameters.disable_scheduling_beware_this_may_degrade_performance()) {
return;
}
@@ -5191,12 +5188,6 @@ void RoutingModel::StoreDimensionCumulOptimizers(
dimension, parameters.continuous_scheduling_solver()),
std::make_unique<LocalDimensionCumulOptimizer>(
dimension, parameters.mixed_integer_scheduling_solver())});
} else if (dimension_cumuls_optimized_with_cumul_dependent_transits_[dim]) {
needs_optimizer = true;
dimension->SetVehicleOffsetsForLocalOptimizer(std::move(vehicle_offsets));
dimension_local_optimizer_for_cumul_dependent_transits_[dim] =
std::make_unique<LocalDimensionCumulOptimizer>(
dimension, parameters.mixed_integer_scheduling_solver());
}
if (needs_optimizer) {
optimized_dimensions_collector_assignment->Add(dimension->cumuls());
@@ -6663,7 +6654,6 @@ void RoutingDimension::InitializeTransits(
InitializeTransitVariables(slack_max);
}
// TODO(user): Apply -pointer-following.
void FillPathEvaluation(const std::vector<int64_t>& path,
const RoutingModel::TransitCallback2& evaluator,
std::vector<int64_t>* values) {
@@ -7288,7 +7278,7 @@ void RoutingDimension::SetBreakIntervalsOfVehicle(
std::vector<int64_t> node_visit_transits) {
if (breaks.empty()) return;
const int visit_evaluator = model()->RegisterTransitCallback(
[node_visit_transits](int64_t from, int64_t to) {
[node_visit_transits](int64_t from, int64_t /*to*/) {
return node_visit_transits[from];
});
SetBreakIntervalsOfVehicle(std::move(breaks), vehicle, visit_evaluator, -1);
@@ -7300,7 +7290,7 @@ void RoutingDimension::SetBreakIntervalsOfVehicle(
std::function<int64_t(int64_t, int64_t)> delays) {
if (breaks.empty()) return;
const int visit_evaluator = model()->RegisterTransitCallback(
[node_visit_transits](int64_t from, int64_t to) {
[node_visit_transits](int64_t from, int64_t /*to*/) {
return node_visit_transits[from];
});
const int delay_evaluator =

View File

@@ -73,8 +73,8 @@ class MaxActiveVehiclesFilter : public IntVarLocalSearchFilter {
routing_model_(routing_model),
is_active_(routing_model.vehicles(), false),
active_vehicles_(0) {}
bool Accept(const Assignment* delta, const Assignment* deltadelta,
int64_t objective_min, int64_t objective_max) override {
bool Accept(const Assignment* delta, const Assignment* /*deltadelta*/,
int64_t /*objective_min*/, int64_t /*objective_max*/) override {
const int64_t kUnassigned = -1;
const Assignment::IntContainer& container = delta->IntVarContainer();
const int delta_size = container.Size();
@@ -103,7 +103,7 @@ class MaxActiveVehiclesFilter : public IntVarLocalSearchFilter {
}
private:
void OnSynchronize(const Assignment* delta) override {
void OnSynchronize(const Assignment* /*delta*/) override {
active_vehicles_ = 0;
for (int i = 0; i < routing_model_.vehicles(); ++i) {
const int index = routing_model_.Start(i);
@@ -144,8 +144,8 @@ class NodeDisjunctionFilter : public IntVarLocalSearchFilter {
filter_cost_(filter_cost),
has_mandatory_disjunctions_(routing_model.HasMandatoryDisjunctions()) {}
bool Accept(const Assignment* delta, const Assignment* deltadelta,
int64_t objective_min, int64_t objective_max) override {
bool Accept(const Assignment* delta, const Assignment* /*deltadelta*/,
int64_t /*objective_min*/, int64_t objective_max) override {
const int64_t kUnassigned = -1;
const Assignment::IntContainer& container = delta->IntVarContainer();
const int delta_size = container.Size();
@@ -236,7 +236,7 @@ class NodeDisjunctionFilter : public IntVarLocalSearchFilter {
}
private:
void OnSynchronize(const Assignment* delta) override {
void OnSynchronize(const Assignment* /*delta*/) override {
synchronized_objective_value_ = 0;
for (RoutingModel::DisjunctionIndex i(0);
i < active_per_disjunction_.size(); ++i) {
@@ -301,8 +301,8 @@ BasePathFilter::BasePathFilter(const std::vector<IntVar*>& nexts,
lns_detected_(false) {}
bool BasePathFilter::Accept(const Assignment* delta,
const Assignment* deltadelta, int64_t objective_min,
int64_t objective_max) {
const Assignment* /*deltadelta*/,
int64_t objective_min, int64_t objective_max) {
if (IsDisabled()) return true;
lns_detected_ = false;
for (const int touched : delta_touched_) {
@@ -660,7 +660,7 @@ bool VehicleAmortizedCostFilter::AcceptPath(int64_t path_start,
return true;
}
bool VehicleAmortizedCostFilter::FinalizeAcceptPath(int64_t objective_min,
bool VehicleAmortizedCostFilter::FinalizeAcceptPath(int64_t /*objective_min*/,
int64_t objective_max) {
return delta_vehicle_cost_ <= objective_max;
}
@@ -1078,12 +1078,11 @@ class PathCumulFilter : public BasePathFilter {
// The DimensionCumulOptimizer is used to compute a more precise value of
// the cost related to the cumul values (soft bounds and span costs).
// It is also used to garantee feasibility with complex mixes of constraints
// and in particular in the presence of break requests along other
// constraints.
// Therefore, without breaks, we only use the optimizer when the costs are
// actually used to filter the solutions, i.e. when filter_objective_cost_
// is true.
// It is also used to guarantee feasibility with complex mixes of
// constraints and in particular in the presence of break requests along
// other constraints. Therefore, without breaks, we only use the optimizer
// when the costs are actually used to filter the solutions, i.e. when
// filter_objective_cost_ is true.
return num_linear_constraints >= 2 &&
(has_breaks || filter_objective_cost_);
}
@@ -1580,8 +1579,8 @@ void PathCumulFilter::OnBeforeSynchronizePaths() {
current_min_start_.cumul_value)));
}
bool PathCumulFilter::AcceptPath(int64_t path_start, int64_t chain_start,
int64_t chain_end) {
bool PathCumulFilter::AcceptPath(int64_t path_start, int64_t /*chain_start*/,
int64_t /*chain_end*/) {
int64_t node = path_start;
int64_t cumul = cumuls_[node]->Min();
int64_t cumul_cost_delta = 0;
@@ -1722,7 +1721,7 @@ bool PathCumulFilter::AcceptPath(int64_t path_start, int64_t chain_start,
StoreMinMaxCumulOfNodesOnPath(path, min_path_cumuls, /*is_delta=*/true);
}
if (!filter_vehicle_costs) {
// If this route's costs should't be taken into account, reset the
// If this route's costs shouldn't be taken into account, reset the
// cumul_cost_delta and delta_path_transits_ for this path.
cumul_cost_delta = 0;
delta_path_transits_.ClearPath(path);
@@ -1742,7 +1741,7 @@ bool PathCumulFilter::AcceptPath(int64_t path_start, int64_t chain_start,
return true;
}
bool PathCumulFilter::FinalizeAcceptPath(int64_t objective_min,
bool PathCumulFilter::FinalizeAcceptPath(int64_t /*objective_min*/,
int64_t objective_max) {
DCHECK(!lns_detected());
if (!FilterSpanCost() && !FilterCumulSoftBounds() && !FilterSlackCost() &&
@@ -2100,12 +2099,12 @@ void AppendLightWeightDimensionFilters(
const PathState* path_state,
const std::vector<RoutingDimension*>& dimensions,
std::vector<LocalSearchFilterManager::FilterEvent>* filters) {
// For every dimension that fits, add a UnaryDimensionChecker.
// For every dimension that fits, add a DimensionChecker.
for (const RoutingDimension* dimension : dimensions) {
// Skip dimension if not unary.
if (dimension->GetUnaryTransitEvaluator(0) == nullptr) continue;
using Intervals = std::vector<UnaryDimensionChecker::Interval>;
using Intervals = std::vector<DimensionChecker::Interval>;
// Fill path capacities and classes.
const int num_vehicles = dimension->model()->vehicles();
Intervals path_capacity(num_vehicles);
@@ -2118,13 +2117,13 @@ void AppendLightWeightDimensionFilters(
// For each class, retrieve the demands of each node.
// Dimension store evaluators with a double indirection for compacity:
// vehicle -> vehicle_class -> evaluator_index.
// We replicate this in UnaryDimensionChecker,
// We replicate this in DimensionChecker,
// except we expand evaluator_index to an array of values for all nodes.
const int num_vehicle_classes =
1 + *std::max_element(path_class.begin(), path_class.end());
const int num_cumuls = dimension->cumuls().size();
const int num_slacks = dimension->slacks().size();
using Interval = UnaryDimensionChecker::Interval;
using Interval = DimensionChecker::Interval;
std::vector<std::function<Interval(int64_t)>> transits(num_vehicle_classes,
nullptr);
for (int vehicle = 0; vehicle < num_vehicles; ++vehicle) {
@@ -2147,11 +2146,11 @@ void AppendLightWeightDimensionFilters(
node_capacity[node] = {cumul->Min(), cumul->Max()};
}
// Make the dimension checker and pass ownership to the filter.
auto checker = std::make_unique<UnaryDimensionChecker>(
auto checker = std::make_unique<DimensionChecker>(
path_state, std::move(path_capacity), std::move(path_class),
std::move(transits), std::move(node_capacity));
const auto kAccept = LocalSearchFilterManager::FilterEventType::kAccept;
LocalSearchFilter* filter = MakeUnaryDimensionFilter(
LocalSearchFilter* filter = MakeDimensionFilter(
dimension->model()->solver(), std::move(checker), dimension->name());
filters->push_back({filter, kAccept});
}
@@ -2312,8 +2311,9 @@ PickupDeliveryFilter::PickupDeliveryFilter(
}
}
bool PickupDeliveryFilter::AcceptPath(int64_t path_start, int64_t chain_start,
int64_t chain_end) {
bool PickupDeliveryFilter::AcceptPath(int64_t path_start,
int64_t /*chain_start*/,
int64_t /*chain_end*/) {
switch (vehicle_policies_[GetPath(path_start)]) {
case RoutingModel::PICKUP_AND_DELIVERY_NO_ORDER:
return AcceptPathDefault(path_start);
@@ -2553,9 +2553,9 @@ CumulBoundsPropagatorFilter::CumulBoundsPropagatorFilter(
delta_nexts_(Size()) {}
bool CumulBoundsPropagatorFilter::Accept(const Assignment* delta,
const Assignment* deltadelta,
int64_t objective_min,
int64_t objective_max) {
const Assignment* /*deltadelta*/,
int64_t /*objective_min*/,
int64_t /*objective_max*/) {
delta_touched_.ClearAll();
for (const IntVarElement& delta_element :
delta->IntVarContainer().elements()) {
@@ -2625,8 +2625,8 @@ LPCumulFilter::LPCumulFilter(const std::vector<IntVar*>& nexts,
delta_nexts_(Size()) {}
bool LPCumulFilter::Accept(const Assignment* delta,
const Assignment* deltadelta, int64_t objective_min,
int64_t objective_max) {
const Assignment* /*deltadelta*/,
int64_t /*objective_min*/, int64_t objective_max) {
delta_touched_.ClearAll();
for (const IntVarElement& delta_element :
delta->IntVarContainer().elements()) {
@@ -2648,11 +2648,10 @@ bool LPCumulFilter::Accept(const Assignment* delta,
// No need to compute the cost of the LP, only verify its feasibility.
delta_cost_without_transit_ = 0;
const DimensionSchedulingStatus status =
optimizer_.ComputeCumuls(next_accessor, {}, nullptr, nullptr, nullptr);
optimizer_.ComputeCumuls(next_accessor, nullptr, nullptr, nullptr);
if (status == DimensionSchedulingStatus::OPTIMAL) return true;
if (status == DimensionSchedulingStatus::RELAXED_OPTIMAL_ONLY &&
mp_optimizer_.ComputeCumuls(next_accessor, {}, nullptr, nullptr,
nullptr) ==
mp_optimizer_.ComputeCumuls(next_accessor, nullptr, nullptr, nullptr) ==
DimensionSchedulingStatus::OPTIMAL) {
return true;
}
@@ -2682,7 +2681,7 @@ int64_t LPCumulFilter::GetAcceptedObjectiveValue() const {
return delta_cost_without_transit_;
}
void LPCumulFilter::OnSynchronize(const Assignment* delta) {
void LPCumulFilter::OnSynchronize(const Assignment* /*delta*/) {
// TODO(user): Try to optimize this so the LP is not called when the last
// computed delta cost corresponds to the solution being synchronized.
const RoutingModel& model = *optimizer_.dimension()->model();
@@ -2805,8 +2804,8 @@ bool ResourceGroupAssignmentFilter::InitializeAcceptPath() {
}
bool ResourceGroupAssignmentFilter::AcceptPath(int64_t path_start,
int64_t chain_start,
int64_t chain_end) {
int64_t /*chain_start*/,
int64_t /*chain_end*/) {
const int vehicle = model_.VehicleIndex(path_start);
return resource_assignment_optimizer_.ComputeAssignmentCostsForVehicle(
vehicle, [this](int64_t index) { return GetNext(index); },
@@ -2814,8 +2813,8 @@ bool ResourceGroupAssignmentFilter::AcceptPath(int64_t path_start,
&delta_vehicle_to_resource_assignment_costs_[vehicle], nullptr, nullptr);
}
bool ResourceGroupAssignmentFilter::FinalizeAcceptPath(int64_t objective_min,
int64_t objective_max) {
bool ResourceGroupAssignmentFilter::FinalizeAcceptPath(
int64_t /*objective_min*/, int64_t objective_max) {
delta_cost_without_transit_ =
resource_assignment_optimizer_.ComputeBestAssignmentCost(
delta_vehicle_to_resource_assignment_costs_,
@@ -3000,8 +2999,9 @@ CPFeasibilityFilter::CPFeasibilityFilter(RoutingModel* routing_model)
}
bool CPFeasibilityFilter::Accept(const Assignment* delta,
const Assignment* deltadelta,
int64_t objective_min, int64_t objective_max) {
const Assignment* /*deltadelta*/,
int64_t /*objective_min*/,
int64_t /*objective_max*/) {
temp_assignment_->Copy(assignment_);
AddDeltaToAssignment(delta, temp_assignment_);

View File

@@ -197,7 +197,7 @@ LocalDimensionCumulOptimizer::LocalDimensionCumulOptimizer(
DimensionSchedulingStatus LocalDimensionCumulOptimizer::ComputeRouteCumulCost(
int vehicle, const std::function<int64_t(int64_t)>& next_accessor,
int64_t* optimal_cost) {
return optimizer_core_.OptimizeSingleRoute(vehicle, next_accessor, {},
return optimizer_core_.OptimizeSingleRoute(vehicle, next_accessor,
solver_[vehicle].get(), nullptr,
nullptr, optimal_cost, nullptr);
}
@@ -209,8 +209,8 @@ LocalDimensionCumulOptimizer::ComputeRouteCumulCostWithoutFixedTransits(
int64_t cost = 0;
int64_t transit_cost = 0;
const DimensionSchedulingStatus status = optimizer_core_.OptimizeSingleRoute(
vehicle, next_accessor, {}, solver_[vehicle].get(), nullptr, nullptr,
&cost, &transit_cost);
vehicle, next_accessor, solver_[vehicle].get(), nullptr, nullptr, &cost,
&transit_cost);
if (status != DimensionSchedulingStatus::INFEASIBLE &&
optimal_cost_without_transits != nullptr) {
*optimal_cost_without_transits = CapSub(cost, transit_cost);
@@ -228,7 +228,7 @@ std::vector<DimensionSchedulingStatus> LocalDimensionCumulOptimizer::
std::vector<std::vector<int64_t>>* optimal_cumuls,
std::vector<std::vector<int64_t>>* optimal_breaks) {
return optimizer_core_.OptimizeSingleRouteWithResources(
vehicle, next_accessor, transit_accessor, {}, resources, resource_indices,
vehicle, next_accessor, transit_accessor, resources, resource_indices,
optimize_vehicle_costs, solver_[vehicle].get(),
optimal_costs_without_transits, optimal_cumuls, optimal_breaks);
}
@@ -863,9 +863,11 @@ DimensionCumulOptimizerCore::OptimizeAndPackSingleRoute(
{*resource}, {0}, /*optimize_vehicle_costs=*/true, solver,
&costs_without_transits, /*cumul_values=*/nullptr,
/*break_values=*/nullptr, /*clear_lp=*/false);
DCHECK_EQ(statuses.size(), 1);
if (statuses[0] == DimensionSchedulingStatus::INFEASIBLE) {
if (dimension_->model()->CheckLimit()) {
status = DimensionSchedulingStatus::INFEASIBLE;
} else {
DCHECK_EQ(statuses.size(), 1);
status = statuses[0];
}
}
@@ -1839,8 +1841,8 @@ GlobalDimensionCumulOptimizer::ComputeCumulCostWithoutFixedTransits(
int64_t cost = 0;
int64_t transit_cost = 0;
DimensionSchedulingStatus status =
optimizer_core_.Optimize(next_accessor, {}, solver_.get(), nullptr,
nullptr, nullptr, &cost, &transit_cost);
optimizer_core_.Optimize(next_accessor, solver_.get(), nullptr, nullptr,
nullptr, &cost, &transit_cost);
if (status != DimensionSchedulingStatus::INFEASIBLE &&
optimal_cost_without_transits != nullptr) {
*optimal_cost_without_transits = CapSub(cost, transit_cost);

View File

@@ -360,9 +360,11 @@ class RoutingGlopWrapper : public RoutingLinearSolverWrapper {
linear_program_.SetConstraintBounds(ct, -glop::kInfinity,
normalized_objective_value);
}
void AddMaximumConstraint(int max_var, std::vector<int> vars) override {}
void AddProductConstraint(int product_var, std::vector<int> vars) override {}
void SetEnforcementLiteral(int ct, int condition) override{};
void AddMaximumConstraint(int /*max_var*/,
std::vector<int> /*vars*/) override {}
void AddProductConstraint(int /*product_var*/,
std::vector<int> /*vars*/) override {}
void SetEnforcementLiteral(int /*ct*/, int /*condition*/) override{};
DimensionSchedulingStatus Solve(absl::Duration duration_limit) override {
lp_solver_.GetMutableParameters()->set_max_time_in_seconds(
absl::ToDoubleSeconds(duration_limit));
@@ -449,7 +451,7 @@ class RoutingCPSatWrapper : public RoutingLinearSolverWrapper {
return index;
}
void SetVariableName(int index, absl::string_view name) override {
model_.mutable_variables(index)->set_name(name);
model_.mutable_variables(index)->set_name(name.data());
}
bool SetVariableBounds(int index, int64_t lower_bound,
int64_t upper_bound) override {
@@ -590,7 +592,9 @@ class RoutingCPSatWrapper : public RoutingLinearSolverWrapper {
bool SolutionIsInteger() const override { return true; }
// NOTE: This function is not implemented for the CP-SAT solver.
void SetParameters(const std::string& parameters) override { DCHECK(false); }
void SetParameters(const std::string& /*parameters*/) override {
DCHECK(false);
}
private:
sat::CpModelProto model_;
@@ -650,7 +654,7 @@ class DimensionCumulOptimizerCore {
private:
// Initializes the containers and given solver. Must be called prior to
// setting any contraints and solving.
// setting any constraints and solving.
void InitOptimizer(RoutingLinearSolverWrapper* solver);
// Computes the minimum/maximum of cumuls for nodes on "route", and sets them