Lucas Stadler лет назад: 10
Родитель
Сommit
4fdf121d23
1 измененных файлов с 12 добавлено и 10 удалено
  1. 12 10
      rust/solve/src/dpll.rs

+ 12 - 10
rust/solve/src/dpll.rs

@ -128,16 +128,18 @@ fn test_is_clause_unit() {
128 128
}
129 129
130 130
pub fn dpll(clauses: Vec<Clause>) -> Option<BoundVars> {
131
    fn dpll_inner(stack: &mut Vec<(Var, BoundVars)>, vars: &mut BoundVars, clauses: Vec<Clause>) -> Option<BoundVars> {
131
    let stack: &mut Vec<(Var, BoundVars)> = &mut Vec::new();
132
    let mut vars = &mut empty_vars();
133
    
134
    loop {
132 135
        if clauses.iter().all(|c| is_clause_satisfied(&vars, c.clone())) { // all clauses satisfied, success
133
            Some(vars.clone())
136
            return Some(vars.clone())
134 137
        } else if clauses.iter().any(|c| is_clause_conflict(&vars, c.clone())) { // a conflict exists, backtrack
135 138
            match stack.pop() {
136
                None => None, // nothing to backtrack, no solution found
139
                None => return None, // nothing to backtrack, no solution found
137 140
                Some((v, b)) => {
138
                    let bv = &mut b.clone();
139
                    bv.insert(v);
140
                    dpll_inner(stack, bv, clauses)
141
                    vars.clone_from(&b);
142
                    vars.insert(v);
141 143
                }
142 144
            }
143 145
        } else if clauses.iter().any(|c| is_clause_unit(&vars, c.clone())) { // a unit clause exists, propagate
@ -145,7 +147,6 @@ pub fn dpll(clauses: Vec<Clause>) -> Option<BoundVars> {
145 147
            let clause = cs.iter().find(|&c| is_clause_unit(&vars, c.clone())).unwrap();
146 148
            let unknown = *clause.iter().find(|&v| is_unknown(&vars, *v)).unwrap();
147 149
            vars.insert(unknown);
148
            dpll_inner(stack, vars, clauses)
149 150
        } else { // none of the above, decide (guess) an unknown variable
150 151
            let mut unknown: Var = 0;
151 152
            for c in clauses.clone() {
@ -155,15 +156,16 @@ pub fn dpll(clauses: Vec<Clause>) -> Option<BoundVars> {
155 156
                        break;
156 157
                    }
157 158
                }
159
                
160
                if unknown != 0 {
161
                    break;
162
                }
158 163
            }
159 164
            assert!(unknown != 0);
160 165
            stack.push((unknown, vars.clone()));
161 166
            vars.insert(-unknown);
162
            dpll_inner(stack, vars, clauses)
163 167
        }
164 168
    }
165
166
    dpll_inner(&mut Vec::new(), &mut empty_vars(), clauses)
167 169
}
168 170
169 171
#[test]