smt2parser/
stats.rs

1// Copyright (c) Facebook, Inc. and its affiliates
2// SPDX-License-Identifier: MIT OR Apache-2.0
3
4//! A demo implementation of visiting traits that counts things.
5
6use crate::{
7    concrete::Error,
8    visitors::{
9        CommandVisitor, ConstantVisitor, KeywordVisitor, QualIdentifierVisitor, SExprVisitor,
10        Smt2Visitor, SortVisitor, SymbolKind, SymbolVisitor, TermVisitor,
11    },
12    Binary, Decimal, Hexadecimal, Numeral, Position,
13};
14
15use serde::{Deserialize, Serialize};
16use std::collections::BTreeMap;
17
18/// An implementation of [`Smt2Visitor`] that returns simple
19/// statistics on the SMT2 inputs.
20#[derive(Clone, Eq, PartialEq, Default, Debug, Serialize, Deserialize)]
21pub struct Smt2Counters {
22    pub numeral_constant_count: usize,
23    pub decimal_constant_count: usize,
24    pub hexadecimal_constant_count: usize,
25    pub binary_constant_count: usize,
26    pub string_constant_count: usize,
27    pub fresh_symbol_count: usize,
28    pub bound_symbol_count: usize,
29    pub any_symbol_count: usize,
30    pub keyword_count: usize,
31    pub constant_s_expr_count: usize,
32    pub symbol_s_expr_count: usize,
33    pub keyword_s_expr_count: usize,
34    pub application_s_expr_count: usize,
35    pub simple_sort_count: usize,
36    pub parameterized_sort_count: usize,
37    pub simple_identifier_count: usize,
38    pub sorted_identifier_count: usize,
39    pub constant_count: usize,
40    pub qual_identifier_count: usize,
41    pub application_count: usize,
42    pub let_count: usize,
43    pub forall_count: usize,
44    pub exists_count: usize,
45    pub match_count: usize,
46    pub attributes_count: usize,
47    pub assert_count: usize,
48    pub check_sat_count: usize,
49    pub check_sat_assuming_count: usize,
50    pub declare_const_count: usize,
51    pub declare_datatype_count: usize,
52    pub declare_datatypes_count: usize,
53    pub declare_fun_count: usize,
54    pub declare_sort_count: usize,
55    pub define_fun_count: usize,
56    pub define_fun_rec_count: usize,
57    pub define_funs_rec_count: usize,
58    pub define_sort_count: usize,
59    pub echo_count: usize,
60    pub exit_count: usize,
61    pub get_assertions_count: usize,
62    pub get_assignment_count: usize,
63    pub get_info_count: usize,
64    pub get_model_count: usize,
65    pub get_option_count: usize,
66    pub get_proof_count: usize,
67    pub get_unsat_assumptions_count: usize,
68    pub get_unsat_core_count: usize,
69    pub get_value_count: usize,
70    pub pop_count: usize,
71    pub push_count: usize,
72    pub reset_count: usize,
73    pub reset_assertions_count: usize,
74    pub set_info_count: usize,
75    pub set_logic_count: usize,
76    pub set_option_count: usize,
77
78    pub term_count: usize,
79    pub term_max_depth: usize,
80    pub term_max_size: usize,
81    pub term_sum_depth: usize,
82    pub term_sum_size: usize,
83
84    pub keyword_counts: BTreeMap<String, usize>,
85    pub symbol_counts: BTreeMap<String, usize>,
86}
87
88impl Smt2Counters {
89    /// Build a Smt2Visitor that holds statistics, including some
90    /// interesting keywords and symbols.
91    pub fn new(keywords: Vec<String>, symbols: Vec<String>) -> Self {
92        let mut state = Self::default();
93        for keyword in keywords {
94            state.keyword_counts.insert(keyword, 0);
95        }
96        for symbol in symbols {
97            state.symbol_counts.insert(symbol, 0);
98        }
99        state
100    }
101
102    fn visit_keyword(&mut self, keyword: &str) {
103        if let Some(entry) = self.keyword_counts.get_mut(keyword) {
104            *entry += 1;
105        }
106    }
107
108    fn visit_symbol(&mut self, symbol: &str) {
109        if let Some(entry) = self.symbol_counts.get_mut(symbol) {
110            *entry += 1;
111        }
112    }
113}
114
115/// Statistics about a term.
116#[derive(Clone, Eq, PartialEq, Default, Debug)]
117pub struct Term {
118    pub tree_depth: usize,
119    pub tree_size: usize,
120}
121
122impl Term {
123    fn node<I>(iter: I) -> Self
124    where
125        I: Iterator<Item = Term>,
126    {
127        let mut result = Term::default();
128        for t in iter {
129            result.tree_depth = std::cmp::max(result.tree_depth, t.tree_depth);
130            result.tree_size += t.tree_size;
131        }
132        result.tree_depth += 1;
133        result.tree_size += 1;
134        result
135    }
136}
137
138impl ConstantVisitor for Smt2Counters {
139    type T = ();
140    type E = Error;
141
142    fn visit_numeral_constant(&mut self, _value: Numeral) -> Result<Self::T, Self::E> {
143        self.numeral_constant_count += 1;
144        Ok(())
145    }
146    fn visit_decimal_constant(&mut self, _value: Decimal) -> Result<Self::T, Self::E> {
147        self.decimal_constant_count += 1;
148        Ok(())
149    }
150    fn visit_hexadecimal_constant(&mut self, _value: Hexadecimal) -> Result<Self::T, Self::E> {
151        self.hexadecimal_constant_count += 1;
152        Ok(())
153    }
154    fn visit_binary_constant(&mut self, _value: Binary) -> Result<Self::T, Self::E> {
155        self.binary_constant_count += 1;
156        Ok(())
157    }
158    fn visit_string_constant(&mut self, _value: String) -> Result<Self::T, Self::E> {
159        self.string_constant_count += 1;
160        Ok(())
161    }
162}
163
164impl SymbolVisitor for Smt2Counters {
165    type T = ();
166    type E = Error;
167
168    fn visit_fresh_symbol(
169        &mut self,
170        _value: String,
171        _kind: SymbolKind,
172    ) -> Result<Self::T, Self::E> {
173        self.fresh_symbol_count += 1;
174        Ok(())
175    }
176
177    fn visit_bound_symbol(&mut self, value: String) -> Result<Self::T, Self::E> {
178        self.bound_symbol_count += 1;
179        self.visit_symbol(&value);
180        Ok(())
181    }
182
183    fn visit_any_symbol(&mut self, _value: String) -> Result<Self::T, Self::E> {
184        self.any_symbol_count += 1;
185        Ok(())
186    }
187}
188
189impl KeywordVisitor for Smt2Counters {
190    type T = ();
191    type E = Error;
192
193    fn visit_keyword(&mut self, value: String) -> Result<Self::T, Self::E> {
194        self.keyword_count += 1;
195        self.visit_keyword(&value);
196        Ok(())
197    }
198}
199
200type Constant = ();
201type Symbol = ();
202type Keyword = ();
203type Sort = ();
204type QualIdentifier = ();
205type SExpr = ();
206
207type Identifier = crate::visitors::Identifier<Symbol>;
208type AttributeValue = crate::visitors::AttributeValue<Constant, Symbol, SExpr>;
209type DatatypeDec = crate::visitors::DatatypeDec<Symbol, Sort>;
210type FunctionDec = crate::visitors::FunctionDec<Symbol, Sort>;
211
212impl SExprVisitor<Constant, Symbol, Keyword> for Smt2Counters {
213    type T = ();
214    type E = Error;
215
216    fn visit_constant_s_expr(&mut self, _value: Constant) -> Result<Self::T, Self::E> {
217        self.constant_s_expr_count += 1;
218        Ok(())
219    }
220
221    fn visit_symbol_s_expr(&mut self, _value: Symbol) -> Result<Self::T, Self::E> {
222        self.symbol_s_expr_count += 1;
223        Ok(())
224    }
225
226    fn visit_keyword_s_expr(&mut self, _value: Keyword) -> Result<Self::T, Self::E> {
227        self.keyword_s_expr_count += 1;
228        Ok(())
229    }
230
231    fn visit_application_s_expr(&mut self, _values: Vec<Self::T>) -> Result<Self::T, Self::E> {
232        self.application_s_expr_count += 1;
233        Ok(())
234    }
235}
236
237impl SortVisitor<Symbol> for Smt2Counters {
238    type T = ();
239    type E = Error;
240
241    fn visit_simple_sort(&mut self, _identifier: Identifier) -> Result<Self::T, Self::E> {
242        self.simple_sort_count += 1;
243        Ok(())
244    }
245
246    fn visit_parameterized_sort(
247        &mut self,
248        _identifier: Identifier,
249        _parameters: Vec<Self::T>,
250    ) -> Result<Self::T, Self::E> {
251        self.parameterized_sort_count += 1;
252        Ok(())
253    }
254}
255
256impl QualIdentifierVisitor<Identifier, Sort> for Smt2Counters {
257    type T = ();
258    type E = Error;
259
260    fn visit_simple_identifier(&mut self, _identifier: Identifier) -> Result<Self::T, Self::E> {
261        self.simple_identifier_count += 1;
262        Ok(())
263    }
264
265    fn visit_sorted_identifier(
266        &mut self,
267        _identifier: Identifier,
268        _sort: Sort,
269    ) -> Result<Self::T, Self::E> {
270        self.sorted_identifier_count += 1;
271        Ok(())
272    }
273}
274
275impl TermVisitor<Constant, QualIdentifier, Keyword, SExpr, Symbol, Sort> for Smt2Counters {
276    type T = Term;
277    type E = Error;
278
279    fn visit_constant(&mut self, _constant: Constant) -> Result<Self::T, Self::E> {
280        self.constant_count += 1;
281        Ok(Term::default())
282    }
283
284    fn visit_qual_identifier(
285        &mut self,
286        _qual_identifier: QualIdentifier,
287    ) -> Result<Self::T, Self::E> {
288        self.qual_identifier_count += 1;
289        Ok(Term::default())
290    }
291
292    fn visit_application(
293        &mut self,
294        _qual_identifier: QualIdentifier,
295        arguments: Vec<Self::T>,
296    ) -> Result<Self::T, Self::E> {
297        self.application_count += 1;
298        Ok(Term::node(arguments.into_iter()))
299    }
300
301    fn visit_let(
302        &mut self,
303        var_bindings: Vec<(Symbol, Self::T)>,
304        term: Self::T,
305    ) -> Result<Self::T, Self::E> {
306        self.let_count += 1;
307        Ok(Term::node(
308            std::iter::once(term).chain(var_bindings.into_iter().map(|(_, t)| t)),
309        ))
310    }
311
312    fn visit_forall(
313        &mut self,
314        _vars: Vec<(Symbol, Sort)>,
315        term: Self::T,
316    ) -> Result<Self::T, Self::E> {
317        self.forall_count += 1;
318        Ok(Term::node(std::iter::once(term)))
319    }
320
321    fn visit_exists(
322        &mut self,
323        _vars: Vec<(Symbol, Sort)>,
324        term: Self::T,
325    ) -> Result<Self::T, Self::E> {
326        self.exists_count += 1;
327        Ok(Term::node(std::iter::once(term)))
328    }
329
330    fn visit_match(
331        &mut self,
332        term: Self::T,
333        cases: Vec<(Vec<Symbol>, Self::T)>,
334    ) -> Result<Self::T, Self::E> {
335        self.match_count += 1;
336        Ok(Term::node(
337            std::iter::once(term).chain(cases.into_iter().map(|(_, t)| t)),
338        ))
339    }
340
341    fn visit_attributes(
342        &mut self,
343        term: Self::T,
344        _attributes: Vec<(Keyword, AttributeValue)>,
345    ) -> Result<Self::T, Self::E> {
346        self.attributes_count += 1;
347        Ok(Term::node(std::iter::once(term)))
348    }
349}
350
351impl Smt2Counters {
352    fn visit_term(&mut self, term: Term) {
353        self.term_count += 1;
354        self.term_max_depth = std::cmp::max(term.tree_depth, self.term_max_depth);
355        self.term_max_size = std::cmp::max(term.tree_size, self.term_max_size);
356        self.term_sum_depth += term.tree_depth;
357        self.term_sum_size += term.tree_size;
358    }
359}
360
361impl CommandVisitor<Term, Symbol, Sort, Keyword, Constant, SExpr> for Smt2Counters {
362    type T = ();
363    type E = Error;
364
365    fn visit_assert(&mut self, term: Term) -> Result<Self::T, Self::E> {
366        self.assert_count += 1;
367        self.visit_term(term);
368        Ok(())
369    }
370
371    fn visit_check_sat(&mut self) -> Result<Self::T, Self::E> {
372        self.check_sat_count += 1;
373        Ok(())
374    }
375
376    fn visit_check_sat_assuming(
377        &mut self,
378        _literals: Vec<(Symbol, bool)>,
379    ) -> Result<Self::T, Self::E> {
380        self.check_sat_assuming_count += 1;
381        Ok(())
382    }
383
384    fn visit_declare_const(&mut self, _symbol: Symbol, _sort: Sort) -> Result<Self::T, Self::E> {
385        self.declare_const_count += 1;
386        Ok(())
387    }
388
389    fn visit_declare_datatype(
390        &mut self,
391        _symbol: Symbol,
392        _datatype: DatatypeDec,
393    ) -> Result<Self::T, Self::E> {
394        self.declare_datatype_count += 1;
395        Ok(())
396    }
397
398    fn visit_declare_datatypes(
399        &mut self,
400        _datatypes: Vec<(Symbol, Numeral, DatatypeDec)>,
401    ) -> Result<Self::T, Self::E> {
402        self.declare_datatypes_count += 1;
403        Ok(())
404    }
405
406    fn visit_declare_fun(
407        &mut self,
408        _symbol: Symbol,
409        _parameters: Vec<Sort>,
410        _sort: Sort,
411    ) -> Result<Self::T, Self::E> {
412        self.declare_fun_count += 1;
413        Ok(())
414    }
415
416    fn visit_declare_sort(&mut self, _symbol: Symbol, _arity: Numeral) -> Result<Self::T, Self::E> {
417        self.declare_sort_count += 1;
418        Ok(())
419    }
420
421    fn visit_define_fun(&mut self, _sig: FunctionDec, term: Term) -> Result<Self::T, Self::E> {
422        self.define_fun_count += 1;
423        self.visit_term(term);
424        Ok(())
425    }
426
427    fn visit_define_fun_rec(&mut self, _sig: FunctionDec, term: Term) -> Result<Self::T, Self::E> {
428        self.define_fun_rec_count += 1;
429        self.visit_term(term);
430        Ok(())
431    }
432
433    fn visit_define_funs_rec(
434        &mut self,
435        funs: Vec<(FunctionDec, Term)>,
436    ) -> Result<Self::T, Self::E> {
437        self.define_funs_rec_count += 1;
438        for (_, term) in funs {
439            self.visit_term(term);
440        }
441        Ok(())
442    }
443
444    fn visit_define_sort(
445        &mut self,
446        _symbol: Symbol,
447        _parameters: Vec<Symbol>,
448        _sort: Sort,
449    ) -> Result<Self::T, Self::E> {
450        self.define_sort_count += 1;
451        Ok(())
452    }
453
454    fn visit_echo(&mut self, _message: String) -> Result<Self::T, Self::E> {
455        self.echo_count += 1;
456        Ok(())
457    }
458
459    fn visit_exit(&mut self) -> Result<Self::T, Self::E> {
460        self.exit_count += 1;
461        Ok(())
462    }
463
464    fn visit_get_assertions(&mut self) -> Result<Self::T, Self::E> {
465        self.get_assertions_count += 1;
466        Ok(())
467    }
468
469    fn visit_get_assignment(&mut self) -> Result<Self::T, Self::E> {
470        self.get_assignment_count += 1;
471        Ok(())
472    }
473
474    fn visit_get_info(&mut self, _flag: Keyword) -> Result<Self::T, Self::E> {
475        self.get_info_count += 1;
476        Ok(())
477    }
478
479    fn visit_get_model(&mut self) -> Result<Self::T, Self::E> {
480        self.get_model_count += 1;
481        Ok(())
482    }
483
484    fn visit_get_option(&mut self, _keyword: Keyword) -> Result<Self::T, Self::E> {
485        self.get_option_count += 1;
486        Ok(())
487    }
488
489    fn visit_get_proof(&mut self) -> Result<Self::T, Self::E> {
490        self.get_proof_count += 1;
491        Ok(())
492    }
493
494    fn visit_get_unsat_assumptions(&mut self) -> Result<Self::T, Self::E> {
495        self.get_unsat_assumptions_count += 1;
496        Ok(())
497    }
498
499    fn visit_get_unsat_core(&mut self) -> Result<Self::T, Self::E> {
500        self.get_unsat_core_count += 1;
501        Ok(())
502    }
503
504    fn visit_get_value(&mut self, terms: Vec<Term>) -> Result<Self::T, Self::E> {
505        self.get_value_count += 1;
506        for term in terms {
507            self.visit_term(term);
508        }
509        Ok(())
510    }
511
512    fn visit_pop(&mut self, _level: Numeral) -> Result<Self::T, Self::E> {
513        self.pop_count += 1;
514        Ok(())
515    }
516
517    fn visit_push(&mut self, _level: Numeral) -> Result<Self::T, Self::E> {
518        self.push_count += 1;
519        Ok(())
520    }
521
522    fn visit_reset(&mut self) -> Result<Self::T, Self::E> {
523        self.reset_count += 1;
524        Ok(())
525    }
526
527    fn visit_reset_assertions(&mut self) -> Result<Self::T, Self::E> {
528        self.reset_assertions_count += 1;
529        Ok(())
530    }
531
532    fn visit_set_info(
533        &mut self,
534        _keyword: Keyword,
535        _value: AttributeValue,
536    ) -> Result<Self::T, Self::E> {
537        self.set_info_count += 1;
538        Ok(())
539    }
540
541    fn visit_set_logic(&mut self, _symbol: Symbol) -> Result<Self::T, Self::E> {
542        self.set_logic_count += 1;
543        Ok(())
544    }
545
546    fn visit_set_option(
547        &mut self,
548        _keyword: Keyword,
549        _value: AttributeValue,
550    ) -> Result<Self::T, Self::E> {
551        self.set_option_count += 1;
552        Ok(())
553    }
554}
555
556impl Smt2Visitor for Smt2Counters {
557    type Error = Error;
558    type Constant = ();
559    type QualIdentifier = ();
560    type Keyword = ();
561    type Sort = ();
562    type SExpr = ();
563    type Symbol = ();
564    type Term = Term;
565    type Command = ();
566
567    fn syntax_error(&mut self, position: Position, s: String) -> Self::Error {
568        Error::SyntaxError(position, s)
569    }
570
571    fn parsing_error(&mut self, position: Position, s: String) -> Self::Error {
572        Error::ParsingError(position, s)
573    }
574}