smt_scope/analysis/graph/
hide.rs1use petgraph::{
2 graph::{DiGraph, EdgeReference, NodeIndex},
3 visit::{Bfs, EdgeFiltered, EdgeRef, Reversed, ReversedEdgeReference, Walker},
4};
5
6use super::{
7 raw::{EdgeKind, IndexesInstGraph, Node, NodeState, RawInstGraph, RawIx},
8 InstGraph, RawNodeIndex,
9};
10
11impl RawInstGraph {
12 pub fn reset_visibility_to(&mut self, hidden: bool) -> bool {
13 let state = if hidden {
14 NodeState::Hidden
15 } else {
16 NodeState::Visible
17 };
18 let mut modified = false;
19 for node in self.graph.node_weights_mut().filter(|n| !n.disabled()) {
20 modified |= self.stats.set_state(node, state);
21 }
22 modified
23 }
24 pub fn can_set_visibility(&self, node: &Node, hidden: bool) -> bool {
25 !node.disabled() && node.hidden() != hidden
26 }
27 pub fn set_visibility<I: IndexesInstGraph>(&mut self, node: I, hidden: bool) -> bool {
28 let node = node.index(self);
29 let node = &mut self.graph[node.0];
30 if node.disabled() {
31 return false;
32 }
33 self.stats.set_state(
34 node,
35 if hidden {
36 NodeState::Hidden
37 } else {
38 NodeState::Visible
39 },
40 )
41 }
42
43 pub fn keep_first_n(
44 &mut self,
45 nodes: impl Iterator<Item = RawNodeIndex>,
46 mut n: usize,
47 ) -> bool {
48 let mut modified = false;
49 for node in nodes {
50 if n == 0 {
51 modified |= self.set_visibility(node, true);
52 } else if self[node].visible() {
53 n -= 1;
54 }
55 }
56 modified
57 }
58
59 pub fn set_visibility_when(
64 &mut self,
65 hidden: bool,
66 mut p: impl FnMut(&Self, RawNodeIndex, &Node) -> bool,
67 ) -> bool {
68 let mut modified = false;
69 for node in self.graph.node_indices().map(RawNodeIndex) {
70 let n = &self[node];
71 if !self.can_set_visibility(n, hidden) {
72 continue;
73 }
74 if p(self, node, n) {
75 modified |= self.set_visibility(node, hidden);
76 }
77 }
78 modified
79 }
80 pub fn set_visibility_all(
83 &mut self,
84 mut p: impl FnMut(&Self, RawNodeIndex, &Node) -> Option<bool>,
85 ) -> bool {
86 let mut modified = false;
87 for node in self.graph.node_indices().map(RawNodeIndex) {
88 let n = &self[node];
89 if n.disabled() {
90 continue;
91 }
92 if let Some(hidden) = p(self, node, n) {
93 modified |= self.set_visibility(node, hidden);
94 }
95 }
96 modified
97 }
98
99 pub fn set_visibility_many<I: IndexesInstGraph>(
100 &mut self,
101 hidden: bool,
102 nodes: impl Iterator<Item = I>,
103 ) -> bool {
104 let mut modified = false;
105 for node in nodes {
106 let node = node.index(self);
107 modified |= self.set_visibility(node, hidden);
108 }
109 modified
110 }
111
112 fn filter_path(
113 &self,
114 edge: impl EdgeRef<NodeId = NodeIndex<RawIx>>,
115 f: impl Fn(&Node) -> u16,
116 ) -> bool {
117 let from = &self.graph[edge.source()];
118 let to = &self.graph[edge.target()];
119 if from.disabled() {
120 f(from) == f(to)
121 } else {
122 f(from) == f(to).saturating_add(1)
123 }
124 }
125 pub fn path_to_root_graph(
129 &self,
130 longest: bool,
131 ) -> EdgeFiltered<
132 Reversed<&DiGraph<Node, EdgeKind, RawIx>>,
133 impl Fn(ReversedEdgeReference<EdgeReference<EdgeKind, RawIx>>) -> bool + '_,
134 > {
135 let f = move |depth: &Node| {
136 if longest {
137 depth.fwd_depth.max
138 } else {
139 depth.fwd_depth.min
140 }
141 };
142 let filter = move |edge: ReversedEdgeReference<EdgeReference<EdgeKind, RawIx>>| {
143 self.filter_path(edge, f)
144 };
145 EdgeFiltered::from_fn(self.rev(), filter)
146 }
147 pub fn path_to_leaf_graph(
151 &self,
152 longest: bool,
153 ) -> EdgeFiltered<
154 &DiGraph<Node, EdgeKind, RawIx>,
155 impl Fn(EdgeReference<EdgeKind, RawIx>) -> bool + '_,
156 > {
157 let f = move |depth: &Node| {
158 if longest {
159 depth.bwd_depth.max
160 } else {
161 depth.bwd_depth.min
162 }
163 };
164 let filter = move |edge: EdgeReference<EdgeKind, RawIx>| self.filter_path(edge, f);
165 EdgeFiltered::from_fn(&self.graph, filter)
166 }
167
168 pub fn show_longest_path_through(&mut self, node: RawNodeIndex) -> (bool, Vec<RawNodeIndex>) {
169 let mut path: Vec<_> = {
170 let to_root = self.path_to_root_graph(true);
171 Bfs::new(&to_root, node.0)
172 .iter(&to_root)
173 .map(RawNodeIndex)
174 .collect()
175 };
176 path.reverse();
177 {
178 let to_leaf = self.path_to_leaf_graph(true);
179 let to_leaf = Bfs::new(&to_leaf, node.0).iter(&to_leaf).skip(1);
180 path.extend(to_leaf.map(RawNodeIndex));
181 };
182 path.retain(|&n| !self[n].disabled());
183 let modified = self.set_visibility_many(false, path.iter().copied());
184 (modified, path)
185 }
186}
187
188impl InstGraph {
189 pub fn keep_first_n_cost(&mut self, n: usize) -> bool {
190 let (top_cost, other) = self.analysis.first_n_cost(&self.raw, n);
191 let cost = top_cost.iter().chain(other).copied();
192 let cost = cost.chain(self.subgraphs.singletons());
193 self.raw.keep_first_n(cost, n)
194 }
195 pub fn keep_first_n_children(&mut self, n: usize) -> bool {
196 let (top_children, other) = self.analysis.first_n_children(&self.raw, n);
197 let children = top_children.iter().chain(other).copied();
198 let children = children.chain(self.subgraphs.singletons());
199 self.raw.keep_first_n(children, n)
200 }
201 pub fn keep_first_n_fwd_depth_min(&mut self, n: usize) -> bool {
202 let (top_fwd_depth_min, other) = self.analysis.first_n_fwd_depth_min(&self.raw, n);
203 let fwd_depth_min = top_fwd_depth_min.iter().chain(other).copied();
204 let fwd_depth_min = fwd_depth_min.chain(self.subgraphs.singletons());
205 self.raw.keep_first_n(fwd_depth_min, n)
206 }
207}