1 /********************* */
2 /*! \file dagification_visitor.h
4 ** Top contributors (to current version):
5 ** Morgan Deters, Andres Noetzli, Mathias Preiner
6 ** This file is part of the CVC4 project.
7 ** Copyright (c) 2009-2020 by the authors listed in the file AUTHORS
8 ** in the top-level source directory) and their institutional affiliations.
9 ** All rights reserved. See the file COPYING in the top-level source
10 ** directory for licensing information.\endverbatim
12 ** \brief A dagifier for CVC4 expressions
14 ** A dagifier for CVC4 expressions.
17 #include "cvc4_private.h"
19 #ifndef CVC4__PRINTER__DAGIFICATION_VISITOR_H
20 #define CVC4__PRINTER__DAGIFICATION_VISITOR_H
23 #include <unordered_map>
24 #include <unordered_set>
27 #include "expr/node.h"
28 #include "util/hash.h"
34 }/* CVC4::context namespace */
37 class SubstitutionMap
;
38 }/* CVC4::theory namespace */
43 * This is a visitor class (intended to be used with CVC4's NodeVisitor)
44 * that visits an expression looking for common subexpressions that appear
45 * more than N times, where N is a configurable threshold. Afterward,
46 * let bindings can be extracted from this visitor and applied to the
49 * This dagifier never introduces let bindings for variables, constants,
50 * unary-minus exprs over variables or constants, or NOT exprs over
51 * variables or constants. This dagifier never introduces let bindings
54 class DagificationVisitor
{
57 * The threshold for dagification. Subexprs occurring more than this
58 * number of times are dagified.
60 const unsigned d_threshold
;
63 * The prefix for introduced let bindings.
65 const std::string d_letVarPrefix
;
68 * A map of subexprs to their occurrence count.
70 std::unordered_map
<TNode
, unsigned, TNodeHashFunction
> d_nodeCount
;
73 * The set of variable names with the let prefix that appear in the
76 std::unordered_set
<std::string
> d_reservedLetNames
;
79 * The top-most node we are visiting.
84 * This class doesn't operate in a context-dependent fashion, but
85 * SubstitutionMap does, so we need a context.
87 context::Context
* d_context
;
90 * A map of subexprs to their newly-introduced let bindings.
92 theory::SubstitutionMap
* d_substitutions
;
95 * The current count of let bindings. Used to build unique names
101 * Keep track of whether we are done yet (for assertions---this visitor
102 * can only be used one time).
107 * If a subexpr occurs uniquely in one parent expr, this map points to
108 * it. An expr not occurring as a key in this map means we haven't
109 * seen it yet (and its occurrence count should be zero). If an expr
110 * points to the null expr in this map, it means we've seen more than
111 * one parent, so the subexpr doesn't have a unique parent.
113 * This information is kept because if a subexpr occurs more than the
114 * threshold, it is normally subject to dagification. But if it occurs
115 * only in one unique parent expression, and the parent meets the
116 * threshold too, then the parent will be dagified and there's no point
117 * in independently dagifying the child. (If it is beyond the threshold
118 * and occurs in more than one parent, we'll independently dagify.)
120 std::unordered_map
<TNode
, TNode
, TNodeHashFunction
> d_uniqueParent
;
123 * A list of all nodes that meet the occurrence threshold and therefore
124 * *may* be subject to dagification, except for the unique-parent rule
127 std::vector
<TNode
> d_substNodes
;
131 /** Our visitor doesn't return anything. */
132 typedef void return_type
;
135 * Construct a dagification visitor with the given threshold and let
138 * @param threshold the threshold to apply for dagification (must be > 0)
139 * @param letVarPrefix prefix for let bindings (by default, "_let_")
141 DagificationVisitor(unsigned threshold
, std::string letVarPrefix
= "_let_");
144 * Simple destructor, clean up memory.
146 ~DagificationVisitor();
149 * Returns true if "current" has already been visited a sufficient
150 * number of times to make it a candidate for dagification, or if
151 * it cannot ever be subject to dagification.
153 bool alreadyVisited(TNode current
, TNode parent
);
156 * Visit the expr "current", it might be a candidate for a let binder.
158 void visit(TNode current
, TNode parent
);
161 * Marks the node as the starting literal.
163 void start(TNode node
);
166 * Called when we're done with all visitation. Does postprocessing.
168 void done(TNode node
);
171 * Get the let substitutions.
173 const theory::SubstitutionMap
& getLets();
176 * Return the let-substituted expression.
178 Node
getDagifiedBody();
180 };/* class DagificationVisitor */
182 }/* CVC4::printer namespace */
183 }/* CVC4 namespace */
185 #endif /* CVC4__PRINTER__DAGIFICATION_VISITOR_H */