Browse Source

Merge branch 'master' of gitea:thajohns/cs451-project

master
Thomas Johnson 3 years ago
parent
commit
cf8b0453f9
  1. 1
      Cargo.toml
  2. 32
      src/clause.rs
  3. 75
      src/clause_gen.rs
  4. 2
      src/main.rs
  5. 23
      src/maxsat.rs

1
Cargo.toml

@ -8,3 +8,4 @@ edition = "2018"
[dependencies]
colored = "1.9.3"
rand = "0.7.3"

32
src/clause.rs

@ -406,17 +406,17 @@ macro_rules! assign_vars {
{
$var.assign(true);
assign_vars! { $($vars$( = $vals)?;)* } //$($vars = $vals;)* }
};
{$var:ident = 0; $($vars:ident$( = $vals:tt)?;)*} =>
{
$var.assign(false);
assign_vars! { $($vars$( = $vals)?;)* }
};
{$var:ident; $($vars:ident$( = $vals:tt)?;)*} =>
{
$var.unassign();
assign_vars! { $($vars$( = $vals)?;)* }
};
};
{$var:ident = 0; $($vars:ident$( = $vals:tt)?;)*} =>
{
$var.assign(false);
assign_vars! { $($vars$( = $vals)?;)* }
};
{$var:ident; $($vars:ident$( = $vals:tt)?;)*} =>
{
$var.unassign();
assign_vars! { $($vars$( = $vals)?;)* }
};
}
#[allow(unused_macros)]
@ -438,10 +438,10 @@ macro_rules! add_terms {
macro_rules! make_clause {
{ } => { Clause::new() };
( $($contents:tt)* ) => {{
let mut clause = $crate::clause::Clause::new();
add_terms!(clause $($contents)*);
clause
}};
let mut clause = $crate::clause::Clause::new();
add_terms!(clause $($contents)*);
clause
}};
}
#[cfg(test)]
@ -457,7 +457,7 @@ mod test {
y.get_name(),
z.get_name(),
w.get_name()
);
);
println!("x: {}, y: {}, z: {}, w: {}", x, y, z, w);
assign_vars! {
x = 1;

75
src/clause_gen.rs

@ -0,0 +1,75 @@
use crate::clause::*;
/*
* Produces a unique variable name from a given usize. The variable name is
* always lower case and will extend to a longer name should the number be
* larger than 25. For reference, 0 maps to 'a' and 26 maps to 'aa'.
*/
fn get_var_name(n: usize) -> String {
let ch = std::char::from_u32((n as u32) % 26 + 0x61).unwrap().to_string();
if n >= 26 {
get_var_name(n / 26) + &ch
} else {
ch
}
}
/*
* Generates a clause with [var_count] literals that are randomly negated.
*/
pub fn gen_clause(var_count: usize) -> Clause {
let mut vars : Vec<Literal> = (0..var_count)
.map(get_var_name)
.map(Variable::from_name)
.map(|v|
if rand::random() {
v.get_pos_literal()
} else {
v.get_neg_literal()
}
)
.collect();
let mut cl = Clause::new();
for _ in 0..var_count {
let idx : usize = rand::random::<usize>() % vars.len();
cl.push(vars.remove(idx));
}
cl
}
/*
* Generates a list of clauses that has [count] clauses that will have up to
* [max_vars] literals in them. No empty clauses are generated.
*/
pub fn gen_clause_list(count: usize, max_vars: usize) -> ClauseList {
let mut cls = ClauseList::new();
for _ in 0..count {
cls.push(gen_clause(rand::random::<usize>() % (max_vars) + 1));
}
cls
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn test_clause_gen() {
let test_var_short = get_var_name(1);
let test_var_long = get_var_name(27);
println!("{}, {}", test_var_short, test_var_long);
assert!(test_var_short == "b");
assert!(test_var_long == "bb");
let test_clause = gen_clause(10);
println!("{}", test_clause);
assert!(test_clause.len() == 10);
let test_clause_list = gen_clause_list(5, 4);
assert!(test_clause_list.len() == 5);
for cl in test_clause_list.iter() {
println!("{}", cl);
assert!(cl.len() <= 4 && cl.len() > 0);
}
}
}

2
src/main.rs

@ -6,5 +6,7 @@ pub mod clause;
/// I made this before I knew I didn't need it. :/
pub mod hash_wrapper;
mod messy_minsat;
mod maxsat;
mod clause_gen;
fn main() {}

23
src/maxsat.rs

@ -0,0 +1,23 @@
use crate::clause::*;
fn bfs_step(cs: &ClauseList, vs: &Vec<Variable>, n: usize) -> usize {
if n == vs.len() {
cs.iter().filter_map(|c| c.eval())
.map(|b| if b { 1 } else { 0 }).sum()
} else {
vs[n].assign(false);
let rf = bfs_step(cs, vs, n+1);
vs[n].assign(true);
let rt = bfs_step(cs, vs, n+1);
usize::max(rt, rf)
}
}
pub fn solve_by_bfs(cs: &ClauseList) -> usize {
let vars: Vec<Variable> = cs.get_vars().into_iter().collect();
bfs_step(cs, &vars, 0)
}
Loading…
Cancel
Save