1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
use plotters::{
evcxr::SVGWrapper,
prelude::{
evcxr_figure, ChartBuilder, Color, IntoFont, LineSeries, Palette9999, PaletteColor,
PathElement, SeriesLabelPosition, BLACK, WHITE,
},
};
use std::collections::{BTreeMap, BinaryHeap};
use z3tracer::{
syntax::{Ident, Term},
Model,
};
pub fn process_file(path: &str) -> std::io::Result<Model> {
let file = std::io::BufReader::new(std::fs::File::open(path)?);
let mut model = Model::default();
if let Err(le) = model.process(Some(path.to_string()), file) {
println!("Error at {:?}: {:?}", le.position, le.error);
}
Ok(model)
}
pub trait ModelExt {
fn id2s(&self, id: &Ident) -> String;
}
impl ModelExt for Model {
fn id2s(&self, id: &Ident) -> String {
self.id_to_sexp(&BTreeMap::new(), id).unwrap()
}
}
pub fn compute_instantiation_times(model: &Model) -> Vec<(String, Vec<usize>)> {
IntoIterSorted::from(model.most_instantiated_terms())
.map(|(_count, id)| {
let mut timestamps = model
.term_data(&id)
.unwrap()
.instantiation_timestamps
.clone();
timestamps.sort_unstable();
let name = match model.term(&id).unwrap() {
Term::Quant { name, .. } | Term::Builtin { name: Some(name) } => name,
_ => "??",
};
(name.to_string(), timestamps)
})
.collect()
}
pub fn plot_instantiations(
times: &[(String, Vec<usize>)],
title: &str,
top_n: usize,
) -> SVGWrapper {
let max_ts = times
.iter()
.map(|(_, v)| v.last().cloned().unwrap_or(0))
.max()
.unwrap_or(1);
let max_count = times[0].1.len();
evcxr_figure((1000, 800), |root| {
root.fill(&WHITE)?;
let mut chart = ChartBuilder::on(&root)
.caption(title, ("Arial", 30).into_font())
.margin(10)
.x_label_area_size(40)
.y_label_area_size(50)
.build_cartesian_2d(0..max_ts, 0..max_count)?;
chart
.configure_mesh()
.y_desc("Cumulative number of instantiations")
.x_desc("Time (line number)")
.draw()?;
for (j, (name, values)) in times.iter().take(top_n).enumerate() {
let color: PaletteColor<Palette9999> = PaletteColor::pick(j);
chart
.draw_series(LineSeries::new(
values.iter().enumerate().map(|(i, c)| (*c, i)),
&color,
))
.unwrap()
.label(name)
.legend(move |(x, y)| PathElement::new(vec![(x, y), (x + 20, y)], color.filled()));
}
chart
.configure_series_labels()
.background_style(&WHITE.mix(0.8))
.border_style(&BLACK)
.position(SeriesLabelPosition::UpperLeft)
.draw()?;
Ok(())
})
}
pub struct IntoIterSorted<T> {
inner: BinaryHeap<T>,
}
impl<T> From<BinaryHeap<T>> for IntoIterSorted<T> {
fn from(inner: BinaryHeap<T>) -> Self {
Self { inner }
}
}
impl<T: Ord> Iterator for IntoIterSorted<T> {
type Item = T;
fn next(&mut self) -> Option<T> {
self.inner.pop()
}
fn size_hint(&self) -> (usize, Option<usize>) {
let exact = self.inner.len();
(exact, Some(exact))
}
}