Commit a0c50601 authored by Ranadeep Biswas's avatar Ranadeep Biswas
Browse files

Uses minisat lib

parent 1d6fd8ff
......@@ -6,6 +6,7 @@ authors = ["Ranadeep Biswas <ranadip.bswas@gmail.com>"]
[dependencies]
rand = "0.7.2"
clap = "2.33.0"
minisat = "0.4.4"
serde = "1.0.103"
serde_derive = "1.0.103"
serde_json = "1.0.44"
......
use std::collections::{HashMap, HashSet};
use std::fs;
use std::fs::{File, OpenOptions};
use std::default::Default;
use std::process::{Command, Stdio};
use std::path::PathBuf;
use std::io::BufRead;
use std::io::{BufReader, BufWriter};
use std::io::Write;
use minisat::{Bool, Solver};
#[derive(Hash, Ord, PartialOrd, Eq, PartialEq, Clone, Copy, Debug)]
pub enum Edge {
......@@ -44,28 +35,24 @@ impl CNF {
self.clauses.push(Vec::new());
}
fn write_to_file(&mut self, path: &PathBuf) {
let mut file = BufWriter::new(
OpenOptions::new()
.write(true)
.create(true)
.truncate(true)
.open(path)
.expect("couldn't create"),
);
writeln!(file, "p cnf {} {}", self.n_variable, self.clauses.len() - 1)
.expect("failed to write parameters");
for clause in self.clauses.drain(..).rev().skip(1) {
for (sign, literal) in clause {
fn add_to_solver(&mut self, solver: &mut Solver) -> HashMap<usize, Bool> {
let mut literal_map = HashMap::new();
for mut clause in self.clauses.drain(..).rev().skip(1) {
let solver_clause : Vec<_> = clause.drain(..).map(|(sign, literal)| {
let solver_lit = literal_map
.entry(literal)
.or_insert_with(|| solver.new_lit());
if sign {
write!(file, "{} ", literal).expect("failed to write cnf to file");
*solver_lit
} else {
write!(file, "-{} ", literal).expect("failed to write cnf to file");
!*solver_lit
}
}).collect();
solver.add_clause(solver_clause);
}
writeln!(file, "0").expect("failed to write cnf to file");
}
literal_map
}
}
......@@ -262,66 +249,19 @@ impl Sat {
self.add_clauses(&clauses);
}
pub fn solve(&mut self, path: &PathBuf) -> Option<Vec<(usize, usize)>> {
let inp_cnf = path.join("history.cnf");
let out_cnf = path.join("result.cnf");
self.cnf.write_to_file(&inp_cnf);
if let Ok(mut child) = Command::new("minisat")
.arg(&inp_cnf)
.arg(&out_cnf)
.stdout(Stdio::null())
.spawn()
{
child.wait().expect("failed to execute process");
} else {
panic!("failed to execute process")
}
fs::remove_file(inp_cnf).expect("couldn't delete input cnf");
// println!("status: {}", output.status);
// println!("stdout: {}", String::from_utf8_lossy(&output.stdout));
// println!("stderr: {}", String::from_utf8_lossy(&output.stderr));
let result = File::open(&out_cnf).expect("file couldn't open");
let reader = BufReader::new(&result);
pub fn solve(&mut self) -> Option<Vec<(usize, usize)>> {
let mut solver = minisat::Solver::new();
let lit_map = self.cnf.add_to_solver(&mut solver);
let mut lines = reader.lines().map(|l| l.unwrap());
let mut assignments = HashMap::new();
match lines.next() {
Some(ref e) if e.as_str() == "SAT" => {
for line in lines {
for var_st in line.split_whitespace() {
let var: isize = var_st.parse().unwrap();
if var != 0 {
assignments.insert(var.abs() as usize, var > 0);
}
}
}
}
Some(ref e) if e.as_str() == "UNSAT" => {
// println!("{:?}", e);
// for line in lines {
// println!("{}", line);
// }
}
_ => {
unreachable!();
}
}
if !assignments.is_empty() {
match solver.solve() {
Ok(m) => {
let edges: Vec<_> = self
.edge_variable
.iter()
.filter_map(|(&k, &v)| {
if k.0 == Edge::CO {
assert!(k.1 != k.2);
Some(if assignments[&v] {
Some(if m.value(&lit_map[&v]) {
(k.1, k.2)
} else {
(k.2, k.1)
......@@ -335,7 +275,8 @@ impl Sat {
// edges.sort_unstable();
// building co
let mut parents: HashMap<(usize, usize), HashSet<(usize, usize)>> = Default::default();
let mut parents: HashMap<(usize, usize), HashSet<(usize, usize)>> =
Default::default();
for e in &edges {
parents
.entry(e.1)
......@@ -364,8 +305,8 @@ impl Sat {
}
Some(lin)
} else {
None
}
Err(()) => None,
}
}
......
extern crate rand;
extern crate chrono;
extern crate minisat;
extern crate rayon;
pub mod consistency;
......
......@@ -424,7 +424,7 @@ impl Verifier {
_ => unreachable!(),
}
if sat_solver.solve(&self.dir).is_some() {
if sat_solver.solve().is_some() {
None
} else {
Some(self.consistency_model)
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment