OR-Tools  9.6
utilities.cc
Go to the documentation of this file.
1 // Copyright 2010-2022 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/strings/str_format.h"
21 #include "absl/strings/str_join.h"
22 #include "ortools/base/hash.h"
24 #include "ortools/base/logging.h"
25 #include "ortools/base/map_util.h"
28 #include "ortools/util/bitset.h"
29 
30 namespace operations_research {
31 
32 // ---------- SmallRevBitSet ----------
33 
34 SmallRevBitSet::SmallRevBitSet(int64_t size) : bits_(0LL) {
35  DCHECK_GT(size, 0);
36  DCHECK_LE(size, 64);
37 }
38 
39 void SmallRevBitSet::SetToOne(Solver* const solver, int64_t pos) {
40  DCHECK_GE(pos, 0);
41  bits_.SetValue(solver, bits_.Value() | OneBit64(pos));
42 }
43 
44 void SmallRevBitSet::SetToZero(Solver* const solver, int64_t pos) {
45  DCHECK_GE(pos, 0);
46  bits_.SetValue(solver, bits_.Value() & ~OneBit64(pos));
47 }
48 
49 int64_t SmallRevBitSet::Cardinality() const {
50  return BitCount64(bits_.Value());
51 }
52 
53 int64_t SmallRevBitSet::GetFirstOne() const {
54  if (bits_.Value() == 0) {
55  return -1;
56  }
57  return LeastSignificantBitPosition64(bits_.Value());
58 }
59 
60 // ---------- RevBitSet ----------
61 
62 RevBitSet::RevBitSet(int64_t size)
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 
77 void 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 
85 void 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 
96 void 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 
107 bool RevBitSet::IsSet(int64_t index) const {
108  DCHECK_GE(index, 0);
109  DCHECK_LT(index, size_);
110  return IsBitSet64(bits_, index);
111 }
112 
113 int64_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 
148 int64_t RevBitSet::GetFirstBit(int start) const {
149  return LeastSignificantBitPosition64(bits_, start, size_ - 1);
150 }
151 
152 void 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 
163 RevBitMatrix::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 
171 void 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 
179 void 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 
188 int64_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 
205 int64_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 
221 void 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 
263 void 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 implicitely 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 
296 bool 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 
314 namespace {
315 class 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(const std::string& prefix) { prefix_ = prefix; }
517 
518  int indent_;
519  std::string prefix_;
520 };
521 
522 // ---------- ModelStatisticsVisitor -----------
523 
524 class 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(const std::string& constraint_type) {
689  constraint_types_[constraint_type]++;
690  }
691 
692  void AddExpressionType(const std::string& expression_type) {
693  expression_types_[expression_type]++;
694  }
695 
696  void AddExtensionType(const std::string& 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 
715 class 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 
829 std::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
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:179
void SetToOne(Solver *const solver, int64_t row, int64_t column)
Sets the 'column' bit in the 'row' row.
Definition: utilities.cc:171
void ClearAll(Solver *const solver)
Cleans all bits.
Definition: utilities.cc:221
int64_t GetFirstBit(int row, int start) const
Returns the first bit in the row 'row' which position is >= 'start'.
Definition: utilities.cc:205
This class represents a reversible bitset.
void SetToOne(Solver *const solver, int64_t index)
Sets the 'index' bit.
Definition: utilities.cc:85
bool IsCardinalityOne() const
Does it contains only one bit set?
Definition: utilities.cc:130
void SetToZero(Solver *const solver, int64_t index)
Erases the 'index' bit.
Definition: utilities.cc:96
int64_t Cardinality() const
Returns the number of bits set to one.
Definition: utilities.cc:113
int64_t GetFirstBit(int start) const
Gets the index of the first bit set starting from start.
Definition: utilities.cc:148
bool IsSet(int64_t index) const
Returns whether the 'index' bit is set.
Definition: utilities.cc:107
void ClearAll(Solver *const solver)
Cleans all bits.
Definition: utilities.cc:152
bool IsCardinalityZero() const
Is bitset null?
Definition: utilities.cc:121
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:49
void SetToZero(Solver *const solver, int64_t pos)
Erases the 'pos' bit.
Definition: utilities.cc:44
int64_t GetFirstOne() const
Gets the index of the first bit set starting from 0.
Definition: utilities.cc:53
void SetToOne(Solver *const solver, int64_t pos)
Sets the 'pos' bit.
Definition: utilities.cc:39
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:822
T * RevAlloc(T *object)
Registers the given object as being reversible.
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:814
ModelVisitor * MakeStatisticsModelVisitor()
Displays some nice statistics on the model.
Definition: utilities.cc:818
bool RevSubtract(Solver *const solver, const std::vector< uint64_t > &mask)
This method subtracts the mask from the active bitset.
Definition: utilities.cc:244
void Init(Solver *const solver, const std::vector< uint64_t > &mask)
This methods overwrites the active bitset with the mask.
Definition: utilities.cc:233
bool RevAnd(Solver *const solver, const std::vector< uint64_t > &mask)
This method ANDs the mask with the active bitset.
Definition: utilities.cc:271
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:296
UnsortedNullableRevBitset(int bit_size)
Size is the number of bits to store in the bitset.
Definition: utilities.cc:227
int64_t value
IntVar * var
Definition: expr_array.cc:1874
int index
RowIndex row
Definition: markowitz.cc:185
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:331
bool IsEmptyRange64(const uint64_t *const bitset, uint64_t start, uint64_t end)
uint64_t BitCount64(uint64_t n)
Definition: bitset.h:43
std::vector< int64_t > ToInt64Vector(const std::vector< int > &input)
Definition: utilities.cc:829
bool IsBitSet64(const uint64_t *const bitset, uint64_t pos)
Definition: bitset.h:347
uint64_t OneBit64(int pos)
Definition: bitset.h:39
uint64_t BitOffset64(uint64_t pos)
Definition: bitset.h:335
uint64_t BitLength64(uint64_t size)
Definition: bitset.h:339
int LeastSignificantBitPosition64(uint64_t n)
Definition: bitset.h:128
int column
Definition: parse_proto.cc:32
static int input(yyscan_t yyscanner)
std::optional< int64_t > end
int64_t start