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"
31 "Display all trace information, even if the modifiers has no effect");
36class TraceIntVar :
public IntVar {
38 TraceIntVar(Solver*
const solver, IntVar*
const inner)
39 : IntVar(solver), inner_(inner) {
40 if (inner->HasName()) {
41 set_name(inner->name());
46 ~TraceIntVar()
override {}
48 int64_t Min()
const override {
return inner_->Min(); }
50 void SetMin(int64_t m)
override {
51 if (m > inner_->Min()) {
52 solver()->GetPropagationMonitor()->SetMin(inner_, m);
57 int64_t Max()
const override {
return inner_->Max(); }
59 void SetMax(int64_t m)
override {
60 if (m < inner_->Max()) {
61 solver()->GetPropagationMonitor()->SetMax(inner_, m);
66 void Range(int64_t* l, int64_t* u)
override { inner_->Range(l, u); }
68 void SetRange(int64_t l, int64_t u)
override {
69 if (l > inner_->Min() || u < inner_->Max()) {
71 solver()->GetPropagationMonitor()->SetValue(inner_, l);
74 solver()->GetPropagationMonitor()->SetRange(inner_, l, u);
75 inner_->SetRange(l, u);
80 bool Bound()
const override {
return inner_->Bound(); }
82 bool IsVar()
const override {
return true; }
84 IntVar* Var()
override {
return this; }
86 int64_t
Value()
const override {
return inner_->Value(); }
88 void RemoveValue(int64_t v)
override {
89 if (inner_->Contains(v)) {
90 solver()->GetPropagationMonitor()->RemoveValue(inner_, v);
91 inner_->RemoveValue(v);
95 void SetValue(int64_t v)
override {
96 solver()->GetPropagationMonitor()->SetValue(inner_, v);
100 void RemoveInterval(int64_t l, int64_t u)
override {
101 solver()->GetPropagationMonitor()->RemoveInterval(inner_, l, u);
102 inner_->RemoveInterval(l, u);
105 void RemoveValues(
const std::vector<int64_t>& values)
override {
106 solver()->GetPropagationMonitor()->RemoveValues(inner_, values);
107 inner_->RemoveValues(values);
110 void SetValues(
const std::vector<int64_t>& values)
override {
111 solver()->GetPropagationMonitor()->SetValues(inner_, values);
112 inner_->SetValues(values);
115 void WhenRange(Demon* d)
override { inner_->WhenRange(d); }
117 void WhenBound(Demon* d)
override { inner_->WhenBound(d); }
119 void WhenDomain(Demon* d)
override { inner_->WhenDomain(d); }
121 uint64_t Size()
const override {
return inner_->Size(); }
123 bool Contains(int64_t v)
const override {
return inner_->Contains(v); }
125 IntVarIterator* MakeHoleIterator(
bool reversible)
const override {
126 return inner_->MakeHoleIterator(reversible);
129 IntVarIterator* MakeDomainIterator(
bool reversible)
const override {
130 return inner_->MakeDomainIterator(reversible);
133 int64_t OldMin()
const override {
return inner_->OldMin(); }
135 int64_t OldMax()
const override {
return inner_->OldMax(); }
137 int VarType()
const override {
return TRACE_VAR; }
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);
150 std::string DebugString()
const override {
return inner_->DebugString(); }
152 IntVar* IsEqual(int64_t constant)
override {
153 return inner_->IsEqual(constant);
156 IntVar* IsDifferent(int64_t constant)
override {
157 return inner_->IsDifferent(constant);
160 IntVar* IsGreaterOrEqual(int64_t constant)
override {
161 return inner_->IsGreaterOrEqual(constant);
164 IntVar* IsLessOrEqual(int64_t constant)
override {
165 return inner_->IsLessOrEqual(constant);
169 IntVar*
const inner_;
172class TraceIntExpr :
public IntExpr {
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());
182 ~TraceIntExpr()
override {}
184 int64_t Min()
const override {
return inner_->Min(); }
186 void SetMin(int64_t m)
override {
187 solver()->GetPropagationMonitor()->SetMin(inner_, m);
191 int64_t Max()
const override {
return inner_->Max(); }
193 void SetMax(int64_t m)
override {
194 solver()->GetPropagationMonitor()->SetMax(inner_, m);
198 void Range(int64_t* l, int64_t* u)
override { inner_->Range(l, u); }
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);
207 bool Bound()
const override {
return inner_->Bound(); }
209 bool IsVar()
const override {
210 DCHECK(!inner_->IsVar());
214 IntVar* Var()
override {
return solver()->RegisterIntVar(inner_->Var()); }
216 void WhenRange(Demon* d)
override { inner_->WhenRange(d); }
218 void Accept(ModelVisitor*
const visitor)
const override {
225 std::string DebugString()
const override {
return inner_->DebugString(); }
228 IntExpr*
const inner_;
231class TraceIntervalVar :
public IntervalVar {
233 TraceIntervalVar(Solver*
const solver, IntervalVar*
const inner)
234 : IntervalVar(solver,
""), inner_(inner) {
235 if (inner->HasName()) {
236 set_name(inner->name());
239 ~TraceIntervalVar()
override {}
241 int64_t StartMin()
const override {
return inner_->StartMin(); }
243 int64_t StartMax()
const override {
return inner_->StartMax(); }
245 void SetStartMin(int64_t m)
override {
246 if (inner_->MayBePerformed() && (m > inner_->StartMin())) {
247 solver()->GetPropagationMonitor()->SetStartMin(inner_, m);
248 inner_->SetStartMin(m);
252 void SetStartMax(int64_t m)
override {
253 if (inner_->MayBePerformed() && (m < inner_->StartMax())) {
254 solver()->GetPropagationMonitor()->SetStartMax(inner_, m);
255 inner_->SetStartMax(m);
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);
267 int64_t OldStartMin()
const override {
return inner_->OldStartMin(); }
269 int64_t OldStartMax()
const override {
return inner_->OldStartMax(); }
271 void WhenStartRange(Demon*
const d)
override { inner_->WhenStartRange(d); }
273 void WhenStartBound(Demon*
const d)
override { inner_->WhenStartBound(d); }
275 int64_t EndMin()
const override {
return inner_->EndMin(); }
277 int64_t EndMax()
const override {
return inner_->EndMax(); }
279 void SetEndMin(int64_t m)
override {
280 if (inner_->MayBePerformed() && (m > inner_->EndMin())) {
281 solver()->GetPropagationMonitor()->SetEndMin(inner_, m);
282 inner_->SetEndMin(m);
286 void SetEndMax(int64_t m)
override {
287 if (inner_->MayBePerformed() && (m < inner_->EndMax())) {
288 solver()->GetPropagationMonitor()->SetEndMax(inner_, m);
289 inner_->SetEndMax(m);
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);
301 int64_t OldEndMin()
const override {
return inner_->OldEndMin(); }
303 int64_t OldEndMax()
const override {
return inner_->OldEndMax(); }
305 void WhenEndRange(Demon*
const d)
override { inner_->WhenEndRange(d); }
307 void WhenEndBound(Demon*
const d)
override { inner_->WhenStartBound(d); }
309 int64_t DurationMin()
const override {
return inner_->DurationMin(); }
311 int64_t DurationMax()
const override {
return inner_->DurationMax(); }
313 void SetDurationMin(int64_t m)
override {
314 if (inner_->MayBePerformed() && (m > inner_->DurationMin())) {
315 solver()->GetPropagationMonitor()->SetDurationMin(inner_, m);
316 inner_->SetDurationMin(m);
320 void SetDurationMax(int64_t m)
override {
321 if (inner_->MayBePerformed() && (m < inner_->DurationMax())) {
322 solver()->GetPropagationMonitor()->SetDurationMax(inner_, m);
323 inner_->SetDurationMax(m);
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);
335 int64_t OldDurationMin()
const override {
return inner_->OldDurationMin(); }
337 int64_t OldDurationMax()
const override {
return inner_->OldDurationMax(); }
339 void WhenDurationRange(Demon*
const d)
override {
340 inner_->WhenDurationRange(d);
343 void WhenDurationBound(Demon*
const d)
override {
344 inner_->WhenDurationBound(d);
347 bool MustBePerformed()
const override {
return inner_->MustBePerformed(); }
349 bool MayBePerformed()
const override {
return inner_->MayBePerformed(); }
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);
359 bool WasPerformedBound()
const override {
360 return inner_->WasPerformedBound();
363 void WhenPerformedBound(Demon*
const d)
override {
364 inner_->WhenPerformedBound(d);
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);
374 IntExpr* SafeDurationExpr(int64_t unperformed_value)
override {
375 return inner_->SafeDurationExpr(unperformed_value);
377 IntExpr* SafeEndExpr(int64_t unperformed_value)
override {
378 return inner_->SafeEndExpr(unperformed_value);
381 void Accept(ModelVisitor*
const visitor)
const override {
382 inner_->Accept(visitor);
385 std::string DebugString()
const override {
return inner_->DebugString(); }
388 IntervalVar*
const inner_;
393class PrintTrace :
public PropagationMonitor {
411 explicit Context(
int start_indent)
442 explicit PrintTrace(Solver*
const s) : PropagationMonitor(s) {
443 contexes_.push(Context());
446 ~PrintTrace()
override {}
450 void BeginInitialPropagation()
override {
452 DisplaySearch(
"Root Node Propagation");
455 void EndInitialPropagation()
override {
457 DisplaySearch(
"Starting Tree Search");
460 void BeginNextDecision(DecisionBuilder*
const b)
override {
461 DisplaySearch(absl::StrFormat(
"DecisionBuilder(%s)",
b->DebugString()));
463 contexes_.top().in_decision_builder =
true;
467 void EndNextDecision(DecisionBuilder*
const b, Decision*
const d)
override {
468 contexes_.top().in_decision_builder =
false;
472 void BeginFail()
override {
473 contexes_.top().Clear();
474 while (!contexes_.top().TopLevel()) {
476 LOG(INFO) << Indent() <<
"}";
479 absl::StrFormat(
"Failure at depth %d", solver()->SearchDepth()));
482 bool AtSolution()
override {
484 absl::StrFormat(
"Solution found at depth %d", solver()->SearchDepth()));
488 void ApplyDecision(Decision*
const decision)
override {
490 absl::StrFormat(
"ApplyDecision(%s)", decision->DebugString()));
492 contexes_.top().in_decision =
true;
495 void RefuteDecision(Decision*
const decision)
override {
496 if (contexes_.top().in_objective) {
498 contexes_.top().in_objective =
false;
501 absl::StrFormat(
"RefuteDecision(%s)", decision->DebugString()));
503 contexes_.top().in_decision =
true;
506 void AfterDecision(Decision*
const decision,
bool direction)
override {
508 contexes_.top().in_decision =
false;
511 void EnterSearch()
override {
512 if (solver()->SolveDepth() == 0) {
513 CHECK_EQ(1, contexes_.size());
514 contexes_.top().Clear();
516 PrintDelayedString();
519 DisplaySearch(
"Enter Search");
522 void ExitSearch()
override {
523 DisplaySearch(
"Exit Search");
524 CHECK(contexes_.top().TopLevel());
525 if (solver()->SolveDepth() > 1) {
530 void RestartSearch()
override { CHECK(contexes_.top().TopLevel()); }
534 void BeginConstraintInitialPropagation(
535 Constraint*
const constraint)
override {
537 absl::StrFormat(
"Constraint(%s)", constraint->DebugString()));
538 contexes_.top().in_constraint =
true;
541 void EndConstraintInitialPropagation(Constraint*
const constraint)
override {
543 contexes_.top().in_constraint =
false;
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;
551 void EndNestedConstraintInitialPropagation(Constraint*
const,
552 Constraint*
const)
override {
554 contexes_.top().in_constraint =
false;
559 void BeginDemonRun(Demon*
const demon)
override {
561 contexes_.top().in_demon =
true;
562 PushDelayedInfo(absl::StrFormat(
"Demon(%s)", demon->DebugString()));
566 void EndDemonRun(Demon*
const demon)
override {
568 contexes_.top().in_demon =
false;
573 void StartProcessingIntegerVariable(IntVar*
const var)
override {
574 PushDelayedInfo(absl::StrFormat(
"StartProcessing(%s)",
var->DebugString()));
577 void EndProcessingIntegerVariable(IntVar*
const var)
override {
581 void PushContext(
const std::string&
context)
override {
585 void PopContext()
override { PopDelayedInfo(); }
589 void SetMin(IntExpr*
const expr, int64_t new_min)
override {
591 absl::StrFormat(
"SetMin(%s, %d)", expr->DebugString(), new_min));
594 void SetMax(IntExpr*
const expr, int64_t new_max)
override {
596 absl::StrFormat(
"SetMax(%s, %d)", expr->DebugString(), new_max));
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));
607 void SetMin(IntVar*
const var, int64_t new_min)
override {
609 absl::StrFormat(
"SetMin(%s, %d)",
var->DebugString(), new_min));
612 void SetMax(IntVar*
const var, int64_t new_max)
override {
614 absl::StrFormat(
"SetMax(%s, %d)",
var->DebugString(), new_max));
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));
622 void RemoveValue(IntVar*
const var, int64_t
value)
override {
624 absl::StrFormat(
"RemoveValue(%s, %d)",
var->DebugString(),
value));
627 void SetValue(IntVar*
const var, int64_t
value)
override {
629 absl::StrFormat(
"SetValue(%s, %d)",
var->DebugString(),
value));
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));
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,
", ")));
643 void RemoveValues(IntVar*
const var,
644 const std::vector<int64_t>& values)
override {
645 DisplayModification(absl::StrFormat(
"RemoveValues(%s, %s)",
647 absl::StrJoin(values,
", ")));
652 void SetStartMin(IntervalVar*
const var, int64_t new_min)
override {
654 absl::StrFormat(
"SetStartMin(%s, %d)",
var->DebugString(), new_min));
657 void SetStartMax(IntervalVar*
const var, int64_t new_max)
override {
659 absl::StrFormat(
"SetStartMax(%s, %d)",
var->DebugString(), new_max));
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));
668 void SetEndMin(IntervalVar*
const var, int64_t new_min)
override {
670 absl::StrFormat(
"SetEndMin(%s, %d)",
var->DebugString(), new_min));
673 void SetEndMax(IntervalVar*
const var, int64_t new_max)
override {
675 absl::StrFormat(
"SetEndMax(%s, %d)",
var->DebugString(), new_max));
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));
684 void SetDurationMin(IntervalVar*
const var, int64_t new_min)
override {
686 absl::StrFormat(
"SetDurationMin(%s, %d)",
var->DebugString(), new_min));
689 void SetDurationMax(IntervalVar*
const var, int64_t new_max)
override {
691 absl::StrFormat(
"SetDurationMax(%s, %d)",
var->DebugString(), new_max));
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));
700 void SetPerformed(IntervalVar*
const var,
bool value)
override {
702 absl::StrFormat(
"SetPerformed(%s, %d)",
var->DebugString(),
value));
705 void RankFirst(SequenceVar*
const var,
int index)
override {
707 absl::StrFormat(
"RankFirst(%s, %d)",
var->DebugString(),
index));
710 void RankNotFirst(SequenceVar*
const var,
int index)
override {
712 absl::StrFormat(
"RankNotFirst(%s, %d)",
var->DebugString(),
index));
715 void RankLast(SequenceVar*
const var,
int index)
override {
717 absl::StrFormat(
"RankLast(%s, %d)",
var->DebugString(),
index));
720 void RankNotLast(SequenceVar*
const var,
int index)
override {
722 absl::StrFormat(
"RankNotLast(%s, %d)",
var->DebugString(),
index));
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,
", ")));
734 void Install()
override {
736 if (solver()->SolveDepth() <= 1) {
737 solver()->AddPropagationMonitor(
this);
741 std::string DebugString()
const override {
return "PrintTrace"; }
744 void PushDelayedInfo(
const std::string& delayed) {
745 if (absl::GetFlag(FLAGS_cp_full_trace)) {
746 LOG(INFO) << Indent() << delayed <<
" {";
749 contexes_.top().delayed_info.push_back(Info(delayed));
753 void PopDelayedInfo() {
754 if (absl::GetFlag(FLAGS_cp_full_trace)) {
756 LOG(INFO) << Indent() <<
"}";
758 CHECK(!contexes_.top().delayed_info.empty());
759 if (contexes_.top().delayed_info.back().displayed &&
760 !contexes_.top().TopLevel()) {
762 LOG(INFO) << Indent() <<
"}";
764 contexes_.top().delayed_info.pop_back();
769 void CheckNoDelayed() { CHECK(contexes_.top().delayed_info.empty()); }
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 <<
" {";
779 contexes_.top().delayed_info[
i].displayed =
true;
784 void DisplayModification(
const std::string& to_print) {
785 if (absl::GetFlag(FLAGS_cp_full_trace)) {
786 LOG(INFO) << Indent() << to_print;
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) {
793 LOG(INFO) << Indent() << to_print;
804 CHECK(contexes_.top().TopLevel());
805 DisplaySearch(absl::StrFormat(
"Objective -> %s", to_print));
807 contexes_.top().in_objective =
true;
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;
817 LOG(INFO) << Indent() <<
"######## Nested Search(" << solve_depth - 1
818 <<
"): " << to_print;
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) {
831 void IncreaseIndent() { contexes_.top().indent++; }
833 void DecreaseIndent() {
834 if (contexes_.top().indent > 0) {
835 contexes_.top().indent--;
839 void PushNestedContext() {
844 std::stack<Context> contexes_;
853 return RevAlloc(
new TraceIntExpr(
this, expr));
878 return s->
RevAlloc(
new PrintTrace(s));
virtual bool IsVar() const
Returns true if the expression is indeed a variable.
virtual IntVar * Var()=0
Creates a variable from the expression.
static const char kTraceOperation[]
static const char kExpressionArgument[]
static const char kTrace[]
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.
IntExpr * RegisterIntExpr(IntExpr *expr)
Registers a new IntExpr and wraps it inside a TraceIntExpr if necessary.
IntervalVar * RegisterIntervalVar(IntervalVar *var)
bool InstrumentsVariables() const
Returns whether we are tracing variables.
GurobiMPCallbackContext * context
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).
std::pair< double, double > Range
A range of values, first is the minimum, second is the maximum.
std::function< int64_t(const Model &)> Value(IntegerVariable v)
This checks that the variable is fixed.
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)
std::vector< Info > delayed_info
ABSL_FLAG(bool, cp_full_trace, false, "Display all trace information, even if the modifiers has no effect")