24#include "absl/strings/str_format.h"
25#include "absl/strings/str_join.h"
38 : solver_(s), pack_(pack) {}
43 const std::vector<int>& undecided) = 0;
45 const std::vector<int>& assigned,
const std::vector<int>& unassigned) = 0;
47 virtual void Propagate(
int bin_index,
const std::vector<int>& forced,
48 const std::vector<int>& removed) = 0;
50 const std::vector<int>& unassigned) = 0;
52 std::string
DebugString()
const override {
return "Dimension"; }
112 bins_(number_of_bins),
120 for (
int i = 0; i < vars_.size(); ++i) {
121 holes_[i] = vars_[i]->MakeHoleIterator(
true);
128 for (
int i = 0; i < vars_.size(); ++i) {
136 for (
int i = 0; i < dims_.size(); ++i) {
144 for (
int bin_index = 0; bin_index <= bins_; ++bin_index) {
145 forced_[bin_index].clear();
146 removed_[bin_index].clear();
155 for (
int i = 0; i < to_set_.size(); ++i) {
156 vars_[to_set_[i].first]->SetValue(to_set_[i].second);
158 for (
int i = 0; i < to_unset_.size(); ++i) {
159 vars_[to_unset_[i].first]->RemoveValue(to_unset_[i].second);
166class InitialPropagateData :
public BaseObject {
168 explicit InitialPropagateData(
size_t num_bins)
170 void PushAssigned(
int index) { assigned_.push_back(
index); }
171 void PushUnassigned(
int index) { unassigned_.push_back(
index); }
172 void PushUndecided(
int bin,
int index) {
173 undecided_.at(bin).push_back(
index);
175 const std::vector<int>& undecided(
int bin)
const {
176 return undecided_.at(bin);
178 const std::vector<int>& assigned()
const {
return assigned_; }
179 const std::vector<int>& unassigned()
const {
return unassigned_; }
181 std::string DebugString()
const override {
return "InitialPropagateData"; }
184 std::vector<std::vector<int>> undecided_;
185 std::vector<int> unassigned_;
186 std::vector<int> assigned_;
195 InitialPropagateData* data = s->
RevAlloc(
new InitialPropagateData(bins_));
198 var->SetRange(0, bins_);
208 DCHECK_GT(bins_,
var->Min())
209 <<
"The variable maximum should be at most " << bins_
210 <<
", and it should be unbound, so its min is expected to be less "
212 if (
var->Max() < bins_) {
215 std::unique_ptr<IntVarIterator> it(
var->MakeDomainIterator(
false));
219 if (
value != bins_) {
226 for (
int bin_index = 0; bin_index < bins_; ++bin_index) {
229 absl::StrFormat(
"Pack(bin %d, forced = [%s], undecided = [%s])",
230 bin_index, absl::StrJoin(forced_[bin_index],
", "),
231 absl::StrJoin(data->undecided(bin_index),
", ")));
234 for (
int dim_index = 0; dim_index < dims_.size(); ++dim_index) {
237 "InitialProgateDimension(%s)", dims_[dim_index]->
DebugString()));
239 dims_[dim_index]->InitialPropagate(bin_index, forced_[bin_index],
240 data->undecided(bin_index));
251 absl::StrFormat(
"Pack(assigned = [%s], unassigned = [%s])",
252 absl::StrJoin(data->assigned(),
", "),
253 absl::StrJoin(data->unassigned(),
", ")));
255 for (
int dim_index = 0; dim_index < dims_.size(); ++dim_index) {
258 "InitialProgateDimension(%s)", dims_[dim_index]->
DebugString()));
260 dims_[dim_index]->InitialPropagateUnassigned(data->assigned(),
262 dims_[dim_index]->EndInitialPropagate();
278 DCHECK_EQ(stamp_,
solver()->fail_stamp());
279 for (
int bin_index = 0; bin_index < bins_; ++bin_index) {
280 if (!removed_[bin_index].empty() || !forced_[bin_index].empty()) {
283 absl::StrFormat(
"Pack(bin %d, forced = [%s], removed = [%s])",
284 bin_index, absl::StrJoin(forced_[bin_index],
", "),
285 absl::StrJoin(removed_[bin_index],
", ")));
288 for (
int dim_index = 0; dim_index < dims_.size(); ++dim_index) {
291 "ProgateDimension(%s)", dims_[dim_index]->
DebugString()));
293 dims_[dim_index]->Propagate(bin_index, forced_[bin_index],
294 removed_[bin_index]);
304 if (!removed_[bins_].empty() || !forced_[bins_].empty()) {
307 absl::StrFormat(
"Pack(removed = [%s], forced = [%s])",
308 absl::StrJoin(removed_[bins_],
", "),
309 absl::StrJoin(forced_[bins_],
", ")));
312 for (
int dim_index = 0; dim_index < dims_.size(); ++dim_index) {
315 "ProgateDimension(%s)", dims_[dim_index]->
DebugString()));
317 dims_[dim_index]->PropagateUnassigned(removed_[bins_], forced_[bins_]);
326 for (
int dim_index = 0; dim_index < dims_.size(); ++dim_index) {
327 dims_[dim_index]->EndPropagate();
338 const uint64_t current_stamp = s->
fail_stamp();
339 if (stamp_ < current_stamp) {
340 stamp_ = current_stamp;
345 const int64_t oldmin =
var->OldMin();
346 const int64_t oldmax =
var->OldMax();
347 const int64_t vmin =
var->Min();
348 const int64_t vmax =
var->Max();
349 for (int64_t
value = std::max(oldmin, int64_t{0});
350 value < std::min(vmin, bins_ + int64_t{1}); ++
value) {
358 if (
value >= std::max(int64_t{0}, vmin) &&
366 for (int64_t
value = std::max(vmax + 1, int64_t{0});
381 std::string result =
"Pack([";
382 for (
int i = 0; i < vars_.size(); ++i) {
383 result += vars_[i]->DebugString() +
" ";
385 result +=
"], dimensions = [";
386 for (
int i = 0; i < dims_.size(); ++i) {
387 result += dims_[i]->DebugString() +
" ";
389 absl::StrAppendFormat(&result,
"], bins = %d)", bins_);
398 for (
int i = 0; i < dims_.size(); ++i) {
399 dims_[i]->Accept(visitor);
405 return unprocessed_->IsSet(bin_index,
var_index);
410 to_unset_.push_back(std::make_pair(
var_index, bin_index));
412 vars_[
var_index]->RemoveValue(bin_index);
418 to_set_.push_back(std::make_pair(
var_index, bin_index));
425 return !unprocessed_->IsSet(bins_,
var_index);
429 return vars_[
var_index]->Contains(bin_index);
438 to_unset_.push_back(std::make_pair(
var_index, bins_));
446 to_set_.push_back(std::make_pair(
var_index, bins_));
452bool Pack::IsInProcess()
const {
457 int var_index = unprocessed_->GetFirstBit(bin_index, 0);
462 : unprocessed_->GetFirstBit(bin_index,
var_index + 1);
467 int var_index = unprocessed_->GetFirstBit(bin_index, 0);
472 : unprocessed_->GetFirstBit(bin_index,
var_index + 1);
477 int var_index = unprocessed_->GetFirstBit(bin_index, 0);
484 int var_index = unprocessed_->GetFirstBit(bins_, 0);
489 : unprocessed_->GetFirstBit(bins_,
var_index + 1);
494 int var_index = unprocessed_->GetFirstBit(bins_, 0);
499 : unprocessed_->GetFirstBit(bins_,
var_index + 1);
508struct WeightContainer {
512 bool operator<(
const WeightContainer& c)
const {
return (weight <
c.weight); }
515void SortWeightVector(std::vector<int>*
const indices,
516 std::vector<WeightContainer>*
const to_sort) {
517 std::sort(to_sort->begin(), to_sort->end());
521 indices->resize(to_sort->size());
524void SortIndexByWeight(std::vector<int>*
const indices,
525 const std::vector<int64_t>& weights) {
526 std::vector<WeightContainer> to_sort;
528 if (weights[
index] != 0) {
529 to_sort.push_back(WeightContainer((*indices)[
index], weights[
index]));
532 SortWeightVector(indices, &to_sort);
535void SortIndexByWeight(std::vector<int>*
const indices,
537 std::vector<WeightContainer> to_sort;
539 const int w = weights(
index);
541 to_sort.push_back(WeightContainer((*indices)[
index],
w));
544 SortWeightVector(indices, &to_sort);
547void SortIndexByWeight(std::vector<int>*
const indices,
549 std::vector<WeightContainer> to_sort;
551 const int w = weights(
index, bin_index);
553 to_sort.push_back(WeightContainer((*indices)[
index],
w));
556 SortWeightVector(indices, &to_sort);
559class DimensionLessThanConstant :
public Dimension {
561 DimensionLessThanConstant(Solver*
const s, Pack*
const p,
562 const std::vector<int64_t>& weights,
565 vars_count_(weights.
size()),
569 first_unbound_backward_vector_(bins_count_, 0),
570 sum_of_bound_variables_vector_(bins_count_, 0LL),
571 ranked_(vars_count_) {
572 for (
int i = 0;
i < vars_count_; ++
i) {
575 SortIndexByWeight(&ranked_, weights_);
578 ~DimensionLessThanConstant()
override {}
580 void Post()
override {}
582 void PushFromTop(
int bin_index) {
583 const int64_t slack =
584 upper_bounds_[bin_index] - sum_of_bound_variables_vector_[bin_index];
588 int last_unbound = first_unbound_backward_vector_[bin_index];
589 for (; last_unbound >= 0; --last_unbound) {
590 const int var_index = ranked_[last_unbound];
599 first_unbound_backward_vector_.SetValue(solver(), bin_index, last_unbound);
602 void InitialPropagate(
int bin_index,
const std::vector<int>& forced,
603 const std::vector<int>& undecided)
override {
604 Solver*
const s = solver();
606 for (
const int value : forced) {
607 sum += weights_[
value];
609 sum_of_bound_variables_vector_.SetValue(s, bin_index, sum);
610 first_unbound_backward_vector_.SetValue(s, bin_index, ranked_.size() - 1);
611 PushFromTop(bin_index);
614 void EndInitialPropagate()
override {}
616 void Propagate(
int bin_index,
const std::vector<int>& forced,
617 const std::vector<int>& removed)
override {
618 if (!forced.empty()) {
619 Solver*
const s = solver();
620 int64_t sum = sum_of_bound_variables_vector_[bin_index];
621 for (
const int value : forced) {
622 sum += weights_[
value];
624 sum_of_bound_variables_vector_.SetValue(s, bin_index, sum);
625 PushFromTop(bin_index);
628 void InitialPropagateUnassigned(
const std::vector<int>& assigned,
629 const std::vector<int>& unassigned)
override {
631 void PropagateUnassigned(
const std::vector<int>& assigned,
632 const std::vector<int>& unassigned)
override {}
634 void EndPropagate()
override {}
636 void Accept(ModelVisitor*
const visitor)
const override {
646 const int vars_count_;
647 const std::vector<int64_t> weights_;
648 const int bins_count_;
649 const std::vector<int64_t> upper_bounds_;
650 RevArray<int> first_unbound_backward_vector_;
651 RevArray<int64_t> sum_of_bound_variables_vector_;
652 std::vector<int> ranked_;
655class DimensionSumCallbackLessThanConstant :
public Dimension {
657 DimensionSumCallbackLessThanConstant(Solver*
const s, Pack*
const p,
662 vars_count_(vars_count),
666 first_unbound_backward_vector_(bins_count_, 0),
667 sum_of_bound_variables_vector_(bins_count_, 0LL),
668 ranked_(vars_count_) {
670 DCHECK_GT(vars_count, 0);
671 for (
int i = 0;
i < vars_count_; ++
i) {
674 SortIndexByWeight(&ranked_, weights_);
677 ~DimensionSumCallbackLessThanConstant()
override {}
679 void Post()
override {}
681 void PushFromTop(
int bin_index) {
682 const int64_t slack =
683 upper_bounds_[bin_index] - sum_of_bound_variables_vector_[bin_index];
687 int last_unbound = first_unbound_backward_vector_[bin_index];
688 for (; last_unbound >= 0; --last_unbound) {
689 const int var_index = ranked_[last_unbound];
698 first_unbound_backward_vector_.SetValue(solver(), bin_index, last_unbound);
701 void InitialPropagate(
int bin_index,
const std::vector<int>& forced,
702 const std::vector<int>& undecided)
override {
703 Solver*
const s = solver();
705 for (
const int value : forced) {
706 sum += weights_(
value);
708 sum_of_bound_variables_vector_.SetValue(s, bin_index, sum);
709 first_unbound_backward_vector_.SetValue(s, bin_index, ranked_.size() - 1);
710 PushFromTop(bin_index);
713 void EndInitialPropagate()
override {}
715 void Propagate(
int bin_index,
const std::vector<int>& forced,
716 const std::vector<int>& removed)
override {
717 if (!forced.empty()) {
718 Solver*
const s = solver();
719 int64_t sum = sum_of_bound_variables_vector_[bin_index];
720 for (
const int value : forced) {
721 sum += weights_(
value);
723 sum_of_bound_variables_vector_.SetValue(s, bin_index, sum);
724 PushFromTop(bin_index);
727 void InitialPropagateUnassigned(
const std::vector<int>& assigned,
728 const std::vector<int>& unassigned)
override {
730 void PropagateUnassigned(
const std::vector<int>& assigned,
731 const std::vector<int>& unassigned)
override {}
733 void EndPropagate()
override {}
735 void Accept(ModelVisitor*
const visitor)
const override {
746 const int vars_count_;
748 const int bins_count_;
749 const std::vector<int64_t> upper_bounds_;
750 RevArray<int> first_unbound_backward_vector_;
751 RevArray<int64_t> sum_of_bound_variables_vector_;
752 std::vector<int> ranked_;
755class DimensionLessThanConstantCallback2 :
public Dimension {
757 DimensionLessThanConstantCallback2(Solver*
const s, Pack*
const p,
762 vars_count_(vars_count),
766 first_unbound_backward_vector_(bins_count_, 0),
767 sum_of_bound_variables_vector_(bins_count_, 0LL),
768 ranked_(bins_count_) {
770 DCHECK_GT(vars_count, 0);
771 for (
int b = 0;
b < bins_count_; ++
b) {
772 ranked_[
b].resize(vars_count);
773 for (
int i = 0;
i < vars_count_; ++
i) {
776 SortIndexByWeight(&ranked_[
b], weights_,
b);
780 ~DimensionLessThanConstantCallback2()
override {}
782 void Post()
override {}
784 void PushFromTop(
int bin_index) {
785 const int64_t slack =
786 upper_bounds_[bin_index] - sum_of_bound_variables_vector_[bin_index];
790 int last_unbound = first_unbound_backward_vector_[bin_index];
791 for (; last_unbound >= 0; --last_unbound) {
792 const int var_index = ranked_[bin_index][last_unbound];
794 if (weights_(
var_index, bin_index) > slack) {
801 first_unbound_backward_vector_.SetValue(solver(), bin_index, last_unbound);
804 void InitialPropagate(
int bin_index,
const std::vector<int>& forced,
805 const std::vector<int>& undecided)
override {
806 Solver*
const s = solver();
808 for (
const int value : forced) {
809 sum += weights_(
value, bin_index);
811 sum_of_bound_variables_vector_.SetValue(s, bin_index, sum);
812 first_unbound_backward_vector_.SetValue(s, bin_index,
813 ranked_[bin_index].
size() - 1);
814 PushFromTop(bin_index);
817 void EndInitialPropagate()
override {}
819 void Propagate(
int bin_index,
const std::vector<int>& forced,
820 const std::vector<int>& removed)
override {
821 if (!forced.empty()) {
822 Solver*
const s = solver();
823 int64_t sum = sum_of_bound_variables_vector_[bin_index];
824 for (
const int value : forced) {
825 sum += weights_(
value, bin_index);
827 sum_of_bound_variables_vector_.SetValue(s, bin_index, sum);
828 PushFromTop(bin_index);
831 void InitialPropagateUnassigned(
const std::vector<int>& assigned,
832 const std::vector<int>& unassigned)
override {
834 void PropagateUnassigned(
const std::vector<int>& assigned,
835 const std::vector<int>& unassigned)
override {}
837 void EndPropagate()
override {}
839 void Accept(ModelVisitor*
const visitor)
const override {
850 const int vars_count_;
852 const int bins_count_;
853 const std::vector<int64_t> upper_bounds_;
854 RevArray<int> first_unbound_backward_vector_;
855 RevArray<int64_t> sum_of_bound_variables_vector_;
856 std::vector<std::vector<int>> ranked_;
859class DimensionWeightedSumEqVar :
public Dimension {
861 class VarDemon :
public Demon {
863 VarDemon(DimensionWeightedSumEqVar*
const dim,
int index)
864 : dim_(dim), index_(
index) {}
865 ~VarDemon()
override {}
867 void Run(Solver*
const s)
override { dim_->PushFromTop(index_); }
870 DimensionWeightedSumEqVar*
const dim_;
874 DimensionWeightedSumEqVar(Solver*
const s, Pack*
const p,
875 const std::vector<int64_t>& weights,
876 const std::vector<IntVar*>& loads)
878 vars_count_(weights.
size()),
880 bins_count_(loads.
size()),
882 first_unbound_backward_vector_(bins_count_, 0),
883 sum_of_bound_variables_vector_(bins_count_, 0LL),
884 sum_of_all_variables_vector_(bins_count_, 0LL),
885 ranked_(vars_count_) {
886 DCHECK_GT(vars_count_, 0);
887 DCHECK_GT(bins_count_, 0);
888 for (
int i = 0;
i < vars_count_; ++
i) {
891 SortIndexByWeight(&ranked_, weights_);
894 ~DimensionWeightedSumEqVar()
override {}
896 std::string DebugString()
const override {
897 return "DimensionWeightedSumEqVar";
900 void Post()
override {
901 for (
int i = 0;
i < bins_count_; ++
i) {
902 Demon*
const d = solver()->RevAlloc(
new VarDemon(
this, i));
903 loads_[
i]->WhenRange(d);
907 void PushFromTop(
int bin_index) {
908 IntVar*
const load = loads_[bin_index];
909 const int64_t sum_min = sum_of_bound_variables_vector_[bin_index];
910 const int64_t sum_max = sum_of_all_variables_vector_[bin_index];
911 load->SetRange(sum_min, sum_max);
912 const int64_t slack_up = load->Max() - sum_min;
913 const int64_t slack_down = sum_max - load->Min();
914 DCHECK_GE(slack_down, 0);
915 DCHECK_GE(slack_up, 0);
916 int last_unbound = first_unbound_backward_vector_[bin_index];
917 for (; last_unbound >= 0; --last_unbound) {
918 const int var_index = ranked_[last_unbound];
923 }
else if (
weight > slack_down) {
930 first_unbound_backward_vector_.SetValue(solver(), bin_index, last_unbound);
933 void InitialPropagate(
int bin_index,
const std::vector<int>& forced,
934 const std::vector<int>& undecided)
override {
935 Solver*
const s = solver();
937 for (
const int value : forced) {
938 sum += weights_[
value];
940 sum_of_bound_variables_vector_.SetValue(s, bin_index, sum);
941 for (
const int value : undecided) {
942 sum += weights_[
value];
944 sum_of_all_variables_vector_.SetValue(s, bin_index, sum);
945 first_unbound_backward_vector_.SetValue(s, bin_index, ranked_.size() - 1);
946 PushFromTop(bin_index);
949 void EndInitialPropagate()
override {}
951 void Propagate(
int bin_index,
const std::vector<int>& forced,
952 const std::vector<int>& removed)
override {
953 Solver*
const s = solver();
954 int64_t down = sum_of_bound_variables_vector_[bin_index];
955 for (
const int value : forced) {
956 down += weights_[
value];
958 sum_of_bound_variables_vector_.SetValue(s, bin_index, down);
959 int64_t up = sum_of_all_variables_vector_[bin_index];
960 for (
const int value : removed) {
961 up -= weights_[
value];
963 sum_of_all_variables_vector_.SetValue(s, bin_index, up);
964 PushFromTop(bin_index);
966 void InitialPropagateUnassigned(
const std::vector<int>& assigned,
967 const std::vector<int>& unassigned)
override {
969 void PropagateUnassigned(
const std::vector<int>& assigned,
970 const std::vector<int>& unassigned)
override {}
972 void EndPropagate()
override {}
974 void Accept(ModelVisitor*
const visitor)
const override {
984 const int vars_count_;
985 const std::vector<int64_t> weights_;
986 const int bins_count_;
987 const std::vector<IntVar*> loads_;
988 RevArray<int> first_unbound_backward_vector_;
989 RevArray<int64_t> sum_of_bound_variables_vector_;
990 RevArray<int64_t> sum_of_all_variables_vector_;
991 std::vector<int> ranked_;
994class DimensionWeightedCallback2SumEqVar :
public Dimension {
996 class VarDemon :
public Demon {
998 VarDemon(DimensionWeightedCallback2SumEqVar*
const dim,
int index)
999 : dim_(dim), index_(
index) {}
1000 ~VarDemon()
override {}
1002 void Run(Solver*
const s)
override { dim_->PushFromTop(index_); }
1005 DimensionWeightedCallback2SumEqVar*
const dim_;
1009 DimensionWeightedCallback2SumEqVar(Solver*
const s, Pack*
const p,
1012 const std::vector<IntVar*>& loads)
1014 vars_count_(vars_count),
1016 bins_count_(loads.
size()),
1018 first_unbound_backward_vector_(bins_count_, 0),
1019 sum_of_bound_variables_vector_(bins_count_, 0LL),
1020 sum_of_all_variables_vector_(bins_count_, 0LL),
1021 ranked_(bins_count_) {
1023 DCHECK_GT(vars_count_, 0);
1024 DCHECK_GT(bins_count_, 0);
1025 for (
int b = 0;
b < bins_count_; ++
b) {
1026 ranked_[
b].resize(vars_count);
1027 for (
int i = 0;
i < vars_count_; ++
i) {
1030 SortIndexByWeight(&ranked_[
b], weights_,
b);
1034 ~DimensionWeightedCallback2SumEqVar()
override {}
1036 std::string DebugString()
const override {
1037 return "DimensionWeightedCallback2SumEqVar";
1040 void Post()
override {
1041 for (
int i = 0;
i < bins_count_; ++
i) {
1042 Demon*
const d = solver()->RevAlloc(
new VarDemon(
this, i));
1043 loads_[
i]->WhenRange(d);
1047 void PushFromTop(
int bin_index) {
1048 IntVar*
const load = loads_[bin_index];
1049 const int64_t sum_min = sum_of_bound_variables_vector_[bin_index];
1050 const int64_t sum_max = sum_of_all_variables_vector_[bin_index];
1051 load->SetRange(sum_min, sum_max);
1052 const int64_t slack_up = load->Max() - sum_min;
1053 const int64_t slack_down = sum_max - load->Min();
1054 DCHECK_GE(slack_down, 0);
1055 DCHECK_GE(slack_up, 0);
1056 int last_unbound = first_unbound_backward_vector_[bin_index];
1057 for (; last_unbound >= 0; --last_unbound) {
1058 const int var_index = ranked_[bin_index][last_unbound];
1060 if (IsUndecided(
var_index, bin_index)) {
1063 }
else if (
weight > slack_down) {
1070 first_unbound_backward_vector_.SetValue(solver(), bin_index, last_unbound);
1073 void InitialPropagate(
int bin_index,
const std::vector<int>& forced,
1074 const std::vector<int>& undecided)
override {
1075 Solver*
const s = solver();
1077 for (
const int value : forced) {
1078 sum += weights_(
value, bin_index);
1080 sum_of_bound_variables_vector_.SetValue(s, bin_index, sum);
1081 for (
const int value : undecided) {
1082 sum += weights_(
value, bin_index);
1084 sum_of_all_variables_vector_.SetValue(s, bin_index, sum);
1085 first_unbound_backward_vector_.SetValue(s, bin_index,
1086 ranked_[bin_index].
size() - 1);
1087 PushFromTop(bin_index);
1090 void EndInitialPropagate()
override {}
1092 void Propagate(
int bin_index,
const std::vector<int>& forced,
1093 const std::vector<int>& removed)
override {
1094 Solver*
const s = solver();
1095 int64_t down = sum_of_bound_variables_vector_[bin_index];
1096 for (
const int value : forced) {
1097 down += weights_(
value, bin_index);
1099 sum_of_bound_variables_vector_.SetValue(s, bin_index, down);
1100 int64_t up = sum_of_all_variables_vector_[bin_index];
1101 for (
const int value : removed) {
1102 up -= weights_(
value, bin_index);
1104 sum_of_all_variables_vector_.SetValue(s, bin_index, up);
1105 PushFromTop(bin_index);
1107 void InitialPropagateUnassigned(
const std::vector<int>& assigned,
1108 const std::vector<int>& unassigned)
override {
1110 void PropagateUnassigned(
const std::vector<int>& assigned,
1111 const std::vector<int>& unassigned)
override {}
1113 void EndPropagate()
override {}
1115 void Accept(ModelVisitor*
const visitor)
const override {
1126 const int vars_count_;
1128 const int bins_count_;
1129 const std::vector<IntVar*> loads_;
1130 RevArray<int> first_unbound_backward_vector_;
1131 RevArray<int64_t> sum_of_bound_variables_vector_;
1132 RevArray<int64_t> sum_of_all_variables_vector_;
1133 std::vector<std::vector<int>> ranked_;
1136class AssignedWeightedSumDimension :
public Dimension {
1138 class VarDemon :
public Demon {
1140 explicit VarDemon(AssignedWeightedSumDimension*
const dim) : dim_(dim) {}
1141 ~VarDemon()
override {}
1143 void Run(Solver*
const s)
override { dim_->PropagateAll(); }
1146 AssignedWeightedSumDimension*
const dim_;
1149 AssignedWeightedSumDimension(Solver*
const s, Pack*
const p,
1150 const std::vector<int64_t>& weights,
1151 int bins_count, IntVar*
const cost_var)
1153 vars_count_(weights.
size()),
1155 bins_count_(bins_count),
1156 cost_var_(cost_var),
1157 first_unbound_backward_(0),
1158 sum_of_assigned_items_(0LL),
1159 sum_of_unassigned_items_(0LL),
1160 ranked_(vars_count_),
1161 sum_all_weights_(0LL) {
1163 DCHECK_GT(vars_count_, 0);
1164 DCHECK_GT(bins_count_, 0);
1165 for (
int i = 0;
i < vars_count_; ++
i) {
1168 SortIndexByWeight(&ranked_, weights_);
1169 first_unbound_backward_.SetValue(s, ranked_.size() - 1);
1172 ~AssignedWeightedSumDimension()
override {}
1174 void Post()
override {
1175 Demon*
const uv = solver()->RevAlloc(
new VarDemon(
this));
1176 cost_var_->WhenRange(uv);
1179 void PropagateAll() {
1180 cost_var_->SetRange(sum_of_assigned_items_.Value(),
1181 sum_all_weights_ - sum_of_unassigned_items_.Value());
1182 const int64_t slack_up = cost_var_->Max() - sum_of_assigned_items_.Value();
1183 const int64_t slack_down = sum_all_weights_ - cost_var_->Min();
1184 int last_unbound = first_unbound_backward_.Value();
1185 for (; last_unbound >= 0; --last_unbound) {
1186 const int var_index = ranked_[last_unbound];
1187 if (!IsAssignedStatusKnown(
var_index)) {
1198 first_unbound_backward_.SetValue(solver(), last_unbound);
1201 void InitialPropagate(
int bin_index,
const std::vector<int>& forced,
1202 const std::vector<int>& undecided)
override {}
1204 void EndInitialPropagate()
override {}
1206 void InitialPropagateUnassigned(
const std::vector<int>& assigned,
1207 const std::vector<int>& unassigned)
override {
1209 sum_all_weights_ += weights_[
index];
1212 PropagateUnassigned(assigned, unassigned);
1215 void Propagate(
int bin_index,
const std::vector<int>& forced,
1216 const std::vector<int>& removed)
override {}
1218 void PropagateUnassigned(
const std::vector<int>& assigned,
1219 const std::vector<int>& unassigned)
override {
1220 int64_t sum_assigned = sum_of_assigned_items_.Value();
1226 int64_t sum_unassigned = sum_of_unassigned_items_.Value();
1232 Solver*
const s = solver();
1233 sum_of_assigned_items_.SetValue(s, sum_assigned);
1234 sum_of_unassigned_items_.SetValue(s, sum_unassigned);
1238 void EndPropagate()
override {}
1240 void Accept(ModelVisitor*
const visitor)
const override {
1241 visitor->BeginVisitExtension(
1247 visitor->EndVisitExtension(
1252 const int vars_count_;
1253 const std::vector<int64_t> weights_;
1254 const int bins_count_;
1255 IntVar*
const cost_var_;
1256 Rev<int> first_unbound_backward_;
1257 Rev<int64_t> sum_of_assigned_items_;
1258 Rev<int64_t> sum_of_unassigned_items_;
1259 std::vector<int> ranked_;
1260 int64_t sum_all_weights_;
1265class CountAssignedItemsDimension :
public Dimension {
1267 class VarDemon :
public Demon {
1269 explicit VarDemon(CountAssignedItemsDimension*
const dim) : dim_(dim) {}
1270 ~VarDemon()
override {}
1272 void Run(Solver*
const s)
override { dim_->PropagateAll(); }
1275 CountAssignedItemsDimension*
const dim_;
1278 CountAssignedItemsDimension(Solver*
const s, Pack*
const p,
int vars_count,
1279 int bins_count, IntVar*
const cost_var)
1281 vars_count_(vars_count),
1282 bins_count_(bins_count),
1283 cost_var_(cost_var),
1284 first_unbound_backward_(0),
1286 unassigned_count_(0) {
1288 DCHECK_GT(vars_count, 0);
1289 DCHECK_GT(bins_count, 0);
1292 ~CountAssignedItemsDimension()
override {}
1294 void Post()
override {
1295 Demon*
const uv = solver()->RevAlloc(
new VarDemon(
this));
1296 cost_var_->WhenRange(uv);
1299 void PropagateAll() {
1300 cost_var_->SetRange(assigned_count_.Value(),
1301 vars_count_ - unassigned_count_.Value());
1302 if (assigned_count_.Value() == cost_var_->Max()) {
1303 UnassignAllRemainingItems();
1304 }
else if (cost_var_->Min() == vars_count_ - unassigned_count_.Value()) {
1305 AssignAllRemainingItems();
1309 void InitialPropagate(
int bin_index,
const std::vector<int>& forced,
1310 const std::vector<int>& undecided)
override {}
1312 void EndInitialPropagate()
override {}
1314 void InitialPropagateUnassigned(
const std::vector<int>& assigned,
1315 const std::vector<int>& unassigned)
override {
1316 PropagateUnassigned(assigned, unassigned);
1319 void Propagate(
int bin_index,
const std::vector<int>& forced,
1320 const std::vector<int>& removed)
override {}
1322 void PropagateUnassigned(
const std::vector<int>& assigned,
1323 const std::vector<int>& unassigned)
override {
1324 Solver*
const s = solver();
1325 assigned_count_.SetValue(s, assigned_count_.Value() + assigned.size());
1326 unassigned_count_.SetValue(s,
1327 unassigned_count_.Value() + unassigned.size());
1331 void EndPropagate()
override {}
1333 void Accept(ModelVisitor*
const visitor)
const override {
1341 const int vars_count_;
1342 const int bins_count_;
1343 IntVar*
const cost_var_;
1344 Rev<int> first_unbound_backward_;
1345 Rev<int> assigned_count_;
1346 Rev<int> unassigned_count_;
1351class CountUsedBinDimension :
public Dimension {
1353 class VarDemon :
public Demon {
1355 explicit VarDemon(CountUsedBinDimension*
const dim) : dim_(dim) {}
1356 ~VarDemon()
override {}
1358 void Run(Solver*
const s)
override { dim_->PropagateAll(); }
1361 CountUsedBinDimension*
const dim_;
1364 CountUsedBinDimension(Solver*
const s, Pack*
const p,
int vars_count,
1365 int bins_count, IntVar*
const count_var)
1367 vars_count_(vars_count),
1368 bins_count_(bins_count),
1369 count_var_(count_var),
1371 candidates_(bins_count_, 0),
1373 card_max_(bins_count_),
1377 DCHECK_GT(vars_count, 0);
1378 DCHECK_GT(bins_count, 0);
1381 ~CountUsedBinDimension()
override {}
1383 void Post()
override {
1384 Demon*
const uv = solver()->RevAlloc(
new VarDemon(
this));
1385 count_var_->WhenRange(uv);
1387 initial_max_ = bins_count_;
1390 void PropagateAll() {
1391 count_var_->SetRange(card_min_.Value(), card_max_.Value());
1392 if (card_min_.Value() == count_var_->Max()) {
1393 for (
int bin_index = 0; bin_index < bins_count_; ++bin_index) {
1394 if (!used_.IsSet(bin_index) && candidates_[bin_index] > 0) {
1395 RemoveAllPossibleFromBin(bin_index);
1398 }
else if (card_max_.Value() == count_var_->Min()) {
1399 for (
int bin_index = 0; bin_index < bins_count_; ++bin_index) {
1400 if (candidates_[bin_index] == 1) {
1401 AssignFirstPossibleToBin(bin_index);
1407 void InitialPropagate(
int bin_index,
const std::vector<int>& forced,
1408 const std::vector<int>& undecided)
override {
1409 if (!forced.empty()) {
1410 used_.SetToOne(solver(), bin_index);
1412 }
else if (!undecided.empty()) {
1413 candidates_.SetValue(solver(), bin_index, undecided.size());
1419 void EndInitialPropagate()
override {
1420 card_min_.SetValue(solver(), initial_min_);
1421 card_max_.SetValue(solver(), initial_max_);
1425 void InitialPropagateUnassigned(
const std::vector<int>& assigned,
1426 const std::vector<int>& unassigned)
override {
1429 void Propagate(
int bin_index,
const std::vector<int>& forced,
1430 const std::vector<int>& removed)
override {
1431 if (!used_.IsSet(bin_index)) {
1432 if (!forced.empty()) {
1433 used_.SetToOne(solver(), bin_index);
1434 card_min_.SetValue(solver(), card_min_.Value() + 1);
1435 }
else if (!removed.empty()) {
1436 candidates_.SetValue(solver(), bin_index,
1437 candidates_.Value(bin_index) - removed.size());
1438 if (candidates_[bin_index] == 0) {
1439 card_max_.SetValue(solver(), card_max_.Value() - 1);
1445 void PropagateUnassigned(
const std::vector<int>& assigned,
1446 const std::vector<int>& unassigned)
override {}
1448 void EndPropagate()
override { PropagateAll(); }
1450 void Accept(ModelVisitor*
const visitor)
const override {
1458 const int vars_count_;
1459 const int bins_count_;
1460 IntVar*
const count_var_;
1462 RevArray<int> candidates_;
1472class VariableUsageDimension :
public Dimension {
1474 VariableUsageDimension(Solver*
const solver, Pack*
const pack,
1475 const std::vector<int64_t>& capacities,
1476 const std::vector<IntVar*>& weights)
1477 : Dimension(solver, pack), capacities_(capacities), weights_(weights) {}
1479 ~VariableUsageDimension()
override {}
1481 void Post()
override {
1482 Solver*
const s = solver();
1483 const int num_bins = capacities_.size();
1484 const int num_items = weights_.size();
1486 for (
int bin_index = 0; bin_index < num_bins; ++bin_index) {
1487 std::vector<IntVar*> terms;
1488 for (
int item_index = 0; item_index < num_items; ++item_index) {
1489 IntVar*
const assign_var = AssignVar(item_index, bin_index);
1490 terms.push_back(s->MakeProd(assign_var, weights_[item_index])->Var());
1492 s->AddConstraint(s->MakeSumLessOrEqual(terms, capacities_[bin_index]));
1496 void InitialPropagate(
int bin_index,
const std::vector<int>& forced,
1497 const std::vector<int>& undecided)
override {}
1498 void InitialPropagateUnassigned(
const std::vector<int>& assigned,
1499 const std::vector<int>& unassigned)
override {
1501 void EndInitialPropagate()
override {}
1502 void Propagate(
int bin_index,
const std::vector<int>& forced,
1503 const std::vector<int>& removed)
override {}
1504 void PropagateUnassigned(
const std::vector<int>& assigned,
1505 const std::vector<int>& unassigned)
override {}
1506 void EndPropagate()
override {}
1508 std::string DebugString()
const override {
return "VariableUsageDimension"; }
1510 void Accept(ModelVisitor*
const visitor)
const override {
1511 visitor->BeginVisitExtension(
1517 visitor->EndVisitExtension(
1522 const std::vector<int64_t> capacities_;
1523 const std::vector<IntVar*> weights_;
1530 const std::vector<int64_t>& weights,
const std::vector<int64_t>& bounds) {
1531 CHECK_EQ(weights.size(), vars_.size());
1532 CHECK_EQ(bounds.size(), bins_);
1535 s->
RevAlloc(
new DimensionLessThanConstant(s,
this, weights, bounds));
1536 dims_.push_back(dim);
1541 CHECK(weights !=
nullptr);
1542 CHECK_EQ(bounds.size(), bins_);
1545 s,
this, weights, vars_.size(), bounds));
1546 dims_.push_back(dim);
1551 CHECK(weights !=
nullptr);
1552 CHECK_EQ(bounds.size(), bins_);
1555 s,
this, weights, vars_.size(), bounds));
1556 dims_.push_back(dim);
1560 const std::vector<IntVar*>& loads) {
1561 CHECK_EQ(weights.size(), vars_.size());
1562 CHECK_EQ(loads.size(), bins_);
1565 s->
RevAlloc(
new DimensionWeightedSumEqVar(s,
this, weights, loads));
1566 dims_.push_back(dim);
1570 const std::vector<IntVar*>& loads) {
1571 CHECK(weights !=
nullptr);
1572 CHECK_EQ(loads.size(), bins_);
1575 s,
this, weights, vars_.size(), loads));
1576 dims_.push_back(dim);
1580 const std::vector<int64_t>& weights,
IntVar*
const cost_var) {
1581 CHECK_EQ(weights.size(), vars_.size());
1584 new AssignedWeightedSumDimension(s,
this, weights, bins_, cost_var));
1585 dims_.push_back(dim);
1589 const std::vector<IntVar*>& usage,
const std::vector<int64_t>& capacity) {
1590 CHECK_EQ(usage.size(), vars_.size());
1591 CHECK_EQ(capacity.size(), bins_);
1594 s->
RevAlloc(
new VariableUsageDimension(s,
this, capacity, usage));
1595 dims_.push_back(dim);
1601 new CountUsedBinDimension(s,
this, vars_.size(), bins_, count_var));
1602 dims_.push_back(dim);
1608 new CountAssignedItemsDimension(s,
this, vars_.size(), bins_, count_var));
1609 dims_.push_back(dim);
const std::vector< IntVar * > vars_
-------— Dimension -------—
void SetUnassigned(int var_index)
void AssignAllRemainingItems()
void SetAssigned(int var_index)
virtual void EndInitialPropagate()=0
bool IsPossible(int var_index, int bin_index) const
virtual void EndPropagate()=0
void AssignFirstPossibleToBin(int bin_index)
void UnassignAllRemainingItems()
void SetImpossible(int var_index, int bin_index)
void AssignAllPossibleToBin(int bin_index)
bool IsUndecided(int var_index, int bin_index) const
std::string DebugString() const override
virtual void PropagateUnassigned(const std::vector< int > &assigned, const std::vector< int > &unassigned)=0
virtual void Propagate(int bin_index, const std::vector< int > &forced, const std::vector< int > &removed)=0
virtual void InitialPropagate(int bin_index, const std::vector< int > &forced, const std::vector< int > &undecided)=0
void RemoveAllPossibleFromBin(int bin_index)
IntVar * AssignVar(int var_index, int bin_index) const
void Assign(int var_index, int bin_index)
virtual void Accept(ModelVisitor *visitor) const =0
bool IsAssignedStatusKnown(int var_index) const
virtual void InitialPropagateUnassigned(const std::vector< int > &assigned, const std::vector< int > &unassigned)=0
Dimension(Solver *const s, Pack *const pack)
static const char kVariableUsageLessConstantExtension[]
virtual void VisitIntegerArgument(const std::string &arg_name, int64_t value)
Visit integer arguments.
static const char kCoefficientsArgument[]
static const char kTargetArgument[]
static const char kSizeArgument[]
virtual void VisitIntegerVariableArrayArgument(const std::string &arg_name, const std::vector< IntVar * > &arguments)
static const char kValuesArgument[]
static const char kPack[]
static const char kUsageLessConstantExtension[]
static const char kVarsArgument[]
virtual void BeginVisitConstraint(const std::string &type_name, const Constraint *constraint)
static const char kUsageEqualVariableExtension[]
static const char kCountAssignedItemsExtension[]
Extension names:
static const char kCountUsedBinsExtension[]
static const char kWeightedSumOfAssignedEqualVariableExtension[]
virtual void EndVisitConstraint(const std::string &type_name, const Constraint *constraint)
void SetUnassigned(int var_index)
void SetAssigned(int var_index)
void Assign(int var_index, int bin_index)
bool IsPossible(int var_index, int bin_index) const
void AddCountUsedBinDimension(IntVar *count_var)
Pack(Solver *s, const std::vector< IntVar * > &vars, int number_of_bins)
--— Pack --—
void AddWeightedSumLessOrEqualConstantDimension(const std::vector< int64_t > &weights, const std::vector< int64_t > &bounds)
-------— API -------—
void AddSumVariableWeightsLessOrEqualConstantDimension(const std::vector< IntVar * > &usage, const std::vector< int64_t > &capacity)
void AddCountAssignedItemsDimension(IntVar *count_var)
void UnassignAllRemainingItems()
void AssignAllRemainingItems()
std::string DebugString() const override
--------------— Constraint class ----------------—
void AssignAllPossibleToBin(int bin_index)
void Accept(ModelVisitor *visitor) const override
Accepts the given visitor.
IntVar * AssignVar(int var_index, int bin_index) const
bool IsAssignedStatusKnown(int var_index) const
void AssignFirstPossibleToBin(int bin_index)
void AddWeightedSumEqualVarDimension(const std::vector< int64_t > &weights, const std::vector< IntVar * > &loads)
void RemoveAllPossibleFromBin(int bin_index)
void AddWeightedSumOfAssignedDimension(const std::vector< int64_t > &weights, IntVar *cost_var)
void InitialPropagate() override
void SetImpossible(int var_index, int bin_index)
void OneDomain(int var_index)
bool IsUndecided(int var_index, int bin_index) const
void EnqueueDelayedDemon(Demon *const d)
virtual void PopContext()=0
virtual void PushContext(const std::string &context)=0
Matrix version of the RevBitSet class.
For the time being, Solver is neither MT_SAFE nor MT_HOT.
Demon * RegisterDemon(Demon *demon)
Adds a new demon and wraps it inside a DemonProfiler if necessary.
uint64_t fail_stamp() const
The fail_stamp() is incremented after each backtrack.
IntVar * MakeIsEqualCstVar(IntExpr *var, int64_t value)
status var of (var == value)
Pack * MakePack(const std::vector< IntVar * > &vars, int number_of_bins)
std::function< int64_t(int64_t)> IndexEvaluator1
Callback typedefs.
std::function< int64_t(int64_t, int64_t)> IndexEvaluator2
PropagationMonitor * GetPropagationMonitor() const
Returns the propagation monitor.
bool InstrumentsVariables() const
Returns whether we are tracing variables.
In SWIG mode, we don't want anything besides these top-level includes.
Demon * MakeDelayedConstraintDemon0(Solver *const s, T *const ct, void(T::*method)(), const std::string &name)
Demon * MakeConstraintDemon1(Solver *const s, T *const ct, void(T::*method)(P), const std::string &name, P param1)
trees with all degrees equal w the current value of w
std::vector< double > upper_bounds