Clean up and preperations for cdcl
This commit is contained in:
parent
9d9f75dd20
commit
830a3387b0
6 changed files with 93 additions and 122 deletions
21
src/cdcl.rs
Normal file
21
src/cdcl.rs
Normal 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,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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};
|
||||||
|
|
||||||
|
|
|
||||||
84
src/expr.rs
84
src/expr.rs
|
|
@ -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!()
|
||||||
}
|
}
|
||||||
|
|
|
||||||
103
src/main.rs
103
src/main.rs
|
|
@ -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(())
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,3 @@
|
||||||
use std::ops::Neg;
|
|
||||||
|
|
||||||
use crate::dpll::Index;
|
use crate::dpll::Index;
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue