Skip to content

Commit 1fa8395

Browse files
committed
Added maplesat
1 parent 2ca5040 commit 1fa8395

File tree

11 files changed

+292
-26
lines changed

11 files changed

+292
-26
lines changed

.gitmodules

+6-6
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,12 @@
44
[submodule "c/minisat-c-bindings"]
55
path = c/minisat-c-bindings
66
url = https://github.com/niklasso/minisat-c-bindings.git
7-
# [submodule "c/manysat"]
8-
# path = c/manysat
9-
# url = https://github.com/rohitjha/manysat.git
10-
[submodule "c/glucose"]
11-
path = c/glucose
12-
url = https://github.com/QuentinJanuel/glucose.git
7+
[submodule "c/maplesat"]
8+
path = c/maplesat
9+
url = https://github.com/QuentinJanuel/maplesat
1310
[submodule "c/manysat"]
1411
path = c/manysat
1512
url = https://github.com/QuentinJanuel/manysat
13+
[submodule "c/glucose"]
14+
path = c/glucose
15+
url = https://github.com/QuentinJanuel/glucose.git

README.md

+1
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ There are two types of solvers:
1111
### External
1212
- Minisat
1313
- Manysat
14+
- Maplesat
1415
- Glucose
1516
### Internal
1617
- DPLL

build.rs

+37-20
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,29 @@ fn download(url: &str, to: &str) {
2424
.expect(&format!("Failed to download {}", to));
2525
}
2626

27+
fn add_pthread(includes: &mut Vec<&str>) {
28+
if cfg!(windows) {
29+
includes.push("c/pthread-win32/include");
30+
let arch = if cfg!(target_arch = "x86_64") {
31+
"x64"
32+
} else if cfg!(target_arch = "x86") {
33+
"x86"
34+
} else {
35+
panic!("Unsupported architecture");
36+
};
37+
println!(
38+
"cargo:rustc-link-search=native={}",
39+
Path::new(env!("CARGO_MANIFEST_DIR"))
40+
.join("c")
41+
.join("pthread-win32")
42+
.join("lib")
43+
.join(arch)
44+
.display(),
45+
);
46+
println!("cargo:rustc-link-lib=pthreadVC3");
47+
}
48+
}
49+
2750
// fn make_bindings(name: &str) {
2851
// println!("cargo:rerun-if-changed=src/solver/{}/bindings.rs", name);
2952
// bindgen::Builder::default()
@@ -67,31 +90,24 @@ fn main() {
6790
.file("c/manysat-c-bindings/manysat.cc")
6891
.flag_if_supported("-fpermissive")
6992
.compile("manysat");
93+
// Maplesat
94+
cc::Build::new()
95+
.warnings(false)
96+
.cpp(true)
97+
.include("c/maplesat")
98+
.include("c/lib")
99+
.file("c/maplesat/core/Solver.cc")
100+
.file("c/maplesat/simp/SimpSolver.cc")
101+
.file("c/maplesat/utils/System.cc")
102+
.file("c/maplesat-c-bindings/maplesat.cc")
103+
.flag_if_supported("-fpermissive")
104+
.compile("maplesat");
70105
// Glucose
71106
let mut includes = vec![
72107
"c/lib",
73108
"c/glucose",
74109
];
75-
if cfg!(windows) {
76-
includes.push("c/pthread-win32/include");
77-
let arch = if cfg!(target_arch = "x86_64") {
78-
"x64"
79-
} else if cfg!(target_arch = "x86") {
80-
"x86"
81-
} else {
82-
panic!("Unsupported architecture");
83-
};
84-
println!(
85-
"cargo:rustc-link-search=native={}",
86-
Path::new(env!("CARGO_MANIFEST_DIR"))
87-
.join("c")
88-
.join("pthread-win32")
89-
.join("lib")
90-
.join(arch)
91-
.display(),
92-
);
93-
println!("cargo:rustc-link-lib=pthreadVC3");
94-
}
110+
add_pthread(&mut includes);
95111
cc::Build::new()
96112
.warnings(false)
97113
.cpp(true)
@@ -111,5 +127,6 @@ fn main() {
111127
// Bindings
112128
// make_bindings("minisat");
113129
// make_bindings("manysat");
130+
// make_bindings("maplesat");
114131
// make_bindings("glucose");
115132
}

c/maplesat

Submodule maplesat added at 564c8ad

c/maplesat-c-bindings/maplesat.cc

+61
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
#include <iostream>
2+
#include "simp/SimpSolver.h"
3+
4+
struct maplesat_solver_t : public Maplesat::Solver {
5+
Maplesat::vec<Maplesat::Lit> clause;
6+
};
7+
8+
extern "C" {
9+
10+
#include "maplesat.h"
11+
12+
maplesat_solver* maplesat_new() {
13+
return new maplesat_solver_t();
14+
}
15+
16+
void maplesat_delete(maplesat_solver* s) {
17+
delete s;
18+
}
19+
20+
void maplesat_add_clause_begin(maplesat_solver* s) {
21+
s->clause.clear();
22+
}
23+
24+
void maplesat_add_clause_add_lit(maplesat_solver* s, maplesat_lit p) {
25+
s->clause.push(Maplesat::toLit(p));
26+
}
27+
28+
maplesat_bool maplesat_add_clause_commit(maplesat_solver* s) {
29+
return s->addClause(s->clause);
30+
}
31+
32+
maplesat_lit maplesat_new_lit(maplesat_solver *s) {
33+
return Maplesat::toInt(Maplesat::mkLit(s->newVar()));
34+
}
35+
36+
maplesat_lit maplesat_make_lit(maplesat_var x) {
37+
return Maplesat::toInt(Maplesat::mkLit(x));
38+
}
39+
40+
maplesat_lit maplesat_negate_lit(maplesat_lit p) {
41+
return Maplesat::toInt(~Maplesat::toLit(p));
42+
}
43+
44+
maplesat_var maplesat_lit_to_var(maplesat_lit p) {
45+
return Maplesat::var(Maplesat::toLit(p));
46+
}
47+
48+
maplesat_bool maplesat_solve(maplesat_solver* s) {
49+
return s->solve();
50+
}
51+
52+
maplesat_lbool maplesat_model_value_var(maplesat_solver* s, maplesat_var x) {
53+
Maplesat::lbool b = s->modelValue(x);
54+
if (b == Maplesat::lbool((uint8_t)0))
55+
return maplesat_ltrue;
56+
else if (b == Maplesat::lbool((uint8_t)1))
57+
return maplesat_lfalse;
58+
return maplesat_lundef;
59+
}
60+
61+
}

c/maplesat-c-bindings/maplesat.h

+26
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
#ifndef __BINDINGS__
2+
#define __BINDINGS__
3+
4+
typedef struct maplesat_solver_t maplesat_solver;
5+
typedef int maplesat_bool;
6+
typedef int maplesat_lbool;
7+
typedef int maplesat_var;
8+
typedef int maplesat_lit;
9+
10+
extern const maplesat_lbool maplesat_ltrue = 1;
11+
extern const maplesat_lbool maplesat_lfalse = 0;
12+
extern const maplesat_lbool maplesat_lundef = -1;
13+
14+
maplesat_solver* maplesat_new();
15+
void maplesat_delete(maplesat_solver* s);
16+
void maplesat_add_clause_begin(maplesat_solver* s);
17+
void maplesat_add_clause_add_lit(maplesat_solver* s, maplesat_lit p);
18+
maplesat_bool maplesat_add_clause_commit(maplesat_solver* s);
19+
maplesat_lit maplesat_new_lit(maplesat_solver* s);
20+
maplesat_lit maplesat_make_lit(maplesat_var x);
21+
maplesat_lit maplesat_negate_lit(maplesat_lit p);
22+
maplesat_var maplesat_lit_to_var(maplesat_lit p);
23+
maplesat_bool maplesat_solve(maplesat_solver* s);
24+
maplesat_lbool maplesat_model_value_var(maplesat_solver* s, maplesat_var x);
25+
26+
#endif

c/wrappers/maplesat-wrapper.h

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
#include "maplesat.h"

src/solver/maplesat/bindings.rs

+48
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
/* automatically generated by rust-bindgen 0.59.2 */
2+
3+
#[repr(C)]
4+
#[derive(Debug, Copy, Clone)]
5+
pub struct maplesat_solver_t {
6+
_unused: [u8; 0],
7+
}
8+
pub type maplesat_solver = maplesat_solver_t;
9+
pub type maplesat_bool = ::std::os::raw::c_int;
10+
pub type maplesat_lbool = ::std::os::raw::c_int;
11+
pub type maplesat_var = ::std::os::raw::c_int;
12+
pub type maplesat_lit = ::std::os::raw::c_int;
13+
pub const maplesat_ltrue: maplesat_lbool = 1;
14+
pub const maplesat_lfalse: maplesat_lbool = 0;
15+
pub const maplesat_lundef: maplesat_lbool = -1;
16+
extern "C" {
17+
pub fn maplesat_new() -> *mut maplesat_solver;
18+
}
19+
extern "C" {
20+
pub fn maplesat_delete(s: *mut maplesat_solver);
21+
}
22+
extern "C" {
23+
pub fn maplesat_add_clause_begin(s: *mut maplesat_solver);
24+
}
25+
extern "C" {
26+
pub fn maplesat_add_clause_add_lit(s: *mut maplesat_solver, p: maplesat_lit);
27+
}
28+
extern "C" {
29+
pub fn maplesat_add_clause_commit(s: *mut maplesat_solver) -> maplesat_bool;
30+
}
31+
extern "C" {
32+
pub fn maplesat_new_lit(s: *mut maplesat_solver) -> maplesat_lit;
33+
}
34+
extern "C" {
35+
pub fn maplesat_make_lit(x: maplesat_var) -> maplesat_lit;
36+
}
37+
extern "C" {
38+
pub fn maplesat_negate_lit(p: maplesat_lit) -> maplesat_lit;
39+
}
40+
extern "C" {
41+
pub fn maplesat_lit_to_var(p: maplesat_lit) -> maplesat_var;
42+
}
43+
extern "C" {
44+
pub fn maplesat_solve(s: *mut maplesat_solver) -> maplesat_bool;
45+
}
46+
extern "C" {
47+
pub fn maplesat_model_value_var(s: *mut maplesat_solver, x: maplesat_var) -> maplesat_lbool;
48+
}

src/solver/maplesat/mod.rs

+108
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
mod bindings {
2+
#![allow(
3+
unused,
4+
non_upper_case_globals,
5+
non_camel_case_types,
6+
non_snake_case,
7+
)]
8+
include!("./bindings.rs");
9+
}
10+
11+
use crate::{
12+
cnf::{
13+
CNF,
14+
Lit,
15+
Var,
16+
},
17+
solver::{
18+
Solver,
19+
Model,
20+
},
21+
};
22+
use std::collections::HashMap;
23+
use super::config::Config;
24+
25+
/// The Maplesat solver
26+
pub struct Maplesat {
27+
n_threads: u32,
28+
clause_limit: u32,
29+
}
30+
31+
impl Maplesat {
32+
pub fn new() -> Self {
33+
Self {
34+
n_threads: 4,
35+
clause_limit: 10,
36+
}
37+
}
38+
pub fn set_n_threads(&mut self, n_threads: u32) {
39+
self.n_threads = n_threads;
40+
}
41+
pub fn set_clause_limit(&mut self, clause_limit: u32) {
42+
self.clause_limit = clause_limit;
43+
}
44+
}
45+
46+
impl Solver for Maplesat {
47+
fn solve_with_config(
48+
&self,
49+
cnf: &CNF,
50+
config: &Config,
51+
) -> Option<Model> {
52+
// Uses the C bindings to create a maplesat solver,
53+
// fill it with the CNF, and solve the CNF
54+
unsafe {
55+
let ptr = bindings::maplesat_new();
56+
let mut m_vars: HashMap<Var, i32> = HashMap::new();
57+
for clause in cnf.get_clauses() {
58+
if config.get_kill() { break; }
59+
bindings::maplesat_add_clause_begin(ptr);
60+
for lit in clause.get_lits() {
61+
let m_var = match m_vars.get(&lit.get_var()) {
62+
Some(m_var) => *m_var,
63+
None => {
64+
let m_lit = bindings::maplesat_new_lit(ptr);
65+
let m_var = bindings::maplesat_lit_to_var(m_lit);
66+
m_vars.insert(lit.get_var(), m_var);
67+
m_var
68+
},
69+
};
70+
let mut m_lit = bindings::maplesat_make_lit(m_var);
71+
if !lit.get_sign() {
72+
m_lit = bindings::maplesat_negate_lit(m_lit);
73+
}
74+
bindings::maplesat_add_clause_add_lit(ptr, m_lit);
75+
}
76+
if bindings::maplesat_add_clause_commit(ptr) == 0 {
77+
return None;
78+
}
79+
}
80+
let sat = if config.get_kill() {
81+
false
82+
} else {
83+
bindings::maplesat_solve(ptr) != 0
84+
};
85+
let model = if sat {
86+
let mut model = Model::new();
87+
for (var, m_var) in m_vars {
88+
let lbool = bindings::maplesat_model_value_var(
89+
ptr,
90+
m_var,
91+
);
92+
if lbool == bindings::maplesat_ltrue {
93+
model.add(Lit::pos(var));
94+
} else if lbool == bindings::maplesat_lfalse {
95+
model.add(Lit::neg(var));
96+
} else {
97+
unreachable!()
98+
}
99+
}
100+
Some(model)
101+
} else {
102+
None
103+
};
104+
bindings::maplesat_delete(ptr);
105+
model
106+
}
107+
}
108+
}

src/solver/mod.rs

+1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ mod model;
22
pub mod dpll;
33
pub mod minisat;
44
pub mod manysat;
5+
pub mod maplesat;
56
pub mod glucose;
67
#[macro_use]
78
pub mod portfolio;

src/tests/mod.rs

+2
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ use crate::{
44
dpll::DPLL,
55
minisat::Minisat,
66
manysat::Manysat,
7+
maplesat::Maplesat,
78
glucose::Glucose,
89
},
910
};
@@ -27,6 +28,7 @@ fn test_solvers() {
2728
test_solver(DPLL::new());
2829
test_solver(Minisat::new());
2930
test_solver(Manysat::new());
31+
test_solver(Maplesat::new());
3032
test_solver(portfolio![
3133
DPLL::new(),
3234
Minisat::new(),

0 commit comments

Comments
 (0)