boolean_circuit/
evaluator.rs

1use std::collections::HashMap;
2
3use crate::{Circuit, Gate, Operation};
4
5/// Returns the value computed in `gate` given assignments to all required variables.
6pub fn evaluate_gate(gate: &Gate, assignments: &HashMap<String, bool>) -> bool {
7    Evaluator {
8        cache: HashMap::new(),
9        assignments,
10    }
11    .evaluate(gate)
12}
13
14/// Returns the values computed in the circuit's output gates given assignments to all required variables.
15pub 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}