25 ABSL_FLAG(
bool, cp_disable_cache,
false,
"Disable caching of model objects");
40 bool IsEqual(
const T& a1,
const T& a2) {
45 bool IsEqual(
const std::vector<T*>& a1,
const std::vector<T*>& a2) {
46 if (a1.size() != a2.size()) {
49 for (
int i = 0; i < a1.size(); ++i) {
57 template <
class A1,
class A2>
58 uint64 Hash2(
const A1& a1,
const A2& a2) {
66 template <
class A1,
class A2,
class A3>
67 uint64 Hash3(
const A1& a1,
const A2& a2,
const A3& a3) {
75 template <
class A1,
class A2,
class A3,
class A4>
76 uint64 Hash4(
const A1& a1,
const A2& a2,
const A3& a3,
const A4& a4) {
85 void Double(C*** array_ptr,
int* size_ptr) {
86 DCHECK(array_ptr !=
nullptr);
87 DCHECK(size_ptr !=
nullptr);
88 C**
const old_cell_array = *array_ptr;
89 const int old_size = *size_ptr;
91 (*array_ptr) =
new C*[(*size_ptr)];
92 memset(*array_ptr, 0, (*size_ptr) *
sizeof(**array_ptr));
93 for (
int i = 0; i < old_size; ++i) {
94 C* tmp = old_cell_array[i];
95 while (tmp !=
nullptr) {
96 C*
const to_reinsert = tmp;
98 const uint64 position = to_reinsert->Hash() % (*size_ptr);
99 to_reinsert->set_next((*array_ptr)[position]);
100 (*array_ptr)[position] = to_reinsert;
103 delete[](old_cell_array);
108 template <
class C,
class A1>
112 : array_(new Cell*[
absl::GetFlag(FLAGS_cache_initial_size)]),
113 size_(
absl::GetFlag(FLAGS_cache_initial_size)),
115 memset(array_, 0,
sizeof(*array_) * size_);
119 for (
int i = 0; i < size_; ++i) {
120 Cell* tmp = array_[i];
121 while (tmp !=
nullptr) {
122 Cell*
const to_delete = tmp;
131 for (
int i = 0; i < size_; ++i) {
132 Cell* tmp = array_[i];
133 while (tmp !=
nullptr) {
134 Cell*
const to_delete = tmp;
142 C* Find(
const A1& a1)
const {
144 Cell* tmp = array_[code];
146 C*
const result = tmp->ReturnsIfEqual(a1);
147 if (result !=
nullptr) {
155 void UnsafeInsert(
const A1& a1, C*
const c) {
156 const int position =
Hash1(a1) % size_;
157 Cell*
const cell =
new Cell(a1, c, array_[position]);
158 array_[position] = cell;
159 if (++num_items_ > 2 * size_) {
160 Double(&array_, &size_);
167 Cell(
const A1& a1, C*
const container, Cell*
const next)
168 : a1_(a1), container_(container), next_(
next) {}
170 C* ReturnsIfEqual(
const A1& a1)
const {
171 if (IsEqual(a1_, a1)) {
179 void set_next(Cell*
const next) { next_ =
next; }
181 Cell*
next()
const {
return next_; }
196 template <
class C,
class A1,
class A2>
200 : array_(new Cell*[
absl::GetFlag(FLAGS_cache_initial_size)]),
201 size_(
absl::GetFlag(FLAGS_cache_initial_size)),
203 memset(array_, 0,
sizeof(*array_) * size_);
207 for (
int i = 0; i < size_; ++i) {
208 Cell* tmp = array_[i];
209 while (tmp !=
nullptr) {
210 Cell*
const to_delete = tmp;
219 for (
int i = 0; i < size_; ++i) {
220 Cell* tmp = array_[i];
221 while (tmp !=
nullptr) {
222 Cell*
const to_delete = tmp;
230 C* Find(
const A1& a1,
const A2& a2)
const {
231 uint64 code = Hash2(a1, a2) % size_;
232 Cell* tmp = array_[code];
234 C*
const result = tmp->ReturnsIfEqual(a1, a2);
235 if (result !=
nullptr) {
243 void UnsafeInsert(
const A1& a1,
const A2& a2, C*
const c) {
244 const int position = Hash2(a1, a2) % size_;
245 Cell*
const cell =
new Cell(a1, a2, c, array_[position]);
246 array_[position] = cell;
247 if (++num_items_ > 2 * size_) {
248 Double(&array_, &size_);
255 Cell(
const A1& a1,
const A2& a2, C*
const container, Cell*
const next)
256 : a1_(a1), a2_(a2), container_(container), next_(
next) {}
258 C* ReturnsIfEqual(
const A1& a1,
const A2& a2)
const {
259 if (IsEqual(a1_, a1) && IsEqual(a2_, a2)) {
265 uint64 Hash()
const {
return Hash2(a1_, a2_); }
267 void set_next(Cell*
const next) { next_ =
next; }
269 Cell*
next()
const {
return next_; }
285 template <
class C,
class A1,
class A2,
class A3>
289 : array_(new Cell*[
absl::GetFlag(FLAGS_cache_initial_size)]),
290 size_(
absl::GetFlag(FLAGS_cache_initial_size)),
292 memset(array_, 0,
sizeof(*array_) * size_);
296 for (
int i = 0; i < size_; ++i) {
297 Cell* tmp = array_[i];
298 while (tmp !=
nullptr) {
299 Cell*
const to_delete = tmp;
308 for (
int i = 0; i < size_; ++i) {
309 Cell* tmp = array_[i];
310 while (tmp !=
nullptr) {
311 Cell*
const to_delete = tmp;
319 C* Find(
const A1& a1,
const A2& a2,
const A3& a3)
const {
320 uint64 code = Hash3(a1, a2, a3) % size_;
321 Cell* tmp = array_[code];
323 C*
const result = tmp->ReturnsIfEqual(a1, a2, a3);
324 if (result !=
nullptr) {
332 void UnsafeInsert(
const A1& a1,
const A2& a2,
const A3& a3, C*
const c) {
333 const int position = Hash3(a1, a2, a3) % size_;
334 Cell*
const cell =
new Cell(a1, a2, a3, c, array_[position]);
335 array_[position] = cell;
336 if (++num_items_ > 2 * size_) {
337 Double(&array_, &size_);
344 Cell(
const A1& a1,
const A2& a2,
const A3& a3, C*
const container,
346 : a1_(a1), a2_(a2), a3_(a3), container_(container), next_(
next) {}
348 C* ReturnsIfEqual(
const A1& a1,
const A2& a2,
const A3& a3)
const {
349 if (IsEqual(a1_, a1) && IsEqual(a2_, a2) && IsEqual(a3_, a3)) {
355 uint64 Hash()
const {
return Hash3(a1_, a2_, a3_); }
357 void set_next(Cell*
const next) { next_ =
next; }
359 Cell*
next()
const {
return next_; }
376 class NonReversibleCache :
public ModelCache {
378 typedef Cache1<IntExpr, IntExpr*> ExprIntExprCache;
379 typedef Cache1<IntExpr, std::vector<IntVar*> > VarArrayIntExprCache;
381 typedef Cache2<Constraint, IntVar*, int64> VarConstantConstraintCache;
382 typedef Cache2<Constraint, IntExpr*, IntExpr*> ExprExprConstraintCache;
383 typedef Cache2<IntExpr, IntVar*, int64> VarConstantIntExprCache;
384 typedef Cache2<IntExpr, IntExpr*, int64> ExprConstantIntExprCache;
385 typedef Cache2<IntExpr, IntExpr*, IntExpr*> ExprExprIntExprCache;
386 typedef Cache2<IntExpr, IntVar*, const std::vector<int64>&>
387 VarConstantArrayIntExprCache;
388 typedef Cache2<IntExpr, std::vector<IntVar*>,
const std::vector<int64>&>
389 VarArrayConstantArrayIntExprCache;
390 typedef Cache2<IntExpr, std::vector<IntVar*>,
int64>
391 VarArrayConstantIntExprCache;
393 typedef Cache3<IntExpr, IntVar*, int64, int64>
394 VarConstantConstantIntExprCache;
395 typedef Cache3<Constraint, IntVar*, int64, int64>
396 VarConstantConstantConstraintCache;
397 typedef Cache3<IntExpr, IntExpr*, IntExpr*, int64>
398 ExprExprConstantIntExprCache;
400 explicit NonReversibleCache(Solver*
const solver)
401 : ModelCache(solver), void_constraints_(VOID_CONSTRAINT_MAX, nullptr) {
402 for (
int i = 0; i < VAR_CONSTANT_CONSTRAINT_MAX; ++i) {
403 var_constant_constraints_.push_back(
new VarConstantConstraintCache);
405 for (
int i = 0; i < EXPR_EXPR_CONSTRAINT_MAX; ++i) {
406 expr_expr_constraints_.push_back(
new ExprExprConstraintCache);
408 for (
int i = 0; i < VAR_CONSTANT_CONSTANT_CONSTRAINT_MAX; ++i) {
409 var_constant_constant_constraints_.push_back(
410 new VarConstantConstantConstraintCache);
412 for (
int i = 0; i < EXPR_EXPRESSION_MAX; ++i) {
413 expr_expressions_.push_back(
new ExprIntExprCache);
415 for (
int i = 0; i < EXPR_CONSTANT_EXPRESSION_MAX; ++i) {
416 expr_constant_expressions_.push_back(
new ExprConstantIntExprCache);
418 for (
int i = 0; i < EXPR_EXPR_EXPRESSION_MAX; ++i) {
419 expr_expr_expressions_.push_back(
new ExprExprIntExprCache);
421 for (
int i = 0; i < VAR_CONSTANT_CONSTANT_EXPRESSION_MAX; ++i) {
422 var_constant_constant_expressions_.push_back(
423 new VarConstantConstantIntExprCache);
425 for (
int i = 0; i < VAR_CONSTANT_ARRAY_EXPRESSION_MAX; ++i) {
426 var_constant_array_expressions_.push_back(
427 new VarConstantArrayIntExprCache);
429 for (
int i = 0; i < VAR_ARRAY_EXPRESSION_MAX; ++i) {
430 var_array_expressions_.push_back(
new VarArrayIntExprCache);
432 for (
int i = 0; i < VAR_ARRAY_CONSTANT_ARRAY_EXPRESSION_MAX; ++i) {
433 var_array_constant_array_expressions_.push_back(
434 new VarArrayConstantArrayIntExprCache);
436 for (
int i = 0; i < VAR_ARRAY_CONSTANT_EXPRESSION_MAX; ++i) {
437 var_array_constant_expressions_.push_back(
438 new VarArrayConstantIntExprCache);
440 for (
int i = 0; i < EXPR_EXPR_CONSTANT_EXPRESSION_MAX; ++i) {
441 expr_expr_constant_expressions_.push_back(
442 new ExprExprConstantIntExprCache);
446 ~NonReversibleCache()
override {
461 void Clear()
override {
462 for (
int i = 0; i < VAR_CONSTANT_CONSTRAINT_MAX; ++i) {
463 var_constant_constraints_[i]->Clear();
465 for (
int i = 0; i < EXPR_EXPR_CONSTRAINT_MAX; ++i) {
466 expr_expr_constraints_[i]->Clear();
468 for (
int i = 0; i < VAR_CONSTANT_CONSTANT_CONSTRAINT_MAX; ++i) {
469 var_constant_constant_constraints_[i]->Clear();
471 for (
int i = 0; i < EXPR_EXPRESSION_MAX; ++i) {
472 expr_expressions_[i]->Clear();
474 for (
int i = 0; i < EXPR_CONSTANT_EXPRESSION_MAX; ++i) {
475 expr_constant_expressions_[i]->Clear();
477 for (
int i = 0; i < EXPR_EXPR_EXPRESSION_MAX; ++i) {
478 expr_expr_expressions_[i]->Clear();
480 for (
int i = 0; i < VAR_CONSTANT_CONSTANT_EXPRESSION_MAX; ++i) {
481 var_constant_constant_expressions_[i]->Clear();
483 for (
int i = 0; i < VAR_CONSTANT_ARRAY_EXPRESSION_MAX; ++i) {
484 var_constant_array_expressions_[i]->Clear();
486 for (
int i = 0; i < VAR_ARRAY_EXPRESSION_MAX; ++i) {
487 var_array_expressions_[i]->Clear();
489 for (
int i = 0; i < VAR_ARRAY_CONSTANT_ARRAY_EXPRESSION_MAX; ++i) {
490 var_array_constant_array_expressions_[i]->Clear();
492 for (
int i = 0; i < VAR_ARRAY_CONSTANT_EXPRESSION_MAX; ++i) {
493 var_array_constant_expressions_[i]->Clear();
495 for (
int i = 0; i < EXPR_EXPR_CONSTANT_EXPRESSION_MAX; ++i) {
496 expr_expr_constant_expressions_[i]->Clear();
502 Constraint* FindVoidConstraint(VoidConstraintType type)
const override {
505 return void_constraints_[type];
508 void InsertVoidConstraint(Constraint*
const ct,
509 VoidConstraintType type)
override {
514 !absl::GetFlag(FLAGS_cp_disable_cache)) {
515 void_constraints_[type] =
ct;
521 Constraint* FindVarConstantConstraint(
523 VarConstantConstraintType type)
const override {
526 DCHECK_LT(type, VAR_CONSTANT_CONSTRAINT_MAX);
527 return var_constant_constraints_[type]->Find(
var,
value);
530 void InsertVarConstantConstraint(Constraint*
const ct, IntVar*
const var,
532 VarConstantConstraintType type)
override {
536 DCHECK_LT(type, VAR_CONSTANT_CONSTRAINT_MAX);
538 !absl::GetFlag(FLAGS_cp_disable_cache) &&
539 var_constant_constraints_[type]->Find(
var,
value) ==
nullptr) {
540 var_constant_constraints_[type]->UnsafeInsert(
var,
value,
ct);
546 Constraint* FindVarConstantConstantConstraint(
548 VarConstantConstantConstraintType type)
const override {
551 DCHECK_LT(type, VAR_CONSTANT_CONSTANT_CONSTRAINT_MAX);
552 return var_constant_constant_constraints_[type]->Find(
var, value1, value2);
555 void InsertVarConstantConstantConstraint(
557 VarConstantConstantConstraintType type)
override {
561 DCHECK_LT(type, VAR_CONSTANT_CONSTANT_CONSTRAINT_MAX);
563 !absl::GetFlag(FLAGS_cp_disable_cache) &&
564 var_constant_constant_constraints_[type]->Find(
var, value1, value2) ==
566 var_constant_constant_constraints_[type]->UnsafeInsert(
var, value1,
573 Constraint* FindExprExprConstraint(
574 IntExpr*
const var1, IntExpr*
const var2,
575 ExprExprConstraintType type)
const override {
579 DCHECK_LT(type, EXPR_EXPR_CONSTRAINT_MAX);
580 return expr_expr_constraints_[type]->Find(var1, var2);
583 void InsertExprExprConstraint(Constraint*
const ct, IntExpr*
const var1,
585 ExprExprConstraintType type)
override {
590 DCHECK_LT(type, EXPR_EXPR_CONSTRAINT_MAX);
592 !absl::GetFlag(FLAGS_cp_disable_cache) &&
593 expr_expr_constraints_[type]->Find(var1, var2) ==
nullptr) {
594 expr_expr_constraints_[type]->UnsafeInsert(var1, var2,
ct);
600 IntExpr* FindExprExpression(IntExpr*
const expr,
601 ExprExpressionType type)
const override {
605 return expr_expressions_[type]->Find(expr);
608 void InsertExprExpression(IntExpr*
const expression, IntExpr*
const expr,
609 ExprExpressionType type)
override {
610 DCHECK(expression !=
nullptr);
615 !absl::GetFlag(FLAGS_cp_disable_cache) &&
616 expr_expressions_[type]->Find(expr) ==
nullptr) {
617 expr_expressions_[type]->UnsafeInsert(expr, expression);
623 IntExpr* FindExprConstantExpression(
625 ExprConstantExpressionType type)
const override {
628 DCHECK_LT(type, EXPR_CONSTANT_EXPRESSION_MAX);
629 return expr_constant_expressions_[type]->Find(expr,
value);
632 void InsertExprConstantExpression(IntExpr*
const expression,
634 ExprConstantExpressionType type)
override {
635 DCHECK(expression !=
nullptr);
638 DCHECK_LT(type, EXPR_CONSTANT_EXPRESSION_MAX);
640 !absl::GetFlag(FLAGS_cp_disable_cache) &&
641 expr_constant_expressions_[type]->Find(expr,
value) ==
nullptr) {
642 expr_constant_expressions_[type]->UnsafeInsert(expr,
value, expression);
648 IntExpr* FindExprExprExpression(IntExpr*
const var1, IntExpr*
const var2,
649 ExprExprExpressionType type)
const override {
653 DCHECK_LT(type, EXPR_EXPR_EXPRESSION_MAX);
654 return expr_expr_expressions_[type]->Find(var1, var2);
657 void InsertExprExprExpression(IntExpr*
const expression, IntExpr*
const var1,
659 ExprExprExpressionType type)
override {
660 DCHECK(expression !=
nullptr);
664 DCHECK_LT(type, EXPR_EXPR_EXPRESSION_MAX);
666 !absl::GetFlag(FLAGS_cp_disable_cache) &&
667 expr_expr_expressions_[type]->Find(var1, var2) ==
nullptr) {
668 expr_expr_expressions_[type]->UnsafeInsert(var1, var2, expression);
674 IntExpr* FindExprExprConstantExpression(
675 IntExpr*
const var1, IntExpr*
const var2,
int64 constant,
676 ExprExprConstantExpressionType type)
const override {
680 DCHECK_LT(type, EXPR_EXPR_CONSTANT_EXPRESSION_MAX);
681 return expr_expr_constant_expressions_[type]->Find(var1, var2, constant);
684 void InsertExprExprConstantExpression(
685 IntExpr*
const expression, IntExpr*
const var1, IntExpr*
const var2,
686 int64 constant, ExprExprConstantExpressionType type)
override {
687 DCHECK(expression !=
nullptr);
691 DCHECK_LT(type, EXPR_EXPR_CONSTANT_EXPRESSION_MAX);
693 !absl::GetFlag(FLAGS_cp_disable_cache) &&
694 expr_expr_constant_expressions_[type]->Find(var1, var2, constant) ==
696 expr_expr_constant_expressions_[type]->UnsafeInsert(var1, var2, constant,
703 IntExpr* FindVarConstantConstantExpression(
705 VarConstantConstantExpressionType type)
const override {
708 DCHECK_LT(type, VAR_CONSTANT_CONSTANT_EXPRESSION_MAX);
709 return var_constant_constant_expressions_[type]->Find(
var, value1, value2);
712 void InsertVarConstantConstantExpression(
713 IntExpr*
const expression, IntVar*
const var,
int64 value1,
int64 value2,
714 VarConstantConstantExpressionType type)
override {
715 DCHECK(expression !=
nullptr);
718 DCHECK_LT(type, VAR_CONSTANT_CONSTANT_EXPRESSION_MAX);
720 !absl::GetFlag(FLAGS_cp_disable_cache) &&
721 var_constant_constant_expressions_[type]->Find(
var, value1, value2) ==
723 var_constant_constant_expressions_[type]->UnsafeInsert(
724 var, value1, value2, expression);
730 IntExpr* FindVarConstantArrayExpression(
731 IntVar*
const var,
const std::vector<int64>& values,
732 VarConstantArrayExpressionType type)
const override {
735 DCHECK_LT(type, VAR_CONSTANT_ARRAY_EXPRESSION_MAX);
736 return var_constant_array_expressions_[type]->Find(
var, values);
739 void InsertVarConstantArrayExpression(
740 IntExpr*
const expression, IntVar*
const var,
741 const std::vector<int64>& values,
742 VarConstantArrayExpressionType type)
override {
743 DCHECK(expression !=
nullptr);
746 DCHECK_LT(type, VAR_CONSTANT_ARRAY_EXPRESSION_MAX);
748 !absl::GetFlag(FLAGS_cp_disable_cache) &&
749 var_constant_array_expressions_[type]->Find(
var, values) ==
nullptr) {
750 var_constant_array_expressions_[type]->UnsafeInsert(
var, values,
757 IntExpr* FindVarArrayExpression(
const std::vector<IntVar*>& vars,
758 VarArrayExpressionType type)
const override {
760 DCHECK_LT(type, VAR_ARRAY_EXPRESSION_MAX);
761 return var_array_expressions_[type]->Find(vars);
764 void InsertVarArrayExpression(IntExpr*
const expression,
765 const std::vector<IntVar*>& vars,
766 VarArrayExpressionType type)
override {
767 DCHECK(expression !=
nullptr);
769 DCHECK_LT(type, VAR_ARRAY_EXPRESSION_MAX);
771 !absl::GetFlag(FLAGS_cp_disable_cache) &&
772 var_array_expressions_[type]->Find(vars) ==
nullptr) {
773 var_array_expressions_[type]->UnsafeInsert(vars, expression);
779 IntExpr* FindVarArrayConstantArrayExpression(
780 const std::vector<IntVar*>& vars,
const std::vector<int64>& values,
781 VarArrayConstantArrayExpressionType type)
const override {
783 DCHECK_LT(type, VAR_ARRAY_CONSTANT_ARRAY_EXPRESSION_MAX);
784 return var_array_constant_array_expressions_[type]->Find(vars, values);
787 void InsertVarArrayConstantArrayExpression(
788 IntExpr*
const expression,
const std::vector<IntVar*>& vars,
789 const std::vector<int64>& values,
790 VarArrayConstantArrayExpressionType type)
override {
791 DCHECK(expression !=
nullptr);
793 DCHECK_LT(type, VAR_ARRAY_CONSTANT_ARRAY_EXPRESSION_MAX);
795 var_array_constant_array_expressions_[type]->Find(vars, values) ==
797 var_array_constant_array_expressions_[type]->UnsafeInsert(vars, values,
804 IntExpr* FindVarArrayConstantExpression(
805 const std::vector<IntVar*>& vars,
int64 value,
806 VarArrayConstantExpressionType type)
const override {
808 DCHECK_LT(type, VAR_ARRAY_CONSTANT_EXPRESSION_MAX);
809 return var_array_constant_expressions_[type]->Find(vars,
value);
812 void InsertVarArrayConstantExpression(
813 IntExpr*
const expression,
const std::vector<IntVar*>& vars,
int64 value,
814 VarArrayConstantExpressionType type)
override {
815 DCHECK(expression !=
nullptr);
817 DCHECK_LT(type, VAR_ARRAY_CONSTANT_EXPRESSION_MAX);
819 var_array_constant_expressions_[type]->Find(vars,
value) ==
nullptr) {
820 var_array_constant_expressions_[type]->UnsafeInsert(vars,
value,
826 std::vector<Constraint*> void_constraints_;
827 std::vector<VarConstantConstraintCache*> var_constant_constraints_;
828 std::vector<ExprExprConstraintCache*> expr_expr_constraints_;
829 std::vector<VarConstantConstantConstraintCache*>
830 var_constant_constant_constraints_;
831 std::vector<ExprIntExprCache*> expr_expressions_;
832 std::vector<ExprConstantIntExprCache*> expr_constant_expressions_;
833 std::vector<ExprExprIntExprCache*> expr_expr_expressions_;
834 std::vector<VarConstantConstantIntExprCache*>
835 var_constant_constant_expressions_;
836 std::vector<VarConstantArrayIntExprCache*> var_constant_array_expressions_;
837 std::vector<VarArrayIntExprCache*> var_array_expressions_;
838 std::vector<VarArrayConstantArrayIntExprCache*>
839 var_array_constant_array_expressions_;
840 std::vector<VarArrayConstantIntExprCache*> var_array_constant_expressions_;
841 std::vector<ExprExprConstantIntExprCache*> expr_expr_constant_expressions_;
846 return new NonReversibleCache(solver);