Skip to main content

trit_core/
bits.rs

1//! 位并行真值表引擎。
2//!
3//! 用位向量同时计算多组变量赋值:每个变量的第 `i` 位表示第 `i` 组赋值中
4//! 该变量的取值。一个 `u64` 字一次处理 64 组赋值。
5//!
6//! 一个三值变量在位并行表示下需要**两个**位平面:
7//! - `ones`:该位为 1 表示该组取真;
8//! - `unknowns`:该位为 1 表示该组取未知。
9//!
10//! 于是取值由两个平面唯一确定:`(ones, unknowns)` 为
11//! `(0,0) → 0`、`(1,0) → 1`、`(0,1) → X`,`(1,1)` 为非法组合(不会出现)。
12
13use crate::algebra::Algebra;
14use crate::value::Ternary;
15
16/// 一个位平面的真值向量。
17#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
18pub struct BitPlane(pub u64);
19
20impl BitPlane {
21    /// 全 0 平面。
22    pub const ZERO: Self = Self(0);
23    /// 全 1 平面。
24    pub const ONES: Self = Self(u64::MAX);
25
26    /// 构造指定位为 1 的平面。
27    pub const fn with_bit(bit: u32) -> Self {
28        Self(1u64 << (bit % 64))
29    }
30
31    /// 该平面第 `bit` 位是否为 1。
32    pub const fn bit(self, bit: u32) -> bool {
33        (self.0 >> (bit % 64)) & 1 == 1
34    }
35
36    /// 平面内 1 的个数(popcount)。
37    pub const fn count_ones(self) -> u32 {
38        self.0.count_ones()
39    }
40}
41
42/// 三值的位并行表示:一对位平面。
43#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
44pub struct TriBit {
45    /// 1 平面:取真的组。
46    pub ones: BitPlane,
47    /// X 平面:取未知的组。
48    pub unknowns: BitPlane,
49}
50
51impl TriBit {
52    /// 从二进制平面构造:`ones` 的位就是 `True`,`unknowns = 0`。
53    ///
54    /// 这是二进制与三值之间的零开销桥:不复制、不分配。
55    pub const fn from_binary(ones: u64) -> Self {
56        Self {
57            ones: BitPlane(ones),
58            unknowns: BitPlane::ZERO,
59        }
60    }
61
62    /// 是否为纯二值(没有 `Unknown`)。
63    pub const fn is_binary(self) -> bool {
64        self.unknowns.0 == 0
65    }
66
67    /// 若是纯二值,取出 `ones` 平面;否则 `None`。
68    pub const fn as_binary(self) -> Option<u64> {
69        if self.is_binary() {
70            Some(self.ones.0)
71        } else {
72            None
73        }
74    }
75
76    /// 全假。
77    pub const FALSE: Self = Self {
78        ones: BitPlane::ZERO,
79        unknowns: BitPlane::ZERO,
80    };
81    /// 全真。
82    pub const TRUE: Self = Self {
83        ones: BitPlane::ONES,
84        unknowns: BitPlane::ZERO,
85    };
86    /// 全未知。
87    pub const UNKNOWN: Self = Self {
88        ones: BitPlane::ZERO,
89        unknowns: BitPlane::ONES,
90    };
91
92    /// 构造常量。
93    pub const fn constant(v: Ternary) -> Self {
94        match v {
95            Ternary::False => Self::FALSE,
96            Ternary::Unknown => Self::UNKNOWN,
97            Ternary::True => Self::TRUE,
98        }
99    }
100
101    /// 读出第 `bit` 组的取值。
102    pub const fn get(self, bit: u32) -> Ternary {
103        if self.unknowns.bit(bit) {
104            Ternary::Unknown
105        } else if self.ones.bit(bit) {
106            Ternary::True
107        } else {
108            Ternary::False
109        }
110    }
111
112    /// 该平面代表的“确定真”位数(ones 且非 unknown)。
113    const fn crisp_ones(self) -> u64 {
114        self.ones.0 & !self.unknowns.0
115    }
116
117    /// 该平面代表的“确定假”位数(既非 one 也非 unknown)。
118    const fn crisp_zeros(self) -> u64 {
119        !self.ones.0 & !self.unknowns.0
120    }
121
122    /// 该平面代表的“未知”位数。
123    const fn unknowns(self) -> u64 {
124        self.unknowns.0
125    }
126
127    /// 按位取反。`¬X = X`。
128    pub const fn not(self) -> Self {
129        Self {
130            ones: BitPlane(!self.crisp_ones() & !self.unknowns()),
131            unknowns: self.unknowns,
132        }
133    }
134
135    /// 按位与。
136    ///
137    /// K3 / Ł3:格序 min(`X` 是中间元)。B3:`X` 吸收。
138    pub const fn and(self, other: Self, alg: Algebra) -> Self {
139        if alg.is_poisonous() {
140            return Self::poison_and(self, other);
141        }
142        self.and_lattice(other)
143    }
144
145    /// 按位或。
146    ///
147    /// K3 / Ł3:格序 max(`X` 是中间元)。B3:`X` 吸收。
148    pub const fn or(self, other: Self, alg: Algebra) -> Self {
149        if alg.is_poisonous() {
150            return Self::poison_or(self, other);
151        }
152        self.or_lattice(other)
153    }
154
155    /// Bochvar 毒值与:任一为 `X` 则结果为 `X`,否则按二值与运算。
156    const fn poison_and(self, other: Self) -> Self {
157        let resx = self.unknowns() | other.unknowns();
158        let a1 = self.crisp_ones();
159        let b1 = other.crisp_ones();
160        let res1 = a1 & b1;
161        Self {
162            ones: BitPlane(res1),
163            unknowns: BitPlane(resx),
164        }
165    }
166
167    /// Bochvar 毒值或:任一为 `X` 则结果为 `X`,否则按二值或运算。
168    const fn poison_or(self, other: Self) -> Self {
169        let resx = self.unknowns() | other.unknowns();
170        let a1 = self.crisp_ones();
171        let b1 = other.crisp_ones();
172        // 1 平面必须扣掉未知位,否则会出现被禁止的 (1,1)。
173        let res1 = (a1 | b1) & !resx;
174        Self {
175            ones: BitPlane(res1),
176            unknowns: BitPlane(resx),
177        }
178    }
179
180    /// 按位与:格序 min(K3 / Ł3)。
181    pub const fn and_lattice(self, other: Self) -> Self {
182        let a0 = self.crisp_zeros();
183        let b0 = other.crisp_zeros();
184        let a1 = self.crisp_ones();
185        let b1 = other.crisp_ones();
186        let res0 = a0 | b0;
187        let res1 = a1 & b1;
188        let resx = !res0 & !res1;
189        Self {
190            ones: BitPlane(res1),
191            unknowns: BitPlane(resx),
192        }
193    }
194
195    /// 按位或:格序 max(K3 / Ł3)。
196    pub const fn or_lattice(self, other: Self) -> Self {
197        let a0 = self.crisp_zeros();
198        let b0 = other.crisp_zeros();
199        let a1 = self.crisp_ones();
200        let b1 = other.crisp_ones();
201        let res1 = a1 | b1;
202        let res0 = a0 & b0;
203        let resx = !res1 & !res0;
204        Self {
205            ones: BitPlane(res1),
206            unknowns: BitPlane(resx),
207        }
208    }
209
210    /// 按位强加法 `⊕`,语义相关。
211    pub const fn strong_add(self, other: Self, alg: Algebra) -> Self {
212        match alg {
213            // Łukasiewicz: min(1, a + b)
214            Algebra::Lukasiewicz => {
215                let a0 = self.crisp_zeros();
216                let a1 = self.crisp_ones();
217                let ax = self.unknowns();
218                let b0 = other.crisp_zeros();
219                let b1 = other.crisp_ones();
220                let bx = other.unknowns();
221                let res1 = (a0 & b1) | (a1 & b0) | (a1 & b1) | (ax & bx) | (ax & b1) | (a1 & bx);
222                let res0 = a0 & b0;
223                let resx = !res1 & !res0;
224                Self {
225                    ones: BitPlane(res1),
226                    unknowns: BitPlane(resx),
227                }
228            }
229            // Kleene / Bochvar: 0/1 上为强加法,X 传播
230            Algebra::Kleene | Algebra::Bochvar => {
231                let a1 = self.crisp_ones();
232                let b1 = other.crisp_ones();
233                let res1 = a1 & b1;
234                let resx = self.unknowns() | other.unknowns();
235                let _res0 = !res1 & !resx;
236                Self {
237                    ones: BitPlane(res1),
238                    unknowns: BitPlane(resx),
239                }
240            }
241        }
242    }
243
244    /// 按位强合取 `⊗`,语义相关。
245    pub const fn strong_and(self, other: Self, alg: Algebra) -> Self {
246        match alg {
247            // Łukasiewicz: max(0, a + b - 1)
248            Algebra::Lukasiewicz => {
249                let a1 = self.crisp_ones();
250                let b1 = other.crisp_ones();
251                let res1 = a1 & b1;
252                let res0 =
253                    self.crisp_zeros() | other.crisp_zeros() | (self.unknowns() & other.unknowns());
254                let resx = !res1 & !res0;
255                Self {
256                    ones: BitPlane(res1),
257                    unknowns: BitPlane(resx),
258                }
259            }
260            // Kleene / Bochvar: 0/1 上为强合取,X 传播
261            Algebra::Kleene | Algebra::Bochvar => {
262                let a1 = self.crisp_ones();
263                let b1 = other.crisp_ones();
264                let res1 = a1 & b1;
265                let resx = self.unknowns() | other.unknowns();
266                let _res0 = !res1 & !resx;
267                Self {
268                    ones: BitPlane(res1),
269                    unknowns: BitPlane(resx),
270                }
271            }
272        }
273    }
274
275    /// 按位蕴含 `⇒`,语义相关。
276    pub const fn implies(self, other: Self, alg: Algebra) -> Self {
277        match alg {
278            // Kleene: 材料蕴含 ¬a ∨ b
279            Algebra::Kleene => self.not().or_lattice(other),
280            // Bochvar: 毒值语义,任一 X 出现即 X;否则 a=1 取 b,a=0 取 1
281            Algebra::Bochvar => {
282                let a0 = self.crisp_zeros();
283                let a1 = self.crisp_ones();
284                let b0 = other.crisp_zeros();
285                let b1 = other.crisp_ones();
286                let res1 = (a0 & (b0 | b1)) | (a1 & b1);
287                let resx = self.unknowns() | other.unknowns();
288                Self {
289                    ones: BitPlane(res1),
290                    unknowns: BitPlane(resx),
291                }
292            }
293            // Łukasiewicz: MV 蕴含 min(1, 1 - a + b)
294            Algebra::Lukasiewicz => {
295                let a0 = self.crisp_zeros();
296                let a1 = self.crisp_ones();
297                let ax = self.unknowns();
298                let b0 = other.crisp_zeros();
299                let b1 = other.crisp_ones();
300                let bx = other.unknowns();
301                let res1 = (a0 & (b0 | bx | b1)) | (ax & (bx | b1)) | (a1 & b1);
302                let res0 = a1 & b0;
303                let resx = !res1 & !res0;
304                Self {
305                    ones: BitPlane(res1),
306                    unknowns: BitPlane(resx),
307                }
308            }
309        }
310    }
311
312    /// 按位等价 `≡`。
313    pub const fn equiv(self, other: Self, alg: Algebra) -> Self {
314        self.implies(other, alg).and(other.implies(self, alg), alg)
315    }
316}
317
318/// 一个表达式的完整真值表结果。
319#[derive(Debug, Clone)]
320pub struct TruthTable {
321    /// 变量名(按编号顺序)。
322    pub variables: Vec<String>,
323    /// 每组赋值的结果值。
324    pub values: Vec<Ternary>,
325}
326
327impl TruthTable {
328    /// 取出指定赋值下的结果。
329    pub fn value_at(&self, index: usize) -> Option<Ternary> {
330        self.values.get(index).copied()
331    }
332
333    /// 结果中出现过的不同取值集合(升序)。
334    pub fn distinct_values(&self) -> Vec<Ternary> {
335        let mut seen = [false; 3];
336        for v in &self.values {
337            seen[match v {
338                Ternary::False => 0,
339                Ternary::Unknown => 1,
340                Ternary::True => 2,
341            }] = true;
342        }
343        let mut out = Vec::new();
344        if seen[0] {
345            out.push(Ternary::False);
346        }
347        if seen[1] {
348            out.push(Ternary::Unknown);
349        }
350        if seen[2] {
351            out.push(Ternary::True);
352        }
353        out
354    }
355
356    /// 结果全为假。
357    pub fn is_always_false(&self) -> bool {
358        self.values.iter().all(|v| v.is_false())
359    }
360
361    /// 结果全为真。
362    pub fn is_always_true(&self) -> bool {
363        self.values.iter().all(|v| v.is_true())
364    }
365
366    /// 结果是否含未知。
367    pub fn has_unknown(&self) -> bool {
368        self.values.iter().any(|v| v.is_unknown())
369    }
370}
371
372/// 位并行求值器:把表达式在全部 `3^n` 组赋值上求值。
373#[derive(Debug, Clone)]
374pub struct Evaluator {
375    algebra: Algebra,
376    variables: Vec<String>,
377}
378
379impl Evaluator {
380    /// 新建求值器。
381    pub fn new(algebra: Algebra) -> Self {
382        Self {
383            algebra,
384            variables: Vec::new(),
385        }
386    }
387
388    /// 语义体系。
389    pub fn algebra(&self) -> Algebra {
390        self.algebra
391    }
392
393    /// 变量名列表。
394    pub fn variables(&self) -> &[String] {
395        &self.variables
396    }
397
398    /// 登记变量(重复登记返回原编号)。
399    pub fn declare(&mut self, name: impl Into<String>) -> usize {
400        let name = name.into();
401        if let Some(idx) = self.variables.iter().position(|v| *v == name) {
402            return idx;
403        }
404        self.variables.push(name);
405        self.variables.len() - 1
406    }
407
408    /// 赋值总数 `3^n`。
409    pub fn assignment_count(&self) -> u64 {
410        3u64.saturating_pow(self.variables.len() as u32)
411    }
412
413    /// 构造一个 64 组分块中各变量的位平面。
414    ///
415    /// `base` 是该分块首个赋值的编号(必为 64 的倍数)。
416    /// 变量 `i` 的取值由赋值编号的第 `i` 个三进制位决定
417    /// (`0 → 0`,`1 → 1`,`2 → X`)。
418    pub fn chunk_planes(&self, base: u64) -> Vec<TriBit> {
419        let mut planes = Vec::with_capacity(self.variables.len());
420        for i in 0..self.variables.len() {
421            let mut ones = 0u64;
422            let mut unknowns = 0u64;
423            let pow = 3u64.saturating_pow(i as u32);
424            for bit in 0..64u32 {
425                let group = base + bit as u64;
426                let digit = (group / pow) % 3;
427                match digit {
428                    1 => ones |= 1u64 << bit,
429                    2 => unknowns |= 1u64 << bit,
430                    _ => {}
431                }
432            }
433            planes.push(TriBit {
434                ones: BitPlane(ones),
435                unknowns: BitPlane(unknowns),
436            });
437        }
438        planes
439    }
440
441    /// 在全部 `3^n` 组赋值上求值。
442    ///
443    /// 内部按 64 组一块做位并行计算,再展开为逐组结果。
444    pub fn evaluate<F>(&self, f: F) -> TruthTable
445    where
446        F: Fn(&[TriBit]) -> TriBit,
447    {
448        let total = self.assignment_count();
449        let mut values = Vec::with_capacity(total as usize);
450        let mut base = 0u64;
451        while base < total {
452            let planes = self.chunk_planes(base);
453            let res = f(&planes);
454            let take = (total - base).min(64) as u32;
455            for bit in 0..take {
456                values.push(res.get(bit));
457            }
458            base += 64;
459        }
460        TruthTable {
461            variables: self.variables.clone(),
462            values,
463        }
464    }
465}
466
467#[cfg(test)]
468mod tests {
469    use super::*;
470
471    fn tri(v: Ternary) -> TriBit {
472        TriBit::constant(v)
473    }
474
475    #[test]
476    fn not_matches_scalar() {
477        for a in Ternary::ALL {
478            assert_eq!(tri(a).not().get(0), Algebra::Kleene.not(a), "NOT {a}");
479        }
480    }
481
482    #[test]
483    fn and_or_match_scalar_for_all_algebras() {
484        for alg in Algebra::ALL {
485            for a in Ternary::ALL {
486                for b in Ternary::ALL {
487                    assert_eq!(
488                        tri(a).and(tri(b), alg).get(0),
489                        alg.and(a, b),
490                        "{alg} {a}&{b}"
491                    );
492                    assert_eq!(tri(a).or(tri(b), alg).get(0), alg.or(a, b), "{alg} {a}|{b}");
493                }
494            }
495        }
496    }
497
498    #[test]
499    fn strong_add_matches_scalar_for_all_algebras() {
500        for alg in Algebra::ALL {
501            for a in Ternary::ALL {
502                for b in Ternary::ALL {
503                    assert_eq!(
504                        tri(a).strong_add(tri(b), alg).get(0),
505                        alg.strong_add(a, b),
506                        "{alg} {a}+{b}"
507                    );
508                }
509            }
510        }
511    }
512
513    #[test]
514    fn strong_and_matches_scalar_for_all_algebras() {
515        for alg in Algebra::ALL {
516            for a in Ternary::ALL {
517                for b in Ternary::ALL {
518                    assert_eq!(
519                        tri(a).strong_and(tri(b), alg).get(0),
520                        alg.strong_and(a, b),
521                        "{alg} {a}*{b}"
522                    );
523                }
524            }
525        }
526    }
527
528    #[test]
529    fn ops_never_produce_illegal_rails() {
530        for alg in Algebra::ALL {
531            for a in Ternary::ALL {
532                for b in Ternary::ALL {
533                    for r in [
534                        tri(a).and(tri(b), alg),
535                        tri(a).or(tri(b), alg),
536                        tri(a).strong_add(tri(b), alg),
537                    ] {
538                        assert_eq!(r.ones.0 & r.unknowns.0, 0, "{alg} {a} {b} 产生了 (1,1)");
539                    }
540                }
541            }
542        }
543    }
544
545    #[test]
546    fn implies_matches_scalar_for_all_algebras() {
547        for alg in Algebra::ALL {
548            for a in Ternary::ALL {
549                for b in Ternary::ALL {
550                    assert_eq!(
551                        tri(a).implies(tri(b), alg).get(0),
552                        alg.implies(a, b),
553                        "{alg} {a}=>{b}"
554                    );
555                }
556            }
557        }
558    }
559
560    #[test]
561    fn equiv_matches_scalar_for_all_algebras() {
562        for alg in Algebra::ALL {
563            for a in Ternary::ALL {
564                for b in Ternary::ALL {
565                    assert_eq!(
566                        tri(a).equiv(tri(b), alg).get(0),
567                        alg.equiv(a, b),
568                        "{alg} {a}<=>{b}"
569                    );
570                }
571            }
572        }
573    }
574
575    #[test]
576    fn bitwise_ops_agree_across_64_lanes() {
577        // 构造一个混合 0/1/X 的 64 位平面,逐位与标量结果比对
578        let mut ones = 0u64;
579        let mut unknowns = 0u64;
580        for i in 0..64u32 {
581            match i % 3 {
582                1 => ones |= 1u64 << i,
583                2 => unknowns |= 1u64 << i,
584                _ => {}
585            }
586        }
587        let t = TriBit {
588            ones: BitPlane(ones),
589            unknowns: BitPlane(unknowns),
590        };
591        let other = TriBit {
592            ones: BitPlane(0x5555_5555_5555_5555),
593            unknowns: BitPlane(0x0f0f_0f0f_0f0f_0f0f),
594        };
595        for alg in Algebra::ALL {
596            let got = t.and(other, alg);
597            for i in 0..64u32 {
598                assert_eq!(
599                    got.get(i),
600                    alg.and(t.get(i), other.get(i)),
601                    "{alg} lane {i}"
602                );
603            }
604        }
605    }
606
607    #[test]
608    fn evaluator_covers_all_assignments() {
609        let mut ev = Evaluator::new(Algebra::Kleene);
610        ev.declare("a");
611        ev.declare("b");
612        assert_eq!(ev.assignment_count(), 9);
613        let tt = ev.evaluate(|p| p[0]);
614        assert_eq!(tt.values.len(), 9);
615        // 三进制混合序:第 0 组 a=0,第 1 组 a=1,第 2 组 a=X
616        assert_eq!(tt.value_at(0), Some(Ternary::False));
617        assert_eq!(tt.value_at(1), Some(Ternary::True));
618        assert_eq!(tt.value_at(2), Some(Ternary::Unknown));
619        assert_eq!(tt.value_at(3), Some(Ternary::False));
620    }
621
622    #[test]
623    fn evaluator_spans_multiple_chunks() {
624        // 4 个变量 → 81 组赋值,跨越 64 组边界
625        let mut ev = Evaluator::new(Algebra::Kleene);
626        for name in ["a", "b", "c", "d"] {
627            ev.declare(name);
628        }
629        assert_eq!(ev.assignment_count(), 81);
630        let tt = ev.evaluate(|p| p[3]);
631        assert_eq!(tt.values.len(), 81);
632        for (i, v) in tt.values.iter().enumerate() {
633            let digit = (i as u64 / 27) % 3;
634            let expect = match digit {
635                0 => Ternary::False,
636                1 => Ternary::True,
637                _ => Ternary::Unknown,
638            };
639            assert_eq!(*v, expect, "group {i}");
640        }
641    }
642}