2013-06-11 14:49:19 +00:00
|
|
|
// Copyright 2010-2013 Google
|
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>
|
|
|
|
|
|
2010-09-15 12:42:33 +00:00
|
|
|
#include "base/integral_types.h"
|
|
|
|
|
#include "base/logging.h"
|
|
|
|
|
#include "base/macros.h"
|
|
|
|
|
#include "base/stringprintf.h"
|
2011-09-21 15:16:48 +00:00
|
|
|
#include "constraint_solver/constraint_solver.h"
|
2010-09-15 12:42:33 +00:00
|
|
|
#include "constraint_solver/constraint_solveri.h"
|
2013-10-10 15:23:20 +00:00
|
|
|
#include "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 {
|
2013-12-05 09:29:08 +00:00
|
|
|
// 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 ------
|
|
|
|
|
|
|
|
|
|
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);
|
2013-12-05 16:06:40 +00:00
|
|
|
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.
|
2010-11-09 09:30:22 +00:00
|
|
|
const int64 IntervalVar::kMaxValidValue = kint64max >> 2;
|
2010-11-30 09:28:02 +00:00
|
|
|
const int64 IntervalVar::kMinValidValue = -kMaxValidValue;
|
2010-11-09 09:30:22 +00:00
|
|
|
|
2011-08-11 05:15:18 +00:00
|
|
|
namespace {
|
2013-10-10 15:23:20 +00:00
|
|
|
enum IntervalField {
|
|
|
|
|
START,
|
|
|
|
|
DURATION,
|
|
|
|
|
END
|
|
|
|
|
};
|
2013-06-11 14:49:19 +00:00
|
|
|
|
2013-10-10 15:23:20 +00:00
|
|
|
IntervalVar* NullInterval() { return nullptr; }
|
2010-10-27 13:25:37 +00:00
|
|
|
// ----- MirrorIntervalVar -----
|
|
|
|
|
|
|
|
|
|
class MirrorIntervalVar : public IntervalVar {
|
|
|
|
|
public:
|
|
|
|
|
MirrorIntervalVar(Solver* const s, IntervalVar* const t)
|
|
|
|
|
: IntervalVar(s, "Mirror<" + t->name() + ">"), t_(t) {}
|
|
|
|
|
virtual ~MirrorIntervalVar() {}
|
|
|
|
|
|
|
|
|
|
// These methods query, set and watch the start position of the
|
|
|
|
|
// interval var.
|
|
|
|
|
virtual int64 StartMin() const { return -t_->EndMax(); }
|
|
|
|
|
virtual int64 StartMax() const { return -t_->EndMin(); }
|
|
|
|
|
virtual void SetStartMin(int64 m) { t_->SetEndMax(-m); }
|
|
|
|
|
virtual void SetStartMax(int64 m) { t_->SetEndMin(-m); }
|
|
|
|
|
virtual void SetStartRange(int64 mi, int64 ma) { t_->SetEndRange(-ma, -mi); }
|
2013-06-11 14:49:19 +00:00
|
|
|
virtual int64 OldStartMin() const { return -t_->OldEndMax(); }
|
|
|
|
|
virtual int64 OldStartMax() const { return -t_->OldEndMin(); }
|
2010-10-27 13:25:37 +00:00
|
|
|
virtual void WhenStartRange(Demon* const d) { t_->WhenEndRange(d); }
|
|
|
|
|
virtual void WhenStartBound(Demon* const d) { t_->WhenEndBound(d); }
|
|
|
|
|
|
|
|
|
|
// These methods query, set and watch the duration of the interval var.
|
|
|
|
|
virtual int64 DurationMin() const { return t_->DurationMin(); }
|
|
|
|
|
virtual int64 DurationMax() const { return t_->DurationMax(); }
|
|
|
|
|
virtual void SetDurationMin(int64 m) { t_->SetDurationMin(m); }
|
|
|
|
|
virtual void SetDurationMax(int64 m) { t_->SetDurationMax(m); }
|
|
|
|
|
virtual void SetDurationRange(int64 mi, int64 ma) {
|
|
|
|
|
t_->SetDurationRange(mi, ma);
|
|
|
|
|
}
|
2013-06-11 14:49:19 +00:00
|
|
|
virtual int64 OldDurationMin() const { return t_->OldDurationMin(); }
|
|
|
|
|
virtual int64 OldDurationMax() const { return t_->OldDurationMax(); }
|
2010-10-27 13:25:37 +00:00
|
|
|
virtual void WhenDurationRange(Demon* const d) { t_->WhenDurationRange(d); }
|
|
|
|
|
virtual void WhenDurationBound(Demon* const d) { t_->WhenDurationBound(d); }
|
|
|
|
|
|
|
|
|
|
// These methods query, set and watch the end position of the interval var.
|
|
|
|
|
virtual int64 EndMin() const { return -t_->StartMax(); }
|
|
|
|
|
virtual int64 EndMax() const { return -t_->StartMin(); }
|
|
|
|
|
virtual void SetEndMin(int64 m) { t_->SetStartMax(-m); }
|
|
|
|
|
virtual void SetEndMax(int64 m) { t_->SetStartMin(-m); }
|
|
|
|
|
virtual void SetEndRange(int64 mi, int64 ma) { t_->SetStartRange(-ma, -mi); }
|
2013-06-11 14:49:19 +00:00
|
|
|
virtual int64 OldEndMin() const { return -t_->OldStartMax(); }
|
|
|
|
|
virtual int64 OldEndMax() const { return -t_->OldStartMin(); }
|
2010-10-27 13:25:37 +00:00
|
|
|
virtual void WhenEndRange(Demon* const d) { t_->WhenStartRange(d); }
|
|
|
|
|
virtual void WhenEndBound(Demon* const d) { t_->WhenStartBound(d); }
|
|
|
|
|
|
|
|
|
|
// These methods query, set and watches the performed status of the
|
|
|
|
|
// interval var.
|
2010-11-02 19:02:53 +00:00
|
|
|
virtual bool MustBePerformed() const { return t_->MustBePerformed(); }
|
|
|
|
|
virtual bool MayBePerformed() const { return t_->MayBePerformed(); }
|
2010-10-27 13:25:37 +00:00
|
|
|
virtual void SetPerformed(bool val) { t_->SetPerformed(val); }
|
2013-06-11 14:49:19 +00:00
|
|
|
virtual bool WasPerformedBound() const { return t_->WasPerformedBound(); }
|
2010-10-27 13:25:37 +00:00
|
|
|
virtual void WhenPerformedBound(Demon* const d) { t_->WhenPerformedBound(d); }
|
|
|
|
|
|
2011-07-11 20:13:14 +00:00
|
|
|
virtual void Accept(ModelVisitor* const visitor) const {
|
2013-06-11 14:49:19 +00:00
|
|
|
visitor->VisitIntervalVariable(this, ModelVisitor::kMirrorOperation, 0, t_);
|
2011-07-11 20:13:14 +00:00
|
|
|
}
|
|
|
|
|
|
2013-12-16 10:24:42 +00:00
|
|
|
virtual std::string DebugString() const {
|
2012-08-14 18:00:08 +00:00
|
|
|
return StringPrintf("MirrorInterval(%s)", t_->DebugString().c_str());
|
|
|
|
|
}
|
|
|
|
|
|
2013-12-05 09:29:08 +00:00
|
|
|
virtual IntExpr* StartExpr() { return solver()->MakeOpposite(t_->EndExpr()); }
|
|
|
|
|
virtual IntExpr* DurationExpr() { return t_->DurationExpr(); }
|
|
|
|
|
virtual IntExpr* EndExpr() { return solver()->MakeOpposite(t_->StartExpr()); }
|
|
|
|
|
virtual IntExpr* PerformedExpr() { 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.
|
|
|
|
|
virtual IntExpr* SafeStartExpr(int64 unperformed_value) {
|
|
|
|
|
return solver()->MakeOpposite(t_->SafeEndExpr(-unperformed_value));
|
|
|
|
|
}
|
|
|
|
|
virtual IntExpr* SafeDurationExpr(int64 unperformed_value) {
|
|
|
|
|
return t_->SafeDurationExpr(unperformed_value);
|
|
|
|
|
}
|
|
|
|
|
virtual IntExpr* SafeEndExpr(int64 unperformed_value) {
|
|
|
|
|
return solver()->MakeOpposite(t_->SafeStartExpr(-unperformed_value));
|
|
|
|
|
}
|
|
|
|
|
|
2010-10-27 13:25:37 +00:00
|
|
|
private:
|
|
|
|
|
IntervalVar* const t_;
|
|
|
|
|
DISALLOW_COPY_AND_ASSIGN(MirrorIntervalVar);
|
|
|
|
|
};
|
|
|
|
|
|
2010-11-09 09:30:22 +00:00
|
|
|
// 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
|
|
|
|
2010-11-09 09:30:22 +00:00
|
|
|
// This class exists so that we can easily implement the
|
|
|
|
|
// IntervalVarRelaxedMax and IntervalVarRelaxedMin classes below.
|
|
|
|
|
class AlwaysPerformedIntervalVarWrapper : public IntervalVar {
|
|
|
|
|
public:
|
|
|
|
|
explicit AlwaysPerformedIntervalVarWrapper(IntervalVar* const t)
|
|
|
|
|
: IntervalVar(t->solver(),
|
2010-11-09 10:30:12 +00:00
|
|
|
StringPrintf("AlwaysPerformed<%s>", t->name().c_str())),
|
2013-12-05 09:29:08 +00:00
|
|
|
t_(t),
|
2013-12-05 16:06:40 +00:00
|
|
|
start_expr_(nullptr),
|
|
|
|
|
duration_expr_(nullptr),
|
|
|
|
|
end_expr_(nullptr) {}
|
|
|
|
|
|
2010-11-09 09:30:22 +00:00
|
|
|
virtual ~AlwaysPerformedIntervalVarWrapper() {}
|
|
|
|
|
virtual int64 StartMin() const {
|
2013-06-11 14:49:19 +00:00
|
|
|
return MayUnderlyingBePerformed() ? t_->StartMin() : kMinValidValue;
|
2010-11-09 09:30:22 +00:00
|
|
|
}
|
|
|
|
|
virtual int64 StartMax() const {
|
|
|
|
|
return MayUnderlyingBePerformed() ? t_->StartMax() : kMaxValidValue;
|
|
|
|
|
}
|
|
|
|
|
virtual void SetStartMin(int64 m) { t_->SetStartMin(m); }
|
|
|
|
|
virtual void SetStartMax(int64 m) { t_->SetStartMax(m); }
|
|
|
|
|
virtual void SetStartRange(int64 mi, int64 ma) { t_->SetStartRange(mi, ma); }
|
2013-06-11 14:49:19 +00:00
|
|
|
virtual int64 OldStartMin() const {
|
|
|
|
|
return MayUnderlyingBePerformed() ? t_->OldStartMin() : kMinValidValue;
|
|
|
|
|
}
|
|
|
|
|
virtual int64 OldStartMax() const {
|
|
|
|
|
return MayUnderlyingBePerformed() ? t_->OldStartMax() : kMaxValidValue;
|
|
|
|
|
}
|
2010-11-09 09:30:22 +00:00
|
|
|
virtual void WhenStartRange(Demon* const d) { t_->WhenStartRange(d); }
|
|
|
|
|
virtual void WhenStartBound(Demon* const d) { t_->WhenStartBound(d); }
|
|
|
|
|
virtual int64 DurationMin() const {
|
|
|
|
|
return MayUnderlyingBePerformed() ? t_->DurationMin() : 0LL;
|
|
|
|
|
}
|
|
|
|
|
virtual int64 DurationMax() const {
|
|
|
|
|
return MayUnderlyingBePerformed() ? t_->DurationMax() : 0LL;
|
|
|
|
|
}
|
|
|
|
|
virtual void SetDurationMin(int64 m) { t_->SetDurationMin(m); }
|
|
|
|
|
virtual void SetDurationMax(int64 m) { t_->SetDurationMax(m); }
|
|
|
|
|
virtual void SetDurationRange(int64 mi, int64 ma) {
|
|
|
|
|
t_->SetDurationRange(mi, ma);
|
|
|
|
|
}
|
2013-06-11 14:49:19 +00:00
|
|
|
virtual int64 OldDurationMin() const {
|
|
|
|
|
return MayUnderlyingBePerformed() ? t_->OldDurationMin() : 0LL;
|
|
|
|
|
}
|
|
|
|
|
virtual int64 OldDurationMax() const {
|
|
|
|
|
return MayUnderlyingBePerformed() ? t_->OldDurationMax() : 0LL;
|
|
|
|
|
}
|
2010-11-09 09:30:22 +00:00
|
|
|
virtual void WhenDurationRange(Demon* const d) { t_->WhenDurationRange(d); }
|
|
|
|
|
virtual void WhenDurationBound(Demon* const d) { t_->WhenDurationBound(d); }
|
|
|
|
|
virtual int64 EndMin() const {
|
|
|
|
|
return MayUnderlyingBePerformed() ? t_->EndMin() : kMinValidValue;
|
|
|
|
|
}
|
|
|
|
|
virtual int64 EndMax() const {
|
|
|
|
|
return MayUnderlyingBePerformed() ? t_->EndMax() : kMaxValidValue;
|
|
|
|
|
}
|
|
|
|
|
virtual void SetEndMin(int64 m) { t_->SetEndMin(m); }
|
|
|
|
|
virtual void SetEndMax(int64 m) { t_->SetEndMax(m); }
|
|
|
|
|
virtual void SetEndRange(int64 mi, int64 ma) { t_->SetEndRange(mi, ma); }
|
2013-06-11 14:49:19 +00:00
|
|
|
virtual int64 OldEndMin() const {
|
|
|
|
|
return MayUnderlyingBePerformed() ? t_->OldEndMin() : kMinValidValue;
|
|
|
|
|
}
|
|
|
|
|
virtual int64 OldEndMax() const {
|
|
|
|
|
return MayUnderlyingBePerformed() ? t_->OldEndMax() : kMaxValidValue;
|
|
|
|
|
}
|
2010-11-09 09:30:22 +00:00
|
|
|
virtual void WhenEndRange(Demon* const d) { t_->WhenEndRange(d); }
|
|
|
|
|
virtual void WhenEndBound(Demon* const d) { t_->WhenEndBound(d); }
|
|
|
|
|
virtual bool MustBePerformed() const { return true; }
|
|
|
|
|
virtual bool MayBePerformed() const { return true; }
|
|
|
|
|
virtual void SetPerformed(bool val) {
|
|
|
|
|
// 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();
|
|
|
|
|
}
|
|
|
|
|
}
|
2013-06-11 14:49:19 +00:00
|
|
|
virtual bool WasPerformedBound() const { return true; }
|
2010-11-09 09:30:22 +00:00
|
|
|
virtual void WhenPerformedBound(Demon* const d) { t_->WhenPerformedBound(d); }
|
2013-12-05 16:06:40 +00:00
|
|
|
virtual IntExpr* StartExpr() {
|
|
|
|
|
if (start_expr_ == nullptr) {
|
|
|
|
|
solver()->SaveValue(reinterpret_cast<void**>(&start_expr_));
|
|
|
|
|
start_expr_ = BuildStartExpr(this);
|
|
|
|
|
}
|
|
|
|
|
return start_expr_;
|
|
|
|
|
}
|
|
|
|
|
IntExpr* DurationExpr() {
|
|
|
|
|
if (duration_expr_ == nullptr) {
|
|
|
|
|
solver()->SaveValue(reinterpret_cast<void**>(&duration_expr_));
|
|
|
|
|
duration_expr_ = BuildDurationExpr(this);
|
|
|
|
|
}
|
|
|
|
|
return duration_expr_;
|
|
|
|
|
}
|
|
|
|
|
IntExpr* EndExpr() {
|
|
|
|
|
if (end_expr_ == nullptr) {
|
|
|
|
|
solver()->SaveValue(reinterpret_cast<void**>(&end_expr_));
|
|
|
|
|
end_expr_ = BuildEndExpr(this);
|
|
|
|
|
}
|
|
|
|
|
return end_expr_;
|
|
|
|
|
}
|
2014-01-08 12:01:58 +00:00
|
|
|
IntExpr* PerformedExpr() { return solver()->MakeIntConst(1); }
|
|
|
|
|
IntExpr* SafeStartExpr(int64 unperformed_value) { return StartExpr(); }
|
|
|
|
|
IntExpr* SafeDurationExpr(int64 unperformed_value) { return DurationExpr(); }
|
|
|
|
|
IntExpr* SafeEndExpr(int64 unperformed_value) { return EndExpr(); }
|
2011-07-11 20:13:14 +00:00
|
|
|
|
2010-11-09 09:30:22 +00:00
|
|
|
protected:
|
2013-10-10 15:23:20 +00:00
|
|
|
IntervalVar* const underlying() const { return t_; }
|
2010-11-09 09:30:22 +00:00
|
|
|
bool MayUnderlyingBePerformed() const {
|
|
|
|
|
return underlying()->MayBePerformed();
|
|
|
|
|
}
|
2011-07-11 20:13:14 +00:00
|
|
|
|
2010-11-09 09:30:22 +00:00
|
|
|
private:
|
|
|
|
|
IntervalVar* const t_;
|
2013-12-05 16:06:40 +00:00
|
|
|
IntExpr* start_expr_;
|
|
|
|
|
IntExpr* duration_expr_;
|
|
|
|
|
IntExpr* end_expr_;
|
2010-11-09 09:30:22 +00:00
|
|
|
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 {
|
|
|
|
|
public:
|
|
|
|
|
explicit IntervalVarRelaxedMax(IntervalVar* const t)
|
2013-06-11 14:49:19 +00:00
|
|
|
: AlwaysPerformedIntervalVarWrapper(t) {}
|
2010-11-09 09:30:22 +00:00
|
|
|
virtual ~IntervalVarRelaxedMax() {}
|
|
|
|
|
virtual int64 StartMax() const {
|
|
|
|
|
// 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());
|
2010-11-09 09:30:22 +00:00
|
|
|
}
|
|
|
|
|
virtual void SetStartMax(int64 m) {
|
|
|
|
|
LOG(FATAL)
|
|
|
|
|
<< "Calling SetStartMax on a IntervalVarRelaxedMax is not supported, "
|
|
|
|
|
<< "as it seems there is no legitimate use case.";
|
|
|
|
|
}
|
|
|
|
|
virtual int64 EndMax() const {
|
2013-06-11 14:49:19 +00:00
|
|
|
return underlying()->MustBePerformed() ? underlying()->EndMax()
|
|
|
|
|
: kMaxValidValue;
|
2010-11-09 09:30:22 +00:00
|
|
|
}
|
|
|
|
|
virtual void SetEndMax(int64 m) {
|
|
|
|
|
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
|
|
|
|
|
|
|
|
virtual void Accept(ModelVisitor* const visitor) const {
|
2013-06-11 14:49:19 +00:00
|
|
|
visitor->VisitIntervalVariable(this, ModelVisitor::kRelaxedMaxOperation, 0,
|
2011-08-11 05:15:18 +00:00
|
|
|
underlying());
|
2011-07-11 20:13:14 +00:00
|
|
|
}
|
2012-08-14 18:00:08 +00:00
|
|
|
|
2013-12-16 10:24:42 +00:00
|
|
|
virtual std::string DebugString() const {
|
2012-08-14 18:00:08 +00:00
|
|
|
return StringPrintf("IntervalVarRelaxedMax(%s)",
|
|
|
|
|
underlying()->DebugString().c_str());
|
|
|
|
|
}
|
2010-11-09 09:30:22 +00:00
|
|
|
};
|
2011-07-11 20:13:14 +00:00
|
|
|
|
2010-11-09 09:30:22 +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.
|
|
|
|
|
//
|
2011-08-11 05:15:18 +00:00
|
|
|
|
2010-11-09 09:30:22 +00:00
|
|
|
// This class is very useful to implement propagators that may only modify
|
|
|
|
|
// the start max or end max.
|
|
|
|
|
class IntervalVarRelaxedMin : public AlwaysPerformedIntervalVarWrapper {
|
|
|
|
|
public:
|
|
|
|
|
explicit IntervalVarRelaxedMin(IntervalVar* const t)
|
|
|
|
|
: AlwaysPerformedIntervalVarWrapper(t) {}
|
|
|
|
|
virtual ~IntervalVarRelaxedMin() {}
|
|
|
|
|
virtual int64 StartMin() const {
|
2013-06-11 14:49:19 +00:00
|
|
|
return underlying()->MustBePerformed() ? underlying()->StartMin()
|
|
|
|
|
: kMinValidValue;
|
2010-11-09 09:30:22 +00:00
|
|
|
}
|
|
|
|
|
virtual void SetStartMin(int64 m) {
|
|
|
|
|
LOG(FATAL)
|
|
|
|
|
<< "Calling SetStartMin on a IntervalVarRelaxedMin is not supported, "
|
|
|
|
|
<< "as it seems there is no legitimate use case.";
|
|
|
|
|
}
|
|
|
|
|
virtual int64 EndMin() const {
|
|
|
|
|
// 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());
|
2010-11-09 09:30:22 +00:00
|
|
|
}
|
|
|
|
|
virtual void SetEndMin(int64 m) {
|
|
|
|
|
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.";
|
2010-11-09 09:30:22 +00:00
|
|
|
}
|
2011-07-11 20:13:14 +00:00
|
|
|
|
|
|
|
|
virtual void Accept(ModelVisitor* const visitor) const {
|
2013-06-11 14:49:19 +00:00
|
|
|
visitor->VisitIntervalVariable(this, ModelVisitor::kRelaxedMinOperation, 0,
|
2011-08-11 05:15:18 +00:00
|
|
|
underlying());
|
2011-07-11 20:13:14 +00:00
|
|
|
}
|
2012-08-14 18:00:08 +00:00
|
|
|
|
2013-12-16 10:24:42 +00:00
|
|
|
virtual std::string DebugString() const {
|
2012-08-14 18:00:08 +00:00
|
|
|
return StringPrintf("IntervalVarRelaxedMin(%s)",
|
|
|
|
|
underlying()->DebugString().c_str());
|
|
|
|
|
}
|
2010-11-09 09:30:22 +00:00
|
|
|
};
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2013-06-11 14:49:19 +00:00
|
|
|
// ----- BaseIntervalVar -----
|
|
|
|
|
|
|
|
|
|
class BaseIntervalVar : public IntervalVar {
|
2010-09-15 12:42:33 +00:00
|
|
|
public:
|
2011-11-03 10:27:53 +00:00
|
|
|
class Handler : public Demon {
|
2010-09-15 12:42:33 +00:00
|
|
|
public:
|
2013-06-11 14:49:19 +00:00
|
|
|
explicit Handler(BaseIntervalVar* const var) : var_(var) {}
|
2011-11-03 10:27:53 +00:00
|
|
|
virtual ~Handler() {}
|
2013-06-11 14:49:19 +00:00
|
|
|
virtual void Run(Solver* const s) { var_->Process(); }
|
2010-09-15 12:42:33 +00:00
|
|
|
virtual Solver::DemonPriority priority() const {
|
|
|
|
|
return Solver::VAR_PRIORITY;
|
|
|
|
|
}
|
2013-12-16 10:24:42 +00:00
|
|
|
virtual std::string DebugString() const {
|
2010-09-15 12:42:33 +00:00
|
|
|
return StringPrintf("Handler(%s)", var_->DebugString().c_str());
|
|
|
|
|
}
|
2013-06-11 14:49:19 +00:00
|
|
|
|
2010-09-15 12:42:33 +00:00
|
|
|
private:
|
2013-06-11 14:49:19 +00:00
|
|
|
BaseIntervalVar* const var_;
|
2010-09-15 12:42:33 +00:00
|
|
|
};
|
|
|
|
|
|
2011-11-03 10:27:53 +00:00
|
|
|
class Cleaner : public Action {
|
2010-09-15 12:42:33 +00:00
|
|
|
public:
|
2013-06-11 14:49:19 +00:00
|
|
|
explicit Cleaner(BaseIntervalVar* const var) : var_(var) {}
|
2011-11-03 10:27:53 +00:00
|
|
|
virtual ~Cleaner() {}
|
2013-06-11 14:49:19 +00:00
|
|
|
virtual void Run(Solver* const s) { var_->ClearInProcess(); }
|
|
|
|
|
|
2010-09-15 12:42:33 +00:00
|
|
|
private:
|
2013-06-11 14:49:19 +00:00
|
|
|
BaseIntervalVar* const var_;
|
2010-09-15 12:42:33 +00:00
|
|
|
};
|
|
|
|
|
|
2013-12-16 10:24:42 +00:00
|
|
|
BaseIntervalVar(Solver* const s, const std::string& name)
|
2013-06-11 14:49:19 +00:00
|
|
|
: IntervalVar(s, name),
|
|
|
|
|
in_process_(false),
|
|
|
|
|
handler_(this),
|
|
|
|
|
cleaner_(this) {}
|
|
|
|
|
|
|
|
|
|
virtual ~BaseIntervalVar() {}
|
|
|
|
|
|
|
|
|
|
virtual void Process() = 0;
|
|
|
|
|
|
|
|
|
|
virtual void Push() = 0;
|
|
|
|
|
|
|
|
|
|
void ClearInProcess() { in_process_ = false; }
|
|
|
|
|
|
2013-12-16 10:24:42 +00:00
|
|
|
virtual std::string BaseName() const { return "IntervalVar"; }
|
2013-06-11 14:49:19 +00:00
|
|
|
|
2013-12-05 09:29:08 +00:00
|
|
|
bool InProcess() const { return in_process_; }
|
|
|
|
|
|
2013-06-11 14:49:19 +00:00
|
|
|
protected:
|
|
|
|
|
bool in_process_;
|
|
|
|
|
Handler handler_;
|
|
|
|
|
Cleaner cleaner_;
|
|
|
|
|
};
|
|
|
|
|
|
2013-12-05 16:06:40 +00:00
|
|
|
class RangeVar : public IntExpr {
|
2013-06-11 14:49:19 +00:00
|
|
|
public:
|
2013-12-05 16:06:40 +00:00
|
|
|
RangeVar(Solver* const s, BaseIntervalVar* var, int64 mi, int64 ma)
|
|
|
|
|
: IntExpr(s),
|
2013-06-11 14:49:19 +00:00
|
|
|
min_(mi),
|
|
|
|
|
max_(ma),
|
2013-12-05 16:06:40 +00:00
|
|
|
var_(var),
|
2013-06-11 14:49:19 +00:00
|
|
|
postponed_min_(mi),
|
|
|
|
|
postponed_max_(ma),
|
|
|
|
|
previous_min_(mi),
|
2013-12-05 16:06:40 +00:00
|
|
|
previous_max_(ma),
|
|
|
|
|
cast_var_(nullptr) {}
|
2013-06-11 14:49:19 +00:00
|
|
|
|
2013-12-05 16:06:40 +00:00
|
|
|
virtual ~RangeVar() {}
|
2013-06-11 14:49:19 +00:00
|
|
|
|
2013-12-05 16:06:40 +00:00
|
|
|
virtual bool Bound() const { return min_.Value() == max_.Value(); }
|
2013-06-11 14:49:19 +00:00
|
|
|
|
2013-12-05 16:06:40 +00:00
|
|
|
virtual int64 Min() const { return min_.Value(); }
|
2013-06-11 14:49:19 +00:00
|
|
|
|
2013-12-05 16:06:40 +00:00
|
|
|
virtual int64 Max() const { return max_.Value(); }
|
2013-06-11 14:49:19 +00:00
|
|
|
|
2013-12-05 16:06:40 +00:00
|
|
|
virtual void SetMin(int64 m) {
|
|
|
|
|
// No Op.
|
|
|
|
|
if (m <= min_.Value()) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
// Inconsistent value.
|
2013-06-11 14:49:19 +00:00
|
|
|
if (m > max_.Value()) {
|
2013-12-05 16:06:40 +00:00
|
|
|
var_->SetPerformed(false);
|
|
|
|
|
return;
|
2013-06-11 14:49:19 +00:00
|
|
|
}
|
2013-12-05 16:06:40 +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);
|
2013-12-05 16:06:40 +00:00
|
|
|
var_->Push();
|
2013-06-11 14:49:19 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2013-12-05 16:06:40 +00:00
|
|
|
int64 OldMin() const {
|
|
|
|
|
DCHECK(var_->InProcess());
|
|
|
|
|
return previous_min_;
|
2013-06-11 14:49:19 +00:00
|
|
|
}
|
|
|
|
|
|
2013-12-05 16:06:40 +00:00
|
|
|
virtual void SetMax(int64 m) {
|
|
|
|
|
if (m >= max_.Value()) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
2013-06-11 14:49:19 +00:00
|
|
|
if (m < min_.Value()) {
|
2013-12-05 16:06:40 +00:00
|
|
|
var_->SetPerformed(false);
|
|
|
|
|
return;
|
2013-06-11 14:49:19 +00:00
|
|
|
}
|
2013-12-05 16:06:40 +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);
|
2013-12-05 16:06:40 +00:00
|
|
|
var_->Push();
|
2013-06-11 14:49:19 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2013-12-05 16:06:40 +00:00
|
|
|
int64 OldMax() const { return previous_min_; }
|
2013-06-11 14:49:19 +00:00
|
|
|
|
2013-12-05 16:06:40 +00:00
|
|
|
virtual void SetRange(int64 mi, int64 ma) {
|
|
|
|
|
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
|
|
|
}
|
2013-12-05 16:06:40 +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);
|
|
|
|
|
}
|
2013-12-05 16:06:40 +00:00
|
|
|
var_->Push();
|
2013-06-11 14:49:19 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
virtual void WhenRange(Demon* const demon) {
|
|
|
|
|
if (!Bound()) {
|
|
|
|
|
if (demon->priority() == Solver::DELAYED_PRIORITY) {
|
|
|
|
|
delayed_range_demons_.PushIfNotTop(solver(),
|
|
|
|
|
solver()->RegisterDemon(demon));
|
|
|
|
|
} else {
|
|
|
|
|
range_demons_.PushIfNotTop(solver(), solver()->RegisterDemon(demon));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
virtual void WhenBound(Demon* const demon) {
|
|
|
|
|
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_);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2013-12-05 16:06:40 +00:00
|
|
|
void UpdatePreviousBounds() {
|
2013-06-11 14:49:19 +00:00
|
|
|
previous_min_ = min_.Value();
|
|
|
|
|
previous_max_ = max_.Value();
|
2013-12-05 16:06:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 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) {
|
|
|
|
|
case START:
|
2013-12-05 16:06:40 +00:00
|
|
|
var_->SetStartRange(std::max(postponed_min_, min_.Value()),
|
|
|
|
|
std::min(postponed_max_, max_.Value()));
|
2013-06-11 14:49:19 +00:00
|
|
|
break;
|
|
|
|
|
case DURATION:
|
2013-12-05 16:06:40 +00:00
|
|
|
var_->SetDurationRange(std::max(postponed_min_, min_.Value()),
|
|
|
|
|
std::min(postponed_max_, max_.Value()));
|
2013-06-11 14:49:19 +00:00
|
|
|
break;
|
|
|
|
|
case END:
|
2013-12-05 16:06:40 +00:00
|
|
|
var_->SetEndRange(std::max(postponed_min_, min_.Value()),
|
|
|
|
|
std::min(postponed_max_, max_.Value()));
|
2013-06-11 14:49:19 +00:00
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2013-12-05 16:06:40 +00:00
|
|
|
IntVar* Var() {
|
|
|
|
|
if (cast_var_ == nullptr) {
|
|
|
|
|
solver()->SaveValue(reinterpret_cast<void**>(&cast_var_));
|
|
|
|
|
cast_var_ = solver()->MakeIntVar(min_.Value(), max_.Value());
|
|
|
|
|
LinkVarExpr(solver(), this, cast_var_);
|
|
|
|
|
}
|
|
|
|
|
return cast_var_;
|
|
|
|
|
}
|
|
|
|
|
|
2013-12-16 10:24:42 +00:00
|
|
|
std::string DebugString() const {
|
|
|
|
|
std::string out = StringPrintf("%" GG_LL_FORMAT "d", min_.Value());
|
2013-06-11 14:49:19 +00:00
|
|
|
if (!Bound()) {
|
|
|
|
|
StringAppendF(&out, " .. %" GG_LL_FORMAT "d", max_.Value());
|
|
|
|
|
}
|
|
|
|
|
return out;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
// 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_;
|
2013-12-05 16:06:40 +00: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).
|
|
|
|
|
SimpleRevFIFO<Demon*> bound_demons_;
|
|
|
|
|
SimpleRevFIFO<Demon*> delayed_bound_demons_;
|
|
|
|
|
// Demons attached to a modification of bounds.
|
|
|
|
|
SimpleRevFIFO<Demon*> range_demons_;
|
|
|
|
|
SimpleRevFIFO<Demon*> delayed_range_demons_;
|
2013-12-05 16:06:40 +00:00
|
|
|
IntVar* cast_var_;
|
|
|
|
|
}; // class RangeVar
|
2013-12-05 09:29:08 +00:00
|
|
|
|
|
|
|
|
// ----- PerformedVar -----
|
|
|
|
|
|
|
|
|
|
class PerformedVar : public BooleanVar {
|
|
|
|
|
public:
|
2013-12-05 16:06:40 +00:00
|
|
|
// Optional = true -> var = [0..1], Optional = false -> var = [1].
|
2013-12-05 09:29:08 +00:00
|
|
|
PerformedVar(Solver* const s, BaseIntervalVar* const var, bool optional)
|
|
|
|
|
: BooleanVar(s, ""),
|
|
|
|
|
var_(var),
|
|
|
|
|
previous_value_(optional ? kUnboundBooleanVarValue : 1),
|
|
|
|
|
postponed_value_(optional ? kUnboundBooleanVarValue : 1) {
|
|
|
|
|
if (!optional) {
|
|
|
|
|
value_ = 1;
|
|
|
|
|
}
|
|
|
|
|
}
|
2013-12-05 16:06:40 +00:00
|
|
|
// var = [0] (always unperformed).
|
2013-12-05 09:29:08 +00:00
|
|
|
PerformedVar(Solver* const s, BaseIntervalVar* var)
|
|
|
|
|
: BooleanVar(s, ""), var_(var), previous_value_(0), postponed_value_(0) {
|
|
|
|
|
value_ = 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
virtual ~PerformedVar() {}
|
|
|
|
|
|
|
|
|
|
virtual void SetValue(int64 v) {
|
|
|
|
|
if ((v & 0xfffffffffffffffe) != 0 || // Not 0 or 1.
|
|
|
|
|
(value_ != kUnboundBooleanVarValue && v != value_)) {
|
|
|
|
|
solver()->Fail();
|
|
|
|
|
}
|
|
|
|
|
if (var_->InProcess()) {
|
|
|
|
|
if (postponed_value_ != kUnboundBooleanVarValue &&
|
|
|
|
|
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();
|
|
|
|
|
}
|
|
|
|
|
}
|
2013-12-05 16:06:40 +00:00
|
|
|
|
2013-12-05 09:29:08 +00:00
|
|
|
virtual int64 OldMin() const { return previous_value_ == 1; }
|
2013-12-05 16:06:40 +00:00
|
|
|
|
2013-12-05 09:29:08 +00:00
|
|
|
virtual int64 OldMax() const { return previous_value_ != 0; }
|
2013-12-05 16:06:40 +00:00
|
|
|
|
2013-12-05 09:29:08 +00:00
|
|
|
virtual void RestoreValue() {
|
|
|
|
|
previous_value_ = kUnboundBooleanVarValue;
|
|
|
|
|
value_ = kUnboundBooleanVarValue;
|
|
|
|
|
postponed_value_ = kUnboundBooleanVarValue;
|
|
|
|
|
}
|
2013-12-05 16:06:40 +00:00
|
|
|
|
2013-12-05 09:29:08 +00:00
|
|
|
void Process() {
|
|
|
|
|
if (previous_value_ != value_) {
|
|
|
|
|
ExecuteAll(bound_demons_);
|
|
|
|
|
EnqueueAll(delayed_bound_demons_);
|
|
|
|
|
}
|
|
|
|
|
}
|
2013-12-05 16:06:40 +00:00
|
|
|
|
|
|
|
|
void UpdatePostponedValue() { postponed_value_ = value_; }
|
|
|
|
|
|
2013-12-05 09:29:08 +00:00
|
|
|
void UpdatePreviousValueAndApplyPostponedValue() {
|
|
|
|
|
previous_value_ = value_;
|
|
|
|
|
if (value_ != postponed_value_) {
|
|
|
|
|
DCHECK_NE(kUnboundBooleanVarValue, postponed_value_);
|
|
|
|
|
SetValue(postponed_value_);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2013-12-16 10:24:42 +00:00
|
|
|
virtual std::string DebugString() const {
|
2013-12-05 09:29:08 +00:00
|
|
|
switch (value_) {
|
2013-12-05 16:06:40 +00:00
|
|
|
case 0:
|
|
|
|
|
return "false";
|
|
|
|
|
case 1:
|
|
|
|
|
return "true";
|
|
|
|
|
default:
|
|
|
|
|
return "undecided";
|
2013-12-05 09:29:08 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
BaseIntervalVar* const var_;
|
|
|
|
|
int previous_value_;
|
|
|
|
|
int postponed_value_;
|
|
|
|
|
};
|
2013-06-11 14:49:19 +00:00
|
|
|
|
|
|
|
|
// ----- FixedDurationIntervalVar -----
|
|
|
|
|
|
|
|
|
|
class FixedDurationIntervalVar : public BaseIntervalVar {
|
|
|
|
|
public:
|
|
|
|
|
FixedDurationIntervalVar(Solver* const s, int64 start_min, int64 start_max,
|
2014-07-07 13:29:56 +00:00
|
|
|
int64 duration, bool optional,
|
|
|
|
|
const std::string& name);
|
2010-09-15 12:42:33 +00:00
|
|
|
// Unperformed interval.
|
2013-12-16 10:24:42 +00:00
|
|
|
FixedDurationIntervalVar(Solver* const s, const std::string& name);
|
2010-09-15 12:42:33 +00:00
|
|
|
virtual ~FixedDurationIntervalVar() {}
|
|
|
|
|
|
|
|
|
|
virtual int64 StartMin() const;
|
|
|
|
|
virtual int64 StartMax() const;
|
|
|
|
|
virtual void SetStartMin(int64 m);
|
|
|
|
|
virtual void SetStartMax(int64 m);
|
|
|
|
|
virtual void SetStartRange(int64 mi, int64 ma);
|
2013-12-05 16:06:40 +00:00
|
|
|
virtual int64 OldStartMin() const { return start_.OldMin(); }
|
|
|
|
|
virtual int64 OldStartMax() const { return start_.OldMax(); }
|
2010-09-15 12:42:33 +00:00
|
|
|
virtual void WhenStartRange(Demon* const d) {
|
2013-12-05 09:29:08 +00:00
|
|
|
if (performed_.Max() == 1) {
|
2013-06-11 14:49:19 +00:00
|
|
|
start_.WhenRange(d);
|
2011-11-03 10:27:53 +00:00
|
|
|
}
|
2010-09-15 12:42:33 +00:00
|
|
|
}
|
|
|
|
|
virtual void WhenStartBound(Demon* const d) {
|
2013-12-05 09:29:08 +00:00
|
|
|
if (performed_.Max() == 1) {
|
2013-06-11 14:49:19 +00:00
|
|
|
start_.WhenBound(d);
|
2011-11-03 10:27:53 +00:00
|
|
|
}
|
2010-09-15 12:42:33 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
virtual int64 DurationMin() const;
|
|
|
|
|
virtual int64 DurationMax() const;
|
|
|
|
|
virtual void SetDurationMin(int64 m);
|
|
|
|
|
virtual void SetDurationMax(int64 m);
|
|
|
|
|
virtual void SetDurationRange(int64 mi, int64 ma);
|
2013-06-11 14:49:19 +00:00
|
|
|
virtual int64 OldDurationMin() const { return duration_; }
|
|
|
|
|
virtual int64 OldDurationMax() const { return duration_; }
|
|
|
|
|
virtual void WhenDurationRange(Demon* const d) {}
|
|
|
|
|
virtual void WhenDurationBound(Demon* const d) {}
|
2010-09-15 12:42:33 +00:00
|
|
|
|
|
|
|
|
virtual int64 EndMin() const;
|
|
|
|
|
virtual int64 EndMax() const;
|
|
|
|
|
virtual void SetEndMin(int64 m);
|
|
|
|
|
virtual void SetEndMax(int64 m);
|
|
|
|
|
virtual void SetEndRange(int64 mi, int64 ma);
|
2013-06-11 14:49:19 +00:00
|
|
|
virtual int64 OldEndMin() const { return CapAdd(OldStartMin(), duration_); }
|
|
|
|
|
virtual int64 OldEndMax() const { return CapAdd(OldStartMax(), duration_); }
|
|
|
|
|
virtual void WhenEndRange(Demon* const d) { WhenStartRange(d); }
|
|
|
|
|
virtual void WhenEndBound(Demon* const d) { WhenStartBound(d); }
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2010-11-02 19:02:53 +00:00
|
|
|
virtual bool MustBePerformed() const;
|
|
|
|
|
virtual bool MayBePerformed() const;
|
2010-09-15 12:42:33 +00:00
|
|
|
virtual void SetPerformed(bool val);
|
2013-12-05 09:29:08 +00:00
|
|
|
virtual bool WasPerformedBound() const {
|
|
|
|
|
return performed_.OldMin() == performed_.OldMax();
|
|
|
|
|
}
|
2013-06-11 14:49:19 +00:00
|
|
|
virtual void WhenPerformedBound(Demon* const d) { performed_.WhenBound(d); }
|
|
|
|
|
virtual void Process();
|
2013-12-16 10:24:42 +00:00
|
|
|
virtual std::string DebugString() const;
|
2011-07-11 20:13:14 +00:00
|
|
|
|
|
|
|
|
virtual void Accept(ModelVisitor* const visitor) const {
|
2013-06-11 14:49:19 +00:00
|
|
|
visitor->VisitIntervalVariable(this, "", 0, NullInterval());
|
2011-07-11 20:13:14 +00:00
|
|
|
}
|
|
|
|
|
|
2013-12-05 16:06:40 +00:00
|
|
|
virtual IntExpr* StartExpr() { return &start_; }
|
|
|
|
|
virtual IntExpr* DurationExpr() { return solver()->MakeIntConst(duration_); }
|
|
|
|
|
virtual IntExpr* EndExpr() {
|
|
|
|
|
return solver()->MakeSum(StartExpr(), duration_);
|
2013-12-05 09:29:08 +00:00
|
|
|
}
|
2013-12-05 16:06:40 +00:00
|
|
|
virtual IntExpr* PerformedExpr() { return &performed_; }
|
|
|
|
|
virtual IntExpr* SafeStartExpr(int64 unperformed_value) {
|
2013-12-05 09:29:08 +00:00
|
|
|
return BuildSafeStartExpr(this, unperformed_value);
|
|
|
|
|
}
|
2013-12-05 16:06:40 +00:00
|
|
|
virtual IntExpr* SafeDurationExpr(int64 unperformed_value) {
|
2013-12-05 09:29:08 +00:00
|
|
|
return BuildSafeDurationExpr(this, unperformed_value);
|
|
|
|
|
}
|
2013-12-05 16:06:40 +00:00
|
|
|
virtual IntExpr* SafeEndExpr(int64 unperformed_value) {
|
2013-12-05 09:29:08 +00:00
|
|
|
return BuildSafeEndExpr(this, unperformed_value);
|
|
|
|
|
}
|
|
|
|
|
|
2013-06-11 14:49:19 +00:00
|
|
|
virtual void Push();
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2013-12-05 09:29:08 +00:00
|
|
|
private:
|
2013-12-05 16:06:40 +00:00
|
|
|
RangeVar start_;
|
2010-09-15 12:42:33 +00:00
|
|
|
int64 duration_;
|
2013-12-05 09:29:08 +00:00
|
|
|
PerformedVar performed_;
|
2010-09-15 12:42:33 +00:00
|
|
|
};
|
|
|
|
|
|
2013-06-11 14:49:19 +00:00
|
|
|
FixedDurationIntervalVar::FixedDurationIntervalVar(
|
|
|
|
|
Solver* const s, int64 start_min, int64 start_max, int64 duration,
|
2013-12-16 10:24:42 +00:00
|
|
|
bool optional, const std::string& name)
|
2013-06-11 14:49:19 +00:00
|
|
|
: BaseIntervalVar(s, name),
|
2013-12-05 16:06:40 +00:00
|
|
|
start_(s, this, start_min, start_max),
|
2010-09-15 12:42:33 +00:00
|
|
|
duration_(duration),
|
2013-12-05 16:06:40 +00:00
|
|
|
performed_(s, this, optional) {}
|
2010-09-15 12:42:33 +00:00
|
|
|
|
|
|
|
|
FixedDurationIntervalVar::FixedDurationIntervalVar(Solver* const s,
|
2013-12-16 10:24:42 +00:00
|
|
|
const std::string& name)
|
2013-12-05 09:29:08 +00:00
|
|
|
: BaseIntervalVar(s, name),
|
2013-12-05 16:06:40 +00:00
|
|
|
start_(s, this, 0, 0),
|
2013-12-05 09:29:08 +00:00
|
|
|
duration_(0),
|
2013-12-05 16:06:40 +00:00
|
|
|
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();
|
2013-12-05 09:29:08 +00:00
|
|
|
performed_.UpdatePostponedValue();
|
2010-09-15 12:42:33 +00:00
|
|
|
set_queue_action_on_fail(&cleaner_);
|
2013-12-05 09:29:08 +00:00
|
|
|
if (performed_.Max() == 1) {
|
2013-06-11 14:49:19 +00:00
|
|
|
start_.ProcessDemons();
|
2010-09-15 12:42:33 +00:00
|
|
|
}
|
2013-12-05 09:29:08 +00:00
|
|
|
performed_.Process();
|
2010-09-15 12:42:33 +00:00
|
|
|
clear_queue_action_on_fail();
|
|
|
|
|
ClearInProcess();
|
2013-12-05 16:06:40 +00:00
|
|
|
start_.UpdatePreviousBounds();
|
|
|
|
|
start_.ApplyPostponedBounds(START);
|
2013-12-05 09:29:08 +00:00
|
|
|
performed_.UpdatePreviousValueAndApplyPostponedValue();
|
2010-09-15 12:42:33 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int64 FixedDurationIntervalVar::StartMin() const {
|
2013-12-05 09:29:08 +00:00
|
|
|
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 {
|
2013-12-05 09:29:08 +00:00
|
|
|
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) {
|
2013-12-05 09:29:08 +00:00
|
|
|
if (performed_.Max() == 1) {
|
2013-12-05 16:06:40 +00:00
|
|
|
start_.SetMin(m);
|
2010-09-15 12:42:33 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void FixedDurationIntervalVar::SetStartMax(int64 m) {
|
2013-12-05 09:29:08 +00:00
|
|
|
if (performed_.Max() == 1) {
|
2013-12-05 16:06:40 +00:00
|
|
|
start_.SetMax(m);
|
2010-09-15 12:42:33 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void FixedDurationIntervalVar::SetStartRange(int64 mi, int64 ma) {
|
2013-12-05 09:29:08 +00:00
|
|
|
if (performed_.Max() == 1) {
|
2013-12-05 16:06:40 +00:00
|
|
|
start_.SetRange(mi, ma);
|
2013-06-11 14:49:19 +00:00
|
|
|
}
|
2010-09-15 12:42:33 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int64 FixedDurationIntervalVar::DurationMin() const {
|
2013-12-05 09:29:08 +00:00
|
|
|
CHECK_EQ(performed_.Max(), 1);
|
2010-09-15 12:42:33 +00:00
|
|
|
return duration_;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int64 FixedDurationIntervalVar::DurationMax() const {
|
2013-12-05 09:29:08 +00:00
|
|
|
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 {
|
2013-12-05 09:29:08 +00:00
|
|
|
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 {
|
2013-12-05 09:29:08 +00:00
|
|
|
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
|
|
|
}
|
|
|
|
|
|
2010-11-02 19:02:53 +00:00
|
|
|
bool FixedDurationIntervalVar::MustBePerformed() const {
|
2013-12-05 09:29:08 +00:00
|
|
|
return (performed_.Min() == 1);
|
2010-09-15 12:42:33 +00:00
|
|
|
}
|
|
|
|
|
|
2010-11-02 19:02:53 +00:00
|
|
|
bool FixedDurationIntervalVar::MayBePerformed() const {
|
2013-12-05 09:29:08 +00:00
|
|
|
return (performed_.Max() == 1);
|
2010-09-15 12:42:33 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void FixedDurationIntervalVar::SetPerformed(bool val) {
|
2013-12-05 09:29:08 +00:00
|
|
|
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_);
|
2012-09-07 15:27:53 +00:00
|
|
|
EnqueueVar(&handler_);
|
2013-06-11 14:49:19 +00:00
|
|
|
DCHECK(!in_process_);
|
2010-09-15 12:42:33 +00:00
|
|
|
}
|
|
|
|
|
|
2013-12-16 10:24:42 +00:00
|
|
|
std::string FixedDurationIntervalVar::DebugString() const {
|
|
|
|
|
const std::string& var_name = name();
|
2013-12-05 09:29:08 +00:00
|
|
|
if (performed_.Max() == 0) {
|
2013-07-29 02:49:12 +00:00
|
|
|
if (!var_name.empty()) {
|
|
|
|
|
return StringPrintf("%s(performed = false)", var_name.c_str());
|
|
|
|
|
} else {
|
|
|
|
|
return "IntervalVar(performed = false)";
|
|
|
|
|
}
|
2010-09-15 12:42:33 +00:00
|
|
|
} else {
|
2013-12-16 10:24:42 +00:00
|
|
|
std::string out;
|
2013-07-29 02:49:12 +00:00
|
|
|
if (!var_name.empty()) {
|
|
|
|
|
out = var_name + "(start = ";
|
|
|
|
|
} else {
|
|
|
|
|
out = "IntervalVar(start = ";
|
|
|
|
|
}
|
|
|
|
|
StringAppendF(&out, "%s, duration = %" GG_LL_FORMAT "d, performed = %s)",
|
|
|
|
|
start_.DebugString().c_str(), duration_,
|
|
|
|
|
performed_.DebugString().c_str());
|
|
|
|
|
return out;
|
2010-09-15 12:42:33 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2011-11-03 10:27:53 +00:00
|
|
|
// ----- FixedDurationPerformedIntervalVar -----
|
|
|
|
|
|
2013-06-11 14:49:19 +00:00
|
|
|
class FixedDurationPerformedIntervalVar : public BaseIntervalVar {
|
2011-11-03 10:27:53 +00:00
|
|
|
public:
|
2013-06-11 14:49:19 +00:00
|
|
|
FixedDurationPerformedIntervalVar(Solver* const s, int64 start_min,
|
|
|
|
|
int64 start_max, int64 duration,
|
2013-12-16 10:24:42 +00:00
|
|
|
const std::string& name);
|
2011-11-03 10:27:53 +00:00
|
|
|
// Unperformed interval.
|
2013-12-16 10:24:42 +00:00
|
|
|
FixedDurationPerformedIntervalVar(Solver* const s, const std::string& name);
|
2011-11-03 10:27:53 +00:00
|
|
|
virtual ~FixedDurationPerformedIntervalVar() {}
|
|
|
|
|
|
|
|
|
|
virtual int64 StartMin() const;
|
|
|
|
|
virtual int64 StartMax() const;
|
|
|
|
|
virtual void SetStartMin(int64 m);
|
|
|
|
|
virtual void SetStartMax(int64 m);
|
|
|
|
|
virtual void SetStartRange(int64 mi, int64 ma);
|
2013-12-05 16:06:40 +00:00
|
|
|
virtual int64 OldStartMin() const { return start_.OldMin(); }
|
|
|
|
|
virtual int64 OldStartMax() const { return start_.OldMax(); }
|
2013-06-11 14:49:19 +00:00
|
|
|
virtual void WhenStartRange(Demon* const d) { start_.WhenRange(d); }
|
|
|
|
|
virtual void WhenStartBound(Demon* const d) { start_.WhenBound(d); }
|
2011-11-03 10:27:53 +00:00
|
|
|
|
|
|
|
|
virtual int64 DurationMin() const;
|
|
|
|
|
virtual int64 DurationMax() const;
|
|
|
|
|
virtual void SetDurationMin(int64 m);
|
|
|
|
|
virtual void SetDurationMax(int64 m);
|
|
|
|
|
virtual void SetDurationRange(int64 mi, int64 ma);
|
2013-06-11 14:49:19 +00:00
|
|
|
virtual int64 OldDurationMin() const { return duration_; }
|
|
|
|
|
virtual int64 OldDurationMax() const { return duration_; }
|
|
|
|
|
virtual void WhenDurationRange(Demon* const d) {}
|
|
|
|
|
virtual void WhenDurationBound(Demon* const d) {}
|
2011-11-03 10:27:53 +00:00
|
|
|
|
|
|
|
|
virtual int64 EndMin() const;
|
|
|
|
|
virtual int64 EndMax() const;
|
|
|
|
|
virtual void SetEndMin(int64 m);
|
|
|
|
|
virtual void SetEndMax(int64 m);
|
|
|
|
|
virtual void SetEndRange(int64 mi, int64 ma);
|
2013-06-11 14:49:19 +00:00
|
|
|
virtual int64 OldEndMin() const { return CapAdd(OldStartMin(), duration_); }
|
|
|
|
|
virtual int64 OldEndMax() const { return CapAdd(OldStartMax(), duration_); }
|
|
|
|
|
virtual void WhenEndRange(Demon* const d) { WhenStartRange(d); }
|
|
|
|
|
virtual void WhenEndBound(Demon* const d) { WhenEndRange(d); }
|
2011-11-03 10:27:53 +00:00
|
|
|
|
|
|
|
|
virtual bool MustBePerformed() const;
|
|
|
|
|
virtual bool MayBePerformed() const;
|
|
|
|
|
virtual void SetPerformed(bool val);
|
2013-06-11 14:49:19 +00:00
|
|
|
virtual bool WasPerformedBound() const { return true; }
|
|
|
|
|
virtual void WhenPerformedBound(Demon* const d) {}
|
|
|
|
|
virtual void Process();
|
2013-12-16 10:24:42 +00:00
|
|
|
virtual std::string DebugString() const;
|
2011-11-03 10:27:53 +00:00
|
|
|
|
|
|
|
|
virtual void Accept(ModelVisitor* const visitor) const {
|
2013-06-11 14:49:19 +00:00
|
|
|
visitor->VisitIntervalVariable(this, "", 0, NullInterval());
|
2011-11-03 10:27:53 +00:00
|
|
|
}
|
|
|
|
|
|
2013-12-05 16:06:40 +00:00
|
|
|
virtual IntExpr* StartExpr() { return &start_; }
|
2013-12-05 09:29:08 +00:00
|
|
|
IntExpr* DurationExpr() { return solver()->MakeIntConst(duration_); }
|
|
|
|
|
IntExpr* EndExpr() { return solver()->MakeSum(StartExpr(), duration_); }
|
|
|
|
|
IntExpr* PerformedExpr() { return solver()->MakeIntConst(1); }
|
|
|
|
|
IntExpr* SafeStartExpr(int64 unperformed_value) { return StartExpr(); }
|
2013-12-05 16:06:40 +00:00
|
|
|
IntExpr* SafeDurationExpr(int64 unperformed_value) { return DurationExpr(); }
|
2013-12-05 09:29:08 +00:00
|
|
|
IntExpr* SafeEndExpr(int64 unperformed_value) { return EndExpr(); }
|
|
|
|
|
|
2011-11-03 10:27:53 +00:00
|
|
|
private:
|
|
|
|
|
void CheckOldPerformed() {}
|
2013-06-11 14:49:19 +00:00
|
|
|
virtual void Push();
|
|
|
|
|
|
2013-12-05 16:06:40 +00:00
|
|
|
RangeVar start_;
|
2011-11-03 10:27:53 +00:00
|
|
|
int64 duration_;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
FixedDurationPerformedIntervalVar::FixedDurationPerformedIntervalVar(
|
2013-06-11 14:49:19 +00:00
|
|
|
Solver* const s, int64 start_min, int64 start_max, int64 duration,
|
2013-12-16 10:24:42 +00:00
|
|
|
const std::string& name)
|
2013-06-11 14:49:19 +00:00
|
|
|
: BaseIntervalVar(s, name),
|
2013-12-05 16:06:40 +00:00
|
|
|
start_(s, this, start_min, start_max),
|
|
|
|
|
duration_(duration) {}
|
2011-11-03 10:27:53 +00:00
|
|
|
|
|
|
|
|
FixedDurationPerformedIntervalVar::FixedDurationPerformedIntervalVar(
|
2013-12-16 10:24:42 +00:00
|
|
|
Solver* const s, const std::string& name)
|
2013-12-05 16:06:40 +00:00
|
|
|
: BaseIntervalVar(s, name), start_(s, this, 0, 0), duration_(0) {}
|
2011-11-03 10:27:53 +00:00
|
|
|
|
|
|
|
|
void FixedDurationPerformedIntervalVar::Process() {
|
|
|
|
|
CHECK(!in_process_);
|
|
|
|
|
in_process_ = true;
|
2013-06-11 14:49:19 +00:00
|
|
|
start_.UpdatePostponedBounds();
|
2011-11-03 10:27:53 +00:00
|
|
|
set_queue_action_on_fail(&cleaner_);
|
2013-06-11 14:49:19 +00:00
|
|
|
start_.ProcessDemons();
|
2011-11-03 10:27:53 +00:00
|
|
|
clear_queue_action_on_fail();
|
|
|
|
|
ClearInProcess();
|
2013-12-05 16:06:40 +00:00
|
|
|
start_.UpdatePreviousBounds();
|
|
|
|
|
start_.ApplyPostponedBounds(START);
|
2011-11-03 10:27:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int64 FixedDurationPerformedIntervalVar::StartMin() const {
|
2013-06-11 14:49:19 +00:00
|
|
|
return start_.Min();
|
2011-11-03 10:27:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int64 FixedDurationPerformedIntervalVar::StartMax() const {
|
2013-06-11 14:49:19 +00:00
|
|
|
return start_.Max();
|
2011-11-03 10:27:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void FixedDurationPerformedIntervalVar::SetStartMin(int64 m) {
|
2013-12-05 16:06:40 +00:00
|
|
|
start_.SetMin(m);
|
2011-11-03 10:27:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void FixedDurationPerformedIntervalVar::SetStartMax(int64 m) {
|
2013-12-05 16:06:40 +00:00
|
|
|
start_.SetMax(m);
|
2011-11-03 10:27:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void FixedDurationPerformedIntervalVar::SetStartRange(int64 mi, int64 ma) {
|
2013-12-05 16:06:40 +00:00
|
|
|
start_.SetRange(mi, ma);
|
2011-11-03 10:27:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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_);
|
2011-11-03 10:27:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int64 FixedDurationPerformedIntervalVar::EndMax() const {
|
2013-06-11 14:49:19 +00:00
|
|
|
return CapAdd(start_.Max(), duration_);
|
2011-11-03 10:27:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void FixedDurationPerformedIntervalVar::SetEndMin(int64 m) {
|
2013-06-11 14:49:19 +00:00
|
|
|
SetStartMin(CapSub(m, duration_));
|
2011-11-03 10:27:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void FixedDurationPerformedIntervalVar::SetEndMax(int64 m) {
|
2013-06-11 14:49:19 +00:00
|
|
|
SetStartMax(CapSub(m, duration_));
|
2011-11-03 10:27:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void FixedDurationPerformedIntervalVar::SetEndRange(int64 mi, int64 ma) {
|
2013-06-11 14:49:19 +00:00
|
|
|
SetStartRange(CapSub(mi, duration_), CapSub(ma, duration_));
|
2011-11-03 10:27:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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; }
|
2011-11-03 10:27:53 +00:00
|
|
|
|
2013-06-11 14:49:19 +00:00
|
|
|
bool FixedDurationPerformedIntervalVar::MayBePerformed() const { return true; }
|
2011-11-03 10:27:53 +00:00
|
|
|
|
|
|
|
|
void FixedDurationPerformedIntervalVar::SetPerformed(bool val) {
|
|
|
|
|
if (!val) {
|
|
|
|
|
solver()->Fail();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void FixedDurationPerformedIntervalVar::Push() {
|
2013-06-11 14:49:19 +00:00
|
|
|
DCHECK(!in_process_);
|
2012-09-07 15:27:53 +00:00
|
|
|
EnqueueVar(&handler_);
|
2013-06-11 14:49:19 +00:00
|
|
|
DCHECK(!in_process_);
|
2011-11-03 10:27:53 +00:00
|
|
|
}
|
|
|
|
|
|
2013-12-16 10:24:42 +00:00
|
|
|
std::string FixedDurationPerformedIntervalVar::DebugString() const {
|
|
|
|
|
std::string out;
|
|
|
|
|
const std::string& var_name = name();
|
2011-11-03 10:27:53 +00:00
|
|
|
if (!var_name.empty()) {
|
|
|
|
|
out = var_name + "(start = ";
|
|
|
|
|
} else {
|
|
|
|
|
out = "IntervalVar(start = ";
|
|
|
|
|
}
|
2013-06-11 14:49:19 +00:00
|
|
|
StringAppendF(&out, "%s, duration = %" GG_LL_FORMAT "d, performed = true)",
|
|
|
|
|
start_.DebugString().c_str(), duration_);
|
2011-11-03 10:27:53 +00:00
|
|
|
return out;
|
|
|
|
|
}
|
|
|
|
|
|
2012-06-12 15:20:03 +00:00
|
|
|
// ----- StartVarPerformedIntervalVar -----
|
|
|
|
|
|
|
|
|
|
class StartVarPerformedIntervalVar : public IntervalVar {
|
|
|
|
|
public:
|
2013-06-11 14:49:19 +00:00
|
|
|
StartVarPerformedIntervalVar(Solver* const s, IntVar* const start_var,
|
2013-12-16 10:24:42 +00:00
|
|
|
int64 duration, const std::string& name);
|
2012-06-12 15:20:03 +00:00
|
|
|
virtual ~StartVarPerformedIntervalVar() {}
|
|
|
|
|
|
|
|
|
|
virtual int64 StartMin() const;
|
|
|
|
|
virtual int64 StartMax() const;
|
|
|
|
|
virtual void SetStartMin(int64 m);
|
|
|
|
|
virtual void SetStartMax(int64 m);
|
|
|
|
|
virtual void SetStartRange(int64 mi, int64 ma);
|
2013-06-11 14:49:19 +00:00
|
|
|
virtual int64 OldStartMin() const { return start_var_->OldMin(); }
|
|
|
|
|
virtual int64 OldStartMax() const { return start_var_->OldMax(); }
|
|
|
|
|
virtual void WhenStartRange(Demon* const d) { start_var_->WhenRange(d); }
|
|
|
|
|
virtual void WhenStartBound(Demon* const d) { start_var_->WhenBound(d); }
|
2012-06-12 15:20:03 +00:00
|
|
|
|
|
|
|
|
virtual int64 DurationMin() const;
|
|
|
|
|
virtual int64 DurationMax() const;
|
|
|
|
|
virtual void SetDurationMin(int64 m);
|
|
|
|
|
virtual void SetDurationMax(int64 m);
|
|
|
|
|
virtual void SetDurationRange(int64 mi, int64 ma);
|
2013-06-11 14:49:19 +00:00
|
|
|
virtual int64 OldDurationMin() const { return duration_; }
|
|
|
|
|
virtual int64 OldDurationMax() const { return duration_; }
|
|
|
|
|
virtual void WhenDurationRange(Demon* const d) {}
|
|
|
|
|
virtual void WhenDurationBound(Demon* const d) {}
|
2012-06-12 15:20:03 +00:00
|
|
|
|
|
|
|
|
virtual int64 EndMin() const;
|
|
|
|
|
virtual int64 EndMax() const;
|
|
|
|
|
virtual void SetEndMin(int64 m);
|
|
|
|
|
virtual void SetEndMax(int64 m);
|
|
|
|
|
virtual void SetEndRange(int64 mi, int64 ma);
|
2013-06-11 14:49:19 +00:00
|
|
|
virtual int64 OldEndMin() const { return CapAdd(OldStartMin(), duration_); }
|
|
|
|
|
virtual int64 OldEndMax() const { return CapAdd(OldStartMax(), duration_); }
|
|
|
|
|
virtual void WhenEndRange(Demon* const d) { start_var_->WhenRange(d); }
|
|
|
|
|
virtual void WhenEndBound(Demon* const d) { start_var_->WhenBound(d); }
|
2012-06-12 15:20:03 +00:00
|
|
|
|
|
|
|
|
virtual bool MustBePerformed() const;
|
|
|
|
|
virtual bool MayBePerformed() const;
|
|
|
|
|
virtual void SetPerformed(bool val);
|
2013-06-11 14:49:19 +00:00
|
|
|
virtual bool WasPerformedBound() const { return true; }
|
2012-06-12 15:20:03 +00:00
|
|
|
virtual void WhenPerformedBound(Demon* const d) {}
|
2013-12-16 10:24:42 +00:00
|
|
|
virtual std::string DebugString() const;
|
2012-06-12 15:20:03 +00:00
|
|
|
|
2013-12-05 09:29:08 +00:00
|
|
|
virtual IntExpr* StartExpr() { return start_var_; }
|
|
|
|
|
virtual IntExpr* DurationExpr() { return solver()->MakeIntConst(duration_); }
|
|
|
|
|
virtual IntExpr* EndExpr() {
|
|
|
|
|
return solver()->MakeSum(start_var_, duration_);
|
|
|
|
|
}
|
|
|
|
|
virtual IntExpr* PerformedExpr() { return solver()->MakeIntConst(1); }
|
|
|
|
|
virtual IntExpr* SafeStartExpr(int64 unperformed_value) {
|
|
|
|
|
return StartExpr();
|
|
|
|
|
}
|
|
|
|
|
virtual IntExpr* SafeDurationExpr(int64 unperformed_value) {
|
|
|
|
|
return DurationExpr();
|
|
|
|
|
}
|
|
|
|
|
virtual IntExpr* SafeEndExpr(int64 unperformed_value) { return EndExpr(); }
|
|
|
|
|
|
2012-06-12 15:20:03 +00:00
|
|
|
virtual void Accept(ModelVisitor* const visitor) const {
|
2013-06-11 14:49:19 +00:00
|
|
|
visitor->VisitIntervalVariable(this, "", 0, NullInterval());
|
2012-06-12 15:20:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
IntVar* const start_var_;
|
|
|
|
|
int64 duration_;
|
|
|
|
|
};
|
|
|
|
|
|
2012-09-13 14:15:39 +00:00
|
|
|
// TODO(user): Take care of overflows.
|
2014-07-07 13:29:56 +00:00
|
|
|
StartVarPerformedIntervalVar::StartVarPerformedIntervalVar(
|
|
|
|
|
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) {}
|
2012-06-12 15:20:03 +00:00
|
|
|
|
|
|
|
|
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_; }
|
2012-06-12 15:20:03 +00:00
|
|
|
|
2013-06-11 14:49:19 +00:00
|
|
|
int64 StartVarPerformedIntervalVar::DurationMax() const { return duration_; }
|
2012-06-12 15:20:03 +00:00
|
|
|
|
|
|
|
|
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) {
|
|
|
|
|
SetStartMin(m - duration_);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void StartVarPerformedIntervalVar::SetEndMax(int64 m) {
|
|
|
|
|
SetStartMax(m - duration_);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void StartVarPerformedIntervalVar::SetEndRange(int64 mi, int64 ma) {
|
|
|
|
|
SetStartRange(mi - duration_, 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; }
|
2012-06-12 15:20:03 +00:00
|
|
|
|
2013-06-11 14:49:19 +00:00
|
|
|
bool StartVarPerformedIntervalVar::MayBePerformed() const { return true; }
|
2012-06-12 15:20:03 +00:00
|
|
|
|
|
|
|
|
void StartVarPerformedIntervalVar::SetPerformed(bool val) {
|
|
|
|
|
if (!val) {
|
|
|
|
|
solver()->Fail();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2013-12-16 10:24:42 +00:00
|
|
|
std::string StartVarPerformedIntervalVar::DebugString() const {
|
|
|
|
|
std::string out;
|
|
|
|
|
const std::string& var_name = name();
|
2012-06-12 15:20:03 +00:00
|
|
|
if (!var_name.empty()) {
|
|
|
|
|
out = var_name + "(start = ";
|
|
|
|
|
} else {
|
|
|
|
|
out = "IntervalVar(start = ";
|
|
|
|
|
}
|
|
|
|
|
StringAppendF(&out, "%" GG_LL_FORMAT "d", start_var_->Min());
|
|
|
|
|
if (!start_var_->Bound()) {
|
|
|
|
|
StringAppendF(&out, " .. %" GG_LL_FORMAT "d", start_var_->Max());
|
|
|
|
|
}
|
|
|
|
|
|
2013-06-11 14:49:19 +00:00
|
|
|
StringAppendF(&out, ", duration = %" GG_LL_FORMAT "d, performed = true)",
|
|
|
|
|
duration_);
|
2012-06-12 15:20:03 +00:00
|
|
|
return out;
|
|
|
|
|
}
|
|
|
|
|
|
2014-05-26 17:59:03 +00:00
|
|
|
// ----- StartVarIntervalVar -----
|
|
|
|
|
|
|
|
|
|
class StartVarIntervalVar : public BaseIntervalVar {
|
|
|
|
|
public:
|
|
|
|
|
StartVarIntervalVar(Solver* const s, IntVar* const start, int64 duration,
|
2014-05-26 22:13:00 +00:00
|
|
|
IntVar* const performed, const std::string& name);
|
2014-05-26 17:59:03 +00:00
|
|
|
virtual ~StartVarIntervalVar() {}
|
|
|
|
|
|
|
|
|
|
virtual int64 StartMin() const;
|
|
|
|
|
virtual int64 StartMax() const;
|
|
|
|
|
virtual void SetStartMin(int64 m);
|
|
|
|
|
virtual void SetStartMax(int64 m);
|
|
|
|
|
virtual void SetStartRange(int64 mi, int64 ma);
|
|
|
|
|
virtual int64 OldStartMin() const { return start_->OldMin(); }
|
|
|
|
|
virtual int64 OldStartMax() const { return start_->OldMax(); }
|
|
|
|
|
virtual void WhenStartRange(Demon* const d) {
|
|
|
|
|
if (performed_->Max() == 1) {
|
|
|
|
|
start_->WhenRange(d);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
virtual void WhenStartBound(Demon* const d) {
|
|
|
|
|
if (performed_->Max() == 1) {
|
|
|
|
|
start_->WhenBound(d);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
virtual int64 DurationMin() const;
|
|
|
|
|
virtual int64 DurationMax() const;
|
|
|
|
|
virtual void SetDurationMin(int64 m);
|
|
|
|
|
virtual void SetDurationMax(int64 m);
|
|
|
|
|
virtual void SetDurationRange(int64 mi, int64 ma);
|
|
|
|
|
virtual int64 OldDurationMin() const { return duration_; }
|
|
|
|
|
virtual int64 OldDurationMax() const { return duration_; }
|
|
|
|
|
virtual void WhenDurationRange(Demon* const d) {}
|
|
|
|
|
virtual void WhenDurationBound(Demon* const d) {}
|
|
|
|
|
|
|
|
|
|
virtual int64 EndMin() const;
|
|
|
|
|
virtual int64 EndMax() const;
|
|
|
|
|
virtual void SetEndMin(int64 m);
|
|
|
|
|
virtual void SetEndMax(int64 m);
|
|
|
|
|
virtual void SetEndRange(int64 mi, int64 ma);
|
|
|
|
|
virtual int64 OldEndMin() const { return CapAdd(OldStartMin(), duration_); }
|
|
|
|
|
virtual int64 OldEndMax() const { return CapAdd(OldStartMax(), duration_); }
|
|
|
|
|
virtual void WhenEndRange(Demon* const d) { WhenStartRange(d); }
|
|
|
|
|
virtual void WhenEndBound(Demon* const d) { WhenStartBound(d); }
|
|
|
|
|
|
|
|
|
|
virtual bool MustBePerformed() const;
|
|
|
|
|
virtual bool MayBePerformed() const;
|
|
|
|
|
virtual void SetPerformed(bool val);
|
|
|
|
|
virtual bool WasPerformedBound() const {
|
|
|
|
|
return performed_->OldMin() == performed_->OldMax();
|
|
|
|
|
}
|
|
|
|
|
virtual void WhenPerformedBound(Demon* const d) { performed_->WhenBound(d); }
|
2014-05-26 22:13:00 +00:00
|
|
|
virtual std::string DebugString() const;
|
2014-05-26 17:59:03 +00:00
|
|
|
|
|
|
|
|
virtual void Accept(ModelVisitor* const visitor) const {
|
|
|
|
|
visitor->VisitIntervalVariable(this, "", 0, NullInterval());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
virtual IntExpr* StartExpr() { return start_; }
|
|
|
|
|
virtual IntExpr* DurationExpr() { return solver()->MakeIntConst(duration_); }
|
|
|
|
|
virtual IntExpr* EndExpr() {
|
|
|
|
|
return solver()->MakeSum(StartExpr(), duration_);
|
|
|
|
|
}
|
|
|
|
|
virtual IntExpr* PerformedExpr() { return performed_; }
|
|
|
|
|
virtual IntExpr* SafeStartExpr(int64 unperformed_value) {
|
|
|
|
|
return BuildSafeStartExpr(this, unperformed_value);
|
|
|
|
|
}
|
|
|
|
|
virtual IntExpr* SafeDurationExpr(int64 unperformed_value) {
|
|
|
|
|
return BuildSafeDurationExpr(this, unperformed_value);
|
|
|
|
|
}
|
|
|
|
|
virtual IntExpr* SafeEndExpr(int64 unperformed_value) {
|
|
|
|
|
return BuildSafeEndExpr(this, unperformed_value);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
virtual void Process() { LOG(FATAL) << "Should not be here"; }
|
|
|
|
|
|
|
|
|
|
virtual void Push() { LOG(FATAL) << "Should not be here"; }
|
|
|
|
|
|
2014-07-07 13:29:56 +00:00
|
|
|
int64 StoredMin() const { return start_min_.Value(); }
|
|
|
|
|
int64 StoredMax() const { return start_max_.Value(); }
|
|
|
|
|
|
2014-05-26 17:59:03 +00:00
|
|
|
private:
|
|
|
|
|
IntVar* const start_;
|
|
|
|
|
int64 duration_;
|
|
|
|
|
IntVar* const performed_;
|
|
|
|
|
Rev<int64> start_min_;
|
|
|
|
|
Rev<int64> start_max_;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
StartVarIntervalVar::StartVarIntervalVar(Solver* const s, IntVar* const start,
|
|
|
|
|
int64 duration,
|
|
|
|
|
IntVar* const performed,
|
2014-05-26 22:13:00 +00:00
|
|
|
const std::string& name)
|
2014-05-26 17:59:03 +00:00
|
|
|
: BaseIntervalVar(s, name),
|
|
|
|
|
start_(start),
|
|
|
|
|
duration_(duration),
|
|
|
|
|
performed_(performed),
|
|
|
|
|
start_min_(start->Min()),
|
|
|
|
|
start_max_(start->Max()) {}
|
|
|
|
|
|
|
|
|
|
int64 StartVarIntervalVar::StartMin() const {
|
|
|
|
|
CHECK_EQ(performed_->Max(), 1);
|
|
|
|
|
return std::max(start_->Min(), start_min_.Value());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int64 StartVarIntervalVar::StartMax() const {
|
|
|
|
|
CHECK_EQ(performed_->Max(), 1);
|
|
|
|
|
return std::min(start_->Max(), start_max_.Value());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void StartVarIntervalVar::SetStartMin(int64 m) {
|
2014-07-07 13:29:56 +00:00
|
|
|
if (performed_->Min() == 1) {
|
2014-05-26 17:59:03 +00:00
|
|
|
start_->SetMin(m);
|
|
|
|
|
} else {
|
|
|
|
|
start_min_.SetValue(solver(), std::max(m, start_min_.Value()));
|
2014-07-04 13:24:05 +00:00
|
|
|
if (start_min_.Value() > std::min(start_max_.Value(), start_->Max())) {
|
2014-05-26 17:59:03 +00:00
|
|
|
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()));
|
2014-07-04 13:24:05 +00:00
|
|
|
if (start_max_.Value() < std::max(start_min_.Value(), start_->Min())) {
|
2014-05-26 17:59:03 +00:00
|
|
|
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()));
|
2014-07-04 13:24:05 +00:00
|
|
|
if (std::max(start_min_.Value(), start_->Min()) >
|
|
|
|
|
std::min(start_max_.Value(), start_->Max())) {
|
2014-05-26 17:59:03 +00:00
|
|
|
performed_->SetValue(0);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int64 StartVarIntervalVar::DurationMin() const {
|
|
|
|
|
CHECK_EQ(performed_->Max(), 1);
|
|
|
|
|
return duration_;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int64 StartVarIntervalVar::DurationMax() const {
|
|
|
|
|
CHECK_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 {
|
|
|
|
|
return CapAdd(StartMin(), duration_);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int64 StartVarIntervalVar::EndMax() const {
|
|
|
|
|
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 {
|
2014-05-26 17:59:03 +00:00
|
|
|
const std::string& var_name = name();
|
|
|
|
|
if (performed_->Max() == 0) {
|
|
|
|
|
if (!var_name.empty()) {
|
|
|
|
|
return StringPrintf("%s(performed = false)", var_name.c_str());
|
|
|
|
|
} else {
|
|
|
|
|
return "IntervalVar(performed = false)";
|
|
|
|
|
}
|
|
|
|
|
} else {
|
2014-05-26 22:13:00 +00:00
|
|
|
std::string out;
|
2014-05-26 17:59:03 +00:00
|
|
|
if (!var_name.empty()) {
|
|
|
|
|
out = var_name + "(start = ";
|
|
|
|
|
} else {
|
|
|
|
|
out = "IntervalVar(start = ";
|
|
|
|
|
}
|
|
|
|
|
StringAppendF(&out, "%s, duration = %" GG_LL_FORMAT "d, performed = %s)",
|
|
|
|
|
start_->DebugString().c_str(), duration_,
|
|
|
|
|
performed_->DebugString().c_str());
|
|
|
|
|
return out;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2014-07-07 13:29:56 +00:00
|
|
|
class LinkStartVarIntervalVar : public Constraint {
|
|
|
|
|
public:
|
|
|
|
|
LinkStartVarIntervalVar(Solver* const solver,
|
|
|
|
|
StartVarIntervalVar* const interval,
|
|
|
|
|
IntVar* const start, IntVar* const performed)
|
|
|
|
|
: Constraint(solver),
|
|
|
|
|
interval_(interval),
|
|
|
|
|
start_(start),
|
|
|
|
|
performed_(performed) {}
|
|
|
|
|
|
|
|
|
|
~LinkStartVarIntervalVar() {}
|
|
|
|
|
|
|
|
|
|
virtual void Post() {
|
|
|
|
|
Demon* const demon = MakeConstraintDemon0(
|
|
|
|
|
solver(), this, &LinkStartVarIntervalVar::PerformedBound,
|
|
|
|
|
"PerformedBound");
|
|
|
|
|
performed_->WhenBound(demon);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
virtual void InitialPropagate() {
|
|
|
|
|
if (performed_->Bound()) {
|
|
|
|
|
PerformedBound();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void PerformedBound() {
|
|
|
|
|
if (performed_->Min() == 1) {
|
|
|
|
|
start_->SetRange(interval_->StoredMin(), interval_->StoredMax());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
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 {
|
|
|
|
|
public:
|
|
|
|
|
FixedInterval(Solver* const s, int64 start, int64 duration,
|
2013-12-16 10:24:42 +00:00
|
|
|
const std::string& name);
|
2010-09-15 12:42:33 +00:00
|
|
|
virtual ~FixedInterval() {}
|
|
|
|
|
|
|
|
|
|
virtual int64 StartMin() const { return start_; }
|
|
|
|
|
virtual int64 StartMax() const { return start_; }
|
|
|
|
|
virtual void SetStartMin(int64 m);
|
|
|
|
|
virtual void SetStartMax(int64 m);
|
|
|
|
|
virtual void SetStartRange(int64 mi, int64 ma);
|
2013-06-11 14:49:19 +00:00
|
|
|
virtual int64 OldStartMin() const { return start_; }
|
|
|
|
|
virtual int64 OldStartMax() const { return start_; }
|
2010-09-15 12:42:33 +00:00
|
|
|
virtual void WhenStartRange(Demon* const d) {}
|
|
|
|
|
virtual void WhenStartBound(Demon* const d) {}
|
|
|
|
|
|
|
|
|
|
virtual int64 DurationMin() const { return duration_; }
|
|
|
|
|
virtual int64 DurationMax() const { return duration_; }
|
|
|
|
|
virtual void SetDurationMin(int64 m);
|
|
|
|
|
virtual void SetDurationMax(int64 m);
|
|
|
|
|
virtual void SetDurationRange(int64 mi, int64 ma);
|
2013-06-11 14:49:19 +00:00
|
|
|
virtual int64 OldDurationMin() const { return duration_; }
|
|
|
|
|
virtual int64 OldDurationMax() const { return duration_; }
|
|
|
|
|
virtual void WhenDurationRange(Demon* const d) {}
|
|
|
|
|
virtual void WhenDurationBound(Demon* const d) {}
|
2010-09-15 12:42:33 +00:00
|
|
|
|
|
|
|
|
virtual int64 EndMin() const { return start_ + duration_; }
|
|
|
|
|
virtual int64 EndMax() const { return start_ + duration_; }
|
|
|
|
|
virtual void SetEndMin(int64 m);
|
|
|
|
|
virtual void SetEndMax(int64 m);
|
|
|
|
|
virtual void SetEndRange(int64 mi, int64 ma);
|
2013-06-11 14:49:19 +00:00
|
|
|
virtual int64 OldEndMin() const { return start_ + duration_; }
|
|
|
|
|
virtual int64 OldEndMax() const { return start_ + duration_; }
|
|
|
|
|
virtual void WhenEndRange(Demon* const d) {}
|
2010-09-15 12:42:33 +00:00
|
|
|
virtual void WhenEndBound(Demon* const d) {}
|
|
|
|
|
|
2010-11-02 19:02:53 +00:00
|
|
|
virtual bool MustBePerformed() const { return true; }
|
|
|
|
|
virtual bool MayBePerformed() const { return true; }
|
2010-09-15 12:42:33 +00:00
|
|
|
virtual void SetPerformed(bool val);
|
2013-06-11 14:49:19 +00:00
|
|
|
virtual bool WasPerformedBound() const { return true; }
|
2010-09-15 12:42:33 +00:00
|
|
|
virtual void WhenPerformedBound(Demon* const d) {}
|
2013-12-16 10:24:42 +00:00
|
|
|
virtual std::string DebugString() const;
|
2011-07-11 20:13:14 +00:00
|
|
|
|
|
|
|
|
virtual void Accept(ModelVisitor* const visitor) const {
|
2013-06-11 14:49:19 +00:00
|
|
|
visitor->VisitIntervalVariable(this, "", 0, NullInterval());
|
2011-07-11 20:13:14 +00:00
|
|
|
}
|
|
|
|
|
|
2013-12-05 09:29:08 +00:00
|
|
|
virtual IntExpr* StartExpr() { return solver()->MakeIntConst(start_); }
|
|
|
|
|
virtual IntExpr* DurationExpr() { return solver()->MakeIntConst(duration_); }
|
|
|
|
|
virtual IntExpr* EndExpr() {
|
|
|
|
|
return solver()->MakeIntConst(start_ + duration_);
|
|
|
|
|
}
|
|
|
|
|
virtual IntExpr* PerformedExpr() { return solver()->MakeIntConst(1); }
|
|
|
|
|
virtual IntExpr* SafeStartExpr(int64 unperformed_value) {
|
|
|
|
|
return StartExpr();
|
|
|
|
|
}
|
|
|
|
|
virtual IntExpr* SafeDurationExpr(int64 unperformed_value) {
|
|
|
|
|
return DurationExpr();
|
|
|
|
|
}
|
|
|
|
|
virtual IntExpr* SafeEndExpr(int64 unperformed_value) { return EndExpr(); }
|
|
|
|
|
|
2010-09-15 12:42:33 +00:00
|
|
|
private:
|
|
|
|
|
const int64 start_;
|
|
|
|
|
const int64 duration_;
|
|
|
|
|
};
|
|
|
|
|
|
2013-06-11 14:49:19 +00:00
|
|
|
FixedInterval::FixedInterval(Solver* const s, int64 start, int64 duration,
|
2013-12-16 10:24:42 +00:00
|
|
|
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();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2013-12-16 10:24:42 +00:00
|
|
|
std::string FixedInterval::DebugString() const {
|
|
|
|
|
std::string out;
|
|
|
|
|
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 = ";
|
|
|
|
|
}
|
|
|
|
|
StringAppendF(&out, "%" GG_LL_FORMAT "d, duration = %" GG_LL_FORMAT
|
2014-07-07 13:29:56 +00:00
|
|
|
"d, performed = true)",
|
2010-09-15 12:42:33 +00:00
|
|
|
start_, duration_);
|
|
|
|
|
return out;
|
|
|
|
|
}
|
2013-06-11 14:49:19 +00:00
|
|
|
|
|
|
|
|
// ----- VariableDurationIntervalVar -----
|
|
|
|
|
|
|
|
|
|
class VariableDurationIntervalVar : public BaseIntervalVar {
|
|
|
|
|
public:
|
|
|
|
|
VariableDurationIntervalVar(Solver* const s, int64 start_min, int64 start_max,
|
|
|
|
|
int64 duration_min, int64 duration_max,
|
|
|
|
|
int64 end_min, int64 end_max, bool optional,
|
2013-12-16 10:24:42 +00:00
|
|
|
const std::string& name)
|
2013-06-11 14:49:19 +00:00
|
|
|
: BaseIntervalVar(s, name),
|
2013-12-05 16:06:40 +00:00
|
|
|
start_(s, this, std::max(start_min, end_min - duration_max),
|
2013-06-11 14:49:19 +00:00
|
|
|
std::min(start_max, end_max - duration_min)),
|
2013-12-05 16:06:40 +00:00
|
|
|
duration_(s, this, std::max(duration_min, end_min - start_max),
|
2013-06-11 14:49:19 +00:00
|
|
|
std::min(duration_max, end_max - start_min)),
|
2013-12-05 16:06:40 +00:00
|
|
|
end_(s, this, std::max(end_min, start_min + duration_min),
|
2013-06-11 14:49:19 +00:00
|
|
|
std::min(end_max, start_max + duration_max)),
|
2013-12-05 16:06:40 +00:00
|
|
|
performed_(s, this, optional) {}
|
2013-06-11 14:49:19 +00:00
|
|
|
|
|
|
|
|
virtual ~VariableDurationIntervalVar() {}
|
|
|
|
|
|
|
|
|
|
virtual int64 StartMin() const {
|
2013-12-05 09:29:08 +00:00
|
|
|
CHECK_EQ(performed_.Max(), 1);
|
2013-06-11 14:49:19 +00:00
|
|
|
return start_.Min();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
virtual int64 StartMax() const {
|
2013-12-05 09:29:08 +00:00
|
|
|
CHECK_EQ(performed_.Max(), 1);
|
2013-06-11 14:49:19 +00:00
|
|
|
return start_.Max();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
virtual void SetStartMin(int64 m) {
|
2013-12-05 09:29:08 +00:00
|
|
|
if (performed_.Max() == 1) {
|
2013-12-05 16:06:40 +00:00
|
|
|
start_.SetMin(m);
|
2013-06-11 14:49:19 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
virtual void SetStartMax(int64 m) {
|
2013-12-05 09:29:08 +00:00
|
|
|
if (performed_.Max() == 1) {
|
2013-12-05 16:06:40 +00:00
|
|
|
start_.SetMax(m);
|
2013-06-11 14:49:19 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
virtual void SetStartRange(int64 mi, int64 ma) {
|
2013-12-05 09:29:08 +00:00
|
|
|
if (performed_.Max() == 1) {
|
2013-12-05 16:06:40 +00:00
|
|
|
start_.SetRange(mi, ma);
|
2013-06-11 14:49:19 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
virtual int64 OldStartMin() const {
|
2013-12-05 09:29:08 +00:00
|
|
|
CHECK_EQ(performed_.Max(), 1);
|
2013-06-11 14:49:19 +00:00
|
|
|
CHECK(in_process_);
|
2013-12-05 16:06:40 +00:00
|
|
|
return start_.OldMin();
|
2013-06-11 14:49:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
virtual int64 OldStartMax() const {
|
2013-12-05 09:29:08 +00:00
|
|
|
CHECK_EQ(performed_.Max(), 1);
|
2013-06-11 14:49:19 +00:00
|
|
|
CHECK(in_process_);
|
2013-12-05 16:06:40 +00:00
|
|
|
return start_.OldMax();
|
2013-06-11 14:49:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
virtual void WhenStartRange(Demon* const d) {
|
2013-12-05 09:29:08 +00:00
|
|
|
if (performed_.Max() == 1) {
|
2013-06-11 14:49:19 +00:00
|
|
|
start_.WhenRange(d);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
virtual void WhenStartBound(Demon* const d) {
|
2013-12-05 09:29:08 +00:00
|
|
|
if (performed_.Max() == 1) {
|
2013-06-11 14:49:19 +00:00
|
|
|
start_.WhenBound(d);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
virtual int64 DurationMin() const {
|
2013-12-05 09:29:08 +00:00
|
|
|
CHECK_EQ(performed_.Max(), 1);
|
2013-06-11 14:49:19 +00:00
|
|
|
return duration_.Min();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
virtual int64 DurationMax() const {
|
2013-12-05 09:29:08 +00:00
|
|
|
CHECK_EQ(performed_.Max(), 1);
|
2013-06-11 14:49:19 +00:00
|
|
|
return duration_.Max();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
virtual void SetDurationMin(int64 m) {
|
2013-12-05 09:29:08 +00:00
|
|
|
if (performed_.Max() == 1) {
|
2013-12-05 16:06:40 +00:00
|
|
|
duration_.SetMin(m);
|
2013-06-11 14:49:19 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
virtual void SetDurationMax(int64 m) {
|
2013-12-05 09:29:08 +00:00
|
|
|
if (performed_.Max() == 1) {
|
2013-12-05 16:06:40 +00:00
|
|
|
duration_.SetMax(m);
|
2013-06-11 14:49:19 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
virtual void SetDurationRange(int64 mi, int64 ma) {
|
2013-12-05 09:29:08 +00:00
|
|
|
if (performed_.Max() == 1) {
|
2013-12-05 16:06:40 +00:00
|
|
|
duration_.SetRange(mi, ma);
|
2013-06-11 14:49:19 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
virtual int64 OldDurationMin() const {
|
2013-12-05 09:29:08 +00:00
|
|
|
CHECK_EQ(performed_.Max(), 1);
|
2013-06-11 14:49:19 +00:00
|
|
|
CHECK(in_process_);
|
2013-12-05 16:06:40 +00:00
|
|
|
return duration_.OldMin();
|
2013-06-11 14:49:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
virtual int64 OldDurationMax() const {
|
2013-12-05 09:29:08 +00:00
|
|
|
CHECK_EQ(performed_.Max(), 1);
|
2013-06-11 14:49:19 +00:00
|
|
|
CHECK(in_process_);
|
2013-12-05 16:06:40 +00:00
|
|
|
return duration_.OldMax();
|
2013-06-11 14:49:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
virtual void WhenDurationRange(Demon* const d) {
|
2013-12-05 09:29:08 +00:00
|
|
|
if (performed_.Max() == 1) {
|
2013-06-11 14:49:19 +00:00
|
|
|
duration_.WhenRange(d);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
virtual void WhenDurationBound(Demon* const d) {
|
2013-12-05 09:29:08 +00:00
|
|
|
if (performed_.Max() == 1) {
|
2013-06-11 14:49:19 +00:00
|
|
|
duration_.WhenBound(d);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
virtual int64 EndMin() const {
|
2013-12-05 09:29:08 +00:00
|
|
|
CHECK_EQ(performed_.Max(), 1);
|
2013-06-11 14:49:19 +00:00
|
|
|
return end_.Min();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
virtual int64 EndMax() const {
|
2013-12-05 09:29:08 +00:00
|
|
|
CHECK_EQ(performed_.Max(), 1);
|
2013-06-11 14:49:19 +00:00
|
|
|
return end_.Max();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
virtual void SetEndMin(int64 m) {
|
2013-12-05 09:29:08 +00:00
|
|
|
if (performed_.Max() == 1) {
|
2013-12-05 16:06:40 +00:00
|
|
|
end_.SetMin(m);
|
2013-06-11 14:49:19 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
virtual void SetEndMax(int64 m) {
|
2013-12-05 09:29:08 +00:00
|
|
|
if (performed_.Max() == 1) {
|
2013-12-05 16:06:40 +00:00
|
|
|
end_.SetMax(m);
|
2013-06-11 14:49:19 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
virtual void SetEndRange(int64 mi, int64 ma) {
|
2013-12-05 09:29:08 +00:00
|
|
|
if (performed_.Max() == 1) {
|
2013-12-05 16:06:40 +00:00
|
|
|
end_.SetRange(mi, ma);
|
2013-06-11 14:49:19 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
virtual int64 OldEndMin() const {
|
2013-12-05 09:29:08 +00:00
|
|
|
CHECK_EQ(performed_.Max(), 1);
|
2013-12-05 16:06:40 +00:00
|
|
|
DCHECK(in_process_);
|
|
|
|
|
return end_.OldMin();
|
2013-06-11 14:49:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
virtual int64 OldEndMax() const {
|
2013-12-05 09:29:08 +00:00
|
|
|
CHECK_EQ(performed_.Max(), 1);
|
2013-12-05 16:06:40 +00:00
|
|
|
DCHECK(in_process_);
|
|
|
|
|
return end_.OldMax();
|
2013-06-11 14:49:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
virtual void WhenEndRange(Demon* const d) {
|
2013-12-05 09:29:08 +00:00
|
|
|
if (performed_.Max() == 1) {
|
2013-06-11 14:49:19 +00:00
|
|
|
end_.WhenRange(d);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
virtual void WhenEndBound(Demon* const d) {
|
2013-12-05 09:29:08 +00:00
|
|
|
if (performed_.Max() == 1) {
|
2013-06-11 14:49:19 +00:00
|
|
|
end_.WhenBound(d);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2013-12-05 09:29:08 +00:00
|
|
|
virtual bool MustBePerformed() const { return (performed_.Min() == 1); }
|
2013-06-11 14:49:19 +00:00
|
|
|
|
2013-12-05 09:29:08 +00:00
|
|
|
virtual bool MayBePerformed() const { return (performed_.Max() == 1); }
|
2013-06-11 14:49:19 +00:00
|
|
|
|
2013-12-05 16:06:40 +00:00
|
|
|
virtual void SetPerformed(bool val) { performed_.SetValue(val); }
|
2013-06-11 14:49:19 +00:00
|
|
|
|
|
|
|
|
virtual bool WasPerformedBound() const {
|
|
|
|
|
CHECK(in_process_);
|
2013-12-05 09:29:08 +00:00
|
|
|
return performed_.OldMin() == performed_.OldMax();
|
2013-06-11 14:49:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
virtual void WhenPerformedBound(Demon* const d) { performed_.WhenBound(d); }
|
|
|
|
|
|
|
|
|
|
virtual void Process() {
|
|
|
|
|
CHECK(!in_process_);
|
|
|
|
|
in_process_ = true;
|
|
|
|
|
start_.UpdatePostponedBounds();
|
|
|
|
|
duration_.UpdatePostponedBounds();
|
|
|
|
|
end_.UpdatePostponedBounds();
|
2013-12-05 09:29:08 +00:00
|
|
|
performed_.UpdatePostponedValue();
|
2013-06-11 14:49:19 +00:00
|
|
|
set_queue_action_on_fail(&cleaner_);
|
2013-12-05 09:29:08 +00:00
|
|
|
if (performed_.Max() == 1) {
|
2013-06-11 14:49:19 +00:00
|
|
|
start_.ProcessDemons();
|
|
|
|
|
duration_.ProcessDemons();
|
|
|
|
|
end_.ProcessDemons();
|
|
|
|
|
}
|
2013-12-05 09:29:08 +00:00
|
|
|
performed_.Process();
|
2013-06-11 14:49:19 +00:00
|
|
|
clear_queue_action_on_fail();
|
|
|
|
|
ClearInProcess();
|
|
|
|
|
// TODO(user): Replace this enum by a callback.
|
2013-12-05 16:06:40 +00:00
|
|
|
start_.UpdatePreviousBounds();
|
|
|
|
|
start_.ApplyPostponedBounds(START);
|
|
|
|
|
duration_.UpdatePreviousBounds();
|
|
|
|
|
duration_.ApplyPostponedBounds(DURATION);
|
|
|
|
|
end_.UpdatePreviousBounds();
|
|
|
|
|
end_.ApplyPostponedBounds(END);
|
2013-12-05 09:29:08 +00:00
|
|
|
performed_.UpdatePreviousValueAndApplyPostponedValue();
|
2013-06-11 14:49:19 +00:00
|
|
|
}
|
|
|
|
|
|
2013-12-16 10:24:42 +00:00
|
|
|
virtual std::string DebugString() const {
|
|
|
|
|
const std::string& var_name = name();
|
2013-12-05 16:06:40 +00:00
|
|
|
if (performed_.Max() != 1) {
|
2013-07-29 02:49:12 +00:00
|
|
|
if (!var_name.empty()) {
|
|
|
|
|
return StringPrintf("%s(performed = false)", var_name.c_str());
|
|
|
|
|
} else {
|
|
|
|
|
return "IntervalVar(performed = false)";
|
|
|
|
|
}
|
2013-06-11 14:49:19 +00:00
|
|
|
} else {
|
2013-12-16 10:24:42 +00:00
|
|
|
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
|
|
|
|
2013-07-29 02:49:12 +00:00
|
|
|
StringAppendF(&out, "%s, duration = %s, end = %s, performed = %s)",
|
|
|
|
|
start_.DebugString().c_str(),
|
2013-10-10 15:23:20 +00:00
|
|
|
duration_.DebugString().c_str(), end_.DebugString().c_str(),
|
2013-07-29 02:49:12 +00:00
|
|
|
performed_.DebugString().c_str());
|
|
|
|
|
return out;
|
|
|
|
|
}
|
2013-06-11 14:49:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
virtual void Accept(ModelVisitor* const visitor) const {
|
|
|
|
|
visitor->VisitIntervalVariable(this, "", 0, NullInterval());
|
|
|
|
|
}
|
|
|
|
|
|
2013-12-05 16:06:40 +00:00
|
|
|
virtual IntExpr* StartExpr() { return &start_; }
|
|
|
|
|
virtual IntExpr* DurationExpr() { return &duration_; }
|
|
|
|
|
virtual IntExpr* EndExpr() { return &end_; }
|
|
|
|
|
virtual IntExpr* PerformedExpr() { return &performed_; }
|
|
|
|
|
virtual IntExpr* SafeStartExpr(int64 unperformed_value) {
|
|
|
|
|
return BuildSafeStartExpr(this, unperformed_value);
|
|
|
|
|
}
|
|
|
|
|
virtual IntExpr* SafeDurationExpr(int64 unperformed_value) {
|
|
|
|
|
return BuildSafeDurationExpr(this, unperformed_value);
|
|
|
|
|
}
|
|
|
|
|
virtual IntExpr* SafeEndExpr(int64 unperformed_value) {
|
|
|
|
|
return BuildSafeEndExpr(this, unperformed_value);
|
|
|
|
|
}
|
2013-12-05 09:29:08 +00:00
|
|
|
|
2013-06-11 14:49:19 +00:00
|
|
|
private:
|
|
|
|
|
virtual void Push() {
|
|
|
|
|
DCHECK(!in_process_);
|
2013-12-05 09:29:08 +00:00
|
|
|
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.
|
2013-12-05 16:06:40 +00:00
|
|
|
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_);
|
|
|
|
|
}
|
|
|
|
|
|
2013-12-05 16:06:40 +00:00
|
|
|
RangeVar start_;
|
|
|
|
|
RangeVar duration_;
|
|
|
|
|
RangeVar end_;
|
2013-12-05 09:29:08 +00:00
|
|
|
PerformedVar performed_;
|
2013-06-11 14:49:19 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// ----- Base synced interval var -----
|
|
|
|
|
|
|
|
|
|
class FixedDurationSyncedIntervalVar : public IntervalVar {
|
|
|
|
|
public:
|
|
|
|
|
FixedDurationSyncedIntervalVar(IntervalVar* const t, int64 duration,
|
2013-12-16 10:24:42 +00:00
|
|
|
int64 offset, const std::string& name)
|
2013-06-11 14:49:19 +00:00
|
|
|
: IntervalVar(t->solver(), name),
|
|
|
|
|
t_(t),
|
|
|
|
|
duration_(duration),
|
|
|
|
|
offset_(offset) {}
|
|
|
|
|
virtual ~FixedDurationSyncedIntervalVar() {}
|
|
|
|
|
virtual int64 DurationMin() const { return duration_; }
|
|
|
|
|
virtual int64 DurationMax() const { return duration_; }
|
|
|
|
|
virtual void SetDurationMin(int64 m) {
|
|
|
|
|
if (m > duration_) {
|
|
|
|
|
solver()->Fail();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
virtual void SetDurationMax(int64 m) {
|
|
|
|
|
if (m < duration_) {
|
|
|
|
|
solver()->Fail();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
virtual void SetDurationRange(int64 mi, int64 ma) {
|
|
|
|
|
if (mi > duration_ || ma < duration_ || mi > ma) {
|
|
|
|
|
solver()->Fail();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
virtual int64 OldDurationMin() const { return duration_; }
|
|
|
|
|
virtual int64 OldDurationMax() const { return duration_; }
|
|
|
|
|
virtual void WhenDurationRange(Demon* const d) {}
|
|
|
|
|
virtual void WhenDurationBound(Demon* const d) {}
|
|
|
|
|
virtual int64 EndMin() const { return CapAdd(StartMin(), duration_); }
|
|
|
|
|
virtual int64 EndMax() const { return CapAdd(StartMax(), duration_); }
|
|
|
|
|
virtual void SetEndMin(int64 m) { SetStartMin(CapSub(m, duration_)); }
|
|
|
|
|
virtual void SetEndMax(int64 m) { SetStartMax(CapSub(m, duration_)); }
|
|
|
|
|
virtual void SetEndRange(int64 mi, int64 ma) {
|
|
|
|
|
SetStartRange(CapSub(mi, duration_), CapSub(ma, duration_));
|
|
|
|
|
}
|
|
|
|
|
virtual int64 OldEndMin() const { return CapAdd(OldStartMin(), duration_); }
|
|
|
|
|
virtual int64 OldEndMax() const { return CapAdd(OldStartMax(), duration_); }
|
|
|
|
|
virtual void WhenEndRange(Demon* const d) { WhenStartRange(d); }
|
|
|
|
|
virtual void WhenEndBound(Demon* const d) { WhenStartBound(d); }
|
|
|
|
|
virtual bool MustBePerformed() const { return t_->MustBePerformed(); }
|
|
|
|
|
virtual bool MayBePerformed() const { return t_->MayBePerformed(); }
|
|
|
|
|
virtual void SetPerformed(bool val) { t_->SetPerformed(val); }
|
|
|
|
|
virtual bool WasPerformedBound() const { return t_->WasPerformedBound(); }
|
|
|
|
|
virtual void WhenPerformedBound(Demon* const d) { t_->WhenPerformedBound(d); }
|
|
|
|
|
|
|
|
|
|
protected:
|
|
|
|
|
IntervalVar* const t_;
|
|
|
|
|
const int64 duration_;
|
|
|
|
|
const int64 offset_;
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
DISALLOW_COPY_AND_ASSIGN(FixedDurationSyncedIntervalVar);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// ----- Fixed duration interval var synced on start -----
|
|
|
|
|
|
2013-10-10 15:23:20 +00:00
|
|
|
class FixedDurationIntervalVarStartSyncedOnStart
|
|
|
|
|
: public FixedDurationSyncedIntervalVar {
|
2013-06-11 14:49:19 +00:00
|
|
|
public:
|
|
|
|
|
FixedDurationIntervalVarStartSyncedOnStart(IntervalVar* const t,
|
|
|
|
|
int64 duration, int64 offset)
|
|
|
|
|
: FixedDurationSyncedIntervalVar(
|
|
|
|
|
t, duration, offset,
|
|
|
|
|
StringPrintf(
|
|
|
|
|
"IntervalStartSyncedOnStart(%s, duration = %" GG_LL_FORMAT
|
|
|
|
|
"d, offset = %" GG_LL_FORMAT "d)",
|
|
|
|
|
t->name().c_str(), duration, offset)) {}
|
|
|
|
|
virtual ~FixedDurationIntervalVarStartSyncedOnStart() {}
|
|
|
|
|
virtual int64 StartMin() const { return CapAdd(t_->StartMin(), offset_); }
|
|
|
|
|
virtual int64 StartMax() const { return CapAdd(t_->StartMax(), offset_); }
|
|
|
|
|
virtual void SetStartMin(int64 m) { t_->SetStartMin(CapSub(m, offset_)); }
|
|
|
|
|
virtual void SetStartMax(int64 m) { t_->SetStartMax(CapSub(m, offset_)); }
|
|
|
|
|
virtual void SetStartRange(int64 mi, int64 ma) {
|
|
|
|
|
t_->SetStartRange(CapSub(mi, offset_), CapSub(ma, offset_));
|
|
|
|
|
}
|
|
|
|
|
virtual int64 OldStartMin() const {
|
|
|
|
|
return CapAdd(t_->OldStartMin(), offset_);
|
|
|
|
|
}
|
|
|
|
|
virtual int64 OldStartMax() const {
|
|
|
|
|
return CapAdd(t_->OldStartMax(), offset_);
|
|
|
|
|
}
|
|
|
|
|
virtual void WhenStartRange(Demon* const d) { t_->WhenStartRange(d); }
|
|
|
|
|
virtual void WhenStartBound(Demon* const d) { t_->WhenStartBound(d); }
|
2013-12-05 09:29:08 +00:00
|
|
|
virtual IntExpr* StartExpr() {
|
|
|
|
|
return solver()->MakeSum(t_->StartExpr(), offset_);
|
|
|
|
|
}
|
|
|
|
|
virtual IntExpr* DurationExpr() { return solver()->MakeIntConst(duration_); }
|
|
|
|
|
virtual IntExpr* EndExpr() {
|
|
|
|
|
return solver()->MakeSum(t_->StartExpr(), offset_ + duration_);
|
|
|
|
|
}
|
|
|
|
|
virtual IntExpr* PerformedExpr() { 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.
|
|
|
|
|
virtual IntExpr* SafeStartExpr(int64 unperformed_value) {
|
|
|
|
|
return BuildSafeStartExpr(t_, unperformed_value);
|
|
|
|
|
}
|
|
|
|
|
virtual IntExpr* SafeDurationExpr(int64 unperformed_value) {
|
|
|
|
|
return BuildSafeDurationExpr(t_, unperformed_value);
|
|
|
|
|
}
|
|
|
|
|
virtual IntExpr* SafeEndExpr(int64 unperformed_value) {
|
|
|
|
|
return BuildSafeEndExpr(t_, unperformed_value);
|
|
|
|
|
}
|
2013-06-11 14:49:19 +00:00
|
|
|
virtual void Accept(ModelVisitor* const visitor) const {
|
|
|
|
|
visitor->VisitIntervalVariable(
|
|
|
|
|
this, ModelVisitor::kStartSyncOnStartOperation, offset_, t_);
|
|
|
|
|
}
|
2013-12-16 10:24:42 +00:00
|
|
|
virtual std::string DebugString() const {
|
2013-06-11 14:49:19 +00:00
|
|
|
return StringPrintf(
|
|
|
|
|
"IntervalStartSyncedOnStart(%s, duration = %" GG_LL_FORMAT
|
|
|
|
|
"d, offset = %" GG_LL_FORMAT "d)",
|
|
|
|
|
t_->DebugString().c_str(), duration_, offset_);
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// ----- Fixed duration interval start synced on end -----
|
|
|
|
|
|
2013-10-10 15:23:20 +00:00
|
|
|
class FixedDurationIntervalVarStartSyncedOnEnd
|
|
|
|
|
: public FixedDurationSyncedIntervalVar {
|
2013-06-11 14:49:19 +00:00
|
|
|
public:
|
|
|
|
|
FixedDurationIntervalVarStartSyncedOnEnd(IntervalVar* const t, int64 duration,
|
|
|
|
|
int64 offset)
|
|
|
|
|
: FixedDurationSyncedIntervalVar(
|
|
|
|
|
t, duration, offset,
|
|
|
|
|
StringPrintf(
|
|
|
|
|
"IntervalStartSyncedOnEnd(%s, duration = %" GG_LL_FORMAT
|
|
|
|
|
"d, offset = %" GG_LL_FORMAT "d)",
|
|
|
|
|
t->name().c_str(), duration, offset)) {}
|
|
|
|
|
virtual ~FixedDurationIntervalVarStartSyncedOnEnd() {}
|
|
|
|
|
virtual int64 StartMin() const { return CapAdd(t_->EndMin(), offset_); }
|
|
|
|
|
virtual int64 StartMax() const { return CapAdd(t_->EndMax(), offset_); }
|
|
|
|
|
virtual void SetStartMin(int64 m) { t_->SetEndMin(CapSub(m, offset_)); }
|
|
|
|
|
virtual void SetStartMax(int64 m) { t_->SetEndMax(CapSub(m, offset_)); }
|
|
|
|
|
virtual void SetStartRange(int64 mi, int64 ma) {
|
|
|
|
|
t_->SetEndRange(CapSub(mi, offset_), CapSub(ma, offset_));
|
|
|
|
|
}
|
|
|
|
|
virtual int64 OldStartMin() const { return CapAdd(t_->OldEndMin(), offset_); }
|
|
|
|
|
virtual int64 OldStartMax() const { return CapAdd(t_->OldEndMax(), offset_); }
|
|
|
|
|
virtual void WhenStartRange(Demon* const d) { t_->WhenEndRange(d); }
|
|
|
|
|
virtual void WhenStartBound(Demon* const d) { t_->WhenEndBound(d); }
|
2013-12-05 09:29:08 +00:00
|
|
|
virtual IntExpr* StartExpr() {
|
|
|
|
|
return solver()->MakeSum(t_->EndExpr(), offset_);
|
|
|
|
|
}
|
|
|
|
|
virtual IntExpr* DurationExpr() { return solver()->MakeIntConst(duration_); }
|
|
|
|
|
virtual IntExpr* EndExpr() {
|
|
|
|
|
return solver()->MakeSum(t_->EndExpr(), offset_ + duration_);
|
|
|
|
|
}
|
|
|
|
|
virtual IntExpr* PerformedExpr() { 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.
|
|
|
|
|
virtual IntExpr* SafeStartExpr(int64 unperformed_value) {
|
|
|
|
|
return BuildSafeStartExpr(t_, unperformed_value);
|
|
|
|
|
}
|
|
|
|
|
virtual IntExpr* SafeDurationExpr(int64 unperformed_value) {
|
|
|
|
|
return BuildSafeDurationExpr(t_, unperformed_value);
|
|
|
|
|
}
|
|
|
|
|
virtual IntExpr* SafeEndExpr(int64 unperformed_value) {
|
|
|
|
|
return BuildSafeEndExpr(t_, unperformed_value);
|
|
|
|
|
}
|
|
|
|
|
|
2013-06-11 14:49:19 +00:00
|
|
|
virtual void Accept(ModelVisitor* const visitor) const {
|
|
|
|
|
visitor->VisitIntervalVariable(this, ModelVisitor::kStartSyncOnEndOperation,
|
|
|
|
|
offset_, t_);
|
|
|
|
|
}
|
2013-12-16 10:24:42 +00:00
|
|
|
virtual std::string DebugString() const {
|
2013-06-11 14:49:19 +00:00
|
|
|
return StringPrintf("IntervalStartSyncedOnEnd(%s, duration = %" GG_LL_FORMAT
|
|
|
|
|
"d, offset = %" GG_LL_FORMAT "d)",
|
|
|
|
|
t_->DebugString().c_str(), duration_, offset_);
|
|
|
|
|
}
|
|
|
|
|
};
|
2011-08-11 05:15:18 +00:00
|
|
|
} // namespace
|
|
|
|
|
|
|
|
|
|
// ----- API -----
|
|
|
|
|
|
2012-08-31 20:55:03 +00:00
|
|
|
IntervalVar* Solver::MakeMirrorInterval(IntervalVar* const t) {
|
|
|
|
|
return RegisterIntervalVar(RevAlloc(new MirrorIntervalVar(this, t)));
|
2011-08-11 05:15:18 +00:00
|
|
|
}
|
|
|
|
|
|
2012-08-31 20:55:03 +00:00
|
|
|
IntervalVar* Solver::MakeIntervalRelaxedMax(IntervalVar* const interval_var) {
|
|
|
|
|
if (interval_var->MustBePerformed()) {
|
|
|
|
|
return interval_var;
|
|
|
|
|
} else {
|
|
|
|
|
return RegisterIntervalVar(
|
|
|
|
|
RevAlloc(new IntervalVarRelaxedMax(interval_var)));
|
2011-08-11 05:15:18 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2012-08-31 20:55:03 +00:00
|
|
|
IntervalVar* Solver::MakeIntervalRelaxedMin(IntervalVar* const interval_var) {
|
|
|
|
|
if (interval_var->MustBePerformed()) {
|
|
|
|
|
return interval_var;
|
|
|
|
|
} else {
|
|
|
|
|
return RegisterIntervalVar(
|
|
|
|
|
RevAlloc(new IntervalVarRelaxedMin(interval_var)));
|
2011-08-11 05:15:18 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2012-08-31 20:55:03 +00:00
|
|
|
void IntervalVar::WhenAnything(Demon* const d) {
|
|
|
|
|
WhenStartRange(d);
|
|
|
|
|
WhenDurationRange(d);
|
|
|
|
|
WhenEndRange(d);
|
|
|
|
|
WhenPerformedBound(d);
|
2011-08-11 05:15:18 +00:00
|
|
|
}
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2013-06-11 14:49:19 +00:00
|
|
|
IntervalVar* Solver::MakeFixedInterval(int64 start, int64 duration,
|
2013-12-16 10:24:42 +00:00
|
|
|
const std::string& name) {
|
2010-09-15 12:42:33 +00:00
|
|
|
return RevAlloc(new FixedInterval(this, start, duration, name));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
IntervalVar* Solver::MakeFixedDurationIntervalVar(int64 start_min,
|
|
|
|
|
int64 start_max,
|
2013-06-11 14:49:19 +00:00
|
|
|
int64 duration, bool optional,
|
2013-12-16 10:24:42 +00: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);
|
2011-11-03 10:27:53 +00:00
|
|
|
} else if (!optional) {
|
2013-06-11 14:49:19 +00:00
|
|
|
return RegisterIntervalVar(RevAlloc(new FixedDurationPerformedIntervalVar(
|
|
|
|
|
this, start_min, start_max, duration, name)));
|
2011-11-09 10:59:31 +00:00
|
|
|
}
|
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
|
|
|
}
|
|
|
|
|
|
2014-07-07 13:29:56 +00:00
|
|
|
void Solver::MakeFixedDurationIntervalVarArray(
|
|
|
|
|
int count, int64 start_min, int64 start_max, int64 duration, bool optional,
|
|
|
|
|
const std::string& name, std::vector<IntervalVar*>* array) {
|
2011-01-06 17:40:30 +00:00
|
|
|
CHECK_GT(count, 0);
|
2013-10-10 15:23:20 +00:00
|
|
|
CHECK(array != nullptr);
|
2011-01-06 17:40:30 +00:00
|
|
|
array->clear();
|
|
|
|
|
for (int i = 0; i < count; ++i) {
|
2013-12-16 10:24:42 +00:00
|
|
|
const std::string var_name = StringPrintf("%s%i", name.c_str(), i);
|
2013-06-11 14:49:19 +00:00
|
|
|
array->push_back(MakeFixedDurationIntervalVar(
|
|
|
|
|
start_min, start_max, duration, optional, var_name));
|
2011-01-06 17:40:30 +00:00
|
|
|
}
|
|
|
|
|
}
|
2012-06-12 15:20:03 +00:00
|
|
|
|
|
|
|
|
IntervalVar* Solver::MakeFixedDurationIntervalVar(IntVar* const start_variable,
|
|
|
|
|
int64 duration,
|
2013-12-16 10:24:42 +00:00
|
|
|
const std::string& name) {
|
2013-10-10 15:23:20 +00:00
|
|
|
CHECK(start_variable != nullptr);
|
2012-06-12 15:20:03 +00:00
|
|
|
CHECK_GE(duration, 0);
|
2013-07-29 02:49:12 +00:00
|
|
|
return RegisterIntervalVar(RevAlloc(
|
|
|
|
|
new StartVarPerformedIntervalVar(this, start_variable, duration, name)));
|
2012-06-12 15:20:03 +00:00
|
|
|
}
|
|
|
|
|
|
2014-07-07 13:29:56 +00:00
|
|
|
// Creates an interval var with a fixed duration, and performed var.
|
|
|
|
|
// The duration must be greater than 0.
|
|
|
|
|
IntervalVar* Solver::MakeFixedDurationIntervalVar(
|
|
|
|
|
IntVar* const start_variable, int64 duration,
|
|
|
|
|
IntVar* const performed_variable, const std::string& name) {
|
2014-05-26 17:59:03 +00:00
|
|
|
CHECK(start_variable != nullptr);
|
|
|
|
|
CHECK(performed_variable != nullptr);
|
|
|
|
|
CHECK_GE(duration, 0);
|
|
|
|
|
if (!performed_variable->Bound()) {
|
2014-07-07 13:29:56 +00: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;
|
2014-05-26 17:59:03 +00:00
|
|
|
} else if (performed_variable->Min() == 1) {
|
2014-07-07 13:29:56 +00:00
|
|
|
return RegisterIntervalVar(RevAlloc(new StartVarPerformedIntervalVar(
|
|
|
|
|
this, start_variable, duration, name)));
|
2014-05-26 17:59:03 +00:00
|
|
|
}
|
|
|
|
|
return nullptr;
|
|
|
|
|
}
|
|
|
|
|
|
2012-06-12 15:20:03 +00:00
|
|
|
void Solver::MakeFixedDurationIntervalVarArray(
|
2014-07-07 13:29:56 +00:00
|
|
|
const std::vector<IntVar*>& start_variables, int64 duration,
|
|
|
|
|
const std::string& name, std::vector<IntervalVar*>* array) {
|
2013-10-10 15:23:20 +00:00
|
|
|
CHECK(array != nullptr);
|
2012-06-12 15:20:03 +00:00
|
|
|
array->clear();
|
|
|
|
|
for (int i = 0; i < start_variables.size(); ++i) {
|
2013-12-16 10:24:42 +00:00
|
|
|
const std::string var_name = StringPrintf("%s%i", name.c_str(), i);
|
2013-06-11 14:49:19 +00:00
|
|
|
array->push_back(
|
|
|
|
|
MakeFixedDurationIntervalVar(start_variables[i], duration, var_name));
|
2012-06-12 15:20:03 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Solver::MakeFixedDurationIntervalVarArray(
|
2014-07-07 13:29:56 +00:00
|
|
|
const std::vector<IntVar*>& start_variables,
|
|
|
|
|
const std::vector<int64>& durations, const std::string& name,
|
|
|
|
|
std::vector<IntervalVar*>* array) {
|
2013-10-10 15:23:20 +00:00
|
|
|
CHECK(array != nullptr);
|
2012-06-12 15:20:03 +00:00
|
|
|
CHECK_EQ(start_variables.size(), durations.size());
|
|
|
|
|
array->clear();
|
|
|
|
|
for (int i = 0; i < start_variables.size(); ++i) {
|
2013-12-16 10:24:42 +00:00
|
|
|
const std::string var_name = StringPrintf("%s%i", name.c_str(), i);
|
2012-06-12 15:20:03 +00:00
|
|
|
array->push_back(MakeFixedDurationIntervalVar(start_variables[i],
|
2013-06-11 14:49:19 +00:00
|
|
|
durations[i], var_name));
|
2012-06-12 15:20:03 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Solver::MakeFixedDurationIntervalVarArray(
|
2014-07-07 13:29:56 +00:00
|
|
|
const std::vector<IntVar*>& start_variables,
|
|
|
|
|
const std::vector<int>& durations, const std::string& name,
|
|
|
|
|
std::vector<IntervalVar*>* array) {
|
2013-10-10 15:23:20 +00:00
|
|
|
CHECK(array != nullptr);
|
2012-06-12 15:20:03 +00:00
|
|
|
CHECK_EQ(start_variables.size(), durations.size());
|
|
|
|
|
array->clear();
|
|
|
|
|
for (int i = 0; i < start_variables.size(); ++i) {
|
2013-12-16 10:24:42 +00:00
|
|
|
const std::string var_name = StringPrintf("%s%i", name.c_str(), i);
|
2012-06-12 15:20:03 +00:00
|
|
|
array->push_back(MakeFixedDurationIntervalVar(start_variables[i],
|
2013-06-11 14:49:19 +00:00
|
|
|
durations[i], var_name));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2014-05-26 17:59:03 +00:00
|
|
|
void Solver::MakeFixedDurationIntervalVarArray(
|
|
|
|
|
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 = StringPrintf("%s%i", name.c_str(), i);
|
2014-07-07 13:29:56 +00:00
|
|
|
array->push_back(MakeFixedDurationIntervalVar(
|
|
|
|
|
start_variables[i], durations[i], performed_variables[i], var_name));
|
2014-05-26 17:59:03 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Solver::MakeFixedDurationIntervalVarArray(
|
|
|
|
|
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 = StringPrintf("%s%i", name.c_str(), i);
|
2014-07-07 13:29:56 +00:00
|
|
|
array->push_back(MakeFixedDurationIntervalVar(
|
|
|
|
|
start_variables[i], durations[i], performed_variables[i], var_name));
|
2014-05-26 17:59:03 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2013-06-11 14:49:19 +00:00
|
|
|
// Variable Duration Interval Var
|
|
|
|
|
|
|
|
|
|
IntervalVar* Solver::MakeIntervalVar(int64 start_min, int64 start_max,
|
|
|
|
|
int64 duration_min, int64 duration_max,
|
|
|
|
|
int64 end_min, int64 end_max,
|
2013-12-16 10:24:42 +00: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,
|
2013-12-16 10:24:42 +00:00
|
|
|
const std::string& name,
|
2013-06-11 14:49:19 +00:00
|
|
|
std::vector<IntervalVar*>* const array) {
|
|
|
|
|
CHECK_GT(count, 0);
|
2013-10-10 15:23:20 +00:00
|
|
|
CHECK(array != nullptr);
|
2013-06-11 14:49:19 +00:00
|
|
|
array->clear();
|
|
|
|
|
for (int i = 0; i < count; ++i) {
|
2013-12-16 10:24:42 +00:00
|
|
|
const std::string var_name = StringPrintf("%s%i", name.c_str(), i);
|
2014-07-07 13:29:56 +00:00
|
|
|
array->push_back(
|
|
|
|
|
MakeIntervalVar(start_min, start_max, duration_min, duration_max,
|
|
|
|
|
end_min, end_max, optional, var_name));
|
2012-06-12 15:20:03 +00:00
|
|
|
}
|
|
|
|
|
}
|
2013-06-11 14:49:19 +00:00
|
|
|
|
|
|
|
|
// Synced Interval Vars
|
|
|
|
|
IntervalVar* Solver::MakeFixedDurationStartSyncedOnStartIntervalVar(
|
|
|
|
|
IntervalVar* const interval_var, int64 duration, int64 offset) {
|
|
|
|
|
return RegisterIntervalVar(
|
|
|
|
|
RevAlloc(new FixedDurationIntervalVarStartSyncedOnStart(
|
|
|
|
|
interval_var, duration, offset)));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
IntervalVar* Solver::MakeFixedDurationStartSyncedOnEndIntervalVar(
|
|
|
|
|
IntervalVar* const interval_var, int64 duration, int64 offset) {
|
|
|
|
|
return RegisterIntervalVar(
|
|
|
|
|
RevAlloc(new FixedDurationIntervalVarStartSyncedOnEnd(interval_var,
|
|
|
|
|
duration, offset)));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
IntervalVar* Solver::MakeFixedDurationEndSyncedOnStartIntervalVar(
|
|
|
|
|
IntervalVar* const interval_var, int64 duration, int64 offset) {
|
|
|
|
|
return RegisterIntervalVar(
|
|
|
|
|
RevAlloc(new FixedDurationIntervalVarStartSyncedOnStart(
|
|
|
|
|
interval_var, duration, offset - duration)));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
IntervalVar* Solver::MakeFixedDurationEndSyncedOnEndIntervalVar(
|
|
|
|
|
IntervalVar* const interval_var, int64 duration, int64 offset) {
|
|
|
|
|
return RegisterIntervalVar(
|
|
|
|
|
RevAlloc(new FixedDurationIntervalVarStartSyncedOnEnd(
|
|
|
|
|
interval_var, duration, offset - duration)));
|
|
|
|
|
}
|
2010-09-15 12:42:33 +00:00
|
|
|
} // namespace operations_research
|