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