2024-01-04 13:43:15 +01:00
|
|
|
// Copyright 2010-2024 Google LLC
|
2010-09-15 12:42:33 +00: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.
|
2014-07-09 15:18:27 +00:00
|
|
|
|
2010-09-15 12:42:33 +00:00
|
|
|
//
|
|
|
|
|
// This file implements the core objects of the constraint solver:
|
|
|
|
|
// Solver, Search, Queue, ... along with the main resolution loop.
|
|
|
|
|
|
2017-04-26 17:30:25 +02:00
|
|
|
#include "ortools/constraint_solver/constraint_solver.h"
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2022-05-18 16:36:05 +02:00
|
|
|
#include <algorithm>
|
2013-12-16 10:24:42 +00:00
|
|
|
#include <csetjmp>
|
2021-04-01 12:13:35 +02:00
|
|
|
#include <cstdint>
|
2015-10-23 13:45:43 +02:00
|
|
|
#include <deque>
|
2011-09-21 15:16:48 +00:00
|
|
|
#include <iosfwd>
|
2021-04-01 12:13:35 +02:00
|
|
|
#include <limits>
|
2015-08-13 16:00:54 +02:00
|
|
|
#include <memory>
|
2022-07-22 14:35:40 +02:00
|
|
|
#include <ostream>
|
2015-04-29 20:05:25 +02:00
|
|
|
#include <string>
|
2022-09-05 18:30:09 +02:00
|
|
|
#include <type_traits>
|
2017-04-19 16:20:56 +02:00
|
|
|
#include <utility>
|
2022-07-22 14:35:40 +02:00
|
|
|
#include <vector>
|
2017-04-26 17:30:25 +02:00
|
|
|
|
2023-12-01 10:32:14 +01:00
|
|
|
#include "absl/flags/flag.h"
|
|
|
|
|
#include "absl/log/check.h"
|
2019-11-20 14:28:11 -08:00
|
|
|
#include "absl/time/time.h"
|
2017-04-26 17:30:25 +02:00
|
|
|
#include "ortools/base/logging.h"
|
|
|
|
|
#include "ortools/base/map_util.h"
|
|
|
|
|
#include "ortools/base/stl_util.h"
|
2021-04-01 12:13:35 +02:00
|
|
|
#include "ortools/base/sysinfo.h"
|
2021-12-05 12:15:27 +01:00
|
|
|
#include "ortools/base/timer.h"
|
2017-04-26 17:30:25 +02:00
|
|
|
#include "ortools/constraint_solver/constraint_solveri.h"
|
|
|
|
|
#include "ortools/util/tuple_set.h"
|
2023-12-01 10:32:14 +01:00
|
|
|
#include "zconf.h"
|
2018-06-08 16:40:43 +02:00
|
|
|
#include "zlib.h"
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2016-02-03 15:15:58 +01:00
|
|
|
// These flags are used to set the fields in the DefaultSolverParameters proto.
|
2020-10-21 15:51:44 +02:00
|
|
|
ABSL_FLAG(bool, cp_trace_propagation, false,
|
|
|
|
|
"Trace propagation events (constraint and demon executions,"
|
|
|
|
|
" variable modifications).");
|
|
|
|
|
ABSL_FLAG(bool, cp_trace_search, false, "Trace search events");
|
|
|
|
|
ABSL_FLAG(bool, cp_print_added_constraints, false,
|
|
|
|
|
"show all constraints added to the solver.");
|
|
|
|
|
ABSL_FLAG(bool, cp_print_model, false,
|
|
|
|
|
"use PrintModelVisitor on model before solving.");
|
|
|
|
|
ABSL_FLAG(bool, cp_model_stats, false,
|
|
|
|
|
"use StatisticsModelVisitor on model before solving.");
|
|
|
|
|
ABSL_FLAG(bool, cp_disable_solve, false,
|
|
|
|
|
"Force failure at the beginning of a search.");
|
|
|
|
|
ABSL_FLAG(std::string, cp_profile_file, "",
|
|
|
|
|
"Export profiling overview to file.");
|
|
|
|
|
ABSL_FLAG(bool, cp_print_local_search_profile, false,
|
|
|
|
|
"Print local search profiling data after solving.");
|
|
|
|
|
ABSL_FLAG(bool, cp_name_variables, false, "Force all variables to have names.");
|
|
|
|
|
ABSL_FLAG(bool, cp_name_cast_variables, false,
|
|
|
|
|
"Name variables casted from expressions");
|
|
|
|
|
ABSL_FLAG(bool, cp_use_small_table, true,
|
|
|
|
|
"Use small compact table constraint when possible.");
|
|
|
|
|
ABSL_FLAG(bool, cp_use_cumulative_edge_finder, true,
|
|
|
|
|
"Use the O(n log n) cumulative edge finding algorithm described "
|
|
|
|
|
"in 'Edge Finding Filtering Algorithm for Discrete Cumulative "
|
|
|
|
|
"Resources in O(kn log n)' by Petr Vilim, CP 2009.");
|
|
|
|
|
ABSL_FLAG(bool, cp_use_cumulative_time_table, true,
|
|
|
|
|
"Use a O(n^2) cumulative time table propagation algorithm.");
|
|
|
|
|
ABSL_FLAG(bool, cp_use_cumulative_time_table_sync, false,
|
|
|
|
|
"Use a synchronized O(n^2 log n) cumulative time table propagation "
|
|
|
|
|
"algorithm.");
|
|
|
|
|
ABSL_FLAG(bool, cp_use_sequence_high_demand_tasks, true,
|
|
|
|
|
"Use a sequence constraints for cumulative tasks that have a "
|
|
|
|
|
"demand greater than half of the capacity of the resource.");
|
|
|
|
|
ABSL_FLAG(bool, cp_use_all_possible_disjunctions, true,
|
|
|
|
|
"Post temporal disjunctions for all pairs of tasks sharing a "
|
|
|
|
|
"cumulative resource and that cannot overlap because the sum of "
|
|
|
|
|
"their demand exceeds the capacity.");
|
|
|
|
|
ABSL_FLAG(int, cp_max_edge_finder_size, 50,
|
|
|
|
|
"Do not post the edge finder in the cumulative constraints if "
|
|
|
|
|
"it contains more than this number of tasks");
|
|
|
|
|
ABSL_FLAG(bool, cp_diffn_use_cumulative, true,
|
|
|
|
|
"Diffn constraint adds redundant cumulative constraint");
|
|
|
|
|
ABSL_FLAG(bool, cp_use_element_rmq, true,
|
|
|
|
|
"If true, rmq's will be used in element expressions.");
|
|
|
|
|
ABSL_FLAG(int, cp_check_solution_period, 1,
|
|
|
|
|
"Number of solutions explored between two solution checks during "
|
|
|
|
|
"local search.");
|
2021-04-01 12:13:35 +02:00
|
|
|
ABSL_FLAG(int64_t, cp_random_seed, 12345,
|
2020-10-21 15:51:44 +02:00
|
|
|
"Random seed used in several (but not all) random number "
|
|
|
|
|
"generators used by the CP solver. Use -1 to auto-generate an"
|
|
|
|
|
"undeterministic random seed.");
|
2016-03-08 09:24:56 -08:00
|
|
|
|
2013-10-10 15:23:20 +00:00
|
|
|
void ConstraintSolverFailsHere() { VLOG(3) << "Fail"; }
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2020-10-22 23:36:58 +02:00
|
|
|
#if defined(_MSC_VER) // WINDOWS
|
2010-09-15 12:42:33 +00:00
|
|
|
#pragma warning(disable : 4351 4355)
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
namespace operations_research {
|
|
|
|
|
|
2016-07-28 10:15:46 -07:00
|
|
|
namespace {
|
|
|
|
|
// Calls the given method with the provided arguments on all objects in the
|
|
|
|
|
// collection.
|
|
|
|
|
template <typename T, typename MethodPointer, typename... Args>
|
2020-10-29 14:25:39 +01:00
|
|
|
void ForAll(const std::vector<T*>& objects, MethodPointer method,
|
|
|
|
|
const Args&... args) {
|
|
|
|
|
for (T* const object : objects) {
|
2016-07-28 10:15:46 -07:00
|
|
|
DCHECK(object != nullptr);
|
|
|
|
|
(object->*method)(args...);
|
|
|
|
|
}
|
|
|
|
|
}
|
2022-09-05 18:30:09 +02:00
|
|
|
|
|
|
|
|
// Converts a scoped enum to its underlying type.
|
|
|
|
|
template <typename E>
|
|
|
|
|
constexpr typename std::underlying_type<E>::type to_underlying(E e) {
|
|
|
|
|
return static_cast<typename std::underlying_type<E>::type>(e);
|
|
|
|
|
}
|
|
|
|
|
|
2020-10-22 23:36:58 +02:00
|
|
|
} // namespace
|
2016-07-28 10:15:46 -07:00
|
|
|
|
2016-02-03 15:15:58 +01:00
|
|
|
// ----- ConstraintSolverParameters -----
|
|
|
|
|
|
|
|
|
|
ConstraintSolverParameters Solver::DefaultSolverParameters() {
|
|
|
|
|
ConstraintSolverParameters params;
|
|
|
|
|
params.set_compress_trail(ConstraintSolverParameters::NO_COMPRESSION);
|
|
|
|
|
params.set_trail_block_size(8000);
|
|
|
|
|
params.set_array_split_size(16);
|
|
|
|
|
params.set_store_names(true);
|
2020-10-21 00:21:54 +02:00
|
|
|
params.set_profile_propagation(!absl::GetFlag(FLAGS_cp_profile_file).empty());
|
|
|
|
|
params.set_trace_propagation(absl::GetFlag(FLAGS_cp_trace_propagation));
|
|
|
|
|
params.set_trace_search(absl::GetFlag(FLAGS_cp_trace_search));
|
|
|
|
|
params.set_name_all_variables(absl::GetFlag(FLAGS_cp_name_variables));
|
|
|
|
|
params.set_profile_file(absl::GetFlag(FLAGS_cp_profile_file));
|
|
|
|
|
params.set_profile_local_search(
|
|
|
|
|
absl::GetFlag(FLAGS_cp_print_local_search_profile));
|
|
|
|
|
params.set_print_local_search_profile(
|
|
|
|
|
absl::GetFlag(FLAGS_cp_print_local_search_profile));
|
|
|
|
|
params.set_print_model(absl::GetFlag(FLAGS_cp_print_model));
|
|
|
|
|
params.set_print_model_stats(absl::GetFlag(FLAGS_cp_model_stats));
|
|
|
|
|
params.set_disable_solve(absl::GetFlag(FLAGS_cp_disable_solve));
|
|
|
|
|
params.set_name_cast_variables(absl::GetFlag(FLAGS_cp_name_cast_variables));
|
|
|
|
|
params.set_print_added_constraints(
|
|
|
|
|
absl::GetFlag(FLAGS_cp_print_added_constraints));
|
|
|
|
|
params.set_use_small_table(absl::GetFlag(FLAGS_cp_use_small_table));
|
|
|
|
|
params.set_use_cumulative_edge_finder(
|
|
|
|
|
absl::GetFlag(FLAGS_cp_use_cumulative_edge_finder));
|
|
|
|
|
params.set_use_cumulative_time_table(
|
|
|
|
|
absl::GetFlag(FLAGS_cp_use_cumulative_time_table));
|
2016-10-12 12:04:32 -07:00
|
|
|
params.set_use_cumulative_time_table_sync(
|
2020-10-21 00:21:54 +02:00
|
|
|
absl::GetFlag(FLAGS_cp_use_cumulative_time_table_sync));
|
2016-03-08 09:24:56 -08:00
|
|
|
params.set_use_sequence_high_demand_tasks(
|
2020-10-21 00:21:54 +02:00
|
|
|
absl::GetFlag(FLAGS_cp_use_sequence_high_demand_tasks));
|
2016-03-08 09:24:56 -08:00
|
|
|
params.set_use_all_possible_disjunctions(
|
2020-10-21 00:21:54 +02:00
|
|
|
absl::GetFlag(FLAGS_cp_use_all_possible_disjunctions));
|
|
|
|
|
params.set_max_edge_finder_size(absl::GetFlag(FLAGS_cp_max_edge_finder_size));
|
|
|
|
|
params.set_diffn_use_cumulative(absl::GetFlag(FLAGS_cp_diffn_use_cumulative));
|
|
|
|
|
params.set_use_element_rmq(absl::GetFlag(FLAGS_cp_use_element_rmq));
|
|
|
|
|
params.set_check_solution_period(
|
|
|
|
|
absl::GetFlag(FLAGS_cp_check_solution_period));
|
2016-02-03 15:15:58 +01:00
|
|
|
return params;
|
|
|
|
|
}
|
2011-09-13 08:18:38 +00:00
|
|
|
|
2011-09-13 09:24:49 +00:00
|
|
|
// ----- Forward Declarations and Profiling Support -----
|
2023-06-05 10:04:48 +02:00
|
|
|
extern void InstallDemonProfiler(DemonProfiler* monitor);
|
2023-05-31 14:27:08 +02:00
|
|
|
extern DemonProfiler* BuildDemonProfiler(Solver* solver);
|
|
|
|
|
extern void DeleteDemonProfiler(DemonProfiler* monitor);
|
2023-06-05 10:04:48 +02:00
|
|
|
extern void InstallLocalSearchProfiler(LocalSearchProfiler* monitor);
|
2020-10-29 14:25:39 +01:00
|
|
|
extern LocalSearchProfiler* BuildLocalSearchProfiler(Solver* solver);
|
|
|
|
|
extern void DeleteLocalSearchProfiler(LocalSearchProfiler* monitor);
|
2011-11-16 17:32:24 +00:00
|
|
|
|
2011-11-09 10:59:31 +00:00
|
|
|
// TODO(user): remove this complex logic.
|
|
|
|
|
// We need the double test because parameters are set too late when using
|
|
|
|
|
// python in the open source. This is the cheapest work-around.
|
2011-11-10 09:36:43 +00:00
|
|
|
bool Solver::InstrumentsDemons() const {
|
2011-11-19 01:59:37 +00:00
|
|
|
return IsProfilingEnabled() || InstrumentsVariables();
|
2011-11-14 20:55:35 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool Solver::IsProfilingEnabled() const {
|
2016-02-03 15:15:58 +01:00
|
|
|
return parameters_.profile_propagation() ||
|
|
|
|
|
!parameters_.profile_file().empty();
|
2011-09-13 09:24:49 +00:00
|
|
|
}
|
|
|
|
|
|
2016-07-28 10:15:46 -07:00
|
|
|
bool Solver::IsLocalSearchProfilingEnabled() const {
|
|
|
|
|
return parameters_.profile_local_search() ||
|
|
|
|
|
parameters_.print_local_search_profile();
|
|
|
|
|
}
|
|
|
|
|
|
2011-11-10 09:36:43 +00:00
|
|
|
bool Solver::InstrumentsVariables() const {
|
2016-02-03 15:15:58 +01:00
|
|
|
return parameters_.trace_propagation();
|
2011-11-09 10:59:31 +00:00
|
|
|
}
|
|
|
|
|
|
2011-11-19 01:59:37 +00:00
|
|
|
bool Solver::NameAllVariables() const {
|
2016-02-03 15:15:58 +01:00
|
|
|
return parameters_.name_all_variables();
|
2011-11-19 01:59:37 +00:00
|
|
|
}
|
|
|
|
|
|
2010-09-15 12:42:33 +00:00
|
|
|
// ------------------ Demon class ----------------
|
|
|
|
|
|
|
|
|
|
Solver::DemonPriority Demon::priority() const {
|
|
|
|
|
return Solver::NORMAL_PRIORITY;
|
|
|
|
|
}
|
|
|
|
|
|
2013-12-16 10:24:42 +00:00
|
|
|
std::string Demon::DebugString() const { return "Demon"; }
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2020-10-29 14:25:39 +01:00
|
|
|
void Demon::inhibit(Solver* const s) {
|
2021-04-01 12:13:35 +02:00
|
|
|
if (stamp_ < std::numeric_limits<uint64_t>::max()) {
|
|
|
|
|
s->SaveAndSetValue(&stamp_, std::numeric_limits<uint64_t>::max());
|
2010-09-15 12:42:33 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-10-29 14:25:39 +01:00
|
|
|
void Demon::desinhibit(Solver* const s) {
|
2021-04-01 12:13:35 +02:00
|
|
|
if (stamp_ == std::numeric_limits<uint64_t>::max()) {
|
2010-09-15 12:42:33 +00:00
|
|
|
s->SaveAndSetValue(&stamp_, s->stamp() - 1);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ------------------ Queue class ------------------
|
|
|
|
|
|
2023-05-31 14:27:08 +02:00
|
|
|
extern void CleanVariableOnFail(IntVar* var);
|
2010-12-06 16:29:32 +00:00
|
|
|
|
|
|
|
|
class Queue {
|
2020-10-22 23:36:58 +02:00
|
|
|
public:
|
2021-04-01 12:13:35 +02:00
|
|
|
static constexpr int64_t kTestPeriod = 10000;
|
2012-09-13 14:15:39 +00:00
|
|
|
|
2020-10-29 14:25:39 +01:00
|
|
|
explicit Queue(Solver* const s)
|
2020-10-22 23:36:58 +02:00
|
|
|
: solver_(s),
|
|
|
|
|
stamp_(1),
|
|
|
|
|
freeze_level_(0),
|
|
|
|
|
in_process_(false),
|
|
|
|
|
clean_action_(nullptr),
|
|
|
|
|
clean_variable_(nullptr),
|
|
|
|
|
in_add_(false),
|
2015-10-23 13:45:43 +02:00
|
|
|
instruments_demons_(s->InstrumentsDemons()) {}
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2015-10-23 13:45:43 +02:00
|
|
|
~Queue() {}
|
2010-09-15 12:42:33 +00:00
|
|
|
|
|
|
|
|
void Freeze() {
|
2010-10-26 08:49:34 +00:00
|
|
|
freeze_level_++;
|
2010-09-15 12:42:33 +00:00
|
|
|
stamp_++;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Unfreeze() {
|
2012-09-07 15:27:53 +00:00
|
|
|
if (--freeze_level_ == 0) {
|
|
|
|
|
Process();
|
|
|
|
|
}
|
2010-09-15 12:42:33 +00:00
|
|
|
}
|
|
|
|
|
|
2020-10-29 14:25:39 +01:00
|
|
|
void ProcessOneDemon(Demon* const demon) {
|
2012-09-07 12:14:10 +00:00
|
|
|
demon->set_stamp(stamp_ - 1);
|
2012-09-07 14:18:09 +00:00
|
|
|
if (!instruments_demons_) {
|
2012-09-13 14:15:39 +00:00
|
|
|
if (++solver_->demon_runs_[demon->priority()] % kTestPeriod == 0) {
|
2012-09-07 14:18:09 +00:00
|
|
|
solver_->TopPeriodicCheck();
|
|
|
|
|
}
|
|
|
|
|
demon->Run(solver_);
|
2014-05-22 17:37:21 +00:00
|
|
|
solver_->CheckFail();
|
2012-09-07 14:18:09 +00:00
|
|
|
} else {
|
2012-09-07 12:14:10 +00:00
|
|
|
solver_->GetPropagationMonitor()->BeginDemonRun(demon);
|
2012-09-13 14:15:39 +00:00
|
|
|
if (++solver_->demon_runs_[demon->priority()] % kTestPeriod == 0) {
|
2012-09-07 14:18:09 +00:00
|
|
|
solver_->TopPeriodicCheck();
|
|
|
|
|
}
|
|
|
|
|
demon->Run(solver_);
|
2014-05-22 17:37:21 +00:00
|
|
|
solver_->CheckFail();
|
2012-09-07 12:14:10 +00:00
|
|
|
solver_->GetPropagationMonitor()->EndDemonRun(demon);
|
2010-09-15 12:42:33 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Process() {
|
|
|
|
|
if (!in_process_) {
|
|
|
|
|
in_process_ = true;
|
2015-10-23 13:45:43 +02:00
|
|
|
while (!var_queue_.empty() || !delayed_queue_.empty()) {
|
|
|
|
|
if (!var_queue_.empty()) {
|
2020-10-29 14:25:39 +01:00
|
|
|
Demon* const demon = var_queue_.front();
|
2015-10-23 13:45:43 +02:00
|
|
|
var_queue_.pop_front();
|
|
|
|
|
ProcessOneDemon(demon);
|
2012-09-10 08:37:41 +00:00
|
|
|
} else {
|
2015-10-23 13:45:43 +02:00
|
|
|
DCHECK(!delayed_queue_.empty());
|
2020-10-29 14:25:39 +01:00
|
|
|
Demon* const demon = delayed_queue_.front();
|
2015-10-23 13:45:43 +02:00
|
|
|
delayed_queue_.pop_front();
|
|
|
|
|
ProcessOneDemon(demon);
|
2012-09-10 08:37:41 +00:00
|
|
|
}
|
2012-09-07 14:48:11 +00:00
|
|
|
}
|
2015-10-23 13:45:43 +02:00
|
|
|
in_process_ = false;
|
2012-09-07 14:48:11 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-10-29 14:25:39 +01:00
|
|
|
void ExecuteAll(const SimpleRevFIFO<Demon*>& demons) {
|
2012-09-10 08:37:41 +00:00
|
|
|
if (!instruments_demons_) {
|
2020-10-29 14:25:39 +01:00
|
|
|
for (SimpleRevFIFO<Demon*>::Iterator it(&demons); it.ok(); ++it) {
|
|
|
|
|
Demon* const demon = *it;
|
2012-09-10 08:37:41 +00:00
|
|
|
if (demon->stamp() < stamp_) {
|
|
|
|
|
DCHECK_EQ(demon->priority(), Solver::NORMAL_PRIORITY);
|
2012-09-13 14:15:39 +00:00
|
|
|
if (++solver_->demon_runs_[Solver::NORMAL_PRIORITY] % kTestPeriod ==
|
|
|
|
|
0) {
|
2012-09-10 08:37:41 +00:00
|
|
|
solver_->TopPeriodicCheck();
|
|
|
|
|
}
|
|
|
|
|
demon->Run(solver_);
|
2014-05-22 17:37:21 +00:00
|
|
|
solver_->CheckFail();
|
2012-09-10 08:37:41 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} else {
|
2020-10-29 14:25:39 +01:00
|
|
|
for (SimpleRevFIFO<Demon*>::Iterator it(&demons); it.ok(); ++it) {
|
|
|
|
|
Demon* const demon = *it;
|
2012-09-10 08:37:41 +00:00
|
|
|
if (demon->stamp() < stamp_) {
|
|
|
|
|
DCHECK_EQ(demon->priority(), Solver::NORMAL_PRIORITY);
|
2015-10-23 13:45:43 +02:00
|
|
|
solver_->GetPropagationMonitor()->BeginDemonRun(demon);
|
|
|
|
|
if (++solver_->demon_runs_[Solver::NORMAL_PRIORITY] % kTestPeriod ==
|
|
|
|
|
0) {
|
|
|
|
|
solver_->TopPeriodicCheck();
|
|
|
|
|
}
|
|
|
|
|
demon->Run(solver_);
|
|
|
|
|
solver_->CheckFail();
|
|
|
|
|
solver_->GetPropagationMonitor()->EndDemonRun(demon);
|
2012-09-10 08:37:41 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-10-29 14:25:39 +01:00
|
|
|
void EnqueueAll(const SimpleRevFIFO<Demon*>& demons) {
|
|
|
|
|
for (SimpleRevFIFO<Demon*>::Iterator it(&demons); it.ok(); ++it) {
|
2015-10-23 13:45:43 +02:00
|
|
|
EnqueueDelayedDemon(*it);
|
2013-06-11 14:49:19 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-10-29 14:25:39 +01:00
|
|
|
void EnqueueVar(Demon* const demon) {
|
2012-09-07 16:41:59 +00:00
|
|
|
DCHECK(demon->priority() == Solver::VAR_PRIORITY);
|
2010-12-06 16:29:32 +00:00
|
|
|
if (demon->stamp() < stamp_) {
|
|
|
|
|
demon->set_stamp(stamp_);
|
2015-10-23 13:45:43 +02:00
|
|
|
var_queue_.push_back(demon);
|
2012-09-07 15:27:53 +00:00
|
|
|
if (freeze_level_ == 0) {
|
|
|
|
|
Process();
|
|
|
|
|
}
|
2010-09-15 12:42:33 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-10-29 14:25:39 +01:00
|
|
|
void EnqueueDelayedDemon(Demon* const demon) {
|
2012-09-07 16:41:59 +00:00
|
|
|
DCHECK(demon->priority() == Solver::DELAYED_PRIORITY);
|
|
|
|
|
if (demon->stamp() < stamp_) {
|
|
|
|
|
demon->set_stamp(stamp_);
|
2015-10-23 13:45:43 +02:00
|
|
|
delayed_queue_.push_back(demon);
|
2012-09-07 16:41:59 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2010-12-06 16:29:32 +00:00
|
|
|
void AfterFailure() {
|
2015-10-23 13:45:43 +02:00
|
|
|
// Clean queue.
|
|
|
|
|
var_queue_.clear();
|
|
|
|
|
delayed_queue_.clear();
|
|
|
|
|
|
|
|
|
|
// Call cleaning actions on variables.
|
|
|
|
|
if (clean_action_ != nullptr) {
|
|
|
|
|
clean_action_(solver_);
|
|
|
|
|
clean_action_ = nullptr;
|
|
|
|
|
} else if (clean_variable_ != nullptr) {
|
|
|
|
|
CleanVariableOnFail(clean_variable_);
|
|
|
|
|
clean_variable_ = nullptr;
|
2010-12-06 16:29:32 +00:00
|
|
|
}
|
2015-10-23 13:45:43 +02:00
|
|
|
|
2010-10-26 08:49:34 +00:00
|
|
|
freeze_level_ = 0;
|
2010-09-15 12:42:33 +00:00
|
|
|
in_process_ = false;
|
2010-11-15 15:08:17 +00:00
|
|
|
in_add_ = false;
|
|
|
|
|
to_add_.clear();
|
2010-09-15 12:42:33 +00:00
|
|
|
}
|
|
|
|
|
|
2013-10-10 15:23:20 +00:00
|
|
|
void increase_stamp() { stamp_++; }
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2021-04-01 12:13:35 +02:00
|
|
|
uint64_t stamp() const { return stamp_; }
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2015-10-23 13:45:43 +02:00
|
|
|
void set_action_on_fail(Solver::Action a) {
|
|
|
|
|
DCHECK(clean_variable_ == nullptr);
|
2017-04-19 16:20:56 +02:00
|
|
|
clean_action_ = std::move(a);
|
2015-10-23 13:45:43 +02:00
|
|
|
}
|
|
|
|
|
|
2020-10-29 14:25:39 +01:00
|
|
|
void set_variable_to_clean_on_fail(IntVar* var) {
|
2015-10-23 13:45:43 +02:00
|
|
|
DCHECK(clean_action_ == nullptr);
|
|
|
|
|
clean_variable_ = var;
|
|
|
|
|
}
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2015-10-23 13:45:43 +02:00
|
|
|
void reset_action_on_fail() {
|
|
|
|
|
DCHECK(clean_variable_ == nullptr);
|
|
|
|
|
clean_action_ = nullptr;
|
|
|
|
|
}
|
2010-11-15 15:08:17 +00:00
|
|
|
|
2020-10-29 14:25:39 +01:00
|
|
|
void AddConstraint(Constraint* const c) {
|
2010-11-15 15:08:17 +00:00
|
|
|
to_add_.push_back(c);
|
|
|
|
|
ProcessConstraints();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ProcessConstraints() {
|
|
|
|
|
if (!in_add_) {
|
|
|
|
|
in_add_ = true;
|
|
|
|
|
// We cannot store to_add_.size() as constraints can add other
|
2016-07-28 10:15:46 -07:00
|
|
|
// constraints. For the same reason a range-based for loop cannot be used.
|
|
|
|
|
// TODO(user): Make to_add_ a queue to make the behavior more obvious.
|
2010-11-15 15:08:17 +00:00
|
|
|
for (int counter = 0; counter < to_add_.size(); ++counter) {
|
2020-10-29 14:25:39 +01:00
|
|
|
Constraint* const constraint = to_add_[counter];
|
2011-01-06 17:40:30 +00:00
|
|
|
// TODO(user): Add profiling to initial propagation
|
2010-11-15 15:08:17 +00:00
|
|
|
constraint->PostAndPropagate();
|
|
|
|
|
}
|
|
|
|
|
in_add_ = false;
|
|
|
|
|
to_add_.clear();
|
|
|
|
|
}
|
|
|
|
|
}
|
2011-06-28 09:27:03 +00:00
|
|
|
|
2020-10-22 23:36:58 +02:00
|
|
|
private:
|
2020-10-29 14:25:39 +01:00
|
|
|
Solver* const solver_;
|
|
|
|
|
std::deque<Demon*> var_queue_;
|
|
|
|
|
std::deque<Demon*> delayed_queue_;
|
2021-04-01 12:13:35 +02:00
|
|
|
uint64_t stamp_;
|
2010-10-26 08:49:34 +00:00
|
|
|
// The number of nested freeze levels. The queue is frozen if and only if
|
|
|
|
|
// freeze_level_ > 0.
|
2021-04-01 12:13:35 +02:00
|
|
|
uint32_t freeze_level_;
|
2010-09-15 12:42:33 +00:00
|
|
|
bool in_process_;
|
2015-10-23 13:45:43 +02:00
|
|
|
Solver::Action clean_action_;
|
2020-10-29 14:25:39 +01:00
|
|
|
IntVar* clean_variable_;
|
|
|
|
|
std::vector<Constraint*> to_add_;
|
2010-11-15 15:08:17 +00:00
|
|
|
bool in_add_;
|
2011-11-16 17:32:24 +00:00
|
|
|
const bool instruments_demons_;
|
2010-09-15 12:42:33 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// ------------------ StateMarker / StateInfo struct -----------
|
|
|
|
|
|
2020-10-22 23:36:58 +02:00
|
|
|
struct StateInfo { // This is an internal structure to store
|
|
|
|
|
// additional information on the choice point.
|
|
|
|
|
public:
|
2015-10-23 13:45:43 +02:00
|
|
|
StateInfo()
|
2020-10-22 23:36:58 +02:00
|
|
|
: ptr_info(nullptr),
|
|
|
|
|
int_info(0),
|
|
|
|
|
depth(0),
|
|
|
|
|
left_depth(0),
|
2015-10-23 13:45:43 +02:00
|
|
|
reversible_action(nullptr) {}
|
2020-10-29 14:25:39 +01:00
|
|
|
StateInfo(void* pinfo, int iinfo)
|
2020-10-22 23:36:58 +02:00
|
|
|
: ptr_info(pinfo),
|
|
|
|
|
int_info(iinfo),
|
|
|
|
|
depth(0),
|
|
|
|
|
left_depth(0),
|
2015-10-23 13:45:43 +02:00
|
|
|
reversible_action(nullptr) {}
|
2020-10-29 14:25:39 +01:00
|
|
|
StateInfo(void* pinfo, int iinfo, int d, int ld)
|
2020-10-22 23:36:58 +02:00
|
|
|
: ptr_info(pinfo),
|
|
|
|
|
int_info(iinfo),
|
|
|
|
|
depth(d),
|
|
|
|
|
left_depth(ld),
|
2015-10-23 13:45:43 +02:00
|
|
|
reversible_action(nullptr) {}
|
|
|
|
|
StateInfo(Solver::Action a, bool fast)
|
2020-10-22 23:36:58 +02:00
|
|
|
: ptr_info(nullptr),
|
|
|
|
|
int_info(static_cast<int>(fast)),
|
|
|
|
|
depth(0),
|
|
|
|
|
left_depth(0),
|
|
|
|
|
reversible_action(std::move(a)) {}
|
2015-10-23 13:45:43 +02:00
|
|
|
|
2020-10-29 14:25:39 +01:00
|
|
|
void* ptr_info;
|
2010-09-15 12:42:33 +00:00
|
|
|
int int_info;
|
|
|
|
|
int depth;
|
|
|
|
|
int left_depth;
|
2015-10-23 13:45:43 +02:00
|
|
|
Solver::Action reversible_action;
|
2010-09-15 12:42:33 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
struct StateMarker {
|
2020-10-22 23:36:58 +02:00
|
|
|
public:
|
2020-10-29 14:25:39 +01:00
|
|
|
StateMarker(Solver::MarkerType t, const StateInfo& info);
|
2010-09-15 12:42:33 +00:00
|
|
|
friend class Solver;
|
|
|
|
|
friend struct Trail;
|
2013-10-10 15:23:20 +00:00
|
|
|
|
2020-10-22 23:36:58 +02:00
|
|
|
private:
|
2011-11-07 15:31:18 +00:00
|
|
|
Solver::MarkerType type_;
|
2010-09-15 12:42:33 +00:00
|
|
|
int rev_int_index_;
|
|
|
|
|
int rev_int64_index_;
|
|
|
|
|
int rev_uint64_index_;
|
2012-11-28 11:57:50 +00:00
|
|
|
int rev_double_index_;
|
2010-09-15 12:42:33 +00:00
|
|
|
int rev_ptr_index_;
|
|
|
|
|
int rev_boolvar_list_index_;
|
|
|
|
|
int rev_bools_index_;
|
|
|
|
|
int rev_int_memory_index_;
|
|
|
|
|
int rev_int64_memory_index_;
|
2012-11-28 12:01:23 +00:00
|
|
|
int rev_double_memory_index_;
|
2010-09-15 12:42:33 +00:00
|
|
|
int rev_object_memory_index_;
|
|
|
|
|
int rev_object_array_memory_index_;
|
|
|
|
|
int rev_memory_index_;
|
|
|
|
|
int rev_memory_array_index_;
|
|
|
|
|
StateInfo info_;
|
|
|
|
|
};
|
|
|
|
|
|
2020-10-29 14:25:39 +01:00
|
|
|
StateMarker::StateMarker(Solver::MarkerType t, const StateInfo& info)
|
2020-10-22 23:36:58 +02:00
|
|
|
: type_(t),
|
|
|
|
|
rev_int_index_(0),
|
|
|
|
|
rev_int64_index_(0),
|
|
|
|
|
rev_uint64_index_(0),
|
|
|
|
|
rev_double_index_(0),
|
|
|
|
|
rev_ptr_index_(0),
|
|
|
|
|
rev_boolvar_list_index_(0),
|
|
|
|
|
rev_bools_index_(0),
|
|
|
|
|
rev_int_memory_index_(0),
|
|
|
|
|
rev_int64_memory_index_(0),
|
|
|
|
|
rev_double_memory_index_(0),
|
|
|
|
|
rev_object_memory_index_(0),
|
|
|
|
|
rev_object_array_memory_index_(0),
|
|
|
|
|
info_(info) {}
|
2010-09-15 12:42:33 +00:00
|
|
|
|
|
|
|
|
// ---------- Trail and Reversibility ----------
|
|
|
|
|
|
2011-08-11 07:26:19 +00:00
|
|
|
namespace {
|
2010-09-15 12:42:33 +00:00
|
|
|
// ----- addrval struct -----
|
|
|
|
|
|
|
|
|
|
// This template class is used internally to implement reversibility.
|
|
|
|
|
// It stores an address and the value that was at the address.
|
2020-10-22 23:36:58 +02:00
|
|
|
template <class T>
|
|
|
|
|
struct addrval {
|
|
|
|
|
public:
|
2013-10-10 15:23:20 +00:00
|
|
|
addrval() : address_(nullptr) {}
|
2020-10-29 14:25:39 +01:00
|
|
|
explicit addrval(T* adr) : address_(adr), old_value_(*adr) {}
|
2010-09-15 12:42:33 +00:00
|
|
|
void restore() const { (*address_) = old_value_; }
|
2013-10-10 15:23:20 +00:00
|
|
|
|
2020-10-22 23:36:58 +02:00
|
|
|
private:
|
2020-10-29 14:25:39 +01:00
|
|
|
T* address_;
|
2010-09-15 12:42:33 +00:00
|
|
|
T old_value_;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// ----- Compressed trail -----
|
|
|
|
|
|
|
|
|
|
// ---------- Trail Packer ---------
|
|
|
|
|
// Abstract class to pack trail blocks.
|
|
|
|
|
|
2020-10-22 23:36:58 +02:00
|
|
|
template <class T>
|
|
|
|
|
class TrailPacker {
|
|
|
|
|
public:
|
2010-09-15 12:42:33 +00:00
|
|
|
explicit TrailPacker(int block_size) : block_size_(block_size) {}
|
2023-09-25 18:06:35 +02:00
|
|
|
|
|
|
|
|
// This type is neither copyable nor movable.
|
|
|
|
|
TrailPacker(const TrailPacker&) = delete;
|
|
|
|
|
TrailPacker& operator=(const TrailPacker&) = delete;
|
2010-09-15 12:42:33 +00:00
|
|
|
virtual ~TrailPacker() {}
|
|
|
|
|
int input_size() const { return block_size_ * sizeof(addrval<T>); }
|
2020-10-29 14:25:39 +01:00
|
|
|
virtual void Pack(const addrval<T>* block, std::string* packed_block) = 0;
|
|
|
|
|
virtual void Unpack(const std::string& packed_block, addrval<T>* block) = 0;
|
2013-10-10 15:23:20 +00:00
|
|
|
|
2020-10-22 23:36:58 +02:00
|
|
|
private:
|
2010-09-15 12:42:33 +00:00
|
|
|
const int block_size_;
|
|
|
|
|
};
|
|
|
|
|
|
2020-10-22 23:36:58 +02:00
|
|
|
template <class T>
|
|
|
|
|
class NoCompressionTrailPacker : public TrailPacker<T> {
|
|
|
|
|
public:
|
2010-09-15 12:42:33 +00:00
|
|
|
explicit NoCompressionTrailPacker(int block_size)
|
|
|
|
|
: TrailPacker<T>(block_size) {}
|
2023-09-25 18:06:35 +02:00
|
|
|
|
|
|
|
|
// This type is neither copyable nor movable.
|
|
|
|
|
NoCompressionTrailPacker(const NoCompressionTrailPacker&) = delete;
|
|
|
|
|
NoCompressionTrailPacker& operator=(const NoCompressionTrailPacker&) = delete;
|
2015-04-16 15:49:51 +02:00
|
|
|
~NoCompressionTrailPacker() override {}
|
2020-10-29 14:25:39 +01:00
|
|
|
void Pack(const addrval<T>* block, std::string* packed_block) override {
|
2013-10-10 15:23:20 +00:00
|
|
|
DCHECK(block != nullptr);
|
|
|
|
|
DCHECK(packed_block != nullptr);
|
2020-10-29 14:25:39 +01:00
|
|
|
absl::string_view block_str(reinterpret_cast<const char*>(block),
|
2017-12-08 14:52:49 +01:00
|
|
|
this->input_size());
|
|
|
|
|
packed_block->assign(block_str.data(), block_str.size());
|
2010-09-15 12:42:33 +00:00
|
|
|
}
|
2020-10-29 14:25:39 +01:00
|
|
|
void Unpack(const std::string& packed_block, addrval<T>* block) override {
|
2013-10-10 15:23:20 +00:00
|
|
|
DCHECK(block != nullptr);
|
2010-09-15 12:42:33 +00:00
|
|
|
memcpy(block, packed_block.c_str(), packed_block.size());
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
2020-10-22 23:36:58 +02:00
|
|
|
template <class T>
|
|
|
|
|
class ZlibTrailPacker : public TrailPacker<T> {
|
|
|
|
|
public:
|
2010-09-15 12:42:33 +00:00
|
|
|
explicit ZlibTrailPacker(int block_size)
|
|
|
|
|
: TrailPacker<T>(block_size),
|
|
|
|
|
tmp_size_(compressBound(this->input_size())),
|
|
|
|
|
tmp_block_(new char[tmp_size_]) {}
|
|
|
|
|
|
2023-09-25 18:06:35 +02:00
|
|
|
// This type is neither copyable nor movable.
|
|
|
|
|
ZlibTrailPacker(const ZlibTrailPacker&) = delete;
|
|
|
|
|
ZlibTrailPacker& operator=(const ZlibTrailPacker&) = delete;
|
|
|
|
|
|
2015-04-16 15:49:51 +02:00
|
|
|
~ZlibTrailPacker() override {}
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2020-10-29 14:25:39 +01:00
|
|
|
void Pack(const addrval<T>* block, std::string* packed_block) override {
|
2013-10-10 15:23:20 +00:00
|
|
|
DCHECK(block != nullptr);
|
|
|
|
|
DCHECK(packed_block != nullptr);
|
2010-09-15 12:42:33 +00:00
|
|
|
uLongf size = tmp_size_;
|
2013-10-10 15:23:20 +00:00
|
|
|
const int result =
|
2020-10-29 14:25:39 +01:00
|
|
|
compress(reinterpret_cast<Bytef*>(tmp_block_.get()), &size,
|
|
|
|
|
reinterpret_cast<const Bytef*>(block), this->input_size());
|
2010-09-15 12:42:33 +00:00
|
|
|
CHECK_EQ(Z_OK, result);
|
2017-12-08 14:52:49 +01:00
|
|
|
absl::string_view block_str;
|
|
|
|
|
block_str = absl::string_view(tmp_block_.get(), size);
|
|
|
|
|
packed_block->assign(block_str.data(), block_str.size());
|
2010-09-15 12:42:33 +00:00
|
|
|
}
|
|
|
|
|
|
2020-10-29 14:25:39 +01:00
|
|
|
void Unpack(const std::string& packed_block, addrval<T>* block) override {
|
2013-10-10 15:23:20 +00:00
|
|
|
DCHECK(block != nullptr);
|
2010-09-15 12:42:33 +00:00
|
|
|
uLongf size = this->input_size();
|
|
|
|
|
const int result =
|
2020-10-29 14:25:39 +01:00
|
|
|
uncompress(reinterpret_cast<Bytef*>(block), &size,
|
|
|
|
|
reinterpret_cast<const Bytef*>(packed_block.c_str()),
|
2010-09-15 12:42:33 +00:00
|
|
|
packed_block.size());
|
|
|
|
|
CHECK_EQ(Z_OK, result);
|
|
|
|
|
}
|
2011-06-28 09:27:03 +00:00
|
|
|
|
2020-10-22 23:36:58 +02:00
|
|
|
private:
|
2021-04-01 12:13:35 +02:00
|
|
|
const uint64_t tmp_size_;
|
2013-12-10 16:02:46 +00:00
|
|
|
std::unique_ptr<char[]> tmp_block_;
|
2010-09-15 12:42:33 +00:00
|
|
|
};
|
|
|
|
|
|
2020-10-22 23:36:58 +02:00
|
|
|
template <class T>
|
|
|
|
|
class CompressedTrail {
|
|
|
|
|
public:
|
2016-02-03 15:15:58 +01:00
|
|
|
CompressedTrail(
|
|
|
|
|
int block_size,
|
|
|
|
|
ConstraintSolverParameters::TrailCompression compression_level)
|
2020-10-22 23:36:58 +02:00
|
|
|
: block_size_(block_size),
|
|
|
|
|
blocks_(nullptr),
|
|
|
|
|
free_blocks_(nullptr),
|
|
|
|
|
data_(new addrval<T>[block_size]),
|
|
|
|
|
buffer_(new addrval<T>[block_size]),
|
|
|
|
|
buffer_used_(false),
|
|
|
|
|
current_(0),
|
|
|
|
|
size_(0) {
|
2010-09-15 12:42:33 +00:00
|
|
|
switch (compression_level) {
|
2020-10-22 23:36:58 +02:00
|
|
|
case ConstraintSolverParameters::NO_COMPRESSION: {
|
|
|
|
|
packer_.reset(new NoCompressionTrailPacker<T>(block_size));
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case ConstraintSolverParameters::COMPRESS_WITH_ZLIB: {
|
|
|
|
|
packer_.reset(new ZlibTrailPacker<T>(block_size));
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
default: {
|
|
|
|
|
LOG(ERROR) << "Should not be here";
|
|
|
|
|
}
|
2010-09-15 12:42:33 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// We zero all memory used by addrval arrays.
|
|
|
|
|
// Because of padding, all bytes may not be initialized, while compression
|
|
|
|
|
// will read them all, even if the uninitialized bytes are never used.
|
|
|
|
|
// This makes valgrind happy.
|
|
|
|
|
|
|
|
|
|
memset(data_.get(), 0, sizeof(*data_.get()) * block_size);
|
|
|
|
|
memset(buffer_.get(), 0, sizeof(*buffer_.get()) * block_size);
|
|
|
|
|
}
|
|
|
|
|
~CompressedTrail() {
|
|
|
|
|
FreeBlocks(blocks_);
|
|
|
|
|
FreeBlocks(free_blocks_);
|
|
|
|
|
}
|
2020-10-29 14:25:39 +01:00
|
|
|
const addrval<T>& Back() const {
|
2010-09-15 12:42:33 +00:00
|
|
|
// Back of empty trail.
|
|
|
|
|
DCHECK_GT(current_, 0);
|
|
|
|
|
return data_[current_ - 1];
|
|
|
|
|
}
|
|
|
|
|
void PopBack() {
|
|
|
|
|
if (size_ > 0) {
|
|
|
|
|
--current_;
|
|
|
|
|
if (current_ <= 0) {
|
|
|
|
|
if (buffer_used_) {
|
|
|
|
|
data_.swap(buffer_);
|
|
|
|
|
current_ = block_size_;
|
|
|
|
|
buffer_used_ = false;
|
2013-10-10 15:23:20 +00:00
|
|
|
} else if (blocks_ != nullptr) {
|
2010-09-15 12:42:33 +00:00
|
|
|
packer_->Unpack(blocks_->compressed, data_.get());
|
|
|
|
|
FreeTopBlock();
|
|
|
|
|
current_ = block_size_;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
--size_;
|
|
|
|
|
}
|
|
|
|
|
}
|
2020-10-29 14:25:39 +01:00
|
|
|
void PushBack(const addrval<T>& addr_val) {
|
2010-09-15 12:42:33 +00:00
|
|
|
if (current_ >= block_size_) {
|
2020-10-22 23:36:58 +02:00
|
|
|
if (buffer_used_) { // Buffer is used.
|
2010-09-15 12:42:33 +00:00
|
|
|
NewTopBlock();
|
|
|
|
|
packer_->Pack(buffer_.get(), &blocks_->compressed);
|
|
|
|
|
// O(1) operation.
|
|
|
|
|
data_.swap(buffer_);
|
|
|
|
|
} else {
|
|
|
|
|
data_.swap(buffer_);
|
|
|
|
|
buffer_used_ = true;
|
|
|
|
|
}
|
|
|
|
|
current_ = 0;
|
|
|
|
|
}
|
|
|
|
|
data_[current_] = addr_val;
|
|
|
|
|
++current_;
|
|
|
|
|
++size_;
|
|
|
|
|
}
|
2021-04-01 12:13:35 +02:00
|
|
|
int64_t size() const { return size_; }
|
2011-06-28 09:27:03 +00:00
|
|
|
|
2020-10-22 23:36:58 +02:00
|
|
|
private:
|
2010-09-15 12:42:33 +00:00
|
|
|
struct Block {
|
2013-12-16 10:24:42 +00:00
|
|
|
std::string compressed;
|
2020-10-29 14:25:39 +01:00
|
|
|
Block* next;
|
2010-09-15 12:42:33 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
void FreeTopBlock() {
|
2020-10-29 14:25:39 +01:00
|
|
|
Block* block = blocks_;
|
2010-09-15 12:42:33 +00:00
|
|
|
blocks_ = block->next;
|
|
|
|
|
block->compressed.clear();
|
|
|
|
|
block->next = free_blocks_;
|
|
|
|
|
free_blocks_ = block;
|
|
|
|
|
}
|
|
|
|
|
void NewTopBlock() {
|
2020-10-29 14:25:39 +01:00
|
|
|
Block* block = nullptr;
|
2013-10-10 15:23:20 +00:00
|
|
|
if (free_blocks_ != nullptr) {
|
2010-09-15 12:42:33 +00:00
|
|
|
block = free_blocks_;
|
|
|
|
|
free_blocks_ = block->next;
|
|
|
|
|
} else {
|
|
|
|
|
block = new Block;
|
|
|
|
|
}
|
|
|
|
|
block->next = blocks_;
|
|
|
|
|
blocks_ = block;
|
|
|
|
|
}
|
2020-10-29 14:25:39 +01:00
|
|
|
void FreeBlocks(Block* blocks) {
|
2013-10-10 15:23:20 +00:00
|
|
|
while (nullptr != blocks) {
|
2020-10-29 14:25:39 +01:00
|
|
|
Block* next = blocks->next;
|
2010-09-15 12:42:33 +00:00
|
|
|
delete blocks;
|
|
|
|
|
blocks = next;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-09-05 18:30:09 +02:00
|
|
|
std::unique_ptr<TrailPacker<T>> packer_;
|
2010-09-15 12:42:33 +00:00
|
|
|
const int block_size_;
|
2020-10-29 14:25:39 +01:00
|
|
|
Block* blocks_;
|
|
|
|
|
Block* free_blocks_;
|
2020-10-22 23:36:58 +02:00
|
|
|
std::unique_ptr<addrval<T>[]> data_;
|
|
|
|
|
std::unique_ptr<addrval<T>[]> buffer_;
|
2010-09-15 12:42:33 +00:00
|
|
|
bool buffer_used_;
|
|
|
|
|
int current_;
|
|
|
|
|
int size_;
|
|
|
|
|
};
|
2020-10-22 23:36:58 +02:00
|
|
|
} // namespace
|
2010-09-15 12:42:33 +00:00
|
|
|
|
|
|
|
|
// ----- Trail -----
|
|
|
|
|
|
2018-10-31 16:18:18 +01:00
|
|
|
// Object are explicitly copied using the copy ctor instead of
|
2010-09-15 12:42:33 +00:00
|
|
|
// passing and storing a pointer. As objects are small, copying is
|
|
|
|
|
// much faster than allocating (around 35% on a complete solve).
|
|
|
|
|
|
2023-05-31 14:27:08 +02:00
|
|
|
extern void RestoreBoolValue(IntVar* var);
|
2010-09-15 12:42:33 +00:00
|
|
|
|
|
|
|
|
struct Trail {
|
|
|
|
|
CompressedTrail<int> rev_ints_;
|
2021-04-01 12:13:35 +02:00
|
|
|
CompressedTrail<int64_t> rev_int64s_;
|
|
|
|
|
CompressedTrail<uint64_t> rev_uint64s_;
|
2012-11-28 11:57:50 +00:00
|
|
|
CompressedTrail<double> rev_doubles_;
|
2020-10-29 14:25:39 +01:00
|
|
|
CompressedTrail<void*> rev_ptrs_;
|
|
|
|
|
std::vector<IntVar*> rev_boolvar_list_;
|
|
|
|
|
std::vector<bool*> rev_bools_;
|
2011-05-17 20:38:55 +00:00
|
|
|
std::vector<bool> rev_bool_value_;
|
2020-10-29 14:25:39 +01:00
|
|
|
std::vector<int*> rev_int_memory_;
|
2021-04-01 12:13:35 +02:00
|
|
|
std::vector<int64_t*> rev_int64_memory_;
|
2020-10-29 14:25:39 +01:00
|
|
|
std::vector<double*> rev_double_memory_;
|
|
|
|
|
std::vector<BaseObject*> rev_object_memory_;
|
|
|
|
|
std::vector<BaseObject**> rev_object_array_memory_;
|
|
|
|
|
std::vector<void*> rev_memory_;
|
|
|
|
|
std::vector<void**> rev_memory_array_;
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2016-02-03 15:15:58 +01:00
|
|
|
Trail(int block_size,
|
|
|
|
|
ConstraintSolverParameters::TrailCompression compression_level)
|
2010-12-06 10:59:35 +00:00
|
|
|
: rev_ints_(block_size, compression_level),
|
|
|
|
|
rev_int64s_(block_size, compression_level),
|
|
|
|
|
rev_uint64s_(block_size, compression_level),
|
2012-11-28 11:57:50 +00:00
|
|
|
rev_doubles_(block_size, compression_level),
|
2010-12-06 10:59:35 +00:00
|
|
|
rev_ptrs_(block_size, compression_level) {}
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2020-10-29 14:25:39 +01:00
|
|
|
void BacktrackTo(StateMarker* m) {
|
2010-09-15 12:42:33 +00:00
|
|
|
int target = m->rev_int_index_;
|
|
|
|
|
for (int curr = rev_ints_.size(); curr > target; --curr) {
|
2020-10-29 14:25:39 +01:00
|
|
|
const addrval<int>& cell = rev_ints_.Back();
|
2010-09-15 12:42:33 +00:00
|
|
|
cell.restore();
|
|
|
|
|
rev_ints_.PopBack();
|
|
|
|
|
}
|
|
|
|
|
DCHECK_EQ(rev_ints_.size(), target);
|
|
|
|
|
// Incorrect trail size after backtrack.
|
|
|
|
|
target = m->rev_int64_index_;
|
|
|
|
|
for (int curr = rev_int64s_.size(); curr > target; --curr) {
|
2021-04-01 12:13:35 +02:00
|
|
|
const addrval<int64_t>& cell = rev_int64s_.Back();
|
2010-09-15 12:42:33 +00:00
|
|
|
cell.restore();
|
|
|
|
|
rev_int64s_.PopBack();
|
|
|
|
|
}
|
|
|
|
|
DCHECK_EQ(rev_int64s_.size(), target);
|
|
|
|
|
// Incorrect trail size after backtrack.
|
|
|
|
|
target = m->rev_uint64_index_;
|
|
|
|
|
for (int curr = rev_uint64s_.size(); curr > target; --curr) {
|
2021-04-01 12:13:35 +02:00
|
|
|
const addrval<uint64_t>& cell = rev_uint64s_.Back();
|
2010-09-15 12:42:33 +00:00
|
|
|
cell.restore();
|
|
|
|
|
rev_uint64s_.PopBack();
|
|
|
|
|
}
|
|
|
|
|
DCHECK_EQ(rev_uint64s_.size(), target);
|
|
|
|
|
// Incorrect trail size after backtrack.
|
2012-11-28 11:57:50 +00:00
|
|
|
target = m->rev_double_index_;
|
|
|
|
|
for (int curr = rev_doubles_.size(); curr > target; --curr) {
|
2020-10-29 14:25:39 +01:00
|
|
|
const addrval<double>& cell = rev_doubles_.Back();
|
2012-11-28 11:57:50 +00:00
|
|
|
cell.restore();
|
|
|
|
|
rev_doubles_.PopBack();
|
|
|
|
|
}
|
|
|
|
|
DCHECK_EQ(rev_doubles_.size(), target);
|
|
|
|
|
// Incorrect trail size after backtrack.
|
2010-09-15 12:42:33 +00:00
|
|
|
target = m->rev_ptr_index_;
|
|
|
|
|
for (int curr = rev_ptrs_.size(); curr > target; --curr) {
|
2020-10-29 14:25:39 +01:00
|
|
|
const addrval<void*>& cell = rev_ptrs_.Back();
|
2010-09-15 12:42:33 +00:00
|
|
|
cell.restore();
|
|
|
|
|
rev_ptrs_.PopBack();
|
|
|
|
|
}
|
|
|
|
|
DCHECK_EQ(rev_ptrs_.size(), target);
|
|
|
|
|
// Incorrect trail size after backtrack.
|
|
|
|
|
target = m->rev_boolvar_list_index_;
|
|
|
|
|
for (int curr = rev_boolvar_list_.size() - 1; curr >= target; --curr) {
|
2020-10-29 14:25:39 +01:00
|
|
|
IntVar* const var = rev_boolvar_list_[curr];
|
2010-09-15 12:42:33 +00:00
|
|
|
RestoreBoolValue(var);
|
|
|
|
|
}
|
|
|
|
|
rev_boolvar_list_.resize(target);
|
|
|
|
|
|
|
|
|
|
DCHECK_EQ(rev_bools_.size(), rev_bool_value_.size());
|
|
|
|
|
target = m->rev_bools_index_;
|
|
|
|
|
for (int curr = rev_bools_.size() - 1; curr >= target; --curr) {
|
|
|
|
|
*(rev_bools_[curr]) = rev_bool_value_[curr];
|
|
|
|
|
}
|
|
|
|
|
rev_bools_.resize(target);
|
|
|
|
|
rev_bool_value_.resize(target);
|
|
|
|
|
|
|
|
|
|
target = m->rev_int_memory_index_;
|
|
|
|
|
for (int curr = rev_int_memory_.size() - 1; curr >= target; --curr) {
|
|
|
|
|
delete[] rev_int_memory_[curr];
|
|
|
|
|
}
|
|
|
|
|
rev_int_memory_.resize(target);
|
|
|
|
|
|
|
|
|
|
target = m->rev_int64_memory_index_;
|
|
|
|
|
for (int curr = rev_int64_memory_.size() - 1; curr >= target; --curr) {
|
|
|
|
|
delete[] rev_int64_memory_[curr];
|
|
|
|
|
}
|
|
|
|
|
rev_int64_memory_.resize(target);
|
|
|
|
|
|
2012-11-28 12:01:23 +00:00
|
|
|
target = m->rev_double_memory_index_;
|
|
|
|
|
for (int curr = rev_double_memory_.size() - 1; curr >= target; --curr) {
|
|
|
|
|
delete[] rev_double_memory_[curr];
|
|
|
|
|
}
|
|
|
|
|
rev_double_memory_.resize(target);
|
|
|
|
|
|
2010-09-15 12:42:33 +00:00
|
|
|
target = m->rev_object_memory_index_;
|
|
|
|
|
for (int curr = rev_object_memory_.size() - 1; curr >= target; --curr) {
|
|
|
|
|
delete rev_object_memory_[curr];
|
|
|
|
|
}
|
|
|
|
|
rev_object_memory_.resize(target);
|
|
|
|
|
|
|
|
|
|
target = m->rev_object_array_memory_index_;
|
2013-10-10 15:23:20 +00:00
|
|
|
for (int curr = rev_object_array_memory_.size() - 1; curr >= target;
|
|
|
|
|
--curr) {
|
2010-09-15 12:42:33 +00:00
|
|
|
delete[] rev_object_array_memory_[curr];
|
|
|
|
|
}
|
|
|
|
|
rev_object_array_memory_.resize(target);
|
|
|
|
|
|
|
|
|
|
target = m->rev_memory_index_;
|
|
|
|
|
for (int curr = rev_memory_.size() - 1; curr >= target; --curr) {
|
2018-10-31 16:18:18 +01:00
|
|
|
// Explicitly call unsized delete
|
2020-10-29 14:25:39 +01:00
|
|
|
::operator delete(reinterpret_cast<char*>(rev_memory_[curr]));
|
2010-09-15 12:42:33 +00:00
|
|
|
// The previous cast is necessary to deallocate generic memory
|
|
|
|
|
// described by a void* when passed to the RevAlloc procedure
|
|
|
|
|
// We cannot do a delete[] there
|
|
|
|
|
// This is useful for cells of RevFIFO and should not be used outside
|
|
|
|
|
// of the product
|
|
|
|
|
}
|
|
|
|
|
rev_memory_.resize(target);
|
|
|
|
|
|
|
|
|
|
target = m->rev_memory_array_index_;
|
|
|
|
|
for (int curr = rev_memory_array_.size() - 1; curr >= target; --curr) {
|
2013-10-10 15:23:20 +00:00
|
|
|
delete[] rev_memory_array_[curr];
|
2010-09-15 12:42:33 +00:00
|
|
|
// delete [] version of the previous unsafe case.
|
|
|
|
|
}
|
|
|
|
|
rev_memory_array_.resize(target);
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
2020-10-29 14:25:39 +01:00
|
|
|
void Solver::InternalSaveValue(int* valptr) {
|
2010-09-15 12:42:33 +00:00
|
|
|
trail_->rev_ints_.PushBack(addrval<int>(valptr));
|
|
|
|
|
}
|
|
|
|
|
|
2021-04-01 12:13:35 +02:00
|
|
|
void Solver::InternalSaveValue(int64_t* valptr) {
|
|
|
|
|
trail_->rev_int64s_.PushBack(addrval<int64_t>(valptr));
|
2010-09-15 12:42:33 +00:00
|
|
|
}
|
|
|
|
|
|
2021-04-01 12:13:35 +02:00
|
|
|
void Solver::InternalSaveValue(uint64_t* valptr) {
|
|
|
|
|
trail_->rev_uint64s_.PushBack(addrval<uint64_t>(valptr));
|
2010-09-15 12:42:33 +00:00
|
|
|
}
|
|
|
|
|
|
2020-10-29 14:25:39 +01:00
|
|
|
void Solver::InternalSaveValue(double* valptr) {
|
2012-11-28 11:57:50 +00:00
|
|
|
trail_->rev_doubles_.PushBack(addrval<double>(valptr));
|
|
|
|
|
}
|
|
|
|
|
|
2020-10-29 14:25:39 +01:00
|
|
|
void Solver::InternalSaveValue(void** valptr) {
|
|
|
|
|
trail_->rev_ptrs_.PushBack(addrval<void*>(valptr));
|
2010-09-15 12:42:33 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// TODO(user) : this code is unsafe if you save the same alternating
|
|
|
|
|
// bool multiple times.
|
|
|
|
|
// The correct code should use a bitset and a single list.
|
2020-10-29 14:25:39 +01:00
|
|
|
void Solver::InternalSaveValue(bool* valptr) {
|
2010-09-15 12:42:33 +00:00
|
|
|
trail_->rev_bools_.push_back(valptr);
|
|
|
|
|
trail_->rev_bool_value_.push_back(*valptr);
|
|
|
|
|
}
|
|
|
|
|
|
2020-10-29 14:25:39 +01:00
|
|
|
BaseObject* Solver::SafeRevAlloc(BaseObject* ptr) {
|
2010-09-15 12:42:33 +00:00
|
|
|
check_alloc_state();
|
2011-11-14 20:55:35 +00:00
|
|
|
trail_->rev_object_memory_.push_back(ptr);
|
2010-09-15 12:42:33 +00:00
|
|
|
return ptr;
|
|
|
|
|
}
|
|
|
|
|
|
2020-10-29 14:25:39 +01:00
|
|
|
int* Solver::SafeRevAllocArray(int* ptr) {
|
2010-09-15 12:42:33 +00:00
|
|
|
check_alloc_state();
|
2011-11-14 20:55:35 +00:00
|
|
|
trail_->rev_int_memory_.push_back(ptr);
|
2010-09-15 12:42:33 +00:00
|
|
|
return ptr;
|
|
|
|
|
}
|
|
|
|
|
|
2021-04-01 12:13:35 +02:00
|
|
|
int64_t* Solver::SafeRevAllocArray(int64_t* ptr) {
|
2010-09-15 12:42:33 +00:00
|
|
|
check_alloc_state();
|
2011-11-14 20:55:35 +00:00
|
|
|
trail_->rev_int64_memory_.push_back(ptr);
|
2010-09-15 12:42:33 +00:00
|
|
|
return ptr;
|
|
|
|
|
}
|
|
|
|
|
|
2020-10-29 14:25:39 +01:00
|
|
|
double* Solver::SafeRevAllocArray(double* ptr) {
|
2012-11-28 12:01:23 +00:00
|
|
|
check_alloc_state();
|
|
|
|
|
trail_->rev_double_memory_.push_back(ptr);
|
|
|
|
|
return ptr;
|
|
|
|
|
}
|
|
|
|
|
|
2021-04-01 12:13:35 +02:00
|
|
|
uint64_t* Solver::SafeRevAllocArray(uint64_t* ptr) {
|
2010-09-15 12:42:33 +00:00
|
|
|
check_alloc_state();
|
2021-04-01 12:13:35 +02:00
|
|
|
trail_->rev_int64_memory_.push_back(reinterpret_cast<int64_t*>(ptr));
|
2010-09-15 12:42:33 +00:00
|
|
|
return ptr;
|
|
|
|
|
}
|
|
|
|
|
|
2020-10-29 14:25:39 +01:00
|
|
|
BaseObject** Solver::SafeRevAllocArray(BaseObject** ptr) {
|
2010-09-15 12:42:33 +00:00
|
|
|
check_alloc_state();
|
|
|
|
|
trail_->rev_object_array_memory_.push_back(ptr);
|
|
|
|
|
return ptr;
|
|
|
|
|
}
|
|
|
|
|
|
2020-10-29 14:25:39 +01:00
|
|
|
IntVar** Solver::SafeRevAllocArray(IntVar** ptr) {
|
|
|
|
|
BaseObject** in = SafeRevAllocArray(reinterpret_cast<BaseObject**>(ptr));
|
|
|
|
|
return reinterpret_cast<IntVar**>(in);
|
2010-09-15 12:42:33 +00:00
|
|
|
}
|
|
|
|
|
|
2020-10-29 14:25:39 +01:00
|
|
|
IntExpr** Solver::SafeRevAllocArray(IntExpr** ptr) {
|
|
|
|
|
BaseObject** in = SafeRevAllocArray(reinterpret_cast<BaseObject**>(ptr));
|
|
|
|
|
return reinterpret_cast<IntExpr**>(in);
|
2010-09-15 12:42:33 +00:00
|
|
|
}
|
|
|
|
|
|
2020-10-29 14:25:39 +01:00
|
|
|
Constraint** Solver::SafeRevAllocArray(Constraint** ptr) {
|
|
|
|
|
BaseObject** in = SafeRevAllocArray(reinterpret_cast<BaseObject**>(ptr));
|
|
|
|
|
return reinterpret_cast<Constraint**>(in);
|
2010-09-15 12:42:33 +00:00
|
|
|
}
|
|
|
|
|
|
2020-10-29 14:25:39 +01:00
|
|
|
void* Solver::UnsafeRevAllocAux(void* ptr) {
|
2010-09-15 12:42:33 +00:00
|
|
|
check_alloc_state();
|
|
|
|
|
trail_->rev_memory_.push_back(ptr);
|
|
|
|
|
return ptr;
|
|
|
|
|
}
|
|
|
|
|
|
2020-10-29 14:25:39 +01:00
|
|
|
void** Solver::UnsafeRevAllocArrayAux(void** ptr) {
|
2010-09-15 12:42:33 +00:00
|
|
|
check_alloc_state();
|
|
|
|
|
trail_->rev_memory_array_.push_back(ptr);
|
|
|
|
|
return ptr;
|
|
|
|
|
}
|
|
|
|
|
|
2020-10-29 14:25:39 +01:00
|
|
|
void InternalSaveBooleanVarValue(Solver* const solver, IntVar* const var) {
|
2011-08-11 05:15:18 +00:00
|
|
|
solver->trail_->rev_boolvar_list_.push_back(var);
|
2010-09-15 12:42:33 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ------------------ Search class -----------------
|
|
|
|
|
|
|
|
|
|
class Search {
|
2020-10-22 23:36:58 +02:00
|
|
|
public:
|
2020-10-29 14:25:39 +01:00
|
|
|
explicit Search(Solver* const s)
|
2020-10-22 23:36:58 +02:00
|
|
|
: solver_(s),
|
|
|
|
|
marker_stack_(),
|
2022-09-05 18:30:09 +02:00
|
|
|
monitor_event_listeners_(to_underlying(Solver::MonitorEvent::kLast)),
|
2020-10-22 23:36:58 +02:00
|
|
|
fail_buffer_(),
|
|
|
|
|
solution_counter_(0),
|
|
|
|
|
unchecked_solution_counter_(0),
|
|
|
|
|
decision_builder_(nullptr),
|
|
|
|
|
created_by_solve_(false),
|
|
|
|
|
search_depth_(0),
|
|
|
|
|
left_search_depth_(0),
|
|
|
|
|
should_restart_(false),
|
|
|
|
|
should_finish_(false),
|
|
|
|
|
sentinel_pushed_(0),
|
|
|
|
|
jmpbuf_filled_(false),
|
|
|
|
|
backtrack_at_the_end_of_the_search_(true) {}
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2011-12-15 11:50:32 +00:00
|
|
|
// Constructor for a dummy search. The only difference between a dummy search
|
|
|
|
|
// and a regular one is that the search depth and left search depth is
|
|
|
|
|
// initialized to -1 instead of zero.
|
2020-10-29 14:25:39 +01:00
|
|
|
Search(Solver* const s, int /* dummy_argument */)
|
2020-10-22 23:36:58 +02:00
|
|
|
: solver_(s),
|
|
|
|
|
marker_stack_(),
|
2022-09-05 18:30:09 +02:00
|
|
|
monitor_event_listeners_(to_underlying(Solver::MonitorEvent::kLast)),
|
2020-10-22 23:36:58 +02:00
|
|
|
fail_buffer_(),
|
|
|
|
|
solution_counter_(0),
|
|
|
|
|
unchecked_solution_counter_(0),
|
|
|
|
|
decision_builder_(nullptr),
|
|
|
|
|
created_by_solve_(false),
|
|
|
|
|
search_depth_(-1),
|
|
|
|
|
left_search_depth_(-1),
|
|
|
|
|
should_restart_(false),
|
|
|
|
|
should_finish_(false),
|
|
|
|
|
sentinel_pushed_(0),
|
|
|
|
|
jmpbuf_filled_(false),
|
|
|
|
|
backtrack_at_the_end_of_the_search_(true) {}
|
2011-12-15 11:50:32 +00:00
|
|
|
|
2018-04-11 13:00:30 +02:00
|
|
|
~Search() { gtl::STLDeleteElements(&marker_stack_); }
|
2011-12-15 11:50:32 +00:00
|
|
|
|
2010-09-15 12:42:33 +00:00
|
|
|
void EnterSearch();
|
|
|
|
|
void RestartSearch();
|
|
|
|
|
void ExitSearch();
|
2023-05-31 14:27:08 +02:00
|
|
|
void BeginNextDecision(DecisionBuilder* db);
|
|
|
|
|
void EndNextDecision(DecisionBuilder* db, Decision* d);
|
|
|
|
|
void ApplyDecision(Decision* d);
|
|
|
|
|
void AfterDecision(Decision* d, bool apply);
|
|
|
|
|
void RefuteDecision(Decision* d);
|
2010-09-15 12:42:33 +00:00
|
|
|
void BeginFail();
|
|
|
|
|
void EndFail();
|
|
|
|
|
void BeginInitialPropagation();
|
|
|
|
|
void EndInitialPropagation();
|
2010-10-06 16:04:31 +00:00
|
|
|
bool AtSolution();
|
|
|
|
|
bool AcceptSolution();
|
2010-09-15 12:42:33 +00:00
|
|
|
void NoMoreSolutions();
|
|
|
|
|
bool LocalOptimum();
|
2020-10-29 14:25:39 +01:00
|
|
|
bool AcceptDelta(Assignment* delta, Assignment* deltadelta);
|
2010-09-15 12:42:33 +00:00
|
|
|
void AcceptNeighbor();
|
2019-03-15 17:17:02 +01:00
|
|
|
void AcceptUncheckedNeighbor();
|
2019-04-16 09:25:06 -07:00
|
|
|
bool IsUncheckedSolutionLimitReached();
|
2010-09-15 12:42:33 +00:00
|
|
|
void PeriodicCheck();
|
2012-02-09 19:42:58 +00:00
|
|
|
int ProgressPercent();
|
2023-05-31 14:27:08 +02:00
|
|
|
void Accept(ModelVisitor* visitor) const;
|
2022-09-05 18:30:09 +02:00
|
|
|
void AddEventListener(Solver::MonitorEvent event, SearchMonitor* monitor) {
|
|
|
|
|
if (monitor != nullptr) {
|
|
|
|
|
monitor_event_listeners_[to_underlying(event)].push_back(monitor);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
const std::vector<SearchMonitor*>& GetEventListeners(
|
|
|
|
|
Solver::MonitorEvent event) const {
|
|
|
|
|
return monitor_event_listeners_[to_underlying(event)];
|
|
|
|
|
}
|
2010-09-15 12:42:33 +00:00
|
|
|
void Clear();
|
|
|
|
|
void IncrementSolutionCounter() { ++solution_counter_; }
|
2021-04-01 12:13:35 +02:00
|
|
|
int64_t solution_counter() const { return solution_counter_; }
|
2019-04-16 09:25:06 -07:00
|
|
|
void IncrementUncheckedSolutionCounter() { ++unchecked_solution_counter_; }
|
2021-04-01 12:13:35 +02:00
|
|
|
int64_t unchecked_solution_counter() const {
|
2019-04-16 09:25:06 -07:00
|
|
|
return unchecked_solution_counter_;
|
|
|
|
|
}
|
2020-10-29 14:25:39 +01:00
|
|
|
void set_decision_builder(DecisionBuilder* const db) {
|
2010-09-15 12:42:33 +00:00
|
|
|
decision_builder_ = db;
|
|
|
|
|
}
|
2020-10-29 14:25:39 +01:00
|
|
|
DecisionBuilder* decision_builder() const { return decision_builder_; }
|
2010-09-15 12:42:33 +00:00
|
|
|
void set_created_by_solve(bool c) { created_by_solve_ = c; }
|
|
|
|
|
bool created_by_solve() const { return created_by_solve_; }
|
|
|
|
|
Solver::DecisionModification ModifyDecision();
|
2017-12-08 14:52:49 +01:00
|
|
|
void SetBranchSelector(Solver::BranchSelector bs);
|
2010-09-15 12:42:33 +00:00
|
|
|
void LeftMove() {
|
|
|
|
|
search_depth_++;
|
|
|
|
|
left_search_depth_++;
|
|
|
|
|
}
|
2013-10-10 15:23:20 +00:00
|
|
|
void RightMove() { search_depth_++; }
|
2012-06-13 16:14:46 +00:00
|
|
|
bool backtrack_at_the_end_of_the_search() const {
|
|
|
|
|
return backtrack_at_the_end_of_the_search_;
|
|
|
|
|
}
|
|
|
|
|
void set_backtrack_at_the_end_of_the_search(bool restore) {
|
|
|
|
|
backtrack_at_the_end_of_the_search_ = restore;
|
|
|
|
|
}
|
2010-09-15 12:42:33 +00:00
|
|
|
int search_depth() const { return search_depth_; }
|
|
|
|
|
void set_search_depth(int d) { search_depth_ = d; }
|
|
|
|
|
int left_search_depth() const { return left_search_depth_; }
|
|
|
|
|
void set_search_left_depth(int d) { left_search_depth_ = d; }
|
|
|
|
|
void set_should_restart(bool s) { should_restart_ = s; }
|
|
|
|
|
bool should_restart() const { return should_restart_; }
|
|
|
|
|
void set_should_finish(bool s) { should_finish_ = s; }
|
|
|
|
|
bool should_finish() const { return should_finish_; }
|
|
|
|
|
void CheckFail() {
|
|
|
|
|
if (should_finish_ || should_restart_) {
|
|
|
|
|
solver_->Fail();
|
|
|
|
|
}
|
|
|
|
|
}
|
2023-11-09 13:46:25 +01:00
|
|
|
void set_search_context(absl::string_view search_context) {
|
2018-10-31 16:18:18 +01:00
|
|
|
search_context_ = search_context;
|
|
|
|
|
}
|
|
|
|
|
std::string search_context() const { return search_context_; }
|
2010-09-15 12:42:33 +00:00
|
|
|
friend class Solver;
|
2013-10-10 15:23:20 +00:00
|
|
|
|
2020-10-22 23:36:58 +02:00
|
|
|
private:
|
2010-09-15 12:42:33 +00:00
|
|
|
// Jumps back to the previous choice point, Checks if it was correctly set.
|
2010-09-16 09:15:57 +00:00
|
|
|
void JumpBack();
|
2010-09-15 12:42:33 +00:00
|
|
|
void ClearBuffer() {
|
2010-09-16 14:16:51 +00:00
|
|
|
CHECK(jmpbuf_filled_) << "Internal error in backtracking";
|
2010-09-15 12:42:33 +00:00
|
|
|
jmpbuf_filled_ = false;
|
|
|
|
|
}
|
|
|
|
|
|
2020-10-29 14:25:39 +01:00
|
|
|
Solver* const solver_;
|
|
|
|
|
std::vector<StateMarker*> marker_stack_;
|
2022-09-05 18:30:09 +02:00
|
|
|
std::vector<std::vector<SearchMonitor*>> monitor_event_listeners_;
|
2010-09-15 12:42:33 +00:00
|
|
|
jmp_buf fail_buffer_;
|
2021-04-01 12:13:35 +02:00
|
|
|
int64_t solution_counter_;
|
|
|
|
|
int64_t unchecked_solution_counter_;
|
2020-10-29 14:25:39 +01:00
|
|
|
DecisionBuilder* decision_builder_;
|
2010-09-15 12:42:33 +00:00
|
|
|
bool created_by_solve_;
|
2015-08-13 16:00:54 +02:00
|
|
|
Solver::BranchSelector selector_;
|
2010-09-15 12:42:33 +00:00
|
|
|
int search_depth_;
|
|
|
|
|
int left_search_depth_;
|
|
|
|
|
bool should_restart_;
|
|
|
|
|
bool should_finish_;
|
|
|
|
|
int sentinel_pushed_;
|
|
|
|
|
bool jmpbuf_filled_;
|
2012-06-13 16:14:46 +00:00
|
|
|
bool backtrack_at_the_end_of_the_search_;
|
2018-10-31 16:18:18 +01:00
|
|
|
std::string search_context_;
|
2010-09-15 12:42:33 +00:00
|
|
|
};
|
|
|
|
|
|
2010-09-16 09:15:57 +00:00
|
|
|
// Backtrack is implemented using 3 primitives:
|
|
|
|
|
// CP_TRY to start searching
|
2010-09-16 14:16:51 +00:00
|
|
|
// CP_DO_FAIL to signal a failure. The program will continue on the CP_ON_FAIL
|
2010-09-16 09:15:57 +00:00
|
|
|
// primitive.
|
2013-06-11 14:49:19 +00:00
|
|
|
// Implementation of backtrack using setjmp/longjmp.
|
|
|
|
|
// The clean portable way is to use exceptions, unfortunately, it can be much
|
|
|
|
|
// slower. Thus we use ideas from Prolog, CP/CLP implementations,
|
|
|
|
|
// continuations in C and implement the default failing and backtracking
|
|
|
|
|
// using setjmp/longjmp. You can still use exceptions by defining
|
|
|
|
|
// CP_USE_EXCEPTIONS_FOR_BACKTRACK
|
|
|
|
|
#ifndef CP_USE_EXCEPTIONS_FOR_BACKTRACK
|
2010-09-16 14:16:51 +00:00
|
|
|
// We cannot use a method/function for this as we would lose the
|
2010-09-16 09:15:57 +00:00
|
|
|
// context in the setjmp implementation.
|
2020-10-22 23:36:58 +02:00
|
|
|
#define CP_TRY(search) \
|
|
|
|
|
CHECK(!search->jmpbuf_filled_) << "Fail() called outside search"; \
|
|
|
|
|
search->jmpbuf_filled_ = true; \
|
2010-09-15 12:42:33 +00:00
|
|
|
if (setjmp(search->fail_buffer_) == 0)
|
2010-09-16 14:16:51 +00:00
|
|
|
#define CP_ON_FAIL else
|
|
|
|
|
#define CP_DO_FAIL(search) longjmp(search->fail_buffer_, 1)
|
2020-10-22 23:36:58 +02:00
|
|
|
#else // CP_USE_EXCEPTIONS_FOR_BACKTRACK
|
|
|
|
|
class FailException {};
|
|
|
|
|
#define CP_TRY(search) \
|
|
|
|
|
CHECK(!search->jmpbuf_filled_) << "Fail() called outside search"; \
|
|
|
|
|
search->jmpbuf_filled_ = true; \
|
2010-09-16 09:15:57 +00:00
|
|
|
try
|
2020-10-29 14:25:39 +01:00
|
|
|
#define CP_ON_FAIL catch (FailException&)
|
2010-09-16 14:16:51 +00:00
|
|
|
#define CP_DO_FAIL(search) throw FailException()
|
2020-10-22 23:36:58 +02:00
|
|
|
#endif // CP_USE_EXCEPTIONS_FOR_BACKTRACK
|
2010-09-16 09:15:57 +00:00
|
|
|
|
|
|
|
|
void Search::JumpBack() {
|
2012-01-04 22:35:44 +00:00
|
|
|
if (jmpbuf_filled_) {
|
|
|
|
|
jmpbuf_filled_ = false;
|
|
|
|
|
CP_DO_FAIL(this);
|
|
|
|
|
} else {
|
2013-12-16 10:24:42 +00:00
|
|
|
std::string explanation = "Failure outside of search";
|
2012-01-04 22:35:44 +00:00
|
|
|
solver_->AddConstraint(solver_->MakeFalseConstraint(explanation));
|
|
|
|
|
}
|
2010-09-16 09:15:57 +00:00
|
|
|
}
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2020-10-29 14:25:39 +01:00
|
|
|
Search* Solver::ActiveSearch() const { return searches_.back(); }
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2011-08-11 07:26:19 +00:00
|
|
|
namespace {
|
2010-09-15 12:42:33 +00:00
|
|
|
class ApplyBranchSelector : public DecisionBuilder {
|
2020-10-22 23:36:58 +02:00
|
|
|
public:
|
2017-04-19 16:20:56 +02:00
|
|
|
explicit ApplyBranchSelector(Solver::BranchSelector bs)
|
|
|
|
|
: selector_(std::move(bs)) {}
|
2015-04-16 15:49:51 +02:00
|
|
|
~ApplyBranchSelector() override {}
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2020-10-29 14:25:39 +01:00
|
|
|
Decision* Next(Solver* const s) override {
|
2010-09-15 12:42:33 +00:00
|
|
|
s->SetBranchSelector(selector_);
|
2013-10-10 15:23:20 +00:00
|
|
|
return nullptr;
|
2010-09-15 12:42:33 +00:00
|
|
|
}
|
|
|
|
|
|
2015-04-16 15:49:51 +02:00
|
|
|
std::string DebugString() const override { return "Apply(BranchSelector)"; }
|
2013-10-10 15:23:20 +00:00
|
|
|
|
2020-10-22 23:36:58 +02:00
|
|
|
private:
|
2015-08-13 16:00:54 +02:00
|
|
|
Solver::BranchSelector const selector_;
|
2010-09-15 12:42:33 +00:00
|
|
|
};
|
2020-10-22 23:36:58 +02:00
|
|
|
} // namespace
|
2011-08-11 07:26:19 +00:00
|
|
|
|
2017-04-19 16:20:56 +02:00
|
|
|
void Search::SetBranchSelector(Solver::BranchSelector bs) {
|
|
|
|
|
selector_ = std::move(bs);
|
|
|
|
|
}
|
2011-08-13 01:52:01 +00:00
|
|
|
|
2015-08-13 16:00:54 +02:00
|
|
|
void Solver::SetBranchSelector(BranchSelector bs) {
|
2011-12-15 11:50:32 +00:00
|
|
|
// We cannot use the trail as the search can be nested and thus
|
|
|
|
|
// deleted upon backtrack. Thus we guard the undo action by a
|
|
|
|
|
// check on the number of nesting of solve().
|
2015-10-23 13:45:43 +02:00
|
|
|
const int solve_depth = SolveDepth();
|
2020-10-22 23:36:58 +02:00
|
|
|
AddBacktrackAction(
|
2020-10-29 14:25:39 +01:00
|
|
|
[solve_depth](Solver* s) {
|
2020-10-22 23:36:58 +02:00
|
|
|
if (s->SolveDepth() == solve_depth) {
|
|
|
|
|
s->ActiveSearch()->SetBranchSelector(nullptr);
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
false);
|
2017-04-19 16:20:56 +02:00
|
|
|
searches_.back()->SetBranchSelector(std::move(bs));
|
2011-08-11 07:26:19 +00:00
|
|
|
}
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2020-10-29 14:25:39 +01:00
|
|
|
DecisionBuilder* Solver::MakeApplyBranchSelector(BranchSelector bs) {
|
2017-04-19 16:20:56 +02:00
|
|
|
return RevAlloc(new ApplyBranchSelector(std::move(bs)));
|
2010-09-15 12:42:33 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int Solver::SolveDepth() const {
|
2012-02-14 14:16:12 +00:00
|
|
|
return state_ == OUTSIDE_SEARCH ? 0 : searches_.size() - 1;
|
2010-09-15 12:42:33 +00:00
|
|
|
}
|
|
|
|
|
|
2013-10-10 15:23:20 +00:00
|
|
|
int Solver::SearchDepth() const { return searches_.back()->search_depth(); }
|
2010-09-15 12:42:33 +00:00
|
|
|
|
|
|
|
|
int Solver::SearchLeftDepth() const {
|
2011-12-15 11:50:32 +00:00
|
|
|
return searches_.back()->left_search_depth();
|
2010-09-15 12:42:33 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Solver::DecisionModification Search::ModifyDecision() {
|
2013-10-10 15:23:20 +00:00
|
|
|
if (selector_ != nullptr) {
|
2015-08-13 16:00:54 +02:00
|
|
|
return selector_();
|
2010-09-15 12:42:33 +00:00
|
|
|
}
|
|
|
|
|
return Solver::NO_CHANGE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Search::Clear() {
|
2022-09-05 18:30:09 +02:00
|
|
|
for (auto& listeners : monitor_event_listeners_) listeners.clear();
|
2010-09-15 12:42:33 +00:00
|
|
|
search_depth_ = 0;
|
|
|
|
|
left_search_depth_ = 0;
|
2015-08-13 16:00:54 +02:00
|
|
|
selector_ = nullptr;
|
2012-06-13 16:14:46 +00:00
|
|
|
backtrack_at_the_end_of_the_search_ = true;
|
2010-09-15 12:42:33 +00:00
|
|
|
}
|
|
|
|
|
|
2022-09-05 18:30:09 +02:00
|
|
|
#define CALL_EVENT_LISTENERS(Event) \
|
|
|
|
|
do { \
|
|
|
|
|
ForAll(GetEventListeners(Solver::MonitorEvent::k##Event), \
|
|
|
|
|
&SearchMonitor::Event); \
|
|
|
|
|
} while (false)
|
|
|
|
|
|
2010-09-15 12:42:33 +00:00
|
|
|
void Search::EnterSearch() {
|
2011-04-11 15:00:18 +00:00
|
|
|
// The solution counter is reset when entering search and not when
|
|
|
|
|
// leaving search. This enables the information to persist outside of
|
|
|
|
|
// top-level search.
|
2011-03-03 21:38:41 +00:00
|
|
|
solution_counter_ = 0;
|
2019-04-16 09:25:06 -07:00
|
|
|
unchecked_solution_counter_ = 0;
|
2011-03-03 21:38:41 +00:00
|
|
|
|
2022-09-05 18:30:09 +02:00
|
|
|
CALL_EVENT_LISTENERS(EnterSearch);
|
2010-09-15 12:42:33 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Search::ExitSearch() {
|
2012-06-13 16:14:46 +00:00
|
|
|
// Backtrack to the correct state.
|
2022-09-05 18:30:09 +02:00
|
|
|
CALL_EVENT_LISTENERS(ExitSearch);
|
2010-09-15 12:42:33 +00:00
|
|
|
}
|
|
|
|
|
|
2022-09-05 18:30:09 +02:00
|
|
|
void Search::RestartSearch() { CALL_EVENT_LISTENERS(RestartSearch); }
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2020-10-29 14:25:39 +01:00
|
|
|
void Search::BeginNextDecision(DecisionBuilder* const db) {
|
2022-09-05 18:30:09 +02:00
|
|
|
ForAll(GetEventListeners(Solver::MonitorEvent::kBeginNextDecision),
|
|
|
|
|
&SearchMonitor::BeginNextDecision, db);
|
2010-09-15 12:42:33 +00:00
|
|
|
CheckFail();
|
|
|
|
|
}
|
|
|
|
|
|
2020-10-29 14:25:39 +01:00
|
|
|
void Search::EndNextDecision(DecisionBuilder* const db, Decision* const d) {
|
2022-09-05 18:30:09 +02:00
|
|
|
ForAll(GetEventListeners(Solver::MonitorEvent::kEndNextDecision),
|
|
|
|
|
&SearchMonitor::EndNextDecision, db, d);
|
2010-09-15 12:42:33 +00:00
|
|
|
CheckFail();
|
|
|
|
|
}
|
|
|
|
|
|
2020-10-29 14:25:39 +01:00
|
|
|
void Search::ApplyDecision(Decision* const d) {
|
2022-09-05 18:30:09 +02:00
|
|
|
ForAll(GetEventListeners(Solver::MonitorEvent::kApplyDecision),
|
|
|
|
|
&SearchMonitor::ApplyDecision, d);
|
2010-09-15 12:42:33 +00:00
|
|
|
CheckFail();
|
|
|
|
|
}
|
|
|
|
|
|
2020-10-29 14:25:39 +01:00
|
|
|
void Search::AfterDecision(Decision* const d, bool apply) {
|
2022-09-05 18:30:09 +02:00
|
|
|
ForAll(GetEventListeners(Solver::MonitorEvent::kAfterDecision),
|
|
|
|
|
&SearchMonitor::AfterDecision, d, apply);
|
2011-03-31 12:28:12 +00:00
|
|
|
CheckFail();
|
|
|
|
|
}
|
|
|
|
|
|
2020-10-29 14:25:39 +01:00
|
|
|
void Search::RefuteDecision(Decision* const d) {
|
2022-09-05 18:30:09 +02:00
|
|
|
ForAll(GetEventListeners(Solver::MonitorEvent::kRefuteDecision),
|
|
|
|
|
&SearchMonitor::RefuteDecision, d);
|
2010-09-15 12:42:33 +00:00
|
|
|
CheckFail();
|
|
|
|
|
}
|
|
|
|
|
|
2022-09-05 18:30:09 +02:00
|
|
|
void Search::BeginFail() { CALL_EVENT_LISTENERS(BeginFail); }
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2022-09-05 18:30:09 +02:00
|
|
|
void Search::EndFail() { CALL_EVENT_LISTENERS(EndFail); }
|
2010-09-15 12:42:33 +00:00
|
|
|
|
|
|
|
|
void Search::BeginInitialPropagation() {
|
2022-09-05 18:30:09 +02:00
|
|
|
CALL_EVENT_LISTENERS(BeginInitialPropagation);
|
2010-09-15 12:42:33 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Search::EndInitialPropagation() {
|
2022-09-05 18:30:09 +02:00
|
|
|
CALL_EVENT_LISTENERS(EndInitialPropagation);
|
2010-09-15 12:42:33 +00:00
|
|
|
}
|
|
|
|
|
|
2010-10-06 16:04:31 +00:00
|
|
|
bool Search::AcceptSolution() {
|
|
|
|
|
bool valid = true;
|
2022-09-05 18:30:09 +02:00
|
|
|
for (SearchMonitor* const monitor :
|
|
|
|
|
GetEventListeners(Solver::MonitorEvent::kAcceptSolution)) {
|
2016-07-28 10:15:46 -07:00
|
|
|
if (!monitor->AcceptSolution()) {
|
2011-11-07 15:31:18 +00:00
|
|
|
// Even though we know the return value, we cannot return yet: this would
|
|
|
|
|
// break the contract we have with solution monitors. They all deserve
|
|
|
|
|
// a chance to look at the solution.
|
2010-10-06 16:04:31 +00:00
|
|
|
valid = false;
|
2010-09-15 12:42:33 +00:00
|
|
|
}
|
|
|
|
|
}
|
2010-10-06 16:04:31 +00:00
|
|
|
return valid;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool Search::AtSolution() {
|
|
|
|
|
bool should_continue = false;
|
2022-09-05 18:30:09 +02:00
|
|
|
for (SearchMonitor* const monitor :
|
|
|
|
|
GetEventListeners(Solver::MonitorEvent::kAtSolution)) {
|
2016-07-28 10:15:46 -07:00
|
|
|
if (monitor->AtSolution()) {
|
2011-11-07 15:31:18 +00:00
|
|
|
// Even though we know the return value, we cannot return yet: this would
|
|
|
|
|
// break the contract we have with solution monitors. They all deserve
|
|
|
|
|
// a chance to look at the solution.
|
2010-10-06 16:04:31 +00:00
|
|
|
should_continue = true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return should_continue;
|
2010-09-15 12:42:33 +00:00
|
|
|
}
|
|
|
|
|
|
2022-09-05 18:30:09 +02:00
|
|
|
void Search::NoMoreSolutions() { CALL_EVENT_LISTENERS(NoMoreSolutions); }
|
2010-09-15 12:42:33 +00:00
|
|
|
|
|
|
|
|
bool Search::LocalOptimum() {
|
2022-09-05 18:30:09 +02:00
|
|
|
bool at_local_optimum = false;
|
|
|
|
|
for (SearchMonitor* const monitor :
|
|
|
|
|
GetEventListeners(Solver::MonitorEvent::kLocalOptimum)) {
|
2016-07-28 10:15:46 -07:00
|
|
|
if (monitor->LocalOptimum()) {
|
2022-09-05 18:30:09 +02:00
|
|
|
at_local_optimum = true;
|
2010-09-15 12:42:33 +00:00
|
|
|
}
|
|
|
|
|
}
|
2022-09-05 18:30:09 +02:00
|
|
|
return at_local_optimum;
|
2010-09-15 12:42:33 +00:00
|
|
|
}
|
|
|
|
|
|
2020-10-29 14:25:39 +01:00
|
|
|
bool Search::AcceptDelta(Assignment* delta, Assignment* deltadelta) {
|
2010-09-15 12:42:33 +00:00
|
|
|
bool accept = true;
|
2022-09-05 18:30:09 +02:00
|
|
|
for (SearchMonitor* const monitor :
|
|
|
|
|
GetEventListeners(Solver::MonitorEvent::kAcceptDelta)) {
|
2016-07-28 10:15:46 -07:00
|
|
|
if (!monitor->AcceptDelta(delta, deltadelta)) {
|
2010-10-06 16:04:31 +00:00
|
|
|
accept = false;
|
|
|
|
|
}
|
2010-09-15 12:42:33 +00:00
|
|
|
}
|
|
|
|
|
return accept;
|
|
|
|
|
}
|
|
|
|
|
|
2022-09-05 18:30:09 +02:00
|
|
|
void Search::AcceptNeighbor() { CALL_EVENT_LISTENERS(AcceptNeighbor); }
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2019-03-15 17:17:02 +01:00
|
|
|
void Search::AcceptUncheckedNeighbor() {
|
2022-09-05 18:30:09 +02:00
|
|
|
CALL_EVENT_LISTENERS(AcceptUncheckedNeighbor);
|
2019-03-15 17:17:02 +01:00
|
|
|
}
|
|
|
|
|
|
2019-04-16 09:25:06 -07:00
|
|
|
bool Search::IsUncheckedSolutionLimitReached() {
|
2022-09-05 18:30:09 +02:00
|
|
|
for (SearchMonitor* const monitor : GetEventListeners(
|
|
|
|
|
Solver::MonitorEvent::kIsUncheckedSolutionLimitReached)) {
|
2019-04-16 09:25:06 -07:00
|
|
|
if (monitor->IsUncheckedSolutionLimitReached()) {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2022-09-05 18:30:09 +02:00
|
|
|
void Search::PeriodicCheck() { CALL_EVENT_LISTENERS(PeriodicCheck); }
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2012-02-09 19:42:58 +00:00
|
|
|
int Search::ProgressPercent() {
|
|
|
|
|
int progress = SearchMonitor::kNoProgress;
|
2022-09-05 18:30:09 +02:00
|
|
|
for (SearchMonitor* const monitor :
|
|
|
|
|
GetEventListeners(Solver::MonitorEvent::kProgressPercent)) {
|
2016-07-28 10:15:46 -07:00
|
|
|
progress = std::max(progress, monitor->ProgressPercent());
|
2012-02-09 19:42:58 +00:00
|
|
|
}
|
|
|
|
|
return progress;
|
|
|
|
|
}
|
|
|
|
|
|
2020-10-29 14:25:39 +01:00
|
|
|
void Search::Accept(ModelVisitor* const visitor) const {
|
2022-09-05 18:30:09 +02:00
|
|
|
ForAll(GetEventListeners(Solver::MonitorEvent::kAccept),
|
|
|
|
|
&SearchMonitor::Accept, visitor);
|
2013-10-10 15:23:20 +00:00
|
|
|
if (decision_builder_ != nullptr) {
|
2011-08-11 05:15:18 +00:00
|
|
|
decision_builder_->Accept(visitor);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-09-05 18:30:09 +02:00
|
|
|
#undef CALL_EVENT_LISTENERS
|
|
|
|
|
|
2023-07-05 13:10:19 +02:00
|
|
|
bool LocalOptimumReached(Search* search) { return search->LocalOptimum(); }
|
2012-02-14 14:16:12 +00:00
|
|
|
|
2023-07-05 13:10:19 +02:00
|
|
|
bool AcceptDelta(Search* search, Assignment* delta, Assignment* deltadelta) {
|
2012-02-14 14:16:12 +00:00
|
|
|
return search->AcceptDelta(delta, deltadelta);
|
|
|
|
|
}
|
|
|
|
|
|
2023-06-05 10:04:48 +02:00
|
|
|
void AcceptNeighbor(Search* search) { search->AcceptNeighbor(); }
|
2012-02-14 14:16:12 +00:00
|
|
|
|
2023-06-05 10:04:48 +02:00
|
|
|
void AcceptUncheckedNeighbor(Search* search) {
|
2019-03-15 17:17:02 +01:00
|
|
|
search->AcceptUncheckedNeighbor();
|
|
|
|
|
}
|
|
|
|
|
|
2011-08-11 07:26:19 +00:00
|
|
|
namespace {
|
2012-02-14 14:16:12 +00:00
|
|
|
|
2010-09-15 12:42:33 +00:00
|
|
|
// ---------- Fail Decision ----------
|
|
|
|
|
|
|
|
|
|
class FailDecision : public Decision {
|
2020-10-22 23:36:58 +02:00
|
|
|
public:
|
2020-10-29 14:25:39 +01:00
|
|
|
void Apply(Solver* const s) override { s->Fail(); }
|
|
|
|
|
void Refute(Solver* const s) override { s->Fail(); }
|
2010-09-15 12:42:33 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// Balancing decision
|
|
|
|
|
|
|
|
|
|
class BalancingDecision : public Decision {
|
2020-10-22 23:36:58 +02:00
|
|
|
public:
|
2015-04-16 15:49:51 +02:00
|
|
|
~BalancingDecision() override {}
|
2022-05-18 16:41:03 +02:00
|
|
|
void Apply(Solver* const /*s*/) override {}
|
|
|
|
|
void Refute(Solver* const /*s*/) override {}
|
2010-09-15 12:42:33 +00:00
|
|
|
};
|
2020-10-22 23:36:58 +02:00
|
|
|
} // namespace
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2020-10-29 14:25:39 +01:00
|
|
|
Decision* Solver::MakeFailDecision() { return fail_decision_.get(); }
|
2011-08-11 07:26:19 +00:00
|
|
|
|
2010-09-15 12:42:33 +00:00
|
|
|
// ------------------ Solver class -----------------
|
|
|
|
|
|
|
|
|
|
// These magic numbers are there to make sure we pop the correct
|
|
|
|
|
// sentinels throughout the search.
|
|
|
|
|
namespace {
|
|
|
|
|
enum SentinelMarker {
|
|
|
|
|
INITIAL_SEARCH_SENTINEL = 10000000,
|
2013-10-10 15:23:20 +00:00
|
|
|
ROOT_NODE_SENTINEL = 20000000,
|
|
|
|
|
SOLVER_CTOR_SENTINEL = 40000000
|
2010-09-15 12:42:33 +00:00
|
|
|
};
|
2020-10-22 23:36:58 +02:00
|
|
|
} // namespace
|
2011-08-11 05:15:18 +00:00
|
|
|
|
2023-05-31 14:27:08 +02:00
|
|
|
extern PropagationMonitor* BuildTrace(Solver* s);
|
|
|
|
|
extern LocalSearchMonitor* BuildLocalSearchMonitorPrimary(Solver* s);
|
|
|
|
|
extern ModelCache* BuildModelCache(Solver* solver);
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2013-12-16 10:24:42 +00:00
|
|
|
std::string Solver::model_name() const { return name_; }
|
2011-09-13 09:24:49 +00:00
|
|
|
|
2016-06-02 13:19:10 +02:00
|
|
|
namespace {
|
2020-10-29 14:25:39 +01:00
|
|
|
void CheckSolverParameters(const ConstraintSolverParameters& parameters) {
|
2016-06-02 13:19:10 +02:00
|
|
|
CHECK_GT(parameters.array_split_size(), 0)
|
|
|
|
|
<< "Were parameters built using Solver::DefaultSolverParameters() ?";
|
|
|
|
|
}
|
2020-10-22 23:36:58 +02:00
|
|
|
} // namespace
|
2016-06-02 13:19:10 +02:00
|
|
|
|
2020-10-29 14:25:39 +01:00
|
|
|
Solver::Solver(const std::string& name,
|
|
|
|
|
const ConstraintSolverParameters& parameters)
|
2020-10-22 23:36:58 +02:00
|
|
|
: name_(name),
|
|
|
|
|
parameters_(parameters),
|
|
|
|
|
random_(CpRandomSeed()),
|
|
|
|
|
demon_profiler_(BuildDemonProfiler(this)),
|
|
|
|
|
use_fast_local_search_(true),
|
2016-07-28 10:15:46 -07:00
|
|
|
local_search_profiler_(BuildLocalSearchProfiler(this)) {
|
2010-12-06 10:59:35 +00:00
|
|
|
Init();
|
|
|
|
|
}
|
|
|
|
|
|
2020-10-29 14:25:39 +01:00
|
|
|
Solver::Solver(const std::string& name)
|
2020-10-22 23:36:58 +02:00
|
|
|
: name_(name),
|
|
|
|
|
parameters_(DefaultSolverParameters()),
|
|
|
|
|
random_(CpRandomSeed()),
|
|
|
|
|
demon_profiler_(BuildDemonProfiler(this)),
|
2019-03-15 17:17:02 +01:00
|
|
|
use_fast_local_search_(true),
|
2016-07-28 10:15:46 -07:00
|
|
|
local_search_profiler_(BuildLocalSearchProfiler(this)) {
|
2010-12-06 10:59:35 +00:00
|
|
|
Init();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Solver::Init() {
|
2016-06-02 13:19:10 +02:00
|
|
|
CheckSolverParameters(parameters_);
|
2022-05-18 16:41:03 +02:00
|
|
|
queue_ = std::make_unique<Queue>(this);
|
|
|
|
|
trail_ = std::make_unique<Trail>(parameters_.trail_block_size(),
|
|
|
|
|
parameters_.compress_trail());
|
2014-07-09 11:10:20 +00:00
|
|
|
state_ = OUTSIDE_SEARCH;
|
|
|
|
|
branches_ = 0;
|
|
|
|
|
fails_ = 0;
|
|
|
|
|
decisions_ = 0;
|
|
|
|
|
neighbors_ = 0;
|
|
|
|
|
filtered_neighbors_ = 0;
|
|
|
|
|
accepted_neighbors_ = 0;
|
2019-03-15 17:17:02 +01:00
|
|
|
optimization_direction_ = NOT_SET;
|
2022-05-18 16:41:03 +02:00
|
|
|
timer_ = std::make_unique<ClockTimer>();
|
2014-07-09 11:10:20 +00:00
|
|
|
searches_.assign(1, new Search(this, 0));
|
2021-02-07 00:45:47 +01:00
|
|
|
fail_stamp_ = uint64_t{1};
|
2022-05-18 16:41:03 +02:00
|
|
|
balancing_decision_ = std::make_unique<BalancingDecision>();
|
2014-07-09 11:10:20 +00:00
|
|
|
fail_intercept_ = nullptr;
|
|
|
|
|
true_constraint_ = nullptr;
|
|
|
|
|
false_constraint_ = nullptr;
|
2022-05-18 16:41:03 +02:00
|
|
|
fail_decision_ = std::make_unique<FailDecision>();
|
2014-07-09 11:10:20 +00:00
|
|
|
constraint_index_ = 0;
|
|
|
|
|
additional_constraint_index_ = 0;
|
2014-11-07 14:30:53 +00:00
|
|
|
num_int_vars_ = 0;
|
2014-07-09 11:10:20 +00:00
|
|
|
propagation_monitor_.reset(BuildTrace(this));
|
2022-06-21 11:43:36 +02:00
|
|
|
local_search_monitor_.reset(BuildLocalSearchMonitorPrimary(this));
|
2014-07-09 11:10:20 +00:00
|
|
|
print_trace_ = nullptr;
|
|
|
|
|
anonymous_variable_index_ = 0;
|
|
|
|
|
should_fail_ = false;
|
|
|
|
|
|
2010-09-15 12:42:33 +00:00
|
|
|
for (int i = 0; i < kNumPriorities; ++i) {
|
|
|
|
|
demon_runs_[i] = 0;
|
|
|
|
|
}
|
|
|
|
|
searches_.push_back(new Search(this));
|
|
|
|
|
PushSentinel(SOLVER_CTOR_SENTINEL);
|
2020-10-22 23:36:58 +02:00
|
|
|
InitCachedIntConstants(); // to be called after the SENTINEL is set.
|
|
|
|
|
InitCachedConstraint(); // Cache the true constraint.
|
2010-10-10 00:23:55 +00:00
|
|
|
timer_->Restart();
|
2011-09-08 00:36:56 +00:00
|
|
|
model_cache_.reset(BuildModelCache(this));
|
2020-10-29 14:25:39 +01:00
|
|
|
AddPropagationMonitor(reinterpret_cast<PropagationMonitor*>(demon_profiler_));
|
2016-07-28 10:15:46 -07:00
|
|
|
AddLocalSearchMonitor(
|
2020-10-29 14:25:39 +01:00
|
|
|
reinterpret_cast<LocalSearchMonitor*>(local_search_profiler_));
|
2010-09-15 12:42:33 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Solver::~Solver() {
|
|
|
|
|
// solver destructor called with searches open.
|
2012-02-14 14:16:12 +00:00
|
|
|
CHECK_EQ(2, searches_.size());
|
2010-09-15 12:42:33 +00:00
|
|
|
BacktrackToSentinel(INITIAL_SEARCH_SENTINEL);
|
|
|
|
|
|
|
|
|
|
StateInfo info;
|
2011-11-07 15:31:18 +00:00
|
|
|
Solver::MarkerType finalType = PopState(&info);
|
2010-09-15 12:42:33 +00:00
|
|
|
// Not popping a SENTINEL in Solver destructor.
|
|
|
|
|
DCHECK_EQ(finalType, SENTINEL);
|
|
|
|
|
// Not popping initial SENTINEL in Solver destructor.
|
|
|
|
|
DCHECK_EQ(info.int_info, SOLVER_CTOR_SENTINEL);
|
2018-04-11 13:00:30 +02:00
|
|
|
gtl::STLDeleteElements(&searches_);
|
2011-11-21 02:52:58 +00:00
|
|
|
DeleteDemonProfiler(demon_profiler_);
|
2016-07-28 10:15:46 -07:00
|
|
|
DeleteLocalSearchProfiler(local_search_profiler_);
|
2010-09-15 12:42:33 +00:00
|
|
|
}
|
|
|
|
|
|
2013-12-16 10:24:42 +00:00
|
|
|
std::string Solver::DebugString() const {
|
|
|
|
|
std::string out = "Solver(name = \"" + name_ + "\", state = ";
|
2010-09-15 12:42:33 +00:00
|
|
|
switch (state_) {
|
2020-10-22 23:36:58 +02:00
|
|
|
case OUTSIDE_SEARCH:
|
|
|
|
|
out += "OUTSIDE_SEARCH";
|
|
|
|
|
break;
|
|
|
|
|
case IN_ROOT_NODE:
|
|
|
|
|
out += "IN_ROOT_NODE";
|
|
|
|
|
break;
|
|
|
|
|
case IN_SEARCH:
|
|
|
|
|
out += "IN_SEARCH";
|
|
|
|
|
break;
|
|
|
|
|
case AT_SOLUTION:
|
|
|
|
|
out += "AT_SOLUTION";
|
|
|
|
|
break;
|
|
|
|
|
case NO_MORE_SOLUTIONS:
|
|
|
|
|
out += "NO_MORE_SOLUTIONS";
|
|
|
|
|
break;
|
|
|
|
|
case PROBLEM_INFEASIBLE:
|
|
|
|
|
out += "PROBLEM_INFEASIBLE";
|
|
|
|
|
break;
|
2010-09-15 12:42:33 +00:00
|
|
|
}
|
2018-10-31 16:18:18 +01:00
|
|
|
absl::StrAppendFormat(
|
2018-06-08 16:40:43 +02:00
|
|
|
&out,
|
2018-12-03 14:26:31 +01:00
|
|
|
", branches = %d, fails = %d, decisions = %d, delayed demon runs = %d, "
|
|
|
|
|
"var demon runs = %d, normal demon runs = %d, Run time = %d ms)",
|
2018-06-08 16:40:43 +02:00
|
|
|
branches_, fails_, decisions_, demon_runs_[DELAYED_PRIORITY],
|
|
|
|
|
demon_runs_[VAR_PRIORITY], demon_runs_[NORMAL_PRIORITY], wall_time());
|
2010-09-15 12:42:33 +00:00
|
|
|
return out;
|
|
|
|
|
}
|
|
|
|
|
|
2021-04-01 12:13:35 +02:00
|
|
|
int64_t Solver::MemoryUsage() { return GetProcessMemoryUsage(); }
|
2010-10-11 17:39:39 +00:00
|
|
|
|
2021-04-01 12:13:35 +02:00
|
|
|
int64_t Solver::wall_time() const {
|
2019-04-01 11:36:53 +02:00
|
|
|
return absl::ToInt64Milliseconds(timer_->GetDuration());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
absl::Time Solver::Now() const {
|
|
|
|
|
return absl::FromUnixSeconds(0) + timer_->GetDuration();
|
|
|
|
|
}
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2021-04-01 12:13:35 +02:00
|
|
|
int64_t Solver::solutions() const {
|
|
|
|
|
return TopLevelSearch()->solution_counter();
|
|
|
|
|
}
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2021-04-01 12:13:35 +02:00
|
|
|
int64_t Solver::unchecked_solutions() const {
|
2019-04-16 09:25:06 -07:00
|
|
|
return TopLevelSearch()->unchecked_solution_counter();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Solver::IncrementUncheckedSolutionCounter() {
|
|
|
|
|
TopLevelSearch()->IncrementUncheckedSolutionCounter();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool Solver::IsUncheckedSolutionLimitReached() {
|
|
|
|
|
return TopLevelSearch()->IsUncheckedSolutionLimitReached();
|
|
|
|
|
}
|
|
|
|
|
|
2013-10-10 15:23:20 +00:00
|
|
|
void Solver::TopPeriodicCheck() { TopLevelSearch()->PeriodicCheck(); }
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2013-10-10 15:23:20 +00:00
|
|
|
int Solver::TopProgressPercent() { return TopLevelSearch()->ProgressPercent(); }
|
2012-02-09 19:42:58 +00:00
|
|
|
|
2020-10-18 16:38:25 +02:00
|
|
|
ConstraintSolverStatistics Solver::GetConstraintSolverStatistics() const {
|
|
|
|
|
ConstraintSolverStatistics stats;
|
|
|
|
|
stats.set_num_branches(branches());
|
|
|
|
|
stats.set_num_failures(failures());
|
|
|
|
|
stats.set_num_solutions(solutions());
|
|
|
|
|
stats.set_bytes_used(MemoryUsage());
|
|
|
|
|
stats.set_duration_seconds(absl::ToDoubleSeconds(timer_->GetDuration()));
|
|
|
|
|
return stats;
|
|
|
|
|
}
|
|
|
|
|
|
2010-09-15 12:42:33 +00:00
|
|
|
void Solver::PushState() {
|
|
|
|
|
StateInfo info;
|
|
|
|
|
PushState(SIMPLE_MARKER, info);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Solver::PopState() {
|
|
|
|
|
StateInfo info;
|
2011-11-07 15:31:18 +00:00
|
|
|
Solver::MarkerType t = PopState(&info);
|
2010-09-15 12:42:33 +00:00
|
|
|
CHECK_EQ(SIMPLE_MARKER, t);
|
|
|
|
|
}
|
|
|
|
|
|
2020-10-29 14:25:39 +01:00
|
|
|
void Solver::PushState(Solver::MarkerType t, const StateInfo& info) {
|
|
|
|
|
StateMarker* m = new StateMarker(t, info);
|
2010-09-15 12:42:33 +00:00
|
|
|
if (t != REVERSIBLE_ACTION || info.int_info == 0) {
|
|
|
|
|
m->rev_int_index_ = trail_->rev_ints_.size();
|
|
|
|
|
m->rev_int64_index_ = trail_->rev_int64s_.size();
|
|
|
|
|
m->rev_uint64_index_ = trail_->rev_uint64s_.size();
|
2012-11-28 11:57:50 +00:00
|
|
|
m->rev_double_index_ = trail_->rev_doubles_.size();
|
2010-09-15 12:42:33 +00:00
|
|
|
m->rev_ptr_index_ = trail_->rev_ptrs_.size();
|
|
|
|
|
m->rev_boolvar_list_index_ = trail_->rev_boolvar_list_.size();
|
|
|
|
|
m->rev_bools_index_ = trail_->rev_bools_.size();
|
|
|
|
|
m->rev_int_memory_index_ = trail_->rev_int_memory_.size();
|
|
|
|
|
m->rev_int64_memory_index_ = trail_->rev_int64_memory_.size();
|
2012-11-28 12:01:23 +00:00
|
|
|
m->rev_double_memory_index_ = trail_->rev_double_memory_.size();
|
2010-09-15 12:42:33 +00:00
|
|
|
m->rev_object_memory_index_ = trail_->rev_object_memory_.size();
|
|
|
|
|
m->rev_object_array_memory_index_ = trail_->rev_object_array_memory_.size();
|
|
|
|
|
m->rev_memory_index_ = trail_->rev_memory_.size();
|
|
|
|
|
m->rev_memory_array_index_ = trail_->rev_memory_array_.size();
|
|
|
|
|
}
|
|
|
|
|
searches_.back()->marker_stack_.push_back(m);
|
|
|
|
|
queue_->increase_stamp();
|
|
|
|
|
}
|
|
|
|
|
|
2015-10-23 13:45:43 +02:00
|
|
|
void Solver::AddBacktrackAction(Action a, bool fast) {
|
2017-04-19 16:20:56 +02:00
|
|
|
StateInfo info(std::move(a), fast);
|
2010-09-15 12:42:33 +00:00
|
|
|
PushState(REVERSIBLE_ACTION, info);
|
|
|
|
|
}
|
|
|
|
|
|
2020-10-29 14:25:39 +01:00
|
|
|
Solver::MarkerType Solver::PopState(StateInfo* info) {
|
2010-09-15 12:42:33 +00:00
|
|
|
CHECK(!searches_.back()->marker_stack_.empty())
|
|
|
|
|
<< "PopState() on an empty stack";
|
2013-10-10 15:23:20 +00:00
|
|
|
CHECK(info != nullptr);
|
2020-10-29 14:25:39 +01:00
|
|
|
StateMarker* const m = searches_.back()->marker_stack_.back();
|
2010-09-15 12:42:33 +00:00
|
|
|
if (m->type_ != REVERSIBLE_ACTION || m->info_.int_info == 0) {
|
|
|
|
|
trail_->BacktrackTo(m);
|
|
|
|
|
}
|
2011-11-07 15:31:18 +00:00
|
|
|
Solver::MarkerType t = m->type_;
|
2010-09-15 12:42:33 +00:00
|
|
|
(*info) = m->info_;
|
|
|
|
|
searches_.back()->marker_stack_.pop_back();
|
|
|
|
|
delete m;
|
|
|
|
|
queue_->increase_stamp();
|
|
|
|
|
return t;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Solver::check_alloc_state() {
|
|
|
|
|
switch (state_) {
|
2020-10-22 23:36:58 +02:00
|
|
|
case OUTSIDE_SEARCH:
|
|
|
|
|
case IN_ROOT_NODE:
|
|
|
|
|
case IN_SEARCH:
|
|
|
|
|
case NO_MORE_SOLUTIONS:
|
|
|
|
|
case PROBLEM_INFEASIBLE:
|
|
|
|
|
break;
|
|
|
|
|
case AT_SOLUTION:
|
|
|
|
|
LOG(FATAL) << "allocating at a leaf node";
|
|
|
|
|
default:
|
|
|
|
|
LOG(FATAL) << "This switch was supposed to be exhaustive, but it is not!";
|
2010-09-15 12:42:33 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2013-10-10 15:23:20 +00:00
|
|
|
void Solver::FreezeQueue() { queue_->Freeze(); }
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2013-10-10 15:23:20 +00:00
|
|
|
void Solver::UnfreezeQueue() { queue_->Unfreeze(); }
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2020-10-29 14:25:39 +01:00
|
|
|
void Solver::EnqueueVar(Demon* const d) { queue_->EnqueueVar(d); }
|
2012-09-07 15:27:53 +00:00
|
|
|
|
2020-10-29 14:25:39 +01:00
|
|
|
void Solver::EnqueueDelayedDemon(Demon* const d) {
|
2012-09-07 16:41:59 +00:00
|
|
|
queue_->EnqueueDelayedDemon(d);
|
2010-09-15 12:42:33 +00:00
|
|
|
}
|
|
|
|
|
|
2020-10-29 14:25:39 +01:00
|
|
|
void Solver::ExecuteAll(const SimpleRevFIFO<Demon*>& demons) {
|
2012-09-10 08:37:41 +00:00
|
|
|
queue_->ExecuteAll(demons);
|
|
|
|
|
}
|
|
|
|
|
|
2020-10-29 14:25:39 +01:00
|
|
|
void Solver::EnqueueAll(const SimpleRevFIFO<Demon*>& demons) {
|
2013-06-11 14:49:19 +00:00
|
|
|
queue_->EnqueueAll(demons);
|
|
|
|
|
}
|
|
|
|
|
|
2021-04-01 12:13:35 +02:00
|
|
|
uint64_t Solver::stamp() const { return queue_->stamp(); }
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2021-04-01 12:13:35 +02:00
|
|
|
uint64_t Solver::fail_stamp() const { return fail_stamp_; }
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2017-04-19 16:20:56 +02:00
|
|
|
void Solver::set_action_on_fail(Action a) {
|
|
|
|
|
queue_->set_action_on_fail(std::move(a));
|
|
|
|
|
}
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2020-10-29 14:25:39 +01:00
|
|
|
void Solver::set_variable_to_clean_on_fail(IntVar* v) {
|
2015-10-23 13:45:43 +02:00
|
|
|
queue_->set_variable_to_clean_on_fail(v);
|
2010-09-15 12:42:33 +00:00
|
|
|
}
|
|
|
|
|
|
2015-10-23 13:45:43 +02:00
|
|
|
void Solver::reset_action_on_fail() { queue_->reset_action_on_fail(); }
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2020-10-29 14:25:39 +01:00
|
|
|
void Solver::AddConstraint(Constraint* const c) {
|
2013-07-22 18:24:02 +00:00
|
|
|
DCHECK(c != nullptr);
|
2012-07-05 14:22:07 +00:00
|
|
|
if (c == true_constraint_) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
2010-09-15 12:42:33 +00:00
|
|
|
if (state_ == IN_SEARCH) {
|
2010-11-15 15:08:17 +00:00
|
|
|
queue_->AddConstraint(c);
|
2011-07-15 18:51:39 +00:00
|
|
|
} else if (state_ == IN_ROOT_NODE) {
|
|
|
|
|
DCHECK_GE(constraint_index_, 0);
|
|
|
|
|
DCHECK_LE(constraint_index_, constraints_list_.size());
|
|
|
|
|
const int constraint_parent =
|
2013-10-10 15:23:20 +00:00
|
|
|
constraint_index_ == constraints_list_.size()
|
|
|
|
|
? additional_constraints_parent_list_[additional_constraint_index_]
|
|
|
|
|
: constraint_index_;
|
2011-07-15 18:51:39 +00:00
|
|
|
additional_constraints_list_.push_back(c);
|
|
|
|
|
additional_constraints_parent_list_.push_back(constraint_parent);
|
2010-09-15 12:42:33 +00:00
|
|
|
} else {
|
2016-02-03 15:15:58 +01:00
|
|
|
if (parameters_.print_added_constraints()) {
|
2010-09-15 12:42:33 +00:00
|
|
|
LOG(INFO) << c->DebugString();
|
|
|
|
|
}
|
|
|
|
|
constraints_list_.push_back(c);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-10-29 14:25:39 +01:00
|
|
|
void Solver::AddCastConstraint(CastConstraint* const constraint,
|
|
|
|
|
IntVar* const target_var, IntExpr* const expr) {
|
2013-10-10 15:23:20 +00:00
|
|
|
if (constraint != nullptr) {
|
2011-11-07 15:31:18 +00:00
|
|
|
if (state_ != IN_SEARCH) {
|
|
|
|
|
cast_constraints_.insert(constraint);
|
|
|
|
|
cast_information_[target_var] =
|
|
|
|
|
Solver::IntegerCastInfo(target_var, expr, constraint);
|
|
|
|
|
}
|
|
|
|
|
AddConstraint(constraint);
|
2011-08-11 05:15:18 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-10-29 14:25:39 +01:00
|
|
|
void Solver::Accept(ModelVisitor* const visitor) const {
|
2011-07-11 20:13:14 +00:00
|
|
|
visitor->BeginVisitModel(name_);
|
2016-07-28 10:15:46 -07:00
|
|
|
ForAll(constraints_list_, &Constraint::Accept, visitor);
|
2011-07-11 20:13:14 +00:00
|
|
|
visitor->EndVisitModel(name_);
|
|
|
|
|
}
|
|
|
|
|
|
2010-09-15 12:42:33 +00:00
|
|
|
void Solver::ProcessConstraints() {
|
2011-07-15 18:51:39 +00:00
|
|
|
// Both constraints_list_ and additional_constraints_list_ are used in
|
|
|
|
|
// a FIFO way.
|
2016-02-03 15:15:58 +01:00
|
|
|
if (parameters_.print_model()) {
|
2020-10-29 14:25:39 +01:00
|
|
|
ModelVisitor* const visitor = MakePrintModelVisitor();
|
2011-07-11 20:13:14 +00:00
|
|
|
Accept(visitor);
|
|
|
|
|
}
|
2016-02-03 15:15:58 +01:00
|
|
|
if (parameters_.print_model_stats()) {
|
2020-10-29 14:25:39 +01:00
|
|
|
ModelVisitor* const visitor = MakeStatisticsModelVisitor();
|
2011-07-13 19:51:33 +00:00
|
|
|
Accept(visitor);
|
|
|
|
|
}
|
2011-09-05 13:45:29 +00:00
|
|
|
|
2016-02-03 15:15:58 +01:00
|
|
|
if (parameters_.disable_solve()) {
|
2011-09-05 13:45:29 +00:00
|
|
|
LOG(INFO) << "Forcing early failure";
|
|
|
|
|
Fail();
|
|
|
|
|
}
|
2011-07-11 20:13:14 +00:00
|
|
|
|
2011-07-15 18:51:39 +00:00
|
|
|
// Clear state before processing constraints.
|
|
|
|
|
const int constraints_size = constraints_list_.size();
|
|
|
|
|
additional_constraints_list_.clear();
|
|
|
|
|
additional_constraints_parent_list_.clear();
|
|
|
|
|
|
2013-10-10 15:23:20 +00:00
|
|
|
for (constraint_index_ = 0; constraint_index_ < constraints_size;
|
2011-07-15 18:51:39 +00:00
|
|
|
++constraint_index_) {
|
2020-10-29 14:25:39 +01:00
|
|
|
Constraint* const constraint = constraints_list_[constraint_index_];
|
2011-11-14 20:55:35 +00:00
|
|
|
propagation_monitor_->BeginConstraintInitialPropagation(constraint);
|
2011-07-15 18:51:39 +00:00
|
|
|
constraint->PostAndPropagate();
|
2011-11-14 20:55:35 +00:00
|
|
|
propagation_monitor_->EndConstraintInitialPropagation(constraint);
|
2011-07-15 18:51:39 +00:00
|
|
|
}
|
|
|
|
|
CHECK_EQ(constraints_list_.size(), constraints_size);
|
|
|
|
|
|
|
|
|
|
// Process nested constraints added during the previous step.
|
|
|
|
|
for (int additional_constraint_index_ = 0;
|
|
|
|
|
additional_constraint_index_ < additional_constraints_list_.size();
|
|
|
|
|
++additional_constraint_index_) {
|
2020-10-29 14:25:39 +01:00
|
|
|
Constraint* const nested =
|
2011-07-15 18:51:39 +00:00
|
|
|
additional_constraints_list_[additional_constraint_index_];
|
2011-09-14 08:15:08 +00:00
|
|
|
const int parent_index =
|
|
|
|
|
additional_constraints_parent_list_[additional_constraint_index_];
|
2020-10-29 14:25:39 +01:00
|
|
|
Constraint* const parent = constraints_list_[parent_index];
|
2011-11-14 20:55:35 +00:00
|
|
|
propagation_monitor_->BeginNestedConstraintInitialPropagation(parent,
|
|
|
|
|
nested);
|
2011-09-17 13:34:27 +00:00
|
|
|
nested->PostAndPropagate();
|
2011-11-14 20:55:35 +00:00
|
|
|
propagation_monitor_->EndNestedConstraintInitialPropagation(parent, nested);
|
2010-09-15 12:42:33 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool Solver::CurrentlyInSolve() const {
|
2011-12-15 11:50:32 +00:00
|
|
|
DCHECK_GT(SolveDepth(), 0);
|
2013-10-10 15:23:20 +00:00
|
|
|
DCHECK(searches_.back() != nullptr);
|
2010-09-15 12:42:33 +00:00
|
|
|
return searches_.back()->created_by_solve();
|
|
|
|
|
}
|
|
|
|
|
|
2020-10-29 14:25:39 +01:00
|
|
|
bool Solver::Solve(DecisionBuilder* const db, SearchMonitor* const m1) {
|
2023-12-01 10:32:14 +01:00
|
|
|
return Solve(db, std::vector<SearchMonitor*>{m1});
|
2010-09-15 12:42:33 +00:00
|
|
|
}
|
|
|
|
|
|
2023-12-01 10:32:14 +01:00
|
|
|
bool Solver::Solve(DecisionBuilder* const db) { return Solve(db, {}); }
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2020-10-29 14:25:39 +01:00
|
|
|
bool Solver::Solve(DecisionBuilder* const db, SearchMonitor* const m1,
|
|
|
|
|
SearchMonitor* const m2) {
|
2023-12-01 10:32:14 +01:00
|
|
|
return Solve(db, {m1, m2});
|
2010-09-15 12:42:33 +00:00
|
|
|
}
|
|
|
|
|
|
2020-10-29 14:25:39 +01:00
|
|
|
bool Solver::Solve(DecisionBuilder* const db, SearchMonitor* const m1,
|
|
|
|
|
SearchMonitor* const m2, SearchMonitor* const m3) {
|
2023-12-01 10:32:14 +01:00
|
|
|
return Solve(db, {m1, m2, m3});
|
2010-09-15 12:42:33 +00:00
|
|
|
}
|
|
|
|
|
|
2020-10-29 14:25:39 +01:00
|
|
|
bool Solver::Solve(DecisionBuilder* const db, SearchMonitor* const m1,
|
|
|
|
|
SearchMonitor* const m2, SearchMonitor* const m3,
|
|
|
|
|
SearchMonitor* const m4) {
|
2023-12-01 10:32:14 +01:00
|
|
|
return Solve(db, {m1, m2, m3, m4});
|
2010-09-15 12:42:33 +00:00
|
|
|
}
|
|
|
|
|
|
2020-10-29 14:25:39 +01:00
|
|
|
bool Solver::Solve(DecisionBuilder* const db,
|
|
|
|
|
const std::vector<SearchMonitor*>& monitors) {
|
2012-05-30 09:18:17 +00:00
|
|
|
NewSearch(db, monitors);
|
2020-10-22 23:36:58 +02:00
|
|
|
searches_.back()->set_created_by_solve(true); // Overwrites default.
|
2010-10-06 16:04:31 +00:00
|
|
|
NextSolution();
|
2011-03-03 21:38:41 +00:00
|
|
|
const bool solution_found = searches_.back()->solution_counter() > 0;
|
2010-09-15 12:42:33 +00:00
|
|
|
EndSearch();
|
2011-03-03 21:38:41 +00:00
|
|
|
return solution_found;
|
2010-09-15 12:42:33 +00:00
|
|
|
}
|
|
|
|
|
|
2020-10-29 14:25:39 +01:00
|
|
|
void Solver::NewSearch(DecisionBuilder* const db, SearchMonitor* const m1) {
|
2023-12-01 10:32:14 +01:00
|
|
|
return NewSearch(db, std::vector<SearchMonitor*>{m1});
|
2010-09-15 12:42:33 +00:00
|
|
|
}
|
|
|
|
|
|
2023-12-01 10:32:14 +01:00
|
|
|
void Solver::NewSearch(DecisionBuilder* const db) { return NewSearch(db, {}); }
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2020-10-29 14:25:39 +01:00
|
|
|
void Solver::NewSearch(DecisionBuilder* const db, SearchMonitor* const m1,
|
|
|
|
|
SearchMonitor* const m2) {
|
2023-12-01 10:32:14 +01:00
|
|
|
return NewSearch(db, {m1, m2});
|
2010-09-15 12:42:33 +00:00
|
|
|
}
|
|
|
|
|
|
2020-10-29 14:25:39 +01:00
|
|
|
void Solver::NewSearch(DecisionBuilder* const db, SearchMonitor* const m1,
|
|
|
|
|
SearchMonitor* const m2, SearchMonitor* const m3) {
|
2023-12-01 10:32:14 +01:00
|
|
|
return NewSearch(db, {m1, m2, m3});
|
2010-09-15 12:42:33 +00:00
|
|
|
}
|
|
|
|
|
|
2020-10-29 14:25:39 +01:00
|
|
|
void Solver::NewSearch(DecisionBuilder* const db, SearchMonitor* const m1,
|
|
|
|
|
SearchMonitor* const m2, SearchMonitor* const m3,
|
|
|
|
|
SearchMonitor* const m4) {
|
2023-12-01 10:32:14 +01:00
|
|
|
return NewSearch(db, {m1, m2, m3, m4});
|
2010-09-15 12:42:33 +00:00
|
|
|
}
|
|
|
|
|
|
2023-05-31 14:27:08 +02:00
|
|
|
extern PropagationMonitor* BuildPrintTrace(Solver* s);
|
2011-11-16 17:32:24 +00:00
|
|
|
|
2010-09-15 12:42:33 +00:00
|
|
|
// Opens a new top level search.
|
2020-10-29 14:25:39 +01:00
|
|
|
void Solver::NewSearch(DecisionBuilder* const db,
|
|
|
|
|
const std::vector<SearchMonitor*>& monitors) {
|
2010-09-15 12:42:33 +00:00
|
|
|
// TODO(user) : reset statistics
|
|
|
|
|
|
2013-10-10 15:23:20 +00:00
|
|
|
CHECK(db != nullptr);
|
2012-05-17 15:43:34 +00:00
|
|
|
const bool nested = state_ == IN_SEARCH;
|
2010-10-11 17:39:39 +00:00
|
|
|
|
2012-05-17 15:43:34 +00:00
|
|
|
if (state_ == IN_ROOT_NODE) {
|
|
|
|
|
LOG(FATAL) << "Cannot start new searches here.";
|
2010-09-15 12:42:33 +00:00
|
|
|
}
|
2012-05-17 15:43:34 +00:00
|
|
|
|
2020-10-29 14:25:39 +01:00
|
|
|
Search* const search = nested ? new Search(this) : searches_.back();
|
2020-10-22 23:36:58 +02:00
|
|
|
search->set_created_by_solve(false); // default behavior.
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2012-05-17 15:43:34 +00:00
|
|
|
// ----- jumps to correct state -----
|
|
|
|
|
|
|
|
|
|
if (nested) {
|
2012-06-13 16:14:46 +00:00
|
|
|
// Nested searches are created on demand, and deleted afterwards.
|
2012-05-17 15:43:34 +00:00
|
|
|
DCHECK_GE(searches_.size(), 2);
|
|
|
|
|
searches_.push_back(search);
|
|
|
|
|
} else {
|
2012-06-13 16:14:46 +00:00
|
|
|
// Top level search is persistent.
|
|
|
|
|
// TODO(user): delete top level search after EndSearch().
|
2012-05-17 15:43:34 +00:00
|
|
|
DCHECK_EQ(2, searches_.size());
|
2012-06-13 16:14:46 +00:00
|
|
|
// TODO(user): Check if these two lines are still necessary.
|
2012-05-17 15:43:34 +00:00
|
|
|
BacktrackToSentinel(INITIAL_SEARCH_SENTINEL);
|
|
|
|
|
state_ = OUTSIDE_SEARCH;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ----- manages all monitors -----
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2016-07-28 10:15:46 -07:00
|
|
|
// Always install the main propagation and local search monitors.
|
2011-11-16 17:32:24 +00:00
|
|
|
propagation_monitor_->Install();
|
2013-10-10 15:23:20 +00:00
|
|
|
if (demon_profiler_ != nullptr) {
|
2011-11-21 02:52:58 +00:00
|
|
|
InstallDemonProfiler(demon_profiler_);
|
2011-11-16 17:32:24 +00:00
|
|
|
}
|
2016-07-28 10:15:46 -07:00
|
|
|
local_search_monitor_->Install();
|
|
|
|
|
if (local_search_profiler_ != nullptr) {
|
|
|
|
|
InstallLocalSearchProfiler(local_search_profiler_);
|
|
|
|
|
}
|
2011-11-16 17:32:24 +00:00
|
|
|
|
2010-09-15 12:42:33 +00:00
|
|
|
// Push monitors and enter search.
|
2020-10-29 14:25:39 +01:00
|
|
|
for (SearchMonitor* const monitor : monitors) {
|
2016-07-28 10:15:46 -07:00
|
|
|
if (monitor != nullptr) {
|
|
|
|
|
monitor->Install();
|
2011-11-16 17:32:24 +00:00
|
|
|
}
|
2010-09-15 12:42:33 +00:00
|
|
|
}
|
2020-10-29 14:25:39 +01:00
|
|
|
std::vector<SearchMonitor*> extras;
|
2011-06-29 09:46:25 +00:00
|
|
|
db->AppendMonitors(this, &extras);
|
2020-10-29 14:25:39 +01:00
|
|
|
for (SearchMonitor* const monitor : extras) {
|
2013-10-10 15:23:20 +00:00
|
|
|
if (monitor != nullptr) {
|
2011-11-16 17:32:24 +00:00
|
|
|
monitor->Install();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// Install the print trace if needed.
|
|
|
|
|
// The print_trace needs to be last to detect propagation from the objective.
|
2012-06-13 16:14:46 +00:00
|
|
|
if (nested) {
|
2020-10-22 23:36:58 +02:00
|
|
|
if (print_trace_ != nullptr) { // Was installed at the top level?
|
|
|
|
|
print_trace_->Install(); // Propagates to nested search.
|
2012-05-17 15:43:34 +00:00
|
|
|
}
|
2020-10-22 23:36:58 +02:00
|
|
|
} else { // Top level search
|
|
|
|
|
print_trace_ = nullptr; // Clears it first.
|
2016-02-03 15:15:58 +01:00
|
|
|
if (parameters_.trace_propagation()) {
|
2012-06-13 16:14:46 +00:00
|
|
|
print_trace_ = BuildPrintTrace(this);
|
|
|
|
|
print_trace_->Install();
|
2016-02-03 15:15:58 +01:00
|
|
|
} else if (parameters_.trace_search()) {
|
2012-06-13 16:14:46 +00:00
|
|
|
// This is useful to trace the exact behavior of the search.
|
|
|
|
|
// The '######## ' prefix is the same as the progagation trace.
|
|
|
|
|
// Search trace is subsumed by propagation trace, thus only one
|
|
|
|
|
// is necessary.
|
2020-10-29 14:25:39 +01:00
|
|
|
SearchMonitor* const trace = MakeSearchTrace("######## ");
|
2012-01-17 15:06:01 +00:00
|
|
|
trace->Install();
|
|
|
|
|
}
|
2011-06-27 13:45:01 +00:00
|
|
|
}
|
2011-11-16 17:32:24 +00:00
|
|
|
|
2012-05-17 15:43:34 +00:00
|
|
|
// ----- enters search -----
|
|
|
|
|
|
2010-09-15 12:42:33 +00:00
|
|
|
search->EnterSearch();
|
|
|
|
|
|
|
|
|
|
// Push sentinel and set decision builder.
|
|
|
|
|
PushSentinel(INITIAL_SEARCH_SENTINEL);
|
|
|
|
|
search->set_decision_builder(db);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Backtrack to the last open right branch in the search tree.
|
|
|
|
|
// It returns true in case the search tree has been completely explored.
|
2020-10-29 14:25:39 +01:00
|
|
|
bool Solver::BacktrackOneLevel(Decision** const fail_decision) {
|
2010-09-15 12:42:33 +00:00
|
|
|
bool no_more_solutions = false;
|
|
|
|
|
bool end_loop = false;
|
|
|
|
|
while (!end_loop) {
|
|
|
|
|
StateInfo info;
|
2011-11-07 15:31:18 +00:00
|
|
|
Solver::MarkerType t = PopState(&info);
|
2010-09-15 12:42:33 +00:00
|
|
|
switch (t) {
|
2020-10-22 23:36:58 +02:00
|
|
|
case SENTINEL:
|
|
|
|
|
CHECK_EQ(info.ptr_info, this) << "Wrong sentinel found";
|
|
|
|
|
CHECK((info.int_info == ROOT_NODE_SENTINEL && SolveDepth() == 1) ||
|
|
|
|
|
(info.int_info == INITIAL_SEARCH_SENTINEL && SolveDepth() > 1));
|
|
|
|
|
searches_.back()->sentinel_pushed_--;
|
|
|
|
|
no_more_solutions = true;
|
2010-09-15 12:42:33 +00:00
|
|
|
end_loop = true;
|
2020-10-22 23:36:58 +02:00
|
|
|
break;
|
|
|
|
|
case SIMPLE_MARKER:
|
|
|
|
|
LOG(ERROR) << "Simple markers should not be encountered during search";
|
|
|
|
|
break;
|
|
|
|
|
case CHOICE_POINT:
|
|
|
|
|
if (info.int_info == 0) { // was left branch
|
2020-10-29 14:25:39 +01:00
|
|
|
(*fail_decision) = reinterpret_cast<Decision*>(info.ptr_info);
|
2020-10-22 23:36:58 +02:00
|
|
|
end_loop = true;
|
|
|
|
|
searches_.back()->set_search_depth(info.depth);
|
|
|
|
|
searches_.back()->set_search_left_depth(info.left_depth);
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case REVERSIBLE_ACTION: {
|
|
|
|
|
if (info.reversible_action != nullptr) {
|
|
|
|
|
info.reversible_action(this);
|
|
|
|
|
}
|
|
|
|
|
break;
|
2020-10-21 00:21:54 +02:00
|
|
|
}
|
2010-09-15 12:42:33 +00:00
|
|
|
}
|
|
|
|
|
}
|
2020-10-29 14:25:39 +01:00
|
|
|
Search* const search = searches_.back();
|
2010-09-15 12:42:33 +00:00
|
|
|
search->EndFail();
|
|
|
|
|
fail_stamp_++;
|
|
|
|
|
if (no_more_solutions) {
|
|
|
|
|
search->NoMoreSolutions();
|
|
|
|
|
}
|
|
|
|
|
return no_more_solutions;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Solver::PushSentinel(int magic_code) {
|
|
|
|
|
StateInfo info(this, magic_code);
|
|
|
|
|
PushState(SENTINEL, info);
|
|
|
|
|
// We do not count the sentinel pushed in the ctor.
|
|
|
|
|
if (magic_code != SOLVER_CTOR_SENTINEL) {
|
|
|
|
|
searches_.back()->sentinel_pushed_++;
|
|
|
|
|
}
|
|
|
|
|
const int pushed = searches_.back()->sentinel_pushed_;
|
|
|
|
|
DCHECK((magic_code == SOLVER_CTOR_SENTINEL) ||
|
|
|
|
|
(magic_code == INITIAL_SEARCH_SENTINEL && pushed == 1) ||
|
|
|
|
|
(magic_code == ROOT_NODE_SENTINEL && pushed == 2));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Solver::RestartSearch() {
|
2020-10-29 14:25:39 +01:00
|
|
|
Search* const search = searches_.back();
|
2010-09-15 12:42:33 +00:00
|
|
|
CHECK_NE(0, search->sentinel_pushed_);
|
2020-10-22 23:36:58 +02:00
|
|
|
if (SolveDepth() == 1) { // top level.
|
2010-09-15 12:42:33 +00:00
|
|
|
if (search->sentinel_pushed_ > 1) {
|
|
|
|
|
BacktrackToSentinel(ROOT_NODE_SENTINEL);
|
|
|
|
|
}
|
|
|
|
|
CHECK_EQ(1, search->sentinel_pushed_);
|
|
|
|
|
PushSentinel(ROOT_NODE_SENTINEL);
|
|
|
|
|
state_ = IN_SEARCH;
|
|
|
|
|
} else {
|
|
|
|
|
CHECK_EQ(IN_SEARCH, state_);
|
|
|
|
|
if (search->sentinel_pushed_ > 0) {
|
|
|
|
|
BacktrackToSentinel(INITIAL_SEARCH_SENTINEL);
|
|
|
|
|
}
|
|
|
|
|
CHECK_EQ(0, search->sentinel_pushed_);
|
|
|
|
|
PushSentinel(INITIAL_SEARCH_SENTINEL);
|
|
|
|
|
}
|
2011-01-06 17:40:30 +00:00
|
|
|
|
2010-09-15 12:42:33 +00:00
|
|
|
search->RestartSearch();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Backtrack to the initial search sentinel.
|
|
|
|
|
// Does not change the state, this should be done by the caller.
|
|
|
|
|
void Solver::BacktrackToSentinel(int magic_code) {
|
2020-10-29 14:25:39 +01:00
|
|
|
Search* const search = searches_.back();
|
2010-09-15 12:42:33 +00:00
|
|
|
bool end_loop = search->sentinel_pushed_ == 0;
|
|
|
|
|
while (!end_loop) {
|
|
|
|
|
StateInfo info;
|
2011-11-07 15:31:18 +00:00
|
|
|
Solver::MarkerType t = PopState(&info);
|
2010-09-15 12:42:33 +00:00
|
|
|
switch (t) {
|
2020-10-22 23:36:58 +02:00
|
|
|
case SENTINEL: {
|
|
|
|
|
CHECK_EQ(info.ptr_info, this) << "Wrong sentinel found";
|
|
|
|
|
CHECK_GE(--search->sentinel_pushed_, 0);
|
|
|
|
|
search->set_search_depth(0);
|
|
|
|
|
search->set_search_left_depth(0);
|
|
|
|
|
|
|
|
|
|
if (info.int_info == magic_code) {
|
|
|
|
|
end_loop = true;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case SIMPLE_MARKER:
|
|
|
|
|
break;
|
|
|
|
|
case CHOICE_POINT:
|
|
|
|
|
break;
|
|
|
|
|
case REVERSIBLE_ACTION: {
|
|
|
|
|
info.reversible_action(this);
|
|
|
|
|
break;
|
2010-09-15 12:42:33 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
fail_stamp_++;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Closes the current search without backtrack.
|
|
|
|
|
void Solver::JumpToSentinelWhenNested() {
|
2011-12-15 11:50:32 +00:00
|
|
|
CHECK_GT(SolveDepth(), 1) << "calling JumpToSentinel from top level";
|
2020-10-29 14:25:39 +01:00
|
|
|
Search* c = searches_.back();
|
|
|
|
|
Search* p = ParentSearch();
|
2010-09-15 12:42:33 +00:00
|
|
|
bool found = false;
|
|
|
|
|
while (!c->marker_stack_.empty()) {
|
2020-10-29 14:25:39 +01:00
|
|
|
StateMarker* const m = c->marker_stack_.back();
|
2010-09-15 12:42:33 +00:00
|
|
|
if (m->type_ == REVERSIBLE_ACTION) {
|
|
|
|
|
p->marker_stack_.push_back(m);
|
|
|
|
|
} else {
|
|
|
|
|
if (m->type_ == SENTINEL) {
|
|
|
|
|
CHECK_EQ(c->marker_stack_.size(), 1) << "Sentinel found too early";
|
|
|
|
|
found = true;
|
|
|
|
|
}
|
|
|
|
|
delete m;
|
|
|
|
|
}
|
|
|
|
|
c->marker_stack_.pop_back();
|
|
|
|
|
}
|
|
|
|
|
c->set_search_depth(0);
|
|
|
|
|
c->set_search_left_depth(0);
|
|
|
|
|
CHECK_EQ(found, true) << "Sentinel not found";
|
|
|
|
|
}
|
|
|
|
|
|
2011-08-11 07:26:19 +00:00
|
|
|
namespace {
|
2010-09-15 12:42:33 +00:00
|
|
|
class ReverseDecision : public Decision {
|
2020-10-22 23:36:58 +02:00
|
|
|
public:
|
2020-10-29 14:25:39 +01:00
|
|
|
explicit ReverseDecision(Decision* const d) : decision_(d) {
|
2013-10-10 15:23:20 +00:00
|
|
|
CHECK(d != nullptr);
|
2010-09-15 12:42:33 +00:00
|
|
|
}
|
2015-04-16 15:49:51 +02:00
|
|
|
~ReverseDecision() override {}
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2020-10-29 14:25:39 +01:00
|
|
|
void Apply(Solver* const s) override { decision_->Refute(s); }
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2020-10-29 14:25:39 +01:00
|
|
|
void Refute(Solver* const s) override { decision_->Apply(s); }
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2020-10-29 14:25:39 +01:00
|
|
|
void Accept(DecisionVisitor* const visitor) const override {
|
2010-09-15 12:42:33 +00:00
|
|
|
decision_->Accept(visitor);
|
|
|
|
|
}
|
|
|
|
|
|
2015-04-16 15:49:51 +02:00
|
|
|
std::string DebugString() const override {
|
2013-12-16 10:24:42 +00:00
|
|
|
std::string str = "Reverse(";
|
2010-09-15 12:42:33 +00:00
|
|
|
str += decision_->DebugString();
|
|
|
|
|
str += ")";
|
|
|
|
|
return str;
|
|
|
|
|
}
|
2011-06-28 09:27:03 +00:00
|
|
|
|
2020-10-22 23:36:58 +02:00
|
|
|
private:
|
2020-10-29 14:25:39 +01:00
|
|
|
Decision* const decision_;
|
2010-09-15 12:42:33 +00:00
|
|
|
};
|
2020-10-22 23:36:58 +02:00
|
|
|
} // namespace
|
2010-09-15 12:42:33 +00:00
|
|
|
|
|
|
|
|
// Search for the next solution in the search tree.
|
|
|
|
|
bool Solver::NextSolution() {
|
2020-10-29 14:25:39 +01:00
|
|
|
Search* const search = searches_.back();
|
|
|
|
|
Decision* fd = nullptr;
|
2012-02-14 14:16:12 +00:00
|
|
|
const int solve_depth = SolveDepth();
|
|
|
|
|
const bool top_level = solve_depth <= 1;
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2012-02-14 14:16:12 +00:00
|
|
|
if (solve_depth == 0 && !search->decision_builder()) {
|
2010-10-09 11:18:45 +00:00
|
|
|
LOG(WARNING) << "NextSolution() called without a NewSearch before";
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2020-10-22 23:36:58 +02:00
|
|
|
if (top_level) { // Manage top level state.
|
2010-09-15 12:42:33 +00:00
|
|
|
switch (state_) {
|
2020-10-22 23:36:58 +02:00
|
|
|
case PROBLEM_INFEASIBLE:
|
2010-09-15 12:42:33 +00:00
|
|
|
return false;
|
2020-10-22 23:36:58 +02:00
|
|
|
case NO_MORE_SOLUTIONS:
|
|
|
|
|
return false;
|
|
|
|
|
case AT_SOLUTION: {
|
|
|
|
|
if (BacktrackOneLevel(&fd)) { // No more solutions.
|
|
|
|
|
state_ = NO_MORE_SOLUTIONS;
|
|
|
|
|
return false;
|
|
|
|
|
}
|
2010-09-15 12:42:33 +00:00
|
|
|
state_ = IN_SEARCH;
|
2020-10-22 23:36:58 +02:00
|
|
|
break;
|
2010-09-15 12:42:33 +00:00
|
|
|
}
|
2020-10-22 23:36:58 +02:00
|
|
|
case OUTSIDE_SEARCH: {
|
|
|
|
|
state_ = IN_ROOT_NODE;
|
|
|
|
|
search->BeginInitialPropagation();
|
|
|
|
|
CP_TRY(search) {
|
|
|
|
|
ProcessConstraints();
|
|
|
|
|
search->EndInitialPropagation();
|
|
|
|
|
PushSentinel(ROOT_NODE_SENTINEL);
|
|
|
|
|
state_ = IN_SEARCH;
|
|
|
|
|
search->ClearBuffer();
|
|
|
|
|
}
|
|
|
|
|
CP_ON_FAIL {
|
|
|
|
|
queue_->AfterFailure();
|
|
|
|
|
BacktrackToSentinel(INITIAL_SEARCH_SENTINEL);
|
|
|
|
|
state_ = PROBLEM_INFEASIBLE;
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
break;
|
2010-09-15 12:42:33 +00:00
|
|
|
}
|
2020-10-22 23:36:58 +02:00
|
|
|
case IN_SEARCH: // Usually after a RestartSearch
|
|
|
|
|
break;
|
|
|
|
|
case IN_ROOT_NODE:
|
|
|
|
|
LOG(FATAL) << "Should not happen";
|
|
|
|
|
break;
|
2010-09-15 12:42:33 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
volatile bool finish = false;
|
|
|
|
|
volatile bool result = false;
|
2020-10-29 14:25:39 +01:00
|
|
|
DecisionBuilder* const db = search->decision_builder();
|
2010-09-15 12:42:33 +00:00
|
|
|
|
|
|
|
|
while (!finish) {
|
|
|
|
|
CP_TRY(search) {
|
2013-10-10 15:23:20 +00:00
|
|
|
if (fd != nullptr) {
|
|
|
|
|
StateInfo i1(fd, 1, search->search_depth(),
|
2020-10-22 23:36:58 +02:00
|
|
|
search->left_search_depth()); // 1 for right branch
|
2010-09-15 12:42:33 +00:00
|
|
|
PushState(CHOICE_POINT, i1);
|
|
|
|
|
search->RefuteDecision(fd);
|
|
|
|
|
branches_++;
|
|
|
|
|
fd->Refute(this);
|
2016-06-02 13:19:10 +02:00
|
|
|
// Check the fail state that could have been set in the python/java/C#
|
|
|
|
|
// layer.
|
2015-12-07 13:27:18 +01:00
|
|
|
CheckFail();
|
2011-03-31 12:28:12 +00:00
|
|
|
search->AfterDecision(fd, false);
|
2010-09-15 12:42:33 +00:00
|
|
|
search->RightMove();
|
2013-10-10 15:23:20 +00:00
|
|
|
fd = nullptr;
|
2010-09-15 12:42:33 +00:00
|
|
|
}
|
2020-10-29 14:25:39 +01:00
|
|
|
Decision* d = nullptr;
|
2010-09-15 12:42:33 +00:00
|
|
|
for (;;) {
|
|
|
|
|
search->BeginNextDecision(db);
|
|
|
|
|
d = db->Next(this);
|
|
|
|
|
search->EndNextDecision(db, d);
|
2013-12-10 16:02:46 +00:00
|
|
|
if (d == fail_decision_.get()) {
|
2020-10-22 23:36:58 +02:00
|
|
|
Fail(); // fail now instead of after 2 branches.
|
2010-09-15 12:42:33 +00:00
|
|
|
}
|
2013-10-10 15:23:20 +00:00
|
|
|
if (d != nullptr) {
|
2010-09-15 12:42:33 +00:00
|
|
|
DecisionModification modification = search->ModifyDecision();
|
|
|
|
|
switch (modification) {
|
2020-10-22 23:36:58 +02:00
|
|
|
case SWITCH_BRANCHES: {
|
|
|
|
|
d = RevAlloc(new ReverseDecision(d));
|
|
|
|
|
// We reverse the decision and fall through the normal code.
|
|
|
|
|
ABSL_FALLTHROUGH_INTENDED;
|
|
|
|
|
}
|
|
|
|
|
case NO_CHANGE: {
|
|
|
|
|
decisions_++;
|
|
|
|
|
StateInfo i2(d, 0, search->search_depth(),
|
|
|
|
|
search->left_search_depth()); // 0 for left branch
|
|
|
|
|
PushState(CHOICE_POINT, i2);
|
|
|
|
|
search->ApplyDecision(d);
|
|
|
|
|
branches_++;
|
|
|
|
|
d->Apply(this);
|
|
|
|
|
CheckFail();
|
|
|
|
|
search->AfterDecision(d, true);
|
|
|
|
|
search->LeftMove();
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case KEEP_LEFT: {
|
|
|
|
|
search->ApplyDecision(d);
|
|
|
|
|
d->Apply(this);
|
|
|
|
|
CheckFail();
|
|
|
|
|
search->AfterDecision(d, true);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case KEEP_RIGHT: {
|
|
|
|
|
search->RefuteDecision(d);
|
|
|
|
|
d->Refute(this);
|
|
|
|
|
CheckFail();
|
|
|
|
|
search->AfterDecision(d, false);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case KILL_BOTH: {
|
|
|
|
|
Fail();
|
|
|
|
|
}
|
2010-09-15 12:42:33 +00:00
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
2010-10-06 16:04:31 +00:00
|
|
|
if (search->AcceptSolution()) {
|
2011-03-03 21:38:41 +00:00
|
|
|
search->IncrementSolutionCounter();
|
2010-10-06 16:04:31 +00:00
|
|
|
if (!search->AtSolution() || !CurrentlyInSolve()) {
|
|
|
|
|
result = true;
|
|
|
|
|
finish = true;
|
|
|
|
|
} else {
|
|
|
|
|
Fail();
|
|
|
|
|
}
|
|
|
|
|
} else {
|
2010-09-15 12:42:33 +00:00
|
|
|
Fail();
|
|
|
|
|
}
|
2013-10-10 15:23:20 +00:00
|
|
|
}
|
|
|
|
|
CP_ON_FAIL {
|
2010-12-06 16:29:32 +00:00
|
|
|
queue_->AfterFailure();
|
2010-09-15 12:42:33 +00:00
|
|
|
if (search->should_finish()) {
|
2013-10-10 15:23:20 +00:00
|
|
|
fd = nullptr;
|
|
|
|
|
BacktrackToSentinel(top_level ? ROOT_NODE_SENTINEL
|
|
|
|
|
: INITIAL_SEARCH_SENTINEL);
|
2010-09-15 12:42:33 +00:00
|
|
|
result = false;
|
|
|
|
|
finish = true;
|
|
|
|
|
search->set_should_finish(false);
|
|
|
|
|
search->set_should_restart(false);
|
|
|
|
|
// We do not need to push back the sentinel as we are exiting anyway.
|
|
|
|
|
} else if (search->should_restart()) {
|
2013-10-10 15:23:20 +00:00
|
|
|
fd = nullptr;
|
|
|
|
|
BacktrackToSentinel(top_level ? ROOT_NODE_SENTINEL
|
|
|
|
|
: INITIAL_SEARCH_SENTINEL);
|
2010-09-15 12:42:33 +00:00
|
|
|
search->set_should_finish(false);
|
|
|
|
|
search->set_should_restart(false);
|
|
|
|
|
PushSentinel(top_level ? ROOT_NODE_SENTINEL : INITIAL_SEARCH_SENTINEL);
|
|
|
|
|
search->RestartSearch();
|
|
|
|
|
} else {
|
2020-10-22 23:36:58 +02:00
|
|
|
if (BacktrackOneLevel(&fd)) { // no more solutions.
|
2010-09-15 12:42:33 +00:00
|
|
|
result = false;
|
|
|
|
|
finish = true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (result) {
|
|
|
|
|
search->ClearBuffer();
|
|
|
|
|
}
|
2020-10-22 23:36:58 +02:00
|
|
|
if (top_level) { // Manage state after NextSolution().
|
2010-10-06 16:04:31 +00:00
|
|
|
state_ = (result ? AT_SOLUTION : NO_MORE_SOLUTIONS);
|
2010-09-15 12:42:33 +00:00
|
|
|
}
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Solver::EndSearch() {
|
2020-10-29 14:25:39 +01:00
|
|
|
Search* const search = searches_.back();
|
2012-06-13 16:14:46 +00:00
|
|
|
if (search->backtrack_at_the_end_of_the_search()) {
|
2012-05-17 15:43:34 +00:00
|
|
|
BacktrackToSentinel(INITIAL_SEARCH_SENTINEL);
|
|
|
|
|
} else {
|
|
|
|
|
CHECK_GT(searches_.size(), 2);
|
|
|
|
|
if (search->sentinel_pushed_ > 0) {
|
|
|
|
|
JumpToSentinelWhenNested();
|
|
|
|
|
}
|
|
|
|
|
}
|
2010-09-15 12:42:33 +00:00
|
|
|
search->ExitSearch();
|
|
|
|
|
search->Clear();
|
2020-10-22 23:36:58 +02:00
|
|
|
if (2 == searches_.size()) { // Ending top level search.
|
2020-11-01 11:47:28 +01:00
|
|
|
// Restores the state.
|
2012-05-17 15:43:34 +00:00
|
|
|
state_ = OUTSIDE_SEARCH;
|
2012-06-13 16:14:46 +00:00
|
|
|
// Checks if we want to export the profile info.
|
2016-02-03 15:15:58 +01:00
|
|
|
if (!parameters_.profile_file().empty()) {
|
2020-10-29 14:25:39 +01:00
|
|
|
const std::string& file_name = parameters_.profile_file();
|
2016-02-03 15:15:58 +01:00
|
|
|
LOG(INFO) << "Exporting profile to " << file_name;
|
|
|
|
|
ExportProfilingOverview(file_name);
|
2012-05-17 15:43:34 +00:00
|
|
|
}
|
2016-07-28 10:15:46 -07:00
|
|
|
if (parameters_.print_local_search_profile()) {
|
2022-12-07 17:37:45 +01:00
|
|
|
const std::string profile = LocalSearchProfile();
|
|
|
|
|
if (!profile.empty()) LOG(INFO) << profile;
|
2016-07-28 10:15:46 -07:00
|
|
|
}
|
2020-10-22 23:36:58 +02:00
|
|
|
} else { // We clean the nested Search.
|
2012-05-17 15:43:34 +00:00
|
|
|
delete search;
|
|
|
|
|
searches_.pop_back();
|
2011-09-13 08:18:38 +00:00
|
|
|
}
|
2010-09-15 12:42:33 +00:00
|
|
|
}
|
|
|
|
|
|
2020-10-29 14:25:39 +01:00
|
|
|
bool Solver::CheckAssignment(Assignment* const solution) {
|
2010-09-15 12:42:33 +00:00
|
|
|
CHECK(solution);
|
2011-07-15 18:51:39 +00:00
|
|
|
if (state_ == IN_SEARCH || state_ == IN_ROOT_NODE) {
|
2012-05-17 15:43:34 +00:00
|
|
|
LOG(FATAL) << "CheckAssignment is only available at the top level.";
|
2010-09-15 12:42:33 +00:00
|
|
|
}
|
|
|
|
|
// Check state and go to OUTSIDE_SEARCH.
|
2020-10-29 14:25:39 +01:00
|
|
|
Search* const search = searches_.back();
|
2020-10-22 23:36:58 +02:00
|
|
|
search->set_created_by_solve(false); // default behavior.
|
2010-09-15 12:42:33 +00:00
|
|
|
|
|
|
|
|
BacktrackToSentinel(INITIAL_SEARCH_SENTINEL);
|
|
|
|
|
state_ = OUTSIDE_SEARCH;
|
|
|
|
|
|
|
|
|
|
// Push monitors and enter search.
|
|
|
|
|
search->EnterSearch();
|
|
|
|
|
|
|
|
|
|
// Push sentinel and set decision builder.
|
2012-02-14 14:16:12 +00:00
|
|
|
DCHECK_EQ(0, SolveDepth());
|
|
|
|
|
DCHECK_EQ(2, searches_.size());
|
2010-09-15 12:42:33 +00:00
|
|
|
PushSentinel(INITIAL_SEARCH_SENTINEL);
|
|
|
|
|
search->BeginInitialPropagation();
|
|
|
|
|
CP_TRY(search) {
|
2011-07-15 18:51:39 +00:00
|
|
|
state_ = IN_ROOT_NODE;
|
2020-10-29 14:25:39 +01:00
|
|
|
DecisionBuilder* const restore = MakeRestoreAssignment(solution);
|
2010-09-15 12:42:33 +00:00
|
|
|
restore->Next(this);
|
|
|
|
|
ProcessConstraints();
|
|
|
|
|
search->EndInitialPropagation();
|
|
|
|
|
BacktrackToSentinel(INITIAL_SEARCH_SENTINEL);
|
|
|
|
|
search->ClearBuffer();
|
2011-07-15 18:51:39 +00:00
|
|
|
state_ = OUTSIDE_SEARCH;
|
2010-09-15 12:42:33 +00:00
|
|
|
return true;
|
2013-10-10 15:23:20 +00:00
|
|
|
}
|
|
|
|
|
CP_ON_FAIL {
|
|
|
|
|
const int index =
|
|
|
|
|
constraint_index_ < constraints_list_.size()
|
|
|
|
|
? constraint_index_
|
|
|
|
|
: additional_constraints_parent_list_[additional_constraint_index_];
|
2020-10-29 14:25:39 +01:00
|
|
|
Constraint* const ct = constraints_list_[index];
|
2010-09-15 12:42:33 +00:00
|
|
|
if (ct->name().empty()) {
|
2011-01-20 14:16:31 +00:00
|
|
|
LOG(INFO) << "Failing constraint = " << ct->DebugString();
|
2010-09-15 12:42:33 +00:00
|
|
|
} else {
|
2011-01-20 14:16:31 +00:00
|
|
|
LOG(INFO) << "Failing constraint = " << ct->name() << ":"
|
|
|
|
|
<< ct->DebugString();
|
2010-09-15 12:42:33 +00:00
|
|
|
}
|
2010-12-06 16:29:32 +00:00
|
|
|
queue_->AfterFailure();
|
2010-09-15 12:42:33 +00:00
|
|
|
BacktrackToSentinel(INITIAL_SEARCH_SENTINEL);
|
|
|
|
|
state_ = PROBLEM_INFEASIBLE;
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2011-10-11 08:19:59 +00:00
|
|
|
namespace {
|
|
|
|
|
class AddConstraintDecisionBuilder : public DecisionBuilder {
|
2020-10-22 23:36:58 +02:00
|
|
|
public:
|
2020-10-29 14:25:39 +01:00
|
|
|
explicit AddConstraintDecisionBuilder(Constraint* const ct)
|
2011-10-11 08:19:59 +00:00
|
|
|
: constraint_(ct) {
|
2013-10-10 15:23:20 +00:00
|
|
|
CHECK(ct != nullptr);
|
2011-10-11 08:19:59 +00:00
|
|
|
}
|
|
|
|
|
|
2015-04-16 15:49:51 +02:00
|
|
|
~AddConstraintDecisionBuilder() override {}
|
2011-10-11 08:19:59 +00:00
|
|
|
|
2020-10-29 14:25:39 +01:00
|
|
|
Decision* Next(Solver* const solver) override {
|
2011-10-11 08:19:59 +00:00
|
|
|
solver->AddConstraint(constraint_);
|
2013-10-10 15:23:20 +00:00
|
|
|
return nullptr;
|
2011-10-11 08:19:59 +00:00
|
|
|
}
|
|
|
|
|
|
2015-04-16 15:49:51 +02:00
|
|
|
std::string DebugString() const override {
|
2018-10-31 16:18:18 +01:00
|
|
|
return absl::StrFormat("AddConstraintDecisionBuilder(%s)",
|
|
|
|
|
constraint_->DebugString());
|
2011-10-11 08:19:59 +00:00
|
|
|
}
|
2013-10-10 15:23:20 +00:00
|
|
|
|
2020-10-22 23:36:58 +02:00
|
|
|
private:
|
2020-10-29 14:25:39 +01:00
|
|
|
Constraint* const constraint_;
|
2011-10-11 08:19:59 +00:00
|
|
|
};
|
2020-10-22 23:36:58 +02:00
|
|
|
} // namespace
|
2011-10-11 08:19:59 +00:00
|
|
|
|
2020-10-29 14:25:39 +01:00
|
|
|
DecisionBuilder* Solver::MakeConstraintAdder(Constraint* const ct) {
|
2011-10-11 08:19:59 +00:00
|
|
|
return RevAlloc(new AddConstraintDecisionBuilder(ct));
|
|
|
|
|
}
|
|
|
|
|
|
2020-10-29 14:25:39 +01:00
|
|
|
bool Solver::CheckConstraint(Constraint* const ct) {
|
2011-10-11 08:19:59 +00:00
|
|
|
return Solve(MakeConstraintAdder(ct));
|
|
|
|
|
}
|
|
|
|
|
|
2020-10-29 14:25:39 +01:00
|
|
|
bool Solver::SolveAndCommit(DecisionBuilder* const db,
|
|
|
|
|
SearchMonitor* const m1) {
|
2023-12-01 10:32:14 +01:00
|
|
|
return SolveAndCommit(db, std::vector<SearchMonitor*>{m1});
|
2010-09-15 12:42:33 +00:00
|
|
|
}
|
|
|
|
|
|
2020-10-29 14:25:39 +01:00
|
|
|
bool Solver::SolveAndCommit(DecisionBuilder* const db) {
|
2023-12-01 10:32:14 +01:00
|
|
|
return SolveAndCommit(db, {});
|
2010-09-15 12:42:33 +00:00
|
|
|
}
|
|
|
|
|
|
2020-10-29 14:25:39 +01:00
|
|
|
bool Solver::SolveAndCommit(DecisionBuilder* const db, SearchMonitor* const m1,
|
|
|
|
|
SearchMonitor* const m2) {
|
2023-12-01 10:32:14 +01:00
|
|
|
return SolveAndCommit(db, {m1, m2});
|
2010-09-15 12:42:33 +00:00
|
|
|
}
|
|
|
|
|
|
2020-10-29 14:25:39 +01:00
|
|
|
bool Solver::SolveAndCommit(DecisionBuilder* const db, SearchMonitor* const m1,
|
|
|
|
|
SearchMonitor* const m2, SearchMonitor* const m3) {
|
2023-12-01 10:32:14 +01:00
|
|
|
return SolveAndCommit(db, {m1, m2, m3});
|
2010-09-15 12:42:33 +00:00
|
|
|
}
|
|
|
|
|
|
2020-10-29 14:25:39 +01:00
|
|
|
bool Solver::SolveAndCommit(DecisionBuilder* const db,
|
|
|
|
|
const std::vector<SearchMonitor*>& monitors) {
|
2012-05-30 09:18:17 +00:00
|
|
|
NewSearch(db, monitors);
|
2020-10-22 23:36:58 +02:00
|
|
|
searches_.back()->set_created_by_solve(true); // Overwrites default.
|
2012-06-13 16:14:46 +00:00
|
|
|
searches_.back()->set_backtrack_at_the_end_of_the_search(false);
|
2012-05-17 15:43:34 +00:00
|
|
|
NextSolution();
|
|
|
|
|
const bool solution_found = searches_.back()->solution_counter() > 0;
|
|
|
|
|
EndSearch();
|
|
|
|
|
return solution_found;
|
2010-09-15 12:42:33 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Solver::Fail() {
|
2010-10-08 23:55:59 +00:00
|
|
|
if (fail_intercept_) {
|
2015-05-04 17:30:16 +02:00
|
|
|
fail_intercept_();
|
2010-10-08 23:55:59 +00:00
|
|
|
return;
|
|
|
|
|
}
|
2011-11-03 10:27:53 +00:00
|
|
|
ConstraintSolverFailsHere();
|
2010-09-15 12:42:33 +00:00
|
|
|
fails_++;
|
|
|
|
|
searches_.back()->BeginFail();
|
|
|
|
|
searches_.back()->JumpBack();
|
|
|
|
|
}
|
|
|
|
|
|
2014-07-09 11:10:20 +00:00
|
|
|
void Solver::FinishCurrentSearch() {
|
|
|
|
|
searches_.back()->set_should_finish(true);
|
|
|
|
|
}
|
2014-05-22 17:37:21 +00:00
|
|
|
|
2014-07-09 11:10:20 +00:00
|
|
|
void Solver::RestartCurrentSearch() {
|
|
|
|
|
searches_.back()->set_should_restart(true);
|
2014-05-22 17:37:21 +00:00
|
|
|
}
|
|
|
|
|
|
2012-06-19 15:24:32 +00:00
|
|
|
// ----- Cast Expression -----
|
|
|
|
|
|
2020-10-29 14:25:39 +01:00
|
|
|
IntExpr* Solver::CastExpression(const IntVar* const var) const {
|
|
|
|
|
const IntegerCastInfo* const cast_info =
|
2018-04-11 13:00:30 +02:00
|
|
|
gtl::FindOrNull(cast_information_, var);
|
2013-10-10 15:23:20 +00:00
|
|
|
if (cast_info != nullptr) {
|
2012-06-19 15:24:32 +00:00
|
|
|
return cast_info->expression;
|
|
|
|
|
}
|
2013-10-10 15:23:20 +00:00
|
|
|
return nullptr;
|
2012-06-19 15:24:32 +00:00
|
|
|
}
|
|
|
|
|
|
2010-09-15 12:42:33 +00:00
|
|
|
// --- Propagation object names ---
|
|
|
|
|
|
2020-10-29 14:25:39 +01:00
|
|
|
std::string Solver::GetName(const PropagationBaseObject* object) {
|
|
|
|
|
const std::string* name = gtl::FindOrNull(propagation_object_names_, object);
|
2013-10-10 15:23:20 +00:00
|
|
|
if (name != nullptr) {
|
2010-09-15 12:42:33 +00:00
|
|
|
return *name;
|
|
|
|
|
}
|
2020-10-29 14:25:39 +01:00
|
|
|
const IntegerCastInfo* const cast_info =
|
2018-04-11 13:00:30 +02:00
|
|
|
gtl::FindOrNull(cast_information_, object);
|
2013-10-10 15:23:20 +00:00
|
|
|
if (cast_info != nullptr && cast_info->expression != nullptr) {
|
2011-11-14 20:55:35 +00:00
|
|
|
if (cast_info->expression->HasName()) {
|
2018-10-31 16:18:18 +01:00
|
|
|
return absl::StrFormat("Var<%s>", cast_info->expression->name());
|
2016-02-03 15:15:58 +01:00
|
|
|
} else if (parameters_.name_cast_variables()) {
|
2018-10-31 16:18:18 +01:00
|
|
|
return absl::StrFormat("Var<%s>", cast_info->expression->DebugString());
|
2012-07-04 13:29:41 +00:00
|
|
|
} else {
|
2013-12-16 10:24:42 +00:00
|
|
|
const std::string new_name =
|
2018-10-31 16:18:18 +01:00
|
|
|
absl::StrFormat("CastVar<%d>", anonymous_variable_index_++);
|
2012-07-04 13:29:41 +00:00
|
|
|
propagation_object_names_[object] = new_name;
|
|
|
|
|
return new_name;
|
2011-11-14 20:55:35 +00:00
|
|
|
}
|
2010-09-15 12:42:33 +00:00
|
|
|
}
|
2013-12-16 10:24:42 +00:00
|
|
|
const std::string base_name = object->BaseName();
|
2016-02-03 15:15:58 +01:00
|
|
|
if (parameters_.name_all_variables() && !base_name.empty()) {
|
2013-12-16 10:24:42 +00:00
|
|
|
const std::string new_name =
|
2018-10-31 16:18:18 +01:00
|
|
|
absl::StrFormat("%s_%d", base_name, anonymous_variable_index_++);
|
2011-11-19 01:59:37 +00:00
|
|
|
propagation_object_names_[object] = new_name;
|
|
|
|
|
return new_name;
|
|
|
|
|
}
|
2010-09-15 12:42:33 +00:00
|
|
|
return empty_name_;
|
|
|
|
|
}
|
|
|
|
|
|
2020-10-29 14:25:39 +01:00
|
|
|
void Solver::SetName(const PropagationBaseObject* object,
|
2023-11-09 13:46:25 +01:00
|
|
|
absl::string_view name) {
|
2016-02-03 15:15:58 +01:00
|
|
|
if (parameters_.store_names() &&
|
2020-10-22 23:36:58 +02:00
|
|
|
GetName(object) != name) { // in particular if name.empty()
|
2010-09-15 12:42:33 +00:00
|
|
|
propagation_object_names_[object] = name;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-10-29 14:25:39 +01:00
|
|
|
bool Solver::HasName(const PropagationBaseObject* const object) const {
|
2021-12-05 12:15:27 +01:00
|
|
|
return propagation_object_names_.contains(
|
|
|
|
|
const_cast<PropagationBaseObject*>(object)) ||
|
2016-02-03 15:15:58 +01:00
|
|
|
(!object->BaseName().empty() && parameters_.name_all_variables());
|
2011-08-11 05:15:18 +00:00
|
|
|
}
|
|
|
|
|
|
2010-09-15 12:42:33 +00:00
|
|
|
// ------------------ Useful Operators ------------------
|
|
|
|
|
|
2020-10-29 14:25:39 +01:00
|
|
|
std::ostream& operator<<(std::ostream& out, const Solver* const s) {
|
2010-09-15 12:42:33 +00:00
|
|
|
out << s->DebugString();
|
|
|
|
|
return out;
|
|
|
|
|
}
|
|
|
|
|
|
2020-10-29 14:25:39 +01:00
|
|
|
std::ostream& operator<<(std::ostream& out, const BaseObject* const o) {
|
2010-09-15 12:42:33 +00:00
|
|
|
out << o->DebugString();
|
|
|
|
|
return out;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ---------- PropagationBaseObject ---------
|
|
|
|
|
|
2013-12-16 10:24:42 +00:00
|
|
|
std::string PropagationBaseObject::name() const {
|
2010-09-15 12:42:33 +00:00
|
|
|
return solver_->GetName(this);
|
|
|
|
|
}
|
|
|
|
|
|
2024-01-08 18:02:13 +01:00
|
|
|
void PropagationBaseObject::set_name(std::string_view name) {
|
2010-09-15 12:42:33 +00:00
|
|
|
solver_->SetName(this, name);
|
|
|
|
|
}
|
|
|
|
|
|
2013-10-10 15:23:20 +00:00
|
|
|
bool PropagationBaseObject::HasName() const { return solver_->HasName(this); }
|
2011-08-11 05:15:18 +00:00
|
|
|
|
2013-12-16 10:24:42 +00:00
|
|
|
std::string PropagationBaseObject::BaseName() const { return ""; }
|
2011-11-19 01:59:37 +00:00
|
|
|
|
2020-10-29 14:25:39 +01:00
|
|
|
void PropagationBaseObject::ExecuteAll(const SimpleRevFIFO<Demon*>& demons) {
|
2012-09-10 08:37:41 +00:00
|
|
|
solver_->ExecuteAll(demons);
|
|
|
|
|
}
|
|
|
|
|
|
2020-10-29 14:25:39 +01:00
|
|
|
void PropagationBaseObject::EnqueueAll(const SimpleRevFIFO<Demon*>& demons) {
|
2013-06-11 14:49:19 +00:00
|
|
|
solver_->EnqueueAll(demons);
|
|
|
|
|
}
|
|
|
|
|
|
2011-06-29 09:46:25 +00:00
|
|
|
// ---------- Decision Builder ----------
|
|
|
|
|
|
2013-12-16 10:24:42 +00:00
|
|
|
std::string DecisionBuilder::DebugString() const { return "DecisionBuilder"; }
|
2011-06-29 09:46:25 +00:00
|
|
|
|
2021-12-05 12:15:27 +01:00
|
|
|
std::string DecisionBuilder::GetName() const {
|
|
|
|
|
return name_.empty() ? DebugString() : name_;
|
|
|
|
|
}
|
|
|
|
|
|
2020-10-22 23:36:58 +02:00
|
|
|
void DecisionBuilder::AppendMonitors(
|
2022-05-18 16:41:03 +02:00
|
|
|
Solver* const /*solver*/, std::vector<SearchMonitor*>* const /*extras*/) {}
|
2011-08-11 05:15:18 +00:00
|
|
|
|
2022-05-18 16:41:03 +02:00
|
|
|
void DecisionBuilder::Accept(ModelVisitor* const /*visitor*/) const {}
|
2011-06-29 09:46:25 +00:00
|
|
|
|
2010-09-15 12:42:33 +00:00
|
|
|
// ---------- Decision and DecisionVisitor ----------
|
|
|
|
|
|
2020-10-29 14:25:39 +01:00
|
|
|
void Decision::Accept(DecisionVisitor* const visitor) const {
|
2010-09-15 12:42:33 +00:00
|
|
|
visitor->VisitUnknownDecision();
|
|
|
|
|
}
|
|
|
|
|
|
2023-12-01 10:32:14 +01:00
|
|
|
void DecisionVisitor::VisitSetVariableValue([[maybe_unused]] IntVar* const var,
|
|
|
|
|
[[maybe_unused]] int64_t value) {}
|
|
|
|
|
void DecisionVisitor::VisitSplitVariableDomain(
|
|
|
|
|
[[maybe_unused]] IntVar* const var, [[maybe_unused]] int64_t value,
|
|
|
|
|
[[maybe_unused]] bool start_with_lower_half) {}
|
2010-09-15 12:42:33 +00:00
|
|
|
void DecisionVisitor::VisitUnknownDecision() {}
|
2023-12-01 10:32:14 +01:00
|
|
|
void DecisionVisitor::VisitScheduleOrPostpone(
|
|
|
|
|
[[maybe_unused]] IntervalVar* const var, [[maybe_unused]] int64_t est) {}
|
|
|
|
|
void DecisionVisitor::VisitScheduleOrExpedite(
|
|
|
|
|
[[maybe_unused]] IntervalVar* const var, [[maybe_unused]] int64_t est) {}
|
|
|
|
|
void DecisionVisitor::VisitRankFirstInterval(
|
|
|
|
|
[[maybe_unused]] SequenceVar* const sequence, [[maybe_unused]] int index) {}
|
2011-12-16 21:02:59 +00:00
|
|
|
|
2023-12-01 10:32:14 +01:00
|
|
|
void DecisionVisitor::VisitRankLastInterval(
|
|
|
|
|
[[maybe_unused]] SequenceVar* const sequence, [[maybe_unused]] int index) {}
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2011-07-11 20:13:14 +00:00
|
|
|
// ---------- ModelVisitor ----------
|
|
|
|
|
|
2011-09-05 13:45:29 +00:00
|
|
|
// Tags for constraints, arguments, extensions.
|
2011-07-11 20:13:14 +00:00
|
|
|
|
|
|
|
|
const char ModelVisitor::kAbs[] = "Abs";
|
2012-06-27 15:24:10 +00:00
|
|
|
const char ModelVisitor::kAbsEqual[] = "AbsEqual";
|
2011-07-11 20:13:14 +00:00
|
|
|
const char ModelVisitor::kAllDifferent[] = "AllDifferent";
|
|
|
|
|
const char ModelVisitor::kAllowedAssignments[] = "AllowedAssignments";
|
2016-10-05 13:45:23 +02:00
|
|
|
const char ModelVisitor::kAtMost[] = "AtMost";
|
2011-07-11 20:13:14 +00:00
|
|
|
const char ModelVisitor::kBetween[] = "Between";
|
2013-12-05 16:06:40 +00:00
|
|
|
const char ModelVisitor::kConditionalExpr[] = "ConditionalExpr";
|
2013-12-10 16:02:46 +00:00
|
|
|
const char ModelVisitor::kCircuit[] = "Circuit";
|
2011-07-11 20:13:14 +00:00
|
|
|
const char ModelVisitor::kConvexPiecewise[] = "ConvexPiecewise";
|
|
|
|
|
const char ModelVisitor::kCountEqual[] = "CountEqual";
|
2013-06-11 14:49:19 +00:00
|
|
|
const char ModelVisitor::kCover[] = "Cover";
|
2011-07-11 20:13:14 +00:00
|
|
|
const char ModelVisitor::kCumulative[] = "Cumulative";
|
|
|
|
|
const char ModelVisitor::kDeviation[] = "Deviation";
|
|
|
|
|
const char ModelVisitor::kDifference[] = "Difference";
|
2011-11-03 10:27:53 +00:00
|
|
|
const char ModelVisitor::kDisjunctive[] = "Disjunctive";
|
2011-07-11 20:13:14 +00:00
|
|
|
const char ModelVisitor::kDistribute[] = "Distribute";
|
|
|
|
|
const char ModelVisitor::kDivide[] = "Divide";
|
2011-08-11 05:15:18 +00:00
|
|
|
const char ModelVisitor::kDurationExpr[] = "DurationExpression";
|
2011-07-11 20:13:14 +00:00
|
|
|
const char ModelVisitor::kElement[] = "Element";
|
2022-09-05 18:30:09 +02:00
|
|
|
const char ModelVisitor::kLightElementEqual[] = "LightElementEqual";
|
2011-08-11 05:15:18 +00:00
|
|
|
const char ModelVisitor::kElementEqual[] = "ElementEqual";
|
|
|
|
|
const char ModelVisitor::kEndExpr[] = "EndExpression";
|
|
|
|
|
const char ModelVisitor::kEquality[] = "Equal";
|
2011-07-11 20:13:14 +00:00
|
|
|
const char ModelVisitor::kFalseConstraint[] = "FalseConstraint";
|
2013-10-10 15:23:20 +00:00
|
|
|
const char ModelVisitor::kGlobalCardinality[] = "GlobalCardinality";
|
2011-07-11 20:13:14 +00:00
|
|
|
const char ModelVisitor::kGreater[] = "Greater";
|
|
|
|
|
const char ModelVisitor::kGreaterOrEqual[] = "GreaterOrEqual";
|
2012-08-17 23:30:10 +00:00
|
|
|
const char ModelVisitor::kIndexOf[] = "IndexOf";
|
2011-08-11 05:15:18 +00:00
|
|
|
const char ModelVisitor::kIntegerVariable[] = "IntegerVariable";
|
2011-07-11 20:13:14 +00:00
|
|
|
const char ModelVisitor::kIntervalBinaryRelation[] = "IntervalBinaryRelation";
|
|
|
|
|
const char ModelVisitor::kIntervalDisjunction[] = "IntervalDisjunction";
|
|
|
|
|
const char ModelVisitor::kIntervalUnaryRelation[] = "IntervalUnaryRelation";
|
2011-08-11 05:15:18 +00:00
|
|
|
const char ModelVisitor::kIntervalVariable[] = "IntervalVariable";
|
2014-04-19 08:53:33 +00:00
|
|
|
const char ModelVisitor::kInversePermutation[] = "InversePermutation";
|
2011-07-11 20:13:14 +00:00
|
|
|
const char ModelVisitor::kIsBetween[] = "IsBetween;";
|
|
|
|
|
const char ModelVisitor::kIsDifferent[] = "IsDifferent";
|
|
|
|
|
const char ModelVisitor::kIsEqual[] = "IsEqual";
|
2012-07-04 22:05:58 +00:00
|
|
|
const char ModelVisitor::kIsGreater[] = "IsGreater";
|
2011-07-11 20:13:14 +00:00
|
|
|
const char ModelVisitor::kIsGreaterOrEqual[] = "IsGreaterOrEqual";
|
2012-07-04 22:05:58 +00:00
|
|
|
const char ModelVisitor::kIsLess[] = "IsLess";
|
2011-07-11 20:13:14 +00:00
|
|
|
const char ModelVisitor::kIsLessOrEqual[] = "IsLessOrEqual";
|
|
|
|
|
const char ModelVisitor::kIsMember[] = "IsMember;";
|
|
|
|
|
const char ModelVisitor::kLess[] = "Less";
|
|
|
|
|
const char ModelVisitor::kLessOrEqual[] = "LessOrEqual";
|
2013-12-20 10:44:30 +00:00
|
|
|
const char ModelVisitor::kLexLess[] = "LexLess";
|
2011-08-11 05:15:18 +00:00
|
|
|
const char ModelVisitor::kLinkExprVar[] = "CastExpressionIntoVariable";
|
2011-07-11 20:13:14 +00:00
|
|
|
const char ModelVisitor::kMapDomain[] = "MapDomain";
|
|
|
|
|
const char ModelVisitor::kMax[] = "Max";
|
|
|
|
|
const char ModelVisitor::kMaxEqual[] = "MaxEqual";
|
|
|
|
|
const char ModelVisitor::kMember[] = "Member";
|
|
|
|
|
const char ModelVisitor::kMin[] = "Min";
|
|
|
|
|
const char ModelVisitor::kMinEqual[] = "MinEqual";
|
2013-06-11 14:49:19 +00:00
|
|
|
const char ModelVisitor::kModulo[] = "Modulo";
|
2011-07-11 20:13:14 +00:00
|
|
|
const char ModelVisitor::kNoCycle[] = "NoCycle";
|
|
|
|
|
const char ModelVisitor::kNonEqual[] = "NonEqual";
|
2016-07-25 11:09:39 -07:00
|
|
|
const char ModelVisitor::kNotBetween[] = "NotBetween";
|
2016-06-02 13:19:10 +02:00
|
|
|
const char ModelVisitor::kNotMember[] = "NotMember";
|
2013-01-10 17:01:34 +00:00
|
|
|
const char ModelVisitor::kNullIntersect[] = "NullIntersect";
|
2011-07-11 20:13:14 +00:00
|
|
|
const char ModelVisitor::kOpposite[] = "Opposite";
|
|
|
|
|
const char ModelVisitor::kPack[] = "Pack";
|
|
|
|
|
const char ModelVisitor::kPathCumul[] = "PathCumul";
|
2016-06-02 13:19:10 +02:00
|
|
|
const char ModelVisitor::kDelayedPathCumul[] = "DelayedPathCumul";
|
2011-08-11 05:15:18 +00:00
|
|
|
const char ModelVisitor::kPerformedExpr[] = "PerformedExpression";
|
2012-06-19 15:24:32 +00:00
|
|
|
const char ModelVisitor::kPower[] = "Power";
|
2011-07-11 20:13:14 +00:00
|
|
|
const char ModelVisitor::kProduct[] = "Product";
|
|
|
|
|
const char ModelVisitor::kScalProd[] = "ScalarProduct";
|
|
|
|
|
const char ModelVisitor::kScalProdEqual[] = "ScalarProductEqual";
|
|
|
|
|
const char ModelVisitor::kScalProdGreaterOrEqual[] =
|
|
|
|
|
"ScalarProductGreaterOrEqual";
|
|
|
|
|
const char ModelVisitor::kScalProdLessOrEqual[] = "ScalarProductLessOrEqual";
|
|
|
|
|
const char ModelVisitor::kSemiContinuous[] = "SemiContinuous";
|
2011-11-03 10:27:53 +00:00
|
|
|
const char ModelVisitor::kSequenceVariable[] = "SequenceVariable";
|
2012-04-10 14:21:22 +00:00
|
|
|
const char ModelVisitor::kSortingConstraint[] = "SortingConstraint";
|
2011-07-11 20:13:14 +00:00
|
|
|
const char ModelVisitor::kSquare[] = "Square";
|
2013-10-10 15:23:20 +00:00
|
|
|
const char ModelVisitor::kStartExpr[] = "StartExpression";
|
2011-07-11 20:13:14 +00:00
|
|
|
const char ModelVisitor::kSum[] = "Sum";
|
|
|
|
|
const char ModelVisitor::kSumEqual[] = "SumEqual";
|
|
|
|
|
const char ModelVisitor::kSumGreaterOrEqual[] = "SumGreaterOrEqual";
|
|
|
|
|
const char ModelVisitor::kSumLessOrEqual[] = "SumLessOrEqual";
|
2013-10-10 15:23:20 +00:00
|
|
|
const char ModelVisitor::kTransition[] = "Transition";
|
2013-06-18 09:43:51 +00:00
|
|
|
const char ModelVisitor::kTrace[] = "Trace";
|
2011-07-11 20:13:14 +00:00
|
|
|
const char ModelVisitor::kTrueConstraint[] = "TrueConstraint";
|
2012-07-04 13:29:41 +00:00
|
|
|
const char ModelVisitor::kVarBoundWatcher[] = "VarBoundWatcher";
|
|
|
|
|
const char ModelVisitor::kVarValueWatcher[] = "VarValueWatcher";
|
2011-07-11 20:13:14 +00:00
|
|
|
|
2011-08-11 05:15:18 +00:00
|
|
|
const char ModelVisitor::kCountAssignedItemsExtension[] = "CountAssignedItems";
|
|
|
|
|
const char ModelVisitor::kCountUsedBinsExtension[] = "CountUsedBins";
|
|
|
|
|
const char ModelVisitor::kInt64ToBoolExtension[] = "Int64ToBoolFunction";
|
|
|
|
|
const char ModelVisitor::kInt64ToInt64Extension[] = "Int64ToInt64Function";
|
|
|
|
|
const char ModelVisitor::kObjectiveExtension[] = "Objective";
|
|
|
|
|
const char ModelVisitor::kSearchLimitExtension[] = "SearchLimit";
|
|
|
|
|
const char ModelVisitor::kUsageEqualVariableExtension[] = "UsageEqualVariable";
|
2013-06-11 14:49:19 +00:00
|
|
|
|
2011-08-11 05:15:18 +00:00
|
|
|
const char ModelVisitor::kUsageLessConstantExtension[] = "UsageLessConstant";
|
|
|
|
|
const char ModelVisitor::kVariableGroupExtension[] = "VariableGroup";
|
|
|
|
|
const char ModelVisitor::kVariableUsageLessConstantExtension[] =
|
|
|
|
|
"VariableUsageLessConstant";
|
|
|
|
|
const char ModelVisitor::kWeightedSumOfAssignedEqualVariableExtension[] =
|
|
|
|
|
"WeightedSumOfAssignedEqualVariable";
|
|
|
|
|
|
2011-07-11 20:13:14 +00:00
|
|
|
const char ModelVisitor::kActiveArgument[] = "active";
|
2011-08-11 05:15:18 +00:00
|
|
|
const char ModelVisitor::kAssumePathsArgument[] = "assume_paths";
|
|
|
|
|
const char ModelVisitor::kBranchesLimitArgument[] = "branches_limit";
|
|
|
|
|
const char ModelVisitor::kCapacityArgument[] = "capacity";
|
2011-07-11 20:13:14 +00:00
|
|
|
const char ModelVisitor::kCardsArgument[] = "cardinalities";
|
|
|
|
|
const char ModelVisitor::kCoefficientsArgument[] = "coefficients";
|
|
|
|
|
const char ModelVisitor::kCountArgument[] = "count";
|
2011-08-11 05:15:18 +00:00
|
|
|
const char ModelVisitor::kCumulativeArgument[] = "cumulative";
|
2011-07-11 20:13:14 +00:00
|
|
|
const char ModelVisitor::kCumulsArgument[] = "cumuls";
|
2011-08-11 05:15:18 +00:00
|
|
|
const char ModelVisitor::kDemandsArgument[] = "demands";
|
|
|
|
|
const char ModelVisitor::kDurationMinArgument[] = "duration_min";
|
|
|
|
|
const char ModelVisitor::kDurationMaxArgument[] = "duration_max";
|
2011-07-11 20:13:14 +00:00
|
|
|
const char ModelVisitor::kEarlyCostArgument[] = "early_cost";
|
|
|
|
|
const char ModelVisitor::kEarlyDateArgument[] = "early_date";
|
2011-08-11 05:15:18 +00:00
|
|
|
const char ModelVisitor::kEndMinArgument[] = "end_min";
|
|
|
|
|
const char ModelVisitor::kEndMaxArgument[] = "end_max";
|
2016-06-02 13:19:10 +02:00
|
|
|
const char ModelVisitor::kEndsArgument[] = "ends";
|
2011-07-11 20:13:14 +00:00
|
|
|
const char ModelVisitor::kExpressionArgument[] = "expression";
|
2011-08-11 05:15:18 +00:00
|
|
|
const char ModelVisitor::kFailuresLimitArgument[] = "failures_limit";
|
|
|
|
|
const char ModelVisitor::kFinalStatesArgument[] = "final_states";
|
2011-07-11 20:13:14 +00:00
|
|
|
const char ModelVisitor::kFixedChargeArgument[] = "fixed_charge";
|
|
|
|
|
const char ModelVisitor::kIndex2Argument[] = "index2";
|
|
|
|
|
const char ModelVisitor::kIndexArgument[] = "index";
|
|
|
|
|
const char ModelVisitor::kInitialState[] = "initial_state";
|
|
|
|
|
const char ModelVisitor::kIntervalArgument[] = "interval";
|
|
|
|
|
const char ModelVisitor::kIntervalsArgument[] = "intervals";
|
|
|
|
|
const char ModelVisitor::kLateCostArgument[] = "late_cost";
|
|
|
|
|
const char ModelVisitor::kLateDateArgument[] = "late_date";
|
|
|
|
|
const char ModelVisitor::kLeftArgument[] = "left";
|
|
|
|
|
const char ModelVisitor::kMaxArgument[] = "max_value";
|
2011-08-11 05:15:18 +00:00
|
|
|
const char ModelVisitor::kMaximizeArgument[] = "maximize";
|
2011-07-11 20:13:14 +00:00
|
|
|
const char ModelVisitor::kMinArgument[] = "min_value";
|
2012-08-14 21:45:43 +00:00
|
|
|
const char ModelVisitor::kModuloArgument[] = "modulo";
|
2011-07-11 20:13:14 +00:00
|
|
|
const char ModelVisitor::kNextsArgument[] = "nexts";
|
2011-08-11 05:15:18 +00:00
|
|
|
const char ModelVisitor::kOptionalArgument[] = "optional";
|
2013-12-16 10:24:42 +00:00
|
|
|
const char ModelVisitor::kPartialArgument[] = "partial";
|
2013-07-05 15:19:52 +00:00
|
|
|
const char ModelVisitor::kPositionXArgument[] = "position_x";
|
|
|
|
|
const char ModelVisitor::kPositionYArgument[] = "position_y";
|
2011-07-11 20:13:14 +00:00
|
|
|
const char ModelVisitor::kRangeArgument[] = "range";
|
|
|
|
|
const char ModelVisitor::kRelationArgument[] = "relation";
|
|
|
|
|
const char ModelVisitor::kRightArgument[] = "right";
|
2011-11-03 10:27:53 +00:00
|
|
|
const char ModelVisitor::kSequenceArgument[] = "sequence";
|
|
|
|
|
const char ModelVisitor::kSequencesArgument[] = "sequences";
|
2011-08-11 05:15:18 +00:00
|
|
|
const char ModelVisitor::kSmartTimeCheckArgument[] = "smart_time_check";
|
2011-07-11 20:13:14 +00:00
|
|
|
const char ModelVisitor::kSizeArgument[] = "size";
|
2013-07-05 15:19:52 +00:00
|
|
|
const char ModelVisitor::kSizeXArgument[] = "size_x";
|
|
|
|
|
const char ModelVisitor::kSizeYArgument[] = "size_y";
|
2011-08-11 05:15:18 +00:00
|
|
|
const char ModelVisitor::kSolutionLimitArgument[] = "solutions_limit";
|
|
|
|
|
const char ModelVisitor::kStartMinArgument[] = "start_min";
|
|
|
|
|
const char ModelVisitor::kStartMaxArgument[] = "start_max";
|
2016-06-02 13:19:10 +02:00
|
|
|
const char ModelVisitor::kStartsArgument[] = "starts";
|
2011-07-11 20:13:14 +00:00
|
|
|
const char ModelVisitor::kStepArgument[] = "step";
|
|
|
|
|
const char ModelVisitor::kTargetArgument[] = "target_variable";
|
2011-08-11 05:15:18 +00:00
|
|
|
const char ModelVisitor::kTimeLimitArgument[] = "time_limit";
|
2011-07-11 20:13:14 +00:00
|
|
|
const char ModelVisitor::kTransitsArgument[] = "transits";
|
|
|
|
|
const char ModelVisitor::kTuplesArgument[] = "tuples";
|
|
|
|
|
const char ModelVisitor::kValueArgument[] = "value";
|
|
|
|
|
const char ModelVisitor::kValuesArgument[] = "values";
|
|
|
|
|
const char ModelVisitor::kVarsArgument[] = "variables";
|
2015-10-23 13:45:43 +02:00
|
|
|
const char ModelVisitor::kEvaluatorArgument[] = "evaluator";
|
|
|
|
|
|
2011-12-17 18:03:38 +00:00
|
|
|
const char ModelVisitor::kVariableArgument[] = "variable";
|
2011-07-11 20:13:14 +00:00
|
|
|
|
2011-08-11 05:15:18 +00:00
|
|
|
const char ModelVisitor::kMirrorOperation[] = "mirror";
|
|
|
|
|
const char ModelVisitor::kRelaxedMaxOperation[] = "relaxed_max";
|
|
|
|
|
const char ModelVisitor::kRelaxedMinOperation[] = "relaxed_min";
|
2011-12-17 18:03:38 +00:00
|
|
|
const char ModelVisitor::kSumOperation[] = "sum";
|
|
|
|
|
const char ModelVisitor::kDifferenceOperation[] = "difference";
|
|
|
|
|
const char ModelVisitor::kProductOperation[] = "product";
|
2013-06-11 14:49:19 +00:00
|
|
|
const char ModelVisitor::kStartSyncOnStartOperation[] = "start_synced_on_start";
|
|
|
|
|
const char ModelVisitor::kStartSyncOnEndOperation[] = "start_synced_on_end";
|
2013-06-18 09:43:51 +00:00
|
|
|
const char ModelVisitor::kTraceOperation[] = "trace";
|
2011-08-11 05:15:18 +00:00
|
|
|
|
2011-07-11 20:13:14 +00:00
|
|
|
// Methods
|
|
|
|
|
|
|
|
|
|
ModelVisitor::~ModelVisitor() {}
|
|
|
|
|
|
2023-12-01 10:32:14 +01:00
|
|
|
void ModelVisitor::BeginVisitModel(
|
|
|
|
|
[[maybe_unused]] const std::string& type_name) {}
|
|
|
|
|
void ModelVisitor::EndVisitModel(
|
|
|
|
|
[[maybe_unused]] const std::string& type_name) {}
|
2011-07-11 20:13:14 +00:00
|
|
|
|
2023-12-01 10:32:14 +01:00
|
|
|
void ModelVisitor::BeginVisitConstraint(
|
|
|
|
|
[[maybe_unused]] const std::string& type_name,
|
|
|
|
|
[[maybe_unused]] const Constraint* const constraint) {}
|
|
|
|
|
void ModelVisitor::EndVisitConstraint(
|
|
|
|
|
[[maybe_unused]] const std::string& type_name,
|
|
|
|
|
[[maybe_unused]] const Constraint* const constraint) {}
|
2011-07-11 20:13:14 +00:00
|
|
|
|
2023-12-01 10:32:14 +01:00
|
|
|
void ModelVisitor::BeginVisitExtension(
|
|
|
|
|
[[maybe_unused]] const std::string& type) {}
|
|
|
|
|
void ModelVisitor::EndVisitExtension([[maybe_unused]] const std::string& type) {
|
|
|
|
|
}
|
2011-07-11 20:13:14 +00:00
|
|
|
|
2023-12-01 10:32:14 +01:00
|
|
|
void ModelVisitor::BeginVisitIntegerExpression(
|
|
|
|
|
[[maybe_unused]] const std::string& type_name,
|
|
|
|
|
[[maybe_unused]] const IntExpr* const expr) {}
|
|
|
|
|
void ModelVisitor::EndVisitIntegerExpression(
|
|
|
|
|
[[maybe_unused]] const std::string& type_name,
|
|
|
|
|
[[maybe_unused]] const IntExpr* const expr) {}
|
2011-07-11 20:13:14 +00:00
|
|
|
|
2023-12-01 10:32:14 +01:00
|
|
|
void ModelVisitor::VisitIntegerVariable(
|
|
|
|
|
[[maybe_unused]] const IntVar* const variable, IntExpr* const delegate) {
|
2013-10-10 15:23:20 +00:00
|
|
|
if (delegate != nullptr) {
|
2011-07-11 20:13:14 +00:00
|
|
|
delegate->Accept(this);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-12-01 10:32:14 +01:00
|
|
|
void ModelVisitor::VisitIntegerVariable(
|
|
|
|
|
[[maybe_unused]] const IntVar* const variable,
|
|
|
|
|
[[maybe_unused]] const std::string& operation,
|
|
|
|
|
[[maybe_unused]] int64_t value, IntVar* const delegate) {
|
2013-10-10 15:23:20 +00:00
|
|
|
if (delegate != nullptr) {
|
2011-12-17 18:03:38 +00:00
|
|
|
delegate->Accept(this);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-12-01 10:32:14 +01:00
|
|
|
void ModelVisitor::VisitIntervalVariable(
|
|
|
|
|
[[maybe_unused]] const IntervalVar* const variable,
|
|
|
|
|
[[maybe_unused]] const std::string& operation,
|
|
|
|
|
[[maybe_unused]] int64_t value, IntervalVar* const delegate) {
|
2013-10-10 15:23:20 +00:00
|
|
|
if (delegate != nullptr) {
|
2011-07-11 20:13:14 +00:00
|
|
|
delegate->Accept(this);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-10-29 14:25:39 +01:00
|
|
|
void ModelVisitor::VisitSequenceVariable(const SequenceVar* const variable) {
|
2011-11-03 10:27:53 +00:00
|
|
|
for (int i = 0; i < variable->size(); ++i) {
|
|
|
|
|
variable->Interval(i)->Accept(this);
|
|
|
|
|
}
|
|
|
|
|
}
|
2011-07-11 20:13:14 +00:00
|
|
|
|
2023-12-01 10:32:14 +01:00
|
|
|
void ModelVisitor::VisitIntegerArgument(
|
|
|
|
|
[[maybe_unused]] const std::string& arg_name,
|
|
|
|
|
[[maybe_unused]] int64_t value) {}
|
2011-07-11 20:13:14 +00:00
|
|
|
|
2021-04-01 12:13:35 +02:00
|
|
|
void ModelVisitor::VisitIntegerArrayArgument(
|
2023-12-01 10:32:14 +01:00
|
|
|
[[maybe_unused]] const std::string& arg_name,
|
|
|
|
|
[[maybe_unused]] const std::vector<int64_t>& values) {}
|
2011-08-11 05:15:18 +00:00
|
|
|
|
2023-12-01 10:32:14 +01:00
|
|
|
void ModelVisitor::VisitIntegerMatrixArgument(
|
|
|
|
|
[[maybe_unused]] const std::string& arg_name,
|
|
|
|
|
[[maybe_unused]] const IntTupleSet& tuples) {}
|
2011-07-11 20:13:14 +00:00
|
|
|
|
2023-12-01 10:32:14 +01:00
|
|
|
void ModelVisitor::VisitIntegerExpressionArgument(
|
|
|
|
|
[[maybe_unused]] const std::string& arg_name, IntExpr* const argument) {
|
2011-07-11 20:13:14 +00:00
|
|
|
argument->Accept(this);
|
|
|
|
|
}
|
|
|
|
|
|
2015-10-23 13:45:43 +02:00
|
|
|
void ModelVisitor::VisitIntegerVariableEvaluatorArgument(
|
2023-12-01 10:32:14 +01:00
|
|
|
[[maybe_unused]] const std::string& arg_name,
|
|
|
|
|
[[maybe_unused]] const Solver::Int64ToIntVar& arguments) {}
|
2015-10-23 13:45:43 +02:00
|
|
|
|
2011-07-11 20:13:14 +00:00
|
|
|
void ModelVisitor::VisitIntegerVariableArrayArgument(
|
2023-12-01 10:32:14 +01:00
|
|
|
[[maybe_unused]] const std::string& arg_name,
|
|
|
|
|
const std::vector<IntVar*>& arguments) {
|
2016-07-28 10:15:46 -07:00
|
|
|
ForAll(arguments, &IntVar::Accept, this);
|
2011-07-11 20:13:14 +00:00
|
|
|
}
|
|
|
|
|
|
2023-12-01 10:32:14 +01:00
|
|
|
void ModelVisitor::VisitIntervalArgument(
|
|
|
|
|
[[maybe_unused]] const std::string& arg_name, IntervalVar* const argument) {
|
2011-07-11 20:13:14 +00:00
|
|
|
argument->Accept(this);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ModelVisitor::VisitIntervalArrayArgument(
|
2023-12-01 10:32:14 +01:00
|
|
|
[[maybe_unused]] const std::string& arg_name,
|
|
|
|
|
const std::vector<IntervalVar*>& arguments) {
|
2016-07-28 10:15:46 -07:00
|
|
|
ForAll(arguments, &IntervalVar::Accept, this);
|
2011-07-11 20:13:14 +00:00
|
|
|
}
|
|
|
|
|
|
2023-12-01 10:32:14 +01:00
|
|
|
void ModelVisitor::VisitSequenceArgument(
|
|
|
|
|
[[maybe_unused]] const std::string& arg_name, SequenceVar* const argument) {
|
2011-11-03 10:27:53 +00:00
|
|
|
argument->Accept(this);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ModelVisitor::VisitSequenceArrayArgument(
|
2023-12-01 10:32:14 +01:00
|
|
|
[[maybe_unused]] const std::string& arg_name,
|
|
|
|
|
const std::vector<SequenceVar*>& arguments) {
|
2016-07-28 10:15:46 -07:00
|
|
|
ForAll(arguments, &SequenceVar::Accept, this);
|
2011-11-03 10:27:53 +00:00
|
|
|
}
|
|
|
|
|
|
2011-07-11 20:13:14 +00:00
|
|
|
// ----- Helpers -----
|
|
|
|
|
|
2015-08-13 16:00:54 +02:00
|
|
|
void ModelVisitor::VisitInt64ToBoolExtension(Solver::IndexFilter1 filter,
|
2021-04-01 12:13:35 +02:00
|
|
|
int64_t index_min,
|
|
|
|
|
int64_t index_max) {
|
2015-08-13 16:00:54 +02:00
|
|
|
if (filter != nullptr) {
|
2021-04-01 12:13:35 +02:00
|
|
|
std::vector<int64_t> cached_results;
|
2015-08-13 16:00:54 +02:00
|
|
|
for (int i = index_min; i <= index_max; ++i) {
|
|
|
|
|
cached_results.push_back(filter(i));
|
|
|
|
|
}
|
|
|
|
|
BeginVisitExtension(kInt64ToBoolExtension);
|
|
|
|
|
VisitIntegerArgument(kMinArgument, index_min);
|
|
|
|
|
VisitIntegerArgument(kMaxArgument, index_max);
|
|
|
|
|
VisitIntegerArrayArgument(kValuesArgument, cached_results);
|
|
|
|
|
EndVisitExtension(kInt64ToBoolExtension);
|
2011-08-11 05:15:18 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-10-22 23:36:58 +02:00
|
|
|
void ModelVisitor::VisitInt64ToInt64Extension(
|
2021-04-01 12:13:35 +02:00
|
|
|
const Solver::IndexEvaluator1& eval, int64_t index_min, int64_t index_max) {
|
2015-08-13 16:00:54 +02:00
|
|
|
CHECK(eval != nullptr);
|
2021-04-01 12:13:35 +02:00
|
|
|
std::vector<int64_t> cached_results;
|
2011-08-11 05:15:18 +00:00
|
|
|
for (int i = index_min; i <= index_max; ++i) {
|
2015-08-13 16:00:54 +02:00
|
|
|
cached_results.push_back(eval(i));
|
2011-08-11 05:15:18 +00:00
|
|
|
}
|
|
|
|
|
BeginVisitExtension(kInt64ToInt64Extension);
|
|
|
|
|
VisitIntegerArgument(kMinArgument, index_min);
|
|
|
|
|
VisitIntegerArgument(kMaxArgument, index_max);
|
2013-10-10 15:23:20 +00:00
|
|
|
VisitIntegerArrayArgument(kValuesArgument, cached_results);
|
2011-08-11 05:15:18 +00:00
|
|
|
EndVisitExtension(kInt64ToInt64Extension);
|
|
|
|
|
}
|
|
|
|
|
|
2020-10-29 14:25:39 +01:00
|
|
|
void ModelVisitor::VisitInt64ToInt64AsArray(const Solver::IndexEvaluator1& eval,
|
|
|
|
|
const std::string& arg_name,
|
2021-04-01 12:13:35 +02:00
|
|
|
int64_t index_max) {
|
2015-08-13 16:00:54 +02:00
|
|
|
CHECK(eval != nullptr);
|
2021-04-01 12:13:35 +02:00
|
|
|
std::vector<int64_t> cached_results;
|
2011-08-11 07:26:19 +00:00
|
|
|
for (int i = 0; i <= index_max; ++i) {
|
2015-08-13 16:00:54 +02:00
|
|
|
cached_results.push_back(eval(i));
|
2011-08-11 07:26:19 +00:00
|
|
|
}
|
2013-10-10 15:23:20 +00:00
|
|
|
VisitIntegerArrayArgument(arg_name, cached_results);
|
2011-08-11 07:26:19 +00:00
|
|
|
}
|
|
|
|
|
|
2010-09-15 12:42:33 +00:00
|
|
|
// ---------- Search Monitor ----------
|
|
|
|
|
|
|
|
|
|
void SearchMonitor::EnterSearch() {}
|
|
|
|
|
void SearchMonitor::RestartSearch() {}
|
|
|
|
|
void SearchMonitor::ExitSearch() {}
|
2023-12-01 10:32:14 +01:00
|
|
|
void SearchMonitor::BeginNextDecision(DecisionBuilder* const) {}
|
|
|
|
|
void SearchMonitor::EndNextDecision(DecisionBuilder* const, Decision* const) {}
|
|
|
|
|
void SearchMonitor::ApplyDecision(Decision* const) {}
|
|
|
|
|
void SearchMonitor::RefuteDecision(Decision* const) {}
|
|
|
|
|
void SearchMonitor::AfterDecision(Decision* const,
|
|
|
|
|
[[maybe_unused]] bool apply) {}
|
2010-09-15 12:42:33 +00:00
|
|
|
void SearchMonitor::BeginFail() {}
|
|
|
|
|
void SearchMonitor::EndFail() {}
|
|
|
|
|
void SearchMonitor::BeginInitialPropagation() {}
|
|
|
|
|
void SearchMonitor::EndInitialPropagation() {}
|
2010-10-06 16:04:31 +00:00
|
|
|
bool SearchMonitor::AcceptSolution() { return true; }
|
|
|
|
|
bool SearchMonitor::AtSolution() { return false; }
|
2010-09-15 12:42:33 +00:00
|
|
|
void SearchMonitor::NoMoreSolutions() {}
|
|
|
|
|
bool SearchMonitor::LocalOptimum() { return false; }
|
2023-12-01 10:32:14 +01:00
|
|
|
bool SearchMonitor::AcceptDelta([[maybe_unused]] Assignment* delta,
|
|
|
|
|
[[maybe_unused]] Assignment* deltadelta) {
|
2013-10-10 15:23:20 +00:00
|
|
|
return true;
|
|
|
|
|
}
|
2010-09-15 12:42:33 +00:00
|
|
|
void SearchMonitor::AcceptNeighbor() {}
|
2019-03-15 17:17:02 +01:00
|
|
|
void SearchMonitor::AcceptUncheckedNeighbor() {}
|
2010-09-15 12:42:33 +00:00
|
|
|
void SearchMonitor::PeriodicCheck() {}
|
2023-12-01 10:32:14 +01:00
|
|
|
void SearchMonitor::Accept([[maybe_unused]] ModelVisitor* const visitor) const {
|
|
|
|
|
}
|
2011-11-19 01:59:37 +00:00
|
|
|
// A search monitors adds itself on the active search.
|
2011-11-16 17:32:24 +00:00
|
|
|
void SearchMonitor::Install() {
|
2022-09-05 18:30:09 +02:00
|
|
|
for (std::underlying_type<Solver::MonitorEvent>::type event = 0;
|
|
|
|
|
event != to_underlying(Solver::MonitorEvent::kLast); ++event) {
|
|
|
|
|
ListenToEvent(static_cast<Solver::MonitorEvent>(event));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SearchMonitor::ListenToEvent(Solver::MonitorEvent event) {
|
|
|
|
|
solver()->searches_.back()->AddEventListener(event, this);
|
2011-11-16 17:32:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ---------- Propagation Monitor -----------
|
2020-10-29 14:25:39 +01:00
|
|
|
PropagationMonitor::PropagationMonitor(Solver* const solver)
|
2017-12-08 14:52:49 +01:00
|
|
|
: SearchMonitor(solver) {}
|
2011-11-16 17:32:24 +00:00
|
|
|
|
|
|
|
|
PropagationMonitor::~PropagationMonitor() {}
|
|
|
|
|
|
2016-07-28 10:15:46 -07:00
|
|
|
// A propagation monitor listens to search events as well as propagation events.
|
2011-11-16 17:32:24 +00:00
|
|
|
void PropagationMonitor::Install() {
|
|
|
|
|
SearchMonitor::Install();
|
|
|
|
|
solver()->AddPropagationMonitor(this);
|
|
|
|
|
}
|
|
|
|
|
|
2016-07-28 10:15:46 -07:00
|
|
|
// ---------- Local Search Monitor -----------
|
2020-10-29 14:25:39 +01:00
|
|
|
LocalSearchMonitor::LocalSearchMonitor(Solver* const solver)
|
2017-12-08 14:52:49 +01:00
|
|
|
: SearchMonitor(solver) {}
|
2016-07-28 10:15:46 -07:00
|
|
|
|
|
|
|
|
LocalSearchMonitor::~LocalSearchMonitor() {}
|
|
|
|
|
|
|
|
|
|
// A local search monitor listens to search events as well as local search
|
|
|
|
|
// events.
|
|
|
|
|
void LocalSearchMonitor::Install() {
|
|
|
|
|
SearchMonitor::Install();
|
|
|
|
|
solver()->AddLocalSearchMonitor(this);
|
|
|
|
|
}
|
|
|
|
|
|
2011-11-16 17:32:24 +00:00
|
|
|
// ---------- Trace ----------
|
|
|
|
|
|
|
|
|
|
class Trace : public PropagationMonitor {
|
2020-10-22 23:36:58 +02:00
|
|
|
public:
|
2020-10-29 14:25:39 +01:00
|
|
|
explicit Trace(Solver* const s) : PropagationMonitor(s) {}
|
2011-11-19 01:59:37 +00:00
|
|
|
|
2015-04-16 15:49:51 +02:00
|
|
|
~Trace() override {}
|
2011-11-16 17:32:24 +00:00
|
|
|
|
2020-10-22 23:36:58 +02:00
|
|
|
void BeginConstraintInitialPropagation(
|
2020-10-29 14:25:39 +01:00
|
|
|
Constraint* const constraint) override {
|
2016-07-28 10:15:46 -07:00
|
|
|
ForAll(monitors_, &PropagationMonitor::BeginConstraintInitialPropagation,
|
|
|
|
|
constraint);
|
2011-11-16 17:32:24 +00:00
|
|
|
}
|
|
|
|
|
|
2020-10-29 14:25:39 +01:00
|
|
|
void EndConstraintInitialPropagation(Constraint* const constraint) override {
|
2016-07-28 10:15:46 -07:00
|
|
|
ForAll(monitors_, &PropagationMonitor::EndConstraintInitialPropagation,
|
|
|
|
|
constraint);
|
2011-11-16 17:32:24 +00:00
|
|
|
}
|
|
|
|
|
|
2020-10-22 23:36:58 +02:00
|
|
|
void BeginNestedConstraintInitialPropagation(
|
2020-10-29 14:25:39 +01:00
|
|
|
Constraint* const parent, Constraint* const nested) override {
|
2016-07-28 10:15:46 -07:00
|
|
|
ForAll(monitors_,
|
|
|
|
|
&PropagationMonitor::BeginNestedConstraintInitialPropagation, parent,
|
|
|
|
|
nested);
|
2011-11-16 17:32:24 +00:00
|
|
|
}
|
|
|
|
|
|
2020-10-22 23:36:58 +02:00
|
|
|
void EndNestedConstraintInitialPropagation(
|
2020-10-29 14:25:39 +01:00
|
|
|
Constraint* const parent, Constraint* const nested) override {
|
2016-07-28 10:15:46 -07:00
|
|
|
ForAll(monitors_,
|
|
|
|
|
&PropagationMonitor::EndNestedConstraintInitialPropagation, parent,
|
|
|
|
|
nested);
|
2011-11-16 17:32:24 +00:00
|
|
|
}
|
|
|
|
|
|
2020-10-29 14:25:39 +01:00
|
|
|
void RegisterDemon(Demon* const demon) override {
|
2016-07-28 10:15:46 -07:00
|
|
|
ForAll(monitors_, &PropagationMonitor::RegisterDemon, demon);
|
2011-11-16 17:32:24 +00:00
|
|
|
}
|
|
|
|
|
|
2020-10-29 14:25:39 +01:00
|
|
|
void BeginDemonRun(Demon* const demon) override {
|
2016-07-28 10:15:46 -07:00
|
|
|
ForAll(monitors_, &PropagationMonitor::BeginDemonRun, demon);
|
2011-11-16 17:32:24 +00:00
|
|
|
}
|
|
|
|
|
|
2020-10-29 14:25:39 +01:00
|
|
|
void EndDemonRun(Demon* const demon) override {
|
2016-07-28 10:15:46 -07:00
|
|
|
ForAll(monitors_, &PropagationMonitor::EndDemonRun, demon);
|
2011-11-16 17:32:24 +00:00
|
|
|
}
|
|
|
|
|
|
2020-10-29 14:25:39 +01:00
|
|
|
void StartProcessingIntegerVariable(IntVar* const var) override {
|
2016-07-28 10:15:46 -07:00
|
|
|
ForAll(monitors_, &PropagationMonitor::StartProcessingIntegerVariable, var);
|
2012-08-06 23:39:19 +00:00
|
|
|
}
|
|
|
|
|
|
2020-10-29 14:25:39 +01:00
|
|
|
void EndProcessingIntegerVariable(IntVar* const var) override {
|
2016-07-28 10:15:46 -07:00
|
|
|
ForAll(monitors_, &PropagationMonitor::EndProcessingIntegerVariable, var);
|
2012-08-06 23:39:19 +00:00
|
|
|
}
|
|
|
|
|
|
2020-10-29 14:25:39 +01:00
|
|
|
void PushContext(const std::string& context) override {
|
2016-07-28 10:15:46 -07:00
|
|
|
ForAll(monitors_, &PropagationMonitor::PushContext, context);
|
2011-11-19 01:59:37 +00:00
|
|
|
}
|
|
|
|
|
|
2015-04-16 15:49:51 +02:00
|
|
|
void PopContext() override {
|
2016-07-28 10:15:46 -07:00
|
|
|
ForAll(monitors_, &PropagationMonitor::PopContext);
|
2011-11-19 01:59:37 +00:00
|
|
|
}
|
|
|
|
|
|
2011-11-16 17:32:24 +00:00
|
|
|
// IntExpr modifiers.
|
2021-04-01 12:13:35 +02:00
|
|
|
void SetMin(IntExpr* const expr, int64_t new_min) override {
|
2020-10-29 14:25:39 +01:00
|
|
|
for (PropagationMonitor* const monitor : monitors_) {
|
2016-07-28 10:15:46 -07:00
|
|
|
monitor->SetMin(expr, new_min);
|
2011-11-16 17:32:24 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-04-01 12:13:35 +02:00
|
|
|
void SetMax(IntExpr* const expr, int64_t new_max) override {
|
2020-10-29 14:25:39 +01:00
|
|
|
for (PropagationMonitor* const monitor : monitors_) {
|
2016-07-28 10:15:46 -07:00
|
|
|
monitor->SetMax(expr, new_max);
|
2011-11-16 17:32:24 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-04-01 12:13:35 +02:00
|
|
|
void SetRange(IntExpr* const expr, int64_t new_min,
|
|
|
|
|
int64_t new_max) override {
|
2020-10-29 14:25:39 +01:00
|
|
|
for (PropagationMonitor* const monitor : monitors_) {
|
2016-07-28 10:15:46 -07:00
|
|
|
monitor->SetRange(expr, new_min, new_max);
|
2011-11-16 17:32:24 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// IntVar modifiers.
|
2021-04-01 12:13:35 +02:00
|
|
|
void SetMin(IntVar* const var, int64_t new_min) override {
|
2020-10-29 14:25:39 +01:00
|
|
|
for (PropagationMonitor* const monitor : monitors_) {
|
2016-07-28 10:15:46 -07:00
|
|
|
monitor->SetMin(var, new_min);
|
2011-11-16 17:32:24 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-04-01 12:13:35 +02:00
|
|
|
void SetMax(IntVar* const var, int64_t new_max) override {
|
2020-10-29 14:25:39 +01:00
|
|
|
for (PropagationMonitor* const monitor : monitors_) {
|
2016-07-28 10:15:46 -07:00
|
|
|
monitor->SetMax(var, new_max);
|
2011-11-16 17:32:24 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-04-01 12:13:35 +02:00
|
|
|
void SetRange(IntVar* const var, int64_t new_min, int64_t new_max) override {
|
2020-10-29 14:25:39 +01:00
|
|
|
for (PropagationMonitor* const monitor : monitors_) {
|
2016-07-28 10:15:46 -07:00
|
|
|
monitor->SetRange(var, new_min, new_max);
|
2011-11-16 17:32:24 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-04-01 12:13:35 +02:00
|
|
|
void RemoveValue(IntVar* const var, int64_t value) override {
|
2016-07-28 10:15:46 -07:00
|
|
|
ForAll(monitors_, &PropagationMonitor::RemoveValue, var, value);
|
2011-11-16 17:32:24 +00:00
|
|
|
}
|
|
|
|
|
|
2021-04-01 12:13:35 +02:00
|
|
|
void SetValue(IntVar* const var, int64_t value) override {
|
2016-07-28 10:15:46 -07:00
|
|
|
ForAll(monitors_, &PropagationMonitor::SetValue, var, value);
|
2011-11-16 17:32:24 +00:00
|
|
|
}
|
|
|
|
|
|
2021-04-01 12:13:35 +02:00
|
|
|
void RemoveInterval(IntVar* const var, int64_t imin, int64_t imax) override {
|
2016-07-28 10:15:46 -07:00
|
|
|
ForAll(monitors_, &PropagationMonitor::RemoveInterval, var, imin, imax);
|
2011-11-16 17:32:24 +00:00
|
|
|
}
|
|
|
|
|
|
2021-04-01 12:13:35 +02:00
|
|
|
void SetValues(IntVar* const var,
|
|
|
|
|
const std::vector<int64_t>& values) override {
|
2016-07-28 10:15:46 -07:00
|
|
|
ForAll(monitors_, &PropagationMonitor::SetValues, var, values);
|
2011-11-16 17:32:24 +00:00
|
|
|
}
|
|
|
|
|
|
2020-10-29 14:25:39 +01:00
|
|
|
void RemoveValues(IntVar* const var,
|
2021-04-01 12:13:35 +02:00
|
|
|
const std::vector<int64_t>& values) override {
|
2016-07-28 10:15:46 -07:00
|
|
|
ForAll(monitors_, &PropagationMonitor::RemoveValues, var, values);
|
2011-11-16 17:32:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// IntervalVar modifiers.
|
2021-04-01 12:13:35 +02:00
|
|
|
void SetStartMin(IntervalVar* const var, int64_t new_min) override {
|
2016-07-28 10:15:46 -07:00
|
|
|
ForAll(monitors_, &PropagationMonitor::SetStartMin, var, new_min);
|
2011-11-16 17:32:24 +00:00
|
|
|
}
|
|
|
|
|
|
2021-04-01 12:13:35 +02:00
|
|
|
void SetStartMax(IntervalVar* const var, int64_t new_max) override {
|
2016-07-28 10:15:46 -07:00
|
|
|
ForAll(monitors_, &PropagationMonitor::SetStartMax, var, new_max);
|
2011-11-16 17:32:24 +00:00
|
|
|
}
|
|
|
|
|
|
2021-04-01 12:13:35 +02:00
|
|
|
void SetStartRange(IntervalVar* const var, int64_t new_min,
|
|
|
|
|
int64_t new_max) override {
|
2016-07-28 10:15:46 -07:00
|
|
|
ForAll(monitors_, &PropagationMonitor::SetStartRange, var, new_min,
|
|
|
|
|
new_max);
|
2011-11-16 17:32:24 +00:00
|
|
|
}
|
|
|
|
|
|
2021-04-01 12:13:35 +02:00
|
|
|
void SetEndMin(IntervalVar* const var, int64_t new_min) override {
|
2016-07-28 10:15:46 -07:00
|
|
|
ForAll(monitors_, &PropagationMonitor::SetEndMin, var, new_min);
|
2011-11-16 17:32:24 +00:00
|
|
|
}
|
|
|
|
|
|
2021-04-01 12:13:35 +02:00
|
|
|
void SetEndMax(IntervalVar* const var, int64_t new_max) override {
|
2016-07-28 10:15:46 -07:00
|
|
|
ForAll(monitors_, &PropagationMonitor::SetEndMax, var, new_max);
|
2011-11-16 17:32:24 +00:00
|
|
|
}
|
|
|
|
|
|
2021-04-01 12:13:35 +02:00
|
|
|
void SetEndRange(IntervalVar* const var, int64_t new_min,
|
|
|
|
|
int64_t new_max) override {
|
2016-07-28 10:15:46 -07:00
|
|
|
ForAll(monitors_, &PropagationMonitor::SetEndRange, var, new_min, new_max);
|
2011-11-16 17:32:24 +00:00
|
|
|
}
|
|
|
|
|
|
2021-04-01 12:13:35 +02:00
|
|
|
void SetDurationMin(IntervalVar* const var, int64_t new_min) override {
|
2016-07-28 10:15:46 -07:00
|
|
|
ForAll(monitors_, &PropagationMonitor::SetDurationMin, var, new_min);
|
2011-11-16 17:32:24 +00:00
|
|
|
}
|
|
|
|
|
|
2021-04-01 12:13:35 +02:00
|
|
|
void SetDurationMax(IntervalVar* const var, int64_t new_max) override {
|
2016-07-28 10:15:46 -07:00
|
|
|
ForAll(monitors_, &PropagationMonitor::SetDurationMax, var, new_max);
|
2011-11-16 17:32:24 +00:00
|
|
|
}
|
|
|
|
|
|
2021-04-01 12:13:35 +02:00
|
|
|
void SetDurationRange(IntervalVar* const var, int64_t new_min,
|
|
|
|
|
int64_t new_max) override {
|
2016-07-28 10:15:46 -07:00
|
|
|
ForAll(monitors_, &PropagationMonitor::SetDurationRange, var, new_min,
|
|
|
|
|
new_max);
|
2011-11-16 17:32:24 +00:00
|
|
|
}
|
|
|
|
|
|
2020-10-29 14:25:39 +01:00
|
|
|
void SetPerformed(IntervalVar* const var, bool value) override {
|
2016-07-28 10:15:46 -07:00
|
|
|
ForAll(monitors_, &PropagationMonitor::SetPerformed, var, value);
|
2011-11-16 17:32:24 +00:00
|
|
|
}
|
|
|
|
|
|
2020-10-29 14:25:39 +01:00
|
|
|
void RankFirst(SequenceVar* const var, int index) override {
|
2016-07-28 10:15:46 -07:00
|
|
|
ForAll(monitors_, &PropagationMonitor::RankFirst, var, index);
|
2011-11-21 02:52:58 +00:00
|
|
|
}
|
|
|
|
|
|
2020-10-29 14:25:39 +01:00
|
|
|
void RankNotFirst(SequenceVar* const var, int index) override {
|
2016-07-28 10:15:46 -07:00
|
|
|
ForAll(monitors_, &PropagationMonitor::RankNotFirst, var, index);
|
2011-11-21 02:52:58 +00:00
|
|
|
}
|
|
|
|
|
|
2020-10-29 14:25:39 +01:00
|
|
|
void RankLast(SequenceVar* const var, int index) override {
|
2016-07-28 10:15:46 -07:00
|
|
|
ForAll(monitors_, &PropagationMonitor::RankLast, var, index);
|
2011-12-16 21:02:59 +00:00
|
|
|
}
|
|
|
|
|
|
2020-10-29 14:25:39 +01:00
|
|
|
void RankNotLast(SequenceVar* const var, int index) override {
|
2016-07-28 10:15:46 -07:00
|
|
|
ForAll(monitors_, &PropagationMonitor::RankNotLast, var, index);
|
2011-12-16 21:02:59 +00:00
|
|
|
}
|
|
|
|
|
|
2020-10-29 14:25:39 +01:00
|
|
|
void RankSequence(SequenceVar* const var, const std::vector<int>& rank_first,
|
|
|
|
|
const std::vector<int>& rank_last,
|
|
|
|
|
const std::vector<int>& unperformed) override {
|
2016-07-28 10:15:46 -07:00
|
|
|
ForAll(monitors_, &PropagationMonitor::RankSequence, var, rank_first,
|
|
|
|
|
rank_last, unperformed);
|
2011-12-16 21:02:59 +00:00
|
|
|
}
|
|
|
|
|
|
2011-11-19 01:59:37 +00:00
|
|
|
// Does not take ownership of monitor.
|
2020-10-29 14:25:39 +01:00
|
|
|
void Add(PropagationMonitor* const monitor) {
|
2013-10-10 15:23:20 +00:00
|
|
|
if (monitor != nullptr) {
|
2011-11-16 17:32:24 +00:00
|
|
|
monitors_.push_back(monitor);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// The trace will dispatch propagation events. It needs to listen to search
|
|
|
|
|
// events.
|
2015-04-16 15:49:51 +02:00
|
|
|
void Install() override { SearchMonitor::Install(); }
|
2011-11-16 17:32:24 +00:00
|
|
|
|
2015-04-16 15:49:51 +02:00
|
|
|
std::string DebugString() const override { return "Trace"; }
|
2012-08-14 18:00:08 +00:00
|
|
|
|
2020-10-22 23:36:58 +02:00
|
|
|
private:
|
2020-10-29 14:25:39 +01:00
|
|
|
std::vector<PropagationMonitor*> monitors_;
|
2011-11-16 17:32:24 +00:00
|
|
|
};
|
|
|
|
|
|
2020-10-29 14:25:39 +01:00
|
|
|
PropagationMonitor* BuildTrace(Solver* const s) { return new Trace(s); }
|
2011-11-16 17:32:24 +00:00
|
|
|
|
2020-10-29 14:25:39 +01:00
|
|
|
void Solver::AddPropagationMonitor(PropagationMonitor* const monitor) {
|
2011-11-16 17:32:24 +00:00
|
|
|
// TODO(user): Check solver state?
|
2020-10-29 14:25:39 +01:00
|
|
|
reinterpret_cast<class Trace*>(propagation_monitor_.get())->Add(monitor);
|
2011-11-16 17:32:24 +00:00
|
|
|
}
|
|
|
|
|
|
2020-10-29 14:25:39 +01:00
|
|
|
PropagationMonitor* Solver::GetPropagationMonitor() const {
|
2011-11-16 17:32:24 +00:00
|
|
|
return propagation_monitor_.get();
|
|
|
|
|
}
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2022-06-21 11:43:36 +02:00
|
|
|
// ---------- Local Search Monitor Primary ----------
|
2016-07-28 10:15:46 -07:00
|
|
|
|
2022-06-21 11:43:36 +02:00
|
|
|
class LocalSearchMonitorPrimary : public LocalSearchMonitor {
|
2020-10-22 23:36:58 +02:00
|
|
|
public:
|
2022-06-21 11:43:36 +02:00
|
|
|
explicit LocalSearchMonitorPrimary(Solver* solver)
|
2016-07-28 10:15:46 -07:00
|
|
|
: LocalSearchMonitor(solver) {}
|
|
|
|
|
|
|
|
|
|
void BeginOperatorStart() override {
|
|
|
|
|
ForAll(monitors_, &LocalSearchMonitor::BeginOperatorStart);
|
|
|
|
|
}
|
|
|
|
|
void EndOperatorStart() override {
|
|
|
|
|
ForAll(monitors_, &LocalSearchMonitor::EndOperatorStart);
|
|
|
|
|
}
|
2020-10-29 14:25:39 +01:00
|
|
|
void BeginMakeNextNeighbor(const LocalSearchOperator* op) override {
|
2016-07-28 10:15:46 -07:00
|
|
|
ForAll(monitors_, &LocalSearchMonitor::BeginMakeNextNeighbor, op);
|
|
|
|
|
}
|
2020-10-29 14:25:39 +01:00
|
|
|
void EndMakeNextNeighbor(const LocalSearchOperator* op, bool neighbor_found,
|
|
|
|
|
const Assignment* delta,
|
|
|
|
|
const Assignment* deltadelta) override {
|
2016-07-28 10:15:46 -07:00
|
|
|
ForAll(monitors_, &LocalSearchMonitor::EndMakeNextNeighbor, op,
|
|
|
|
|
neighbor_found, delta, deltadelta);
|
|
|
|
|
}
|
2020-10-29 14:25:39 +01:00
|
|
|
void BeginFilterNeighbor(const LocalSearchOperator* op) override {
|
2016-07-28 10:15:46 -07:00
|
|
|
ForAll(monitors_, &LocalSearchMonitor::BeginFilterNeighbor, op);
|
|
|
|
|
}
|
2020-10-29 14:25:39 +01:00
|
|
|
void EndFilterNeighbor(const LocalSearchOperator* op,
|
2020-10-22 23:36:58 +02:00
|
|
|
bool neighbor_found) override {
|
2016-07-28 10:15:46 -07:00
|
|
|
ForAll(monitors_, &LocalSearchMonitor::EndFilterNeighbor, op,
|
|
|
|
|
neighbor_found);
|
|
|
|
|
}
|
2020-10-29 14:25:39 +01:00
|
|
|
void BeginAcceptNeighbor(const LocalSearchOperator* op) override {
|
2016-07-28 10:15:46 -07:00
|
|
|
ForAll(monitors_, &LocalSearchMonitor::BeginAcceptNeighbor, op);
|
|
|
|
|
}
|
2020-10-29 14:25:39 +01:00
|
|
|
void EndAcceptNeighbor(const LocalSearchOperator* op,
|
2020-10-22 23:36:58 +02:00
|
|
|
bool neighbor_found) override {
|
2016-07-28 10:15:46 -07:00
|
|
|
ForAll(monitors_, &LocalSearchMonitor::EndAcceptNeighbor, op,
|
|
|
|
|
neighbor_found);
|
|
|
|
|
}
|
2020-10-29 14:25:39 +01:00
|
|
|
void BeginFiltering(const LocalSearchFilter* filter) override {
|
2017-03-28 16:10:01 +02:00
|
|
|
ForAll(monitors_, &LocalSearchMonitor::BeginFiltering, filter);
|
|
|
|
|
}
|
2020-10-29 14:25:39 +01:00
|
|
|
void EndFiltering(const LocalSearchFilter* filter, bool reject) override {
|
2017-03-28 16:10:01 +02:00
|
|
|
ForAll(monitors_, &LocalSearchMonitor::EndFiltering, filter, reject);
|
|
|
|
|
}
|
2023-12-01 10:32:14 +01:00
|
|
|
bool IsActive() const override { return !monitors_.empty(); }
|
2016-07-28 10:15:46 -07:00
|
|
|
|
|
|
|
|
// Does not take ownership of monitor.
|
2020-10-29 14:25:39 +01:00
|
|
|
void Add(LocalSearchMonitor* monitor) {
|
2016-07-28 10:15:46 -07:00
|
|
|
if (monitor != nullptr) {
|
|
|
|
|
monitors_.push_back(monitor);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// The trace will dispatch propagation events. It needs to listen to search
|
|
|
|
|
// events.
|
|
|
|
|
void Install() override { SearchMonitor::Install(); }
|
|
|
|
|
|
2018-06-08 16:40:43 +02:00
|
|
|
std::string DebugString() const override {
|
2022-06-21 11:43:36 +02:00
|
|
|
return "LocalSearchMonitorPrimary";
|
2018-06-08 16:40:43 +02:00
|
|
|
}
|
2016-07-28 10:15:46 -07:00
|
|
|
|
2020-10-22 23:36:58 +02:00
|
|
|
private:
|
2020-10-29 14:25:39 +01:00
|
|
|
std::vector<LocalSearchMonitor*> monitors_;
|
2016-07-28 10:15:46 -07:00
|
|
|
};
|
|
|
|
|
|
2022-06-21 11:43:36 +02:00
|
|
|
LocalSearchMonitor* BuildLocalSearchMonitorPrimary(Solver* const s) {
|
|
|
|
|
return new LocalSearchMonitorPrimary(s);
|
2016-07-28 10:15:46 -07:00
|
|
|
}
|
|
|
|
|
|
2020-10-29 14:25:39 +01:00
|
|
|
void Solver::AddLocalSearchMonitor(LocalSearchMonitor* const monitor) {
|
2022-06-21 11:43:36 +02:00
|
|
|
reinterpret_cast<class LocalSearchMonitorPrimary*>(
|
|
|
|
|
local_search_monitor_.get())
|
2020-10-22 23:36:58 +02:00
|
|
|
->Add(monitor);
|
2016-07-28 10:15:46 -07:00
|
|
|
}
|
|
|
|
|
|
2020-10-29 14:25:39 +01:00
|
|
|
LocalSearchMonitor* Solver::GetLocalSearchMonitor() const {
|
2016-07-28 10:15:46 -07:00
|
|
|
return local_search_monitor_.get();
|
|
|
|
|
}
|
|
|
|
|
|
2020-10-29 14:25:39 +01:00
|
|
|
void Solver::SetSearchContext(Search* search,
|
2024-01-08 13:18:01 +01:00
|
|
|
absl::string_view search_context) {
|
2018-10-31 16:18:18 +01:00
|
|
|
search->set_search_context(search_context);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
std::string Solver::SearchContext() const {
|
|
|
|
|
return ActiveSearch()->search_context();
|
|
|
|
|
}
|
|
|
|
|
|
2020-10-29 14:25:39 +01:00
|
|
|
std::string Solver::SearchContext(const Search* search) const {
|
2018-10-31 16:18:18 +01:00
|
|
|
return search->search_context();
|
|
|
|
|
}
|
|
|
|
|
|
2020-10-29 14:25:39 +01:00
|
|
|
Assignment* Solver::GetOrCreateLocalSearchState() {
|
2019-03-15 17:17:02 +01:00
|
|
|
if (local_search_state_ == nullptr) {
|
2022-05-18 16:41:03 +02:00
|
|
|
local_search_state_ = std::make_unique<Assignment>(this);
|
2019-03-15 17:17:02 +01:00
|
|
|
}
|
|
|
|
|
return local_search_state_.get();
|
|
|
|
|
}
|
|
|
|
|
|
2021-12-05 12:15:27 +01:00
|
|
|
// ----------------- ProfiledDecisionBuilder ------------
|
|
|
|
|
|
|
|
|
|
ProfiledDecisionBuilder::ProfiledDecisionBuilder(DecisionBuilder* db)
|
|
|
|
|
: db_(db), name_(db_->GetName()), seconds_(0) {}
|
|
|
|
|
|
|
|
|
|
Decision* ProfiledDecisionBuilder::Next(Solver* const solver) {
|
|
|
|
|
timer_.Start();
|
2022-12-07 17:37:45 +01:00
|
|
|
solver->set_context(name());
|
2021-12-05 12:15:27 +01:00
|
|
|
// In case db_->Next() fails, gathering the running time on backtrack.
|
|
|
|
|
solver->AddBacktrackAction(
|
|
|
|
|
[this](Solver* solver) {
|
|
|
|
|
if (timer_.IsRunning()) {
|
|
|
|
|
timer_.Stop();
|
|
|
|
|
seconds_ += timer_.Get();
|
|
|
|
|
}
|
2022-12-07 17:37:45 +01:00
|
|
|
solver->set_context("");
|
2021-12-05 12:15:27 +01:00
|
|
|
},
|
|
|
|
|
true);
|
|
|
|
|
Decision* const decision = db_->Next(solver);
|
|
|
|
|
timer_.Stop();
|
|
|
|
|
seconds_ += timer_.Get();
|
|
|
|
|
return decision;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
std::string ProfiledDecisionBuilder::DebugString() const {
|
|
|
|
|
return db_->DebugString();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ProfiledDecisionBuilder::AppendMonitors(
|
|
|
|
|
Solver* const solver, std::vector<SearchMonitor*>* const extras) {
|
|
|
|
|
db_->AppendMonitors(solver, extras);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ProfiledDecisionBuilder::Accept(ModelVisitor* const visitor) const {
|
|
|
|
|
db_->Accept(visitor);
|
|
|
|
|
}
|
|
|
|
|
|
2010-09-15 12:42:33 +00:00
|
|
|
// ----------------- Constraint class -------------------
|
|
|
|
|
|
2013-12-16 10:24:42 +00:00
|
|
|
std::string Constraint::DebugString() const { return "Constraint"; }
|
2010-09-15 12:42:33 +00:00
|
|
|
|
|
|
|
|
void Constraint::PostAndPropagate() {
|
|
|
|
|
FreezeQueue();
|
|
|
|
|
Post();
|
|
|
|
|
InitialPropagate();
|
2014-05-22 17:37:21 +00:00
|
|
|
solver()->CheckFail();
|
2010-09-15 12:42:33 +00:00
|
|
|
UnfreezeQueue();
|
|
|
|
|
}
|
|
|
|
|
|
2020-10-29 14:25:39 +01:00
|
|
|
void Constraint::Accept(ModelVisitor* const visitor) const {
|
2011-07-11 20:13:14 +00:00
|
|
|
visitor->BeginVisitConstraint("unknown", this);
|
2013-01-10 17:01:34 +00:00
|
|
|
VLOG(3) << "Unknown constraint " << DebugString();
|
2011-07-11 20:13:14 +00:00
|
|
|
visitor->EndVisitConstraint("unknown", this);
|
|
|
|
|
}
|
|
|
|
|
|
2011-11-07 15:31:18 +00:00
|
|
|
bool Constraint::IsCastConstraint() const {
|
2021-12-05 12:15:27 +01:00
|
|
|
return solver()->cast_constraints_.contains(this);
|
2011-08-11 05:15:18 +00:00
|
|
|
}
|
|
|
|
|
|
2020-10-29 14:25:39 +01:00
|
|
|
IntVar* Constraint::Var() { return nullptr; }
|
2012-03-19 17:14:57 +00:00
|
|
|
|
2011-07-11 20:13:14 +00:00
|
|
|
// ----- Class IntExpr -----
|
|
|
|
|
|
2020-10-29 14:25:39 +01:00
|
|
|
void IntExpr::Accept(ModelVisitor* const visitor) const {
|
2011-07-11 20:13:14 +00:00
|
|
|
visitor->BeginVisitIntegerExpression("unknown", this);
|
2013-01-10 17:01:34 +00:00
|
|
|
VLOG(3) << "Unknown expression " << DebugString();
|
2011-07-11 20:13:14 +00:00
|
|
|
visitor->EndVisitIntegerExpression("unknown", this);
|
|
|
|
|
}
|
|
|
|
|
|
2020-10-22 23:36:58 +02:00
|
|
|
#undef CP_TRY // We no longer need those.
|
2010-09-16 15:34:10 +00:00
|
|
|
#undef CP_ON_FAIL
|
|
|
|
|
#undef CP_DO_FAIL
|
|
|
|
|
|
2020-10-22 23:36:58 +02:00
|
|
|
} // namespace operations_research
|