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