1use super::functions::*;
6use oxilean_kernel::{BinderInfo, Declaration, Environment, Expr, InductiveEnv, Level, Name};
7
8#[allow(dead_code)]
10#[derive(Debug, Clone, Copy, PartialEq, Eq)]
11pub enum Kleene3Val {
12 False,
14 Unknown,
16 True,
18}
19impl Kleene3Val {
20 #[allow(dead_code)]
22 pub fn not(self) -> Self {
23 match self {
24 Kleene3Val::True => Kleene3Val::False,
25 Kleene3Val::False => Kleene3Val::True,
26 Kleene3Val::Unknown => Kleene3Val::Unknown,
27 }
28 }
29 #[allow(dead_code)]
31 pub fn and(self, other: Self) -> Self {
32 match (self, other) {
33 (Kleene3Val::False, _) | (_, Kleene3Val::False) => Kleene3Val::False,
34 (Kleene3Val::True, Kleene3Val::True) => Kleene3Val::True,
35 _ => Kleene3Val::Unknown,
36 }
37 }
38 #[allow(dead_code)]
40 pub fn or(self, other: Self) -> Self {
41 match (self, other) {
42 (Kleene3Val::True, _) | (_, Kleene3Val::True) => Kleene3Val::True,
43 (Kleene3Val::False, Kleene3Val::False) => Kleene3Val::False,
44 _ => Kleene3Val::Unknown,
45 }
46 }
47 #[allow(dead_code)]
49 pub fn from_bool(b: bool) -> Self {
50 if b {
51 Kleene3Val::True
52 } else {
53 Kleene3Val::False
54 }
55 }
56}
57#[allow(dead_code)]
59#[derive(Debug, Clone)]
60pub struct TruthTable {
61 pub entries: [TruthTableEntry; 4],
63 pub name: &'static str,
65}
66impl TruthTable {
67 #[allow(dead_code)]
69 pub fn compute(name: &'static str, f: fn(bool, bool) -> bool) -> Self {
70 Self {
71 name,
72 entries: [
73 TruthTableEntry {
74 a: false,
75 b: false,
76 output: f(false, false),
77 },
78 TruthTableEntry {
79 a: false,
80 b: true,
81 output: f(false, true),
82 },
83 TruthTableEntry {
84 a: true,
85 b: false,
86 output: f(true, false),
87 },
88 TruthTableEntry {
89 a: true,
90 b: true,
91 output: f(true, true),
92 },
93 ],
94 }
95 }
96 #[allow(dead_code)]
98 pub fn lookup(&self, a: bool, b: bool) -> bool {
99 self.entries
100 .iter()
101 .find(|e| e.a == a && e.b == b)
102 .map(|e| e.output)
103 .expect("Truth table must have all 4 entries")
104 }
105 #[allow(dead_code)]
107 pub fn is_commutative(&self) -> bool {
108 self.lookup(true, false) == self.lookup(false, true)
109 }
110 #[allow(dead_code)]
112 pub fn is_tautology(&self) -> bool {
113 self.entries.iter().all(|e| e.output)
114 }
115 #[allow(dead_code)]
117 pub fn is_contradiction(&self) -> bool {
118 self.entries.iter().all(|e| !e.output)
119 }
120 #[allow(dead_code)]
122 pub fn true_count(&self) -> usize {
123 self.entries.iter().filter(|e| e.output).count()
124 }
125}
126#[allow(dead_code)]
128pub struct DecidablePred<T> {
129 pub decide: Box<dyn Fn(&T) -> bool>,
131 pub name: String,
133}
134#[allow(dead_code)]
136pub struct SATInstance {
137 pub num_vars: usize,
139 pub clauses: Vec<Vec<i32>>,
141}
142impl SATInstance {
143 #[allow(dead_code)]
145 pub fn new(num_vars: usize) -> Self {
146 SATInstance {
147 num_vars,
148 clauses: Vec::new(),
149 }
150 }
151 #[allow(dead_code)]
153 pub fn add_clause(&mut self, clause: Vec<i32>) {
154 self.clauses.push(clause);
155 }
156 #[allow(dead_code)]
158 pub fn solve(&self) -> Option<Vec<bool>> {
159 let n = self.num_vars;
160 for mask in 0..(1u64 << n) {
161 let assignment: Vec<bool> = (0..n).map(|i| (mask >> i) & 1 == 1).collect();
162 if self.evaluate(&assignment) {
163 return Some(assignment);
164 }
165 }
166 None
167 }
168 #[allow(dead_code)]
170 pub fn evaluate(&self, assignment: &[bool]) -> bool {
171 self.clauses.iter().all(|clause| {
172 clause.iter().any(|&lit| {
173 if lit > 0 {
174 assignment.get((lit - 1) as usize).copied().unwrap_or(false)
175 } else {
176 !assignment.get((-lit - 1) as usize).copied().unwrap_or(true)
177 }
178 })
179 })
180 }
181}
182#[allow(dead_code)]
184#[derive(Debug, Clone, PartialEq)]
185pub enum BoolExpr {
186 Const(bool),
188 Var(String),
190 Not(Box<BoolExpr>),
192 And(Box<BoolExpr>, Box<BoolExpr>),
194 Or(Box<BoolExpr>, Box<BoolExpr>),
196 Xor(Box<BoolExpr>, Box<BoolExpr>),
198 Implies(Box<BoolExpr>, Box<BoolExpr>),
200 Iff(Box<BoolExpr>, Box<BoolExpr>),
202}
203impl BoolExpr {
204 #[allow(dead_code)]
208 pub fn eval(&self, env: &std::collections::HashMap<&str, bool>) -> Option<bool> {
209 match self {
210 BoolExpr::Const(b) => Some(*b),
211 BoolExpr::Var(name) => env.get(name.as_str()).copied(),
212 BoolExpr::Not(e) => e.eval(env).map(|b| !b),
213 BoolExpr::And(l, r) => Some(l.eval(env)? && r.eval(env)?),
214 BoolExpr::Or(l, r) => Some(l.eval(env)? || r.eval(env)?),
215 BoolExpr::Xor(l, r) => Some(l.eval(env)? ^ r.eval(env)?),
216 BoolExpr::Implies(l, r) => Some(!l.eval(env)? || r.eval(env)?),
217 BoolExpr::Iff(l, r) => Some(l.eval(env)? == r.eval(env)?),
218 }
219 }
220 #[allow(dead_code)]
222 pub fn variables(&self) -> Vec<String> {
223 let mut vars = Vec::new();
224 self.collect_vars(&mut vars);
225 vars
226 }
227 fn collect_vars(&self, vars: &mut Vec<String>) {
228 match self {
229 BoolExpr::Var(name) => {
230 if !vars.contains(name) {
231 vars.push(name.clone());
232 }
233 }
234 BoolExpr::Not(e) => e.collect_vars(vars),
235 BoolExpr::And(l, r)
236 | BoolExpr::Or(l, r)
237 | BoolExpr::Xor(l, r)
238 | BoolExpr::Implies(l, r)
239 | BoolExpr::Iff(l, r) => {
240 l.collect_vars(vars);
241 r.collect_vars(vars);
242 }
243 BoolExpr::Const(_) => {}
244 }
245 }
246 #[allow(dead_code)]
248 pub fn is_tautology(&self) -> bool {
249 let vars = self.variables();
250 let n = vars.len();
251 for mask in 0..(1u64 << n) {
252 let mut env = std::collections::HashMap::new();
253 for (i, var) in vars.iter().enumerate() {
254 env.insert(var.as_str(), (mask >> i) & 1 == 1);
255 }
256 if self.eval(&env) != Some(true) {
257 return false;
258 }
259 }
260 true
261 }
262}
263#[allow(dead_code)]
265pub struct XorMonoid {
266 pub identity: bool,
268 pub associative: bool,
270 pub self_inverse: bool,
272}
273#[allow(dead_code)]
275pub struct BoolAlgebra {
276 pub carrier_size: usize,
278 pub involutive: bool,
280 pub de_morgan: bool,
282}
283#[allow(dead_code)]
285pub struct BoolLattice {
286 pub bottom: bool,
288 pub top: bool,
290 pub distributive: bool,
292 pub complemented: bool,
294}
295#[allow(dead_code)]
297#[derive(Debug, Clone, Copy, PartialEq, Eq)]
298pub struct TruthTableEntry {
299 pub a: bool,
301 pub b: bool,
303 pub output: bool,
305}