1 /*********************                                                        */
2 /*! \file datatypes_rewriter.h
3  ** \verbatim
4  ** Top contributors (to current version):
5  **   Andrew Reynolds, Morgan Deters, Dejan Jovanovic
6  ** This file is part of the CVC4 project.
7  ** Copyright (c) 2009-2019 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
11  **
12  ** \brief Rewriter for the theory of (co)inductive datatypes
13  **
14  ** Rewriter for the theory of (co)inductive datatypes.
15  **/
16 
17 #include "cvc4_private.h"
18 
19 #ifndef __CVC4__THEORY__DATATYPES__DATATYPES_REWRITER_H
20 #define __CVC4__THEORY__DATATYPES__DATATYPES_REWRITER_H
21 
22 #include "expr/node_manager_attributes.h"
23 #include "options/datatypes_options.h"
24 #include "theory/rewriter.h"
25 #include "theory/type_enumerator.h"
26 
27 namespace CVC4 {
28 namespace theory {
29 
30 /** sygus var num */
31 struct SygusVarNumAttributeId
32 {
33 };
34 typedef expr::Attribute<SygusVarNumAttributeId, uint64_t> SygusVarNumAttribute;
35 
36 /** Attribute true for variables that represent any constant */
37 struct SygusAnyConstAttributeId
38 {
39 };
40 typedef expr::Attribute<SygusAnyConstAttributeId, bool> SygusAnyConstAttribute;
41 
42 /**
43  * Attribute true for enumerators whose current model values were registered by
44  * the datatypes sygus solver, and were not excluded by sygus symmetry breaking.
45  * This is set by the datatypes sygus solver during LAST_CALL effort checks for
46  * each active sygus enumerator.
47  */
48 struct SygusSymBreakOkAttributeId
49 {
50 };
51 typedef expr::Attribute<SygusSymBreakOkAttributeId, bool>
52     SygusSymBreakOkAttribute;
53 
54 namespace datatypes {
55 
56 class DatatypesRewriter {
57 public:
58  static RewriteResponse postRewrite(TNode in);
59 
60  static RewriteResponse preRewrite(TNode in);
61 
init()62  static inline void init() {}
shutdown()63  static inline void shutdown() {}
64  /** get instantiate cons
65   *
66   * This returns the term C( sel^{C,1}( n ), ..., sel^{C,m}( n ) ),
67   * where C is the index^{th} constructor of datatype dt.
68   */
69  static Node getInstCons(Node n, const Datatype& dt, int index);
70  /** is instantiation cons
71   *
72   * If this method returns a value >=0, then that value, call it index,
73   * is such that n = C( sel^{C,1}( t ), ..., sel^{C,m}( t ) ),
74   * where C is the index^{th} constructor of dt.
75   */
76  static int isInstCons(Node t, Node n, const Datatype& dt);
77  /** is tester
78   *
79   * This method returns a value >=0 if n is a tester predicate. The return
80   * value indicates the constructor index that the tester n is for. If this
81   * method returns a value >=0, then it updates a to the argument that the
82   * tester n applies to.
83   */
84  static int isTester(Node n, Node& a);
85  /** is tester, same as above but does not update an argument */
86  static int isTester(Node n);
87  /**
88   * Get the index of a constructor or tester in its datatype, or the
89   * index of a selector in its constructor.  (Zero is always the
90   * first index.)
91   */
92  static unsigned indexOf(Node n);
93  /** make tester is-C( n ), where C is the i^{th} constructor of dt */
94  static Node mkTester(Node n, int i, const Datatype& dt);
95  /** make tester split
96   *
97   * Returns the formula (OR is-C1( n ) ... is-Ck( n ) ), where C1...Ck
98   * are the constructors of n's type (dt).
99   */
100  static Node mkSplit(Node n, const Datatype& dt);
101  /** returns true iff n is a constructor term with no datatype children */
102  static bool isNullaryApplyConstructor(Node n);
103  /** returns true iff c is a constructor with no datatype children */
104  static bool isNullaryConstructor(const DatatypeConstructor& c);
105  /** normalize codatatype constant
106   *
107   * This returns the normal form of the codatatype constant n. This runs a
108   * DFA minimization algorithm based on the private functions below.
109   *
110   * In particular, we first call collectRefs to setup initial information
111   * about what terms occur in n. Then, we run a DFA minimization algorithm to
112   * partition these subterms in equivalence classes. Finally, we call
113   * normalizeCodatatypeConstantEqc to construct the normalized codatatype
114   * constant that is equivalent to n.
115   */
116  static Node normalizeCodatatypeConstant(Node n);
117  /** normalize constant
118   *
119   * This method returns the normal form of n, which calls the above function
120   * on all top-level codatatype subterms of n.
121   */
122  static Node normalizeConstant(Node n);
123  /** check clash
124   *
125   * This method returns true if and only if n1 and n2 have a skeleton that has
126   * conflicting constructors at some term position.
127   * Examples of terms that clash are:
128   *   C( x, y ) and D( z )
129   *   C( D( x ), y ) and C( E( x ), y )
130   * Examples of terms that do not clash are:
131   *   C( x, y ) and C( D( x ), y )
132   *   C( D( x ), y ) and C( x, E( z ) )
133   *   C( x, y ) and z
134   */
135  static bool checkClash(Node n1, Node n2, std::vector<Node>& rew);
136  /** get operator kind for sygus builtin
137   *
138   * This returns the Kind corresponding to applications of the operator op
139   * when building the builtin version of sygus terms. This is used by the
140   * function mkSygusTerm.
141   */
142  static Kind getOperatorKindForSygusBuiltin(Node op);
143  /** make sygus term
144   *
145   * This function returns a builtin term f( children[0], ..., children[n] )
146   * where f is the builtin op that the i^th constructor of sygus datatype dt
147   * encodes.
148   */
149  static Node mkSygusTerm(const Datatype& dt,
150                          unsigned i,
151                          const std::vector<Node>& children);
152  /**
153   * Get the builtin sygus operator for constructor term n of sygus datatype
154   * type. For example, if n is the term C_+( d1, d2 ) where C_+ is a sygus
155   * constructor whose sygus op is the builtin operator +, this method returns +.
156   */
157  static Node getSygusOpForCTerm(Node n);
158 
159 private:
160  /** rewrite constructor term in */
161  static RewriteResponse rewriteConstructor(TNode in);
162  /** rewrite selector term in */
163  static RewriteResponse rewriteSelector(TNode in);
164  /** rewrite tester term in */
165  static RewriteResponse rewriteTester(TNode in);
166 
167  /** collect references
168   *
169   * This function, given as input a codatatype term n, collects the necessary
170   * information for constructing a (canonical) codatatype constant that is
171   * equivalent to n if one exists, or null otherwise.
172   *
173   * In particular it returns a term ret such that all non-codatatype datatype
174   * subterms of n are replaced by a constant that is equal to them via a
175   * (mutually) recursive call to normalizeConstant above. Additionally, this
176   * function replaces references to mu-binders with fresh variables.
177   * In detail, mu-terms are represented by uninterpreted constants of datatype
178   * type that carry their Debruijn index.
179   *
180   * Consider the example of a codatatype representing a stream of integers:
181   *   Stream := cons( head : Int, tail : Stream )
182   * The stream 1,0,1,0,1,0... when written in mu-notation is the term:
183   *   mu x. cons( 1, mu y. cons( 0, x ) )
184   * This is represented in CVC4 by the Node:
185   *   cons( 1, cons( 0, c[1] ) )
186   * where c[1] is a uninterpreted constant datatype with Debruijn index 1,
187   * indicating that c[1] is nested underneath 1 level on the path to the
188   * term which it binds. On the other hand, the stream 1,0,0,0,0,... is
189   * represented by the codatatype term:
190   *   cons( 1, cons( 0, c[0] ) )
191   *
192   * Subterms that are references to mu-binders in n are replaced by a new
193   * variable. If n contains any subterm that is a reference to a mu-binder not
194   * bound in n, then we return null. For example we return null when n is:
195   *   cons( 1, cons( 0, c[2] ) )
196   * since c[2] is not bound by this codatatype term.
197   *
198   * All valid references to mu-binders are replaced by a variable that is unique
199   * for the term it references. For example, for the infinite tree codatatype:
200   *   Tree : node( data : Int, left : Tree, right : Tree )
201   * If n is the term:
202   *   node( 0, c[0], node( 1, c[0], c[1] ) )
203   * then the return value ret of this function is:
204   *   node( 0, x, node( 1, y, x ) )
205   * where x refers to the root of the term and y refers to the right tree of the
206   * root.
207   *
208   * The argument sk stores the current set of node that we are traversing
209   * beneath. The argument rf_pending stores, for each node that we are
210   * traversing beneath either null or the free variable that we are using to
211   * refer to its mu-binder. The remaining arguments store information that is
212   * relevant when performing normalization of n using the value of ret:
213   *
214   * rf : maps subterms of n to the corresponding term in ret for all subterms
215   * where the corresponding term in ret is different.
216   * terms : stores all subterms of ret.
217   * cdts : for each term t in terms, stores whether t is a codatatype.
218   */
219  static Node collectRef(Node n,
220                         std::vector<Node>& sk,
221                         std::map<Node, Node>& rf,
222                         std::vector<Node>& rf_pending,
223                         std::vector<Node>& terms,
224                         std::map<Node, bool>& cdts);
225  /** normalize codatatype constant eqc
226   *
227   * This recursive function returns a codatatype constant that is equivalent to
228   * n based on a pre-computed partition of the subterms of n into equivalence
229   * classes, as stored in the mapping eqc, which maps the subterms of n to
230   * equivalence class ids. The arguments eqc_stack and depth store information
231   * about the traversal in a term we have recursed, where
232   *
233   * eqc_stack : maps the depth of each term we have traversed to its equivalence
234   * class id.
235   * depth : the number of levels which we have traversed.
236   */
237  static Node normalizeCodatatypeConstantEqc(Node n,
238                                             std::map<int, int>& eqc_stack,
239                                             std::map<Node, int>& eqc,
240                                             int depth);
241  /** replace debruijn
242   *
243   * This function, given codatatype term n, returns a node
244   * where all subterms of n that have Debruijn indices that refer to a
245   * term of input depth are replaced by orig. For example, for the infinite Tree
246   * datatype,
247   *   replaceDebruijn( node( 0, c[0], node( 1, c[0], c[1] ) ), t, Tree, 0 )
248   * returns
249   *   node( 0, t, node( 1, c[0], t ) ).
250   */
251  static Node replaceDebruijn(Node n,
252                              Node orig,
253                              TypeNode orig_tn,
254                              unsigned depth);
255 };/* class DatatypesRewriter */
256 
257 }/* CVC4::theory::datatypes namespace */
258 }/* CVC4::theory namespace */
259 }/* CVC4 namespace */
260 
261 #endif /* __CVC4__THEORY__DATATYPES__DATATYPES_REWRITER_H */
262