OR-Tools  9.3
utilities.cc
Go to the documentation of this file.
1// Copyright 2010-2021 Google LLC
2// Licensed under the Apache License, Version 2.0 (the "License");
3// you may not use this file except in compliance with the License.
4// You may obtain a copy of the License at
5//
6// http://www.apache.org/licenses/LICENSE-2.0
7//
8// Unless required by applicable law or agreed to in writing, software
9// distributed under the License is distributed on an "AS IS" BASIS,
10// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11// See the License for the specific language governing permissions and
12// limitations under the License.
13
14#include <cstdint>
15#include <string>
16
17#include "absl/container/flat_hash_map.h"
18#include "absl/container/flat_hash_set.h"
19#include "absl/strings/str_format.h"
20#include "absl/strings/str_join.h"
21#include "ortools/base/hash.h"
27#include "ortools/util/bitset.h"
28
29namespace operations_research {
30
31// ---------- SmallRevBitSet ----------
32
33SmallRevBitSet::SmallRevBitSet(int64_t size) : bits_(0LL) {
34 DCHECK_GT(size, 0);
35 DCHECK_LE(size, 64);
36}
37
38void SmallRevBitSet::SetToOne(Solver* const solver, int64_t pos) {
39 DCHECK_GE(pos, 0);
40 bits_.SetValue(solver, bits_.Value() | OneBit64(pos));
41}
42
43void SmallRevBitSet::SetToZero(Solver* const solver, int64_t pos) {
44 DCHECK_GE(pos, 0);
45 bits_.SetValue(solver, bits_.Value() & ~OneBit64(pos));
46}
47
49 return BitCount64(bits_.Value());
50}
51
53 if (bits_.Value() == 0) {
54 return -1;
55 }
57}
58
59// ---------- RevBitSet ----------
60
62 : size_(size),
63 length_(BitLength64(size)),
64 bits_(new uint64_t[length_]),
65 stamps_(new uint64_t[length_]) {
66 DCHECK_GE(size, 1);
67 memset(bits_, 0, sizeof(*bits_) * length_);
68 memset(stamps_, 0, sizeof(*stamps_) * length_);
69}
70
72 delete[] bits_;
73 delete[] stamps_;
74}
75
76void RevBitSet::Save(Solver* const solver, int offset) {
77 const uint64_t current_stamp = solver->stamp();
78 if (current_stamp > stamps_[offset]) {
79 stamps_[offset] = current_stamp;
80 solver->SaveValue(&bits_[offset]);
81 }
82}
83
84void RevBitSet::SetToOne(Solver* const solver, int64_t index) {
85 DCHECK_GE(index, 0);
86 DCHECK_LT(index, size_);
87 const int64_t offset = BitOffset64(index);
88 const int64_t pos = BitPos64(index);
89 if (!(bits_[offset] & OneBit64(pos))) {
90 Save(solver, offset);
91 bits_[offset] |= OneBit64(pos);
92 }
93}
94
95void RevBitSet::SetToZero(Solver* const solver, int64_t index) {
96 DCHECK_GE(index, 0);
97 DCHECK_LT(index, size_);
98 const int64_t offset = BitOffset64(index);
99 const int64_t pos = BitPos64(index);
100 if (bits_[offset] & OneBit64(pos)) {
101 Save(solver, offset);
102 bits_[offset] &= ~OneBit64(pos);
103 }
104}
105
106bool RevBitSet::IsSet(int64_t index) const {
107 DCHECK_GE(index, 0);
108 DCHECK_LT(index, size_);
109 return IsBitSet64(bits_, index);
110}
111
112int64_t RevBitSet::Cardinality() const {
113 int64_t card = 0;
114 for (int i = 0; i < length_; ++i) {
115 card += BitCount64(bits_[i]);
116 }
117 return card;
118}
119
121 for (int i = 0; i < length_; ++i) {
122 if (bits_[i]) {
123 return false;
124 }
125 }
126 return true;
127}
128
130 bool found_one = false;
131 for (int i = 0; i < length_; ++i) {
132 const uint64_t partial = bits_[i];
133 if (partial) {
134 if (!(partial & (partial - 1))) {
135 if (found_one) {
136 return false;
137 }
138 found_one = true;
139 } else {
140 return false;
141 }
142 }
143 }
144 return found_one;
145}
146
147int64_t RevBitSet::GetFirstBit(int start) const {
148 return LeastSignificantBitPosition64(bits_, start, size_ - 1);
149}
150
151void RevBitSet::ClearAll(Solver* const solver) {
152 for (int offset = 0; offset < length_; ++offset) {
153 if (bits_[offset]) {
154 Save(solver, offset);
155 bits_[offset] = uint64_t{0};
156 }
157 }
158}
159
160// ----- RevBitMatrix -----
161
162RevBitMatrix::RevBitMatrix(int64_t rows, int64_t columns)
163 : RevBitSet(rows * columns), rows_(rows), columns_(columns) {
164 DCHECK_GE(rows, 1);
165 DCHECK_GE(columns, 1);
166}
167
169
170void RevBitMatrix::SetToOne(Solver* const solver, int64_t row, int64_t column) {
171 DCHECK_GE(row, 0);
172 DCHECK_LT(row, rows_);
173 DCHECK_GE(column, 0);
174 DCHECK_LT(column, columns_);
175 RevBitSet::SetToOne(solver, row * columns_ + column);
176}
177
178void RevBitMatrix::SetToZero(Solver* const solver, int64_t row,
179 int64_t column) {
180 DCHECK_GE(row, 0);
181 DCHECK_LT(row, rows_);
182 DCHECK_GE(column, 0);
183 DCHECK_LT(column, columns_);
184 RevBitSet::SetToZero(solver, row * columns_ + column);
185}
186
187int64_t RevBitMatrix::Cardinality(int row) const {
188 DCHECK_GE(row, 0);
189 DCHECK_LT(row, rows_);
190 const int start = row * columns_;
191 return BitCountRange64(bits_, start, start + columns_ - 1);
192}
193
195 // TODO(user) : Optimize this one.
196 return Cardinality(row) == 1;
197}
198
200 const int start = row * columns_;
201 return IsEmptyRange64(bits_, start, start + columns_ - 1);
202}
203
204int64_t RevBitMatrix::GetFirstBit(int row, int start) const {
205 DCHECK_GE(start, 0);
206 DCHECK_GE(row, 0);
207 DCHECK_LT(row, rows_);
208 DCHECK_LT(start, columns_);
209 const int beginning = row * columns_;
210 const int end = beginning + columns_ - 1;
211 int64_t position =
212 LeastSignificantBitPosition64(bits_, beginning + start, end);
213 if (position == -1) {
214 return -1;
215 } else {
216 return position - beginning;
217 }
218}
219
220void RevBitMatrix::ClearAll(Solver* const solver) {
221 RevBitSet::ClearAll(solver);
222}
223
224// ----- UnsortedNullableRevBitset -----
225
227 : bit_size_(bit_size),
228 word_size_(BitLength64(bit_size)),
229 bits_(word_size_, 0),
230 active_words_(word_size_) {}
231
233 const std::vector<uint64_t>& mask) {
234 CHECK_LE(mask.size(), word_size_);
235 for (int i = 0; i < mask.size(); ++i) {
236 if (mask[i]) {
237 bits_.SetValue(solver, i, mask[i]);
238 active_words_.Insert(solver, i);
239 }
240 }
241}
242
244 const std::vector<uint64_t>& mask) {
245 bool changed = false;
246 to_remove_.clear();
247 for (int index : active_words_) {
248 if (index < mask.size() && (bits_[index] & mask[index]) != 0) {
249 changed = true;
250 const uint64_t result = bits_[index] & ~mask[index];
251 bits_.SetValue(solver, index, result);
252 if (result == 0) {
253 to_remove_.push_back(index);
254 }
255 }
256 }
257
258 CleanUpActives(solver);
259 return changed;
260}
261
262void UnsortedNullableRevBitset::CleanUpActives(Solver* const solver) {
263 // We remove indices of null words in reverse order, as this may be a simpler
264 // operations on the RevIntSet (no actual swap).
265 for (int i = to_remove_.size() - 1; i >= 0; --i) {
266 active_words_.Remove(solver, to_remove_[i]);
267 }
268}
269
271 const std::vector<uint64_t>& mask) {
272 bool changed = false;
273 to_remove_.clear();
274 for (int index : active_words_) {
275 if (index < mask.size()) {
276 if ((bits_[index] & ~mask[index]) != 0) {
277 changed = true;
278 const uint64_t result = bits_[index] & mask[index];
279 bits_.SetValue(solver, index, result);
280 if (result == 0) {
281 to_remove_.push_back(index);
282 }
283 }
284 } else {
285 // Zero the word as the mask is implicitely null.
286 changed = true;
287 bits_.SetValue(solver, index, 0);
288 to_remove_.push_back(index);
289 }
290 }
291 CleanUpActives(solver);
292 return changed;
293}
294
295bool UnsortedNullableRevBitset::Intersects(const std::vector<uint64_t>& mask,
296 int* support_index) {
297 DCHECK_GE(*support_index, 0);
298 DCHECK_LT(*support_index, word_size_);
299 if (mask[*support_index] & bits_[*support_index]) {
300 return true;
301 }
302 for (int index : active_words_) {
303 if (bits_[index] & mask[index]) {
304 *support_index = index;
305 return true;
306 }
307 }
308 return false;
309}
310
311// ----- PrintModelVisitor -----
312
313namespace {
314class PrintModelVisitor : public ModelVisitor {
315 public:
316 PrintModelVisitor() : indent_(0) {}
317 ~PrintModelVisitor() override {}
318
319 // Header/footers.
320 void BeginVisitModel(const std::string& solver_name) override {
321 LOG(INFO) << "Model " << solver_name << " {";
322 Increase();
323 }
324
325 void EndVisitModel(const std::string& solver_name) override {
326 LOG(INFO) << "}";
327 Decrease();
328 CHECK_EQ(0, indent_);
329 }
330
331 void BeginVisitConstraint(const std::string& type_name,
332 const Constraint* const constraint) override {
333 LOG(INFO) << Spaces() << type_name;
334 Increase();
335 }
336
337 void EndVisitConstraint(const std::string& type_name,
338 const Constraint* const constraint) override {
339 Decrease();
340 }
341
342 void BeginVisitIntegerExpression(const std::string& type_name,
343 const IntExpr* const expr) override {
344 LOG(INFO) << Spaces() << type_name;
345 Increase();
346 }
347
348 void EndVisitIntegerExpression(const std::string& type_name,
349 const IntExpr* const expr) override {
350 Decrease();
351 }
352
353 void BeginVisitExtension(const std::string& type_name) override {
354 LOG(INFO) << Spaces() << type_name;
355 Increase();
356 }
357
358 void EndVisitExtension(const std::string& type_name) override { Decrease(); }
359
360 void VisitIntegerVariable(const IntVar* const variable,
361 IntExpr* const delegate) override {
362 if (delegate != nullptr) {
363 delegate->Accept(this);
364 } else {
365 if (variable->Bound() && variable->name().empty()) {
366 LOG(INFO) << Spaces() << variable->Min();
367 } else {
368 LOG(INFO) << Spaces() << variable->DebugString();
369 }
370 }
371 }
372
373 void VisitIntegerVariable(const IntVar* const variable,
374 const std::string& operation, int64_t value,
375 IntVar* const delegate) override {
376 LOG(INFO) << Spaces() << "IntVar";
377 Increase();
378 LOG(INFO) << Spaces() << value;
379 LOG(INFO) << Spaces() << operation;
380 delegate->Accept(this);
381 Decrease();
382 }
383
384 void VisitIntervalVariable(const IntervalVar* const variable,
385 const std::string& operation, int64_t value,
386 IntervalVar* const delegate) override {
387 if (delegate != nullptr) {
388 LOG(INFO) << Spaces() << operation << " <" << value << ", ";
389 Increase();
390 delegate->Accept(this);
391 Decrease();
392 LOG(INFO) << Spaces() << ">";
393 } else {
394 LOG(INFO) << Spaces() << variable->DebugString();
395 }
396 }
397
398 void VisitSequenceVariable(const SequenceVar* const sequence) override {
399 LOG(INFO) << Spaces() << sequence->DebugString();
400 }
401
402 // Variables.
403 void VisitIntegerArgument(const std::string& arg_name,
404 int64_t value) override {
405 LOG(INFO) << Spaces() << arg_name << ": " << value;
406 }
407
408 void VisitIntegerArrayArgument(const std::string& arg_name,
409 const std::vector<int64_t>& values) override {
410 LOG(INFO) << Spaces() << arg_name << ": [" << absl::StrJoin(values, ", ")
411 << "]";
412 }
413
414 void VisitIntegerMatrixArgument(const std::string& arg_name,
415 const IntTupleSet& values) override {
416 const int rows = values.NumTuples();
417 const int columns = values.Arity();
418 std::string array = "[";
419 for (int i = 0; i < rows; ++i) {
420 if (i != 0) {
421 array.append(", ");
422 }
423 array.append("[");
424 for (int j = 0; j < columns; ++j) {
425 if (j != 0) {
426 array.append(", ");
427 }
428 absl::StrAppendFormat(&array, "%d", values.Value(i, j));
429 }
430 array.append("]");
431 }
432 array.append("]");
433 LOG(INFO) << Spaces() << arg_name << ": " << array;
434 }
435
436 void VisitIntegerExpressionArgument(const std::string& arg_name,
437 IntExpr* const argument) override {
438 set_prefix(absl::StrFormat("%s: ", arg_name));
439 Increase();
440 argument->Accept(this);
441 Decrease();
442 }
443
444 void VisitIntegerVariableArrayArgument(
445 const std::string& arg_name,
446 const std::vector<IntVar*>& arguments) override {
447 LOG(INFO) << Spaces() << arg_name << ": [";
448 Increase();
449 for (int i = 0; i < arguments.size(); ++i) {
450 arguments[i]->Accept(this);
451 }
452 Decrease();
453 LOG(INFO) << Spaces() << "]";
454 }
455
456 // Visit interval argument.
457 void VisitIntervalArgument(const std::string& arg_name,
458 IntervalVar* const argument) override {
459 set_prefix(absl::StrFormat("%s: ", arg_name));
460 Increase();
461 argument->Accept(this);
462 Decrease();
463 }
464
465 virtual void VisitIntervalArgumentArray(
466 const std::string& arg_name, const std::vector<IntervalVar*>& arguments) {
467 LOG(INFO) << Spaces() << arg_name << ": [";
468 Increase();
469 for (int i = 0; i < arguments.size(); ++i) {
470 arguments[i]->Accept(this);
471 }
472 Decrease();
473 LOG(INFO) << Spaces() << "]";
474 }
475
476 // Visit sequence argument.
477 void VisitSequenceArgument(const std::string& arg_name,
478 SequenceVar* const argument) override {
479 set_prefix(absl::StrFormat("%s: ", arg_name));
480 Increase();
481 argument->Accept(this);
482 Decrease();
483 }
484
485 virtual void VisitSequenceArgumentArray(
486 const std::string& arg_name, const std::vector<SequenceVar*>& arguments) {
487 LOG(INFO) << Spaces() << arg_name << ": [";
488 Increase();
489 for (int i = 0; i < arguments.size(); ++i) {
490 arguments[i]->Accept(this);
491 }
492 Decrease();
493 LOG(INFO) << Spaces() << "]";
494 }
495
496 std::string DebugString() const override { return "PrintModelVisitor"; }
497
498 private:
499 void Increase() { indent_ += 2; }
500
501 void Decrease() { indent_ -= 2; }
502
503 std::string Spaces() {
504 std::string result;
505 for (int i = 0; i < indent_ - 2 * (!prefix_.empty()); ++i) {
506 result.append(" ");
507 }
508 if (!prefix_.empty()) {
509 result.append(prefix_);
510 prefix_ = "";
511 }
512 return result;
513 }
514
515 void set_prefix(const std::string& prefix) { prefix_ = prefix; }
516
517 int indent_;
518 std::string prefix_;
519};
520
521// ---------- ModelStatisticsVisitor -----------
522
523class ModelStatisticsVisitor : public ModelVisitor {
524 public:
525 ModelStatisticsVisitor()
526 : num_constraints_(0),
527 num_variables_(0),
528 num_expressions_(0),
529 num_casts_(0),
530 num_intervals_(0),
531 num_sequences_(0),
532 num_extensions_(0) {}
533
534 ~ModelStatisticsVisitor() override {}
535
536 // Begin/End visit element.
537 void BeginVisitModel(const std::string& solver_name) override {
538 // Reset statistics.
539 num_constraints_ = 0;
540 num_variables_ = 0;
541 num_expressions_ = 0;
542 num_casts_ = 0;
543 num_intervals_ = 0;
544 num_sequences_ = 0;
545 num_extensions_ = 0;
546 already_visited_.clear();
547 constraint_types_.clear();
548 expression_types_.clear();
549 extension_types_.clear();
550 }
551
552 void EndVisitModel(const std::string& solver_name) override {
553 // Display statistics.
554 LOG(INFO) << "Model has:";
555 LOG(INFO) << " - " << num_constraints_ << " constraints.";
556 for (const auto& it : constraint_types_) {
557 LOG(INFO) << " * " << it.second << " " << it.first;
558 }
559 LOG(INFO) << " - " << num_variables_ << " integer variables.";
560 LOG(INFO) << " - " << num_expressions_ << " integer expressions.";
561 for (const auto& it : expression_types_) {
562 LOG(INFO) << " * " << it.second << " " << it.first;
563 }
564 LOG(INFO) << " - " << num_casts_ << " expressions casted into variables.";
565 LOG(INFO) << " - " << num_intervals_ << " interval variables.";
566 LOG(INFO) << " - " << num_sequences_ << " sequence variables.";
567 LOG(INFO) << " - " << num_extensions_ << " model extensions.";
568 for (const auto& it : extension_types_) {
569 LOG(INFO) << " * " << it.second << " " << it.first;
570 }
571 }
572
573 void BeginVisitConstraint(const std::string& type_name,
574 const Constraint* const constraint) override {
575 num_constraints_++;
576 AddConstraintType(type_name);
577 }
578
579 void BeginVisitIntegerExpression(const std::string& type_name,
580 const IntExpr* const expr) override {
581 AddExpressionType(type_name);
582 num_expressions_++;
583 }
584
585 void BeginVisitExtension(const std::string& type_name) override {
586 AddExtensionType(type_name);
587 num_extensions_++;
588 }
589
590 void VisitIntegerVariable(const IntVar* const variable,
591 IntExpr* const delegate) override {
592 num_variables_++;
593 Register(variable);
594 if (delegate) {
595 num_casts_++;
596 VisitSubArgument(delegate);
597 }
598 }
599
600 void VisitIntegerVariable(const IntVar* const variable,
601 const std::string& operation, int64_t value,
602 IntVar* const delegate) override {
603 num_variables_++;
604 Register(variable);
605 num_casts_++;
606 VisitSubArgument(delegate);
607 }
608
609 void VisitIntervalVariable(const IntervalVar* const variable,
610 const std::string& operation, int64_t value,
611 IntervalVar* const delegate) override {
612 num_intervals_++;
613 if (delegate) {
614 VisitSubArgument(delegate);
615 }
616 }
617
618 void VisitSequenceVariable(const SequenceVar* const sequence) override {
619 num_sequences_++;
620 for (int i = 0; i < sequence->size(); ++i) {
621 VisitSubArgument(sequence->Interval(i));
622 }
623 }
624
625 // Visit integer expression argument.
626 void VisitIntegerExpressionArgument(const std::string& arg_name,
627 IntExpr* const argument) override {
628 VisitSubArgument(argument);
629 }
630
631 void VisitIntegerVariableArrayArgument(
632 const std::string& arg_name,
633 const std::vector<IntVar*>& arguments) override {
634 for (int i = 0; i < arguments.size(); ++i) {
635 VisitSubArgument(arguments[i]);
636 }
637 }
638
639 // Visit interval argument.
640 void VisitIntervalArgument(const std::string& arg_name,
641 IntervalVar* const argument) override {
642 VisitSubArgument(argument);
643 }
644
645 void VisitIntervalArrayArgument(
646 const std::string& arg_name,
647 const std::vector<IntervalVar*>& arguments) override {
648 for (int i = 0; i < arguments.size(); ++i) {
649 VisitSubArgument(arguments[i]);
650 }
651 }
652
653 // Visit sequence argument.
654 void VisitSequenceArgument(const std::string& arg_name,
655 SequenceVar* const argument) override {
656 VisitSubArgument(argument);
657 }
658
659 void VisitSequenceArrayArgument(
660 const std::string& arg_name,
661 const std::vector<SequenceVar*>& arguments) override {
662 for (int i = 0; i < arguments.size(); ++i) {
663 VisitSubArgument(arguments[i]);
664 }
665 }
666
667 std::string DebugString() const override { return "ModelStatisticsVisitor"; }
668
669 private:
670 void Register(const BaseObject* const object) {
671 already_visited_.insert(object);
672 }
673
674 bool AlreadyVisited(const BaseObject* const object) {
675 return already_visited_.contains(object);
676 }
677
678 // T should derive from BaseObject
679 template <typename T>
680 void VisitSubArgument(T* object) {
681 if (!AlreadyVisited(object)) {
682 Register(object);
683 object->Accept(this);
684 }
685 }
686
687 void AddConstraintType(const std::string& constraint_type) {
688 constraint_types_[constraint_type]++;
689 }
690
691 void AddExpressionType(const std::string& expression_type) {
692 expression_types_[expression_type]++;
693 }
694
695 void AddExtensionType(const std::string& extension_type) {
696 extension_types_[extension_type]++;
697 }
698
699 absl::flat_hash_map<std::string, int> constraint_types_;
700 absl::flat_hash_map<std::string, int> expression_types_;
701 absl::flat_hash_map<std::string, int> extension_types_;
702 int num_constraints_;
703 int num_variables_;
704 int num_expressions_;
705 int num_casts_;
706 int num_intervals_;
707 int num_sequences_;
708 int num_extensions_;
709 absl::flat_hash_set<const BaseObject*> already_visited_;
710};
711
712// ---------- Variable Degree Visitor ---------
713
714class VariableDegreeVisitor : public ModelVisitor {
715 public:
716 explicit VariableDegreeVisitor(
717 absl::flat_hash_map<const IntVar*, int>* const map)
718 : map_(map) {}
719
720 ~VariableDegreeVisitor() override {}
721
722 // Begin/End visit element.
723 void VisitIntegerVariable(const IntVar* const variable,
724 IntExpr* const delegate) override {
725 IntVar* const var = const_cast<IntVar*>(variable);
726 if (map_->contains(var)) {
727 (*map_)[var]++;
728 }
729 if (delegate) {
730 VisitSubArgument(delegate);
731 }
732 }
733
734 void VisitIntegerVariable(const IntVar* const variable,
735 const std::string& operation, int64_t value,
736 IntVar* const delegate) override {
737 IntVar* const var = const_cast<IntVar*>(variable);
738 if (map_->contains(var)) {
739 (*map_)[var]++;
740 }
741 VisitSubArgument(delegate);
742 }
743
744 void VisitIntervalVariable(const IntervalVar* const variable,
745 const std::string& operation, int64_t value,
746 IntervalVar* const delegate) override {
747 if (delegate) {
748 VisitSubArgument(delegate);
749 }
750 }
751
752 void VisitSequenceVariable(const SequenceVar* const sequence) override {
753 for (int i = 0; i < sequence->size(); ++i) {
754 VisitSubArgument(sequence->Interval(i));
755 }
756 }
757
758 // Visit integer expression argument.
759 void VisitIntegerExpressionArgument(const std::string& arg_name,
760 IntExpr* const argument) override {
761 VisitSubArgument(argument);
762 }
763
764 void VisitIntegerVariableArrayArgument(
765 const std::string& arg_name,
766 const std::vector<IntVar*>& arguments) override {
767 for (int i = 0; i < arguments.size(); ++i) {
768 VisitSubArgument(arguments[i]);
769 }
770 }
771
772 // Visit interval argument.
773 void VisitIntervalArgument(const std::string& arg_name,
774 IntervalVar* const argument) override {
775 VisitSubArgument(argument);
776 }
777
778 void VisitIntervalArrayArgument(
779 const std::string& arg_name,
780 const std::vector<IntervalVar*>& arguments) override {
781 for (int i = 0; i < arguments.size(); ++i) {
782 VisitSubArgument(arguments[i]);
783 }
784 }
785
786 // Visit sequence argument.
787 void VisitSequenceArgument(const std::string& arg_name,
788 SequenceVar* const argument) override {
789 VisitSubArgument(argument);
790 }
791
792 void VisitSequenceArrayArgument(
793 const std::string& arg_name,
794 const std::vector<SequenceVar*>& arguments) override {
795 for (int i = 0; i < arguments.size(); ++i) {
796 VisitSubArgument(arguments[i]);
797 }
798 }
799
800 std::string DebugString() const override { return "VariableDegreeVisitor"; }
801
802 private:
803 // T should derive from BaseObject
804 template <typename T>
805 void VisitSubArgument(T* object) {
806 object->Accept(this);
807 }
808
809 absl::flat_hash_map<const IntVar*, int>* const map_;
810};
811} // namespace
812
814 return RevAlloc(new PrintModelVisitor);
815}
816
818 return RevAlloc(new ModelStatisticsVisitor);
819}
820
822 absl::flat_hash_map<const IntVar*, int>* const map) {
823 return RevAlloc(new VariableDegreeVisitor(map));
824}
825
826// ----- Vector manipulations -----
827
828std::vector<int64_t> ToInt64Vector(const std::vector<int>& input) {
829 std::vector<int64_t> result(input.size());
830 for (int i = 0; i < input.size(); ++i) {
831 result[i] = input[i];
832 }
833 return result;
834}
835} // namespace operations_research
#define DCHECK_LE(val1, val2)
Definition: base/logging.h:893
#define CHECK_EQ(val1, val2)
Definition: base/logging.h:703
#define DCHECK_GE(val1, val2)
Definition: base/logging.h:895
#define DCHECK_GT(val1, val2)
Definition: base/logging.h:896
#define DCHECK_LT(val1, val2)
Definition: base/logging.h:894
#define LOG(severity)
Definition: base/logging.h:420
#define CHECK_LE(val1, val2)
Definition: base/logging.h:705
void SetValue(Solver *const s, int index, const T &val)
void SetToZero(Solver *const solver, int64_t row, int64_t column)
Erases the 'column' bit in the 'row' row.
Definition: utilities.cc:178
void SetToOne(Solver *const solver, int64_t row, int64_t column)
Sets the 'column' bit in the 'row' row.
Definition: utilities.cc:170
void ClearAll(Solver *const solver)
Cleans all bits.
Definition: utilities.cc:220
int64_t GetFirstBit(int row, int start) const
Returns the first bit in the row 'row' which position is >= 'start'.
Definition: utilities.cc:204
This class represents a reversible bitset.
void SetToOne(Solver *const solver, int64_t index)
Sets the 'index' bit.
Definition: utilities.cc:84
bool IsCardinalityOne() const
Does it contains only one bit set?
Definition: utilities.cc:129
void SetToZero(Solver *const solver, int64_t index)
Erases the 'index' bit.
Definition: utilities.cc:95
int64_t Cardinality() const
Returns the number of bits set to one.
Definition: utilities.cc:112
int64_t GetFirstBit(int start) const
Gets the index of the first bit set starting from start.
Definition: utilities.cc:147
bool IsSet(int64_t index) const
Returns whether the 'index' bit is set.
Definition: utilities.cc:106
void ClearAll(Solver *const solver)
Cleans all bits.
Definition: utilities.cc:151
bool IsCardinalityZero() const
Is bitset null?
Definition: utilities.cc:120
void SetValue(Solver *const s, const T &val)
void Insert(Solver *const solver, const T &elt)
void Remove(Solver *const solver, const T &value_index)
int64_t Cardinality() const
Returns the number of bits set to one.
Definition: utilities.cc:48
void SetToZero(Solver *const solver, int64_t pos)
Erases the 'pos' bit.
Definition: utilities.cc:43
int64_t GetFirstOne() const
Gets the index of the first bit set starting from 0.
Definition: utilities.cc:52
void SetToOne(Solver *const solver, int64_t pos)
Sets the 'pos' bit.
Definition: utilities.cc:38
void SaveValue(T *o)
reversibility
ModelVisitor * MakeVariableDegreeVisitor(absl::flat_hash_map< const IntVar *, int > *const map)
Compute the number of constraints a variable is attached to.
Definition: utilities.cc:821
uint64_t stamp() const
The stamp indicates how many moves in the search tree we have performed.
ModelVisitor * MakePrintModelVisitor()
Prints the model.
Definition: utilities.cc:813
T * RevAlloc(T *object)
Registers the given object as being reversible.
ModelVisitor * MakeStatisticsModelVisitor()
Displays some nice statistics on the model.
Definition: utilities.cc:817
bool RevSubtract(Solver *const solver, const std::vector< uint64_t > &mask)
This method subtracts the mask from the active bitset.
Definition: utilities.cc:243
void Init(Solver *const solver, const std::vector< uint64_t > &mask)
This methods overwrites the active bitset with the mask.
Definition: utilities.cc:232
bool RevAnd(Solver *const solver, const std::vector< uint64_t > &mask)
This method ANDs the mask with the active bitset.
Definition: utilities.cc:270
bool Intersects(const std::vector< uint64_t > &mask, int *support_index)
This method returns true iff the mask and the active bitset have a non null intersection.
Definition: utilities.cc:295
UnsortedNullableRevBitset(int bit_size)
Size is the number of bits to store in the bitset.
Definition: utilities.cc:226
int64_t value
IntVar * var
Definition: expr_array.cc:1874
int index
const int INFO
Definition: log_severity.h:31
RowIndex row
Definition: markowitz.cc:182
Collection of objects used to extend the Constraint Solver library.
uint64_t BitCountRange64(const uint64_t *const bitset, uint64_t start, uint64_t end)
uint32_t BitPos64(uint64_t pos)
Definition: bitset.h:330
bool IsEmptyRange64(const uint64_t *const bitset, uint64_t start, uint64_t end)
uint64_t BitCount64(uint64_t n)
Definition: bitset.h:42
std::vector< int64_t > ToInt64Vector(const std::vector< int > &input)
Definition: utilities.cc:828
bool IsBitSet64(const uint64_t *const bitset, uint64_t pos)
Definition: bitset.h:346
uint64_t OneBit64(int pos)
Definition: bitset.h:38
uint64_t BitOffset64(uint64_t pos)
Definition: bitset.h:334
uint64_t BitLength64(uint64_t size)
Definition: bitset.h:338
int LeastSignificantBitPosition64(uint64_t n)
Definition: bitset.h:127
static int input(yyscan_t yyscanner)
std::optional< int64_t > end
int64_t start