use crate::cnf::{to_variable, Assignment};
use crate::dpll::solve_dpll;
use crate::expression::{self, Expression};
use std::sync::mpsc;
fn verify_assignment(expression: &Expression, assignment: &Assignment) -> bool {
for clause in expression.get_clauses() {
let mut satisfied = false;
for literal in clause.literals() {
let term = to_variable(*literal);
let sign = *literal > 0;
if assignment[&term] == sign {
satisfied = true;
break;
}
}
if !satisfied {
return false;
}
}
return true;
}
pub fn solve(expression: Expression, use_multiple_threads: bool, verify: bool) -> Option<Assignment> {
let mut expression_max_literals = expression.clone();
let mut expression_min_clause_len = expression.clone();
let (send_channel, recv_channel) = mpsc::channel();
let send_channel_copy = send_channel.clone();
std::thread::spawn(move || {
expression_max_literals.optimize();
expression_max_literals
.set_heuristic(expression::SolverHeuristic::MostLiteralOccurances);
let result = solve_dpll(&mut expression_max_literals);
let _ = send_channel.send(result);
});
if use_multiple_threads {
std::thread::spawn(move || {
expression_min_clause_len.optimize();
expression_min_clause_len
.set_heuristic(expression::SolverHeuristic::MinimizeClauseLength);
let result = solve_dpll(&mut expression_min_clause_len);
let _ = send_channel_copy.send(result);
});
}
let solution = recv_channel.recv().expect("Could not receive result from solver.");
if solution.is_some() && verify {
let assignment = solution.clone().unwrap();
if !verify_assignment(&expression, &assignment) {
panic!("Solution is invalid!");
}
}
return solution;
}
#[cfg(test)]
mod tests {
use super::*;
use crate::cnf::{Clause, CNF};
use crate::expression::Expression;
#[test]
fn test_verify_assignment() {
let mut expression = Expression::new();
let mut clause = Clause::new();
clause.insert_checked(1);
clause.insert_checked(-2);
expression.add_clause(clause);
let mut assignment = Assignment::new();
assignment.insert(1, true);
assignment.insert(2, false);
assert!(verify_assignment(&expression, &assignment));
}
#[test]
fn test_verify_assignment_unsatisfied() {
let mut expression = Expression::new();
let mut clause = Clause::new();
clause.insert_checked(1);
clause.insert_checked(2);
expression.add_clause(clause);
let mut assignment = Assignment::new();
assignment.insert(1, false);
assignment.insert(2, false);
assert!(!verify_assignment(&expression, &assignment));
}
#[test]
fn test_verify_assignment_unsatisfied_multiple_clauses() {
let mut expression = Expression::new();
let mut clause = Clause::new();
clause.insert_checked(1);
clause.insert_checked(2);
expression.add_clause(clause);
let mut clause = Clause::new();
clause.insert_checked(-3);
clause.insert_checked(-4);
expression.add_clause(clause);
let mut assignment = Assignment::new();
assignment.insert(1, false);
assignment.insert(2, false);
assignment.insert(3, true);
assignment.insert(4, true);
assert!(!verify_assignment(&expression, &assignment));
}
#[test]
fn test_verify_assignment_satisfied_multiple_clauses() {
let mut expression = Expression::new();
let mut clause = Clause::new();
clause.insert_checked(1);
clause.insert_checked(-2);
expression.add_clause(clause);
let mut clause = Clause::new();
clause.insert_checked(3);
clause.insert_checked(-4);
expression.add_clause(clause);
let mut assignment = Assignment::new();
assignment.insert(1, true);
assignment.insert(2, false);
assignment.insert(3, true);
assignment.insert(4, false);
assert!(verify_assignment(&expression, &assignment));
}
}