2025-01-10 11:35:44 +01:00
|
|
|
// Copyright 2010-2025 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
|
|
|
|
2025-11-07 18:15:22 +01:00
|
|
|
/** @file constraint_solver.h
|
2025-11-12 14:11:31 +01:00
|
|
|
Declaration of the core objects for the constraint solver.
|
|
|
|
|
|
|
|
|
|
The literature around constraint programming is extremely dense but one
|
|
|
|
|
can find some basic introductions in the following links:
|
|
|
|
|
- http://en.wikipedia.org/wiki/Constraint_programming
|
|
|
|
|
- http://kti.mff.cuni.cz/~bartak/constraints/index.html
|
|
|
|
|
|
|
|
|
|
Here is a very simple Constraint Programming problem:
|
|
|
|
|
|
|
|
|
|
If we see 56 legs and 20 heads, how many two-legged pheasants
|
|
|
|
|
and four-legged rabbits are we looking at?
|
|
|
|
|
|
|
|
|
|
Here is some simple Constraint Programming code to find out:
|
|
|
|
|
@code{.cpp}
|
|
|
|
|
void pheasant() {
|
|
|
|
|
Solver s("pheasant");
|
|
|
|
|
// Create integer variables to represent the number of pheasants and
|
|
|
|
|
// rabbits, with a minimum of 0 and a maximum of 20.
|
|
|
|
|
IntVar* const p = s.MakeIntVar(0, 20, "pheasant"));
|
|
|
|
|
IntVar* const r = s.MakeIntVar(0, 20, "rabbit"));
|
|
|
|
|
// The number of heads is the sum of pheasants and rabbits.
|
|
|
|
|
IntExpr* const heads = s.MakeSum(p, r);
|
|
|
|
|
// The number of legs is the sum of pheasants * 2 and rabbits * 4.
|
|
|
|
|
IntExpr* const legs = s.MakeSum(s.MakeProd(p, 2), s.MakeProd(r, 4));
|
|
|
|
|
// Constraints: the number of legs is 56 and heads is 20.
|
|
|
|
|
Constraint* const ct_legs = s.MakeEquality(legs, 56);
|
|
|
|
|
Constraint* const ct_heads = s.MakeEquality(heads, 20);
|
|
|
|
|
s.AddConstraint(ct_legs);
|
|
|
|
|
s.AddConstraint(ct_heads);
|
|
|
|
|
DecisionBuilder* const db = s.MakePhase(p, r,
|
|
|
|
|
Solver::CHOOSE_FIRST_UNBOUND,
|
|
|
|
|
Solver::ASSIGN_MIN_VALUE);
|
|
|
|
|
s.NewSearch(db);
|
|
|
|
|
CHECK(s.NextSolution());
|
|
|
|
|
LOG(INFO) << "rabbits -> " << r->Value() << ", pheasants -> "
|
|
|
|
|
<< p->Value();
|
|
|
|
|
LOG(INFO) << s.DebugString();
|
|
|
|
|
s.EndSearch();
|
|
|
|
|
}
|
|
|
|
|
@endcode
|
|
|
|
|
which outputs:
|
2025-11-07 18:15:22 +01:00
|
|
|
@verbatim
|
|
|
|
|
rabbits -> 8, pheasants -> 12
|
|
|
|
|
Solver(name = "pheasant",
|
|
|
|
|
state = OUTSIDE_SEARCH,
|
|
|
|
|
branches = 0,
|
|
|
|
|
fails = 0,
|
|
|
|
|
decisions = 0
|
|
|
|
|
propagation loops = 11,
|
|
|
|
|
demons Run = 25,
|
|
|
|
|
Run time = 0 ms)
|
|
|
|
|
@endverbatim
|
|
|
|
|
*/
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2025-11-05 11:34:49 +01:00
|
|
|
#ifndef ORTOOLS_CONSTRAINT_SOLVER_CONSTRAINT_SOLVER_H_
|
|
|
|
|
#define ORTOOLS_CONSTRAINT_SOLVER_CONSTRAINT_SOLVER_H_
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2021-04-01 12:13:35 +02:00
|
|
|
#include <stddef.h>
|
|
|
|
|
#include <stdint.h>
|
|
|
|
|
|
|
|
|
|
#include <deque>
|
2015-05-04 17:30:16 +02:00
|
|
|
#include <functional>
|
2015-08-13 16:00:54 +02:00
|
|
|
#include <memory>
|
2023-09-25 18:06:35 +02:00
|
|
|
#include <ostream>
|
2019-11-20 14:28:11 -08:00
|
|
|
#include <random>
|
2010-09-15 12:42:33 +00:00
|
|
|
#include <string>
|
2011-03-31 08:32:48 +00:00
|
|
|
#include <utility>
|
2011-05-09 08:30:19 +00:00
|
|
|
#include <vector>
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2021-12-05 12:15:27 +01:00
|
|
|
#include "absl/base/attributes.h"
|
2021-04-01 12:13:35 +02:00
|
|
|
#include "absl/base/log_severity.h"
|
2018-10-31 16:18:18 +01:00
|
|
|
#include "absl/container/flat_hash_map.h"
|
|
|
|
|
#include "absl/container/flat_hash_set.h"
|
2021-04-01 12:13:35 +02:00
|
|
|
#include "absl/flags/declare.h"
|
|
|
|
|
#include "absl/flags/flag.h"
|
2023-09-25 18:06:35 +02:00
|
|
|
#include "absl/log/check.h"
|
2019-11-20 14:28:11 -08:00
|
|
|
#include "absl/random/random.h"
|
2018-10-31 16:18:18 +01:00
|
|
|
#include "absl/strings/str_format.h"
|
2023-11-09 13:46:25 +01:00
|
|
|
#include "absl/strings/string_view.h"
|
2021-04-01 12:13:35 +02:00
|
|
|
#include "absl/time/time.h"
|
2023-09-25 18:06:35 +02:00
|
|
|
#include "absl/types/span.h"
|
2025-03-07 10:33:36 +01:00
|
|
|
#include "ortools/base/base_export.h"
|
2017-04-26 17:30:25 +02:00
|
|
|
#include "ortools/base/logging.h"
|
2018-06-08 16:40:43 +02:00
|
|
|
#include "ortools/base/map_util.h"
|
2017-04-26 17:30:25 +02:00
|
|
|
#include "ortools/base/timer.h"
|
2023-08-18 16:14:58 +02:00
|
|
|
#include "ortools/base/types.h"
|
2020-10-18 16:38:25 +02:00
|
|
|
#include "ortools/constraint_solver/search_stats.pb.h"
|
2017-04-26 17:30:25 +02:00
|
|
|
#include "ortools/constraint_solver/solver_parameters.pb.h"
|
|
|
|
|
#include "ortools/util/piecewise_linear_function.h"
|
2023-08-24 17:14:58 +02:00
|
|
|
#include "ortools/util/saturated_arithmetic.h"
|
2017-04-26 17:30:25 +02:00
|
|
|
#include "ortools/util/sorted_interval_list.h"
|
|
|
|
|
#include "ortools/util/tuple_set.h"
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2025-11-14 15:05:36 +01:00
|
|
|
#ifndef SWIG
|
2025-01-27 02:01:03 -08:00
|
|
|
OR_DLL ABSL_DECLARE_FLAG(int64_t, cp_random_seed);
|
|
|
|
|
OR_DLL ABSL_DECLARE_FLAG(bool, cp_disable_solve);
|
2025-11-14 15:05:36 +01:00
|
|
|
#endif // SWIG
|
2019-11-20 14:28:11 -08:00
|
|
|
|
2010-09-15 12:42:33 +00:00
|
|
|
class File;
|
2011-05-09 08:30:19 +00:00
|
|
|
|
2010-09-15 12:42:33 +00:00
|
|
|
namespace operations_research {
|
|
|
|
|
|
|
|
|
|
class Assignment;
|
|
|
|
|
class AssignmentProto;
|
|
|
|
|
class BaseObject;
|
2011-11-07 15:31:18 +00:00
|
|
|
class CastConstraint;
|
2011-09-21 15:16:48 +00:00
|
|
|
class Constraint;
|
2010-09-15 12:42:33 +00:00
|
|
|
class Decision;
|
|
|
|
|
class DecisionBuilder;
|
|
|
|
|
class DecisionVisitor;
|
|
|
|
|
class Demon;
|
2011-11-19 01:59:37 +00:00
|
|
|
class DemonProfiler;
|
2010-09-15 12:42:33 +00:00
|
|
|
class Dimension;
|
2012-07-18 19:54:04 +00:00
|
|
|
class DisjunctiveConstraint;
|
2021-04-01 12:13:35 +02:00
|
|
|
class ImprovementSearchLimit;
|
2010-09-15 12:42:33 +00:00
|
|
|
class IntExpr;
|
|
|
|
|
class IntVar;
|
2016-02-03 15:15:58 +01:00
|
|
|
class IntVarAssignment;
|
2021-04-01 12:13:35 +02:00
|
|
|
class IntVarLocalSearchFilter;
|
2011-05-09 08:30:19 +00:00
|
|
|
class IntervalVar;
|
2016-02-03 15:15:58 +01:00
|
|
|
class IntervalVarAssignment;
|
2023-09-25 18:06:35 +02:00
|
|
|
class LocalSearch;
|
2010-09-15 12:42:33 +00:00
|
|
|
class LocalSearchFilter;
|
2020-08-10 10:55:34 +02:00
|
|
|
class LocalSearchFilterManager;
|
2021-04-01 12:13:35 +02:00
|
|
|
class LocalSearchMonitor;
|
2010-09-15 12:42:33 +00:00
|
|
|
class LocalSearchOperator;
|
|
|
|
|
class LocalSearchPhaseParameters;
|
2021-04-01 12:13:35 +02:00
|
|
|
class LocalSearchProfiler;
|
2011-09-08 00:36:56 +00:00
|
|
|
class ModelCache;
|
2011-07-11 20:13:14 +00:00
|
|
|
class ModelVisitor;
|
2023-05-24 15:32:06 +02:00
|
|
|
class ObjectiveMonitor;
|
2024-11-18 11:32:13 +01:00
|
|
|
class BaseObjectiveMonitor;
|
2010-09-15 12:42:33 +00:00
|
|
|
class OptimizeVar;
|
|
|
|
|
class Pack;
|
2021-12-05 12:15:27 +01:00
|
|
|
class ProfiledDecisionBuilder;
|
2010-09-15 12:42:33 +00:00
|
|
|
class PropagationBaseObject;
|
2011-11-10 09:36:43 +00:00
|
|
|
class PropagationMonitor;
|
2010-09-15 12:42:33 +00:00
|
|
|
class Queue;
|
2019-04-11 09:39:02 -07:00
|
|
|
class RegularLimit;
|
|
|
|
|
class RegularLimitParameters;
|
2021-04-01 12:13:35 +02:00
|
|
|
class RevBitMatrix;
|
2010-09-15 12:42:33 +00:00
|
|
|
class Search;
|
|
|
|
|
class SearchLimit;
|
|
|
|
|
class SearchMonitor;
|
2011-11-03 10:27:53 +00:00
|
|
|
class SequenceVar;
|
2016-02-03 15:15:58 +01:00
|
|
|
class SequenceVarAssignment;
|
2010-09-15 12:42:33 +00:00
|
|
|
class SolutionCollector;
|
|
|
|
|
class SolutionPool;
|
|
|
|
|
class SymmetryBreaker;
|
2011-05-09 08:30:19 +00:00
|
|
|
struct StateInfo;
|
|
|
|
|
struct Trail;
|
2020-10-22 23:36:58 +02:00
|
|
|
template <class T>
|
|
|
|
|
class SimpleRevFIFO;
|
2022-09-05 18:30:09 +02:00
|
|
|
template <typename F>
|
|
|
|
|
class LightIntFunctionElementCt;
|
|
|
|
|
template <typename F>
|
|
|
|
|
class LightIntIntFunctionElementCt;
|
2024-11-18 11:32:13 +01:00
|
|
|
template <typename F>
|
|
|
|
|
class LightIntIntIntFunctionElementCt;
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2021-04-01 12:13:35 +02:00
|
|
|
inline int64_t CpRandomSeed() {
|
2020-10-21 00:21:54 +02:00
|
|
|
return absl::GetFlag(FLAGS_cp_random_seed) == -1
|
2021-04-01 12:13:35 +02:00
|
|
|
? absl::Uniform<int64_t>(absl::BitGen(), 0, kint64max)
|
2020-10-21 00:21:54 +02:00
|
|
|
: absl::GetFlag(FLAGS_cp_random_seed);
|
2019-11-20 14:28:11 -08:00
|
|
|
}
|
|
|
|
|
|
2025-11-14 15:05:36 +01:00
|
|
|
/// @brief This struct holds all parameters for the default search.
|
|
|
|
|
/// @details DefaultPhaseParameters is only used by Solver::MakeDefaultPhase
|
|
|
|
|
/// methods. Note this is for advanced users only.
|
2010-11-04 16:23:44 +00:00
|
|
|
struct DefaultPhaseParameters {
|
2020-10-22 23:36:58 +02:00
|
|
|
public:
|
2010-11-04 16:23:44 +00:00
|
|
|
enum VariableSelection {
|
2010-11-10 10:38:31 +00:00
|
|
|
CHOOSE_MAX_SUM_IMPACT = 0,
|
|
|
|
|
CHOOSE_MAX_AVERAGE_IMPACT = 1,
|
|
|
|
|
CHOOSE_MAX_VALUE_IMPACT = 2,
|
2010-11-04 16:23:44 +00:00
|
|
|
};
|
|
|
|
|
|
2014-07-09 11:10:20 +00:00
|
|
|
enum ValueSelection {
|
|
|
|
|
SELECT_MIN_IMPACT = 0,
|
|
|
|
|
SELECT_MAX_IMPACT = 1,
|
|
|
|
|
};
|
2010-11-04 16:23:44 +00:00
|
|
|
|
2020-10-22 23:36:58 +02:00
|
|
|
enum DisplayLevel { NONE = 0, NORMAL = 1, VERBOSE = 2 };
|
2011-03-21 12:57:08 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// This parameter describes how the next variable to instantiate
|
|
|
|
|
/// will be chosen.
|
2010-11-04 16:23:44 +00:00
|
|
|
VariableSelection var_selection_schema;
|
2011-11-07 15:31:18 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// This parameter describes which value to select for a given var.
|
2010-11-04 16:23:44 +00:00
|
|
|
ValueSelection value_selection_schema;
|
2011-11-07 15:31:18 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Maximum number of intervals that the initialization of impacts will scan
|
|
|
|
|
/// per variable.
|
2010-11-04 16:23:44 +00:00
|
|
|
int initialization_splits;
|
2011-11-07 15:31:18 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// The default phase will run heuristics periodically. This parameter
|
|
|
|
|
/// indicates if we should run all heuristics, or a randomly selected
|
|
|
|
|
/// one.
|
2010-11-04 16:23:44 +00:00
|
|
|
bool run_all_heuristics;
|
2011-11-07 15:31:18 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// The distance in nodes between each run of the heuristics. A
|
|
|
|
|
/// negative or null value will mean that we will not run heuristics
|
|
|
|
|
/// at all.
|
2010-11-10 10:38:31 +00:00
|
|
|
int heuristic_period;
|
2011-11-07 15:31:18 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// The failure limit for each heuristic that we run.
|
2010-11-10 10:38:31 +00:00
|
|
|
int heuristic_num_failures_limit;
|
2011-11-07 15:31:18 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Whether to keep the impact from the first search for other searches,
|
|
|
|
|
/// or to recompute the impact for each new search.
|
2011-03-21 12:57:08 +00:00
|
|
|
bool persistent_impact;
|
2011-11-07 15:31:18 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Seed used to initialize the random part in some heuristics.
|
2010-11-04 16:23:44 +00:00
|
|
|
int random_seed;
|
2011-11-07 15:31:18 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// This represents the amount of information displayed by the default search.
|
|
|
|
|
/// NONE means no display, VERBOSE means extra information.
|
2011-03-21 12:57:08 +00:00
|
|
|
DisplayLevel display_level;
|
2012-01-17 15:06:01 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Should we use last conflict method. The default is false.
|
2015-05-27 00:36:07 +02:00
|
|
|
bool use_last_conflict;
|
|
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// When defined, this overrides the default impact based decision builder.
|
2020-10-29 14:25:39 +01:00
|
|
|
DecisionBuilder* decision_builder;
|
2015-05-27 00:36:07 +02:00
|
|
|
|
|
|
|
|
DefaultPhaseParameters();
|
2010-11-04 16:23:44 +00:00
|
|
|
};
|
|
|
|
|
|
2025-11-14 15:05:36 +01:00
|
|
|
/** @brief Solver Class.
|
|
|
|
|
@details A solver represents the main computation engine. It implements the
|
|
|
|
|
entire range of Constraint Programming protocols:
|
|
|
|
|
- Reversibility
|
|
|
|
|
- Propagation
|
|
|
|
|
- Search
|
|
|
|
|
|
|
|
|
|
Usually, Constraint Programming code consists of
|
|
|
|
|
- the creation of the Solver,
|
|
|
|
|
- the creation of the decision variables of the model,
|
|
|
|
|
- the creation of the constraints of the model and their addition to the
|
|
|
|
|
solver() through the AddConstraint() method,
|
|
|
|
|
- the creation of the main DecisionBuilder class,
|
|
|
|
|
- the launch of the solve() method with the decision builder.
|
|
|
|
|
|
|
|
|
|
For the time being, Solver is neither MT_SAFE nor MT_HOT. */
|
2010-09-15 12:42:33 +00:00
|
|
|
class Solver {
|
2020-10-22 23:36:58 +02:00
|
|
|
public:
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Holds semantic information stating that the 'expression' has been
|
|
|
|
|
/// cast into 'variable' using the Var() method, and that
|
|
|
|
|
/// 'maintainer' is responsible for maintaining the equality between
|
|
|
|
|
/// 'variable' and 'expression'.
|
2011-11-07 15:31:18 +00:00
|
|
|
struct IntegerCastInfo {
|
2013-10-10 15:23:20 +00:00
|
|
|
IntegerCastInfo()
|
|
|
|
|
: variable(nullptr), expression(nullptr), maintainer(nullptr) {}
|
2020-10-29 14:25:39 +01:00
|
|
|
IntegerCastInfo(IntVar* const v, IntExpr* const e, Constraint* const c)
|
2011-11-07 15:31:18 +00:00
|
|
|
: variable(v), expression(e), maintainer(c) {}
|
2020-10-29 14:25:39 +01:00
|
|
|
IntVar* variable;
|
|
|
|
|
IntExpr* expression;
|
|
|
|
|
Constraint* maintainer;
|
2011-11-07 15:31:18 +00:00
|
|
|
};
|
|
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Number of priorities for demons.
|
2020-08-10 10:55:34 +02:00
|
|
|
static constexpr int kNumPriorities = 3;
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// This enum describes the strategy used to select the next branching
|
|
|
|
|
/// variable at each node during the search.
|
2010-09-15 12:42:33 +00:00
|
|
|
enum IntVarStrategy {
|
2019-07-05 00:25:55 +02:00
|
|
|
/// The default behavior is CHOOSE_FIRST_UNBOUND.
|
2010-09-15 12:42:33 +00:00
|
|
|
INT_VAR_DEFAULT,
|
2011-11-07 15:31:18 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// The simple selection is CHOOSE_FIRST_UNBOUND.
|
2010-09-15 12:42:33 +00:00
|
|
|
INT_VAR_SIMPLE,
|
2011-11-07 15:31:18 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Select the first unbound variable.
|
|
|
|
|
/// Variables are considered in the order of the vector of IntVars used
|
|
|
|
|
/// to create the selector.
|
2010-09-15 12:42:33 +00:00
|
|
|
CHOOSE_FIRST_UNBOUND,
|
2011-11-07 15:31:18 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Randomly select one of the remaining unbound variables.
|
2010-09-15 12:42:33 +00:00
|
|
|
CHOOSE_RANDOM,
|
2011-11-07 15:31:18 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Among unbound variables, select the variable with the smallest size,
|
|
|
|
|
/// i.e., the smallest number of possible values.
|
|
|
|
|
/// In case of a tie, the selected variables is the one with the lowest min
|
|
|
|
|
/// value.
|
|
|
|
|
/// In case of a tie, the first one is selected, first being defined by the
|
|
|
|
|
/// order in the vector of IntVars used to create the selector.
|
2010-09-15 12:42:33 +00:00
|
|
|
CHOOSE_MIN_SIZE_LOWEST_MIN,
|
2011-11-07 15:31:18 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Among unbound variables, select the variable with the smallest size,
|
|
|
|
|
/// i.e., the smallest number of possible values.
|
|
|
|
|
/// In case of a tie, the selected variable is the one with the highest min
|
|
|
|
|
/// value.
|
|
|
|
|
/// In case of a tie, the first one is selected, first being defined by the
|
|
|
|
|
/// order in the vector of IntVars used to create the selector.
|
2010-09-15 12:42:33 +00:00
|
|
|
CHOOSE_MIN_SIZE_HIGHEST_MIN,
|
2011-11-07 15:31:18 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Among unbound variables, select the variable with the smallest size,
|
|
|
|
|
/// i.e., the smallest number of possible values.
|
|
|
|
|
/// In case of a tie, the selected variables is the one with the lowest max
|
|
|
|
|
/// value.
|
|
|
|
|
/// In case of a tie, the first one is selected, first being defined by the
|
|
|
|
|
/// order in the vector of IntVars used to create the selector.
|
2010-09-15 12:42:33 +00:00
|
|
|
CHOOSE_MIN_SIZE_LOWEST_MAX,
|
2011-11-07 15:31:18 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Among unbound variables, select the variable with the smallest size,
|
|
|
|
|
/// i.e., the smallest number of possible values.
|
|
|
|
|
/// In case of a tie, the selected variable is the one with the highest max
|
|
|
|
|
/// value.
|
|
|
|
|
/// In case of a tie, the first one is selected, first being defined by the
|
|
|
|
|
/// order in the vector of IntVars used to create the selector.
|
2010-09-15 12:42:33 +00:00
|
|
|
CHOOSE_MIN_SIZE_HIGHEST_MAX,
|
2011-11-07 15:31:18 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Among unbound variables, select the variable with the smallest minimal
|
|
|
|
|
/// value.
|
|
|
|
|
/// In case of a tie, the first one is selected, "first" defined by the
|
|
|
|
|
/// order in the vector of IntVars used to create the selector.
|
2012-06-06 13:48:50 +00:00
|
|
|
CHOOSE_LOWEST_MIN,
|
|
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Among unbound variables, select the variable with the highest maximal
|
|
|
|
|
/// value.
|
|
|
|
|
/// In case of a tie, the first one is selected, first being defined by the
|
|
|
|
|
/// order in the vector of IntVars used to create the selector.
|
2012-06-06 13:48:50 +00:00
|
|
|
CHOOSE_HIGHEST_MAX,
|
|
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Among unbound variables, select the variable with the smallest size.
|
|
|
|
|
/// In case of a tie, the first one is selected, first being defined by the
|
|
|
|
|
/// order in the vector of IntVars used to create the selector.
|
2012-06-06 13:48:50 +00:00
|
|
|
CHOOSE_MIN_SIZE,
|
|
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Among unbound variables, select the variable with the highest size.
|
|
|
|
|
/// In case of a tie, the first one is selected, first being defined by the
|
|
|
|
|
/// order in the vector of IntVars used to create the selector.
|
2012-06-06 13:48:50 +00:00
|
|
|
CHOOSE_MAX_SIZE,
|
|
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Among unbound variables, select the variable with the largest
|
|
|
|
|
/// gap between the first and the second values of the domain.
|
2013-06-11 14:49:19 +00:00
|
|
|
CHOOSE_MAX_REGRET_ON_MIN,
|
2012-06-13 09:59:11 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Selects the next unbound variable on a path, the path being defined by
|
|
|
|
|
/// the variables: var[i] corresponds to the index of the next of i.
|
2010-09-15 12:42:33 +00:00
|
|
|
CHOOSE_PATH,
|
|
|
|
|
};
|
2013-06-11 14:49:19 +00:00
|
|
|
// TODO(user): add HIGHEST_MIN and LOWEST_MAX.
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// This enum describes the strategy used to select the next variable value to
|
|
|
|
|
/// set.
|
2010-09-15 12:42:33 +00:00
|
|
|
enum IntValueStrategy {
|
2019-07-05 00:25:55 +02:00
|
|
|
/// The default behavior is ASSIGN_MIN_VALUE.
|
2010-09-15 12:42:33 +00:00
|
|
|
INT_VALUE_DEFAULT,
|
2011-11-07 15:31:18 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// The simple selection is ASSIGN_MIN_VALUE.
|
2010-09-15 12:42:33 +00:00
|
|
|
INT_VALUE_SIMPLE,
|
2011-11-07 15:31:18 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Selects the min value of the selected variable.
|
2010-09-15 12:42:33 +00:00
|
|
|
ASSIGN_MIN_VALUE,
|
2011-11-07 15:31:18 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Selects the max value of the selected variable.
|
2010-09-15 12:42:33 +00:00
|
|
|
ASSIGN_MAX_VALUE,
|
2011-11-07 15:31:18 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Selects randomly one of the possible values of the selected variable.
|
2010-09-15 12:42:33 +00:00
|
|
|
ASSIGN_RANDOM_VALUE,
|
2011-11-07 15:31:18 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Selects the first possible value which is the closest to the center
|
|
|
|
|
/// of the domain of the selected variable.
|
|
|
|
|
/// The center is defined as (min + max) / 2.
|
2011-06-15 09:56:44 +00:00
|
|
|
ASSIGN_CENTER_VALUE,
|
2012-06-10 09:51:16 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Split the domain in two around the center, and choose the lower
|
|
|
|
|
/// part first.
|
2012-06-10 09:51:16 +00:00
|
|
|
SPLIT_LOWER_HALF,
|
|
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Split the domain in two around the center, and choose the lower
|
|
|
|
|
/// part first.
|
2012-06-10 09:51:16 +00:00
|
|
|
SPLIT_UPPER_HALF,
|
2010-09-15 12:42:33 +00:00
|
|
|
};
|
|
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// This enum is used by Solver::MakePhase to specify how to select variables
|
|
|
|
|
/// and values during the search.
|
|
|
|
|
/// In Solver::MakePhase(const std::vector<IntVar*>&, IntVarStrategy,
|
|
|
|
|
/// IntValueStrategy), variables are selected first, and then the associated
|
|
|
|
|
/// value.
|
|
|
|
|
/// In Solver::MakePhase(const std::vector<IntVar*>& vars, IndexEvaluator2,
|
|
|
|
|
/// EvaluatorStrategy), the selection is done scanning every pair
|
|
|
|
|
/// <variable, possible value>. The next selected pair is then the best among
|
|
|
|
|
/// all possibilities, i.e. the pair with the smallest evaluation.
|
|
|
|
|
/// As this is costly, two options are offered: static or dynamic evaluation.
|
2010-09-15 12:42:33 +00:00
|
|
|
enum EvaluatorStrategy {
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Pairs are compared at the first call of the selector, and results are
|
|
|
|
|
/// cached. Next calls to the selector use the previous computation, and so
|
|
|
|
|
/// are not up-to-date, e.g. some <variable, value> pairs may not be
|
|
|
|
|
/// possible anymore due to propagation since the first to call.
|
2010-09-15 12:42:33 +00:00
|
|
|
CHOOSE_STATIC_GLOBAL_BEST,
|
2011-11-07 15:31:18 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Pairs are compared each time a variable is selected. That way all pairs
|
|
|
|
|
/// are relevant and evaluation is accurate.
|
|
|
|
|
/// This strategy runs in O(number-of-pairs) at each variable selection,
|
|
|
|
|
/// versus O(1) in the static version.
|
2010-09-15 12:42:33 +00:00
|
|
|
CHOOSE_DYNAMIC_GLOBAL_BEST,
|
|
|
|
|
};
|
|
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Used for scheduling. Not yet implemented.
|
2010-09-15 12:42:33 +00:00
|
|
|
enum SequenceStrategy {
|
|
|
|
|
SEQUENCE_DEFAULT,
|
|
|
|
|
SEQUENCE_SIMPLE,
|
2011-11-03 10:27:53 +00:00
|
|
|
CHOOSE_MIN_SLACK_RANK_FORWARD,
|
2011-12-16 21:02:59 +00:00
|
|
|
CHOOSE_RANDOM_RANK_FORWARD,
|
2010-09-15 12:42:33 +00:00
|
|
|
};
|
|
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// This enum describes the straregy used to select the next interval variable
|
|
|
|
|
/// and its value to be fixed.
|
2010-09-15 12:42:33 +00:00
|
|
|
enum IntervalStrategy {
|
2019-07-05 00:25:55 +02:00
|
|
|
/// The default is INTERVAL_SET_TIMES_FORWARD.
|
2010-09-15 12:42:33 +00:00
|
|
|
INTERVAL_DEFAULT,
|
2019-07-05 00:25:55 +02:00
|
|
|
/// The simple is INTERVAL_SET_TIMES_FORWARD.
|
2010-09-15 12:42:33 +00:00
|
|
|
INTERVAL_SIMPLE,
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Selects the variable with the lowest starting time of all variables,
|
|
|
|
|
/// and fixes its starting time to this lowest value.
|
2014-01-17 18:36:18 +00:00
|
|
|
INTERVAL_SET_TIMES_FORWARD,
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Selects the variable with the highest ending time of all variables,
|
|
|
|
|
/// and fixes the ending time to this highest values.
|
2014-01-17 18:36:18 +00:00
|
|
|
INTERVAL_SET_TIMES_BACKWARD
|
2010-09-15 12:42:33 +00:00
|
|
|
};
|
|
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// This enum is used in Solver::MakeOperator to specify the neighborhood to
|
|
|
|
|
/// create.
|
2010-09-15 12:42:33 +00:00
|
|
|
enum LocalSearchOperators {
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Operator which reverses a sub-chain of a path. It is called TwoOpt
|
|
|
|
|
/// because it breaks two arcs on the path; resulting paths are called
|
|
|
|
|
/// two-optimal.
|
|
|
|
|
/// Possible neighbors for the path 1 -> 2 -> 3 -> 4 -> 5
|
|
|
|
|
/// (where (1, 5) are first and last nodes of the path and can therefore not
|
|
|
|
|
/// be moved):
|
2025-11-14 15:05:36 +01:00
|
|
|
/// @code
|
2019-07-05 00:25:55 +02:00
|
|
|
/// 1 -> [3 -> 2] -> 4 -> 5
|
|
|
|
|
/// 1 -> [4 -> 3 -> 2] -> 5
|
|
|
|
|
/// 1 -> 2 -> [4 -> 3] -> 5
|
2025-11-14 15:05:36 +01:00
|
|
|
/// @endcode
|
2010-09-15 12:42:33 +00:00
|
|
|
TWOOPT,
|
2011-11-07 15:31:18 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Relocate: OROPT and RELOCATE.
|
|
|
|
|
/// Operator which moves a sub-chain of a path to another position; the
|
|
|
|
|
/// specified chain length is the fixed length of the chains being moved.
|
|
|
|
|
/// When this length is 1, the operator simply moves a node to another
|
|
|
|
|
/// position.
|
|
|
|
|
/// Possible neighbors for the path 1 -> 2 -> 3 -> 4 -> 5, for a chain
|
|
|
|
|
/// length of 2 (where (1, 5) are first and last nodes of the path and can
|
|
|
|
|
/// therefore not be moved):
|
2025-11-14 15:05:36 +01:00
|
|
|
/// @code
|
2019-07-05 00:25:55 +02:00
|
|
|
/// 1 -> 4 -> [2 -> 3] -> 5
|
|
|
|
|
/// 1 -> [3 -> 4] -> 2 -> 5
|
2025-11-14 15:05:36 +01:00
|
|
|
/// @endcode
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Using Relocate with chain lengths of 1, 2 and 3 together is equivalent
|
|
|
|
|
/// to the OrOpt operator on a path. The OrOpt operator is a limited
|
|
|
|
|
/// version of 3Opt (breaks 3 arcs on a path).
|
2010-09-15 12:42:33 +00:00
|
|
|
OROPT,
|
2011-11-07 15:31:18 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Relocate neighborhood with length of 1 (see OROPT comment).
|
2010-09-15 12:42:33 +00:00
|
|
|
RELOCATE,
|
2011-11-07 15:31:18 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Operator which exchanges the positions of two nodes.
|
|
|
|
|
/// Possible neighbors for the path 1 -> 2 -> 3 -> 4 -> 5
|
|
|
|
|
/// (where (1, 5) are first and last nodes of the path and can therefore not
|
|
|
|
|
/// be moved):
|
2025-11-14 15:05:36 +01:00
|
|
|
/// @code
|
2019-07-05 00:25:55 +02:00
|
|
|
/// 1 -> [3] -> [2] -> 4 -> 5
|
|
|
|
|
/// 1 -> [4] -> 3 -> [2] -> 5
|
|
|
|
|
/// 1 -> 2 -> [4] -> [3] -> 5
|
2025-11-14 15:05:36 +01:00
|
|
|
/// @endcode
|
2010-09-15 12:42:33 +00:00
|
|
|
EXCHANGE,
|
2011-11-07 15:31:18 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Operator which cross exchanges the starting chains of 2 paths, including
|
|
|
|
|
/// exchanging the whole paths.
|
|
|
|
|
/// First and last nodes are not moved.
|
|
|
|
|
/// Possible neighbors for the paths 1 -> 2 -> 3 -> 4 -> 5 and 6 -> 7 -> 8
|
|
|
|
|
/// (where (1, 5) and (6, 8) are first and last nodes of the paths and can
|
|
|
|
|
/// therefore not be moved):
|
2025-11-14 15:05:36 +01:00
|
|
|
/// @code
|
2019-07-05 00:25:55 +02:00
|
|
|
/// 1 -> [7] -> 3 -> 4 -> 5 6 -> [2] -> 8
|
|
|
|
|
/// 1 -> [7] -> 4 -> 5 6 -> [2 -> 3] -> 8
|
|
|
|
|
/// 1 -> [7] -> 5 6 -> [2 -> 3 -> 4] -> 8
|
2025-11-14 15:05:36 +01:00
|
|
|
/// @endcode
|
2010-09-15 12:42:33 +00:00
|
|
|
CROSS,
|
2011-11-07 15:31:18 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Operator which inserts an inactive node into a path.
|
|
|
|
|
/// Possible neighbors for the path 1 -> 2 -> 3 -> 4 with 5 inactive
|
|
|
|
|
/// (where 1 and 4 are first and last nodes of the path) are:
|
2025-11-14 15:05:36 +01:00
|
|
|
/// @code
|
2019-07-05 00:25:55 +02:00
|
|
|
/// 1 -> [5] -> 2 -> 3 -> 4
|
|
|
|
|
/// 1 -> 2 -> [5] -> 3 -> 4
|
|
|
|
|
/// 1 -> 2 -> 3 -> [5] -> 4
|
2025-11-14 15:05:36 +01:00
|
|
|
/// @endcode
|
2010-09-15 12:42:33 +00:00
|
|
|
MAKEACTIVE,
|
2011-11-07 15:31:18 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Operator which makes path nodes inactive.
|
|
|
|
|
/// Possible neighbors for the path 1 -> 2 -> 3 -> 4 (where 1 and 4 are
|
|
|
|
|
/// first and last nodes of the path) are:
|
2025-11-14 15:05:36 +01:00
|
|
|
/// @code
|
2019-07-05 00:25:55 +02:00
|
|
|
/// 1 -> 3 -> 4 with 2 inactive
|
|
|
|
|
/// 1 -> 2 -> 4 with 3 inactive
|
2025-11-14 15:05:36 +01:00
|
|
|
/// @endcode
|
2010-09-15 12:42:33 +00:00
|
|
|
MAKEINACTIVE,
|
2011-11-07 15:31:18 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Operator which makes a "chain" of path nodes inactive.
|
|
|
|
|
/// Possible neighbors for the path 1 -> 2 -> 3 -> 4 (where 1 and 4 are
|
|
|
|
|
/// first and last nodes of the path) are:
|
2025-11-14 15:05:36 +01:00
|
|
|
/// @code
|
2019-07-05 00:25:55 +02:00
|
|
|
/// 1 -> 3 -> 4 with 2 inactive
|
|
|
|
|
/// 1 -> 2 -> 4 with 3 inactive
|
|
|
|
|
/// 1 -> 4 with 2 and 3 inactive
|
2025-11-14 15:05:36 +01:00
|
|
|
/// @endcode
|
2013-06-11 14:49:19 +00:00
|
|
|
MAKECHAININACTIVE,
|
|
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Operator which replaces an active node by an inactive one.
|
|
|
|
|
/// Possible neighbors for the path 1 -> 2 -> 3 -> 4 with 5 inactive
|
|
|
|
|
/// (where 1 and 4 are first and last nodes of the path) are:
|
2025-11-14 15:05:36 +01:00
|
|
|
/// @code
|
2019-07-05 00:25:55 +02:00
|
|
|
/// 1 -> [5] -> 3 -> 4 with 2 inactive
|
|
|
|
|
/// 1 -> 2 -> [5] -> 4 with 3 inactive
|
2025-11-14 15:05:36 +01:00
|
|
|
/// @endcode
|
2010-09-15 12:42:33 +00:00
|
|
|
SWAPACTIVE,
|
2011-11-07 15:31:18 +00:00
|
|
|
|
2024-11-18 11:32:13 +01:00
|
|
|
/// Operator which replaces a chain of active nodes by an inactive one.
|
|
|
|
|
/// Possible neighbors for the path 1 -> 2 -> 3 -> 4 with 5 inactive
|
|
|
|
|
/// (where 1 and 4 are first and last nodes of the path) are:
|
2025-11-14 15:05:36 +01:00
|
|
|
/// @code
|
2024-11-18 11:32:13 +01:00
|
|
|
/// 1 -> [5] -> 3 -> 4 with 2 inactive
|
|
|
|
|
/// 1 -> 2 -> [5] -> 4 with 3 inactive
|
|
|
|
|
/// 1 -> [5] -> 4 with 2 and 3 inactive
|
2025-11-14 15:05:36 +01:00
|
|
|
/// @endcode
|
2024-11-18 11:32:13 +01:00
|
|
|
SWAPACTIVECHAIN,
|
|
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Operator which makes an inactive node active and an active one inactive.
|
|
|
|
|
/// It is similar to SwapActiveOperator except that it tries to insert the
|
|
|
|
|
/// inactive node in all possible positions instead of just the position of
|
|
|
|
|
/// the node made inactive.
|
|
|
|
|
/// Possible neighbors for the path 1 -> 2 -> 3 -> 4 with 5 inactive
|
|
|
|
|
/// (where 1 and 4 are first and last nodes of the path) are:
|
2025-11-14 15:05:36 +01:00
|
|
|
/// @code
|
2019-07-05 00:25:55 +02:00
|
|
|
/// 1 -> [5] -> 3 -> 4 with 2 inactive
|
|
|
|
|
/// 1 -> 3 -> [5] -> 4 with 2 inactive
|
|
|
|
|
/// 1 -> [5] -> 2 -> 4 with 3 inactive
|
|
|
|
|
/// 1 -> 2 -> [5] -> 4 with 3 inactive
|
2025-11-14 15:05:36 +01:00
|
|
|
/// @endcode
|
2010-09-15 12:42:33 +00:00
|
|
|
EXTENDEDSWAPACTIVE,
|
2011-11-07 15:31:18 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Operator which relaxes two sub-chains of three consecutive arcs each.
|
|
|
|
|
/// Each sub-chain is defined by a start node and the next three arcs. Those
|
|
|
|
|
/// six arcs are relaxed to build a new neighbor.
|
|
|
|
|
/// PATHLNS explores all possible pairs of starting nodes and so defines
|
|
|
|
|
/// n^2 neighbors, n being the number of nodes.
|
|
|
|
|
/// Note that the two sub-chains can be part of the same path; they even may
|
|
|
|
|
/// overlap.
|
2010-09-15 12:42:33 +00:00
|
|
|
PATHLNS,
|
2011-11-07 15:31:18 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Operator which relaxes one entire path and all inactive nodes, thus
|
|
|
|
|
/// defining num_paths neighbors.
|
2013-07-10 12:28:21 +00:00
|
|
|
FULLPATHLNS,
|
|
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Operator which relaxes all inactive nodes and one sub-chain of six
|
|
|
|
|
/// consecutive arcs. That way the path can be improved by inserting
|
|
|
|
|
/// inactive nodes or swapping arcs.
|
2010-09-15 12:42:33 +00:00
|
|
|
UNACTIVELNS,
|
2011-11-07 15:31:18 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Operator which defines one neighbor per variable. Each neighbor tries to
|
|
|
|
|
/// increment by one the value of the corresponding variable. When a new
|
|
|
|
|
/// solution is found the neighborhood is rebuilt from scratch, i.e., tries
|
|
|
|
|
/// to increment values in the variable order.
|
|
|
|
|
/// Consider for instance variables x and y. x is incremented one by one to
|
|
|
|
|
/// its max, and when it is not possible to increment x anymore, y is
|
|
|
|
|
/// incremented once. If this is a solution, then next neighbor tries to
|
|
|
|
|
/// increment x.
|
2010-09-15 12:42:33 +00:00
|
|
|
INCREMENT,
|
2011-11-07 15:31:18 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Operator which defines a neighborhood to decrement values.
|
|
|
|
|
/// The behavior is the same as INCREMENT, except values are decremented
|
|
|
|
|
/// instead of incremented.
|
2010-09-15 12:42:33 +00:00
|
|
|
DECREMENT,
|
2011-11-07 15:31:18 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Operator which defines one neighbor per variable. Each neighbor relaxes
|
|
|
|
|
/// one variable.
|
|
|
|
|
/// When a new solution is found the neighborhood is rebuilt from scratch.
|
|
|
|
|
/// Consider for instance variables x and y. First x is relaxed and the
|
|
|
|
|
/// solver is looking for the best possible solution (with only x relaxed).
|
|
|
|
|
/// Then y is relaxed, and the solver is looking for a new solution.
|
|
|
|
|
/// If a new solution is found, then the next variable to be relaxed is x.
|
2010-09-15 12:42:33 +00:00
|
|
|
SIMPLELNS
|
|
|
|
|
};
|
|
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// This enum is used in Solver::MakeOperator associated with an evaluator
|
|
|
|
|
/// to specify the neighborhood to create.
|
2010-09-15 12:42:33 +00:00
|
|
|
enum EvaluatorLocalSearchOperators {
|
2019-11-14 13:38:48 -08:00
|
|
|
/// Lin-Kernighan local search.
|
2019-07-05 00:25:55 +02:00
|
|
|
/// While the accumulated local gain is positive, perform a 2opt or a 3opt
|
|
|
|
|
/// move followed by a series of 2opt moves. Return a neighbor for which the
|
|
|
|
|
/// global gain is positive.
|
2010-09-15 12:42:33 +00:00
|
|
|
LK,
|
2011-11-07 15:31:18 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Sliding TSP operator.
|
|
|
|
|
/// Uses an exact dynamic programming algorithm to solve the TSP
|
|
|
|
|
/// corresponding to path sub-chains.
|
|
|
|
|
/// For a subchain 1 -> 2 -> 3 -> 4 -> 5 -> 6, solves the TSP on
|
|
|
|
|
/// nodes A, 2, 3, 4, 5, where A is a merger of nodes 1 and 6 such that
|
|
|
|
|
/// cost(A,i) = cost(1,i) and cost(i,A) = cost(i,6).
|
2010-09-15 12:42:33 +00:00
|
|
|
TSPOPT,
|
2011-11-07 15:31:18 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// TSP-base LNS.
|
|
|
|
|
/// Randomly merge consecutive nodes until n "meta"-nodes remain and solve
|
|
|
|
|
/// the corresponding TSP.
|
|
|
|
|
/// This is an "unlimited" neighborhood which must be stopped by search
|
|
|
|
|
/// limits. To force diversification, the operator iteratively forces each
|
|
|
|
|
/// node to serve as base of a meta-node.
|
2010-09-15 12:42:33 +00:00
|
|
|
TSPLNS
|
|
|
|
|
};
|
|
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// This enum is used in Solver::MakeLocalSearchObjectiveFilter. It specifies
|
|
|
|
|
/// the behavior of the objective filter to create. The goal is to define
|
|
|
|
|
/// under which condition a move is accepted based on the current objective
|
|
|
|
|
/// value.
|
2010-09-15 12:42:33 +00:00
|
|
|
enum LocalSearchFilterBound {
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Move is accepted when the current objective value >= objective.Min.
|
2010-09-15 12:42:33 +00:00
|
|
|
GE,
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Move is accepted when the current objective value <= objective.Max.
|
2010-09-15 12:42:33 +00:00
|
|
|
LE,
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Move is accepted when the current objective value is in the interval
|
|
|
|
|
/// objective.Min .. objective.Max.
|
2010-09-15 12:42:33 +00:00
|
|
|
EQ
|
|
|
|
|
};
|
|
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// This enum represents the three possible priorities for a demon in the
|
|
|
|
|
/// Solver queue.
|
|
|
|
|
/// Note: this is for advanced users only.
|
2010-09-15 12:42:33 +00:00
|
|
|
enum DemonPriority {
|
2019-07-05 00:25:55 +02:00
|
|
|
/// DELAYED_PRIORITY is the lowest priority: Demons will be processed after
|
|
|
|
|
/// VAR_PRIORITY and NORMAL_PRIORITY demons.
|
2010-09-15 12:42:33 +00:00
|
|
|
DELAYED_PRIORITY = 0,
|
2011-11-07 15:31:18 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// VAR_PRIORITY is between DELAYED_PRIORITY and NORMAL_PRIORITY.
|
2010-09-15 12:42:33 +00:00
|
|
|
VAR_PRIORITY = 1,
|
2011-11-07 15:31:18 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// NORMAL_PRIORITY is the highest priority: Demons will be processed first.
|
2010-09-15 12:42:33 +00:00
|
|
|
NORMAL_PRIORITY = 2,
|
|
|
|
|
};
|
|
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// This enum is used in Solver::MakeIntervalVarRelation to specify the
|
|
|
|
|
/// temporal relation between the two intervals t1 and t2.
|
2010-09-15 12:42:33 +00:00
|
|
|
enum BinaryIntervalRelation {
|
2019-07-05 00:25:55 +02:00
|
|
|
/// t1 ends after t2 end, i.e. End(t1) >= End(t2) + delay.
|
2010-09-15 12:42:33 +00:00
|
|
|
ENDS_AFTER_END,
|
2011-11-07 15:31:18 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// t1 ends after t2 start, i.e. End(t1) >= Start(t2) + delay.
|
2010-09-15 12:42:33 +00:00
|
|
|
ENDS_AFTER_START,
|
2011-11-07 15:31:18 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// t1 ends at t2 end, i.e. End(t1) == End(t2) + delay.
|
2010-09-15 12:42:33 +00:00
|
|
|
ENDS_AT_END,
|
2011-11-07 15:31:18 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// t1 ends at t2 start, i.e. End(t1) == Start(t2) + delay.
|
2010-09-15 12:42:33 +00:00
|
|
|
ENDS_AT_START,
|
2011-11-07 15:31:18 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// t1 starts after t2 end, i.e. Start(t1) >= End(t2) + delay.
|
2010-09-15 12:42:33 +00:00
|
|
|
STARTS_AFTER_END,
|
2011-11-07 15:31:18 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// t1 starts after t2 start, i.e. Start(t1) >= Start(t2) + delay.
|
2010-09-15 12:42:33 +00:00
|
|
|
STARTS_AFTER_START,
|
2011-11-07 15:31:18 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// t1 starts at t2 end, i.e. Start(t1) == End(t2) + delay.
|
2010-09-15 12:42:33 +00:00
|
|
|
STARTS_AT_END,
|
2011-11-07 15:31:18 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// t1 starts at t2 start, i.e. Start(t1) == Start(t2) + delay.
|
2011-08-11 01:17:17 +00:00
|
|
|
STARTS_AT_START,
|
2011-11-07 15:31:18 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// STARTS_AT_START and ENDS_AT_END at the same time.
|
|
|
|
|
/// t1 starts at t2 start, i.e. Start(t1) == Start(t2) + delay.
|
|
|
|
|
/// t1 ends at t2 end, i.e. End(t1) == End(t2).
|
2011-08-11 01:17:17 +00:00
|
|
|
STAYS_IN_SYNC
|
2010-09-15 12:42:33 +00:00
|
|
|
};
|
|
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// This enum is used in Solver::MakeIntervalVarRelation to specify the
|
|
|
|
|
/// temporal relation between an interval t and an integer d.
|
2010-09-15 12:42:33 +00:00
|
|
|
enum UnaryIntervalRelation {
|
2019-07-05 00:25:55 +02:00
|
|
|
/// t ends after d, i.e. End(t) >= d.
|
2010-09-15 12:42:33 +00:00
|
|
|
ENDS_AFTER,
|
2011-11-07 15:31:18 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// t ends at d, i.e. End(t) == d.
|
2010-09-15 12:42:33 +00:00
|
|
|
ENDS_AT,
|
2011-11-07 15:31:18 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// t ends before d, i.e. End(t) <= d.
|
2010-09-15 12:42:33 +00:00
|
|
|
ENDS_BEFORE,
|
2011-11-07 15:31:18 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// t starts after d, i.e. Start(t) >= d.
|
2010-09-15 12:42:33 +00:00
|
|
|
STARTS_AFTER,
|
2011-11-07 15:31:18 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// t starts at d, i.e. Start(t) == d.
|
2010-09-15 12:42:33 +00:00
|
|
|
STARTS_AT,
|
2011-11-07 15:31:18 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// t starts before d, i.e. Start(t) <= d.
|
2010-09-15 12:42:33 +00:00
|
|
|
STARTS_BEFORE,
|
2011-11-07 15:31:18 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// STARTS_BEFORE and ENDS_AFTER at the same time, i.e. d is in t.
|
|
|
|
|
/// t starts before d, i.e. Start(t) <= d.
|
|
|
|
|
/// t ends after d, i.e. End(t) >= d.
|
2010-09-15 12:42:33 +00:00
|
|
|
CROSS_DATE,
|
2011-11-07 15:31:18 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// STARTS_AFTER or ENDS_BEFORE, i.e. d is not in t.
|
|
|
|
|
/// t starts after d, i.e. Start(t) >= d.
|
|
|
|
|
/// t ends before d, i.e. End(t) <= d.
|
2010-09-15 12:42:33 +00:00
|
|
|
AVOID_DATE
|
|
|
|
|
};
|
|
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// The Solver is responsible for creating the search tree. Thanks to the
|
|
|
|
|
/// DecisionBuilder, it creates a new decision with two branches at each node:
|
|
|
|
|
/// left and right.
|
|
|
|
|
/// The DecisionModification enum is used to specify how the branch selector
|
|
|
|
|
/// should behave.
|
2010-09-15 12:42:33 +00:00
|
|
|
enum DecisionModification {
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Keeps the default behavior, i.e. apply left branch first, and then right
|
|
|
|
|
/// branch in case of backtracking.
|
2010-09-15 12:42:33 +00:00
|
|
|
NO_CHANGE,
|
2011-11-07 15:31:18 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Right branches are ignored. This is used to make the code faster when
|
|
|
|
|
/// backtrack makes no sense or is not useful.
|
|
|
|
|
/// This is faster as there is no need to create one new node per decision.
|
2010-09-15 12:42:33 +00:00
|
|
|
KEEP_LEFT,
|
2011-11-07 15:31:18 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Left branches are ignored. This is used to make the code faster when
|
|
|
|
|
/// backtrack makes no sense or is not useful.
|
|
|
|
|
/// This is faster as there is no need to create one new node per decision.
|
2010-09-15 12:42:33 +00:00
|
|
|
KEEP_RIGHT,
|
2011-11-07 15:31:18 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Backtracks to the previous decisions, i.e. left and right branches are
|
|
|
|
|
/// not applied.
|
2010-09-15 12:42:33 +00:00
|
|
|
KILL_BOTH,
|
2011-11-07 15:31:18 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Applies right branch first. Left branch will be applied in case of
|
|
|
|
|
/// backtracking.
|
2010-09-15 12:42:33 +00:00
|
|
|
SWITCH_BRANCHES
|
|
|
|
|
};
|
|
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// This enum is used internally in private methods Solver::PushState and
|
|
|
|
|
/// Solver::PopState to tag states in the search tree.
|
2020-10-22 23:36:58 +02:00
|
|
|
enum MarkerType { SENTINEL, SIMPLE_MARKER, CHOICE_POINT, REVERSIBLE_ACTION };
|
2011-11-07 15:31:18 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// This enum represents the state of the solver w.r.t. the search.
|
2011-11-07 15:31:18 +00:00
|
|
|
enum SolverState {
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Before search, after search.
|
|
|
|
|
OUTSIDE_SEARCH,
|
|
|
|
|
/// Executing the root node.
|
|
|
|
|
IN_ROOT_NODE,
|
|
|
|
|
/// Executing the search code.
|
|
|
|
|
IN_SEARCH,
|
|
|
|
|
/// After successful NextSolution and before EndSearch.
|
|
|
|
|
AT_SOLUTION,
|
|
|
|
|
/// After failed NextSolution and before EndSearch.
|
|
|
|
|
NO_MORE_SOLUTIONS,
|
|
|
|
|
/// After search, the model is infeasible.
|
|
|
|
|
PROBLEM_INFEASIBLE
|
2011-11-07 15:31:18 +00:00
|
|
|
};
|
|
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Optimization directions.
|
2020-10-22 23:36:58 +02:00
|
|
|
enum OptimizationDirection { NOT_SET, MAXIMIZATION, MINIMIZATION };
|
2019-01-28 14:25:29 +01:00
|
|
|
|
2022-09-05 18:30:09 +02:00
|
|
|
#ifndef SWIG
|
|
|
|
|
/// Search monitor events.
|
|
|
|
|
enum class MonitorEvent : int {
|
|
|
|
|
kEnterSearch = 0,
|
|
|
|
|
kRestartSearch,
|
|
|
|
|
kExitSearch,
|
|
|
|
|
kBeginNextDecision,
|
|
|
|
|
kEndNextDecision,
|
|
|
|
|
kApplyDecision,
|
|
|
|
|
kRefuteDecision,
|
|
|
|
|
kAfterDecision,
|
|
|
|
|
kBeginFail,
|
|
|
|
|
kEndFail,
|
|
|
|
|
kBeginInitialPropagation,
|
|
|
|
|
kEndInitialPropagation,
|
|
|
|
|
kAcceptSolution,
|
|
|
|
|
kAtSolution,
|
|
|
|
|
kNoMoreSolutions,
|
|
|
|
|
kLocalOptimum,
|
|
|
|
|
kAcceptDelta,
|
|
|
|
|
kAcceptNeighbor,
|
|
|
|
|
kAcceptUncheckedNeighbor,
|
|
|
|
|
kIsUncheckedSolutionLimitReached,
|
|
|
|
|
kPeriodicCheck,
|
|
|
|
|
kProgressPercent,
|
|
|
|
|
kAccept,
|
|
|
|
|
// Dummy event whose underlying int is the number of MonitorEvent enums.
|
|
|
|
|
kLast,
|
|
|
|
|
};
|
|
|
|
|
#endif // SWIG
|
|
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Callback typedefs
|
2021-04-01 12:13:35 +02:00
|
|
|
typedef std::function<int64_t(int64_t)> IndexEvaluator1;
|
|
|
|
|
typedef std::function<int64_t(int64_t, int64_t)> IndexEvaluator2;
|
|
|
|
|
typedef std::function<int64_t(int64_t, int64_t, int64_t)> IndexEvaluator3;
|
2015-08-13 16:00:54 +02:00
|
|
|
|
2021-04-01 12:13:35 +02:00
|
|
|
typedef std::function<bool(int64_t)> IndexFilter1;
|
2015-08-13 16:00:54 +02:00
|
|
|
|
2021-04-01 12:13:35 +02:00
|
|
|
typedef std::function<IntVar*(int64_t)> Int64ToIntVar;
|
2015-10-23 13:45:43 +02:00
|
|
|
|
2021-04-11 11:29:32 +02:00
|
|
|
typedef std::function<int64_t(Solver* solver,
|
|
|
|
|
const std::vector<IntVar*>& vars,
|
|
|
|
|
int64_t first_unbound, int64_t last_unbound)>
|
2015-08-13 16:00:54 +02:00
|
|
|
VariableIndexSelector;
|
|
|
|
|
|
2021-04-11 11:29:32 +02:00
|
|
|
typedef std::function<int64_t(const IntVar* v, int64_t id)>
|
|
|
|
|
VariableValueSelector;
|
|
|
|
|
typedef std::function<bool(int64_t, int64_t, int64_t)>
|
|
|
|
|
VariableValueComparator;
|
2015-08-13 16:00:54 +02:00
|
|
|
typedef std::function<DecisionModification()> BranchSelector;
|
2015-10-23 13:45:43 +02:00
|
|
|
// TODO(user): wrap in swig.
|
2020-10-29 14:25:39 +01:00
|
|
|
typedef std::function<void(Solver*)> Action;
|
2015-10-23 13:45:43 +02:00
|
|
|
typedef std::function<void()> Closure;
|
2015-08-13 16:00:54 +02:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Solver API
|
2020-10-29 14:25:39 +01:00
|
|
|
explicit Solver(const std::string& name);
|
|
|
|
|
Solver(const std::string& name, const ConstraintSolverParameters& parameters);
|
2023-09-25 18:06:35 +02:00
|
|
|
|
|
|
|
|
#ifndef SWIG
|
|
|
|
|
// This type is neither copyable nor movable.
|
|
|
|
|
Solver(const Solver&) = delete;
|
|
|
|
|
Solver& operator=(const Solver&) = delete;
|
|
|
|
|
#endif
|
|
|
|
|
|
2010-09-15 12:42:33 +00:00
|
|
|
~Solver();
|
|
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Stored Parameters.
|
2016-02-03 15:15:58 +01:00
|
|
|
ConstraintSolverParameters parameters() const { return parameters_; }
|
2022-08-04 16:24:13 +02:00
|
|
|
// Read-only.
|
|
|
|
|
const ConstraintSolverParameters& const_parameters() const {
|
|
|
|
|
return parameters_;
|
|
|
|
|
}
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Create a ConstraintSolverParameters proto with all the default values.
|
2017-12-08 14:52:49 +01:00
|
|
|
// TODO(user): Move to constraint_solver_parameters.h.
|
2016-02-03 15:15:58 +01:00
|
|
|
static ConstraintSolverParameters DefaultSolverParameters();
|
2010-12-06 10:59:35 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// reversibility
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// SaveValue() saves the value of the corresponding object. It must be
|
|
|
|
|
/// called before modifying the object. The value will be restored upon
|
|
|
|
|
/// backtrack.
|
2020-10-22 23:36:58 +02:00
|
|
|
template <class T>
|
2020-10-29 14:25:39 +01:00
|
|
|
void SaveValue(T* o) {
|
2020-10-22 23:36:58 +02:00
|
|
|
InternalSaveValue(o);
|
|
|
|
|
}
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Registers the given object as being reversible. By calling this method,
|
|
|
|
|
/// the caller gives ownership of the object to the solver, which will
|
|
|
|
|
/// delete it when there is a backtrack out of the current state.
|
|
|
|
|
///
|
|
|
|
|
/// Returns the argument for convenience: this way, the caller may directly
|
|
|
|
|
/// invoke a constructor in the argument, without having to store the pointer
|
|
|
|
|
/// first.
|
|
|
|
|
///
|
|
|
|
|
/// This function is only for users that define their own subclasses of
|
|
|
|
|
/// BaseObject: for all subclasses predefined in the library, the
|
|
|
|
|
/// corresponding factory methods (e.g., MakeIntVar(...),
|
|
|
|
|
/// MakeAllDifferent(...) already take care of the registration.
|
2020-10-22 23:36:58 +02:00
|
|
|
template <typename T>
|
2020-10-29 14:25:39 +01:00
|
|
|
T* RevAlloc(T* object) {
|
|
|
|
|
return reinterpret_cast<T*>(SafeRevAlloc(object));
|
2010-09-15 12:42:33 +00:00
|
|
|
}
|
|
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Like RevAlloc() above, but for an array of objects: the array
|
|
|
|
|
/// must have been allocated with the new[] operator. The entire array
|
|
|
|
|
/// will be deleted when backtracking out of the current state.
|
|
|
|
|
///
|
2021-04-01 12:13:35 +02:00
|
|
|
/// This method is valid for arrays of int, int64_t, uint64_t, bool,
|
2019-07-05 00:25:55 +02:00
|
|
|
/// BaseObject*, IntVar*, IntExpr*, and Constraint*.
|
2020-10-22 23:36:58 +02:00
|
|
|
template <typename T>
|
2020-10-29 14:25:39 +01:00
|
|
|
T* RevAllocArray(T* object) {
|
|
|
|
|
return reinterpret_cast<T*>(SafeRevAllocArray(object));
|
2011-11-14 20:55:35 +00:00
|
|
|
}
|
|
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Adds the constraint 'c' to the model.
|
|
|
|
|
///
|
|
|
|
|
/// After calling this method, and until there is a backtrack that undoes the
|
|
|
|
|
/// addition, any assignment of variables to values must satisfy the given
|
|
|
|
|
/// constraint in order to be considered feasible. There are two fairly
|
|
|
|
|
/// different use cases:
|
|
|
|
|
///
|
|
|
|
|
/// - the most common use case is modeling: the given constraint is really
|
|
|
|
|
/// part of the problem that the user is trying to solve. In this use case,
|
2020-10-18 16:38:25 +02:00
|
|
|
/// AddConstraint is called outside of search (i.e., with <tt>state() ==
|
|
|
|
|
/// OUTSIDE_SEARCH</tt>). Most users should only use AddConstraint in this
|
2019-07-05 00:25:55 +02:00
|
|
|
/// way. In this case, the constraint will belong to the model forever: it
|
2023-08-24 17:14:58 +02:00
|
|
|
/// cannot be removed by backtracking.
|
2019-07-05 00:25:55 +02:00
|
|
|
///
|
|
|
|
|
/// - a rarer use case is that 'c' is not a real constraint of the model. It
|
|
|
|
|
/// may be a constraint generated by a branching decision (a constraint whose
|
|
|
|
|
/// goal is to restrict the search space), a symmetry breaking constraint (a
|
|
|
|
|
/// constraint that does restrict the search space, but in a way that cannot
|
|
|
|
|
/// have an impact on the quality of the solutions in the subtree), or an
|
|
|
|
|
/// inferred constraint that, while having no semantic value to the model (it
|
|
|
|
|
/// does not restrict the set of solutions), is worth having because we
|
|
|
|
|
/// believe it may strengthen the propagation. In these cases, it happens
|
|
|
|
|
/// that the constraint is added during the search (i.e., with state() ==
|
|
|
|
|
/// IN_SEARCH or state() == IN_ROOT_NODE). When a constraint is
|
|
|
|
|
/// added during a search, it applies only to the subtree of the search tree
|
|
|
|
|
/// rooted at the current node, and will be automatically removed by
|
|
|
|
|
/// backtracking.
|
|
|
|
|
///
|
|
|
|
|
/// This method does not take ownership of the constraint. If the constraint
|
|
|
|
|
/// has been created by any factory method (Solver::MakeXXX), it will
|
|
|
|
|
/// automatically be deleted. However, power users who implement their own
|
|
|
|
|
/// constraints should do: solver.AddConstraint(solver.RevAlloc(new
|
|
|
|
|
/// MyConstraint(...));
|
2023-05-31 14:27:08 +02:00
|
|
|
void AddConstraint(Constraint* c);
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Adds 'constraint' to the solver and marks it as a cast constraint, that
|
|
|
|
|
/// is, a constraint created calling Var() on an expression. This is used
|
|
|
|
|
/// internally.
|
2023-05-31 14:27:08 +02:00
|
|
|
void AddCastConstraint(CastConstraint* constraint, IntVar* target_var,
|
|
|
|
|
IntExpr* expr);
|
2011-11-07 15:31:18 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// @{
|
|
|
|
|
/// Solves the problem using the given DecisionBuilder and returns true if a
|
|
|
|
|
/// solution was found and accepted.
|
|
|
|
|
///
|
|
|
|
|
/// These methods are the ones most users should use to search for a solution.
|
|
|
|
|
/// Note that the definition of 'solution' is subtle. A solution here is
|
|
|
|
|
/// defined as a leaf of the search tree with respect to the given decision
|
|
|
|
|
/// builder for which there is no failure. What this means is that, contrary
|
|
|
|
|
/// to intuition, a solution may not have all variables of the model bound.
|
|
|
|
|
/// It is the responsibility of the decision builder to keep returning
|
|
|
|
|
/// decisions until all variables are indeed bound. The most extreme
|
|
|
|
|
/// counterexample is calling Solve with a trivial decision builder whose
|
|
|
|
|
/// Next() method always returns nullptr. In this case, Solve immediately
|
|
|
|
|
/// returns 'true', since not assigning any variable to any value is a
|
|
|
|
|
/// solution, unless the root node propagation discovers that the model is
|
|
|
|
|
/// infeasible.
|
|
|
|
|
///
|
|
|
|
|
/// This function must be called either from outside of search,
|
|
|
|
|
/// or from within the Next() method of a decision builder.
|
|
|
|
|
///
|
|
|
|
|
/// Solve will terminate whenever any of the following event arise:
|
|
|
|
|
/// * A search monitor asks the solver to terminate the search by calling
|
|
|
|
|
/// solver()->FinishCurrentSearch().
|
|
|
|
|
/// * A solution is found that is accepted by all search monitors, and none of
|
|
|
|
|
/// the search monitors decides to search for another one.
|
|
|
|
|
///
|
|
|
|
|
/// Upon search termination, there will be a series of backtracks all the way
|
|
|
|
|
/// to the top level. This means that a user cannot expect to inspect the
|
|
|
|
|
/// solution by querying variables after a call to Solve(): all the
|
|
|
|
|
/// information will be lost. In order to do something with the solution, the
|
|
|
|
|
/// user must either:
|
|
|
|
|
///
|
|
|
|
|
/// * Use a search monitor that can process such a leaf. See, in particular,
|
|
|
|
|
/// the SolutionCollector class.
|
|
|
|
|
/// * Do not use Solve. Instead, use the more fine-grained approach using
|
|
|
|
|
/// methods NewSearch(...), NextSolution(), and EndSearch().
|
|
|
|
|
///
|
|
|
|
|
/// @param db The decision builder that will generate the search tree.
|
|
|
|
|
/// @param monitors A vector of search monitors that will be notified of
|
|
|
|
|
/// various events during the search. In their reaction to these events, such
|
|
|
|
|
/// monitors may influence the search.
|
2023-05-31 14:27:08 +02:00
|
|
|
bool Solve(DecisionBuilder* db, const std::vector<SearchMonitor*>& monitors);
|
|
|
|
|
bool Solve(DecisionBuilder* db);
|
|
|
|
|
bool Solve(DecisionBuilder* db, SearchMonitor* m1);
|
|
|
|
|
bool Solve(DecisionBuilder* db, SearchMonitor* m1, SearchMonitor* m2);
|
|
|
|
|
bool Solve(DecisionBuilder* db, SearchMonitor* m1, SearchMonitor* m2,
|
|
|
|
|
SearchMonitor* m3);
|
|
|
|
|
bool Solve(DecisionBuilder* db, SearchMonitor* m1, SearchMonitor* m2,
|
|
|
|
|
SearchMonitor* m3, SearchMonitor* m4);
|
2019-07-05 00:25:55 +02:00
|
|
|
/// @}
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// @{
|
|
|
|
|
/// Decomposed search.
|
|
|
|
|
/// The code for a top level search should look like
|
|
|
|
|
/// solver->NewSearch(db);
|
|
|
|
|
/// while (solver->NextSolution()) {
|
|
|
|
|
/// //.. use the current solution
|
|
|
|
|
/// }
|
|
|
|
|
/// solver()->EndSearch();
|
2012-05-17 15:43:34 +00:00
|
|
|
|
2023-05-31 14:27:08 +02:00
|
|
|
void NewSearch(DecisionBuilder* db,
|
2020-10-29 14:25:39 +01:00
|
|
|
const std::vector<SearchMonitor*>& monitors);
|
2023-05-31 14:27:08 +02:00
|
|
|
void NewSearch(DecisionBuilder* db);
|
|
|
|
|
void NewSearch(DecisionBuilder* db, SearchMonitor* m1);
|
|
|
|
|
void NewSearch(DecisionBuilder* db, SearchMonitor* m1, SearchMonitor* m2);
|
|
|
|
|
void NewSearch(DecisionBuilder* db, SearchMonitor* m1, SearchMonitor* m2,
|
|
|
|
|
SearchMonitor* m3);
|
|
|
|
|
void NewSearch(DecisionBuilder* db, SearchMonitor* m1, SearchMonitor* m2,
|
|
|
|
|
SearchMonitor* m3, SearchMonitor* m4);
|
2010-09-15 12:42:33 +00:00
|
|
|
|
|
|
|
|
bool NextSolution();
|
|
|
|
|
void RestartSearch();
|
|
|
|
|
void EndSearch();
|
2019-07-05 00:25:55 +02:00
|
|
|
/// @}
|
|
|
|
|
|
|
|
|
|
/// SolveAndCommit using a decision builder and up to three
|
|
|
|
|
/// search monitors, usually one for the objective, one for the limits
|
|
|
|
|
/// and one to collect solutions.
|
|
|
|
|
///
|
|
|
|
|
/// The difference between a SolveAndCommit() and a Solve() method
|
|
|
|
|
/// call is the fact that SolveAndCommit will not backtrack all
|
|
|
|
|
/// modifications at the end of the search. This method is only
|
|
|
|
|
/// usable during the Next() method of a decision builder.
|
2023-05-31 14:27:08 +02:00
|
|
|
bool SolveAndCommit(DecisionBuilder* db,
|
2020-10-29 14:25:39 +01:00
|
|
|
const std::vector<SearchMonitor*>& monitors);
|
2023-05-31 14:27:08 +02:00
|
|
|
bool SolveAndCommit(DecisionBuilder* db);
|
|
|
|
|
bool SolveAndCommit(DecisionBuilder* db, SearchMonitor* m1);
|
|
|
|
|
bool SolveAndCommit(DecisionBuilder* db, SearchMonitor* m1,
|
|
|
|
|
SearchMonitor* m2);
|
|
|
|
|
bool SolveAndCommit(DecisionBuilder* db, SearchMonitor* m1, SearchMonitor* m2,
|
|
|
|
|
SearchMonitor* m3);
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Checks whether the given assignment satisfies all relevant constraints.
|
2023-05-31 14:27:08 +02:00
|
|
|
bool CheckAssignment(Assignment* solution);
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Checks whether adding this constraint will lead to an immediate
|
|
|
|
|
/// failure. It will return false if the model is already inconsistent, or if
|
|
|
|
|
/// adding the constraint makes it inconsistent.
|
2023-05-31 14:27:08 +02:00
|
|
|
bool CheckConstraint(Constraint* ct);
|
2011-10-11 08:19:59 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// State of the solver.
|
2010-09-15 12:42:33 +00:00
|
|
|
SolverState state() const { return state_; }
|
|
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Abandon the current branch in the search tree. A backtrack will follow.
|
2010-09-15 12:42:33 +00:00
|
|
|
void Fail();
|
|
|
|
|
|
2015-11-20 11:32:37 +01:00
|
|
|
#if !defined(SWIG)
|
2019-07-05 00:25:55 +02:00
|
|
|
/// When SaveValue() is not the best way to go, one can create a reversible
|
|
|
|
|
/// action that will be called upon backtrack. The "fast" parameter
|
|
|
|
|
/// indicates whether we need restore all values saved through SaveValue()
|
|
|
|
|
/// before calling this method.
|
2015-10-23 13:45:43 +02:00
|
|
|
void AddBacktrackAction(Action a, bool fast);
|
2020-10-22 23:36:58 +02:00
|
|
|
#endif /// !defined(SWIG)
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2019-12-05 18:10:18 +01:00
|
|
|
/// misc debug string.
|
2013-12-16 10:24:42 +00:00
|
|
|
std::string DebugString() const;
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Current memory usage in bytes
|
2021-04-01 12:13:35 +02:00
|
|
|
static int64_t MemoryUsage();
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// The 'absolute time' as seen by the solver. Unless a user-provided clock
|
|
|
|
|
/// was injected via SetClock() (eg. for unit tests), this is a real walltime,
|
|
|
|
|
/// shifted so that it was 0 at construction. All so-called "walltime" limits
|
|
|
|
|
/// are relative to this time.
|
2019-04-01 11:36:53 +02:00
|
|
|
absl::Time Now() const;
|
|
|
|
|
|
2025-11-12 14:11:31 +01:00
|
|
|
/// @deprecated Use Now() instead.
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Time elapsed, in ms since the creation of the solver.
|
2021-04-01 12:13:35 +02:00
|
|
|
int64_t wall_time() const;
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// The number of branches explored since the creation of the solver.
|
2021-04-01 12:13:35 +02:00
|
|
|
int64_t branches() const { return branches_; }
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// The number of solutions found since the start of the search.
|
2021-04-01 12:13:35 +02:00
|
|
|
int64_t solutions() const;
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// The number of unchecked solutions found by local search.
|
2021-04-01 12:13:35 +02:00
|
|
|
int64_t unchecked_solutions() const;
|
2019-04-16 09:25:06 -07:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// The number of demons executed during search for a given priority.
|
2021-04-01 12:13:35 +02:00
|
|
|
int64_t demon_runs(DemonPriority p) const { return demon_runs_[p]; }
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// The number of failures encountered since the creation of the solver.
|
2021-04-01 12:13:35 +02:00
|
|
|
int64_t failures() const { return fails_; }
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// The number of neighbors created.
|
2021-04-01 12:13:35 +02:00
|
|
|
int64_t neighbors() const { return neighbors_; }
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2023-05-24 15:32:06 +02:00
|
|
|
/// Manipulate neighbors count; to be used for testing purposes only.
|
|
|
|
|
/// TODO(user): Find a workaround to avoid exposing this.
|
|
|
|
|
void ClearNeighbors() { neighbors_ = 0; }
|
|
|
|
|
void IncrementNeighbors() { ++neighbors_; }
|
|
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// The number of filtered neighbors (neighbors accepted by filters).
|
2021-04-01 12:13:35 +02:00
|
|
|
int64_t filtered_neighbors() const { return filtered_neighbors_; }
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// The number of accepted neighbors.
|
2021-04-01 12:13:35 +02:00
|
|
|
int64_t accepted_neighbors() const { return accepted_neighbors_; }
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// The stamp indicates how many moves in the search tree we have performed.
|
|
|
|
|
/// It is useful to detect if we need to update same lazy structures.
|
2021-04-01 12:13:35 +02:00
|
|
|
uint64_t stamp() const;
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// The fail_stamp() is incremented after each backtrack.
|
2021-04-01 12:13:35 +02:00
|
|
|
uint64_t fail_stamp() const;
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2022-12-07 17:37:45 +01:00
|
|
|
/// Sets the current context of the search.
|
2023-11-09 13:46:25 +01:00
|
|
|
void set_context(absl::string_view context) { context_ = context; }
|
2022-12-07 17:37:45 +01:00
|
|
|
|
|
|
|
|
/// Gets the current context of the search.
|
|
|
|
|
const std::string& context() const { return context_; }
|
|
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// The direction of optimization, getter and setter.
|
2019-03-15 17:17:02 +01:00
|
|
|
OptimizationDirection optimization_direction() const {
|
|
|
|
|
return optimization_direction_;
|
|
|
|
|
}
|
|
|
|
|
void set_optimization_direction(OptimizationDirection direction) {
|
|
|
|
|
optimization_direction_ = direction;
|
|
|
|
|
}
|
|
|
|
|
|
2024-11-18 11:32:13 +01:00
|
|
|
// An internal method called by Guided Local Search to share current
|
|
|
|
|
// penalties with the solver.
|
|
|
|
|
void SetGuidedLocalSearchPenaltyCallback(
|
|
|
|
|
std::function<int64_t(int64_t, int64_t, int64_t)> penalty_callback) {
|
|
|
|
|
penalty_callback_ = std::move(penalty_callback);
|
|
|
|
|
}
|
|
|
|
|
// Returns the current (Guided Local Search)penalty of the given arc tuple.
|
|
|
|
|
int64_t GetGuidedLocalSearchPenalty(int64_t i, int64_t j, int64_t k) const {
|
|
|
|
|
return (penalty_callback_ == nullptr) ? 0 : penalty_callback_(i, j, k);
|
|
|
|
|
}
|
|
|
|
|
|
2010-09-15 12:42:33 +00:00
|
|
|
// All factories (MakeXXX methods) encapsulate creation of objects
|
|
|
|
|
// through RevAlloc(). Hence, the Solver used for allocating the
|
|
|
|
|
// returned object will retain ownership of the allocated memory.
|
|
|
|
|
// Destructors are called upon backtrack, or when the Solver is
|
|
|
|
|
// itself destructed.
|
|
|
|
|
|
|
|
|
|
// ----- Int Variables and Constants -----
|
|
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// MakeIntVar will create the best range based int var for the bounds given.
|
2021-04-01 12:13:35 +02:00
|
|
|
IntVar* MakeIntVar(int64_t min, int64_t max, const std::string& name);
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// MakeIntVar will create a variable with the given sparse domain.
|
2021-04-11 11:29:32 +02:00
|
|
|
IntVar* MakeIntVar(const std::vector<int64_t>& values,
|
|
|
|
|
const std::string& name);
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// MakeIntVar will create a variable with the given sparse domain.
|
2020-10-29 14:25:39 +01:00
|
|
|
IntVar* MakeIntVar(const std::vector<int>& values, const std::string& name);
|
2011-05-20 14:01:28 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// MakeIntVar will create the best range based int var for the bounds given.
|
2021-04-01 12:13:35 +02:00
|
|
|
IntVar* MakeIntVar(int64_t min, int64_t max);
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// MakeIntVar will create a variable with the given sparse domain.
|
2021-04-01 12:13:35 +02:00
|
|
|
IntVar* MakeIntVar(const std::vector<int64_t>& values);
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// MakeIntVar will create a variable with the given sparse domain.
|
2020-10-29 14:25:39 +01:00
|
|
|
IntVar* MakeIntVar(const std::vector<int>& values);
|
2011-05-20 14:01:28 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// MakeBoolVar will create a variable with a {0, 1} domain.
|
2020-10-29 14:25:39 +01:00
|
|
|
IntVar* MakeBoolVar(const std::string& name);
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// MakeBoolVar will create a variable with a {0, 1} domain.
|
2020-10-29 14:25:39 +01:00
|
|
|
IntVar* MakeBoolVar();
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// IntConst will create a constant expression.
|
2021-04-01 12:13:35 +02:00
|
|
|
IntVar* MakeIntConst(int64_t val, const std::string& name);
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// IntConst will create a constant expression.
|
2021-04-01 12:13:35 +02:00
|
|
|
IntVar* MakeIntConst(int64_t val);
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// This method will append the vector vars with 'var_count' variables
|
|
|
|
|
/// having bounds vmin and vmax and having name "name<i>" where <i> is
|
|
|
|
|
/// the index of the variable.
|
2021-04-01 12:13:35 +02:00
|
|
|
void MakeIntVarArray(int var_count, int64_t vmin, int64_t vmax,
|
2020-10-29 14:25:39 +01:00
|
|
|
const std::string& name, std::vector<IntVar*>* vars);
|
2019-07-05 00:25:55 +02:00
|
|
|
/// This method will append the vector vars with 'var_count' variables
|
|
|
|
|
/// having bounds vmin and vmax and having no names.
|
2021-04-01 12:13:35 +02:00
|
|
|
void MakeIntVarArray(int var_count, int64_t vmin, int64_t vmax,
|
2020-10-29 14:25:39 +01:00
|
|
|
std::vector<IntVar*>* vars);
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Same but allocates an array and returns it.
|
2021-04-01 12:13:35 +02:00
|
|
|
IntVar** MakeIntVarArray(int var_count, int64_t vmin, int64_t vmax,
|
2020-10-29 14:25:39 +01:00
|
|
|
const std::string& name);
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// This method will append the vector vars with 'var_count' boolean
|
|
|
|
|
/// variables having name "name<i>" where <i> is the index of the
|
|
|
|
|
/// variable.
|
2020-10-29 14:25:39 +01:00
|
|
|
void MakeBoolVarArray(int var_count, const std::string& name,
|
|
|
|
|
std::vector<IntVar*>* vars);
|
2019-07-05 00:25:55 +02:00
|
|
|
/// This method will append the vector vars with 'var_count' boolean
|
|
|
|
|
/// variables having no names.
|
2020-10-29 14:25:39 +01:00
|
|
|
void MakeBoolVarArray(int var_count, std::vector<IntVar*>* vars);
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Same but allocates an array and returns it.
|
2020-10-29 14:25:39 +01:00
|
|
|
IntVar** MakeBoolVarArray(int var_count, const std::string& name);
|
2010-09-15 12:42:33 +00:00
|
|
|
|
|
|
|
|
// ----- Integer Expressions -----
|
|
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// left + right.
|
2023-05-31 14:27:08 +02:00
|
|
|
IntExpr* MakeSum(IntExpr* left, IntExpr* right);
|
2019-07-05 00:25:55 +02:00
|
|
|
/// expr + value.
|
2023-05-31 14:27:08 +02:00
|
|
|
IntExpr* MakeSum(IntExpr* expr, int64_t value);
|
2019-07-05 00:25:55 +02:00
|
|
|
/// sum of all vars.
|
2020-10-29 14:25:39 +01:00
|
|
|
IntExpr* MakeSum(const std::vector<IntVar*>& vars);
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// scalar product
|
2020-10-29 14:25:39 +01:00
|
|
|
IntExpr* MakeScalProd(const std::vector<IntVar*>& vars,
|
2021-04-01 12:13:35 +02:00
|
|
|
const std::vector<int64_t>& coefs);
|
2019-07-05 00:25:55 +02:00
|
|
|
/// scalar product
|
2020-10-29 14:25:39 +01:00
|
|
|
IntExpr* MakeScalProd(const std::vector<IntVar*>& vars,
|
|
|
|
|
const std::vector<int>& coefs);
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// left - right
|
2023-05-31 14:27:08 +02:00
|
|
|
IntExpr* MakeDifference(IntExpr* left, IntExpr* right);
|
2019-07-05 00:25:55 +02:00
|
|
|
/// value - expr
|
2023-05-31 14:27:08 +02:00
|
|
|
IntExpr* MakeDifference(int64_t value, IntExpr* expr);
|
2019-07-05 00:25:55 +02:00
|
|
|
/// -expr
|
2023-05-31 14:27:08 +02:00
|
|
|
IntExpr* MakeOpposite(IntExpr* expr);
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// left * right
|
2023-05-31 14:27:08 +02:00
|
|
|
IntExpr* MakeProd(IntExpr* left, IntExpr* right);
|
2019-07-05 00:25:55 +02:00
|
|
|
/// expr * value
|
2023-05-31 14:27:08 +02:00
|
|
|
IntExpr* MakeProd(IntExpr* expr, int64_t value);
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// expr / value (integer division)
|
2023-05-31 14:27:08 +02:00
|
|
|
IntExpr* MakeDiv(IntExpr* expr, int64_t value);
|
2019-07-05 00:25:55 +02:00
|
|
|
/// numerator / denominator (integer division). Terms need to be positive.
|
2023-05-31 14:27:08 +02:00
|
|
|
IntExpr* MakeDiv(IntExpr* numerator, IntExpr* denominator);
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// |expr|
|
2023-05-31 14:27:08 +02:00
|
|
|
IntExpr* MakeAbs(IntExpr* expr);
|
2019-07-05 00:25:55 +02:00
|
|
|
/// expr * expr
|
2023-05-31 14:27:08 +02:00
|
|
|
IntExpr* MakeSquare(IntExpr* expr);
|
2019-07-05 00:25:55 +02:00
|
|
|
/// expr ^ n (n > 0)
|
2023-05-31 14:27:08 +02:00
|
|
|
IntExpr* MakePower(IntExpr* expr, int64_t n);
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// values[index]
|
2023-05-31 14:27:08 +02:00
|
|
|
IntExpr* MakeElement(const std::vector<int64_t>& values, IntVar* index);
|
2019-07-05 00:25:55 +02:00
|
|
|
/// values[index]
|
2023-05-31 14:27:08 +02:00
|
|
|
IntExpr* MakeElement(const std::vector<int>& values, IntVar* index);
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Function-based element. The constraint takes ownership of the
|
|
|
|
|
/// callback. The callback must be able to cope with any possible
|
|
|
|
|
/// value in the domain of 'index' (potentially negative ones too).
|
2023-05-31 14:27:08 +02:00
|
|
|
IntExpr* MakeElement(IndexEvaluator1 values, IntVar* index);
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Function based element. The constraint takes ownership of the
|
|
|
|
|
/// callback. The callback must be monotonic. It must be able to
|
|
|
|
|
/// cope with any possible value in the domain of 'index'
|
|
|
|
|
/// (potentially negative ones too). Furtermore, monotonicity is not
|
|
|
|
|
/// checked. Thus giving a non-monotonic function, or specifying an
|
|
|
|
|
/// incorrect increasing parameter will result in undefined behavior.
|
2020-10-29 14:25:39 +01:00
|
|
|
IntExpr* MakeMonotonicElement(IndexEvaluator1 values, bool increasing,
|
2023-05-31 14:27:08 +02:00
|
|
|
IntVar* index);
|
2019-07-05 00:25:55 +02:00
|
|
|
/// 2D version of function-based element expression, values(expr1, expr2).
|
2023-05-31 14:27:08 +02:00
|
|
|
IntExpr* MakeElement(IndexEvaluator2 values, IntVar* index1, IntVar* index2);
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// vars[expr]
|
2023-05-31 14:27:08 +02:00
|
|
|
IntExpr* MakeElement(const std::vector<IntVar*>& vars, IntVar* index);
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2015-10-23 13:45:43 +02:00
|
|
|
#if !defined(SWIG)
|
2019-07-05 00:25:55 +02:00
|
|
|
/// vars(argument)
|
2021-04-11 11:29:32 +02:00
|
|
|
IntExpr* MakeElement(Int64ToIntVar vars, int64_t range_start,
|
|
|
|
|
int64_t range_end, IntVar* argument);
|
2020-10-22 23:36:58 +02:00
|
|
|
#endif // SWIG
|
2015-10-23 13:45:43 +02:00
|
|
|
|
2022-09-05 18:30:09 +02:00
|
|
|
/// Light versions of function-based elements, in constraint version only,
|
|
|
|
|
/// well-suited for use within Local Search.
|
|
|
|
|
/// These constraints are "checking" constraints, only triggered on WhenBound
|
|
|
|
|
/// events. They provide very little (or no) domain filtering.
|
|
|
|
|
|
|
|
|
|
/// Returns a light one-dimension function-based element constraint ensuring
|
|
|
|
|
/// var == values(index).
|
|
|
|
|
/// The constraint does not perform bound reduction of the resulting variable
|
|
|
|
|
/// until the index variable is bound.
|
|
|
|
|
/// If deep_serialize returns false, the model visitor will not extract all
|
|
|
|
|
/// possible values from the values function.
|
|
|
|
|
template <typename F>
|
|
|
|
|
Constraint* MakeLightElement(F values, IntVar* const var, IntVar* const index,
|
|
|
|
|
std::function<bool()> deep_serialize = nullptr) {
|
|
|
|
|
return RevAlloc(new LightIntFunctionElementCt<F>(
|
|
|
|
|
this, var, index, std::move(values), std::move(deep_serialize)));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Light two-dimension function-based element constraint ensuring
|
|
|
|
|
/// var == values(index1, index2).
|
|
|
|
|
/// The constraint does not perform bound reduction of the resulting variable
|
|
|
|
|
/// until the index variables are bound.
|
|
|
|
|
/// If deep_serialize returns false, the model visitor will not extract all
|
|
|
|
|
/// possible values from the values function.
|
|
|
|
|
template <typename F>
|
|
|
|
|
Constraint* MakeLightElement(F values, IntVar* const var,
|
|
|
|
|
IntVar* const index1, IntVar* const index2,
|
|
|
|
|
std::function<bool()> deep_serialize = nullptr) {
|
|
|
|
|
return RevAlloc(new LightIntIntFunctionElementCt<F>(
|
|
|
|
|
this, var, index1, index2, std::move(values),
|
|
|
|
|
std::move(deep_serialize)));
|
|
|
|
|
}
|
|
|
|
|
|
2024-11-18 11:32:13 +01:00
|
|
|
/// Light three-dimension function-based element constraint ensuring
|
|
|
|
|
/// var == values(index1, index2, index3).
|
|
|
|
|
/// The constraint does not perform bound reduction of the resulting variable
|
|
|
|
|
/// until the index variables are bound.
|
|
|
|
|
template <typename F>
|
|
|
|
|
Constraint* MakeLightElement(F values, IntVar* const var,
|
|
|
|
|
IntVar* const index1, IntVar* const index2,
|
|
|
|
|
IntVar* const index3) {
|
|
|
|
|
return RevAlloc(new LightIntIntIntFunctionElementCt<F>(
|
|
|
|
|
this, var, index1, index2, index3, std::move(values)));
|
|
|
|
|
}
|
|
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Returns the expression expr such that vars[expr] == value.
|
|
|
|
|
/// It assumes that vars are all different.
|
2021-04-01 12:13:35 +02:00
|
|
|
IntExpr* MakeIndexExpression(const std::vector<IntVar*>& vars, int64_t value);
|
2012-06-26 04:59:29 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Special cases with arrays of size two.
|
2023-05-31 14:27:08 +02:00
|
|
|
Constraint* MakeIfThenElseCt(IntVar* condition, IntExpr* then_expr,
|
|
|
|
|
IntExpr* else_expr, IntVar* target_var);
|
2014-07-30 16:32:00 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// std::min(vars)
|
2020-10-29 14:25:39 +01:00
|
|
|
IntExpr* MakeMin(const std::vector<IntVar*>& vars);
|
2019-07-05 00:25:55 +02:00
|
|
|
/// std::min (left, right)
|
2023-05-31 14:27:08 +02:00
|
|
|
IntExpr* MakeMin(IntExpr* left, IntExpr* right);
|
2019-07-05 00:25:55 +02:00
|
|
|
/// std::min(expr, value)
|
2023-05-31 14:27:08 +02:00
|
|
|
IntExpr* MakeMin(IntExpr* expr, int64_t value);
|
2019-07-05 00:25:55 +02:00
|
|
|
/// std::min(expr, value)
|
2023-05-31 14:27:08 +02:00
|
|
|
IntExpr* MakeMin(IntExpr* expr, int value);
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// std::max(vars)
|
2020-10-29 14:25:39 +01:00
|
|
|
IntExpr* MakeMax(const std::vector<IntVar*>& vars);
|
2019-07-05 00:25:55 +02:00
|
|
|
/// std::max(left, right)
|
2023-05-31 14:27:08 +02:00
|
|
|
IntExpr* MakeMax(IntExpr* left, IntExpr* right);
|
2019-07-05 00:25:55 +02:00
|
|
|
/// std::max(expr, value)
|
2023-05-31 14:27:08 +02:00
|
|
|
IntExpr* MakeMax(IntExpr* expr, int64_t value);
|
2019-07-05 00:25:55 +02:00
|
|
|
/// std::max(expr, value)
|
2023-05-31 14:27:08 +02:00
|
|
|
IntExpr* MakeMax(IntExpr* expr, int value);
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Convex piecewise function.
|
2021-04-01 12:13:35 +02:00
|
|
|
IntExpr* MakeConvexPiecewiseExpr(IntExpr* expr, int64_t early_cost,
|
|
|
|
|
int64_t early_date, int64_t late_date,
|
|
|
|
|
int64_t late_cost);
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Semi continuous Expression (x <= 0 -> f(x) = 0; x > 0 -> f(x) = ax + b)
|
|
|
|
|
/// a >= 0 and b >= 0
|
2023-05-31 14:27:08 +02:00
|
|
|
IntExpr* MakeSemiContinuousExpr(IntExpr* expr, int64_t fixed_charge,
|
2021-04-01 12:13:35 +02:00
|
|
|
int64_t step);
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2020-10-29 15:56:44 +01:00
|
|
|
/// General piecewise-linear function expression, built from f(x) where f is
|
|
|
|
|
/// piecewise-linear. The resulting expression is f(expr).
|
|
|
|
|
// TODO(user): Investigate if we can merge all three piecewise linear
|
|
|
|
|
/// expressions.
|
2017-03-28 16:10:01 +02:00
|
|
|
#ifndef SWIG
|
2020-10-29 14:25:39 +01:00
|
|
|
IntExpr* MakePiecewiseLinearExpr(IntExpr* expr,
|
|
|
|
|
const PiecewiseLinearFunction& f);
|
2017-03-28 16:10:01 +02:00
|
|
|
#endif
|
|
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Modulo expression x % mod (with the python convention for modulo).
|
2023-05-31 14:27:08 +02:00
|
|
|
IntExpr* MakeModulo(IntExpr* x, int64_t mod);
|
2013-06-11 14:49:19 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Modulo expression x % mod (with the python convention for modulo).
|
2023-05-31 14:27:08 +02:00
|
|
|
IntExpr* MakeModulo(IntExpr* x, IntExpr* mod);
|
2013-06-11 14:49:19 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Conditional Expr condition ? expr : unperformed_value
|
2023-05-31 14:27:08 +02:00
|
|
|
IntExpr* MakeConditionalExpression(IntVar* condition, IntExpr* expr,
|
2021-04-01 12:13:35 +02:00
|
|
|
int64_t unperformed_value);
|
2013-12-05 16:06:40 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// This constraint always succeeds.
|
2020-10-29 14:25:39 +01:00
|
|
|
Constraint* MakeTrueConstraint();
|
2019-07-05 00:25:55 +02:00
|
|
|
/// This constraint always fails.
|
2020-10-29 14:25:39 +01:00
|
|
|
Constraint* MakeFalseConstraint();
|
|
|
|
|
Constraint* MakeFalseConstraint(const std::string& explanation);
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// boolvar == (var == value)
|
2023-05-31 14:27:08 +02:00
|
|
|
Constraint* MakeIsEqualCstCt(IntExpr* var, int64_t value, IntVar* boolvar);
|
2019-07-05 00:25:55 +02:00
|
|
|
/// status var of (var == value)
|
2023-05-31 14:27:08 +02:00
|
|
|
IntVar* MakeIsEqualCstVar(IntExpr* var, int64_t value);
|
2019-07-05 00:25:55 +02:00
|
|
|
/// b == (v1 == v2)
|
2023-05-31 14:27:08 +02:00
|
|
|
Constraint* MakeIsEqualCt(IntExpr* v1, IntExpr* v2, IntVar* b);
|
2019-07-05 00:25:55 +02:00
|
|
|
/// status var of (v1 == v2)
|
2023-05-31 14:27:08 +02:00
|
|
|
IntVar* MakeIsEqualVar(IntExpr* v1, IntExpr* v2);
|
2019-07-05 00:25:55 +02:00
|
|
|
/// left == right
|
2023-05-31 14:27:08 +02:00
|
|
|
Constraint* MakeEquality(IntExpr* left, IntExpr* right);
|
2019-07-05 00:25:55 +02:00
|
|
|
/// expr == value
|
2023-05-31 14:27:08 +02:00
|
|
|
Constraint* MakeEquality(IntExpr* expr, int64_t value);
|
2019-07-05 00:25:55 +02:00
|
|
|
/// expr == value
|
2023-05-31 14:27:08 +02:00
|
|
|
Constraint* MakeEquality(IntExpr* expr, int value);
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// boolvar == (var != value)
|
2023-05-31 14:27:08 +02:00
|
|
|
Constraint* MakeIsDifferentCstCt(IntExpr* var, int64_t value,
|
|
|
|
|
IntVar* boolvar);
|
2019-07-05 00:25:55 +02:00
|
|
|
/// status var of (var != value)
|
2023-05-31 14:27:08 +02:00
|
|
|
IntVar* MakeIsDifferentCstVar(IntExpr* var, int64_t value);
|
2019-07-05 00:25:55 +02:00
|
|
|
/// status var of (v1 != v2)
|
2023-05-31 14:27:08 +02:00
|
|
|
IntVar* MakeIsDifferentVar(IntExpr* v1, IntExpr* v2);
|
2019-07-05 00:25:55 +02:00
|
|
|
/// b == (v1 != v2)
|
2023-05-31 14:27:08 +02:00
|
|
|
Constraint* MakeIsDifferentCt(IntExpr* v1, IntExpr* v2, IntVar* b);
|
2019-07-05 00:25:55 +02:00
|
|
|
/// left != right
|
2023-05-31 14:27:08 +02:00
|
|
|
Constraint* MakeNonEquality(IntExpr* left, IntExpr* right);
|
2019-07-05 00:25:55 +02:00
|
|
|
/// expr != value
|
2023-05-31 14:27:08 +02:00
|
|
|
Constraint* MakeNonEquality(IntExpr* expr, int64_t value);
|
2019-07-05 00:25:55 +02:00
|
|
|
/// expr != value
|
2023-05-31 14:27:08 +02:00
|
|
|
Constraint* MakeNonEquality(IntExpr* expr, int value);
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// boolvar == (var <= value)
|
2023-05-31 14:27:08 +02:00
|
|
|
Constraint* MakeIsLessOrEqualCstCt(IntExpr* var, int64_t value,
|
|
|
|
|
IntVar* boolvar);
|
2019-07-05 00:25:55 +02:00
|
|
|
/// status var of (var <= value)
|
2023-05-31 14:27:08 +02:00
|
|
|
IntVar* MakeIsLessOrEqualCstVar(IntExpr* var, int64_t value);
|
2019-07-05 00:25:55 +02:00
|
|
|
/// status var of (left <= right)
|
2023-05-31 14:27:08 +02:00
|
|
|
IntVar* MakeIsLessOrEqualVar(IntExpr* left, IntExpr* right);
|
2019-07-05 00:25:55 +02:00
|
|
|
/// b == (left <= right)
|
2023-05-31 14:27:08 +02:00
|
|
|
Constraint* MakeIsLessOrEqualCt(IntExpr* left, IntExpr* right, IntVar* b);
|
2019-07-05 00:25:55 +02:00
|
|
|
/// left <= right
|
2023-05-31 14:27:08 +02:00
|
|
|
Constraint* MakeLessOrEqual(IntExpr* left, IntExpr* right);
|
2019-07-05 00:25:55 +02:00
|
|
|
/// expr <= value
|
2023-05-31 14:27:08 +02:00
|
|
|
Constraint* MakeLessOrEqual(IntExpr* expr, int64_t value);
|
2019-07-05 00:25:55 +02:00
|
|
|
/// expr <= value
|
2023-05-31 14:27:08 +02:00
|
|
|
Constraint* MakeLessOrEqual(IntExpr* expr, int value);
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// boolvar == (var >= value)
|
2023-05-31 14:27:08 +02:00
|
|
|
Constraint* MakeIsGreaterOrEqualCstCt(IntExpr* var, int64_t value,
|
|
|
|
|
IntVar* boolvar);
|
2019-07-05 00:25:55 +02:00
|
|
|
/// status var of (var >= value)
|
2023-05-31 14:27:08 +02:00
|
|
|
IntVar* MakeIsGreaterOrEqualCstVar(IntExpr* var, int64_t value);
|
2019-07-05 00:25:55 +02:00
|
|
|
/// status var of (left >= right)
|
2023-05-31 14:27:08 +02:00
|
|
|
IntVar* MakeIsGreaterOrEqualVar(IntExpr* left, IntExpr* right);
|
2019-07-05 00:25:55 +02:00
|
|
|
/// b == (left >= right)
|
2023-05-31 14:27:08 +02:00
|
|
|
Constraint* MakeIsGreaterOrEqualCt(IntExpr* left, IntExpr* right, IntVar* b);
|
2019-07-05 00:25:55 +02:00
|
|
|
/// left >= right
|
2023-05-31 14:27:08 +02:00
|
|
|
Constraint* MakeGreaterOrEqual(IntExpr* left, IntExpr* right);
|
2019-07-05 00:25:55 +02:00
|
|
|
/// expr >= value
|
2023-05-31 14:27:08 +02:00
|
|
|
Constraint* MakeGreaterOrEqual(IntExpr* expr, int64_t value);
|
2019-07-05 00:25:55 +02:00
|
|
|
/// expr >= value
|
2023-05-31 14:27:08 +02:00
|
|
|
Constraint* MakeGreaterOrEqual(IntExpr* expr, int value);
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// b == (v > c)
|
2023-05-31 14:27:08 +02:00
|
|
|
Constraint* MakeIsGreaterCstCt(IntExpr* v, int64_t c, IntVar* b);
|
2019-07-05 00:25:55 +02:00
|
|
|
/// status var of (var > value)
|
2023-05-31 14:27:08 +02:00
|
|
|
IntVar* MakeIsGreaterCstVar(IntExpr* var, int64_t value);
|
2019-07-05 00:25:55 +02:00
|
|
|
/// status var of (left > right)
|
2023-05-31 14:27:08 +02:00
|
|
|
IntVar* MakeIsGreaterVar(IntExpr* left, IntExpr* right);
|
2019-07-05 00:25:55 +02:00
|
|
|
/// b == (left > right)
|
2023-05-31 14:27:08 +02:00
|
|
|
Constraint* MakeIsGreaterCt(IntExpr* left, IntExpr* right, IntVar* b);
|
2019-07-05 00:25:55 +02:00
|
|
|
/// left > right
|
2023-05-31 14:27:08 +02:00
|
|
|
Constraint* MakeGreater(IntExpr* left, IntExpr* right);
|
2019-07-05 00:25:55 +02:00
|
|
|
/// expr > value
|
2023-05-31 14:27:08 +02:00
|
|
|
Constraint* MakeGreater(IntExpr* expr, int64_t value);
|
2019-07-05 00:25:55 +02:00
|
|
|
/// expr > value
|
2023-05-31 14:27:08 +02:00
|
|
|
Constraint* MakeGreater(IntExpr* expr, int value);
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// b == (v < c)
|
2023-05-31 14:27:08 +02:00
|
|
|
Constraint* MakeIsLessCstCt(IntExpr* v, int64_t c, IntVar* b);
|
2019-07-05 00:25:55 +02:00
|
|
|
/// status var of (var < value)
|
2023-05-31 14:27:08 +02:00
|
|
|
IntVar* MakeIsLessCstVar(IntExpr* var, int64_t value);
|
2019-07-05 00:25:55 +02:00
|
|
|
/// status var of (left < right)
|
2023-05-31 14:27:08 +02:00
|
|
|
IntVar* MakeIsLessVar(IntExpr* left, IntExpr* right);
|
2019-07-05 00:25:55 +02:00
|
|
|
/// b == (left < right)
|
2023-05-31 14:27:08 +02:00
|
|
|
Constraint* MakeIsLessCt(IntExpr* left, IntExpr* right, IntVar* b);
|
2019-07-05 00:25:55 +02:00
|
|
|
/// left < right
|
2023-05-31 14:27:08 +02:00
|
|
|
Constraint* MakeLess(IntExpr* left, IntExpr* right);
|
2019-07-05 00:25:55 +02:00
|
|
|
/// expr < value
|
2023-05-31 14:27:08 +02:00
|
|
|
Constraint* MakeLess(IntExpr* expr, int64_t value);
|
2019-07-05 00:25:55 +02:00
|
|
|
/// expr < value
|
2023-05-31 14:27:08 +02:00
|
|
|
Constraint* MakeLess(IntExpr* expr, int value);
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Variation on arrays.
|
2021-04-01 12:13:35 +02:00
|
|
|
Constraint* MakeSumLessOrEqual(const std::vector<IntVar*>& vars, int64_t cst);
|
2020-10-29 14:25:39 +01:00
|
|
|
Constraint* MakeSumGreaterOrEqual(const std::vector<IntVar*>& vars,
|
2021-04-01 12:13:35 +02:00
|
|
|
int64_t cst);
|
|
|
|
|
Constraint* MakeSumEquality(const std::vector<IntVar*>& vars, int64_t cst);
|
2023-05-31 14:27:08 +02:00
|
|
|
Constraint* MakeSumEquality(const std::vector<IntVar*>& vars, IntVar* var);
|
2020-10-29 14:25:39 +01:00
|
|
|
Constraint* MakeScalProdEquality(const std::vector<IntVar*>& vars,
|
2021-04-01 12:13:35 +02:00
|
|
|
const std::vector<int64_t>& coefficients,
|
|
|
|
|
int64_t cst);
|
2020-10-29 14:25:39 +01:00
|
|
|
Constraint* MakeScalProdEquality(const std::vector<IntVar*>& vars,
|
|
|
|
|
const std::vector<int>& coefficients,
|
2021-04-01 12:13:35 +02:00
|
|
|
int64_t cst);
|
2020-10-29 14:25:39 +01:00
|
|
|
Constraint* MakeScalProdEquality(const std::vector<IntVar*>& vars,
|
2021-04-01 12:13:35 +02:00
|
|
|
const std::vector<int64_t>& coefficients,
|
2023-05-31 14:27:08 +02:00
|
|
|
IntVar* target);
|
2020-10-29 14:25:39 +01:00
|
|
|
Constraint* MakeScalProdEquality(const std::vector<IntVar*>& vars,
|
|
|
|
|
const std::vector<int>& coefficients,
|
2023-05-31 14:27:08 +02:00
|
|
|
IntVar* target);
|
2020-10-29 14:25:39 +01:00
|
|
|
Constraint* MakeScalProdGreaterOrEqual(const std::vector<IntVar*>& vars,
|
2021-04-01 12:13:35 +02:00
|
|
|
const std::vector<int64_t>& coeffs,
|
|
|
|
|
int64_t cst);
|
2020-10-29 14:25:39 +01:00
|
|
|
Constraint* MakeScalProdGreaterOrEqual(const std::vector<IntVar*>& vars,
|
|
|
|
|
const std::vector<int>& coeffs,
|
2021-04-01 12:13:35 +02:00
|
|
|
int64_t cst);
|
2020-10-29 14:25:39 +01:00
|
|
|
Constraint* MakeScalProdLessOrEqual(const std::vector<IntVar*>& vars,
|
2021-04-01 12:13:35 +02:00
|
|
|
const std::vector<int64_t>& coefficients,
|
|
|
|
|
int64_t cst);
|
2020-10-29 14:25:39 +01:00
|
|
|
Constraint* MakeScalProdLessOrEqual(const std::vector<IntVar*>& vars,
|
|
|
|
|
const std::vector<int>& coefficients,
|
2021-04-01 12:13:35 +02:00
|
|
|
int64_t cst);
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2020-10-29 14:25:39 +01:00
|
|
|
Constraint* MakeMinEquality(const std::vector<IntVar*>& vars,
|
2023-05-31 14:27:08 +02:00
|
|
|
IntVar* min_var);
|
2020-10-29 14:25:39 +01:00
|
|
|
Constraint* MakeMaxEquality(const std::vector<IntVar*>& vars,
|
2023-05-31 14:27:08 +02:00
|
|
|
IntVar* max_var);
|
2020-10-29 14:25:39 +01:00
|
|
|
|
2021-04-01 12:13:35 +02:00
|
|
|
Constraint* MakeElementEquality(const std::vector<int64_t>& vals,
|
2023-05-31 14:27:08 +02:00
|
|
|
IntVar* index, IntVar* target);
|
|
|
|
|
Constraint* MakeElementEquality(const std::vector<int>& vals, IntVar* index,
|
|
|
|
|
IntVar* target);
|
2020-10-29 14:25:39 +01:00
|
|
|
Constraint* MakeElementEquality(const std::vector<IntVar*>& vars,
|
2023-05-31 14:27:08 +02:00
|
|
|
IntVar* index, IntVar* target);
|
2020-10-29 14:25:39 +01:00
|
|
|
Constraint* MakeElementEquality(const std::vector<IntVar*>& vars,
|
2023-05-31 14:27:08 +02:00
|
|
|
IntVar* index, int64_t target);
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Creates the constraint abs(var) == abs_var.
|
2023-05-31 14:27:08 +02:00
|
|
|
Constraint* MakeAbsEquality(IntVar* var, IntVar* abs_var);
|
2019-07-05 00:25:55 +02:00
|
|
|
/// This constraint is a special case of the element constraint with
|
|
|
|
|
/// an array of integer variables, where the variables are all
|
|
|
|
|
/// different and the index variable is constrained such that
|
|
|
|
|
/// vars[index] == target.
|
2020-10-29 14:25:39 +01:00
|
|
|
Constraint* MakeIndexOfConstraint(const std::vector<IntVar*>& vars,
|
2023-05-31 14:27:08 +02:00
|
|
|
IntVar* index, int64_t target);
|
2012-05-30 07:57:52 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// This method is a specialized case of the MakeConstraintDemon
|
|
|
|
|
/// method to call the InitiatePropagate of the constraint 'ct'.
|
2023-05-31 14:27:08 +02:00
|
|
|
Demon* MakeConstraintInitialPropagateCallback(Constraint* ct);
|
2019-07-05 00:25:55 +02:00
|
|
|
/// This method is a specialized case of the MakeConstraintDemon
|
|
|
|
|
/// method to call the InitiatePropagate of the constraint 'ct' with
|
|
|
|
|
/// low priority.
|
2023-05-31 14:27:08 +02:00
|
|
|
Demon* MakeDelayedConstraintInitialPropagateCallback(Constraint* ct);
|
2015-11-18 16:45:30 +01:00
|
|
|
#if !defined(SWIG)
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Creates a demon from a callback.
|
2020-10-29 14:25:39 +01:00
|
|
|
Demon* MakeActionDemon(Action action);
|
2020-10-22 23:36:58 +02:00
|
|
|
#endif /// !defined(SWIG)
|
2020-10-29 15:56:44 +01:00
|
|
|
/// Creates a demon from a closure.
|
2020-10-29 14:25:39 +01:00
|
|
|
Demon* MakeClosureDemon(Closure closure);
|
2011-11-03 10:27:53 +00:00
|
|
|
|
2016-08-05 15:38:20 +02:00
|
|
|
// ----- Between and related constraints -----
|
|
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// (l <= expr <= u)
|
2023-05-31 14:27:08 +02:00
|
|
|
Constraint* MakeBetweenCt(IntExpr* expr, int64_t l, int64_t u);
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// (expr < l || expr > u)
|
|
|
|
|
/// This constraint is lazy as it will not make holes in the domain of
|
|
|
|
|
/// variables. It will propagate only when expr->Min() >= l
|
|
|
|
|
/// or expr->Max() <= u.
|
2023-05-31 14:27:08 +02:00
|
|
|
Constraint* MakeNotBetweenCt(IntExpr* expr, int64_t l, int64_t u);
|
2016-07-25 11:09:39 -07:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// b == (l <= expr <= u)
|
2023-05-31 14:27:08 +02:00
|
|
|
Constraint* MakeIsBetweenCt(IntExpr* expr, int64_t l, int64_t u, IntVar* b);
|
|
|
|
|
IntVar* MakeIsBetweenVar(IntExpr* v, int64_t l, int64_t u);
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2016-08-05 15:38:20 +02:00
|
|
|
// ----- Member and related constraints -----
|
|
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// expr in set. Propagation is lazy, i.e. this constraint does not
|
|
|
|
|
/// creates holes in the domain of the variable.
|
2023-05-31 14:27:08 +02:00
|
|
|
Constraint* MakeMemberCt(IntExpr* expr, const std::vector<int64_t>& values);
|
|
|
|
|
Constraint* MakeMemberCt(IntExpr* expr, const std::vector<int>& values);
|
2016-04-12 13:25:46 +02:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// expr not in set.
|
2023-05-31 14:27:08 +02:00
|
|
|
Constraint* MakeNotMemberCt(IntExpr* expr,
|
2021-04-01 12:13:35 +02:00
|
|
|
const std::vector<int64_t>& values);
|
2023-05-31 14:27:08 +02:00
|
|
|
Constraint* MakeNotMemberCt(IntExpr* expr, const std::vector<int>& values);
|
2016-07-25 11:09:39 -07:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// expr should not be in the list of forbidden intervals [start[i]..end[i]].
|
2023-05-31 14:27:08 +02:00
|
|
|
Constraint* MakeNotMemberCt(IntExpr* expr, std::vector<int64_t> starts,
|
2021-04-01 12:13:35 +02:00
|
|
|
std::vector<int64_t> ends);
|
2019-07-05 00:25:55 +02:00
|
|
|
/// expr should not be in the list of forbidden intervals [start[i]..end[i]].
|
2023-05-31 14:27:08 +02:00
|
|
|
Constraint* MakeNotMemberCt(IntExpr* expr, std::vector<int> starts,
|
2016-06-02 13:19:10 +02:00
|
|
|
std::vector<int> ends);
|
2016-07-13 14:51:35 -07:00
|
|
|
#if !defined(SWIG)
|
2019-07-05 00:25:55 +02:00
|
|
|
/// expr should not be in the list of forbidden intervals.
|
2020-10-29 14:25:39 +01:00
|
|
|
Constraint* MakeNotMemberCt(IntExpr* expr,
|
2017-12-08 14:52:49 +01:00
|
|
|
SortedDisjointIntervalList intervals);
|
2020-10-22 23:36:58 +02:00
|
|
|
#endif // !defined(SWIG)
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// boolvar == (expr in set)
|
2023-05-31 14:27:08 +02:00
|
|
|
Constraint* MakeIsMemberCt(IntExpr* expr, const std::vector<int64_t>& values,
|
|
|
|
|
IntVar* boolvar);
|
|
|
|
|
Constraint* MakeIsMemberCt(IntExpr* expr, const std::vector<int>& values,
|
|
|
|
|
IntVar* boolvar);
|
|
|
|
|
IntVar* MakeIsMemberVar(IntExpr* expr, const std::vector<int64_t>& values);
|
|
|
|
|
IntVar* MakeIsMemberVar(IntExpr* expr, const std::vector<int>& values);
|
2017-12-08 14:52:49 +01:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// |{i | vars[i] == value}| <= max_count
|
2021-04-01 12:13:35 +02:00
|
|
|
Constraint* MakeAtMost(std::vector<IntVar*> vars, int64_t value,
|
|
|
|
|
int64_t max_count);
|
2019-07-05 00:25:55 +02:00
|
|
|
/// |{i | vars[i] == value}| == max_count
|
2021-04-01 12:13:35 +02:00
|
|
|
Constraint* MakeCount(const std::vector<IntVar*>& vars, int64_t value,
|
|
|
|
|
int64_t max_count);
|
2019-07-05 00:25:55 +02:00
|
|
|
/// |{i | vars[i] == value}| == max_count
|
2021-04-01 12:13:35 +02:00
|
|
|
Constraint* MakeCount(const std::vector<IntVar*>& vars, int64_t value,
|
2023-05-31 14:27:08 +02:00
|
|
|
IntVar* max_count);
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Aggregated version of count: |{i | v[i] == values[j]}| == cards[j]
|
2020-10-29 14:25:39 +01:00
|
|
|
Constraint* MakeDistribute(const std::vector<IntVar*>& vars,
|
2021-04-01 12:13:35 +02:00
|
|
|
const std::vector<int64_t>& values,
|
2020-10-29 14:25:39 +01:00
|
|
|
const std::vector<IntVar*>& cards);
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Aggregated version of count: |{i | v[i] == values[j]}| == cards[j]
|
2020-10-29 14:25:39 +01:00
|
|
|
Constraint* MakeDistribute(const std::vector<IntVar*>& vars,
|
|
|
|
|
const std::vector<int>& values,
|
|
|
|
|
const std::vector<IntVar*>& cards);
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Aggregated version of count: |{i | v[i] == j}| == cards[j]
|
2020-10-29 14:25:39 +01:00
|
|
|
Constraint* MakeDistribute(const std::vector<IntVar*>& vars,
|
|
|
|
|
const std::vector<IntVar*>& cards);
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Aggregated version of count with bounded cardinalities:
|
|
|
|
|
/// forall j in 0 .. card_size - 1: card_min <= |{i | v[i] == j}| <= card_max
|
2021-04-01 12:13:35 +02:00
|
|
|
Constraint* MakeDistribute(const std::vector<IntVar*>& vars, int64_t card_min,
|
|
|
|
|
int64_t card_max, int64_t card_size);
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Aggregated version of count with bounded cardinalities:
|
|
|
|
|
/// forall j in 0 .. card_size - 1:
|
|
|
|
|
/// card_min[j] <= |{i | v[i] == j}| <= card_max[j]
|
2020-10-29 14:25:39 +01:00
|
|
|
Constraint* MakeDistribute(const std::vector<IntVar*>& vars,
|
2021-04-01 12:13:35 +02:00
|
|
|
const std::vector<int64_t>& card_min,
|
|
|
|
|
const std::vector<int64_t>& card_max);
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Aggregated version of count with bounded cardinalities:
|
|
|
|
|
/// forall j in 0 .. card_size - 1:
|
|
|
|
|
/// card_min[j] <= |{i | v[i] == j}| <= card_max[j]
|
2020-10-29 14:25:39 +01:00
|
|
|
Constraint* MakeDistribute(const std::vector<IntVar*>& vars,
|
|
|
|
|
const std::vector<int>& card_min,
|
|
|
|
|
const std::vector<int>& card_max);
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Aggregated version of count with bounded cardinalities:
|
|
|
|
|
/// forall j in 0 .. card_size - 1:
|
|
|
|
|
/// card_min[j] <= |{i | v[i] == values[j]}| <= card_max[j]
|
2020-10-29 14:25:39 +01:00
|
|
|
Constraint* MakeDistribute(const std::vector<IntVar*>& vars,
|
2021-04-01 12:13:35 +02:00
|
|
|
const std::vector<int64_t>& values,
|
|
|
|
|
const std::vector<int64_t>& card_min,
|
|
|
|
|
const std::vector<int64_t>& card_max);
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Aggregated version of count with bounded cardinalities:
|
|
|
|
|
/// forall j in 0 .. card_size - 1:
|
|
|
|
|
/// card_min[j] <= |{i | v[i] == values[j]}| <= card_max[j]
|
2020-10-29 14:25:39 +01:00
|
|
|
Constraint* MakeDistribute(const std::vector<IntVar*>& vars,
|
|
|
|
|
const std::vector<int>& values,
|
|
|
|
|
const std::vector<int>& card_min,
|
|
|
|
|
const std::vector<int>& card_max);
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Deviation constraint:
|
|
|
|
|
/// sum_i |n * vars[i] - total_sum| <= deviation_var and
|
|
|
|
|
/// sum_i vars[i] == total_sum
|
|
|
|
|
/// n = #vars
|
2020-10-29 14:25:39 +01:00
|
|
|
Constraint* MakeDeviation(const std::vector<IntVar*>& vars,
|
2023-05-31 14:27:08 +02:00
|
|
|
IntVar* deviation_var, int64_t total_sum);
|
2011-06-22 08:37:18 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// All variables are pairwise different. This corresponds to the
|
|
|
|
|
/// stronger version of the propagation algorithm.
|
2020-10-29 14:25:39 +01:00
|
|
|
Constraint* MakeAllDifferent(const std::vector<IntVar*>& vars);
|
2012-01-25 18:03:36 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// All variables are pairwise different. If 'stronger_propagation'
|
|
|
|
|
/// is true, stronger, and potentially slower propagation will
|
|
|
|
|
/// occur. This API will be deprecated in the future.
|
2020-10-29 14:25:39 +01:00
|
|
|
Constraint* MakeAllDifferent(const std::vector<IntVar*>& vars,
|
2012-01-25 18:03:36 +00:00
|
|
|
bool stronger_propagation);
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// All variables are pairwise different, unless they are assigned to
|
|
|
|
|
/// the escape value.
|
2020-10-29 14:25:39 +01:00
|
|
|
Constraint* MakeAllDifferentExcept(const std::vector<IntVar*>& vars,
|
2021-04-01 12:13:35 +02:00
|
|
|
int64_t escape_value);
|
2019-07-05 00:25:55 +02:00
|
|
|
// TODO(user): Do we need a version with an array of escape values.
|
|
|
|
|
|
|
|
|
|
/// Creates a constraint binding the arrays of variables "vars" and
|
|
|
|
|
/// "sorted_vars": sorted_vars[0] must be equal to the minimum of all
|
|
|
|
|
/// variables in vars, and so on: the value of sorted_vars[i] must be
|
|
|
|
|
/// equal to the i-th value of variables invars.
|
|
|
|
|
///
|
|
|
|
|
/// This constraint propagates in both directions: from "vars" to
|
|
|
|
|
/// "sorted_vars" and vice-versa.
|
|
|
|
|
///
|
|
|
|
|
/// Behind the scenes, this constraint maintains that:
|
|
|
|
|
/// - sorted is always increasing.
|
|
|
|
|
/// - whatever the values of vars, there exists a permutation that
|
|
|
|
|
/// injects its values into the sorted variables.
|
|
|
|
|
///
|
|
|
|
|
/// For more info, please have a look at:
|
|
|
|
|
/// https://mpi-inf.mpg.de/~mehlhorn/ftp/Mehlhorn-Thiel.pdf
|
2020-10-29 14:25:39 +01:00
|
|
|
Constraint* MakeSortingConstraint(const std::vector<IntVar*>& vars,
|
|
|
|
|
const std::vector<IntVar*>& sorted);
|
2019-11-20 14:28:11 -08:00
|
|
|
// TODO(user): Add void MakeSortedArray(
|
|
|
|
|
// const std::vector<IntVar*>& vars,
|
|
|
|
|
// std::vector<IntVar*>* const sorted);
|
2012-04-05 20:24:29 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Creates a constraint that enforces that left is lexicographically less
|
|
|
|
|
/// than right.
|
2020-10-29 14:25:39 +01:00
|
|
|
Constraint* MakeLexicalLess(const std::vector<IntVar*>& left,
|
|
|
|
|
const std::vector<IntVar*>& right);
|
2013-12-20 10:44:30 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Creates a constraint that enforces that left is lexicographically less
|
|
|
|
|
/// than or equal to right.
|
2020-10-29 14:25:39 +01:00
|
|
|
Constraint* MakeLexicalLessOrEqual(const std::vector<IntVar*>& left,
|
|
|
|
|
const std::vector<IntVar*>& right);
|
2013-12-20 10:44:30 +00:00
|
|
|
|
2023-05-24 15:32:06 +02:00
|
|
|
/// Creates a constraint that enforces that left is lexicographically less
|
|
|
|
|
/// than or equal to right with an offset. This means that for the first index
|
|
|
|
|
/// i such that left[i] is not in [right[i] - (offset[i] - 1), right[i]],
|
|
|
|
|
/// left[i] + offset[i] <= right[i]. Offset values must be > 0.
|
|
|
|
|
Constraint* MakeLexicalLessOrEqualWithOffsets(std::vector<IntVar*> left,
|
|
|
|
|
std::vector<IntVar*> right,
|
|
|
|
|
std::vector<int64_t> offsets);
|
|
|
|
|
|
|
|
|
|
// Semi-reified version of the above: boolvar -> LexLE(left, right, offsets).
|
|
|
|
|
Constraint* MakeIsLexicalLessOrEqualWithOffsetsCt(
|
|
|
|
|
std::vector<IntVar*> left, std::vector<IntVar*> right,
|
|
|
|
|
std::vector<int64_t> offsets, IntVar* boolvar);
|
|
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Creates a constraint that enforces that 'left' and 'right' both
|
|
|
|
|
/// represent permutations of [0..left.size()-1], and that 'right' is
|
|
|
|
|
/// the inverse permutation of 'left', i.e. for all i in
|
|
|
|
|
/// [0..left.size()-1], right[left[i]] = i.
|
2020-10-29 14:25:39 +01:00
|
|
|
Constraint* MakeInversePermutationConstraint(
|
|
|
|
|
const std::vector<IntVar*>& left, const std::vector<IntVar*>& right);
|
2014-04-19 08:53:33 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Creates a constraint that binds the index variable to the index of the
|
|
|
|
|
/// first variable with the maximum value.
|
2020-10-29 14:25:39 +01:00
|
|
|
Constraint* MakeIndexOfFirstMaxValueConstraint(
|
|
|
|
|
IntVar* index, const std::vector<IntVar*>& vars);
|
2015-07-13 17:08:20 -07:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Creates a constraint that binds the index variable to the index of the
|
|
|
|
|
/// first variable with the minimum value.
|
2020-10-29 14:25:39 +01:00
|
|
|
Constraint* MakeIndexOfFirstMinValueConstraint(
|
|
|
|
|
IntVar* index, const std::vector<IntVar*>& vars);
|
2015-07-13 17:08:20 -07:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Creates a constraint that states that all variables in the first
|
|
|
|
|
/// vector are different from all variables in the second
|
|
|
|
|
/// group. Thus the set of values in the first vector does not
|
|
|
|
|
/// intersect with the set of values in the second vector.
|
2020-10-29 14:25:39 +01:00
|
|
|
Constraint* MakeNullIntersect(const std::vector<IntVar*>& first_vars,
|
|
|
|
|
const std::vector<IntVar*>& second_vars);
|
2013-01-10 17:01:34 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Creates a constraint that states that all variables in the first
|
|
|
|
|
/// vector are different from all variables from the second group,
|
|
|
|
|
/// unless they are assigned to the escape value. Thus the set of
|
|
|
|
|
/// values in the first vector minus the escape value does not
|
|
|
|
|
/// intersect with the set of values in the second vector.
|
2020-10-29 14:25:39 +01:00
|
|
|
Constraint* MakeNullIntersectExcept(const std::vector<IntVar*>& first_vars,
|
|
|
|
|
const std::vector<IntVar*>& second_vars,
|
2021-04-01 12:13:35 +02:00
|
|
|
int64_t escape_value);
|
2013-01-10 17:01:34 +00:00
|
|
|
|
|
|
|
|
// TODO(user): Implement MakeAllNullIntersect taking an array of
|
|
|
|
|
// variable vectors.
|
|
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Prevent cycles. The "nexts" variables represent the next in the chain.
|
|
|
|
|
/// "active" variables indicate if the corresponding next variable is active;
|
|
|
|
|
/// this could be useful to model unperformed nodes in a routing problem.
|
|
|
|
|
/// A callback can be added to specify sink values (by default sink values
|
|
|
|
|
/// are values >= vars.size()). Ownership of the callback is passed to the
|
|
|
|
|
/// constraint.
|
|
|
|
|
/// If assume_paths is either not specified or true, the constraint assumes
|
|
|
|
|
/// the "nexts" variables represent paths (and performs a faster propagation);
|
|
|
|
|
/// otherwise the constraint assumes they represent a forest.
|
2020-10-29 14:25:39 +01:00
|
|
|
Constraint* MakeNoCycle(const std::vector<IntVar*>& nexts,
|
|
|
|
|
const std::vector<IntVar*>& active,
|
2015-08-13 16:00:54 +02:00
|
|
|
IndexFilter1 sink_handler = nullptr);
|
2020-10-29 14:25:39 +01:00
|
|
|
Constraint* MakeNoCycle(const std::vector<IntVar*>& nexts,
|
|
|
|
|
const std::vector<IntVar*>& active,
|
2015-08-13 16:00:54 +02:00
|
|
|
IndexFilter1 sink_handler, bool assume_paths);
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Force the "nexts" variable to create a complete Hamiltonian path.
|
2020-10-29 14:25:39 +01:00
|
|
|
Constraint* MakeCircuit(const std::vector<IntVar*>& nexts);
|
2013-07-24 00:28:11 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Force the "nexts" variable to create a complete Hamiltonian path
|
|
|
|
|
/// for those that do not loop upon themselves.
|
2020-10-29 14:25:39 +01:00
|
|
|
Constraint* MakeSubCircuit(const std::vector<IntVar*>& nexts);
|
2013-09-18 13:58:17 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Creates a constraint which accumulates values along a path such that:
|
|
|
|
|
/// cumuls[next[i]] = cumuls[i] + transits[i].
|
|
|
|
|
/// Active variables indicate if the corresponding next variable is active;
|
|
|
|
|
/// this could be useful to model unperformed nodes in a routing problem.
|
2020-10-29 14:25:39 +01:00
|
|
|
Constraint* MakePathCumul(const std::vector<IntVar*>& nexts,
|
|
|
|
|
const std::vector<IntVar*>& active,
|
|
|
|
|
const std::vector<IntVar*>& cumuls,
|
|
|
|
|
const std::vector<IntVar*>& transits);
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Delayed version of the same constraint: propagation on the nexts variables
|
|
|
|
|
/// is delayed until all constraints have propagated.
|
2014-03-12 17:30:11 +00:00
|
|
|
// TODO(user): Merge with other path-cumuls constraints.
|
2020-10-29 14:25:39 +01:00
|
|
|
Constraint* MakeDelayedPathCumul(const std::vector<IntVar*>& nexts,
|
|
|
|
|
const std::vector<IntVar*>& active,
|
|
|
|
|
const std::vector<IntVar*>& cumuls,
|
|
|
|
|
const std::vector<IntVar*>& transits);
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Creates a constraint which accumulates values along a path such that:
|
|
|
|
|
/// cumuls[next[i]] = cumuls[i] + transit_evaluator(i, next[i]).
|
|
|
|
|
/// Active variables indicate if the corresponding next variable is active;
|
|
|
|
|
/// this could be useful to model unperformed nodes in a routing problem.
|
|
|
|
|
/// Ownership of transit_evaluator is taken and it must be a repeatable
|
|
|
|
|
/// callback.
|
2020-10-29 14:25:39 +01:00
|
|
|
Constraint* MakePathCumul(const std::vector<IntVar*>& nexts,
|
|
|
|
|
const std::vector<IntVar*>& active,
|
|
|
|
|
const std::vector<IntVar*>& cumuls,
|
2015-08-13 16:00:54 +02:00
|
|
|
IndexEvaluator2 transit_evaluator);
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Creates a constraint which accumulates values along a path such that:
|
|
|
|
|
/// cumuls[next[i]] = cumuls[i] + transit_evaluator(i, next[i]) + slacks[i].
|
|
|
|
|
/// Active variables indicate if the corresponding next variable is active;
|
|
|
|
|
/// this could be useful to model unperformed nodes in a routing problem.
|
|
|
|
|
/// Ownership of transit_evaluator is taken and it must be a repeatable
|
|
|
|
|
/// callback.
|
2020-10-29 14:25:39 +01:00
|
|
|
Constraint* MakePathCumul(const std::vector<IntVar*>& nexts,
|
|
|
|
|
const std::vector<IntVar*>& active,
|
|
|
|
|
const std::vector<IntVar*>& cumuls,
|
|
|
|
|
const std::vector<IntVar*>& slacks,
|
2015-08-13 16:00:54 +02:00
|
|
|
IndexEvaluator2 transit_evaluator);
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Constraint enforcing that status[i] is true iff there's a path defined on
|
|
|
|
|
/// next variables from sources[i] to sinks[i].
|
2016-09-14 15:32:21 +02:00
|
|
|
// TODO(user): Only does checking on WhenBound events on next variables.
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Check whether more propagation is needed.
|
2020-10-29 14:25:39 +01:00
|
|
|
Constraint* MakePathConnected(std::vector<IntVar*> nexts,
|
2021-04-01 12:13:35 +02:00
|
|
|
std::vector<int64_t> sources,
|
|
|
|
|
std::vector<int64_t> sinks,
|
2020-10-29 14:25:39 +01:00
|
|
|
std::vector<IntVar*> status);
|
2016-10-05 13:45:23 +02:00
|
|
|
#ifndef SWIG
|
2021-08-15 23:11:16 +07:00
|
|
|
/// Constraint enforcing, for each pair (i,j) in precedences, i to be before j
|
2019-07-05 00:25:55 +02:00
|
|
|
/// in paths defined by next variables.
|
2016-10-05 13:45:23 +02:00
|
|
|
// TODO(user): This constraint does not make holes in variable domains;
|
2019-07-05 00:25:55 +02:00
|
|
|
/// the implementation can easily be modified to do that; evaluate the impact
|
|
|
|
|
/// on models solved with local search.
|
2020-10-29 14:25:39 +01:00
|
|
|
Constraint* MakePathPrecedenceConstraint(
|
|
|
|
|
std::vector<IntVar*> nexts,
|
2020-11-01 11:47:28 +01:00
|
|
|
const std::vector<std::pair<int, int>>& precedences);
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Same as MakePathPrecedenceConstraint but ensures precedence pairs on some
|
|
|
|
|
/// paths follow a LIFO or FIFO order.
|
|
|
|
|
/// LIFO order: given 2 pairs (a,b) and (c,d), if a is before c on the path
|
|
|
|
|
/// then d must be before b or b must be before c.
|
|
|
|
|
/// FIFO order: given 2 pairs (a,b) and (c,d), if a is before c on the path
|
|
|
|
|
/// then b must be before d.
|
|
|
|
|
/// LIFO (resp. FIFO) orders are enforced only on paths starting by indices in
|
|
|
|
|
/// lifo_path_starts (resp. fifo_path_start).
|
2020-10-29 14:25:39 +01:00
|
|
|
Constraint* MakePathPrecedenceConstraint(
|
|
|
|
|
std::vector<IntVar*> nexts,
|
2020-11-01 11:47:28 +01:00
|
|
|
const std::vector<std::pair<int, int>>& precedences,
|
2023-09-25 18:06:35 +02:00
|
|
|
absl::Span<const int> lifo_path_starts,
|
|
|
|
|
absl::Span<const int> fifo_path_starts);
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Same as MakePathPrecedenceConstraint but will force i to be before j if
|
|
|
|
|
/// the sum of transits on the path from i to j is strictly positive.
|
2020-10-29 14:25:39 +01:00
|
|
|
Constraint* MakePathTransitPrecedenceConstraint(
|
|
|
|
|
std::vector<IntVar*> nexts, std::vector<IntVar*> transits,
|
2020-11-01 11:47:28 +01:00
|
|
|
const std::vector<std::pair<int, int>>& precedences);
|
2023-05-24 15:32:06 +02:00
|
|
|
/// A constraint that maintains the energy cost of paths.
|
|
|
|
|
/// Energy is the integral of force applied over distance.
|
|
|
|
|
/// More formally, the energy used on a path is:
|
|
|
|
|
/// energy[path] = sum(node | paths[node] == path /\ node not end)
|
|
|
|
|
/// forces[next[node]] * distances[node]
|
|
|
|
|
/// where forces[n] is the force needed to move loads accumulated until, but
|
|
|
|
|
/// excluding weight and distances[n] is the distance from n to its successor.
|
|
|
|
|
/// For instance, if a path has a route with two pickup/delivery pairs
|
|
|
|
|
/// where the first shipment weighs 1 unit, the second weighs 2 units,
|
|
|
|
|
/// and the distance between nodes is one, the {force/distance} of nodes
|
|
|
|
|
/// would be: start{0/1} P1{0/1} P2{1/1} D1{3/1} D2{2/1} end{0/0}.
|
|
|
|
|
/// The energy would be 0*1 + 1*1 + 3*1 + 2*1 + 0*1.
|
2024-11-18 11:32:13 +01:00
|
|
|
/// The cost per unit of energy is cost_per_unit_below_threshold until the
|
|
|
|
|
/// force reaches the threshold, then it is cost_per_unit_above_threshold:
|
|
|
|
|
/// min(threshold, force.CumulVar(Next(node))) * distance.TransitVar(node) *
|
|
|
|
|
/// cost_per_unit_below_threshold + max(0, force.CumulVar(Next(node)) -
|
|
|
|
|
/// threshold) * distance.TransitVar(node) * cost_per_unit_above_threshold.
|
2023-05-24 15:32:06 +02:00
|
|
|
struct PathEnergyCostConstraintSpecification {
|
2024-11-18 11:32:13 +01:00
|
|
|
struct EnergyCost {
|
|
|
|
|
int64_t threshold;
|
|
|
|
|
int64_t cost_per_unit_below_threshold;
|
|
|
|
|
int64_t cost_per_unit_above_threshold;
|
|
|
|
|
bool IsNull() const {
|
|
|
|
|
return (cost_per_unit_below_threshold == 0 || threshold == 0) &&
|
|
|
|
|
(cost_per_unit_above_threshold == 0 || threshold == kint64max);
|
|
|
|
|
}
|
|
|
|
|
};
|
2023-05-24 15:32:06 +02:00
|
|
|
std::vector<IntVar*> nexts;
|
|
|
|
|
std::vector<IntVar*> paths;
|
|
|
|
|
std::vector<IntVar*> forces;
|
|
|
|
|
std::vector<IntVar*> distances;
|
2024-11-18 11:32:13 +01:00
|
|
|
std::vector<EnergyCost> path_energy_costs;
|
2023-05-24 15:32:06 +02:00
|
|
|
std::vector<bool> path_used_when_empty;
|
|
|
|
|
std::vector<int64_t> path_starts;
|
|
|
|
|
std::vector<int64_t> path_ends;
|
|
|
|
|
std::vector<IntVar*> costs;
|
|
|
|
|
};
|
|
|
|
|
Constraint* MakePathEnergyCostConstraint(
|
|
|
|
|
PathEnergyCostConstraintSpecification specification);
|
2020-11-01 11:47:28 +01:00
|
|
|
#endif // !SWIG
|
2019-07-05 00:25:55 +02:00
|
|
|
/// This constraint maps the domain of 'var' onto the array of
|
|
|
|
|
/// variables 'actives'. That is
|
|
|
|
|
/// for all i in [0 .. size - 1]: actives[i] == 1 <=> var->Contains(i);
|
2023-05-31 14:27:08 +02:00
|
|
|
Constraint* MakeMapDomain(IntVar* var, const std::vector<IntVar*>& actives);
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// This method creates a constraint where the graph of the relation
|
|
|
|
|
/// between the variables is given in extension. There are 'arity'
|
|
|
|
|
/// variables involved in the relation and the graph is given by a
|
|
|
|
|
/// integer tuple set.
|
2020-10-29 14:25:39 +01:00
|
|
|
Constraint* MakeAllowedAssignments(const std::vector<IntVar*>& vars,
|
|
|
|
|
const IntTupleSet& tuples);
|
2011-05-20 14:01:28 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// This constraint create a finite automaton that will check the
|
|
|
|
|
/// sequence of variables vars. It uses a transition table called
|
|
|
|
|
/// 'transition_table'. Each transition is a triple
|
|
|
|
|
/// (current_state, variable_value, new_state).
|
|
|
|
|
/// The initial state is given, and the set of accepted states is decribed
|
|
|
|
|
/// by 'final_states'. These states are hidden inside the constraint.
|
|
|
|
|
/// Only the transitions (i.e. the variables) are visible.
|
2021-04-11 11:29:32 +02:00
|
|
|
Constraint* MakeTransitionConstraint(
|
|
|
|
|
const std::vector<IntVar*>& vars, const IntTupleSet& transition_table,
|
|
|
|
|
int64_t initial_state, const std::vector<int64_t>& final_states);
|
2010-11-07 18:46:11 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// This constraint create a finite automaton that will check the
|
|
|
|
|
/// sequence of variables vars. It uses a transition table called
|
|
|
|
|
/// 'transition_table'. Each transition is a triple
|
|
|
|
|
/// (current_state, variable_value, new_state).
|
|
|
|
|
/// The initial state is given, and the set of accepted states is decribed
|
|
|
|
|
/// by 'final_states'. These states are hidden inside the constraint.
|
|
|
|
|
/// Only the transitions (i.e. the variables) are visible.
|
2020-10-29 14:25:39 +01:00
|
|
|
Constraint* MakeTransitionConstraint(const std::vector<IntVar*>& vars,
|
|
|
|
|
const IntTupleSet& transition_table,
|
2021-04-01 12:13:35 +02:00
|
|
|
int64_t initial_state,
|
2020-10-29 14:25:39 +01:00
|
|
|
const std::vector<int>& final_states);
|
2011-05-20 14:01:28 +00:00
|
|
|
|
2012-03-19 17:14:57 +00:00
|
|
|
#if defined(SWIGPYTHON)
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Compatibility layer for Python API.
|
2020-10-29 14:25:39 +01:00
|
|
|
Constraint* MakeAllowedAssignments(
|
|
|
|
|
const std::vector<IntVar*>& vars,
|
2021-04-01 12:13:35 +02:00
|
|
|
const std::vector<std::vector<int64_t> /*keep for swig*/>& raw_tuples) {
|
2012-03-19 17:14:57 +00:00
|
|
|
IntTupleSet tuples(vars.size());
|
|
|
|
|
tuples.InsertAll(raw_tuples);
|
|
|
|
|
return MakeAllowedAssignments(vars, tuples);
|
|
|
|
|
}
|
|
|
|
|
|
2020-10-29 14:25:39 +01:00
|
|
|
Constraint* MakeTransitionConstraint(
|
|
|
|
|
const std::vector<IntVar*>& vars,
|
2021-04-11 11:29:32 +02:00
|
|
|
const std::vector<std::vector<int64_t> /*keep for swig*/>&
|
|
|
|
|
raw_transitions,
|
2021-04-01 12:13:35 +02:00
|
|
|
int64_t initial_state, const std::vector<int>& final_states) {
|
2012-03-19 17:14:57 +00:00
|
|
|
IntTupleSet transitions(3);
|
|
|
|
|
transitions.InsertAll(raw_transitions);
|
2013-10-10 15:23:20 +00:00
|
|
|
return MakeTransitionConstraint(vars, transitions, initial_state,
|
2012-03-19 17:14:57 +00:00
|
|
|
final_states);
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// This constraint states that all the boxes must not overlap.
|
|
|
|
|
/// The coordinates of box i are:
|
|
|
|
|
/// (x_vars[i], y_vars[i]),
|
|
|
|
|
/// (x_vars[i], y_vars[i] + y_size[i]),
|
|
|
|
|
/// (x_vars[i] + x_size[i], y_vars[i]),
|
|
|
|
|
/// (x_vars[i] + x_size[i], y_vars[i] + y_size[i]).
|
|
|
|
|
/// The sizes must be non-negative. Boxes with a zero dimension can be
|
|
|
|
|
/// pushed like any box.
|
2020-10-29 14:25:39 +01:00
|
|
|
Constraint* MakeNonOverlappingBoxesConstraint(
|
|
|
|
|
const std::vector<IntVar*>& x_vars, const std::vector<IntVar*>& y_vars,
|
|
|
|
|
const std::vector<IntVar*>& x_size, const std::vector<IntVar*>& y_size);
|
|
|
|
|
Constraint* MakeNonOverlappingBoxesConstraint(
|
|
|
|
|
const std::vector<IntVar*>& x_vars, const std::vector<IntVar*>& y_vars,
|
2023-09-25 18:06:35 +02:00
|
|
|
absl::Span<const int64_t> x_size, absl::Span<const int64_t> y_size);
|
2020-10-29 14:25:39 +01:00
|
|
|
Constraint* MakeNonOverlappingBoxesConstraint(
|
|
|
|
|
const std::vector<IntVar*>& x_vars, const std::vector<IntVar*>& y_vars,
|
2023-09-25 18:06:35 +02:00
|
|
|
absl::Span<const int> x_size, absl::Span<const int> y_size);
|
2011-05-20 14:01:28 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// This constraint states that all the boxes must not overlap.
|
|
|
|
|
/// The coordinates of box i are:
|
|
|
|
|
/// (x_vars[i], y_vars[i]),
|
|
|
|
|
/// (x_vars[i], y_vars[i] + y_size[i]),
|
|
|
|
|
/// (x_vars[i] + x_size[i], y_vars[i]),
|
|
|
|
|
/// (x_vars[i] + x_size[i], y_vars[i] + y_size[i]).
|
|
|
|
|
/// The sizes must be positive.
|
|
|
|
|
/// Boxes with a zero dimension can be placed anywhere.
|
2020-10-29 14:25:39 +01:00
|
|
|
Constraint* MakeNonOverlappingNonStrictBoxesConstraint(
|
|
|
|
|
const std::vector<IntVar*>& x_vars, const std::vector<IntVar*>& y_vars,
|
|
|
|
|
const std::vector<IntVar*>& x_size, const std::vector<IntVar*>& y_size);
|
|
|
|
|
Constraint* MakeNonOverlappingNonStrictBoxesConstraint(
|
|
|
|
|
const std::vector<IntVar*>& x_vars, const std::vector<IntVar*>& y_vars,
|
2023-09-25 18:06:35 +02:00
|
|
|
absl::Span<const int64_t> x_size, absl::Span<const int64_t> y_size);
|
2020-10-29 14:25:39 +01:00
|
|
|
Constraint* MakeNonOverlappingNonStrictBoxesConstraint(
|
|
|
|
|
const std::vector<IntVar*>& x_vars, const std::vector<IntVar*>& y_vars,
|
2023-09-25 18:06:35 +02:00
|
|
|
absl::Span<const int> x_size, absl::Span<const int> y_size);
|
2015-07-20 16:21:56 -07:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// This constraint packs all variables onto 'number_of_bins'
|
|
|
|
|
/// variables. For any given variable, a value of 'number_of_bins'
|
|
|
|
|
/// indicates that the variable is not assigned to any bin.
|
|
|
|
|
/// Dimensions, i.e., cumulative constraints on this packing, can be
|
|
|
|
|
/// added directly from the pack class.
|
2020-10-29 14:25:39 +01:00
|
|
|
Pack* MakePack(const std::vector<IntVar*>& vars, int number_of_bins);
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Creates an interval var with a fixed duration. The duration must
|
|
|
|
|
/// be greater than 0. If optional is true, then the interval can be
|
|
|
|
|
/// performed or unperformed. If optional is false, then the interval
|
|
|
|
|
/// is always performed.
|
2021-04-11 11:29:32 +02:00
|
|
|
IntervalVar* MakeFixedDurationIntervalVar(int64_t start_min,
|
|
|
|
|
int64_t start_max, int64_t duration,
|
|
|
|
|
bool optional,
|
2020-10-29 14:25:39 +01:00
|
|
|
const std::string& name);
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// This method fills the vector with 'count' interval variables built with
|
|
|
|
|
/// the corresponding parameters.
|
2023-05-31 14:27:08 +02:00
|
|
|
void MakeFixedDurationIntervalVarArray(int count, int64_t start_min,
|
|
|
|
|
int64_t start_max, int64_t duration,
|
2023-11-09 13:46:25 +01:00
|
|
|
bool optional, absl::string_view name,
|
2023-05-31 14:27:08 +02:00
|
|
|
std::vector<IntervalVar*>* array);
|
2012-06-12 15:20:03 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Creates a performed interval var with a fixed duration. The duration must
|
|
|
|
|
/// be greater than 0.
|
2023-05-31 14:27:08 +02:00
|
|
|
IntervalVar* MakeFixedDurationIntervalVar(IntVar* start_variable,
|
2021-04-01 12:13:35 +02:00
|
|
|
int64_t duration,
|
2020-10-29 14:25:39 +01:00
|
|
|
const std::string& name);
|
2012-06-12 15:20:03 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Creates an interval var with a fixed duration, and performed_variable.
|
|
|
|
|
/// The duration must be greater than 0.
|
2023-05-31 14:27:08 +02:00
|
|
|
IntervalVar* MakeFixedDurationIntervalVar(IntVar* start_variable,
|
2021-04-01 12:13:35 +02:00
|
|
|
int64_t duration,
|
2023-05-31 14:27:08 +02:00
|
|
|
IntVar* performed_variable,
|
2020-10-29 14:25:39 +01:00
|
|
|
const std::string& name);
|
2014-05-26 17:59:03 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// This method fills the vector with 'count' interval var built with
|
|
|
|
|
/// the corresponding start variables.
|
2016-11-23 22:08:43 +01:00
|
|
|
void MakeFixedDurationIntervalVarArray(
|
2021-04-01 12:13:35 +02:00
|
|
|
const std::vector<IntVar*>& start_variables, int64_t duration,
|
2023-11-09 13:46:25 +01:00
|
|
|
absl::string_view name, std::vector<IntervalVar*>* array);
|
2012-06-12 15:20:03 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// This method fills the vector with interval variables built with
|
|
|
|
|
/// the corresponding start variables.
|
2016-11-23 22:08:43 +01:00
|
|
|
void MakeFixedDurationIntervalVarArray(
|
2020-10-29 14:25:39 +01:00
|
|
|
const std::vector<IntVar*>& start_variables,
|
2023-11-09 13:46:25 +01:00
|
|
|
absl::Span<const int64_t> durations, absl::string_view name,
|
2023-05-31 14:27:08 +02:00
|
|
|
std::vector<IntervalVar*>* array);
|
2019-07-05 00:25:55 +02:00
|
|
|
/// This method fills the vector with interval variables built with
|
|
|
|
|
/// the corresponding start variables.
|
2016-11-23 22:08:43 +01:00
|
|
|
void MakeFixedDurationIntervalVarArray(
|
2020-10-29 14:25:39 +01:00
|
|
|
const std::vector<IntVar*>& start_variables,
|
2023-11-09 13:46:25 +01:00
|
|
|
absl::Span<const int> durations, absl::string_view name,
|
2023-05-31 14:27:08 +02:00
|
|
|
std::vector<IntervalVar*>* array);
|
2011-01-06 17:40:30 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// This method fills the vector with interval variables built with
|
|
|
|
|
/// the corresponding start and performed variables.
|
2015-04-29 19:40:01 +02:00
|
|
|
void MakeFixedDurationIntervalVarArray(
|
2020-10-29 14:25:39 +01:00
|
|
|
const std::vector<IntVar*>& start_variables,
|
2023-09-25 18:06:35 +02:00
|
|
|
absl::Span<const int64_t> durations,
|
2023-11-09 13:46:25 +01:00
|
|
|
const std::vector<IntVar*>& performed_variables, absl::string_view name,
|
2023-05-31 14:27:08 +02:00
|
|
|
std::vector<IntervalVar*>* array);
|
2014-05-26 17:59:03 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// This method fills the vector with interval variables built with
|
|
|
|
|
/// the corresponding start and performed variables.
|
2015-04-29 19:40:01 +02:00
|
|
|
void MakeFixedDurationIntervalVarArray(
|
2020-10-29 14:25:39 +01:00
|
|
|
const std::vector<IntVar*>& start_variables,
|
2023-09-25 18:06:35 +02:00
|
|
|
absl::Span<const int> durations,
|
2023-11-09 13:46:25 +01:00
|
|
|
const std::vector<IntVar*>& performed_variables, absl::string_view name,
|
2023-05-31 14:27:08 +02:00
|
|
|
std::vector<IntervalVar*>* array);
|
2014-05-26 17:59:03 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Creates a fixed and performed interval.
|
2021-04-01 12:13:35 +02:00
|
|
|
IntervalVar* MakeFixedInterval(int64_t start, int64_t duration,
|
2020-10-29 14:25:39 +01:00
|
|
|
const std::string& name);
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Creates an interval var by specifying the bounds on start,
|
|
|
|
|
/// duration, and end.
|
2021-04-01 12:13:35 +02:00
|
|
|
IntervalVar* MakeIntervalVar(int64_t start_min, int64_t start_max,
|
|
|
|
|
int64_t duration_min, int64_t duration_max,
|
|
|
|
|
int64_t end_min, int64_t end_max, bool optional,
|
2020-10-29 14:25:39 +01:00
|
|
|
const std::string& name);
|
2013-06-11 14:49:19 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// This method fills the vector with 'count' interval var built with
|
|
|
|
|
/// the corresponding parameters.
|
2021-04-01 12:13:35 +02:00
|
|
|
void MakeIntervalVarArray(int count, int64_t start_min, int64_t start_max,
|
|
|
|
|
int64_t duration_min, int64_t duration_max,
|
|
|
|
|
int64_t end_min, int64_t end_max, bool optional,
|
2023-11-09 13:46:25 +01:00
|
|
|
absl::string_view name,
|
2023-05-31 14:27:08 +02:00
|
|
|
std::vector<IntervalVar*>* array);
|
2013-06-11 14:49:19 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Creates an interval var that is the mirror image of the given one, that
|
|
|
|
|
/// is, the interval var obtained by reversing the axis.
|
2023-05-31 14:27:08 +02:00
|
|
|
IntervalVar* MakeMirrorInterval(IntervalVar* interval_var);
|
2010-10-27 13:25:37 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Creates an interval var with a fixed duration whose start is
|
|
|
|
|
/// synchronized with the start of another interval, with a given
|
|
|
|
|
/// offset. The performed status is also in sync with the performed
|
|
|
|
|
/// status of the given interval variable.
|
2020-10-29 14:25:39 +01:00
|
|
|
IntervalVar* MakeFixedDurationStartSyncedOnStartIntervalVar(
|
2023-05-31 14:27:08 +02:00
|
|
|
IntervalVar* interval_var, int64_t duration, int64_t offset);
|
2013-06-11 14:49:19 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Creates an interval var with a fixed duration whose start is
|
|
|
|
|
/// synchronized with the end of another interval, with a given
|
|
|
|
|
/// offset. The performed status is also in sync with the performed
|
|
|
|
|
/// status of the given interval variable.
|
2020-10-29 14:25:39 +01:00
|
|
|
IntervalVar* MakeFixedDurationStartSyncedOnEndIntervalVar(
|
2023-05-31 14:27:08 +02:00
|
|
|
IntervalVar* interval_var, int64_t duration, int64_t offset);
|
2013-06-11 14:49:19 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Creates an interval var with a fixed duration whose end is
|
|
|
|
|
/// synchronized with the start of another interval, with a given
|
|
|
|
|
/// offset. The performed status is also in sync with the performed
|
|
|
|
|
/// status of the given interval variable.
|
2020-10-29 14:25:39 +01:00
|
|
|
IntervalVar* MakeFixedDurationEndSyncedOnStartIntervalVar(
|
2023-05-31 14:27:08 +02:00
|
|
|
IntervalVar* interval_var, int64_t duration, int64_t offset);
|
2013-06-11 14:49:19 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Creates an interval var with a fixed duration whose end is
|
|
|
|
|
/// synchronized with the end of another interval, with a given
|
|
|
|
|
/// offset. The performed status is also in sync with the performed
|
|
|
|
|
/// status of the given interval variable.
|
2020-10-29 14:25:39 +01:00
|
|
|
IntervalVar* MakeFixedDurationEndSyncedOnEndIntervalVar(
|
2023-05-31 14:27:08 +02:00
|
|
|
IntervalVar* interval_var, int64_t duration, int64_t offset);
|
2013-06-11 14:49:19 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Creates and returns an interval variable that wraps around the given one,
|
|
|
|
|
/// relaxing the min start and end. Relaxing means making unbounded when
|
|
|
|
|
/// optional. If the variable is non-optional, this method returns
|
|
|
|
|
/// interval_var.
|
|
|
|
|
///
|
|
|
|
|
/// More precisely, such an interval variable behaves as follows:
|
|
|
|
|
/// * When the underlying must be performed, the returned interval variable
|
|
|
|
|
/// behaves exactly as the underlying;
|
|
|
|
|
/// * When the underlying may or may not be performed, the returned interval
|
|
|
|
|
/// variable behaves like the underlying, except that it is unbounded on
|
|
|
|
|
/// the min side;
|
|
|
|
|
/// * When the underlying cannot be performed, the returned interval variable
|
|
|
|
|
/// is of duration 0 and must be performed in an interval unbounded on
|
|
|
|
|
/// both sides.
|
|
|
|
|
///
|
|
|
|
|
/// This is very useful to implement propagators that may only modify
|
|
|
|
|
/// the start max or end max.
|
2023-05-31 14:27:08 +02:00
|
|
|
IntervalVar* MakeIntervalRelaxedMin(IntervalVar* interval_var);
|
2010-11-09 09:30:22 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Creates and returns an interval variable that wraps around the given one,
|
|
|
|
|
/// relaxing the max start and end. Relaxing means making unbounded when
|
|
|
|
|
/// optional. If the variable is non optional, this method returns
|
|
|
|
|
/// interval_var.
|
|
|
|
|
///
|
|
|
|
|
/// More precisely, such an interval variable behaves as follows:
|
|
|
|
|
/// * When the underlying must be performed, the returned interval variable
|
|
|
|
|
/// behaves exactly as the underlying;
|
|
|
|
|
/// * When the underlying may or may not be performed, the returned interval
|
|
|
|
|
/// variable behaves like the underlying, except that it is unbounded on
|
|
|
|
|
/// the max side;
|
|
|
|
|
/// * When the underlying cannot be performed, the returned interval variable
|
|
|
|
|
/// is of duration 0 and must be performed in an interval unbounded on
|
|
|
|
|
/// both sides.
|
|
|
|
|
///
|
|
|
|
|
/// This is very useful for implementing propagators that may only modify
|
|
|
|
|
/// the start min or end min.
|
2023-05-31 14:27:08 +02:00
|
|
|
IntervalVar* MakeIntervalRelaxedMax(IntervalVar* interval_var);
|
2010-11-09 09:30:22 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// This method creates a relation between an interval var and a
|
|
|
|
|
/// date.
|
2023-05-31 14:27:08 +02:00
|
|
|
Constraint* MakeIntervalVarRelation(IntervalVar* t, UnaryIntervalRelation r,
|
|
|
|
|
int64_t d);
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// This method creates a relation between two interval vars.
|
2023-05-31 14:27:08 +02:00
|
|
|
Constraint* MakeIntervalVarRelation(IntervalVar* t1, BinaryIntervalRelation r,
|
|
|
|
|
IntervalVar* t2);
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// This method creates a relation between two interval vars.
|
|
|
|
|
/// The given delay is added to the second interval.
|
|
|
|
|
/// i.e.: t1 STARTS_AFTER_END of t2 with a delay of 2
|
|
|
|
|
/// means t1 will start at least two units of time after the end of t2.
|
2023-05-31 14:27:08 +02:00
|
|
|
Constraint* MakeIntervalVarRelationWithDelay(IntervalVar* t1,
|
2015-05-19 19:50:48 +02:00
|
|
|
BinaryIntervalRelation r,
|
2023-05-31 14:27:08 +02:00
|
|
|
IntervalVar* t2, int64_t delay);
|
2015-05-19 19:50:48 +02:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// This constraint implements a temporal disjunction between two
|
|
|
|
|
/// interval vars t1 and t2. 'alt' indicates which alternative was
|
|
|
|
|
/// chosen (alt == 0 is equivalent to t1 before t2).
|
2023-05-31 14:27:08 +02:00
|
|
|
Constraint* MakeTemporalDisjunction(IntervalVar* t1, IntervalVar* t2,
|
|
|
|
|
IntVar* alt);
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// This constraint implements a temporal disjunction between two
|
|
|
|
|
/// interval vars.
|
2023-05-31 14:27:08 +02:00
|
|
|
Constraint* MakeTemporalDisjunction(IntervalVar* t1, IntervalVar* t2);
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// This constraint forces all interval vars into an non-overlapping
|
|
|
|
|
/// sequence. Intervals with zero duration can be scheduled anywhere.
|
2020-10-29 14:25:39 +01:00
|
|
|
DisjunctiveConstraint* MakeDisjunctiveConstraint(
|
|
|
|
|
const std::vector<IntervalVar*>& intervals, const std::string& name);
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// This constraint forces all interval vars into an non-overlapping
|
|
|
|
|
/// sequence. Intervals with zero durations cannot overlap with over
|
|
|
|
|
/// intervals.
|
2020-10-29 14:25:39 +01:00
|
|
|
DisjunctiveConstraint* MakeStrictDisjunctiveConstraint(
|
|
|
|
|
const std::vector<IntervalVar*>& intervals, const std::string& name);
|
2015-07-20 16:59:30 -07:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// This constraint forces that, for any integer t, the sum of the demands
|
|
|
|
|
/// corresponding to an interval containing t does not exceed the given
|
|
|
|
|
/// capacity.
|
|
|
|
|
///
|
|
|
|
|
/// Intervals and demands should be vectors of equal size.
|
|
|
|
|
///
|
|
|
|
|
/// Demands should only contain non-negative values. Zero values are
|
|
|
|
|
/// supported, and the corresponding intervals are filtered out, as they
|
|
|
|
|
/// neither impact nor are impacted by this constraint.
|
2020-10-29 14:25:39 +01:00
|
|
|
Constraint* MakeCumulative(const std::vector<IntervalVar*>& intervals,
|
2021-04-11 11:29:32 +02:00
|
|
|
const std::vector<int64_t>& demands,
|
|
|
|
|
int64_t capacity, const std::string& name);
|
2010-11-19 18:28:33 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// This constraint forces that, for any integer t, the sum of the demands
|
|
|
|
|
/// corresponding to an interval containing t does not exceed the given
|
|
|
|
|
/// capacity.
|
|
|
|
|
///
|
|
|
|
|
/// Intervals and demands should be vectors of equal size.
|
|
|
|
|
///
|
|
|
|
|
/// Demands should only contain non-negative values. Zero values are
|
|
|
|
|
/// supported, and the corresponding intervals are filtered out, as they
|
|
|
|
|
/// neither impact nor are impacted by this constraint.
|
2020-10-29 14:25:39 +01:00
|
|
|
Constraint* MakeCumulative(const std::vector<IntervalVar*>& intervals,
|
2021-04-01 12:13:35 +02:00
|
|
|
const std::vector<int>& demands, int64_t capacity,
|
2020-10-29 14:25:39 +01:00
|
|
|
const std::string& name);
|
2011-05-20 14:01:28 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// This constraint forces that, for any integer t, the sum of the demands
|
|
|
|
|
/// corresponding to an interval containing t does not exceed the given
|
|
|
|
|
/// capacity.
|
|
|
|
|
///
|
|
|
|
|
/// Intervals and demands should be vectors of equal size.
|
|
|
|
|
///
|
|
|
|
|
/// Demands should only contain non-negative values. Zero values are
|
|
|
|
|
/// supported, and the corresponding intervals are filtered out, as they
|
|
|
|
|
/// neither impact nor are impacted by this constraint.
|
2020-10-29 14:25:39 +01:00
|
|
|
Constraint* MakeCumulative(const std::vector<IntervalVar*>& intervals,
|
2021-04-01 12:13:35 +02:00
|
|
|
const std::vector<int64_t>& demands,
|
2024-01-08 13:18:01 +01:00
|
|
|
IntVar* capacity, absl::string_view name);
|
2012-06-16 06:49:34 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// This constraint enforces that, for any integer t, the sum of the demands
|
|
|
|
|
/// corresponding to an interval containing t does not exceed the given
|
|
|
|
|
/// capacity.
|
|
|
|
|
///
|
|
|
|
|
/// Intervals and demands should be vectors of equal size.
|
|
|
|
|
///
|
|
|
|
|
/// Demands should only contain non-negative values. Zero values are
|
|
|
|
|
/// supported, and the corresponding intervals are filtered out, as they
|
|
|
|
|
/// neither impact nor are impacted by this constraint.
|
2020-10-29 14:25:39 +01:00
|
|
|
Constraint* MakeCumulative(const std::vector<IntervalVar*>& intervals,
|
2023-05-31 14:27:08 +02:00
|
|
|
const std::vector<int>& demands, IntVar* capacity,
|
|
|
|
|
const std::string& name);
|
2012-06-16 06:49:34 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// This constraint enforces that, for any integer t, the sum of demands
|
|
|
|
|
/// corresponding to an interval containing t does not exceed the given
|
|
|
|
|
/// capacity.
|
|
|
|
|
///
|
|
|
|
|
/// Intervals and demands should be vectors of equal size.
|
|
|
|
|
///
|
|
|
|
|
/// Demands should be positive.
|
2020-10-29 14:25:39 +01:00
|
|
|
Constraint* MakeCumulative(const std::vector<IntervalVar*>& intervals,
|
|
|
|
|
const std::vector<IntVar*>& demands,
|
2021-04-01 12:13:35 +02:00
|
|
|
int64_t capacity, const std::string& name);
|
2014-07-04 11:03:57 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// This constraint enforces that, for any integer t, the sum of demands
|
|
|
|
|
/// corresponding to an interval containing t does not exceed the given
|
|
|
|
|
/// capacity.
|
|
|
|
|
///
|
|
|
|
|
/// Intervals and demands should be vectors of equal size.
|
|
|
|
|
///
|
|
|
|
|
/// Demands should be positive.
|
2020-10-29 14:25:39 +01:00
|
|
|
Constraint* MakeCumulative(const std::vector<IntervalVar*>& intervals,
|
|
|
|
|
const std::vector<IntVar*>& demands,
|
2023-05-31 14:27:08 +02:00
|
|
|
IntVar* capacity, const std::string& name);
|
2014-07-04 11:03:57 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// This constraint states that the target_var is the convex hull of
|
|
|
|
|
/// the intervals. If none of the interval variables is performed,
|
|
|
|
|
/// then the target var is unperformed too. Also, if the target
|
|
|
|
|
/// variable is unperformed, then all the intervals variables are
|
|
|
|
|
/// unperformed too.
|
2020-10-29 14:25:39 +01:00
|
|
|
Constraint* MakeCover(const std::vector<IntervalVar*>& vars,
|
2023-05-31 14:27:08 +02:00
|
|
|
IntervalVar* target_var);
|
2013-06-11 14:49:19 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// This constraints states that the two interval variables are equal.
|
2023-05-31 14:27:08 +02:00
|
|
|
Constraint* MakeEquality(IntervalVar* var1, IntervalVar* var2);
|
2013-06-11 14:49:19 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// This method creates an empty assignment.
|
2020-10-29 14:25:39 +01:00
|
|
|
Assignment* MakeAssignment();
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// This method creates an assignment which is a copy of 'a'.
|
2023-05-31 14:27:08 +02:00
|
|
|
Assignment* MakeAssignment(const Assignment* a);
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Collect the first solution of the search.
|
2023-05-31 14:27:08 +02:00
|
|
|
SolutionCollector* MakeFirstSolutionCollector(const Assignment* assignment);
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Collect the first solution of the search. The variables will need to
|
|
|
|
|
/// be added later.
|
2020-10-29 14:25:39 +01:00
|
|
|
SolutionCollector* MakeFirstSolutionCollector();
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Collect the last solution of the search.
|
2023-05-31 14:27:08 +02:00
|
|
|
SolutionCollector* MakeLastSolutionCollector(const Assignment* assignment);
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Collect the last solution of the search. The variables will need to
|
|
|
|
|
/// be added later.
|
2020-10-29 14:25:39 +01:00
|
|
|
SolutionCollector* MakeLastSolutionCollector();
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Collect the solution corresponding to the optimal value of the objective
|
|
|
|
|
/// of 'assignment'; if 'assignment' does not have an objective no solution is
|
|
|
|
|
/// collected. This collector only collects one solution corresponding to the
|
|
|
|
|
/// best objective value (the first one found).
|
2020-10-29 14:25:39 +01:00
|
|
|
SolutionCollector* MakeBestValueSolutionCollector(
|
2023-05-24 15:32:06 +02:00
|
|
|
const Assignment* assignment, bool maximize);
|
|
|
|
|
/// Same as above, but supporting lexicographic objectives; 'maximize'
|
|
|
|
|
/// specifies the optimization direction for each objective in 'assignment'.
|
|
|
|
|
SolutionCollector* MakeBestLexicographicValueSolutionCollector(
|
|
|
|
|
const Assignment* assignment, std::vector<bool> maximize);
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Collect the solution corresponding to the optimal value of the
|
2023-05-24 15:32:06 +02:00
|
|
|
/// objective of the internal assignment; if this assignment does not have an
|
|
|
|
|
/// objective no solution is collected. This collector only collects one
|
|
|
|
|
/// solution corresponding to the best objective value (the first one found).
|
|
|
|
|
/// The variables and objective(s) will need to be added later.
|
2020-10-29 14:25:39 +01:00
|
|
|
SolutionCollector* MakeBestValueSolutionCollector(bool maximize);
|
2023-05-24 15:32:06 +02:00
|
|
|
/// Same as above, but supporting lexicographic objectives; 'maximize'
|
|
|
|
|
/// specifies the optimization direction for each objective.
|
|
|
|
|
SolutionCollector* MakeBestLexicographicValueSolutionCollector(
|
|
|
|
|
std::vector<bool> maximize);
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Same as MakeBestValueSolutionCollector but collects the best
|
|
|
|
|
/// solution_count solutions. Collected solutions are sorted in increasing
|
|
|
|
|
/// optimality order (the best solution is the last one).
|
2020-10-29 14:25:39 +01:00
|
|
|
SolutionCollector* MakeNBestValueSolutionCollector(
|
2023-05-24 15:32:06 +02:00
|
|
|
const Assignment* assignment, int solution_count, bool maximize);
|
2020-10-29 14:25:39 +01:00
|
|
|
SolutionCollector* MakeNBestValueSolutionCollector(int solution_count,
|
2017-12-08 14:52:49 +01:00
|
|
|
bool maximize);
|
2023-05-24 15:32:06 +02:00
|
|
|
/// Same as above but supporting lexicographic objectives; 'maximize'
|
|
|
|
|
/// specifies the optimization direction for each objective.
|
|
|
|
|
SolutionCollector* MakeNBestLexicographicValueSolutionCollector(
|
|
|
|
|
const Assignment* assignment, int solution_count,
|
|
|
|
|
std::vector<bool> maximize);
|
|
|
|
|
SolutionCollector* MakeNBestLexicographicValueSolutionCollector(
|
|
|
|
|
int solution_count, std::vector<bool> maximize);
|
2017-12-08 14:52:49 +01:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Collect all solutions of the search.
|
2023-05-31 14:27:08 +02:00
|
|
|
SolutionCollector* MakeAllSolutionCollector(const Assignment* assignment);
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Collect all solutions of the search. The variables will need to
|
|
|
|
|
/// be added later.
|
2020-10-29 14:25:39 +01:00
|
|
|
SolutionCollector* MakeAllSolutionCollector();
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Creates a minimization objective.
|
2023-05-31 14:27:08 +02:00
|
|
|
OptimizeVar* MakeMinimize(IntVar* v, int64_t step);
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Creates a maximization objective.
|
2023-05-31 14:27:08 +02:00
|
|
|
OptimizeVar* MakeMaximize(IntVar* v, int64_t step);
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Creates a objective with a given sense (true = maximization).
|
2023-05-31 14:27:08 +02:00
|
|
|
OptimizeVar* MakeOptimize(bool maximize, IntVar* v, int64_t step);
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Creates a minimization weighted objective. The actual objective is
|
|
|
|
|
/// scalar_prod(sub_objectives, weights).
|
2020-10-29 14:25:39 +01:00
|
|
|
OptimizeVar* MakeWeightedMinimize(const std::vector<IntVar*>& sub_objectives,
|
2021-04-01 12:13:35 +02:00
|
|
|
const std::vector<int64_t>& weights,
|
|
|
|
|
int64_t step);
|
2011-01-18 15:00:12 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Creates a minimization weighted objective. The actual objective is
|
|
|
|
|
/// scalar_prod(sub_objectives, weights).
|
2020-10-29 14:25:39 +01:00
|
|
|
OptimizeVar* MakeWeightedMinimize(const std::vector<IntVar*>& sub_objectives,
|
|
|
|
|
const std::vector<int>& weights,
|
2021-04-01 12:13:35 +02:00
|
|
|
int64_t step);
|
2011-05-20 14:01:28 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Creates a maximization weigthed objective.
|
2020-10-29 14:25:39 +01:00
|
|
|
OptimizeVar* MakeWeightedMaximize(const std::vector<IntVar*>& sub_objectives,
|
2021-04-01 12:13:35 +02:00
|
|
|
const std::vector<int64_t>& weights,
|
|
|
|
|
int64_t step);
|
2011-01-18 15:00:12 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Creates a maximization weigthed objective.
|
2020-10-29 14:25:39 +01:00
|
|
|
OptimizeVar* MakeWeightedMaximize(const std::vector<IntVar*>& sub_objectives,
|
|
|
|
|
const std::vector<int>& weights,
|
2021-04-01 12:13:35 +02:00
|
|
|
int64_t step);
|
2011-05-20 14:01:28 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Creates a weighted objective with a given sense (true = maximization).
|
2020-10-29 14:25:39 +01:00
|
|
|
OptimizeVar* MakeWeightedOptimize(bool maximize,
|
|
|
|
|
const std::vector<IntVar*>& sub_objectives,
|
2021-04-01 12:13:35 +02:00
|
|
|
const std::vector<int64_t>& weights,
|
|
|
|
|
int64_t step);
|
2011-01-18 15:00:12 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Creates a weighted objective with a given sense (true = maximization).
|
2020-10-29 14:25:39 +01:00
|
|
|
OptimizeVar* MakeWeightedOptimize(bool maximize,
|
|
|
|
|
const std::vector<IntVar*>& sub_objectives,
|
|
|
|
|
const std::vector<int>& weights,
|
2021-04-01 12:13:35 +02:00
|
|
|
int64_t step);
|
2011-05-20 14:01:28 +00:00
|
|
|
|
2023-05-24 15:32:06 +02:00
|
|
|
/// Creates a lexicographic objective, following the order of the variables
|
|
|
|
|
/// given. Each variable has a corresponding optimization direction and step.
|
|
|
|
|
OptimizeVar* MakeLexicographicOptimize(std::vector<bool> maximize,
|
|
|
|
|
std::vector<IntVar*> variables,
|
|
|
|
|
std::vector<int64_t> steps);
|
|
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// MetaHeuristics which try to get the search out of local optima.
|
|
|
|
|
|
|
|
|
|
/// Creates a Tabu Search monitor.
|
|
|
|
|
/// In the context of local search the behavior is similar to MakeOptimize(),
|
|
|
|
|
/// creating an objective in a given sense. The behavior differs once a local
|
|
|
|
|
/// optimum is reached: thereafter solutions which degrade the value of the
|
|
|
|
|
/// objective are allowed if they are not "tabu". A solution is "tabu" if it
|
|
|
|
|
/// doesn't respect the following rules:
|
|
|
|
|
/// - improving the best solution found so far
|
|
|
|
|
/// - variables in the "keep" list must keep their value, variables in the
|
|
|
|
|
/// "forbid" list must not take the value they have in the list.
|
|
|
|
|
/// Variables with new values enter the tabu lists after each new solution
|
|
|
|
|
/// found and leave the lists after a given number of iterations (called
|
|
|
|
|
/// tenure). Only the variables passed to the method can enter the lists.
|
|
|
|
|
/// The tabu criterion is softened by the tabu factor which gives the number
|
|
|
|
|
/// of "tabu" violations which is tolerated; a factor of 1 means no violations
|
|
|
|
|
/// allowed; a factor of 0 means all violations are allowed.
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2023-05-24 15:32:06 +02:00
|
|
|
ObjectiveMonitor* MakeTabuSearch(bool maximize, IntVar* objective,
|
|
|
|
|
int64_t step,
|
|
|
|
|
const std::vector<IntVar*>& vars,
|
|
|
|
|
int64_t keep_tenure, int64_t forbid_tenure,
|
|
|
|
|
double tabu_factor);
|
|
|
|
|
|
|
|
|
|
ObjectiveMonitor* MakeLexicographicTabuSearch(
|
|
|
|
|
const std::vector<bool>& maximize, std::vector<IntVar*> objectives,
|
|
|
|
|
std::vector<int64_t> steps, const std::vector<IntVar*>& vars,
|
|
|
|
|
int64_t keep_tenure, int64_t forbid_tenure, double tabu_factor);
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Creates a Tabu Search based on the vars |vars|.
|
|
|
|
|
/// A solution is "tabu" if all the vars in |vars| keep their value.
|
2023-05-24 15:32:06 +02:00
|
|
|
ObjectiveMonitor* MakeGenericTabuSearch(bool maximize, IntVar* v,
|
|
|
|
|
int64_t step,
|
|
|
|
|
const std::vector<IntVar*>& tabu_vars,
|
|
|
|
|
int64_t forbid_tenure);
|
2017-02-06 16:11:43 +01:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Creates a Simulated Annealing monitor.
|
2010-09-15 12:42:33 +00:00
|
|
|
// TODO(user): document behavior
|
2023-05-24 15:32:06 +02:00
|
|
|
ObjectiveMonitor* MakeSimulatedAnnealing(bool maximize, IntVar* v,
|
|
|
|
|
int64_t step,
|
|
|
|
|
int64_t initial_temperature);
|
|
|
|
|
ObjectiveMonitor* MakeLexicographicSimulatedAnnealing(
|
|
|
|
|
const std::vector<bool>& maximize, std::vector<IntVar*> vars,
|
|
|
|
|
std::vector<int64_t> steps, std::vector<int64_t> initial_temperatures);
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Creates a Guided Local Search monitor.
|
|
|
|
|
/// Description here: http://en.wikipedia.org/wiki/Guided_Local_Search
|
2024-11-18 11:32:13 +01:00
|
|
|
#ifndef SWIG
|
2023-05-24 15:32:06 +02:00
|
|
|
ObjectiveMonitor* MakeGuidedLocalSearch(
|
2022-12-18 22:10:40 +01:00
|
|
|
bool maximize, IntVar* objective, IndexEvaluator2 objective_function,
|
|
|
|
|
int64_t step, const std::vector<IntVar*>& vars, double penalty_factor,
|
2024-11-18 11:32:13 +01:00
|
|
|
std::function<std::vector<std::pair<int64_t, int64_t>>(int64_t, int64_t)>
|
|
|
|
|
get_equivalent_pairs = nullptr,
|
2022-12-18 22:10:40 +01:00
|
|
|
bool reset_penalties_on_new_best_solution = false);
|
2023-05-24 15:32:06 +02:00
|
|
|
ObjectiveMonitor* MakeGuidedLocalSearch(
|
2022-12-18 22:10:40 +01:00
|
|
|
bool maximize, IntVar* objective, IndexEvaluator3 objective_function,
|
|
|
|
|
int64_t step, const std::vector<IntVar*>& vars,
|
|
|
|
|
const std::vector<IntVar*>& secondary_vars, double penalty_factor,
|
2024-11-18 11:32:13 +01:00
|
|
|
std::function<std::vector<std::pair<int64_t, int64_t>>(int64_t, int64_t)>
|
|
|
|
|
get_equivalent_pairs = nullptr,
|
2022-12-18 22:10:40 +01:00
|
|
|
bool reset_penalties_on_new_best_solution = false);
|
2024-11-18 11:32:13 +01:00
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
// Creates a composite objective monitor which alternates between objective
|
|
|
|
|
// monitors every time the search reaches a local optimum local optimium
|
|
|
|
|
// reached. This will stop if all monitors return false when LocalOptimium is
|
|
|
|
|
// called.
|
|
|
|
|
BaseObjectiveMonitor* MakeRoundRobinCompoundObjectiveMonitor(
|
|
|
|
|
std::vector<BaseObjectiveMonitor*> monitors,
|
|
|
|
|
int num_max_local_optima_before_metaheuristic_switch);
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// This search monitor will restart the search periodically.
|
|
|
|
|
/// At the iteration n, it will restart after scale_factor * Luby(n) failures
|
|
|
|
|
/// where Luby is the Luby Strategy (i.e. 1 1 2 1 1 2 4 1 1 2 1 1 2 4 8...).
|
2020-10-29 14:25:39 +01:00
|
|
|
SearchMonitor* MakeLubyRestart(int scale_factor);
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// This search monitor will restart the search periodically after 'frequency'
|
|
|
|
|
/// failures.
|
2020-10-29 14:25:39 +01:00
|
|
|
SearchMonitor* MakeConstantRestart(int frequency);
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2020-08-10 10:55:34 +02:00
|
|
|
/// Creates a search limit that constrains the running time.
|
2021-12-05 12:15:27 +01:00
|
|
|
ABSL_MUST_USE_RESULT RegularLimit* MakeTimeLimit(absl::Duration time);
|
2020-08-10 15:53:52 +02:00
|
|
|
#if !defined(SWIG)
|
2020-08-10 10:55:34 +02:00
|
|
|
ABSL_DEPRECATED("Use the version taking absl::Duration() as argument")
|
2020-11-03 14:01:06 +01:00
|
|
|
#endif // !defined(SWIG)
|
2021-12-05 12:15:27 +01:00
|
|
|
ABSL_MUST_USE_RESULT RegularLimit* MakeTimeLimit(int64_t time_in_ms) {
|
2020-08-10 10:55:34 +02:00
|
|
|
return MakeTimeLimit(time_in_ms == kint64max
|
|
|
|
|
? absl::InfiniteDuration()
|
|
|
|
|
: absl::Milliseconds(time_in_ms));
|
|
|
|
|
}
|
2011-10-04 09:32:00 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Creates a search limit that constrains the number of branches
|
|
|
|
|
/// explored in the search tree.
|
2021-12-05 12:15:27 +01:00
|
|
|
ABSL_MUST_USE_RESULT RegularLimit* MakeBranchesLimit(int64_t branches);
|
2011-10-04 09:32:00 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Creates a search limit that constrains the number of failures
|
|
|
|
|
/// that can happen when exploring the search tree.
|
2021-12-05 12:15:27 +01:00
|
|
|
ABSL_MUST_USE_RESULT RegularLimit* MakeFailuresLimit(int64_t failures);
|
2011-10-04 09:32:00 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Creates a search limit that constrains the number of solutions found
|
|
|
|
|
/// during the search.
|
2021-12-05 12:15:27 +01:00
|
|
|
ABSL_MUST_USE_RESULT RegularLimit* MakeSolutionsLimit(int64_t solutions);
|
2011-10-04 09:32:00 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Limits the search with the 'time', 'branches', 'failures' and
|
2020-08-10 10:55:34 +02:00
|
|
|
/// 'solutions' limits. 'smart_time_check' reduces the calls to the wall
|
|
|
|
|
// timer by estimating the number of remaining calls, and 'cumulative' means
|
|
|
|
|
// that the limit applies cumulatively, instead of search-by-search.
|
2021-12-05 12:15:27 +01:00
|
|
|
ABSL_MUST_USE_RESULT RegularLimit* MakeLimit(absl::Duration time,
|
|
|
|
|
int64_t branches,
|
|
|
|
|
int64_t failures,
|
|
|
|
|
int64_t solutions,
|
|
|
|
|
bool smart_time_check = false,
|
|
|
|
|
bool cumulative = false);
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Creates a search limit from its protobuf description
|
2021-12-05 12:15:27 +01:00
|
|
|
ABSL_MUST_USE_RESULT RegularLimit* MakeLimit(
|
|
|
|
|
const RegularLimitParameters& proto);
|
2016-02-03 15:15:58 +01:00
|
|
|
|
2020-08-10 15:53:52 +02:00
|
|
|
#if !defined(SWIG)
|
2020-08-10 10:55:34 +02:00
|
|
|
ABSL_DEPRECATED("Use other MakeLimit() versions")
|
2020-11-03 14:01:06 +01:00
|
|
|
#endif // !defined(SWIG)
|
2021-12-05 12:15:27 +01:00
|
|
|
ABSL_MUST_USE_RESULT RegularLimit* MakeLimit(int64_t time, int64_t branches,
|
|
|
|
|
int64_t failures,
|
|
|
|
|
int64_t solutions,
|
|
|
|
|
bool smart_time_check = false,
|
|
|
|
|
bool cumulative = false);
|
2020-08-10 10:55:34 +02:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Creates a regular limit proto containing default values.
|
2019-04-11 09:39:02 -07:00
|
|
|
RegularLimitParameters MakeDefaultRegularLimitParameters() const;
|
2011-04-05 13:35:20 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Creates a search limit that is reached when either of the underlying limit
|
2019-12-05 18:10:18 +01:00
|
|
|
/// is reached. That is, the returned limit is more stringent than both
|
2019-07-05 00:25:55 +02:00
|
|
|
/// argument limits.
|
2023-05-31 14:27:08 +02:00
|
|
|
ABSL_MUST_USE_RESULT SearchLimit* MakeLimit(SearchLimit* limit_1,
|
|
|
|
|
SearchLimit* limit_2);
|
2011-05-26 09:33:36 +00:00
|
|
|
|
2020-10-18 16:38:25 +02:00
|
|
|
/// Limits the search based on the improvements of 'objective_var'. Stops the
|
|
|
|
|
/// search when the improvement rate gets lower than a threshold value. This
|
|
|
|
|
/// threshold value is computed based on the improvement rate during the first
|
|
|
|
|
/// phase of the search.
|
2021-12-05 12:15:27 +01:00
|
|
|
ABSL_MUST_USE_RESULT ImprovementSearchLimit* MakeImprovementLimit(
|
2020-10-29 14:25:39 +01:00
|
|
|
IntVar* objective_var, bool maximize, double objective_scaling_factor,
|
2020-10-18 16:38:25 +02:00
|
|
|
double objective_offset, double improvement_rate_coefficient,
|
|
|
|
|
int improvement_rate_solutions_distance);
|
2023-05-24 15:32:06 +02:00
|
|
|
/// Same as MakeImprovementLimit on a lexicographic objective based on
|
|
|
|
|
/// 'objective_vars' and related arguments.
|
|
|
|
|
ABSL_MUST_USE_RESULT ImprovementSearchLimit*
|
|
|
|
|
MakeLexicographicImprovementLimit(
|
|
|
|
|
std::vector<IntVar*> objective_vars, std::vector<bool> maximize,
|
|
|
|
|
std::vector<double> objective_scaling_factors,
|
|
|
|
|
std::vector<double> objective_offsets,
|
|
|
|
|
double improvement_rate_coefficient,
|
|
|
|
|
int improvement_rate_solutions_distance);
|
2020-10-18 16:38:25 +02:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Callback-based search limit. Search stops when limiter returns true; if
|
|
|
|
|
/// this happens at a leaf the corresponding solution will be rejected.
|
2021-12-05 12:15:27 +01:00
|
|
|
ABSL_MUST_USE_RESULT SearchLimit* MakeCustomLimit(
|
|
|
|
|
std::function<bool()> limiter);
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2011-01-18 15:00:12 +00:00
|
|
|
// TODO(user): DEPRECATE API of MakeSearchLog(.., IntVar* var,..).
|
2011-01-27 11:30:29 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// The SearchMonitors below will display a periodic search log
|
|
|
|
|
/// on LOG(INFO) every branch_period branches explored.
|
2020-10-29 14:25:39 +01:00
|
|
|
SearchMonitor* MakeSearchLog(int branch_period);
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// At each solution, this monitor also display the var value.
|
2023-05-31 14:27:08 +02:00
|
|
|
SearchMonitor* MakeSearchLog(int branch_period, IntVar* var);
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// At each solution, this monitor will also display result of @p
|
|
|
|
|
/// display_callback.
|
2020-10-29 14:25:39 +01:00
|
|
|
SearchMonitor* MakeSearchLog(int branch_period,
|
2019-03-15 17:17:02 +01:00
|
|
|
std::function<std::string()> display_callback);
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// At each solution, this monitor will display the 'var' value and the
|
|
|
|
|
/// result of @p display_callback.
|
2020-10-29 14:25:39 +01:00
|
|
|
SearchMonitor* MakeSearchLog(int branch_period, IntVar* var,
|
2019-03-15 17:17:02 +01:00
|
|
|
std::function<std::string()> display_callback);
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2023-07-10 13:15:40 +02:00
|
|
|
/// At each solution, this monitor will display the 'vars' values and the
|
|
|
|
|
/// result of @p display_callback.
|
|
|
|
|
SearchMonitor* MakeSearchLog(int branch_period, std::vector<IntVar*> vars,
|
|
|
|
|
std::function<std::string()> display_callback);
|
|
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// OptimizeVar Search Logs
|
|
|
|
|
/// At each solution, this monitor will also display the 'opt_var' value.
|
2023-05-31 14:27:08 +02:00
|
|
|
SearchMonitor* MakeSearchLog(int branch_period, OptimizeVar* opt_var);
|
2011-01-18 15:00:12 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Creates a search monitor that will also print the result of the
|
|
|
|
|
/// display callback.
|
2023-05-31 14:27:08 +02:00
|
|
|
SearchMonitor* MakeSearchLog(int branch_period, OptimizeVar* opt_var,
|
2019-03-15 17:17:02 +01:00
|
|
|
std::function<std::string()> display_callback);
|
2011-01-18 15:00:12 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Creates a search monitor from logging parameters.
|
2018-12-06 17:16:22 +01:00
|
|
|
struct SearchLogParameters {
|
2019-07-05 00:25:55 +02:00
|
|
|
/// SearchMonitors will display a periodic search log every branch_period
|
|
|
|
|
/// branches explored.
|
2018-12-06 17:16:22 +01:00
|
|
|
int branch_period = 1;
|
2023-07-10 13:15:40 +02:00
|
|
|
/// SearchMonitors will display values of objective or variables (both
|
|
|
|
|
/// cannot be used together).
|
2020-10-29 14:25:39 +01:00
|
|
|
OptimizeVar* objective = nullptr;
|
2023-07-10 13:15:40 +02:00
|
|
|
std::vector<IntVar*> variables;
|
2019-07-22 10:18:30 -07:00
|
|
|
/// When displayed, objective or var values will be scaled and offset by
|
|
|
|
|
/// the given values in the following way:
|
|
|
|
|
/// scaling_factor * (value + offset).
|
2023-07-10 13:15:40 +02:00
|
|
|
std::vector<double> scaling_factors;
|
|
|
|
|
std::vector<double> offsets;
|
2019-07-05 00:25:55 +02:00
|
|
|
/// SearchMonitors will display the result of display_callback at each new
|
2020-10-18 16:38:25 +02:00
|
|
|
/// solution found and when the search finishes if
|
|
|
|
|
/// display_on_new_solutions_only is false.
|
2019-03-15 17:17:02 +01:00
|
|
|
std::function<std::string()> display_callback;
|
2020-10-18 16:38:25 +02:00
|
|
|
/// To be used to protect from cases where display_callback assumes
|
|
|
|
|
/// variables are instantiated, which only happens in AtSolution().
|
|
|
|
|
bool display_on_new_solutions_only = true;
|
2018-12-06 17:16:22 +01:00
|
|
|
};
|
2020-10-29 14:25:39 +01:00
|
|
|
SearchMonitor* MakeSearchLog(SearchLogParameters parameters);
|
2018-12-06 17:16:22 +01:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Creates a search monitor that will trace precisely the behavior of the
|
|
|
|
|
/// search. Use this only for low level debugging.
|
2020-10-29 14:25:39 +01:00
|
|
|
SearchMonitor* MakeSearchTrace(const std::string& prefix);
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// ----- Callback-based search monitors -----
|
2020-10-29 14:25:39 +01:00
|
|
|
SearchMonitor* MakeEnterSearchCallback(std::function<void()> callback);
|
|
|
|
|
SearchMonitor* MakeExitSearchCallback(std::function<void()> callback);
|
|
|
|
|
SearchMonitor* MakeAtSolutionCallback(std::function<void()> callback);
|
2016-02-04 14:06:30 +01:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Prints the model.
|
2020-10-29 14:25:39 +01:00
|
|
|
ModelVisitor* MakePrintModelVisitor();
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Displays some nice statistics on the model.
|
2020-10-29 14:25:39 +01:00
|
|
|
ModelVisitor* MakeStatisticsModelVisitor();
|
2012-06-21 08:58:29 +00:00
|
|
|
#if !defined(SWIG)
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Compute the number of constraints a variable is attached to.
|
2020-10-29 14:25:39 +01:00
|
|
|
ModelVisitor* MakeVariableDegreeVisitor(
|
2023-05-31 14:27:08 +02:00
|
|
|
absl::flat_hash_map<const IntVar*, int>* map);
|
2020-10-22 23:36:58 +02:00
|
|
|
#endif // !defined(SWIG)
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Symmetry Breaking.
|
2020-10-29 14:25:39 +01:00
|
|
|
SearchMonitor* MakeSymmetryManager(
|
|
|
|
|
const std::vector<SymmetryBreaker*>& visitors);
|
2023-05-31 14:27:08 +02:00
|
|
|
SearchMonitor* MakeSymmetryManager(SymmetryBreaker* v1);
|
|
|
|
|
SearchMonitor* MakeSymmetryManager(SymmetryBreaker* v1, SymmetryBreaker* v2);
|
|
|
|
|
SearchMonitor* MakeSymmetryManager(SymmetryBreaker* v1, SymmetryBreaker* v2,
|
|
|
|
|
SymmetryBreaker* v3);
|
|
|
|
|
SearchMonitor* MakeSymmetryManager(SymmetryBreaker* v1, SymmetryBreaker* v2,
|
|
|
|
|
SymmetryBreaker* v3, SymmetryBreaker* v4);
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Decisions.
|
2023-05-31 14:27:08 +02:00
|
|
|
Decision* MakeAssignVariableValue(IntVar* var, int64_t val);
|
|
|
|
|
Decision* MakeVariableLessOrEqualValue(IntVar* var, int64_t value);
|
|
|
|
|
Decision* MakeVariableGreaterOrEqualValue(IntVar* var, int64_t value);
|
|
|
|
|
Decision* MakeSplitVariableDomain(IntVar* var, int64_t val,
|
2010-10-15 13:22:21 +00:00
|
|
|
bool start_with_lower_half);
|
2023-05-31 14:27:08 +02:00
|
|
|
Decision* MakeAssignVariableValueOrFail(IntVar* var, int64_t value);
|
|
|
|
|
Decision* MakeAssignVariableValueOrDoNothing(IntVar* var, int64_t value);
|
2020-10-29 14:25:39 +01:00
|
|
|
Decision* MakeAssignVariablesValues(const std::vector<IntVar*>& vars,
|
2021-04-01 12:13:35 +02:00
|
|
|
const std::vector<int64_t>& values);
|
2021-12-05 12:15:27 +01:00
|
|
|
Decision* MakeAssignVariablesValuesOrDoNothing(
|
|
|
|
|
const std::vector<IntVar*>& vars, const std::vector<int64_t>& values);
|
|
|
|
|
Decision* MakeAssignVariablesValuesOrFail(const std::vector<IntVar*>& vars,
|
|
|
|
|
const std::vector<int64_t>& values);
|
2020-10-29 14:25:39 +01:00
|
|
|
Decision* MakeFailDecision();
|
|
|
|
|
Decision* MakeDecision(Action apply, Action refute);
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Creates a decision builder which sequentially composes decision builders.
|
|
|
|
|
/// At each leaf of a decision builder, the next decision builder is therefore
|
|
|
|
|
/// called. For instance, Compose(db1, db2) will result in the following tree:
|
|
|
|
|
/// d1 tree |
|
|
|
|
|
/// / | \ |
|
|
|
|
|
/// db1 leaves |
|
|
|
|
|
/// / | \ |
|
|
|
|
|
/// db2 tree db2 tree db2 tree |
|
2023-05-31 14:27:08 +02:00
|
|
|
DecisionBuilder* Compose(DecisionBuilder* db1, DecisionBuilder* db2);
|
|
|
|
|
DecisionBuilder* Compose(DecisionBuilder* db1, DecisionBuilder* db2,
|
|
|
|
|
DecisionBuilder* db3);
|
|
|
|
|
DecisionBuilder* Compose(DecisionBuilder* db1, DecisionBuilder* db2,
|
|
|
|
|
DecisionBuilder* db3, DecisionBuilder* db4);
|
2020-10-29 14:25:39 +01:00
|
|
|
DecisionBuilder* Compose(const std::vector<DecisionBuilder*>& dbs);
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Creates a decision builder which will create a search tree where each
|
|
|
|
|
/// decision builder is called from the top of the search tree. For instance
|
|
|
|
|
/// the decision builder Try(db1, db2) will entirely explore the search tree
|
|
|
|
|
/// of db1 then the one of db2, resulting in the following search tree:
|
|
|
|
|
/// Tree root |
|
|
|
|
|
/// / \ |
|
|
|
|
|
/// db1 tree db2 tree |
|
|
|
|
|
///
|
|
|
|
|
/// This is very handy to try a decision builder which partially explores the
|
|
|
|
|
/// search space and if it fails to try another decision builder.
|
|
|
|
|
///
|
2012-02-20 12:10:32 +00:00
|
|
|
// TODO(user): The search tree can be balanced by using binary
|
2019-07-05 00:25:55 +02:00
|
|
|
/// "Try"-builders "recursively". For instance, Try(a,b,c,d) will give a tree
|
|
|
|
|
/// unbalanced to the right, whereas Try(Try(a,b), Try(b,c)) will give a
|
|
|
|
|
/// balanced tree. Investigate if we should only provide the binary version
|
|
|
|
|
/// and/or if we should balance automatically.
|
2023-05-31 14:27:08 +02:00
|
|
|
DecisionBuilder* Try(DecisionBuilder* db1, DecisionBuilder* db2);
|
|
|
|
|
DecisionBuilder* Try(DecisionBuilder* db1, DecisionBuilder* db2,
|
|
|
|
|
DecisionBuilder* db3);
|
|
|
|
|
DecisionBuilder* Try(DecisionBuilder* db1, DecisionBuilder* db2,
|
|
|
|
|
DecisionBuilder* db3, DecisionBuilder* db4);
|
2020-10-29 14:25:39 +01:00
|
|
|
DecisionBuilder* Try(const std::vector<DecisionBuilder*>& dbs);
|
2012-02-20 12:10:32 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Phases on IntVar arrays.
|
2013-10-10 15:23:20 +00:00
|
|
|
// TODO(user): name each of them differently, and document them (and do that
|
2019-07-05 00:25:55 +02:00
|
|
|
/// for all other functions that have several homonyms in this .h).
|
2020-10-29 14:25:39 +01:00
|
|
|
DecisionBuilder* MakePhase(const std::vector<IntVar*>& vars,
|
2013-10-10 15:23:20 +00:00
|
|
|
IntVarStrategy var_str, IntValueStrategy val_str);
|
2020-10-29 14:25:39 +01:00
|
|
|
DecisionBuilder* MakePhase(const std::vector<IntVar*>& vars,
|
2015-08-13 16:00:54 +02:00
|
|
|
IndexEvaluator1 var_evaluator,
|
2010-09-15 12:42:33 +00:00
|
|
|
IntValueStrategy val_str);
|
|
|
|
|
|
2020-10-29 14:25:39 +01:00
|
|
|
DecisionBuilder* MakePhase(const std::vector<IntVar*>& vars,
|
2017-12-08 14:52:49 +01:00
|
|
|
IntVarStrategy var_str,
|
|
|
|
|
IndexEvaluator2 value_evaluator);
|
2013-10-10 15:23:20 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// var_val1_val2_comparator(var, val1, val2) is true iff assigning value
|
|
|
|
|
/// "val1" to variable "var" is better than assigning value "val2".
|
2020-10-29 14:25:39 +01:00
|
|
|
DecisionBuilder* MakePhase(const std::vector<IntVar*>& vars,
|
2019-07-05 00:25:55 +02:00
|
|
|
IntVarStrategy var_str,
|
|
|
|
|
VariableValueComparator var_val1_val2_comparator);
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2020-10-29 14:25:39 +01:00
|
|
|
DecisionBuilder* MakePhase(const std::vector<IntVar*>& vars,
|
2015-08-13 16:00:54 +02:00
|
|
|
IndexEvaluator1 var_evaluator,
|
2017-12-08 14:52:49 +01:00
|
|
|
IndexEvaluator2 value_evaluator);
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2020-10-29 14:25:39 +01:00
|
|
|
DecisionBuilder* MakePhase(const std::vector<IntVar*>& vars,
|
2017-12-08 14:52:49 +01:00
|
|
|
IntVarStrategy var_str,
|
|
|
|
|
IndexEvaluator2 value_evaluator,
|
2015-08-13 16:00:54 +02:00
|
|
|
IndexEvaluator1 tie_breaker);
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2020-10-29 14:25:39 +01:00
|
|
|
DecisionBuilder* MakePhase(const std::vector<IntVar*>& vars,
|
2015-08-13 16:00:54 +02:00
|
|
|
IndexEvaluator1 var_evaluator,
|
2017-12-08 14:52:49 +01:00
|
|
|
IndexEvaluator2 value_evaluator,
|
2015-08-13 16:00:54 +02:00
|
|
|
IndexEvaluator1 tie_breaker);
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2020-10-29 14:25:39 +01:00
|
|
|
DecisionBuilder* MakeDefaultPhase(const std::vector<IntVar*>& vars);
|
|
|
|
|
DecisionBuilder* MakeDefaultPhase(const std::vector<IntVar*>& vars,
|
|
|
|
|
const DefaultPhaseParameters& parameters);
|
2010-10-28 16:36:21 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Shortcuts for small arrays.
|
2023-05-31 14:27:08 +02:00
|
|
|
DecisionBuilder* MakePhase(IntVar* v0, IntVarStrategy var_str,
|
2010-09-15 12:42:33 +00:00
|
|
|
IntValueStrategy val_str);
|
2023-05-31 14:27:08 +02:00
|
|
|
DecisionBuilder* MakePhase(IntVar* v0, IntVar* v1, IntVarStrategy var_str,
|
2010-09-15 12:42:33 +00:00
|
|
|
IntValueStrategy val_str);
|
2023-05-31 14:27:08 +02:00
|
|
|
DecisionBuilder* MakePhase(IntVar* v0, IntVar* v1, IntVar* v2,
|
|
|
|
|
IntVarStrategy var_str, IntValueStrategy val_str);
|
|
|
|
|
DecisionBuilder* MakePhase(IntVar* v0, IntVar* v1, IntVar* v2, IntVar* v3,
|
2013-10-10 15:23:20 +00:00
|
|
|
IntVarStrategy var_str, IntValueStrategy val_str);
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Returns a decision that tries to schedule a task at a given time.
|
|
|
|
|
/// On the Apply branch, it will set that interval var as performed and set
|
|
|
|
|
/// its start to 'est'. On the Refute branch, it will just update the
|
|
|
|
|
/// 'marker' to 'est' + 1. This decision is used in the
|
|
|
|
|
/// INTERVAL_SET_TIMES_FORWARD strategy.
|
2023-05-31 14:27:08 +02:00
|
|
|
Decision* MakeScheduleOrPostpone(IntervalVar* var, int64_t est,
|
|
|
|
|
int64_t* marker);
|
2011-01-06 17:40:30 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Returns a decision that tries to schedule a task at a given time.
|
|
|
|
|
/// On the Apply branch, it will set that interval var as performed and set
|
|
|
|
|
/// its end to 'est'. On the Refute branch, it will just update the
|
|
|
|
|
/// 'marker' to 'est' - 1. This decision is used in the
|
|
|
|
|
/// INTERVAL_SET_TIMES_BACKWARD strategy.
|
2023-05-31 14:27:08 +02:00
|
|
|
Decision* MakeScheduleOrExpedite(IntervalVar* var, int64_t est,
|
|
|
|
|
int64_t* marker);
|
2014-01-17 18:36:18 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Returns a decision that tries to rank first the ith interval var
|
|
|
|
|
/// in the sequence variable.
|
2023-05-31 14:27:08 +02:00
|
|
|
Decision* MakeRankFirstInterval(SequenceVar* sequence, int index);
|
2011-12-16 21:02:59 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Returns a decision that tries to rank last the ith interval var
|
|
|
|
|
/// in the sequence variable.
|
2023-05-31 14:27:08 +02:00
|
|
|
Decision* MakeRankLastInterval(SequenceVar* sequence, int index);
|
2011-01-06 17:40:30 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Returns a decision builder which assigns values to variables which
|
|
|
|
|
/// minimize the values returned by the evaluator. The arguments passed to the
|
|
|
|
|
/// evaluator callback are the indices of the variables in vars and the values
|
|
|
|
|
/// of these variables. Ownership of the callback is passed to the decision
|
|
|
|
|
/// builder.
|
2020-10-29 14:25:39 +01:00
|
|
|
DecisionBuilder* MakePhase(const std::vector<IntVar*>& vars,
|
2017-12-08 14:52:49 +01:00
|
|
|
IndexEvaluator2 eval, EvaluatorStrategy str);
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Returns a decision builder which assigns values to variables
|
|
|
|
|
/// which minimize the values returned by the evaluator. In case of
|
|
|
|
|
/// tie breaks, the second callback is used to choose the best index
|
|
|
|
|
/// in the array of equivalent pairs with equivalent evaluations. The
|
|
|
|
|
/// arguments passed to the evaluator callback are the indices of the
|
|
|
|
|
/// variables in vars and the values of these variables. Ownership of
|
|
|
|
|
/// the callback is passed to the decision builder.
|
2020-10-29 14:25:39 +01:00
|
|
|
DecisionBuilder* MakePhase(const std::vector<IntVar*>& vars,
|
2017-12-08 14:52:49 +01:00
|
|
|
IndexEvaluator2 eval, IndexEvaluator1 tie_breaker,
|
2010-09-15 12:42:33 +00:00
|
|
|
EvaluatorStrategy str);
|
2010-10-28 16:36:21 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Scheduling phases.
|
2020-10-29 14:25:39 +01:00
|
|
|
DecisionBuilder* MakePhase(const std::vector<IntervalVar*>& intervals,
|
2010-09-15 12:42:33 +00:00
|
|
|
IntervalStrategy str);
|
|
|
|
|
|
2020-10-29 14:25:39 +01:00
|
|
|
DecisionBuilder* MakePhase(const std::vector<SequenceVar*>& sequences,
|
2010-09-15 12:42:33 +00:00
|
|
|
SequenceStrategy str);
|
|
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Returns a decision builder for which the left-most leaf corresponds
|
|
|
|
|
/// to assignment, the rest of the tree being explored using 'db'.
|
2020-10-29 14:25:39 +01:00
|
|
|
DecisionBuilder* MakeDecisionBuilderFromAssignment(
|
2023-05-31 14:27:08 +02:00
|
|
|
Assignment* assignment, DecisionBuilder* db,
|
2020-10-29 14:25:39 +01:00
|
|
|
const std::vector<IntVar*>& vars);
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Returns a decision builder that will add the given constraint to
|
|
|
|
|
/// the model.
|
2023-05-31 14:27:08 +02:00
|
|
|
DecisionBuilder* MakeConstraintAdder(Constraint* ct);
|
2011-10-11 08:19:59 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// SolveOnce will collapse a search tree described by a decision
|
|
|
|
|
/// builder 'db' and a set of monitors and wrap it into a single point.
|
|
|
|
|
/// If there are no solutions to this nested tree, then SolveOnce will
|
|
|
|
|
/// fail. If there is a solution, it will find it and returns nullptr.
|
2023-05-31 14:27:08 +02:00
|
|
|
DecisionBuilder* MakeSolveOnce(DecisionBuilder* db);
|
|
|
|
|
DecisionBuilder* MakeSolveOnce(DecisionBuilder* db, SearchMonitor* monitor1);
|
|
|
|
|
DecisionBuilder* MakeSolveOnce(DecisionBuilder* db, SearchMonitor* monitor1,
|
|
|
|
|
SearchMonitor* monitor2);
|
|
|
|
|
DecisionBuilder* MakeSolveOnce(DecisionBuilder* db, SearchMonitor* monitor1,
|
|
|
|
|
SearchMonitor* monitor2,
|
|
|
|
|
SearchMonitor* monitor3);
|
|
|
|
|
DecisionBuilder* MakeSolveOnce(DecisionBuilder* db, SearchMonitor* monitor1,
|
|
|
|
|
SearchMonitor* monitor2,
|
|
|
|
|
SearchMonitor* monitor3,
|
|
|
|
|
SearchMonitor* monitor4);
|
|
|
|
|
DecisionBuilder* MakeSolveOnce(DecisionBuilder* db,
|
2020-10-29 14:25:39 +01:00
|
|
|
const std::vector<SearchMonitor*>& monitors);
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// NestedOptimize will collapse a search tree described by a
|
|
|
|
|
/// decision builder 'db' and a set of monitors and wrap it into a
|
|
|
|
|
/// single point. If there are no solutions to this nested tree, then
|
|
|
|
|
/// NestedOptimize will fail. If there are solutions, it will find
|
|
|
|
|
/// the best as described by the mandatory objective in the solution
|
|
|
|
|
/// as well as the optimization direction, instantiate all variables
|
|
|
|
|
/// to this solution, and return nullptr.
|
2023-05-31 14:27:08 +02:00
|
|
|
DecisionBuilder* MakeNestedOptimize(DecisionBuilder* db, Assignment* solution,
|
|
|
|
|
bool maximize, int64_t step);
|
|
|
|
|
DecisionBuilder* MakeNestedOptimize(DecisionBuilder* db, Assignment* solution,
|
|
|
|
|
bool maximize, int64_t step,
|
|
|
|
|
SearchMonitor* monitor1);
|
|
|
|
|
DecisionBuilder* MakeNestedOptimize(DecisionBuilder* db, Assignment* solution,
|
|
|
|
|
bool maximize, int64_t step,
|
|
|
|
|
SearchMonitor* monitor1,
|
|
|
|
|
SearchMonitor* monitor2);
|
|
|
|
|
DecisionBuilder* MakeNestedOptimize(DecisionBuilder* db, Assignment* solution,
|
|
|
|
|
bool maximize, int64_t step,
|
|
|
|
|
SearchMonitor* monitor1,
|
|
|
|
|
SearchMonitor* monitor2,
|
|
|
|
|
SearchMonitor* monitor3);
|
|
|
|
|
DecisionBuilder* MakeNestedOptimize(DecisionBuilder* db, Assignment* solution,
|
|
|
|
|
bool maximize, int64_t step,
|
|
|
|
|
SearchMonitor* monitor1,
|
|
|
|
|
SearchMonitor* monitor2,
|
|
|
|
|
SearchMonitor* monitor3,
|
|
|
|
|
SearchMonitor* monitor4);
|
2020-10-29 14:25:39 +01:00
|
|
|
DecisionBuilder* MakeNestedOptimize(
|
2023-05-31 14:27:08 +02:00
|
|
|
DecisionBuilder* db, Assignment* solution, bool maximize, int64_t step,
|
|
|
|
|
const std::vector<SearchMonitor*>& monitors);
|
2011-03-31 08:32:48 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Returns a DecisionBuilder which restores an Assignment
|
|
|
|
|
/// (calls void Assignment::Restore())
|
2020-10-29 14:25:39 +01:00
|
|
|
DecisionBuilder* MakeRestoreAssignment(Assignment* assignment);
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Returns a DecisionBuilder which stores an Assignment
|
|
|
|
|
/// (calls void Assignment::Store())
|
2020-10-29 14:25:39 +01:00
|
|
|
DecisionBuilder* MakeStoreAssignment(Assignment* assignment);
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Local Search Operators.
|
2023-05-24 15:32:06 +02:00
|
|
|
LocalSearchOperator* MakeOperator(
|
|
|
|
|
const std::vector<IntVar*>& vars, LocalSearchOperators op,
|
2024-11-18 11:32:13 +01:00
|
|
|
std::function<const std::vector<int>&(int, int)> get_incoming_neighbors =
|
|
|
|
|
nullptr,
|
|
|
|
|
std::function<const std::vector<int>&(int, int)> get_outgoing_neighbors =
|
|
|
|
|
nullptr);
|
2023-05-24 15:32:06 +02:00
|
|
|
LocalSearchOperator* MakeOperator(
|
|
|
|
|
const std::vector<IntVar*>& vars,
|
|
|
|
|
const std::vector<IntVar*>& secondary_vars, LocalSearchOperators op,
|
2024-11-18 11:32:13 +01:00
|
|
|
std::function<const std::vector<int>&(int, int)> get_incoming_neighbors =
|
|
|
|
|
nullptr,
|
|
|
|
|
std::function<const std::vector<int>&(int, int)> get_outgoing_neighbors =
|
|
|
|
|
nullptr);
|
2011-11-19 01:59:37 +00:00
|
|
|
// TODO(user): Make the callback an IndexEvaluator2 when there are no
|
2010-09-15 12:42:33 +00:00
|
|
|
// secondary variables.
|
2020-10-29 14:25:39 +01:00
|
|
|
LocalSearchOperator* MakeOperator(const std::vector<IntVar*>& vars,
|
2015-08-13 16:00:54 +02:00
|
|
|
IndexEvaluator3 evaluator,
|
2010-09-15 12:42:33 +00:00
|
|
|
EvaluatorLocalSearchOperators op);
|
2020-10-29 14:25:39 +01:00
|
|
|
LocalSearchOperator* MakeOperator(const std::vector<IntVar*>& vars,
|
|
|
|
|
const std::vector<IntVar*>& secondary_vars,
|
2015-08-13 16:00:54 +02:00
|
|
|
IndexEvaluator3 evaluator,
|
2010-09-15 12:42:33 +00:00
|
|
|
EvaluatorLocalSearchOperators op);
|
2010-10-15 13:22:21 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Creates a large neighborhood search operator which creates fragments (set
|
|
|
|
|
/// of relaxed variables) with up to number_of_variables random variables
|
|
|
|
|
/// (sampling with replacement is performed meaning that at most
|
|
|
|
|
/// number_of_variables variables are selected). Warning: this operator will
|
|
|
|
|
/// always return neighbors; using it without a search limit will result in a
|
|
|
|
|
/// non-ending search.
|
|
|
|
|
/// Optionally a random seed can be specified.
|
2020-10-29 14:25:39 +01:00
|
|
|
LocalSearchOperator* MakeRandomLnsOperator(const std::vector<IntVar*>& vars,
|
2010-10-15 13:22:21 +00:00
|
|
|
int number_of_variables);
|
2020-10-29 14:25:39 +01:00
|
|
|
LocalSearchOperator* MakeRandomLnsOperator(const std::vector<IntVar*>& vars,
|
2010-10-15 13:22:21 +00:00
|
|
|
int number_of_variables,
|
2021-04-01 12:13:35 +02:00
|
|
|
int32_t seed);
|
2010-10-15 13:22:21 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Creates a local search operator that tries to move the assignment of some
|
|
|
|
|
/// variables toward a target. The target is given as an Assignment. This
|
|
|
|
|
/// operator generates neighbors in which the only difference compared to the
|
|
|
|
|
/// current state is that one variable that belongs to the target assignment
|
|
|
|
|
/// is set to its target value.
|
2020-10-29 14:25:39 +01:00
|
|
|
LocalSearchOperator* MakeMoveTowardTargetOperator(const Assignment& target);
|
2011-04-26 08:59:55 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Creates a local search operator that tries to move the assignment of some
|
|
|
|
|
/// variables toward a target. The target is given either as two vectors: a
|
|
|
|
|
/// vector of variables and a vector of associated target values. The two
|
|
|
|
|
/// vectors should be of the same length. This operator generates neighbors in
|
|
|
|
|
/// which the only difference compared to the current state is that one
|
|
|
|
|
/// variable that belongs to the given vector is set to its target value.
|
2020-10-29 14:25:39 +01:00
|
|
|
LocalSearchOperator* MakeMoveTowardTargetOperator(
|
|
|
|
|
const std::vector<IntVar*>& variables,
|
2021-04-01 12:13:35 +02:00
|
|
|
const std::vector<int64_t>& target_values);
|
2011-04-26 08:59:55 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Creates a local search operator which concatenates a vector of operators.
|
|
|
|
|
/// Each operator from the vector is called sequentially. By default, when a
|
|
|
|
|
/// neighbor is found the neighborhood exploration restarts from the last
|
|
|
|
|
/// active operator (the one which produced the neighbor).
|
|
|
|
|
/// This can be overridden by setting restart to true to force the exploration
|
|
|
|
|
/// to start from the first operator in the vector.
|
|
|
|
|
///
|
|
|
|
|
/// The default behavior can also be overridden using an evaluation callback
|
|
|
|
|
/// to set the order in which the operators are explored (the callback is
|
|
|
|
|
/// called in LocalSearchOperator::Start()). The first argument of the
|
|
|
|
|
/// callback is the index of the operator which produced the last move, the
|
|
|
|
|
/// second argument is the index of the operator to be evaluated. Ownership of
|
|
|
|
|
/// the callback is taken by ConcatenateOperators.
|
|
|
|
|
///
|
|
|
|
|
/// Example:
|
|
|
|
|
///
|
|
|
|
|
/// const int kPriorities = {10, 100, 10, 0};
|
2021-04-01 12:13:35 +02:00
|
|
|
/// int64_t Evaluate(int active_operator, int current_operator) {
|
2019-07-05 00:25:55 +02:00
|
|
|
/// return kPriorities[current_operator];
|
|
|
|
|
/// }
|
|
|
|
|
///
|
|
|
|
|
/// LocalSearchOperator* concat =
|
|
|
|
|
/// solver.ConcatenateOperators(operators,
|
|
|
|
|
/// NewPermanentCallback(&Evaluate));
|
|
|
|
|
///
|
|
|
|
|
/// The elements of the vector operators will be sorted by increasing priority
|
|
|
|
|
/// and explored in that order (tie-breaks are handled by keeping the relative
|
|
|
|
|
/// operator order in the vector). This would result in the following order:
|
|
|
|
|
/// operators[3], operators[0], operators[2], operators[1].
|
|
|
|
|
///
|
2020-10-29 14:25:39 +01:00
|
|
|
LocalSearchOperator* ConcatenateOperators(
|
|
|
|
|
const std::vector<LocalSearchOperator*>& ops);
|
|
|
|
|
LocalSearchOperator* ConcatenateOperators(
|
|
|
|
|
const std::vector<LocalSearchOperator*>& ops, bool restart);
|
|
|
|
|
LocalSearchOperator* ConcatenateOperators(
|
|
|
|
|
const std::vector<LocalSearchOperator*>& ops,
|
2021-04-01 12:13:35 +02:00
|
|
|
std::function<int64_t(int, int)> evaluator);
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Randomized version of local search concatenator; calls a random operator
|
|
|
|
|
/// at each call to MakeNextNeighbor().
|
2020-10-29 14:25:39 +01:00
|
|
|
LocalSearchOperator* RandomConcatenateOperators(
|
|
|
|
|
const std::vector<LocalSearchOperator*>& ops);
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Randomized version of local search concatenator; calls a random operator
|
|
|
|
|
/// at each call to MakeNextNeighbor(). The provided seed is used to
|
|
|
|
|
/// initialize the random number generator.
|
2020-10-29 14:25:39 +01:00
|
|
|
LocalSearchOperator* RandomConcatenateOperators(
|
2021-04-01 12:13:35 +02:00
|
|
|
const std::vector<LocalSearchOperator*>& ops, int32_t seed);
|
2012-06-13 16:14:46 +00:00
|
|
|
|
2020-10-18 16:38:25 +02:00
|
|
|
/// Creates a local search operator which concatenates a vector of operators.
|
2020-11-01 11:47:28 +01:00
|
|
|
/// Uses Multi-Armed Bandit approach for choosing the next operator to use.
|
|
|
|
|
/// Sorts operators based on Upper Confidence Bound Algorithm which evaluates
|
|
|
|
|
/// each operator as sum of average improvement and exploration function.
|
2020-10-18 16:38:25 +02:00
|
|
|
///
|
2020-11-01 11:47:28 +01:00
|
|
|
/// Updates the order of operators when accepts a neighbor with objective
|
|
|
|
|
/// improvement.
|
|
|
|
|
LocalSearchOperator* MultiArmedBanditConcatenateOperators(
|
|
|
|
|
const std::vector<LocalSearchOperator*>& ops, double memory_coefficient,
|
|
|
|
|
double exploration_coefficient, bool maximize);
|
2020-10-18 16:38:25 +02:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Creates a local search operator that wraps another local search
|
|
|
|
|
/// operator and limits the number of neighbors explored (i.e., calls
|
|
|
|
|
/// to MakeNextNeighbor from the current solution (between two calls
|
|
|
|
|
/// to Start()). When this limit is reached, MakeNextNeighbor()
|
|
|
|
|
/// returns false. The counter is cleared when Start() is called.
|
2023-05-31 14:27:08 +02:00
|
|
|
LocalSearchOperator* MakeNeighborhoodLimit(LocalSearchOperator* op,
|
2021-04-01 12:13:35 +02:00
|
|
|
int64_t limit);
|
2011-02-13 20:51:08 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Local Search decision builders factories.
|
|
|
|
|
/// Local search is used to improve a given solution. This initial solution
|
|
|
|
|
/// can be specified either by an Assignment or by a DecisionBulder, and the
|
|
|
|
|
/// corresponding variables, the initial solution being the first solution
|
|
|
|
|
/// found by the DecisionBuilder.
|
|
|
|
|
/// The LocalSearchPhaseParameters parameter holds the actual definition of
|
|
|
|
|
/// the local search phase:
|
|
|
|
|
/// - a local search operator used to explore the neighborhood of the current
|
|
|
|
|
/// solution,
|
|
|
|
|
/// - a decision builder to instantiate unbound variables once a neighbor has
|
|
|
|
|
/// been defined; in the case of LNS-based operators instantiates fragment
|
|
|
|
|
/// variables; search monitors can be added to this sub-search by wrapping
|
|
|
|
|
/// the decision builder with MakeSolveOnce.
|
|
|
|
|
/// - a search limit specifying how long local search looks for neighbors
|
|
|
|
|
/// before accepting one; the last neighbor is always taken and in the case
|
|
|
|
|
/// of a greedy search, this corresponds to the best local neighbor;
|
|
|
|
|
/// first-accept (which is the default behavior) can be modeled using a
|
|
|
|
|
/// solution found limit of 1,
|
|
|
|
|
/// - a vector of local search filters used to speed up the search by pruning
|
|
|
|
|
/// unfeasible neighbors.
|
|
|
|
|
/// Metaheuristics can be added by defining specialized search monitors;
|
|
|
|
|
/// currently down/up-hill climbing is available through OptimizeVar, as well
|
|
|
|
|
/// as Guided Local Search, Tabu Search and Simulated Annealing.
|
|
|
|
|
///
|
2010-09-15 12:42:33 +00:00
|
|
|
// TODO(user): Make a variant which runs a local search after each
|
2018-10-31 16:18:18 +01:00
|
|
|
// solution found in a DFS.
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2023-05-31 14:27:08 +02:00
|
|
|
DecisionBuilder* MakeLocalSearchPhase(Assignment* assignment,
|
|
|
|
|
LocalSearchPhaseParameters* parameters);
|
|
|
|
|
DecisionBuilder* MakeLocalSearchPhase(const std::vector<IntVar*>& vars,
|
|
|
|
|
DecisionBuilder* first_solution,
|
|
|
|
|
LocalSearchPhaseParameters* parameters);
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Variant with a sub_decison_builder specific to the first solution.
|
2020-10-29 14:25:39 +01:00
|
|
|
DecisionBuilder* MakeLocalSearchPhase(
|
2023-05-31 14:27:08 +02:00
|
|
|
const std::vector<IntVar*>& vars, DecisionBuilder* first_solution,
|
|
|
|
|
DecisionBuilder* first_solution_sub_decision_builder,
|
|
|
|
|
LocalSearchPhaseParameters* parameters);
|
|
|
|
|
DecisionBuilder* MakeLocalSearchPhase(const std::vector<SequenceVar*>& vars,
|
|
|
|
|
DecisionBuilder* first_solution,
|
|
|
|
|
LocalSearchPhaseParameters* parameters);
|
2010-10-14 13:47:55 +00:00
|
|
|
|
2023-12-01 10:32:14 +01:00
|
|
|
/// Experimental: runs a local search on the given initial solution, checking
|
|
|
|
|
/// the feasibility and the objective value of solutions using the filter
|
|
|
|
|
/// manager only (solutions are never restored in the CP world). Only greedy
|
|
|
|
|
/// descent is supported.
|
|
|
|
|
Assignment* RunUncheckedLocalSearch(
|
|
|
|
|
const Assignment* initial_solution,
|
|
|
|
|
LocalSearchFilterManager* filter_manager,
|
|
|
|
|
LocalSearchOperator* ls_operator,
|
2024-01-08 13:18:01 +01:00
|
|
|
const std::vector<SearchMonitor*>& monitors, RegularLimit* limit,
|
|
|
|
|
absl::flat_hash_set<IntVar*>* touched = nullptr);
|
2023-12-01 10:32:14 +01:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Solution Pool.
|
2020-10-29 14:25:39 +01:00
|
|
|
SolutionPool* MakeDefaultSolutionPool();
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Local Search Phase Parameters
|
2020-10-29 14:25:39 +01:00
|
|
|
LocalSearchPhaseParameters* MakeLocalSearchPhaseParameters(
|
2023-05-31 14:27:08 +02:00
|
|
|
IntVar* objective, LocalSearchOperator* ls_operator,
|
|
|
|
|
DecisionBuilder* sub_decision_builder);
|
2020-10-29 14:25:39 +01:00
|
|
|
LocalSearchPhaseParameters* MakeLocalSearchPhaseParameters(
|
2023-05-31 14:27:08 +02:00
|
|
|
IntVar* objective, LocalSearchOperator* ls_operator,
|
|
|
|
|
DecisionBuilder* sub_decision_builder, RegularLimit* limit);
|
2020-10-29 14:25:39 +01:00
|
|
|
LocalSearchPhaseParameters* MakeLocalSearchPhaseParameters(
|
2023-05-31 14:27:08 +02:00
|
|
|
IntVar* objective, LocalSearchOperator* ls_operator,
|
|
|
|
|
DecisionBuilder* sub_decision_builder, RegularLimit* limit,
|
2020-10-29 14:25:39 +01:00
|
|
|
LocalSearchFilterManager* filter_manager);
|
|
|
|
|
|
|
|
|
|
LocalSearchPhaseParameters* MakeLocalSearchPhaseParameters(
|
2023-05-31 14:27:08 +02:00
|
|
|
IntVar* objective, SolutionPool* pool, LocalSearchOperator* ls_operator,
|
|
|
|
|
DecisionBuilder* sub_decision_builder);
|
2020-10-29 14:25:39 +01:00
|
|
|
LocalSearchPhaseParameters* MakeLocalSearchPhaseParameters(
|
2023-05-31 14:27:08 +02:00
|
|
|
IntVar* objective, SolutionPool* pool, LocalSearchOperator* ls_operator,
|
|
|
|
|
DecisionBuilder* sub_decision_builder, RegularLimit* limit);
|
2020-10-29 14:25:39 +01:00
|
|
|
LocalSearchPhaseParameters* MakeLocalSearchPhaseParameters(
|
2023-05-31 14:27:08 +02:00
|
|
|
IntVar* objective, SolutionPool* pool, LocalSearchOperator* ls_operator,
|
|
|
|
|
DecisionBuilder* sub_decision_builder, RegularLimit* limit,
|
2020-10-29 14:25:39 +01:00
|
|
|
LocalSearchFilterManager* filter_manager);
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Local Search Filters
|
2020-10-29 14:25:39 +01:00
|
|
|
LocalSearchFilter* MakeAcceptFilter();
|
|
|
|
|
LocalSearchFilter* MakeRejectFilter();
|
|
|
|
|
LocalSearchFilter* MakeVariableDomainFilter();
|
|
|
|
|
IntVarLocalSearchFilter* MakeSumObjectiveFilter(
|
|
|
|
|
const std::vector<IntVar*>& vars, IndexEvaluator2 values,
|
2020-10-22 23:36:58 +02:00
|
|
|
Solver::LocalSearchFilterBound filter_enum);
|
2020-10-29 14:25:39 +01:00
|
|
|
IntVarLocalSearchFilter* MakeSumObjectiveFilter(
|
|
|
|
|
const std::vector<IntVar*>& vars,
|
|
|
|
|
const std::vector<IntVar*>& secondary_vars, IndexEvaluator3 values,
|
2020-10-22 23:36:58 +02:00
|
|
|
Solver::LocalSearchFilterBound filter_enum);
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Performs PeriodicCheck on the top-level search; for instance, can be
|
|
|
|
|
/// called from a nested solve to check top-level limits.
|
2010-09-15 12:42:33 +00:00
|
|
|
void TopPeriodicCheck();
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Returns a percentage representing the propress of the search before
|
|
|
|
|
/// reaching the limits of the top-level search (can be called from a nested
|
|
|
|
|
/// solve).
|
2012-02-09 19:42:58 +00:00
|
|
|
int TopProgressPercent();
|
|
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// The PushState and PopState methods manipulates the states
|
|
|
|
|
/// of the reversible objects. They are visible only because they
|
|
|
|
|
/// are useful to write unitary tests.
|
2010-09-15 12:42:33 +00:00
|
|
|
void PushState();
|
|
|
|
|
void PopState();
|
|
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Gets the search depth of the current active search. Returns -1 if
|
|
|
|
|
/// there is no active search opened.
|
2010-09-15 12:42:33 +00:00
|
|
|
int SearchDepth() const;
|
|
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Gets the search left depth of the current active search. Returns -1 if
|
|
|
|
|
/// there is no active search opened.
|
2010-09-15 12:42:33 +00:00
|
|
|
int SearchLeftDepth() const;
|
|
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Gets the number of nested searches. It returns 0 outside search,
|
|
|
|
|
/// 1 during the top level search, 2 or more in case of nested searches.
|
2010-09-15 12:42:33 +00:00
|
|
|
int SolveDepth() const;
|
|
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Sets the given branch selector on the current active search.
|
2015-08-13 16:00:54 +02:00
|
|
|
void SetBranchSelector(BranchSelector bs);
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Creates a decision builder that will set the branch selector.
|
2020-10-29 14:25:39 +01:00
|
|
|
DecisionBuilder* MakeApplyBranchSelector(BranchSelector bs);
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// All-in-one SaveAndSetValue.
|
2020-10-22 23:36:58 +02:00
|
|
|
template <class T>
|
2020-10-29 14:25:39 +01:00
|
|
|
void SaveAndSetValue(T* adr, T val) {
|
2010-09-15 12:42:33 +00:00
|
|
|
if (*adr != val) {
|
|
|
|
|
InternalSaveValue(adr);
|
|
|
|
|
*adr = val;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// All-in-one SaveAndAdd_value.
|
2020-10-22 23:36:58 +02:00
|
|
|
template <class T>
|
2020-10-29 14:25:39 +01:00
|
|
|
void SaveAndAdd(T* adr, T val) {
|
2011-12-16 21:02:59 +00:00
|
|
|
if (val != 0) {
|
|
|
|
|
InternalSaveValue(adr);
|
|
|
|
|
(*adr) += val;
|
|
|
|
|
}
|
2010-09-15 12:42:33 +00:00
|
|
|
}
|
|
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Returns a random value between 0 and 'size' - 1;
|
2021-04-01 12:13:35 +02:00
|
|
|
int64_t Rand64(int64_t size) {
|
2019-11-20 14:28:11 -08:00
|
|
|
DCHECK_GT(size, 0);
|
2021-04-01 12:13:35 +02:00
|
|
|
return absl::Uniform<int64_t>(random_, 0, size);
|
2019-11-20 14:28:11 -08:00
|
|
|
}
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Returns a random value between 0 and 'size' - 1;
|
2021-04-01 12:13:35 +02:00
|
|
|
int32_t Rand32(int32_t size) {
|
2019-11-20 14:28:11 -08:00
|
|
|
DCHECK_GT(size, 0);
|
2021-04-01 12:13:35 +02:00
|
|
|
return absl::Uniform<int32_t>(random_, 0, size);
|
2019-11-20 14:28:11 -08:00
|
|
|
}
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Reseed the solver random generator.
|
2021-04-01 12:13:35 +02:00
|
|
|
void ReSeed(int32_t seed) { random_.seed(seed); }
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Exports the profiling information in a human readable overview.
|
|
|
|
|
/// The parameter profile_level used to create the solver must be
|
|
|
|
|
/// set to true.
|
2020-10-29 14:25:39 +01:00
|
|
|
void ExportProfilingOverview(const std::string& filename);
|
2011-01-06 17:40:30 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Returns local search profiling information in a human readable format.
|
2020-08-10 10:55:34 +02:00
|
|
|
// TODO(user): Merge demon and local search profiles.
|
2016-07-28 10:15:46 -07:00
|
|
|
std::string LocalSearchProfile() const;
|
|
|
|
|
|
2020-08-10 10:55:34 +02:00
|
|
|
#if !defined(SWIG)
|
2020-10-18 16:38:25 +02:00
|
|
|
/// Returns detailed cp search statistics.
|
|
|
|
|
ConstraintSolverStatistics GetConstraintSolverStatistics() const;
|
2020-08-10 10:55:34 +02:00
|
|
|
/// Returns detailed local search statistics.
|
|
|
|
|
LocalSearchStatistics GetLocalSearchStatistics() const;
|
2020-10-22 23:36:58 +02:00
|
|
|
#endif // !defined(SWIG)
|
2020-08-10 10:55:34 +02:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Returns true whether the current search has been
|
|
|
|
|
/// created using a Solve() call instead of a NewSearch one. It
|
|
|
|
|
/// returns false if the solver is not in search at all.
|
2010-09-15 12:42:33 +00:00
|
|
|
bool CurrentlyInSolve() const;
|
|
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Counts the number of constraints that have been added
|
|
|
|
|
/// to the solver before the search.
|
2011-07-15 18:51:39 +00:00
|
|
|
int constraints() const { return constraints_list_.size(); }
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Accepts the given model visitor.
|
2023-05-31 14:27:08 +02:00
|
|
|
void Accept(ModelVisitor* visitor) const;
|
2011-08-11 07:26:19 +00:00
|
|
|
|
2020-10-29 14:25:39 +01:00
|
|
|
Decision* balancing_decision() const { return balancing_decision_.get(); }
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2020-10-29 15:56:44 +01:00
|
|
|
/// Internal
|
2015-08-13 16:00:54 +02:00
|
|
|
#if !defined(SWIG)
|
2015-05-04 17:30:16 +02:00
|
|
|
void set_fail_intercept(std::function<void()> fail_intercept) {
|
2017-04-19 16:20:56 +02:00
|
|
|
fail_intercept_ = std::move(fail_intercept);
|
2015-05-04 17:30:16 +02:00
|
|
|
}
|
2020-10-22 23:36:58 +02:00
|
|
|
#endif // !defined(SWIG)
|
2013-10-10 15:23:20 +00:00
|
|
|
void clear_fail_intercept() { fail_intercept_ = nullptr; }
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Access to demon profiler.
|
2020-10-29 14:25:39 +01:00
|
|
|
DemonProfiler* demon_profiler() const { return demon_profiler_; }
|
2019-03-15 17:17:02 +01:00
|
|
|
// TODO(user): Get rid of the following methods once fast local search is
|
2019-07-05 00:25:55 +02:00
|
|
|
/// enabled for metaheuristics.
|
|
|
|
|
/// Disables/enables fast local search.
|
2019-03-15 17:17:02 +01:00
|
|
|
void SetUseFastLocalSearch(bool use_fast_local_search) {
|
|
|
|
|
use_fast_local_search_ = use_fast_local_search;
|
|
|
|
|
}
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Returns true if fast local search is enabled.
|
2019-03-15 17:17:02 +01:00
|
|
|
bool UseFastLocalSearch() const { return use_fast_local_search_; }
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Returns whether the object has been named or not.
|
2020-10-29 14:25:39 +01:00
|
|
|
bool HasName(const PropagationBaseObject* object) const;
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Adds a new demon and wraps it inside a DemonProfiler if necessary.
|
2023-05-31 14:27:08 +02:00
|
|
|
Demon* RegisterDemon(Demon* demon);
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Registers a new IntExpr and wraps it inside a TraceIntExpr if necessary.
|
2023-05-31 14:27:08 +02:00
|
|
|
IntExpr* RegisterIntExpr(IntExpr* expr);
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Registers a new IntVar and wraps it inside a TraceIntVar if necessary.
|
2023-05-31 14:27:08 +02:00
|
|
|
IntVar* RegisterIntVar(IntVar* var);
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Registers a new IntervalVar and wraps it inside a TraceIntervalVar
|
|
|
|
|
/// if necessary.
|
2023-05-31 14:27:08 +02:00
|
|
|
IntervalVar* RegisterIntervalVar(IntervalVar* var);
|
2011-11-09 10:59:31 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Returns the active search, nullptr outside search.
|
2020-10-29 14:25:39 +01:00
|
|
|
Search* ActiveSearch() const;
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Returns the cache of the model.
|
2020-10-29 14:25:39 +01:00
|
|
|
ModelCache* Cache() const;
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Returns whether we are instrumenting demons.
|
2011-11-10 09:36:43 +00:00
|
|
|
bool InstrumentsDemons() const;
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Returns whether we are profiling the solver.
|
2011-11-14 20:55:35 +00:00
|
|
|
bool IsProfilingEnabled() const;
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Returns whether we are profiling local search.
|
2016-07-28 10:15:46 -07:00
|
|
|
bool IsLocalSearchProfilingEnabled() const;
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Returns whether we are tracing variables.
|
2011-11-10 09:36:43 +00:00
|
|
|
bool InstrumentsVariables() const;
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Returns whether all variables should be named.
|
2011-11-19 01:59:37 +00:00
|
|
|
bool NameAllVariables() const;
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Returns the name of the model.
|
2013-12-16 10:24:42 +00:00
|
|
|
std::string model_name() const;
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Returns the propagation monitor.
|
2020-10-29 14:25:39 +01:00
|
|
|
PropagationMonitor* GetPropagationMonitor() const;
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Adds the propagation monitor to the solver. This is called internally when
|
|
|
|
|
/// a propagation monitor is passed to the Solve() or NewSearch() method.
|
2023-05-31 14:27:08 +02:00
|
|
|
void AddPropagationMonitor(PropagationMonitor* monitor);
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Returns the local search monitor.
|
2020-10-29 14:25:39 +01:00
|
|
|
LocalSearchMonitor* GetLocalSearchMonitor() const;
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Adds the local search monitor to the solver. This is called internally
|
|
|
|
|
/// when a propagation monitor is passed to the Solve() or NewSearch() method.
|
2020-10-29 14:25:39 +01:00
|
|
|
void AddLocalSearchMonitor(LocalSearchMonitor* monitor);
|
2024-01-08 13:18:01 +01:00
|
|
|
void SetSearchContext(Search* search, absl::string_view search_context);
|
2018-10-31 16:18:18 +01:00
|
|
|
std::string SearchContext() const;
|
2020-10-29 14:25:39 +01:00
|
|
|
std::string SearchContext(const Search* search) const;
|
2025-07-23 15:07:49 +02:00
|
|
|
bool AcceptSolution(Search* search) const;
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Returns (or creates) an assignment representing the state of local search.
|
2019-03-15 17:17:02 +01:00
|
|
|
// TODO(user): Investigate if this should be moved to Search.
|
2020-10-29 14:25:39 +01:00
|
|
|
Assignment* GetOrCreateLocalSearchState();
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Clears the local search state.
|
2019-03-15 17:17:02 +01:00
|
|
|
void ClearLocalSearchState() { local_search_state_.reset(nullptr); }
|
2010-10-08 23:55:59 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Unsafe temporary vector. It is used to avoid leaks in operations
|
|
|
|
|
/// that need storage and that may fail. See IntVar::SetValues() for
|
|
|
|
|
/// instance. It is not locked; do not use in a multi-threaded or reentrant
|
|
|
|
|
/// setup.
|
2021-04-01 12:13:35 +02:00
|
|
|
std::vector<int64_t> tmp_vector_;
|
2013-10-10 15:23:20 +00:00
|
|
|
|
2011-01-06 17:40:30 +00:00
|
|
|
friend class BaseIntExpr;
|
2011-08-11 05:15:18 +00:00
|
|
|
friend class Constraint;
|
2011-01-06 17:40:30 +00:00
|
|
|
friend class DemonProfiler;
|
|
|
|
|
friend class FindOneNeighbor;
|
2011-07-11 20:13:14 +00:00
|
|
|
friend class IntVar;
|
2011-01-06 17:40:30 +00:00
|
|
|
friend class PropagationBaseObject;
|
|
|
|
|
friend class Queue;
|
2010-09-15 12:42:33 +00:00
|
|
|
friend class SearchMonitor;
|
2013-07-18 14:53:24 +00:00
|
|
|
friend class SearchLimit;
|
2016-06-02 13:19:10 +02:00
|
|
|
friend class RoutingModel;
|
2023-09-25 18:06:35 +02:00
|
|
|
friend class LocalSearch;
|
2016-07-28 10:15:46 -07:00
|
|
|
friend class LocalSearchProfiler;
|
2011-08-11 05:15:18 +00:00
|
|
|
|
2016-02-03 15:15:58 +01:00
|
|
|
#if !defined(SWIG)
|
2023-05-31 14:27:08 +02:00
|
|
|
friend void InternalSaveBooleanVarValue(Solver*, IntVar*);
|
2020-10-22 23:36:58 +02:00
|
|
|
template <class>
|
|
|
|
|
friend class SimpleRevFIFO;
|
|
|
|
|
template <class K, class V>
|
|
|
|
|
friend class RevImmutableMultiMap;
|
2016-02-03 15:15:58 +01:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Returns true if expr represents either boolean_var or 1 -
|
|
|
|
|
/// boolean_var. In that case, it fills inner_var and is_negated to be
|
|
|
|
|
/// true if the expression is 1 - boolean_var -- equivalent to
|
|
|
|
|
/// not(boolean_var).
|
2023-05-31 14:27:08 +02:00
|
|
|
bool IsBooleanVar(IntExpr* expr, IntVar** inner_var, bool* is_negated) const;
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Returns true if expr represents a product of a expr and a
|
|
|
|
|
/// constant. In that case, it fills inner_expr and coefficient with
|
|
|
|
|
/// these, and returns true. In the other case, it fills inner_expr
|
|
|
|
|
/// with expr, coefficient with 1, and returns false.
|
2023-05-31 14:27:08 +02:00
|
|
|
bool IsProduct(IntExpr* expr, IntExpr** inner_expr, int64_t* coefficient);
|
2020-10-22 23:36:58 +02:00
|
|
|
#endif /// !defined(SWIG)
|
2013-09-19 06:59:49 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Internal. If the variables is the result of expr->Var(), this
|
|
|
|
|
/// method returns expr, nullptr otherwise.
|
2023-05-31 14:27:08 +02:00
|
|
|
IntExpr* CastExpression(const IntVar* var) const;
|
2013-06-11 14:49:19 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Tells the solver to kill or restart the current search.
|
2014-07-09 11:10:20 +00:00
|
|
|
void FinishCurrentSearch();
|
|
|
|
|
void RestartCurrentSearch();
|
|
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// These methods are only useful for the SWIG wrappers, which need a way
|
|
|
|
|
/// to externally cause the Solver to fail.
|
2014-07-09 11:10:20 +00:00
|
|
|
void ShouldFail() { should_fail_ = true; }
|
|
|
|
|
void CheckFail() {
|
2020-10-22 23:36:58 +02:00
|
|
|
if (!should_fail_) return;
|
2014-07-09 11:10:20 +00:00
|
|
|
should_fail_ = false;
|
|
|
|
|
Fail();
|
|
|
|
|
}
|
2014-05-22 17:37:21 +00:00
|
|
|
|
2021-12-05 12:15:27 +01:00
|
|
|
/// Activates profiling on a decision builder.
|
|
|
|
|
DecisionBuilder* MakeProfiledDecisionBuilderWrapper(DecisionBuilder* db);
|
|
|
|
|
|
2020-10-22 23:36:58 +02:00
|
|
|
private:
|
|
|
|
|
void Init(); /// Initialization. To be called by the constructors only.
|
2020-10-29 14:25:39 +01:00
|
|
|
void PushState(MarkerType t, const StateInfo& info);
|
|
|
|
|
MarkerType PopState(StateInfo* info);
|
2010-09-15 12:42:33 +00:00
|
|
|
void PushSentinel(int magic_code);
|
|
|
|
|
void BacktrackToSentinel(int magic_code);
|
|
|
|
|
void ProcessConstraints();
|
2020-10-29 14:25:39 +01:00
|
|
|
bool BacktrackOneLevel(Decision** fail_decision);
|
2010-09-15 12:42:33 +00:00
|
|
|
void JumpToSentinelWhenNested();
|
|
|
|
|
void JumpToSentinel();
|
|
|
|
|
void check_alloc_state();
|
|
|
|
|
void FreezeQueue();
|
2023-05-31 14:27:08 +02:00
|
|
|
void EnqueueVar(Demon* d);
|
|
|
|
|
void EnqueueDelayedDemon(Demon* d);
|
2020-10-29 14:25:39 +01:00
|
|
|
void ExecuteAll(const SimpleRevFIFO<Demon*>& demons);
|
|
|
|
|
void EnqueueAll(const SimpleRevFIFO<Demon*>& demons);
|
2010-09-15 12:42:33 +00:00
|
|
|
void UnfreezeQueue();
|
2015-10-23 13:45:43 +02:00
|
|
|
void reset_action_on_fail();
|
|
|
|
|
void set_action_on_fail(Action a);
|
2020-10-29 14:25:39 +01:00
|
|
|
void set_variable_to_clean_on_fail(IntVar* v);
|
2019-04-16 09:25:06 -07:00
|
|
|
void IncrementUncheckedSolutionCounter();
|
|
|
|
|
bool IsUncheckedSolutionLimitReached();
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2020-10-29 14:25:39 +01:00
|
|
|
void InternalSaveValue(int* valptr);
|
2021-04-01 12:13:35 +02:00
|
|
|
void InternalSaveValue(int64_t* valptr);
|
|
|
|
|
void InternalSaveValue(uint64_t* valptr);
|
2020-10-29 14:25:39 +01:00
|
|
|
void InternalSaveValue(double* valptr);
|
|
|
|
|
void InternalSaveValue(bool* valptr);
|
|
|
|
|
void InternalSaveValue(void** valptr);
|
2021-04-01 12:13:35 +02:00
|
|
|
void InternalSaveValue(int64_t** valptr) {
|
2020-10-29 14:25:39 +01:00
|
|
|
InternalSaveValue(reinterpret_cast<void**>(valptr));
|
2010-09-15 12:42:33 +00:00
|
|
|
}
|
2011-01-06 17:40:30 +00:00
|
|
|
|
2020-10-29 14:25:39 +01:00
|
|
|
BaseObject* SafeRevAlloc(BaseObject* ptr);
|
2011-11-14 20:55:35 +00:00
|
|
|
|
2020-10-29 14:25:39 +01:00
|
|
|
int* SafeRevAllocArray(int* ptr);
|
2021-04-01 12:13:35 +02:00
|
|
|
int64_t* SafeRevAllocArray(int64_t* ptr);
|
|
|
|
|
uint64_t* SafeRevAllocArray(uint64_t* ptr);
|
2020-10-29 14:25:39 +01:00
|
|
|
double* SafeRevAllocArray(double* ptr);
|
|
|
|
|
BaseObject** SafeRevAllocArray(BaseObject** ptr);
|
|
|
|
|
IntVar** SafeRevAllocArray(IntVar** ptr);
|
|
|
|
|
IntExpr** SafeRevAllocArray(IntExpr** ptr);
|
|
|
|
|
Constraint** SafeRevAllocArray(Constraint** ptr);
|
2019-07-05 00:25:55 +02:00
|
|
|
/// UnsafeRevAlloc is used internally for cells in SimpleRevFIFO
|
|
|
|
|
/// and other structures like this.
|
2020-10-29 14:25:39 +01:00
|
|
|
void* UnsafeRevAllocAux(void* ptr);
|
2020-10-22 23:36:58 +02:00
|
|
|
template <class T>
|
2020-10-29 14:25:39 +01:00
|
|
|
T* UnsafeRevAlloc(T* ptr) {
|
|
|
|
|
return reinterpret_cast<T*>(
|
|
|
|
|
UnsafeRevAllocAux(reinterpret_cast<void*>(ptr)));
|
2010-09-15 12:42:33 +00:00
|
|
|
}
|
2020-10-29 14:25:39 +01:00
|
|
|
void** UnsafeRevAllocArrayAux(void** ptr);
|
2020-10-22 23:36:58 +02:00
|
|
|
template <class T>
|
2020-10-29 14:25:39 +01:00
|
|
|
T** UnsafeRevAllocArray(T** ptr) {
|
|
|
|
|
return reinterpret_cast<T**>(
|
|
|
|
|
UnsafeRevAllocArrayAux(reinterpret_cast<void**>(ptr)));
|
2010-09-15 12:42:33 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void InitCachedIntConstants();
|
|
|
|
|
void InitCachedConstraint();
|
2018-10-31 16:18:18 +01:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Returns the Search object that is at the bottom of the search stack.
|
|
|
|
|
/// Contrast with ActiveSearch(), which returns the search at the
|
|
|
|
|
/// top of the stack.
|
2020-10-29 14:25:39 +01:00
|
|
|
Search* TopLevelSearch() const { return searches_.at(1); }
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Returns the Search object which is the parent of the active search, i.e.,
|
|
|
|
|
/// the search below the top of the stack. If the active search is at the
|
|
|
|
|
/// bottom of the stack, returns the active search.
|
2020-10-29 14:25:39 +01:00
|
|
|
Search* ParentSearch() const {
|
2012-02-14 14:16:12 +00:00
|
|
|
const size_t search_size = searches_.size();
|
|
|
|
|
DCHECK_GT(search_size, 1);
|
|
|
|
|
return searches_[search_size - 2];
|
|
|
|
|
}
|
2011-12-15 11:50:32 +00:00
|
|
|
|
2023-12-01 10:32:14 +01:00
|
|
|
template <bool is_profile_active>
|
|
|
|
|
Assignment* RunUncheckedLocalSearchInternal(
|
|
|
|
|
const Assignment* initial_solution,
|
|
|
|
|
LocalSearchFilterManager* filter_manager,
|
|
|
|
|
LocalSearchOperator* ls_operator,
|
2024-01-08 13:18:01 +01:00
|
|
|
const std::vector<SearchMonitor*>& monitors, RegularLimit* limit,
|
|
|
|
|
absl::flat_hash_set<IntVar*>* touched);
|
2023-12-01 10:32:14 +01:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Naming
|
2020-10-29 14:25:39 +01:00
|
|
|
std::string GetName(const PropagationBaseObject* object);
|
2023-11-09 13:46:25 +01:00
|
|
|
void SetName(const PropagationBaseObject* object, absl::string_view name);
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Variable indexing (note that indexing is not reversible).
|
|
|
|
|
/// Returns a new index for an IntVar.
|
2014-11-07 14:30:53 +00:00
|
|
|
int GetNewIntVarIndex() { return num_int_vars_++; }
|
|
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Internal.
|
2023-05-31 14:27:08 +02:00
|
|
|
bool IsADifference(IntExpr* expr, IntExpr** left, IntExpr** right);
|
2012-06-19 15:24:32 +00:00
|
|
|
|
2013-12-16 10:24:42 +00:00
|
|
|
const std::string name_;
|
2016-02-03 15:15:58 +01:00
|
|
|
const ConstraintSolverParameters parameters_;
|
2020-10-29 14:25:39 +01:00
|
|
|
absl::flat_hash_map<const PropagationBaseObject*, std::string>
|
2018-06-08 16:40:43 +02:00
|
|
|
propagation_object_names_;
|
2020-10-29 14:25:39 +01:00
|
|
|
absl::flat_hash_map<const PropagationBaseObject*, IntegerCastInfo>
|
2018-06-08 16:40:43 +02:00
|
|
|
cast_information_;
|
2020-10-29 14:25:39 +01:00
|
|
|
absl::flat_hash_set<const Constraint*> cast_constraints_;
|
2013-12-16 10:24:42 +00:00
|
|
|
const std::string empty_name_;
|
2013-12-10 16:02:46 +00:00
|
|
|
std::unique_ptr<Queue> queue_;
|
|
|
|
|
std::unique_ptr<Trail> trail_;
|
2020-10-29 14:25:39 +01:00
|
|
|
std::vector<Constraint*> constraints_list_;
|
|
|
|
|
std::vector<Constraint*> additional_constraints_list_;
|
2011-07-15 18:51:39 +00:00
|
|
|
std::vector<int> additional_constraints_parent_list_;
|
2010-09-15 12:42:33 +00:00
|
|
|
SolverState state_;
|
2021-04-01 12:13:35 +02:00
|
|
|
int64_t branches_;
|
|
|
|
|
int64_t fails_;
|
|
|
|
|
int64_t decisions_;
|
|
|
|
|
int64_t demon_runs_[kNumPriorities];
|
|
|
|
|
int64_t neighbors_;
|
|
|
|
|
int64_t filtered_neighbors_;
|
|
|
|
|
int64_t accepted_neighbors_;
|
2022-12-07 17:37:45 +01:00
|
|
|
std::string context_;
|
2019-03-15 17:17:02 +01:00
|
|
|
OptimizationDirection optimization_direction_;
|
2013-12-10 16:02:46 +00:00
|
|
|
std::unique_ptr<ClockTimer> timer_;
|
2020-10-29 14:25:39 +01:00
|
|
|
std::vector<Search*> searches_;
|
2019-11-20 14:28:11 -08:00
|
|
|
std::mt19937 random_;
|
2021-04-01 12:13:35 +02:00
|
|
|
uint64_t fail_stamp_;
|
2013-12-10 16:02:46 +00:00
|
|
|
std::unique_ptr<Decision> balancing_decision_;
|
2019-07-05 00:25:55 +02:00
|
|
|
/// intercept failures
|
2015-05-04 17:30:16 +02:00
|
|
|
std::function<void()> fail_intercept_;
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Demon monitor
|
2020-10-29 14:25:39 +01:00
|
|
|
DemonProfiler* const demon_profiler_;
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Local search mode
|
2019-03-15 17:17:02 +01:00
|
|
|
bool use_fast_local_search_;
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Local search profiler monitor
|
2020-10-29 14:25:39 +01:00
|
|
|
LocalSearchProfiler* const local_search_profiler_;
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Local search state.
|
2019-03-15 17:17:02 +01:00
|
|
|
std::unique_ptr<Assignment> local_search_state_;
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// interval of constants cached, inclusive:
|
2020-10-22 23:36:58 +02:00
|
|
|
enum { MIN_CACHED_INT_CONST = -8, MAX_CACHED_INT_CONST = 8 };
|
2020-10-29 14:25:39 +01:00
|
|
|
IntVar* cached_constants_[MAX_CACHED_INT_CONST + 1 - MIN_CACHED_INT_CONST];
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Cached constraints.
|
2020-10-29 14:25:39 +01:00
|
|
|
Constraint* true_constraint_;
|
|
|
|
|
Constraint* false_constraint_;
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2013-12-10 16:02:46 +00:00
|
|
|
std::unique_ptr<Decision> fail_decision_;
|
2011-07-15 18:51:39 +00:00
|
|
|
int constraint_index_;
|
|
|
|
|
int additional_constraint_index_;
|
2014-11-07 14:30:53 +00:00
|
|
|
int num_int_vars_;
|
2011-01-06 17:40:30 +00:00
|
|
|
|
2013-12-10 16:02:46 +00:00
|
|
|
std::unique_ptr<ModelCache> model_cache_;
|
|
|
|
|
std::unique_ptr<PropagationMonitor> propagation_monitor_;
|
2020-10-29 14:25:39 +01:00
|
|
|
PropagationMonitor* print_trace_;
|
2016-07-28 10:15:46 -07:00
|
|
|
std::unique_ptr<LocalSearchMonitor> local_search_monitor_;
|
2011-11-19 01:59:37 +00:00
|
|
|
int anonymous_variable_index_;
|
2014-05-22 17:37:21 +00:00
|
|
|
bool should_fail_;
|
2024-11-18 11:32:13 +01:00
|
|
|
|
|
|
|
|
std::function<int64_t(int64_t, int64_t, int64_t)> penalty_callback_;
|
2010-09-15 12:42:33 +00:00
|
|
|
};
|
|
|
|
|
|
2020-10-29 14:25:39 +01:00
|
|
|
std::ostream& operator<<(std::ostream& out, const Solver* const s); /// NOLINT
|
2011-12-16 21:02:59 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// This method returns 0. It is useful when 0 can be cast either as
|
|
|
|
|
/// a pointer or as an integer value and thus lead to an ambiguous
|
|
|
|
|
/// function call.
|
2021-04-01 12:13:35 +02:00
|
|
|
inline int64_t Zero() { return 0; }
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// This method returns 1
|
2021-04-01 12:13:35 +02:00
|
|
|
inline int64_t One() { return 1; }
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// A BaseObject is the root of all reversibly allocated objects.
|
2020-10-18 16:38:25 +02:00
|
|
|
/// A DebugString method and the associated << operator are implemented
|
|
|
|
|
/// as a convenience.
|
2010-09-15 12:42:33 +00:00
|
|
|
class BaseObject {
|
2020-10-22 23:36:58 +02:00
|
|
|
public:
|
2010-09-15 12:42:33 +00:00
|
|
|
BaseObject() {}
|
2023-09-25 18:06:35 +02:00
|
|
|
|
|
|
|
|
#ifndef SWIG
|
|
|
|
|
// This type is neither copyable nor movable.
|
|
|
|
|
BaseObject(const BaseObject&) = delete;
|
|
|
|
|
BaseObject& operator=(const BaseObject&) = delete;
|
|
|
|
|
#endif
|
2025-03-07 10:33:36 +01:00
|
|
|
virtual ~BaseObject() = default;
|
2013-12-16 10:24:42 +00:00
|
|
|
virtual std::string DebugString() const { return "BaseObject"; }
|
2010-09-15 12:42:33 +00:00
|
|
|
};
|
|
|
|
|
|
2020-10-29 14:25:39 +01:00
|
|
|
std::ostream& operator<<(std::ostream& out, const BaseObject* o); /// NOLINT
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// The PropagationBaseObject is a subclass of BaseObject that is also
|
|
|
|
|
/// friend to the Solver class. It allows accessing methods useful when
|
|
|
|
|
/// writing new constraints or new expressions.
|
2010-09-15 12:42:33 +00:00
|
|
|
class PropagationBaseObject : public BaseObject {
|
2020-10-22 23:36:58 +02:00
|
|
|
public:
|
2020-10-29 14:25:39 +01:00
|
|
|
explicit PropagationBaseObject(Solver* const s) : solver_(s) {}
|
2023-09-25 18:06:35 +02:00
|
|
|
|
|
|
|
|
#ifndef SWIG
|
|
|
|
|
// This type is neither copyable nor movable.
|
|
|
|
|
PropagationBaseObject(const PropagationBaseObject&) = delete;
|
|
|
|
|
PropagationBaseObject& operator=(const PropagationBaseObject&) = delete;
|
|
|
|
|
#endif
|
2024-11-18 11:32:13 +01:00
|
|
|
~PropagationBaseObject() override {};
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2015-04-16 15:49:51 +02:00
|
|
|
std::string DebugString() const override {
|
2010-11-25 16:17:02 +00:00
|
|
|
if (name().empty()) {
|
|
|
|
|
return "PropagationBaseObject";
|
|
|
|
|
} else {
|
2018-10-31 16:18:18 +01:00
|
|
|
return absl::StrFormat("PropagationBaseObject: %s", name());
|
2010-11-25 16:17:02 +00:00
|
|
|
}
|
2010-09-15 12:42:33 +00:00
|
|
|
}
|
2020-10-29 14:25:39 +01:00
|
|
|
Solver* solver() const { return solver_; }
|
2019-07-05 00:25:55 +02:00
|
|
|
|
|
|
|
|
/// This method freezes the propagation queue. It is useful when you
|
|
|
|
|
/// need to apply multiple modifications at once.
|
2010-09-15 12:42:33 +00:00
|
|
|
void FreezeQueue() { solver_->FreezeQueue(); }
|
|
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// This method unfreezes the propagation queue. All modifications
|
|
|
|
|
/// that happened when the queue was frozen will be processed.
|
2010-09-15 12:42:33 +00:00
|
|
|
void UnfreezeQueue() { solver_->UnfreezeQueue(); }
|
|
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// This method pushes the demon onto the propagation queue. It will
|
|
|
|
|
/// be processed directly if the queue is empty. It will be enqueued
|
|
|
|
|
/// according to its priority otherwise.
|
2020-10-29 14:25:39 +01:00
|
|
|
void EnqueueDelayedDemon(Demon* const d) { solver_->EnqueueDelayedDemon(d); }
|
|
|
|
|
void EnqueueVar(Demon* const d) { solver_->EnqueueVar(d); }
|
|
|
|
|
void ExecuteAll(const SimpleRevFIFO<Demon*>& demons);
|
|
|
|
|
void EnqueueAll(const SimpleRevFIFO<Demon*>& demons);
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2015-11-18 16:45:30 +01:00
|
|
|
#if !defined(SWIG)
|
2010-09-15 12:42:33 +00:00
|
|
|
// This method sets a callback that will be called if a failure
|
|
|
|
|
// happens during the propagation of the queue.
|
2017-04-19 16:20:56 +02:00
|
|
|
void set_action_on_fail(Solver::Action a) {
|
|
|
|
|
solver_->set_action_on_fail(std::move(a));
|
|
|
|
|
}
|
2020-10-22 23:36:58 +02:00
|
|
|
#endif // !defined(SWIG)
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// This method clears the failure callback.
|
2015-10-23 13:45:43 +02:00
|
|
|
void reset_action_on_fail() { solver_->reset_action_on_fail(); }
|
|
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Shortcut for variable cleaner.
|
2020-10-29 14:25:39 +01:00
|
|
|
void set_variable_to_clean_on_fail(IntVar* v) {
|
2015-10-23 13:45:43 +02:00
|
|
|
solver_->set_variable_to_clean_on_fail(v);
|
|
|
|
|
}
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Object naming.
|
2013-12-16 10:24:42 +00:00
|
|
|
virtual std::string name() const;
|
2024-01-10 14:23:02 +01:00
|
|
|
void set_name(absl::string_view name);
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Returns whether the object has been named or not.
|
2011-08-11 05:15:18 +00:00
|
|
|
bool HasName() const;
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Returns a base name for automatic naming.
|
2013-12-16 10:24:42 +00:00
|
|
|
virtual std::string BaseName() const;
|
2011-08-11 05:15:18 +00:00
|
|
|
|
2020-10-22 23:36:58 +02:00
|
|
|
private:
|
2020-10-29 14:25:39 +01:00
|
|
|
Solver* const solver_;
|
2010-09-15 12:42:33 +00:00
|
|
|
};
|
|
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// A Decision represents a choice point in the search tree. The two main
|
|
|
|
|
/// methods are Apply() to go left, or Refute() to go right.
|
2010-09-15 12:42:33 +00:00
|
|
|
class Decision : public BaseObject {
|
2020-10-22 23:36:58 +02:00
|
|
|
public:
|
2010-09-15 12:42:33 +00:00
|
|
|
Decision() {}
|
2023-09-25 18:06:35 +02:00
|
|
|
|
|
|
|
|
#ifndef SWIG
|
|
|
|
|
// This type is neither copyable nor movable.
|
|
|
|
|
Decision(const Decision&) = delete;
|
|
|
|
|
Decision& operator=(const Decision&) = delete;
|
|
|
|
|
#endif
|
2015-04-16 15:49:51 +02:00
|
|
|
~Decision() override {}
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Apply will be called first when the decision is executed.
|
2023-05-31 14:27:08 +02:00
|
|
|
virtual void Apply(Solver* s) = 0;
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Refute will be called after a backtrack.
|
2023-05-31 14:27:08 +02:00
|
|
|
virtual void Refute(Solver* s) = 0;
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2015-04-16 15:49:51 +02:00
|
|
|
std::string DebugString() const override { return "Decision"; }
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Accepts the given visitor.
|
2023-05-31 14:27:08 +02:00
|
|
|
virtual void Accept(DecisionVisitor* visitor) const;
|
2010-09-15 12:42:33 +00:00
|
|
|
};
|
|
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// A DecisionVisitor is used to inspect a decision.
|
|
|
|
|
/// It contains virtual methods for all type of 'declared' decisions.
|
2010-09-15 12:42:33 +00:00
|
|
|
class DecisionVisitor : public BaseObject {
|
2020-10-22 23:36:58 +02:00
|
|
|
public:
|
2010-09-15 12:42:33 +00:00
|
|
|
DecisionVisitor() {}
|
2023-09-25 18:06:35 +02:00
|
|
|
|
|
|
|
|
#ifndef SWIG
|
|
|
|
|
// This type is neither copyable nor movable.
|
|
|
|
|
DecisionVisitor(const DecisionVisitor&) = delete;
|
|
|
|
|
DecisionVisitor& operator=(const DecisionVisitor&) = delete;
|
|
|
|
|
#endif
|
2015-04-16 15:49:51 +02:00
|
|
|
~DecisionVisitor() override {}
|
2023-05-31 14:27:08 +02:00
|
|
|
virtual void VisitSetVariableValue(IntVar* var, int64_t value);
|
|
|
|
|
virtual void VisitSplitVariableDomain(IntVar* var, int64_t value,
|
2010-10-15 13:22:21 +00:00
|
|
|
bool start_with_lower_half);
|
2023-05-31 14:27:08 +02:00
|
|
|
virtual void VisitScheduleOrPostpone(IntervalVar* var, int64_t est);
|
|
|
|
|
virtual void VisitScheduleOrExpedite(IntervalVar* var, int64_t est);
|
|
|
|
|
virtual void VisitRankFirstInterval(SequenceVar* sequence, int index);
|
|
|
|
|
virtual void VisitRankLastInterval(SequenceVar* sequence, int index);
|
2010-09-15 12:42:33 +00:00
|
|
|
virtual void VisitUnknownDecision();
|
|
|
|
|
};
|
|
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// A DecisionBuilder is responsible for creating the search tree. The
|
|
|
|
|
/// important method is Next(), which returns the next decision to execute.
|
2010-09-15 12:42:33 +00:00
|
|
|
class DecisionBuilder : public BaseObject {
|
2020-10-22 23:36:58 +02:00
|
|
|
public:
|
2010-09-15 12:42:33 +00:00
|
|
|
DecisionBuilder() {}
|
2023-09-25 18:06:35 +02:00
|
|
|
|
|
|
|
|
#ifndef SWIG
|
|
|
|
|
// This type is neither copyable nor movable.
|
|
|
|
|
DecisionBuilder(const DecisionBuilder&) = delete;
|
|
|
|
|
DecisionBuilder& operator=(const DecisionBuilder&) = delete;
|
|
|
|
|
#endif
|
2015-04-16 15:49:51 +02:00
|
|
|
~DecisionBuilder() override {}
|
2019-07-05 00:25:55 +02:00
|
|
|
/// This is the main method of the decision builder class. It must
|
|
|
|
|
/// return a decision (an instance of the class Decision). If it
|
|
|
|
|
/// returns nullptr, this means that the decision builder has finished
|
|
|
|
|
/// its work.
|
2023-05-31 14:27:08 +02:00
|
|
|
virtual Decision* Next(Solver* s) = 0;
|
2015-04-16 15:49:51 +02:00
|
|
|
std::string DebugString() const override;
|
2014-07-09 11:10:20 +00:00
|
|
|
#if !defined(SWIG)
|
2019-07-05 00:25:55 +02:00
|
|
|
/// This method will be called at the start of the search. It asks
|
|
|
|
|
/// the decision builder if it wants to append search monitors to the
|
|
|
|
|
/// list of active monitors for this search. Please note there are no
|
|
|
|
|
/// checks at this point for duplication.
|
2023-05-31 14:27:08 +02:00
|
|
|
virtual void AppendMonitors(Solver* solver,
|
|
|
|
|
std::vector<SearchMonitor*>* extras);
|
|
|
|
|
virtual void Accept(ModelVisitor* visitor) const;
|
2014-07-09 11:10:20 +00:00
|
|
|
#endif
|
2023-11-09 13:46:25 +01:00
|
|
|
void set_name(absl::string_view name) { name_ = name; }
|
2021-12-05 12:15:27 +01:00
|
|
|
std::string GetName() const;
|
2011-06-28 09:27:03 +00:00
|
|
|
|
2020-10-22 23:36:58 +02:00
|
|
|
private:
|
2021-12-05 12:15:27 +01:00
|
|
|
std::string name_;
|
2010-09-15 12:42:33 +00:00
|
|
|
};
|
|
|
|
|
|
2021-12-05 12:15:27 +01:00
|
|
|
#if !defined(SWIG)
|
|
|
|
|
class ProfiledDecisionBuilder : public DecisionBuilder {
|
|
|
|
|
public:
|
|
|
|
|
explicit ProfiledDecisionBuilder(DecisionBuilder* db);
|
|
|
|
|
~ProfiledDecisionBuilder() override {}
|
|
|
|
|
const std::string& name() const { return name_; }
|
|
|
|
|
double seconds() const { return seconds_; }
|
2023-05-31 14:27:08 +02:00
|
|
|
Decision* Next(Solver* solver) override;
|
2021-12-05 12:15:27 +01:00
|
|
|
std::string DebugString() const override;
|
2023-05-31 14:27:08 +02:00
|
|
|
void AppendMonitors(Solver* solver,
|
|
|
|
|
std::vector<SearchMonitor*>* extras) override;
|
|
|
|
|
void Accept(ModelVisitor* visitor) const override;
|
2021-12-05 12:15:27 +01:00
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
DecisionBuilder* const db_;
|
|
|
|
|
const std::string name_;
|
|
|
|
|
SimpleCycleTimer timer_;
|
|
|
|
|
double seconds_;
|
|
|
|
|
};
|
|
|
|
|
#endif
|
|
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// A Demon is the base element of a propagation queue. It is the main
|
|
|
|
|
/// object responsible for implementing the actual propagation
|
|
|
|
|
/// of the constraint and pruning the inconsistent values in the domains
|
|
|
|
|
/// of the variables. The main concept is that demons are listeners that are
|
|
|
|
|
/// attached to the variables and listen to their modifications.
|
|
|
|
|
/// There are two methods:
|
|
|
|
|
/// - Run() is the actual method called when the demon is processed.
|
|
|
|
|
/// - priority() returns its priority. Standard priorities are slow, normal
|
|
|
|
|
/// or fast. "immediate" is reserved for variables and is treated separately.
|
2010-09-15 12:42:33 +00:00
|
|
|
class Demon : public BaseObject {
|
2020-10-22 23:36:58 +02:00
|
|
|
public:
|
2019-07-05 00:25:55 +02:00
|
|
|
/// This indicates the priority of a demon. Immediate demons are treated
|
|
|
|
|
/// separately and corresponds to variables.
|
2021-02-07 00:45:47 +01:00
|
|
|
Demon() : stamp_(uint64_t{0}) {}
|
2023-09-25 18:06:35 +02:00
|
|
|
|
|
|
|
|
#ifndef SWIG
|
|
|
|
|
// This type is neither copyable nor movable.
|
|
|
|
|
Demon(const Demon&) = delete;
|
|
|
|
|
Demon& operator=(const Demon&) = delete;
|
|
|
|
|
#endif
|
2015-04-16 15:49:51 +02:00
|
|
|
~Demon() override {}
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// This is the main callback of the demon.
|
2023-05-31 14:27:08 +02:00
|
|
|
virtual void Run(Solver* s) = 0;
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// This method returns the priority of the demon. Usually a demon is
|
|
|
|
|
/// fast, slow or normal. Immediate demons are reserved for internal
|
|
|
|
|
/// use to maintain variables.
|
2010-09-15 12:42:33 +00:00
|
|
|
virtual Solver::DemonPriority priority() const;
|
|
|
|
|
|
2015-04-16 15:49:51 +02:00
|
|
|
std::string DebugString() const override;
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// This method inhibits the demon in the search tree below the
|
|
|
|
|
/// current position.
|
2023-05-31 14:27:08 +02:00
|
|
|
void inhibit(Solver* s);
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// This method un-inhibits the demon that was previously inhibited.
|
2023-05-31 14:27:08 +02:00
|
|
|
void desinhibit(Solver* s);
|
2011-06-07 21:52:02 +00:00
|
|
|
|
2020-10-22 23:36:58 +02:00
|
|
|
private:
|
2010-09-15 12:42:33 +00:00
|
|
|
friend class Queue;
|
2021-04-01 12:13:35 +02:00
|
|
|
void set_stamp(int64_t stamp) { stamp_ = stamp; }
|
|
|
|
|
uint64_t stamp() const { return stamp_; }
|
|
|
|
|
uint64_t stamp_;
|
2010-09-15 12:42:33 +00:00
|
|
|
};
|
|
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Model visitor.
|
2025-11-14 15:05:36 +01:00
|
|
|
class
|
|
|
|
|
#ifndef SWIG
|
|
|
|
|
OR_DLL
|
|
|
|
|
#endif
|
|
|
|
|
ModelVisitor : public BaseObject {
|
2020-10-22 23:36:58 +02:00
|
|
|
public:
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Constraint and Expression types.
|
2011-07-11 20:13:14 +00:00
|
|
|
static const char kAbs[];
|
2012-06-27 15:24:10 +00:00
|
|
|
static const char kAbsEqual[];
|
2011-07-11 20:13:14 +00:00
|
|
|
static const char kAllDifferent[];
|
|
|
|
|
static const char kAllowedAssignments[];
|
2016-10-05 13:45:23 +02:00
|
|
|
static const char kAtMost[];
|
2012-08-17 23:20:02 +00:00
|
|
|
static const char kIndexOf[];
|
2011-07-11 20:13:14 +00:00
|
|
|
static const char kBetween[];
|
2013-12-05 16:06:40 +00:00
|
|
|
static const char kConditionalExpr[];
|
2013-12-10 16:02:46 +00:00
|
|
|
static const char kCircuit[];
|
2011-07-11 20:13:14 +00:00
|
|
|
static const char kConvexPiecewise[];
|
|
|
|
|
static const char kCountEqual[];
|
2013-06-11 14:49:19 +00:00
|
|
|
static const char kCover[];
|
2011-07-11 20:13:14 +00:00
|
|
|
static const char kCumulative[];
|
|
|
|
|
static const char kDeviation[];
|
|
|
|
|
static const char kDifference[];
|
2011-11-03 10:27:53 +00:00
|
|
|
static const char kDisjunctive[];
|
2011-07-11 20:13:14 +00:00
|
|
|
static const char kDistribute[];
|
|
|
|
|
static const char kDivide[];
|
|
|
|
|
static const char kDurationExpr[];
|
|
|
|
|
static const char kElement[];
|
2022-09-05 18:30:09 +02:00
|
|
|
static const char kLightElementEqual[];
|
2011-08-11 05:15:18 +00:00
|
|
|
static const char kElementEqual[];
|
2011-07-11 20:13:14 +00:00
|
|
|
static const char kEndExpr[];
|
|
|
|
|
static const char kEquality[];
|
|
|
|
|
static const char kFalseConstraint[];
|
2012-08-14 21:45:43 +00:00
|
|
|
static const char kGlobalCardinality[];
|
2011-07-11 20:13:14 +00:00
|
|
|
static const char kGreater[];
|
|
|
|
|
static const char kGreaterOrEqual[];
|
2011-08-11 05:15:18 +00:00
|
|
|
static const char kIntegerVariable[];
|
2011-07-11 20:13:14 +00:00
|
|
|
static const char kIntervalBinaryRelation[];
|
|
|
|
|
static const char kIntervalDisjunction[];
|
|
|
|
|
static const char kIntervalUnaryRelation[];
|
2011-08-11 05:15:18 +00:00
|
|
|
static const char kIntervalVariable[];
|
2014-04-19 08:53:33 +00:00
|
|
|
static const char kInversePermutation[];
|
2011-07-11 20:13:14 +00:00
|
|
|
static const char kIsBetween[];
|
|
|
|
|
static const char kIsDifferent[];
|
|
|
|
|
static const char kIsEqual[];
|
2012-07-04 22:05:58 +00:00
|
|
|
static const char kIsGreater[];
|
2011-07-11 20:13:14 +00:00
|
|
|
static const char kIsGreaterOrEqual[];
|
2012-07-04 22:05:58 +00:00
|
|
|
static const char kIsLess[];
|
2011-07-11 20:13:14 +00:00
|
|
|
static const char kIsLessOrEqual[];
|
|
|
|
|
static const char kIsMember[];
|
|
|
|
|
static const char kLess[];
|
|
|
|
|
static const char kLessOrEqual[];
|
2013-12-20 10:44:30 +00:00
|
|
|
static const char kLexLess[];
|
2011-07-11 20:13:14 +00:00
|
|
|
static const char kLinkExprVar[];
|
|
|
|
|
static const char kMapDomain[];
|
|
|
|
|
static const char kMax[];
|
|
|
|
|
static const char kMaxEqual[];
|
|
|
|
|
static const char kMember[];
|
|
|
|
|
static const char kMin[];
|
|
|
|
|
static const char kMinEqual[];
|
2013-06-11 14:49:19 +00:00
|
|
|
static const char kModulo[];
|
2011-07-11 20:13:14 +00:00
|
|
|
static const char kNoCycle[];
|
|
|
|
|
static const char kNonEqual[];
|
2016-07-25 11:09:39 -07:00
|
|
|
static const char kNotBetween[];
|
2016-06-02 13:19:10 +02:00
|
|
|
static const char kNotMember[];
|
2013-01-10 17:01:34 +00:00
|
|
|
static const char kNullIntersect[];
|
2011-07-11 20:13:14 +00:00
|
|
|
static const char kOpposite[];
|
|
|
|
|
static const char kPack[];
|
|
|
|
|
static const char kPathCumul[];
|
2016-06-02 13:19:10 +02:00
|
|
|
static const char kDelayedPathCumul[];
|
2011-07-11 20:13:14 +00:00
|
|
|
static const char kPerformedExpr[];
|
2012-06-19 15:24:32 +00:00
|
|
|
static const char kPower[];
|
2011-07-11 20:13:14 +00:00
|
|
|
static const char kProduct[];
|
|
|
|
|
static const char kScalProd[];
|
|
|
|
|
static const char kScalProdEqual[];
|
|
|
|
|
static const char kScalProdGreaterOrEqual[];
|
|
|
|
|
static const char kScalProdLessOrEqual[];
|
|
|
|
|
static const char kSemiContinuous[];
|
2011-11-03 10:27:53 +00:00
|
|
|
static const char kSequenceVariable[];
|
2012-04-10 14:21:22 +00:00
|
|
|
static const char kSortingConstraint[];
|
2011-07-11 20:13:14 +00:00
|
|
|
static const char kSquare[];
|
|
|
|
|
static const char kStartExpr[];
|
|
|
|
|
static const char kSum[];
|
|
|
|
|
static const char kSumEqual[];
|
|
|
|
|
static const char kSumGreaterOrEqual[];
|
|
|
|
|
static const char kSumLessOrEqual[];
|
2013-06-18 09:43:51 +00:00
|
|
|
static const char kTrace[];
|
2011-07-11 20:13:14 +00:00
|
|
|
static const char kTransition[];
|
|
|
|
|
static const char kTrueConstraint[];
|
2012-07-04 13:29:41 +00:00
|
|
|
static const char kVarBoundWatcher[];
|
|
|
|
|
static const char kVarValueWatcher[];
|
2011-07-11 20:13:14 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Extension names:
|
2011-08-11 05:15:18 +00:00
|
|
|
static const char kCountAssignedItemsExtension[];
|
|
|
|
|
static const char kCountUsedBinsExtension[];
|
|
|
|
|
static const char kInt64ToBoolExtension[];
|
|
|
|
|
static const char kInt64ToInt64Extension[];
|
|
|
|
|
static const char kObjectiveExtension[];
|
|
|
|
|
static const char kSearchLimitExtension[];
|
|
|
|
|
static const char kUsageEqualVariableExtension[];
|
2013-06-11 14:49:19 +00:00
|
|
|
|
2011-08-11 05:15:18 +00:00
|
|
|
static const char kUsageLessConstantExtension[];
|
|
|
|
|
static const char kVariableGroupExtension[];
|
|
|
|
|
static const char kVariableUsageLessConstantExtension[];
|
|
|
|
|
static const char kWeightedSumOfAssignedEqualVariableExtension[];
|
|
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// argument names:
|
2011-07-11 20:13:14 +00:00
|
|
|
static const char kActiveArgument[];
|
2011-08-11 05:15:18 +00:00
|
|
|
static const char kAssumePathsArgument[];
|
|
|
|
|
static const char kBranchesLimitArgument[];
|
|
|
|
|
static const char kCapacityArgument[];
|
2011-07-11 20:13:14 +00:00
|
|
|
static const char kCardsArgument[];
|
|
|
|
|
static const char kCoefficientsArgument[];
|
|
|
|
|
static const char kCountArgument[];
|
2011-08-11 05:15:18 +00:00
|
|
|
static const char kCumulativeArgument[];
|
2011-07-11 20:13:14 +00:00
|
|
|
static const char kCumulsArgument[];
|
2011-08-11 05:15:18 +00:00
|
|
|
static const char kDemandsArgument[];
|
|
|
|
|
static const char kDurationMaxArgument[];
|
|
|
|
|
static const char kDurationMinArgument[];
|
2011-07-11 20:13:14 +00:00
|
|
|
static const char kEarlyCostArgument[];
|
|
|
|
|
static const char kEarlyDateArgument[];
|
2011-08-11 05:15:18 +00:00
|
|
|
static const char kEndMaxArgument[];
|
|
|
|
|
static const char kEndMinArgument[];
|
2016-06-02 13:19:10 +02:00
|
|
|
static const char kEndsArgument[];
|
2011-07-11 20:13:14 +00:00
|
|
|
static const char kExpressionArgument[];
|
2011-08-11 05:15:18 +00:00
|
|
|
static const char kFailuresLimitArgument[];
|
|
|
|
|
static const char kFinalStatesArgument[];
|
2011-07-11 20:13:14 +00:00
|
|
|
static const char kFixedChargeArgument[];
|
|
|
|
|
static const char kIndex2Argument[];
|
2024-11-18 11:32:13 +01:00
|
|
|
static const char kIndex3Argument[];
|
2011-07-11 20:13:14 +00:00
|
|
|
static const char kIndexArgument[];
|
|
|
|
|
static const char kInitialState[];
|
|
|
|
|
static const char kIntervalArgument[];
|
|
|
|
|
static const char kIntervalsArgument[];
|
|
|
|
|
static const char kLateCostArgument[];
|
|
|
|
|
static const char kLateDateArgument[];
|
|
|
|
|
static const char kLeftArgument[];
|
|
|
|
|
static const char kMaxArgument[];
|
2011-08-11 05:15:18 +00:00
|
|
|
static const char kMaximizeArgument[];
|
2011-07-11 20:13:14 +00:00
|
|
|
static const char kMinArgument[];
|
2012-08-14 21:45:43 +00:00
|
|
|
static const char kModuloArgument[];
|
2011-07-11 20:13:14 +00:00
|
|
|
static const char kNextsArgument[];
|
2011-08-11 05:15:18 +00:00
|
|
|
static const char kOptionalArgument[];
|
2013-12-16 10:24:42 +00:00
|
|
|
static const char kPartialArgument[];
|
2013-07-05 15:19:52 +00:00
|
|
|
static const char kPositionXArgument[];
|
|
|
|
|
static const char kPositionYArgument[];
|
2011-07-11 20:13:14 +00:00
|
|
|
static const char kRangeArgument[];
|
|
|
|
|
static const char kRelationArgument[];
|
|
|
|
|
static const char kRightArgument[];
|
2011-11-03 10:27:53 +00:00
|
|
|
static const char kSequenceArgument[];
|
|
|
|
|
static const char kSequencesArgument[];
|
2011-07-11 20:13:14 +00:00
|
|
|
static const char kSizeArgument[];
|
2013-07-05 15:19:52 +00:00
|
|
|
static const char kSizeXArgument[];
|
|
|
|
|
static const char kSizeYArgument[];
|
2011-08-11 05:15:18 +00:00
|
|
|
static const char kSmartTimeCheckArgument[];
|
|
|
|
|
static const char kSolutionLimitArgument[];
|
|
|
|
|
static const char kStartMaxArgument[];
|
|
|
|
|
static const char kStartMinArgument[];
|
2016-06-02 13:19:10 +02:00
|
|
|
static const char kStartsArgument[];
|
2011-07-11 20:13:14 +00:00
|
|
|
static const char kStepArgument[];
|
|
|
|
|
static const char kTargetArgument[];
|
2011-08-11 05:15:18 +00:00
|
|
|
static const char kTimeLimitArgument[];
|
2011-07-11 20:13:14 +00:00
|
|
|
static const char kTransitsArgument[];
|
|
|
|
|
static const char kTuplesArgument[];
|
|
|
|
|
static const char kValueArgument[];
|
|
|
|
|
static const char kValuesArgument[];
|
2011-12-17 18:03:38 +00:00
|
|
|
static const char kVariableArgument[];
|
2011-07-11 20:13:14 +00:00
|
|
|
static const char kVarsArgument[];
|
2015-10-23 13:45:43 +02:00
|
|
|
static const char kEvaluatorArgument[];
|
2011-07-11 20:13:14 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Operations.
|
2011-08-11 05:15:18 +00:00
|
|
|
static const char kMirrorOperation[];
|
|
|
|
|
static const char kRelaxedMaxOperation[];
|
|
|
|
|
static const char kRelaxedMinOperation[];
|
2011-12-17 18:03:38 +00:00
|
|
|
static const char kSumOperation[];
|
|
|
|
|
static const char kDifferenceOperation[];
|
|
|
|
|
static const char kProductOperation[];
|
2013-06-11 14:49:19 +00:00
|
|
|
static const char kStartSyncOnStartOperation[];
|
|
|
|
|
static const char kStartSyncOnEndOperation[];
|
2013-06-18 09:43:51 +00:00
|
|
|
static const char kTraceOperation[];
|
2011-08-11 05:15:18 +00:00
|
|
|
|
2015-04-16 15:49:51 +02:00
|
|
|
~ModelVisitor() override;
|
2011-07-11 20:13:14 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// ----- Virtual methods for visitors -----
|
2011-07-11 20:13:14 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Begin/End visit element.
|
2020-10-29 14:25:39 +01:00
|
|
|
virtual void BeginVisitModel(const std::string& type_name);
|
|
|
|
|
virtual void EndVisitModel(const std::string& type_name);
|
|
|
|
|
virtual void BeginVisitConstraint(const std::string& type_name,
|
2023-05-31 14:27:08 +02:00
|
|
|
const Constraint* constraint);
|
2020-10-29 14:25:39 +01:00
|
|
|
virtual void EndVisitConstraint(const std::string& type_name,
|
2023-05-31 14:27:08 +02:00
|
|
|
const Constraint* constraint);
|
2020-10-29 14:25:39 +01:00
|
|
|
virtual void BeginVisitExtension(const std::string& type);
|
|
|
|
|
virtual void EndVisitExtension(const std::string& type);
|
|
|
|
|
virtual void BeginVisitIntegerExpression(const std::string& type_name,
|
2023-05-31 14:27:08 +02:00
|
|
|
const IntExpr* expr);
|
2020-10-29 14:25:39 +01:00
|
|
|
virtual void EndVisitIntegerExpression(const std::string& type_name,
|
2023-05-31 14:27:08 +02:00
|
|
|
const IntExpr* expr);
|
|
|
|
|
virtual void VisitIntegerVariable(const IntVar* variable, IntExpr* delegate);
|
|
|
|
|
virtual void VisitIntegerVariable(const IntVar* variable,
|
2021-04-01 12:13:35 +02:00
|
|
|
const std::string& operation, int64_t value,
|
2023-05-31 14:27:08 +02:00
|
|
|
IntVar* delegate);
|
|
|
|
|
virtual void VisitIntervalVariable(const IntervalVar* variable,
|
2021-04-11 11:29:32 +02:00
|
|
|
const std::string& operation,
|
2023-05-31 14:27:08 +02:00
|
|
|
int64_t value, IntervalVar* delegate);
|
|
|
|
|
virtual void VisitSequenceVariable(const SequenceVar* variable);
|
2011-11-03 10:27:53 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Visit integer arguments.
|
2021-04-01 12:13:35 +02:00
|
|
|
virtual void VisitIntegerArgument(const std::string& arg_name, int64_t value);
|
2020-10-29 14:25:39 +01:00
|
|
|
virtual void VisitIntegerArrayArgument(const std::string& arg_name,
|
2021-04-01 12:13:35 +02:00
|
|
|
const std::vector<int64_t>& values);
|
2020-10-29 14:25:39 +01:00
|
|
|
virtual void VisitIntegerMatrixArgument(const std::string& arg_name,
|
|
|
|
|
const IntTupleSet& tuples);
|
2011-07-11 20:13:14 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Visit integer expression argument.
|
2020-10-29 14:25:39 +01:00
|
|
|
virtual void VisitIntegerExpressionArgument(const std::string& arg_name,
|
2023-05-31 14:27:08 +02:00
|
|
|
IntExpr* argument);
|
2011-07-11 20:13:14 +00:00
|
|
|
|
2020-10-22 23:36:58 +02:00
|
|
|
virtual void VisitIntegerVariableArrayArgument(
|
2020-10-29 14:25:39 +01:00
|
|
|
const std::string& arg_name, const std::vector<IntVar*>& arguments);
|
2011-07-11 20:13:14 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Visit interval argument.
|
2020-10-29 14:25:39 +01:00
|
|
|
virtual void VisitIntervalArgument(const std::string& arg_name,
|
2023-05-31 14:27:08 +02:00
|
|
|
IntervalVar* argument);
|
2011-07-11 20:13:14 +00:00
|
|
|
|
2020-10-22 23:36:58 +02:00
|
|
|
virtual void VisitIntervalArrayArgument(
|
2020-10-29 14:25:39 +01:00
|
|
|
const std::string& arg_name, const std::vector<IntervalVar*>& arguments);
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Visit sequence argument.
|
2020-10-29 14:25:39 +01:00
|
|
|
virtual void VisitSequenceArgument(const std::string& arg_name,
|
2023-05-31 14:27:08 +02:00
|
|
|
SequenceVar* argument);
|
2011-08-11 05:15:18 +00:00
|
|
|
|
2020-10-22 23:36:58 +02:00
|
|
|
virtual void VisitSequenceArrayArgument(
|
2020-10-29 14:25:39 +01:00
|
|
|
const std::string& arg_name, const std::vector<SequenceVar*>& arguments);
|
2011-08-11 05:15:18 +00:00
|
|
|
#if !defined(SWIG)
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Helpers.
|
2015-10-23 13:45:43 +02:00
|
|
|
virtual void VisitIntegerVariableEvaluatorArgument(
|
2020-10-29 14:25:39 +01:00
|
|
|
const std::string& arg_name, const Solver::Int64ToIntVar& arguments);
|
2015-10-23 13:45:43 +02:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Using SWIG on callbacks is troublesome, so we hide these methods during
|
|
|
|
|
/// the wrapping.
|
2021-04-01 12:13:35 +02:00
|
|
|
void VisitInt64ToBoolExtension(Solver::IndexFilter1 filter, int64_t index_min,
|
|
|
|
|
int64_t index_max);
|
2020-10-29 14:25:39 +01:00
|
|
|
void VisitInt64ToInt64Extension(const Solver::IndexEvaluator1& eval,
|
2021-04-01 12:13:35 +02:00
|
|
|
int64_t index_min, int64_t index_max);
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Expands function as array when index min is 0.
|
2020-10-29 14:25:39 +01:00
|
|
|
void VisitInt64ToInt64AsArray(const Solver::IndexEvaluator1& eval,
|
2021-04-01 12:13:35 +02:00
|
|
|
const std::string& arg_name, int64_t index_max);
|
2020-10-22 23:36:58 +02:00
|
|
|
#endif // #if !defined(SWIG)
|
2011-07-11 20:13:14 +00:00
|
|
|
};
|
|
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// A constraint is the main modeling object. It provides two methods:
|
|
|
|
|
/// - Post() is responsible for creating the demons and attaching them to
|
|
|
|
|
/// immediate demons().
|
|
|
|
|
/// - InitialPropagate() is called once just after Post and performs
|
|
|
|
|
/// the initial propagation. The subsequent propagations will be performed
|
|
|
|
|
/// by the demons Posted during the post() method.
|
2010-09-15 12:42:33 +00:00
|
|
|
class Constraint : public PropagationBaseObject {
|
2020-10-22 23:36:58 +02:00
|
|
|
public:
|
2020-10-29 14:25:39 +01:00
|
|
|
explicit Constraint(Solver* const solver) : PropagationBaseObject(solver) {}
|
2023-09-25 18:06:35 +02:00
|
|
|
|
|
|
|
|
#ifndef SWIG
|
|
|
|
|
// This type is neither copyable nor movable.
|
|
|
|
|
Constraint(const Constraint&) = delete;
|
|
|
|
|
Constraint& operator=(const Constraint&) = delete;
|
|
|
|
|
#endif
|
2015-04-16 15:49:51 +02:00
|
|
|
~Constraint() override {}
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// This method is called when the constraint is processed by the
|
|
|
|
|
/// solver. Its main usage is to attach demons to variables.
|
2010-09-15 12:42:33 +00:00
|
|
|
virtual void Post() = 0;
|
|
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// This method performs the initial propagation of the
|
|
|
|
|
/// constraint. It is called just after the post.
|
2010-09-15 12:42:33 +00:00
|
|
|
virtual void InitialPropagate() = 0;
|
2015-04-16 15:49:51 +02:00
|
|
|
std::string DebugString() const override;
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Calls Post and then Propagate to initialize the constraints. This
|
|
|
|
|
/// is usually done in the root node.
|
2010-09-15 12:42:33 +00:00
|
|
|
void PostAndPropagate();
|
2011-06-28 09:27:03 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Accepts the given visitor.
|
2023-05-31 14:27:08 +02:00
|
|
|
virtual void Accept(ModelVisitor* visitor) const;
|
2011-07-11 20:13:14 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Is the constraint created by a cast from expression to integer variable?
|
2011-11-07 15:31:18 +00:00
|
|
|
bool IsCastConstraint() const;
|
2011-08-11 05:15:18 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Creates a Boolean variable representing the status of the constraint
|
|
|
|
|
/// (false = constraint is violated, true = constraint is satisfied). It
|
|
|
|
|
/// returns nullptr if the constraint does not support this API.
|
2020-10-29 14:25:39 +01:00
|
|
|
virtual IntVar* Var();
|
2010-09-15 12:42:33 +00:00
|
|
|
};
|
|
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Cast constraints are special channeling constraints designed
|
|
|
|
|
/// to keep a variable in sync with an expression. They are
|
|
|
|
|
/// created internally when Var() is called on a subclass of IntExpr.
|
2011-11-07 15:31:18 +00:00
|
|
|
class CastConstraint : public Constraint {
|
2020-10-22 23:36:58 +02:00
|
|
|
public:
|
2020-10-29 14:25:39 +01:00
|
|
|
CastConstraint(Solver* const solver, IntVar* const target_var)
|
2011-11-07 15:31:18 +00:00
|
|
|
: Constraint(solver), target_var_(target_var) {
|
2013-10-10 15:23:20 +00:00
|
|
|
CHECK(target_var != nullptr);
|
2011-11-07 15:31:18 +00:00
|
|
|
}
|
2015-04-16 15:49:51 +02:00
|
|
|
~CastConstraint() override {}
|
2011-11-07 15:31:18 +00:00
|
|
|
|
2020-10-29 14:25:39 +01:00
|
|
|
IntVar* target_var() const { return target_var_; }
|
2011-11-07 15:31:18 +00:00
|
|
|
|
2020-10-22 23:36:58 +02:00
|
|
|
protected:
|
2020-10-29 14:25:39 +01:00
|
|
|
IntVar* const target_var_;
|
2011-11-07 15:31:18 +00:00
|
|
|
};
|
|
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// A search monitor is a simple set of callbacks to monitor all search events
|
2010-09-15 12:42:33 +00:00
|
|
|
class SearchMonitor : public BaseObject {
|
2020-10-22 23:36:58 +02:00
|
|
|
public:
|
2020-08-10 10:55:34 +02:00
|
|
|
static constexpr int kNoProgress = -1;
|
2012-02-09 19:42:58 +00:00
|
|
|
|
2020-10-29 14:25:39 +01:00
|
|
|
explicit SearchMonitor(Solver* const s) : solver_(s) {}
|
2023-09-25 18:06:35 +02:00
|
|
|
|
|
|
|
|
#ifndef SWIG
|
|
|
|
|
// This type is neither copyable nor movable.
|
|
|
|
|
SearchMonitor(const SearchMonitor&) = delete;
|
|
|
|
|
SearchMonitor& operator=(const SearchMonitor&) = delete;
|
|
|
|
|
#endif
|
2015-04-16 15:49:51 +02:00
|
|
|
~SearchMonitor() override {}
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Beginning of the search.
|
2010-09-15 12:42:33 +00:00
|
|
|
virtual void EnterSearch();
|
|
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Restart the search.
|
2010-09-15 12:42:33 +00:00
|
|
|
virtual void RestartSearch();
|
|
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// End of the search.
|
2010-09-15 12:42:33 +00:00
|
|
|
virtual void ExitSearch();
|
|
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Before calling DecisionBuilder::Next.
|
2023-05-31 14:27:08 +02:00
|
|
|
virtual void BeginNextDecision(DecisionBuilder* b);
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// After calling DecisionBuilder::Next, along with the returned decision.
|
2023-05-31 14:27:08 +02:00
|
|
|
virtual void EndNextDecision(DecisionBuilder* b, Decision* d);
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Before applying the decision.
|
2023-05-31 14:27:08 +02:00
|
|
|
virtual void ApplyDecision(Decision* d);
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Before refuting the decision.
|
2023-05-31 14:27:08 +02:00
|
|
|
virtual void RefuteDecision(Decision* d);
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Just after refuting or applying the decision, apply is true after Apply.
|
|
|
|
|
/// This is called only if the Apply() or Refute() methods have not failed.
|
2023-05-31 14:27:08 +02:00
|
|
|
virtual void AfterDecision(Decision* d, bool apply);
|
2011-03-31 12:28:12 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Just when the failure occurs.
|
2010-09-15 12:42:33 +00:00
|
|
|
virtual void BeginFail();
|
|
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// After completing the backtrack.
|
2010-09-15 12:42:33 +00:00
|
|
|
virtual void EndFail();
|
|
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Before the initial propagation.
|
2010-09-15 12:42:33 +00:00
|
|
|
virtual void BeginInitialPropagation();
|
|
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// After the initial propagation.
|
2010-09-15 12:42:33 +00:00
|
|
|
virtual void EndInitialPropagation();
|
|
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// This method is called when a solution is found. It asserts whether the
|
|
|
|
|
/// solution is valid. A value of false indicates that the solution
|
|
|
|
|
/// should be discarded.
|
2010-10-06 16:04:31 +00:00
|
|
|
virtual bool AcceptSolution();
|
|
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// This method is called when a valid solution is found. If the
|
|
|
|
|
/// return value is true, then search will resume after. If the result
|
|
|
|
|
/// is false, then search will stop there.
|
2010-10-06 16:04:31 +00:00
|
|
|
virtual bool AtSolution();
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// When the search tree is finished.
|
2010-09-15 12:42:33 +00:00
|
|
|
virtual void NoMoreSolutions();
|
|
|
|
|
|
2025-07-23 15:07:49 +02:00
|
|
|
/// Called when a local optimum is reached. If 'true' is returned, the last
|
|
|
|
|
/// solution is discarded and the search proceeds with the next one.
|
|
|
|
|
virtual bool AtLocalOptimum();
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
///
|
2020-10-29 14:25:39 +01:00
|
|
|
virtual bool AcceptDelta(Assignment* delta, Assignment* deltadelta);
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// After accepting a neighbor during local search.
|
2010-09-15 12:42:33 +00:00
|
|
|
virtual void AcceptNeighbor();
|
|
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// After accepting an unchecked neighbor during local search.
|
2019-03-15 17:17:02 +01:00
|
|
|
virtual void AcceptUncheckedNeighbor();
|
|
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Returns true if the limit of solutions has been reached including
|
|
|
|
|
/// unchecked solutions.
|
2019-04-16 09:25:06 -07:00
|
|
|
virtual bool IsUncheckedSolutionLimitReached() { return false; }
|
|
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Periodic call to check limits in long running methods.
|
2010-09-15 12:42:33 +00:00
|
|
|
virtual void PeriodicCheck();
|
2011-06-28 09:27:03 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Returns a percentage representing the propress of the search before
|
|
|
|
|
/// reaching limits.
|
2012-02-09 19:42:58 +00:00
|
|
|
virtual int ProgressPercent() { return kNoProgress; }
|
|
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Accepts the given model visitor.
|
2023-05-31 14:27:08 +02:00
|
|
|
virtual void Accept(ModelVisitor* visitor) const;
|
2011-08-11 05:15:18 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Registers itself on the solver such that it gets notified of the search
|
2022-09-05 18:30:09 +02:00
|
|
|
/// and propagation events. Override to incrementally install listeners for
|
|
|
|
|
/// specific events.
|
2011-11-16 17:32:24 +00:00
|
|
|
virtual void Install();
|
|
|
|
|
|
2022-09-05 18:30:09 +02:00
|
|
|
Solver* solver() const { return solver_; }
|
|
|
|
|
|
|
|
|
|
protected:
|
|
|
|
|
void ListenToEvent(Solver::MonitorEvent event);
|
|
|
|
|
|
2020-10-22 23:36:58 +02:00
|
|
|
private:
|
2020-10-29 14:25:39 +01:00
|
|
|
Solver* const solver_;
|
2010-09-15 12:42:33 +00:00
|
|
|
};
|
|
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// This class adds reversibility to a POD type.
|
|
|
|
|
/// It contains the stamp optimization. i.e. the SaveValue call is done
|
|
|
|
|
/// only once per node of the search tree. Please note that actual
|
|
|
|
|
/// stamps always starts at 1, thus an initial value of 0 will always
|
|
|
|
|
/// trigger the first SaveValue.
|
2020-10-22 23:36:58 +02:00
|
|
|
template <class T>
|
|
|
|
|
class Rev {
|
|
|
|
|
public:
|
2020-10-29 14:25:39 +01:00
|
|
|
explicit Rev(const T& val) : stamp_(0), value_(val) {}
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2020-10-29 14:25:39 +01:00
|
|
|
const T& Value() const { return value_; }
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2020-10-29 14:25:39 +01:00
|
|
|
void SetValue(Solver* const s, const T& val) {
|
2010-09-15 12:42:33 +00:00
|
|
|
if (val != value_) {
|
|
|
|
|
if (stamp_ < s->stamp()) {
|
|
|
|
|
s->SaveValue(&value_);
|
|
|
|
|
stamp_ = s->stamp();
|
|
|
|
|
}
|
|
|
|
|
value_ = val;
|
|
|
|
|
}
|
|
|
|
|
}
|
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
|
|
|
uint64_t stamp_;
|
2010-09-15 12:42:33 +00:00
|
|
|
T value_;
|
|
|
|
|
};
|
|
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Subclass of Rev<T> which adds numerical operations.
|
2020-10-22 23:36:58 +02:00
|
|
|
template <class T>
|
|
|
|
|
class NumericalRev : public Rev<T> {
|
|
|
|
|
public:
|
2020-10-29 14:25:39 +01:00
|
|
|
explicit NumericalRev(const T& val) : Rev<T>(val) {}
|
2011-12-16 21:02:59 +00:00
|
|
|
|
2020-10-29 14:25:39 +01:00
|
|
|
void Add(Solver* const s, const T& to_add) {
|
2011-12-16 21:02:59 +00:00
|
|
|
this->SetValue(s, this->Value() + to_add);
|
|
|
|
|
}
|
|
|
|
|
|
2020-10-29 14:25:39 +01:00
|
|
|
void Incr(Solver* const s) { Add(s, 1); }
|
2011-12-16 21:02:59 +00:00
|
|
|
|
2020-10-29 14:25:39 +01:00
|
|
|
void Decr(Solver* const s) { Add(s, -1); }
|
2011-12-16 21:02:59 +00:00
|
|
|
};
|
|
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Reversible array of POD types.
|
|
|
|
|
/// It contains the stamp optimization. I.e., the SaveValue call is done only
|
|
|
|
|
/// once per node of the search tree.
|
|
|
|
|
/// Please note that actual stamp always starts at 1, thus an initial value of
|
|
|
|
|
/// 0 always triggers the first SaveValue.
|
2020-10-22 23:36:58 +02:00
|
|
|
template <class T>
|
|
|
|
|
class RevArray {
|
|
|
|
|
public:
|
2020-10-29 14:25:39 +01:00
|
|
|
RevArray(int size, const T& val)
|
2021-04-01 12:13:35 +02:00
|
|
|
: stamps_(new uint64_t[size]), values_(new T[size]), size_(size) {
|
2011-12-16 21:02:59 +00:00
|
|
|
for (int i = 0; i < size; ++i) {
|
|
|
|
|
stamps_[i] = 0;
|
|
|
|
|
values_[i] = val;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
~RevArray() {}
|
|
|
|
|
|
2021-04-01 12:13:35 +02:00
|
|
|
int64_t size() const { return size_; }
|
2012-09-19 13:45:22 +00:00
|
|
|
|
2020-10-29 14:25:39 +01:00
|
|
|
const T& Value(int index) const { return values_[index]; }
|
2011-12-16 21:02:59 +00:00
|
|
|
|
|
|
|
|
#if !defined(SWIG)
|
2020-10-29 14:25:39 +01:00
|
|
|
const T& operator[](int index) const { return values_[index]; }
|
2011-12-16 21:02:59 +00:00
|
|
|
#endif
|
|
|
|
|
|
2020-10-29 14:25:39 +01:00
|
|
|
void SetValue(Solver* const s, int index, const T& val) {
|
2016-10-05 13:45:23 +02:00
|
|
|
DCHECK_LT(index, size_);
|
2011-12-16 21:02:59 +00:00
|
|
|
if (val != values_[index]) {
|
|
|
|
|
if (stamps_[index] < s->stamp()) {
|
|
|
|
|
s->SaveValue(&values_[index]);
|
|
|
|
|
stamps_[index] = s->stamp();
|
|
|
|
|
}
|
|
|
|
|
values_[index] = val;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-10-22 23:36:58 +02:00
|
|
|
private:
|
2021-04-01 12:13:35 +02:00
|
|
|
std::unique_ptr<uint64_t[]> stamps_;
|
2013-12-10 16:02:46 +00:00
|
|
|
std::unique_ptr<T[]> values_;
|
2012-09-19 13:45:22 +00:00
|
|
|
const int size_;
|
2011-12-16 21:02:59 +00:00
|
|
|
};
|
|
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Subclass of RevArray<T> which adds numerical operations.
|
2020-10-22 23:36:58 +02:00
|
|
|
template <class T>
|
|
|
|
|
class NumericalRevArray : public RevArray<T> {
|
|
|
|
|
public:
|
2020-10-29 14:25:39 +01:00
|
|
|
NumericalRevArray(int size, const T& val) : RevArray<T>(size, val) {}
|
2011-12-16 21:02:59 +00:00
|
|
|
|
2020-10-29 14:25:39 +01:00
|
|
|
void Add(Solver* const s, int index, const T& to_add) {
|
2011-12-16 21:02:59 +00:00
|
|
|
this->SetValue(s, index, this->Value(index) + to_add);
|
|
|
|
|
}
|
|
|
|
|
|
2020-10-29 14:25:39 +01:00
|
|
|
void Incr(Solver* const s, int index) { Add(s, index, 1); }
|
2011-12-16 21:02:59 +00:00
|
|
|
|
2020-10-29 14:25:39 +01:00
|
|
|
void Decr(Solver* const s, int index) { Add(s, index, -1); }
|
2011-12-16 21:02:59 +00:00
|
|
|
};
|
|
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// The class IntExpr is the base of all integer expressions in
|
|
|
|
|
/// constraint programming.
|
|
|
|
|
/// It contains the basic protocol for an expression:
|
|
|
|
|
/// - setting and modifying its bound
|
|
|
|
|
/// - querying if it is bound
|
|
|
|
|
/// - listening to events modifying its bounds
|
|
|
|
|
/// - casting it into a variable (instance of IntVar)
|
2010-09-15 12:42:33 +00:00
|
|
|
class IntExpr : public PropagationBaseObject {
|
2020-10-22 23:36:58 +02:00
|
|
|
public:
|
2020-10-29 14:25:39 +01:00
|
|
|
explicit IntExpr(Solver* const s) : PropagationBaseObject(s) {}
|
2023-09-25 18:06:35 +02:00
|
|
|
|
|
|
|
|
#ifndef SWIG
|
|
|
|
|
// This type is neither copyable nor movable.
|
|
|
|
|
IntExpr(const IntExpr&) = delete;
|
|
|
|
|
IntExpr& operator=(const IntExpr&) = delete;
|
|
|
|
|
#endif
|
2015-04-16 15:49:51 +02:00
|
|
|
~IntExpr() override {}
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2021-04-01 12:13:35 +02:00
|
|
|
virtual int64_t Min() const = 0;
|
|
|
|
|
virtual void SetMin(int64_t m) = 0;
|
|
|
|
|
virtual int64_t Max() const = 0;
|
|
|
|
|
virtual void SetMax(int64_t m) = 0;
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// By default calls Min() and Max(), but can be redefined when Min and Max
|
|
|
|
|
/// code can be factorized.
|
2021-04-01 12:13:35 +02:00
|
|
|
virtual void Range(int64_t* l, int64_t* u) {
|
2010-09-15 12:42:33 +00:00
|
|
|
*l = Min();
|
|
|
|
|
*u = Max();
|
|
|
|
|
}
|
2019-07-05 00:25:55 +02:00
|
|
|
/// This method sets both the min and the max of the expression.
|
2021-04-01 12:13:35 +02:00
|
|
|
virtual void SetRange(int64_t l, int64_t u) {
|
2010-09-15 12:42:33 +00:00
|
|
|
SetMin(l);
|
|
|
|
|
SetMax(u);
|
|
|
|
|
}
|
|
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// This method sets the value of the expression.
|
2021-04-01 12:13:35 +02:00
|
|
|
virtual void SetValue(int64_t v) { SetRange(v, v); }
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Returns true if the min and the max of the expression are equal.
|
2010-09-15 12:42:33 +00:00
|
|
|
virtual bool Bound() const { return (Min() == Max()); }
|
|
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Returns true if the expression is indeed a variable.
|
2010-09-15 12:42:33 +00:00
|
|
|
virtual bool IsVar() const { return false; }
|
|
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Creates a variable from the expression.
|
2020-10-29 14:25:39 +01:00
|
|
|
virtual IntVar* Var() = 0;
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Creates a variable from the expression and set the name of the
|
|
|
|
|
/// resulting var. If the expression is already a variable, then it
|
|
|
|
|
/// will set the name of the expression, possibly overwriting it.
|
|
|
|
|
/// This is just a shortcut to Var() followed by set_name().
|
2020-10-29 14:25:39 +01:00
|
|
|
IntVar* VarWithName(const std::string& name);
|
2012-01-21 16:20:55 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Attach a demon that will watch the min or the max of the expression.
|
2020-10-29 14:25:39 +01:00
|
|
|
virtual void WhenRange(Demon* d) = 0;
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Attach a demon that will watch the min or the max of the expression.
|
2015-10-23 13:45:43 +02:00
|
|
|
void WhenRange(Solver::Closure closure) {
|
2017-04-19 16:20:56 +02:00
|
|
|
WhenRange(solver()->MakeClosureDemon(std::move(closure)));
|
2015-10-23 13:45:43 +02:00
|
|
|
}
|
2016-03-12 06:32:56 -08:00
|
|
|
|
2015-11-18 16:45:30 +01:00
|
|
|
#if !defined(SWIG)
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Attach a demon that will watch the min or the max of the expression.
|
2015-10-23 13:45:43 +02:00
|
|
|
void WhenRange(Solver::Action action) {
|
2017-04-19 16:20:56 +02:00
|
|
|
WhenRange(solver()->MakeActionDemon(std::move(action)));
|
2015-10-23 13:45:43 +02:00
|
|
|
}
|
2020-10-22 23:36:58 +02:00
|
|
|
#endif // SWIG
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Accepts the given visitor.
|
2023-05-31 14:27:08 +02:00
|
|
|
virtual void Accept(ModelVisitor* visitor) const;
|
2010-09-15 12:42:33 +00:00
|
|
|
};
|
|
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// The class Iterator has two direct subclasses. HoleIterators
|
|
|
|
|
/// iterates over all holes, that is value removed between the
|
|
|
|
|
/// current min and max of the variable since the last time the
|
|
|
|
|
/// variable was processed in the queue. DomainIterators iterates
|
|
|
|
|
/// over all elements of the variable domain. Both iterators are not
|
|
|
|
|
/// robust to domain changes. Hole iterators can also report values outside
|
|
|
|
|
/// the current min and max of the variable.
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// HoleIterators should only be called from a demon attached to the
|
|
|
|
|
/// variable that has created this iterator.
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// IntVar* current_var;
|
|
|
|
|
/// std::unique_ptr<IntVarIterator> it(current_var->MakeHoleIterator(false));
|
2021-04-01 12:13:35 +02:00
|
|
|
/// for (const int64_t hole : InitAndGetValues(it)) {
|
2019-07-05 00:25:55 +02:00
|
|
|
/// /// use the hole
|
|
|
|
|
/// }
|
2010-09-15 12:42:33 +00:00
|
|
|
|
|
|
|
|
class IntVarIterator : public BaseObject {
|
2020-10-22 23:36:58 +02:00
|
|
|
public:
|
2015-04-16 15:49:51 +02:00
|
|
|
~IntVarIterator() override {}
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// This method must be called before each loop.
|
2010-09-15 12:42:33 +00:00
|
|
|
virtual void Init() = 0;
|
|
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// This method indicates if we can call Value() or not.
|
2010-09-15 12:42:33 +00:00
|
|
|
virtual bool Ok() const = 0;
|
|
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// This method returns the current value of the iterator.
|
2021-04-01 12:13:35 +02:00
|
|
|
virtual int64_t Value() const = 0;
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// This method moves the iterator to the next value.
|
2010-09-15 12:42:33 +00:00
|
|
|
virtual void Next() = 0;
|
|
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Pretty Print.
|
2015-04-16 15:49:51 +02:00
|
|
|
std::string DebugString() const override { return "IntVar::Iterator"; }
|
2010-09-15 12:42:33 +00:00
|
|
|
};
|
|
|
|
|
|
2014-05-21 13:01:04 +00:00
|
|
|
#ifndef SWIG
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Utility class to encapsulate an IntVarIterator and use it in a range-based
|
|
|
|
|
/// loop. See the code snippet above IntVarIterator.
|
|
|
|
|
///
|
|
|
|
|
/// It contains DEBUG_MODE-enabled code that DCHECKs that the
|
|
|
|
|
/// same iterator instance isn't being iterated on in multiple places
|
|
|
|
|
/// simultaneously.
|
2014-05-21 13:01:04 +00:00
|
|
|
class InitAndGetValues {
|
2020-10-22 23:36:58 +02:00
|
|
|
public:
|
2020-10-29 14:25:39 +01:00
|
|
|
explicit InitAndGetValues(IntVarIterator* it)
|
2014-05-21 13:01:04 +00:00
|
|
|
: it_(it), begin_was_called_(false) {
|
|
|
|
|
it_->Init();
|
|
|
|
|
}
|
|
|
|
|
struct Iterator;
|
2021-04-01 12:13:35 +02:00
|
|
|
|
2014-05-21 13:01:04 +00:00
|
|
|
Iterator begin() {
|
|
|
|
|
if (DEBUG_MODE) {
|
|
|
|
|
DCHECK(!begin_was_called_);
|
|
|
|
|
begin_was_called_ = true;
|
|
|
|
|
}
|
|
|
|
|
return Iterator::Begin(it_);
|
|
|
|
|
}
|
|
|
|
|
Iterator end() { return Iterator::End(it_); }
|
|
|
|
|
|
|
|
|
|
struct Iterator {
|
2019-07-05 00:25:55 +02:00
|
|
|
/// These are the only way to construct an Iterator.
|
2020-10-29 14:25:39 +01:00
|
|
|
static Iterator Begin(IntVarIterator* it) {
|
2020-10-22 23:36:58 +02:00
|
|
|
return Iterator(it, /*is_end=*/false);
|
2014-05-21 13:01:04 +00:00
|
|
|
}
|
2020-10-29 14:25:39 +01:00
|
|
|
static Iterator End(IntVarIterator* it) {
|
2020-10-22 23:36:58 +02:00
|
|
|
return Iterator(it, /*is_end=*/true);
|
2014-05-21 13:01:04 +00:00
|
|
|
}
|
|
|
|
|
|
2021-04-01 12:13:35 +02:00
|
|
|
int64_t operator*() const {
|
2023-09-25 18:06:35 +02:00
|
|
|
DCHECK(it->Ok());
|
|
|
|
|
return it->Value();
|
2014-05-21 13:01:04 +00:00
|
|
|
}
|
2020-10-29 14:25:39 +01:00
|
|
|
Iterator& operator++() {
|
2023-09-25 18:06:35 +02:00
|
|
|
DCHECK(it->Ok());
|
|
|
|
|
it->Next();
|
2014-05-21 13:01:04 +00:00
|
|
|
return *this;
|
|
|
|
|
}
|
2020-10-29 14:25:39 +01:00
|
|
|
bool operator!=(const Iterator& other) const {
|
2023-09-25 18:06:35 +02:00
|
|
|
DCHECK(other.it == it);
|
|
|
|
|
DCHECK(other.is_end);
|
|
|
|
|
return it->Ok();
|
2014-05-21 13:01:04 +00:00
|
|
|
}
|
|
|
|
|
|
2020-10-22 23:36:58 +02:00
|
|
|
private:
|
2023-09-25 18:06:35 +02:00
|
|
|
Iterator(IntVarIterator* it, bool is_end) : it(it), is_end(is_end) {}
|
2014-05-21 13:01:04 +00:00
|
|
|
|
2023-09-25 18:06:35 +02:00
|
|
|
IntVarIterator* const it;
|
|
|
|
|
const bool is_end;
|
2014-05-21 13:01:04 +00:00
|
|
|
};
|
|
|
|
|
|
2020-10-22 23:36:58 +02:00
|
|
|
private:
|
2020-10-29 14:25:39 +01:00
|
|
|
IntVarIterator* const it_;
|
2014-05-21 13:01:04 +00:00
|
|
|
bool begin_was_called_;
|
|
|
|
|
};
|
2020-10-22 23:36:58 +02:00
|
|
|
#endif // SWIG
|
2014-05-21 13:01:04 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// The class IntVar is a subset of IntExpr. In addition to the
|
|
|
|
|
/// IntExpr protocol, it offers persistence, removing values from the domains,
|
|
|
|
|
/// and a finer model for events.
|
2010-09-15 12:42:33 +00:00
|
|
|
class IntVar : public IntExpr {
|
2020-10-22 23:36:58 +02:00
|
|
|
public:
|
2023-05-31 14:27:08 +02:00
|
|
|
explicit IntVar(Solver* s);
|
|
|
|
|
IntVar(Solver* s, const std::string& name);
|
2023-09-25 18:06:35 +02:00
|
|
|
|
|
|
|
|
#ifndef SWIG
|
|
|
|
|
// This type is neither copyable nor movable.
|
|
|
|
|
IntVar(const IntVar&) = delete;
|
|
|
|
|
IntVar& operator=(const IntVar&) = delete;
|
|
|
|
|
#endif
|
|
|
|
|
|
2024-11-18 11:32:13 +01:00
|
|
|
~IntVar() override {};
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2015-04-16 15:49:51 +02:00
|
|
|
bool IsVar() const override { return true; }
|
2020-10-29 14:25:39 +01:00
|
|
|
IntVar* Var() override { return this; }
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// This method returns the value of the variable. This method checks
|
|
|
|
|
/// before that the variable is bound.
|
2021-04-01 12:13:35 +02:00
|
|
|
virtual int64_t Value() const = 0;
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// This method removes the value 'v' from the domain of the variable.
|
2021-04-01 12:13:35 +02:00
|
|
|
virtual void RemoveValue(int64_t v) = 0;
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// This method removes the interval 'l' .. 'u' from the domain of
|
|
|
|
|
/// the variable. It assumes that 'l' <= 'u'.
|
2021-04-01 12:13:35 +02:00
|
|
|
virtual void RemoveInterval(int64_t l, int64_t u) = 0;
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// This method remove the values from the domain of the variable.
|
2021-04-01 12:13:35 +02:00
|
|
|
virtual void RemoveValues(const std::vector<int64_t>& values);
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// This method intersects the current domain with the values in the array.
|
2021-04-01 12:13:35 +02:00
|
|
|
virtual void SetValues(const std::vector<int64_t>& values);
|
2012-06-07 19:56:43 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// This method attaches a demon that will be awakened when the
|
|
|
|
|
/// variable is bound.
|
2020-10-29 14:25:39 +01:00
|
|
|
virtual void WhenBound(Demon* d) = 0;
|
2019-07-05 00:25:55 +02:00
|
|
|
/// This method attaches a closure that will be awakened when the
|
|
|
|
|
/// variable is bound.
|
2015-10-23 13:45:43 +02:00
|
|
|
void WhenBound(Solver::Closure closure) {
|
2017-04-19 16:20:56 +02:00
|
|
|
WhenBound(solver()->MakeClosureDemon(std::move(closure)));
|
2015-10-23 13:45:43 +02:00
|
|
|
}
|
2015-11-18 16:45:30 +01:00
|
|
|
|
|
|
|
|
#if !defined(SWIG)
|
2019-07-05 00:25:55 +02:00
|
|
|
/// This method attaches an action that will be awakened when the
|
|
|
|
|
/// variable is bound.
|
2015-10-23 13:45:43 +02:00
|
|
|
void WhenBound(Solver::Action action) {
|
2017-04-19 16:20:56 +02:00
|
|
|
WhenBound(solver()->MakeActionDemon(std::move(action)));
|
2015-10-23 13:45:43 +02:00
|
|
|
}
|
2020-10-22 23:36:58 +02:00
|
|
|
#endif // SWIG
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// This method attaches a demon that will watch any domain
|
|
|
|
|
/// modification of the domain of the variable.
|
2020-10-29 14:25:39 +01:00
|
|
|
virtual void WhenDomain(Demon* d) = 0;
|
2019-07-05 00:25:55 +02:00
|
|
|
/// This method attaches a closure that will watch any domain
|
|
|
|
|
/// modification of the domain of the variable.
|
2015-10-23 13:45:43 +02:00
|
|
|
void WhenDomain(Solver::Closure closure) {
|
2017-04-19 16:20:56 +02:00
|
|
|
WhenDomain(solver()->MakeClosureDemon(std::move(closure)));
|
2015-10-23 13:45:43 +02:00
|
|
|
}
|
2015-11-18 16:45:30 +01:00
|
|
|
#if !defined(SWIG)
|
2019-07-05 00:25:55 +02:00
|
|
|
/// This method attaches an action that will watch any domain
|
|
|
|
|
/// modification of the domain of the variable.
|
2015-10-23 13:45:43 +02:00
|
|
|
void WhenDomain(Solver::Action action) {
|
2017-04-19 16:20:56 +02:00
|
|
|
WhenDomain(solver()->MakeActionDemon(std::move(action)));
|
2015-10-23 13:45:43 +02:00
|
|
|
}
|
2020-10-22 23:36:58 +02:00
|
|
|
#endif // SWIG
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// This method returns the number of values in the domain of the variable.
|
2021-04-01 12:13:35 +02:00
|
|
|
virtual uint64_t Size() const = 0;
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// This method returns whether the value 'v' is in the domain of the
|
|
|
|
|
/// variable.
|
2021-04-01 12:13:35 +02:00
|
|
|
virtual bool Contains(int64_t v) const = 0;
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Creates a hole iterator. When 'reversible' is false, the returned
|
|
|
|
|
/// object is created on the normal C++ heap and the solver does NOT
|
|
|
|
|
/// take ownership of the object.
|
2020-10-29 14:25:39 +01:00
|
|
|
virtual IntVarIterator* MakeHoleIterator(bool reversible) const = 0;
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Creates a domain iterator. When 'reversible' is false, the
|
|
|
|
|
/// returned object is created on the normal C++ heap and the solver
|
|
|
|
|
/// does NOT take ownership of the object.
|
2020-10-29 14:25:39 +01:00
|
|
|
virtual IntVarIterator* MakeDomainIterator(bool reversible) const = 0;
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Returns the previous min.
|
2021-04-01 12:13:35 +02:00
|
|
|
virtual int64_t OldMin() const = 0;
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Returns the previous max.
|
2021-04-01 12:13:35 +02:00
|
|
|
virtual int64_t OldMax() const = 0;
|
2010-09-15 12:42:33 +00:00
|
|
|
|
|
|
|
|
virtual int VarType() const;
|
|
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Accepts the given visitor.
|
2023-05-31 14:27:08 +02:00
|
|
|
void Accept(ModelVisitor* visitor) const override;
|
2011-07-11 20:13:14 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// IsEqual
|
2021-04-01 12:13:35 +02:00
|
|
|
virtual IntVar* IsEqual(int64_t constant) = 0;
|
|
|
|
|
virtual IntVar* IsDifferent(int64_t constant) = 0;
|
|
|
|
|
virtual IntVar* IsGreaterOrEqual(int64_t constant) = 0;
|
|
|
|
|
virtual IntVar* IsLessOrEqual(int64_t constant) = 0;
|
2012-06-14 21:14:09 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Returns the index of the variable.
|
2014-11-07 14:30:53 +00:00
|
|
|
int index() const { return index_; }
|
|
|
|
|
|
2020-10-22 23:36:58 +02:00
|
|
|
private:
|
2014-11-07 14:30:53 +00:00
|
|
|
const int index_;
|
2010-09-15 12:42:33 +00:00
|
|
|
};
|
|
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// This class is the root class of all solution collectors.
|
|
|
|
|
/// It implements a basic query API to be used independently
|
|
|
|
|
/// of the collector used.
|
2010-09-15 12:42:33 +00:00
|
|
|
class SolutionCollector : public SearchMonitor {
|
2020-10-22 23:36:58 +02:00
|
|
|
public:
|
2023-05-24 15:32:06 +02:00
|
|
|
SolutionCollector(Solver* solver, const Assignment* assignment);
|
|
|
|
|
explicit SolutionCollector(Solver* solver);
|
2023-09-25 18:06:35 +02:00
|
|
|
|
|
|
|
|
#ifndef SWIG
|
|
|
|
|
// This type is neither copyable nor movable.
|
|
|
|
|
SolutionCollector(const SolutionCollector&) = delete;
|
|
|
|
|
SolutionCollector& operator=(const SolutionCollector&) = delete;
|
|
|
|
|
#endif
|
|
|
|
|
|
2015-04-16 15:49:51 +02:00
|
|
|
~SolutionCollector() override;
|
2022-09-05 18:30:09 +02:00
|
|
|
void Install() override;
|
2018-10-31 16:18:18 +01:00
|
|
|
std::string DebugString() const override { return "SolutionCollector"; }
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Add API.
|
2023-05-24 15:32:06 +02:00
|
|
|
void Add(IntVar* var);
|
2020-10-29 14:25:39 +01:00
|
|
|
void Add(const std::vector<IntVar*>& vars);
|
2023-05-24 15:32:06 +02:00
|
|
|
void Add(IntervalVar* var);
|
2020-10-29 14:25:39 +01:00
|
|
|
void Add(const std::vector<IntervalVar*>& vars);
|
2023-05-24 15:32:06 +02:00
|
|
|
void Add(SequenceVar* var);
|
2020-10-29 14:25:39 +01:00
|
|
|
void Add(const std::vector<SequenceVar*>& vars);
|
2023-05-24 15:32:06 +02:00
|
|
|
void AddObjective(IntVar* objective);
|
|
|
|
|
void AddObjectives(const std::vector<IntVar*>& objectives);
|
2011-01-06 17:40:30 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Beginning of the search.
|
2015-04-16 15:49:51 +02:00
|
|
|
void EnterSearch() override;
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Returns how many solutions were stored during the search.
|
2010-09-15 12:42:33 +00:00
|
|
|
int solution_count() const;
|
|
|
|
|
|
2023-09-25 18:06:35 +02:00
|
|
|
/// Returns whether any solutions were stored during the search.
|
|
|
|
|
bool has_solution() const;
|
|
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Returns the nth solution.
|
2020-10-29 14:25:39 +01:00
|
|
|
Assignment* solution(int n) const;
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2023-09-25 18:06:35 +02:00
|
|
|
/// Returns the last solution if there are any, nullptr otherwise.
|
|
|
|
|
Assignment* last_solution_or_null() const;
|
|
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Returns the wall time in ms for the nth solution.
|
2021-04-01 12:13:35 +02:00
|
|
|
int64_t wall_time(int n) const;
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Returns the number of branches when the nth solution was found.
|
2021-04-01 12:13:35 +02:00
|
|
|
int64_t branches(int n) const;
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Returns the number of failures encountered at the time of the nth
|
|
|
|
|
/// solution.
|
2021-04-01 12:13:35 +02:00
|
|
|
int64_t failures(int n) const;
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Returns the objective value of the nth solution.
|
2021-04-01 12:13:35 +02:00
|
|
|
int64_t objective_value(int n) const;
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2023-05-24 15:32:06 +02:00
|
|
|
/// Returns the value of the index-th objective of the nth solution.
|
|
|
|
|
int64_t ObjectiveValueFromIndex(int n, int index) const;
|
|
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// This is a shortcut to get the Value of 'var' in the nth solution.
|
2023-05-24 15:32:06 +02:00
|
|
|
int64_t Value(int n, IntVar* var) const;
|
2010-10-07 00:15:54 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// This is a shortcut to get the StartValue of 'var' in the nth solution.
|
2023-05-24 15:32:06 +02:00
|
|
|
int64_t StartValue(int n, IntervalVar* var) const;
|
2010-10-07 00:15:54 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// This is a shortcut to get the EndValue of 'var' in the nth solution.
|
2023-05-24 15:32:06 +02:00
|
|
|
int64_t EndValue(int n, IntervalVar* var) const;
|
2010-10-07 00:15:54 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// This is a shortcut to get the DurationValue of 'var' in the nth solution.
|
2023-05-24 15:32:06 +02:00
|
|
|
int64_t DurationValue(int n, IntervalVar* var) const;
|
2010-10-07 00:15:54 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// This is a shortcut to get the PerformedValue of 'var' in the nth solution.
|
2023-05-24 15:32:06 +02:00
|
|
|
int64_t PerformedValue(int n, IntervalVar* var) const;
|
2010-10-07 00:15:54 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// This is a shortcut to get the ForwardSequence of 'var' in the
|
|
|
|
|
/// nth solution. The forward sequence is the list of ranked interval
|
|
|
|
|
/// variables starting from the start of the sequence.
|
2023-05-24 15:32:06 +02:00
|
|
|
const std::vector<int>& ForwardSequence(int n, SequenceVar* var) const;
|
2019-07-05 00:25:55 +02:00
|
|
|
/// This is a shortcut to get the BackwardSequence of 'var' in the
|
|
|
|
|
/// nth solution. The backward sequence is the list of ranked interval
|
|
|
|
|
/// variables starting from the end of the sequence.
|
2023-05-24 15:32:06 +02:00
|
|
|
const std::vector<int>& BackwardSequence(int n, SequenceVar* var) const;
|
2019-07-05 00:25:55 +02:00
|
|
|
/// This is a shortcut to get the list of unperformed of 'var' in the
|
|
|
|
|
/// nth solution.
|
2023-05-24 15:32:06 +02:00
|
|
|
const std::vector<int>& Unperformed(int n, SequenceVar* var) const;
|
2012-07-20 17:18:59 +00:00
|
|
|
|
2020-10-22 23:36:58 +02:00
|
|
|
protected:
|
2017-12-08 14:52:49 +01:00
|
|
|
struct SolutionData {
|
2020-10-29 14:25:39 +01:00
|
|
|
Assignment* solution;
|
2021-04-01 12:13:35 +02:00
|
|
|
int64_t time;
|
|
|
|
|
int64_t branches;
|
|
|
|
|
int64_t failures;
|
2023-05-24 15:32:06 +02:00
|
|
|
int64_t ObjectiveValue() const;
|
|
|
|
|
int64_t ObjectiveValueFromIndex(int index) const;
|
|
|
|
|
bool operator<(const SolutionData& other) const;
|
2017-12-08 14:52:49 +01:00
|
|
|
};
|
|
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Push the current state as a new solution.
|
2010-09-15 12:42:33 +00:00
|
|
|
void PushSolution();
|
2020-10-29 14:25:39 +01:00
|
|
|
void Push(const SolutionData& data) { solution_data_.push_back(data); }
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Remove and delete the last popped solution.
|
2010-09-15 12:42:33 +00:00
|
|
|
void PopSolution();
|
2017-12-08 14:52:49 +01:00
|
|
|
SolutionData BuildSolutionDataForCurrentState();
|
2020-10-29 14:25:39 +01:00
|
|
|
void FreeSolution(Assignment* solution);
|
2010-09-15 12:42:33 +00:00
|
|
|
void check_index(int n) const;
|
2017-12-08 14:52:49 +01:00
|
|
|
|
2013-12-10 16:02:46 +00:00
|
|
|
std::unique_ptr<Assignment> prototype_;
|
2017-12-08 14:52:49 +01:00
|
|
|
std::vector<SolutionData> solution_data_;
|
2020-10-29 14:25:39 +01:00
|
|
|
std::vector<Assignment*> recycle_solutions_;
|
2023-05-24 15:32:06 +02:00
|
|
|
#if !defined(SWIG)
|
|
|
|
|
std::vector<std::unique_ptr<Assignment>> solution_pool_;
|
|
|
|
|
#endif // SWIG
|
2010-09-15 12:42:33 +00:00
|
|
|
};
|
|
|
|
|
|
2024-11-18 11:32:13 +01:00
|
|
|
// Base objective monitor class. All metaheuristics and metaheuristic combiners
|
|
|
|
|
// derive from this.
|
|
|
|
|
class BaseObjectiveMonitor : public SearchMonitor {
|
|
|
|
|
public:
|
|
|
|
|
explicit BaseObjectiveMonitor(Solver* solver) : SearchMonitor(solver) {}
|
|
|
|
|
~BaseObjectiveMonitor() override {}
|
|
|
|
|
#ifndef SWIG
|
|
|
|
|
BaseObjectiveMonitor(const BaseObjectiveMonitor&) = delete;
|
|
|
|
|
BaseObjectiveMonitor& operator=(const BaseObjectiveMonitor&) = delete;
|
|
|
|
|
#endif // SWIG
|
|
|
|
|
virtual IntVar* ObjectiveVar(int index) const = 0;
|
|
|
|
|
virtual IntVar* MinimizationVar(int index) const = 0;
|
|
|
|
|
virtual int64_t Step(int index) const = 0;
|
|
|
|
|
virtual bool Maximize(int index) const = 0;
|
|
|
|
|
virtual int64_t BestValue(int index) const = 0;
|
|
|
|
|
virtual int Size() const = 0;
|
|
|
|
|
bool is_active() const { return is_active_; }
|
|
|
|
|
void set_active(bool is_active) { is_active_ = is_active; }
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
bool is_active_ = true;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// Base atomic objective monitor class. All non-composite metaheuristics derive
|
|
|
|
|
// from this.
|
|
|
|
|
class ObjectiveMonitor : public BaseObjectiveMonitor {
|
2023-05-24 15:32:06 +02:00
|
|
|
public:
|
|
|
|
|
ObjectiveMonitor(Solver* solver, const std::vector<bool>& maximize,
|
|
|
|
|
std::vector<IntVar*> vars, std::vector<int64_t> steps);
|
2023-05-31 14:27:08 +02:00
|
|
|
~ObjectiveMonitor() override {}
|
2023-05-24 15:32:06 +02:00
|
|
|
#ifndef SWIG
|
|
|
|
|
ObjectiveMonitor(const ObjectiveMonitor&) = delete;
|
|
|
|
|
ObjectiveMonitor& operator=(const ObjectiveMonitor&) = delete;
|
|
|
|
|
#endif // SWIG
|
2024-11-18 11:32:13 +01:00
|
|
|
IntVar* ObjectiveVar(int index) const override {
|
|
|
|
|
return objective_vars_[index];
|
|
|
|
|
}
|
|
|
|
|
IntVar* MinimizationVar(int index) const override {
|
|
|
|
|
return minimization_vars_[index];
|
|
|
|
|
}
|
|
|
|
|
int64_t Step(int index) const override { return steps_[index]; }
|
|
|
|
|
bool Maximize(int index) const override {
|
2023-05-24 15:32:06 +02:00
|
|
|
return ObjectiveVar(index) != MinimizationVar(index);
|
|
|
|
|
}
|
2024-11-18 11:32:13 +01:00
|
|
|
int64_t BestValue(int index) const override {
|
2023-05-24 15:32:06 +02:00
|
|
|
return Maximize(index) ? CapOpp(BestInternalValue(index))
|
|
|
|
|
: BestInternalValue(index);
|
|
|
|
|
}
|
2024-11-18 11:32:13 +01:00
|
|
|
int Size() const override { return objective_vars_.size(); }
|
2023-05-24 15:32:06 +02:00
|
|
|
void EnterSearch() override;
|
|
|
|
|
bool AtSolution() override;
|
2023-09-25 18:06:35 +02:00
|
|
|
bool AcceptDelta(Assignment* delta, Assignment* deltadelta) override;
|
2023-05-24 15:32:06 +02:00
|
|
|
void Accept(ModelVisitor* visitor) const override;
|
|
|
|
|
|
|
|
|
|
protected:
|
|
|
|
|
const std::vector<IntVar*>& objective_vars() const { return objective_vars_; }
|
|
|
|
|
const std::vector<IntVar*>& minimization_vars() const {
|
|
|
|
|
return minimization_vars_;
|
|
|
|
|
}
|
|
|
|
|
int64_t BestInternalValue(int index) const { return best_values_[index]; }
|
|
|
|
|
int64_t CurrentInternalValue(int index) const {
|
|
|
|
|
return current_values_[index];
|
|
|
|
|
}
|
|
|
|
|
void SetCurrentInternalValue(int index, int64_t value) {
|
|
|
|
|
current_values_[index] = value;
|
|
|
|
|
}
|
|
|
|
|
template <typename T>
|
|
|
|
|
void MakeMinimizationVarsLessOrEqualWithSteps(const T& upper_bounds) {
|
|
|
|
|
if (Size() == 1) {
|
|
|
|
|
MinimizationVar(0)->SetMax(CapSub(upper_bounds(0), Step(0)));
|
|
|
|
|
} else {
|
|
|
|
|
Solver* const solver = this->solver();
|
|
|
|
|
for (int i = 0; i < Size(); ++i) {
|
|
|
|
|
upper_bounds_[i] = solver->MakeIntConst(upper_bounds(i));
|
|
|
|
|
}
|
|
|
|
|
solver->AddConstraint(solver->MakeLexicalLessOrEqualWithOffsets(
|
|
|
|
|
minimization_vars_, upper_bounds_, steps_));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
template <typename T>
|
|
|
|
|
IntVar* MakeMinimizationVarsLessOrEqualWithStepsStatus(
|
|
|
|
|
const T& upper_bounds) {
|
|
|
|
|
Solver* const solver = this->solver();
|
|
|
|
|
IntVar* status = solver->MakeBoolVar();
|
|
|
|
|
if (Size() == 1) {
|
|
|
|
|
solver->AddConstraint(solver->MakeIsLessOrEqualCstCt(
|
|
|
|
|
MinimizationVar(0), CapSub(upper_bounds(0), Step(0)), status));
|
|
|
|
|
} else {
|
|
|
|
|
for (int i = 0; i < Size(); ++i) {
|
|
|
|
|
upper_bounds_[i] = solver->MakeIntConst(upper_bounds(i));
|
|
|
|
|
}
|
|
|
|
|
solver->AddConstraint(solver->MakeIsLexicalLessOrEqualWithOffsetsCt(
|
|
|
|
|
minimization_vars_, upper_bounds_, steps_, status));
|
|
|
|
|
}
|
|
|
|
|
return status;
|
|
|
|
|
}
|
|
|
|
|
bool CurrentInternalValuesAreConstraining() const;
|
|
|
|
|
|
|
|
|
|
bool found_initial_solution_;
|
|
|
|
|
|
|
|
|
|
private:
|
2023-07-10 13:15:40 +02:00
|
|
|
friend class Solver;
|
2023-05-24 15:32:06 +02:00
|
|
|
const std::vector<IntVar*> objective_vars_;
|
|
|
|
|
std::vector<IntVar*> minimization_vars_;
|
|
|
|
|
std::vector<IntVar*> upper_bounds_;
|
|
|
|
|
std::vector<int64_t> steps_;
|
|
|
|
|
std::vector<int64_t> best_values_;
|
|
|
|
|
std::vector<int64_t> current_values_;
|
|
|
|
|
};
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// This class encapsulates an objective. It requires the direction
|
|
|
|
|
/// (minimize or maximize), the variable to optimize, and the
|
|
|
|
|
/// improvement step.
|
2023-05-24 15:32:06 +02:00
|
|
|
class OptimizeVar : public ObjectiveMonitor {
|
2020-10-22 23:36:58 +02:00
|
|
|
public:
|
2023-05-24 15:32:06 +02:00
|
|
|
OptimizeVar(Solver* solver, bool maximize, IntVar* var, int64_t step);
|
|
|
|
|
// Specifies a lexicographic objective. Each objective is specified in
|
|
|
|
|
// decreasing order with the corresponding direction and step.
|
|
|
|
|
OptimizeVar(Solver* solver, const std::vector<bool>& maximize,
|
|
|
|
|
std::vector<IntVar*> vars, std::vector<int64_t> steps);
|
|
|
|
|
#ifndef SWIG
|
2023-05-31 14:27:08 +02:00
|
|
|
~OptimizeVar() override {}
|
2023-05-24 15:32:06 +02:00
|
|
|
#endif // SIWG
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Returns the best value found during search.
|
2023-05-24 15:32:06 +02:00
|
|
|
int64_t best() const { return BestValue(0); }
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Returns the variable that is optimized.
|
2023-05-24 15:32:06 +02:00
|
|
|
IntVar* var() const { return Size() == 0 ? nullptr : ObjectiveVar(0); }
|
|
|
|
|
|
2025-12-01 11:34:13 +01:00
|
|
|
#ifndef SWIG
|
|
|
|
|
/// Sets a callback to be called when the objective value is found to be
|
|
|
|
|
/// optimal.
|
|
|
|
|
void SetOnOptimalFoundcallback(
|
|
|
|
|
std::function<void(int64_t)> on_optimal_found) {
|
|
|
|
|
on_optimal_found_ = std::move(on_optimal_found);
|
|
|
|
|
}
|
|
|
|
|
#endif // SWIG
|
|
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Internal methods.
|
2023-05-24 15:32:06 +02:00
|
|
|
void BeginNextDecision(DecisionBuilder* db) override;
|
|
|
|
|
void RefuteDecision(Decision* d) override;
|
2015-04-16 15:49:51 +02:00
|
|
|
bool AtSolution() override;
|
|
|
|
|
bool AcceptSolution() override;
|
2023-07-10 13:15:40 +02:00
|
|
|
virtual std::string Name() const;
|
2015-04-16 15:49:51 +02:00
|
|
|
std::string DebugString() const override;
|
2010-09-15 12:42:33 +00:00
|
|
|
|
|
|
|
|
void ApplyBound();
|
2025-12-01 11:34:13 +01:00
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
std::function<void(int64_t)> on_optimal_found_;
|
2010-09-15 12:42:33 +00:00
|
|
|
};
|
|
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Base class of all search limits.
|
2010-09-15 12:42:33 +00:00
|
|
|
class SearchLimit : public SearchMonitor {
|
2020-10-22 23:36:58 +02:00
|
|
|
public:
|
2020-10-29 14:25:39 +01:00
|
|
|
explicit SearchLimit(Solver* const s) : SearchMonitor(s), crossed_(false) {}
|
2023-09-25 18:06:35 +02:00
|
|
|
|
|
|
|
|
#ifndef SWIG
|
|
|
|
|
// This type is neither copyable nor movable.
|
|
|
|
|
SearchLimit(const SearchLimit&) = delete;
|
|
|
|
|
SearchLimit& operator=(const SearchLimit&) = delete;
|
|
|
|
|
#endif
|
2015-04-16 15:49:51 +02:00
|
|
|
~SearchLimit() override;
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Returns true if the limit has been crossed.
|
2010-09-15 12:42:33 +00:00
|
|
|
bool crossed() const { return crossed_; }
|
|
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// This method is called to check the status of the limit. A return
|
|
|
|
|
/// value of true indicates that we have indeed crossed the limit. In
|
|
|
|
|
/// that case, this method will not be called again and the remaining
|
|
|
|
|
/// search will be discarded.
|
2022-10-21 09:10:53 +02:00
|
|
|
bool Check() { return CheckWithOffset(absl::ZeroDuration()); }
|
|
|
|
|
/// Same as Check() but adds the 'offset' value to the current time when time
|
|
|
|
|
/// is considered in the limit.
|
|
|
|
|
virtual bool CheckWithOffset(absl::Duration offset) = 0;
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// This method is called when the search limit is initialized.
|
2010-09-15 12:42:33 +00:00
|
|
|
virtual void Init() = 0;
|
|
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Copy a limit. Warning: leads to a direct (no check) downcasting of 'limit'
|
|
|
|
|
/// so one needs to be sure both SearchLimits are of the same type.
|
2023-05-31 14:27:08 +02:00
|
|
|
virtual void Copy(const SearchLimit* limit) = 0;
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Allocates a clone of the limit.
|
2020-10-29 14:25:39 +01:00
|
|
|
virtual SearchLimit* MakeClone() const = 0;
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Internal methods.
|
2015-04-16 15:49:51 +02:00
|
|
|
void EnterSearch() override;
|
2023-05-31 14:27:08 +02:00
|
|
|
void BeginNextDecision(DecisionBuilder* b) override;
|
2015-04-16 15:49:51 +02:00
|
|
|
void PeriodicCheck() override;
|
2023-05-31 14:27:08 +02:00
|
|
|
void RefuteDecision(Decision* d) override;
|
2015-04-16 15:49:51 +02:00
|
|
|
std::string DebugString() const override {
|
2018-10-31 16:18:18 +01:00
|
|
|
return absl::StrFormat("SearchLimit(crossed = %i)", crossed_);
|
2010-09-15 12:42:33 +00:00
|
|
|
}
|
2022-09-05 18:30:09 +02:00
|
|
|
void Install() override;
|
2011-06-28 09:27:03 +00:00
|
|
|
|
2020-10-22 23:36:58 +02:00
|
|
|
private:
|
2013-07-18 14:53:24 +00:00
|
|
|
void TopPeriodicCheck();
|
|
|
|
|
|
2010-09-15 12:42:33 +00:00
|
|
|
bool crossed_;
|
|
|
|
|
};
|
|
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Usual limit based on wall_time, number of explored branches and
|
|
|
|
|
/// number of failures in the search tree
|
2019-04-11 09:39:02 -07:00
|
|
|
class RegularLimit : public SearchLimit {
|
2020-10-22 23:36:58 +02:00
|
|
|
public:
|
2023-05-31 14:27:08 +02:00
|
|
|
RegularLimit(Solver* s, absl::Duration time, int64_t branches,
|
2021-04-01 12:13:35 +02:00
|
|
|
int64_t failures, int64_t solutions, bool smart_time_check,
|
2020-03-09 17:52:25 +01:00
|
|
|
bool cumulative);
|
2019-04-11 09:39:02 -07:00
|
|
|
~RegularLimit() override;
|
2023-05-31 14:27:08 +02:00
|
|
|
void Copy(const SearchLimit* limit) override;
|
2020-10-29 14:25:39 +01:00
|
|
|
SearchLimit* MakeClone() const override;
|
|
|
|
|
RegularLimit* MakeIdenticalClone() const;
|
2022-10-21 09:10:53 +02:00
|
|
|
bool CheckWithOffset(absl::Duration offset) override;
|
2019-04-11 09:39:02 -07:00
|
|
|
void Init() override;
|
|
|
|
|
void ExitSearch() override;
|
2021-04-01 12:13:35 +02:00
|
|
|
void UpdateLimits(absl::Duration time, int64_t branches, int64_t failures,
|
|
|
|
|
int64_t solutions);
|
2019-04-11 09:39:02 -07:00
|
|
|
absl::Duration duration_limit() const { return duration_limit_; }
|
2021-04-01 12:13:35 +02:00
|
|
|
int64_t wall_time() const {
|
2019-04-11 09:39:02 -07:00
|
|
|
return duration_limit_ == absl::InfiniteDuration()
|
|
|
|
|
? kint64max
|
|
|
|
|
: absl::ToInt64Milliseconds(duration_limit());
|
|
|
|
|
}
|
2021-04-01 12:13:35 +02:00
|
|
|
int64_t branches() const { return branches_; }
|
|
|
|
|
int64_t failures() const { return failures_; }
|
|
|
|
|
int64_t solutions() const { return solutions_; }
|
2019-04-16 09:25:06 -07:00
|
|
|
bool IsUncheckedSolutionLimitReached() override;
|
2019-04-11 09:39:02 -07:00
|
|
|
int ProgressPercent() override;
|
|
|
|
|
std::string DebugString() const override;
|
2022-09-05 18:30:09 +02:00
|
|
|
void Install() override;
|
2019-04-11 09:39:02 -07:00
|
|
|
|
|
|
|
|
absl::Time AbsoluteSolverDeadline() const {
|
|
|
|
|
return solver_time_at_limit_start_ + duration_limit_;
|
|
|
|
|
}
|
|
|
|
|
|
2023-05-31 14:27:08 +02:00
|
|
|
void Accept(ModelVisitor* visitor) const override;
|
2019-04-11 09:39:02 -07:00
|
|
|
|
2020-10-22 23:36:58 +02:00
|
|
|
private:
|
2022-10-21 09:10:53 +02:00
|
|
|
bool CheckTime(absl::Duration offset);
|
2019-04-11 09:39:02 -07:00
|
|
|
absl::Duration TimeElapsed();
|
2021-04-01 12:13:35 +02:00
|
|
|
static int64_t GetPercent(int64_t value, int64_t offset, int64_t total) {
|
2019-04-11 09:39:02 -07:00
|
|
|
return (total > 0 && total < kint64max) ? 100 * (value - offset) / total
|
|
|
|
|
: -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
absl::Duration duration_limit_;
|
|
|
|
|
absl::Time solver_time_at_limit_start_;
|
|
|
|
|
absl::Duration last_time_elapsed_;
|
2021-04-01 12:13:35 +02:00
|
|
|
int64_t check_count_;
|
|
|
|
|
int64_t next_check_;
|
2019-04-11 09:39:02 -07:00
|
|
|
bool smart_time_check_;
|
2021-04-01 12:13:35 +02:00
|
|
|
int64_t branches_;
|
|
|
|
|
int64_t branches_offset_;
|
|
|
|
|
int64_t failures_;
|
|
|
|
|
int64_t failures_offset_;
|
|
|
|
|
int64_t solutions_;
|
|
|
|
|
int64_t solutions_offset_;
|
2019-07-05 00:25:55 +02:00
|
|
|
/// If cumulative if false, then the limit applies to each search
|
|
|
|
|
/// independently. If it's true, the limit applies globally to all search for
|
|
|
|
|
/// which this monitor is used.
|
|
|
|
|
/// When cumulative is true, the offset fields have two different meanings
|
|
|
|
|
/// depending on context:
|
|
|
|
|
/// - within a search, it's an offset to be subtracted from the current value
|
|
|
|
|
/// - outside of search, it's the amount consumed in previous searches
|
2019-04-11 09:39:02 -07:00
|
|
|
bool cumulative_;
|
|
|
|
|
};
|
|
|
|
|
|
2023-05-24 15:32:06 +02:00
|
|
|
// Limit based on the improvement rate of 'objective_var' or a lexicographic
|
|
|
|
|
// objective composed of 'objective_vars'.
|
2020-10-18 16:38:25 +02:00
|
|
|
// This limit proceeds in two stages:
|
2023-05-24 15:32:06 +02:00
|
|
|
// 1) During the phase of the search in which the objective is strictly
|
2020-10-18 16:38:25 +02:00
|
|
|
// improving, a threshold value is computed as the minimum improvement rate of
|
|
|
|
|
// the objective, based on the 'improvement_rate_coefficient' and
|
|
|
|
|
// 'improvement_rate_solutions_distance' parameters.
|
|
|
|
|
// 2) Then, if the search continues beyond this phase of strict improvement, the
|
|
|
|
|
// limit stops the search when the improvement rate of the objective gets below
|
|
|
|
|
// this threshold value.
|
|
|
|
|
class ImprovementSearchLimit : public SearchLimit {
|
2020-10-22 23:36:58 +02:00
|
|
|
public:
|
2023-05-24 15:32:06 +02:00
|
|
|
ImprovementSearchLimit(Solver* solver, IntVar* objective_var, bool maximize,
|
2020-10-18 16:38:25 +02:00
|
|
|
double objective_scaling_factor,
|
|
|
|
|
double objective_offset,
|
|
|
|
|
double improvement_rate_coefficient,
|
|
|
|
|
int improvement_rate_solutions_distance);
|
2023-05-24 15:32:06 +02:00
|
|
|
ImprovementSearchLimit(Solver* solver, std::vector<IntVar*> objective_vars,
|
|
|
|
|
std::vector<bool> maximize,
|
|
|
|
|
std::vector<double> objective_scaling_factors,
|
|
|
|
|
std::vector<double> objective_offsets,
|
|
|
|
|
double improvement_rate_coefficient,
|
|
|
|
|
int improvement_rate_solutions_distance);
|
2020-10-18 16:38:25 +02:00
|
|
|
~ImprovementSearchLimit() override;
|
2023-05-24 15:32:06 +02:00
|
|
|
void Copy(const SearchLimit* limit) override;
|
2020-10-29 14:25:39 +01:00
|
|
|
SearchLimit* MakeClone() const override;
|
2022-10-21 09:10:53 +02:00
|
|
|
bool CheckWithOffset(absl::Duration offset) override;
|
2020-10-18 16:38:25 +02:00
|
|
|
bool AtSolution() override;
|
|
|
|
|
void Init() override;
|
2022-09-05 18:30:09 +02:00
|
|
|
void Install() override;
|
2020-10-18 16:38:25 +02:00
|
|
|
|
2020-10-22 23:36:58 +02:00
|
|
|
private:
|
2023-05-24 15:32:06 +02:00
|
|
|
std::vector<IntVar*> objective_vars_;
|
|
|
|
|
std::vector<bool> maximize_;
|
|
|
|
|
std::vector<double> objective_scaling_factors_;
|
|
|
|
|
std::vector<double> objective_offsets_;
|
2020-10-18 16:38:25 +02:00
|
|
|
double improvement_rate_coefficient_;
|
|
|
|
|
int improvement_rate_solutions_distance_;
|
|
|
|
|
|
2023-05-24 15:32:06 +02:00
|
|
|
std::vector<double> best_objectives_;
|
2020-10-18 16:38:25 +02:00
|
|
|
// clang-format off
|
2023-05-24 15:32:06 +02:00
|
|
|
std::vector<std::deque<std::pair<double, int64_t> > > improvements_;
|
2020-10-18 16:38:25 +02:00
|
|
|
// clang-format on
|
2023-05-24 15:32:06 +02:00
|
|
|
std::vector<double> thresholds_;
|
2020-10-18 16:38:25 +02:00
|
|
|
bool objective_updated_;
|
|
|
|
|
bool gradient_stage_;
|
|
|
|
|
};
|
|
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Interval variables are often used in scheduling. The main characteristics
|
|
|
|
|
/// of an IntervalVar are the start position, duration, and end
|
|
|
|
|
/// date. All these characteristics can be queried and set, and demons can
|
|
|
|
|
/// be posted on their modifications.
|
|
|
|
|
///
|
|
|
|
|
/// An important aspect is optionality: an IntervalVar can be performed or not.
|
|
|
|
|
/// If unperformed, then it simply does not exist, and its characteristics
|
|
|
|
|
/// cannot be accessed any more. An interval var is automatically marked
|
|
|
|
|
/// as unperformed when it is not consistent anymore (start greater
|
|
|
|
|
/// than end, duration < 0...)
|
2025-11-14 15:05:36 +01:00
|
|
|
class
|
|
|
|
|
#ifndef SWIG
|
|
|
|
|
OR_DLL
|
|
|
|
|
#endif
|
|
|
|
|
IntervalVar : public PropagationBaseObject {
|
2020-10-22 23:36:58 +02:00
|
|
|
public:
|
2019-07-05 00:25:55 +02:00
|
|
|
/// The smallest acceptable value to be returned by StartMin()
|
2021-04-01 12:13:35 +02:00
|
|
|
static const int64_t kMinValidValue;
|
2019-07-05 00:25:55 +02:00
|
|
|
/// The largest acceptable value to be returned by EndMax()
|
2021-04-01 12:13:35 +02:00
|
|
|
static const int64_t kMaxValidValue;
|
2020-10-29 14:25:39 +01:00
|
|
|
IntervalVar(Solver* const solver, const std::string& name)
|
2013-12-05 09:29:08 +00:00
|
|
|
: PropagationBaseObject(solver) {
|
2010-09-15 12:42:33 +00:00
|
|
|
set_name(name);
|
|
|
|
|
}
|
2023-09-25 18:06:35 +02:00
|
|
|
|
|
|
|
|
#ifndef SWIG
|
|
|
|
|
// This type is neither copyable nor movable.
|
|
|
|
|
IntervalVar(const IntervalVar&) = delete;
|
|
|
|
|
IntervalVar& operator=(const IntervalVar&) = delete;
|
|
|
|
|
#endif
|
2015-04-16 15:49:51 +02:00
|
|
|
~IntervalVar() override {}
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// These methods query, set, and watch the start position of the
|
|
|
|
|
/// interval var.
|
2021-04-01 12:13:35 +02:00
|
|
|
virtual int64_t StartMin() const = 0;
|
|
|
|
|
virtual int64_t StartMax() const = 0;
|
|
|
|
|
virtual void SetStartMin(int64_t m) = 0;
|
|
|
|
|
virtual void SetStartMax(int64_t m) = 0;
|
|
|
|
|
virtual void SetStartRange(int64_t mi, int64_t ma) = 0;
|
|
|
|
|
virtual int64_t OldStartMin() const = 0;
|
|
|
|
|
virtual int64_t OldStartMax() const = 0;
|
2023-05-31 14:27:08 +02:00
|
|
|
virtual void WhenStartRange(Demon* d) = 0;
|
2015-10-23 13:45:43 +02:00
|
|
|
void WhenStartRange(Solver::Closure closure) {
|
2017-04-19 16:20:56 +02:00
|
|
|
WhenStartRange(solver()->MakeClosureDemon(std::move(closure)));
|
2015-10-23 13:45:43 +02:00
|
|
|
}
|
2015-11-18 16:45:30 +01:00
|
|
|
#if !defined(SWIG)
|
2015-10-23 13:45:43 +02:00
|
|
|
void WhenStartRange(Solver::Action action) {
|
2017-04-19 16:20:56 +02:00
|
|
|
WhenStartRange(solver()->MakeActionDemon(std::move(action)));
|
2015-10-23 13:45:43 +02:00
|
|
|
}
|
2020-10-22 23:36:58 +02:00
|
|
|
#endif // SWIG
|
2023-05-31 14:27:08 +02:00
|
|
|
virtual void WhenStartBound(Demon* d) = 0;
|
2015-10-23 13:45:43 +02:00
|
|
|
void WhenStartBound(Solver::Closure closure) {
|
2017-04-19 16:20:56 +02:00
|
|
|
WhenStartBound(solver()->MakeClosureDemon(std::move(closure)));
|
2015-10-23 13:45:43 +02:00
|
|
|
}
|
2015-11-18 16:45:30 +01:00
|
|
|
#if !defined(SWIG)
|
2015-10-23 13:45:43 +02:00
|
|
|
void WhenStartBound(Solver::Action action) {
|
2017-04-19 16:20:56 +02:00
|
|
|
WhenStartBound(solver()->MakeActionDemon(std::move(action)));
|
2015-10-23 13:45:43 +02:00
|
|
|
}
|
2020-10-22 23:36:58 +02:00
|
|
|
#endif // SWIG
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// These methods query, set, and watch the duration of the interval var.
|
2021-04-01 12:13:35 +02:00
|
|
|
virtual int64_t DurationMin() const = 0;
|
|
|
|
|
virtual int64_t DurationMax() const = 0;
|
|
|
|
|
virtual void SetDurationMin(int64_t m) = 0;
|
|
|
|
|
virtual void SetDurationMax(int64_t m) = 0;
|
|
|
|
|
virtual void SetDurationRange(int64_t mi, int64_t ma) = 0;
|
|
|
|
|
virtual int64_t OldDurationMin() const = 0;
|
|
|
|
|
virtual int64_t OldDurationMax() const = 0;
|
2023-05-31 14:27:08 +02:00
|
|
|
virtual void WhenDurationRange(Demon* d) = 0;
|
2015-10-23 13:45:43 +02:00
|
|
|
void WhenDurationRange(Solver::Closure closure) {
|
2017-04-19 16:20:56 +02:00
|
|
|
WhenDurationRange(solver()->MakeClosureDemon(std::move(closure)));
|
2015-10-23 13:45:43 +02:00
|
|
|
}
|
2015-11-18 16:45:30 +01:00
|
|
|
#if !defined(SWIG)
|
2015-10-23 13:45:43 +02:00
|
|
|
void WhenDurationRange(Solver::Action action) {
|
2017-04-19 16:20:56 +02:00
|
|
|
WhenDurationRange(solver()->MakeActionDemon(std::move(action)));
|
2015-10-23 13:45:43 +02:00
|
|
|
}
|
2020-10-22 23:36:58 +02:00
|
|
|
#endif // SWIG
|
2023-05-31 14:27:08 +02:00
|
|
|
virtual void WhenDurationBound(Demon* d) = 0;
|
2015-10-23 13:45:43 +02:00
|
|
|
void WhenDurationBound(Solver::Closure closure) {
|
2017-04-19 16:20:56 +02:00
|
|
|
WhenDurationBound(solver()->MakeClosureDemon(std::move(closure)));
|
2015-10-23 13:45:43 +02:00
|
|
|
}
|
2015-11-18 16:45:30 +01:00
|
|
|
#if !defined(SWIG)
|
2015-10-23 13:45:43 +02:00
|
|
|
void WhenDurationBound(Solver::Action action) {
|
2017-04-19 16:20:56 +02:00
|
|
|
WhenDurationBound(solver()->MakeActionDemon(std::move(action)));
|
2015-10-23 13:45:43 +02:00
|
|
|
}
|
2020-10-22 23:36:58 +02:00
|
|
|
#endif // SWIG
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// These methods query, set, and watch the end position of the interval var.
|
2021-04-01 12:13:35 +02:00
|
|
|
virtual int64_t EndMin() const = 0;
|
|
|
|
|
virtual int64_t EndMax() const = 0;
|
|
|
|
|
virtual void SetEndMin(int64_t m) = 0;
|
|
|
|
|
virtual void SetEndMax(int64_t m) = 0;
|
|
|
|
|
virtual void SetEndRange(int64_t mi, int64_t ma) = 0;
|
|
|
|
|
virtual int64_t OldEndMin() const = 0;
|
|
|
|
|
virtual int64_t OldEndMax() const = 0;
|
2023-05-31 14:27:08 +02:00
|
|
|
virtual void WhenEndRange(Demon* d) = 0;
|
2015-10-23 13:45:43 +02:00
|
|
|
void WhenEndRange(Solver::Closure closure) {
|
2017-04-19 16:20:56 +02:00
|
|
|
WhenEndRange(solver()->MakeClosureDemon(std::move(closure)));
|
2015-10-23 13:45:43 +02:00
|
|
|
}
|
2015-11-18 16:45:30 +01:00
|
|
|
#if !defined(SWIG)
|
2015-10-23 13:45:43 +02:00
|
|
|
void WhenEndRange(Solver::Action action) {
|
2017-04-19 16:20:56 +02:00
|
|
|
WhenEndRange(solver()->MakeActionDemon(std::move(action)));
|
2015-10-23 13:45:43 +02:00
|
|
|
}
|
2020-10-22 23:36:58 +02:00
|
|
|
#endif // SWIG
|
2023-05-31 14:27:08 +02:00
|
|
|
virtual void WhenEndBound(Demon* d) = 0;
|
2015-10-23 13:45:43 +02:00
|
|
|
void WhenEndBound(Solver::Closure closure) {
|
2017-04-19 16:20:56 +02:00
|
|
|
WhenEndBound(solver()->MakeClosureDemon(std::move(closure)));
|
2015-10-23 13:45:43 +02:00
|
|
|
}
|
2015-11-18 16:45:30 +01:00
|
|
|
#if !defined(SWIG)
|
2015-10-23 13:45:43 +02:00
|
|
|
void WhenEndBound(Solver::Action action) {
|
2017-04-19 16:20:56 +02:00
|
|
|
WhenEndBound(solver()->MakeActionDemon(std::move(action)));
|
2015-10-23 13:45:43 +02:00
|
|
|
}
|
2020-10-22 23:36:58 +02:00
|
|
|
#endif // SWIG
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// These methods query, set, and watch the performed status of the
|
|
|
|
|
/// interval var.
|
2010-11-02 19:02:53 +00:00
|
|
|
virtual bool MustBePerformed() const = 0;
|
|
|
|
|
virtual bool MayBePerformed() const = 0;
|
2010-11-09 09:30:22 +00:00
|
|
|
bool CannotBePerformed() const { return !MayBePerformed(); }
|
2013-06-11 14:49:19 +00:00
|
|
|
bool IsPerformedBound() const {
|
2013-12-05 09:29:08 +00:00
|
|
|
return MustBePerformed() || !MayBePerformed();
|
2010-11-02 19:02:53 +00:00
|
|
|
}
|
2010-09-15 12:42:33 +00:00
|
|
|
virtual void SetPerformed(bool val) = 0;
|
2013-06-11 14:49:19 +00:00
|
|
|
virtual bool WasPerformedBound() const = 0;
|
2023-05-31 14:27:08 +02:00
|
|
|
virtual void WhenPerformedBound(Demon* d) = 0;
|
2015-10-23 13:45:43 +02:00
|
|
|
void WhenPerformedBound(Solver::Closure closure) {
|
2017-04-19 16:20:56 +02:00
|
|
|
WhenPerformedBound(solver()->MakeClosureDemon(std::move(closure)));
|
2015-10-23 13:45:43 +02:00
|
|
|
}
|
2015-11-18 16:45:30 +01:00
|
|
|
#if !defined(SWIG)
|
2015-10-23 13:45:43 +02:00
|
|
|
void WhenPerformedBound(Solver::Action action) {
|
2017-04-19 16:20:56 +02:00
|
|
|
WhenPerformedBound(solver()->MakeActionDemon(std::move(action)));
|
2015-10-23 13:45:43 +02:00
|
|
|
}
|
2020-10-22 23:36:58 +02:00
|
|
|
#endif // SWIG
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Attaches a demon awakened when anything about this interval changes.
|
2023-05-31 14:27:08 +02:00
|
|
|
void WhenAnything(Demon* d);
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Attaches a closure awakened when anything about this interval changes.
|
2015-10-23 13:45:43 +02:00
|
|
|
void WhenAnything(Solver::Closure closure) {
|
2017-04-19 16:20:56 +02:00
|
|
|
WhenAnything(solver()->MakeClosureDemon(std::move(closure)));
|
2015-10-23 13:45:43 +02:00
|
|
|
}
|
2015-11-18 16:45:30 +01:00
|
|
|
#if !defined(SWIG)
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Attaches an action awakened when anything about this interval changes.
|
2015-10-23 13:45:43 +02:00
|
|
|
void WhenAnything(Solver::Action action) {
|
2017-04-19 16:20:56 +02:00
|
|
|
WhenAnything(solver()->MakeActionDemon(std::move(action)));
|
2015-10-23 13:45:43 +02:00
|
|
|
}
|
2020-10-22 23:36:58 +02:00
|
|
|
#endif // SWIG
|
2010-11-17 16:43:58 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// These methods create expressions encapsulating the start, end
|
|
|
|
|
/// and duration of the interval var. Please note that these must not
|
|
|
|
|
/// be used if the interval var is unperformed.
|
2020-10-29 14:25:39 +01:00
|
|
|
virtual IntExpr* StartExpr() = 0;
|
|
|
|
|
virtual IntExpr* DurationExpr() = 0;
|
|
|
|
|
virtual IntExpr* EndExpr() = 0;
|
|
|
|
|
virtual IntExpr* PerformedExpr() = 0;
|
2019-07-05 00:25:55 +02:00
|
|
|
/// These methods create expressions encapsulating the start, end
|
|
|
|
|
/// and duration of the interval var. If the interval var is
|
|
|
|
|
/// unperformed, they will return the unperformed_value.
|
2021-04-01 12:13:35 +02:00
|
|
|
virtual IntExpr* SafeStartExpr(int64_t unperformed_value) = 0;
|
|
|
|
|
virtual IntExpr* SafeDurationExpr(int64_t unperformed_value) = 0;
|
|
|
|
|
virtual IntExpr* SafeEndExpr(int64_t unperformed_value) = 0;
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Accepts the given visitor.
|
2023-05-31 14:27:08 +02:00
|
|
|
virtual void Accept(ModelVisitor* visitor) const = 0;
|
2010-09-15 12:42:33 +00:00
|
|
|
};
|
|
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// A sequence variable is a variable whose domain is a set of possible
|
|
|
|
|
/// orderings of the interval variables. It allows ordering of tasks. It
|
|
|
|
|
/// has two sets of methods: ComputePossibleFirstsAndLasts(), which
|
|
|
|
|
/// returns the list of interval variables that can be ranked first or
|
|
|
|
|
/// last; and RankFirst/RankNotFirst/RankLast/RankNotLast, which can be
|
|
|
|
|
/// used to create the search decision.
|
2011-11-03 10:27:53 +00:00
|
|
|
class SequenceVar : public PropagationBaseObject {
|
2020-10-22 23:36:58 +02:00
|
|
|
public:
|
2023-05-31 14:27:08 +02:00
|
|
|
SequenceVar(Solver* s, const std::vector<IntervalVar*>& intervals,
|
2020-10-29 14:25:39 +01:00
|
|
|
const std::vector<IntVar*>& nexts, const std::string& name);
|
2012-07-21 01:19:32 +00:00
|
|
|
|
2015-04-16 15:49:51 +02:00
|
|
|
~SequenceVar() override;
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2015-04-16 15:49:51 +02:00
|
|
|
std::string DebugString() const override;
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2015-08-13 16:00:54 +02:00
|
|
|
#if !defined(SWIG)
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Returns the minimum and maximum duration of combined interval
|
|
|
|
|
/// vars in the sequence.
|
2023-05-31 14:27:08 +02:00
|
|
|
void DurationRange(int64_t* dmin, int64_t* dmax) const;
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Returns the minimum start min and the maximum end max of all
|
|
|
|
|
/// interval vars in the sequence.
|
2023-05-31 14:27:08 +02:00
|
|
|
void HorizonRange(int64_t* hmin, int64_t* hmax) const;
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Returns the minimum start min and the maximum end max of all
|
|
|
|
|
/// unranked interval vars in the sequence.
|
2023-05-31 14:27:08 +02:00
|
|
|
void ActiveHorizonRange(int64_t* hmin, int64_t* hmax) const;
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Compute statistics on the sequence.
|
2023-05-31 14:27:08 +02:00
|
|
|
void ComputeStatistics(int* ranked, int* not_ranked, int* unperformed) const;
|
2020-10-22 23:36:58 +02:00
|
|
|
#endif // !defined(SWIG)
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Ranks the index_th interval var first of all unranked interval
|
|
|
|
|
/// vars. After that, it will no longer be considered ranked.
|
2010-09-15 12:42:33 +00:00
|
|
|
void RankFirst(int index);
|
|
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Indicates that the index_th interval var will not be ranked first
|
|
|
|
|
/// of all currently unranked interval vars.
|
2010-09-15 12:42:33 +00:00
|
|
|
void RankNotFirst(int index);
|
|
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Ranks the index_th interval var first of all unranked interval
|
|
|
|
|
/// vars. After that, it will no longer be considered ranked.
|
2011-12-16 21:02:59 +00:00
|
|
|
void RankLast(int index);
|
2011-11-03 10:27:53 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Indicates that the index_th interval var will not be ranked first
|
|
|
|
|
/// of all currently unranked interval vars.
|
2011-12-16 21:02:59 +00:00
|
|
|
void RankNotLast(int index);
|
|
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Computes the set of indices of interval variables that can be
|
|
|
|
|
/// ranked first in the set of unranked activities.
|
2023-05-31 14:27:08 +02:00
|
|
|
void ComputePossibleFirstsAndLasts(std::vector<int>* possible_firsts,
|
|
|
|
|
std::vector<int>* possible_lasts);
|
2011-12-16 21:02:59 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Applies the following sequence of ranks, ranks first, then rank
|
|
|
|
|
/// last. rank_first and rank_last represents different directions.
|
|
|
|
|
/// rank_first[0] corresponds to the first interval of the sequence.
|
|
|
|
|
/// rank_last[0] corresponds to the last interval of the sequence.
|
|
|
|
|
/// All intervals in the unperformed vector will be marked as such.
|
2020-10-29 14:25:39 +01:00
|
|
|
void RankSequence(const std::vector<int>& rank_first,
|
|
|
|
|
const std::vector<int>& rank_last,
|
|
|
|
|
const std::vector<int>& unperformed);
|
2011-12-16 21:02:59 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Clears 'rank_first' and 'rank_last', and fills them with the
|
|
|
|
|
/// intervals in the order of the ranks. If all variables are ranked,
|
|
|
|
|
/// 'rank_first' will contain all variables, and 'rank_last' will
|
|
|
|
|
/// contain none.
|
|
|
|
|
/// 'unperformed' will contains all such interval variables.
|
|
|
|
|
/// rank_first and rank_last represents different directions.
|
|
|
|
|
/// rank_first[0] corresponds to the first interval of the sequence.
|
|
|
|
|
/// rank_last[0] corresponds to the last interval of the sequence.
|
2023-05-31 14:27:08 +02:00
|
|
|
void FillSequence(std::vector<int>* rank_first, std::vector<int>* rank_last,
|
|
|
|
|
std::vector<int>* unperformed) const;
|
2011-11-03 10:27:53 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Returns the index_th interval of the sequence.
|
2020-10-29 14:25:39 +01:00
|
|
|
IntervalVar* Interval(int index) const;
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Returns the next of the index_th interval of the sequence.
|
2020-10-29 14:25:39 +01:00
|
|
|
IntVar* Next(int index) const;
|
2012-07-21 01:19:32 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Returns the number of interval vars in the sequence.
|
2021-04-01 12:13:35 +02:00
|
|
|
int64_t size() const { return intervals_.size(); }
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Accepts the given visitor.
|
2023-05-31 14:27:08 +02:00
|
|
|
virtual void Accept(ModelVisitor* visitor) const;
|
2011-07-11 20:13:14 +00:00
|
|
|
|
2020-10-22 23:36:58 +02:00
|
|
|
private:
|
2012-07-21 01:19:32 +00:00
|
|
|
int ComputeForwardFrontier();
|
|
|
|
|
int ComputeBackwardFrontier();
|
|
|
|
|
void UpdatePrevious() const;
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2020-10-29 14:25:39 +01:00
|
|
|
const std::vector<IntervalVar*> intervals_;
|
|
|
|
|
const std::vector<IntVar*> nexts_;
|
2012-07-21 01:19:32 +00:00
|
|
|
mutable std::vector<int> previous_;
|
2010-09-15 12:42:33 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
class AssignmentElement {
|
2020-10-22 23:36:58 +02:00
|
|
|
public:
|
2010-09-15 12:42:33 +00:00
|
|
|
AssignmentElement() : activated_(true) {}
|
2025-08-08 15:03:52 +02:00
|
|
|
AssignmentElement(const AssignmentElement&) = default;
|
2010-09-15 12:42:33 +00:00
|
|
|
|
|
|
|
|
void Activate() { activated_ = true; }
|
|
|
|
|
void Deactivate() { activated_ = false; }
|
|
|
|
|
bool Activated() const { return activated_; }
|
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
|
|
|
bool activated_;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
class IntVarElement : public AssignmentElement {
|
2020-10-22 23:36:58 +02:00
|
|
|
public:
|
2010-09-15 12:42:33 +00:00
|
|
|
IntVarElement();
|
2023-05-31 14:27:08 +02:00
|
|
|
explicit IntVarElement(IntVar* var);
|
2025-08-08 15:03:52 +02:00
|
|
|
IntVarElement(const IntVarElement& element) = default;
|
2023-05-31 14:27:08 +02:00
|
|
|
void Reset(IntVar* var);
|
2020-10-29 14:25:39 +01:00
|
|
|
IntVarElement* Clone();
|
|
|
|
|
void Copy(const IntVarElement& element);
|
|
|
|
|
IntVar* Var() const { return var_; }
|
2010-09-15 12:42:33 +00:00
|
|
|
void Store() {
|
|
|
|
|
min_ = var_->Min();
|
|
|
|
|
max_ = var_->Max();
|
|
|
|
|
}
|
2014-11-07 14:30:53 +00:00
|
|
|
void Restore() {
|
|
|
|
|
if (var_ != nullptr) {
|
|
|
|
|
var_->SetRange(min_, max_);
|
|
|
|
|
}
|
|
|
|
|
}
|
2020-10-29 14:25:39 +01:00
|
|
|
void LoadFromProto(const IntVarAssignment& int_var_assignment_proto);
|
|
|
|
|
void WriteToProto(IntVarAssignment* int_var_assignment_proto) const;
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2021-04-01 12:13:35 +02:00
|
|
|
int64_t Min() const { return min_; }
|
|
|
|
|
void SetMin(int64_t m) { min_ = m; }
|
|
|
|
|
int64_t Max() const { return max_; }
|
|
|
|
|
void SetMax(int64_t m) { max_ = m; }
|
|
|
|
|
int64_t Value() const {
|
2012-02-09 19:42:58 +00:00
|
|
|
DCHECK_EQ(min_, max_);
|
2018-10-31 16:18:18 +01:00
|
|
|
// Get the value from an unbound int var assignment element.
|
2010-09-15 12:42:33 +00:00
|
|
|
return min_;
|
|
|
|
|
}
|
|
|
|
|
bool Bound() const { return (max_ == min_); }
|
2021-04-01 12:13:35 +02:00
|
|
|
void SetRange(int64_t l, int64_t u) {
|
2010-09-15 12:42:33 +00:00
|
|
|
min_ = l;
|
|
|
|
|
max_ = u;
|
|
|
|
|
}
|
2021-04-01 12:13:35 +02:00
|
|
|
void SetValue(int64_t v) {
|
2010-09-15 12:42:33 +00:00
|
|
|
min_ = v;
|
|
|
|
|
max_ = v;
|
|
|
|
|
}
|
2013-12-16 10:24:42 +00:00
|
|
|
std::string DebugString() const;
|
2011-06-28 09:27:03 +00:00
|
|
|
|
2020-10-29 14:25:39 +01:00
|
|
|
bool operator==(const IntVarElement& element) const;
|
|
|
|
|
bool operator!=(const IntVarElement& element) const {
|
2011-11-03 10:27:53 +00:00
|
|
|
return !(*this == element);
|
|
|
|
|
}
|
|
|
|
|
|
2020-10-22 23:36:58 +02:00
|
|
|
private:
|
2020-10-29 14:25:39 +01:00
|
|
|
IntVar* var_;
|
2021-04-01 12:13:35 +02:00
|
|
|
int64_t min_;
|
|
|
|
|
int64_t max_;
|
2010-09-15 12:42:33 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
class IntervalVarElement : public AssignmentElement {
|
2020-10-22 23:36:58 +02:00
|
|
|
public:
|
2010-09-15 12:42:33 +00:00
|
|
|
IntervalVarElement();
|
2023-05-31 14:27:08 +02:00
|
|
|
explicit IntervalVarElement(IntervalVar* var);
|
|
|
|
|
void Reset(IntervalVar* var);
|
2020-10-29 14:25:39 +01:00
|
|
|
IntervalVarElement* Clone();
|
|
|
|
|
void Copy(const IntervalVarElement& element);
|
|
|
|
|
IntervalVar* Var() const { return var_; }
|
2010-09-15 12:42:33 +00:00
|
|
|
void Store();
|
|
|
|
|
void Restore();
|
2020-10-22 23:36:58 +02:00
|
|
|
void LoadFromProto(
|
2020-10-29 14:25:39 +01:00
|
|
|
const IntervalVarAssignment& interval_var_assignment_proto);
|
|
|
|
|
void WriteToProto(IntervalVarAssignment* interval_var_assignment_proto) const;
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2021-04-01 12:13:35 +02:00
|
|
|
int64_t StartMin() const { return start_min_; }
|
|
|
|
|
int64_t StartMax() const { return start_max_; }
|
|
|
|
|
int64_t StartValue() const {
|
2010-10-07 00:15:54 +00:00
|
|
|
CHECK_EQ(start_max_, start_min_);
|
|
|
|
|
return start_max_;
|
|
|
|
|
}
|
2021-04-01 12:13:35 +02:00
|
|
|
int64_t DurationMin() const { return duration_min_; }
|
|
|
|
|
int64_t DurationMax() const { return duration_max_; }
|
|
|
|
|
int64_t DurationValue() const {
|
2010-10-07 00:15:54 +00:00
|
|
|
CHECK_EQ(duration_max_, duration_min_);
|
|
|
|
|
return duration_max_;
|
|
|
|
|
}
|
2021-04-01 12:13:35 +02:00
|
|
|
int64_t EndMin() const { return end_min_; }
|
|
|
|
|
int64_t EndMax() const { return end_max_; }
|
|
|
|
|
int64_t EndValue() const {
|
2010-10-07 00:15:54 +00:00
|
|
|
CHECK_EQ(end_max_, end_min_);
|
|
|
|
|
return end_max_;
|
|
|
|
|
}
|
2021-04-01 12:13:35 +02:00
|
|
|
int64_t PerformedMin() const { return performed_min_; }
|
|
|
|
|
int64_t PerformedMax() const { return performed_max_; }
|
|
|
|
|
int64_t PerformedValue() const {
|
2010-10-07 00:15:54 +00:00
|
|
|
CHECK_EQ(performed_max_, performed_min_);
|
|
|
|
|
return performed_max_;
|
|
|
|
|
}
|
2021-04-01 12:13:35 +02:00
|
|
|
void SetStartMin(int64_t m) { start_min_ = m; }
|
|
|
|
|
void SetStartMax(int64_t m) { start_max_ = m; }
|
|
|
|
|
void SetStartRange(int64_t mi, int64_t ma) {
|
2010-09-15 12:42:33 +00:00
|
|
|
start_min_ = mi;
|
|
|
|
|
start_max_ = ma;
|
|
|
|
|
}
|
2021-04-01 12:13:35 +02:00
|
|
|
void SetStartValue(int64_t v) {
|
2010-09-15 12:42:33 +00:00
|
|
|
start_min_ = v;
|
|
|
|
|
start_max_ = v;
|
|
|
|
|
}
|
2021-04-01 12:13:35 +02:00
|
|
|
void SetDurationMin(int64_t m) { duration_min_ = m; }
|
|
|
|
|
void SetDurationMax(int64_t m) { duration_max_ = m; }
|
|
|
|
|
void SetDurationRange(int64_t mi, int64_t ma) {
|
2010-09-15 12:42:33 +00:00
|
|
|
duration_min_ = mi;
|
|
|
|
|
duration_max_ = ma;
|
|
|
|
|
}
|
2021-04-01 12:13:35 +02:00
|
|
|
void SetDurationValue(int64_t v) {
|
2010-09-15 12:42:33 +00:00
|
|
|
duration_min_ = v;
|
|
|
|
|
duration_max_ = v;
|
|
|
|
|
}
|
2021-04-01 12:13:35 +02:00
|
|
|
void SetEndMin(int64_t m) { end_min_ = m; }
|
|
|
|
|
void SetEndMax(int64_t m) { end_max_ = m; }
|
|
|
|
|
void SetEndRange(int64_t mi, int64_t ma) {
|
2010-09-15 12:42:33 +00:00
|
|
|
end_min_ = mi;
|
|
|
|
|
end_max_ = ma;
|
|
|
|
|
}
|
2021-04-01 12:13:35 +02:00
|
|
|
void SetEndValue(int64_t v) {
|
2010-09-15 12:42:33 +00:00
|
|
|
end_min_ = v;
|
|
|
|
|
end_max_ = v;
|
|
|
|
|
}
|
2021-04-01 12:13:35 +02:00
|
|
|
void SetPerformedMin(int64_t m) { performed_min_ = m; }
|
|
|
|
|
void SetPerformedMax(int64_t m) { performed_max_ = m; }
|
|
|
|
|
void SetPerformedRange(int64_t mi, int64_t ma) {
|
2010-09-15 12:42:33 +00:00
|
|
|
performed_min_ = mi;
|
|
|
|
|
performed_max_ = ma;
|
|
|
|
|
}
|
2021-04-01 12:13:35 +02:00
|
|
|
void SetPerformedValue(int64_t v) {
|
2010-09-15 12:42:33 +00:00
|
|
|
performed_min_ = v;
|
|
|
|
|
performed_max_ = v;
|
|
|
|
|
}
|
2019-03-15 17:17:02 +01:00
|
|
|
bool Bound() const {
|
|
|
|
|
return (start_min_ == start_max_ && duration_min_ == duration_max_ &&
|
|
|
|
|
end_min_ == end_max_ && performed_min_ == performed_max_);
|
|
|
|
|
}
|
2013-12-16 10:24:42 +00:00
|
|
|
std::string DebugString() const;
|
2020-10-29 14:25:39 +01:00
|
|
|
bool operator==(const IntervalVarElement& element) const;
|
|
|
|
|
bool operator!=(const IntervalVarElement& element) const {
|
2011-11-03 10:27:53 +00:00
|
|
|
return !(*this == element);
|
|
|
|
|
}
|
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
|
|
|
int64_t start_min_;
|
|
|
|
|
int64_t start_max_;
|
|
|
|
|
int64_t duration_min_;
|
|
|
|
|
int64_t duration_max_;
|
|
|
|
|
int64_t end_min_;
|
|
|
|
|
int64_t end_max_;
|
|
|
|
|
int64_t performed_min_;
|
|
|
|
|
int64_t performed_max_;
|
2020-10-29 14:25:39 +01:00
|
|
|
IntervalVar* var_;
|
2010-09-15 12:42:33 +00:00
|
|
|
};
|
|
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// The SequenceVarElement stores a partial representation of ranked
|
|
|
|
|
/// interval variables in the underlying sequence variable.
|
|
|
|
|
/// This representation consists of three vectors:
|
|
|
|
|
/// - the forward sequence. That is the list of interval variables
|
|
|
|
|
/// ranked first in the sequence. The first element of the backward
|
|
|
|
|
/// sequence is the first interval in the sequence variable.
|
|
|
|
|
/// - the backward sequence. That is the list of interval variables
|
|
|
|
|
/// ranked last in the sequence. The first element of the backward
|
|
|
|
|
/// sequence is the last interval in the sequence variable.
|
|
|
|
|
/// - The list of unperformed interval variables.
|
|
|
|
|
/// Furthermore, if all performed variables are ranked, then by
|
|
|
|
|
/// convention, the forward_sequence will contain all such variables
|
|
|
|
|
/// and the backward_sequence will be empty.
|
2011-11-03 10:27:53 +00:00
|
|
|
class SequenceVarElement : public AssignmentElement {
|
2020-10-22 23:36:58 +02:00
|
|
|
public:
|
2011-11-03 10:27:53 +00:00
|
|
|
SequenceVarElement();
|
2023-05-31 14:27:08 +02:00
|
|
|
explicit SequenceVarElement(SequenceVar* var);
|
|
|
|
|
void Reset(SequenceVar* var);
|
2020-10-29 14:25:39 +01:00
|
|
|
SequenceVarElement* Clone();
|
|
|
|
|
void Copy(const SequenceVarElement& element);
|
|
|
|
|
SequenceVar* Var() const { return var_; }
|
2011-11-03 10:27:53 +00:00
|
|
|
void Store();
|
|
|
|
|
void Restore();
|
2020-10-22 23:36:58 +02:00
|
|
|
void LoadFromProto(
|
2020-10-29 14:25:39 +01:00
|
|
|
const SequenceVarAssignment& sequence_var_assignment_proto);
|
|
|
|
|
void WriteToProto(SequenceVarAssignment* sequence_var_assignment_proto) const;
|
|
|
|
|
|
|
|
|
|
const std::vector<int>& ForwardSequence() const;
|
|
|
|
|
const std::vector<int>& BackwardSequence() const;
|
|
|
|
|
const std::vector<int>& Unperformed() const;
|
|
|
|
|
void SetSequence(const std::vector<int>& forward_sequence,
|
|
|
|
|
const std::vector<int>& backward_sequence,
|
|
|
|
|
const std::vector<int>& unperformed);
|
|
|
|
|
void SetForwardSequence(const std::vector<int>& forward_sequence);
|
|
|
|
|
void SetBackwardSequence(const std::vector<int>& backward_sequence);
|
|
|
|
|
void SetUnperformed(const std::vector<int>& unperformed);
|
2019-03-15 17:17:02 +01:00
|
|
|
bool Bound() const {
|
|
|
|
|
return forward_sequence_.size() + unperformed_.size() == var_->size();
|
|
|
|
|
}
|
2011-11-03 10:27:53 +00:00
|
|
|
|
2013-12-16 10:24:42 +00:00
|
|
|
std::string DebugString() const;
|
2011-11-03 10:27:53 +00:00
|
|
|
|
2020-10-29 14:25:39 +01:00
|
|
|
bool operator==(const SequenceVarElement& element) const;
|
|
|
|
|
bool operator!=(const SequenceVarElement& element) const {
|
2011-11-03 10:27:53 +00:00
|
|
|
return !(*this == element);
|
|
|
|
|
}
|
|
|
|
|
|
2020-10-22 23:36:58 +02:00
|
|
|
private:
|
2011-12-16 21:02:59 +00:00
|
|
|
bool CheckClassInvariants();
|
|
|
|
|
|
2020-10-29 14:25:39 +01:00
|
|
|
SequenceVar* var_;
|
2011-12-16 21:02:59 +00:00
|
|
|
std::vector<int> forward_sequence_;
|
|
|
|
|
std::vector<int> backward_sequence_;
|
|
|
|
|
std::vector<int> unperformed_;
|
2011-11-03 10:27:53 +00:00
|
|
|
};
|
|
|
|
|
|
2020-10-22 23:36:58 +02:00
|
|
|
template <class V, class E>
|
|
|
|
|
class AssignmentContainer {
|
|
|
|
|
public:
|
2010-09-15 12:42:33 +00:00
|
|
|
AssignmentContainer() {}
|
2020-10-29 14:25:39 +01:00
|
|
|
E* Add(V* var) {
|
2013-10-10 15:23:20 +00:00
|
|
|
CHECK(var != nullptr);
|
2010-09-15 12:42:33 +00:00
|
|
|
int index = -1;
|
|
|
|
|
if (!Find(var, &index)) {
|
|
|
|
|
return FastAdd(var);
|
|
|
|
|
} else {
|
2013-12-05 09:29:08 +00:00
|
|
|
return &elements_[index];
|
2010-09-15 12:42:33 +00:00
|
|
|
}
|
|
|
|
|
}
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Adds element without checking its presence in the container.
|
2020-10-29 14:25:39 +01:00
|
|
|
E* FastAdd(V* var) {
|
2013-10-10 15:23:20 +00:00
|
|
|
DCHECK(var != nullptr);
|
2014-07-24 18:12:50 +00:00
|
|
|
elements_.emplace_back(var);
|
2013-12-05 09:29:08 +00:00
|
|
|
return &elements_.back();
|
|
|
|
|
}
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Advanced usage: Adds element at a given position; position has to have
|
|
|
|
|
/// been allocated with AssignmentContainer::Resize() beforehand.
|
2020-10-29 14:25:39 +01:00
|
|
|
E* AddAtPosition(V* var, int position) {
|
2013-12-05 09:29:08 +00:00
|
|
|
elements_[position].Reset(var);
|
|
|
|
|
return &elements_[position];
|
2010-09-15 12:42:33 +00:00
|
|
|
}
|
|
|
|
|
void Clear() {
|
|
|
|
|
elements_.clear();
|
2020-12-24 15:34:22 +01:00
|
|
|
if (!elements_map_.empty()) { /// 2x speedup on OR-Tools.
|
2012-01-17 10:10:08 +00:00
|
|
|
elements_map_.clear();
|
|
|
|
|
}
|
2010-09-15 12:42:33 +00:00
|
|
|
}
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Advanced usage: Resizes the container, potentially adding elements with
|
|
|
|
|
/// null variables.
|
2014-01-08 12:01:58 +00:00
|
|
|
void Resize(size_t size) { elements_.resize(size); }
|
2013-10-10 15:23:20 +00:00
|
|
|
bool Empty() const { return elements_.empty(); }
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Copies the elements of 'container' which are already in the calling
|
|
|
|
|
/// container.
|
2020-10-29 14:25:39 +01:00
|
|
|
void CopyIntersection(const AssignmentContainer<V, E>& container) {
|
2010-09-15 12:42:33 +00:00
|
|
|
for (int i = 0; i < container.elements_.size(); ++i) {
|
2020-10-29 14:25:39 +01:00
|
|
|
const E& element = container.elements_[i];
|
|
|
|
|
const V* const var = element.Var();
|
2010-09-15 12:42:33 +00:00
|
|
|
int index = -1;
|
|
|
|
|
if (i < elements_.size() && elements_[i].Var() == var) {
|
|
|
|
|
index = i;
|
|
|
|
|
} else if (!Find(var, &index)) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
DCHECK_GE(index, 0);
|
2020-10-29 14:25:39 +01:00
|
|
|
E* const local_element = &elements_[index];
|
2013-12-05 09:29:08 +00:00
|
|
|
local_element->Copy(element);
|
2010-09-15 12:42:33 +00:00
|
|
|
if (element.Activated()) {
|
2013-12-05 09:29:08 +00:00
|
|
|
local_element->Activate();
|
2010-09-15 12:42:33 +00:00
|
|
|
} else {
|
2013-12-05 09:29:08 +00:00
|
|
|
local_element->Deactivate();
|
2010-09-15 12:42:33 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Copies all the elements of 'container' to this container, clearing its
|
|
|
|
|
/// previous content.
|
2020-10-29 14:25:39 +01:00
|
|
|
void Copy(const AssignmentContainer<V, E>& container) {
|
2017-12-08 14:52:49 +01:00
|
|
|
Clear();
|
2025-08-08 15:03:52 +02:00
|
|
|
for (const E& element : container.elements_) {
|
|
|
|
|
elements_.emplace_back(element);
|
2017-12-08 14:52:49 +01:00
|
|
|
}
|
|
|
|
|
}
|
2020-10-29 14:25:39 +01:00
|
|
|
bool Contains(const V* const var) const {
|
2010-09-15 12:42:33 +00:00
|
|
|
int index;
|
|
|
|
|
return Find(var, &index);
|
|
|
|
|
}
|
2020-10-29 14:25:39 +01:00
|
|
|
E* MutableElement(const V* const var) {
|
|
|
|
|
E* const element = MutableElementOrNull(var);
|
2020-10-22 23:36:58 +02:00
|
|
|
DCHECK(element != nullptr)
|
|
|
|
|
<< "Unknown variable " << var->DebugString() << " in solution";
|
2014-01-17 18:36:18 +00:00
|
|
|
return element;
|
|
|
|
|
}
|
2020-10-29 14:25:39 +01:00
|
|
|
E* MutableElementOrNull(const V* const var) {
|
2010-09-15 12:42:33 +00:00
|
|
|
int index = -1;
|
2014-01-17 18:36:18 +00:00
|
|
|
if (Find(var, &index)) {
|
|
|
|
|
return MutableElement(index);
|
|
|
|
|
}
|
|
|
|
|
return nullptr;
|
2010-09-15 12:42:33 +00:00
|
|
|
}
|
2020-10-29 14:25:39 +01:00
|
|
|
const E& Element(const V* const var) const {
|
|
|
|
|
const E* const element = ElementPtrOrNull(var);
|
2020-10-22 23:36:58 +02:00
|
|
|
DCHECK(element != nullptr)
|
|
|
|
|
<< "Unknown variable " << var->DebugString() << " in solution";
|
2014-01-17 18:36:18 +00:00
|
|
|
return *element;
|
|
|
|
|
}
|
2020-10-29 14:25:39 +01:00
|
|
|
const E* ElementPtrOrNull(const V* const var) const {
|
2010-09-15 12:42:33 +00:00
|
|
|
int index = -1;
|
2014-01-17 18:36:18 +00:00
|
|
|
if (Find(var, &index)) {
|
|
|
|
|
return &Element(index);
|
|
|
|
|
}
|
|
|
|
|
return nullptr;
|
2010-09-15 12:42:33 +00:00
|
|
|
}
|
2020-10-29 14:25:39 +01:00
|
|
|
const std::vector<E>& elements() const { return elements_; }
|
|
|
|
|
E* MutableElement(int index) { return &elements_[index]; }
|
|
|
|
|
const E& Element(int index) const { return elements_[index]; }
|
2010-09-15 12:42:33 +00:00
|
|
|
int Size() const { return elements_.size(); }
|
|
|
|
|
void Store() {
|
2020-10-29 14:25:39 +01:00
|
|
|
for (E& element : elements_) {
|
2014-01-27 15:05:30 +00:00
|
|
|
element.Store();
|
2010-09-15 12:42:33 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
void Restore() {
|
2020-10-29 14:25:39 +01:00
|
|
|
for (E& element : elements_) {
|
2014-01-27 15:05:30 +00:00
|
|
|
if (element.Activated()) {
|
|
|
|
|
element.Restore();
|
2010-09-15 12:42:33 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2019-03-15 17:17:02 +01:00
|
|
|
bool AreAllElementsBound() const {
|
2020-10-29 14:25:39 +01:00
|
|
|
for (const E& element : elements_) {
|
2020-10-22 23:36:58 +02:00
|
|
|
if (!element.Bound()) return false;
|
2019-03-15 17:17:02 +01:00
|
|
|
}
|
|
|
|
|
return true;
|
|
|
|
|
}
|
2011-06-28 09:27:03 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Returns true if this and 'container' both represent the same V* -> E map.
|
|
|
|
|
/// Runs in linear time; requires that the == operator on the type E is well
|
|
|
|
|
/// defined.
|
2020-10-29 14:25:39 +01:00
|
|
|
bool operator==(const AssignmentContainer<V, E>& container) const {
|
2019-07-05 00:25:55 +02:00
|
|
|
/// We may not have any work to do
|
2011-11-03 10:27:53 +00:00
|
|
|
if (Size() != container.Size()) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
2019-07-05 00:25:55 +02:00
|
|
|
/// The == should be order-independent
|
2011-11-03 10:27:53 +00:00
|
|
|
EnsureMapIsUpToDate();
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Do not use the hash_map::== operator! It
|
|
|
|
|
/// compares both content and how the map is hashed (e.g., number of
|
|
|
|
|
/// buckets). This is not what we want.
|
2020-10-29 14:25:39 +01:00
|
|
|
for (const E& element : container.elements_) {
|
2018-06-08 16:40:43 +02:00
|
|
|
const int position =
|
|
|
|
|
gtl::FindWithDefault(elements_map_, element.Var(), -1);
|
2014-01-27 15:05:30 +00:00
|
|
|
if (position < 0 || elements_[position] != element) {
|
2011-11-03 10:27:53 +00:00
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return true;
|
|
|
|
|
}
|
2020-10-29 14:25:39 +01:00
|
|
|
bool operator!=(const AssignmentContainer<V, E>& container) const {
|
2011-11-03 10:27:53 +00:00
|
|
|
return !(*this == container);
|
|
|
|
|
}
|
|
|
|
|
|
2020-10-22 23:36:58 +02:00
|
|
|
private:
|
2011-11-03 10:27:53 +00:00
|
|
|
void EnsureMapIsUpToDate() const {
|
2020-10-29 14:25:39 +01:00
|
|
|
absl::flat_hash_map<const V*, int>* map =
|
|
|
|
|
const_cast<absl::flat_hash_map<const V*, int>*>(&elements_map_);
|
2011-11-03 10:27:53 +00:00
|
|
|
for (int i = map->size(); i < elements_.size(); ++i) {
|
|
|
|
|
(*map)[elements_[i].Var()] = i;
|
2010-09-15 12:42:33 +00:00
|
|
|
}
|
|
|
|
|
}
|
2020-10-29 14:25:39 +01:00
|
|
|
bool Find(const V* const var, int* index) const {
|
2019-07-05 00:25:55 +02:00
|
|
|
/// This threshold was determined from microbenchmarks on Nehalem platform.
|
2014-01-17 18:36:18 +00:00
|
|
|
const size_t kMaxSizeForLinearAccess = 11;
|
|
|
|
|
if (Size() <= kMaxSizeForLinearAccess) {
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Look for 'var' in the container by performing a linear
|
|
|
|
|
/// search, avoiding the access to (and creation of) the elements
|
|
|
|
|
/// hash table.
|
2014-01-17 18:36:18 +00:00
|
|
|
for (int i = 0; i < elements_.size(); ++i) {
|
|
|
|
|
if (var == elements_[i].Var()) {
|
|
|
|
|
*index = i;
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
} else {
|
|
|
|
|
EnsureMapIsUpToDate();
|
|
|
|
|
DCHECK_EQ(elements_map_.size(), elements_.size());
|
2018-04-11 13:00:30 +02:00
|
|
|
return gtl::FindCopy(elements_map_, var, index);
|
2014-01-17 18:36:18 +00:00
|
|
|
}
|
2010-09-15 12:42:33 +00:00
|
|
|
}
|
|
|
|
|
|
2011-05-17 20:38:55 +00:00
|
|
|
std::vector<E> elements_;
|
2020-10-29 14:25:39 +01:00
|
|
|
absl::flat_hash_map<const V*, int> elements_map_;
|
2010-09-15 12:42:33 +00:00
|
|
|
};
|
|
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// An Assignment is a variable -> domains mapping, used
|
|
|
|
|
/// to report solutions to the user.
|
2010-09-15 12:42:33 +00:00
|
|
|
class Assignment : public PropagationBaseObject {
|
2020-10-22 23:36:58 +02:00
|
|
|
public:
|
2010-09-15 12:42:33 +00:00
|
|
|
typedef AssignmentContainer<IntVar, IntVarElement> IntContainer;
|
|
|
|
|
typedef AssignmentContainer<IntervalVar, IntervalVarElement>
|
2013-10-10 15:23:20 +00:00
|
|
|
IntervalContainer;
|
2011-11-03 10:27:53 +00:00
|
|
|
typedef AssignmentContainer<SequenceVar, SequenceVarElement>
|
2013-10-10 15:23:20 +00:00
|
|
|
SequenceContainer;
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2023-05-24 15:32:06 +02:00
|
|
|
explicit Assignment(Solver* solver);
|
2023-05-31 14:27:08 +02:00
|
|
|
explicit Assignment(const Assignment* copy);
|
2023-09-25 18:06:35 +02:00
|
|
|
|
|
|
|
|
#ifndef SWIG
|
|
|
|
|
// This type is neither copyable nor movable.
|
|
|
|
|
Assignment(const Assignment&) = delete;
|
|
|
|
|
Assignment& operator=(const Assignment&) = delete;
|
|
|
|
|
#endif
|
|
|
|
|
|
2015-04-16 15:49:51 +02:00
|
|
|
~Assignment() override;
|
2010-09-15 12:42:33 +00:00
|
|
|
|
|
|
|
|
void Clear();
|
|
|
|
|
bool Empty() const {
|
2013-10-10 15:23:20 +00:00
|
|
|
return int_var_container_.Empty() && interval_var_container_.Empty() &&
|
|
|
|
|
sequence_var_container_.Empty();
|
2010-09-15 12:42:33 +00:00
|
|
|
}
|
|
|
|
|
int Size() const {
|
2011-11-03 10:27:53 +00:00
|
|
|
return NumIntVars() + NumIntervalVars() + NumSequenceVars();
|
2011-04-26 08:59:55 +00:00
|
|
|
}
|
2013-10-10 15:23:20 +00:00
|
|
|
int NumIntVars() const { return int_var_container_.Size(); }
|
|
|
|
|
int NumIntervalVars() const { return interval_var_container_.Size(); }
|
|
|
|
|
int NumSequenceVars() const { return sequence_var_container_.Size(); }
|
2010-09-15 12:42:33 +00:00
|
|
|
void Store();
|
|
|
|
|
void Restore();
|
|
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Loads an assignment from a file; does not add variables to the
|
|
|
|
|
/// assignment (only the variables contained in the assignment are modified).
|
2020-10-29 14:25:39 +01:00
|
|
|
bool Load(const std::string& filename);
|
2011-07-26 17:04:47 +00:00
|
|
|
#if !defined(SWIG)
|
2020-10-29 14:25:39 +01:00
|
|
|
bool Load(File* file);
|
2020-10-22 23:36:58 +02:00
|
|
|
#endif /// #if !defined(SWIG)
|
2020-10-29 14:25:39 +01:00
|
|
|
void Load(const AssignmentProto& assignment_proto);
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Saves the assignment to a file.
|
2020-10-29 14:25:39 +01:00
|
|
|
bool Save(const std::string& filename) const;
|
2011-07-26 17:04:47 +00:00
|
|
|
#if !defined(SWIG)
|
2020-10-29 14:25:39 +01:00
|
|
|
bool Save(File* file) const;
|
2020-10-22 23:36:58 +02:00
|
|
|
#endif // #if !defined(SWIG)
|
2023-05-31 14:27:08 +02:00
|
|
|
void Save(AssignmentProto* assignment_proto) const;
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2023-05-24 15:32:06 +02:00
|
|
|
void AddObjective(IntVar* const v) { AddObjectives({v}); }
|
|
|
|
|
void AddObjectives(const std::vector<IntVar*>& vars) {
|
2022-09-05 18:30:09 +02:00
|
|
|
// Objective can only set once.
|
|
|
|
|
DCHECK(!HasObjective());
|
2023-05-24 15:32:06 +02:00
|
|
|
objective_elements_.reserve(vars.size());
|
|
|
|
|
for (IntVar* const var : vars) {
|
|
|
|
|
if (var != nullptr) {
|
|
|
|
|
objective_elements_.emplace_back(var);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
void ClearObjective() { objective_elements_.clear(); }
|
|
|
|
|
int NumObjectives() const { return objective_elements_.size(); }
|
|
|
|
|
IntVar* Objective() const { return ObjectiveFromIndex(0); }
|
|
|
|
|
IntVar* ObjectiveFromIndex(int index) const {
|
|
|
|
|
return HasObjectiveFromIndex(index) ? objective_elements_[index].Var()
|
|
|
|
|
: nullptr;
|
|
|
|
|
}
|
|
|
|
|
bool HasObjective() const { return !objective_elements_.empty(); }
|
|
|
|
|
bool HasObjectiveFromIndex(int index) const {
|
|
|
|
|
return index < objective_elements_.size();
|
|
|
|
|
}
|
|
|
|
|
int64_t ObjectiveMin() const { return ObjectiveMinFromIndex(0); }
|
|
|
|
|
int64_t ObjectiveMax() const { return ObjectiveMaxFromIndex(0); }
|
|
|
|
|
int64_t ObjectiveValue() const { return ObjectiveValueFromIndex(0); }
|
|
|
|
|
bool ObjectiveBound() const { return ObjectiveBoundFromIndex(0); }
|
|
|
|
|
void SetObjectiveMin(int64_t m) { SetObjectiveMinFromIndex(0, m); }
|
|
|
|
|
void SetObjectiveMax(int64_t m) { SetObjectiveMaxFromIndex(0, m); }
|
|
|
|
|
void SetObjectiveValue(int64_t value) {
|
|
|
|
|
SetObjectiveValueFromIndex(0, value);
|
|
|
|
|
}
|
|
|
|
|
void SetObjectiveRange(int64_t l, int64_t u) {
|
|
|
|
|
SetObjectiveRangeFromIndex(0, l, u);
|
|
|
|
|
}
|
|
|
|
|
int64_t ObjectiveMinFromIndex(int index) const {
|
|
|
|
|
return HasObjectiveFromIndex(index) ? objective_elements_[index].Min() : 0;
|
|
|
|
|
}
|
|
|
|
|
int64_t ObjectiveMaxFromIndex(int index) const {
|
|
|
|
|
return HasObjectiveFromIndex(index) ? objective_elements_[index].Max() : 0;
|
|
|
|
|
}
|
|
|
|
|
int64_t ObjectiveValueFromIndex(int index) const {
|
|
|
|
|
return HasObjectiveFromIndex(index) ? objective_elements_[index].Value()
|
|
|
|
|
: 0;
|
|
|
|
|
}
|
|
|
|
|
bool ObjectiveBoundFromIndex(int index) const {
|
|
|
|
|
return HasObjectiveFromIndex(index) ? objective_elements_[index].Bound()
|
|
|
|
|
: true;
|
|
|
|
|
}
|
|
|
|
|
void SetObjectiveMinFromIndex(int index, int64_t m) {
|
|
|
|
|
if (HasObjectiveFromIndex(index)) {
|
|
|
|
|
objective_elements_[index].SetMin(m);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
void SetObjectiveMaxFromIndex(int index, int64_t m) {
|
|
|
|
|
if (HasObjectiveFromIndex(index)) {
|
|
|
|
|
objective_elements_[index].SetMax(m);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
void SetObjectiveValueFromIndex(int index, int64_t value) {
|
|
|
|
|
if (HasObjectiveFromIndex(index)) {
|
|
|
|
|
objective_elements_[index].SetValue(value);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
void SetObjectiveRangeFromIndex(int index, int64_t l, int64_t u) {
|
|
|
|
|
if (HasObjectiveFromIndex(index)) {
|
|
|
|
|
objective_elements_[index].SetRange(l, u);
|
|
|
|
|
}
|
|
|
|
|
}
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2023-05-31 14:27:08 +02:00
|
|
|
IntVarElement* Add(IntVar* var);
|
2020-10-29 14:25:39 +01:00
|
|
|
void Add(const std::vector<IntVar*>& vars);
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Adds without checking if variable has been previously added.
|
2023-05-31 14:27:08 +02:00
|
|
|
IntVarElement* FastAdd(IntVar* var);
|
|
|
|
|
int64_t Min(const IntVar* var) const;
|
|
|
|
|
int64_t Max(const IntVar* var) const;
|
|
|
|
|
int64_t Value(const IntVar* var) const;
|
|
|
|
|
bool Bound(const IntVar* var) const;
|
|
|
|
|
void SetMin(const IntVar* var, int64_t m);
|
|
|
|
|
void SetMax(const IntVar* var, int64_t m);
|
|
|
|
|
void SetRange(const IntVar* var, int64_t l, int64_t u);
|
|
|
|
|
void SetValue(const IntVar* var, int64_t value);
|
|
|
|
|
|
|
|
|
|
IntervalVarElement* Add(IntervalVar* var);
|
2020-10-29 14:25:39 +01:00
|
|
|
void Add(const std::vector<IntervalVar*>& vars);
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Adds without checking if variable has been previously added.
|
2023-05-31 14:27:08 +02:00
|
|
|
IntervalVarElement* FastAdd(IntervalVar* var);
|
|
|
|
|
int64_t StartMin(const IntervalVar* var) const;
|
|
|
|
|
int64_t StartMax(const IntervalVar* var) const;
|
|
|
|
|
int64_t StartValue(const IntervalVar* var) const;
|
|
|
|
|
int64_t DurationMin(const IntervalVar* var) const;
|
|
|
|
|
int64_t DurationMax(const IntervalVar* var) const;
|
|
|
|
|
int64_t DurationValue(const IntervalVar* var) const;
|
|
|
|
|
int64_t EndMin(const IntervalVar* var) const;
|
|
|
|
|
int64_t EndMax(const IntervalVar* var) const;
|
|
|
|
|
int64_t EndValue(const IntervalVar* var) const;
|
|
|
|
|
int64_t PerformedMin(const IntervalVar* var) const;
|
|
|
|
|
int64_t PerformedMax(const IntervalVar* var) const;
|
|
|
|
|
int64_t PerformedValue(const IntervalVar* var) const;
|
|
|
|
|
void SetStartMin(const IntervalVar* var, int64_t m);
|
|
|
|
|
void SetStartMax(const IntervalVar* var, int64_t m);
|
|
|
|
|
void SetStartRange(const IntervalVar* var, int64_t mi, int64_t ma);
|
|
|
|
|
void SetStartValue(const IntervalVar* var, int64_t value);
|
|
|
|
|
void SetDurationMin(const IntervalVar* var, int64_t m);
|
|
|
|
|
void SetDurationMax(const IntervalVar* var, int64_t m);
|
|
|
|
|
void SetDurationRange(const IntervalVar* var, int64_t mi, int64_t ma);
|
|
|
|
|
void SetDurationValue(const IntervalVar* var, int64_t value);
|
|
|
|
|
void SetEndMin(const IntervalVar* var, int64_t m);
|
|
|
|
|
void SetEndMax(const IntervalVar* var, int64_t m);
|
|
|
|
|
void SetEndRange(const IntervalVar* var, int64_t mi, int64_t ma);
|
|
|
|
|
void SetEndValue(const IntervalVar* var, int64_t value);
|
|
|
|
|
void SetPerformedMin(const IntervalVar* var, int64_t m);
|
|
|
|
|
void SetPerformedMax(const IntervalVar* var, int64_t m);
|
|
|
|
|
void SetPerformedRange(const IntervalVar* var, int64_t mi, int64_t ma);
|
|
|
|
|
void SetPerformedValue(const IntervalVar* var, int64_t value);
|
|
|
|
|
|
|
|
|
|
SequenceVarElement* Add(SequenceVar* var);
|
2020-10-29 14:25:39 +01:00
|
|
|
void Add(const std::vector<SequenceVar*>& vars);
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Adds without checking if the variable had been previously added.
|
2023-05-31 14:27:08 +02:00
|
|
|
SequenceVarElement* FastAdd(SequenceVar* var);
|
|
|
|
|
const std::vector<int>& ForwardSequence(const SequenceVar* var) const;
|
|
|
|
|
const std::vector<int>& BackwardSequence(const SequenceVar* var) const;
|
|
|
|
|
const std::vector<int>& Unperformed(const SequenceVar* var) const;
|
|
|
|
|
void SetSequence(const SequenceVar* var,
|
2020-10-29 14:25:39 +01:00
|
|
|
const std::vector<int>& forward_sequence,
|
|
|
|
|
const std::vector<int>& backward_sequence,
|
|
|
|
|
const std::vector<int>& unperformed);
|
2023-05-31 14:27:08 +02:00
|
|
|
void SetForwardSequence(const SequenceVar* var,
|
2020-10-29 14:25:39 +01:00
|
|
|
const std::vector<int>& forward_sequence);
|
2023-05-31 14:27:08 +02:00
|
|
|
void SetBackwardSequence(const SequenceVar* var,
|
2020-10-29 14:25:39 +01:00
|
|
|
const std::vector<int>& backward_sequence);
|
2023-05-31 14:27:08 +02:00
|
|
|
void SetUnperformed(const SequenceVar* var,
|
2020-10-29 14:25:39 +01:00
|
|
|
const std::vector<int>& unperformed);
|
|
|
|
|
|
2023-05-31 14:27:08 +02:00
|
|
|
void Activate(const IntVar* var);
|
|
|
|
|
void Deactivate(const IntVar* var);
|
|
|
|
|
bool Activated(const IntVar* var) const;
|
2020-10-29 14:25:39 +01:00
|
|
|
|
2023-05-31 14:27:08 +02:00
|
|
|
void Activate(const IntervalVar* var);
|
|
|
|
|
void Deactivate(const IntervalVar* var);
|
|
|
|
|
bool Activated(const IntervalVar* var) const;
|
2020-10-29 14:25:39 +01:00
|
|
|
|
2023-05-31 14:27:08 +02:00
|
|
|
void Activate(const SequenceVar* var);
|
|
|
|
|
void Deactivate(const SequenceVar* var);
|
|
|
|
|
bool Activated(const SequenceVar* var) const;
|
2011-11-03 10:27:53 +00:00
|
|
|
|
2023-05-24 15:32:06 +02:00
|
|
|
void ActivateObjective() { ActivateObjectiveFromIndex(0); }
|
|
|
|
|
void DeactivateObjective() { DeactivateObjectiveFromIndex(0); }
|
|
|
|
|
bool ActivatedObjective() const { return ActivatedObjectiveFromIndex(0); }
|
|
|
|
|
void ActivateObjectiveFromIndex(int index) {
|
|
|
|
|
if (HasObjectiveFromIndex(index)) {
|
|
|
|
|
objective_elements_[index].Activate();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
void DeactivateObjectiveFromIndex(int index) {
|
|
|
|
|
if (HasObjectiveFromIndex(index)) {
|
|
|
|
|
objective_elements_[index].Deactivate();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
bool ActivatedObjectiveFromIndex(int index) const {
|
|
|
|
|
return HasObjectiveFromIndex(index) ? objective_elements_[index].Activated()
|
|
|
|
|
: true;
|
|
|
|
|
}
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2015-04-16 15:49:51 +02:00
|
|
|
std::string DebugString() const override;
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2019-03-15 17:17:02 +01:00
|
|
|
bool AreAllElementsBound() const {
|
|
|
|
|
return int_var_container_.AreAllElementsBound() &&
|
|
|
|
|
interval_var_container_.AreAllElementsBound() &&
|
|
|
|
|
sequence_var_container_.AreAllElementsBound();
|
|
|
|
|
}
|
|
|
|
|
|
2023-05-31 14:27:08 +02:00
|
|
|
bool Contains(const IntVar* var) const;
|
|
|
|
|
bool Contains(const IntervalVar* var) const;
|
|
|
|
|
bool Contains(const SequenceVar* var) const;
|
2023-05-24 15:32:06 +02:00
|
|
|
/// Copies the intersection of the two assignments to the current
|
|
|
|
|
/// assignment.
|
2020-10-29 14:25:39 +01:00
|
|
|
void CopyIntersection(const Assignment* assignment);
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Copies 'assignment' to the current assignment, clearing its previous
|
|
|
|
|
/// content.
|
2020-10-29 14:25:39 +01:00
|
|
|
void Copy(const Assignment* assignment);
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2018-10-31 16:18:18 +01:00
|
|
|
// TODO(user): Add element iterators to avoid exposing container class.
|
2020-10-29 14:25:39 +01:00
|
|
|
const IntContainer& IntVarContainer() const { return int_var_container_; }
|
|
|
|
|
IntContainer* MutableIntVarContainer() { return &int_var_container_; }
|
|
|
|
|
const IntervalContainer& IntervalVarContainer() const {
|
2010-09-15 12:42:33 +00:00
|
|
|
return interval_var_container_;
|
|
|
|
|
}
|
2020-10-29 14:25:39 +01:00
|
|
|
IntervalContainer* MutableIntervalVarContainer() {
|
2013-12-05 09:29:08 +00:00
|
|
|
return &interval_var_container_;
|
2010-09-15 12:42:33 +00:00
|
|
|
}
|
2020-10-29 14:25:39 +01:00
|
|
|
const SequenceContainer& SequenceVarContainer() const {
|
2011-11-03 10:27:53 +00:00
|
|
|
return sequence_var_container_;
|
|
|
|
|
}
|
2020-10-29 14:25:39 +01:00
|
|
|
SequenceContainer* MutableSequenceVarContainer() {
|
2013-12-05 09:29:08 +00:00
|
|
|
return &sequence_var_container_;
|
2011-11-03 10:27:53 +00:00
|
|
|
}
|
2020-10-29 14:25:39 +01:00
|
|
|
bool operator==(const Assignment& assignment) const {
|
2013-10-10 15:23:20 +00:00
|
|
|
return int_var_container_ == assignment.int_var_container_ &&
|
|
|
|
|
interval_var_container_ == assignment.interval_var_container_ &&
|
|
|
|
|
sequence_var_container_ == assignment.sequence_var_container_ &&
|
2023-05-24 15:32:06 +02:00
|
|
|
objective_elements_ == assignment.objective_elements_;
|
2011-11-03 10:27:53 +00:00
|
|
|
}
|
2020-10-29 14:25:39 +01:00
|
|
|
bool operator!=(const Assignment& assignment) const {
|
2011-11-03 10:27:53 +00:00
|
|
|
return !(*this == assignment);
|
|
|
|
|
}
|
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
|
|
|
IntContainer int_var_container_;
|
|
|
|
|
IntervalContainer interval_var_container_;
|
2011-11-03 10:27:53 +00:00
|
|
|
SequenceContainer sequence_var_container_;
|
2023-05-24 15:32:06 +02:00
|
|
|
std::vector<IntVarElement> objective_elements_;
|
2010-09-15 12:42:33 +00:00
|
|
|
};
|
|
|
|
|
|
2020-10-29 14:25:39 +01:00
|
|
|
std::ostream& operator<<(std::ostream& out,
|
|
|
|
|
const Assignment& assignment); /// NOLINT
|
2011-11-03 10:27:53 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Given a "source_assignment", clears the "target_assignment" and adds
|
|
|
|
|
/// all IntVars in "target_vars", with the values of the variables set according
|
|
|
|
|
/// to the corresponding values of "source_vars" in "source_assignment".
|
|
|
|
|
/// source_vars and target_vars must have the same number of elements.
|
|
|
|
|
/// The source and target assignments can belong to different Solvers.
|
2020-10-29 14:25:39 +01:00
|
|
|
void SetAssignmentFromAssignment(Assignment* target_assignment,
|
|
|
|
|
const std::vector<IntVar*>& target_vars,
|
|
|
|
|
const Assignment* source_assignment,
|
|
|
|
|
const std::vector<IntVar*>& source_vars);
|
2017-12-08 14:52:49 +01:00
|
|
|
|
2010-09-15 12:42:33 +00:00
|
|
|
class Pack : public Constraint {
|
2020-10-22 23:36:58 +02:00
|
|
|
public:
|
2023-05-31 14:27:08 +02:00
|
|
|
Pack(Solver* s, const std::vector<IntVar*>& vars, int number_of_bins);
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2015-04-16 15:49:51 +02:00
|
|
|
~Pack() override;
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Dimensions are additional constraints than can restrict what is
|
|
|
|
|
/// possible with the pack constraint. It can be used to set capacity
|
|
|
|
|
/// limits, to count objects per bin, to compute unassigned
|
|
|
|
|
/// penalties...
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// This dimension imposes that for all bins b, the weighted sum
|
|
|
|
|
/// (weights[i]) of all objects i assigned to 'b' is less or equal
|
|
|
|
|
/// 'bounds[b]'.
|
2016-11-23 22:08:43 +01:00
|
|
|
void AddWeightedSumLessOrEqualConstantDimension(
|
2021-04-01 12:13:35 +02:00
|
|
|
const std::vector<int64_t>& weights, const std::vector<int64_t>& bounds);
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// This dimension imposes that for all bins b, the weighted sum
|
|
|
|
|
/// (weights->Run(i)) of all objects i assigned to 'b' is less or
|
|
|
|
|
/// equal to 'bounds[b]'. Ownership of the callback is transferred to
|
|
|
|
|
/// the pack constraint.
|
2015-08-13 16:00:54 +02:00
|
|
|
void AddWeightedSumLessOrEqualConstantDimension(
|
2021-04-01 12:13:35 +02:00
|
|
|
Solver::IndexEvaluator1 weights, const std::vector<int64_t>& bounds);
|
2013-01-10 17:01:34 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// This dimension imposes that for all bins b, the weighted sum
|
|
|
|
|
/// (weights->Run(i, b) of all objects i assigned to 'b' is less or
|
|
|
|
|
/// equal to 'bounds[b]'. Ownership of the callback is transferred to
|
|
|
|
|
/// the pack constraint.
|
2013-01-10 17:01:34 +00:00
|
|
|
void AddWeightedSumLessOrEqualConstantDimension(
|
2021-04-01 12:13:35 +02:00
|
|
|
Solver::IndexEvaluator2 weights, const std::vector<int64_t>& bounds);
|
2013-01-10 17:01:34 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// This dimension imposes that for all bins b, the weighted sum
|
|
|
|
|
/// (weights[i]) of all objects i assigned to 'b' is equal to loads[b].
|
2021-04-01 12:13:35 +02:00
|
|
|
void AddWeightedSumEqualVarDimension(const std::vector<int64_t>& weights,
|
2020-10-29 14:25:39 +01:00
|
|
|
const std::vector<IntVar*>& loads);
|
2010-10-13 15:05:40 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// This dimension imposes that for all bins b, the weighted sum
|
|
|
|
|
/// (weights->Run(i, b)) of all objects i assigned to 'b' is equal to
|
|
|
|
|
/// loads[b].
|
2015-08-13 16:00:54 +02:00
|
|
|
void AddWeightedSumEqualVarDimension(Solver::IndexEvaluator2 weights,
|
2020-10-29 14:25:39 +01:00
|
|
|
const std::vector<IntVar*>& loads);
|
2013-01-10 17:01:34 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// This dimension imposes:
|
|
|
|
|
/// forall b in bins,
|
|
|
|
|
/// sum (i in items: usage[i] * is_assigned(i, b)) <= capacity[b]
|
|
|
|
|
/// where is_assigned(i, b) is true if and only if item i is assigned
|
|
|
|
|
/// to the bin b.
|
|
|
|
|
///
|
|
|
|
|
/// This can be used to model shapes of items by linking variables of
|
|
|
|
|
/// the same item on parallel dimensions with an allowed assignment
|
|
|
|
|
/// constraint.
|
2011-05-11 16:07:52 +00:00
|
|
|
void AddSumVariableWeightsLessOrEqualConstantDimension(
|
2021-04-01 12:13:35 +02:00
|
|
|
const std::vector<IntVar*>& usage, const std::vector<int64_t>& capacity);
|
2011-05-11 16:07:52 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// This dimension enforces that cost_var == sum of weights[i] for
|
|
|
|
|
/// all objects 'i' assigned to a bin.
|
2021-04-01 12:13:35 +02:00
|
|
|
void AddWeightedSumOfAssignedDimension(const std::vector<int64_t>& weights,
|
2023-05-31 14:27:08 +02:00
|
|
|
IntVar* cost_var);
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// This dimension links 'count_var' to the actual number of bins used in the
|
|
|
|
|
/// pack.
|
2023-05-31 14:27:08 +02:00
|
|
|
void AddCountUsedBinDimension(IntVar* count_var);
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// This dimension links 'count_var' to the actual number of items
|
|
|
|
|
/// assigned to a bin in the pack.
|
2023-05-31 14:27:08 +02:00
|
|
|
void AddCountAssignedItemsDimension(IntVar* count_var);
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2015-04-16 15:49:51 +02:00
|
|
|
void Post() override;
|
2010-09-15 12:42:33 +00:00
|
|
|
void ClearAll();
|
|
|
|
|
void PropagateDelayed();
|
2015-04-16 15:49:51 +02:00
|
|
|
void InitialPropagate() override;
|
2010-09-15 12:42:33 +00:00
|
|
|
void Propagate();
|
|
|
|
|
void OneDomain(int var_index);
|
2015-04-16 15:49:51 +02:00
|
|
|
std::string DebugString() const override;
|
2013-01-10 17:01:34 +00:00
|
|
|
bool IsUndecided(int var_index, int bin_index) const;
|
|
|
|
|
void SetImpossible(int var_index, int bin_index);
|
|
|
|
|
void Assign(int var_index, int bin_index);
|
|
|
|
|
bool IsAssignedStatusKnown(int var_index) const;
|
|
|
|
|
bool IsPossible(int var_index, int bin_index) const;
|
2020-10-29 14:25:39 +01:00
|
|
|
IntVar* AssignVar(int var_index, int bin_index) const;
|
2013-01-10 17:01:34 +00:00
|
|
|
void SetAssigned(int var_index);
|
|
|
|
|
void SetUnassigned(int var_index);
|
|
|
|
|
void RemoveAllPossibleFromBin(int bin_index);
|
|
|
|
|
void AssignAllPossibleToBin(int bin_index);
|
|
|
|
|
void AssignFirstPossibleToBin(int bin_index);
|
2010-09-15 12:42:33 +00:00
|
|
|
void AssignAllRemainingItems();
|
|
|
|
|
void UnassignAllRemainingItems();
|
2023-05-31 14:27:08 +02:00
|
|
|
void Accept(ModelVisitor* visitor) const override;
|
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
|
|
|
bool IsInProcess() const;
|
2020-10-29 14:25:39 +01:00
|
|
|
const std::vector<IntVar*> vars_;
|
2013-01-10 17:01:34 +00:00
|
|
|
const int bins_;
|
2020-10-29 14:25:39 +01:00
|
|
|
std::vector<Dimension*> dims_;
|
2013-12-10 16:02:46 +00:00
|
|
|
std::unique_ptr<RevBitMatrix> unprocessed_;
|
2020-11-01 11:47:28 +01:00
|
|
|
std::vector<std::vector<int>> forced_;
|
|
|
|
|
std::vector<std::vector<int>> removed_;
|
2020-10-29 14:25:39 +01:00
|
|
|
std::vector<IntVarIterator*> holes_;
|
2021-04-01 12:13:35 +02:00
|
|
|
uint64_t stamp_;
|
2020-10-29 14:25:39 +01:00
|
|
|
Demon* demon_;
|
2020-11-01 11:47:28 +01:00
|
|
|
std::vector<std::pair<int, int>> to_set_;
|
|
|
|
|
std::vector<std::pair<int, int>> to_unset_;
|
2010-09-15 12:42:33 +00:00
|
|
|
bool in_process_;
|
|
|
|
|
};
|
|
|
|
|
|
2012-07-18 19:54:04 +00:00
|
|
|
class DisjunctiveConstraint : public Constraint {
|
2020-10-22 23:36:58 +02:00
|
|
|
public:
|
2023-05-31 14:27:08 +02:00
|
|
|
DisjunctiveConstraint(Solver* s, const std::vector<IntervalVar*>& intervals,
|
2020-10-29 14:25:39 +01:00
|
|
|
const std::string& name);
|
2023-09-25 18:06:35 +02:00
|
|
|
|
|
|
|
|
#ifndef SWIG
|
|
|
|
|
// This type is neither copyable nor movable.
|
|
|
|
|
DisjunctiveConstraint(const DisjunctiveConstraint&) = delete;
|
|
|
|
|
DisjunctiveConstraint& operator=(const DisjunctiveConstraint&) = delete;
|
|
|
|
|
#endif
|
|
|
|
|
|
2015-04-16 15:49:51 +02:00
|
|
|
~DisjunctiveConstraint() override;
|
2012-07-18 19:54:04 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Creates a sequence variable from the constraint.
|
2020-10-29 14:25:39 +01:00
|
|
|
virtual SequenceVar* MakeSequenceVar() = 0;
|
2012-07-18 23:43:45 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// Add a transition time between intervals. It forces the distance between
|
|
|
|
|
/// the end of interval a and start of interval b that follows it to be at
|
|
|
|
|
/// least transition_time(a, b). This function must always return
|
|
|
|
|
/// a positive or null value.
|
2017-12-08 14:52:49 +01:00
|
|
|
void SetTransitionTime(Solver::IndexEvaluator2 transition_time);
|
2013-10-10 15:23:20 +00:00
|
|
|
|
2021-04-01 12:13:35 +02:00
|
|
|
int64_t TransitionTime(int before_index, int after_index) {
|
2015-08-13 16:00:54 +02:00
|
|
|
DCHECK(transition_time_);
|
|
|
|
|
return transition_time_(before_index, after_index);
|
2014-05-26 01:25:01 +00:00
|
|
|
}
|
|
|
|
|
|
2014-02-14 11:50:48 +00:00
|
|
|
#if !defined(SWIG)
|
2020-10-29 14:25:39 +01:00
|
|
|
virtual const std::vector<IntVar*>& nexts() const = 0;
|
|
|
|
|
virtual const std::vector<IntVar*>& actives() const = 0;
|
|
|
|
|
virtual const std::vector<IntVar*>& time_cumuls() const = 0;
|
|
|
|
|
virtual const std::vector<IntVar*>& time_slacks() const = 0;
|
2020-10-22 23:36:58 +02:00
|
|
|
#endif // !defined(SWIG)
|
2020-10-21 00:21:54 +02:00
|
|
|
|
2020-10-22 23:36:58 +02:00
|
|
|
protected:
|
2020-10-29 14:25:39 +01:00
|
|
|
const std::vector<IntervalVar*> intervals_;
|
2015-08-13 16:00:54 +02:00
|
|
|
Solver::IndexEvaluator2 transition_time_;
|
2012-07-18 19:54:04 +00:00
|
|
|
};
|
|
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// This class is used to manage a pool of solutions. It can transform
|
|
|
|
|
/// a single point local search into a multipoint local search.
|
2010-09-15 12:42:33 +00:00
|
|
|
class SolutionPool : public BaseObject {
|
2020-10-22 23:36:58 +02:00
|
|
|
public:
|
2010-09-15 12:42:33 +00:00
|
|
|
SolutionPool() {}
|
2015-04-16 15:49:51 +02:00
|
|
|
~SolutionPool() override {}
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// This method is called to initialize the solution pool with the assignment
|
|
|
|
|
/// from the local search.
|
2023-05-31 14:27:08 +02:00
|
|
|
virtual void Initialize(Assignment* assignment) = 0;
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// This method is called when a new solution has been accepted by the local
|
|
|
|
|
/// search.
|
2023-05-31 14:27:08 +02:00
|
|
|
virtual void RegisterNewSolution(Assignment* assignment) = 0;
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// This method is called when the local search starts a new neighborhood to
|
|
|
|
|
/// initialize the default assignment.
|
2023-05-31 14:27:08 +02:00
|
|
|
virtual void GetNextSolution(Assignment* assignment) = 0;
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2019-07-05 00:25:55 +02:00
|
|
|
/// This method checks if the local solution needs to be updated with
|
|
|
|
|
/// an external one.
|
2023-05-31 14:27:08 +02:00
|
|
|
virtual bool SyncNeeded(Assignment* local_assignment) = 0;
|
2010-09-15 12:42:33 +00:00
|
|
|
};
|
2020-10-22 23:36:58 +02:00
|
|
|
} // namespace operations_research
|
2019-07-05 00:25:55 +02:00
|
|
|
|
2025-11-05 11:34:49 +01:00
|
|
|
#endif // ORTOOLS_CONSTRAINT_SOLVER_CONSTRAINT_SOLVER_H_
|