2022-06-17 08:40:20 +02:00
|
|
|
// Copyright 2010-2022 Google LLC
|
2010-09-15 12:42:33 +00:00
|
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
|
// you may not use this file except in compliance with the License.
|
|
|
|
|
// You may obtain a copy of the License at
|
|
|
|
|
//
|
|
|
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
|
//
|
|
|
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
|
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
|
// See the License for the specific language governing permissions and
|
|
|
|
|
// limitations under the License.
|
|
|
|
|
|
|
|
|
|
// Packing constraints
|
|
|
|
|
|
2011-09-21 15:16:48 +00:00
|
|
|
#include <algorithm>
|
2013-12-16 10:24:42 +00:00
|
|
|
#include <cstddef>
|
2021-04-01 12:13:35 +02:00
|
|
|
#include <cstdint>
|
2015-08-13 16:00:54 +02:00
|
|
|
#include <memory>
|
2011-09-21 15:16:48 +00:00
|
|
|
#include <string>
|
2011-05-17 20:38:55 +00:00
|
|
|
#include <utility>
|
2011-09-21 15:16:48 +00:00
|
|
|
#include <vector>
|
2011-05-17 20:38:55 +00:00
|
|
|
|
2018-10-31 16:18:18 +01:00
|
|
|
#include "absl/strings/str_format.h"
|
|
|
|
|
#include "absl/strings/str_join.h"
|
2017-04-26 17:30:25 +02:00
|
|
|
#include "ortools/base/integral_types.h"
|
|
|
|
|
#include "ortools/base/logging.h"
|
|
|
|
|
#include "ortools/constraint_solver/constraint_solver.h"
|
|
|
|
|
#include "ortools/constraint_solver/constraint_solveri.h"
|
2010-09-15 12:42:33 +00:00
|
|
|
|
|
|
|
|
namespace operations_research {
|
|
|
|
|
|
|
|
|
|
// ---------- Dimension ----------
|
|
|
|
|
|
|
|
|
|
class Dimension : public BaseObject {
|
2020-10-22 23:36:58 +02:00
|
|
|
public:
|
2020-10-29 14:25:39 +01:00
|
|
|
explicit Dimension(Solver* const s, Pack* const pack)
|
2010-09-15 12:42:33 +00:00
|
|
|
: solver_(s), pack_(pack) {}
|
2015-04-16 15:49:51 +02:00
|
|
|
~Dimension() override {}
|
2010-09-15 12:42:33 +00:00
|
|
|
|
|
|
|
|
virtual void Post() = 0;
|
2020-10-29 14:25:39 +01:00
|
|
|
virtual void InitialPropagate(int bin_index, const std::vector<int>& forced,
|
|
|
|
|
const std::vector<int>& undecided) = 0;
|
2020-10-22 23:36:58 +02:00
|
|
|
virtual void InitialPropagateUnassigned(
|
2020-10-29 14:25:39 +01:00
|
|
|
const std::vector<int>& assigned, const std::vector<int>& unassigned) = 0;
|
2010-09-15 12:42:33 +00:00
|
|
|
virtual void EndInitialPropagate() = 0;
|
2020-10-29 14:25:39 +01:00
|
|
|
virtual void Propagate(int bin_index, const std::vector<int>& forced,
|
|
|
|
|
const std::vector<int>& removed) = 0;
|
|
|
|
|
virtual void PropagateUnassigned(const std::vector<int>& assigned,
|
|
|
|
|
const std::vector<int>& unassigned) = 0;
|
2010-09-15 12:42:33 +00:00
|
|
|
virtual void EndPropagate() = 0;
|
2015-04-16 15:49:51 +02:00
|
|
|
std::string DebugString() const override { return "Dimension"; }
|
2020-10-29 14:25:39 +01:00
|
|
|
virtual void Accept(ModelVisitor* const visitor) const = 0;
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2020-10-29 14:25:39 +01:00
|
|
|
Solver* solver() const { return solver_; }
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2013-01-10 17:01:34 +00:00
|
|
|
bool IsUndecided(int var_index, int bin_index) const {
|
2010-09-15 12:42:33 +00:00
|
|
|
return pack_->IsUndecided(var_index, bin_index);
|
|
|
|
|
}
|
|
|
|
|
|
2013-01-10 17:01:34 +00:00
|
|
|
bool IsPossible(int var_index, int bin_index) const {
|
2011-05-11 16:07:52 +00:00
|
|
|
return pack_->IsPossible(var_index, bin_index);
|
|
|
|
|
}
|
|
|
|
|
|
2020-10-29 14:25:39 +01:00
|
|
|
IntVar* AssignVar(int var_index, int bin_index) const {
|
2011-05-11 16:07:52 +00:00
|
|
|
return pack_->AssignVar(var_index, bin_index);
|
|
|
|
|
}
|
|
|
|
|
|
2013-01-10 17:01:34 +00:00
|
|
|
void SetImpossible(int var_index, int bin_index) {
|
2010-09-15 12:42:33 +00:00
|
|
|
pack_->SetImpossible(var_index, bin_index);
|
|
|
|
|
}
|
|
|
|
|
|
2013-01-10 17:01:34 +00:00
|
|
|
void Assign(int var_index, int bin_index) {
|
2010-09-15 12:42:33 +00:00
|
|
|
pack_->Assign(var_index, bin_index);
|
|
|
|
|
}
|
|
|
|
|
|
2013-01-10 17:01:34 +00:00
|
|
|
bool IsAssignedStatusKnown(int var_index) const {
|
2010-09-15 12:42:33 +00:00
|
|
|
return pack_->IsAssignedStatusKnown(var_index);
|
|
|
|
|
}
|
|
|
|
|
|
2013-10-10 15:23:20 +00:00
|
|
|
void SetAssigned(int var_index) { pack_->SetAssigned(var_index); }
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2013-10-10 15:23:20 +00:00
|
|
|
void SetUnassigned(int var_index) { pack_->SetUnassigned(var_index); }
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2013-01-10 17:01:34 +00:00
|
|
|
void RemoveAllPossibleFromBin(int bin_index) {
|
2010-09-15 12:42:33 +00:00
|
|
|
pack_->RemoveAllPossibleFromBin(bin_index);
|
|
|
|
|
}
|
|
|
|
|
|
2013-01-10 17:01:34 +00:00
|
|
|
void AssignAllPossibleToBin(int bin_index) {
|
2010-09-15 12:42:33 +00:00
|
|
|
pack_->AssignAllPossibleToBin(bin_index);
|
|
|
|
|
}
|
|
|
|
|
|
2013-01-10 17:01:34 +00:00
|
|
|
void AssignFirstPossibleToBin(int bin_index) {
|
2010-09-15 12:42:33 +00:00
|
|
|
pack_->AssignFirstPossibleToBin(bin_index);
|
|
|
|
|
}
|
|
|
|
|
|
2013-10-10 15:23:20 +00:00
|
|
|
void AssignAllRemainingItems() { pack_->AssignAllRemainingItems(); }
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2013-10-10 15:23:20 +00:00
|
|
|
void UnassignAllRemainingItems() { pack_->UnassignAllRemainingItems(); }
|
2011-07-11 20:13:14 +00:00
|
|
|
|
2020-10-22 23:36:58 +02:00
|
|
|
private:
|
2020-10-29 14:25:39 +01:00
|
|
|
Solver* const solver_;
|
|
|
|
|
Pack* const pack_;
|
2010-09-15 12:42:33 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// ----- Pack -----
|
|
|
|
|
|
2020-10-29 14:25:39 +01:00
|
|
|
Pack::Pack(Solver* const s, const std::vector<IntVar*>& vars,
|
2016-11-29 13:40:04 +01:00
|
|
|
int number_of_bins)
|
2020-10-22 23:36:58 +02:00
|
|
|
: Constraint(s),
|
|
|
|
|
vars_(vars),
|
|
|
|
|
bins_(number_of_bins),
|
2013-10-10 15:23:20 +00:00
|
|
|
unprocessed_(new RevBitMatrix(bins_ + 1, vars_.size())),
|
2020-10-22 23:36:58 +02:00
|
|
|
forced_(bins_ + 1),
|
|
|
|
|
removed_(bins_ + 1),
|
|
|
|
|
holes_(vars_.size()),
|
2021-02-07 00:45:47 +01:00
|
|
|
stamp_(uint64_t{0}),
|
2020-10-22 23:36:58 +02:00
|
|
|
demon_(nullptr),
|
|
|
|
|
in_process_(false) {
|
2013-10-10 15:23:20 +00:00
|
|
|
for (int i = 0; i < vars_.size(); ++i) {
|
2010-09-15 12:42:33 +00:00
|
|
|
holes_[i] = vars_[i]->MakeHoleIterator(true);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Pack::~Pack() {}
|
|
|
|
|
|
|
|
|
|
void Pack::Post() {
|
2013-10-10 15:23:20 +00:00
|
|
|
for (int i = 0; i < vars_.size(); ++i) {
|
2020-10-29 14:25:39 +01:00
|
|
|
IntVar* const var = vars_[i];
|
2010-09-15 12:42:33 +00:00
|
|
|
if (!var->Bound()) {
|
2020-10-29 14:25:39 +01:00
|
|
|
Demon* const d = MakeConstraintDemon1(solver(), this, &Pack::OneDomain,
|
2013-10-10 15:23:20 +00:00
|
|
|
"OneDomain", i);
|
2010-09-15 12:42:33 +00:00
|
|
|
var->WhenDomain(d);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
for (int i = 0; i < dims_.size(); ++i) {
|
|
|
|
|
dims_[i]->Post();
|
|
|
|
|
}
|
2011-11-16 17:32:24 +00:00
|
|
|
demon_ = solver()->RegisterDemon(MakeDelayedConstraintDemon0(
|
2013-10-10 15:23:20 +00:00
|
|
|
solver(), this, &Pack::Propagate, "Propagate"));
|
2010-09-15 12:42:33 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Pack::ClearAll() {
|
|
|
|
|
for (int bin_index = 0; bin_index <= bins_; ++bin_index) {
|
|
|
|
|
forced_[bin_index].clear();
|
|
|
|
|
removed_[bin_index].clear();
|
|
|
|
|
}
|
|
|
|
|
to_set_.clear();
|
|
|
|
|
to_unset_.clear();
|
|
|
|
|
in_process_ = false;
|
|
|
|
|
stamp_ = solver()->fail_stamp();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Pack::PropagateDelayed() {
|
|
|
|
|
for (int i = 0; i < to_set_.size(); ++i) {
|
|
|
|
|
vars_[to_set_[i].first]->SetValue(to_set_[i].second);
|
|
|
|
|
}
|
|
|
|
|
for (int i = 0; i < to_unset_.size(); ++i) {
|
|
|
|
|
vars_[to_unset_[i].first]->RemoveValue(to_unset_[i].second);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2011-03-16 15:32:09 +00:00
|
|
|
// A reversibly-allocable container for the data needed in
|
|
|
|
|
// Pack::InitialPropagate()
|
|
|
|
|
namespace {
|
|
|
|
|
class InitialPropagateData : public BaseObject {
|
2020-10-22 23:36:58 +02:00
|
|
|
public:
|
2011-03-16 15:32:09 +00:00
|
|
|
explicit InitialPropagateData(size_t num_bins)
|
|
|
|
|
: BaseObject(), undecided_(num_bins) {}
|
2013-01-10 17:01:34 +00:00
|
|
|
void PushAssigned(int index) { assigned_.push_back(index); }
|
|
|
|
|
void PushUnassigned(int index) { unassigned_.push_back(index); }
|
|
|
|
|
void PushUndecided(int bin, int index) {
|
2011-03-16 15:32:09 +00:00
|
|
|
undecided_.at(bin).push_back(index);
|
|
|
|
|
}
|
2020-10-29 14:25:39 +01:00
|
|
|
const std::vector<int>& undecided(int bin) const {
|
2016-11-29 13:40:04 +01:00
|
|
|
return undecided_.at(bin);
|
|
|
|
|
}
|
2020-10-29 14:25:39 +01:00
|
|
|
const std::vector<int>& assigned() const { return assigned_; }
|
|
|
|
|
const std::vector<int>& unassigned() const { return unassigned_; }
|
2011-03-16 15:32:09 +00:00
|
|
|
|
2015-04-16 15:49:51 +02:00
|
|
|
std::string DebugString() const override { return "InitialPropagateData"; }
|
2012-08-14 18:00:08 +00:00
|
|
|
|
2020-10-22 23:36:58 +02:00
|
|
|
private:
|
2020-11-01 11:47:28 +01:00
|
|
|
std::vector<std::vector<int>> undecided_;
|
2013-01-10 17:01:34 +00:00
|
|
|
std::vector<int> unassigned_;
|
|
|
|
|
std::vector<int> assigned_;
|
2011-03-16 15:32:09 +00:00
|
|
|
};
|
2020-10-22 23:36:58 +02:00
|
|
|
} // namespace
|
2011-03-16 15:32:09 +00:00
|
|
|
|
2010-09-15 12:42:33 +00:00
|
|
|
void Pack::InitialPropagate() {
|
2011-11-19 01:59:37 +00:00
|
|
|
const bool need_context = solver()->InstrumentsVariables();
|
2011-04-08 15:13:24 +00:00
|
|
|
ClearAll();
|
2020-10-29 14:25:39 +01:00
|
|
|
Solver* const s = solver();
|
2010-09-15 12:42:33 +00:00
|
|
|
in_process_ = true;
|
2020-10-29 14:25:39 +01:00
|
|
|
InitialPropagateData* data = s->RevAlloc(new InitialPropagateData(bins_));
|
2013-10-10 15:23:20 +00:00
|
|
|
for (int var_index = 0; var_index < vars_.size(); ++var_index) {
|
2020-10-29 14:25:39 +01:00
|
|
|
IntVar* const var = vars_[var_index];
|
2020-10-22 23:36:58 +02:00
|
|
|
var->SetRange(0, bins_); // bins_ -> item is not assigned to a bin.
|
2010-09-15 12:42:33 +00:00
|
|
|
if (var->Bound()) {
|
2021-04-01 12:13:35 +02:00
|
|
|
const int64_t value = var->Min();
|
2010-09-15 12:42:33 +00:00
|
|
|
if (value < bins_) {
|
|
|
|
|
forced_[value].push_back(var_index);
|
2011-03-16 15:32:09 +00:00
|
|
|
data->PushAssigned(var_index);
|
2010-09-15 12:42:33 +00:00
|
|
|
} else {
|
2011-03-16 15:32:09 +00:00
|
|
|
data->PushUnassigned(var_index);
|
2010-09-15 12:42:33 +00:00
|
|
|
}
|
|
|
|
|
} else {
|
2013-10-10 15:23:20 +00:00
|
|
|
DCHECK_GT(bins_, var->Min())
|
|
|
|
|
<< "The variable maximum should be at most " << bins_
|
|
|
|
|
<< ", and it should be unbound, so its min is expected to be less "
|
|
|
|
|
<< "than " << bins_;
|
2010-09-15 12:42:33 +00:00
|
|
|
if (var->Max() < bins_) {
|
2011-03-16 15:32:09 +00:00
|
|
|
data->PushAssigned(var_index);
|
2010-09-15 12:42:33 +00:00
|
|
|
}
|
2013-12-05 09:29:08 +00:00
|
|
|
std::unique_ptr<IntVarIterator> it(var->MakeDomainIterator(false));
|
2021-04-01 12:13:35 +02:00
|
|
|
for (const int64_t value : InitAndGetValues(it.get())) {
|
2010-09-15 12:42:33 +00:00
|
|
|
if (value >= 0 && value <= bins_) {
|
2011-12-16 21:02:59 +00:00
|
|
|
unprocessed_->SetToOne(s, value, var_index);
|
2010-09-15 12:42:33 +00:00
|
|
|
if (value != bins_) {
|
2011-03-16 15:32:09 +00:00
|
|
|
data->PushUndecided(value, var_index);
|
2010-09-15 12:42:33 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
for (int bin_index = 0; bin_index < bins_; ++bin_index) {
|
2011-11-19 01:59:37 +00:00
|
|
|
if (need_context) {
|
2018-10-31 16:18:18 +01:00
|
|
|
solver()->GetPropagationMonitor()->PushContext(
|
|
|
|
|
absl::StrFormat("Pack(bin %d, forced = [%s], undecided = [%s])",
|
|
|
|
|
bin_index, absl::StrJoin(forced_[bin_index], ", "),
|
|
|
|
|
absl::StrJoin(data->undecided(bin_index), ", ")));
|
2011-11-19 01:59:37 +00:00
|
|
|
}
|
|
|
|
|
|
2010-09-15 12:42:33 +00:00
|
|
|
for (int dim_index = 0; dim_index < dims_.size(); ++dim_index) {
|
2011-11-19 01:59:37 +00:00
|
|
|
if (need_context) {
|
2018-10-31 16:18:18 +01:00
|
|
|
solver()->GetPropagationMonitor()->PushContext(absl::StrFormat(
|
|
|
|
|
"InitialProgateDimension(%s)", dims_[dim_index]->DebugString()));
|
2011-11-19 01:59:37 +00:00
|
|
|
}
|
2013-10-10 15:23:20 +00:00
|
|
|
dims_[dim_index]->InitialPropagate(bin_index, forced_[bin_index],
|
2011-03-16 15:32:09 +00:00
|
|
|
data->undecided(bin_index));
|
2011-11-19 01:59:37 +00:00
|
|
|
if (need_context) {
|
|
|
|
|
solver()->GetPropagationMonitor()->PopContext();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (need_context) {
|
|
|
|
|
solver()->GetPropagationMonitor()->PopContext();
|
2010-09-15 12:42:33 +00:00
|
|
|
}
|
|
|
|
|
}
|
2011-11-19 01:59:37 +00:00
|
|
|
if (need_context) {
|
|
|
|
|
solver()->GetPropagationMonitor()->PushContext(
|
2018-10-31 16:18:18 +01:00
|
|
|
absl::StrFormat("Pack(assigned = [%s], unassigned = [%s])",
|
|
|
|
|
absl::StrJoin(data->assigned(), ", "),
|
|
|
|
|
absl::StrJoin(data->unassigned(), ", ")));
|
2011-11-19 01:59:37 +00:00
|
|
|
}
|
2010-09-15 12:42:33 +00:00
|
|
|
for (int dim_index = 0; dim_index < dims_.size(); ++dim_index) {
|
2011-11-19 01:59:37 +00:00
|
|
|
if (need_context) {
|
2018-10-31 16:18:18 +01:00
|
|
|
solver()->GetPropagationMonitor()->PushContext(absl::StrFormat(
|
|
|
|
|
"InitialProgateDimension(%s)", dims_[dim_index]->DebugString()));
|
2011-11-19 01:59:37 +00:00
|
|
|
}
|
2020-10-22 23:36:58 +02:00
|
|
|
dims_[dim_index]->InitialPropagateUnassigned(data->assigned(),
|
|
|
|
|
data->unassigned());
|
2010-09-15 12:42:33 +00:00
|
|
|
dims_[dim_index]->EndInitialPropagate();
|
2011-11-19 01:59:37 +00:00
|
|
|
if (need_context) {
|
|
|
|
|
solver()->GetPropagationMonitor()->PopContext();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (need_context) {
|
|
|
|
|
solver()->GetPropagationMonitor()->PopContext();
|
2010-09-15 12:42:33 +00:00
|
|
|
}
|
2011-03-16 15:32:09 +00:00
|
|
|
|
2010-09-15 12:42:33 +00:00
|
|
|
PropagateDelayed();
|
|
|
|
|
ClearAll();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Pack::Propagate() {
|
2011-11-19 01:59:37 +00:00
|
|
|
const bool need_context = solver()->InstrumentsVariables();
|
2010-09-15 12:42:33 +00:00
|
|
|
in_process_ = true;
|
|
|
|
|
DCHECK_EQ(stamp_, solver()->fail_stamp());
|
|
|
|
|
for (int bin_index = 0; bin_index < bins_; ++bin_index) {
|
|
|
|
|
if (!removed_[bin_index].empty() || !forced_[bin_index].empty()) {
|
2011-11-19 01:59:37 +00:00
|
|
|
if (need_context) {
|
2018-10-31 16:18:18 +01:00
|
|
|
solver()->GetPropagationMonitor()->PushContext(
|
|
|
|
|
absl::StrFormat("Pack(bin %d, forced = [%s], removed = [%s])",
|
|
|
|
|
bin_index, absl::StrJoin(forced_[bin_index], ", "),
|
|
|
|
|
absl::StrJoin(removed_[bin_index], ", ")));
|
2011-11-19 01:59:37 +00:00
|
|
|
}
|
|
|
|
|
|
2010-09-15 12:42:33 +00:00
|
|
|
for (int dim_index = 0; dim_index < dims_.size(); ++dim_index) {
|
2011-11-19 01:59:37 +00:00
|
|
|
if (need_context) {
|
2018-10-31 16:18:18 +01:00
|
|
|
solver()->GetPropagationMonitor()->PushContext(absl::StrFormat(
|
|
|
|
|
"ProgateDimension(%s)", dims_[dim_index]->DebugString()));
|
2011-11-19 01:59:37 +00:00
|
|
|
}
|
2020-10-22 23:36:58 +02:00
|
|
|
dims_[dim_index]->Propagate(bin_index, forced_[bin_index],
|
|
|
|
|
removed_[bin_index]);
|
2011-11-19 01:59:37 +00:00
|
|
|
if (need_context) {
|
|
|
|
|
solver()->GetPropagationMonitor()->PopContext();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (need_context) {
|
|
|
|
|
solver()->GetPropagationMonitor()->PopContext();
|
2010-09-15 12:42:33 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (!removed_[bins_].empty() || !forced_[bins_].empty()) {
|
2011-11-19 01:59:37 +00:00
|
|
|
if (need_context) {
|
2020-10-22 23:36:58 +02:00
|
|
|
solver()->GetPropagationMonitor()->PushContext(
|
|
|
|
|
absl::StrFormat("Pack(removed = [%s], forced = [%s])",
|
|
|
|
|
absl::StrJoin(removed_[bins_], ", "),
|
|
|
|
|
absl::StrJoin(forced_[bins_], ", ")));
|
2011-11-19 01:59:37 +00:00
|
|
|
}
|
|
|
|
|
|
2010-09-15 12:42:33 +00:00
|
|
|
for (int dim_index = 0; dim_index < dims_.size(); ++dim_index) {
|
2011-11-19 01:59:37 +00:00
|
|
|
if (need_context) {
|
2018-10-31 16:18:18 +01:00
|
|
|
solver()->GetPropagationMonitor()->PushContext(absl::StrFormat(
|
|
|
|
|
"ProgateDimension(%s)", dims_[dim_index]->DebugString()));
|
2011-11-19 01:59:37 +00:00
|
|
|
}
|
2010-09-15 12:42:33 +00:00
|
|
|
dims_[dim_index]->PropagateUnassigned(removed_[bins_], forced_[bins_]);
|
2011-11-19 01:59:37 +00:00
|
|
|
if (need_context) {
|
|
|
|
|
solver()->GetPropagationMonitor()->PopContext();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (need_context) {
|
|
|
|
|
solver()->GetPropagationMonitor()->PopContext();
|
2010-09-15 12:42:33 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
for (int dim_index = 0; dim_index < dims_.size(); ++dim_index) {
|
|
|
|
|
dims_[dim_index]->EndPropagate();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
PropagateDelayed();
|
|
|
|
|
ClearAll();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Pack::OneDomain(int var_index) {
|
|
|
|
|
// TODO(user): We know var ranges from 0 to bins_. There are lots
|
|
|
|
|
// of simplifications possible.
|
2020-10-29 14:25:39 +01:00
|
|
|
Solver* const s = solver();
|
2021-04-01 12:13:35 +02:00
|
|
|
const uint64_t current_stamp = s->fail_stamp();
|
2010-09-15 12:42:33 +00:00
|
|
|
if (stamp_ < current_stamp) {
|
|
|
|
|
stamp_ = current_stamp;
|
|
|
|
|
ClearAll();
|
|
|
|
|
}
|
2020-10-29 14:25:39 +01:00
|
|
|
IntVar* const var = vars_[var_index];
|
2010-09-15 12:42:33 +00:00
|
|
|
bool bound = var->Bound();
|
2021-04-01 12:13:35 +02:00
|
|
|
const int64_t oldmin = var->OldMin();
|
|
|
|
|
const int64_t oldmax = var->OldMax();
|
|
|
|
|
const int64_t vmin = var->Min();
|
|
|
|
|
const int64_t vmax = var->Max();
|
|
|
|
|
for (int64_t value = std::max(oldmin, int64_t{0});
|
|
|
|
|
value < std::min(vmin, bins_ + int64_t{1}); ++value) {
|
2011-12-16 21:02:59 +00:00
|
|
|
if (unprocessed_->IsSet(value, var_index)) {
|
|
|
|
|
unprocessed_->SetToZero(s, value, var_index);
|
2010-09-15 12:42:33 +00:00
|
|
|
removed_[value].push_back(var_index);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (!bound) {
|
2021-04-01 12:13:35 +02:00
|
|
|
for (const int64_t value : InitAndGetValues(holes_[var_index])) {
|
|
|
|
|
if (value >= std::max(int64_t{0}, vmin) &&
|
|
|
|
|
value <= std::min(static_cast<int64_t>(bins_), vmax)) {
|
2011-12-16 21:02:59 +00:00
|
|
|
DCHECK(unprocessed_->IsSet(value, var_index));
|
|
|
|
|
unprocessed_->SetToZero(s, value, var_index);
|
2010-09-15 12:42:33 +00:00
|
|
|
removed_[value].push_back(var_index);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2021-04-01 12:13:35 +02:00
|
|
|
for (int64_t value = std::max(vmax + 1, int64_t{0});
|
|
|
|
|
value <= std::min(oldmax, static_cast<int64_t>(bins_)); ++value) {
|
2011-12-16 21:02:59 +00:00
|
|
|
if (unprocessed_->IsSet(value, var_index)) {
|
|
|
|
|
unprocessed_->SetToZero(s, value, var_index);
|
2010-09-15 12:42:33 +00:00
|
|
|
removed_[value].push_back(var_index);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (bound) {
|
2011-12-16 21:02:59 +00:00
|
|
|
unprocessed_->SetToZero(s, var->Min(), var_index);
|
2010-09-15 12:42:33 +00:00
|
|
|
forced_[var->Min()].push_back(var_index);
|
|
|
|
|
}
|
2012-09-07 15:27:53 +00:00
|
|
|
EnqueueDelayedDemon(demon_);
|
2010-09-15 12:42:33 +00:00
|
|
|
}
|
|
|
|
|
|
2013-12-16 10:24:42 +00:00
|
|
|
std::string Pack::DebugString() const {
|
|
|
|
|
std::string result = "Pack([";
|
2013-10-10 15:23:20 +00:00
|
|
|
for (int i = 0; i < vars_.size(); ++i) {
|
|
|
|
|
result += vars_[i]->DebugString() + " ";
|
2010-09-15 12:42:33 +00:00
|
|
|
}
|
|
|
|
|
result += "], dimensions = [";
|
|
|
|
|
for (int i = 0; i < dims_.size(); ++i) {
|
2013-10-10 15:23:20 +00:00
|
|
|
result += dims_[i]->DebugString() + " ";
|
2010-09-15 12:42:33 +00:00
|
|
|
}
|
2018-10-31 16:18:18 +01:00
|
|
|
absl::StrAppendFormat(&result, "], bins = %d)", bins_);
|
2010-09-15 12:42:33 +00:00
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
2020-10-29 14:25:39 +01:00
|
|
|
void Pack::Accept(ModelVisitor* const visitor) const {
|
2011-07-11 20:13:14 +00:00
|
|
|
visitor->BeginVisitConstraint(ModelVisitor::kPack, this);
|
2011-07-14 23:40:36 +00:00
|
|
|
visitor->VisitIntegerVariableArrayArgument(ModelVisitor::kVarsArgument,
|
2013-10-10 15:23:20 +00:00
|
|
|
vars_);
|
2011-07-14 23:40:36 +00:00
|
|
|
visitor->VisitIntegerArgument(ModelVisitor::kSizeArgument, bins_);
|
|
|
|
|
for (int i = 0; i < dims_.size(); ++i) {
|
2011-07-14 23:42:49 +00:00
|
|
|
dims_[i]->Accept(visitor);
|
2011-07-14 23:40:36 +00:00
|
|
|
}
|
|
|
|
|
visitor->EndVisitConstraint(ModelVisitor::kPack, this);
|
2011-07-11 20:13:14 +00:00
|
|
|
}
|
|
|
|
|
|
2013-01-10 17:01:34 +00:00
|
|
|
bool Pack::IsUndecided(int var_index, int bin_index) const {
|
2011-12-16 21:02:59 +00:00
|
|
|
return unprocessed_->IsSet(bin_index, var_index);
|
|
|
|
|
}
|
|
|
|
|
|
2013-01-10 17:01:34 +00:00
|
|
|
void Pack::SetImpossible(int var_index, int bin_index) {
|
2010-09-15 12:42:33 +00:00
|
|
|
if (IsInProcess()) {
|
2011-05-17 20:38:55 +00:00
|
|
|
to_unset_.push_back(std::make_pair(var_index, bin_index));
|
2010-09-15 12:42:33 +00:00
|
|
|
} else {
|
|
|
|
|
vars_[var_index]->RemoveValue(bin_index);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2013-01-10 17:01:34 +00:00
|
|
|
void Pack::Assign(int var_index, int bin_index) {
|
2010-09-15 12:42:33 +00:00
|
|
|
if (IsInProcess()) {
|
2011-05-17 20:38:55 +00:00
|
|
|
to_set_.push_back(std::make_pair(var_index, bin_index));
|
2010-09-15 12:42:33 +00:00
|
|
|
} else {
|
|
|
|
|
vars_[var_index]->SetValue(bin_index);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2013-01-10 17:01:34 +00:00
|
|
|
bool Pack::IsAssignedStatusKnown(int var_index) const {
|
2011-12-16 21:02:59 +00:00
|
|
|
return !unprocessed_->IsSet(bins_, var_index);
|
2010-09-15 12:42:33 +00:00
|
|
|
}
|
|
|
|
|
|
2013-01-10 17:01:34 +00:00
|
|
|
bool Pack::IsPossible(int var_index, int bin_index) const {
|
2011-05-11 16:07:52 +00:00
|
|
|
return vars_[var_index]->Contains(bin_index);
|
|
|
|
|
}
|
|
|
|
|
|
2020-10-29 14:25:39 +01:00
|
|
|
IntVar* Pack::AssignVar(int var_index, int bin_index) const {
|
2011-05-11 16:07:52 +00:00
|
|
|
return solver()->MakeIsEqualCstVar(vars_[var_index], bin_index);
|
|
|
|
|
}
|
|
|
|
|
|
2013-01-10 17:01:34 +00:00
|
|
|
void Pack::SetAssigned(int var_index) {
|
2010-09-15 12:42:33 +00:00
|
|
|
if (IsInProcess()) {
|
2011-05-17 20:38:55 +00:00
|
|
|
to_unset_.push_back(std::make_pair(var_index, bins_));
|
2010-09-15 12:42:33 +00:00
|
|
|
} else {
|
|
|
|
|
vars_[var_index]->RemoveValue(bins_);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2013-01-10 17:01:34 +00:00
|
|
|
void Pack::SetUnassigned(int var_index) {
|
2010-09-15 12:42:33 +00:00
|
|
|
if (IsInProcess()) {
|
2011-05-17 20:38:55 +00:00
|
|
|
to_set_.push_back(std::make_pair(var_index, bins_));
|
2010-09-15 12:42:33 +00:00
|
|
|
} else {
|
|
|
|
|
vars_[var_index]->SetValue(bins_);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool Pack::IsInProcess() const {
|
|
|
|
|
return in_process_ && (solver()->fail_stamp() == stamp_);
|
|
|
|
|
}
|
|
|
|
|
|
2013-01-10 17:01:34 +00:00
|
|
|
void Pack::RemoveAllPossibleFromBin(int bin_index) {
|
2011-12-16 21:02:59 +00:00
|
|
|
int var_index = unprocessed_->GetFirstBit(bin_index, 0);
|
2013-10-10 15:23:20 +00:00
|
|
|
while (var_index != -1 && var_index < vars_.size()) {
|
2010-09-15 12:42:33 +00:00
|
|
|
SetImpossible(var_index, bin_index);
|
2013-10-10 15:23:20 +00:00
|
|
|
var_index = var_index == vars_.size() - 1
|
|
|
|
|
? -1
|
|
|
|
|
: unprocessed_->GetFirstBit(bin_index, var_index + 1);
|
2010-09-15 12:42:33 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2013-01-10 17:01:34 +00:00
|
|
|
void Pack::AssignAllPossibleToBin(int bin_index) {
|
2011-12-16 21:02:59 +00:00
|
|
|
int var_index = unprocessed_->GetFirstBit(bin_index, 0);
|
2013-10-10 15:23:20 +00:00
|
|
|
while (var_index != -1 && var_index < vars_.size()) {
|
2010-09-15 12:42:33 +00:00
|
|
|
Assign(var_index, bin_index);
|
2013-10-10 15:23:20 +00:00
|
|
|
var_index = var_index == vars_.size() - 1
|
|
|
|
|
? -1
|
|
|
|
|
: unprocessed_->GetFirstBit(bin_index, var_index + 1);
|
2010-09-15 12:42:33 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2013-01-10 17:01:34 +00:00
|
|
|
void Pack::AssignFirstPossibleToBin(int bin_index) {
|
2011-12-16 21:02:59 +00:00
|
|
|
int var_index = unprocessed_->GetFirstBit(bin_index, 0);
|
2013-10-10 15:23:20 +00:00
|
|
|
if (var_index != -1 && var_index < vars_.size()) {
|
2010-09-15 12:42:33 +00:00
|
|
|
Assign(var_index, bin_index);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Pack::AssignAllRemainingItems() {
|
2011-12-16 21:02:59 +00:00
|
|
|
int var_index = unprocessed_->GetFirstBit(bins_, 0);
|
2013-10-10 15:23:20 +00:00
|
|
|
while (var_index != -1 && var_index < vars_.size()) {
|
2010-09-15 12:42:33 +00:00
|
|
|
SetAssigned(var_index);
|
2020-10-22 23:36:58 +02:00
|
|
|
var_index = var_index == vars_.size() - 1
|
|
|
|
|
? -1
|
|
|
|
|
: unprocessed_->GetFirstBit(bins_, var_index + 1);
|
2010-09-15 12:42:33 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Pack::UnassignAllRemainingItems() {
|
2011-12-16 21:02:59 +00:00
|
|
|
int var_index = unprocessed_->GetFirstBit(bins_, 0);
|
2013-10-10 15:23:20 +00:00
|
|
|
while (var_index != -1 && var_index < vars_.size()) {
|
2010-09-15 12:42:33 +00:00
|
|
|
SetUnassigned(var_index);
|
2020-10-22 23:36:58 +02:00
|
|
|
var_index = var_index == vars_.size() - 1
|
|
|
|
|
? -1
|
|
|
|
|
: unprocessed_->GetFirstBit(bins_, var_index + 1);
|
2010-09-15 12:42:33 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ----- Dimension -----
|
|
|
|
|
|
|
|
|
|
// ----- Class Dimension Less Than Constant -----
|
|
|
|
|
|
|
|
|
|
namespace {
|
|
|
|
|
struct WeightContainer {
|
|
|
|
|
int index;
|
2021-04-01 12:13:35 +02:00
|
|
|
int64_t weight;
|
|
|
|
|
WeightContainer(int i, int64_t w) : index(i), weight(w) {}
|
2020-10-29 14:25:39 +01:00
|
|
|
bool operator<(const WeightContainer& c) const { return (weight < c.weight); }
|
2010-09-15 12:42:33 +00:00
|
|
|
};
|
|
|
|
|
|
2020-10-29 14:25:39 +01:00
|
|
|
void SortWeightVector(std::vector<int>* const indices,
|
|
|
|
|
std::vector<WeightContainer>* const to_sort) {
|
2013-01-10 17:01:34 +00:00
|
|
|
std::sort(to_sort->begin(), to_sort->end());
|
|
|
|
|
for (int index = 0; index < to_sort->size(); ++index) {
|
2013-10-10 15:23:20 +00:00
|
|
|
(*indices)[index] = (*to_sort)[index].index;
|
2013-01-10 17:01:34 +00:00
|
|
|
}
|
2013-10-10 15:23:20 +00:00
|
|
|
indices->resize(to_sort->size());
|
2013-01-10 17:01:34 +00:00
|
|
|
}
|
|
|
|
|
|
2020-10-29 14:25:39 +01:00
|
|
|
void SortIndexByWeight(std::vector<int>* const indices,
|
2021-04-01 12:13:35 +02:00
|
|
|
const std::vector<int64_t>& weights) {
|
2011-05-17 20:38:55 +00:00
|
|
|
std::vector<WeightContainer> to_sort;
|
2013-10-10 15:23:20 +00:00
|
|
|
for (int index = 0; index < indices->size(); ++index) {
|
2010-09-15 12:42:33 +00:00
|
|
|
if (weights[index] != 0) {
|
2013-10-10 15:23:20 +00:00
|
|
|
to_sort.push_back(WeightContainer((*indices)[index], weights[index]));
|
2010-09-15 12:42:33 +00:00
|
|
|
}
|
|
|
|
|
}
|
2013-10-10 15:23:20 +00:00
|
|
|
SortWeightVector(indices, &to_sort);
|
2013-01-10 17:01:34 +00:00
|
|
|
}
|
|
|
|
|
|
2020-10-29 14:25:39 +01:00
|
|
|
void SortIndexByWeight(std::vector<int>* const indices,
|
|
|
|
|
const Solver::IndexEvaluator1& weights) {
|
2013-01-10 17:01:34 +00:00
|
|
|
std::vector<WeightContainer> to_sort;
|
2013-10-10 15:23:20 +00:00
|
|
|
for (int index = 0; index < indices->size(); ++index) {
|
2015-08-13 16:00:54 +02:00
|
|
|
const int w = weights(index);
|
2013-01-10 17:01:34 +00:00
|
|
|
if (w != 0) {
|
2013-10-10 15:23:20 +00:00
|
|
|
to_sort.push_back(WeightContainer((*indices)[index], w));
|
2013-01-10 17:01:34 +00:00
|
|
|
}
|
2010-09-15 12:42:33 +00:00
|
|
|
}
|
2013-10-10 15:23:20 +00:00
|
|
|
SortWeightVector(indices, &to_sort);
|
2013-01-10 17:01:34 +00:00
|
|
|
}
|
|
|
|
|
|
2020-10-29 14:25:39 +01:00
|
|
|
void SortIndexByWeight(std::vector<int>* const indices,
|
|
|
|
|
const Solver::IndexEvaluator2& weights, int bin_index) {
|
2013-01-10 17:01:34 +00:00
|
|
|
std::vector<WeightContainer> to_sort;
|
2013-10-10 15:23:20 +00:00
|
|
|
for (int index = 0; index < indices->size(); ++index) {
|
2015-08-13 16:00:54 +02:00
|
|
|
const int w = weights(index, bin_index);
|
2013-01-10 17:01:34 +00:00
|
|
|
if (w != 0) {
|
2013-10-10 15:23:20 +00:00
|
|
|
to_sort.push_back(WeightContainer((*indices)[index], w));
|
2013-01-10 17:01:34 +00:00
|
|
|
}
|
2010-09-15 12:42:33 +00:00
|
|
|
}
|
2013-10-10 15:23:20 +00:00
|
|
|
SortWeightVector(indices, &to_sort);
|
2010-09-15 12:42:33 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class DimensionLessThanConstant : public Dimension {
|
2020-10-22 23:36:58 +02:00
|
|
|
public:
|
2020-10-29 14:25:39 +01:00
|
|
|
DimensionLessThanConstant(Solver* const s, Pack* const p,
|
2021-04-01 12:13:35 +02:00
|
|
|
const std::vector<int64_t>& weights,
|
|
|
|
|
const std::vector<int64_t>& upper_bounds)
|
2020-10-22 23:36:58 +02:00
|
|
|
: Dimension(s, p),
|
|
|
|
|
vars_count_(weights.size()),
|
|
|
|
|
weights_(weights),
|
|
|
|
|
bins_count_(upper_bounds.size()),
|
|
|
|
|
upper_bounds_(upper_bounds),
|
2013-10-10 15:23:20 +00:00
|
|
|
first_unbound_backward_vector_(bins_count_, 0),
|
2020-10-22 23:36:58 +02:00
|
|
|
sum_of_bound_variables_vector_(bins_count_, 0LL),
|
|
|
|
|
ranked_(vars_count_) {
|
2010-09-15 12:42:33 +00:00
|
|
|
for (int i = 0; i < vars_count_; ++i) {
|
|
|
|
|
ranked_[i] = i;
|
|
|
|
|
}
|
2013-10-10 15:23:20 +00:00
|
|
|
SortIndexByWeight(&ranked_, weights_);
|
2010-09-15 12:42:33 +00:00
|
|
|
}
|
|
|
|
|
|
2015-04-16 15:49:51 +02:00
|
|
|
~DimensionLessThanConstant() override {}
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2015-04-16 15:49:51 +02:00
|
|
|
void Post() override {}
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2013-01-10 17:01:34 +00:00
|
|
|
void PushFromTop(int bin_index) {
|
2021-04-01 12:13:35 +02:00
|
|
|
const int64_t slack =
|
2013-10-10 15:23:20 +00:00
|
|
|
upper_bounds_[bin_index] - sum_of_bound_variables_vector_[bin_index];
|
2010-09-15 12:42:33 +00:00
|
|
|
if (slack < 0) {
|
|
|
|
|
solver()->Fail();
|
|
|
|
|
}
|
2013-01-10 17:01:34 +00:00
|
|
|
int last_unbound = first_unbound_backward_vector_[bin_index];
|
2010-09-15 12:42:33 +00:00
|
|
|
for (; last_unbound >= 0; --last_unbound) {
|
2013-01-10 17:01:34 +00:00
|
|
|
const int var_index = ranked_[last_unbound];
|
2010-09-15 12:42:33 +00:00
|
|
|
if (IsUndecided(var_index, bin_index)) {
|
|
|
|
|
if (weights_[var_index] > slack) {
|
|
|
|
|
SetImpossible(var_index, bin_index);
|
|
|
|
|
} else {
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2011-12-16 21:02:59 +00:00
|
|
|
first_unbound_backward_vector_.SetValue(solver(), bin_index, last_unbound);
|
2010-09-15 12:42:33 +00:00
|
|
|
}
|
|
|
|
|
|
2020-10-29 14:25:39 +01:00
|
|
|
void InitialPropagate(int bin_index, const std::vector<int>& forced,
|
|
|
|
|
const std::vector<int>& undecided) override {
|
|
|
|
|
Solver* const s = solver();
|
2021-04-01 12:13:35 +02:00
|
|
|
int64_t sum = 0LL;
|
2014-04-15 09:38:36 +00:00
|
|
|
for (const int value : forced) {
|
|
|
|
|
sum += weights_[value];
|
2010-09-15 12:42:33 +00:00
|
|
|
}
|
2011-12-16 21:02:59 +00:00
|
|
|
sum_of_bound_variables_vector_.SetValue(s, bin_index, sum);
|
2013-10-10 15:23:20 +00:00
|
|
|
first_unbound_backward_vector_.SetValue(s, bin_index, ranked_.size() - 1);
|
2010-09-15 12:42:33 +00:00
|
|
|
PushFromTop(bin_index);
|
|
|
|
|
}
|
|
|
|
|
|
2015-04-16 15:49:51 +02:00
|
|
|
void EndInitialPropagate() override {}
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2020-10-29 14:25:39 +01:00
|
|
|
void Propagate(int bin_index, const std::vector<int>& forced,
|
|
|
|
|
const std::vector<int>& removed) override {
|
2017-04-19 16:20:56 +02:00
|
|
|
if (!forced.empty()) {
|
2020-10-29 14:25:39 +01:00
|
|
|
Solver* const s = solver();
|
2021-04-01 12:13:35 +02:00
|
|
|
int64_t sum = sum_of_bound_variables_vector_[bin_index];
|
2014-04-15 09:38:36 +00:00
|
|
|
for (const int value : forced) {
|
|
|
|
|
sum += weights_[value];
|
2010-09-15 12:42:33 +00:00
|
|
|
}
|
2011-12-16 21:02:59 +00:00
|
|
|
sum_of_bound_variables_vector_.SetValue(s, bin_index, sum);
|
2010-09-15 12:42:33 +00:00
|
|
|
PushFromTop(bin_index);
|
|
|
|
|
}
|
|
|
|
|
}
|
2020-10-29 14:25:39 +01:00
|
|
|
void InitialPropagateUnassigned(const std::vector<int>& assigned,
|
|
|
|
|
const std::vector<int>& unassigned) override {
|
2016-11-29 13:40:04 +01:00
|
|
|
}
|
2020-10-29 14:25:39 +01:00
|
|
|
void PropagateUnassigned(const std::vector<int>& assigned,
|
|
|
|
|
const std::vector<int>& unassigned) override {}
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2015-04-16 15:49:51 +02:00
|
|
|
void EndPropagate() override {}
|
2011-07-11 20:13:14 +00:00
|
|
|
|
2020-10-29 14:25:39 +01:00
|
|
|
void Accept(ModelVisitor* const visitor) const override {
|
2011-09-17 13:34:27 +00:00
|
|
|
visitor->BeginVisitExtension(ModelVisitor::kUsageLessConstantExtension);
|
2011-07-14 23:37:47 +00:00
|
|
|
visitor->VisitIntegerArrayArgument(ModelVisitor::kCoefficientsArgument,
|
2013-10-10 15:23:20 +00:00
|
|
|
weights_);
|
2011-08-11 05:15:18 +00:00
|
|
|
visitor->VisitIntegerArrayArgument(ModelVisitor::kValuesArgument,
|
2013-10-10 15:23:20 +00:00
|
|
|
upper_bounds_);
|
2011-09-17 13:34:27 +00:00
|
|
|
visitor->EndVisitExtension(ModelVisitor::kUsageLessConstantExtension);
|
2011-07-14 23:37:47 +00:00
|
|
|
}
|
|
|
|
|
|
2020-10-22 23:36:58 +02:00
|
|
|
private:
|
2010-09-15 12:42:33 +00:00
|
|
|
const int vars_count_;
|
2021-04-01 12:13:35 +02:00
|
|
|
const std::vector<int64_t> weights_;
|
2010-09-15 12:42:33 +00:00
|
|
|
const int bins_count_;
|
2021-04-01 12:13:35 +02:00
|
|
|
const std::vector<int64_t> upper_bounds_;
|
2011-12-16 21:02:59 +00:00
|
|
|
RevArray<int> first_unbound_backward_vector_;
|
2021-04-01 12:13:35 +02:00
|
|
|
RevArray<int64_t> sum_of_bound_variables_vector_;
|
2013-10-10 15:23:20 +00:00
|
|
|
std::vector<int> ranked_;
|
2013-01-10 17:01:34 +00:00
|
|
|
};
|
|
|
|
|
|
2013-10-10 15:23:20 +00:00
|
|
|
class DimensionSumCallbackLessThanConstant : public Dimension {
|
2020-10-22 23:36:58 +02:00
|
|
|
public:
|
2020-10-29 14:25:39 +01:00
|
|
|
DimensionSumCallbackLessThanConstant(Solver* const s, Pack* const p,
|
|
|
|
|
const Solver::IndexEvaluator1& weights,
|
2013-10-10 15:23:20 +00:00
|
|
|
int vars_count,
|
2021-04-01 12:13:35 +02:00
|
|
|
const std::vector<int64_t>& upper_bounds)
|
2020-10-22 23:36:58 +02:00
|
|
|
: Dimension(s, p),
|
|
|
|
|
vars_count_(vars_count),
|
|
|
|
|
weights_(weights),
|
|
|
|
|
bins_count_(upper_bounds.size()),
|
|
|
|
|
upper_bounds_(upper_bounds),
|
2013-10-10 15:23:20 +00:00
|
|
|
first_unbound_backward_vector_(bins_count_, 0),
|
2020-10-22 23:36:58 +02:00
|
|
|
sum_of_bound_variables_vector_(bins_count_, 0LL),
|
|
|
|
|
ranked_(vars_count_) {
|
2013-01-10 17:01:34 +00:00
|
|
|
DCHECK(weights);
|
|
|
|
|
DCHECK_GT(vars_count, 0);
|
|
|
|
|
for (int i = 0; i < vars_count_; ++i) {
|
|
|
|
|
ranked_[i] = i;
|
|
|
|
|
}
|
2015-08-13 16:00:54 +02:00
|
|
|
SortIndexByWeight(&ranked_, weights_);
|
2013-01-10 17:01:34 +00:00
|
|
|
}
|
|
|
|
|
|
2015-04-16 15:49:51 +02:00
|
|
|
~DimensionSumCallbackLessThanConstant() override {}
|
2013-01-10 17:01:34 +00:00
|
|
|
|
2015-04-16 15:49:51 +02:00
|
|
|
void Post() override {}
|
2013-01-10 17:01:34 +00:00
|
|
|
|
|
|
|
|
void PushFromTop(int bin_index) {
|
2021-04-01 12:13:35 +02:00
|
|
|
const int64_t slack =
|
2013-10-10 15:23:20 +00:00
|
|
|
upper_bounds_[bin_index] - sum_of_bound_variables_vector_[bin_index];
|
2013-01-10 17:01:34 +00:00
|
|
|
if (slack < 0) {
|
|
|
|
|
solver()->Fail();
|
|
|
|
|
}
|
|
|
|
|
int last_unbound = first_unbound_backward_vector_[bin_index];
|
|
|
|
|
for (; last_unbound >= 0; --last_unbound) {
|
|
|
|
|
const int var_index = ranked_[last_unbound];
|
|
|
|
|
if (IsUndecided(var_index, bin_index)) {
|
2015-08-13 16:00:54 +02:00
|
|
|
if (weights_(var_index) > slack) {
|
2013-01-10 17:01:34 +00:00
|
|
|
SetImpossible(var_index, bin_index);
|
|
|
|
|
} else {
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
first_unbound_backward_vector_.SetValue(solver(), bin_index, last_unbound);
|
|
|
|
|
}
|
|
|
|
|
|
2020-10-29 14:25:39 +01:00
|
|
|
void InitialPropagate(int bin_index, const std::vector<int>& forced,
|
|
|
|
|
const std::vector<int>& undecided) override {
|
|
|
|
|
Solver* const s = solver();
|
2021-04-01 12:13:35 +02:00
|
|
|
int64_t sum = 0LL;
|
2014-04-15 09:38:36 +00:00
|
|
|
for (const int value : forced) {
|
2015-08-13 16:00:54 +02:00
|
|
|
sum += weights_(value);
|
2013-01-10 17:01:34 +00:00
|
|
|
}
|
|
|
|
|
sum_of_bound_variables_vector_.SetValue(s, bin_index, sum);
|
2013-10-10 15:23:20 +00:00
|
|
|
first_unbound_backward_vector_.SetValue(s, bin_index, ranked_.size() - 1);
|
2013-01-10 17:01:34 +00:00
|
|
|
PushFromTop(bin_index);
|
|
|
|
|
}
|
|
|
|
|
|
2015-04-16 15:49:51 +02:00
|
|
|
void EndInitialPropagate() override {}
|
2013-01-10 17:01:34 +00:00
|
|
|
|
2020-10-29 14:25:39 +01:00
|
|
|
void Propagate(int bin_index, const std::vector<int>& forced,
|
|
|
|
|
const std::vector<int>& removed) override {
|
2017-04-19 16:20:56 +02:00
|
|
|
if (!forced.empty()) {
|
2020-10-29 14:25:39 +01:00
|
|
|
Solver* const s = solver();
|
2021-04-01 12:13:35 +02:00
|
|
|
int64_t sum = sum_of_bound_variables_vector_[bin_index];
|
2014-04-15 09:38:36 +00:00
|
|
|
for (const int value : forced) {
|
2015-08-13 16:00:54 +02:00
|
|
|
sum += weights_(value);
|
2013-01-10 17:01:34 +00:00
|
|
|
}
|
|
|
|
|
sum_of_bound_variables_vector_.SetValue(s, bin_index, sum);
|
|
|
|
|
PushFromTop(bin_index);
|
|
|
|
|
}
|
|
|
|
|
}
|
2020-10-29 14:25:39 +01:00
|
|
|
void InitialPropagateUnassigned(const std::vector<int>& assigned,
|
|
|
|
|
const std::vector<int>& unassigned) override {
|
2016-11-29 13:40:04 +01:00
|
|
|
}
|
2020-10-29 14:25:39 +01:00
|
|
|
void PropagateUnassigned(const std::vector<int>& assigned,
|
|
|
|
|
const std::vector<int>& unassigned) override {}
|
2013-01-10 17:01:34 +00:00
|
|
|
|
2015-04-16 15:49:51 +02:00
|
|
|
void EndPropagate() override {}
|
2013-01-10 17:01:34 +00:00
|
|
|
|
2020-10-29 14:25:39 +01:00
|
|
|
void Accept(ModelVisitor* const visitor) const override {
|
2013-01-10 17:01:34 +00:00
|
|
|
visitor->BeginVisitExtension(ModelVisitor::kUsageLessConstantExtension);
|
|
|
|
|
// TODO(user) : Visit weight correctly.
|
|
|
|
|
// visitor->VisitIntegerArrayArgument(ModelVisitor::kCoefficientsArgument,
|
2013-10-10 15:23:20 +00:00
|
|
|
// weights_);
|
2013-01-10 17:01:34 +00:00
|
|
|
visitor->VisitIntegerArrayArgument(ModelVisitor::kValuesArgument,
|
2013-10-10 15:23:20 +00:00
|
|
|
upper_bounds_);
|
2013-01-10 17:01:34 +00:00
|
|
|
visitor->EndVisitExtension(ModelVisitor::kUsageLessConstantExtension);
|
|
|
|
|
}
|
|
|
|
|
|
2020-10-22 23:36:58 +02:00
|
|
|
private:
|
2013-01-10 17:01:34 +00:00
|
|
|
const int vars_count_;
|
2015-08-13 16:00:54 +02:00
|
|
|
Solver::IndexEvaluator1 weights_;
|
2013-01-10 17:01:34 +00:00
|
|
|
const int bins_count_;
|
2021-04-01 12:13:35 +02:00
|
|
|
const std::vector<int64_t> upper_bounds_;
|
2013-01-10 17:01:34 +00:00
|
|
|
RevArray<int> first_unbound_backward_vector_;
|
2021-04-01 12:13:35 +02:00
|
|
|
RevArray<int64_t> sum_of_bound_variables_vector_;
|
2013-10-10 15:23:20 +00:00
|
|
|
std::vector<int> ranked_;
|
2010-09-15 12:42:33 +00:00
|
|
|
};
|
|
|
|
|
|
2013-01-10 17:01:34 +00:00
|
|
|
class DimensionLessThanConstantCallback2 : public Dimension {
|
2020-10-22 23:36:58 +02:00
|
|
|
public:
|
2020-10-29 14:25:39 +01:00
|
|
|
DimensionLessThanConstantCallback2(Solver* const s, Pack* const p,
|
|
|
|
|
const Solver::IndexEvaluator2& weights,
|
2013-01-10 17:01:34 +00:00
|
|
|
int vars_count,
|
2021-04-01 12:13:35 +02:00
|
|
|
const std::vector<int64_t>& upper_bounds)
|
2020-10-22 23:36:58 +02:00
|
|
|
: Dimension(s, p),
|
|
|
|
|
vars_count_(vars_count),
|
|
|
|
|
weights_(weights),
|
|
|
|
|
bins_count_(upper_bounds.size()),
|
|
|
|
|
upper_bounds_(upper_bounds),
|
2013-10-10 15:23:20 +00:00
|
|
|
first_unbound_backward_vector_(bins_count_, 0),
|
2020-10-22 23:36:58 +02:00
|
|
|
sum_of_bound_variables_vector_(bins_count_, 0LL),
|
|
|
|
|
ranked_(bins_count_) {
|
2013-01-10 17:01:34 +00:00
|
|
|
DCHECK(weights);
|
|
|
|
|
DCHECK_GT(vars_count, 0);
|
|
|
|
|
for (int b = 0; b < bins_count_; ++b) {
|
|
|
|
|
ranked_[b].resize(vars_count);
|
|
|
|
|
for (int i = 0; i < vars_count_; ++i) {
|
|
|
|
|
ranked_[b][i] = i;
|
|
|
|
|
}
|
2015-08-13 16:00:54 +02:00
|
|
|
SortIndexByWeight(&ranked_[b], weights_, b);
|
2013-01-10 17:01:34 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2015-04-16 15:49:51 +02:00
|
|
|
~DimensionLessThanConstantCallback2() override {}
|
2013-01-10 17:01:34 +00:00
|
|
|
|
2015-04-16 15:49:51 +02:00
|
|
|
void Post() override {}
|
2013-01-10 17:01:34 +00:00
|
|
|
|
|
|
|
|
void PushFromTop(int bin_index) {
|
2021-04-01 12:13:35 +02:00
|
|
|
const int64_t slack =
|
2013-10-10 15:23:20 +00:00
|
|
|
upper_bounds_[bin_index] - sum_of_bound_variables_vector_[bin_index];
|
2013-01-10 17:01:34 +00:00
|
|
|
if (slack < 0) {
|
|
|
|
|
solver()->Fail();
|
|
|
|
|
}
|
|
|
|
|
int last_unbound = first_unbound_backward_vector_[bin_index];
|
|
|
|
|
for (; last_unbound >= 0; --last_unbound) {
|
|
|
|
|
const int var_index = ranked_[bin_index][last_unbound];
|
|
|
|
|
if (IsUndecided(var_index, bin_index)) {
|
2015-08-13 16:00:54 +02:00
|
|
|
if (weights_(var_index, bin_index) > slack) {
|
2013-01-10 17:01:34 +00:00
|
|
|
SetImpossible(var_index, bin_index);
|
|
|
|
|
} else {
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
first_unbound_backward_vector_.SetValue(solver(), bin_index, last_unbound);
|
|
|
|
|
}
|
|
|
|
|
|
2020-10-29 14:25:39 +01:00
|
|
|
void InitialPropagate(int bin_index, const std::vector<int>& forced,
|
|
|
|
|
const std::vector<int>& undecided) override {
|
|
|
|
|
Solver* const s = solver();
|
2021-04-01 12:13:35 +02:00
|
|
|
int64_t sum = 0LL;
|
2014-04-15 09:38:36 +00:00
|
|
|
for (const int value : forced) {
|
2015-08-13 16:00:54 +02:00
|
|
|
sum += weights_(value, bin_index);
|
2013-01-10 17:01:34 +00:00
|
|
|
}
|
|
|
|
|
sum_of_bound_variables_vector_.SetValue(s, bin_index, sum);
|
2013-10-10 15:23:20 +00:00
|
|
|
first_unbound_backward_vector_.SetValue(s, bin_index,
|
|
|
|
|
ranked_[bin_index].size() - 1);
|
2013-01-10 17:01:34 +00:00
|
|
|
PushFromTop(bin_index);
|
|
|
|
|
}
|
|
|
|
|
|
2015-04-16 15:49:51 +02:00
|
|
|
void EndInitialPropagate() override {}
|
2013-01-10 17:01:34 +00:00
|
|
|
|
2020-10-29 14:25:39 +01:00
|
|
|
void Propagate(int bin_index, const std::vector<int>& forced,
|
|
|
|
|
const std::vector<int>& removed) override {
|
2017-04-19 16:20:56 +02:00
|
|
|
if (!forced.empty()) {
|
2020-10-29 14:25:39 +01:00
|
|
|
Solver* const s = solver();
|
2021-04-01 12:13:35 +02:00
|
|
|
int64_t sum = sum_of_bound_variables_vector_[bin_index];
|
2014-04-15 09:38:36 +00:00
|
|
|
for (const int value : forced) {
|
2015-08-13 16:00:54 +02:00
|
|
|
sum += weights_(value, bin_index);
|
2013-01-10 17:01:34 +00:00
|
|
|
}
|
|
|
|
|
sum_of_bound_variables_vector_.SetValue(s, bin_index, sum);
|
|
|
|
|
PushFromTop(bin_index);
|
|
|
|
|
}
|
|
|
|
|
}
|
2020-10-29 14:25:39 +01:00
|
|
|
void InitialPropagateUnassigned(const std::vector<int>& assigned,
|
|
|
|
|
const std::vector<int>& unassigned) override {
|
2016-11-29 13:40:04 +01:00
|
|
|
}
|
2020-10-29 14:25:39 +01:00
|
|
|
void PropagateUnassigned(const std::vector<int>& assigned,
|
|
|
|
|
const std::vector<int>& unassigned) override {}
|
2013-01-10 17:01:34 +00:00
|
|
|
|
2015-04-16 15:49:51 +02:00
|
|
|
void EndPropagate() override {}
|
2013-01-10 17:01:34 +00:00
|
|
|
|
2020-10-29 14:25:39 +01:00
|
|
|
void Accept(ModelVisitor* const visitor) const override {
|
2013-01-10 17:01:34 +00:00
|
|
|
visitor->BeginVisitExtension(ModelVisitor::kUsageLessConstantExtension);
|
|
|
|
|
// TODO(user): Visit weight correctly
|
|
|
|
|
// visitor->VisitIntegerArrayArgument(ModelVisitor::kCoefficientsArgument,
|
2013-10-10 15:23:20 +00:00
|
|
|
// weights_);
|
2013-01-10 17:01:34 +00:00
|
|
|
visitor->VisitIntegerArrayArgument(ModelVisitor::kValuesArgument,
|
2013-10-10 15:23:20 +00:00
|
|
|
upper_bounds_);
|
2013-01-10 17:01:34 +00:00
|
|
|
visitor->EndVisitExtension(ModelVisitor::kUsageLessConstantExtension);
|
|
|
|
|
}
|
|
|
|
|
|
2020-10-22 23:36:58 +02:00
|
|
|
private:
|
2013-01-10 17:01:34 +00:00
|
|
|
const int vars_count_;
|
2015-08-13 16:00:54 +02:00
|
|
|
Solver::IndexEvaluator2 weights_;
|
2013-01-10 17:01:34 +00:00
|
|
|
const int bins_count_;
|
2021-04-01 12:13:35 +02:00
|
|
|
const std::vector<int64_t> upper_bounds_;
|
2013-01-10 17:01:34 +00:00
|
|
|
RevArray<int> first_unbound_backward_vector_;
|
2021-04-01 12:13:35 +02:00
|
|
|
RevArray<int64_t> sum_of_bound_variables_vector_;
|
2020-11-01 11:47:28 +01:00
|
|
|
std::vector<std::vector<int>> ranked_;
|
2013-01-10 17:01:34 +00:00
|
|
|
};
|
|
|
|
|
|
2010-10-13 15:05:40 +00:00
|
|
|
class DimensionWeightedSumEqVar : public Dimension {
|
2020-10-22 23:36:58 +02:00
|
|
|
public:
|
2010-10-13 15:05:40 +00:00
|
|
|
class VarDemon : public Demon {
|
2020-10-22 23:36:58 +02:00
|
|
|
public:
|
2020-10-29 14:25:39 +01:00
|
|
|
VarDemon(DimensionWeightedSumEqVar* const dim, int index)
|
2010-10-13 16:22:18 +00:00
|
|
|
: dim_(dim), index_(index) {}
|
2015-04-16 15:49:51 +02:00
|
|
|
~VarDemon() override {}
|
2010-10-13 15:05:40 +00:00
|
|
|
|
2020-10-29 14:25:39 +01:00
|
|
|
void Run(Solver* const s) override { dim_->PushFromTop(index_); }
|
2011-07-11 20:13:14 +00:00
|
|
|
|
2020-10-22 23:36:58 +02:00
|
|
|
private:
|
2020-10-29 14:25:39 +01:00
|
|
|
DimensionWeightedSumEqVar* const dim_;
|
2010-10-13 15:05:40 +00:00
|
|
|
const int index_;
|
|
|
|
|
};
|
|
|
|
|
|
2020-10-29 14:25:39 +01:00
|
|
|
DimensionWeightedSumEqVar(Solver* const s, Pack* const p,
|
2021-04-01 12:13:35 +02:00
|
|
|
const std::vector<int64_t>& weights,
|
2020-10-29 14:25:39 +01:00
|
|
|
const std::vector<IntVar*>& loads)
|
2020-10-22 23:36:58 +02:00
|
|
|
: Dimension(s, p),
|
|
|
|
|
vars_count_(weights.size()),
|
|
|
|
|
weights_(weights),
|
|
|
|
|
bins_count_(loads.size()),
|
|
|
|
|
loads_(loads),
|
2013-10-10 15:23:20 +00:00
|
|
|
first_unbound_backward_vector_(bins_count_, 0),
|
|
|
|
|
sum_of_bound_variables_vector_(bins_count_, 0LL),
|
2020-10-22 23:36:58 +02:00
|
|
|
sum_of_all_variables_vector_(bins_count_, 0LL),
|
|
|
|
|
ranked_(vars_count_) {
|
2013-10-10 15:23:20 +00:00
|
|
|
DCHECK_GT(vars_count_, 0);
|
|
|
|
|
DCHECK_GT(bins_count_, 0);
|
2010-10-13 15:05:40 +00:00
|
|
|
for (int i = 0; i < vars_count_; ++i) {
|
|
|
|
|
ranked_[i] = i;
|
|
|
|
|
}
|
2013-10-10 15:23:20 +00:00
|
|
|
SortIndexByWeight(&ranked_, weights_);
|
2010-10-13 15:05:40 +00:00
|
|
|
}
|
|
|
|
|
|
2015-04-16 15:49:51 +02:00
|
|
|
~DimensionWeightedSumEqVar() override {}
|
2010-10-13 15:05:40 +00:00
|
|
|
|
2018-06-08 16:40:43 +02:00
|
|
|
std::string DebugString() const override {
|
|
|
|
|
return "DimensionWeightedSumEqVar";
|
|
|
|
|
}
|
2010-10-13 15:05:40 +00:00
|
|
|
|
2015-04-16 15:49:51 +02:00
|
|
|
void Post() override {
|
2010-10-13 15:05:40 +00:00
|
|
|
for (int i = 0; i < bins_count_; ++i) {
|
2020-10-29 14:25:39 +01:00
|
|
|
Demon* const d = solver()->RevAlloc(new VarDemon(this, i));
|
2010-10-13 15:05:40 +00:00
|
|
|
loads_[i]->WhenRange(d);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2013-01-10 17:01:34 +00:00
|
|
|
void PushFromTop(int bin_index) {
|
2020-10-29 14:25:39 +01:00
|
|
|
IntVar* const load = loads_[bin_index];
|
2021-04-01 12:13:35 +02:00
|
|
|
const int64_t sum_min = sum_of_bound_variables_vector_[bin_index];
|
|
|
|
|
const int64_t sum_max = sum_of_all_variables_vector_[bin_index];
|
2010-10-13 16:22:18 +00:00
|
|
|
load->SetRange(sum_min, sum_max);
|
2021-04-01 12:13:35 +02:00
|
|
|
const int64_t slack_up = load->Max() - sum_min;
|
|
|
|
|
const int64_t slack_down = sum_max - load->Min();
|
2010-10-13 16:22:18 +00:00
|
|
|
DCHECK_GE(slack_down, 0);
|
|
|
|
|
DCHECK_GE(slack_up, 0);
|
2013-01-10 17:01:34 +00:00
|
|
|
int last_unbound = first_unbound_backward_vector_[bin_index];
|
2010-10-13 15:05:40 +00:00
|
|
|
for (; last_unbound >= 0; --last_unbound) {
|
2013-01-10 17:01:34 +00:00
|
|
|
const int var_index = ranked_[last_unbound];
|
2021-04-01 12:13:35 +02:00
|
|
|
const int64_t weight = weights_[var_index];
|
2010-10-13 15:05:40 +00:00
|
|
|
if (IsUndecided(var_index, bin_index)) {
|
|
|
|
|
if (weight > slack_up) {
|
|
|
|
|
SetImpossible(var_index, bin_index);
|
|
|
|
|
} else if (weight > slack_down) {
|
|
|
|
|
Assign(var_index, bin_index);
|
|
|
|
|
} else {
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2011-12-16 21:02:59 +00:00
|
|
|
first_unbound_backward_vector_.SetValue(solver(), bin_index, last_unbound);
|
2010-10-13 15:05:40 +00:00
|
|
|
}
|
|
|
|
|
|
2020-10-29 14:25:39 +01:00
|
|
|
void InitialPropagate(int bin_index, const std::vector<int>& forced,
|
|
|
|
|
const std::vector<int>& undecided) override {
|
|
|
|
|
Solver* const s = solver();
|
2021-04-01 12:13:35 +02:00
|
|
|
int64_t sum = 0LL;
|
2014-04-15 09:38:36 +00:00
|
|
|
for (const int value : forced) {
|
|
|
|
|
sum += weights_[value];
|
2010-10-13 15:05:40 +00:00
|
|
|
}
|
2011-12-16 21:02:59 +00:00
|
|
|
sum_of_bound_variables_vector_.SetValue(s, bin_index, sum);
|
2014-04-15 09:38:36 +00:00
|
|
|
for (const int value : undecided) {
|
|
|
|
|
sum += weights_[value];
|
2010-10-13 15:05:40 +00:00
|
|
|
}
|
2011-12-16 21:02:59 +00:00
|
|
|
sum_of_all_variables_vector_.SetValue(s, bin_index, sum);
|
2013-10-10 15:23:20 +00:00
|
|
|
first_unbound_backward_vector_.SetValue(s, bin_index, ranked_.size() - 1);
|
2010-10-13 15:05:40 +00:00
|
|
|
PushFromTop(bin_index);
|
|
|
|
|
}
|
|
|
|
|
|
2015-04-16 15:49:51 +02:00
|
|
|
void EndInitialPropagate() override {}
|
2010-10-13 15:05:40 +00:00
|
|
|
|
2020-10-29 14:25:39 +01:00
|
|
|
void Propagate(int bin_index, const std::vector<int>& forced,
|
|
|
|
|
const std::vector<int>& removed) override {
|
|
|
|
|
Solver* const s = solver();
|
2021-04-01 12:13:35 +02:00
|
|
|
int64_t down = sum_of_bound_variables_vector_[bin_index];
|
2014-04-15 09:38:36 +00:00
|
|
|
for (const int value : forced) {
|
|
|
|
|
down += weights_[value];
|
2010-10-13 15:05:40 +00:00
|
|
|
}
|
2011-12-16 21:02:59 +00:00
|
|
|
sum_of_bound_variables_vector_.SetValue(s, bin_index, down);
|
2021-04-01 12:13:35 +02:00
|
|
|
int64_t up = sum_of_all_variables_vector_[bin_index];
|
2014-04-15 09:38:36 +00:00
|
|
|
for (const int value : removed) {
|
|
|
|
|
up -= weights_[value];
|
2010-10-13 15:05:40 +00:00
|
|
|
}
|
2011-12-16 21:02:59 +00:00
|
|
|
sum_of_all_variables_vector_.SetValue(s, bin_index, up);
|
2010-10-13 15:05:40 +00:00
|
|
|
PushFromTop(bin_index);
|
|
|
|
|
}
|
2020-10-29 14:25:39 +01:00
|
|
|
void InitialPropagateUnassigned(const std::vector<int>& assigned,
|
|
|
|
|
const std::vector<int>& unassigned) override {
|
2016-11-29 13:40:04 +01:00
|
|
|
}
|
2020-10-29 14:25:39 +01:00
|
|
|
void PropagateUnassigned(const std::vector<int>& assigned,
|
|
|
|
|
const std::vector<int>& unassigned) override {}
|
2010-10-13 15:05:40 +00:00
|
|
|
|
2015-04-16 15:49:51 +02:00
|
|
|
void EndPropagate() override {}
|
2011-07-11 20:13:14 +00:00
|
|
|
|
2020-10-29 14:25:39 +01:00
|
|
|
void Accept(ModelVisitor* const visitor) const override {
|
2011-08-11 05:15:18 +00:00
|
|
|
visitor->BeginVisitExtension(ModelVisitor::kUsageEqualVariableExtension);
|
2011-07-14 23:37:47 +00:00
|
|
|
visitor->VisitIntegerArrayArgument(ModelVisitor::kCoefficientsArgument,
|
2013-10-10 15:23:20 +00:00
|
|
|
weights_);
|
2011-07-14 23:37:47 +00:00
|
|
|
visitor->VisitIntegerVariableArrayArgument(ModelVisitor::kVarsArgument,
|
2013-10-10 15:23:20 +00:00
|
|
|
loads_);
|
2011-08-11 05:15:18 +00:00
|
|
|
visitor->EndVisitExtension(ModelVisitor::kUsageEqualVariableExtension);
|
2011-07-14 23:37:47 +00:00
|
|
|
}
|
|
|
|
|
|
2020-10-22 23:36:58 +02:00
|
|
|
private:
|
2010-10-13 15:05:40 +00:00
|
|
|
const int vars_count_;
|
2021-04-01 12:13:35 +02:00
|
|
|
const std::vector<int64_t> weights_;
|
2010-10-13 15:05:40 +00:00
|
|
|
const int bins_count_;
|
2020-10-29 14:25:39 +01:00
|
|
|
const std::vector<IntVar*> loads_;
|
2011-12-16 21:02:59 +00:00
|
|
|
RevArray<int> first_unbound_backward_vector_;
|
2021-04-01 12:13:35 +02:00
|
|
|
RevArray<int64_t> sum_of_bound_variables_vector_;
|
|
|
|
|
RevArray<int64_t> sum_of_all_variables_vector_;
|
2013-10-10 15:23:20 +00:00
|
|
|
std::vector<int> ranked_;
|
2010-10-13 15:05:40 +00:00
|
|
|
};
|
|
|
|
|
|
2013-01-10 17:01:34 +00:00
|
|
|
class DimensionWeightedCallback2SumEqVar : public Dimension {
|
2020-10-22 23:36:58 +02:00
|
|
|
public:
|
2013-01-10 17:01:34 +00:00
|
|
|
class VarDemon : public Demon {
|
2020-10-22 23:36:58 +02:00
|
|
|
public:
|
2020-10-29 14:25:39 +01:00
|
|
|
VarDemon(DimensionWeightedCallback2SumEqVar* const dim, int index)
|
2013-01-10 17:01:34 +00:00
|
|
|
: dim_(dim), index_(index) {}
|
2015-04-16 15:49:51 +02:00
|
|
|
~VarDemon() override {}
|
2013-01-10 17:01:34 +00:00
|
|
|
|
2020-10-29 14:25:39 +01:00
|
|
|
void Run(Solver* const s) override { dim_->PushFromTop(index_); }
|
2013-01-10 17:01:34 +00:00
|
|
|
|
2020-10-22 23:36:58 +02:00
|
|
|
private:
|
2020-10-29 14:25:39 +01:00
|
|
|
DimensionWeightedCallback2SumEqVar* const dim_;
|
2013-01-10 17:01:34 +00:00
|
|
|
const int index_;
|
|
|
|
|
};
|
|
|
|
|
|
2020-10-29 14:25:39 +01:00
|
|
|
DimensionWeightedCallback2SumEqVar(Solver* const s, Pack* const p,
|
|
|
|
|
const Solver::IndexEvaluator2& weights,
|
2013-01-10 17:01:34 +00:00
|
|
|
int vars_count,
|
2020-10-29 14:25:39 +01:00
|
|
|
const std::vector<IntVar*>& loads)
|
2020-10-22 23:36:58 +02:00
|
|
|
: Dimension(s, p),
|
|
|
|
|
vars_count_(vars_count),
|
|
|
|
|
weights_(weights),
|
|
|
|
|
bins_count_(loads.size()),
|
|
|
|
|
loads_(loads),
|
2013-10-10 15:23:20 +00:00
|
|
|
first_unbound_backward_vector_(bins_count_, 0),
|
|
|
|
|
sum_of_bound_variables_vector_(bins_count_, 0LL),
|
2020-10-22 23:36:58 +02:00
|
|
|
sum_of_all_variables_vector_(bins_count_, 0LL),
|
|
|
|
|
ranked_(bins_count_) {
|
2013-01-10 17:01:34 +00:00
|
|
|
DCHECK(weights);
|
2013-10-10 15:23:20 +00:00
|
|
|
DCHECK_GT(vars_count_, 0);
|
|
|
|
|
DCHECK_GT(bins_count_, 0);
|
2013-01-10 17:01:34 +00:00
|
|
|
for (int b = 0; b < bins_count_; ++b) {
|
|
|
|
|
ranked_[b].resize(vars_count);
|
|
|
|
|
for (int i = 0; i < vars_count_; ++i) {
|
|
|
|
|
ranked_[b][i] = i;
|
|
|
|
|
}
|
2015-08-13 16:00:54 +02:00
|
|
|
SortIndexByWeight(&ranked_[b], weights_, b);
|
2013-01-10 17:01:34 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2015-04-16 15:49:51 +02:00
|
|
|
~DimensionWeightedCallback2SumEqVar() override {}
|
2013-01-10 17:01:34 +00:00
|
|
|
|
2015-04-16 15:49:51 +02:00
|
|
|
std::string DebugString() const override {
|
2013-01-10 17:01:34 +00:00
|
|
|
return "DimensionWeightedCallback2SumEqVar";
|
|
|
|
|
}
|
|
|
|
|
|
2015-04-16 15:49:51 +02:00
|
|
|
void Post() override {
|
2013-01-10 17:01:34 +00:00
|
|
|
for (int i = 0; i < bins_count_; ++i) {
|
2020-10-29 14:25:39 +01:00
|
|
|
Demon* const d = solver()->RevAlloc(new VarDemon(this, i));
|
2013-01-10 17:01:34 +00:00
|
|
|
loads_[i]->WhenRange(d);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void PushFromTop(int bin_index) {
|
2020-10-29 14:25:39 +01:00
|
|
|
IntVar* const load = loads_[bin_index];
|
2021-04-01 12:13:35 +02:00
|
|
|
const int64_t sum_min = sum_of_bound_variables_vector_[bin_index];
|
|
|
|
|
const int64_t sum_max = sum_of_all_variables_vector_[bin_index];
|
2013-01-10 17:01:34 +00:00
|
|
|
load->SetRange(sum_min, sum_max);
|
2021-04-01 12:13:35 +02:00
|
|
|
const int64_t slack_up = load->Max() - sum_min;
|
|
|
|
|
const int64_t slack_down = sum_max - load->Min();
|
2013-01-10 17:01:34 +00:00
|
|
|
DCHECK_GE(slack_down, 0);
|
|
|
|
|
DCHECK_GE(slack_up, 0);
|
|
|
|
|
int last_unbound = first_unbound_backward_vector_[bin_index];
|
|
|
|
|
for (; last_unbound >= 0; --last_unbound) {
|
|
|
|
|
const int var_index = ranked_[bin_index][last_unbound];
|
2021-04-01 12:13:35 +02:00
|
|
|
const int64_t weight = weights_(var_index, bin_index);
|
2013-01-10 17:01:34 +00:00
|
|
|
if (IsUndecided(var_index, bin_index)) {
|
|
|
|
|
if (weight > slack_up) {
|
|
|
|
|
SetImpossible(var_index, bin_index);
|
|
|
|
|
} else if (weight > slack_down) {
|
|
|
|
|
Assign(var_index, bin_index);
|
|
|
|
|
} else {
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
first_unbound_backward_vector_.SetValue(solver(), bin_index, last_unbound);
|
|
|
|
|
}
|
|
|
|
|
|
2020-10-29 14:25:39 +01:00
|
|
|
void InitialPropagate(int bin_index, const std::vector<int>& forced,
|
|
|
|
|
const std::vector<int>& undecided) override {
|
|
|
|
|
Solver* const s = solver();
|
2021-04-01 12:13:35 +02:00
|
|
|
int64_t sum = 0LL;
|
2014-04-15 09:38:36 +00:00
|
|
|
for (const int value : forced) {
|
2015-08-13 16:00:54 +02:00
|
|
|
sum += weights_(value, bin_index);
|
2013-01-10 17:01:34 +00:00
|
|
|
}
|
|
|
|
|
sum_of_bound_variables_vector_.SetValue(s, bin_index, sum);
|
2014-04-15 09:38:36 +00:00
|
|
|
for (const int value : undecided) {
|
2015-08-13 16:00:54 +02:00
|
|
|
sum += weights_(value, bin_index);
|
2013-01-10 17:01:34 +00:00
|
|
|
}
|
|
|
|
|
sum_of_all_variables_vector_.SetValue(s, bin_index, sum);
|
|
|
|
|
first_unbound_backward_vector_.SetValue(s, bin_index,
|
2013-10-10 15:23:20 +00:00
|
|
|
ranked_[bin_index].size() - 1);
|
2013-01-10 17:01:34 +00:00
|
|
|
PushFromTop(bin_index);
|
|
|
|
|
}
|
|
|
|
|
|
2015-04-16 15:49:51 +02:00
|
|
|
void EndInitialPropagate() override {}
|
2013-01-10 17:01:34 +00:00
|
|
|
|
2020-10-29 14:25:39 +01:00
|
|
|
void Propagate(int bin_index, const std::vector<int>& forced,
|
|
|
|
|
const std::vector<int>& removed) override {
|
|
|
|
|
Solver* const s = solver();
|
2021-04-01 12:13:35 +02:00
|
|
|
int64_t down = sum_of_bound_variables_vector_[bin_index];
|
2014-04-15 09:38:36 +00:00
|
|
|
for (const int value : forced) {
|
2015-08-13 16:00:54 +02:00
|
|
|
down += weights_(value, bin_index);
|
2013-01-10 17:01:34 +00:00
|
|
|
}
|
|
|
|
|
sum_of_bound_variables_vector_.SetValue(s, bin_index, down);
|
2021-04-01 12:13:35 +02:00
|
|
|
int64_t up = sum_of_all_variables_vector_[bin_index];
|
2014-04-15 09:38:36 +00:00
|
|
|
for (const int value : removed) {
|
2015-08-13 16:00:54 +02:00
|
|
|
up -= weights_(value, bin_index);
|
2013-01-10 17:01:34 +00:00
|
|
|
}
|
|
|
|
|
sum_of_all_variables_vector_.SetValue(s, bin_index, up);
|
|
|
|
|
PushFromTop(bin_index);
|
|
|
|
|
}
|
2020-10-29 14:25:39 +01:00
|
|
|
void InitialPropagateUnassigned(const std::vector<int>& assigned,
|
|
|
|
|
const std::vector<int>& unassigned) override {
|
2016-11-29 13:40:04 +01:00
|
|
|
}
|
2020-10-29 14:25:39 +01:00
|
|
|
void PropagateUnassigned(const std::vector<int>& assigned,
|
|
|
|
|
const std::vector<int>& unassigned) override {}
|
2013-01-10 17:01:34 +00:00
|
|
|
|
2015-04-16 15:49:51 +02:00
|
|
|
void EndPropagate() override {}
|
2013-01-10 17:01:34 +00:00
|
|
|
|
2020-10-29 14:25:39 +01:00
|
|
|
void Accept(ModelVisitor* const visitor) const override {
|
2013-10-10 15:23:20 +00:00
|
|
|
visitor->BeginVisitExtension(ModelVisitor::kUsageEqualVariableExtension);
|
2013-01-10 17:01:34 +00:00
|
|
|
// TODO(user): Visit weight correctly
|
|
|
|
|
// visitor->VisitIntegerArrayArgument(ModelVisitor::kCoefficientsArgument,
|
2013-10-10 15:23:20 +00:00
|
|
|
// weights_);
|
2013-01-10 17:01:34 +00:00
|
|
|
visitor->VisitIntegerVariableArrayArgument(ModelVisitor::kVarsArgument,
|
2013-10-10 15:23:20 +00:00
|
|
|
loads_);
|
|
|
|
|
visitor->EndVisitExtension(ModelVisitor::kUsageEqualVariableExtension);
|
2013-01-10 17:01:34 +00:00
|
|
|
}
|
|
|
|
|
|
2020-10-22 23:36:58 +02:00
|
|
|
private:
|
2013-01-10 17:01:34 +00:00
|
|
|
const int vars_count_;
|
2015-08-13 16:00:54 +02:00
|
|
|
Solver::IndexEvaluator2 weights_;
|
2013-01-10 17:01:34 +00:00
|
|
|
const int bins_count_;
|
2020-10-29 14:25:39 +01:00
|
|
|
const std::vector<IntVar*> loads_;
|
2013-01-10 17:01:34 +00:00
|
|
|
RevArray<int> first_unbound_backward_vector_;
|
2021-04-01 12:13:35 +02:00
|
|
|
RevArray<int64_t> sum_of_bound_variables_vector_;
|
|
|
|
|
RevArray<int64_t> sum_of_all_variables_vector_;
|
2020-11-01 11:47:28 +01:00
|
|
|
std::vector<std::vector<int>> ranked_;
|
2013-01-10 17:01:34 +00:00
|
|
|
};
|
|
|
|
|
|
2010-09-15 12:42:33 +00:00
|
|
|
class AssignedWeightedSumDimension : public Dimension {
|
2020-10-22 23:36:58 +02:00
|
|
|
public:
|
2010-09-15 12:42:33 +00:00
|
|
|
class VarDemon : public Demon {
|
2020-10-22 23:36:58 +02:00
|
|
|
public:
|
2020-10-29 14:25:39 +01:00
|
|
|
explicit VarDemon(AssignedWeightedSumDimension* const dim) : dim_(dim) {}
|
2015-04-16 15:49:51 +02:00
|
|
|
~VarDemon() override {}
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2020-10-29 14:25:39 +01:00
|
|
|
void Run(Solver* const s) override { dim_->PropagateAll(); }
|
2011-07-11 20:13:14 +00:00
|
|
|
|
2020-10-22 23:36:58 +02:00
|
|
|
private:
|
2020-10-29 14:25:39 +01:00
|
|
|
AssignedWeightedSumDimension* const dim_;
|
2010-09-15 12:42:33 +00:00
|
|
|
};
|
|
|
|
|
|
2020-10-29 14:25:39 +01:00
|
|
|
AssignedWeightedSumDimension(Solver* const s, Pack* const p,
|
2021-04-01 12:13:35 +02:00
|
|
|
const std::vector<int64_t>& weights,
|
2020-10-29 14:25:39 +01:00
|
|
|
int bins_count, IntVar* const cost_var)
|
2020-10-22 23:36:58 +02:00
|
|
|
: Dimension(s, p),
|
|
|
|
|
vars_count_(weights.size()),
|
|
|
|
|
weights_(weights),
|
|
|
|
|
bins_count_(bins_count),
|
|
|
|
|
cost_var_(cost_var),
|
|
|
|
|
first_unbound_backward_(0),
|
|
|
|
|
sum_of_assigned_items_(0LL),
|
|
|
|
|
sum_of_unassigned_items_(0LL),
|
|
|
|
|
ranked_(vars_count_),
|
2010-09-15 12:42:33 +00:00
|
|
|
sum_all_weights_(0LL) {
|
|
|
|
|
DCHECK(cost_var);
|
2013-10-10 15:23:20 +00:00
|
|
|
DCHECK_GT(vars_count_, 0);
|
|
|
|
|
DCHECK_GT(bins_count_, 0);
|
2010-09-15 12:42:33 +00:00
|
|
|
for (int i = 0; i < vars_count_; ++i) {
|
|
|
|
|
ranked_[i] = i;
|
|
|
|
|
}
|
2013-10-10 15:23:20 +00:00
|
|
|
SortIndexByWeight(&ranked_, weights_);
|
|
|
|
|
first_unbound_backward_.SetValue(s, ranked_.size() - 1);
|
2010-09-15 12:42:33 +00:00
|
|
|
}
|
|
|
|
|
|
2015-04-16 15:49:51 +02:00
|
|
|
~AssignedWeightedSumDimension() override {}
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2015-04-16 15:49:51 +02:00
|
|
|
void Post() override {
|
2020-10-29 14:25:39 +01:00
|
|
|
Demon* const uv = solver()->RevAlloc(new VarDemon(this));
|
2010-09-15 12:42:33 +00:00
|
|
|
cost_var_->WhenRange(uv);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void PropagateAll() {
|
|
|
|
|
cost_var_->SetRange(sum_of_assigned_items_.Value(),
|
|
|
|
|
sum_all_weights_ - sum_of_unassigned_items_.Value());
|
2021-04-01 12:13:35 +02:00
|
|
|
const int64_t slack_up = cost_var_->Max() - sum_of_assigned_items_.Value();
|
|
|
|
|
const int64_t slack_down = sum_all_weights_ - cost_var_->Min();
|
2013-01-10 17:01:34 +00:00
|
|
|
int last_unbound = first_unbound_backward_.Value();
|
2010-09-15 12:42:33 +00:00
|
|
|
for (; last_unbound >= 0; --last_unbound) {
|
|
|
|
|
const int var_index = ranked_[last_unbound];
|
|
|
|
|
if (!IsAssignedStatusKnown(var_index)) {
|
2021-04-01 12:13:35 +02:00
|
|
|
const int64_t coefficient = weights_[var_index];
|
2010-09-15 12:42:33 +00:00
|
|
|
if (coefficient > slack_up) {
|
|
|
|
|
SetUnassigned(var_index);
|
|
|
|
|
} else if (coefficient > slack_down) {
|
|
|
|
|
SetAssigned(var_index);
|
|
|
|
|
} else {
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
first_unbound_backward_.SetValue(solver(), last_unbound);
|
|
|
|
|
}
|
|
|
|
|
|
2020-10-29 14:25:39 +01:00
|
|
|
void InitialPropagate(int bin_index, const std::vector<int>& forced,
|
|
|
|
|
const std::vector<int>& undecided) override {}
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2015-04-16 15:49:51 +02:00
|
|
|
void EndInitialPropagate() override {}
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2020-10-29 14:25:39 +01:00
|
|
|
void InitialPropagateUnassigned(const std::vector<int>& assigned,
|
|
|
|
|
const std::vector<int>& unassigned) override {
|
2010-09-15 12:42:33 +00:00
|
|
|
for (int index = 0; index < vars_count_; ++index) {
|
|
|
|
|
sum_all_weights_ += weights_[index];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
PropagateUnassigned(assigned, unassigned);
|
|
|
|
|
}
|
|
|
|
|
|
2020-10-29 14:25:39 +01:00
|
|
|
void Propagate(int bin_index, const std::vector<int>& forced,
|
|
|
|
|
const std::vector<int>& removed) override {}
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2020-10-29 14:25:39 +01:00
|
|
|
void PropagateUnassigned(const std::vector<int>& assigned,
|
|
|
|
|
const std::vector<int>& unassigned) override {
|
2021-04-01 12:13:35 +02:00
|
|
|
int64_t sum_assigned = sum_of_assigned_items_.Value();
|
2010-09-15 12:42:33 +00:00
|
|
|
for (int index = 0; index < assigned.size(); ++index) {
|
|
|
|
|
const int var_index = assigned[index];
|
|
|
|
|
sum_assigned += weights_[var_index];
|
|
|
|
|
}
|
|
|
|
|
|
2021-04-01 12:13:35 +02:00
|
|
|
int64_t sum_unassigned = sum_of_unassigned_items_.Value();
|
2010-09-15 12:42:33 +00:00
|
|
|
for (int index = 0; index < unassigned.size(); ++index) {
|
|
|
|
|
const int var_index = unassigned[index];
|
|
|
|
|
sum_unassigned += weights_[var_index];
|
|
|
|
|
}
|
|
|
|
|
|
2020-10-29 14:25:39 +01:00
|
|
|
Solver* const s = solver();
|
2010-09-15 12:42:33 +00:00
|
|
|
sum_of_assigned_items_.SetValue(s, sum_assigned);
|
|
|
|
|
sum_of_unassigned_items_.SetValue(s, sum_unassigned);
|
|
|
|
|
PropagateAll();
|
|
|
|
|
}
|
|
|
|
|
|
2015-04-16 15:49:51 +02:00
|
|
|
void EndPropagate() override {}
|
2011-07-11 20:13:14 +00:00
|
|
|
|
2020-10-29 14:25:39 +01:00
|
|
|
void Accept(ModelVisitor* const visitor) const override {
|
2011-08-11 05:15:18 +00:00
|
|
|
visitor->BeginVisitExtension(
|
|
|
|
|
ModelVisitor::kWeightedSumOfAssignedEqualVariableExtension);
|
2011-07-14 23:37:47 +00:00
|
|
|
visitor->VisitIntegerArrayArgument(ModelVisitor::kCoefficientsArgument,
|
2013-10-10 15:23:20 +00:00
|
|
|
weights_);
|
2011-07-14 23:37:47 +00:00
|
|
|
visitor->VisitIntegerExpressionArgument(ModelVisitor::kTargetArgument,
|
|
|
|
|
cost_var_);
|
2011-08-11 05:15:18 +00:00
|
|
|
visitor->EndVisitExtension(
|
|
|
|
|
ModelVisitor::kWeightedSumOfAssignedEqualVariableExtension);
|
2011-07-14 23:37:47 +00:00
|
|
|
}
|
|
|
|
|
|
2020-10-22 23:36:58 +02:00
|
|
|
private:
|
2010-09-15 12:42:33 +00:00
|
|
|
const int vars_count_;
|
2021-04-01 12:13:35 +02:00
|
|
|
const std::vector<int64_t> weights_;
|
2010-09-15 12:42:33 +00:00
|
|
|
const int bins_count_;
|
2020-10-29 14:25:39 +01:00
|
|
|
IntVar* const cost_var_;
|
2010-09-15 12:42:33 +00:00
|
|
|
Rev<int> first_unbound_backward_;
|
2021-04-01 12:13:35 +02:00
|
|
|
Rev<int64_t> sum_of_assigned_items_;
|
|
|
|
|
Rev<int64_t> sum_of_unassigned_items_;
|
2013-10-10 15:23:20 +00:00
|
|
|
std::vector<int> ranked_;
|
2021-04-01 12:13:35 +02:00
|
|
|
int64_t sum_all_weights_;
|
2010-09-15 12:42:33 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// ----- Count unassigned jobs dimension -----
|
|
|
|
|
|
|
|
|
|
class CountAssignedItemsDimension : public Dimension {
|
2020-10-22 23:36:58 +02:00
|
|
|
public:
|
2010-09-15 12:42:33 +00:00
|
|
|
class VarDemon : public Demon {
|
2020-10-22 23:36:58 +02:00
|
|
|
public:
|
2020-10-29 14:25:39 +01:00
|
|
|
explicit VarDemon(CountAssignedItemsDimension* const dim) : dim_(dim) {}
|
2015-04-16 15:49:51 +02:00
|
|
|
~VarDemon() override {}
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2020-10-29 14:25:39 +01:00
|
|
|
void Run(Solver* const s) override { dim_->PropagateAll(); }
|
2011-07-11 20:13:14 +00:00
|
|
|
|
2020-10-22 23:36:58 +02:00
|
|
|
private:
|
2020-10-29 14:25:39 +01:00
|
|
|
CountAssignedItemsDimension* const dim_;
|
2010-09-15 12:42:33 +00:00
|
|
|
};
|
|
|
|
|
|
2020-10-29 14:25:39 +01:00
|
|
|
CountAssignedItemsDimension(Solver* const s, Pack* const p, int vars_count,
|
|
|
|
|
int bins_count, IntVar* const cost_var)
|
2020-10-22 23:36:58 +02:00
|
|
|
: Dimension(s, p),
|
|
|
|
|
vars_count_(vars_count),
|
|
|
|
|
bins_count_(bins_count),
|
|
|
|
|
cost_var_(cost_var),
|
|
|
|
|
first_unbound_backward_(0),
|
|
|
|
|
assigned_count_(0),
|
2010-09-15 12:42:33 +00:00
|
|
|
unassigned_count_(0) {
|
|
|
|
|
DCHECK(cost_var);
|
|
|
|
|
DCHECK_GT(vars_count, 0);
|
|
|
|
|
DCHECK_GT(bins_count, 0);
|
|
|
|
|
}
|
|
|
|
|
|
2015-04-16 15:49:51 +02:00
|
|
|
~CountAssignedItemsDimension() override {}
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2015-04-16 15:49:51 +02:00
|
|
|
void Post() override {
|
2020-10-29 14:25:39 +01:00
|
|
|
Demon* const uv = solver()->RevAlloc(new VarDemon(this));
|
2010-09-15 12:42:33 +00:00
|
|
|
cost_var_->WhenRange(uv);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void PropagateAll() {
|
|
|
|
|
cost_var_->SetRange(assigned_count_.Value(),
|
2013-10-10 15:23:20 +00:00
|
|
|
vars_count_ - unassigned_count_.Value());
|
2010-09-15 12:42:33 +00:00
|
|
|
if (assigned_count_.Value() == cost_var_->Max()) {
|
|
|
|
|
UnassignAllRemainingItems();
|
|
|
|
|
} else if (cost_var_->Min() == vars_count_ - unassigned_count_.Value()) {
|
|
|
|
|
AssignAllRemainingItems();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-10-29 14:25:39 +01:00
|
|
|
void InitialPropagate(int bin_index, const std::vector<int>& forced,
|
|
|
|
|
const std::vector<int>& undecided) override {}
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2015-04-16 15:49:51 +02:00
|
|
|
void EndInitialPropagate() override {}
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2020-10-29 14:25:39 +01:00
|
|
|
void InitialPropagateUnassigned(const std::vector<int>& assigned,
|
|
|
|
|
const std::vector<int>& unassigned) override {
|
2010-09-15 12:42:33 +00:00
|
|
|
PropagateUnassigned(assigned, unassigned);
|
|
|
|
|
}
|
|
|
|
|
|
2020-10-29 14:25:39 +01:00
|
|
|
void Propagate(int bin_index, const std::vector<int>& forced,
|
|
|
|
|
const std::vector<int>& removed) override {}
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2020-10-29 14:25:39 +01:00
|
|
|
void PropagateUnassigned(const std::vector<int>& assigned,
|
|
|
|
|
const std::vector<int>& unassigned) override {
|
|
|
|
|
Solver* const s = solver();
|
2010-09-15 12:42:33 +00:00
|
|
|
assigned_count_.SetValue(s, assigned_count_.Value() + assigned.size());
|
|
|
|
|
unassigned_count_.SetValue(s,
|
|
|
|
|
unassigned_count_.Value() + unassigned.size());
|
|
|
|
|
PropagateAll();
|
|
|
|
|
}
|
|
|
|
|
|
2015-04-16 15:49:51 +02:00
|
|
|
void EndPropagate() override {}
|
2011-07-11 20:13:14 +00:00
|
|
|
|
2020-10-29 14:25:39 +01:00
|
|
|
void Accept(ModelVisitor* const visitor) const override {
|
2011-08-11 05:15:18 +00:00
|
|
|
visitor->BeginVisitExtension(ModelVisitor::kCountAssignedItemsExtension);
|
2011-07-14 23:37:47 +00:00
|
|
|
visitor->VisitIntegerExpressionArgument(ModelVisitor::kTargetArgument,
|
|
|
|
|
cost_var_);
|
2011-08-11 05:15:18 +00:00
|
|
|
visitor->EndVisitExtension(ModelVisitor::kCountAssignedItemsExtension);
|
2011-07-14 23:37:47 +00:00
|
|
|
}
|
|
|
|
|
|
2020-10-22 23:36:58 +02:00
|
|
|
private:
|
2010-09-15 12:42:33 +00:00
|
|
|
const int vars_count_;
|
|
|
|
|
const int bins_count_;
|
2020-10-29 14:25:39 +01:00
|
|
|
IntVar* const cost_var_;
|
2010-09-15 12:42:33 +00:00
|
|
|
Rev<int> first_unbound_backward_;
|
|
|
|
|
Rev<int> assigned_count_;
|
|
|
|
|
Rev<int> unassigned_count_;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// ----- Count used bin dimension -----
|
|
|
|
|
|
|
|
|
|
class CountUsedBinDimension : public Dimension {
|
2020-10-22 23:36:58 +02:00
|
|
|
public:
|
2010-09-15 12:42:33 +00:00
|
|
|
class VarDemon : public Demon {
|
2020-10-22 23:36:58 +02:00
|
|
|
public:
|
2020-10-29 14:25:39 +01:00
|
|
|
explicit VarDemon(CountUsedBinDimension* const dim) : dim_(dim) {}
|
2015-04-16 15:49:51 +02:00
|
|
|
~VarDemon() override {}
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2020-10-29 14:25:39 +01:00
|
|
|
void Run(Solver* const s) override { dim_->PropagateAll(); }
|
2011-07-11 20:13:14 +00:00
|
|
|
|
2020-10-22 23:36:58 +02:00
|
|
|
private:
|
2020-10-29 14:25:39 +01:00
|
|
|
CountUsedBinDimension* const dim_;
|
2010-09-15 12:42:33 +00:00
|
|
|
};
|
|
|
|
|
|
2020-10-29 14:25:39 +01:00
|
|
|
CountUsedBinDimension(Solver* const s, Pack* const p, int vars_count,
|
|
|
|
|
int bins_count, IntVar* const count_var)
|
2020-10-22 23:36:58 +02:00
|
|
|
: Dimension(s, p),
|
|
|
|
|
vars_count_(vars_count),
|
|
|
|
|
bins_count_(bins_count),
|
|
|
|
|
count_var_(count_var),
|
|
|
|
|
used_(bins_count_),
|
|
|
|
|
candidates_(bins_count_, 0),
|
|
|
|
|
card_min_(0),
|
|
|
|
|
card_max_(bins_count_),
|
|
|
|
|
initial_min_(0),
|
|
|
|
|
initial_max_(0) {
|
2010-09-15 12:42:33 +00:00
|
|
|
DCHECK(count_var);
|
|
|
|
|
DCHECK_GT(vars_count, 0);
|
|
|
|
|
DCHECK_GT(bins_count, 0);
|
|
|
|
|
}
|
|
|
|
|
|
2015-04-16 15:49:51 +02:00
|
|
|
~CountUsedBinDimension() override {}
|
2011-12-16 21:02:59 +00:00
|
|
|
|
2015-04-16 15:49:51 +02:00
|
|
|
void Post() override {
|
2020-10-29 14:25:39 +01:00
|
|
|
Demon* const uv = solver()->RevAlloc(new VarDemon(this));
|
2010-09-15 12:42:33 +00:00
|
|
|
count_var_->WhenRange(uv);
|
|
|
|
|
initial_min_ = 0;
|
|
|
|
|
initial_max_ = bins_count_;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void PropagateAll() {
|
|
|
|
|
count_var_->SetRange(card_min_.Value(), card_max_.Value());
|
|
|
|
|
if (card_min_.Value() == count_var_->Max()) {
|
|
|
|
|
for (int bin_index = 0; bin_index < bins_count_; ++bin_index) {
|
2011-12-16 21:02:59 +00:00
|
|
|
if (!used_.IsSet(bin_index) && candidates_[bin_index] > 0) {
|
2010-09-15 12:42:33 +00:00
|
|
|
RemoveAllPossibleFromBin(bin_index);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} else if (card_max_.Value() == count_var_->Min()) {
|
|
|
|
|
for (int bin_index = 0; bin_index < bins_count_; ++bin_index) {
|
|
|
|
|
if (candidates_[bin_index] == 1) {
|
|
|
|
|
AssignFirstPossibleToBin(bin_index);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-10-29 14:25:39 +01:00
|
|
|
void InitialPropagate(int bin_index, const std::vector<int>& forced,
|
|
|
|
|
const std::vector<int>& undecided) override {
|
2017-04-19 16:20:56 +02:00
|
|
|
if (!forced.empty()) {
|
2011-12-16 21:02:59 +00:00
|
|
|
used_.SetToOne(solver(), bin_index);
|
2010-09-15 12:42:33 +00:00
|
|
|
initial_min_++;
|
2017-04-19 16:20:56 +02:00
|
|
|
} else if (!undecided.empty()) {
|
2011-12-16 21:02:59 +00:00
|
|
|
candidates_.SetValue(solver(), bin_index, undecided.size());
|
2010-09-15 12:42:33 +00:00
|
|
|
} else {
|
|
|
|
|
initial_max_--;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2015-04-16 15:49:51 +02:00
|
|
|
void EndInitialPropagate() override {
|
2010-09-15 12:42:33 +00:00
|
|
|
card_min_.SetValue(solver(), initial_min_);
|
|
|
|
|
card_max_.SetValue(solver(), initial_max_);
|
|
|
|
|
PropagateAll();
|
|
|
|
|
}
|
|
|
|
|
|
2020-10-29 14:25:39 +01:00
|
|
|
void InitialPropagateUnassigned(const std::vector<int>& assigned,
|
|
|
|
|
const std::vector<int>& unassigned) override {
|
2016-11-29 13:40:04 +01:00
|
|
|
}
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2020-10-29 14:25:39 +01:00
|
|
|
void Propagate(int bin_index, const std::vector<int>& forced,
|
|
|
|
|
const std::vector<int>& removed) override {
|
2011-12-16 21:02:59 +00:00
|
|
|
if (!used_.IsSet(bin_index)) {
|
2017-04-19 16:20:56 +02:00
|
|
|
if (!forced.empty()) {
|
2011-12-16 21:02:59 +00:00
|
|
|
used_.SetToOne(solver(), bin_index);
|
2010-09-15 12:42:33 +00:00
|
|
|
card_min_.SetValue(solver(), card_min_.Value() + 1);
|
2017-04-19 16:20:56 +02:00
|
|
|
} else if (!removed.empty()) {
|
2013-10-10 15:23:20 +00:00
|
|
|
candidates_.SetValue(solver(), bin_index,
|
2011-12-16 21:02:59 +00:00
|
|
|
candidates_.Value(bin_index) - removed.size());
|
2010-09-15 12:42:33 +00:00
|
|
|
if (candidates_[bin_index] == 0) {
|
|
|
|
|
card_max_.SetValue(solver(), card_max_.Value() - 1);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-10-29 14:25:39 +01:00
|
|
|
void PropagateUnassigned(const std::vector<int>& assigned,
|
|
|
|
|
const std::vector<int>& unassigned) override {}
|
2010-09-15 12:42:33 +00:00
|
|
|
|
2015-04-16 15:49:51 +02:00
|
|
|
void EndPropagate() override { PropagateAll(); }
|
2011-07-11 20:13:14 +00:00
|
|
|
|
2020-10-29 14:25:39 +01:00
|
|
|
void Accept(ModelVisitor* const visitor) const override {
|
2011-08-11 05:15:18 +00:00
|
|
|
visitor->BeginVisitExtension(ModelVisitor::kCountUsedBinsExtension);
|
2011-07-14 23:37:47 +00:00
|
|
|
visitor->VisitIntegerExpressionArgument(ModelVisitor::kTargetArgument,
|
|
|
|
|
count_var_);
|
2011-08-11 05:15:18 +00:00
|
|
|
visitor->EndVisitExtension(ModelVisitor::kCountUsedBinsExtension);
|
2011-07-14 23:37:47 +00:00
|
|
|
}
|
|
|
|
|
|
2020-10-22 23:36:58 +02:00
|
|
|
private:
|
2010-09-15 12:42:33 +00:00
|
|
|
const int vars_count_;
|
|
|
|
|
const int bins_count_;
|
2020-10-29 14:25:39 +01:00
|
|
|
IntVar* const count_var_;
|
2011-12-16 21:02:59 +00:00
|
|
|
RevBitSet used_;
|
|
|
|
|
RevArray<int> candidates_;
|
2010-09-15 12:42:33 +00:00
|
|
|
Rev<int> card_min_;
|
|
|
|
|
Rev<int> card_max_;
|
|
|
|
|
int initial_min_;
|
|
|
|
|
int initial_max_;
|
|
|
|
|
};
|
|
|
|
|
|
2011-05-11 16:07:52 +00:00
|
|
|
// ---------- Variable Usage Dimension ----------
|
|
|
|
|
|
|
|
|
|
// This is a very naive, but correct implementation of the constraint.
|
|
|
|
|
class VariableUsageDimension : public Dimension {
|
2020-10-22 23:36:58 +02:00
|
|
|
public:
|
2020-10-29 14:25:39 +01:00
|
|
|
VariableUsageDimension(Solver* const solver, Pack* const pack,
|
2021-04-01 12:13:35 +02:00
|
|
|
const std::vector<int64_t>& capacities,
|
2020-10-29 14:25:39 +01:00
|
|
|
const std::vector<IntVar*>& weights)
|
2011-05-11 16:07:52 +00:00
|
|
|
: Dimension(solver, pack), capacities_(capacities), weights_(weights) {}
|
|
|
|
|
|
2015-04-16 15:49:51 +02:00
|
|
|
~VariableUsageDimension() override {}
|
2011-05-11 16:07:52 +00:00
|
|
|
|
2015-04-16 15:49:51 +02:00
|
|
|
void Post() override {
|
2020-10-29 14:25:39 +01:00
|
|
|
Solver* const s = solver();
|
2011-05-11 16:07:52 +00:00
|
|
|
const int num_bins = capacities_.size();
|
|
|
|
|
const int num_items = weights_.size();
|
|
|
|
|
|
|
|
|
|
for (int bin_index = 0; bin_index < num_bins; ++bin_index) {
|
2020-10-29 14:25:39 +01:00
|
|
|
std::vector<IntVar*> terms;
|
2011-05-11 16:07:52 +00:00
|
|
|
for (int item_index = 0; item_index < num_items; ++item_index) {
|
2020-10-29 14:25:39 +01:00
|
|
|
IntVar* const assign_var = AssignVar(item_index, bin_index);
|
2011-05-11 16:07:52 +00:00
|
|
|
terms.push_back(s->MakeProd(assign_var, weights_[item_index])->Var());
|
|
|
|
|
}
|
|
|
|
|
s->AddConstraint(s->MakeSumLessOrEqual(terms, capacities_[bin_index]));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-10-29 14:25:39 +01:00
|
|
|
void InitialPropagate(int bin_index, const std::vector<int>& forced,
|
|
|
|
|
const std::vector<int>& undecided) override {}
|
|
|
|
|
void InitialPropagateUnassigned(const std::vector<int>& assigned,
|
|
|
|
|
const std::vector<int>& unassigned) override {
|
2016-11-29 13:40:04 +01:00
|
|
|
}
|
2015-04-16 15:49:51 +02:00
|
|
|
void EndInitialPropagate() override {}
|
2020-10-29 14:25:39 +01:00
|
|
|
void Propagate(int bin_index, const std::vector<int>& forced,
|
|
|
|
|
const std::vector<int>& removed) override {}
|
|
|
|
|
void PropagateUnassigned(const std::vector<int>& assigned,
|
|
|
|
|
const std::vector<int>& unassigned) override {}
|
2015-04-16 15:49:51 +02:00
|
|
|
void EndPropagate() override {}
|
2011-05-11 16:07:52 +00:00
|
|
|
|
2015-04-16 15:49:51 +02:00
|
|
|
std::string DebugString() const override { return "VariableUsageDimension"; }
|
2011-07-11 20:13:14 +00:00
|
|
|
|
2020-10-29 14:25:39 +01:00
|
|
|
void Accept(ModelVisitor* const visitor) const override {
|
2011-08-11 05:15:18 +00:00
|
|
|
visitor->BeginVisitExtension(
|
|
|
|
|
ModelVisitor::kVariableUsageLessConstantExtension);
|
2011-07-14 23:37:47 +00:00
|
|
|
visitor->VisitIntegerArrayArgument(ModelVisitor::kValuesArgument,
|
2013-10-10 15:23:20 +00:00
|
|
|
capacities_);
|
2011-07-14 23:37:47 +00:00
|
|
|
visitor->VisitIntegerVariableArrayArgument(ModelVisitor::kVarsArgument,
|
2013-10-10 15:23:20 +00:00
|
|
|
weights_);
|
2011-08-11 05:15:18 +00:00
|
|
|
visitor->EndVisitExtension(
|
|
|
|
|
ModelVisitor::kVariableUsageLessConstantExtension);
|
2011-07-14 23:37:47 +00:00
|
|
|
}
|
|
|
|
|
|
2020-10-22 23:36:58 +02:00
|
|
|
private:
|
2021-04-01 12:13:35 +02:00
|
|
|
const std::vector<int64_t> capacities_;
|
2020-10-29 14:25:39 +01:00
|
|
|
const std::vector<IntVar*> weights_;
|
2011-05-11 16:07:52 +00:00
|
|
|
};
|
2020-10-22 23:36:58 +02:00
|
|
|
} // namespace
|
2011-05-11 16:07:52 +00:00
|
|
|
|
2010-09-15 12:42:33 +00:00
|
|
|
// ---------- API ----------
|
|
|
|
|
|
|
|
|
|
void Pack::AddWeightedSumLessOrEqualConstantDimension(
|
2021-04-01 12:13:35 +02:00
|
|
|
const std::vector<int64_t>& weights, const std::vector<int64_t>& bounds) {
|
2013-10-10 15:23:20 +00:00
|
|
|
CHECK_EQ(weights.size(), vars_.size());
|
2010-10-13 16:22:18 +00:00
|
|
|
CHECK_EQ(bounds.size(), bins_);
|
2020-10-29 14:25:39 +01:00
|
|
|
Solver* const s = solver();
|
|
|
|
|
Dimension* const dim =
|
2013-10-10 15:23:20 +00:00
|
|
|
s->RevAlloc(new DimensionLessThanConstant(s, this, weights, bounds));
|
2010-09-15 12:42:33 +00:00
|
|
|
dims_.push_back(dim);
|
|
|
|
|
}
|
|
|
|
|
|
2013-01-10 17:01:34 +00:00
|
|
|
void Pack::AddWeightedSumLessOrEqualConstantDimension(
|
2021-04-01 12:13:35 +02:00
|
|
|
Solver::IndexEvaluator1 weights, const std::vector<int64_t>& bounds) {
|
2013-10-10 15:23:20 +00:00
|
|
|
CHECK(weights != nullptr);
|
2013-01-10 17:01:34 +00:00
|
|
|
CHECK_EQ(bounds.size(), bins_);
|
2020-10-29 14:25:39 +01:00
|
|
|
Solver* const s = solver();
|
|
|
|
|
Dimension* const dim = s->RevAlloc(new DimensionSumCallbackLessThanConstant(
|
2013-10-10 15:23:20 +00:00
|
|
|
s, this, weights, vars_.size(), bounds));
|
2013-01-10 17:01:34 +00:00
|
|
|
dims_.push_back(dim);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Pack::AddWeightedSumLessOrEqualConstantDimension(
|
2021-04-01 12:13:35 +02:00
|
|
|
Solver::IndexEvaluator2 weights, const std::vector<int64_t>& bounds) {
|
2013-10-10 15:23:20 +00:00
|
|
|
CHECK(weights != nullptr);
|
2013-01-10 17:01:34 +00:00
|
|
|
CHECK_EQ(bounds.size(), bins_);
|
2020-10-29 14:25:39 +01:00
|
|
|
Solver* const s = solver();
|
|
|
|
|
Dimension* const dim = s->RevAlloc(new DimensionLessThanConstantCallback2(
|
2013-10-10 15:23:20 +00:00
|
|
|
s, this, weights, vars_.size(), bounds));
|
2013-01-10 17:01:34 +00:00
|
|
|
dims_.push_back(dim);
|
|
|
|
|
}
|
|
|
|
|
|
2021-04-01 12:13:35 +02:00
|
|
|
void Pack::AddWeightedSumEqualVarDimension(const std::vector<int64_t>& weights,
|
2020-10-29 14:25:39 +01:00
|
|
|
const std::vector<IntVar*>& loads) {
|
2013-10-10 15:23:20 +00:00
|
|
|
CHECK_EQ(weights.size(), vars_.size());
|
2010-10-13 16:22:18 +00:00
|
|
|
CHECK_EQ(loads.size(), bins_);
|
2020-10-29 14:25:39 +01:00
|
|
|
Solver* const s = solver();
|
|
|
|
|
Dimension* const dim =
|
2013-10-10 15:23:20 +00:00
|
|
|
s->RevAlloc(new DimensionWeightedSumEqVar(s, this, weights, loads));
|
2010-10-13 15:05:40 +00:00
|
|
|
dims_.push_back(dim);
|
|
|
|
|
}
|
|
|
|
|
|
2015-08-13 16:00:54 +02:00
|
|
|
void Pack::AddWeightedSumEqualVarDimension(Solver::IndexEvaluator2 weights,
|
2020-10-29 14:25:39 +01:00
|
|
|
const std::vector<IntVar*>& loads) {
|
2013-10-10 15:23:20 +00:00
|
|
|
CHECK(weights != nullptr);
|
2013-01-10 17:01:34 +00:00
|
|
|
CHECK_EQ(loads.size(), bins_);
|
2020-10-29 14:25:39 +01:00
|
|
|
Solver* const s = solver();
|
|
|
|
|
Dimension* const dim = s->RevAlloc(new DimensionWeightedCallback2SumEqVar(
|
2013-10-10 15:23:20 +00:00
|
|
|
s, this, weights, vars_.size(), loads));
|
2013-01-10 17:01:34 +00:00
|
|
|
dims_.push_back(dim);
|
|
|
|
|
}
|
|
|
|
|
|
2021-04-01 12:13:35 +02:00
|
|
|
void Pack::AddWeightedSumOfAssignedDimension(
|
|
|
|
|
const std::vector<int64_t>& weights, IntVar* const cost_var) {
|
2013-10-10 15:23:20 +00:00
|
|
|
CHECK_EQ(weights.size(), vars_.size());
|
2020-10-29 14:25:39 +01:00
|
|
|
Solver* const s = solver();
|
|
|
|
|
Dimension* const dim = s->RevAlloc(
|
2013-10-10 15:23:20 +00:00
|
|
|
new AssignedWeightedSumDimension(s, this, weights, bins_, cost_var));
|
2010-09-15 12:42:33 +00:00
|
|
|
dims_.push_back(dim);
|
|
|
|
|
}
|
|
|
|
|
|
2011-05-11 16:07:52 +00:00
|
|
|
void Pack::AddSumVariableWeightsLessOrEqualConstantDimension(
|
2021-04-01 12:13:35 +02:00
|
|
|
const std::vector<IntVar*>& usage, const std::vector<int64_t>& capacity) {
|
2013-10-10 15:23:20 +00:00
|
|
|
CHECK_EQ(usage.size(), vars_.size());
|
2011-09-05 13:45:29 +00:00
|
|
|
CHECK_EQ(capacity.size(), bins_);
|
2020-10-29 14:25:39 +01:00
|
|
|
Solver* const s = solver();
|
|
|
|
|
Dimension* const dim =
|
2013-10-10 15:23:20 +00:00
|
|
|
s->RevAlloc(new VariableUsageDimension(s, this, capacity, usage));
|
2011-05-11 16:07:52 +00:00
|
|
|
dims_.push_back(dim);
|
|
|
|
|
}
|
|
|
|
|
|
2020-10-29 14:25:39 +01:00
|
|
|
void Pack::AddCountUsedBinDimension(IntVar* const count_var) {
|
|
|
|
|
Solver* const s = solver();
|
|
|
|
|
Dimension* const dim = s->RevAlloc(
|
2013-10-10 15:23:20 +00:00
|
|
|
new CountUsedBinDimension(s, this, vars_.size(), bins_, count_var));
|
2010-09-15 12:42:33 +00:00
|
|
|
dims_.push_back(dim);
|
|
|
|
|
}
|
|
|
|
|
|
2020-10-29 14:25:39 +01:00
|
|
|
void Pack::AddCountAssignedItemsDimension(IntVar* const count_var) {
|
|
|
|
|
Solver* const s = solver();
|
|
|
|
|
Dimension* const dim = s->RevAlloc(
|
2013-10-10 15:23:20 +00:00
|
|
|
new CountAssignedItemsDimension(s, this, vars_.size(), bins_, count_var));
|
2010-09-15 12:42:33 +00:00
|
|
|
dims_.push_back(dim);
|
|
|
|
|
}
|
|
|
|
|
|
2020-10-29 14:25:39 +01:00
|
|
|
Pack* Solver::MakePack(const std::vector<IntVar*>& vars, int number_of_bins) {
|
2013-10-10 15:23:20 +00:00
|
|
|
return RevAlloc(new Pack(this, vars, number_of_bins));
|
2010-09-15 12:42:33 +00:00
|
|
|
}
|
2020-10-22 23:36:58 +02:00
|
|
|
} // namespace operations_research
|