Progress with cdcl
This commit is contained in:
parent
cdb1e893ab
commit
63b1350b3b
1 changed files with 102 additions and 33 deletions
135
src/cdcl.rs
135
src/cdcl.rs
|
|
@ -10,6 +10,13 @@ enum StateItem {
|
||||||
Unknown,
|
Unknown,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy)]
|
||||||
|
enum ClauseState {
|
||||||
|
Satisfied,
|
||||||
|
UnitPropagate(Index),
|
||||||
|
Unknown,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
struct State {
|
struct State {
|
||||||
map: Vec<StateItem>,
|
map: Vec<StateItem>,
|
||||||
|
|
@ -36,12 +43,79 @@ impl State {
|
||||||
self.set_literal(l);
|
self.set_literal(l);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn add_literal_propagate(&mut self, l: Index, cnf: &NormalForm) -> Result<(), Vec<Index>> {
|
fn add_literal_propagate(
|
||||||
|
&mut self,
|
||||||
|
l: Index,
|
||||||
|
source_slice: &[Index],
|
||||||
|
cnf: &NormalForm,
|
||||||
|
) -> Result<(), Vec<Index>> {
|
||||||
|
for &i in source_slice.iter().filter(|&&i| i != l) {
|
||||||
|
self.graph.push((i, l));
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(NormalFormIteratorItem {
|
||||||
|
slice,
|
||||||
|
len: _,
|
||||||
|
index: _,
|
||||||
|
}) = cnf.iter().find(
|
||||||
|
|&NormalFormIteratorItem {
|
||||||
|
slice,
|
||||||
|
len: _,
|
||||||
|
index: _,
|
||||||
|
}| {
|
||||||
|
match self.get_clause_state(slice) {
|
||||||
|
ClauseState::UnitPropagate(other) => other == -l,
|
||||||
|
_ => false,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
) {
|
||||||
|
let mut conflict: Vec<_> = source_slice
|
||||||
|
.iter()
|
||||||
|
.copied()
|
||||||
|
.filter(|&i| i != l)
|
||||||
|
.chain(slice.iter().copied().filter(|&i| i != -l))
|
||||||
|
.collect();
|
||||||
|
conflict.sort();
|
||||||
|
conflict.dedup();
|
||||||
|
|
||||||
|
return Err(conflict);
|
||||||
|
}
|
||||||
|
|
||||||
self.set_literal(l);
|
self.set_literal(l);
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn get_clause_state(&self, s: &[Index]) -> ClauseState {
|
||||||
|
let mut unknown_literal = None;
|
||||||
|
for &l in s {
|
||||||
|
match self.get_literal(l) {
|
||||||
|
StateItem::True => {
|
||||||
|
if l > 0 {
|
||||||
|
return ClauseState::Satisfied;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
StateItem::False => {
|
||||||
|
if l < 0 {
|
||||||
|
return ClauseState::Satisfied;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
StateItem::Unknown => {
|
||||||
|
if unknown_literal.is_some() {
|
||||||
|
return ClauseState::Unknown;
|
||||||
|
} else {
|
||||||
|
unknown_literal = Some(l);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
match unknown_literal {
|
||||||
|
Some(l) => ClauseState::UnitPropagate(l),
|
||||||
|
None => panic!("Fully false clause."),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn get_literal(&self, l: Index) -> StateItem {
|
fn get_literal(&self, l: Index) -> StateItem {
|
||||||
self.map[l.unsigned_abs() as usize - 1]
|
self.map[l.unsigned_abs() as usize - 1]
|
||||||
}
|
}
|
||||||
|
|
@ -84,28 +158,25 @@ impl State {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn unit_propagate(cnf: &NormalForm, state: &mut State) -> Result<(), Vec<Index>> {
|
fn unit_propagate(cnf: &NormalForm, state: &mut State) -> Result<(), Vec<Index>> {
|
||||||
if let Some(nfii) = cnf.iter().find(
|
if let Some(NormalFormIteratorItem {
|
||||||
|
slice,
|
||||||
|
len: _,
|
||||||
|
index: _,
|
||||||
|
}) = cnf.iter().find(
|
||||||
|NormalFormIteratorItem {
|
|NormalFormIteratorItem {
|
||||||
slice,
|
slice,
|
||||||
len: _,
|
len: _,
|
||||||
index: _,
|
index: _,
|
||||||
}| {
|
}| { matches!(state.get_clause_state(slice), ClauseState::UnitPropagate(_)) },
|
||||||
slice
|
|
||||||
.iter()
|
|
||||||
.filter(|&&l| state.is_unknown_literal(l))
|
|
||||||
.count()
|
|
||||||
== 1
|
|
||||||
},
|
|
||||||
) {
|
) {
|
||||||
let i = nfii
|
let i = slice
|
||||||
.slice
|
|
||||||
.iter()
|
.iter()
|
||||||
.position(|&i| state.is_unknown_literal(i))
|
.position(|&i| state.is_unknown_literal(i))
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
let l = nfii.slice[i];
|
let l = slice[i];
|
||||||
|
|
||||||
state.add_literal_propagate(l, cnf)?;
|
state.add_literal_propagate(l, slice, cnf)?;
|
||||||
|
|
||||||
unit_propagate(cnf, state)
|
unit_propagate(cnf, state)
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -116,36 +187,34 @@ fn unit_propagate(cnf: &NormalForm, state: &mut State) -> Result<(), Vec<Index>>
|
||||||
fn cdcl_internal(cnf: &mut NormalForm, mut state: State) -> Result<State, Vec<Index>> {
|
fn cdcl_internal(cnf: &mut NormalForm, mut state: State) -> Result<State, Vec<Index>> {
|
||||||
unit_propagate(cnf, &mut state)?;
|
unit_propagate(cnf, &mut state)?;
|
||||||
|
|
||||||
dbg!(&state);
|
let l = match state.get_arbitrary_literal() {
|
||||||
|
Some(l) => l,
|
||||||
if state.is_complete() {
|
None => return Ok(state),
|
||||||
return Ok(state);
|
};
|
||||||
}
|
|
||||||
|
|
||||||
let l = state.get_arbitrary_literal().unwrap();
|
|
||||||
|
|
||||||
let mut state_clone = state.clone();
|
let mut state_clone = state.clone();
|
||||||
state_clone.add_literal_arbitrary(l);
|
state_clone.add_literal_arbitrary(l);
|
||||||
|
|
||||||
match cdcl_internal(cnf, state_clone) {
|
match cdcl_internal(cnf, state_clone) {
|
||||||
Ok(_) => todo!(),
|
Ok(s) => Ok(s),
|
||||||
Err(_) => todo!(),
|
Err(c) => {
|
||||||
};
|
let count_unknown_literals =
|
||||||
|
c.iter().filter(|&&i| !state.is_unknown_literal(i)).count();
|
||||||
|
|
||||||
let mut state_clone = state.clone();
|
if count_unknown_literals >= 2 || (count_unknown_literals == c.len()) {
|
||||||
state_clone.add_literal_arbitrary(-l);
|
cnf.add_clause(&c);
|
||||||
|
|
||||||
match cdcl_internal(cnf, state_clone) {
|
cdcl_internal(cnf, state)
|
||||||
Ok(_) => todo!(),
|
} else {
|
||||||
Err(_) => todo!(),
|
Err(c)
|
||||||
};
|
}
|
||||||
|
}
|
||||||
Ok(state)
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn cdcl(mut cnf: &mut NormalForm) -> Option<Vec<Index>> {
|
pub fn cdcl(cnf: &mut NormalForm) -> Option<Vec<Index>> {
|
||||||
let num_literals = cnf.get_num_literals();
|
let num_literals = cnf.get_num_literals();
|
||||||
match cdcl_internal(&mut cnf, State::new(num_literals)) {
|
match cdcl_internal(cnf, State::new(num_literals)) {
|
||||||
Ok(state) => {
|
Ok(state) => {
|
||||||
if state.is_complete() {
|
if state.is_complete() {
|
||||||
Some(state.get_solution())
|
Some(state.get_solution())
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue