OR-Tools  9.6
trace.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 <algorithm>
15 #include <cmath>
16 #include <cstdint>
17 #include <stack>
18 #include <string>
19 #include <utility>
20 #include <vector>
21 
22 #include "absl/container/flat_hash_map.h"
23 #include "absl/strings/str_format.h"
24 #include "absl/strings/str_join.h"
27 #include "ortools/base/logging.h"
28 #include "ortools/base/map_util.h"
31 
32 ABSL_FLAG(bool, cp_full_trace, false,
33  "Display all trace information, even if the modifiers has no effect");
34 
35 namespace operations_research {
36 namespace {
37 // ---------- Code Instrumentation ----------
38 class TraceIntVar : public IntVar {
39  public:
40  TraceIntVar(Solver* const solver, IntVar* const inner)
41  : IntVar(solver), inner_(inner) {
42  if (inner->HasName()) {
43  set_name(inner->name());
44  }
45  CHECK_NE(inner->VarType(), TRACE_VAR);
46  }
47 
48  ~TraceIntVar() override {}
49 
50  int64_t Min() const override { return inner_->Min(); }
51 
52  void SetMin(int64_t m) override {
53  if (m > inner_->Min()) {
54  solver()->GetPropagationMonitor()->SetMin(inner_, m);
55  inner_->SetMin(m);
56  }
57  }
58 
59  int64_t Max() const override { return inner_->Max(); }
60 
61  void SetMax(int64_t m) override {
62  if (m < inner_->Max()) {
63  solver()->GetPropagationMonitor()->SetMax(inner_, m);
64  inner_->SetMax(m);
65  }
66  }
67 
68  void Range(int64_t* l, int64_t* u) override { inner_->Range(l, u); }
69 
70  void SetRange(int64_t l, int64_t u) override {
71  if (l > inner_->Min() || u < inner_->Max()) {
72  if (l == u) {
73  solver()->GetPropagationMonitor()->SetValue(inner_, l);
74  inner_->SetValue(l);
75  } else {
76  solver()->GetPropagationMonitor()->SetRange(inner_, l, u);
77  inner_->SetRange(l, u);
78  }
79  }
80  }
81 
82  bool Bound() const override { return inner_->Bound(); }
83 
84  bool IsVar() const override { return true; }
85 
86  IntVar* Var() override { return this; }
87 
88  int64_t Value() const override { return inner_->Value(); }
89 
90  void RemoveValue(int64_t v) override {
91  if (inner_->Contains(v)) {
92  solver()->GetPropagationMonitor()->RemoveValue(inner_, v);
93  inner_->RemoveValue(v);
94  }
95  }
96 
97  void SetValue(int64_t v) override {
98  solver()->GetPropagationMonitor()->SetValue(inner_, v);
99  inner_->SetValue(v);
100  }
101 
102  void RemoveInterval(int64_t l, int64_t u) override {
103  solver()->GetPropagationMonitor()->RemoveInterval(inner_, l, u);
104  inner_->RemoveInterval(l, u);
105  }
106 
107  void RemoveValues(const std::vector<int64_t>& values) override {
108  solver()->GetPropagationMonitor()->RemoveValues(inner_, values);
109  inner_->RemoveValues(values);
110  }
111 
112  void SetValues(const std::vector<int64_t>& values) override {
113  solver()->GetPropagationMonitor()->SetValues(inner_, values);
114  inner_->SetValues(values);
115  }
116 
117  void WhenRange(Demon* d) override { inner_->WhenRange(d); }
118 
119  void WhenBound(Demon* d) override { inner_->WhenBound(d); }
120 
121  void WhenDomain(Demon* d) override { inner_->WhenDomain(d); }
122 
123  uint64_t Size() const override { return inner_->Size(); }
124 
125  bool Contains(int64_t v) const override { return inner_->Contains(v); }
126 
127  IntVarIterator* MakeHoleIterator(bool reversible) const override {
128  return inner_->MakeHoleIterator(reversible);
129  }
130 
131  IntVarIterator* MakeDomainIterator(bool reversible) const override {
132  return inner_->MakeDomainIterator(reversible);
133  }
134 
135  int64_t OldMin() const override { return inner_->OldMin(); }
136 
137  int64_t OldMax() const override { return inner_->OldMax(); }
138 
139  int VarType() const override { return TRACE_VAR; }
140 
141  void Accept(ModelVisitor* const visitor) const override {
142  IntExpr* const cast_expr =
143  solver()->CastExpression(const_cast<TraceIntVar*>(this));
144  if (cast_expr != nullptr) {
145  visitor->VisitIntegerVariable(this, cast_expr);
146  } else {
147  visitor->VisitIntegerVariable(this, ModelVisitor::kTraceOperation, 0,
148  inner_);
149  }
150  }
151 
152  std::string DebugString() const override { return inner_->DebugString(); }
153 
154  IntVar* IsEqual(int64_t constant) override {
155  return inner_->IsEqual(constant);
156  }
157 
158  IntVar* IsDifferent(int64_t constant) override {
159  return inner_->IsDifferent(constant);
160  }
161 
162  IntVar* IsGreaterOrEqual(int64_t constant) override {
163  return inner_->IsGreaterOrEqual(constant);
164  }
165 
166  IntVar* IsLessOrEqual(int64_t constant) override {
167  return inner_->IsLessOrEqual(constant);
168  }
169 
170  private:
171  IntVar* const inner_;
172 };
173 
174 class TraceIntExpr : public IntExpr {
175  public:
176  TraceIntExpr(Solver* const solver, IntExpr* const inner)
177  : IntExpr(solver), inner_(inner) {
178  CHECK(!inner->IsVar());
179  if (inner->HasName()) {
180  set_name(inner->name());
181  }
182  }
183 
184  ~TraceIntExpr() override {}
185 
186  int64_t Min() const override { return inner_->Min(); }
187 
188  void SetMin(int64_t m) override {
189  solver()->GetPropagationMonitor()->SetMin(inner_, m);
190  inner_->SetMin(m);
191  }
192 
193  int64_t Max() const override { return inner_->Max(); }
194 
195  void SetMax(int64_t m) override {
196  solver()->GetPropagationMonitor()->SetMax(inner_, m);
197  inner_->SetMax(m);
198  }
199 
200  void Range(int64_t* l, int64_t* u) override { inner_->Range(l, u); }
201 
202  void SetRange(int64_t l, int64_t u) override {
203  if (l > inner_->Min() || u < inner_->Max()) {
204  solver()->GetPropagationMonitor()->SetRange(inner_, l, u);
205  inner_->SetRange(l, u);
206  }
207  }
208 
209  bool Bound() const override { return inner_->Bound(); }
210 
211  bool IsVar() const override {
212  DCHECK(!inner_->IsVar());
213  return false;
214  }
215 
216  IntVar* Var() override { return solver()->RegisterIntVar(inner_->Var()); }
217 
218  void WhenRange(Demon* d) override { inner_->WhenRange(d); }
219 
220  void Accept(ModelVisitor* const visitor) const override {
221  visitor->BeginVisitIntegerExpression(ModelVisitor::kTrace, this);
222  visitor->VisitIntegerExpressionArgument(ModelVisitor::kExpressionArgument,
223  inner_);
224  visitor->EndVisitIntegerExpression(ModelVisitor::kTrace, this);
225  }
226 
227  std::string DebugString() const override { return inner_->DebugString(); }
228 
229  private:
230  IntExpr* const inner_;
231 };
232 
233 class TraceIntervalVar : public IntervalVar {
234  public:
235  TraceIntervalVar(Solver* const solver, IntervalVar* const inner)
236  : IntervalVar(solver, ""), inner_(inner) {
237  if (inner->HasName()) {
238  set_name(inner->name());
239  }
240  }
241  ~TraceIntervalVar() override {}
242 
243  int64_t StartMin() const override { return inner_->StartMin(); }
244 
245  int64_t StartMax() const override { return inner_->StartMax(); }
246 
247  void SetStartMin(int64_t m) override {
248  if (inner_->MayBePerformed() && (m > inner_->StartMin())) {
249  solver()->GetPropagationMonitor()->SetStartMin(inner_, m);
250  inner_->SetStartMin(m);
251  }
252  }
253 
254  void SetStartMax(int64_t m) override {
255  if (inner_->MayBePerformed() && (m < inner_->StartMax())) {
256  solver()->GetPropagationMonitor()->SetStartMax(inner_, m);
257  inner_->SetStartMax(m);
258  }
259  }
260 
261  void SetStartRange(int64_t mi, int64_t ma) override {
262  if (inner_->MayBePerformed() &&
263  (mi > inner_->StartMin() || ma < inner_->StartMax())) {
264  solver()->GetPropagationMonitor()->SetStartRange(inner_, mi, ma);
265  inner_->SetStartRange(mi, ma);
266  }
267  }
268 
269  int64_t OldStartMin() const override { return inner_->OldStartMin(); }
270 
271  int64_t OldStartMax() const override { return inner_->OldStartMax(); }
272 
273  void WhenStartRange(Demon* const d) override { inner_->WhenStartRange(d); }
274 
275  void WhenStartBound(Demon* const d) override { inner_->WhenStartBound(d); }
276 
277  int64_t EndMin() const override { return inner_->EndMin(); }
278 
279  int64_t EndMax() const override { return inner_->EndMax(); }
280 
281  void SetEndMin(int64_t m) override {
282  if (inner_->MayBePerformed() && (m > inner_->EndMin())) {
283  solver()->GetPropagationMonitor()->SetEndMin(inner_, m);
284  inner_->SetEndMin(m);
285  }
286  }
287 
288  void SetEndMax(int64_t m) override {
289  if (inner_->MayBePerformed() && (m < inner_->EndMax())) {
290  solver()->GetPropagationMonitor()->SetEndMax(inner_, m);
291  inner_->SetEndMax(m);
292  }
293  }
294 
295  void SetEndRange(int64_t mi, int64_t ma) override {
296  if (inner_->MayBePerformed() &&
297  (mi > inner_->EndMin() || ma < inner_->EndMax())) {
298  solver()->GetPropagationMonitor()->SetEndRange(inner_, mi, ma);
299  inner_->SetEndRange(mi, ma);
300  }
301  }
302 
303  int64_t OldEndMin() const override { return inner_->OldEndMin(); }
304 
305  int64_t OldEndMax() const override { return inner_->OldEndMax(); }
306 
307  void WhenEndRange(Demon* const d) override { inner_->WhenEndRange(d); }
308 
309  void WhenEndBound(Demon* const d) override { inner_->WhenStartBound(d); }
310 
311  int64_t DurationMin() const override { return inner_->DurationMin(); }
312 
313  int64_t DurationMax() const override { return inner_->DurationMax(); }
314 
315  void SetDurationMin(int64_t m) override {
316  if (inner_->MayBePerformed() && (m > inner_->DurationMin())) {
317  solver()->GetPropagationMonitor()->SetDurationMin(inner_, m);
318  inner_->SetDurationMin(m);
319  }
320  }
321 
322  void SetDurationMax(int64_t m) override {
323  if (inner_->MayBePerformed() && (m < inner_->DurationMax())) {
324  solver()->GetPropagationMonitor()->SetDurationMax(inner_, m);
325  inner_->SetDurationMax(m);
326  }
327  }
328 
329  void SetDurationRange(int64_t mi, int64_t ma) override {
330  if (inner_->MayBePerformed() &&
331  (mi > inner_->DurationMin() || ma < inner_->DurationMax())) {
332  solver()->GetPropagationMonitor()->SetDurationRange(inner_, mi, ma);
333  inner_->SetDurationRange(mi, ma);
334  }
335  }
336 
337  int64_t OldDurationMin() const override { return inner_->OldDurationMin(); }
338 
339  int64_t OldDurationMax() const override { return inner_->OldDurationMax(); }
340 
341  void WhenDurationRange(Demon* const d) override {
342  inner_->WhenDurationRange(d);
343  }
344 
345  void WhenDurationBound(Demon* const d) override {
346  inner_->WhenDurationBound(d);
347  }
348 
349  bool MustBePerformed() const override { return inner_->MustBePerformed(); }
350 
351  bool MayBePerformed() const override { return inner_->MayBePerformed(); }
352 
353  void SetPerformed(bool value) override {
354  if ((value && !inner_->MustBePerformed()) ||
355  (!value && inner_->MayBePerformed())) {
356  solver()->GetPropagationMonitor()->SetPerformed(inner_, value);
357  inner_->SetPerformed(value);
358  }
359  }
360 
361  bool WasPerformedBound() const override {
362  return inner_->WasPerformedBound();
363  }
364 
365  void WhenPerformedBound(Demon* const d) override {
366  inner_->WhenPerformedBound(d);
367  }
368 
369  IntExpr* StartExpr() override { return inner_->StartExpr(); }
370  IntExpr* DurationExpr() override { return inner_->DurationExpr(); }
371  IntExpr* EndExpr() override { return inner_->EndExpr(); }
372  IntExpr* PerformedExpr() override { return inner_->PerformedExpr(); }
373  IntExpr* SafeStartExpr(int64_t unperformed_value) override {
374  return inner_->SafeStartExpr(unperformed_value);
375  }
376  IntExpr* SafeDurationExpr(int64_t unperformed_value) override {
377  return inner_->SafeDurationExpr(unperformed_value);
378  }
379  IntExpr* SafeEndExpr(int64_t unperformed_value) override {
380  return inner_->SafeEndExpr(unperformed_value);
381  }
382 
383  void Accept(ModelVisitor* const visitor) const override {
384  inner_->Accept(visitor);
385  }
386 
387  std::string DebugString() const override { return inner_->DebugString(); }
388 
389  private:
390  IntervalVar* const inner_;
391 };
392 
393 // ---------- PrintTrace ----------
394 
395 class PrintTrace : public PropagationMonitor {
396  public:
397  struct Info {
398  explicit Info(const std::string& m) : message(m), displayed(false) {}
399  std::string message;
400  bool displayed;
401  };
402 
403  struct Context {
404  Context()
405  : initial_indent(0),
406  indent(0),
407  in_demon(false),
408  in_constraint(false),
409  in_decision_builder(false),
410  in_decision(false),
411  in_objective(false) {}
412 
413  explicit Context(int start_indent)
414  : initial_indent(start_indent),
415  indent(start_indent),
416  in_demon(false),
417  in_constraint(false),
418  in_decision_builder(false),
419  in_decision(false),
420  in_objective(false) {}
421 
422  bool TopLevel() const { return initial_indent == indent; }
423 
424  void Clear() {
426  in_demon = false;
427  in_constraint = false;
428  in_decision_builder = false;
429  in_decision = false;
430  in_objective = false;
431  delayed_info.clear();
432  }
433 
435  int indent;
436  bool in_demon;
441  std::vector<Info> delayed_info;
442  };
443 
444  explicit PrintTrace(Solver* const s) : PropagationMonitor(s) {
445  contexes_.push(Context());
446  }
447 
448  ~PrintTrace() override {}
449 
450  // ----- Search events -----
451 
452  void BeginInitialPropagation() override {
453  CheckNoDelayed();
454  DisplaySearch("Root Node Propagation");
455  IncreaseIndent();
456  }
457  void EndInitialPropagation() override {
458  DecreaseIndent();
459  DisplaySearch("Starting Tree Search");
460  }
461 
462  void BeginNextDecision(DecisionBuilder* const b) override {
463  DisplaySearch(absl::StrFormat("DecisionBuilder(%s)", b->DebugString()));
464  IncreaseIndent();
465  contexes_.top().in_decision_builder = true;
466  }
467 
468  // After calling DecisionBuilder::Next, along with the returned decision.
469  void EndNextDecision(DecisionBuilder* const b, Decision* const d) override {
470  contexes_.top().in_decision_builder = false;
471  DecreaseIndent();
472  }
473 
474  void BeginFail() override {
475  contexes_.top().Clear();
476  while (!contexes_.top().TopLevel()) {
477  DecreaseIndent();
478  LOG(INFO) << Indent() << "}";
479  }
480  DisplaySearch(
481  absl::StrFormat("Failure at depth %d", solver()->SearchDepth()));
482  }
483 
484  bool AtSolution() override {
485  DisplaySearch(
486  absl::StrFormat("Solution found at depth %d", solver()->SearchDepth()));
487  return false;
488  }
489 
490  void ApplyDecision(Decision* const decision) override {
491  DisplaySearch(
492  absl::StrFormat("ApplyDecision(%s)", decision->DebugString()));
493  IncreaseIndent();
494  contexes_.top().in_decision = true;
495  }
496 
497  void RefuteDecision(Decision* const decision) override {
498  if (contexes_.top().in_objective) {
499  DecreaseIndent();
500  contexes_.top().in_objective = false;
501  }
502  DisplaySearch(
503  absl::StrFormat("RefuteDecision(%s)", decision->DebugString()));
504  IncreaseIndent();
505  contexes_.top().in_decision = true;
506  }
507 
508  void AfterDecision(Decision* const decision, bool direction) override {
509  DecreaseIndent();
510  contexes_.top().in_decision = false;
511  }
512 
513  void EnterSearch() override {
514  if (solver()->SolveDepth() == 0) {
515  CHECK_EQ(1, contexes_.size());
516  contexes_.top().Clear();
517  } else {
518  PrintDelayedString();
519  PushNestedContext();
520  }
521  DisplaySearch("Enter Search");
522  }
523 
524  void ExitSearch() override {
525  DisplaySearch("Exit Search");
526  CHECK(contexes_.top().TopLevel());
527  if (solver()->SolveDepth() > 1) {
528  contexes_.pop();
529  }
530  }
531 
532  void RestartSearch() override { CHECK(contexes_.top().TopLevel()); }
533 
534  // ----- Propagation events -----
535 
536  void BeginConstraintInitialPropagation(
537  Constraint* const constraint) override {
538  PushDelayedInfo(
539  absl::StrFormat("Constraint(%s)", constraint->DebugString()));
540  contexes_.top().in_constraint = true;
541  }
542 
543  void EndConstraintInitialPropagation(Constraint* const constraint) override {
544  PopDelayedInfo();
545  contexes_.top().in_constraint = false;
546  }
547 
548  void BeginNestedConstraintInitialPropagation(
549  Constraint* const parent, Constraint* const nested) override {
550  PushDelayedInfo(absl::StrFormat("Constraint(%s)", nested->DebugString()));
551  contexes_.top().in_constraint = true;
552  }
553  void EndNestedConstraintInitialPropagation(Constraint* const,
554  Constraint* const) override {
555  PopDelayedInfo();
556  contexes_.top().in_constraint = false;
557  }
558 
559  void RegisterDemon(Demon* const demon) override {}
560 
561  void BeginDemonRun(Demon* const demon) override {
562  if (demon->priority() != Solver::VAR_PRIORITY) {
563  contexes_.top().in_demon = true;
564  PushDelayedInfo(absl::StrFormat("Demon(%s)", demon->DebugString()));
565  }
566  }
567 
568  void EndDemonRun(Demon* const demon) override {
569  if (demon->priority() != Solver::VAR_PRIORITY) {
570  contexes_.top().in_demon = false;
571  PopDelayedInfo();
572  }
573  }
574 
575  void StartProcessingIntegerVariable(IntVar* const var) override {
576  PushDelayedInfo(absl::StrFormat("StartProcessing(%s)", var->DebugString()));
577  }
578 
579  void EndProcessingIntegerVariable(IntVar* const var) override {
580  PopDelayedInfo();
581  }
582 
583  void PushContext(const std::string& context) override {
584  PushDelayedInfo(context);
585  }
586 
587  void PopContext() override { PopDelayedInfo(); }
588 
589  // ----- IntExpr modifiers -----
590 
591  void SetMin(IntExpr* const expr, int64_t new_min) override {
592  DisplayModification(
593  absl::StrFormat("SetMin(%s, %d)", expr->DebugString(), new_min));
594  }
595 
596  void SetMax(IntExpr* const expr, int64_t new_max) override {
597  DisplayModification(
598  absl::StrFormat("SetMax(%s, %d)", expr->DebugString(), new_max));
599  }
600 
601  void SetRange(IntExpr* const expr, int64_t new_min,
602  int64_t new_max) override {
603  DisplayModification(absl::StrFormat("SetRange(%s, [%d .. %d])",
604  expr->DebugString(), new_min, new_max));
605  }
606 
607  // ----- IntVar modifiers -----
608 
609  void SetMin(IntVar* const var, int64_t new_min) override {
610  DisplayModification(
611  absl::StrFormat("SetMin(%s, %d)", var->DebugString(), new_min));
612  }
613 
614  void SetMax(IntVar* const var, int64_t new_max) override {
615  DisplayModification(
616  absl::StrFormat("SetMax(%s, %d)", var->DebugString(), new_max));
617  }
618 
619  void SetRange(IntVar* const var, int64_t new_min, int64_t new_max) override {
620  DisplayModification(absl::StrFormat("SetRange(%s, [%d .. %d])",
621  var->DebugString(), new_min, new_max));
622  }
623 
624  void RemoveValue(IntVar* const var, int64_t value) override {
625  DisplayModification(
626  absl::StrFormat("RemoveValue(%s, %d)", var->DebugString(), value));
627  }
628 
629  void SetValue(IntVar* const var, int64_t value) override {
630  DisplayModification(
631  absl::StrFormat("SetValue(%s, %d)", var->DebugString(), value));
632  }
633 
634  void RemoveInterval(IntVar* const var, int64_t imin, int64_t imax) override {
635  DisplayModification(absl::StrFormat("RemoveInterval(%s, [%d .. %d])",
636  var->DebugString(), imin, imax));
637  }
638 
639  void SetValues(IntVar* const var,
640  const std::vector<int64_t>& values) override {
641  DisplayModification(absl::StrFormat("SetValues(%s, %s)", var->DebugString(),
642  absl::StrJoin(values, ", ")));
643  }
644 
645  void RemoveValues(IntVar* const var,
646  const std::vector<int64_t>& values) override {
647  DisplayModification(absl::StrFormat("RemoveValues(%s, %s)",
648  var->DebugString(),
649  absl::StrJoin(values, ", ")));
650  }
651 
652  // ----- IntervalVar modifiers -----
653 
654  void SetStartMin(IntervalVar* const var, int64_t new_min) override {
655  DisplayModification(
656  absl::StrFormat("SetStartMin(%s, %d)", var->DebugString(), new_min));
657  }
658 
659  void SetStartMax(IntervalVar* const var, int64_t new_max) override {
660  DisplayModification(
661  absl::StrFormat("SetStartMax(%s, %d)", var->DebugString(), new_max));
662  }
663 
664  void SetStartRange(IntervalVar* const var, int64_t new_min,
665  int64_t new_max) override {
666  DisplayModification(absl::StrFormat("SetStartRange(%s, [%d .. %d])",
667  var->DebugString(), new_min, new_max));
668  }
669 
670  void SetEndMin(IntervalVar* const var, int64_t new_min) override {
671  DisplayModification(
672  absl::StrFormat("SetEndMin(%s, %d)", var->DebugString(), new_min));
673  }
674 
675  void SetEndMax(IntervalVar* const var, int64_t new_max) override {
676  DisplayModification(
677  absl::StrFormat("SetEndMax(%s, %d)", var->DebugString(), new_max));
678  }
679 
680  void SetEndRange(IntervalVar* const var, int64_t new_min,
681  int64_t new_max) override {
682  DisplayModification(absl::StrFormat("SetEndRange(%s, [%d .. %d])",
683  var->DebugString(), new_min, new_max));
684  }
685 
686  void SetDurationMin(IntervalVar* const var, int64_t new_min) override {
687  DisplayModification(
688  absl::StrFormat("SetDurationMin(%s, %d)", var->DebugString(), new_min));
689  }
690 
691  void SetDurationMax(IntervalVar* const var, int64_t new_max) override {
692  DisplayModification(
693  absl::StrFormat("SetDurationMax(%s, %d)", var->DebugString(), new_max));
694  }
695 
696  void SetDurationRange(IntervalVar* const var, int64_t new_min,
697  int64_t new_max) override {
698  DisplayModification(absl::StrFormat("SetDurationRange(%s, [%d .. %d])",
699  var->DebugString(), new_min, new_max));
700  }
701 
702  void SetPerformed(IntervalVar* const var, bool value) override {
703  DisplayModification(
704  absl::StrFormat("SetPerformed(%s, %d)", var->DebugString(), value));
705  }
706 
707  void RankFirst(SequenceVar* const var, int index) override {
708  DisplayModification(
709  absl::StrFormat("RankFirst(%s, %d)", var->DebugString(), index));
710  }
711 
712  void RankNotFirst(SequenceVar* const var, int index) override {
713  DisplayModification(
714  absl::StrFormat("RankNotFirst(%s, %d)", var->DebugString(), index));
715  }
716 
717  void RankLast(SequenceVar* const var, int index) override {
718  DisplayModification(
719  absl::StrFormat("RankLast(%s, %d)", var->DebugString(), index));
720  }
721 
722  void RankNotLast(SequenceVar* const var, int index) override {
723  DisplayModification(
724  absl::StrFormat("RankNotLast(%s, %d)", var->DebugString(), index));
725  }
726 
727  void RankSequence(SequenceVar* const var, const std::vector<int>& rank_first,
728  const std::vector<int>& rank_last,
729  const std::vector<int>& unperformed) override {
730  DisplayModification(absl::StrFormat(
731  "RankSequence(%s, forward [%s], backward[%s], unperformed[%s])",
732  var->DebugString(), absl::StrJoin(rank_first, ", "),
733  absl::StrJoin(rank_last, ", "), absl::StrJoin(unperformed, ", ")));
734  }
735 
736  void Install() override {
738  if (solver()->SolveDepth() <= 1) {
739  solver()->AddPropagationMonitor(this);
740  }
741  }
742 
743  std::string DebugString() const override { return "PrintTrace"; }
744 
745  private:
746  void PushDelayedInfo(const std::string& delayed) {
747  if (absl::GetFlag(FLAGS_cp_full_trace)) {
748  LOG(INFO) << Indent() << delayed << " {";
749  IncreaseIndent();
750  } else {
751  contexes_.top().delayed_info.push_back(Info(delayed));
752  }
753  }
754 
755  void PopDelayedInfo() {
756  if (absl::GetFlag(FLAGS_cp_full_trace)) {
757  DecreaseIndent();
758  LOG(INFO) << Indent() << "}";
759  } else {
760  CHECK(!contexes_.top().delayed_info.empty());
761  if (contexes_.top().delayed_info.back().displayed &&
762  !contexes_.top().TopLevel()) {
763  DecreaseIndent();
764  LOG(INFO) << Indent() << "}";
765  } else {
766  contexes_.top().delayed_info.pop_back();
767  }
768  }
769  }
770 
771  void CheckNoDelayed() { CHECK(contexes_.top().delayed_info.empty()); }
772 
773  void PrintDelayedString() {
774  const std::vector<Info>& infos = contexes_.top().delayed_info;
775  for (int i = 0; i < infos.size(); ++i) {
776  const Info& info = infos[i];
777  if (!info.displayed) {
778  LOG(INFO) << Indent() << info.message << " {";
779  IncreaseIndent();
780  // Marks it as displayed.
781  contexes_.top().delayed_info[i].displayed = true;
782  }
783  }
784  }
785 
786  void DisplayModification(const std::string& to_print) {
787  if (absl::GetFlag(FLAGS_cp_full_trace)) {
788  LOG(INFO) << Indent() << to_print;
789  } else {
790  PrintDelayedString();
791  if (contexes_.top().in_demon || contexes_.top().in_constraint ||
792  contexes_.top().in_decision_builder || contexes_.top().in_decision ||
793  contexes_.top().in_objective) {
794  // Inside a demon, constraint, decision builder -> normal print.
795  LOG(INFO) << Indent() << to_print;
796  } else {
797  // Top level, modification pushed by the objective. This is a
798  // hack. The SetMax or SetMin done by the objective happens in
799  // the RefuteDecision callback of search monitors. We cannot
800  // easily differentiate that from the actual modifications done
801  // by the Refute() call itself. To distinguish that, we force
802  // the print trace to be last in the list of monitors. Thus
803  // modifications that happens at the top level before the
804  // RefuteDecision() callbacks must be from the objective.
805  // In that case, we push the in_objective context.
806  CHECK(contexes_.top().TopLevel());
807  DisplaySearch(absl::StrFormat("Objective -> %s", to_print));
808  IncreaseIndent();
809  contexes_.top().in_objective = true;
810  }
811  }
812  }
813 
814  void DisplaySearch(const std::string& to_print) {
815  const int solve_depth = solver()->SolveDepth();
816  if (solve_depth <= 1) {
817  LOG(INFO) << Indent() << "######## Top Level Search: " << to_print;
818  } else {
819  LOG(INFO) << Indent() << "######## Nested Search(" << solve_depth - 1
820  << "): " << to_print;
821  }
822  }
823 
824  std::string Indent() {
825  CHECK_GE(contexes_.top().indent, 0);
826  std::string output = " @ ";
827  for (int i = 0; i < contexes_.top().indent; ++i) {
828  output.append(" ");
829  }
830  return output;
831  }
832 
833  void IncreaseIndent() { contexes_.top().indent++; }
834 
835  void DecreaseIndent() {
836  if (contexes_.top().indent > 0) {
837  contexes_.top().indent--;
838  }
839  }
840 
841  void PushNestedContext() {
842  const int initial_indent = contexes_.top().indent;
843  contexes_.push(Context(initial_indent));
844  }
845 
846  std::stack<Context> contexes_;
847 };
848 } // namespace
849 
851  if (InstrumentsVariables()) {
852  if (expr->IsVar()) {
853  return RegisterIntVar(expr->Var());
854  } else {
855  return RevAlloc(new TraceIntExpr(this, expr));
856  }
857  } else {
858  return expr;
859  }
860 }
861 
863  if (InstrumentsVariables() && var->VarType() != TRACE_VAR) { // Not already a
864  // trace var.
865  return RevAlloc(new TraceIntVar(this, var));
866  } else {
867  return var;
868  }
869 }
870 
872  if (InstrumentsVariables()) {
873  return RevAlloc(new TraceIntervalVar(this, var));
874  } else {
875  return var;
876  }
877 }
878 
880  return s->RevAlloc(new PrintTrace(s));
881 }
882 } // namespace operations_research
The class IntExpr is the base of all integer expressions in constraint programming.
virtual IntVar * Var()=0
Creates a variable from the expression.
virtual bool IsVar() const
Returns true if the expression is indeed a variable.
The class IntVar is a subset of IntExpr.
Interval variables are often used in scheduling.
virtual void Install()
Registers itself on the solver such that it gets notified of the search and propagation events.
IntExpr * RegisterIntExpr(IntExpr *const expr)
Registers a new IntExpr and wraps it inside a TraceIntExpr if necessary.
Definition: trace.cc:850
@ VAR_PRIORITY
VAR_PRIORITY is between DELAYED_PRIORITY and NORMAL_PRIORITY.
IntVar * RegisterIntVar(IntVar *const var)
Registers a new IntVar and wraps it inside a TraceIntVar if necessary.
Definition: trace.cc:862
bool InstrumentsVariables() const
Returns whether we are tracing variables.
T * RevAlloc(T *object)
Registers the given object as being reversible.
IntervalVar * RegisterIntervalVar(IntervalVar *const var)
Registers a new IntervalVar and wraps it inside a TraceIntervalVar if necessary.
Definition: trace.cc:871
int64_t b
int64_t value
IntVar * var
Definition: expr_array.cc:1874
GurobiMPCallbackContext * context
int index
std::pair< double, double > Range
Definition: statistics.h:27
std::function< int64_t(const Model &)> Value(IntegerVariable v)
Definition: integer.h:1795
Collection of objects used to extend the Constraint Solver library.
PropagationMonitor * BuildPrintTrace(Solver *const s)
Definition: trace.cc:879
void RegisterDemon(Solver *const solver, Demon *const demon, DemonProfiler *const monitor)
bool in_decision_builder
Definition: trace.cc:438
bool in_decision
Definition: trace.cc:439
bool displayed
Definition: trace.cc:400
std::string message
Definition: trace.cc:399
int initial_indent
Definition: trace.cc:434
int indent
Definition: trace.cc:435
std::vector< Info > delayed_info
Definition: trace.cc:441
bool in_demon
Definition: trace.cc:436
bool in_objective
Definition: trace.cc:440
bool in_constraint
Definition: trace.cc:437
ABSL_FLAG(bool, cp_full_trace, false, "Display all trace information, even if the modifiers has no effect")