Skip to main content

trit_eval/
eval.rs

1//! 表达式求值:把 [`Expr`] 在给定赋值或全部赋值上求值。
2
3use std::collections::HashMap;
4
5use trit_core::algebra::Algebra;
6use trit_core::ast::Expr;
7use trit_core::bits::{Evaluator, TriBit, TruthTable};
8use trit_core::value::Ternary;
9
10/// 变量赋值:一组 `变量名 → 取值`。
11#[derive(Debug, Clone, Default, PartialEq, Eq)]
12pub struct Assignment {
13    entries: Vec<(String, Ternary)>,
14}
15
16impl Assignment {
17    /// 空赋值。
18    pub fn new() -> Self {
19        Self::default()
20    }
21
22    /// 绑定一个变量。
23    pub fn set(&mut self, name: impl Into<String>, value: Ternary) -> &mut Self {
24        let name = name.into();
25        match self.entries.iter_mut().find(|(n, _)| *n == name) {
26            Some(slot) => slot.1 = value,
27            None => self.entries.push((name, value)),
28        }
29        self
30    }
31
32    /// 查询变量的取值;未绑定时返回 `None`。
33    pub fn get(&self, name: &str) -> Option<Ternary> {
34        self.entries
35            .iter()
36            .find(|(n, _)| n == name)
37            .map(|(_, v)| *v)
38    }
39
40    /// 已绑定的变量名。
41    pub fn variables(&self) -> Vec<String> {
42        self.entries.iter().map(|(n, _)| n.clone()).collect()
43    }
44
45    /// 赋值条目数。
46    pub fn len(&self) -> usize {
47        self.entries.len()
48    }
49
50    /// 是否为空。
51    pub fn is_empty(&self) -> bool {
52        self.entries.is_empty()
53    }
54}
55
56/// 单点求值:按赋值计算表达式值。
57///
58/// 未在赋值中出现的变量视为 `X`(未知)。
59pub fn eval(expr: &Expr, assignment: &Assignment, alg: Algebra) -> Ternary {
60    match expr {
61        Expr::Const(v) => *v,
62        Expr::Var(name) => assignment.get(name).unwrap_or(Ternary::Unknown),
63        Expr::Not(a) => alg.not(eval(a, assignment, alg)),
64        Expr::And(a, b) => alg.and(eval(a, assignment, alg), eval(b, assignment, alg)),
65        Expr::Or(a, b) => alg.or(eval(a, assignment, alg), eval(b, assignment, alg)),
66        Expr::Xor(a, b) => alg.strong_add(eval(a, assignment, alg), eval(b, assignment, alg)),
67        Expr::Implies(a, b) => alg.implies(eval(a, assignment, alg), eval(b, assignment, alg)),
68        Expr::Equiv(a, b) => alg.equiv(eval(a, assignment, alg), eval(b, assignment, alg)),
69    }
70}
71
72/// 变量名 → 位平面下标的映射。
73pub type VarMap = HashMap<String, usize>;
74
75/// 位并行求值:把表达式编译成对位平面的操作。
76pub fn eval_bitwise(expr: &Expr, planes: &[TriBit], vars: &VarMap, alg: Algebra) -> TriBit {
77    match expr {
78        Expr::Const(v) => TriBit::constant(*v),
79        Expr::Var(name) => match vars.get(name) {
80            Some(idx) => planes.get(*idx).copied().unwrap_or(TriBit::UNKNOWN),
81            None => TriBit::UNKNOWN,
82        },
83        Expr::Not(a) => eval_bitwise(a, planes, vars, alg).not(),
84        Expr::And(a, b) => {
85            let (x, y) = (
86                eval_bitwise(a, planes, vars, alg),
87                eval_bitwise(b, planes, vars, alg),
88            );
89            x.and(y, alg)
90        }
91        Expr::Or(a, b) => {
92            let (x, y) = (
93                eval_bitwise(a, planes, vars, alg),
94                eval_bitwise(b, planes, vars, alg),
95            );
96            x.or(y, alg)
97        }
98        Expr::Xor(a, b) => {
99            let (x, y) = (
100                eval_bitwise(a, planes, vars, alg),
101                eval_bitwise(b, planes, vars, alg),
102            );
103            x.strong_add(y, alg)
104        }
105        Expr::Implies(a, b) => {
106            let (x, y) = (
107                eval_bitwise(a, planes, vars, alg),
108                eval_bitwise(b, planes, vars, alg),
109            );
110            x.implies(y, alg)
111        }
112        Expr::Equiv(a, b) => {
113            let (x, y) = (
114                eval_bitwise(a, planes, vars, alg),
115                eval_bitwise(b, planes, vars, alg),
116            );
117            x.equiv(y, alg)
118        }
119    }
120}
121
122/// 构造求值器并返回「变量名 → 下标」映射。
123fn evaluator_for(vars: &[String], alg: Algebra) -> (Evaluator, VarMap) {
124    let mut ev = Evaluator::new(alg);
125    let mut map = VarMap::new();
126    for name in vars {
127        let idx = ev.declare(name.clone());
128        map.insert(name.clone(), idx);
129    }
130    (ev, map)
131}
132
133/// 全真值表求值。
134///
135/// 变量顺序取自 [`Expr::variables`](首次出现顺序)。
136pub fn truth_table(expr: &Expr, alg: Algebra) -> TruthTable {
137    let vars = expr.variables();
138    let (ev, map) = evaluator_for(&vars, alg);
139    ev.evaluate(|planes| eval_bitwise(expr, planes, &map, alg))
140}
141
142/// 两个表达式在给定语义下是否等价(真值表完全相同)。
143#[derive(Debug, Clone, PartialEq, Eq)]
144pub struct EquivalenceResult {
145    /// 是否等价。
146    pub equivalent: bool,
147    /// 第一个反例的赋值编号(`None` 表示等价或编号超出 u64)。
148    pub counterexample: Option<u64>,
149    /// 第一个反例的完整赋值(等价时为 `None`)。
150    pub counterexample_assignment: Option<Assignment>,
151    /// 参与比较的变量数。
152    pub variable_count: usize,
153}
154
155/// 判断两个表达式在给定语义下是否逻辑等价。
156pub fn equivalent(a: &Expr, b: &Expr, alg: Algebra) -> EquivalenceResult {
157    // 变量取并集,保证两边在同一组赋值上比较
158    let mut vars = a.variables();
159    for v in b.variables() {
160        if !vars.contains(&v) {
161            vars.push(v);
162        }
163    }
164    let (ev, map) = evaluator_for(&vars, alg);
165    let total = ev.assignment_count();
166    let mut base = 0u64;
167    while base < total {
168        let planes = ev.chunk_planes(base);
169        let va = eval_bitwise(a, &planes, &map, alg);
170        let vb = eval_bitwise(b, &planes, &map, alg);
171        let take = (total - base).min(64) as u32;
172        for bit in 0..take {
173            if va.get(bit) != vb.get(bit) {
174                let index = base + bit as u64;
175                return EquivalenceResult {
176                    equivalent: false,
177                    counterexample: Some(index),
178                    counterexample_assignment: Some(decode_assignment(index, &vars)),
179                    variable_count: vars.len(),
180                };
181            }
182        }
183        base += 64;
184    }
185    EquivalenceResult {
186        equivalent: true,
187        counterexample: None,
188        counterexample_assignment: None,
189        variable_count: vars.len(),
190    }
191}
192
193/// 把赋值编码成编号;变量多到超出 `u64` 时返回 `None`。
194///
195/// 编号约定与 [`decode_assignment`] 一致:False=0、True=1、Unknown=2。
196pub fn assignment_index(assignment: &Assignment, vars: &[String]) -> Option<u64> {
197    let mut index = 0u64;
198    let mut power = 1u64;
199    for name in vars {
200        let digit = match assignment.get(name).unwrap_or(Ternary::Unknown) {
201            Ternary::False => 0u64,
202            Ternary::True => 1u64,
203            Ternary::Unknown => 2u64,
204        };
205        index = index.checked_add(digit.checked_mul(power)?)?;
206        power = power.checked_mul(3)?;
207    }
208    Some(index)
209}
210
211/// 把三进制赋值编号解码为各变量的取值。
212pub fn decode_assignment(index: u64, vars: &[String]) -> Assignment {
213    let mut asg = Assignment::new();
214    let mut t = index;
215    for name in vars {
216        let digit = t % 3;
217        t /= 3;
218        let v = match digit {
219            0 => Ternary::False,
220            1 => Ternary::True,
221            _ => Ternary::Unknown,
222        };
223        asg.set(name.clone(), v);
224    }
225    asg
226}
227
228#[cfg(test)]
229mod tests {
230    use super::*;
231    use trit_core::parser::Parser;
232
233    #[test]
234    fn eval_single_assignment() {
235        let e = Parser::parse("a & b").unwrap();
236        let mut asg = Assignment::new();
237        asg.set("a", Ternary::True).set("b", Ternary::False);
238        assert_eq!(eval(&e, &asg, Algebra::Kleene), Ternary::False);
239    }
240
241    #[test]
242    fn unbound_variable_is_unknown() {
243        let e = Parser::parse("a").unwrap();
244        assert_eq!(
245            eval(&e, &Assignment::new(), Algebra::Kleene),
246            Ternary::Unknown
247        );
248    }
249
250    #[test]
251    fn truth_table_covers_all_rows() {
252        let e = Parser::parse("a | b").unwrap();
253        let tt = truth_table(&e, Algebra::Kleene);
254        assert_eq!(tt.variables.len(), 2);
255        assert_eq!(tt.values.len(), 9);
256    }
257
258    #[test]
259    fn truth_table_matches_scalar_evaluation() {
260        let e = Parser::parse("(a & b) | (!a & c)").unwrap();
261        let vars = e.variables();
262        let tt = truth_table(&e, Algebra::Kleene);
263        for (i, expected) in tt.values.iter().enumerate() {
264            let asg = decode_assignment(i as u64, &vars);
265            assert_eq!(eval(&e, &asg, Algebra::Kleene), *expected, "row {i}");
266        }
267    }
268
269    #[test]
270    fn equivalent_detects_equal_expressions() {
271        let a = Parser::parse("a & b").unwrap();
272        let b = Parser::parse("b & a").unwrap();
273        let r = equivalent(&a, &b, Algebra::Kleene);
274        assert!(r.equivalent);
275        assert!(r.counterexample.is_none());
276    }
277
278    #[test]
279    fn equivalent_finds_counterexample() {
280        let a = Parser::parse("a & b").unwrap();
281        let b = Parser::parse("a | b").unwrap();
282        let r = equivalent(&a, &b, Algebra::Kleene);
283        assert!(!r.equivalent);
284        assert!(r.counterexample.is_some());
285    }
286
287    #[test]
288    fn decode_assignment_round_trips() {
289        let vars = vec!["a".to_string(), "b".to_string()];
290        let asg = decode_assignment(0, &vars);
291        assert_eq!(asg.get("a"), Some(Ternary::False));
292        assert_eq!(asg.get("b"), Some(Ternary::False));
293        let asg = decode_assignment(5, &vars);
294        // 变量 0 取最低三进制位:5 = 2 + 1*3 → a=2(unknown), b=1(true)
295        assert_eq!(asg.get("a"), Some(Ternary::Unknown));
296        assert_eq!(asg.get("b"), Some(Ternary::True));
297    }
298}