OR-Tools  9.2
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"
23 #include "ortools/base/logging.h"
24 #include "ortools/base/map_util.h"
27 #include "ortools/util/bitset.h"
28 
29 namespace operations_research {
30 
31 // ---------- SmallRevBitSet ----------
32 
33 SmallRevBitSet::SmallRevBitSet(int64_t size) : bits_(0LL) {
34  DCHECK_GT(size, 0);
35  DCHECK_LE(size, 64);
36 }
37 
38 void SmallRevBitSet::SetToOne(Solver* const solver, int64_t pos) {
39  DCHECK_GE(pos, 0);
40  bits_.SetValue(solver, bits_.Value() | OneBit64(pos));
41 }
42 
43 void SmallRevBitSet::SetToZero(Solver* const solver, int64_t pos) {
44  DCHECK_GE(pos, 0);
45  bits_.SetValue(solver, bits_.Value() & ~OneBit64(pos));
46 }
47 
48 int64_t SmallRevBitSet::Cardinality() const {
49  return BitCount64(bits_.Value());
50 }
51 
52 int64_t SmallRevBitSet::GetFirstOne() const {
53  if (bits_.Value() == 0) {
54  return -1;
55  }
56  return LeastSignificantBitPosition64(bits_.Value());
57 }
58 
59 // ---------- RevBitSet ----------
60 
61 RevBitSet::RevBitSet(int64_t size)
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 
76 void 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 
84 void 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 
95 void 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 
106 bool RevBitSet::IsSet(int64_t index) const {
107  DCHECK_GE(index, 0);
108  DCHECK_LT(index, size_);
109  return IsBitSet64(bits_, index);
110 }
111 
112 int64_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 
147 int64_t RevBitSet::GetFirstBit(int start) const {
148  return LeastSignificantBitPosition64(bits_, start, size_ - 1);
149 }
150 
151 void 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 
162 RevBitMatrix::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 
170 void 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 
178 void 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 
187 int64_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 
204 int64_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 
220 void 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 
262 void 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 
295 bool 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 
313 namespace {
314 class 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 
523 class 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 gtl::ContainsKey(already_visited_, 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 
714 class 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 (gtl::ContainsKey(*map_, 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 (gtl::ContainsKey(*map_, 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 
828 std::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
void SetToZero(Solver *const solver, int64_t pos)
Erases the 'pos' bit.
Definition: utilities.cc:43
int64_t GetFirstBit(int row, int start) const
Returns the first bit in the row 'row' which position is >= 'start'.
Definition: utilities.cc:204
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 BitLength64(uint64_t size)
Definition: bitset.h:338
bool IsSet(int64_t index) const
Returns whether the 'index' bit is set.
Definition: utilities.cc:106
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 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
#define LOG(severity)
Definition: base/logging.h:420
void ClearAll(Solver *const solver)
Cleans all bits.
Definition: utilities.cc:220
#define DCHECK_GT(val1, val2)
Definition: base/logging.h:895
RowIndex row
Definition: markowitz.cc:182
void ClearAll(Solver *const solver)
Cleans all bits.
Definition: utilities.cc:151
void SetToOne(Solver *const solver, int64_t row, int64_t column)
Sets the 'column' bit in the 'row' row.
Definition: utilities.cc:170
This class represents a reversible bitset.
void SaveValue(T *o)
reversibility
int64_t Cardinality() const
Returns the number of bits set to one.
Definition: utilities.cc:112
std::vector< int64_t > ToInt64Vector(const std::vector< int > &input)
Definition: utilities.cc:828
int64_t GetFirstOne() const
Gets the index of the first bit set starting from 0.
Definition: utilities.cc:52
void SetToZero(Solver *const solver, int64_t row, int64_t column)
Erases the 'column' bit in the 'row' row.
Definition: utilities.cc:178
void Remove(Solver *const solver, const T &value_index)
bool RevAnd(Solver *const solver, const std::vector< uint64_t > &mask)
This method ANDs the mask with the active bitset.
Definition: utilities.cc:270
#define CHECK_LE(val1, val2)
Definition: base/logging.h:704
uint64_t BitOffset64(uint64_t pos)
Definition: bitset.h:334
void SetToOne(Solver *const solver, int64_t pos)
Sets the 'pos' bit.
Definition: utilities.cc:38
bool ContainsKey(const Collection &collection, const Key &key)
Definition: map_util.h:200
uint64_t stamp() const
The stamp indicates how many moves in the search tree we have performed.
bool IsCardinalityZero() const
Is bitset null?
Definition: utilities.cc:120
static int input(yyscan_t yyscanner)
int index
Definition: pack.cc:509
#define DCHECK_GE(val1, val2)
Definition: base/logging.h:894
int64_t GetFirstBit(int start) const
Gets the index of the first bit set starting from start.
Definition: utilities.cc:147
void SetValue(Solver *const s, int index, const T &val)
#define CHECK_EQ(val1, val2)
Definition: base/logging.h:702
UnsortedNullableRevBitset(int bit_size)
Size is the number of bits to store in the bitset.
Definition: utilities.cc:226
T * RevAlloc(T *object)
Registers the given object as being reversible.
RevBitMatrix(int64_t rows, int64_t columns)
Definition: utilities.cc:162
uint64_t BitCountRange64(const uint64_t *const bitset, uint64_t start, uint64_t end)
int LeastSignificantBitPosition64(uint64_t n)
Definition: bitset.h:127
uint64_t BitCount64(uint64_t n)
Definition: bitset.h:42
void Insert(Solver *const solver, const T &elt)
void SetValue(Solver *const s, const T &val)
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 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
#define DCHECK_LE(val1, val2)
Definition: base/logging.h:892
uint32_t BitPos64(uint64_t pos)
Definition: bitset.h:330
Collection of objects used to extend the Constraint Solver library.
bool IsBitSet64(const uint64_t *const bitset, uint64_t pos)
Definition: bitset.h:346
int64_t Cardinality() const
Returns the number of bits set to one.
Definition: utilities.cc:48
bool IsEmptyRange64(const uint64_t *const bitset, uint64_t start, uint64_t end)
IntVar * var
Definition: expr_array.cc:1874
ModelVisitor * MakePrintModelVisitor()
Prints the model.
Definition: utilities.cc:813
ModelVisitor * MakeStatisticsModelVisitor()
Displays some nice statistics on the model.
Definition: utilities.cc:817
int64_t value
uint64_t OneBit64(int pos)
Definition: bitset.h:38
#define DCHECK_LT(val1, val2)
Definition: base/logging.h:893
void SetToZero(Solver *const solver, int64_t index)
Erases the 'index' bit.
Definition: utilities.cc:95
const int INFO
Definition: log_severity.h:31