1use std::{collections::HashSet, rc::Rc};
2
3use super::literal::Literal;
4
5#[derive(Clone, Debug)]
14pub struct Gate(Rc<Operation>);
15
16#[derive(Clone, Debug)]
18pub enum Operation {
19 Variable(Rc<String>),
21 Constant(bool),
23 Negation(Gate),
25 Conjunction(Gate, Gate),
27 Disjunction(Gate, Gate),
29 Xor(Gate, Gate),
31}
32
33impl From<&str> for Gate {
34 fn from(name: &str) -> Gate {
39 name.to_string().into()
40 }
41}
42
43impl From<String> for Gate {
44 fn from(name: String) -> Gate {
49 Gate(Rc::new(Operation::Variable(Rc::new(name))))
50 }
51}
52
53impl From<bool> for Gate {
54 fn from(value: bool) -> Gate {
56 Gate(Rc::new(Operation::Constant(value)))
57 }
58}
59
60impl From<&Literal> for Gate {
61 fn from(literal: &Literal) -> Gate {
64 let v = literal.var().into();
65 if literal.is_negated() {
66 !&v
67 } else {
68 v
69 }
70 }
71}
72
73impl Gate {
74 pub fn id(&self) -> usize {
77 Rc::as_ptr(&self.0) as usize
78 }
79
80 pub fn operation(&self) -> &Operation {
82 &self.0
83 }
84
85 pub fn iter(&self) -> impl Iterator<Item = &Gate> {
88 self.into_iter()
89 }
90
91 pub fn post_visit_iter(&self) -> impl Iterator<Item = &Gate> {
95 PostVisitIterator::new(std::iter::once(self))
96 }
97
98 pub fn to_string_as_tree(&self) -> String {
100 match self.operation() {
101 Operation::Variable(name) => format!("{name}"),
102 Operation::Constant(value) => format!("{value}"),
103 Operation::Conjunction(left, right) => {
104 format!(
105 "({} & {})",
106 left.to_string_as_tree(),
107 right.to_string_as_tree()
108 )
109 }
110 Operation::Disjunction(left, right) => {
111 format!(
112 "({} | {})",
113 left.to_string_as_tree(),
114 right.to_string_as_tree()
115 )
116 }
117 Operation::Xor(left, right) => format!(
118 "({} ^ {})",
119 left.to_string_as_tree(),
120 right.to_string_as_tree()
121 ),
122 Operation::Negation(gate) => format!("!{}", gate.to_string_as_tree()),
123 }
124 }
125
126 pub fn try_to_constant(&self) -> Option<bool> {
128 match self.operation() {
129 Operation::Constant(value) => Some(*value),
130 _ => None,
131 }
132 }
133
134 pub fn gate_count(&self) -> (usize, usize) {
140 let mut vars: HashSet<_> = Default::default();
141 let mut gate_count = 0;
142 for n in self {
143 match n.operation() {
144 Operation::Variable(v) => {
145 vars.insert(v.as_str());
146 }
147 Operation::Constant(_) => {}
148 Operation::Negation(..)
149 | Operation::Conjunction(..)
150 | Operation::Disjunction(..)
151 | Operation::Xor(..) => {
152 gate_count += 1;
153 }
154 }
155 }
156 (vars.len(), gate_count)
157 }
158}
159
160impl std::ops::BitAnd for Gate {
161 type Output = Gate;
162
163 fn bitand(self, other: Gate) -> Gate {
164 Gate(Rc::new(Operation::Conjunction(self, other)))
165 }
166}
167
168impl std::ops::BitAnd for &Gate {
169 type Output = Gate;
170
171 fn bitand(self, other: &Gate) -> Gate {
172 Gate::bitand(self.clone(), other.clone())
173 }
174}
175
176impl std::ops::BitOr for Gate {
177 type Output = Gate;
178
179 fn bitor(self, other: Gate) -> Gate {
180 Gate(Rc::new(Operation::Disjunction(self, other)))
181 }
182}
183
184impl std::ops::BitOr for &Gate {
185 type Output = Gate;
186
187 fn bitor(self, other: &Gate) -> Gate {
188 Gate::bitor(self.clone(), other.clone())
189 }
190}
191
192impl std::ops::BitXor for Gate {
193 type Output = Gate;
194
195 fn bitxor(self, other: Gate) -> Gate {
196 Gate(Rc::new(Operation::Xor(self, other)))
197 }
198}
199
200impl std::ops::BitXor for &Gate {
201 type Output = Gate;
202
203 fn bitxor(self, other: &Gate) -> Gate {
204 Gate::bitxor(self.clone(), other.clone())
205 }
206}
207
208impl std::ops::Not for Gate {
209 type Output = Gate;
210
211 fn not(self) -> Gate {
212 Gate(Rc::new(Operation::Negation(self)))
213 }
214}
215
216impl std::ops::Not for &Gate {
217 type Output = Gate;
218
219 fn not(self) -> Gate {
220 Gate::not(self.clone())
221 }
222}
223
224impl<'a> IntoIterator for &'a Gate {
225 type Item = &'a Gate;
226 type IntoIter = GraphIterator<'a>;
227
228 fn into_iter(self) -> Self::IntoIter {
230 GraphIterator::new(std::iter::once(self))
231 }
232}
233
234pub struct GraphIterator<'a> {
235 visited: HashSet<usize>,
236 stack: Vec<&'a Gate>,
237}
238
239impl<'a> GraphIterator<'a> {
240 pub(crate) fn new(gates: impl IntoIterator<Item = &'a Gate>) -> Self {
241 Self {
242 visited: HashSet::new(),
243 stack: gates.into_iter().collect(),
244 }
245 }
246
247 fn add_predecessors(&mut self, gate: &'a Gate) {
248 match gate.operation() {
249 Operation::Variable(_) | Operation::Constant(_) => {}
250 Operation::Conjunction(left, right)
251 | Operation::Disjunction(left, right)
252 | Operation::Xor(left, right) => {
253 self.stack.push(right);
254 self.stack.push(left);
255 }
256 Operation::Negation(inner) => {
257 self.stack.push(inner);
258 }
259 }
260 }
261}
262
263impl<'a> Iterator for GraphIterator<'a> {
264 type Item = &'a Gate;
265
266 fn next(&mut self) -> Option<Self::Item> {
267 while let Some(gate) = self.stack.pop() {
268 if self.visited.insert(gate.id()) {
269 self.add_predecessors(gate);
270 return Some(gate);
271 }
272 }
273 None
274 }
275}
276
277pub(crate) struct PostVisitIterator<'a> {
278 visited: HashSet<usize>,
279 stack: Vec<(&'a Gate, bool)>,
282}
283
284impl<'a> PostVisitIterator<'a> {
285 pub(crate) fn new(gates: impl IntoIterator<Item = &'a Gate>) -> Self {
286 Self {
287 visited: HashSet::new(),
288 stack: gates.into_iter().map(|n| (n, false)).collect(),
289 }
290 }
291}
292
293impl<'a> Iterator for PostVisitIterator<'a> {
294 type Item = &'a Gate;
295
296 fn next(&mut self) -> Option<Self::Item> {
297 while let Some((gate, visited_predecessors)) = self.stack.pop() {
298 if visited_predecessors {
299 return Some(gate);
300 } else if self.visited.insert(gate.id()) {
301 self.stack.push((gate, true));
302 match gate.operation() {
303 Operation::Variable(_) | Operation::Constant(_) => {}
304 Operation::Conjunction(left, right)
305 | Operation::Disjunction(left, right)
306 | Operation::Xor(left, right) => {
307 self.stack.push((right, false));
308 self.stack.push((left, false));
309 }
310 Operation::Negation(inner) => {
311 self.stack.push((inner, false));
312 }
313 }
314 }
315 }
316 None
317 }
318}