use super::functions::*;
use oxilean_kernel::{BinderInfo, Declaration, Environment, Expr, InductiveEnv, Level, Name};
#[allow(dead_code)]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Kleene3Val {
False,
Unknown,
True,
}
impl Kleene3Val {
#[allow(dead_code)]
pub fn not(self) -> Self {
match self {
Kleene3Val::True => Kleene3Val::False,
Kleene3Val::False => Kleene3Val::True,
Kleene3Val::Unknown => Kleene3Val::Unknown,
}
}
#[allow(dead_code)]
pub fn and(self, other: Self) -> Self {
match (self, other) {
(Kleene3Val::False, _) | (_, Kleene3Val::False) => Kleene3Val::False,
(Kleene3Val::True, Kleene3Val::True) => Kleene3Val::True,
_ => Kleene3Val::Unknown,
}
}
#[allow(dead_code)]
pub fn or(self, other: Self) -> Self {
match (self, other) {
(Kleene3Val::True, _) | (_, Kleene3Val::True) => Kleene3Val::True,
(Kleene3Val::False, Kleene3Val::False) => Kleene3Val::False,
_ => Kleene3Val::Unknown,
}
}
#[allow(dead_code)]
pub fn from_bool(b: bool) -> Self {
if b {
Kleene3Val::True
} else {
Kleene3Val::False
}
}
}
#[allow(dead_code)]
#[derive(Debug, Clone)]
pub struct TruthTable {
pub entries: [TruthTableEntry; 4],
pub name: &'static str,
}
impl TruthTable {
#[allow(dead_code)]
pub fn compute(name: &'static str, f: fn(bool, bool) -> bool) -> Self {
Self {
name,
entries: [
TruthTableEntry {
a: false,
b: false,
output: f(false, false),
},
TruthTableEntry {
a: false,
b: true,
output: f(false, true),
},
TruthTableEntry {
a: true,
b: false,
output: f(true, false),
},
TruthTableEntry {
a: true,
b: true,
output: f(true, true),
},
],
}
}
#[allow(dead_code)]
pub fn lookup(&self, a: bool, b: bool) -> bool {
self.entries
.iter()
.find(|e| e.a == a && e.b == b)
.map(|e| e.output)
.expect("Truth table must have all 4 entries")
}
#[allow(dead_code)]
pub fn is_commutative(&self) -> bool {
self.lookup(true, false) == self.lookup(false, true)
}
#[allow(dead_code)]
pub fn is_tautology(&self) -> bool {
self.entries.iter().all(|e| e.output)
}
#[allow(dead_code)]
pub fn is_contradiction(&self) -> bool {
self.entries.iter().all(|e| !e.output)
}
#[allow(dead_code)]
pub fn true_count(&self) -> usize {
self.entries.iter().filter(|e| e.output).count()
}
}
#[allow(dead_code)]
pub struct DecidablePred<T> {
pub decide: Box<dyn Fn(&T) -> bool>,
pub name: String,
}
#[allow(dead_code)]
pub struct SATInstance {
pub num_vars: usize,
pub clauses: Vec<Vec<i32>>,
}
impl SATInstance {
#[allow(dead_code)]
pub fn new(num_vars: usize) -> Self {
SATInstance {
num_vars,
clauses: Vec::new(),
}
}
#[allow(dead_code)]
pub fn add_clause(&mut self, clause: Vec<i32>) {
self.clauses.push(clause);
}
#[allow(dead_code)]
pub fn solve(&self) -> Option<Vec<bool>> {
let n = self.num_vars;
for mask in 0..(1u64 << n) {
let assignment: Vec<bool> = (0..n).map(|i| (mask >> i) & 1 == 1).collect();
if self.evaluate(&assignment) {
return Some(assignment);
}
}
None
}
#[allow(dead_code)]
pub fn evaluate(&self, assignment: &[bool]) -> bool {
self.clauses.iter().all(|clause| {
clause.iter().any(|&lit| {
if lit > 0 {
assignment.get((lit - 1) as usize).copied().unwrap_or(false)
} else {
!assignment.get((-lit - 1) as usize).copied().unwrap_or(true)
}
})
})
}
}
#[allow(dead_code)]
#[derive(Debug, Clone, PartialEq)]
pub enum BoolExpr {
Const(bool),
Var(String),
Not(Box<BoolExpr>),
And(Box<BoolExpr>, Box<BoolExpr>),
Or(Box<BoolExpr>, Box<BoolExpr>),
Xor(Box<BoolExpr>, Box<BoolExpr>),
Implies(Box<BoolExpr>, Box<BoolExpr>),
Iff(Box<BoolExpr>, Box<BoolExpr>),
}
impl BoolExpr {
#[allow(dead_code)]
pub fn eval(&self, env: &std::collections::HashMap<&str, bool>) -> Option<bool> {
match self {
BoolExpr::Const(b) => Some(*b),
BoolExpr::Var(name) => env.get(name.as_str()).copied(),
BoolExpr::Not(e) => e.eval(env).map(|b| !b),
BoolExpr::And(l, r) => Some(l.eval(env)? && r.eval(env)?),
BoolExpr::Or(l, r) => Some(l.eval(env)? || r.eval(env)?),
BoolExpr::Xor(l, r) => Some(l.eval(env)? ^ r.eval(env)?),
BoolExpr::Implies(l, r) => Some(!l.eval(env)? || r.eval(env)?),
BoolExpr::Iff(l, r) => Some(l.eval(env)? == r.eval(env)?),
}
}
#[allow(dead_code)]
pub fn variables(&self) -> Vec<String> {
let mut vars = Vec::new();
self.collect_vars(&mut vars);
vars
}
fn collect_vars(&self, vars: &mut Vec<String>) {
match self {
BoolExpr::Var(name) => {
if !vars.contains(name) {
vars.push(name.clone());
}
}
BoolExpr::Not(e) => e.collect_vars(vars),
BoolExpr::And(l, r)
| BoolExpr::Or(l, r)
| BoolExpr::Xor(l, r)
| BoolExpr::Implies(l, r)
| BoolExpr::Iff(l, r) => {
l.collect_vars(vars);
r.collect_vars(vars);
}
BoolExpr::Const(_) => {}
}
}
#[allow(dead_code)]
pub fn is_tautology(&self) -> bool {
let vars = self.variables();
let n = vars.len();
for mask in 0..(1u64 << n) {
let mut env = std::collections::HashMap::new();
for (i, var) in vars.iter().enumerate() {
env.insert(var.as_str(), (mask >> i) & 1 == 1);
}
if self.eval(&env) != Some(true) {
return false;
}
}
true
}
}
#[allow(dead_code)]
pub struct XorMonoid {
pub identity: bool,
pub associative: bool,
pub self_inverse: bool,
}
#[allow(dead_code)]
pub struct BoolAlgebra {
pub carrier_size: usize,
pub involutive: bool,
pub de_morgan: bool,
}
#[allow(dead_code)]
pub struct BoolLattice {
pub bottom: bool,
pub top: bool,
pub distributive: bool,
pub complemented: bool,
}
#[allow(dead_code)]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct TruthTableEntry {
pub a: bool,
pub b: bool,
pub output: bool,
}