support cumulative with variable capacity

This commit is contained in:
lperron@google.com
2012-06-16 06:49:34 +00:00
parent f03db02c3f
commit 8f4c1bb6a4
6 changed files with 192 additions and 6 deletions

View File

@@ -1,6 +1,10 @@
predicate all_different_int(array [int] of var int: x);
predicate count(array [int] of var int: x, var int: y, var int: c);
predicate fixed_cumulative(array [int] of var int: s, array [int] of int: d, array [int] of int: r, int: b);
predicate global_cardinality(array [int] of var int: x, array [int] of int: cover, array [int] of var int: counts);
predicate maximum_int(var int: m, array [int] of var int: x);
predicate minimum_int(var int: m, array [int] of var int: x);
predicate sort(array [int] of var int: x, array [int] of var int: y);
predicate table_bool(array [int] of var bool: x, array [int, int] of bool: t);
predicate table_int(array [int] of var int: x, array [int, int] of int: t);
var 4..36: INT____00001 :: is_defined_var :: var_is_introduced;

View File

@@ -1829,6 +1829,34 @@ class Solver {
int64 capacity,
const string& name);
// This constraint forces that, for any integer t, the sum of the demands
// corresponding to an interval containing t does not exceed the given
// capacity.
//
// Intervals and demands should be vectors of equal size.
//
// Demands should only contain non-negative values. Zero values are supported,
// and the corresponding intervals are filtered out, as they neither impact
// nor are impacted by this constraint.
Constraint* MakeCumulative(const std::vector<IntervalVar*>& intervals,
const std::vector<int64>& demands,
IntVar* const capacity,
const string& name);
// This constraint forces that, for any integer t, the sum of the demands
// corresponding to an interval containing t does not exceed the given
// capacity.
//
// Intervals and demands should be vectors of equal size.
//
// Demands should only contain non-negative values. Zero values are supported,
// and the corresponding intervals are filtered out, as they neither impact
// nor are impacted by this constraint.
Constraint* MakeCumulative(const std::vector<IntervalVar*>& intervals,
const std::vector<int>& demands,
IntVar* const capacity,
const string& name);
// ----- Assignments -----
// This method creates an empty assignment.

View File

@@ -889,15 +889,17 @@ class VariableModulo : public Constraint {
virtual void Post() {
Solver* const s = solver();
IntVar* const div = s->MakeDiv(x_, mod_)->Var();
s->AddConstraint(s->MakeLess(y_, mod_));
s->AddConstraint(s->MakeGreaterOrEqual(y_, Zero()));
s->AddConstraint(s->MakeGreater(mod_, Zero()));
s->AddConstraint(s->MakeEquality(y_, s->MakeProd(div, mod_)->Var()));
IntVar* const d = s->MakeIntVar(std::min(x_->Min(), -x_->Max()),
std::max(x_->Max(), -x_->Min()));
s->AddConstraint(s->MakeEquality(x_, s->MakeSum(s->MakeProd(mod_, d), y_)->Var()));
s->AddConstraint(s->MakeGreater(y_, s->MakeOpposite(s->MakeAbs(mod_))->Var()));
s->AddConstraint(s->MakeLess(y_, s->MakeAbs(mod_)->Var()));
s->AddConstraint(s->MakeGreaterOrEqual(d, s->MakeMin(x_, s->MakeOpposite(x_))->Var()));
s->AddConstraint(s->MakeLessOrEqual(d, s->MakeMax(x_, s->MakeOpposite(x_))->Var()));
}
virtual void InitialPropagate() {
mod_->SetMin(1);
mod_->RemoveValue(0);
}
private:

View File

@@ -2189,4 +2189,110 @@ Constraint* Solver::MakeCumulative(const std::vector<IntervalVar*>& intervals,
capacity,
name));
}
Constraint* Solver::MakeCumulative(const std::vector<IntervalVar*>& intervals,
const std::vector<int64>& demands,
IntVar* const capacity,
const string& name) {
CHECK_EQ(intervals.size(), demands.size());
for (int i = 0; i < intervals.size(); ++i) {
CHECK_GE(demands[i], 0);
}
if (capacity->Bound()) {
return MakeCumulative(intervals, demands, capacity->Min(), name);
}
std::vector<IntervalVar*> a_intervals;
std::vector<int64> a_demands;
int64 horizon_min = kint64max;
int64 horizon_max = kint64min;
for (int i = 0; i < demands.size(); ++i) {
if (demands[i] > 0) {
a_intervals.push_back(intervals[i]);
a_demands.push_back(demands[i]);
horizon_max = std::max(horizon_max, intervals[i]->EndMax());
horizon_min = std::min(horizon_min, intervals[i]->StartMin());
}
}
const int64 total_duration = horizon_max = horizon_max + 1;
const int64 capacity_min = std::max(capacity->Min(), 0LL);
const int64 capacity_max = capacity->Max();
const int64 delta_capacity = capacity_max - capacity_min;
std::vector<IntVar*> o_vars; // Optional variables.
std::vector<int64> o_coefs;
for (int64 mult = 1; mult <= delta_capacity; mult *= 2) {
const string name =
StringPrintf("VariableCapacity<%" GG_LL_FORMAT "d>", mult);
IntervalVar* const var = MakeFixedDurationIntervalVar(horizon_min,
horizon_min,
total_duration,
true,
name);
a_intervals.push_back(var);
a_demands.push_back(mult);
o_vars.push_back(var->PerformedExpr()->Var());
o_coefs.push_back(mult);
}
o_vars.push_back(capacity);
o_coefs.push_back(1);
AddConstraint(MakeScalProdEquality(o_vars, o_coefs, capacity_max));
return RevAlloc(new CumulativeConstraint(this,
a_intervals.data(),
a_demands.data(),
a_intervals.size(),
capacity_max,
name));
}
Constraint* Solver::MakeCumulative(const std::vector<IntervalVar*>& intervals,
const std::vector<int>& demands,
IntVar* const capacity,
const string& name) {
CHECK_EQ(intervals.size(), demands.size());
for (int i = 0; i < intervals.size(); ++i) {
CHECK_GE(demands[i], 0);
}
if (capacity->Bound()) {
return MakeCumulative(intervals, demands, capacity->Min(), name);
}
std::vector<IntervalVar*> a_intervals;
std::vector<int64> a_demands;
int64 horizon_min = kint64max;
int64 horizon_max = kint64min;
for (int i = 0; i < demands.size(); ++i) {
if (demands[i] > 0) {
a_intervals.push_back(intervals[i]);
a_demands.push_back(demands[i]);
horizon_max = std::max(horizon_max, intervals[i]->EndMax());
horizon_min = std::min(horizon_min, intervals[i]->StartMin());
}
}
const int64 total_duration = horizon_max = horizon_max + 1;
const int64 capacity_min = std::max(capacity->Min(), 0LL);
const int64 capacity_max = capacity->Max();
const int64 delta_capacity = capacity_max - capacity_min;
std::vector<IntVar*> o_vars; // Optional variables.
std::vector<int64> o_coefs;
for (int64 mult = 1; mult <= delta_capacity; mult *= 2) {
const string name =
StringPrintf("VariableCapacity<%" GG_LL_FORMAT "d>", mult);
IntervalVar* const var = MakeFixedDurationIntervalVar(horizon_min,
horizon_min,
total_duration,
true,
name);
a_intervals.push_back(var);
a_demands.push_back(mult);
o_vars.push_back(var->PerformedExpr()->Var());
o_coefs.push_back(mult);
}
o_vars.push_back(capacity);
o_coefs.push_back(1);
AddConstraint(MakeScalProdEquality(o_vars, o_coefs, capacity_max));
return RevAlloc(new CumulativeConstraint(this,
a_intervals.data(),
a_demands.data(),
a_intervals.size(),
capacity_max,
name));
}
} // namespace operations_research

View File

@@ -10,6 +10,11 @@ predicate fixed_cumulative(array[int] of var int: s,
array[int] of int: r,
int: b);
predicate var_cumulative(array[int] of var int: s,
array[int] of int: d,
array[int] of int: r,
var int: b);
predicate variable_cumulative(array[int] of var int: s,
array[int] of var int: d,
array[int] of var int: r,
@@ -40,6 +45,12 @@ predicate cumulative(array[int] of var int: s,
int: b) =
fixed_cumulative(s, d, r, b);
predicate cumulative(array[int] of var int: s,
array[int] of int: d,
array[int] of int: r,
var int: b) =
var_cumulative(s, d, r, b);
predicate cumulative(array[int] of var int: s,
array[int] of var int: d,
array[int] of var int: r,

View File

@@ -1167,6 +1167,40 @@ void p_fixed_cumulative(FlatZincModel* const model, CtSpec* const spec) {
solver->AddConstraint(ct);
}
void p_var_cumulative(FlatZincModel* const model, CtSpec* const spec) {
Solver* const solver = model->solver();
AST::Array* const array_variables = spec->Arg(0)->getArray();
const int size = array_variables->a.size();
std::vector<IntVar*> start_variables(size);
for (int i = 0; i < size; ++i) {
start_variables[i] = model->GetIntVar(array_variables->a[i]);
}
AST::Array* const array_durations = spec->Arg(1)->getArray();
const int dsize = array_durations->a.size();
std::vector<int> durations(dsize);
for (int i = 0; i < dsize; ++i) {
durations[i] = array_durations->a[i]->getInt();
}
AST::Array* const array_usages = spec->Arg(2)->getArray();
const int usize = array_usages->a.size();
std::vector<int> usages(usize);
for (int i = 0; i < usize; ++i) {
usages[i] = array_usages->a[i]->getInt();
}
std::vector<IntervalVar*> intervals;
solver->MakeFixedDurationIntervalVarArray(start_variables,
durations,
"",
&intervals);
IntVar* const capacity = model->GetIntVar(spec->Arg(3));
Constraint* const ct = solver->MakeCumulative(intervals,
usages,
capacity,
"");
VLOG(1) << "Posted " << ct->DebugString();
solver->AddConstraint(ct);
}
class IntBuilder {
public:
IntBuilder(void) {
@@ -1244,6 +1278,7 @@ class IntBuilder {
global_model_builder.Register("minimum_int", &p_minimum_int);
global_model_builder.Register("sort", &p_sort);
global_model_builder.Register("fixed_cumulative", &p_fixed_cumulative);
global_model_builder.Register("var_cumulative", &p_var_cumulative);
}
};
IntBuilder __int_Builder;