5ab5a4b1b97beed76ce55d6fa4ffcbc0c2b5ab11
1 /******************************************************************************
2 * Top contributors (to current version):
3 * Andrew Reynolds, Aina Niemetz
5 * This file is part of the cvc5 project.
7 * Copyright (c) 2009-2021 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.
11 * ****************************************************************************
13 * Implementation of term canonize.
16 #include "expr/term_canonize.h"
20 // TODO #1216: move the code in this include
21 #include "theory/quantifiers/term_util.h"
23 using namespace cvc5::kind
;
28 TermCanonize::TermCanonize(TypeClassCallback
* tcc
)
29 : d_tcc(tcc
), d_op_id_count(0), d_typ_id_count(0)
33 int TermCanonize::getIdForOperator(Node op
)
35 std::map
<Node
, int>::iterator it
= d_op_id
.find(op
);
36 if (it
== d_op_id
.end())
38 d_op_id
[op
] = d_op_id_count
;
45 int TermCanonize::getIdForType(TypeNode t
)
47 std::map
<TypeNode
, int>::iterator it
= d_typ_id
.find(t
);
48 if (it
== d_typ_id
.end())
50 d_typ_id
[t
] = d_typ_id_count
;
57 bool TermCanonize::getTermOrder(Node a
, Node b
)
59 if (a
.getKind() == BOUND_VARIABLE
)
61 if (b
.getKind() == BOUND_VARIABLE
)
63 return getIndexForFreeVariable(a
) < getIndexForFreeVariable(b
);
67 if (b
.getKind() != BOUND_VARIABLE
)
69 Node aop
= a
.hasOperator() ? a
.getOperator() : a
;
70 Node bop
= b
.hasOperator() ? b
.getOperator() : b
;
71 Trace("aeq-debug2") << a
<< "...op..." << aop
<< std::endl
;
72 Trace("aeq-debug2") << b
<< "...op..." << bop
<< std::endl
;
75 if (a
.getNumChildren() == b
.getNumChildren())
77 for (unsigned i
= 0, size
= a
.getNumChildren(); i
< size
; i
++)
81 // first distinct child determines the ordering
82 return getTermOrder(a
[i
], b
[i
]);
88 return aop
.getNumChildren() < bop
.getNumChildren();
93 return getIdForOperator(aop
) < getIdForOperator(bop
);
99 Node
TermCanonize::getCanonicalFreeVar(TypeNode tn
, unsigned i
, uint32_t tc
)
101 Assert(!tn
.isNull());
102 NodeManager
* nm
= NodeManager::currentNM();
103 std::pair
<TypeNode
, uint32_t> key(tn
, tc
);
104 std::vector
<Node
>& tvars
= d_cn_free_var
[key
];
105 while (tvars
.size() <= i
)
107 std::stringstream oss
;
109 std::string typ_name
= oss
.str();
110 while (typ_name
[0] == '(')
112 typ_name
.erase(typ_name
.begin());
114 std::stringstream os
;
115 os
<< typ_name
[0] << i
;
116 Node x
= nm
->mkBoundVar(os
.str().c_str(), tn
);
117 d_fvIndex
[x
] = tvars
.size();
123 uint32_t TermCanonize::getTypeClass(TNode v
)
125 return d_tcc
== nullptr ? 0 : d_tcc
->getTypeClass(v
);
128 size_t TermCanonize::getIndexForFreeVariable(Node v
) const
130 std::map
<Node
, size_t>::const_iterator it
= d_fvIndex
.find(v
);
131 if (it
== d_fvIndex
.end())
141 bool operator()(Node i
, Node j
) { return d_tu
->getTermOrder(i
, j
); }
144 Node
TermCanonize::getCanonicalTerm(
148 std::map
<std::pair
<TypeNode
, uint32_t>, unsigned>& var_count
,
149 std::map
<TNode
, Node
>& visited
)
151 std::map
<TNode
, Node
>::iterator it
= visited
.find(n
);
152 if (it
!= visited
.end())
157 Trace("canon-term-debug") << "Get canonical term for " << n
<< std::endl
;
158 if (n
.getKind() == BOUND_VARIABLE
)
160 uint32_t tc
= getTypeClass(n
);
161 TypeNode tn
= n
.getType();
162 std::pair
<TypeNode
, uint32_t> key(tn
, tc
);
164 unsigned vn
= var_count
[key
];
166 Node fv
= getCanonicalFreeVar(tn
, vn
, tc
);
168 Trace("canon-term-debug") << "...allocate variable." << std::endl
;
171 else if (n
.getNumChildren() > 0)
174 Trace("canon-term-debug") << "Collect children" << std::endl
;
175 std::vector
<Node
> cchildren
;
176 for (const Node
& cn
: n
)
178 cchildren
.push_back(cn
);
180 // if applicable, first sort by term order
181 if (apply_torder
&& theory::quantifiers::TermUtil::isComm(n
.getKind()))
183 Trace("canon-term-debug")
184 << "Sort based on commutative operator " << n
.getKind() << std::endl
;
187 std::sort(cchildren
.begin(), cchildren
.end(), sto
);
189 // now make canonical
190 Trace("canon-term-debug") << "Make canonical children" << std::endl
;
191 for (unsigned i
= 0, size
= cchildren
.size(); i
< size
; i
++)
193 cchildren
[i
] = getCanonicalTerm(
194 cchildren
[i
], apply_torder
, doHoVar
, var_count
, visited
);
196 if (n
.getMetaKind() == metakind::PARAMETERIZED
)
198 Node op
= n
.getOperator();
201 op
= getCanonicalTerm(op
, apply_torder
, doHoVar
, var_count
, visited
);
203 Trace("canon-term-debug") << "Insert operator " << op
<< std::endl
;
204 cchildren
.insert(cchildren
.begin(), op
);
206 Trace("canon-term-debug")
207 << "...constructing for " << n
<< "." << std::endl
;
208 Node ret
= NodeManager::currentNM()->mkNode(n
.getKind(), cchildren
);
209 Trace("canon-term-debug")
210 << "...constructed " << ret
<< " for " << n
<< "." << std::endl
;
214 Trace("canon-term-debug") << "...return 0-child term." << std::endl
;
218 Node
TermCanonize::getCanonicalTerm(TNode n
, bool apply_torder
, bool doHoVar
)
220 std::map
<std::pair
<TypeNode
, uint32_t>, unsigned> var_count
;
221 std::map
<TNode
, Node
> visited
;
222 return getCanonicalTerm(n
, apply_torder
, doHoVar
, var_count
, visited
);
225 Node
TermCanonize::getCanonicalTerm(TNode n
,
226 std::map
<TNode
, Node
>& visited
,
230 std::map
<std::pair
<TypeNode
, uint32_t>, unsigned> var_count
;
231 return getCanonicalTerm(n
, apply_torder
, doHoVar
, var_count
, visited
);