boolean_circuit/
evaluator.rs1use std::collections::HashMap;
2
3use crate::{Circuit, Gate, Operation};
4
5pub fn evaluate_gate(gate: &Gate, assignments: &HashMap<String, bool>) -> bool {
7 Evaluator {
8 cache: HashMap::new(),
9 assignments,
10 }
11 .evaluate(gate)
12}
13
14pub fn evaluate(circuit: &Circuit, assignments: &HashMap<String, bool>) -> Vec<bool> {
16 let mut evaluator = Evaluator {
17 cache: HashMap::new(),
18 assignments,
19 };
20 circuit
21 .outputs()
22 .iter()
23 .map(|gate| evaluator.evaluate(gate))
24 .collect()
25}
26
27struct Evaluator<'a> {
28 cache: HashMap<usize, bool>,
29 assignments: &'a HashMap<String, bool>,
30}
31
32impl Evaluator<'_> {
33 fn evaluate(&mut self, gate: &Gate) -> bool {
34 if let Some(&result) = self.cache.get(&gate.id()) {
35 return result;
36 }
37 let result = match gate.operation() {
38 Operation::Variable(name) => {
39 *self.assignments.get(name.as_str()).unwrap_or_else(|| {
40 panic!("No assignment for variable '{name}'");
41 })
42 }
43 Operation::Constant(value) => *value,
44 Operation::Negation(inner) => !self.evaluate(inner),
45 Operation::Conjunction(left, right) => self.evaluate(left) && self.evaluate(right),
46 Operation::Disjunction(left, right) => self.evaluate(left) || self.evaluate(right),
47 Operation::Xor(left, right) => self.evaluate(left) ^ self.evaluate(right),
48 };
49 self.cache.insert(gate.id(), result);
50 result
51 }
52}