From c52997f1b197e08fea863b73dd74520899c50da3 Mon Sep 17 00:00:00 2001 From: "lperron@google.com" Date: Wed, 11 May 2011 16:07:52 +0000 Subject: [PATCH] change header macros; added crude implementation of new dimension in the pack constraint with variable weights for items --- constraint_solver/constraint_solver.h | 21 ++++++- constraint_solver/constraint_solveri.h | 6 +- constraint_solver/pack.cc | 78 ++++++++++++++++++++++++++ constraint_solver/routing.h | 6 +- 4 files changed, 102 insertions(+), 9 deletions(-) diff --git a/constraint_solver/constraint_solver.h b/constraint_solver/constraint_solver.h index 349116b29c..77c04068f0 100644 --- a/constraint_solver/constraint_solver.h +++ b/constraint_solver/constraint_solver.h @@ -55,8 +55,8 @@ // either a const vector& or a IntVar* const* and a size; the two // signatures are equivalent, size defining the number of variables. -#ifndef CONSTRAINT_SOLVER_CONSTRAINT_SOLVER_H_ -#define CONSTRAINT_SOLVER_CONSTRAINT_SOLVER_H_ +#ifndef OR_TOOLS_CONSTRAINT_SOLVER_CONSTRAINT_SOLVER_H_ +#define OR_TOOLS_CONSTRAINT_SOLVER_CONSTRAINT_SOLVER_H_ #include #include @@ -3495,6 +3495,19 @@ class Pack : public Constraint { void AddWeightedSumEqualVarDimension(const vector& weights, const vector& loads); + // This dimension imposes: + // forall b in bins, + // sum (i in items: weight[i] * is_assigned(i, b)) <= capacities[b] + // where is_assigned(i, b) is true if and only if item i is assigned + // to the bin b. + // + // This can be used to model shapes of items by linking variables of + // the same item on parallel dimensions with an allowed assignment + // constraint. + void AddSumVariableWeightsLessOrEqualConstantDimension( + const vector& weights, + const vector& capacities); + // This dimension enforces that cost_var == sum of weights[i] for // all objects 'i' assigned to a bin. void AddWeightedSumOfAssignedDimension(const vector& weights, @@ -3522,6 +3535,8 @@ class Pack : public Constraint { void SetImpossible(int64 var_index, int64 bin_index); void Assign(int64 var_index, int64 bin_index); bool IsAssignedStatusKnown(int64 var_index) const; + bool IsPossible(int64 var_index, int64 bin_index) const; + IntVar* AssignVar(int64 var_index, int64 bin_index) const; void SetAssigned(int64 var_index); void SetUnassigned(int64 var_index); void RemoveAllPossibleFromBin(int64 bin_index); @@ -3574,4 +3589,4 @@ class SolutionPool : public BaseObject { } // namespace operations_research -#endif // CONSTRAINT_SOLVER_CONSTRAINT_SOLVER_H_ +#endif // OR_TOOLS_CONSTRAINT_SOLVER_CONSTRAINT_SOLVER_H_ diff --git a/constraint_solver/constraint_solveri.h b/constraint_solver/constraint_solveri.h index 6ad8fc13f9..3e5132a99b 100644 --- a/constraint_solver/constraint_solveri.h +++ b/constraint_solver/constraint_solveri.h @@ -11,8 +11,8 @@ // See the License for the specific language governing permissions and // limitations under the License. -#ifndef CONSTRAINT_SOLVER_CONSTRAINT_SOLVERI_H_ -#define CONSTRAINT_SOLVER_CONSTRAINT_SOLVERI_H_ +#ifndef OR_TOOLS_CONSTRAINT_SOLVER_CONSTRAINT_SOLVERI_H_ +#define OR_TOOLS_CONSTRAINT_SOLVER_CONSTRAINT_SOLVERI_H_ #include @@ -799,4 +799,4 @@ class SearchLog : public SearchMonitor { }; } // namespace operations_research -#endif // CONSTRAINT_SOLVER_CONSTRAINT_SOLVERI_H_ +#endif // OR_TOOLS_CONSTRAINT_SOLVER_CONSTRAINT_SOLVERI_H_ diff --git a/constraint_solver/pack.cc b/constraint_solver/pack.cc index 2581c56f01..1183bbeb56 100644 --- a/constraint_solver/pack.cc +++ b/constraint_solver/pack.cc @@ -55,6 +55,14 @@ class Dimension : public BaseObject { return pack_->IsUndecided(var_index, bin_index); } + bool IsPossible(int64 var_index, int64 bin_index) const { + return pack_->IsPossible(var_index, bin_index); + } + + IntVar* AssignVar(int64 var_index, int64 bin_index) const { + return pack_->AssignVar(var_index, bin_index); + } + void SetImpossible(int64 var_index, int64 bin_index) { pack_->SetImpossible(var_index, bin_index); } @@ -345,6 +353,14 @@ bool Pack::IsAssignedStatusKnown(int64 var_index) const { return !unprocessed_.IsSet(bins_, var_index); } +bool Pack::IsPossible(int64 var_index, int64 bin_index) const { + return vars_[var_index]->Contains(bin_index); +} + +IntVar* Pack::AssignVar(int64 var_index, int64 bin_index) const { + return solver()->MakeIsEqualCstVar(vars_[var_index], bin_index); +} + void Pack::SetAssigned(int64 var_index) { if (IsInProcess()) { to_unset_.push_back(make_pair(var_index, bins_)); @@ -1030,6 +1046,55 @@ class CountUsedBinDimension : public Dimension { int initial_max_; }; +// ---------- Variable Usage Dimension ---------- + +// This is a very naive, but correct implementation of the constraint. +class VariableUsageDimension : public Dimension { + public: + VariableUsageDimension(Solver* const solver, + Pack* const pack, + const vector& capacities, + const vector& weights) + : Dimension(solver, pack), capacities_(capacities), weights_(weights) {} + + virtual ~VariableUsageDimension() {} + + virtual void Post() { + Solver* const s = solver(); + const int num_bins = capacities_.size(); + const int num_items = weights_.size(); + + for (int bin_index = 0; bin_index < num_bins; ++bin_index) { + vector terms; + for (int item_index = 0; item_index < num_items; ++item_index) { + IntVar* const assign_var = AssignVar(item_index, bin_index); + terms.push_back(s->MakeProd(assign_var, weights_[item_index])->Var()); + } + s->AddConstraint(s->MakeSumLessOrEqual(terms, capacities_[bin_index])); + } + } + + virtual void InitialPropagate(int64 bin_index, + const vector& forced, + const vector& undecided) {} + virtual void InitialPropagateUnassigned(const vector& assigned, + const vector& unassigned) {} + virtual void EndInitialPropagate() {} + virtual void Propagate(int64 bin_index, + const vector& forced, + const vector& removed) {} + virtual void PropagateUnassigned(const vector& assigned, + const vector& unassigned) {} + virtual void EndPropagate() {} + + virtual string DebugString() const { + return "VariableUsageDimension"; + } + private: + const vector capacities_; + const vector weights_; +}; + // ---------- API ---------- void Pack::AddWeightedSumLessOrEqualConstantDimension( @@ -1077,6 +1142,19 @@ void Pack::AddWeightedSumOfAssignedDimension(const vector& weights, dims_.push_back(dim); } +void Pack::AddSumVariableWeightsLessOrEqualConstantDimension( + const vector& usage, + const vector& capacity) { + Solver* const s = solver(); + Dimension* const dim = + s->RevAlloc(new VariableUsageDimension(s, + this, + capacity, + usage)); + dims_.push_back(dim); +} + + void Pack::AddCountUsedBinDimension(IntVar* const count_var) { Solver* const s = solver(); Dimension* const dim = diff --git a/constraint_solver/routing.h b/constraint_solver/routing.h index 94389fa2fd..bac4d8092e 100644 --- a/constraint_solver/routing.h +++ b/constraint_solver/routing.h @@ -23,8 +23,8 @@ // solution. The model is "closed" after the first call to Solve() and cannot // be modified afterwards; however Solve can be called more than once. -#ifndef CONSTRAINT_SOLVER_ROUTING_H_ -#define CONSTRAINT_SOLVER_ROUTING_H_ +#ifndef OR_TOOLS_CONSTRAINT_SOLVER_ROUTING_H_ +#define OR_TOOLS_CONSTRAINT_SOLVER_ROUTING_H_ #include #include @@ -303,4 +303,4 @@ class RoutingModel { } // namespace operations_research -#endif // CONSTRAINT_SOLVER_ROUTING_H_ +#endif // OR_TOOLS_CONSTRAINT_SOLVER_ROUTING_H_