1 /********************* */
2 /*! \file sort_inference.cpp
4 ** Original author: Andrew Reynolds
5 ** Major contributors: Morgan Deters
6 ** Minor contributors (to current version): Kshitij Bansal
7 ** This file is part of the CVC4 project.
8 ** Copyright (c) 2009-2014 New York University and The University of Iowa
9 ** See the file COPYING in the top-level source directory for licensing
10 ** information.\endverbatim
12 ** \brief Sort inference module
14 ** This class implements sort inference, based on a simple algorithm:
15 ** First, we assume all functions and predicates have distinct uninterpreted types.
16 ** One pass is made through the input assertions, while a union-find data structure
17 ** maintains necessary information regarding constraints on these types.
20 #include "theory/sort_inference.h"
24 #include "options/quantifiers_options.h"
25 #include "options/smt_options.h"
26 #include "options/uf_options.h"
27 #include "proof/proof_manager.h"
28 #include "theory/rewriter.h"
29 #include "theory/quantifiers/quant_util.h"
36 void SortInference::UnionFind::print(const char * c
){
37 for( std::map
< int, int >::iterator it
= d_eqc
.begin(); it
!= d_eqc
.end(); ++it
){
38 Trace(c
) << "s_" << it
->first
<< " = s_" << it
->second
<< ", ";
40 for( unsigned i
=0; i
<d_deq
.size(); i
++ ){
41 Trace(c
) << "s_" << d_deq
[i
].first
<< " != s_" << d_deq
[i
].second
<< ", ";
43 Trace(c
) << std::endl
;
45 void SortInference::UnionFind::set( UnionFind
& c
) {
47 for( std::map
< int, int >::iterator it
= c
.d_eqc
.begin(); it
!= c
.d_eqc
.end(); ++it
){
48 d_eqc
[ it
->first
] = it
->second
;
50 d_deq
.insert( d_deq
.end(), c
.d_deq
.begin(), c
.d_deq
.end() );
52 int SortInference::UnionFind::getRepresentative( int t
){
53 std::map
< int, int >::iterator it
= d_eqc
.find( t
);
54 if( it
==d_eqc
.end() || it
->second
==t
){
57 int rt
= getRepresentative( it
->second
);
62 void SortInference::UnionFind::setEqual( int t1
, int t2
){
64 int rt1
= getRepresentative( t1
);
65 int rt2
= getRepresentative( t2
);
73 bool SortInference::UnionFind::isValid() {
74 for( unsigned i
=0; i
<d_deq
.size(); i
++ ){
75 if( areEqual( d_deq
[i
].first
, d_deq
[i
].second
) ){
83 void SortInference::recordSubsort( TypeNode tn
, int s
){
84 s
= d_type_union_find
.getRepresentative( s
);
85 if( std::find( d_sub_sorts
.begin(), d_sub_sorts
.end(), s
)==d_sub_sorts
.end() ){
86 d_sub_sorts
.push_back( s
);
87 d_type_sub_sorts
[tn
].push_back( s
);
91 void SortInference::printSort( const char* c
, int t
){
92 int rt
= d_type_union_find
.getRepresentative( t
);
93 if( d_type_types
.find( rt
)!=d_type_types
.end() ){
94 Trace(c
) << d_type_types
[rt
];
96 Trace(c
) << "s_" << rt
;
100 void SortInference::reset() {
102 d_non_monotonic_sorts
.clear();
103 d_type_sub_sorts
.clear();
106 d_type_union_find
.clear();
107 d_type_types
.clear();
108 d_id_for_types
.clear();
109 d_op_return_types
.clear();
110 d_op_arg_types
.clear();
113 d_symbol_map
.clear();
117 void SortInference::simplify( std::vector
< Node
>& assertions
, bool doSortInference
, bool doMonotonicyInference
){
118 if( doSortInference
){
119 Trace("sort-inference-proc") << "Calculating sort inference..." << std::endl
;
120 //process all assertions
121 for( unsigned i
=0; i
<assertions
.size(); i
++ ){
122 Trace("sort-inference-debug") << "Process " << assertions
[i
] << std::endl
;
123 std::map
< Node
, Node
> var_bound
;
124 process( assertions
[i
], var_bound
);
126 Trace("sort-inference-proc") << "...done" << std::endl
;
127 for( std::map
< Node
, int >::iterator it
= d_op_return_types
.begin(); it
!= d_op_return_types
.end(); ++it
){
128 Trace("sort-inference") << it
->first
<< " : ";
129 TypeNode retTn
= it
->first
.getType();
130 if( !d_op_arg_types
[ it
->first
].empty() ){
131 Trace("sort-inference") << "( ";
132 for( size_t i
=0; i
<d_op_arg_types
[ it
->first
].size(); i
++ ){
133 recordSubsort( retTn
[i
], d_op_arg_types
[ it
->first
][i
] );
134 printSort( "sort-inference", d_op_arg_types
[ it
->first
][i
] );
135 Trace("sort-inference") << " ";
137 Trace("sort-inference") << ") -> ";
138 retTn
= retTn
[(int)retTn
.getNumChildren()-1];
140 recordSubsort( retTn
, it
->second
);
141 printSort( "sort-inference", it
->second
);
142 Trace("sort-inference") << std::endl
;
144 for( std::map
< Node
, std::map
< Node
, int > >::iterator it
= d_var_types
.begin(); it
!= d_var_types
.end(); ++it
){
145 Trace("sort-inference") << "Quantified formula : " << it
->first
<< " : " << std::endl
;
146 for( unsigned i
=0; i
<it
->first
[0].getNumChildren(); i
++ ){
147 recordSubsort( it
->first
[0][i
].getType(), it
->second
[it
->first
[0][i
]] );
148 printSort( "sort-inference", it
->second
[it
->first
[0][i
]] );
149 Trace("sort-inference") << std::endl
;
151 Trace("sort-inference") << std::endl
;
154 if( !options::ufssSymBreak() ){
155 bool rewritten
= false;
156 //determine monotonicity of sorts
157 Trace("sort-inference-proc") << "Calculating monotonicty for subsorts..." << std::endl
;
158 for( unsigned i
=0; i
<assertions
.size(); i
++ ){
159 Trace("sort-inference-debug") << "Process monotonicity for " << assertions
[i
] << std::endl
;
160 std::map
< Node
, Node
> var_bound
;
161 processMonotonic( assertions
[i
], true, true, var_bound
);
163 Trace("sort-inference-proc") << "...done" << std::endl
;
165 Trace("sort-inference") << "We have " << d_sub_sorts
.size() << " sub-sorts : " << std::endl
;
166 for( unsigned i
=0; i
<d_sub_sorts
.size(); i
++ ){
167 printSort( "sort-inference", d_sub_sorts
[i
] );
168 if( d_type_types
.find( d_sub_sorts
[i
] )!=d_type_types
.end() ){
169 Trace("sort-inference") << " is interpreted." << std::endl
;
170 }else if( d_non_monotonic_sorts
.find( d_sub_sorts
[i
] )==d_non_monotonic_sorts
.end() ){
171 Trace("sort-inference") << " is monotonic." << std::endl
;
173 Trace("sort-inference") << " is not monotonic." << std::endl
;
177 //simplify all assertions by introducing new symbols wherever necessary
178 Trace("sort-inference-proc") << "Perform simplification..." << std::endl
;
179 for( unsigned i
=0; i
<assertions
.size(); i
++ ){
180 Node prev
= assertions
[i
];
181 std::map
< Node
, Node
> var_bound
;
182 Trace("sort-inference-debug") << "Rewrite " << assertions
[i
] << std::endl
;
183 Node curr
= simplify( assertions
[i
], var_bound
);
184 Trace("sort-inference-debug") << "Done." << std::endl
;
185 if( curr
!=assertions
[i
] ){
186 curr
= theory::Rewriter::rewrite( curr
);
188 Trace("sort-inference-rewrite") << assertions
<< std::endl
;
189 Trace("sort-inference-rewrite") << " --> " << curr
<< std::endl
;
190 PROOF( ProofManager::currentPM()->addDependence(curr
, assertions
[i
]); );
191 assertions
[i
] = curr
;
194 Trace("sort-inference-proc") << "...done" << std::endl
;
195 //now, ensure constants are distinct
196 for( std::map
< TypeNode
, std::map
< Node
, Node
> >::iterator it
= d_const_map
.begin(); it
!= d_const_map
.end(); ++it
){
197 std::vector
< Node
> consts
;
198 for( std::map
< Node
, Node
>::iterator it2
= it
->second
.begin(); it2
!= it
->second
.end(); ++it2
){
199 consts
.push_back( it2
->second
);
201 //TODO: add lemma enforcing introduced constants to be distinct
204 //enforce constraints based on monotonicity
205 Trace("sort-inference-proc") << "Enforce monotonicity..." << std::endl
;
206 for( std::map
< TypeNode
, std::vector
< int > >::iterator it
= d_type_sub_sorts
.begin(); it
!= d_type_sub_sorts
.end(); ++it
){
208 for( unsigned i
=0; i
<it
->second
.size(); i
++ ){
209 if( d_non_monotonic_sorts
.find( it
->second
[i
] )!=d_non_monotonic_sorts
.end() ){
210 nmonSort
= it
->second
[i
];
215 std::vector
< Node
> injections
;
216 TypeNode base_tn
= getOrCreateTypeForId( nmonSort
, it
->first
);
217 for( unsigned i
=0; i
<it
->second
.size(); i
++ ){
218 if( it
->second
[i
]!=nmonSort
){
219 TypeNode new_tn
= getOrCreateTypeForId( it
->second
[i
], it
->first
);
220 //make injection to nmonSort
221 Node a1
= mkInjection( new_tn
, base_tn
);
222 injections
.push_back( a1
);
223 if( d_non_monotonic_sorts
.find( it
->second
[i
] )!=d_non_monotonic_sorts
.end() ){
224 //also must make injection from nmonSort to this
225 Node a2
= mkInjection( base_tn
, new_tn
);
226 injections
.push_back( a2
);
230 Trace("sort-inference-rewrite") << "Add the following injections for " << it
->first
<< " to ensure consistency wrt non-monotonic sorts : " << std::endl
;
231 for( unsigned j
=0; j
<injections
.size(); j
++ ){
232 Trace("sort-inference-rewrite") << " " << injections
[j
] << std::endl
;
234 assertions
.insert( assertions
.end(), injections
.begin(), injections
.end() );
235 if( !injections
.empty() ){
240 Trace("sort-inference-proc") << "...done" << std::endl
;
241 //no sub-sort information is stored
243 Trace("sort-inference-debug") << "Finished sort inference, rewritten = " << rewritten
<< std::endl
;
246 else if( !options::ufssSymBreak() ){
247 //just add the unit lemmas between constants
248 std::map< TypeNode, std::map< int, Node > > constants;
249 for( std::map< Node, int >::iterator it = d_op_return_types.begin(); it != d_op_return_types.end(); ++it ){
250 int rt = d_type_union_find.getRepresentative( it->second );
251 if( d_op_arg_types[ it->first ].empty() ){
252 TypeNode tn = it->first.getType();
253 if( constants[ tn ].find( rt )==constants[ tn ].end() ){
254 constants[ tn ][ rt ] = it->first;
258 //add unit lemmas for each constant
259 for( std::map< TypeNode, std::map< int, Node > >::iterator it = constants.begin(); it != constants.end(); ++it ){
261 for( std::map< int, Node >::iterator it2 = it->second.begin(); it2 != it->second.end(); ++it2 ){
262 if( first_const.isNull() ){
263 first_const = it2->second;
265 Node eq = first_const.eqNode( it2->second );
266 //eq = Rewriter::rewrite( eq );
267 Trace("sort-inference-lemma") << "Sort inference lemma : " << eq << std::endl;
268 assertions.push_back( eq );
274 initialSortCount
= sortCount
;
276 if( doMonotonicyInference
){
277 Trace("sort-inference-proc") << "Calculating monotonicty for types..." << std::endl
;
278 for( unsigned i
=0; i
<assertions
.size(); i
++ ){
279 Trace("sort-inference-debug") << "Process type monotonicity for " << assertions
[i
] << std::endl
;
280 std::map
< Node
, Node
> var_bound
;
281 processMonotonic( assertions
[i
], true, true, var_bound
, true );
283 Trace("sort-inference-proc") << "...done" << std::endl
;
287 void SortInference::setEqual( int t1
, int t2
){
289 int rt1
= d_type_union_find
.getRepresentative( t1
);
290 int rt2
= d_type_union_find
.getRepresentative( t2
);
292 Trace("sort-inference-debug") << "Set equal : ";
293 printSort( "sort-inference-debug", rt1
);
294 Trace("sort-inference-debug") << " ";
295 printSort( "sort-inference-debug", rt2
);
296 Trace("sort-inference-debug") << std::endl
;
298 d_type_eq_class[rt1].insert( d_type_eq_class[rt1].end(), d_type_eq_class[rt2].begin(), d_type_eq_class[rt2].end() );
299 d_type_eq_class[rt2].clear();
300 Trace("sort-inference-debug") << "EqClass : { ";
301 for( int i=0; i<(int)d_type_eq_class[rt1].size(); i++ ){
302 Trace("sort-inference-debug") << d_type_eq_class[rt1][i] << ", ";
304 Trace("sort-inference-debug") << "}" << std::endl;
312 std::map
< int, TypeNode
>::iterator it1
= d_type_types
.find( rt1
);
313 if( it1
!=d_type_types
.end() ){
314 if( d_type_types
.find( rt2
)==d_type_types
.end() ){
315 d_type_types
[rt2
] = it1
->second
;
316 d_type_types
.erase( rt1
);
318 Trace("sort-inference-debug") << "...fail : associated with types " << d_type_types
[rt1
] << " and " << d_type_types
[rt2
] << std::endl
;
322 d_type_union_find
.d_eqc
[rt1
] = rt2
;
327 int SortInference::getIdForType( TypeNode tn
){
328 //register the return type
329 std::map
< TypeNode
, int >::iterator it
= d_id_for_types
.find( tn
);
330 if( it
==d_id_for_types
.end() ){
332 d_type_types
[ sortCount
] = tn
;
333 d_id_for_types
[ tn
] = sortCount
;
341 int SortInference::process( Node n
, std::map
< Node
, Node
>& var_bound
){
342 //add to variable bindings
343 if( n
.getKind()==kind::FORALL
|| n
.getKind()==kind::EXISTS
){
344 if( d_var_types
.find( n
)!=d_var_types
.end() ){
345 return getIdForType( n
.getType() );
347 for( size_t i
=0; i
<n
[0].getNumChildren(); i
++ ){
348 //apply sort inference to quantified variables
349 d_var_types
[n
][ n
[0][i
] ] = sortCount
;
352 //type of the quantified variable must be the same
353 var_bound
[ n
[0][i
] ] = n
;
359 std::vector
< Node
> children
;
360 std::vector
< int > child_types
;
361 for( size_t i
=0; i
<n
.getNumChildren(); i
++ ){
362 bool processChild
= true;
363 if( n
.getKind()==kind::FORALL
|| n
.getKind()==kind::EXISTS
){
364 processChild
= options::userPatternsQuant()==theory::quantifiers::USER_PAT_MODE_IGNORE
? i
==1 : i
>=1;
367 children
.push_back( n
[i
] );
368 child_types
.push_back( process( n
[i
], var_bound
) );
372 //remove from variable bindings
373 if( n
.getKind()==kind::FORALL
|| n
.getKind()==kind::EXISTS
){
374 //erase from variable bound
375 for( size_t i
=0; i
<n
[0].getNumChildren(); i
++ ){
376 var_bound
.erase( n
[0][i
] );
379 Trace("sort-inference-debug") << "...Process " << n
<< std::endl
;
382 if( n
.getKind()==kind::EQUAL
){
383 Trace("sort-inference-debug") << "For equality " << n
<< ", set equal types from : " << n
[0].getType() << " " << n
[1].getType() << std::endl
;
384 //if original types are mixed (e.g. Int/Real), don't commit type equality in either direction
385 if( n
[0].getType()!=n
[1].getType() ){
386 //for now, assume the original types
387 for( unsigned i
=0; i
<2; i
++ ){
388 int ct
= getIdForType( n
[i
].getType() );
389 setEqual( child_types
[i
], ct
);
392 //we only require that the left and right hand side must be equal
393 setEqual( child_types
[0], child_types
[1] );
395 //int eqType = getIdForType( n[0].getType() );
396 //setEqual( child_types[0], eqType );
397 //setEqual( child_types[1], eqType );
398 retType
= getIdForType( n
.getType() );
399 }else if( n
.getKind()==kind::APPLY_UF
){
400 Node op
= n
.getOperator();
401 TypeNode tn_op
= op
.getType();
402 if( d_op_return_types
.find( op
)==d_op_return_types
.end() ){
403 if( n
.getType().isBoolean() ){
405 d_op_return_types
[op
] = getIdForType( n
.getType() );
407 //assign arbitrary sort for return type
408 d_op_return_types
[op
] = sortCount
;
411 //d_type_eq_class[sortCount].push_back( op );
412 //assign arbitrary sort for argument types
413 for( size_t i
=0; i
<n
.getNumChildren(); i
++ ){
414 d_op_arg_types
[op
].push_back( sortCount
);
418 for( size_t i
=0; i
<n
.getNumChildren(); i
++ ){
419 //the argument of the operator must match the return type of the subterm
420 if( n
[i
].getType()!=tn_op
[i
] ){
421 //if type mismatch, assume original types
422 Trace("sort-inference-debug") << "Argument " << i
<< " of " << op
<< " " << n
[i
] << " has type " << n
[i
].getType();
423 Trace("sort-inference-debug") << ", while operator arg has type " << tn_op
[i
] << std::endl
;
424 int ct1
= getIdForType( n
[i
].getType() );
425 setEqual( child_types
[i
], ct1
);
426 int ct2
= getIdForType( tn_op
[i
] );
427 setEqual( d_op_arg_types
[op
][i
], ct2
);
429 setEqual( child_types
[i
], d_op_arg_types
[op
][i
] );
432 //return type is the return type
433 retType
= d_op_return_types
[op
];
435 std::map
< Node
, Node
>::iterator it
= var_bound
.find( n
);
436 if( it
!=var_bound
.end() ){
437 Trace("sort-inference-debug") << n
<< " is a bound variable." << std::endl
;
438 //the return type was specified while binding
439 retType
= d_var_types
[it
->second
][n
];
440 }else if( n
.getKind() == kind::VARIABLE
|| n
.getKind()==kind::SKOLEM
){
441 Trace("sort-inference-debug") << n
<< " is a variable." << std::endl
;
442 if( d_op_return_types
.find( n
)==d_op_return_types
.end() ){
443 //assign arbitrary sort
444 d_op_return_types
[n
] = sortCount
;
446 //d_type_eq_class[sortCount].push_back( n );
448 retType
= d_op_return_types
[n
];
449 //}else if( n.isConst() ){
450 // Trace("sort-inference-debug") << n << " is a constant." << std::endl;
451 //can be any type we want
452 // retType = sortCount;
455 Trace("sort-inference-debug") << n
<< " is a interpreted symbol." << std::endl
;
456 //it is an interpretted term
457 for( size_t i
=0; i
<children
.size(); i
++ ){
458 Trace("sort-inference-debug") << children
[i
] << " forced to have " << children
[i
].getType() << std::endl
;
459 //must enforce the actual type of the operator on the children
460 int ct
= getIdForType( children
[i
].getType() );
461 setEqual( child_types
[i
], ct
);
463 //return type must be the actual return type
464 retType
= getIdForType( n
.getType() );
467 Trace("sort-inference-debug") << "...Type( " << n
<< " ) = ";
468 printSort("sort-inference-debug", retType
);
469 Trace("sort-inference-debug") << std::endl
;
473 void SortInference::processMonotonic( Node n
, bool pol
, bool hasPol
, std::map
< Node
, Node
>& var_bound
, bool typeMode
) {
474 Trace("sort-inference-debug") << "...Process monotonic " << pol
<< " " << hasPol
<< " " << n
<< std::endl
;
475 if( n
.getKind()==kind::FORALL
){
476 //only consider variables universally if it is possible this quantified formula is asserted positively
477 if( !hasPol
|| pol
){
478 for( unsigned i
=0; i
<n
[0].getNumChildren(); i
++ ){
479 var_bound
[n
[0][i
]] = n
;
482 processMonotonic( n
[1], pol
, hasPol
, var_bound
, typeMode
);
483 if( !hasPol
|| pol
){
484 for( unsigned i
=0; i
<n
[0].getNumChildren(); i
++ ){
485 var_bound
.erase( n
[0][i
] );
489 }else if( n
.getKind()==kind::EQUAL
){
490 if( !hasPol
|| pol
){
491 for( unsigned i
=0; i
<2; i
++ ){
492 if( var_bound
.find( n
[i
] )!=var_bound
.end() ){
494 int sid
= getSortId( var_bound
[n
[i
]], n
[i
] );
495 d_non_monotonic_sorts
[sid
] = true;
497 d_non_monotonic_sorts_orig
[n
[i
].getType()] = true;
504 for( unsigned i
=0; i
<n
.getNumChildren(); i
++ ){
507 theory::QuantPhaseReq::getPolarity( n
, i
, hasPol
, pol
, nhasPol
, npol
);
508 processMonotonic( n
[i
], npol
, nhasPol
, var_bound
, typeMode
);
513 TypeNode
SortInference::getOrCreateTypeForId( int t
, TypeNode pref
){
514 int rt
= d_type_union_find
.getRepresentative( t
);
515 if( d_type_types
.find( rt
)!=d_type_types
.end() ){
516 return d_type_types
[rt
];
519 //see if we can assign pref
520 if( !pref
.isNull() && d_id_for_types
.find( pref
)==d_id_for_types
.end() ){
523 //must create new type
524 std::stringstream ss
;
525 ss
<< "it_" << t
<< "_" << pref
;
526 retType
= NodeManager::currentNM()->mkSort( ss
.str() );
528 Trace("sort-inference") << "-> Make type " << retType
<< " to correspond to ";
529 printSort("sort-inference", t
);
530 Trace("sort-inference") << std::endl
;
531 d_id_for_types
[ retType
] = rt
;
532 d_type_types
[ rt
] = retType
;
537 TypeNode
SortInference::getTypeForId( int t
){
538 int rt
= d_type_union_find
.getRepresentative( t
);
539 if( d_type_types
.find( rt
)!=d_type_types
.end() ){
540 return d_type_types
[rt
];
542 return TypeNode::null();
546 Node
SortInference::getNewSymbol( Node old
, TypeNode tn
){
547 if( tn
==old
.getType() ){
549 }else if( old
.isConst() ){
550 //must make constant of type tn
551 if( d_const_map
[tn
].find( old
)==d_const_map
[tn
].end() ){
552 std::stringstream ss
;
553 ss
<< "ic_" << tn
<< "_" << old
;
554 d_const_map
[tn
][ old
] = NodeManager::currentNM()->mkSkolem( ss
.str(), tn
, "constant created during sort inference" ); //use mkConst???
556 return d_const_map
[tn
][ old
];
557 }else if( old
.getKind()==kind::BOUND_VARIABLE
){
558 std::stringstream ss
;
560 return NodeManager::currentNM()->mkBoundVar( ss
.str(), tn
);
562 std::stringstream ss
;
564 return NodeManager::currentNM()->mkSkolem( ss
.str(), tn
, "created during sort inference" );
568 Node
SortInference::simplify( Node n
, std::map
< Node
, Node
>& var_bound
){
569 Trace("sort-inference-debug2") << "Simplify " << n
<< std::endl
;
570 std::vector
< Node
> children
;
571 if( n
.getKind()==kind::FORALL
|| n
.getKind()==kind::EXISTS
){
572 //recreate based on types of variables
573 std::vector
< Node
> new_children
;
574 for( size_t i
=0; i
<n
[0].getNumChildren(); i
++ ){
575 TypeNode tn
= getOrCreateTypeForId( d_var_types
[n
][ n
[0][i
] ], n
[0][i
].getType() );
576 Node v
= getNewSymbol( n
[0][i
], tn
);
577 Trace("sort-inference-debug2") << "Map variable " << n
[0][i
] << " to " << v
<< std::endl
;
578 new_children
.push_back( v
);
579 var_bound
[ n
[0][i
] ] = v
;
581 children
.push_back( NodeManager::currentNM()->mkNode( n
[0].getKind(), new_children
) );
585 if( n
.getMetaKind() == kind::metakind::PARAMETERIZED
){
586 children
.push_back( n
.getOperator() );
588 bool childChanged
= false;
589 for( size_t i
=0; i
<n
.getNumChildren(); i
++ ){
590 bool processChild
= true;
591 if( n
.getKind()==kind::FORALL
|| n
.getKind()==kind::EXISTS
){
592 processChild
= options::userPatternsQuant()==theory::quantifiers::USER_PAT_MODE_IGNORE
? i
==1 : i
>=1;
595 Node nc
= simplify( n
[i
], var_bound
);
596 Trace("sort-inference-debug2") << "Simplify " << i
<< " " << n
[i
] << " returned " << nc
<< std::endl
;
597 children
.push_back( nc
);
598 childChanged
= childChanged
|| nc
!=n
[i
];
602 //remove from variable bindings
603 if( n
.getKind()==kind::FORALL
|| n
.getKind()==kind::EXISTS
){
604 //erase from variable bound
605 for( size_t i
=0; i
<n
[0].getNumChildren(); i
++ ){
606 Trace("sort-inference-debug2") << "Remove bound for " << n
[0][i
] << std::endl
;
607 var_bound
.erase( n
[0][i
] );
609 return NodeManager::currentNM()->mkNode( n
.getKind(), children
);
610 }else if( n
.getKind()==kind::EQUAL
){
611 TypeNode tn1
= children
[0].getType();
612 TypeNode tn2
= children
[1].getType();
613 if( !tn1
.isSubtypeOf( tn2
) && !tn2
.isSubtypeOf( tn1
) ){
614 if( children
[0].isConst() ){
615 children
[0] = getNewSymbol( children
[0], children
[1].getType() );
616 }else if( children
[1].isConst() ){
617 children
[1] = getNewSymbol( children
[1], children
[0].getType() );
619 Trace("sort-inference-warn") << "Sort inference created bad equality: " << children
[0] << " = " << children
[1] << std::endl
;
620 Trace("sort-inference-warn") << " Types : " << children
[0].getType() << " " << children
[1].getType() << std::endl
;
624 return NodeManager::currentNM()->mkNode( kind::EQUAL
, children
);
625 }else if( n
.getKind()==kind::APPLY_UF
){
626 Node op
= n
.getOperator();
627 if( d_symbol_map
.find( op
)==d_symbol_map
.end() ){
628 //make the new operator if necessary
629 bool opChanged
= false;
630 std::vector
< TypeNode
> argTypes
;
631 for( size_t i
=0; i
<n
.getNumChildren(); i
++ ){
632 TypeNode tn
= getOrCreateTypeForId( d_op_arg_types
[op
][i
], n
[i
].getType() );
633 argTypes
.push_back( tn
);
634 if( tn
!=n
[i
].getType() ){
638 TypeNode retType
= getOrCreateTypeForId( d_op_return_types
[op
], n
.getType() );
639 if( retType
!=n
.getType() ){
643 std::stringstream ss
;
645 TypeNode typ
= NodeManager::currentNM()->mkFunctionType( argTypes
, retType
);
646 d_symbol_map
[op
] = NodeManager::currentNM()->mkSkolem( ss
.str(), typ
, "op created during sort inference" );
647 Trace("setp-model") << "Function " << op
<< " is replaced with " << d_symbol_map
[op
] << std::endl
;
648 d_model_replace_f
[op
] = d_symbol_map
[op
];
650 d_symbol_map
[op
] = op
;
653 children
[0] = d_symbol_map
[op
];
654 //make sure all children have been taken care of
655 for( size_t i
=0; i
<n
.getNumChildren(); i
++ ){
656 TypeNode tn
= children
[i
+1].getType();
657 TypeNode tna
= getTypeForId( d_op_arg_types
[op
][i
] );
659 if( n
[i
].isConst() ){
660 children
[i
+1] = getNewSymbol( n
[i
], tna
);
662 Trace("sort-inference-warn") << "Sort inference created bad child: " << n
<< " " << n
[i
] << " " << tn
<< " " << tna
<< std::endl
;
667 return NodeManager::currentNM()->mkNode( kind::APPLY_UF
, children
);
669 std::map
< Node
, Node
>::iterator it
= var_bound
.find( n
);
670 if( it
!=var_bound
.end() ){
672 }else if( n
.getKind() == kind::VARIABLE
|| n
.getKind() == kind::SKOLEM
){
673 if( d_symbol_map
.find( n
)==d_symbol_map
.end() ){
674 TypeNode tn
= getOrCreateTypeForId( d_op_return_types
[n
], n
.getType() );
675 d_symbol_map
[n
] = getNewSymbol( n
, tn
);
677 return d_symbol_map
[n
];
678 }else if( n
.isConst() ){
679 //just return n, we will fix at higher scope
683 return NodeManager::currentNM()->mkNode( n
.getKind(), children
);
692 Node
SortInference::mkInjection( TypeNode tn1
, TypeNode tn2
) {
693 std::vector
< TypeNode
> tns
;
694 tns
.push_back( tn1
);
695 TypeNode typ
= NodeManager::currentNM()->mkFunctionType( tns
, tn2
);
696 Node f
= NodeManager::currentNM()->mkSkolem( "inj", typ
, "injection for monotonicity constraint" );
697 Trace("sort-inference") << "-> Make injection " << f
<< " from " << tn1
<< " to " << tn2
<< std::endl
;
698 Node v1
= NodeManager::currentNM()->mkBoundVar( "?x", tn1
);
699 Node v2
= NodeManager::currentNM()->mkBoundVar( "?y", tn1
);
700 Node ret
= NodeManager::currentNM()->mkNode( kind::FORALL
,
701 NodeManager::currentNM()->mkNode( kind::BOUND_VAR_LIST
, v1
, v2
),
702 NodeManager::currentNM()->mkNode( kind::OR
,
703 NodeManager::currentNM()->mkNode( kind::APPLY_UF
, f
, v1
).eqNode( NodeManager::currentNM()->mkNode( kind::APPLY_UF
, f
, v2
) ).negate(),
705 ret
= theory::Rewriter::rewrite( ret
);
709 int SortInference::getSortId( Node n
) {
710 Node op
= n
.getKind()==kind::APPLY_UF
? n
.getOperator() : n
;
711 if( d_op_return_types
.find( op
)!=d_op_return_types
.end() ){
712 return d_type_union_find
.getRepresentative( d_op_return_types
[op
] );
718 int SortInference::getSortId( Node f
, Node v
) {
719 if( d_var_types
.find( f
)!=d_var_types
.end() ){
720 return d_type_union_find
.getRepresentative( d_var_types
[f
][v
] );
726 void SortInference::setSkolemVar( Node f
, Node v
, Node sk
){
727 Trace("sort-inference-temp") << "Set skolem var for " << f
<< ", variable " << v
<< std::endl
;
728 if( isWellSortedFormula( f
) && d_var_types
.find( f
)==d_var_types
.end() ){
729 //calculate the sort for variables if not done so already
730 std::map
< Node
, Node
> var_bound
;
731 process( f
, var_bound
);
733 d_op_return_types
[sk
] = getSortId( f
, v
);
734 Trace("sort-inference-temp") << "Set skolem sort id for " << sk
<< " to " << d_op_return_types
[sk
] << std::endl
;
737 bool SortInference::isWellSortedFormula( Node n
) {
738 if( n
.getType().isBoolean() && n
.getKind()!=kind::APPLY_UF
){
739 for( unsigned i
=0; i
<n
.getNumChildren(); i
++ ){
740 if( !isWellSortedFormula( n
[i
] ) ){
746 return isWellSorted( n
);
750 bool SortInference::isWellSorted( Node n
) {
751 if( getSortId( n
)==0 ){
754 if( n
.getKind()==kind::APPLY_UF
){
755 for( unsigned i
=0; i
<n
.getNumChildren(); i
++ ){
756 int s1
= getSortId( n
[i
] );
757 int s2
= d_type_union_find
.getRepresentative( d_op_arg_types
[ n
.getOperator() ][i
] );
761 if( !isWellSorted( n
[i
] ) ){
770 void SortInference::getSortConstraints( Node n
, UnionFind
& uf
) {
771 if( n
.getKind()==kind::APPLY_UF
){
772 for( unsigned i
=0; i
<n
.getNumChildren(); i
++ ){
773 getSortConstraints( n
[i
], uf
);
774 uf
.setEqual( getSortId( n
[i
] ), d_type_union_find
.getRepresentative( d_op_arg_types
[ n
.getOperator() ][i
] ) );
779 bool SortInference::isMonotonic( TypeNode tn
) {
780 Assert( tn
.isSort() );
781 return d_non_monotonic_sorts_orig
.find( tn
)==d_non_monotonic_sorts_orig
.end();
784 }/* CVC4 namespace */