Clean up and preperations for cdcl

This commit is contained in:
hal8174 2024-10-22 14:45:02 +02:00
parent 9d9f75dd20
commit 830a3387b0
6 changed files with 93 additions and 122 deletions

21
src/cdcl.rs Normal file
View file

@ -0,0 +1,21 @@
use crate::{dpll::Index, normal_form::NormalForm};
enum Result {
Complete,
Conflict(Vec<Index>),
}
fn cdcl_internal(
cnf: &NormalForm,
solution: &mut Vec<Index>,
graph: Vec<(Index, Index)>,
) -> Result {
todo!()
}
pub fn cdcl(cnf: &NormalForm, solution: &mut Vec<Index>) -> bool {
match cdcl_internal(cnf, solution, vec![]) {
Result::Complete => true,
Result::Conflict(_) => false,
}
}

View file

@ -21,7 +21,6 @@ fn unit_propagate(cnf: &mut Vec<Vec<Index>>, solution: &mut Vec<Index>) {
{ {
let l = cnf[i][0]; let l = cnf[i][0];
solution.push(l); solution.push(l);
cnf.swap_remove(i);
remvove_literal(cnf, l); remvove_literal(cnf, l);
unit_propagate(cnf, solution); unit_propagate(cnf, solution);
} }

View file

@ -1,6 +1,4 @@
use std::{ use std::{cell::RefCell, collections::HashSet};
borrow::BorrowMut, cell::RefCell, collections::HashSet, ops::DerefMut, sync::RwLockWriteGuard,
};
use crate::{dpll::Index, normal_form::NormalForm}; use crate::{dpll::Index, normal_form::NormalForm};

View file

@ -1,6 +1,5 @@
use crate::{dpll::Index, mapping::Mapping, normal_form::NormalForm}; use crate::{dpll::Index, mapping::Mapping, normal_form::NormalForm};
use miette::{miette, Context, Result}; use miette::{miette, Context, Result};
use std::collections::HashMap;
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub enum Expr<'s> { pub enum Expr<'s> {
@ -171,25 +170,25 @@ impl<'s> Expr<'s> {
} }
} }
pub fn disjunctiveNormalForm(self) -> Self { pub fn disjunctive_normal_form(self) -> Self {
// dbg!(&self); // dbg!(&self);
match self { match self {
Expr::Literal(_) => self, Expr::Literal(_) => self,
Expr::Not(n) => match *n { Expr::Not(n) => match *n {
Expr::Literal(_) => Expr::Not(n), Expr::Literal(_) => Expr::Not(n),
Expr::Not(i) => i.disjunctiveNormalForm(), Expr::Not(i) => i.disjunctive_normal_form(),
Expr::And(v) => Expr::Or( Expr::And(v) => Expr::Or(
v.into_iter() v.into_iter()
.map(|e| Expr::Not(Box::new(e)).disjunctiveNormalForm()) .map(|e| Expr::Not(Box::new(e)).disjunctive_normal_form())
.collect(), .collect(),
) )
.disjunctiveNormalForm(), .disjunctive_normal_form(),
Expr::Or(v) => Expr::And( Expr::Or(v) => Expr::And(
v.into_iter() v.into_iter()
.map(|e| Expr::Not(Box::new(e)).disjunctiveNormalForm()) .map(|e| Expr::Not(Box::new(e)).disjunctive_normal_form())
.collect(), .collect(),
) )
.disjunctiveNormalForm(), .disjunctive_normal_form(),
}, },
Expr::And(v) => { Expr::And(v) => {
let v = v let v = v
@ -213,7 +212,7 @@ impl<'s> Expr<'s> {
v.into_iter().next().unwrap() v.into_iter().next().unwrap()
} else { } else {
let mut iter = v.into_iter(); let mut iter = v.into_iter();
let mut v = match iter.next().unwrap().disjunctiveNormalForm() { let mut v = match iter.next().unwrap().disjunctive_normal_form() {
Expr::Literal(s) => vec![Expr::Literal(s)], Expr::Literal(s) => vec![Expr::Literal(s)],
Expr::Not(n) => vec![Expr::Not(n)], Expr::Not(n) => vec![Expr::Not(n)],
Expr::And(_) => unreachable!(), Expr::And(_) => unreachable!(),
@ -223,16 +222,16 @@ impl<'s> Expr<'s> {
for e in iter { for e in iter {
v = v v = v
.into_iter() .into_iter()
.map(|i| Expr::And(vec![e.clone(), i]).disjunctiveNormalForm()) .map(|i| Expr::And(vec![e.clone(), i]).disjunctive_normal_form())
.collect() .collect()
} }
Expr::Or(v).disjunctiveNormalForm() Expr::Or(v).disjunctive_normal_form()
} }
} }
Expr::Or(v) => Expr::Or( Expr::Or(v) => Expr::Or(
v.into_iter() v.into_iter()
.flat_map(|e| match e.disjunctiveNormalForm() { .flat_map(|e| match e.disjunctive_normal_form() {
Expr::Literal(s) => vec![Expr::Literal(s)].into_iter(), Expr::Literal(s) => vec![Expr::Literal(s)].into_iter(),
Expr::Not(n) => vec![Expr::Not(n)].into_iter(), Expr::Not(n) => vec![Expr::Not(n)].into_iter(),
Expr::And(_) => unreachable!(), Expr::And(_) => unreachable!(),
@ -243,7 +242,7 @@ impl<'s> Expr<'s> {
} }
} }
pub fn disjunctiveNormalForm2(self, mapping: &mut Mapping<'s>) -> NormalForm { pub fn disjunctive_normal_form2(self, mapping: &mut Mapping<'s>) -> NormalForm {
match self { match self {
Expr::Literal(l) => { Expr::Literal(l) => {
let mut n = NormalForm::new(); let mut n = NormalForm::new();
@ -256,12 +255,12 @@ impl<'s> Expr<'s> {
n.add_clause(&[-mapping.forward(l)]); n.add_clause(&[-mapping.forward(l)]);
n n
} }
Expr::Not(n) => n.disjunctiveNormalForm2(mapping), Expr::Not(n) => n.disjunctive_normal_form2(mapping),
Expr::And(v) => { Expr::And(v) => {
let mut n = NormalForm::new(); let mut n = NormalForm::new();
for e in v for e in v
.into_iter() .into_iter()
.map(|e| Expr::Not(Box::new(e)).disjunctiveNormalForm2(mapping)) .map(|e| Expr::Not(Box::new(e)).disjunctive_normal_form2(mapping))
{ {
for (s, _, _) in e.iter() { for (s, _, _) in e.iter() {
n.add_clause(s); n.add_clause(s);
@ -271,12 +270,12 @@ impl<'s> Expr<'s> {
} }
Expr::Or(v) => Expr::And(v.into_iter().map(|e| Expr::Not(Box::new(e))).collect()) Expr::Or(v) => Expr::And(v.into_iter().map(|e| Expr::Not(Box::new(e))).collect())
.disjunctiveNormalForm2(mapping), .disjunctive_normal_form2(mapping),
}, },
Expr::And(v) => { Expr::And(v) => {
let mut v: Vec<_> = v let mut v: Vec<_> = v
.into_iter() .into_iter()
.map(|e| e.disjunctiveNormalForm2(mapping)) .map(|e| e.disjunctive_normal_form2(mapping))
.collect(); .collect();
let mut n = v.pop().unwrap(); let mut n = v.pop().unwrap();
@ -305,7 +304,7 @@ impl<'s> Expr<'s> {
Expr::Or(v) => { Expr::Or(v) => {
let mut n = NormalForm::new(); let mut n = NormalForm::new();
for e in v { for e in v {
let on = e.disjunctiveNormalForm2(mapping); let on = e.disjunctive_normal_form2(mapping);
for (s, _, _) in on.iter() { for (s, _, _) in on.iter() {
n.add_clause(s); n.add_clause(s);
} }
@ -316,8 +315,8 @@ impl<'s> Expr<'s> {
} }
} }
pub fn conjunctiveNormalForm(self) -> Self { pub fn conjunctive_normal_form(self) -> Self {
if let Expr::Or(v) = Expr::Not(Box::new(self)).disjunctiveNormalForm() { if let Expr::Or(v) = Expr::Not(Box::new(self)).disjunctive_normal_form() {
Expr::And( Expr::And(
v.into_iter() v.into_iter()
.map(|e| match e { .map(|e| match e {
@ -348,51 +347,37 @@ impl<'s> Expr<'s> {
} }
} }
pub fn to_dpll_cnf_normal_form(self) -> (NormalForm, Mapping<'s>) { pub fn cnf_normal_form(self) -> (NormalForm, Mapping<'s>) {
let mut mapping = Mapping::new(); let mut mapping = Mapping::new();
let mut cnf = Expr::Not(Box::new(self)).disjunctiveNormalForm2(&mut mapping); let mut cnf = Expr::Not(Box::new(self)).disjunctive_normal_form2(&mut mapping);
cnf.negate(); cnf.negate();
(cnf, mapping) (cnf, mapping)
} }
pub fn to_dpll_cnf(self) -> (Vec<Vec<Index>>, HashMap<&'s str, Index>) { pub fn cnf(self) -> (Vec<Vec<Index>>, Mapping<'s>) {
let mut map = HashMap::new(); let mut map = Mapping::new();
let mut cnf = Vec::new(); let mut cnf = Vec::new();
let v = if let Expr::And(v) = self.conjunctiveNormalForm() { let v = if let Expr::And(v) = self.conjunctive_normal_form() {
v v
} else { } else {
unreachable!() unreachable!()
}; };
let mut nextfree = 1;
for e in v { for e in v {
let s = match e { let s = match e {
Expr::Or(v) => { Expr::Or(v) => {
let mut s = Vec::new(); let mut s = Vec::new();
for l in v { for l in v {
if let Expr::Literal(l) = l { if let Expr::Literal(l) = l {
if let Some(&i) = map.get(&l) { s.push(map.forward(l));
s.push(i);
} else {
map.insert(l, nextfree);
s.push(nextfree);
nextfree += 1;
}
} else if let Expr::Not(n) = l { } else if let Expr::Not(n) = l {
if let Expr::Literal(l) = *n { if let Expr::Literal(l) = *n {
if let Some(&i) = map.get(&l) { s.push(-map.forward(l));
s.push(-i);
} else {
map.insert(l, nextfree);
s.push(-nextfree);
nextfree += 1;
}
} else { } else {
unreachable!() unreachable!()
} }
@ -401,28 +386,15 @@ impl<'s> Expr<'s> {
} }
} }
s.sort(); s.sort();
s.dedup();
s s
} }
Expr::Literal(l) => { Expr::Literal(l) => {
if let Some(&i) = map.get(&l) { vec![-map.forward(l)]
vec![-i]
} else {
map.insert(l, nextfree);
let i = nextfree;
nextfree += 1;
vec![-i]
}
} }
Expr::Not(n) => { Expr::Not(n) => {
if let Expr::Literal(l) = *n { if let Expr::Literal(l) = *n {
if let Some(&i) = map.get(&l) { vec![map.forward(l)]
vec![i]
} else {
map.insert(l, nextfree);
let i = nextfree;
nextfree += 1;
vec![i]
}
} else { } else {
unreachable!() unreachable!()
} }

View file

@ -1,88 +1,71 @@
use std::collections::HashMap; use clap::{Parser, ValueEnum};
use expr::Expr;
use clap::Parser;
use dpll::dpll;
use expr::{Expr, Tokanizer};
use mapping::Mapping;
use miette::{IntoDiagnostic, Result}; use miette::{IntoDiagnostic, Result};
use normal_form::NormalForm;
mod cdcl;
mod dpll; mod dpll;
mod dpll_normal_form; mod dpll_normal_form;
mod expr;
mod mapping; mod mapping;
mod normal_form; mod normal_form;
mod expr; #[derive(ValueEnum, Clone)]
enum Method {
DpllExpr,
Dpll,
Cdcl,
}
#[derive(Parser)] #[derive(Parser)]
struct Args { struct Args {
method: Method,
inputfile: std::path::PathBuf, inputfile: std::path::PathBuf,
} }
fn main() -> Result<()> { fn main() -> Result<()> {
let args = Args::parse(); let args = Args::parse();
let start = std::time::Instant::now();
let s = std::fs::read_to_string(args.inputfile).into_diagnostic()?; let s = std::fs::read_to_string(args.inputfile).into_diagnostic()?;
let e = Expr::parse(&s)?; let e = Expr::parse(&s)?;
println!("Expression parsed succesfully."); let elapsed = start.elapsed();
println!("Expression parsed succesfully in {elapsed:?}");
// dbg!(&e);
// dbg!(Expr::Not(Box::new(e.clone())).disjunctiveNormalForm());
let (cnf, map) = e.to_dpll_cnf_normal_form();
println!("Normal form created.");
cnf.stats();
let mut solution = Vec::new(); let mut solution = Vec::new();
let start = std::time::Instant::now(); let start = std::time::Instant::now();
dbg!(crate::dpll_normal_form::dpll(&cnf, &mut solution)); let (result, map) = match args.method {
Method::DpllExpr => {
let (cnf, map) = e.cnf();
(crate::dpll::dpll(&cnf, &mut solution), map)
}
Method::Dpll => {
let (cnf, map) = e.cnf_normal_form();
(crate::dpll_normal_form::dpll(&cnf, &mut solution), map)
}
Method::Cdcl => {
let (cnf, map) = e.cnf_normal_form();
(crate::cdcl::cdcl(&cnf, &mut solution), map)
}
};
let elapsed = start.elapsed(); let elapsed = start.elapsed();
println!("Time dpll: {elapsed:?}"); println!("Time: {elapsed:?}");
// dbg!(&solution); if result {
// dbg!(e.clone().conjunctiveNormalForm()); println!("Solution found:");
let mut s = Vec::new();
// let (cnf, map) = e.to_dpll_cnf(); for i in solution {
if i > 0 {
// dbg!(&cnf, &map); s.push((map.backward(i), true));
// println!("cnf clauses: {}", cnf.len()); } else {
s.push((map.backward(i.abs()), false));
// let mut solution = Vec::new(); }
}
// dpll(&cnf, &mut solution); s.sort();
for (s, b) in s {
// dbg!(solution); println!("{s}: {b}");
// let inv_map: HashMap<_, _> = map.into_iter().map(|(k, v)| (v, k)).collect();
// dbg!(&solution);
let mut s = Vec::new();
for i in solution {
if i > 0 {
s.push((map.backward(i), true));
} else {
s.push((map.backward(i.abs()), false));
} }
} }
s.sort();
for (s, b) in s {
println!("{s}: {b}");
}
// let mut nf = NormalForm::from_slices(&cnf);
// dbg!(&nf);
// nf.remove_literal(-1);
// dbg!(&nf);
// let mut s2 = Vec::new();
// dbg!(dpll_normal_form::dpll(&nf, &mut s2));
// dbg!(s2 == solution);
Ok(()) Ok(())
} }

View file

@ -1,5 +1,3 @@
use std::ops::Neg;
use crate::dpll::Index; use crate::dpll::Index;
#[derive(Debug, Clone)] #[derive(Debug, Clone)]