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