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