1 |
|
/****************************************************************************** |
2 |
|
* Top contributors (to current version): |
3 |
|
* Andrew Reynolds, Mathias Preiner, Aina Niemetz |
4 |
|
* |
5 |
|
* This file is part of the cvc5 project. |
6 |
|
* |
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 |
|
* **************************************************************************** |
12 |
|
* |
13 |
|
* conjecture generator class |
14 |
|
*/ |
15 |
|
|
16 |
|
#include "theory/quantifiers/conjecture_generator.h" |
17 |
|
|
18 |
|
#include "expr/skolem_manager.h" |
19 |
|
#include "expr/term_canonize.h" |
20 |
|
#include "options/quantifiers_options.h" |
21 |
|
#include "theory/quantifiers/ematching/trigger_term_info.h" |
22 |
|
#include "theory/quantifiers/first_order_model.h" |
23 |
|
#include "theory/quantifiers/skolemize.h" |
24 |
|
#include "theory/quantifiers/term_database.h" |
25 |
|
#include "theory/quantifiers/term_enumeration.h" |
26 |
|
#include "theory/quantifiers/term_util.h" |
27 |
|
#include "theory/rewriter.h" |
28 |
|
#include "util/random.h" |
29 |
|
|
30 |
|
using namespace cvc5; |
31 |
|
using namespace cvc5::kind; |
32 |
|
using namespace cvc5::theory; |
33 |
|
using namespace cvc5::theory::quantifiers; |
34 |
|
using namespace std; |
35 |
|
|
36 |
|
namespace cvc5 { |
37 |
|
|
38 |
|
struct sortConjectureScore { |
39 |
|
std::vector< int > d_scores; |
40 |
|
bool operator() (unsigned i, unsigned j) { return d_scores[i]>d_scores[j]; } |
41 |
|
}; |
42 |
|
|
43 |
|
|
44 |
21734 |
void OpArgIndex::addTerm( std::vector< TNode >& terms, TNode n, unsigned index ){ |
45 |
21734 |
if( index==n.getNumChildren() ){ |
46 |
8860 |
Assert(n.hasOperator()); |
47 |
8860 |
if( std::find( d_ops.begin(), d_ops.end(), n.getOperator() )==d_ops.end() ){ |
48 |
8848 |
d_ops.push_back( n.getOperator() ); |
49 |
8848 |
d_op_terms.push_back( n ); |
50 |
|
} |
51 |
|
}else{ |
52 |
12874 |
d_child[terms[index]].addTerm( terms, n, index+1 ); |
53 |
|
} |
54 |
21734 |
} |
55 |
|
|
56 |
9966 |
Node OpArgIndex::getGroundTerm( ConjectureGenerator * s, std::vector< TNode >& args ) { |
57 |
9966 |
if( d_ops.empty() ){ |
58 |
8476 |
for( std::map< TNode, OpArgIndex >::iterator it = d_child.begin(); it != d_child.end(); ++it ){ |
59 |
6714 |
std::map< TNode, Node >::iterator itf = s->d_ground_eqc_map.find( it->first ); |
60 |
6714 |
if( itf!=s->d_ground_eqc_map.end() ){ |
61 |
5055 |
args.push_back( itf->second ); |
62 |
5200 |
Node n = it->second.getGroundTerm( s, args ); |
63 |
5055 |
args.pop_back(); |
64 |
5055 |
if( !n.isNull() ){ |
65 |
4910 |
return n; |
66 |
|
} |
67 |
|
} |
68 |
|
} |
69 |
1762 |
return Node::null(); |
70 |
|
} |
71 |
6588 |
std::vector<TNode> args2; |
72 |
3294 |
if (d_op_terms[0].getMetaKind() == kind::metakind::PARAMETERIZED) |
73 |
|
{ |
74 |
3294 |
args2.push_back( d_ops[0] ); |
75 |
|
} |
76 |
3294 |
args2.insert(args2.end(), args.begin(), args.end()); |
77 |
3294 |
return NodeManager::currentNM()->mkNode(d_op_terms[0].getKind(), args2); |
78 |
|
} |
79 |
|
|
80 |
14059 |
void OpArgIndex::getGroundTerms( ConjectureGenerator * s, std::vector< TNode >& terms ) { |
81 |
14059 |
terms.insert( terms.end(), d_op_terms.begin(), d_op_terms.end() ); |
82 |
24121 |
for( std::map< TNode, OpArgIndex >::iterator it = d_child.begin(); it != d_child.end(); ++it ){ |
83 |
10062 |
if( s->isGroundEqc( it->first ) ){ |
84 |
9302 |
it->second.getGroundTerms( s, terms ); |
85 |
|
} |
86 |
|
} |
87 |
14059 |
} |
88 |
|
|
89 |
10 |
ConjectureGenerator::ConjectureGenerator(QuantifiersState& qs, |
90 |
|
QuantifiersInferenceManager& qim, |
91 |
|
QuantifiersRegistry& qr, |
92 |
10 |
TermRegistry& tr) |
93 |
|
: QuantifiersModule(qs, qim, qr, tr), |
94 |
|
d_notify(*this), |
95 |
|
d_uequalityEngine( |
96 |
|
d_notify, qs.getSatContext(), "ConjectureGenerator::ee", false), |
97 |
|
d_ee_conjectures(qs.getSatContext()), |
98 |
|
d_conj_count(0), |
99 |
|
d_subs_confirmCount(0), |
100 |
|
d_subs_unkCount(0), |
101 |
|
d_fullEffortCount(0), |
102 |
10 |
d_hasAddedLemma(false) |
103 |
|
{ |
104 |
10 |
d_true = NodeManager::currentNM()->mkConst(true); |
105 |
10 |
d_false = NodeManager::currentNM()->mkConst(false); |
106 |
10 |
d_uequalityEngine.addFunctionKind( kind::APPLY_UF ); |
107 |
10 |
d_uequalityEngine.addFunctionKind( kind::APPLY_CONSTRUCTOR ); |
108 |
|
|
109 |
10 |
} |
110 |
|
|
111 |
30 |
ConjectureGenerator::~ConjectureGenerator() |
112 |
|
{ |
113 |
33 |
for (std::map<Node, EqcInfo*>::iterator i = d_eqc_info.begin(), |
114 |
10 |
iend = d_eqc_info.end(); |
115 |
33 |
i != iend; |
116 |
|
++i) |
117 |
|
{ |
118 |
23 |
EqcInfo* current = (*i).second; |
119 |
23 |
Assert(current != nullptr); |
120 |
23 |
delete current; |
121 |
|
} |
122 |
20 |
} |
123 |
|
|
124 |
1618 |
void ConjectureGenerator::eqNotifyNewClass( TNode t ){ |
125 |
1618 |
Trace("thm-ee-debug") << "UEE : new equivalence class " << t << std::endl; |
126 |
1618 |
d_upendingAdds.push_back( t ); |
127 |
1618 |
} |
128 |
|
|
129 |
196 |
void ConjectureGenerator::eqNotifyMerge(TNode t1, TNode t2) |
130 |
|
{ |
131 |
|
//get maintained representatives |
132 |
392 |
TNode rt1 = t1; |
133 |
392 |
TNode rt2 = t2; |
134 |
196 |
std::map< Node, EqcInfo* >::iterator it1 = d_eqc_info.find( t1 ); |
135 |
196 |
if( it1!=d_eqc_info.end() && !it1->second->d_rep.get().isNull() ){ |
136 |
24 |
rt1 = it1->second->d_rep.get(); |
137 |
|
} |
138 |
196 |
std::map< Node, EqcInfo* >::iterator it2 = d_eqc_info.find( t2 ); |
139 |
196 |
if( it2!=d_eqc_info.end() && !it2->second->d_rep.get().isNull() ){ |
140 |
|
rt2 = it2->second->d_rep.get(); |
141 |
|
} |
142 |
196 |
Trace("thm-ee-debug") << "UEE : equality holds : " << t1 << " == " << t2 << std::endl; |
143 |
196 |
Trace("thm-ee-debug") << " ureps : " << rt1 << " == " << rt2 << std::endl; |
144 |
196 |
Trace("thm-ee-debug") << " relevant : " << d_pattern_is_relevant[rt1] << " " << d_pattern_is_relevant[rt2] << std::endl; |
145 |
196 |
Trace("thm-ee-debug") << " normal : " << d_pattern_is_normal[rt1] << " " << d_pattern_is_normal[rt2] << std::endl; |
146 |
196 |
Trace("thm-ee-debug") << " size : " << d_pattern_fun_sum[rt1] << " " << d_pattern_fun_sum[rt2] << std::endl; |
147 |
|
|
148 |
196 |
if( isUniversalLessThan( rt2, rt1 ) ){ |
149 |
|
EqcInfo * ei; |
150 |
45 |
if( it1==d_eqc_info.end() ){ |
151 |
23 |
ei = getOrMakeEqcInfo( t1, true ); |
152 |
|
}else{ |
153 |
22 |
ei = it1->second; |
154 |
|
} |
155 |
45 |
ei->d_rep = t2; |
156 |
|
} |
157 |
196 |
} |
158 |
|
|
159 |
|
|
160 |
23 |
ConjectureGenerator::EqcInfo::EqcInfo( context::Context* c ) : d_rep( c, Node::null() ){ |
161 |
|
|
162 |
23 |
} |
163 |
|
|
164 |
7720 |
ConjectureGenerator::EqcInfo* ConjectureGenerator::getOrMakeEqcInfo( TNode n, bool doMake ) { |
165 |
|
//Assert( getUniversalRepresentative( n )==n ); |
166 |
7720 |
std::map< Node, EqcInfo* >::iterator eqc_i = d_eqc_info.find( n ); |
167 |
7720 |
if( eqc_i!=d_eqc_info.end() ){ |
168 |
369 |
return eqc_i->second; |
169 |
7351 |
}else if( doMake ){ |
170 |
23 |
EqcInfo* ei = new EqcInfo(d_qstate.getSatContext()); |
171 |
23 |
d_eqc_info[n] = ei; |
172 |
23 |
return ei; |
173 |
|
}else{ |
174 |
7328 |
return NULL; |
175 |
|
} |
176 |
|
} |
177 |
|
|
178 |
5018 |
void ConjectureGenerator::setUniversalRelevant( TNode n ) { |
179 |
|
//add pattern information |
180 |
5018 |
registerPattern( n, n.getType() ); |
181 |
5018 |
d_urelevant_terms[n] = true; |
182 |
8637 |
for( unsigned i=0; i<n.getNumChildren(); i++ ){ |
183 |
3619 |
setUniversalRelevant( n[i] ); |
184 |
|
} |
185 |
5018 |
} |
186 |
|
|
187 |
307 |
bool ConjectureGenerator::isUniversalLessThan( TNode rt1, TNode rt2 ) { |
188 |
|
//prefer the one that is (normal, smaller) lexographically |
189 |
307 |
Assert(d_pattern_is_relevant.find(rt1) != d_pattern_is_relevant.end()); |
190 |
307 |
Assert(d_pattern_is_relevant.find(rt2) != d_pattern_is_relevant.end()); |
191 |
307 |
Assert(d_pattern_is_normal.find(rt1) != d_pattern_is_normal.end()); |
192 |
307 |
Assert(d_pattern_is_normal.find(rt2) != d_pattern_is_normal.end()); |
193 |
307 |
Assert(d_pattern_fun_sum.find(rt1) != d_pattern_fun_sum.end()); |
194 |
307 |
Assert(d_pattern_fun_sum.find(rt2) != d_pattern_fun_sum.end()); |
195 |
|
|
196 |
307 |
if( d_pattern_is_relevant[rt1] && !d_pattern_is_relevant[rt2] ){ |
197 |
|
Trace("thm-ee-debug") << "UEE : LT due to relevant." << std::endl; |
198 |
|
return true; |
199 |
307 |
}else if( d_pattern_is_relevant[rt1]==d_pattern_is_relevant[rt2] ){ |
200 |
290 |
if( d_pattern_is_normal[rt1] && !d_pattern_is_normal[rt2] ){ |
201 |
|
Trace("thm-ee-debug") << "UEE : LT due to normal." << std::endl; |
202 |
|
return true; |
203 |
290 |
}else if( d_pattern_is_normal[rt1]==d_pattern_is_normal[rt2] ){ |
204 |
290 |
if( d_pattern_fun_sum[rt1]<d_pattern_fun_sum[rt2] ){ |
205 |
56 |
Trace("thm-ee-debug") << "UEE : LT due to size." << std::endl; |
206 |
|
//decide which representative to use : based on size of the term |
207 |
56 |
return true; |
208 |
234 |
}else if( d_pattern_fun_sum[rt1]==d_pattern_fun_sum[rt2] ){ |
209 |
|
//same size : tie goes to term that has already been reported |
210 |
147 |
return isReportedCanon( rt1 ) && !isReportedCanon( rt2 ); |
211 |
|
} |
212 |
|
} |
213 |
|
} |
214 |
104 |
return false; |
215 |
|
} |
216 |
|
|
217 |
|
|
218 |
7487 |
bool ConjectureGenerator::isReportedCanon( TNode n ) { |
219 |
7487 |
return std::find( d_ue_canon.begin(), d_ue_canon.end(), n )==d_ue_canon.end(); |
220 |
|
} |
221 |
|
|
222 |
7193 |
void ConjectureGenerator::markReportedCanon( TNode n ) { |
223 |
7193 |
if( !isReportedCanon( n ) ){ |
224 |
|
d_ue_canon.push_back( n ); |
225 |
|
} |
226 |
7193 |
} |
227 |
|
|
228 |
46 |
bool ConjectureGenerator::areUniversalEqual( TNode n1, TNode n2 ) { |
229 |
46 |
return n1==n2 || ( d_uequalityEngine.hasTerm( n1 ) && d_uequalityEngine.hasTerm( n2 ) && d_uequalityEngine.areEqual( n1, n2 ) ); |
230 |
|
} |
231 |
|
|
232 |
|
bool ConjectureGenerator::areUniversalDisequal( TNode n1, TNode n2 ) { |
233 |
|
return n1!=n2 && d_uequalityEngine.hasTerm( n1 ) && d_uequalityEngine.hasTerm( n2 ) && d_uequalityEngine.areDisequal( n1, n2, false ); |
234 |
|
} |
235 |
|
|
236 |
7697 |
Node ConjectureGenerator::getUniversalRepresentative(TNode n, bool add) |
237 |
|
{ |
238 |
7697 |
if( add ){ |
239 |
7645 |
if( d_urelevant_terms.find( n )==d_urelevant_terms.end() ){ |
240 |
1388 |
setUniversalRelevant( n ); |
241 |
|
//add term to universal equality engine |
242 |
1388 |
d_uequalityEngine.addTerm( n ); |
243 |
|
// addding this term to equality engine will lead to a set of new terms (the new subterms of n) |
244 |
|
// now, do instantiation-based merging for each of these terms |
245 |
1388 |
Trace("thm-ee-debug") << "Merge equivalence classes based on instantiations of terms..." << std::endl; |
246 |
|
//merge all pending equalities |
247 |
4186 |
while( !d_upendingAdds.empty() ){ |
248 |
1399 |
Trace("sg-pending") << "Add " << d_upendingAdds.size() << " pending terms..." << std::endl; |
249 |
2798 |
std::vector< Node > pending; |
250 |
1399 |
pending.insert( pending.end(), d_upendingAdds.begin(), d_upendingAdds.end() ); |
251 |
1399 |
d_upendingAdds.clear(); |
252 |
3017 |
for( unsigned i=0; i<pending.size(); i++ ){ |
253 |
3236 |
Node t = pending[i]; |
254 |
3236 |
TypeNode tn = t.getType(); |
255 |
1618 |
Trace("thm-ee-add") << "UEE : Add universal term " << t << std::endl; |
256 |
3236 |
std::vector< Node > eq_terms; |
257 |
|
//if occurs modulo equality at ground level, it is equivalent to representative of ground equality engine |
258 |
3236 |
Node gt = getTermDatabase()->evaluateTerm(t); |
259 |
1618 |
if( !gt.isNull() && gt!=t ){ |
260 |
56 |
eq_terms.push_back( gt ); |
261 |
|
} |
262 |
|
//get all equivalent terms based on theorem database |
263 |
1618 |
d_thm_index.getEquivalentTerms( t, eq_terms ); |
264 |
1618 |
if( !eq_terms.empty() ){ |
265 |
218 |
Trace("thm-ee-add") << "UEE : Based on ground EE/theorem DB, it is equivalent to " << eq_terms.size() << " terms : " << std::endl; |
266 |
|
//add equivalent terms as equalities to universal engine |
267 |
440 |
for (const Node& eqt : eq_terms) |
268 |
|
{ |
269 |
222 |
Trace("thm-ee-add") << " " << eqt << std::endl; |
270 |
222 |
bool assertEq = false; |
271 |
222 |
if (d_urelevant_terms.find(eqt) != d_urelevant_terms.end()) |
272 |
|
{ |
273 |
111 |
assertEq = true; |
274 |
|
} |
275 |
|
else |
276 |
|
{ |
277 |
111 |
Assert(eqt.getType() == tn); |
278 |
111 |
registerPattern(eqt, tn); |
279 |
444 |
if (isUniversalLessThan(eqt, t) |
280 |
455 |
|| (options::conjectureUeeIntro() |
281 |
111 |
&& d_pattern_fun_sum[t] >= d_pattern_fun_sum[eqt])) |
282 |
|
{ |
283 |
11 |
setUniversalRelevant(eqt); |
284 |
11 |
assertEq = true; |
285 |
|
} |
286 |
|
} |
287 |
222 |
if( assertEq ){ |
288 |
244 |
Node exp; |
289 |
122 |
d_uequalityEngine.assertEquality(t.eqNode(eqt), true, exp); |
290 |
|
}else{ |
291 |
200 |
Trace("thm-ee-no-add") |
292 |
100 |
<< "Do not add : " << t << " == " << eqt << std::endl; |
293 |
|
} |
294 |
|
} |
295 |
|
}else{ |
296 |
1400 |
Trace("thm-ee-add") << "UEE : No equivalent terms." << std::endl; |
297 |
|
} |
298 |
|
} |
299 |
|
} |
300 |
|
} |
301 |
|
} |
302 |
|
|
303 |
7697 |
if( d_uequalityEngine.hasTerm( n ) ){ |
304 |
15394 |
Node r = d_uequalityEngine.getRepresentative( n ); |
305 |
7697 |
EqcInfo * ei = getOrMakeEqcInfo( r ); |
306 |
7697 |
if( ei && !ei->d_rep.get().isNull() ){ |
307 |
351 |
return ei->d_rep.get(); |
308 |
|
}else{ |
309 |
7346 |
return r; |
310 |
|
} |
311 |
|
}else{ |
312 |
|
return n; |
313 |
|
} |
314 |
|
} |
315 |
|
|
316 |
40890 |
Node ConjectureGenerator::getFreeVar( TypeNode tn, unsigned i ) { |
317 |
40890 |
return d_termCanon.getCanonicalFreeVar(tn, i); |
318 |
|
} |
319 |
|
|
320 |
23941 |
bool ConjectureGenerator::isHandledTerm( TNode n ){ |
321 |
71823 |
return getTermDatabase()->isTermActive(n) |
322 |
44802 |
&& inst::TriggerTermInfo::isAtomicTrigger(n) |
323 |
108455 |
&& (n.getKind() != APPLY_UF || n.getOperator().getKind() != SKOLEM); |
324 |
|
} |
325 |
|
|
326 |
|
Node ConjectureGenerator::getGroundEqc( TNode r ) { |
327 |
|
std::map< TNode, Node >::iterator it = d_ground_eqc_map.find( r ); |
328 |
|
return it!=d_ground_eqc_map.end() ? it->second : Node::null(); |
329 |
|
} |
330 |
|
|
331 |
350235 |
bool ConjectureGenerator::isGroundEqc( TNode r ) { |
332 |
350235 |
return d_ground_eqc_map.find( r )!=d_ground_eqc_map.end(); |
333 |
|
} |
334 |
|
|
335 |
|
bool ConjectureGenerator::isGroundTerm( TNode n ) { |
336 |
|
return std::find( d_ground_terms.begin(), d_ground_terms.end(), n )!=d_ground_terms.end(); |
337 |
|
} |
338 |
|
|
339 |
724 |
bool ConjectureGenerator::needsCheck( Theory::Effort e ) { |
340 |
|
// synchonized with instantiation engine |
341 |
724 |
return d_qstate.getInstWhenNeedsCheck(e); |
342 |
|
} |
343 |
|
|
344 |
77 |
bool ConjectureGenerator::hasEnumeratedUf( Node n ) { |
345 |
77 |
if( options::conjectureGenGtEnum()>0 ){ |
346 |
77 |
std::map< Node, bool >::iterator it = d_uf_enum.find( n.getOperator() ); |
347 |
77 |
if( it==d_uf_enum.end() ){ |
348 |
15 |
d_uf_enum[n.getOperator()] = true; |
349 |
15 |
std::vector< Node > lem; |
350 |
15 |
getEnumeratePredUfTerm( n, options::conjectureGenGtEnum(), lem ); |
351 |
15 |
if( !lem.empty() ){ |
352 |
765 |
for (const Node& l : lem) |
353 |
|
{ |
354 |
750 |
d_qim.addPendingLemma(l, InferenceId::QUANTIFIERS_CONJ_GEN_GT_ENUM); |
355 |
|
} |
356 |
15 |
d_hasAddedLemma = true; |
357 |
15 |
return false; |
358 |
|
} |
359 |
|
} |
360 |
|
} |
361 |
62 |
return true; |
362 |
|
} |
363 |
|
|
364 |
152 |
void ConjectureGenerator::reset_round( Theory::Effort e ) { |
365 |
|
|
366 |
152 |
} |
367 |
166 |
void ConjectureGenerator::check(Theory::Effort e, QEffort quant_e) |
368 |
|
{ |
369 |
166 |
if (quant_e == QEFFORT_STANDARD) |
370 |
|
{ |
371 |
44 |
d_fullEffortCount++; |
372 |
44 |
if( d_fullEffortCount%optFullCheckFrequency()==0 ){ |
373 |
44 |
d_hasAddedLemma = false; |
374 |
44 |
d_tge.d_cg = this; |
375 |
44 |
double clSet = 0; |
376 |
44 |
if( Trace.isOn("sg-engine") ){ |
377 |
|
clSet = double(clock())/double(CLOCKS_PER_SEC); |
378 |
|
Trace("sg-engine") << "---Conjecture Engine Round, effort = " << e << "---" << std::endl; |
379 |
|
} |
380 |
44 |
eq::EqualityEngine * ee = getEqualityEngine(); |
381 |
44 |
d_conj_count = 0; |
382 |
|
|
383 |
44 |
Trace("sg-proc") << "Get eq classes..." << std::endl; |
384 |
44 |
d_op_arg_index.clear(); |
385 |
44 |
d_ground_eqc_map.clear(); |
386 |
44 |
d_bool_eqc[0] = Node::null(); |
387 |
44 |
d_bool_eqc[1] = Node::null(); |
388 |
88 |
std::vector< TNode > eqcs; |
389 |
44 |
d_em.clear(); |
390 |
44 |
eq::EqClassesIterator eqcs_i = eq::EqClassesIterator( ee ); |
391 |
9558 |
while( !eqcs_i.isFinished() ){ |
392 |
9514 |
TNode r = (*eqcs_i); |
393 |
4757 |
Trace("sg-proc-debug") << "...eqc : " << r << std::endl; |
394 |
4757 |
eqcs.push_back( r ); |
395 |
4757 |
if( r.getType().isBoolean() ){ |
396 |
853 |
if (areEqual(r, d_true)) |
397 |
|
{ |
398 |
44 |
d_ground_eqc_map[r] = d_true; |
399 |
44 |
d_bool_eqc[0] = r; |
400 |
|
} |
401 |
809 |
else if (areEqual(r, d_false)) |
402 |
|
{ |
403 |
44 |
d_ground_eqc_map[r] = d_false; |
404 |
44 |
d_bool_eqc[1] = r; |
405 |
|
} |
406 |
|
} |
407 |
4757 |
d_em[r] = eqcs.size(); |
408 |
4757 |
eq::EqClassIterator ieqc_i = eq::EqClassIterator( r, ee ); |
409 |
51185 |
while( !ieqc_i.isFinished() ){ |
410 |
46428 |
TNode n = (*ieqc_i); |
411 |
23214 |
Trace("sg-proc-debug") << "......term : " << n << std::endl; |
412 |
23214 |
if( getTermDatabase()->hasTermCurrent( n ) ){ |
413 |
23214 |
if( isHandledTerm( n ) ){ |
414 |
17720 |
std::vector<TNode> areps; |
415 |
21734 |
for (const Node& nc : n) |
416 |
|
{ |
417 |
12874 |
areps.push_back(d_qstate.getRepresentative(nc)); |
418 |
|
} |
419 |
8860 |
d_op_arg_index[r].addTerm(areps, n); |
420 |
|
} |
421 |
|
} |
422 |
23214 |
++ieqc_i; |
423 |
|
} |
424 |
4757 |
++eqcs_i; |
425 |
|
} |
426 |
44 |
Assert(!d_bool_eqc[0].isNull()); |
427 |
44 |
Assert(!d_bool_eqc[1].isNull()); |
428 |
44 |
d_urelevant_terms.clear(); |
429 |
44 |
Trace("sg-proc") << "...done get eq classes" << std::endl; |
430 |
|
|
431 |
44 |
Trace("sg-proc") << "Determine ground EQC..." << std::endl; |
432 |
|
bool success; |
433 |
111 |
do{ |
434 |
111 |
success = false; |
435 |
12938 |
for( unsigned i=0; i<eqcs.size(); i++ ){ |
436 |
25654 |
TNode r = eqcs[i]; |
437 |
12827 |
if( d_ground_eqc_map.find( r )==d_ground_eqc_map.end() ){ |
438 |
11376 |
std::vector< TNode > args; |
439 |
5688 |
Trace("sg-pat-debug") << "******* Get ground term for " << r << std::endl; |
440 |
11376 |
Node n; |
441 |
5688 |
if (Skolemize::isInductionTerm(r)) |
442 |
|
{ |
443 |
4911 |
n = d_op_arg_index[r].getGroundTerm( this, args ); |
444 |
|
}else{ |
445 |
777 |
n = r; |
446 |
|
} |
447 |
5688 |
if( !n.isNull() ){ |
448 |
4071 |
Trace("sg-pat") << "Ground term for eqc " << r << " : " << std::endl; |
449 |
4071 |
Trace("sg-pat") << " " << n << std::endl; |
450 |
4071 |
d_ground_eqc_map[r] = n; |
451 |
4071 |
success = true; |
452 |
|
}else{ |
453 |
1617 |
Trace("sg-pat-debug") << "...could not find ground term." << std::endl; |
454 |
|
} |
455 |
|
} |
456 |
|
} |
457 |
|
}while( success ); |
458 |
|
//also get ground terms |
459 |
44 |
d_ground_terms.clear(); |
460 |
4801 |
for( unsigned i=0; i<eqcs.size(); i++ ){ |
461 |
9514 |
TNode r = eqcs[i]; |
462 |
4757 |
d_op_arg_index[r].getGroundTerms( this, d_ground_terms ); |
463 |
|
} |
464 |
44 |
Trace("sg-proc") << "...done determine ground EQC" << std::endl; |
465 |
|
|
466 |
|
//debug printing |
467 |
44 |
if( Trace.isOn("sg-gen-eqc") ){ |
468 |
|
for( unsigned i=0; i<eqcs.size(); i++ ){ |
469 |
|
TNode r = eqcs[i]; |
470 |
|
//print out members |
471 |
|
bool firstTime = true; |
472 |
|
bool isFalse = areEqual(r, d_false); |
473 |
|
eq::EqClassIterator eqc_i = eq::EqClassIterator( r, ee ); |
474 |
|
while( !eqc_i.isFinished() ){ |
475 |
|
TNode n = (*eqc_i); |
476 |
|
if( getTermDatabase()->hasTermCurrent( n ) && getTermDatabase()->isTermActive( n ) && ( n.getKind()!=EQUAL || isFalse ) ){ |
477 |
|
if( firstTime ){ |
478 |
|
Trace("sg-gen-eqc") << "e" << d_em[r] << " : { " << std::endl; |
479 |
|
firstTime = false; |
480 |
|
} |
481 |
|
if( n.hasOperator() ){ |
482 |
|
Trace("sg-gen-eqc") << " (" << n.getOperator(); |
483 |
|
for (const Node& nc : n) |
484 |
|
{ |
485 |
|
TNode ar = d_qstate.getRepresentative(nc); |
486 |
|
Trace("sg-gen-eqc") << " e" << d_em[ar]; |
487 |
|
} |
488 |
|
Trace("sg-gen-eqc") << ") :: " << n << std::endl; |
489 |
|
}else{ |
490 |
|
Trace("sg-gen-eqc") << " " << n << std::endl; |
491 |
|
} |
492 |
|
} |
493 |
|
++eqc_i; |
494 |
|
} |
495 |
|
if( !firstTime ){ |
496 |
|
Trace("sg-gen-eqc") << "}" << std::endl; |
497 |
|
//print out ground term |
498 |
|
std::map< TNode, Node >::iterator it = d_ground_eqc_map.find( r ); |
499 |
|
if( it!=d_ground_eqc_map.end() ){ |
500 |
|
Trace("sg-gen-eqc") << "- Ground term : " << it->second << std::endl; |
501 |
|
} |
502 |
|
} |
503 |
|
} |
504 |
|
} |
505 |
|
|
506 |
44 |
Trace("sg-proc") << "Compute relevant eqc..." << std::endl; |
507 |
44 |
d_tge.d_relevant_eqc[0].clear(); |
508 |
44 |
d_tge.d_relevant_eqc[1].clear(); |
509 |
4801 |
for( unsigned i=0; i<eqcs.size(); i++ ){ |
510 |
9514 |
TNode r = eqcs[i]; |
511 |
4757 |
std::map< TNode, Node >::iterator it = d_ground_eqc_map.find( r ); |
512 |
4757 |
unsigned index = 1; |
513 |
4757 |
if( it==d_ground_eqc_map.end() ){ |
514 |
598 |
index = 0; |
515 |
|
} |
516 |
|
//based on unproven conjectures? TODO |
517 |
4757 |
d_tge.d_relevant_eqc[index].push_back( r ); |
518 |
|
} |
519 |
44 |
Trace("sg-gen-tg-debug") << "Initial relevant eqc : "; |
520 |
642 |
for( unsigned i=0; i<d_tge.d_relevant_eqc[0].size(); i++ ){ |
521 |
598 |
Trace("sg-gen-tg-debug") << "e" << d_em[d_tge.d_relevant_eqc[0][i]] << " "; |
522 |
|
} |
523 |
44 |
Trace("sg-gen-tg-debug") << std::endl; |
524 |
44 |
Trace("sg-proc") << "...done compute relevant eqc" << std::endl; |
525 |
|
|
526 |
|
|
527 |
44 |
Trace("sg-proc") << "Collect signature information..." << std::endl; |
528 |
44 |
d_tge.collectSignatureInformation(); |
529 |
44 |
if( d_hasAddedLemma ){ |
530 |
8 |
Trace("sg-proc") << "...added enumeration lemmas." << std::endl; |
531 |
|
} |
532 |
44 |
Trace("sg-proc") << "...done collect signature information" << std::endl; |
533 |
|
|
534 |
|
|
535 |
|
|
536 |
44 |
Trace("sg-proc") << "Build theorem index..." << std::endl; |
537 |
44 |
d_ue_canon.clear(); |
538 |
44 |
d_thm_index.clear(); |
539 |
88 |
std::vector< Node > provenConj; |
540 |
44 |
quantifiers::FirstOrderModel* m = d_treg.getModel(); |
541 |
263 |
for( unsigned i=0; i<m->getNumAssertedQuantifiers(); i++ ){ |
542 |
438 |
Node q = m->getAssertedQuantifier( i ); |
543 |
219 |
Trace("thm-db-debug") << "Is " << q << " a relevant theorem?" << std::endl; |
544 |
438 |
Node conjEq; |
545 |
219 |
if( q[1].getKind()==EQUAL ){ |
546 |
119 |
bool isSubsume = false; |
547 |
119 |
bool inEe = false; |
548 |
211 |
for( unsigned r=0; r<2; r++ ){ |
549 |
257 |
TNode nl = q[1][r==0 ? 0 : 1]; |
550 |
257 |
TNode nr = q[1][r==0 ? 1 : 0]; |
551 |
257 |
Node eq = nl.eqNode( nr ); |
552 |
165 |
if( r==1 || std::find( d_conjectures.begin(), d_conjectures.end(), q )==d_conjectures.end() ){ |
553 |
|
//check if it contains only relevant functions |
554 |
165 |
if( d_tge.isRelevantTerm( eq ) ){ |
555 |
|
//make it canonical |
556 |
92 |
Trace("sg-proc-debug") << "get canonical " << eq << std::endl; |
557 |
92 |
eq = d_termCanon.getCanonicalTerm(eq); |
558 |
|
}else{ |
559 |
73 |
eq = Node::null(); |
560 |
|
} |
561 |
|
} |
562 |
165 |
if( !eq.isNull() ){ |
563 |
92 |
if( r==0 ){ |
564 |
46 |
inEe = d_ee_conjectures.find( q[1] )!=d_ee_conjectures.end(); |
565 |
46 |
if( !inEe ){ |
566 |
|
//add to universal equality engine |
567 |
92 |
Node nlu = getUniversalRepresentative(eq[0], true); |
568 |
92 |
Node nru = getUniversalRepresentative(eq[1], true); |
569 |
46 |
if (areUniversalEqual(nlu, nru)) |
570 |
|
{ |
571 |
|
isSubsume = true; |
572 |
|
//set inactive (will be ignored by other modules) |
573 |
|
m->setQuantifierActive(q, false); |
574 |
|
} |
575 |
|
else |
576 |
|
{ |
577 |
92 |
Node exp; |
578 |
46 |
d_ee_conjectures[q[1]] = true; |
579 |
138 |
d_uequalityEngine.assertEquality( |
580 |
92 |
nlu.eqNode(nru), true, exp); |
581 |
|
} |
582 |
|
} |
583 |
46 |
Trace("sg-conjecture") << "*** CONJECTURE : currently proven" << (isSubsume ? " and subsumed" : ""); |
584 |
46 |
Trace("sg-conjecture") << " : " << q[1] << std::endl; |
585 |
46 |
provenConj.push_back( q ); |
586 |
|
} |
587 |
92 |
if( !isSubsume ){ |
588 |
92 |
Trace("thm-db-debug") << "Adding theorem to database " << eq[0] << " == " << eq[1] << std::endl; |
589 |
92 |
d_thm_index.addTheorem( eq[0], eq[1] ); |
590 |
|
}else{ |
591 |
|
break; |
592 |
|
} |
593 |
|
}else{ |
594 |
73 |
break; |
595 |
|
} |
596 |
|
} |
597 |
|
} |
598 |
|
} |
599 |
|
//examine status of other conjectures |
600 |
77 |
for( unsigned i=0; i<d_conjectures.size(); i++ ){ |
601 |
66 |
Node q = d_conjectures[i]; |
602 |
33 |
if( std::find( provenConj.begin(), provenConj.end(), q )==provenConj.end() ){ |
603 |
|
//check each skolem variable |
604 |
33 |
bool disproven = true; |
605 |
66 |
std::vector<Node> skolems; |
606 |
33 |
d_qim.getSkolemize()->getSkolemConstants(q, skolems); |
607 |
33 |
Trace("sg-conjecture") << " CONJECTURE : "; |
608 |
66 |
std::vector< Node > ce; |
609 |
38 |
for (unsigned j = 0; j < skolems.size(); j++) |
610 |
|
{ |
611 |
43 |
TNode rk = getRepresentative(skolems[j]); |
612 |
38 |
std::map< TNode, Node >::iterator git = d_ground_eqc_map.find( rk ); |
613 |
|
//check if it is a ground term |
614 |
38 |
if( git==d_ground_eqc_map.end() ){ |
615 |
33 |
Trace("sg-conjecture") << "ACTIVE : " << q; |
616 |
33 |
if( Trace.isOn("sg-gen-eqc") ){ |
617 |
|
Trace("sg-conjecture") << " { "; |
618 |
|
for (unsigned k = 0; k < skolems.size(); k++) |
619 |
|
{ |
620 |
|
Trace("sg-conjecture") << skolems[k] << (j == k ? "*" : "") |
621 |
|
<< " "; |
622 |
|
} |
623 |
|
Trace("sg-conjecture") << "}"; |
624 |
|
} |
625 |
33 |
Trace("sg-conjecture") << std::endl; |
626 |
33 |
disproven = false; |
627 |
33 |
break; |
628 |
|
}else{ |
629 |
5 |
ce.push_back( git->second ); |
630 |
|
} |
631 |
|
} |
632 |
33 |
if( disproven ){ |
633 |
|
Trace("sg-conjecture") << "disproven : " << q << " : "; |
634 |
|
for (unsigned j = 0, ceSize = ce.size(); j < ceSize; j++) |
635 |
|
{ |
636 |
|
Trace("sg-conjecture") << q[0][j] << " -> " << ce[j] << " "; |
637 |
|
} |
638 |
|
Trace("sg-conjecture") << std::endl; |
639 |
|
} |
640 |
|
} |
641 |
|
} |
642 |
44 |
Trace("thm-db") << "Theorem database is : " << std::endl; |
643 |
44 |
d_thm_index.debugPrint( "thm-db" ); |
644 |
44 |
Trace("thm-db") << std::endl; |
645 |
44 |
Trace("sg-proc") << "...done build theorem index" << std::endl; |
646 |
|
|
647 |
|
|
648 |
|
//clear patterns |
649 |
44 |
d_patterns.clear(); |
650 |
44 |
d_pattern_var_id.clear(); |
651 |
44 |
d_pattern_var_duplicate.clear(); |
652 |
44 |
d_pattern_is_normal.clear(); |
653 |
44 |
d_pattern_is_relevant.clear(); |
654 |
44 |
d_pattern_fun_id.clear(); |
655 |
44 |
d_pattern_fun_sum.clear(); |
656 |
44 |
d_rel_patterns.clear(); |
657 |
44 |
d_rel_pattern_var_sum.clear(); |
658 |
44 |
d_rel_pattern_typ_index.clear(); |
659 |
44 |
d_rel_pattern_subs_index.clear(); |
660 |
|
|
661 |
44 |
unsigned rel_term_count = 0; |
662 |
88 |
std::map< TypeNode, unsigned > rt_var_max; |
663 |
88 |
std::vector< TypeNode > rt_types; |
664 |
88 |
std::map< TypeNode, std::map< int, std::vector< Node > > > conj_lhs; |
665 |
44 |
unsigned addedLemmas = 0; |
666 |
44 |
unsigned maxDepth = options::conjectureGenMaxDepth(); |
667 |
147 |
for( unsigned depth=1; depth<=maxDepth; depth++ ){ |
668 |
121 |
Trace("sg-proc") << "Generate relevant LHS at depth " << depth << "..." << std::endl; |
669 |
121 |
Trace("sg-rel-term") << "Relevant terms of depth " << depth << " : " << std::endl; |
670 |
|
//set up environment |
671 |
121 |
d_tge.d_var_id.clear(); |
672 |
121 |
d_tge.d_var_limit.clear(); |
673 |
121 |
d_tge.reset( depth, true, TypeNode::null() ); |
674 |
1461 |
while( d_tge.getNextTerm() ){ |
675 |
|
//construct term |
676 |
1340 |
Node nn = d_tge.getTerm(); |
677 |
670 |
if( !options::conjectureFilterCanonical() || considerTermCanon( nn, true ) ){ |
678 |
670 |
rel_term_count++; |
679 |
670 |
Trace("sg-rel-term") << "*** Relevant term : "; |
680 |
670 |
d_tge.debugPrint( "sg-rel-term", "sg-rel-term-debug2" ); |
681 |
670 |
Trace("sg-rel-term") << std::endl; |
682 |
|
|
683 |
2010 |
for( unsigned r=0; r<2; r++ ){ |
684 |
1340 |
Trace("sg-rel-term-debug") << "...from equivalence classes (" << r << ") : "; |
685 |
1340 |
int index = d_tge.d_ccand_eqc[r].size()-1; |
686 |
25144 |
for( unsigned j=0; j<d_tge.d_ccand_eqc[r][index].size(); j++ ){ |
687 |
23804 |
Trace("sg-rel-term-debug") << "e" << d_em[d_tge.d_ccand_eqc[r][index][j]] << " "; |
688 |
|
} |
689 |
1340 |
Trace("sg-rel-term-debug") << std::endl; |
690 |
|
} |
691 |
1340 |
TypeNode tnn = nn.getType(); |
692 |
670 |
Trace("sg-gen-tg-debug") << "...term is " << nn << std::endl; |
693 |
670 |
conj_lhs[tnn][depth].push_back( nn ); |
694 |
|
|
695 |
|
//add information about pattern |
696 |
670 |
Trace("sg-gen-tg-debug") << "Collect pattern information..." << std::endl; |
697 |
670 |
Assert(std::find(d_rel_patterns[tnn].begin(), |
698 |
|
d_rel_patterns[tnn].end(), |
699 |
|
nn) |
700 |
|
== d_rel_patterns[tnn].end()); |
701 |
670 |
d_rel_patterns[tnn].push_back( nn ); |
702 |
|
//build information concerning the variables in this pattern |
703 |
670 |
unsigned sum = 0; |
704 |
1340 |
std::map< TypeNode, unsigned > typ_to_subs_index; |
705 |
1340 |
std::vector< TNode > gsubs_vars; |
706 |
1870 |
for( std::map< TypeNode, unsigned >::iterator it = d_tge.d_var_id.begin(); it != d_tge.d_var_id.end(); ++it ){ |
707 |
1200 |
if( it->second>0 ){ |
708 |
920 |
typ_to_subs_index[it->first] = sum; |
709 |
920 |
sum += it->second; |
710 |
2010 |
for( unsigned i=0; i<it->second; i++ ){ |
711 |
1090 |
gsubs_vars.push_back( |
712 |
2180 |
d_termCanon.getCanonicalFreeVar(it->first, i)); |
713 |
|
} |
714 |
|
} |
715 |
|
} |
716 |
670 |
d_rel_pattern_var_sum[nn] = sum; |
717 |
|
//register the pattern |
718 |
670 |
registerPattern( nn, tnn ); |
719 |
670 |
Assert(d_pattern_is_normal[nn]); |
720 |
670 |
Trace("sg-gen-tg-debug") << "...done collect pattern information" << std::endl; |
721 |
|
|
722 |
|
//record information about types |
723 |
670 |
Trace("sg-gen-tg-debug") << "Collect type information..." << std::endl; |
724 |
670 |
PatternTypIndex * pti = &d_rel_pattern_typ_index; |
725 |
1870 |
for( std::map< TypeNode, unsigned >::iterator it = d_tge.d_var_id.begin(); it != d_tge.d_var_id.end(); ++it ){ |
726 |
1200 |
pti = &pti->d_children[it->first][it->second]; |
727 |
|
//record maximum |
728 |
1200 |
if( rt_var_max.find( it->first )==rt_var_max.end() || it->second>rt_var_max[it->first] ){ |
729 |
60 |
rt_var_max[it->first] = it->second; |
730 |
|
} |
731 |
|
} |
732 |
670 |
if( std::find( rt_types.begin(), rt_types.end(), tnn )==rt_types.end() ){ |
733 |
95 |
rt_types.push_back( tnn ); |
734 |
|
} |
735 |
670 |
pti->d_terms.push_back( nn ); |
736 |
670 |
Trace("sg-gen-tg-debug") << "...done collect type information" << std::endl; |
737 |
|
|
738 |
670 |
Trace("sg-gen-tg-debug") << "Build substitutions for ground EQC..." << std::endl; |
739 |
1340 |
std::vector< TNode > gsubs_terms; |
740 |
670 |
gsubs_terms.resize( gsubs_vars.size() ); |
741 |
670 |
int index = d_tge.d_ccand_eqc[1].size()-1; |
742 |
23173 |
for( unsigned j=0; j<d_tge.d_ccand_eqc[1][index].size(); j++ ){ |
743 |
45006 |
TNode r = d_tge.d_ccand_eqc[1][index][j]; |
744 |
22503 |
Trace("sg-rel-term-debug") << " Matches for e" << d_em[r] << ", which is ground term " << d_ground_eqc_map[r] << ":" << std::endl; |
745 |
45006 |
std::map< TypeNode, std::map< unsigned, TNode > > subs; |
746 |
45006 |
std::map< TNode, bool > rev_subs; |
747 |
|
//only get ground terms |
748 |
22503 |
unsigned mode = 2; |
749 |
22503 |
d_tge.resetMatching( r, mode ); |
750 |
193755 |
while( d_tge.getNextMatch( r, subs, rev_subs ) ){ |
751 |
|
//we will be building substitutions |
752 |
85626 |
bool firstTime = true; |
753 |
215227 |
for( std::map< TypeNode, std::map< unsigned, TNode > >::iterator it = subs.begin(); it != subs.end(); ++it ){ |
754 |
129601 |
unsigned tindex = typ_to_subs_index[it->first]; |
755 |
318500 |
for( std::map< unsigned, TNode >::iterator it2 = it->second.begin(); it2 != it->second.end(); ++it2 ){ |
756 |
188899 |
if( !firstTime ){ |
757 |
103337 |
Trace("sg-rel-term-debug") << ", "; |
758 |
|
}else{ |
759 |
85562 |
firstTime = false; |
760 |
85562 |
Trace("sg-rel-term-debug") << " "; |
761 |
|
} |
762 |
188899 |
Trace("sg-rel-term-debug") << it->first << ":x" << it2->first << " -> " << it2->second; |
763 |
188899 |
Assert(tindex + it2->first < gsubs_terms.size()); |
764 |
188899 |
gsubs_terms[tindex+it2->first] = it2->second; |
765 |
|
} |
766 |
|
} |
767 |
85626 |
Trace("sg-rel-term-debug") << std::endl; |
768 |
85626 |
d_rel_pattern_subs_index[nn].addSubstitution( r, gsubs_vars, gsubs_terms ); |
769 |
|
} |
770 |
|
} |
771 |
670 |
Trace("sg-gen-tg-debug") << "...done build substitutions for ground EQC" << std::endl; |
772 |
|
}else{ |
773 |
|
Trace("sg-gen-tg-debug") << "> not canonical : " << nn << std::endl; |
774 |
|
} |
775 |
|
} |
776 |
121 |
Trace("sg-proc") << "...done generate terms at depth " << depth << std::endl; |
777 |
121 |
Trace("sg-stats") << "--------> Total LHS of depth " << depth << " : " << rel_term_count << std::endl; |
778 |
|
//Trace("conjecture-count") << "Total LHS of depth " << depth << " : " << conj_lhs[depth].size() << std::endl; |
779 |
|
|
780 |
|
/* test... |
781 |
|
for( unsigned i=0; i<rt_types.size(); i++ ){ |
782 |
|
Trace("sg-term-enum") << "Term enumeration for " << rt_types[i] << " : " << std::endl; |
783 |
|
Trace("sg-term-enum") << "Ground term : " << rt_types[i].mkGroundTerm() << std::endl; |
784 |
|
for( unsigned j=0; j<150; j++ ){ |
785 |
|
Trace("sg-term-enum") << " " << getEnumerateTerm( rt_types[i], j ) << std::endl; |
786 |
|
} |
787 |
|
} |
788 |
|
*/ |
789 |
|
|
790 |
|
//consider types from relevant terms |
791 |
439 |
for( unsigned rdepth=0; rdepth<=depth; rdepth++ ){ |
792 |
|
//set up environment |
793 |
336 |
d_tge.d_var_id.clear(); |
794 |
336 |
d_tge.d_var_limit.clear(); |
795 |
612 |
for( std::map< TypeNode, unsigned >::iterator it = rt_var_max.begin(); it != rt_var_max.end(); ++it ){ |
796 |
276 |
d_tge.d_var_id[ it->first ] = it->second; |
797 |
276 |
d_tge.d_var_limit[ it->first ] = it->second; |
798 |
|
} |
799 |
336 |
std::shuffle(rt_types.begin(), rt_types.end(), Random::getRandom()); |
800 |
654 |
std::map< TypeNode, std::vector< Node > > conj_rhs; |
801 |
1053 |
for( unsigned i=0; i<rt_types.size(); i++ ){ |
802 |
|
|
803 |
717 |
Trace("sg-proc") << "Generate relevant RHS terms of type " << rt_types[i] << " at depth " << rdepth << "..." << std::endl; |
804 |
717 |
d_tge.reset( rdepth, false, rt_types[i] ); |
805 |
|
|
806 |
5091 |
while( d_tge.getNextTerm() ){ |
807 |
4374 |
Node rhs = d_tge.getTerm(); |
808 |
2187 |
if( considerTermCanon( rhs, false ) ){ |
809 |
2187 |
Trace("sg-rel-prop") << "Relevant RHS : " << rhs << std::endl; |
810 |
|
//register pattern |
811 |
2187 |
Assert(rhs.getType() == rt_types[i]); |
812 |
2187 |
registerPattern( rhs, rt_types[i] ); |
813 |
2187 |
if( rdepth<depth ){ |
814 |
|
//consider against all LHS at depth |
815 |
15207 |
for( unsigned j=0; j<conj_lhs[rt_types[i]][depth].size(); j++ ){ |
816 |
13913 |
processCandidateConjecture( conj_lhs[rt_types[i]][depth][j], rhs, depth, rdepth ); |
817 |
|
} |
818 |
|
}else{ |
819 |
893 |
conj_rhs[rt_types[i]].push_back( rhs ); |
820 |
|
} |
821 |
|
} |
822 |
|
} |
823 |
|
} |
824 |
336 |
flushWaitingConjectures( addedLemmas, depth, rdepth ); |
825 |
|
//consider against all LHS up to depth |
826 |
336 |
if( rdepth==depth ){ |
827 |
304 |
for( unsigned lhs_depth = 1; lhs_depth<=depth; lhs_depth++ ){ |
828 |
197 |
if( (int)addedLemmas<options::conjectureGenPerRound() ){ |
829 |
197 |
Trace("sg-proc") << "Consider conjectures at depth (" << lhs_depth << ", " << rdepth << ")..." << std::endl; |
830 |
396 |
for( std::map< TypeNode, std::vector< Node > >::iterator it = conj_rhs.begin(); it != conj_rhs.end(); ++it ){ |
831 |
1815 |
for( unsigned j=0; j<it->second.size(); j++ ){ |
832 |
8843 |
for( unsigned k=0; k<conj_lhs[it->first][lhs_depth].size(); k++ ){ |
833 |
7227 |
processCandidateConjecture( conj_lhs[it->first][lhs_depth][k], it->second[j], lhs_depth, rdepth ); |
834 |
|
} |
835 |
|
} |
836 |
|
} |
837 |
197 |
flushWaitingConjectures( addedLemmas, lhs_depth, depth ); |
838 |
|
} |
839 |
|
} |
840 |
|
} |
841 |
336 |
if( (int)addedLemmas>=options::conjectureGenPerRound() ){ |
842 |
18 |
break; |
843 |
|
} |
844 |
|
} |
845 |
121 |
if( (int)addedLemmas>=options::conjectureGenPerRound() ){ |
846 |
18 |
break; |
847 |
|
} |
848 |
|
} |
849 |
44 |
Trace("sg-stats") << "Total conjectures considered : " << d_conj_count << std::endl; |
850 |
44 |
if( Trace.isOn("thm-ee") ){ |
851 |
|
Trace("thm-ee") << "Universal equality engine is : " << std::endl; |
852 |
|
eq::EqClassesIterator ueqcs_i = eq::EqClassesIterator( &d_uequalityEngine ); |
853 |
|
while( !ueqcs_i.isFinished() ){ |
854 |
|
TNode r = (*ueqcs_i); |
855 |
|
bool firstTime = true; |
856 |
|
Node rr = getUniversalRepresentative(r); |
857 |
|
Trace("thm-ee") << " " << rr; |
858 |
|
Trace("thm-ee") << " : { "; |
859 |
|
eq::EqClassIterator ueqc_i = eq::EqClassIterator( r, &d_uequalityEngine ); |
860 |
|
while( !ueqc_i.isFinished() ){ |
861 |
|
TNode n = (*ueqc_i); |
862 |
|
if( rr!=n ){ |
863 |
|
if( firstTime ){ |
864 |
|
Trace("thm-ee") << std::endl; |
865 |
|
firstTime = false; |
866 |
|
} |
867 |
|
Trace("thm-ee") << " " << n << std::endl; |
868 |
|
} |
869 |
|
++ueqc_i; |
870 |
|
} |
871 |
|
if( !firstTime ){ Trace("thm-ee") << " "; } |
872 |
|
Trace("thm-ee") << "}" << std::endl; |
873 |
|
++ueqcs_i; |
874 |
|
} |
875 |
|
Trace("thm-ee") << std::endl; |
876 |
|
} |
877 |
44 |
if( Trace.isOn("sg-engine") ){ |
878 |
|
double clSet2 = double(clock())/double(CLOCKS_PER_SEC); |
879 |
|
Trace("sg-engine") << "Finished conjecture generator, time = " << (clSet2-clSet) << std::endl; |
880 |
|
} |
881 |
|
} |
882 |
|
} |
883 |
166 |
} |
884 |
|
|
885 |
533 |
unsigned ConjectureGenerator::flushWaitingConjectures( unsigned& addedLemmas, int ldepth, int rdepth ) { |
886 |
533 |
if( !d_waiting_conjectures_lhs.empty() ){ |
887 |
26 |
Trace("sg-proc") << "Generated " << d_waiting_conjectures_lhs.size() << " conjectures at depth " << ldepth << "/" << rdepth << "." << std::endl; |
888 |
26 |
if( (int)addedLemmas<options::conjectureGenPerRound() ){ |
889 |
|
/* |
890 |
|
std::vector< unsigned > indices; |
891 |
|
for( unsigned i=0; i<d_waiting_conjectures_lhs.size(); i++ ){ |
892 |
|
indices.push_back( i ); |
893 |
|
} |
894 |
|
bool doSort = false; |
895 |
|
if( doSort ){ |
896 |
|
//sort them based on score |
897 |
|
sortConjectureScore scs; |
898 |
|
scs.d_scores.insert( scs.d_scores.begin(), d_waiting_conjectures_score.begin(), d_waiting_conjectures_score.end() ); |
899 |
|
std::sort( indices.begin(), indices.end(), scs ); |
900 |
|
} |
901 |
|
//if( doSort && d_waiting_conjectures_score[indices[0]]<optFilterScoreThreshold() ){ |
902 |
|
*/ |
903 |
26 |
unsigned prevCount = d_conj_count; |
904 |
42 |
for( unsigned i=0; i<d_waiting_conjectures_lhs.size(); i++ ){ |
905 |
34 |
if( d_waiting_conjectures_score[i]>=optFilterScoreThreshold() ){ |
906 |
|
//we have determined a relevant subgoal |
907 |
50 |
Node lhs = d_waiting_conjectures_lhs[i]; |
908 |
50 |
Node rhs = d_waiting_conjectures_rhs[i]; |
909 |
34 |
if( options::conjectureFilterCanonical() && ( getUniversalRepresentative( lhs )!=lhs || getUniversalRepresentative( rhs )!=rhs ) ){ |
910 |
|
//skip |
911 |
|
}else{ |
912 |
18 |
Trace("sg-engine") << "*** Consider conjecture : " << lhs << " == " << rhs << std::endl; |
913 |
18 |
Trace("sg-engine-debug") << " score : " << d_waiting_conjectures_score[i] << std::endl; |
914 |
18 |
if( optStatsOnly() ){ |
915 |
|
d_conj_count++; |
916 |
|
}else{ |
917 |
18 |
std::vector< Node > bvs; |
918 |
25 |
for (const std::pair<const TypeNode, unsigned>& lhs_pattern : |
919 |
18 |
d_pattern_var_id[lhs]) |
920 |
|
{ |
921 |
50 |
for (unsigned j = 0; j <= lhs_pattern.second; j++) |
922 |
|
{ |
923 |
25 |
bvs.push_back(getFreeVar(lhs_pattern.first, j)); |
924 |
|
} |
925 |
|
} |
926 |
18 |
Node rsg; |
927 |
18 |
if( !bvs.empty() ){ |
928 |
36 |
Node bvl = NodeManager::currentNM()->mkNode( BOUND_VAR_LIST, bvs ); |
929 |
18 |
rsg = NodeManager::currentNM()->mkNode( FORALL, bvl, lhs.eqNode( rhs ) ); |
930 |
|
}else{ |
931 |
|
rsg = lhs.eqNode( rhs ); |
932 |
|
} |
933 |
18 |
rsg = Rewriter::rewrite( rsg ); |
934 |
18 |
d_conjectures.push_back( rsg ); |
935 |
18 |
d_eq_conjectures[lhs].push_back( rhs ); |
936 |
18 |
d_eq_conjectures[rhs].push_back( lhs ); |
937 |
|
|
938 |
18 |
Node lem = NodeManager::currentNM()->mkNode( OR, rsg.negate(), rsg ); |
939 |
18 |
d_qim.addPendingLemma(lem, |
940 |
|
InferenceId::QUANTIFIERS_CONJ_GEN_SPLIT); |
941 |
18 |
d_qim.addPendingPhaseRequirement(rsg, false); |
942 |
18 |
addedLemmas++; |
943 |
18 |
if( (int)addedLemmas>=options::conjectureGenPerRound() ){ |
944 |
18 |
break; |
945 |
|
} |
946 |
|
} |
947 |
|
} |
948 |
|
} |
949 |
|
} |
950 |
26 |
Trace("sg-proc") << "...have now added " << addedLemmas << " conjecture lemmas." << std::endl; |
951 |
26 |
if( optStatsOnly() ){ |
952 |
|
Trace("sg-stats") << "Generated " << (d_conj_count-prevCount) << " conjectures at depth " << ldepth << "/" << rdepth << "." << std::endl; |
953 |
|
} |
954 |
|
} |
955 |
26 |
d_waiting_conjectures_lhs.clear(); |
956 |
26 |
d_waiting_conjectures_rhs.clear(); |
957 |
26 |
d_waiting_conjectures_score.clear(); |
958 |
26 |
d_waiting_conjectures.clear(); |
959 |
|
} |
960 |
533 |
return addedLemmas; |
961 |
|
} |
962 |
|
|
963 |
7553 |
bool ConjectureGenerator::considerTermCanon( Node ln, bool genRelevant ){ |
964 |
7553 |
if( !ln.isNull() ){ |
965 |
|
//do not consider if it is non-canonical, and either: |
966 |
|
// (1) we are not generating relevant terms, or |
967 |
|
// (2) its canonical form is a generalization. |
968 |
14938 |
Node lnr = getUniversalRepresentative(ln, true); |
969 |
7553 |
if( lnr==ln ){ |
970 |
7193 |
markReportedCanon( ln ); |
971 |
360 |
}else if( !genRelevant || isGeneralization( lnr, ln ) ){ |
972 |
168 |
Trace("sg-gen-consider-term") << "Do not consider term, " << ln << " is not canonical representation (which is " << lnr << ")." << std::endl; |
973 |
168 |
return false; |
974 |
|
} |
975 |
|
} |
976 |
7385 |
Trace("sg-gen-tg-debug") << "Will consider term canon " << ln << std::endl; |
977 |
7385 |
Trace("sg-gen-consider-term-debug") << std::endl; |
978 |
7385 |
return true; |
979 |
|
} |
980 |
|
|
981 |
5547 |
unsigned ConjectureGenerator::collectFunctions( TNode opat, TNode pat, std::map< TNode, unsigned >& funcs, |
982 |
|
std::map< TypeNode, unsigned >& mnvn, std::map< TypeNode, unsigned >& mxvn ){ |
983 |
5547 |
if( pat.hasOperator() ){ |
984 |
3003 |
funcs[pat.getOperator()]++; |
985 |
3003 |
if( !d_tge.isRelevantFunc( pat.getOperator() ) ){ |
986 |
|
d_pattern_is_relevant[opat] = false; |
987 |
|
} |
988 |
3003 |
unsigned sum = 1; |
989 |
6940 |
for( unsigned i=0; i<pat.getNumChildren(); i++ ){ |
990 |
3937 |
sum += collectFunctions( opat, pat[i], funcs, mnvn, mxvn ); |
991 |
|
} |
992 |
3003 |
return sum; |
993 |
|
}else{ |
994 |
2544 |
Assert(pat.getNumChildren() == 0); |
995 |
2544 |
funcs[pat]++; |
996 |
|
//for variables |
997 |
2544 |
if( pat.getKind()==BOUND_VARIABLE ){ |
998 |
2527 |
if( funcs[pat]>1 ){ |
999 |
|
//duplicate variable |
1000 |
31 |
d_pattern_var_duplicate[opat]++; |
1001 |
|
}else{ |
1002 |
|
//check for max/min |
1003 |
4992 |
TypeNode tn = pat.getType(); |
1004 |
2496 |
unsigned vn = pat.getAttribute(InstVarNumAttribute()); |
1005 |
2496 |
std::map< TypeNode, unsigned >::iterator it = mnvn.find( tn ); |
1006 |
2496 |
if( it!=mnvn.end() ){ |
1007 |
316 |
if( vn<it->second ){ |
1008 |
|
d_pattern_is_normal[opat] = false; |
1009 |
|
mnvn[tn] = vn; |
1010 |
316 |
}else if( vn>mxvn[tn] ){ |
1011 |
|
if( vn!=mxvn[tn]+1 ){ |
1012 |
|
d_pattern_is_normal[opat] = false; |
1013 |
|
} |
1014 |
|
mxvn[tn] = vn; |
1015 |
|
} |
1016 |
|
}else{ |
1017 |
|
//first variable of this type |
1018 |
2180 |
mnvn[tn] = vn; |
1019 |
2180 |
mxvn[tn] = vn; |
1020 |
|
} |
1021 |
|
} |
1022 |
|
}else{ |
1023 |
17 |
d_pattern_is_relevant[opat] = false; |
1024 |
|
} |
1025 |
2544 |
return 1; |
1026 |
|
} |
1027 |
|
} |
1028 |
|
|
1029 |
7986 |
void ConjectureGenerator::registerPattern( Node pat, TypeNode tpat ) { |
1030 |
7986 |
if( std::find( d_patterns[tpat].begin(), d_patterns[tpat].end(), pat )==d_patterns[tpat].end() ){ |
1031 |
1610 |
d_patterns[TypeNode::null()].push_back( pat ); |
1032 |
1610 |
d_patterns[tpat].push_back( pat ); |
1033 |
|
|
1034 |
1610 |
Assert(d_pattern_fun_id.find(pat) == d_pattern_fun_id.end()); |
1035 |
1610 |
Assert(d_pattern_var_id.find(pat) == d_pattern_var_id.end()); |
1036 |
|
|
1037 |
|
//collect functions |
1038 |
3220 |
std::map< TypeNode, unsigned > mnvn; |
1039 |
1610 |
d_pattern_fun_sum[pat] = collectFunctions( pat, pat, d_pattern_fun_id[pat], mnvn, d_pattern_var_id[pat] ); |
1040 |
1610 |
if( d_pattern_is_normal.find( pat )==d_pattern_is_normal.end() ){ |
1041 |
1610 |
d_pattern_is_normal[pat] = true; |
1042 |
|
} |
1043 |
1610 |
if( d_pattern_is_relevant.find( pat )==d_pattern_is_relevant.end() ){ |
1044 |
1593 |
d_pattern_is_relevant[pat] = true; |
1045 |
|
} |
1046 |
|
} |
1047 |
7986 |
} |
1048 |
|
|
1049 |
234 |
bool ConjectureGenerator::isGeneralization( TNode patg, TNode pat, std::map< TNode, TNode >& subs ) { |
1050 |
234 |
if( patg.getKind()==BOUND_VARIABLE ){ |
1051 |
8 |
std::map< TNode, TNode >::iterator it = subs.find( patg ); |
1052 |
8 |
if( it!=subs.end() ){ |
1053 |
|
return it->second==pat; |
1054 |
|
}else{ |
1055 |
8 |
subs[patg] = pat; |
1056 |
8 |
return true; |
1057 |
|
} |
1058 |
|
}else{ |
1059 |
226 |
Assert(patg.hasOperator()); |
1060 |
226 |
if( !pat.hasOperator() || patg.getOperator()!=pat.getOperator() ){ |
1061 |
192 |
return false; |
1062 |
|
}else{ |
1063 |
34 |
Assert(patg.getNumChildren() == pat.getNumChildren()); |
1064 |
42 |
for( unsigned i=0; i<patg.getNumChildren(); i++ ){ |
1065 |
42 |
if( !isGeneralization( patg[i], pat[i], subs ) ){ |
1066 |
34 |
return false; |
1067 |
|
} |
1068 |
|
} |
1069 |
|
return true; |
1070 |
|
} |
1071 |
|
} |
1072 |
|
} |
1073 |
|
|
1074 |
|
int ConjectureGenerator::calculateGeneralizationDepth( TNode n, std::vector< TNode >& fv ) { |
1075 |
|
if( n.getKind()==BOUND_VARIABLE ){ |
1076 |
|
if( std::find( fv.begin(), fv.end(), n )==fv.end() ){ |
1077 |
|
fv.push_back( n ); |
1078 |
|
return 0; |
1079 |
|
}else{ |
1080 |
|
return 1; |
1081 |
|
} |
1082 |
|
}else{ |
1083 |
|
int depth = 1; |
1084 |
|
for( unsigned i=0; i<n.getNumChildren(); i++ ){ |
1085 |
|
depth += calculateGeneralizationDepth( n[i], fv ); |
1086 |
|
} |
1087 |
|
return depth; |
1088 |
|
} |
1089 |
|
} |
1090 |
|
|
1091 |
15 |
Node ConjectureGenerator::getPredicateForType( TypeNode tn ) { |
1092 |
15 |
std::map< TypeNode, Node >::iterator it = d_typ_pred.find( tn ); |
1093 |
15 |
if( it==d_typ_pred.end() ){ |
1094 |
11 |
NodeManager* nm = NodeManager::currentNM(); |
1095 |
11 |
SkolemManager* sm = nm->getSkolemManager(); |
1096 |
22 |
TypeNode op_tn = nm->mkFunctionType(tn, nm->booleanType()); |
1097 |
|
Node op = sm->mkDummySkolem( |
1098 |
22 |
"PE", op_tn, "was created by conjecture ground term enumerator."); |
1099 |
11 |
d_typ_pred[tn] = op; |
1100 |
11 |
return op; |
1101 |
|
}else{ |
1102 |
4 |
return it->second; |
1103 |
|
} |
1104 |
|
} |
1105 |
|
|
1106 |
15 |
void ConjectureGenerator::getEnumerateUfTerm( Node n, unsigned num, std::vector< Node >& terms ) { |
1107 |
15 |
if( n.getNumChildren()>0 ){ |
1108 |
30 |
Trace("sg-gt-enum-debug") << "Get enumerate uf terms " << n << " (" << num |
1109 |
15 |
<< ")" << std::endl; |
1110 |
15 |
TermEnumeration* te = d_treg.getTermEnumeration(); |
1111 |
|
// below, we do a fair enumeration of vectors vec of indices whose sum is |
1112 |
|
// 1,2,3, ... |
1113 |
30 |
std::vector< int > vec; |
1114 |
30 |
std::vector< TypeNode > types; |
1115 |
34 |
for( unsigned i=0; i<n.getNumChildren(); i++ ){ |
1116 |
19 |
vec.push_back( 0 ); |
1117 |
38 |
TypeNode tn = n[i].getType(); |
1118 |
19 |
if (tn.isClosedEnumerable()) |
1119 |
|
{ |
1120 |
19 |
types.push_back( tn ); |
1121 |
|
}else{ |
1122 |
|
return; |
1123 |
|
} |
1124 |
|
} |
1125 |
|
// the index of the last child is determined by the limit of the sum |
1126 |
|
// of indices of children (size_limit) and the sum of the indices of the |
1127 |
|
// other children (vec_sum). Hence, we pop here and add this value at each |
1128 |
|
// iteration of the loop. |
1129 |
15 |
vec.pop_back(); |
1130 |
15 |
int size_limit = 0; |
1131 |
15 |
int vec_sum = -1; |
1132 |
15 |
unsigned index = 0; |
1133 |
15 |
unsigned last_size = terms.size(); |
1134 |
2665 |
while( terms.size()<num ){ |
1135 |
1325 |
if( vec_sum==-1 ){ |
1136 |
590 |
vec_sum = 0; |
1137 |
|
// we will construct a new child below |
1138 |
|
// since sum is 0, the index of last child is limit |
1139 |
590 |
vec.push_back( size_limit ); |
1140 |
|
} |
1141 |
735 |
else if (index < vec.size()) |
1142 |
|
{ |
1143 |
196 |
Assert(index < types.size()); |
1144 |
|
//see if we can iterate current |
1145 |
392 |
if (vec_sum < size_limit |
1146 |
392 |
&& !te->getEnumerateTerm(types[index], vec[index] + 1).isNull()) |
1147 |
|
{ |
1148 |
160 |
vec[index]++; |
1149 |
160 |
vec_sum++; |
1150 |
|
// we will construct a new child below |
1151 |
|
// add the index of the last child, its index is (limit-sum) |
1152 |
160 |
vec.push_back( size_limit - vec_sum ); |
1153 |
|
}else{ |
1154 |
|
// reset the index |
1155 |
36 |
vec_sum -= vec[index]; |
1156 |
36 |
vec[index] = 0; |
1157 |
36 |
index++; |
1158 |
|
} |
1159 |
|
} |
1160 |
1325 |
if (index < vec.size()) |
1161 |
|
{ |
1162 |
|
// if we are ready to construct the term |
1163 |
750 |
if( vec.size()==n.getNumChildren() ){ |
1164 |
|
Node lc = |
1165 |
1500 |
te->getEnumerateTerm(types[vec.size() - 1], vec[vec.size() - 1]); |
1166 |
750 |
if( !lc.isNull() ){ |
1167 |
1700 |
for( unsigned i=0; i<vec.size(); i++ ){ |
1168 |
950 |
Trace("sg-gt-enum-debug") << vec[i] << " "; |
1169 |
|
} |
1170 |
750 |
Trace("sg-gt-enum-debug") << " / " << size_limit << std::endl; |
1171 |
1700 |
for( unsigned i=0; i<n.getNumChildren(); i++ ){ |
1172 |
950 |
Trace("sg-gt-enum-debug") << n[i].getType() << " "; |
1173 |
|
} |
1174 |
750 |
Trace("sg-gt-enum-debug") << std::endl; |
1175 |
1500 |
std::vector< Node > children; |
1176 |
750 |
children.push_back( n.getOperator() ); |
1177 |
950 |
for( unsigned i=0; i<(vec.size()-1); i++ ){ |
1178 |
400 |
Node nn = te->getEnumerateTerm(types[i], vec[i]); |
1179 |
200 |
Assert(!nn.isNull()); |
1180 |
200 |
Assert(nn.getType() == n[i].getType()); |
1181 |
200 |
children.push_back( nn ); |
1182 |
|
} |
1183 |
750 |
children.push_back( lc ); |
1184 |
1500 |
Node nenum = NodeManager::currentNM()->mkNode(APPLY_UF, children); |
1185 |
1500 |
Trace("sg-gt-enum") |
1186 |
750 |
<< "Ground term enumerate : " << nenum << std::endl; |
1187 |
750 |
terms.push_back(nenum); |
1188 |
|
} |
1189 |
|
// pop the index for the last child |
1190 |
750 |
vec.pop_back(); |
1191 |
750 |
index = 0; |
1192 |
|
} |
1193 |
|
}else{ |
1194 |
|
// no more indices to increment, we reset and increment size_limit |
1195 |
575 |
if( terms.size()>last_size ){ |
1196 |
575 |
last_size = terms.size(); |
1197 |
575 |
size_limit++; |
1198 |
611 |
for( unsigned i=0; i<vec.size(); i++ ){ |
1199 |
36 |
vec[i] = 0; |
1200 |
|
} |
1201 |
575 |
vec_sum = -1; |
1202 |
|
}else{ |
1203 |
|
// No terms were generated at the previous size. |
1204 |
|
// Thus, we've saturated, no more terms can be enumerated. |
1205 |
|
return; |
1206 |
|
} |
1207 |
|
} |
1208 |
|
} |
1209 |
|
}else{ |
1210 |
|
terms.push_back( n ); |
1211 |
|
} |
1212 |
|
} |
1213 |
|
|
1214 |
15 |
void ConjectureGenerator::getEnumeratePredUfTerm( Node n, unsigned num, std::vector< Node >& terms ) { |
1215 |
30 |
std::vector< Node > uf_terms; |
1216 |
15 |
getEnumerateUfTerm( n, num, uf_terms ); |
1217 |
30 |
Node p = getPredicateForType( n.getType() ); |
1218 |
765 |
for( unsigned i=0; i<uf_terms.size(); i++ ){ |
1219 |
750 |
terms.push_back( NodeManager::currentNM()->mkNode( APPLY_UF, p, uf_terms[i] ) ); |
1220 |
|
} |
1221 |
15 |
} |
1222 |
|
|
1223 |
21140 |
void ConjectureGenerator::processCandidateConjecture( TNode lhs, TNode rhs, unsigned lhs_depth, unsigned rhs_depth ) { |
1224 |
21140 |
int score = considerCandidateConjecture( lhs, rhs ); |
1225 |
21140 |
if( score>0 ){ |
1226 |
63 |
Trace("sg-conjecture") << "* Candidate conjecture : " << lhs << " == " << rhs << std::endl; |
1227 |
63 |
Trace("sg-conjecture-debug") << " LHS, RHS generalization depth : " << lhs_depth << ", " << rhs_depth << std::endl; |
1228 |
63 |
Trace("sg-conjecture-debug") << " confirmed = " << d_subs_confirmCount << ", #witnesses range = " << d_subs_confirmWitnessRange.size() << "." << std::endl; |
1229 |
63 |
Trace("sg-conjecture-debug") << " #witnesses for "; |
1230 |
63 |
bool firstTime = true; |
1231 |
170 |
for( std::map< TNode, std::vector< TNode > >::iterator it = d_subs_confirmWitnessDomain.begin(); it != d_subs_confirmWitnessDomain.end(); ++it ){ |
1232 |
107 |
if( !firstTime ){ |
1233 |
44 |
Trace("sg-conjecture-debug") << ", "; |
1234 |
|
} |
1235 |
107 |
Trace("sg-conjecture-debug") << it->first << " : " << it->second.size(); |
1236 |
|
//if( it->second.size()==1 ){ |
1237 |
|
// Trace("sg-conjecture-debug") << " (" << it->second[0] << ")"; |
1238 |
|
//} |
1239 |
107 |
Trace("sg-conjecture-debug2") << " ("; |
1240 |
2919 |
for( unsigned j=0; j<it->second.size(); j++ ){ |
1241 |
2812 |
if( j>0 ){ Trace("sg-conjecture-debug2") << " "; } |
1242 |
2812 |
Trace("sg-conjecture-debug2") << d_ground_eqc_map[it->second[j]]; |
1243 |
|
} |
1244 |
107 |
Trace("sg-conjecture-debug2") << ")"; |
1245 |
107 |
firstTime = false; |
1246 |
|
} |
1247 |
63 |
Trace("sg-conjecture-debug") << std::endl; |
1248 |
63 |
Trace("sg-conjecture-debug") << " unknown = " << d_subs_unkCount << std::endl; |
1249 |
|
//Assert( getUniversalRepresentative( rhs )==rhs ); |
1250 |
|
//Assert( getUniversalRepresentative( lhs )==lhs ); |
1251 |
63 |
d_waiting_conjectures_lhs.push_back( lhs ); |
1252 |
63 |
d_waiting_conjectures_rhs.push_back( rhs ); |
1253 |
63 |
d_waiting_conjectures_score.push_back( score ); |
1254 |
63 |
d_waiting_conjectures[lhs].push_back( rhs ); |
1255 |
63 |
d_waiting_conjectures[rhs].push_back( lhs ); |
1256 |
|
}else{ |
1257 |
21077 |
Trace("sg-conjecture-debug2") << "...do not consider " << lhs << " == " << rhs << ", score = " << score << std::endl; |
1258 |
|
} |
1259 |
21140 |
} |
1260 |
|
|
1261 |
21140 |
int ConjectureGenerator::considerCandidateConjecture( TNode lhs, TNode rhs ) { |
1262 |
21140 |
Assert(lhs.getType() == rhs.getType()); |
1263 |
|
|
1264 |
21140 |
Trace("sg-cconj-debug") << "Consider candidate conjecture : " << lhs << " == " << rhs << "?" << std::endl; |
1265 |
21140 |
if( lhs==rhs ){ |
1266 |
318 |
Trace("sg-cconj-debug") << " -> trivial." << std::endl; |
1267 |
318 |
return -1; |
1268 |
|
}else{ |
1269 |
20822 |
if( lhs.getKind()==APPLY_CONSTRUCTOR && rhs.getKind()==APPLY_CONSTRUCTOR ){ |
1270 |
3794 |
Trace("sg-cconj-debug") << " -> irrelevant by syntactic analysis." << std::endl; |
1271 |
3794 |
return -1; |
1272 |
|
} |
1273 |
|
//variables of LHS must subsume variables of RHS |
1274 |
36987 |
for( std::map< TypeNode, unsigned >::iterator it = d_pattern_var_id[rhs].begin(); it != d_pattern_var_id[rhs].end(); ++it ){ |
1275 |
24750 |
std::map< TypeNode, unsigned >::iterator itl = d_pattern_var_id[lhs].find( it->first ); |
1276 |
24750 |
if( itl!=d_pattern_var_id[lhs].end() ){ |
1277 |
19959 |
if( itl->second<it->second ){ |
1278 |
|
Trace("sg-cconj-debug") << " -> variables of sort " << it->first << " are not subsumed." << std::endl; |
1279 |
4791 |
return -1; |
1280 |
|
}else{ |
1281 |
19959 |
Trace("sg-cconj-debug2") << " variables of sort " << it->first << " are : " << itl->second << " vs " << it->second << std::endl; |
1282 |
|
} |
1283 |
|
}else{ |
1284 |
4791 |
Trace("sg-cconj-debug") << " -> has no variables of sort " << it->first << "." << std::endl; |
1285 |
4791 |
return -1; |
1286 |
|
} |
1287 |
|
} |
1288 |
|
|
1289 |
|
//currently active conjecture? |
1290 |
12237 |
std::map< Node, std::vector< Node > >::iterator iteq = d_eq_conjectures.find( lhs ); |
1291 |
12237 |
if( iteq!=d_eq_conjectures.end() ){ |
1292 |
353 |
if( std::find( iteq->second.begin(), iteq->second.end(), rhs )!=iteq->second.end() ){ |
1293 |
31 |
Trace("sg-cconj-debug") << " -> this conjecture is already active." << std::endl; |
1294 |
31 |
return -1; |
1295 |
|
} |
1296 |
|
} |
1297 |
|
//current a waiting conjecture? |
1298 |
12206 |
std::map< Node, std::vector< Node > >::iterator itw = d_waiting_conjectures.find( lhs ); |
1299 |
12206 |
if( itw!=d_waiting_conjectures.end() ){ |
1300 |
165 |
if( std::find( itw->second.begin(), itw->second.end(), rhs )!=itw->second.end() ){ |
1301 |
|
Trace("sg-cconj-debug") << " -> already are considering this conjecture." << std::endl; |
1302 |
|
return -1; |
1303 |
|
} |
1304 |
|
} |
1305 |
|
//check if canonical representation (should be, but for efficiency this is not guarenteed) |
1306 |
|
//if( options::conjectureFilterCanonical() && ( getUniversalRepresentative( lhs )!=lhs || getUniversalRepresentative( rhs )!=rhs ) ){ |
1307 |
|
// Trace("sg-cconj") << " -> after processing, not canonical." << std::endl; |
1308 |
|
// return -1; |
1309 |
|
//} |
1310 |
|
|
1311 |
|
int score; |
1312 |
12206 |
bool scoreSet = false; |
1313 |
|
|
1314 |
12206 |
Trace("sg-cconj") << "Consider possible candidate conjecture : " << lhs << " == " << rhs << "?" << std::endl; |
1315 |
|
//find witness for counterexample, if possible |
1316 |
12206 |
if( options::conjectureFilterModel() ){ |
1317 |
12206 |
Assert(d_rel_pattern_var_sum.find(lhs) != d_rel_pattern_var_sum.end()); |
1318 |
12206 |
Trace("sg-cconj-debug") << "Notify substitutions over " << d_rel_pattern_var_sum[lhs] << " variables." << std::endl; |
1319 |
19215 |
std::map< TNode, TNode > subs; |
1320 |
12206 |
d_subs_confirmCount = 0; |
1321 |
12206 |
d_subs_confirmWitnessRange.clear(); |
1322 |
12206 |
d_subs_confirmWitnessDomain.clear(); |
1323 |
12206 |
d_subs_unkCount = 0; |
1324 |
12206 |
if( !d_rel_pattern_subs_index[lhs].notifySubstitutions( this, subs, rhs, d_rel_pattern_var_sum[lhs] ) ){ |
1325 |
5197 |
Trace("sg-cconj") << " -> found witness that falsifies the conjecture." << std::endl; |
1326 |
5197 |
return -1; |
1327 |
|
} |
1328 |
|
//score is the minimum number of distinct substitutions for a variable |
1329 |
7116 |
for( std::map< TNode, std::vector< TNode > >::iterator it = d_subs_confirmWitnessDomain.begin(); it != d_subs_confirmWitnessDomain.end(); ++it ){ |
1330 |
107 |
int num = (int)it->second.size(); |
1331 |
107 |
if( !scoreSet || num<score ){ |
1332 |
73 |
score = num; |
1333 |
73 |
scoreSet = true; |
1334 |
|
} |
1335 |
|
} |
1336 |
7009 |
if( !scoreSet ){ |
1337 |
6946 |
score = 0; |
1338 |
|
} |
1339 |
7009 |
Trace("sg-cconj") << " confirmed = " << d_subs_confirmCount << ", #witnesses range = " << d_subs_confirmWitnessRange.size() << "." << std::endl; |
1340 |
7116 |
for( std::map< TNode, std::vector< TNode > >::iterator it = d_subs_confirmWitnessDomain.begin(); it != d_subs_confirmWitnessDomain.end(); ++it ){ |
1341 |
107 |
Trace("sg-cconj") << " #witnesses for " << it->first << " : " << it->second.size() << std::endl; |
1342 |
|
} |
1343 |
|
}else{ |
1344 |
|
score = 1; |
1345 |
|
} |
1346 |
|
|
1347 |
7009 |
Trace("sg-cconj") << " -> SUCCESS." << std::endl; |
1348 |
7009 |
Trace("sg-cconj") << " score : " << score << std::endl; |
1349 |
|
|
1350 |
7009 |
return score; |
1351 |
|
} |
1352 |
|
} |
1353 |
|
|
1354 |
860201 |
bool ConjectureGenerator::notifySubstitution( TNode glhs, std::map< TNode, TNode >& subs, TNode rhs ) { |
1355 |
860201 |
if( Trace.isOn("sg-cconj-debug") ){ |
1356 |
|
Trace("sg-cconj-debug") << "Ground eqc for LHS : " << glhs << ", based on substituion: " << std::endl; |
1357 |
|
for( std::map< TNode, TNode >::iterator it = subs.begin(); it != subs.end(); ++it ){ |
1358 |
|
Assert(getRepresentative(it->second) == it->second); |
1359 |
|
Trace("sg-cconj-debug") << " " << it->first << " -> " << it->second << std::endl; |
1360 |
|
} |
1361 |
|
} |
1362 |
860201 |
Trace("sg-cconj-debug") << "Evaluate RHS : : " << rhs << std::endl; |
1363 |
|
//get the representative of rhs with substitution subs |
1364 |
1720402 |
TNode grhs = getTermDatabase()->getEntailedTerm( rhs, subs, true ); |
1365 |
860201 |
Trace("sg-cconj-debug") << "...done evaluating term, got : " << grhs << std::endl; |
1366 |
860201 |
if( !grhs.isNull() ){ |
1367 |
17604 |
if( glhs!=grhs ){ |
1368 |
5197 |
Trace("sg-cconj-debug") << "Ground eqc for RHS : " << grhs << std::endl; |
1369 |
|
//check based on ground terms |
1370 |
5197 |
std::map< TNode, Node >::iterator itl = d_ground_eqc_map.find( glhs ); |
1371 |
5197 |
if( itl!=d_ground_eqc_map.end() ){ |
1372 |
5197 |
std::map< TNode, Node >::iterator itr = d_ground_eqc_map.find( grhs ); |
1373 |
5197 |
if( itr!=d_ground_eqc_map.end() ){ |
1374 |
1785 |
Trace("sg-cconj-debug") << "We have ground terms " << itl->second << " and " << itr->second << "." << std::endl; |
1375 |
1785 |
if( itl->second.isConst() && itr->second.isConst() ){ |
1376 |
1717 |
Trace("sg-cconj-debug") << "...disequal constants." << std::endl; |
1377 |
1717 |
Trace("sg-cconj-witness") << " Witness of falsification : " << itl->second << " != " << itr->second << ", substutition is : " << std::endl; |
1378 |
5671 |
for( std::map< TNode, TNode >::iterator it = subs.begin(); it != subs.end(); ++it ){ |
1379 |
3954 |
Trace("sg-cconj-witness") << " " << it->first << " -> " << it->second << std::endl; |
1380 |
|
} |
1381 |
1717 |
return false; |
1382 |
|
} |
1383 |
|
} |
1384 |
|
} |
1385 |
|
} |
1386 |
15887 |
Trace("sg-cconj-debug") << "RHS is identical." << std::endl; |
1387 |
15887 |
bool isGroundSubs = true; |
1388 |
48948 |
for( std::map< TNode, TNode >::iterator it = subs.begin(); it != subs.end(); ++it ){ |
1389 |
33061 |
std::map< TNode, Node >::iterator git = d_ground_eqc_map.find( it->second ); |
1390 |
33061 |
if( git==d_ground_eqc_map.end() ){ |
1391 |
|
isGroundSubs = false; |
1392 |
|
break; |
1393 |
|
} |
1394 |
|
} |
1395 |
15887 |
if( isGroundSubs ){ |
1396 |
15887 |
if( glhs==grhs ){ |
1397 |
12407 |
Trace("sg-cconj-witness") << " Witnessed " << glhs << " == " << grhs << ", substutition is : " << std::endl; |
1398 |
37039 |
for( std::map< TNode, TNode >::iterator it = subs.begin(); it != subs.end(); ++it ){ |
1399 |
24632 |
Trace("sg-cconj-witness") << " " << it->first << " -> " << it->second << std::endl; |
1400 |
24632 |
if( std::find( d_subs_confirmWitnessDomain[it->first].begin(), d_subs_confirmWitnessDomain[it->first].end(), it->second )==d_subs_confirmWitnessDomain[it->first].end() ){ |
1401 |
5642 |
d_subs_confirmWitnessDomain[it->first].push_back( it->second ); |
1402 |
|
} |
1403 |
|
} |
1404 |
12407 |
d_subs_confirmCount++; |
1405 |
12407 |
if( std::find( d_subs_confirmWitnessRange.begin(), d_subs_confirmWitnessRange.end(), glhs )==d_subs_confirmWitnessRange.end() ){ |
1406 |
2660 |
d_subs_confirmWitnessRange.push_back( glhs ); |
1407 |
|
} |
1408 |
|
}else{ |
1409 |
3480 |
if( optFilterUnknown() ){ |
1410 |
3480 |
Trace("sg-cconj-debug") << "...ground substitution giving terms that are neither equal nor disequal." << std::endl; |
1411 |
3480 |
return false; |
1412 |
|
} |
1413 |
|
} |
1414 |
|
} |
1415 |
|
}else{ |
1416 |
842597 |
Trace("sg-cconj-debug") << "(could not ground eqc for RHS)." << std::endl; |
1417 |
|
} |
1418 |
855004 |
return true; |
1419 |
|
} |
1420 |
|
|
1421 |
|
|
1422 |
|
|
1423 |
|
|
1424 |
|
|
1425 |
|
|
1426 |
3660 |
void TermGenerator::reset( TermGenEnv * s, TypeNode tn ) { |
1427 |
3660 |
Assert(d_children.empty()); |
1428 |
3660 |
d_typ = tn; |
1429 |
3660 |
d_status = 0; |
1430 |
3660 |
d_status_num = 0; |
1431 |
3660 |
d_children.clear(); |
1432 |
3660 |
Trace("sg-gen-tg-debug2") << "...add to context " << this << std::endl; |
1433 |
3660 |
d_id = s->d_tg_id; |
1434 |
3660 |
s->changeContext( true ); |
1435 |
3660 |
} |
1436 |
|
|
1437 |
48520 |
bool TermGenerator::getNextTerm( TermGenEnv * s, unsigned depth ) { |
1438 |
48520 |
if( Trace.isOn("sg-gen-tg-debug2") ){ |
1439 |
|
Trace("sg-gen-tg-debug2") << this << " getNextTerm depth " << depth << " : status = " << d_status << ", num = " << d_status_num; |
1440 |
|
if( d_status==5 ){ |
1441 |
|
TNode f = s->getTgFunc( d_typ, d_status_num ); |
1442 |
|
Trace("sg-gen-tg-debug2") << ", f = " << f; |
1443 |
|
Trace("sg-gen-tg-debug2") << ", #args = " << s->d_func_args[f].size(); |
1444 |
|
Trace("sg-gen-tg-debug2") << ", childNum = " << d_status_child_num; |
1445 |
|
Trace("sg-gen-tg-debug2") << ", #children = " << d_children.size(); |
1446 |
|
} |
1447 |
|
Trace("sg-gen-tg-debug2") << std::endl; |
1448 |
|
} |
1449 |
|
|
1450 |
48520 |
if( d_status==0 ){ |
1451 |
3660 |
d_status++; |
1452 |
3660 |
if( !d_typ.isNull() ){ |
1453 |
3539 |
if( s->allowVar( d_typ ) ){ |
1454 |
|
//allocate variable |
1455 |
1689 |
d_status_num = s->d_var_id[d_typ]; |
1456 |
1689 |
s->addVar( d_typ ); |
1457 |
1689 |
Trace("sg-gen-tg-debug2") << this << " ...return unique var #" << d_status_num << std::endl; |
1458 |
1689 |
return s->considerCurrentTerm() ? true : getNextTerm( s, depth ); |
1459 |
|
}else{ |
1460 |
|
//check allocating new variable |
1461 |
1850 |
d_status++; |
1462 |
1850 |
d_status_num = -1; |
1463 |
1850 |
if( s->d_gen_relevant_terms ){ |
1464 |
|
s->d_tg_gdepth++; |
1465 |
|
} |
1466 |
1850 |
return getNextTerm( s, depth ); |
1467 |
|
} |
1468 |
|
}else{ |
1469 |
121 |
d_status = 4; |
1470 |
121 |
d_status_num = -1; |
1471 |
121 |
return getNextTerm( s, depth ); |
1472 |
|
} |
1473 |
44860 |
}else if( d_status==2 ){ |
1474 |
|
//cleanup previous information |
1475 |
|
//if( d_status_num>=0 ){ |
1476 |
|
// s->d_var_eq_tg[d_status_num].pop_back(); |
1477 |
|
//} |
1478 |
|
//check if there is another variable |
1479 |
6992 |
if( (d_status_num+1)<(int)s->getNumTgVars( d_typ ) ){ |
1480 |
3453 |
d_status_num++; |
1481 |
|
//we have equated two variables |
1482 |
|
//s->d_var_eq_tg[d_status_num].push_back( d_id ); |
1483 |
3453 |
Trace("sg-gen-tg-debug2") << this << "...consider other var #" << d_status_num << std::endl; |
1484 |
3453 |
return s->considerCurrentTerm() ? true : getNextTerm( s, depth ); |
1485 |
|
}else{ |
1486 |
3539 |
if( s->d_gen_relevant_terms ){ |
1487 |
1248 |
s->d_tg_gdepth--; |
1488 |
|
} |
1489 |
3539 |
d_status++; |
1490 |
3539 |
return getNextTerm( s, depth ); |
1491 |
|
} |
1492 |
37868 |
}else if( d_status==4 ){ |
1493 |
8738 |
d_status++; |
1494 |
8738 |
if( depth>0 && (d_status_num+1)<(int)s->getNumTgFuncs( d_typ ) ){ |
1495 |
5078 |
d_status_num++; |
1496 |
5078 |
d_status_child_num = 0; |
1497 |
5078 |
Trace("sg-gen-tg-debug2") << this << "...consider function " << s->getTgFunc( d_typ, d_status_num ) << std::endl; |
1498 |
5078 |
s->d_tg_gdepth++; |
1499 |
5078 |
if( !s->considerCurrentTerm() ){ |
1500 |
2380 |
s->d_tg_gdepth--; |
1501 |
|
//don't consider this function |
1502 |
2380 |
d_status--; |
1503 |
|
}else{ |
1504 |
|
//we have decided on a function application |
1505 |
|
} |
1506 |
5078 |
return getNextTerm( s, depth ); |
1507 |
|
}else{ |
1508 |
|
//do not choose function applications at depth 0 |
1509 |
3660 |
d_status++; |
1510 |
3660 |
return getNextTerm( s, depth ); |
1511 |
|
} |
1512 |
29130 |
}else if( d_status==5 ){ |
1513 |
|
//iterating over arguments |
1514 |
40484 |
TNode f = s->getTgFunc( d_typ, d_status_num ); |
1515 |
20242 |
if( d_status_child_num<0 ){ |
1516 |
|
//no more arguments |
1517 |
2698 |
s->d_tg_gdepth--; |
1518 |
2698 |
d_status--; |
1519 |
2698 |
return getNextTerm( s, depth ); |
1520 |
17544 |
}else if( d_status_child_num==(int)s->d_func_args[f].size() ){ |
1521 |
5888 |
d_status_child_num--; |
1522 |
5888 |
return s->considerCurrentTermCanon( d_id ) ? true : getNextTerm( s, depth ); |
1523 |
|
//return true; |
1524 |
|
}else{ |
1525 |
11656 |
Assert(d_status_child_num < (int)s->d_func_args[f].size()); |
1526 |
11656 |
if( d_status_child_num==(int)d_children.size() ){ |
1527 |
2822 |
d_children.push_back( s->d_tg_id ); |
1528 |
2822 |
Assert(s->d_tg_alloc.find(s->d_tg_id) == s->d_tg_alloc.end()); |
1529 |
2822 |
s->d_tg_alloc[d_children[d_status_child_num]].reset( s, s->d_func_args[f][d_status_child_num] ); |
1530 |
2822 |
return getNextTerm( s, depth ); |
1531 |
|
}else{ |
1532 |
8834 |
Assert(d_status_child_num + 1 == (int)d_children.size()); |
1533 |
8834 |
if( s->d_tg_alloc[d_children[d_status_child_num]].getNextTerm( s, depth-1 ) ){ |
1534 |
6012 |
d_status_child_num++; |
1535 |
6012 |
return getNextTerm( s, depth ); |
1536 |
|
}else{ |
1537 |
5644 |
Trace("sg-gen-tg-debug2") |
1538 |
2822 |
<< "...remove child from context " << std::endl; |
1539 |
2822 |
s->changeContext(false); |
1540 |
2822 |
d_children.pop_back(); |
1541 |
2822 |
d_status_child_num--; |
1542 |
2822 |
return getNextTerm( s, depth ); |
1543 |
|
} |
1544 |
|
} |
1545 |
|
} |
1546 |
8888 |
}else if( d_status==1 || d_status==3 ){ |
1547 |
5228 |
if( d_status==1 ){ |
1548 |
1689 |
s->removeVar( d_typ ); |
1549 |
1689 |
Assert(d_status_num == (int)s->d_var_id[d_typ]); |
1550 |
|
//check if there is only one feasible equivalence class. if so, don't make pattern any more specific. |
1551 |
|
//unsigned i = s->d_ccand_eqc[0].size()-1; |
1552 |
|
//if( s->d_ccand_eqc[0][i].size()==1 && s->d_ccand_eqc[1][i].empty() ){ |
1553 |
|
// d_status = 6; |
1554 |
|
// return getNextTerm( s, depth ); |
1555 |
|
//} |
1556 |
1689 |
s->d_tg_gdepth++; |
1557 |
|
} |
1558 |
5228 |
d_status++; |
1559 |
5228 |
d_status_num = -1; |
1560 |
5228 |
return getNextTerm( s, depth ); |
1561 |
|
}else{ |
1562 |
3660 |
Assert(d_children.empty()); |
1563 |
3660 |
return false; |
1564 |
|
} |
1565 |
|
} |
1566 |
|
|
1567 |
869329 |
void TermGenerator::resetMatching( TermGenEnv * s, TNode eqc, unsigned mode ) { |
1568 |
869329 |
d_match_status = 0; |
1569 |
869329 |
d_match_status_child_num = 0; |
1570 |
869329 |
d_match_children.clear(); |
1571 |
869329 |
d_match_children_end.clear(); |
1572 |
869329 |
d_match_mode = mode; |
1573 |
|
//if this term generalizes, it must generalize a non-ground term |
1574 |
|
//if( (d_match_mode & ( 1 << 2 ))!=0 && s->isGroundEqc( eqc ) && d_status==5 ){ |
1575 |
|
// d_match_status = -1; |
1576 |
|
//} |
1577 |
869329 |
} |
1578 |
|
|
1579 |
3362974 |
bool TermGenerator::getNextMatch( TermGenEnv * s, TNode eqc, std::map< TypeNode, std::map< unsigned, TNode > >& subs, std::map< TNode, bool >& rev_subs ) { |
1580 |
3362974 |
if( d_match_status<0 ){ |
1581 |
|
return false; |
1582 |
|
} |
1583 |
3362974 |
if( Trace.isOn("sg-gen-tg-match") ){ |
1584 |
|
Trace("sg-gen-tg-match") << "Matching "; |
1585 |
|
debugPrint( s, "sg-gen-tg-match", "sg-gen-tg-match" ); |
1586 |
|
Trace("sg-gen-tg-match") << " with eqc e" << s->d_cg->d_em[eqc] << "..." << std::endl; |
1587 |
|
Trace("sg-gen-tg-match") << " mstatus = " << d_match_status; |
1588 |
|
if( d_status==5 ){ |
1589 |
|
TNode f = s->getTgFunc( d_typ, d_status_num ); |
1590 |
|
Trace("sg-gen-tg-debug2") << ", f = " << f; |
1591 |
|
Trace("sg-gen-tg-debug2") << ", #args = " << s->d_func_args[f].size(); |
1592 |
|
Trace("sg-gen-tg-debug2") << ", mchildNum = " << d_match_status_child_num; |
1593 |
|
Trace("sg-gen-tg-debug2") << ", #mchildren = " << d_match_children.size(); |
1594 |
|
} |
1595 |
|
Trace("sg-gen-tg-debug2") << ", current substitution : {"; |
1596 |
|
for( std::map< TypeNode, std::map< unsigned, TNode > >::iterator itt = subs.begin(); itt != subs.end(); ++itt ){ |
1597 |
|
for( std::map< unsigned, TNode >::iterator it = itt->second.begin(); it != itt->second.end(); ++it ){ |
1598 |
|
Trace("sg-gen-tg-debug2") << " " << it->first << " -> e" << s->d_cg->d_em[it->second]; |
1599 |
|
} |
1600 |
|
} |
1601 |
|
Trace("sg-gen-tg-debug2") << " } " << std::endl; |
1602 |
|
} |
1603 |
3362974 |
if( d_status==1 ){ |
1604 |
|
//a variable |
1605 |
562071 |
if( d_match_status==0 ){ |
1606 |
346339 |
d_match_status++; |
1607 |
346339 |
if( (d_match_mode & ( 1 << 1 ))!=0 ){ |
1608 |
|
//only ground terms |
1609 |
340173 |
if( !s->isGroundEqc( eqc ) ){ |
1610 |
3941 |
return false; |
1611 |
|
} |
1612 |
6166 |
}else if( (d_match_mode & ( 1 << 2 ))!=0 ){ |
1613 |
|
//only non-ground terms |
1614 |
|
//if( s->isGroundEqc( eqc ) ){ |
1615 |
|
// return false; |
1616 |
|
//} |
1617 |
|
} |
1618 |
|
//store the match : restricted if match_mode.0 = 1 |
1619 |
342398 |
if( (d_match_mode & ( 1 << 0 ))!=0 ){ |
1620 |
|
std::map< TNode, bool >::iterator it = rev_subs.find( eqc ); |
1621 |
|
if( it==rev_subs.end() ){ |
1622 |
|
rev_subs[eqc] = true; |
1623 |
|
}else{ |
1624 |
|
return false; |
1625 |
|
} |
1626 |
|
} |
1627 |
342398 |
Assert(subs[d_typ].find(d_status_num) == subs[d_typ].end()); |
1628 |
342398 |
subs[d_typ][d_status_num] = eqc; |
1629 |
342398 |
return true; |
1630 |
|
}else{ |
1631 |
|
//clean up |
1632 |
215732 |
subs[d_typ].erase( d_status_num ); |
1633 |
215732 |
if( (d_match_mode & ( 1 << 0 ))!=0 ){ |
1634 |
|
rev_subs.erase( eqc ); |
1635 |
|
} |
1636 |
215732 |
return false; |
1637 |
|
} |
1638 |
2800903 |
}else if( d_status==2 ){ |
1639 |
9795 |
if( d_match_status==0 ){ |
1640 |
9793 |
d_match_status++; |
1641 |
9793 |
Assert(d_status_num < (int)s->getNumTgVars(d_typ)); |
1642 |
9793 |
std::map< unsigned, TNode >::iterator it = subs[d_typ].find( d_status_num ); |
1643 |
9793 |
Assert(it != subs[d_typ].end()); |
1644 |
9793 |
return it->second==eqc; |
1645 |
|
}else{ |
1646 |
2 |
return false; |
1647 |
|
} |
1648 |
2791108 |
}else if( d_status==5 ){ |
1649 |
|
//Assert( d_match_children.size()<=d_children.size() ); |
1650 |
|
//enumerating over f-applications in eqc |
1651 |
2791108 |
if( d_match_status_child_num<0 ){ |
1652 |
276495 |
return false; |
1653 |
2514613 |
}else if( d_match_status==0 ){ |
1654 |
|
//set up next binding |
1655 |
1513905 |
if( d_match_status_child_num==(int)d_match_children.size() ){ |
1656 |
1135445 |
if( d_match_status_child_num==0 ){ |
1657 |
|
//initial binding |
1658 |
879323 |
TNode f = s->getTgFunc( d_typ, d_status_num ); |
1659 |
513197 |
Assert(!eqc.isNull()); |
1660 |
513197 |
TNodeTrie* tat = s->getTermDatabase()->getTermArgTrie(eqc, f); |
1661 |
513197 |
if( tat ){ |
1662 |
366126 |
d_match_children.push_back( tat->d_data.begin() ); |
1663 |
366126 |
d_match_children_end.push_back( tat->d_data.end() ); |
1664 |
|
}else{ |
1665 |
147071 |
d_match_status++; |
1666 |
147071 |
d_match_status_child_num--; |
1667 |
147071 |
return getNextMatch( s, eqc, subs, rev_subs ); |
1668 |
|
} |
1669 |
|
}else{ |
1670 |
622248 |
d_match_children.push_back( d_match_children[d_match_status_child_num-1]->second.d_data.begin() ); |
1671 |
622248 |
d_match_children_end.push_back( d_match_children[d_match_status_child_num-1]->second.d_data.end() ); |
1672 |
|
} |
1673 |
|
} |
1674 |
1366834 |
d_match_status++; |
1675 |
1366834 |
Assert(d_match_status_child_num + 1 == (int)d_match_children.size()); |
1676 |
1366834 |
if( d_match_children[d_match_status_child_num]==d_match_children_end[d_match_status_child_num] ){ |
1677 |
|
//no more arguments to bind |
1678 |
259532 |
d_match_children.pop_back(); |
1679 |
259532 |
d_match_children_end.pop_back(); |
1680 |
259532 |
d_match_status_child_num--; |
1681 |
259532 |
return getNextMatch( s, eqc, subs, rev_subs ); |
1682 |
|
}else{ |
1683 |
1107302 |
if( d_match_status_child_num==(int)d_children.size() ){ |
1684 |
|
//successfully matched all children |
1685 |
480737 |
d_match_children.pop_back(); |
1686 |
480737 |
d_match_children_end.pop_back(); |
1687 |
480737 |
d_match_status_child_num--; |
1688 |
480737 |
return true;//return d_match_children[d_match_status]!=d_match_children_end[d_match_status]; |
1689 |
|
}else{ |
1690 |
|
//do next binding |
1691 |
626565 |
s->d_tg_alloc[d_children[d_match_status_child_num]].resetMatching( s, d_match_children[d_match_status_child_num]->first, d_match_mode ); |
1692 |
626565 |
return getNextMatch( s, eqc, subs, rev_subs ); |
1693 |
|
} |
1694 |
|
} |
1695 |
|
}else{ |
1696 |
1000708 |
Assert(d_match_status == 1); |
1697 |
1000708 |
Assert(d_match_status_child_num + 1 == (int)d_match_children.size()); |
1698 |
1000708 |
Assert(d_match_children[d_match_status_child_num] |
1699 |
|
!= d_match_children_end[d_match_status_child_num]); |
1700 |
1000708 |
d_match_status--; |
1701 |
1000708 |
if( s->d_tg_alloc[d_children[d_match_status_child_num]].getNextMatch( s, d_match_children[d_match_status_child_num]->first, subs, rev_subs ) ){ |
1702 |
622248 |
d_match_status_child_num++; |
1703 |
622248 |
return getNextMatch( s, eqc, subs, rev_subs ); |
1704 |
|
}else{ |
1705 |
|
//iterate |
1706 |
378460 |
d_match_children[d_match_status_child_num]++; |
1707 |
378460 |
return getNextMatch( s, eqc, subs, rev_subs ); |
1708 |
|
} |
1709 |
|
} |
1710 |
|
} |
1711 |
|
Assert(false); |
1712 |
|
return false; |
1713 |
|
} |
1714 |
|
|
1715 |
|
unsigned TermGenerator::getDepth( TermGenEnv * s ) { |
1716 |
|
if( d_status==5 ){ |
1717 |
|
unsigned maxd = 0; |
1718 |
|
for( unsigned i=0; i<d_children.size(); i++ ){ |
1719 |
|
unsigned d = s->d_tg_alloc[d_children[i]].getDepth( s ); |
1720 |
|
if( d>maxd ){ |
1721 |
|
maxd = d; |
1722 |
|
} |
1723 |
|
} |
1724 |
|
return 1+maxd; |
1725 |
|
}else{ |
1726 |
|
return 0; |
1727 |
|
} |
1728 |
|
} |
1729 |
|
|
1730 |
60640 |
unsigned TermGenerator::calculateGeneralizationDepth( TermGenEnv * s, std::map< TypeNode, std::vector< int > >& fvs ) { |
1731 |
60640 |
if( d_status==5 ){ |
1732 |
36729 |
unsigned sum = 1; |
1733 |
76415 |
for( unsigned i=0; i<d_children.size(); i++ ){ |
1734 |
39686 |
sum += s->d_tg_alloc[d_children[i]].calculateGeneralizationDepth( s, fvs ); |
1735 |
|
} |
1736 |
36729 |
return sum; |
1737 |
|
}else{ |
1738 |
23911 |
Assert(d_status == 2 || d_status == 1); |
1739 |
23911 |
std::map< TypeNode, std::vector< int > >::iterator it = fvs.find( d_typ ); |
1740 |
23911 |
if( it!=fvs.end() ){ |
1741 |
3252 |
if( std::find( it->second.begin(), it->second.end(), d_status_num )!=it->second.end() ){ |
1742 |
979 |
return 1; |
1743 |
|
} |
1744 |
|
} |
1745 |
22932 |
fvs[d_typ].push_back( d_status_num ); |
1746 |
22932 |
return 0; |
1747 |
|
} |
1748 |
|
} |
1749 |
|
|
1750 |
20954 |
unsigned TermGenerator::getGeneralizationDepth( TermGenEnv * s ) { |
1751 |
|
//if( s->d_gen_relevant_terms ){ |
1752 |
|
// return s->d_tg_gdepth; |
1753 |
|
//}else{ |
1754 |
41908 |
std::map< TypeNode, std::vector< int > > fvs; |
1755 |
41908 |
return calculateGeneralizationDepth( s, fvs ); |
1756 |
|
//} |
1757 |
|
} |
1758 |
|
|
1759 |
23000 |
Node TermGenerator::getTerm( TermGenEnv * s ) { |
1760 |
23000 |
if( d_status==1 || d_status==2 ){ |
1761 |
11278 |
Assert(!d_typ.isNull()); |
1762 |
11278 |
return s->getFreeVar( d_typ, d_status_num ); |
1763 |
11722 |
}else if( d_status==5 ){ |
1764 |
11722 |
Node f = s->getTgFunc( d_typ, d_status_num ); |
1765 |
11722 |
if( d_children.size()==s->d_func_args[f].size() ){ |
1766 |
23444 |
std::vector< Node > children; |
1767 |
11722 |
if( s->d_tg_func_param[f] ){ |
1768 |
11722 |
children.push_back( f ); |
1769 |
|
} |
1770 |
27079 |
for( unsigned i=0; i<d_children.size(); i++ ){ |
1771 |
30714 |
Node nc = s->d_tg_alloc[d_children[i]].getTerm( s ); |
1772 |
15357 |
if( nc.isNull() ){ |
1773 |
|
return Node::null(); |
1774 |
|
}else{ |
1775 |
|
//Assert( nc.getType()==s->d_func_args[f][i] ); |
1776 |
15357 |
children.push_back( nc ); |
1777 |
|
} |
1778 |
|
} |
1779 |
11722 |
return NodeManager::currentNM()->mkNode( s->d_func_kind[f], children ); |
1780 |
|
} |
1781 |
|
}else{ |
1782 |
|
Assert(false); |
1783 |
|
} |
1784 |
|
return Node::null(); |
1785 |
|
} |
1786 |
|
|
1787 |
78979 |
void TermGenerator::debugPrint( TermGenEnv * s, const char * c, const char * cd ) { |
1788 |
78979 |
Trace(cd) << "[*" << d_id << "," << d_status << "]:"; |
1789 |
78979 |
if( d_status==1 || d_status==2 ){ |
1790 |
29587 |
Trace(c) << s->getFreeVar( d_typ, d_status_num ); |
1791 |
49392 |
}else if( d_status==5 ){ |
1792 |
98784 |
TNode f = s->getTgFunc( d_typ, d_status_num ); |
1793 |
49392 |
Trace(c) << "(" << f; |
1794 |
102475 |
for( unsigned i=0; i<d_children.size(); i++ ){ |
1795 |
53083 |
Trace(c) << " "; |
1796 |
53083 |
s->d_tg_alloc[d_children[i]].debugPrint( s, c, cd ); |
1797 |
|
} |
1798 |
49392 |
if( d_children.size()<s->d_func_args[f].size() ){ |
1799 |
10450 |
Trace(c) << " ..."; |
1800 |
|
} |
1801 |
49392 |
Trace(c) << ")"; |
1802 |
|
}else{ |
1803 |
|
Trace(c) << "???"; |
1804 |
|
} |
1805 |
78979 |
} |
1806 |
|
|
1807 |
44 |
void TermGenEnv::collectSignatureInformation() { |
1808 |
44 |
d_typ_tg_funcs.clear(); |
1809 |
44 |
d_funcs.clear(); |
1810 |
44 |
d_func_kind.clear(); |
1811 |
44 |
d_func_args.clear(); |
1812 |
88 |
TypeNode tnull; |
1813 |
44 |
TermDb* tdb = getTermDatabase(); |
1814 |
783 |
for (size_t i = 0, nops = tdb->getNumOperators(); i < nops; i++) |
1815 |
|
{ |
1816 |
1478 |
Node op = tdb->getOperator(i); |
1817 |
739 |
DbList* dbl = tdb->getOrMkDbListForOp(op); |
1818 |
739 |
if (!dbl->d_list.empty()) |
1819 |
|
{ |
1820 |
1454 |
Node nn = dbl->d_list[0]; |
1821 |
727 |
Trace("sg-rel-sig-debug") << "Check in signature : " << nn << std::endl; |
1822 |
727 |
if( d_cg->isHandledTerm( nn ) && nn.getKind()!=APPLY_SELECTOR_TOTAL && !nn.getType().isBoolean() ){ |
1823 |
225 |
bool do_enum = true; |
1824 |
|
//check if we have enumerated ground terms |
1825 |
225 |
if( nn.getKind()==APPLY_UF ){ |
1826 |
77 |
Trace("sg-rel-sig-debug") << "Check enumeration..." << std::endl; |
1827 |
77 |
if( !d_cg->hasEnumeratedUf( nn ) ){ |
1828 |
15 |
do_enum = false; |
1829 |
|
} |
1830 |
|
} |
1831 |
225 |
if( do_enum ){ |
1832 |
210 |
Trace("sg-rel-sig-debug") << "Set enumeration..." << std::endl; |
1833 |
210 |
d_funcs.push_back(op); |
1834 |
364 |
for (const Node& nnc : nn) |
1835 |
|
{ |
1836 |
154 |
d_func_args[op].push_back(nnc.getType()); |
1837 |
|
} |
1838 |
210 |
d_func_kind[op] = nn.getKind(); |
1839 |
210 |
d_typ_tg_funcs[tnull].push_back(op); |
1840 |
210 |
d_typ_tg_funcs[nn.getType()].push_back(op); |
1841 |
210 |
d_tg_func_param[op] = |
1842 |
210 |
(nn.getMetaKind() == kind::metakind::PARAMETERIZED); |
1843 |
420 |
Trace("sg-rel-sig") |
1844 |
210 |
<< "Will enumerate function applications of : " << op |
1845 |
420 |
<< ", #args = " << d_func_args[op].size() |
1846 |
210 |
<< ", kind = " << nn.getKind() << std::endl; |
1847 |
|
} |
1848 |
|
} |
1849 |
727 |
Trace("sg-rel-sig-debug") << "Done check in signature : " << nn << std::endl; |
1850 |
|
} |
1851 |
|
} |
1852 |
|
//shuffle functions |
1853 |
144 |
for (std::map<TypeNode, std::vector<TNode> >::iterator it = |
1854 |
44 |
d_typ_tg_funcs.begin(); |
1855 |
188 |
it != d_typ_tg_funcs.end(); |
1856 |
|
++it) |
1857 |
|
{ |
1858 |
144 |
std::shuffle(it->second.begin(), it->second.end(), Random::getRandom()); |
1859 |
144 |
if (it->first.isNull()) |
1860 |
|
{ |
1861 |
38 |
Trace("sg-gen-tg-debug") << "In this order : "; |
1862 |
248 |
for (unsigned i = 0; i < it->second.size(); i++) |
1863 |
|
{ |
1864 |
210 |
Trace("sg-gen-tg-debug") << it->second[i] << " "; |
1865 |
|
} |
1866 |
38 |
Trace("sg-gen-tg-debug") << std::endl; |
1867 |
|
} |
1868 |
|
} |
1869 |
44 |
} |
1870 |
|
|
1871 |
838 |
void TermGenEnv::reset( unsigned depth, bool genRelevant, TypeNode tn ) { |
1872 |
838 |
Assert(d_tg_alloc.empty()); |
1873 |
838 |
d_tg_alloc.clear(); |
1874 |
|
|
1875 |
838 |
if( genRelevant ){ |
1876 |
363 |
for( unsigned i=0; i<2; i++ ){ |
1877 |
242 |
d_ccand_eqc[i].clear(); |
1878 |
242 |
d_ccand_eqc[i].push_back( d_relevant_eqc[i] ); |
1879 |
|
} |
1880 |
|
} |
1881 |
|
|
1882 |
838 |
d_tg_id = 0; |
1883 |
838 |
d_tg_gdepth = 0; |
1884 |
838 |
d_tg_gdepth_limit = depth; |
1885 |
838 |
d_gen_relevant_terms = genRelevant; |
1886 |
838 |
d_tg_alloc[0].reset( this, tn ); |
1887 |
838 |
} |
1888 |
|
|
1889 |
5255 |
bool TermGenEnv::getNextTerm() { |
1890 |
5255 |
if( d_tg_alloc[0].getNextTerm( this, d_tg_gdepth_limit ) ){ |
1891 |
4417 |
Assert((int)d_tg_alloc[0].getGeneralizationDepth(this) |
1892 |
|
<= d_tg_gdepth_limit); |
1893 |
4417 |
if( (int)d_tg_alloc[0].getGeneralizationDepth( this )!=d_tg_gdepth_limit ){ |
1894 |
1560 |
return getNextTerm(); |
1895 |
|
}else{ |
1896 |
2857 |
return true; |
1897 |
|
} |
1898 |
|
} |
1899 |
838 |
Trace("sg-gen-tg-debug2") << "...remove from context " << std::endl; |
1900 |
838 |
changeContext(false); |
1901 |
838 |
return false; |
1902 |
|
} |
1903 |
|
|
1904 |
|
//reset matching |
1905 |
22503 |
void TermGenEnv::resetMatching( TNode eqc, unsigned mode ) { |
1906 |
22503 |
d_tg_alloc[0].resetMatching( this, eqc, mode ); |
1907 |
22503 |
} |
1908 |
|
|
1909 |
|
//get next match |
1910 |
108129 |
bool TermGenEnv::getNextMatch( TNode eqc, std::map< TypeNode, std::map< unsigned, TNode > >& subs, std::map< TNode, bool >& rev_subs ) { |
1911 |
108129 |
return d_tg_alloc[0].getNextMatch( this, eqc, subs, rev_subs ); |
1912 |
|
} |
1913 |
|
|
1914 |
|
//get term |
1915 |
2857 |
Node TermGenEnv::getTerm() { |
1916 |
2857 |
return d_tg_alloc[0].getTerm( this ); |
1917 |
|
} |
1918 |
|
|
1919 |
670 |
void TermGenEnv::debugPrint( const char * c, const char * cd ) { |
1920 |
670 |
d_tg_alloc[0].debugPrint( this, c, cd ); |
1921 |
670 |
} |
1922 |
|
|
1923 |
16785 |
unsigned TermGenEnv::getNumTgVars( TypeNode tn ) { |
1924 |
16785 |
return d_var_id[tn]; |
1925 |
|
} |
1926 |
|
|
1927 |
3539 |
bool TermGenEnv::allowVar( TypeNode tn ) { |
1928 |
3539 |
std::map< TypeNode, unsigned >::iterator it = d_var_limit.find( tn ); |
1929 |
3539 |
if( it==d_var_limit.end() ){ |
1930 |
1689 |
return true; |
1931 |
|
}else{ |
1932 |
1850 |
return d_var_id[tn]<it->second; |
1933 |
|
} |
1934 |
|
} |
1935 |
|
|
1936 |
1689 |
void TermGenEnv::addVar( TypeNode tn ) { |
1937 |
1689 |
d_var_id[tn]++; |
1938 |
1689 |
} |
1939 |
|
|
1940 |
1689 |
void TermGenEnv::removeVar( TypeNode tn ) { |
1941 |
1689 |
d_var_id[tn]--; |
1942 |
|
//d_var_eq_tg.pop_back(); |
1943 |
|
//d_var_tg.pop_back(); |
1944 |
1689 |
} |
1945 |
|
|
1946 |
6739 |
unsigned TermGenEnv::getNumTgFuncs( TypeNode tn ) { |
1947 |
6739 |
return d_typ_tg_funcs[tn].size(); |
1948 |
|
} |
1949 |
|
|
1950 |
599631 |
TNode TermGenEnv::getTgFunc( TypeNode tn, unsigned i ) { |
1951 |
599631 |
return d_typ_tg_funcs[tn][i]; |
1952 |
|
} |
1953 |
|
|
1954 |
40865 |
Node TermGenEnv::getFreeVar( TypeNode tn, unsigned i ) { |
1955 |
40865 |
return d_cg->getFreeVar( tn, i ); |
1956 |
|
} |
1957 |
|
|
1958 |
10220 |
bool TermGenEnv::considerCurrentTerm() { |
1959 |
10220 |
Assert(!d_tg_alloc.empty()); |
1960 |
|
|
1961 |
|
//if generalization depth is too large, don't consider it |
1962 |
10220 |
unsigned i = d_tg_alloc.size(); |
1963 |
10220 |
Trace("sg-gen-tg-debug") << "Consider term "; |
1964 |
10220 |
d_tg_alloc[0].debugPrint( this, "sg-gen-tg-debug", "sg-gen-tg-debug" ); |
1965 |
10220 |
Trace("sg-gen-tg-debug") << "? curr term size = " << d_tg_alloc.size() << ", last status = " << d_tg_alloc[i-1].d_status; |
1966 |
10220 |
Trace("sg-gen-tg-debug") << std::endl; |
1967 |
|
|
1968 |
10220 |
if( d_tg_gdepth_limit>=0 && d_tg_alloc[0].getGeneralizationDepth( this )>(unsigned)d_tg_gdepth_limit ){ |
1969 |
1900 |
Trace("sg-gen-consider-term") << "-> generalization depth of "; |
1970 |
1900 |
d_tg_alloc[0].debugPrint( this, "sg-gen-consider-term", "sg-gen-tg-debug" ); |
1971 |
1900 |
Trace("sg-gen-consider-term") << " is too high " << d_tg_gdepth << " " << d_tg_alloc[0].getGeneralizationDepth( this ) << ", do not consider." << std::endl; |
1972 |
1900 |
return false; |
1973 |
|
} |
1974 |
|
|
1975 |
|
//----optimizations |
1976 |
|
/* |
1977 |
|
if( d_tg_alloc[i-1].d_status==1 ){ |
1978 |
|
}else if( d_tg_alloc[i-1].d_status==2 ){ |
1979 |
|
}else if( d_tg_alloc[i-1].d_status==5 ){ |
1980 |
|
}else{ |
1981 |
|
Trace("sg-gen-tg-debug") << "Bad tg: " << &d_tg_alloc[i-1] << std::endl; |
1982 |
|
Assert( false ); |
1983 |
|
} |
1984 |
|
*/ |
1985 |
|
//if equated two variables, first check if context-independent TODO |
1986 |
|
//----end optimizations |
1987 |
|
|
1988 |
|
|
1989 |
|
//check based on which candidate equivalence classes match |
1990 |
8320 |
if( d_gen_relevant_terms ){ |
1991 |
3243 |
Trace("sg-gen-tg-debug") << "Filter based on relevant ground EQC"; |
1992 |
3243 |
Trace("sg-gen-tg-debug") << ", #eqc to try = " << d_ccand_eqc[0][i-1].size() << "/" << d_ccand_eqc[1][i-1].size() << std::endl; |
1993 |
|
|
1994 |
3243 |
Assert(d_ccand_eqc[0].size() >= 2); |
1995 |
3243 |
Assert(d_ccand_eqc[0].size() == d_ccand_eqc[1].size()); |
1996 |
3243 |
Assert(d_ccand_eqc[0].size() == d_tg_id + 1); |
1997 |
3243 |
Assert(d_tg_id == d_tg_alloc.size()); |
1998 |
9729 |
for( unsigned r=0; r<2; r++ ){ |
1999 |
6486 |
d_ccand_eqc[r][i].clear(); |
2000 |
|
} |
2001 |
|
|
2002 |
|
//re-check feasibility of EQC |
2003 |
9729 |
for( unsigned r=0; r<2; r++ ){ |
2004 |
226747 |
for( unsigned j=0; j<d_ccand_eqc[r][i-1].size(); j++ ){ |
2005 |
440522 |
std::map< TypeNode, std::map< unsigned, TNode > > subs; |
2006 |
440522 |
std::map< TNode, bool > rev_subs; |
2007 |
|
unsigned mode; |
2008 |
220261 |
if( r==0 ){ |
2009 |
19020 |
mode = d_cg->optReqDistinctVarPatterns() ? ( 1 << 0 ) : 0; |
2010 |
19020 |
mode = mode | (1 << 2 ); |
2011 |
|
}else{ |
2012 |
201241 |
mode = 1 << 1; |
2013 |
|
} |
2014 |
220261 |
d_tg_alloc[0].resetMatching( this, d_ccand_eqc[r][i-1][j], mode ); |
2015 |
220261 |
if( d_tg_alloc[0].getNextMatch( this, d_ccand_eqc[r][i-1][j], subs, rev_subs ) ){ |
2016 |
115749 |
d_ccand_eqc[r][i].push_back( d_ccand_eqc[r][i-1][j] ); |
2017 |
|
} |
2018 |
|
} |
2019 |
|
} |
2020 |
9729 |
for( unsigned r=0; r<2; r++ ){ |
2021 |
6486 |
Trace("sg-gen-tg-debug") << "Current eqc of type " << r << " : "; |
2022 |
122235 |
for( unsigned j=0; j<d_ccand_eqc[r][i].size(); j++ ){ |
2023 |
115749 |
Trace("sg-gen-tg-debug") << "e" << d_cg->d_em[d_ccand_eqc[r][i][j]] << " "; |
2024 |
|
} |
2025 |
6486 |
Trace("sg-gen-tg-debug") << std::endl; |
2026 |
|
} |
2027 |
3243 |
if( options::conjectureFilterActiveTerms() && d_ccand_eqc[0][i].empty() ){ |
2028 |
859 |
Trace("sg-gen-consider-term") << "Do not consider term of form "; |
2029 |
859 |
d_tg_alloc[0].debugPrint( this, "sg-gen-consider-term", "sg-gen-consider-term-debug" ); |
2030 |
859 |
Trace("sg-gen-consider-term") << " since no relevant EQC matches it." << std::endl; |
2031 |
859 |
return false; |
2032 |
|
} |
2033 |
2384 |
if( options::conjectureFilterModel() && d_ccand_eqc[1][i].empty() ){ |
2034 |
54 |
Trace("sg-gen-consider-term") << "Do not consider term of form "; |
2035 |
54 |
d_tg_alloc[0].debugPrint( this, "sg-gen-consider-term", "sg-gen-consider-term-debug" ); |
2036 |
54 |
Trace("sg-gen-consider-term") << " since no ground EQC matches it." << std::endl; |
2037 |
54 |
return false; |
2038 |
|
} |
2039 |
|
} |
2040 |
7407 |
Trace("sg-gen-tg-debug") << "Will consider term "; |
2041 |
7407 |
d_tg_alloc[0].debugPrint( this, "sg-gen-tg-debug", "sg-gen-tg-debug" ); |
2042 |
7407 |
Trace("sg-gen-tg-debug") << std::endl; |
2043 |
7407 |
Trace("sg-gen-consider-term-debug") << std::endl; |
2044 |
7407 |
return true; |
2045 |
|
} |
2046 |
|
|
2047 |
7320 |
void TermGenEnv::changeContext( bool add ) { |
2048 |
7320 |
if( add ){ |
2049 |
10980 |
for( unsigned r=0; r<2; r++ ){ |
2050 |
7320 |
d_ccand_eqc[r].push_back( std::vector< TNode >() ); |
2051 |
|
} |
2052 |
3660 |
d_tg_id++; |
2053 |
|
}else{ |
2054 |
10980 |
for( unsigned r=0; r<2; r++ ){ |
2055 |
7320 |
d_ccand_eqc[r].pop_back(); |
2056 |
|
} |
2057 |
3660 |
d_tg_id--; |
2058 |
3660 |
Assert(d_tg_alloc.find(d_tg_id) != d_tg_alloc.end()); |
2059 |
3660 |
d_tg_alloc.erase( d_tg_id ); |
2060 |
|
} |
2061 |
7320 |
} |
2062 |
|
|
2063 |
5888 |
bool TermGenEnv::considerCurrentTermCanon( unsigned tg_id ){ |
2064 |
5888 |
Assert(tg_id < d_tg_alloc.size()); |
2065 |
5888 |
if( options::conjectureFilterCanonical() ){ |
2066 |
|
//check based on a canonicity of the term (if there is one) |
2067 |
4786 |
Trace("sg-gen-tg-debug") << "Consider term canon "; |
2068 |
4786 |
d_tg_alloc[0].debugPrint( this, "sg-gen-tg-debug", "sg-gen-tg-debug" ); |
2069 |
4786 |
Trace("sg-gen-tg-debug") << ", tg is [" << tg_id << "]..." << std::endl; |
2070 |
|
|
2071 |
9572 |
Node ln = d_tg_alloc[tg_id].getTerm( this ); |
2072 |
4786 |
Trace("sg-gen-tg-debug") << "Term is " << ln << std::endl; |
2073 |
4786 |
return d_cg->considerTermCanon( ln, d_gen_relevant_terms ); |
2074 |
|
} |
2075 |
1102 |
return true; |
2076 |
|
} |
2077 |
|
|
2078 |
3488 |
bool TermGenEnv::isRelevantFunc( Node f ) { |
2079 |
3488 |
return std::find( d_funcs.begin(), d_funcs.end(), f )!=d_funcs.end(); |
2080 |
|
} |
2081 |
|
|
2082 |
958 |
bool TermGenEnv::isRelevantTerm( Node t ) { |
2083 |
958 |
if( t.getKind()!=BOUND_VARIABLE ){ |
2084 |
658 |
if( t.getKind()!=EQUAL ){ |
2085 |
489 |
if( t.hasOperator() ){ |
2086 |
901 |
TNode op = t.getOperator(); |
2087 |
485 |
if( !isRelevantFunc( op ) ){ |
2088 |
69 |
return false; |
2089 |
|
} |
2090 |
|
}else{ |
2091 |
4 |
return false; |
2092 |
|
} |
2093 |
|
} |
2094 |
1293 |
for( unsigned i=0; i<t.getNumChildren(); i++ ){ |
2095 |
793 |
if( !isRelevantTerm( t[i] ) ){ |
2096 |
85 |
return false; |
2097 |
|
} |
2098 |
|
} |
2099 |
|
} |
2100 |
800 |
return true; |
2101 |
|
} |
2102 |
|
|
2103 |
513241 |
TermDb * TermGenEnv::getTermDatabase() { |
2104 |
513241 |
return d_cg->getTermDatabase(); |
2105 |
|
} |
2106 |
|
Node TermGenEnv::getGroundEqc( TNode r ) { |
2107 |
|
return d_cg->getGroundEqc( r ); |
2108 |
|
} |
2109 |
340173 |
bool TermGenEnv::isGroundEqc( TNode r ){ |
2110 |
340173 |
return d_cg->isGroundEqc( r ); |
2111 |
|
} |
2112 |
|
bool TermGenEnv::isGroundTerm( TNode n ){ |
2113 |
|
return d_cg->isGroundTerm( n ); |
2114 |
|
} |
2115 |
|
|
2116 |
|
|
2117 |
274525 |
void SubstitutionIndex::addSubstitution( TNode eqc, std::vector< TNode >& vars, std::vector< TNode >& terms, unsigned i ) { |
2118 |
274525 |
if( i==vars.size() ){ |
2119 |
85626 |
d_var = eqc; |
2120 |
|
}else{ |
2121 |
188899 |
Assert(d_var.isNull() || d_var == vars[i]); |
2122 |
188899 |
d_var = vars[i]; |
2123 |
188899 |
d_children[terms[i]].addSubstitution( eqc, vars, terms, i+1 ); |
2124 |
|
} |
2125 |
274525 |
} |
2126 |
|
|
2127 |
1157231 |
bool SubstitutionIndex::notifySubstitutions( ConjectureGenerator * s, std::map< TNode, TNode >& subs, TNode rhs, unsigned numVars, unsigned i ) { |
2128 |
1157231 |
if( i==numVars ){ |
2129 |
860201 |
Assert(d_children.empty()); |
2130 |
860201 |
return s->notifySubstitution( d_var, subs, rhs ); |
2131 |
|
}else{ |
2132 |
297030 |
Assert(i == 0 || !d_children.empty()); |
2133 |
1429672 |
for( std::map< TNode, SubstitutionIndex >::iterator it = d_children.begin(); it != d_children.end(); ++it ){ |
2134 |
1145025 |
Trace("sg-cconj-debug2") << "Try " << d_var << " -> " << it->first << " (" << i << "/" << numVars << ")" << std::endl; |
2135 |
1145025 |
subs[d_var] = it->first; |
2136 |
1145025 |
if( !it->second.notifySubstitutions( s, subs, rhs, numVars, i+1 ) ){ |
2137 |
12383 |
return false; |
2138 |
|
} |
2139 |
|
} |
2140 |
284647 |
return true; |
2141 |
|
} |
2142 |
|
} |
2143 |
|
|
2144 |
|
|
2145 |
506 |
void TheoremIndex::addTheorem( std::vector< TNode >& lhs_v, std::vector< unsigned >& lhs_arg, TNode rhs ){ |
2146 |
506 |
if( lhs_v.empty() ){ |
2147 |
92 |
if( std::find( d_terms.begin(), d_terms.end(), rhs )==d_terms.end() ){ |
2148 |
92 |
d_terms.push_back( rhs ); |
2149 |
|
} |
2150 |
|
}else{ |
2151 |
414 |
unsigned index = lhs_v.size()-1; |
2152 |
414 |
if( lhs_arg[index]==lhs_v[index].getNumChildren() ){ |
2153 |
184 |
lhs_v.pop_back(); |
2154 |
184 |
lhs_arg.pop_back(); |
2155 |
184 |
addTheorem( lhs_v, lhs_arg, rhs ); |
2156 |
|
}else{ |
2157 |
230 |
lhs_arg[index]++; |
2158 |
230 |
addTheoremNode( lhs_v[index][lhs_arg[index]-1], lhs_v, lhs_arg, rhs ); |
2159 |
|
} |
2160 |
|
} |
2161 |
506 |
} |
2162 |
|
|
2163 |
322 |
void TheoremIndex::addTheoremNode( TNode curr, std::vector< TNode >& lhs_v, std::vector< unsigned >& lhs_arg, TNode rhs ){ |
2164 |
322 |
Trace("thm-db-debug") << "Adding conjecture for subterm " << curr << "..." << std::endl; |
2165 |
322 |
if( curr.hasOperator() ){ |
2166 |
184 |
lhs_v.push_back( curr ); |
2167 |
184 |
lhs_arg.push_back( 0 ); |
2168 |
184 |
d_children[curr.getOperator()].addTheorem( lhs_v, lhs_arg, rhs ); |
2169 |
|
}else{ |
2170 |
138 |
Assert(curr.getKind() == kind::BOUND_VARIABLE); |
2171 |
276 |
TypeNode tn = curr.getType(); |
2172 |
138 |
Assert(d_var[tn].isNull() || d_var[tn] == curr); |
2173 |
138 |
d_var[tn] = curr; |
2174 |
138 |
d_children[curr].addTheorem( lhs_v, lhs_arg, rhs ); |
2175 |
|
} |
2176 |
322 |
} |
2177 |
|
|
2178 |
2280 |
void TheoremIndex::getEquivalentTerms( std::vector< TNode >& n_v, std::vector< unsigned >& n_arg, |
2179 |
|
std::map< TNode, TNode >& smap, std::vector< TNode >& vars, std::vector< TNode >& subs, |
2180 |
|
std::vector< Node >& terms ) { |
2181 |
2280 |
Trace("thm-db-debug") << "Get equivalent terms " << n_v.size() << " " << n_arg.size() << std::endl; |
2182 |
2280 |
if( n_v.empty() ){ |
2183 |
166 |
Trace("thm-db-debug") << "Number of terms : " << d_terms.size() << std::endl; |
2184 |
|
//apply substutitions to RHS's |
2185 |
332 |
for( unsigned i=0; i<d_terms.size(); i++ ){ |
2186 |
332 |
Node n = d_terms[i].substitute( vars.begin(), vars.end(), subs.begin(), subs.end() ); |
2187 |
166 |
terms.push_back( n ); |
2188 |
|
} |
2189 |
|
}else{ |
2190 |
2114 |
unsigned index = n_v.size()-1; |
2191 |
2114 |
if( n_arg[index]==n_v[index].getNumChildren() ){ |
2192 |
332 |
n_v.pop_back(); |
2193 |
332 |
n_arg.pop_back(); |
2194 |
332 |
getEquivalentTerms( n_v, n_arg, smap, vars, subs, terms ); |
2195 |
|
}else{ |
2196 |
1782 |
n_arg[index]++; |
2197 |
1782 |
getEquivalentTermsNode( n_v[index][n_arg[index]-1], n_v, n_arg, smap, vars, subs, terms ); |
2198 |
|
} |
2199 |
|
} |
2200 |
2280 |
} |
2201 |
|
|
2202 |
3400 |
void TheoremIndex::getEquivalentTermsNode( Node curr, std::vector< TNode >& n_v, std::vector< unsigned >& n_arg, |
2203 |
|
std::map< TNode, TNode >& smap, std::vector< TNode >& vars, std::vector< TNode >& subs, |
2204 |
|
std::vector< Node >& terms ) { |
2205 |
3400 |
Trace("thm-db-debug") << "Get equivalent based on subterm " << curr << "..." << std::endl; |
2206 |
3400 |
if( curr.hasOperator() ){ |
2207 |
2379 |
Trace("thm-db-debug") << "Check based on operator..." << std::endl; |
2208 |
2379 |
std::map< TNode, TheoremIndex >::iterator it = d_children.find( curr.getOperator() ); |
2209 |
2379 |
if( it!=d_children.end() ){ |
2210 |
1143 |
n_v.push_back( curr ); |
2211 |
1143 |
n_arg.push_back( 0 ); |
2212 |
1143 |
it->second.getEquivalentTerms( n_v, n_arg, smap, vars, subs, terms ); |
2213 |
|
} |
2214 |
2379 |
Trace("thm-db-debug") << "...done check based on operator" << std::endl; |
2215 |
|
} |
2216 |
6800 |
TypeNode tn = curr.getType(); |
2217 |
3400 |
std::map< TypeNode, TNode >::iterator itt = d_var.find( tn ); |
2218 |
3400 |
if( itt!=d_var.end() ){ |
2219 |
805 |
Trace("thm-db-debug") << "Check for substitution with " << itt->second << "..." << std::endl; |
2220 |
805 |
Assert(curr.getType() == itt->second.getType()); |
2221 |
|
//add to substitution if possible |
2222 |
805 |
bool success = false; |
2223 |
805 |
std::map< TNode, TNode >::iterator it = smap.find( itt->second ); |
2224 |
805 |
if( it==smap.end() ){ |
2225 |
805 |
smap[itt->second] = curr; |
2226 |
805 |
vars.push_back( itt->second ); |
2227 |
805 |
subs.push_back( curr ); |
2228 |
805 |
success = true; |
2229 |
|
}else if( it->second==curr ){ |
2230 |
|
success = true; |
2231 |
|
}else{ |
2232 |
|
//also check modulo equality (in universal equality engine) |
2233 |
|
} |
2234 |
805 |
Trace("thm-db-debug") << "...check for substitution with " << itt->second << ", success = " << success << "." << std::endl; |
2235 |
805 |
if( success ){ |
2236 |
805 |
d_children[itt->second].getEquivalentTerms( n_v, n_arg, smap, vars, subs, terms ); |
2237 |
|
} |
2238 |
|
} |
2239 |
3400 |
} |
2240 |
|
|
2241 |
338 |
void TheoremIndex::debugPrint( const char * c, unsigned ind ) { |
2242 |
632 |
for( std::map< TNode, TheoremIndex >::iterator it = d_children.begin(); it != d_children.end(); ++it ){ |
2243 |
294 |
for( unsigned i=0; i<ind; i++ ){ Trace(c) << " "; } |
2244 |
294 |
Trace(c) << it->first << std::endl; |
2245 |
294 |
it->second.debugPrint( c, ind+1 ); |
2246 |
|
} |
2247 |
338 |
if( !d_terms.empty() ){ |
2248 |
92 |
for( unsigned i=0; i<ind; i++ ){ Trace(c) << " "; } |
2249 |
92 |
Trace(c) << "{"; |
2250 |
184 |
for( unsigned i=0; i<d_terms.size(); i++ ){ |
2251 |
92 |
Trace(c) << " " << d_terms[i]; |
2252 |
|
} |
2253 |
92 |
Trace(c) << " }" << std::endl; |
2254 |
|
} |
2255 |
|
//if( !d_var.isNull() ){ |
2256 |
|
// for( unsigned i=0; i<ind; i++ ){ Trace(c) << " "; } |
2257 |
|
// Trace(c) << "var:" << d_var << std::endl; |
2258 |
|
//} |
2259 |
338 |
} |
2260 |
|
|
2261 |
19020 |
bool ConjectureGenerator::optReqDistinctVarPatterns() { return false; } |
2262 |
3480 |
bool ConjectureGenerator::optFilterUnknown() { return true; } //may change |
2263 |
34 |
int ConjectureGenerator::optFilterScoreThreshold() { return 1; } |
2264 |
44 |
unsigned ConjectureGenerator::optFullCheckFrequency() { return 1; } |
2265 |
|
|
2266 |
44 |
bool ConjectureGenerator::optStatsOnly() { return false; } |
2267 |
|
|
2268 |
29502 |
} // namespace cvc5 |