Files
ortools-clone/ortools/constraint_solver/interval.cc

2424 lines
79 KiB
C++
Raw Normal View History

2018-11-10 18:00:53 +01:00
// Copyright 2010-2018 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.
2011-09-21 15:16:48 +00:00
#include <string>
#include <vector>
dotnet: Remove reference to dotnet release command - Currently not implemented... Add abseil patch - Add patches/absl-config.cmake Makefile: Add abseil-cpp on unix - Force abseil-cpp SHA1 to 45221cc note: Just before the PR #136 which break all CMake Makefile: Add abseil-cpp on windows - Force abseil-cpp SHA1 to 45221cc note: Just before the PR #136 which break all CMake CMake: Add abseil-cpp - Force abseil-cpp SHA1 to 45221cc note: Just before the PR #136 which break all CMake port to absl: C++ Part - Fix warning with the use of ABSL_MUST_USE_RESULT > The macro must appear as the very first part of a function declaration or definition: ... Note: past advice was to place the macro after the argument list. src: dependencies/sources/abseil-cpp-master/absl/base/attributes.h:418 - Rename enum after windows clash - Remove non compact table constraints - Change index type from int64 to int in routing library - Fix file_nonport compilation on windows - Fix another naming conflict with windows (NO_ERROR is a macro) - Cleanup hash containers; work on sat internals - Add optional_boolean sub-proto Sync cpp examples with internal code - reenable issue173 after reducing number of loops port to absl: Python Part - Add back cp_model.INT32_MIN|MAX for examples Update Python examples - Add random_tsp.py - Run words_square example - Run magic_square in python tests port to absl: Java Part - Fix compilation of the new routing parameters in java - Protect some code from SWIG parsing Update Java Examples port to absl: .Net Part Update .Net examples work on sat internals; Add C++ CP-SAT CpModelBuilder API; update sample code and recipes to use the new API; sync with internal code Remove VS 2015 in Appveyor-CI - abseil-cpp does not support VS 2015... improve tables upgrade C++ sat examples to use the new API; work on sat internals update license dates rewrite jobshop_ft06_distance.py to use the CP-SAT solver rename last example revert last commit more work on SAT internals fix
2018-10-31 16:18:18 +01:00
#include "absl/strings/str_cat.h"
#include "absl/strings/str_format.h"
#include "ortools/base/integral_types.h"
#include "ortools/base/logging.h"
#include "ortools/base/macros.h"
#include "ortools/constraint_solver/constraint_solver.h"
#include "ortools/constraint_solver/constraint_solveri.h"
#include "ortools/util/saturated_arithmetic.h"
2010-09-15 12:42:33 +00:00
#if defined(_MSC_VER)
#pragma warning(disable : 4351 4355 4804 4805)
#endif
namespace operations_research {
// Generic code for start/end/duration expressions.
// This is not done in a superclass as this is not compatible with the current
// class hierarchy.
// ----- Expression builders ------
2020-10-29 14:25:39 +01:00
IntExpr* BuildStartExpr(IntervalVar* var);
IntExpr* BuildDurationExpr(IntervalVar* var);
IntExpr* BuildEndExpr(IntervalVar* var);
IntExpr* BuildSafeStartExpr(IntervalVar* var, int64 unperformed_value);
IntExpr* BuildSafeDurationExpr(IntervalVar* var, int64 unperformed_value);
IntExpr* BuildSafeEndExpr(IntervalVar* var, int64 unperformed_value);
void LinkVarExpr(Solver* const s, IntExpr* const expr, IntVar* const var);
2010-09-15 12:42:33 +00:00
2010-11-30 09:28:02 +00:00
// It's good to have the two extreme values being symmetrical around zero: it
// makes mirroring easier.
const int64 IntervalVar::kMaxValidValue = kint64max >> 2;
2010-11-30 09:28:02 +00:00
const int64 IntervalVar::kMinValidValue = -kMaxValidValue;
namespace {
2020-10-22 23:36:58 +02:00
enum IntervalField { START, DURATION, END };
2013-06-11 14:49:19 +00:00
2020-10-29 14:25:39 +01:00
IntervalVar* NullInterval() { return nullptr; }
// ----- MirrorIntervalVar -----
class MirrorIntervalVar : public IntervalVar {
2020-10-22 23:36:58 +02:00
public:
2020-10-29 14:25:39 +01:00
MirrorIntervalVar(Solver* const s, IntervalVar* const t)
: IntervalVar(s, "Mirror<" + t->name() + ">"), t_(t) {}
~MirrorIntervalVar() override {}
// These methods query, set and watch the start position of the
// interval var.
int64 StartMin() const override { return -t_->EndMax(); }
int64 StartMax() const override { return -t_->EndMin(); }
void SetStartMin(int64 m) override { t_->SetEndMax(-m); }
void SetStartMax(int64 m) override { t_->SetEndMin(-m); }
void SetStartRange(int64 mi, int64 ma) override { t_->SetEndRange(-ma, -mi); }
int64 OldStartMin() const override { return -t_->OldEndMax(); }
int64 OldStartMax() const override { return -t_->OldEndMin(); }
2020-10-29 14:25:39 +01:00
void WhenStartRange(Demon* const d) override { t_->WhenEndRange(d); }
void WhenStartBound(Demon* const d) override { t_->WhenEndBound(d); }
// These methods query, set and watch the duration of the interval var.
int64 DurationMin() const override { return t_->DurationMin(); }
int64 DurationMax() const override { return t_->DurationMax(); }
void SetDurationMin(int64 m) override { t_->SetDurationMin(m); }
void SetDurationMax(int64 m) override { t_->SetDurationMax(m); }
void SetDurationRange(int64 mi, int64 ma) override {
t_->SetDurationRange(mi, ma);
}
int64 OldDurationMin() const override { return t_->OldDurationMin(); }
int64 OldDurationMax() const override { return t_->OldDurationMax(); }
2020-10-29 14:25:39 +01:00
void WhenDurationRange(Demon* const d) override { t_->WhenDurationRange(d); }
void WhenDurationBound(Demon* const d) override { t_->WhenDurationBound(d); }
// These methods query, set and watch the end position of the interval var.
int64 EndMin() const override { return -t_->StartMax(); }
int64 EndMax() const override { return -t_->StartMin(); }
void SetEndMin(int64 m) override { t_->SetStartMax(-m); }
void SetEndMax(int64 m) override { t_->SetStartMin(-m); }
void SetEndRange(int64 mi, int64 ma) override { t_->SetStartRange(-ma, -mi); }
int64 OldEndMin() const override { return -t_->OldStartMax(); }
int64 OldEndMax() const override { return -t_->OldStartMin(); }
2020-10-29 14:25:39 +01:00
void WhenEndRange(Demon* const d) override { t_->WhenStartRange(d); }
void WhenEndBound(Demon* const d) override { t_->WhenStartBound(d); }
// These methods query, set and watches the performed status of the
// interval var.
bool MustBePerformed() const override { return t_->MustBePerformed(); }
bool MayBePerformed() const override { return t_->MayBePerformed(); }
void SetPerformed(bool val) override { t_->SetPerformed(val); }
bool WasPerformedBound() const override { return t_->WasPerformedBound(); }
2020-10-29 14:25:39 +01:00
void WhenPerformedBound(Demon* const d) override {
t_->WhenPerformedBound(d);
}
2020-10-29 14:25:39 +01:00
void Accept(ModelVisitor* const visitor) const override {
2013-06-11 14:49:19 +00:00
visitor->VisitIntervalVariable(this, ModelVisitor::kMirrorOperation, 0, t_);
2011-07-11 20:13:14 +00:00
}
std::string DebugString() const override {
dotnet: Remove reference to dotnet release command - Currently not implemented... Add abseil patch - Add patches/absl-config.cmake Makefile: Add abseil-cpp on unix - Force abseil-cpp SHA1 to 45221cc note: Just before the PR #136 which break all CMake Makefile: Add abseil-cpp on windows - Force abseil-cpp SHA1 to 45221cc note: Just before the PR #136 which break all CMake CMake: Add abseil-cpp - Force abseil-cpp SHA1 to 45221cc note: Just before the PR #136 which break all CMake port to absl: C++ Part - Fix warning with the use of ABSL_MUST_USE_RESULT > The macro must appear as the very first part of a function declaration or definition: ... Note: past advice was to place the macro after the argument list. src: dependencies/sources/abseil-cpp-master/absl/base/attributes.h:418 - Rename enum after windows clash - Remove non compact table constraints - Change index type from int64 to int in routing library - Fix file_nonport compilation on windows - Fix another naming conflict with windows (NO_ERROR is a macro) - Cleanup hash containers; work on sat internals - Add optional_boolean sub-proto Sync cpp examples with internal code - reenable issue173 after reducing number of loops port to absl: Python Part - Add back cp_model.INT32_MIN|MAX for examples Update Python examples - Add random_tsp.py - Run words_square example - Run magic_square in python tests port to absl: Java Part - Fix compilation of the new routing parameters in java - Protect some code from SWIG parsing Update Java Examples port to absl: .Net Part Update .Net examples work on sat internals; Add C++ CP-SAT CpModelBuilder API; update sample code and recipes to use the new API; sync with internal code Remove VS 2015 in Appveyor-CI - abseil-cpp does not support VS 2015... improve tables upgrade C++ sat examples to use the new API; work on sat internals update license dates rewrite jobshop_ft06_distance.py to use the CP-SAT solver rename last example revert last commit more work on SAT internals fix
2018-10-31 16:18:18 +01:00
return absl::StrFormat("MirrorInterval(%s)", t_->DebugString());
}
2020-10-29 14:25:39 +01:00
IntExpr* StartExpr() override {
return solver()->MakeOpposite(t_->EndExpr());
}
2020-10-29 14:25:39 +01:00
IntExpr* DurationExpr() override { return t_->DurationExpr(); }
IntExpr* EndExpr() override {
return solver()->MakeOpposite(t_->StartExpr());
}
2020-10-29 14:25:39 +01:00
IntExpr* PerformedExpr() override { return t_->PerformedExpr(); }
// 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.
2020-10-29 14:25:39 +01:00
IntExpr* SafeStartExpr(int64 unperformed_value) override {
return solver()->MakeOpposite(t_->SafeEndExpr(-unperformed_value));
}
2020-10-29 14:25:39 +01:00
IntExpr* SafeDurationExpr(int64 unperformed_value) override {
return t_->SafeDurationExpr(unperformed_value);
}
2020-10-29 14:25:39 +01:00
IntExpr* SafeEndExpr(int64 unperformed_value) override {
return solver()->MakeOpposite(t_->SafeStartExpr(-unperformed_value));
}
2020-10-22 23:36:58 +02:00
private:
2020-10-29 14:25:39 +01:00
IntervalVar* const t_;
DISALLOW_COPY_AND_ASSIGN(MirrorIntervalVar);
};
// An IntervalVar that passes all function calls to an underlying interval
// variable as long as it is not prohibited, and that interprets prohibited
// intervals as intervals of duration 0 that must be executed between
// [kMinValidValue and kMaxValidValue].
//
// Such interval variables have a very similar behavior to others.
// Invariants such as StartMin() + DurationMin() <= EndMin() that are maintained
// for traditional interval variables are maintained for instances of
// AlwaysPerformedIntervalVarWrapper. However, there is no monotonicity of the
// values returned by the start/end getters. For example, during a given
// propagation, three successive calls to StartMin could return,
// in this order, 1, 2, and kMinValidValue.
//
2012-08-31 20:55:03 +00:00
// This class exists so that we can easily implement the
// IntervalVarRelaxedMax and IntervalVarRelaxedMin classes below.
class AlwaysPerformedIntervalVarWrapper : public IntervalVar {
2020-10-22 23:36:58 +02:00
public:
2020-10-29 14:25:39 +01:00
explicit AlwaysPerformedIntervalVarWrapper(IntervalVar* const t)
: IntervalVar(t->solver(),
dotnet: Remove reference to dotnet release command - Currently not implemented... Add abseil patch - Add patches/absl-config.cmake Makefile: Add abseil-cpp on unix - Force abseil-cpp SHA1 to 45221cc note: Just before the PR #136 which break all CMake Makefile: Add abseil-cpp on windows - Force abseil-cpp SHA1 to 45221cc note: Just before the PR #136 which break all CMake CMake: Add abseil-cpp - Force abseil-cpp SHA1 to 45221cc note: Just before the PR #136 which break all CMake port to absl: C++ Part - Fix warning with the use of ABSL_MUST_USE_RESULT > The macro must appear as the very first part of a function declaration or definition: ... Note: past advice was to place the macro after the argument list. src: dependencies/sources/abseil-cpp-master/absl/base/attributes.h:418 - Rename enum after windows clash - Remove non compact table constraints - Change index type from int64 to int in routing library - Fix file_nonport compilation on windows - Fix another naming conflict with windows (NO_ERROR is a macro) - Cleanup hash containers; work on sat internals - Add optional_boolean sub-proto Sync cpp examples with internal code - reenable issue173 after reducing number of loops port to absl: Python Part - Add back cp_model.INT32_MIN|MAX for examples Update Python examples - Add random_tsp.py - Run words_square example - Run magic_square in python tests port to absl: Java Part - Fix compilation of the new routing parameters in java - Protect some code from SWIG parsing Update Java Examples port to absl: .Net Part Update .Net examples work on sat internals; Add C++ CP-SAT CpModelBuilder API; update sample code and recipes to use the new API; sync with internal code Remove VS 2015 in Appveyor-CI - abseil-cpp does not support VS 2015... improve tables upgrade C++ sat examples to use the new API; work on sat internals update license dates rewrite jobshop_ft06_distance.py to use the CP-SAT solver rename last example revert last commit more work on SAT internals fix
2018-10-31 16:18:18 +01:00
absl::StrFormat("AlwaysPerformed<%s>", t->name())),
2020-10-22 23:36:58 +02:00
t_(t),
start_expr_(nullptr),
duration_expr_(nullptr),
end_expr_(nullptr) {}
~AlwaysPerformedIntervalVarWrapper() override {}
int64 StartMin() const override {
2013-06-11 14:49:19 +00:00
return MayUnderlyingBePerformed() ? t_->StartMin() : kMinValidValue;
}
int64 StartMax() const override {
return MayUnderlyingBePerformed() ? t_->StartMax() : kMaxValidValue;
}
void SetStartMin(int64 m) override { t_->SetStartMin(m); }
void SetStartMax(int64 m) override { t_->SetStartMax(m); }
void SetStartRange(int64 mi, int64 ma) override { t_->SetStartRange(mi, ma); }
int64 OldStartMin() const override {
2013-06-11 14:49:19 +00:00
return MayUnderlyingBePerformed() ? t_->OldStartMin() : kMinValidValue;
}
int64 OldStartMax() const override {
2013-06-11 14:49:19 +00:00
return MayUnderlyingBePerformed() ? t_->OldStartMax() : kMaxValidValue;
}
2020-10-29 14:25:39 +01:00
void WhenStartRange(Demon* const d) override { t_->WhenStartRange(d); }
void WhenStartBound(Demon* const d) override { t_->WhenStartBound(d); }
int64 DurationMin() const override {
return MayUnderlyingBePerformed() ? t_->DurationMin() : 0LL;
}
int64 DurationMax() const override {
return MayUnderlyingBePerformed() ? t_->DurationMax() : 0LL;
}
void SetDurationMin(int64 m) override { t_->SetDurationMin(m); }
void SetDurationMax(int64 m) override { t_->SetDurationMax(m); }
void SetDurationRange(int64 mi, int64 ma) override {
t_->SetDurationRange(mi, ma);
}
int64 OldDurationMin() const override {
2013-06-11 14:49:19 +00:00
return MayUnderlyingBePerformed() ? t_->OldDurationMin() : 0LL;
}
int64 OldDurationMax() const override {
2013-06-11 14:49:19 +00:00
return MayUnderlyingBePerformed() ? t_->OldDurationMax() : 0LL;
}
2020-10-29 14:25:39 +01:00
void WhenDurationRange(Demon* const d) override { t_->WhenDurationRange(d); }
void WhenDurationBound(Demon* const d) override { t_->WhenDurationBound(d); }
int64 EndMin() const override {
return MayUnderlyingBePerformed() ? t_->EndMin() : kMinValidValue;
}
int64 EndMax() const override {
return MayUnderlyingBePerformed() ? t_->EndMax() : kMaxValidValue;
}
void SetEndMin(int64 m) override { t_->SetEndMin(m); }
void SetEndMax(int64 m) override { t_->SetEndMax(m); }
void SetEndRange(int64 mi, int64 ma) override { t_->SetEndRange(mi, ma); }
int64 OldEndMin() const override {
2013-06-11 14:49:19 +00:00
return MayUnderlyingBePerformed() ? t_->OldEndMin() : kMinValidValue;
}
int64 OldEndMax() const override {
2013-06-11 14:49:19 +00:00
return MayUnderlyingBePerformed() ? t_->OldEndMax() : kMaxValidValue;
}
2020-10-29 14:25:39 +01:00
void WhenEndRange(Demon* const d) override { t_->WhenEndRange(d); }
void WhenEndBound(Demon* const d) override { t_->WhenEndBound(d); }
bool MustBePerformed() const override { return true; }
bool MayBePerformed() const override { return true; }
void SetPerformed(bool val) override {
// An AlwaysPerformedIntervalVarWrapper interval variable is always
// performed. So setting it to be performed does not change anything,
// and setting it not to be performed is inconsistent and should cause
// a failure.
if (!val) {
solver()->Fail();
}
}
bool WasPerformedBound() const override { return true; }
2020-10-29 14:25:39 +01:00
void WhenPerformedBound(Demon* const d) override {
t_->WhenPerformedBound(d);
}
2020-10-29 14:25:39 +01:00
IntExpr* StartExpr() override {
if (start_expr_ == nullptr) {
2020-10-29 14:25:39 +01:00
solver()->SaveValue(reinterpret_cast<void**>(&start_expr_));
start_expr_ = BuildStartExpr(this);
}
return start_expr_;
}
2020-10-29 14:25:39 +01:00
IntExpr* DurationExpr() override {
if (duration_expr_ == nullptr) {
2020-10-29 14:25:39 +01:00
solver()->SaveValue(reinterpret_cast<void**>(&duration_expr_));
duration_expr_ = BuildDurationExpr(this);
}
return duration_expr_;
}
2020-10-29 14:25:39 +01:00
IntExpr* EndExpr() override {
if (end_expr_ == nullptr) {
2020-10-29 14:25:39 +01:00
solver()->SaveValue(reinterpret_cast<void**>(&end_expr_));
end_expr_ = BuildEndExpr(this);
}
return end_expr_;
}
2020-10-29 14:25:39 +01:00
IntExpr* PerformedExpr() override { return solver()->MakeIntConst(1); }
IntExpr* SafeStartExpr(int64 unperformed_value) override {
return StartExpr();
}
2020-10-29 14:25:39 +01:00
IntExpr* SafeDurationExpr(int64 unperformed_value) override {
return DurationExpr();
}
2020-10-29 14:25:39 +01:00
IntExpr* SafeEndExpr(int64 unperformed_value) override { return EndExpr(); }
2011-07-11 20:13:14 +00:00
2020-10-22 23:36:58 +02:00
protected:
2020-10-29 14:25:39 +01:00
IntervalVar* const underlying() const { return t_; }
bool MayUnderlyingBePerformed() const {
return underlying()->MayBePerformed();
}
2011-07-11 20:13:14 +00:00
2020-10-22 23:36:58 +02:00
private:
2020-10-29 14:25:39 +01:00
IntervalVar* const t_;
IntExpr* start_expr_;
IntExpr* duration_expr_;
IntExpr* end_expr_;
DISALLOW_COPY_AND_ASSIGN(AlwaysPerformedIntervalVarWrapper);
};
// An interval variable that wraps around an underlying one, relaxing the max
// start and end. Relaxing means making unbounded when optional.
//
// More precisely, such an interval variable behaves as follows:
// * When the underlying must be performed, this interval variable behaves
// exactly as the underlying;
// * When the underlying may or may not be performed, this interval variable
// behaves like the underlying, except that it is unbounded on the max side;
// * When the underlying cannot be performed, this interval variable is of
// duration 0 and must be performed in an interval unbounded on both sides.
//
// This class is very useful to implement propagators that may only modify
// the start min or end min.
class IntervalVarRelaxedMax : public AlwaysPerformedIntervalVarWrapper {
2020-10-22 23:36:58 +02:00
public:
2020-10-29 14:25:39 +01:00
explicit IntervalVarRelaxedMax(IntervalVar* const t)
2013-06-11 14:49:19 +00:00
: AlwaysPerformedIntervalVarWrapper(t) {}
~IntervalVarRelaxedMax() override {}
int64 StartMax() const override {
// It matters to use DurationMin() and not underlying()->DurationMin() here.
2013-06-11 14:49:19 +00:00
return underlying()->MustBePerformed() ? underlying()->StartMax()
: (kMaxValidValue - DurationMin());
}
void SetStartMax(int64 m) override {
LOG(FATAL)
<< "Calling SetStartMax on a IntervalVarRelaxedMax is not supported, "
<< "as it seems there is no legitimate use case.";
}
int64 EndMax() const override {
2013-06-11 14:49:19 +00:00
return underlying()->MustBePerformed() ? underlying()->EndMax()
: kMaxValidValue;
}
void SetEndMax(int64 m) override {
LOG(FATAL)
<< "Calling SetEndMax on a IntervalVarRelaxedMax is not supported, "
<< "as it seems there is no legitimate use case.";
}
2011-07-11 20:13:14 +00:00
2020-10-29 14:25:39 +01:00
void Accept(ModelVisitor* const visitor) const override {
2013-06-11 14:49:19 +00:00
visitor->VisitIntervalVariable(this, ModelVisitor::kRelaxedMaxOperation, 0,
underlying());
2011-07-11 20:13:14 +00:00
}
std::string DebugString() const override {
dotnet: Remove reference to dotnet release command - Currently not implemented... Add abseil patch - Add patches/absl-config.cmake Makefile: Add abseil-cpp on unix - Force abseil-cpp SHA1 to 45221cc note: Just before the PR #136 which break all CMake Makefile: Add abseil-cpp on windows - Force abseil-cpp SHA1 to 45221cc note: Just before the PR #136 which break all CMake CMake: Add abseil-cpp - Force abseil-cpp SHA1 to 45221cc note: Just before the PR #136 which break all CMake port to absl: C++ Part - Fix warning with the use of ABSL_MUST_USE_RESULT > The macro must appear as the very first part of a function declaration or definition: ... Note: past advice was to place the macro after the argument list. src: dependencies/sources/abseil-cpp-master/absl/base/attributes.h:418 - Rename enum after windows clash - Remove non compact table constraints - Change index type from int64 to int in routing library - Fix file_nonport compilation on windows - Fix another naming conflict with windows (NO_ERROR is a macro) - Cleanup hash containers; work on sat internals - Add optional_boolean sub-proto Sync cpp examples with internal code - reenable issue173 after reducing number of loops port to absl: Python Part - Add back cp_model.INT32_MIN|MAX for examples Update Python examples - Add random_tsp.py - Run words_square example - Run magic_square in python tests port to absl: Java Part - Fix compilation of the new routing parameters in java - Protect some code from SWIG parsing Update Java Examples port to absl: .Net Part Update .Net examples work on sat internals; Add C++ CP-SAT CpModelBuilder API; update sample code and recipes to use the new API; sync with internal code Remove VS 2015 in Appveyor-CI - abseil-cpp does not support VS 2015... improve tables upgrade C++ sat examples to use the new API; work on sat internals update license dates rewrite jobshop_ft06_distance.py to use the CP-SAT solver rename last example revert last commit more work on SAT internals fix
2018-10-31 16:18:18 +01:00
return absl::StrFormat("IntervalVarRelaxedMax(%s)",
underlying()->DebugString());
}
};
2011-07-11 20:13:14 +00:00
// An interval variable that wraps around an underlying one, relaxing the min
// start and end. Relaxing means making unbounded when optional.
//
// More precisely, such an interval variable behaves as follows:
// * When the underlying must be performed, this interval variable behaves
// exactly as the underlying;
// * When the underlying may or may not be performed, this interval variable
// behaves like the underlying, except that it is unbounded on the min side;
// * When the underlying cannot be performed, this interval variable is of
// duration 0 and must be performed in an interval unbounded on both sides.
//
// This class is very useful to implement propagators that may only modify
// the start max or end max.
class IntervalVarRelaxedMin : public AlwaysPerformedIntervalVarWrapper {
2020-10-22 23:36:58 +02:00
public:
2020-10-29 14:25:39 +01:00
explicit IntervalVarRelaxedMin(IntervalVar* const t)
: AlwaysPerformedIntervalVarWrapper(t) {}
~IntervalVarRelaxedMin() override {}
int64 StartMin() const override {
2013-06-11 14:49:19 +00:00
return underlying()->MustBePerformed() ? underlying()->StartMin()
: kMinValidValue;
}
void SetStartMin(int64 m) override {
LOG(FATAL)
<< "Calling SetStartMin on a IntervalVarRelaxedMin is not supported, "
<< "as it seems there is no legitimate use case.";
}
int64 EndMin() const override {
// It matters to use DurationMin() and not underlying()->DurationMin() here.
2013-06-11 14:49:19 +00:00
return underlying()->MustBePerformed() ? underlying()->EndMin()
: (kMinValidValue + DurationMin());
}
void SetEndMin(int64 m) override {
LOG(FATAL)
2013-06-11 14:49:19 +00:00
<< "Calling SetEndMin on a IntervalVarRelaxedMin is not supported, "
<< "as it seems there is no legitimate use case.";
}
2011-07-11 20:13:14 +00:00
2020-10-29 14:25:39 +01:00
void Accept(ModelVisitor* const visitor) const override {
2013-06-11 14:49:19 +00:00
visitor->VisitIntervalVariable(this, ModelVisitor::kRelaxedMinOperation, 0,
underlying());
2011-07-11 20:13:14 +00:00
}
std::string DebugString() const override {
dotnet: Remove reference to dotnet release command - Currently not implemented... Add abseil patch - Add patches/absl-config.cmake Makefile: Add abseil-cpp on unix - Force abseil-cpp SHA1 to 45221cc note: Just before the PR #136 which break all CMake Makefile: Add abseil-cpp on windows - Force abseil-cpp SHA1 to 45221cc note: Just before the PR #136 which break all CMake CMake: Add abseil-cpp - Force abseil-cpp SHA1 to 45221cc note: Just before the PR #136 which break all CMake port to absl: C++ Part - Fix warning with the use of ABSL_MUST_USE_RESULT > The macro must appear as the very first part of a function declaration or definition: ... Note: past advice was to place the macro after the argument list. src: dependencies/sources/abseil-cpp-master/absl/base/attributes.h:418 - Rename enum after windows clash - Remove non compact table constraints - Change index type from int64 to int in routing library - Fix file_nonport compilation on windows - Fix another naming conflict with windows (NO_ERROR is a macro) - Cleanup hash containers; work on sat internals - Add optional_boolean sub-proto Sync cpp examples with internal code - reenable issue173 after reducing number of loops port to absl: Python Part - Add back cp_model.INT32_MIN|MAX for examples Update Python examples - Add random_tsp.py - Run words_square example - Run magic_square in python tests port to absl: Java Part - Fix compilation of the new routing parameters in java - Protect some code from SWIG parsing Update Java Examples port to absl: .Net Part Update .Net examples work on sat internals; Add C++ CP-SAT CpModelBuilder API; update sample code and recipes to use the new API; sync with internal code Remove VS 2015 in Appveyor-CI - abseil-cpp does not support VS 2015... improve tables upgrade C++ sat examples to use the new API; work on sat internals update license dates rewrite jobshop_ft06_distance.py to use the CP-SAT solver rename last example revert last commit more work on SAT internals fix
2018-10-31 16:18:18 +01:00
return absl::StrFormat("IntervalVarRelaxedMin(%s)",
underlying()->DebugString());
}
};
2010-09-15 12:42:33 +00:00
2013-06-11 14:49:19 +00:00
// ----- BaseIntervalVar -----
class BaseIntervalVar : public IntervalVar {
2020-10-22 23:36:58 +02:00
public:
class Handler : public Demon {
2020-10-22 23:36:58 +02:00
public:
2020-10-29 14:25:39 +01:00
explicit Handler(BaseIntervalVar* const var) : var_(var) {}
~Handler() override {}
2020-10-29 14:25:39 +01:00
void Run(Solver* const s) override { var_->Process(); }
Solver::DemonPriority priority() const override {
2010-09-15 12:42:33 +00:00
return Solver::VAR_PRIORITY;
}
std::string DebugString() const override {
dotnet: Remove reference to dotnet release command - Currently not implemented... Add abseil patch - Add patches/absl-config.cmake Makefile: Add abseil-cpp on unix - Force abseil-cpp SHA1 to 45221cc note: Just before the PR #136 which break all CMake Makefile: Add abseil-cpp on windows - Force abseil-cpp SHA1 to 45221cc note: Just before the PR #136 which break all CMake CMake: Add abseil-cpp - Force abseil-cpp SHA1 to 45221cc note: Just before the PR #136 which break all CMake port to absl: C++ Part - Fix warning with the use of ABSL_MUST_USE_RESULT > The macro must appear as the very first part of a function declaration or definition: ... Note: past advice was to place the macro after the argument list. src: dependencies/sources/abseil-cpp-master/absl/base/attributes.h:418 - Rename enum after windows clash - Remove non compact table constraints - Change index type from int64 to int in routing library - Fix file_nonport compilation on windows - Fix another naming conflict with windows (NO_ERROR is a macro) - Cleanup hash containers; work on sat internals - Add optional_boolean sub-proto Sync cpp examples with internal code - reenable issue173 after reducing number of loops port to absl: Python Part - Add back cp_model.INT32_MIN|MAX for examples Update Python examples - Add random_tsp.py - Run words_square example - Run magic_square in python tests port to absl: Java Part - Fix compilation of the new routing parameters in java - Protect some code from SWIG parsing Update Java Examples port to absl: .Net Part Update .Net examples work on sat internals; Add C++ CP-SAT CpModelBuilder API; update sample code and recipes to use the new API; sync with internal code Remove VS 2015 in Appveyor-CI - abseil-cpp does not support VS 2015... improve tables upgrade C++ sat examples to use the new API; work on sat internals update license dates rewrite jobshop_ft06_distance.py to use the CP-SAT solver rename last example revert last commit more work on SAT internals fix
2018-10-31 16:18:18 +01:00
return absl::StrFormat("Handler(%s)", var_->DebugString());
2010-09-15 12:42:33 +00:00
}
2013-06-11 14:49:19 +00:00
2020-10-22 23:36:58 +02:00
private:
2020-10-29 14:25:39 +01:00
BaseIntervalVar* const var_;
2010-09-15 12:42:33 +00:00
};
2020-10-29 14:25:39 +01:00
BaseIntervalVar(Solver* const s, const std::string& name)
2020-10-22 23:36:58 +02:00
: IntervalVar(s, name),
in_process_(false),
handler_(this),
2020-10-29 14:25:39 +01:00
cleaner_([this](Solver* s) { CleanInProcess(); }) {}
2013-06-11 14:49:19 +00:00
~BaseIntervalVar() override {}
2013-06-11 14:49:19 +00:00
virtual void Process() = 0;
virtual void Push() = 0;
void CleanInProcess() { in_process_ = false; }
2013-06-11 14:49:19 +00:00
std::string BaseName() const override { return "IntervalVar"; }
2013-06-11 14:49:19 +00:00
bool InProcess() const { return in_process_; }
2020-10-22 23:36:58 +02:00
protected:
2013-06-11 14:49:19 +00:00
bool in_process_;
Handler handler_;
Solver::Action cleaner_;
2013-06-11 14:49:19 +00:00
};
class RangeVar : public IntExpr {
2020-10-22 23:36:58 +02:00
public:
2020-10-29 14:25:39 +01:00
RangeVar(Solver* const s, BaseIntervalVar* var, int64 mi, int64 ma)
2020-10-22 23:36:58 +02:00
: IntExpr(s),
min_(mi),
max_(ma),
var_(var),
postponed_min_(mi),
postponed_max_(ma),
previous_min_(mi),
previous_max_(ma),
cast_var_(nullptr) {}
2013-06-11 14:49:19 +00:00
~RangeVar() override {}
2013-06-11 14:49:19 +00:00
bool Bound() const override { return min_.Value() == max_.Value(); }
2013-06-11 14:49:19 +00:00
int64 Min() const override { return min_.Value(); }
2013-06-11 14:49:19 +00:00
int64 Max() const override { return max_.Value(); }
2013-06-11 14:49:19 +00:00
void SetMin(int64 m) override {
// No Op.
if (m <= min_.Value()) {
return;
}
// Inconsistent value.
2013-06-11 14:49:19 +00:00
if (m > max_.Value()) {
var_->SetPerformed(false);
return;
2013-06-11 14:49:19 +00:00
}
if (var_->InProcess()) {
// In process, postpone modifications.
if (m > postponed_max_) {
var_->SetPerformed(false);
}
if (m > postponed_min_) {
postponed_min_ = m;
}
} else {
// Not in process.
2013-06-11 14:49:19 +00:00
SyncPreviousBounds();
min_.SetValue(solver(), m);
var_->Push();
2013-06-11 14:49:19 +00:00
}
}
int64 OldMin() const {
DCHECK(var_->InProcess());
return previous_min_;
2013-06-11 14:49:19 +00:00
}
void SetMax(int64 m) override {
if (m >= max_.Value()) {
return;
}
2013-06-11 14:49:19 +00:00
if (m < min_.Value()) {
var_->SetPerformed(false);
return;
2013-06-11 14:49:19 +00:00
}
if (var_->InProcess()) {
// In process, postpone modifications.
if (m < postponed_min_) {
var_->SetPerformed(false);
}
if (m < postponed_max_) {
postponed_max_ = m;
}
} else {
// Not in process.
2013-06-11 14:49:19 +00:00
SyncPreviousBounds();
max_.SetValue(solver(), m);
var_->Push();
2013-06-11 14:49:19 +00:00
}
}
int64 OldMax() const { return previous_min_; }
2013-06-11 14:49:19 +00:00
void SetRange(int64 mi, int64 ma) override {
if (mi <= min_.Value() && ma >= max_.Value()) {
// No Op.
return;
}
if (mi > max_.Value() || ma < min_.Value() || mi > ma) {
var_->SetPerformed(false);
2013-06-11 14:49:19 +00:00
}
if (var_->InProcess()) {
if (mi > postponed_max_ || ma < postponed_min_) {
var_->SetPerformed(false);
}
if (mi > postponed_min_) {
postponed_min_ = mi;
}
if (ma < postponed_max_) {
postponed_max_ = ma;
}
} else {
// Not in process.
2013-06-11 14:49:19 +00:00
SyncPreviousBounds();
if (mi > min_.Value()) {
min_.SetValue(solver(), mi);
}
if (ma < max_.Value()) {
max_.SetValue(solver(), ma);
}
var_->Push();
2013-06-11 14:49:19 +00:00
}
}
2020-10-29 14:25:39 +01:00
void WhenRange(Demon* const demon) override {
2013-06-11 14:49:19 +00:00
if (!Bound()) {
if (demon->priority() == Solver::DELAYED_PRIORITY) {
delayed_range_demons_.PushIfNotTop(solver(),
solver()->RegisterDemon(demon));
} else {
range_demons_.PushIfNotTop(solver(), solver()->RegisterDemon(demon));
}
}
}
2020-10-29 14:25:39 +01:00
virtual void WhenBound(Demon* const demon) {
2013-06-11 14:49:19 +00:00
if (!Bound()) {
if (demon->priority() == Solver::DELAYED_PRIORITY) {
delayed_bound_demons_.PushIfNotTop(solver(),
solver()->RegisterDemon(demon));
} else {
bound_demons_.PushIfNotTop(solver(), solver()->RegisterDemon(demon));
}
}
}
void UpdatePostponedBounds() {
postponed_min_ = min_.Value();
postponed_max_ = max_.Value();
}
void ProcessDemons() {
if (Bound()) {
ExecuteAll(bound_demons_);
EnqueueAll(delayed_bound_demons_);
}
if (min_.Value() != previous_min_ || max_.Value() != previous_max_) {
ExecuteAll(range_demons_);
EnqueueAll(delayed_range_demons_);
}
}
void UpdatePreviousBounds() {
2013-06-11 14:49:19 +00:00
previous_min_ = min_.Value();
previous_max_ = max_.Value();
}
// TODO(user): Remove this interval field enum.
void ApplyPostponedBounds(IntervalField which) {
2013-06-11 14:49:19 +00:00
if (min_.Value() < postponed_min_ || max_.Value() > postponed_max_) {
switch (which) {
2020-10-22 23:36:58 +02:00
case START:
var_->SetStartRange(std::max(postponed_min_, min_.Value()),
std::min(postponed_max_, max_.Value()));
break;
case DURATION:
var_->SetDurationRange(std::max(postponed_min_, min_.Value()),
std::min(postponed_max_, max_.Value()));
break;
case END:
var_->SetEndRange(std::max(postponed_min_, min_.Value()),
std::min(postponed_max_, max_.Value()));
2020-10-22 23:36:58 +02:00
break;
2013-06-11 14:49:19 +00:00
}
}
}
2020-10-29 14:25:39 +01:00
IntVar* Var() override {
if (cast_var_ == nullptr) {
2020-10-29 14:25:39 +01:00
solver()->SaveValue(reinterpret_cast<void**>(&cast_var_));
cast_var_ = solver()->MakeIntVar(min_.Value(), max_.Value());
LinkVarExpr(solver(), this, cast_var_);
}
return cast_var_;
}
std::string DebugString() const override {
std::string out = absl::StrCat(min_.Value());
2013-06-11 14:49:19 +00:00
if (!Bound()) {
absl::StrAppendFormat(&out, " .. %d", max_.Value());
2013-06-11 14:49:19 +00:00
}
return out;
}
2020-10-22 23:36:58 +02:00
private:
2013-06-11 14:49:19 +00:00
// The previous bounds are maintained lazily and non reversibly.
// When going down in the search tree, the modifications are
// monotonic, thus SyncPreviousBounds is a no-op because they are
// correctly updated at the end of the ProcessDemons() call. After
// a fail, if they are inconsistent, then they will be outside the
// current interval, thus this check.
void SyncPreviousBounds() {
if (previous_min_ > min_.Value()) {
previous_min_ = min_.Value();
}
if (previous_max_ < max_.Value()) {
previous_max_ = max_.Value();
}
}
// The current reversible bounds of the interval.
NumericalRev<int64> min_;
NumericalRev<int64> max_;
2020-10-29 14:25:39 +01:00
BaseIntervalVar* const var_;
2013-06-11 14:49:19 +00:00
// When in process, the modifications are postponed and stored in
// these 2 fields.
int64 postponed_min_;
int64 postponed_max_;
// The previous bounds stores the bounds since the last time
// ProcessDemons() was run. These are maintained lazily.
int64 previous_min_;
int64 previous_max_;
// Demons attached to the 'bound' event (min == max).
2020-10-29 14:25:39 +01:00
SimpleRevFIFO<Demon*> bound_demons_;
SimpleRevFIFO<Demon*> delayed_bound_demons_;
2013-06-11 14:49:19 +00:00
// Demons attached to a modification of bounds.
2020-10-29 14:25:39 +01:00
SimpleRevFIFO<Demon*> range_demons_;
SimpleRevFIFO<Demon*> delayed_range_demons_;
IntVar* cast_var_;
2020-10-22 23:36:58 +02:00
}; // class RangeVar
// ----- PerformedVar -----
class PerformedVar : public BooleanVar {
2020-10-22 23:36:58 +02:00
public:
// Optional = true -> var = [0..1], Optional = false -> var = [1].
2020-10-29 14:25:39 +01:00
PerformedVar(Solver* const s, BaseIntervalVar* const var, bool optional)
2020-10-22 23:36:58 +02:00
: BooleanVar(s, ""),
var_(var),
previous_value_(optional ? kUnboundBooleanVarValue : 1),
postponed_value_(optional ? kUnboundBooleanVarValue : 1) {
if (!optional) {
value_ = 1;
}
}
// var = [0] (always unperformed).
2020-10-29 14:25:39 +01:00
PerformedVar(Solver* const s, BaseIntervalVar* var)
: BooleanVar(s, ""), var_(var), previous_value_(0), postponed_value_(0) {
value_ = 1;
}
~PerformedVar() override {}
void SetValue(int64 v) override {
2020-10-22 23:36:58 +02:00
if ((v & 0xfffffffffffffffe) != 0 || // Not 0 or 1.
(value_ != kUnboundBooleanVarValue && v != value_)) {
solver()->Fail();
}
if (var_->InProcess()) {
if (postponed_value_ != kUnboundBooleanVarValue &&
2020-10-22 23:36:58 +02:00
v != postponed_value_) { // Fail early.
solver()->Fail();
} else {
postponed_value_ = v;
}
} else if (value_ == kUnboundBooleanVarValue) {
previous_value_ = kUnboundBooleanVarValue;
InternalSaveBooleanVarValue(solver(), this);
value_ = static_cast<int>(v);
var_->Push();
}
}
int64 OldMin() const override { return previous_value_ == 1; }
int64 OldMax() const override { return previous_value_ != 0; }
void RestoreValue() override {
previous_value_ = kUnboundBooleanVarValue;
value_ = kUnboundBooleanVarValue;
postponed_value_ = kUnboundBooleanVarValue;
}
void Process() {
if (previous_value_ != value_) {
ExecuteAll(bound_demons_);
EnqueueAll(delayed_bound_demons_);
}
}
void UpdatePostponedValue() { postponed_value_ = value_; }
void UpdatePreviousValueAndApplyPostponedValue() {
previous_value_ = value_;
if (value_ != postponed_value_) {
DCHECK_NE(kUnboundBooleanVarValue, postponed_value_);
SetValue(postponed_value_);
}
}
std::string DebugString() const override {
switch (value_) {
2020-10-22 23:36:58 +02:00
case 0:
return "false";
case 1:
return "true";
default:
return "undecided";
}
}
2020-10-22 23:36:58 +02:00
private:
2020-10-29 14:25:39 +01:00
BaseIntervalVar* const var_;
int previous_value_;
int postponed_value_;
};
2013-06-11 14:49:19 +00:00
// ----- FixedDurationIntervalVar -----
class FixedDurationIntervalVar : public BaseIntervalVar {
2020-10-22 23:36:58 +02:00
public:
2020-10-29 14:25:39 +01:00
FixedDurationIntervalVar(Solver* const s, int64 start_min, int64 start_max,
2018-06-08 16:40:43 +02:00
int64 duration, bool optional,
2020-10-29 14:25:39 +01:00
const std::string& name);
2010-09-15 12:42:33 +00:00
// Unperformed interval.
2020-10-29 14:25:39 +01:00
FixedDurationIntervalVar(Solver* const s, const std::string& name);
~FixedDurationIntervalVar() override {}
int64 StartMin() const override;
int64 StartMax() const override;
void SetStartMin(int64 m) override;
void SetStartMax(int64 m) override;
void SetStartRange(int64 mi, int64 ma) override;
int64 OldStartMin() const override { return start_.OldMin(); }
int64 OldStartMax() const override { return start_.OldMax(); }
2020-10-29 14:25:39 +01:00
void WhenStartRange(Demon* const d) override {
if (performed_.Max() == 1) {
2013-06-11 14:49:19 +00:00
start_.WhenRange(d);
}
2010-09-15 12:42:33 +00:00
}
2020-10-29 14:25:39 +01:00
void WhenStartBound(Demon* const d) override {
if (performed_.Max() == 1) {
2013-06-11 14:49:19 +00:00
start_.WhenBound(d);
}
2010-09-15 12:42:33 +00:00
}
int64 DurationMin() const override;
int64 DurationMax() const override;
void SetDurationMin(int64 m) override;
void SetDurationMax(int64 m) override;
void SetDurationRange(int64 mi, int64 ma) override;
int64 OldDurationMin() const override { return duration_; }
int64 OldDurationMax() const override { return duration_; }
2020-10-29 14:25:39 +01:00
void WhenDurationRange(Demon* const d) override {}
void WhenDurationBound(Demon* const d) override {}
int64 EndMin() const override;
int64 EndMax() const override;
void SetEndMin(int64 m) override;
void SetEndMax(int64 m) override;
void SetEndRange(int64 mi, int64 ma) override;
int64 OldEndMin() const override { return CapAdd(OldStartMin(), duration_); }
int64 OldEndMax() const override { return CapAdd(OldStartMax(), duration_); }
2020-10-29 14:25:39 +01:00
void WhenEndRange(Demon* const d) override { WhenStartRange(d); }
void WhenEndBound(Demon* const d) override { WhenStartBound(d); }
bool MustBePerformed() const override;
bool MayBePerformed() const override;
void SetPerformed(bool val) override;
bool WasPerformedBound() const override {
return performed_.OldMin() == performed_.OldMax();
}
2020-10-29 14:25:39 +01:00
void WhenPerformedBound(Demon* const d) override { performed_.WhenBound(d); }
void Process() override;
std::string DebugString() const override;
2011-07-11 20:13:14 +00:00
2020-10-29 14:25:39 +01:00
void Accept(ModelVisitor* const visitor) const override {
2013-06-11 14:49:19 +00:00
visitor->VisitIntervalVariable(this, "", 0, NullInterval());
2011-07-11 20:13:14 +00:00
}
2020-10-29 14:25:39 +01:00
IntExpr* StartExpr() override { return &start_; }
IntExpr* DurationExpr() override { return solver()->MakeIntConst(duration_); }
IntExpr* EndExpr() override {
return solver()->MakeSum(StartExpr(), duration_);
}
2020-10-29 14:25:39 +01:00
IntExpr* PerformedExpr() override { return &performed_; }
IntExpr* SafeStartExpr(int64 unperformed_value) override {
return BuildSafeStartExpr(this, unperformed_value);
}
2020-10-29 14:25:39 +01:00
IntExpr* SafeDurationExpr(int64 unperformed_value) override {
return BuildSafeDurationExpr(this, unperformed_value);
}
2020-10-29 14:25:39 +01:00
IntExpr* SafeEndExpr(int64 unperformed_value) override {
return BuildSafeEndExpr(this, unperformed_value);
}
void Push() override;
2010-09-15 12:42:33 +00:00
2020-10-22 23:36:58 +02:00
private:
RangeVar start_;
2010-09-15 12:42:33 +00:00
int64 duration_;
PerformedVar performed_;
2010-09-15 12:42:33 +00:00
};
2013-06-11 14:49:19 +00:00
FixedDurationIntervalVar::FixedDurationIntervalVar(
2020-10-29 14:25:39 +01:00
Solver* const s, int64 start_min, int64 start_max, int64 duration,
bool optional, const std::string& name)
2020-10-22 23:36:58 +02:00
: BaseIntervalVar(s, name),
start_(s, this, start_min, start_max),
duration_(duration),
performed_(s, this, optional) {}
2020-10-29 14:25:39 +01:00
FixedDurationIntervalVar::FixedDurationIntervalVar(Solver* const s,
const std::string& name)
2020-10-22 23:36:58 +02:00
: BaseIntervalVar(s, name),
start_(s, this, 0, 0),
duration_(0),
performed_(s, this) {}
2010-09-15 12:42:33 +00:00
void FixedDurationIntervalVar::Process() {
CHECK(!in_process_);
in_process_ = true;
2013-06-11 14:49:19 +00:00
start_.UpdatePostponedBounds();
performed_.UpdatePostponedValue();
set_action_on_fail(cleaner_);
if (performed_.Max() == 1) {
2013-06-11 14:49:19 +00:00
start_.ProcessDemons();
2010-09-15 12:42:33 +00:00
}
performed_.Process();
reset_action_on_fail();
CleanInProcess();
start_.UpdatePreviousBounds();
start_.ApplyPostponedBounds(START);
performed_.UpdatePreviousValueAndApplyPostponedValue();
2010-09-15 12:42:33 +00:00
}
int64 FixedDurationIntervalVar::StartMin() const {
CHECK_EQ(performed_.Max(), 1);
2013-06-11 14:49:19 +00:00
return start_.Min();
2010-09-15 12:42:33 +00:00
}
int64 FixedDurationIntervalVar::StartMax() const {
CHECK_EQ(performed_.Max(), 1);
2013-06-11 14:49:19 +00:00
return start_.Max();
2010-09-15 12:42:33 +00:00
}
void FixedDurationIntervalVar::SetStartMin(int64 m) {
if (performed_.Max() == 1) {
start_.SetMin(m);
2010-09-15 12:42:33 +00:00
}
}
void FixedDurationIntervalVar::SetStartMax(int64 m) {
if (performed_.Max() == 1) {
start_.SetMax(m);
2010-09-15 12:42:33 +00:00
}
}
void FixedDurationIntervalVar::SetStartRange(int64 mi, int64 ma) {
if (performed_.Max() == 1) {
start_.SetRange(mi, ma);
2013-06-11 14:49:19 +00:00
}
2010-09-15 12:42:33 +00:00
}
int64 FixedDurationIntervalVar::DurationMin() const {
CHECK_EQ(performed_.Max(), 1);
2010-09-15 12:42:33 +00:00
return duration_;
}
int64 FixedDurationIntervalVar::DurationMax() const {
CHECK_EQ(performed_.Max(), 1);
2010-09-15 12:42:33 +00:00
return duration_;
}
void FixedDurationIntervalVar::SetDurationMin(int64 m) {
if (m > duration_) {
SetPerformed(false);
}
}
void FixedDurationIntervalVar::SetDurationMax(int64 m) {
if (m < duration_) {
SetPerformed(false);
}
}
2013-06-11 14:49:19 +00:00
void FixedDurationIntervalVar::SetDurationRange(int64 mi, int64 ma) {
if (mi > duration_ || ma < duration_ || mi > ma) {
SetPerformed(false);
}
}
2010-09-15 12:42:33 +00:00
int64 FixedDurationIntervalVar::EndMin() const {
CHECK_EQ(performed_.Max(), 1);
2013-06-11 14:49:19 +00:00
return start_.Min() + duration_;
2010-09-15 12:42:33 +00:00
}
int64 FixedDurationIntervalVar::EndMax() const {
CHECK_EQ(performed_.Max(), 1);
2013-06-11 14:49:19 +00:00
return CapAdd(start_.Max(), duration_);
2010-09-15 12:42:33 +00:00
}
void FixedDurationIntervalVar::SetEndMin(int64 m) {
2013-06-11 14:49:19 +00:00
SetStartMin(CapSub(m, duration_));
2010-09-15 12:42:33 +00:00
}
void FixedDurationIntervalVar::SetEndMax(int64 m) {
2013-06-11 14:49:19 +00:00
SetStartMax(CapSub(m, duration_));
2010-09-15 12:42:33 +00:00
}
void FixedDurationIntervalVar::SetEndRange(int64 mi, int64 ma) {
2013-06-11 14:49:19 +00:00
SetStartRange(CapSub(mi, duration_), CapSub(ma, duration_));
2010-09-15 12:42:33 +00:00
}
bool FixedDurationIntervalVar::MustBePerformed() const {
return (performed_.Min() == 1);
2010-09-15 12:42:33 +00:00
}
bool FixedDurationIntervalVar::MayBePerformed() const {
return (performed_.Max() == 1);
2010-09-15 12:42:33 +00:00
}
void FixedDurationIntervalVar::SetPerformed(bool val) {
performed_.SetValue(val);
2010-09-15 12:42:33 +00:00
}
void FixedDurationIntervalVar::Push() {
2013-06-11 14:49:19 +00:00
DCHECK(!in_process_);
EnqueueVar(&handler_);
2013-06-11 14:49:19 +00:00
DCHECK(!in_process_);
2010-09-15 12:42:33 +00:00
}
std::string FixedDurationIntervalVar::DebugString() const {
2020-10-29 14:25:39 +01:00
const std::string& var_name = name();
if (performed_.Max() == 0) {
2013-07-29 02:49:12 +00:00
if (!var_name.empty()) {
dotnet: Remove reference to dotnet release command - Currently not implemented... Add abseil patch - Add patches/absl-config.cmake Makefile: Add abseil-cpp on unix - Force abseil-cpp SHA1 to 45221cc note: Just before the PR #136 which break all CMake Makefile: Add abseil-cpp on windows - Force abseil-cpp SHA1 to 45221cc note: Just before the PR #136 which break all CMake CMake: Add abseil-cpp - Force abseil-cpp SHA1 to 45221cc note: Just before the PR #136 which break all CMake port to absl: C++ Part - Fix warning with the use of ABSL_MUST_USE_RESULT > The macro must appear as the very first part of a function declaration or definition: ... Note: past advice was to place the macro after the argument list. src: dependencies/sources/abseil-cpp-master/absl/base/attributes.h:418 - Rename enum after windows clash - Remove non compact table constraints - Change index type from int64 to int in routing library - Fix file_nonport compilation on windows - Fix another naming conflict with windows (NO_ERROR is a macro) - Cleanup hash containers; work on sat internals - Add optional_boolean sub-proto Sync cpp examples with internal code - reenable issue173 after reducing number of loops port to absl: Python Part - Add back cp_model.INT32_MIN|MAX for examples Update Python examples - Add random_tsp.py - Run words_square example - Run magic_square in python tests port to absl: Java Part - Fix compilation of the new routing parameters in java - Protect some code from SWIG parsing Update Java Examples port to absl: .Net Part Update .Net examples work on sat internals; Add C++ CP-SAT CpModelBuilder API; update sample code and recipes to use the new API; sync with internal code Remove VS 2015 in Appveyor-CI - abseil-cpp does not support VS 2015... improve tables upgrade C++ sat examples to use the new API; work on sat internals update license dates rewrite jobshop_ft06_distance.py to use the CP-SAT solver rename last example revert last commit more work on SAT internals fix
2018-10-31 16:18:18 +01:00
return absl::StrFormat("%s(performed = false)", var_name);
2013-07-29 02:49:12 +00:00
} else {
return "IntervalVar(performed = false)";
}
2010-09-15 12:42:33 +00:00
} else {
std::string out;
2013-07-29 02:49:12 +00:00
if (!var_name.empty()) {
out = var_name + "(start = ";
} else {
out = "IntervalVar(start = ";
}
absl::StrAppendFormat(&out, "%s, duration = %d, performed = %s)",
start_.DebugString(), duration_,
performed_.DebugString());
2013-07-29 02:49:12 +00:00
return out;
2010-09-15 12:42:33 +00:00
}
}
// ----- FixedDurationPerformedIntervalVar -----
2013-06-11 14:49:19 +00:00
class FixedDurationPerformedIntervalVar : public BaseIntervalVar {
2020-10-22 23:36:58 +02:00
public:
2020-10-29 14:25:39 +01:00
FixedDurationPerformedIntervalVar(Solver* const s, int64 start_min,
2013-06-11 14:49:19 +00:00
int64 start_max, int64 duration,
2020-10-29 14:25:39 +01:00
const std::string& name);
// Unperformed interval.
2020-10-29 14:25:39 +01:00
FixedDurationPerformedIntervalVar(Solver* const s, const std::string& name);
~FixedDurationPerformedIntervalVar() override {}
int64 StartMin() const override;
int64 StartMax() const override;
void SetStartMin(int64 m) override;
void SetStartMax(int64 m) override;
void SetStartRange(int64 mi, int64 ma) override;
int64 OldStartMin() const override { return start_.OldMin(); }
int64 OldStartMax() const override { return start_.OldMax(); }
2020-10-29 14:25:39 +01:00
void WhenStartRange(Demon* const d) override { start_.WhenRange(d); }
void WhenStartBound(Demon* const d) override { start_.WhenBound(d); }
int64 DurationMin() const override;
int64 DurationMax() const override;
void SetDurationMin(int64 m) override;
void SetDurationMax(int64 m) override;
void SetDurationRange(int64 mi, int64 ma) override;
int64 OldDurationMin() const override { return duration_; }
int64 OldDurationMax() const override { return duration_; }
2020-10-29 14:25:39 +01:00
void WhenDurationRange(Demon* const d) override {}
void WhenDurationBound(Demon* const d) override {}
int64 EndMin() const override;
int64 EndMax() const override;
void SetEndMin(int64 m) override;
void SetEndMax(int64 m) override;
void SetEndRange(int64 mi, int64 ma) override;
int64 OldEndMin() const override { return CapAdd(OldStartMin(), duration_); }
int64 OldEndMax() const override { return CapAdd(OldStartMax(), duration_); }
2020-10-29 14:25:39 +01:00
void WhenEndRange(Demon* const d) override { WhenStartRange(d); }
void WhenEndBound(Demon* const d) override { WhenEndRange(d); }
bool MustBePerformed() const override;
bool MayBePerformed() const override;
void SetPerformed(bool val) override;
bool WasPerformedBound() const override { return true; }
2020-10-29 14:25:39 +01:00
void WhenPerformedBound(Demon* const d) override {}
void Process() override;
std::string DebugString() const override;
2020-10-29 14:25:39 +01:00
void Accept(ModelVisitor* const visitor) const override {
2013-06-11 14:49:19 +00:00
visitor->VisitIntervalVariable(this, "", 0, NullInterval());
}
2020-10-29 14:25:39 +01:00
IntExpr* StartExpr() override { return &start_; }
IntExpr* DurationExpr() override { return solver()->MakeIntConst(duration_); }
IntExpr* EndExpr() override {
return solver()->MakeSum(StartExpr(), duration_);
}
2020-10-29 14:25:39 +01:00
IntExpr* PerformedExpr() override { return solver()->MakeIntConst(1); }
IntExpr* SafeStartExpr(int64 unperformed_value) override {
return StartExpr();
}
2020-10-29 14:25:39 +01:00
IntExpr* SafeDurationExpr(int64 unperformed_value) override {
return DurationExpr();
}
2020-10-29 14:25:39 +01:00
IntExpr* SafeEndExpr(int64 unperformed_value) override { return EndExpr(); }
2020-10-22 23:36:58 +02:00
private:
void CheckOldPerformed() {}
void Push() override;
2013-06-11 14:49:19 +00:00
RangeVar start_;
int64 duration_;
};
FixedDurationPerformedIntervalVar::FixedDurationPerformedIntervalVar(
2020-10-29 14:25:39 +01:00
Solver* const s, int64 start_min, int64 start_max, int64 duration,
const std::string& name)
2020-10-22 23:36:58 +02:00
: BaseIntervalVar(s, name),
start_(s, this, start_min, start_max),
duration_(duration) {}
FixedDurationPerformedIntervalVar::FixedDurationPerformedIntervalVar(
2020-10-29 14:25:39 +01:00
Solver* const s, const std::string& name)
: BaseIntervalVar(s, name), start_(s, this, 0, 0), duration_(0) {}
void FixedDurationPerformedIntervalVar::Process() {
CHECK(!in_process_);
in_process_ = true;
2013-06-11 14:49:19 +00:00
start_.UpdatePostponedBounds();
set_action_on_fail(cleaner_);
2013-06-11 14:49:19 +00:00
start_.ProcessDemons();
reset_action_on_fail();
CleanInProcess();
start_.UpdatePreviousBounds();
start_.ApplyPostponedBounds(START);
}
int64 FixedDurationPerformedIntervalVar::StartMin() const {
2013-06-11 14:49:19 +00:00
return start_.Min();
}
int64 FixedDurationPerformedIntervalVar::StartMax() const {
2013-06-11 14:49:19 +00:00
return start_.Max();
}
void FixedDurationPerformedIntervalVar::SetStartMin(int64 m) {
start_.SetMin(m);
}
void FixedDurationPerformedIntervalVar::SetStartMax(int64 m) {
start_.SetMax(m);
}
void FixedDurationPerformedIntervalVar::SetStartRange(int64 mi, int64 ma) {
start_.SetRange(mi, ma);
}
int64 FixedDurationPerformedIntervalVar::DurationMin() const {
return duration_;
}
int64 FixedDurationPerformedIntervalVar::DurationMax() const {
return duration_;
}
void FixedDurationPerformedIntervalVar::SetDurationMin(int64 m) {
if (m > duration_) {
SetPerformed(false);
}
}
void FixedDurationPerformedIntervalVar::SetDurationMax(int64 m) {
if (m < duration_) {
SetPerformed(false);
}
}
int64 FixedDurationPerformedIntervalVar::EndMin() const {
2013-06-11 14:49:19 +00:00
return CapAdd(start_.Min(), duration_);
}
int64 FixedDurationPerformedIntervalVar::EndMax() const {
2013-06-11 14:49:19 +00:00
return CapAdd(start_.Max(), duration_);
}
void FixedDurationPerformedIntervalVar::SetEndMin(int64 m) {
2013-06-11 14:49:19 +00:00
SetStartMin(CapSub(m, duration_));
}
void FixedDurationPerformedIntervalVar::SetEndMax(int64 m) {
2013-06-11 14:49:19 +00:00
SetStartMax(CapSub(m, duration_));
}
void FixedDurationPerformedIntervalVar::SetEndRange(int64 mi, int64 ma) {
2013-06-11 14:49:19 +00:00
SetStartRange(CapSub(mi, duration_), CapSub(ma, duration_));
}
void FixedDurationPerformedIntervalVar::SetDurationRange(int64 mi, int64 ma) {
if (mi > duration_ || ma < duration_ || mi > ma) {
SetPerformed(false);
}
}
2013-06-11 14:49:19 +00:00
bool FixedDurationPerformedIntervalVar::MustBePerformed() const { return true; }
2013-06-11 14:49:19 +00:00
bool FixedDurationPerformedIntervalVar::MayBePerformed() const { return true; }
void FixedDurationPerformedIntervalVar::SetPerformed(bool val) {
if (!val) {
solver()->Fail();
}
}
void FixedDurationPerformedIntervalVar::Push() {
2013-06-11 14:49:19 +00:00
DCHECK(!in_process_);
EnqueueVar(&handler_);
2013-06-11 14:49:19 +00:00
DCHECK(!in_process_);
}
std::string FixedDurationPerformedIntervalVar::DebugString() const {
std::string out;
2020-10-29 14:25:39 +01:00
const std::string& var_name = name();
if (!var_name.empty()) {
out = var_name + "(start = ";
} else {
out = "IntervalVar(start = ";
}
absl::StrAppendFormat(&out, "%s, duration = %d, performed = true)",
dotnet: Remove reference to dotnet release command - Currently not implemented... Add abseil patch - Add patches/absl-config.cmake Makefile: Add abseil-cpp on unix - Force abseil-cpp SHA1 to 45221cc note: Just before the PR #136 which break all CMake Makefile: Add abseil-cpp on windows - Force abseil-cpp SHA1 to 45221cc note: Just before the PR #136 which break all CMake CMake: Add abseil-cpp - Force abseil-cpp SHA1 to 45221cc note: Just before the PR #136 which break all CMake port to absl: C++ Part - Fix warning with the use of ABSL_MUST_USE_RESULT > The macro must appear as the very first part of a function declaration or definition: ... Note: past advice was to place the macro after the argument list. src: dependencies/sources/abseil-cpp-master/absl/base/attributes.h:418 - Rename enum after windows clash - Remove non compact table constraints - Change index type from int64 to int in routing library - Fix file_nonport compilation on windows - Fix another naming conflict with windows (NO_ERROR is a macro) - Cleanup hash containers; work on sat internals - Add optional_boolean sub-proto Sync cpp examples with internal code - reenable issue173 after reducing number of loops port to absl: Python Part - Add back cp_model.INT32_MIN|MAX for examples Update Python examples - Add random_tsp.py - Run words_square example - Run magic_square in python tests port to absl: Java Part - Fix compilation of the new routing parameters in java - Protect some code from SWIG parsing Update Java Examples port to absl: .Net Part Update .Net examples work on sat internals; Add C++ CP-SAT CpModelBuilder API; update sample code and recipes to use the new API; sync with internal code Remove VS 2015 in Appveyor-CI - abseil-cpp does not support VS 2015... improve tables upgrade C++ sat examples to use the new API; work on sat internals update license dates rewrite jobshop_ft06_distance.py to use the CP-SAT solver rename last example revert last commit more work on SAT internals fix
2018-10-31 16:18:18 +01:00
start_.DebugString(), duration_);
return out;
}
// ----- StartVarPerformedIntervalVar -----
class StartVarPerformedIntervalVar : public IntervalVar {
2020-10-22 23:36:58 +02:00
public:
2020-10-29 14:25:39 +01:00
StartVarPerformedIntervalVar(Solver* const s, IntVar* const var,
int64 duration, const std::string& name);
~StartVarPerformedIntervalVar() override {}
int64 StartMin() const override;
int64 StartMax() const override;
void SetStartMin(int64 m) override;
void SetStartMax(int64 m) override;
void SetStartRange(int64 mi, int64 ma) override;
int64 OldStartMin() const override { return start_var_->OldMin(); }
int64 OldStartMax() const override { return start_var_->OldMax(); }
2020-10-29 14:25:39 +01:00
void WhenStartRange(Demon* const d) override { start_var_->WhenRange(d); }
void WhenStartBound(Demon* const d) override { start_var_->WhenBound(d); }
int64 DurationMin() const override;
int64 DurationMax() const override;
void SetDurationMin(int64 m) override;
void SetDurationMax(int64 m) override;
void SetDurationRange(int64 mi, int64 ma) override;
int64 OldDurationMin() const override { return duration_; }
int64 OldDurationMax() const override { return duration_; }
2020-10-29 14:25:39 +01:00
void WhenDurationRange(Demon* const d) override {}
void WhenDurationBound(Demon* const d) override {}
int64 EndMin() const override;
int64 EndMax() const override;
void SetEndMin(int64 m) override;
void SetEndMax(int64 m) override;
void SetEndRange(int64 mi, int64 ma) override;
int64 OldEndMin() const override { return CapAdd(OldStartMin(), duration_); }
int64 OldEndMax() const override { return CapAdd(OldStartMax(), duration_); }
2020-10-29 14:25:39 +01:00
void WhenEndRange(Demon* const d) override { start_var_->WhenRange(d); }
void WhenEndBound(Demon* const d) override { start_var_->WhenBound(d); }
bool MustBePerformed() const override;
bool MayBePerformed() const override;
void SetPerformed(bool val) override;
bool WasPerformedBound() const override { return true; }
2020-10-29 14:25:39 +01:00
void WhenPerformedBound(Demon* const d) override {}
std::string DebugString() const override;
2020-10-29 14:25:39 +01:00
IntExpr* StartExpr() override { return start_var_; }
IntExpr* DurationExpr() override { return solver()->MakeIntConst(duration_); }
IntExpr* EndExpr() override {
return solver()->MakeSum(start_var_, duration_);
}
2020-10-29 14:25:39 +01:00
IntExpr* PerformedExpr() override { return solver()->MakeIntConst(1); }
IntExpr* SafeStartExpr(int64 unperformed_value) override {
return StartExpr();
}
2020-10-29 14:25:39 +01:00
IntExpr* SafeDurationExpr(int64 unperformed_value) override {
return DurationExpr();
}
2020-10-29 14:25:39 +01:00
IntExpr* SafeEndExpr(int64 unperformed_value) override { return EndExpr(); }
2020-10-29 14:25:39 +01:00
void Accept(ModelVisitor* const visitor) const override {
2013-06-11 14:49:19 +00:00
visitor->VisitIntervalVariable(this, "", 0, NullInterval());
}
2020-10-22 23:36:58 +02:00
private:
2020-10-29 14:25:39 +01:00
IntVar* const start_var_;
int64 duration_;
};
2012-09-13 14:15:39 +00:00
// TODO(user): Take care of overflows.
2018-06-08 16:40:43 +02:00
StartVarPerformedIntervalVar::StartVarPerformedIntervalVar(
2020-10-29 14:25:39 +01:00
Solver* const s, IntVar* const var, int64 duration, const std::string& name)
2013-06-11 14:49:19 +00:00
: IntervalVar(s, name), start_var_(var), duration_(duration) {}
int64 StartVarPerformedIntervalVar::StartMin() const {
return start_var_->Min();
}
int64 StartVarPerformedIntervalVar::StartMax() const {
return start_var_->Max();
}
void StartVarPerformedIntervalVar::SetStartMin(int64 m) {
start_var_->SetMin(m);
}
void StartVarPerformedIntervalVar::SetStartMax(int64 m) {
start_var_->SetMax(m);
}
void StartVarPerformedIntervalVar::SetStartRange(int64 mi, int64 ma) {
start_var_->SetRange(mi, ma);
}
2013-06-11 14:49:19 +00:00
int64 StartVarPerformedIntervalVar::DurationMin() const { return duration_; }
2013-06-11 14:49:19 +00:00
int64 StartVarPerformedIntervalVar::DurationMax() const { return duration_; }
void StartVarPerformedIntervalVar::SetDurationMin(int64 m) {
if (m > duration_) {
solver()->Fail();
}
}
void StartVarPerformedIntervalVar::SetDurationMax(int64 m) {
if (m < duration_) {
solver()->Fail();
}
}
int64 StartVarPerformedIntervalVar::EndMin() const {
return start_var_->Min() + duration_;
}
int64 StartVarPerformedIntervalVar::EndMax() const {
return start_var_->Max() + duration_;
}
void StartVarPerformedIntervalVar::SetEndMin(int64 m) {
2016-08-05 15:38:20 +02:00
SetStartMin(CapSub(m, duration_));
}
void StartVarPerformedIntervalVar::SetEndMax(int64 m) {
2016-08-05 15:38:20 +02:00
SetStartMax(CapSub(m, duration_));
}
void StartVarPerformedIntervalVar::SetEndRange(int64 mi, int64 ma) {
2016-08-05 15:38:20 +02:00
SetStartRange(CapSub(mi, duration_), CapSub(ma, duration_));
}
void StartVarPerformedIntervalVar::SetDurationRange(int64 mi, int64 ma) {
if (mi > duration_ || ma < duration_ || mi > ma) {
solver()->Fail();
}
}
2013-06-11 14:49:19 +00:00
bool StartVarPerformedIntervalVar::MustBePerformed() const { return true; }
2013-06-11 14:49:19 +00:00
bool StartVarPerformedIntervalVar::MayBePerformed() const { return true; }
void StartVarPerformedIntervalVar::SetPerformed(bool val) {
if (!val) {
solver()->Fail();
}
}
std::string StartVarPerformedIntervalVar::DebugString() const {
std::string out;
2020-10-29 14:25:39 +01:00
const std::string& var_name = name();
if (!var_name.empty()) {
out = var_name + "(start = ";
} else {
out = "IntervalVar(start = ";
}
absl::StrAppendFormat(&out, "%d", start_var_->Min());
if (!start_var_->Bound()) {
absl::StrAppendFormat(&out, " .. %d", start_var_->Max());
}
absl::StrAppendFormat(&out, ", duration = %d, performed = true)", duration_);
return out;
}
// ----- StartVarIntervalVar -----
class StartVarIntervalVar : public BaseIntervalVar {
2020-10-22 23:36:58 +02:00
public:
2020-10-29 14:25:39 +01:00
StartVarIntervalVar(Solver* const s, IntVar* const start, int64 duration,
IntVar* const performed, const std::string& name);
~StartVarIntervalVar() override {}
int64 StartMin() const override;
int64 StartMax() const override;
void SetStartMin(int64 m) override;
void SetStartMax(int64 m) override;
void SetStartRange(int64 mi, int64 ma) override;
int64 OldStartMin() const override { return start_->OldMin(); }
int64 OldStartMax() const override { return start_->OldMax(); }
2020-10-29 14:25:39 +01:00
void WhenStartRange(Demon* const d) override {
if (performed_->Max() == 1) {
start_->WhenRange(d);
}
}
2020-10-29 14:25:39 +01:00
void WhenStartBound(Demon* const d) override {
if (performed_->Max() == 1) {
start_->WhenBound(d);
}
}
int64 DurationMin() const override;
int64 DurationMax() const override;
void SetDurationMin(int64 m) override;
void SetDurationMax(int64 m) override;
void SetDurationRange(int64 mi, int64 ma) override;
int64 OldDurationMin() const override { return duration_; }
int64 OldDurationMax() const override { return duration_; }
2020-10-29 14:25:39 +01:00
void WhenDurationRange(Demon* const d) override {}
void WhenDurationBound(Demon* const d) override {}
int64 EndMin() const override;
int64 EndMax() const override;
void SetEndMin(int64 m) override;
void SetEndMax(int64 m) override;
void SetEndRange(int64 mi, int64 ma) override;
int64 OldEndMin() const override { return CapAdd(OldStartMin(), duration_); }
int64 OldEndMax() const override { return CapAdd(OldStartMax(), duration_); }
2020-10-29 14:25:39 +01:00
void WhenEndRange(Demon* const d) override { WhenStartRange(d); }
void WhenEndBound(Demon* const d) override { WhenStartBound(d); }
bool MustBePerformed() const override;
bool MayBePerformed() const override;
void SetPerformed(bool val) override;
bool WasPerformedBound() const override {
return performed_->OldMin() == performed_->OldMax();
}
2020-10-29 14:25:39 +01:00
void WhenPerformedBound(Demon* const d) override { performed_->WhenBound(d); }
std::string DebugString() const override;
2020-10-29 14:25:39 +01:00
void Accept(ModelVisitor* const visitor) const override {
visitor->VisitIntervalVariable(this, "", 0, NullInterval());
}
2020-10-29 14:25:39 +01:00
IntExpr* StartExpr() override { return start_; }
IntExpr* DurationExpr() override { return solver()->MakeIntConst(duration_); }
IntExpr* EndExpr() override {
return solver()->MakeSum(StartExpr(), duration_);
}
2020-10-29 14:25:39 +01:00
IntExpr* PerformedExpr() override { return performed_; }
IntExpr* SafeStartExpr(int64 unperformed_value) override {
return BuildSafeStartExpr(this, unperformed_value);
}
2020-10-29 14:25:39 +01:00
IntExpr* SafeDurationExpr(int64 unperformed_value) override {
return BuildSafeDurationExpr(this, unperformed_value);
}
2020-10-29 14:25:39 +01:00
IntExpr* SafeEndExpr(int64 unperformed_value) override {
return BuildSafeEndExpr(this, unperformed_value);
}
void Process() override { LOG(FATAL) << "Should not be here"; }
void Push() override { LOG(FATAL) << "Should not be here"; }
int64 StoredMin() const { return start_min_.Value(); }
int64 StoredMax() const { return start_max_.Value(); }
2020-10-22 23:36:58 +02:00
private:
2020-10-29 14:25:39 +01:00
IntVar* const start_;
int64 duration_;
2020-10-29 14:25:39 +01:00
IntVar* const performed_;
Rev<int64> start_min_;
Rev<int64> start_max_;
};
2020-10-29 14:25:39 +01:00
StartVarIntervalVar::StartVarIntervalVar(Solver* const s, IntVar* const start,
int64 duration,
2020-10-29 14:25:39 +01:00
IntVar* const performed,
const std::string& name)
2020-10-22 23:36:58 +02:00
: BaseIntervalVar(s, name),
start_(start),
duration_(duration),
performed_(performed),
start_min_(start->Min()),
start_max_(start->Max()) {}
int64 StartVarIntervalVar::StartMin() const {
2014-07-07 15:14:50 +00:00
DCHECK_EQ(performed_->Max(), 1);
return std::max(start_->Min(), start_min_.Value());
}
int64 StartVarIntervalVar::StartMax() const {
2014-07-07 15:14:50 +00:00
DCHECK_EQ(performed_->Max(), 1);
return std::min(start_->Max(), start_max_.Value());
}
void StartVarIntervalVar::SetStartMin(int64 m) {
if (performed_->Min() == 1) {
start_->SetMin(m);
} else {
start_min_.SetValue(solver(), std::max(m, start_min_.Value()));
if (start_min_.Value() > std::min(start_max_.Value(), start_->Max())) {
performed_->SetValue(0);
}
}
}
void StartVarIntervalVar::SetStartMax(int64 m) {
if (performed_->Min() == 1) {
start_->SetMax(m);
} else {
start_max_.SetValue(solver(), std::min(m, start_max_.Value()));
if (start_max_.Value() < std::max(start_min_.Value(), start_->Min())) {
performed_->SetValue(0);
}
}
}
void StartVarIntervalVar::SetStartRange(int64 mi, int64 ma) {
if (performed_->Min() == 1) {
start_->SetRange(mi, ma);
} else {
start_min_.SetValue(solver(), std::max(mi, start_min_.Value()));
start_max_.SetValue(solver(), std::min(ma, start_max_.Value()));
if (std::max(start_min_.Value(), start_->Min()) >
std::min(start_max_.Value(), start_->Max())) {
performed_->SetValue(0);
}
}
}
int64 StartVarIntervalVar::DurationMin() const {
2014-07-07 15:14:50 +00:00
DCHECK_EQ(performed_->Max(), 1);
return duration_;
}
int64 StartVarIntervalVar::DurationMax() const {
2014-07-07 15:14:50 +00:00
DCHECK_EQ(performed_->Max(), 1);
return duration_;
}
void StartVarIntervalVar::SetDurationMin(int64 m) {
if (m > duration_) {
SetPerformed(false);
}
}
void StartVarIntervalVar::SetDurationMax(int64 m) {
if (m < duration_) {
SetPerformed(false);
}
}
void StartVarIntervalVar::SetDurationRange(int64 mi, int64 ma) {
if (mi > duration_ || ma < duration_ || mi > ma) {
SetPerformed(false);
}
}
int64 StartVarIntervalVar::EndMin() const {
2014-07-07 15:50:43 +00:00
DCHECK_EQ(performed_->Max(), 1);
2015-02-04 12:04:59 +00:00
return CapAdd(StartMin(), duration_);
}
int64 StartVarIntervalVar::EndMax() const {
2014-07-07 15:50:43 +00:00
DCHECK_EQ(performed_->Max(), 1);
2015-02-04 12:04:59 +00:00
return CapAdd(StartMax(), duration_);
}
void StartVarIntervalVar::SetEndMin(int64 m) {
SetStartMin(CapSub(m, duration_));
}
void StartVarIntervalVar::SetEndMax(int64 m) {
SetStartMax(CapSub(m, duration_));
}
void StartVarIntervalVar::SetEndRange(int64 mi, int64 ma) {
SetStartRange(CapSub(mi, duration_), CapSub(ma, duration_));
}
bool StartVarIntervalVar::MustBePerformed() const {
return (performed_->Min() == 1);
}
bool StartVarIntervalVar::MayBePerformed() const {
return (performed_->Max() == 1);
}
void StartVarIntervalVar::SetPerformed(bool val) {
const bool was_bound = performed_->Bound();
performed_->SetValue(val);
if (val && !was_bound) {
start_->SetRange(start_min_.Value(), start_max_.Value());
}
}
2014-05-26 22:13:00 +00:00
std::string StartVarIntervalVar::DebugString() const {
2020-10-29 14:25:39 +01:00
const std::string& var_name = name();
if (performed_->Max() == 0) {
if (!var_name.empty()) {
dotnet: Remove reference to dotnet release command - Currently not implemented... Add abseil patch - Add patches/absl-config.cmake Makefile: Add abseil-cpp on unix - Force abseil-cpp SHA1 to 45221cc note: Just before the PR #136 which break all CMake Makefile: Add abseil-cpp on windows - Force abseil-cpp SHA1 to 45221cc note: Just before the PR #136 which break all CMake CMake: Add abseil-cpp - Force abseil-cpp SHA1 to 45221cc note: Just before the PR #136 which break all CMake port to absl: C++ Part - Fix warning with the use of ABSL_MUST_USE_RESULT > The macro must appear as the very first part of a function declaration or definition: ... Note: past advice was to place the macro after the argument list. src: dependencies/sources/abseil-cpp-master/absl/base/attributes.h:418 - Rename enum after windows clash - Remove non compact table constraints - Change index type from int64 to int in routing library - Fix file_nonport compilation on windows - Fix another naming conflict with windows (NO_ERROR is a macro) - Cleanup hash containers; work on sat internals - Add optional_boolean sub-proto Sync cpp examples with internal code - reenable issue173 after reducing number of loops port to absl: Python Part - Add back cp_model.INT32_MIN|MAX for examples Update Python examples - Add random_tsp.py - Run words_square example - Run magic_square in python tests port to absl: Java Part - Fix compilation of the new routing parameters in java - Protect some code from SWIG parsing Update Java Examples port to absl: .Net Part Update .Net examples work on sat internals; Add C++ CP-SAT CpModelBuilder API; update sample code and recipes to use the new API; sync with internal code Remove VS 2015 in Appveyor-CI - abseil-cpp does not support VS 2015... improve tables upgrade C++ sat examples to use the new API; work on sat internals update license dates rewrite jobshop_ft06_distance.py to use the CP-SAT solver rename last example revert last commit more work on SAT internals fix
2018-10-31 16:18:18 +01:00
return absl::StrFormat("%s(performed = false)", var_name);
} else {
return "IntervalVar(performed = false)";
}
} else {
2014-05-26 22:13:00 +00:00
std::string out;
if (!var_name.empty()) {
out = var_name + "(start = ";
} else {
out = "IntervalVar(start = ";
}
absl::StrAppendFormat(&out, "%s, duration = %d, performed = %s)",
start_->DebugString(), duration_,
performed_->DebugString());
return out;
}
}
class LinkStartVarIntervalVar : public Constraint {
2020-10-22 23:36:58 +02:00
public:
2020-10-29 14:25:39 +01:00
LinkStartVarIntervalVar(Solver* const solver,
StartVarIntervalVar* const interval,
IntVar* const start, IntVar* const performed)
2020-10-22 23:36:58 +02:00
: Constraint(solver),
interval_(interval),
start_(start),
performed_(performed) {}
~LinkStartVarIntervalVar() override {}
void Post() override {
2020-10-29 14:25:39 +01:00
Demon* const demon = MakeConstraintDemon0(
solver(), this, &LinkStartVarIntervalVar::PerformedBound,
"PerformedBound");
performed_->WhenBound(demon);
}
void InitialPropagate() override {
if (performed_->Bound()) {
PerformedBound();
}
}
void PerformedBound() {
if (performed_->Min() == 1) {
start_->SetRange(interval_->StoredMin(), interval_->StoredMax());
}
}
2020-10-22 23:36:58 +02:00
private:
2020-10-29 14:25:39 +01:00
StartVarIntervalVar* const interval_;
IntVar* const start_;
IntVar* const performed_;
};
2013-06-11 14:49:19 +00:00
// ----- FixedInterval -----
2010-09-15 12:42:33 +00:00
class FixedInterval : public IntervalVar {
2020-10-22 23:36:58 +02:00
public:
2020-10-29 14:25:39 +01:00
FixedInterval(Solver* const s, int64 start, int64 duration,
const std::string& name);
~FixedInterval() override {}
int64 StartMin() const override { return start_; }
int64 StartMax() const override { return start_; }
void SetStartMin(int64 m) override;
void SetStartMax(int64 m) override;
void SetStartRange(int64 mi, int64 ma) override;
int64 OldStartMin() const override { return start_; }
int64 OldStartMax() const override { return start_; }
2020-10-29 14:25:39 +01:00
void WhenStartRange(Demon* const d) override {}
void WhenStartBound(Demon* const d) override {}
int64 DurationMin() const override { return duration_; }
int64 DurationMax() const override { return duration_; }
void SetDurationMin(int64 m) override;
void SetDurationMax(int64 m) override;
void SetDurationRange(int64 mi, int64 ma) override;
int64 OldDurationMin() const override { return duration_; }
int64 OldDurationMax() const override { return duration_; }
2020-10-29 14:25:39 +01:00
void WhenDurationRange(Demon* const d) override {}
void WhenDurationBound(Demon* const d) override {}
int64 EndMin() const override { return start_ + duration_; }
int64 EndMax() const override { return start_ + duration_; }
void SetEndMin(int64 m) override;
void SetEndMax(int64 m) override;
void SetEndRange(int64 mi, int64 ma) override;
int64 OldEndMin() const override { return start_ + duration_; }
int64 OldEndMax() const override { return start_ + duration_; }
2020-10-29 14:25:39 +01:00
void WhenEndRange(Demon* const d) override {}
void WhenEndBound(Demon* const d) override {}
bool MustBePerformed() const override { return true; }
bool MayBePerformed() const override { return true; }
void SetPerformed(bool val) override;
bool WasPerformedBound() const override { return true; }
2020-10-29 14:25:39 +01:00
void WhenPerformedBound(Demon* const d) override {}
std::string DebugString() const override;
2020-10-29 14:25:39 +01:00
void Accept(ModelVisitor* const visitor) const override {
2013-06-11 14:49:19 +00:00
visitor->VisitIntervalVariable(this, "", 0, NullInterval());
2011-07-11 20:13:14 +00:00
}
2020-10-29 14:25:39 +01:00
IntExpr* StartExpr() override { return solver()->MakeIntConst(start_); }
IntExpr* DurationExpr() override { return solver()->MakeIntConst(duration_); }
IntExpr* EndExpr() override {
return solver()->MakeIntConst(start_ + duration_);
}
2020-10-29 14:25:39 +01:00
IntExpr* PerformedExpr() override { return solver()->MakeIntConst(1); }
IntExpr* SafeStartExpr(int64 unperformed_value) override {
return StartExpr();
}
2020-10-29 14:25:39 +01:00
IntExpr* SafeDurationExpr(int64 unperformed_value) override {
return DurationExpr();
}
2020-10-29 14:25:39 +01:00
IntExpr* SafeEndExpr(int64 unperformed_value) override { return EndExpr(); }
2020-10-22 23:36:58 +02:00
private:
2010-09-15 12:42:33 +00:00
const int64 start_;
const int64 duration_;
};
2020-10-29 14:25:39 +01:00
FixedInterval::FixedInterval(Solver* const s, int64 start, int64 duration,
const std::string& name)
2013-06-11 14:49:19 +00:00
: IntervalVar(s, name), start_(start), duration_(duration) {}
2010-09-15 12:42:33 +00:00
void FixedInterval::SetStartMin(int64 m) {
if (m > start_) {
solver()->Fail();
}
}
void FixedInterval::SetStartMax(int64 m) {
if (m < start_) {
solver()->Fail();
}
}
void FixedInterval::SetStartRange(int64 mi, int64 ma) {
if (mi > start_ || ma < start_) {
solver()->Fail();
}
}
void FixedInterval::SetDurationMin(int64 m) {
if (m > duration_) {
solver()->Fail();
}
}
void FixedInterval::SetDurationMax(int64 m) {
if (m < duration_) {
solver()->Fail();
}
}
void FixedInterval::SetEndMin(int64 m) {
if (m > start_ + duration_) {
solver()->Fail();
}
}
void FixedInterval::SetEndMax(int64 m) {
if (m < start_ + duration_) {
solver()->Fail();
}
}
void FixedInterval::SetEndRange(int64 mi, int64 ma) {
if (mi > start_ + duration_ || ma < start_ + duration_) {
solver()->Fail();
}
}
void FixedInterval::SetDurationRange(int64 mi, int64 ma) {
if (mi > duration_ || ma < duration_) {
solver()->Fail();
}
}
void FixedInterval::SetPerformed(bool val) {
if (!val) {
solver()->Fail();
}
}
std::string FixedInterval::DebugString() const {
std::string out;
2020-10-29 14:25:39 +01:00
const std::string& var_name = name();
2010-09-15 12:42:33 +00:00
if (!var_name.empty()) {
out = var_name + "(start = ";
} else {
out = "IntervalVar(start = ";
}
absl::StrAppendFormat(&out, "%d, duration = %d, performed = true)", start_,
duration_);
2010-09-15 12:42:33 +00:00
return out;
}
2013-06-11 14:49:19 +00:00
// ----- VariableDurationIntervalVar -----
class VariableDurationIntervalVar : public BaseIntervalVar {
2020-10-22 23:36:58 +02:00
public:
2020-10-29 14:25:39 +01:00
VariableDurationIntervalVar(Solver* const s, int64 start_min, int64 start_max,
2013-06-11 14:49:19 +00:00
int64 duration_min, int64 duration_max,
int64 end_min, int64 end_max, bool optional,
2020-10-29 14:25:39 +01:00
const std::string& name)
2013-06-11 14:49:19 +00:00
: BaseIntervalVar(s, name),
2016-08-05 15:38:20 +02:00
start_(s, this, std::max(start_min, CapSub(end_min, duration_max)),
std::min(start_max, CapSub(end_max, duration_min))),
duration_(s, this, std::max(duration_min, CapSub(end_min, start_max)),
std::min(duration_max, CapSub(end_max, start_min))),
end_(s, this, std::max(end_min, CapAdd(start_min, duration_min)),
std::min(end_max, CapAdd(start_max, duration_max))),
performed_(s, this, optional) {}
2013-06-11 14:49:19 +00:00
~VariableDurationIntervalVar() override {}
2013-06-11 14:49:19 +00:00
int64 StartMin() const override {
CHECK_EQ(performed_.Max(), 1);
2013-06-11 14:49:19 +00:00
return start_.Min();
}
int64 StartMax() const override {
CHECK_EQ(performed_.Max(), 1);
2013-06-11 14:49:19 +00:00
return start_.Max();
}
void SetStartMin(int64 m) override {
if (performed_.Max() == 1) {
start_.SetMin(m);
2013-06-11 14:49:19 +00:00
}
}
void SetStartMax(int64 m) override {
if (performed_.Max() == 1) {
start_.SetMax(m);
2013-06-11 14:49:19 +00:00
}
}
void SetStartRange(int64 mi, int64 ma) override {
if (performed_.Max() == 1) {
start_.SetRange(mi, ma);
2013-06-11 14:49:19 +00:00
}
}
int64 OldStartMin() const override {
CHECK_EQ(performed_.Max(), 1);
2013-06-11 14:49:19 +00:00
CHECK(in_process_);
return start_.OldMin();
2013-06-11 14:49:19 +00:00
}
int64 OldStartMax() const override {
CHECK_EQ(performed_.Max(), 1);
2013-06-11 14:49:19 +00:00
CHECK(in_process_);
return start_.OldMax();
2013-06-11 14:49:19 +00:00
}
2020-10-29 14:25:39 +01:00
void WhenStartRange(Demon* const d) override {
if (performed_.Max() == 1) {
2013-06-11 14:49:19 +00:00
start_.WhenRange(d);
}
}
2020-10-29 14:25:39 +01:00
void WhenStartBound(Demon* const d) override {
if (performed_.Max() == 1) {
2013-06-11 14:49:19 +00:00
start_.WhenBound(d);
}
}
int64 DurationMin() const override {
CHECK_EQ(performed_.Max(), 1);
2013-06-11 14:49:19 +00:00
return duration_.Min();
}
int64 DurationMax() const override {
CHECK_EQ(performed_.Max(), 1);
2013-06-11 14:49:19 +00:00
return duration_.Max();
}
void SetDurationMin(int64 m) override {
if (performed_.Max() == 1) {
duration_.SetMin(m);
2013-06-11 14:49:19 +00:00
}
}
void SetDurationMax(int64 m) override {
if (performed_.Max() == 1) {
duration_.SetMax(m);
2013-06-11 14:49:19 +00:00
}
}
void SetDurationRange(int64 mi, int64 ma) override {
if (performed_.Max() == 1) {
duration_.SetRange(mi, ma);
2013-06-11 14:49:19 +00:00
}
}
int64 OldDurationMin() const override {
CHECK_EQ(performed_.Max(), 1);
2013-06-11 14:49:19 +00:00
CHECK(in_process_);
return duration_.OldMin();
2013-06-11 14:49:19 +00:00
}
int64 OldDurationMax() const override {
CHECK_EQ(performed_.Max(), 1);
2013-06-11 14:49:19 +00:00
CHECK(in_process_);
return duration_.OldMax();
2013-06-11 14:49:19 +00:00
}
2020-10-29 14:25:39 +01:00
void WhenDurationRange(Demon* const d) override {
if (performed_.Max() == 1) {
2013-06-11 14:49:19 +00:00
duration_.WhenRange(d);
}
}
2020-10-29 14:25:39 +01:00
void WhenDurationBound(Demon* const d) override {
if (performed_.Max() == 1) {
2013-06-11 14:49:19 +00:00
duration_.WhenBound(d);
}
}
int64 EndMin() const override {
CHECK_EQ(performed_.Max(), 1);
2013-06-11 14:49:19 +00:00
return end_.Min();
}
int64 EndMax() const override {
CHECK_EQ(performed_.Max(), 1);
2013-06-11 14:49:19 +00:00
return end_.Max();
}
void SetEndMin(int64 m) override {
if (performed_.Max() == 1) {
end_.SetMin(m);
2013-06-11 14:49:19 +00:00
}
}
void SetEndMax(int64 m) override {
if (performed_.Max() == 1) {
end_.SetMax(m);
2013-06-11 14:49:19 +00:00
}
}
void SetEndRange(int64 mi, int64 ma) override {
if (performed_.Max() == 1) {
end_.SetRange(mi, ma);
2013-06-11 14:49:19 +00:00
}
}
int64 OldEndMin() const override {
CHECK_EQ(performed_.Max(), 1);
DCHECK(in_process_);
return end_.OldMin();
2013-06-11 14:49:19 +00:00
}
int64 OldEndMax() const override {
CHECK_EQ(performed_.Max(), 1);
DCHECK(in_process_);
return end_.OldMax();
2013-06-11 14:49:19 +00:00
}
2020-10-29 14:25:39 +01:00
void WhenEndRange(Demon* const d) override {
if (performed_.Max() == 1) {
2013-06-11 14:49:19 +00:00
end_.WhenRange(d);
}
}
2020-10-29 14:25:39 +01:00
void WhenEndBound(Demon* const d) override {
if (performed_.Max() == 1) {
2013-06-11 14:49:19 +00:00
end_.WhenBound(d);
}
}
bool MustBePerformed() const override { return (performed_.Min() == 1); }
2013-06-11 14:49:19 +00:00
bool MayBePerformed() const override { return (performed_.Max() == 1); }
2013-06-11 14:49:19 +00:00
void SetPerformed(bool val) override { performed_.SetValue(val); }
2013-06-11 14:49:19 +00:00
bool WasPerformedBound() const override {
2013-06-11 14:49:19 +00:00
CHECK(in_process_);
return performed_.OldMin() == performed_.OldMax();
2013-06-11 14:49:19 +00:00
}
2020-10-29 14:25:39 +01:00
void WhenPerformedBound(Demon* const d) override { performed_.WhenBound(d); }
2013-06-11 14:49:19 +00:00
void Process() override {
2013-06-11 14:49:19 +00:00
CHECK(!in_process_);
in_process_ = true;
start_.UpdatePostponedBounds();
duration_.UpdatePostponedBounds();
end_.UpdatePostponedBounds();
performed_.UpdatePostponedValue();
set_action_on_fail(cleaner_);
if (performed_.Max() == 1) {
2013-06-11 14:49:19 +00:00
start_.ProcessDemons();
duration_.ProcessDemons();
end_.ProcessDemons();
}
performed_.Process();
reset_action_on_fail();
CleanInProcess();
2013-06-11 14:49:19 +00:00
// TODO(user): Replace this enum by a callback.
start_.UpdatePreviousBounds();
start_.ApplyPostponedBounds(START);
duration_.UpdatePreviousBounds();
duration_.ApplyPostponedBounds(DURATION);
end_.UpdatePreviousBounds();
end_.ApplyPostponedBounds(END);
performed_.UpdatePreviousValueAndApplyPostponedValue();
2013-06-11 14:49:19 +00:00
}
std::string DebugString() const override {
2020-10-29 14:25:39 +01:00
const std::string& var_name = name();
if (performed_.Max() != 1) {
2013-07-29 02:49:12 +00:00
if (!var_name.empty()) {
dotnet: Remove reference to dotnet release command - Currently not implemented... Add abseil patch - Add patches/absl-config.cmake Makefile: Add abseil-cpp on unix - Force abseil-cpp SHA1 to 45221cc note: Just before the PR #136 which break all CMake Makefile: Add abseil-cpp on windows - Force abseil-cpp SHA1 to 45221cc note: Just before the PR #136 which break all CMake CMake: Add abseil-cpp - Force abseil-cpp SHA1 to 45221cc note: Just before the PR #136 which break all CMake port to absl: C++ Part - Fix warning with the use of ABSL_MUST_USE_RESULT > The macro must appear as the very first part of a function declaration or definition: ... Note: past advice was to place the macro after the argument list. src: dependencies/sources/abseil-cpp-master/absl/base/attributes.h:418 - Rename enum after windows clash - Remove non compact table constraints - Change index type from int64 to int in routing library - Fix file_nonport compilation on windows - Fix another naming conflict with windows (NO_ERROR is a macro) - Cleanup hash containers; work on sat internals - Add optional_boolean sub-proto Sync cpp examples with internal code - reenable issue173 after reducing number of loops port to absl: Python Part - Add back cp_model.INT32_MIN|MAX for examples Update Python examples - Add random_tsp.py - Run words_square example - Run magic_square in python tests port to absl: Java Part - Fix compilation of the new routing parameters in java - Protect some code from SWIG parsing Update Java Examples port to absl: .Net Part Update .Net examples work on sat internals; Add C++ CP-SAT CpModelBuilder API; update sample code and recipes to use the new API; sync with internal code Remove VS 2015 in Appveyor-CI - abseil-cpp does not support VS 2015... improve tables upgrade C++ sat examples to use the new API; work on sat internals update license dates rewrite jobshop_ft06_distance.py to use the CP-SAT solver rename last example revert last commit more work on SAT internals fix
2018-10-31 16:18:18 +01:00
return absl::StrFormat("%s(performed = false)", var_name);
2013-07-29 02:49:12 +00:00
} else {
return "IntervalVar(performed = false)";
}
2013-06-11 14:49:19 +00:00
} else {
std::string out;
2013-07-29 02:49:12 +00:00
if (!var_name.empty()) {
out = var_name + "(start = ";
} else {
out = "IntervalVar(start = ";
}
2013-06-11 14:49:19 +00:00
2020-10-22 23:36:58 +02:00
absl::StrAppendFormat(&out,
"%s, duration = %s, end = %s, performed = %s)",
start_.DebugString(), duration_.DebugString(),
end_.DebugString(), performed_.DebugString());
2013-07-29 02:49:12 +00:00
return out;
}
2013-06-11 14:49:19 +00:00
}
2020-10-29 14:25:39 +01:00
void Accept(ModelVisitor* const visitor) const override {
2013-06-11 14:49:19 +00:00
visitor->VisitIntervalVariable(this, "", 0, NullInterval());
}
2020-10-29 14:25:39 +01:00
IntExpr* StartExpr() override { return &start_; }
IntExpr* DurationExpr() override { return &duration_; }
IntExpr* EndExpr() override { return &end_; }
IntExpr* PerformedExpr() override { return &performed_; }
IntExpr* SafeStartExpr(int64 unperformed_value) override {
return BuildSafeStartExpr(this, unperformed_value);
}
2020-10-29 14:25:39 +01:00
IntExpr* SafeDurationExpr(int64 unperformed_value) override {
return BuildSafeDurationExpr(this, unperformed_value);
}
2020-10-29 14:25:39 +01:00
IntExpr* SafeEndExpr(int64 unperformed_value) override {
return BuildSafeEndExpr(this, unperformed_value);
}
2020-10-22 23:36:58 +02:00
private:
void Push() override {
2013-06-11 14:49:19 +00:00
DCHECK(!in_process_);
if (performed_.Max() == 1) {
2013-06-11 14:49:19 +00:00
// Performs the intersection on all intervals before pushing the
// variable onto the queue. This way, we make sure the interval variable
// is always in a consistent minimal state.
start_.SetRange(CapSub(end_.Min(), duration_.Max()),
CapSub(end_.Max(), duration_.Min()));
duration_.SetRange(CapSub(end_.Min(), start_.Max()),
CapSub(end_.Max(), start_.Min()));
end_.SetRange(CapAdd(start_.Min(), duration_.Min()),
CapAdd(start_.Max(), duration_.Max()));
2013-06-11 14:49:19 +00:00
}
EnqueueVar(&handler_);
DCHECK(!in_process_);
}
RangeVar start_;
RangeVar duration_;
RangeVar end_;
PerformedVar performed_;
2013-06-11 14:49:19 +00:00
};
// ----- Base synced interval var -----
class FixedDurationSyncedIntervalVar : public IntervalVar {
2020-10-22 23:36:58 +02:00
public:
2020-10-29 14:25:39 +01:00
FixedDurationSyncedIntervalVar(IntervalVar* const t, int64 duration,
int64 offset, const std::string& name)
2020-10-22 23:36:58 +02:00
: IntervalVar(t->solver(), name),
t_(t),
duration_(duration),
2013-06-11 14:49:19 +00:00
offset_(offset) {}
~FixedDurationSyncedIntervalVar() override {}
int64 DurationMin() const override { return duration_; }
int64 DurationMax() const override { return duration_; }
void SetDurationMin(int64 m) override {
2013-06-11 14:49:19 +00:00
if (m > duration_) {
solver()->Fail();
}
}
void SetDurationMax(int64 m) override {
2013-06-11 14:49:19 +00:00
if (m < duration_) {
solver()->Fail();
}
}
void SetDurationRange(int64 mi, int64 ma) override {
2013-06-11 14:49:19 +00:00
if (mi > duration_ || ma < duration_ || mi > ma) {
solver()->Fail();
}
}
int64 OldDurationMin() const override { return duration_; }
int64 OldDurationMax() const override { return duration_; }
2020-10-29 14:25:39 +01:00
void WhenDurationRange(Demon* const d) override {}
void WhenDurationBound(Demon* const d) override {}
int64 EndMin() const override { return CapAdd(StartMin(), duration_); }
int64 EndMax() const override { return CapAdd(StartMax(), duration_); }
void SetEndMin(int64 m) override { SetStartMin(CapSub(m, duration_)); }
void SetEndMax(int64 m) override { SetStartMax(CapSub(m, duration_)); }
void SetEndRange(int64 mi, int64 ma) override {
2013-06-11 14:49:19 +00:00
SetStartRange(CapSub(mi, duration_), CapSub(ma, duration_));
}
int64 OldEndMin() const override { return CapAdd(OldStartMin(), duration_); }
int64 OldEndMax() const override { return CapAdd(OldStartMax(), duration_); }
2020-10-29 14:25:39 +01:00
void WhenEndRange(Demon* const d) override { WhenStartRange(d); }
void WhenEndBound(Demon* const d) override { WhenStartBound(d); }
bool MustBePerformed() const override { return t_->MustBePerformed(); }
bool MayBePerformed() const override { return t_->MayBePerformed(); }
void SetPerformed(bool val) override { t_->SetPerformed(val); }
bool WasPerformedBound() const override { return t_->WasPerformedBound(); }
2020-10-29 14:25:39 +01:00
void WhenPerformedBound(Demon* const d) override {
t_->WhenPerformedBound(d);
}
2013-06-11 14:49:19 +00:00
2020-10-22 23:36:58 +02:00
protected:
2020-10-29 14:25:39 +01:00
IntervalVar* const t_;
2013-06-11 14:49:19 +00:00
const int64 duration_;
const int64 offset_;
2020-10-22 23:36:58 +02:00
private:
2013-06-11 14:49:19 +00:00
DISALLOW_COPY_AND_ASSIGN(FixedDurationSyncedIntervalVar);
};
// ----- Fixed duration interval var synced on start -----
class FixedDurationIntervalVarStartSyncedOnStart
: public FixedDurationSyncedIntervalVar {
2020-10-22 23:36:58 +02:00
public:
2020-10-29 14:25:39 +01:00
FixedDurationIntervalVarStartSyncedOnStart(IntervalVar* const t,
2013-06-11 14:49:19 +00:00
int64 duration, int64 offset)
: FixedDurationSyncedIntervalVar(
t, duration, offset,
dotnet: Remove reference to dotnet release command - Currently not implemented... Add abseil patch - Add patches/absl-config.cmake Makefile: Add abseil-cpp on unix - Force abseil-cpp SHA1 to 45221cc note: Just before the PR #136 which break all CMake Makefile: Add abseil-cpp on windows - Force abseil-cpp SHA1 to 45221cc note: Just before the PR #136 which break all CMake CMake: Add abseil-cpp - Force abseil-cpp SHA1 to 45221cc note: Just before the PR #136 which break all CMake port to absl: C++ Part - Fix warning with the use of ABSL_MUST_USE_RESULT > The macro must appear as the very first part of a function declaration or definition: ... Note: past advice was to place the macro after the argument list. src: dependencies/sources/abseil-cpp-master/absl/base/attributes.h:418 - Rename enum after windows clash - Remove non compact table constraints - Change index type from int64 to int in routing library - Fix file_nonport compilation on windows - Fix another naming conflict with windows (NO_ERROR is a macro) - Cleanup hash containers; work on sat internals - Add optional_boolean sub-proto Sync cpp examples with internal code - reenable issue173 after reducing number of loops port to absl: Python Part - Add back cp_model.INT32_MIN|MAX for examples Update Python examples - Add random_tsp.py - Run words_square example - Run magic_square in python tests port to absl: Java Part - Fix compilation of the new routing parameters in java - Protect some code from SWIG parsing Update Java Examples port to absl: .Net Part Update .Net examples work on sat internals; Add C++ CP-SAT CpModelBuilder API; update sample code and recipes to use the new API; sync with internal code Remove VS 2015 in Appveyor-CI - abseil-cpp does not support VS 2015... improve tables upgrade C++ sat examples to use the new API; work on sat internals update license dates rewrite jobshop_ft06_distance.py to use the CP-SAT solver rename last example revert last commit more work on SAT internals fix
2018-10-31 16:18:18 +01:00
absl::StrFormat(
"IntervalStartSyncedOnStart(%s, duration = %d, offset = %d)",
dotnet: Remove reference to dotnet release command - Currently not implemented... Add abseil patch - Add patches/absl-config.cmake Makefile: Add abseil-cpp on unix - Force abseil-cpp SHA1 to 45221cc note: Just before the PR #136 which break all CMake Makefile: Add abseil-cpp on windows - Force abseil-cpp SHA1 to 45221cc note: Just before the PR #136 which break all CMake CMake: Add abseil-cpp - Force abseil-cpp SHA1 to 45221cc note: Just before the PR #136 which break all CMake port to absl: C++ Part - Fix warning with the use of ABSL_MUST_USE_RESULT > The macro must appear as the very first part of a function declaration or definition: ... Note: past advice was to place the macro after the argument list. src: dependencies/sources/abseil-cpp-master/absl/base/attributes.h:418 - Rename enum after windows clash - Remove non compact table constraints - Change index type from int64 to int in routing library - Fix file_nonport compilation on windows - Fix another naming conflict with windows (NO_ERROR is a macro) - Cleanup hash containers; work on sat internals - Add optional_boolean sub-proto Sync cpp examples with internal code - reenable issue173 after reducing number of loops port to absl: Python Part - Add back cp_model.INT32_MIN|MAX for examples Update Python examples - Add random_tsp.py - Run words_square example - Run magic_square in python tests port to absl: Java Part - Fix compilation of the new routing parameters in java - Protect some code from SWIG parsing Update Java Examples port to absl: .Net Part Update .Net examples work on sat internals; Add C++ CP-SAT CpModelBuilder API; update sample code and recipes to use the new API; sync with internal code Remove VS 2015 in Appveyor-CI - abseil-cpp does not support VS 2015... improve tables upgrade C++ sat examples to use the new API; work on sat internals update license dates rewrite jobshop_ft06_distance.py to use the CP-SAT solver rename last example revert last commit more work on SAT internals fix
2018-10-31 16:18:18 +01:00
t->name(), duration, offset)) {}
~FixedDurationIntervalVarStartSyncedOnStart() override {}
int64 StartMin() const override { return CapAdd(t_->StartMin(), offset_); }
int64 StartMax() const override { return CapAdd(t_->StartMax(), offset_); }
void SetStartMin(int64 m) override { t_->SetStartMin(CapSub(m, offset_)); }
void SetStartMax(int64 m) override { t_->SetStartMax(CapSub(m, offset_)); }
void SetStartRange(int64 mi, int64 ma) override {
2013-06-11 14:49:19 +00:00
t_->SetStartRange(CapSub(mi, offset_), CapSub(ma, offset_));
}
int64 OldStartMin() const override {
2013-06-11 14:49:19 +00:00
return CapAdd(t_->OldStartMin(), offset_);
}
int64 OldStartMax() const override {
2013-06-11 14:49:19 +00:00
return CapAdd(t_->OldStartMax(), offset_);
}
2020-10-29 14:25:39 +01:00
void WhenStartRange(Demon* const d) override { t_->WhenStartRange(d); }
void WhenStartBound(Demon* const d) override { t_->WhenStartBound(d); }
IntExpr* StartExpr() override {
return solver()->MakeSum(t_->StartExpr(), offset_);
}
2020-10-29 14:25:39 +01:00
IntExpr* DurationExpr() override { return solver()->MakeIntConst(duration_); }
IntExpr* EndExpr() override {
return solver()->MakeSum(t_->StartExpr(), offset_ + duration_);
}
2020-10-29 14:25:39 +01:00
IntExpr* PerformedExpr() override { return t_->PerformedExpr(); }
// 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.
2020-10-29 14:25:39 +01:00
IntExpr* SafeStartExpr(int64 unperformed_value) override {
return BuildSafeStartExpr(t_, unperformed_value);
}
2020-10-29 14:25:39 +01:00
IntExpr* SafeDurationExpr(int64 unperformed_value) override {
return BuildSafeDurationExpr(t_, unperformed_value);
}
2020-10-29 14:25:39 +01:00
IntExpr* SafeEndExpr(int64 unperformed_value) override {
return BuildSafeEndExpr(t_, unperformed_value);
}
2020-10-29 14:25:39 +01:00
void Accept(ModelVisitor* const visitor) const override {
2013-06-11 14:49:19 +00:00
visitor->VisitIntervalVariable(
this, ModelVisitor::kStartSyncOnStartOperation, offset_, t_);
}
std::string DebugString() const override {
dotnet: Remove reference to dotnet release command - Currently not implemented... Add abseil patch - Add patches/absl-config.cmake Makefile: Add abseil-cpp on unix - Force abseil-cpp SHA1 to 45221cc note: Just before the PR #136 which break all CMake Makefile: Add abseil-cpp on windows - Force abseil-cpp SHA1 to 45221cc note: Just before the PR #136 which break all CMake CMake: Add abseil-cpp - Force abseil-cpp SHA1 to 45221cc note: Just before the PR #136 which break all CMake port to absl: C++ Part - Fix warning with the use of ABSL_MUST_USE_RESULT > The macro must appear as the very first part of a function declaration or definition: ... Note: past advice was to place the macro after the argument list. src: dependencies/sources/abseil-cpp-master/absl/base/attributes.h:418 - Rename enum after windows clash - Remove non compact table constraints - Change index type from int64 to int in routing library - Fix file_nonport compilation on windows - Fix another naming conflict with windows (NO_ERROR is a macro) - Cleanup hash containers; work on sat internals - Add optional_boolean sub-proto Sync cpp examples with internal code - reenable issue173 after reducing number of loops port to absl: Python Part - Add back cp_model.INT32_MIN|MAX for examples Update Python examples - Add random_tsp.py - Run words_square example - Run magic_square in python tests port to absl: Java Part - Fix compilation of the new routing parameters in java - Protect some code from SWIG parsing Update Java Examples port to absl: .Net Part Update .Net examples work on sat internals; Add C++ CP-SAT CpModelBuilder API; update sample code and recipes to use the new API; sync with internal code Remove VS 2015 in Appveyor-CI - abseil-cpp does not support VS 2015... improve tables upgrade C++ sat examples to use the new API; work on sat internals update license dates rewrite jobshop_ft06_distance.py to use the CP-SAT solver rename last example revert last commit more work on SAT internals fix
2018-10-31 16:18:18 +01:00
return absl::StrFormat(
"IntervalStartSyncedOnStart(%s, duration = %d, offset = %d)",
dotnet: Remove reference to dotnet release command - Currently not implemented... Add abseil patch - Add patches/absl-config.cmake Makefile: Add abseil-cpp on unix - Force abseil-cpp SHA1 to 45221cc note: Just before the PR #136 which break all CMake Makefile: Add abseil-cpp on windows - Force abseil-cpp SHA1 to 45221cc note: Just before the PR #136 which break all CMake CMake: Add abseil-cpp - Force abseil-cpp SHA1 to 45221cc note: Just before the PR #136 which break all CMake port to absl: C++ Part - Fix warning with the use of ABSL_MUST_USE_RESULT > The macro must appear as the very first part of a function declaration or definition: ... Note: past advice was to place the macro after the argument list. src: dependencies/sources/abseil-cpp-master/absl/base/attributes.h:418 - Rename enum after windows clash - Remove non compact table constraints - Change index type from int64 to int in routing library - Fix file_nonport compilation on windows - Fix another naming conflict with windows (NO_ERROR is a macro) - Cleanup hash containers; work on sat internals - Add optional_boolean sub-proto Sync cpp examples with internal code - reenable issue173 after reducing number of loops port to absl: Python Part - Add back cp_model.INT32_MIN|MAX for examples Update Python examples - Add random_tsp.py - Run words_square example - Run magic_square in python tests port to absl: Java Part - Fix compilation of the new routing parameters in java - Protect some code from SWIG parsing Update Java Examples port to absl: .Net Part Update .Net examples work on sat internals; Add C++ CP-SAT CpModelBuilder API; update sample code and recipes to use the new API; sync with internal code Remove VS 2015 in Appveyor-CI - abseil-cpp does not support VS 2015... improve tables upgrade C++ sat examples to use the new API; work on sat internals update license dates rewrite jobshop_ft06_distance.py to use the CP-SAT solver rename last example revert last commit more work on SAT internals fix
2018-10-31 16:18:18 +01:00
t_->DebugString(), duration_, offset_);
2013-06-11 14:49:19 +00:00
}
};
// ----- Fixed duration interval start synced on end -----
class FixedDurationIntervalVarStartSyncedOnEnd
: public FixedDurationSyncedIntervalVar {
2020-10-22 23:36:58 +02:00
public:
2020-10-29 14:25:39 +01:00
FixedDurationIntervalVarStartSyncedOnEnd(IntervalVar* const t, int64 duration,
2013-06-11 14:49:19 +00:00
int64 offset)
: FixedDurationSyncedIntervalVar(
t, duration, offset,
dotnet: Remove reference to dotnet release command - Currently not implemented... Add abseil patch - Add patches/absl-config.cmake Makefile: Add abseil-cpp on unix - Force abseil-cpp SHA1 to 45221cc note: Just before the PR #136 which break all CMake Makefile: Add abseil-cpp on windows - Force abseil-cpp SHA1 to 45221cc note: Just before the PR #136 which break all CMake CMake: Add abseil-cpp - Force abseil-cpp SHA1 to 45221cc note: Just before the PR #136 which break all CMake port to absl: C++ Part - Fix warning with the use of ABSL_MUST_USE_RESULT > The macro must appear as the very first part of a function declaration or definition: ... Note: past advice was to place the macro after the argument list. src: dependencies/sources/abseil-cpp-master/absl/base/attributes.h:418 - Rename enum after windows clash - Remove non compact table constraints - Change index type from int64 to int in routing library - Fix file_nonport compilation on windows - Fix another naming conflict with windows (NO_ERROR is a macro) - Cleanup hash containers; work on sat internals - Add optional_boolean sub-proto Sync cpp examples with internal code - reenable issue173 after reducing number of loops port to absl: Python Part - Add back cp_model.INT32_MIN|MAX for examples Update Python examples - Add random_tsp.py - Run words_square example - Run magic_square in python tests port to absl: Java Part - Fix compilation of the new routing parameters in java - Protect some code from SWIG parsing Update Java Examples port to absl: .Net Part Update .Net examples work on sat internals; Add C++ CP-SAT CpModelBuilder API; update sample code and recipes to use the new API; sync with internal code Remove VS 2015 in Appveyor-CI - abseil-cpp does not support VS 2015... improve tables upgrade C++ sat examples to use the new API; work on sat internals update license dates rewrite jobshop_ft06_distance.py to use the CP-SAT solver rename last example revert last commit more work on SAT internals fix
2018-10-31 16:18:18 +01:00
absl::StrFormat(
"IntervalStartSyncedOnEnd(%s, duration = %d, offset = %d)",
dotnet: Remove reference to dotnet release command - Currently not implemented... Add abseil patch - Add patches/absl-config.cmake Makefile: Add abseil-cpp on unix - Force abseil-cpp SHA1 to 45221cc note: Just before the PR #136 which break all CMake Makefile: Add abseil-cpp on windows - Force abseil-cpp SHA1 to 45221cc note: Just before the PR #136 which break all CMake CMake: Add abseil-cpp - Force abseil-cpp SHA1 to 45221cc note: Just before the PR #136 which break all CMake port to absl: C++ Part - Fix warning with the use of ABSL_MUST_USE_RESULT > The macro must appear as the very first part of a function declaration or definition: ... Note: past advice was to place the macro after the argument list. src: dependencies/sources/abseil-cpp-master/absl/base/attributes.h:418 - Rename enum after windows clash - Remove non compact table constraints - Change index type from int64 to int in routing library - Fix file_nonport compilation on windows - Fix another naming conflict with windows (NO_ERROR is a macro) - Cleanup hash containers; work on sat internals - Add optional_boolean sub-proto Sync cpp examples with internal code - reenable issue173 after reducing number of loops port to absl: Python Part - Add back cp_model.INT32_MIN|MAX for examples Update Python examples - Add random_tsp.py - Run words_square example - Run magic_square in python tests port to absl: Java Part - Fix compilation of the new routing parameters in java - Protect some code from SWIG parsing Update Java Examples port to absl: .Net Part Update .Net examples work on sat internals; Add C++ CP-SAT CpModelBuilder API; update sample code and recipes to use the new API; sync with internal code Remove VS 2015 in Appveyor-CI - abseil-cpp does not support VS 2015... improve tables upgrade C++ sat examples to use the new API; work on sat internals update license dates rewrite jobshop_ft06_distance.py to use the CP-SAT solver rename last example revert last commit more work on SAT internals fix
2018-10-31 16:18:18 +01:00
t->name(), duration, offset)) {}
~FixedDurationIntervalVarStartSyncedOnEnd() override {}
int64 StartMin() const override { return CapAdd(t_->EndMin(), offset_); }
int64 StartMax() const override { return CapAdd(t_->EndMax(), offset_); }
void SetStartMin(int64 m) override { t_->SetEndMin(CapSub(m, offset_)); }
void SetStartMax(int64 m) override { t_->SetEndMax(CapSub(m, offset_)); }
void SetStartRange(int64 mi, int64 ma) override {
2013-06-11 14:49:19 +00:00
t_->SetEndRange(CapSub(mi, offset_), CapSub(ma, offset_));
}
int64 OldStartMin() const override {
return CapAdd(t_->OldEndMin(), offset_);
}
int64 OldStartMax() const override {
return CapAdd(t_->OldEndMax(), offset_);
}
2020-10-29 14:25:39 +01:00
void WhenStartRange(Demon* const d) override { t_->WhenEndRange(d); }
void WhenStartBound(Demon* const d) override { t_->WhenEndBound(d); }
IntExpr* StartExpr() override {
return solver()->MakeSum(t_->EndExpr(), offset_);
}
2020-10-29 14:25:39 +01:00
IntExpr* DurationExpr() override { return solver()->MakeIntConst(duration_); }
IntExpr* EndExpr() override {
return solver()->MakeSum(t_->EndExpr(), offset_ + duration_);
}
2020-10-29 14:25:39 +01:00
IntExpr* PerformedExpr() override { return t_->PerformedExpr(); }
// 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.
2020-10-29 14:25:39 +01:00
IntExpr* SafeStartExpr(int64 unperformed_value) override {
return BuildSafeStartExpr(t_, unperformed_value);
}
2020-10-29 14:25:39 +01:00
IntExpr* SafeDurationExpr(int64 unperformed_value) override {
return BuildSafeDurationExpr(t_, unperformed_value);
}
2020-10-29 14:25:39 +01:00
IntExpr* SafeEndExpr(int64 unperformed_value) override {
return BuildSafeEndExpr(t_, unperformed_value);
}
2020-10-29 14:25:39 +01:00
void Accept(ModelVisitor* const visitor) const override {
2013-06-11 14:49:19 +00:00
visitor->VisitIntervalVariable(this, ModelVisitor::kStartSyncOnEndOperation,
offset_, t_);
}
std::string DebugString() const override {
dotnet: Remove reference to dotnet release command - Currently not implemented... Add abseil patch - Add patches/absl-config.cmake Makefile: Add abseil-cpp on unix - Force abseil-cpp SHA1 to 45221cc note: Just before the PR #136 which break all CMake Makefile: Add abseil-cpp on windows - Force abseil-cpp SHA1 to 45221cc note: Just before the PR #136 which break all CMake CMake: Add abseil-cpp - Force abseil-cpp SHA1 to 45221cc note: Just before the PR #136 which break all CMake port to absl: C++ Part - Fix warning with the use of ABSL_MUST_USE_RESULT > The macro must appear as the very first part of a function declaration or definition: ... Note: past advice was to place the macro after the argument list. src: dependencies/sources/abseil-cpp-master/absl/base/attributes.h:418 - Rename enum after windows clash - Remove non compact table constraints - Change index type from int64 to int in routing library - Fix file_nonport compilation on windows - Fix another naming conflict with windows (NO_ERROR is a macro) - Cleanup hash containers; work on sat internals - Add optional_boolean sub-proto Sync cpp examples with internal code - reenable issue173 after reducing number of loops port to absl: Python Part - Add back cp_model.INT32_MIN|MAX for examples Update Python examples - Add random_tsp.py - Run words_square example - Run magic_square in python tests port to absl: Java Part - Fix compilation of the new routing parameters in java - Protect some code from SWIG parsing Update Java Examples port to absl: .Net Part Update .Net examples work on sat internals; Add C++ CP-SAT CpModelBuilder API; update sample code and recipes to use the new API; sync with internal code Remove VS 2015 in Appveyor-CI - abseil-cpp does not support VS 2015... improve tables upgrade C++ sat examples to use the new API; work on sat internals update license dates rewrite jobshop_ft06_distance.py to use the CP-SAT solver rename last example revert last commit more work on SAT internals fix
2018-10-31 16:18:18 +01:00
return absl::StrFormat(
"IntervalStartSyncedOnEnd(%s, duration = %d, offset = %d)",
dotnet: Remove reference to dotnet release command - Currently not implemented... Add abseil patch - Add patches/absl-config.cmake Makefile: Add abseil-cpp on unix - Force abseil-cpp SHA1 to 45221cc note: Just before the PR #136 which break all CMake Makefile: Add abseil-cpp on windows - Force abseil-cpp SHA1 to 45221cc note: Just before the PR #136 which break all CMake CMake: Add abseil-cpp - Force abseil-cpp SHA1 to 45221cc note: Just before the PR #136 which break all CMake port to absl: C++ Part - Fix warning with the use of ABSL_MUST_USE_RESULT > The macro must appear as the very first part of a function declaration or definition: ... Note: past advice was to place the macro after the argument list. src: dependencies/sources/abseil-cpp-master/absl/base/attributes.h:418 - Rename enum after windows clash - Remove non compact table constraints - Change index type from int64 to int in routing library - Fix file_nonport compilation on windows - Fix another naming conflict with windows (NO_ERROR is a macro) - Cleanup hash containers; work on sat internals - Add optional_boolean sub-proto Sync cpp examples with internal code - reenable issue173 after reducing number of loops port to absl: Python Part - Add back cp_model.INT32_MIN|MAX for examples Update Python examples - Add random_tsp.py - Run words_square example - Run magic_square in python tests port to absl: Java Part - Fix compilation of the new routing parameters in java - Protect some code from SWIG parsing Update Java Examples port to absl: .Net Part Update .Net examples work on sat internals; Add C++ CP-SAT CpModelBuilder API; update sample code and recipes to use the new API; sync with internal code Remove VS 2015 in Appveyor-CI - abseil-cpp does not support VS 2015... improve tables upgrade C++ sat examples to use the new API; work on sat internals update license dates rewrite jobshop_ft06_distance.py to use the CP-SAT solver rename last example revert last commit more work on SAT internals fix
2018-10-31 16:18:18 +01:00
t_->DebugString(), duration_, offset_);
2013-06-11 14:49:19 +00:00
}
};
2020-10-22 23:36:58 +02:00
} // namespace
// ----- API -----
2020-10-29 14:25:39 +01:00
IntervalVar* Solver::MakeMirrorInterval(IntervalVar* const interval_var) {
return RegisterIntervalVar(
RevAlloc(new MirrorIntervalVar(this, interval_var)));
}
2020-10-29 14:25:39 +01:00
IntervalVar* Solver::MakeIntervalRelaxedMax(IntervalVar* const interval_var) {
2012-08-31 20:55:03 +00:00
if (interval_var->MustBePerformed()) {
return interval_var;
} else {
return RegisterIntervalVar(
RevAlloc(new IntervalVarRelaxedMax(interval_var)));
}
}
2020-10-29 14:25:39 +01:00
IntervalVar* Solver::MakeIntervalRelaxedMin(IntervalVar* const interval_var) {
2012-08-31 20:55:03 +00:00
if (interval_var->MustBePerformed()) {
return interval_var;
} else {
return RegisterIntervalVar(
RevAlloc(new IntervalVarRelaxedMin(interval_var)));
}
}
2020-10-29 14:25:39 +01:00
void IntervalVar::WhenAnything(Demon* const d) {
2012-08-31 20:55:03 +00:00
WhenStartRange(d);
WhenDurationRange(d);
WhenEndRange(d);
WhenPerformedBound(d);
}
2010-09-15 12:42:33 +00:00
2020-10-29 14:25:39 +01:00
IntervalVar* Solver::MakeFixedInterval(int64 start, int64 duration,
const std::string& name) {
2010-09-15 12:42:33 +00:00
return RevAlloc(new FixedInterval(this, start, duration, name));
}
2020-10-29 14:25:39 +01:00
IntervalVar* Solver::MakeFixedDurationIntervalVar(int64 start_min,
2010-09-15 12:42:33 +00:00
int64 start_max,
2013-06-11 14:49:19 +00:00
int64 duration, bool optional,
2020-10-29 14:25:39 +01:00
const std::string& name) {
2010-09-15 12:42:33 +00:00
if (start_min == start_max && !optional) {
return MakeFixedInterval(start_min, duration, name);
} else if (!optional) {
2013-06-11 14:49:19 +00:00
return RegisterIntervalVar(RevAlloc(new FixedDurationPerformedIntervalVar(
this, start_min, start_max, duration, name)));
}
2013-06-11 14:49:19 +00:00
return RegisterIntervalVar(RevAlloc(new FixedDurationIntervalVar(
this, start_min, start_max, duration, optional, name)));
2010-09-15 12:42:33 +00:00
}
2016-11-29 13:40:04 +01:00
void Solver::MakeFixedDurationIntervalVarArray(
int count, int64 start_min, int64 start_max, int64 duration, bool optional,
2020-10-29 14:25:39 +01:00
const std::string& name, std::vector<IntervalVar*>* array) {
CHECK_GT(count, 0);
CHECK(array != nullptr);
array->clear();
for (int i = 0; i < count; ++i) {
const std::string var_name = absl::StrCat(name, i);
2013-06-11 14:49:19 +00:00
array->push_back(MakeFixedDurationIntervalVar(
start_min, start_max, duration, optional, var_name));
}
}
2020-10-29 14:25:39 +01:00
IntervalVar* Solver::MakeFixedDurationIntervalVar(IntVar* const start_variable,
int64 duration,
2020-10-29 14:25:39 +01:00
const std::string& name) {
CHECK(start_variable != nullptr);
CHECK_GE(duration, 0);
2013-07-29 02:49:12 +00:00
return RegisterIntervalVar(RevAlloc(
new StartVarPerformedIntervalVar(this, start_variable, duration, name)));
}
// Creates an interval var with a fixed duration, and performed var.
// The duration must be greater than 0.
2020-10-29 14:25:39 +01:00
IntervalVar* Solver::MakeFixedDurationIntervalVar(
IntVar* const start_variable, int64 duration,
IntVar* const performed_variable, const std::string& name) {
CHECK(start_variable != nullptr);
CHECK(performed_variable != nullptr);
CHECK_GE(duration, 0);
if (!performed_variable->Bound()) {
2020-10-29 14:25:39 +01:00
StartVarIntervalVar* const interval =
reinterpret_cast<StartVarIntervalVar*>(
RegisterIntervalVar(RevAlloc(new StartVarIntervalVar(
this, start_variable, duration, performed_variable, name))));
AddConstraint(RevAlloc(new LinkStartVarIntervalVar(
this, interval, start_variable, performed_variable)));
return interval;
} else if (performed_variable->Min() == 1) {
return RegisterIntervalVar(RevAlloc(new StartVarPerformedIntervalVar(
this, start_variable, duration, name)));
}
return nullptr;
}
void Solver::MakeFixedDurationIntervalVarArray(
2020-10-29 14:25:39 +01:00
const std::vector<IntVar*>& start_variables, int64 duration,
const std::string& name, std::vector<IntervalVar*>* array) {
CHECK(array != nullptr);
array->clear();
for (int i = 0; i < start_variables.size(); ++i) {
const std::string var_name = absl::StrCat(name, i);
2013-06-11 14:49:19 +00:00
array->push_back(
MakeFixedDurationIntervalVar(start_variables[i], duration, var_name));
}
}
2014-07-09 11:10:20 +00:00
// This method fills the vector with interval variables built with
// the corresponding start variables.
void Solver::MakeFixedDurationIntervalVarArray(
2020-10-29 14:25:39 +01:00
const std::vector<IntVar*>& start_variables,
const std::vector<int64>& durations, const std::string& name,
std::vector<IntervalVar*>* array) {
CHECK(array != nullptr);
CHECK_EQ(start_variables.size(), durations.size());
array->clear();
for (int i = 0; i < start_variables.size(); ++i) {
const std::string var_name = absl::StrCat(name, i);
array->push_back(MakeFixedDurationIntervalVar(start_variables[i],
2013-06-11 14:49:19 +00:00
durations[i], var_name));
}
}
void Solver::MakeFixedDurationIntervalVarArray(
2020-10-29 14:25:39 +01:00
const std::vector<IntVar*>& start_variables,
const std::vector<int>& durations, const std::string& name,
std::vector<IntervalVar*>* array) {
CHECK(array != nullptr);
CHECK_EQ(start_variables.size(), durations.size());
array->clear();
for (int i = 0; i < start_variables.size(); ++i) {
const std::string var_name = absl::StrCat(name, i);
array->push_back(MakeFixedDurationIntervalVar(start_variables[i],
2013-06-11 14:49:19 +00:00
durations[i], var_name));
}
}
void Solver::MakeFixedDurationIntervalVarArray(
2020-10-29 14:25:39 +01:00
const std::vector<IntVar*>& start_variables,
const std::vector<int>& durations,
const std::vector<IntVar*>& performed_variables, const std::string& name,
std::vector<IntervalVar*>* array) {
CHECK(array != nullptr);
array->clear();
for (int i = 0; i < start_variables.size(); ++i) {
const std::string var_name = absl::StrCat(name, i);
array->push_back(MakeFixedDurationIntervalVar(
start_variables[i], durations[i], performed_variables[i], var_name));
}
}
void Solver::MakeFixedDurationIntervalVarArray(
2020-10-29 14:25:39 +01:00
const std::vector<IntVar*>& start_variables,
const std::vector<int64>& durations,
const std::vector<IntVar*>& performed_variables, const std::string& name,
std::vector<IntervalVar*>* array) {
CHECK(array != nullptr);
array->clear();
for (int i = 0; i < start_variables.size(); ++i) {
const std::string var_name = absl::StrCat(name, i);
array->push_back(MakeFixedDurationIntervalVar(
start_variables[i], durations[i], performed_variables[i], var_name));
}
}
2013-06-11 14:49:19 +00:00
// Variable Duration Interval Var
2020-10-29 14:25:39 +01:00
IntervalVar* Solver::MakeIntervalVar(int64 start_min, int64 start_max,
2013-06-11 14:49:19 +00:00
int64 duration_min, int64 duration_max,
int64 end_min, int64 end_max,
2020-10-29 14:25:39 +01:00
bool optional, const std::string& name) {
2013-06-11 14:49:19 +00:00
return RegisterIntervalVar(RevAlloc(new VariableDurationIntervalVar(
this, start_min, start_max, duration_min, duration_max, end_min, end_max,
optional, name)));
}
void Solver::MakeIntervalVarArray(int count, int64 start_min, int64 start_max,
int64 duration_min, int64 duration_max,
int64 end_min, int64 end_max, bool optional,
2020-10-29 14:25:39 +01:00
const std::string& name,
std::vector<IntervalVar*>* const array) {
2013-06-11 14:49:19 +00:00
CHECK_GT(count, 0);
CHECK(array != nullptr);
2013-06-11 14:49:19 +00:00
array->clear();
for (int i = 0; i < count; ++i) {
const std::string var_name = absl::StrCat(name, i);
2020-10-22 23:36:58 +02:00
array->push_back(MakeIntervalVar(start_min, start_max, duration_min,
duration_max, end_min, end_max, optional,
var_name));
}
}
2013-06-11 14:49:19 +00:00
// Synced Interval Vars
2020-10-29 14:25:39 +01:00
IntervalVar* Solver::MakeFixedDurationStartSyncedOnStartIntervalVar(
IntervalVar* const interval_var, int64 duration, int64 offset) {
2013-06-11 14:49:19 +00:00
return RegisterIntervalVar(
RevAlloc(new FixedDurationIntervalVarStartSyncedOnStart(
interval_var, duration, offset)));
}
2020-10-29 14:25:39 +01:00
IntervalVar* Solver::MakeFixedDurationStartSyncedOnEndIntervalVar(
IntervalVar* const interval_var, int64 duration, int64 offset) {
2013-06-11 14:49:19 +00:00
return RegisterIntervalVar(
RevAlloc(new FixedDurationIntervalVarStartSyncedOnEnd(interval_var,
duration, offset)));
}
2020-10-29 14:25:39 +01:00
IntervalVar* Solver::MakeFixedDurationEndSyncedOnStartIntervalVar(
IntervalVar* const interval_var, int64 duration, int64 offset) {
2013-06-11 14:49:19 +00:00
return RegisterIntervalVar(
RevAlloc(new FixedDurationIntervalVarStartSyncedOnStart(
2016-08-05 15:38:20 +02:00
interval_var, duration, CapSub(offset, duration))));
2013-06-11 14:49:19 +00:00
}
2020-10-29 14:25:39 +01:00
IntervalVar* Solver::MakeFixedDurationEndSyncedOnEndIntervalVar(
IntervalVar* const interval_var, int64 duration, int64 offset) {
2013-06-11 14:49:19 +00:00
return RegisterIntervalVar(
RevAlloc(new FixedDurationIntervalVarStartSyncedOnEnd(
2016-08-05 15:38:20 +02:00
interval_var, duration, CapSub(offset, duration))));
2013-06-11 14:49:19 +00:00
}
2020-10-22 23:36:58 +02:00
} // namespace operations_research