2022-06-17 08:40:20 +02:00
|
|
|
// Copyright 2010-2022 Google LLC
|
2018-10-31 16:18:18 +01:00
|
|
|
// 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.
|
|
|
|
|
|
|
|
|
|
#include "ortools/constraint_solver/routing_parameters.h"
|
|
|
|
|
|
2022-07-22 14:35:40 +02:00
|
|
|
#include <cmath>
|
2021-04-01 12:13:35 +02:00
|
|
|
#include <cstdint>
|
2022-01-21 17:51:38 +01:00
|
|
|
#include <string>
|
2022-07-22 14:35:40 +02:00
|
|
|
#include <vector>
|
2021-04-01 12:13:35 +02:00
|
|
|
|
2018-10-31 16:18:18 +01:00
|
|
|
#include "absl/strings/str_cat.h"
|
2022-05-18 16:36:05 +02:00
|
|
|
#include "absl/strings/str_format.h"
|
2018-10-31 16:18:18 +01:00
|
|
|
#include "absl/time/time.h"
|
|
|
|
|
#include "google/protobuf/descriptor.h"
|
|
|
|
|
#include "google/protobuf/duration.pb.h"
|
|
|
|
|
#include "google/protobuf/message.h"
|
|
|
|
|
#include "google/protobuf/text_format.h"
|
|
|
|
|
#include "ortools/base/logging.h"
|
|
|
|
|
#include "ortools/base/protoutil.h"
|
|
|
|
|
#include "ortools/constraint_solver/constraint_solver.h"
|
|
|
|
|
#include "ortools/constraint_solver/routing_enums.pb.h"
|
|
|
|
|
#include "ortools/constraint_solver/solver_parameters.pb.h"
|
2021-08-23 16:08:30 +02:00
|
|
|
#include "ortools/sat/sat_parameters.pb.h"
|
2018-10-31 16:18:18 +01:00
|
|
|
#include "ortools/util/optional_boolean.pb.h"
|
2022-06-21 11:43:36 +02:00
|
|
|
#include "ortools/util/testing_utils.h"
|
2018-10-31 16:18:18 +01:00
|
|
|
|
|
|
|
|
namespace operations_research {
|
|
|
|
|
|
|
|
|
|
RoutingModelParameters DefaultRoutingModelParameters() {
|
|
|
|
|
RoutingModelParameters parameters;
|
2020-10-29 14:25:39 +01:00
|
|
|
ConstraintSolverParameters* const solver_parameters =
|
2018-10-31 16:18:18 +01:00
|
|
|
parameters.mutable_solver_parameters();
|
|
|
|
|
*solver_parameters = Solver::DefaultSolverParameters();
|
|
|
|
|
solver_parameters->set_compress_trail(
|
|
|
|
|
ConstraintSolverParameters::COMPRESS_WITH_ZLIB);
|
|
|
|
|
solver_parameters->set_skip_locally_optimal_paths(true);
|
|
|
|
|
parameters.set_reduce_vehicle_cost_model(true);
|
|
|
|
|
return parameters;
|
|
|
|
|
}
|
|
|
|
|
|
2022-06-21 11:43:36 +02:00
|
|
|
namespace {
|
|
|
|
|
RoutingSearchParameters CreateDefaultRoutingSearchParameters() {
|
|
|
|
|
static constexpr char kSearchParameters[] = R"pb(
|
|
|
|
|
first_solution_strategy: AUTOMATIC
|
|
|
|
|
use_unfiltered_first_solution_strategy: false
|
|
|
|
|
savings_neighbors_ratio: 1
|
|
|
|
|
savings_max_memory_usage_bytes: 6e9
|
|
|
|
|
savings_add_reverse_arcs: false
|
|
|
|
|
savings_arc_coefficient: 1
|
|
|
|
|
savings_parallel_routes: false
|
|
|
|
|
cheapest_insertion_farthest_seeds_ratio: 0
|
|
|
|
|
cheapest_insertion_first_solution_neighbors_ratio: 1
|
|
|
|
|
cheapest_insertion_first_solution_min_neighbors: 1
|
|
|
|
|
cheapest_insertion_ls_operator_neighbors_ratio: 1
|
|
|
|
|
cheapest_insertion_ls_operator_min_neighbors: 1
|
|
|
|
|
cheapest_insertion_first_solution_use_neighbors_ratio_for_initialization:
|
|
|
|
|
false
|
|
|
|
|
cheapest_insertion_add_unperformed_entries: false
|
2022-12-07 17:37:45 +01:00
|
|
|
local_cheapest_insertion_pickup_delivery_strategy:
|
|
|
|
|
BEST_PICKUP_THEN_BEST_DELIVERY
|
2022-06-21 11:43:36 +02:00
|
|
|
local_search_operators {
|
|
|
|
|
use_relocate: BOOL_TRUE
|
|
|
|
|
use_relocate_pair: BOOL_TRUE
|
|
|
|
|
use_light_relocate_pair: BOOL_TRUE
|
|
|
|
|
use_relocate_subtrip: BOOL_TRUE
|
|
|
|
|
use_relocate_neighbors: BOOL_FALSE
|
|
|
|
|
use_exchange: BOOL_TRUE
|
|
|
|
|
use_exchange_pair: BOOL_TRUE
|
|
|
|
|
use_exchange_subtrip: BOOL_TRUE
|
|
|
|
|
use_cross: BOOL_TRUE
|
|
|
|
|
use_cross_exchange: BOOL_FALSE
|
|
|
|
|
use_relocate_expensive_chain: BOOL_TRUE
|
|
|
|
|
use_two_opt: BOOL_TRUE
|
|
|
|
|
use_or_opt: BOOL_TRUE
|
|
|
|
|
use_lin_kernighan: BOOL_TRUE
|
|
|
|
|
use_tsp_opt: BOOL_FALSE
|
|
|
|
|
use_make_active: BOOL_TRUE
|
|
|
|
|
use_relocate_and_make_active: BOOL_FALSE # costly if true by default
|
|
|
|
|
use_make_inactive: BOOL_TRUE
|
|
|
|
|
use_make_chain_inactive: BOOL_TRUE
|
|
|
|
|
use_swap_active: BOOL_TRUE
|
|
|
|
|
use_extended_swap_active: BOOL_FALSE
|
2022-10-21 09:10:53 +02:00
|
|
|
use_node_pair_swap_active: BOOL_FALSE
|
2022-06-21 11:43:36 +02:00
|
|
|
use_path_lns: BOOL_FALSE
|
|
|
|
|
use_full_path_lns: BOOL_FALSE
|
|
|
|
|
use_tsp_lns: BOOL_FALSE
|
|
|
|
|
use_inactive_lns: BOOL_FALSE
|
|
|
|
|
use_global_cheapest_insertion_path_lns: BOOL_TRUE
|
|
|
|
|
use_local_cheapest_insertion_path_lns: BOOL_TRUE
|
|
|
|
|
use_relocate_path_global_cheapest_insertion_insert_unperformed: BOOL_TRUE
|
|
|
|
|
use_global_cheapest_insertion_expensive_chain_lns: BOOL_FALSE
|
|
|
|
|
use_local_cheapest_insertion_expensive_chain_lns: BOOL_FALSE
|
|
|
|
|
use_global_cheapest_insertion_close_nodes_lns: BOOL_FALSE
|
|
|
|
|
use_local_cheapest_insertion_close_nodes_lns: BOOL_FALSE
|
|
|
|
|
}
|
|
|
|
|
use_multi_armed_bandit_concatenate_operators: false
|
|
|
|
|
multi_armed_bandit_compound_operator_memory_coefficient: 0.04
|
|
|
|
|
multi_armed_bandit_compound_operator_exploration_coefficient: 1e12
|
|
|
|
|
relocate_expensive_chain_num_arcs_to_consider: 4
|
|
|
|
|
heuristic_expensive_chain_lns_num_arcs_to_consider: 4
|
|
|
|
|
heuristic_close_nodes_lns_num_nodes: 5
|
|
|
|
|
local_search_metaheuristic: AUTOMATIC
|
|
|
|
|
guided_local_search_lambda_coefficient: 0.1
|
|
|
|
|
use_depth_first_search: false
|
|
|
|
|
use_cp: BOOL_TRUE
|
|
|
|
|
use_cp_sat: BOOL_FALSE
|
|
|
|
|
use_generalized_cp_sat: BOOL_FALSE
|
|
|
|
|
sat_parameters { linearization_level: 2 num_search_workers: 1 }
|
|
|
|
|
continuous_scheduling_solver: SCHEDULING_GLOP
|
|
|
|
|
mixed_integer_scheduling_solver: SCHEDULING_CP_SAT
|
|
|
|
|
disable_scheduling_beware_this_may_degrade_performance: false
|
|
|
|
|
optimization_step: 0.0
|
|
|
|
|
number_of_solutions_to_collect: 1
|
|
|
|
|
# No global time_limit by default.
|
|
|
|
|
solution_limit: 0x7fffffffffffffff # kint64max
|
|
|
|
|
lns_time_limit: { seconds: 0 nanos: 100000000 } # 0.1s
|
|
|
|
|
use_full_propagation: false
|
|
|
|
|
log_search: false
|
|
|
|
|
log_cost_scaling_factor: 1.0
|
|
|
|
|
log_cost_offset: 0.0
|
|
|
|
|
)pb";
|
2018-10-31 16:18:18 +01:00
|
|
|
RoutingSearchParameters parameters;
|
2022-06-21 11:43:36 +02:00
|
|
|
using TextFormat = google::protobuf::TextFormat;
|
|
|
|
|
if (!TextFormat::ParseFromString(kSearchParameters, ¶meters)) {
|
2020-10-22 23:36:58 +02:00
|
|
|
LOG(DFATAL) << "Unsupported default search parameters: "
|
|
|
|
|
<< kSearchParameters;
|
2018-10-31 16:18:18 +01:00
|
|
|
}
|
|
|
|
|
const std::string error = FindErrorInRoutingSearchParameters(parameters);
|
|
|
|
|
LOG_IF(DFATAL, !error.empty())
|
|
|
|
|
<< "The default search parameters aren't valid: " << error;
|
|
|
|
|
return parameters;
|
|
|
|
|
}
|
2022-06-21 11:43:36 +02:00
|
|
|
} // namespace
|
|
|
|
|
|
|
|
|
|
// static
|
|
|
|
|
RoutingSearchParameters DefaultRoutingSearchParameters() {
|
|
|
|
|
static const auto* default_parameters =
|
|
|
|
|
new RoutingSearchParameters(CreateDefaultRoutingSearchParameters());
|
|
|
|
|
return *default_parameters;
|
|
|
|
|
}
|
2018-10-31 16:18:18 +01:00
|
|
|
|
|
|
|
|
namespace {
|
2020-10-29 14:25:39 +01:00
|
|
|
bool IsValidNonNegativeDuration(const google::protobuf::Duration& d) {
|
2018-10-31 16:18:18 +01:00
|
|
|
const auto status_or_duration = util_time::DecodeGoogleApiProto(d);
|
|
|
|
|
return status_or_duration.ok() &&
|
2020-05-06 18:22:10 +02:00
|
|
|
status_or_duration.value() >= absl::ZeroDuration();
|
2018-10-31 16:18:18 +01:00
|
|
|
}
|
2020-10-22 23:36:58 +02:00
|
|
|
} // namespace
|
2018-10-31 16:18:18 +01:00
|
|
|
|
|
|
|
|
std::string FindErrorInRoutingSearchParameters(
|
2020-10-29 14:25:39 +01:00
|
|
|
const RoutingSearchParameters& search_parameters) {
|
2022-05-18 16:41:03 +02:00
|
|
|
const std::vector<std::string> errors =
|
|
|
|
|
FindErrorsInRoutingSearchParameters(search_parameters);
|
|
|
|
|
return (errors.empty()) ? "" : errors[0];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
std::vector<std::string> FindErrorsInRoutingSearchParameters(
|
|
|
|
|
const RoutingSearchParameters& search_parameters) {
|
2018-10-31 16:18:18 +01:00
|
|
|
using absl::StrCat;
|
2022-05-18 16:41:03 +02:00
|
|
|
std::vector<std::string> errors;
|
|
|
|
|
|
2018-10-31 16:18:18 +01:00
|
|
|
// Check that all local search operators are set to either BOOL_TRUE or
|
|
|
|
|
// BOOL_FALSE (and not BOOL_UNSPECIFIED).
|
|
|
|
|
{
|
|
|
|
|
using Reflection = google::protobuf::Reflection;
|
|
|
|
|
using Descriptor = google::protobuf::Descriptor;
|
|
|
|
|
using FieldDescriptor = google::protobuf::FieldDescriptor;
|
2020-10-29 14:25:39 +01:00
|
|
|
const RoutingSearchParameters::LocalSearchNeighborhoodOperators& operators =
|
2018-10-31 16:18:18 +01:00
|
|
|
search_parameters.local_search_operators();
|
2020-10-29 14:25:39 +01:00
|
|
|
const Reflection* ls_reflection = operators.GetReflection();
|
|
|
|
|
const Descriptor* ls_descriptor = operators.GetDescriptor();
|
2018-10-31 16:18:18 +01:00
|
|
|
for (int /*this is NOT the field's tag number*/ field_index = 0;
|
|
|
|
|
field_index < ls_descriptor->field_count(); ++field_index) {
|
2020-10-29 14:25:39 +01:00
|
|
|
const FieldDescriptor* field = ls_descriptor->field(field_index);
|
2018-10-31 16:18:18 +01:00
|
|
|
if (field->type() != FieldDescriptor::TYPE_ENUM ||
|
|
|
|
|
field->enum_type() != OptionalBoolean_descriptor()) {
|
|
|
|
|
DLOG(FATAL)
|
|
|
|
|
<< "In RoutingSearchParameters::LocalSearchNeighborhoodOperators,"
|
|
|
|
|
<< " field '" << field->name() << "' is not an OptionalBoolean.";
|
2022-05-18 16:41:03 +02:00
|
|
|
} else {
|
|
|
|
|
const int value = ls_reflection->GetEnum(operators, field)->number();
|
|
|
|
|
if (!OptionalBoolean_IsValid(value) || value == 0) {
|
|
|
|
|
errors.emplace_back(absl::StrFormat(
|
|
|
|
|
"local_search_neighborhood_operator.%s should be set to "
|
|
|
|
|
"BOOL_TRUE or BOOL_FALSE instead of %s (value: %d)",
|
|
|
|
|
field->name(),
|
|
|
|
|
OptionalBoolean_Name(static_cast<OptionalBoolean>(value)),
|
|
|
|
|
value));
|
|
|
|
|
}
|
2018-10-31 16:18:18 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2022-05-18 16:41:03 +02:00
|
|
|
if (const double ratio = search_parameters.savings_neighbors_ratio();
|
|
|
|
|
std::isnan(ratio) || ratio <= 0 || ratio > 1) {
|
|
|
|
|
errors.emplace_back(StrCat("Invalid savings_neighbors_ratio: ", ratio));
|
2018-10-31 16:18:18 +01:00
|
|
|
}
|
2022-05-18 16:41:03 +02:00
|
|
|
if (const double max_memory =
|
|
|
|
|
search_parameters.savings_max_memory_usage_bytes();
|
|
|
|
|
std::isnan(max_memory) || max_memory <= 0 || max_memory > 1e10) {
|
|
|
|
|
errors.emplace_back(
|
|
|
|
|
StrCat("Invalid savings_max_memory_usage_bytes: ", max_memory));
|
2018-10-31 16:18:18 +01:00
|
|
|
}
|
2022-05-18 16:41:03 +02:00
|
|
|
if (const double coefficient = search_parameters.savings_arc_coefficient();
|
|
|
|
|
std::isnan(coefficient) || coefficient <= 0 || std::isinf(coefficient)) {
|
|
|
|
|
errors.emplace_back(
|
|
|
|
|
StrCat("Invalid savings_arc_coefficient: ", coefficient));
|
2018-10-31 16:18:18 +01:00
|
|
|
}
|
2022-05-18 16:41:03 +02:00
|
|
|
if (const double ratio =
|
|
|
|
|
search_parameters.cheapest_insertion_farthest_seeds_ratio();
|
|
|
|
|
std::isnan(ratio) || ratio < 0 || ratio > 1) {
|
|
|
|
|
errors.emplace_back(
|
|
|
|
|
StrCat("Invalid cheapest_insertion_farthest_seeds_ratio: ", ratio));
|
2019-11-20 14:28:11 -08:00
|
|
|
}
|
2022-05-18 16:41:03 +02:00
|
|
|
if (const double ratio =
|
|
|
|
|
search_parameters.cheapest_insertion_first_solution_neighbors_ratio();
|
|
|
|
|
std::isnan(ratio) || ratio <= 0 || ratio > 1) {
|
|
|
|
|
errors.emplace_back(StrCat(
|
|
|
|
|
"Invalid cheapest_insertion_first_solution_neighbors_ratio: ", ratio));
|
2021-01-20 14:53:52 +01:00
|
|
|
}
|
2022-05-18 16:41:03 +02:00
|
|
|
if (const int32_t min_neighbors =
|
|
|
|
|
search_parameters.cheapest_insertion_first_solution_min_neighbors();
|
|
|
|
|
min_neighbors < 1) {
|
|
|
|
|
errors.emplace_back(
|
|
|
|
|
StrCat("Invalid cheapest_insertion_first_solution_min_neighbors: ",
|
|
|
|
|
min_neighbors, ". Must be greater or equal to 1."));
|
2018-10-31 16:18:18 +01:00
|
|
|
}
|
2022-05-18 16:41:03 +02:00
|
|
|
if (const double ratio =
|
|
|
|
|
search_parameters.cheapest_insertion_ls_operator_neighbors_ratio();
|
|
|
|
|
std::isnan(ratio) || ratio <= 0 || ratio > 1) {
|
|
|
|
|
errors.emplace_back(StrCat(
|
|
|
|
|
"Invalid cheapest_insertion_ls_operator_neighbors_ratio: ", ratio));
|
2021-01-20 14:53:52 +01:00
|
|
|
}
|
2022-05-18 16:41:03 +02:00
|
|
|
if (const int32_t min_neighbors =
|
|
|
|
|
search_parameters.cheapest_insertion_ls_operator_min_neighbors();
|
|
|
|
|
min_neighbors < 1) {
|
|
|
|
|
errors.emplace_back(StrCat(
|
|
|
|
|
"Invalid cheapest_insertion_ls_operator_min_neighbors: ", min_neighbors,
|
|
|
|
|
". Must be greater or equal to 1."));
|
2018-10-31 16:18:18 +01:00
|
|
|
}
|
2022-05-18 16:41:03 +02:00
|
|
|
if (const int32_t num_arcs =
|
|
|
|
|
search_parameters.relocate_expensive_chain_num_arcs_to_consider();
|
|
|
|
|
num_arcs < 2 || num_arcs > 1e6) {
|
|
|
|
|
errors.emplace_back(StrCat(
|
|
|
|
|
"Invalid relocate_expensive_chain_num_arcs_to_consider: ", num_arcs,
|
|
|
|
|
". Must be between 2 and 10^6 (included)."));
|
2019-11-20 14:28:11 -08:00
|
|
|
}
|
2022-05-18 16:41:03 +02:00
|
|
|
if (const int32_t num_arcs =
|
|
|
|
|
search_parameters
|
|
|
|
|
.heuristic_expensive_chain_lns_num_arcs_to_consider();
|
|
|
|
|
num_arcs < 2 || num_arcs > 1e6) {
|
|
|
|
|
errors.emplace_back(
|
|
|
|
|
StrCat("Invalid heuristic_expensive_chain_lns_num_arcs_to_consider: ",
|
|
|
|
|
num_arcs, ". Must be between 2 and 10^6 (included)."));
|
2020-08-10 10:55:34 +02:00
|
|
|
}
|
2022-05-18 16:41:03 +02:00
|
|
|
if (const int32_t num_nodes =
|
|
|
|
|
search_parameters.heuristic_close_nodes_lns_num_nodes();
|
|
|
|
|
num_nodes < 0 || num_nodes > 1e4) {
|
|
|
|
|
errors.emplace_back(
|
|
|
|
|
StrCat("Invalid heuristic_close_nodes_lns_num_nodes: ", num_nodes,
|
|
|
|
|
". Must be between 0 and 10000 (included)."));
|
2018-10-31 16:18:18 +01:00
|
|
|
}
|
2022-05-18 16:41:03 +02:00
|
|
|
if (const double gls_coefficient =
|
|
|
|
|
search_parameters.guided_local_search_lambda_coefficient();
|
|
|
|
|
std::isnan(gls_coefficient) || gls_coefficient < 0 ||
|
|
|
|
|
std::isinf(gls_coefficient)) {
|
|
|
|
|
errors.emplace_back(StrCat(
|
|
|
|
|
"Invalid guided_local_search_lambda_coefficient: ", gls_coefficient));
|
2018-10-31 16:18:18 +01:00
|
|
|
}
|
2022-05-18 16:41:03 +02:00
|
|
|
if (const double step = search_parameters.optimization_step();
|
|
|
|
|
std::isnan(step) || step < 0.0) {
|
|
|
|
|
errors.emplace_back(StrCat("Invalid optimization_step: ", step));
|
2018-10-31 16:18:18 +01:00
|
|
|
}
|
2022-05-18 16:41:03 +02:00
|
|
|
if (const int32_t num = search_parameters.number_of_solutions_to_collect();
|
|
|
|
|
num < 1) {
|
|
|
|
|
errors.emplace_back(
|
|
|
|
|
StrCat("Invalid number_of_solutions_to_collect: ", num));
|
2018-10-31 16:18:18 +01:00
|
|
|
}
|
2022-05-18 16:41:03 +02:00
|
|
|
if (const int64_t lim = search_parameters.solution_limit(); lim < 1)
|
|
|
|
|
errors.emplace_back(StrCat("Invalid solution_limit: ", lim));
|
2018-10-31 16:18:18 +01:00
|
|
|
if (!IsValidNonNegativeDuration(search_parameters.time_limit())) {
|
2022-05-18 16:41:03 +02:00
|
|
|
errors.emplace_back("Invalid time_limit: " +
|
|
|
|
|
search_parameters.time_limit().ShortDebugString());
|
2018-10-31 16:18:18 +01:00
|
|
|
}
|
|
|
|
|
if (!IsValidNonNegativeDuration(search_parameters.lns_time_limit())) {
|
2022-05-18 16:41:03 +02:00
|
|
|
errors.emplace_back("Invalid lns_time_limit: " +
|
|
|
|
|
search_parameters.lns_time_limit().ShortDebugString());
|
2018-10-31 16:18:18 +01:00
|
|
|
}
|
|
|
|
|
if (!FirstSolutionStrategy::Value_IsValid(
|
|
|
|
|
search_parameters.first_solution_strategy())) {
|
2022-05-18 16:41:03 +02:00
|
|
|
errors.emplace_back(StrCat("Invalid first_solution_strategy: ",
|
|
|
|
|
search_parameters.first_solution_strategy()));
|
2018-10-31 16:18:18 +01:00
|
|
|
}
|
|
|
|
|
if (!LocalSearchMetaheuristic::Value_IsValid(
|
|
|
|
|
search_parameters.local_search_metaheuristic())) {
|
2022-05-18 16:41:03 +02:00
|
|
|
errors.emplace_back(StrCat("Invalid metaheuristic: ",
|
|
|
|
|
search_parameters.local_search_metaheuristic()));
|
2018-10-31 16:18:18 +01:00
|
|
|
}
|
|
|
|
|
|
2019-07-22 10:18:30 -07:00
|
|
|
const double scaling_factor = search_parameters.log_cost_scaling_factor();
|
|
|
|
|
if (scaling_factor == 0 || std::isnan(scaling_factor) ||
|
|
|
|
|
std::isinf(scaling_factor)) {
|
2022-05-18 16:41:03 +02:00
|
|
|
errors.emplace_back(
|
|
|
|
|
StrCat("Invalid value for log_cost_scaling_factor: ", scaling_factor));
|
2019-07-22 10:18:30 -07:00
|
|
|
}
|
|
|
|
|
const double offset = search_parameters.log_cost_offset();
|
|
|
|
|
if (std::isnan(offset) || std::isinf(offset)) {
|
2022-05-18 16:41:03 +02:00
|
|
|
errors.emplace_back(StrCat("Invalid value for log_cost_offset: ", offset));
|
2018-12-06 17:16:22 +01:00
|
|
|
}
|
2020-03-09 17:52:25 +01:00
|
|
|
const RoutingSearchParameters::SchedulingSolver continuous_scheduling_solver =
|
|
|
|
|
search_parameters.continuous_scheduling_solver();
|
2022-02-22 19:25:31 +01:00
|
|
|
if (continuous_scheduling_solver ==
|
|
|
|
|
RoutingSearchParameters::SCHEDULING_UNSET ||
|
|
|
|
|
continuous_scheduling_solver ==
|
|
|
|
|
RoutingSearchParameters::SCHEDULING_CP_SAT) {
|
2022-05-18 16:41:03 +02:00
|
|
|
errors.emplace_back(
|
|
|
|
|
StrCat("Invalid value for continuous_scheduling_solver: ",
|
|
|
|
|
RoutingSearchParameters::SchedulingSolver_Name(
|
|
|
|
|
continuous_scheduling_solver)));
|
2020-03-09 17:52:25 +01:00
|
|
|
}
|
2022-05-18 16:41:03 +02:00
|
|
|
|
|
|
|
|
if (const RoutingSearchParameters::SchedulingSolver
|
|
|
|
|
mixed_integer_scheduling_solver =
|
|
|
|
|
search_parameters.mixed_integer_scheduling_solver();
|
|
|
|
|
mixed_integer_scheduling_solver ==
|
2022-02-22 19:25:31 +01:00
|
|
|
RoutingSearchParameters::SCHEDULING_UNSET) {
|
2022-05-18 16:41:03 +02:00
|
|
|
errors.emplace_back(
|
|
|
|
|
StrCat("Invalid value for mixed_integer_scheduling_solver: ",
|
|
|
|
|
RoutingSearchParameters::SchedulingSolver_Name(
|
|
|
|
|
mixed_integer_scheduling_solver)));
|
2020-03-09 17:52:25 +01:00
|
|
|
}
|
2018-12-06 17:16:22 +01:00
|
|
|
|
2020-10-18 16:38:25 +02:00
|
|
|
if (search_parameters.has_improvement_limit_parameters()) {
|
2020-10-22 23:36:58 +02:00
|
|
|
const double improvement_rate_coefficient =
|
|
|
|
|
search_parameters.improvement_limit_parameters()
|
|
|
|
|
.improvement_rate_coefficient();
|
2020-10-18 16:38:25 +02:00
|
|
|
if (std::isnan(improvement_rate_coefficient) ||
|
|
|
|
|
improvement_rate_coefficient <= 0) {
|
2022-05-18 16:41:03 +02:00
|
|
|
errors.emplace_back(
|
|
|
|
|
StrCat("Invalid value for "
|
|
|
|
|
"improvement_limit_parameters.improvement_rate_coefficient: ",
|
|
|
|
|
improvement_rate_coefficient));
|
2020-10-18 16:38:25 +02:00
|
|
|
}
|
|
|
|
|
|
2021-04-01 12:13:35 +02:00
|
|
|
const int32_t improvement_rate_solutions_distance =
|
2020-10-22 23:36:58 +02:00
|
|
|
search_parameters.improvement_limit_parameters()
|
|
|
|
|
.improvement_rate_solutions_distance();
|
2020-10-20 12:57:24 +02:00
|
|
|
if (improvement_rate_solutions_distance <= 0) {
|
2022-05-18 16:41:03 +02:00
|
|
|
errors.emplace_back(StrCat(
|
2020-10-18 16:38:25 +02:00
|
|
|
"Invalid value for "
|
|
|
|
|
"improvement_limit_parameters.improvement_rate_solutions_distance: ",
|
2022-05-18 16:41:03 +02:00
|
|
|
improvement_rate_solutions_distance));
|
2020-10-18 16:38:25 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-05-18 16:41:03 +02:00
|
|
|
if (const double memory_coefficient =
|
|
|
|
|
search_parameters
|
|
|
|
|
.multi_armed_bandit_compound_operator_memory_coefficient();
|
|
|
|
|
std::isnan(memory_coefficient) || memory_coefficient < 0 ||
|
|
|
|
|
memory_coefficient > 1) {
|
|
|
|
|
errors.emplace_back(
|
|
|
|
|
StrCat("Invalid value for "
|
|
|
|
|
"multi_armed_bandit_compound_operator_memory_coefficient: ",
|
|
|
|
|
memory_coefficient));
|
2020-11-01 11:47:28 +01:00
|
|
|
}
|
2022-05-18 16:41:03 +02:00
|
|
|
if (const double exploration_coefficient =
|
|
|
|
|
search_parameters
|
|
|
|
|
.multi_armed_bandit_compound_operator_exploration_coefficient();
|
|
|
|
|
std::isnan(exploration_coefficient) || exploration_coefficient < 0) {
|
|
|
|
|
errors.emplace_back(
|
|
|
|
|
StrCat("Invalid value for "
|
|
|
|
|
"multi_armed_bandit_compound_operator_exploration_coefficient: ",
|
|
|
|
|
exploration_coefficient));
|
2020-11-01 11:47:28 +01:00
|
|
|
}
|
|
|
|
|
|
2022-05-18 16:41:03 +02:00
|
|
|
if (const sat::SatParameters& sat_parameters =
|
|
|
|
|
search_parameters.sat_parameters();
|
|
|
|
|
sat_parameters.enumerate_all_solutions() &&
|
|
|
|
|
(sat_parameters.num_search_workers() > 1 ||
|
|
|
|
|
sat_parameters.interleave_search())) {
|
|
|
|
|
errors.emplace_back(
|
|
|
|
|
"sat_parameters.enumerate_all_solutions cannot be true in parallel"
|
|
|
|
|
" search");
|
2021-08-23 16:08:30 +02:00
|
|
|
}
|
|
|
|
|
|
2022-05-18 16:41:03 +02:00
|
|
|
return errors;
|
2018-10-31 16:18:18 +01:00
|
|
|
}
|
|
|
|
|
|
2020-10-22 23:36:58 +02:00
|
|
|
} // namespace operations_research
|