Browse Source

Started work on clauses API

clause_generator
Thomas Johnson 2 years ago
parent
commit
114734ec3c
  1. 1
      Cargo.toml
  2. 18
      recommended-pre-commit-unstable
  3. 0
      rustfmt.toml
  4. 249
      src/clause.rs
  5. 48
      src/hash_wrapper.rs
  6. 3
      src/main.rs

1
Cargo.toml

@ -7,3 +7,4 @@ edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
colored = "1.9.3"

18
recommended-pre-commit → recommended-pre-commit-unstable

@ -6,15 +6,17 @@ HAS_ISSUES=0
FIRST_FILE=1
for file in $(git diff --name-only --staged); do
FMT_RESULT="$(rustfmt --check $file 2>/dev/null || true)"
MODE_LINE="$(head -n1 $file || true)"
if [ "$FMT_RESULT" != "" -o "$MODE_LINE" != "// vim: ts=4 sw=4 et" ]; then
if [ $FIRST_FILE -eq 0 ]; then
echo -n ", "
if [ "${file: -3}" == ".rs" ]; then
FMT_RESULT="$(rustfmt --unstable-features --skip-children --check $file 2>/dev/null || true)"
MODE_LINE="$(head -n1 $file || true)"
if [ "$FMT_RESULT" != "" -o "$MODE_LINE" != "// vim: ts=4 sw=4 et" ]; then
if [ $FIRST_FILE -eq 0 ]; then
echo -n ", "
fi
echo -n "$file"
HAS_ISSUES=1
FIRST_FILE=0
fi
echo -n "$file"
HAS_ISSUES=1
FIRST_FILE=0
fi
done

0
rustfmt.toml

249
src/clause.rs

@ -1,5 +1,7 @@
// vim: ts=4 sw=4 et
use colored::{control::ShouldColorize, Colorize};
use core::fmt::{Display, Formatter};
use std::cell::RefCell;
use std::rc::Rc;
@ -13,6 +15,13 @@ struct VariableInner {
pub struct Variable(Rc<VariableInner>);
impl Variable {
pub fn from_name(name: String) -> Variable {
Variable(Rc::new(VariableInner {
name,
assignment: RefCell::new(None),
}))
}
pub fn get_name(&self) -> &String {
&self.0.name
}
@ -36,8 +45,51 @@ impl Variable {
}
}
pub fn get_pos_literal(&self) -> Literal { self.get_literal(false) }
pub fn get_neg_literal(&self) -> Literal { self.get_literal(true) }
pub fn get_pos_literal(&self) -> Literal {
self.get_literal(false)
}
pub fn get_neg_literal(&self) -> Literal {
self.get_literal(true)
}
fn get_uncolored_string(&self) -> String {
let should_color = ShouldColorize::from_env().should_colorize();
macro_rules! cd {
($($s:literal)?) => {
if should_color {
format!("{}", self.0.name)
} else {
format!(concat!($($s, )?"{}"), self.0.name)
}
}
}
match self.get_assignment() {
None => cd!(),
Some(true) => cd!("¹"),
Some(false) => cd!("⁰"),
}
}
}
impl Display for Variable {
fn fmt(&self, fmt: &mut Formatter) -> core::fmt::Result {
let should_color = ShouldColorize::from_env().should_colorize();
macro_rules! cd {
($($s:literal)?$(, $col:ident)?) => {
if should_color {
write!(fmt, "{}", self.0.name$(.$col())?)
} else {
write!(fmt, concat!($($s, )?"{}"), self.0.name)
}
}
}
match self.get_assignment() {
None => cd!(),
Some(true) => cd!("¹", bright_blue),
Some(false) => cd!("⁰", bright_red),
}
}
}
#[derive(Clone, Debug)]
@ -60,7 +112,198 @@ impl Literal {
}
}
impl Display for Literal {
fn fmt(&self, fmt: &mut Formatter) -> core::fmt::Result {
let should_color = ShouldColorize::from_env().should_colorize();
macro_rules! cd {
($($s:literal)?, $($n:literal)?, $($coln:ident, $colt:ident)?) => {
if should_color {
write!(fmt, "{}{}", {concat!($($n, )?"")}$(.$coln())?.bold(), self.var.get_uncolored_string()$(.$colt())?.bold())
} else {
write!(fmt, concat!($($s, )?$($n, )?"{}"), self.var)
}
}
}
macro_rules! nd {
($($s:literal)?$(, $coln:ident, $colt:ident)?) => {
if self.neg {
cd!($($s)?, "¬", $($coln, $colt)?)
} else {
cd!($($s)?, , $($coln, $colt)?)
}
}
}
match (self.get_assignment(), self.neg) {
(None, _) => nd!(),
(Some(true), true) => nd!("¹", bright_blue, bright_blue),
(Some(true), false) => nd!("¹", bright_cyan, bright_cyan),
(Some(false), true) => nd!("⁰", yellow, yellow),
(Some(false), false) => nd!("⁰", bright_red, bright_red),
}
}
}
#[derive(Clone, Debug)]
pub struct Clause {
pub literals: Vec<Literal>,
literals: Vec<Literal>,
}
impl Clause {
pub fn new() -> Clause {
Clause {
literals: Vec::new(),
}
}
pub fn push(&mut self, l: Literal) {
self.literals.push(l);
}
pub fn len(&self) -> usize {
self.literals.len()
}
pub fn iter(&self) -> impl Iterator<Item = &Literal> {
self.literals.iter()
}
pub fn eval(&self) -> Option<bool> {
self.literals.iter().fold(Some(false), |r, o| {
r.and_then(|b| o.get_assignment().map(|v| v | b))
})
}
}
impl core::ops::Index<usize> for Clause {
type Output = Literal;
fn index(&self, idx: usize) -> &Self::Output {
&self.literals[idx]
}
}
impl Display for Clause {
fn fmt(&self, fmt: &mut Formatter) -> core::fmt::Result {
if self.literals.len() == 0 {
write!(fmt, "⊥")
} else {
let mut iter = self.literals.iter();
write!(fmt, "{} ", iter.next().unwrap())?;
for lit in iter {
write!(fmt, " ∨ {}", lit)?;
}
Ok(())
}
}
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn clause_test() {
let x = Variable::from_name("x".into());
let y = Variable::from_name("y".into());
let z = Variable::from_name("z".into());
let w = Variable::from_name("w".into());
println!(
"names: {} {} {} {}",
x.get_name(),
y.get_name(),
z.get_name(),
w.get_name()
);
println!("x: {}, y: {}, z: {}, w: {}", x, y, z, w);
x.assign(true);
y.assign(false);
z.unassign();
println!("x: {}, y: {}, z: {}, w: {}", x, y, z, w);
assert_eq!(x.get_assignment(), Some(true));
assert_eq!(y.get_assignment(), Some(false));
assert_eq!(z.get_assignment(), None);
assert_eq!(w.get_assignment(), None);
let xl = x.get_literal(false);
let yl = y.get_literal(true);
let zl = z.get_pos_literal();
let wl = w.get_neg_literal();
println!("xl: {}, yl: {}, zl: {}, wl: {}", xl, yl, zl, wl);
assert_eq!(xl.get_assignment(), Some(true));
assert_eq!(yl.get_assignment(), Some(true));
assert_eq!(zl.get_assignment(), None);
assert_eq!(wl.get_assignment(), None);
xl.assign(false);
yl.assign(true);
zl.assign(true);
wl.assign(false);
println!("assigned literals");
println!("x: {}, y: {}, z: {}, w: {}", x, y, z, w);
assert_eq!(x.get_assignment(), Some(false));
assert_eq!(y.get_assignment(), Some(false));
assert_eq!(z.get_assignment(), Some(true));
assert_eq!(w.get_assignment(), Some(true));
println!("xl: {}, yl: {}, zl: {}, wl: {}", xl, yl, zl, wl);
assert_eq!(xl.get_assignment(), Some(false));
assert_eq!(yl.get_assignment(), Some(true));
assert_eq!(zl.get_assignment(), Some(true));
assert_eq!(wl.get_assignment(), Some(false));
xl.unassign();
yl.unassign();
zl.unassign();
wl.unassign();
println!("unassigned literals");
println!("x: {}, y: {}, z: {}, w: {}", x, y, z, w);
assert_eq!(x.get_assignment(), None);
assert_eq!(y.get_assignment(), None);
assert_eq!(z.get_assignment(), None);
assert_eq!(w.get_assignment(), None);
println!("xl: {}, yl: {}, zl: {}, wl: {}", xl, yl, zl, wl);
assert_eq!(xl.get_assignment(), None);
assert_eq!(yl.get_assignment(), None);
assert_eq!(zl.get_assignment(), None);
assert_eq!(wl.get_assignment(), None);
let mut clause = Clause::new();
println!("clause: {}", clause);
println!("value: {:?}", clause.eval());
assert_eq!(clause.eval(), Some(false));
clause.push(xl);
println!("clause: {}", clause);
println!("value: {:?}", clause.eval());
assert_eq!(clause.eval(), None);
x.assign(true);
println!("clause: {}", clause);
println!("value: {:?}", clause.eval());
assert_eq!(clause.eval(), Some(true));
x.assign(false);
println!("clause: {}", clause);
println!("value: {:?}", clause.eval());
assert_eq!(clause.eval(), Some(false));
clause.push(yl);
println!("clause: {}", clause);
println!("value: {:?}", clause.eval());
assert_eq!(clause.eval(), None);
y.assign(true);
println!("clause: {}", clause);
println!("value: {:?}", clause.eval());
assert_eq!(clause.eval(), Some(false));
clause.push(zl);
clause.push(wl);
println!("clause: {}", clause);
println!("value: {:?}", clause.eval());
assert_eq!(clause.eval(), None);
z.assign(false);
w.assign(true);
println!("clause: {}", clause);
println!("value: {:?}", clause.eval());
assert_eq!(clause.eval(), Some(false));
x.assign(true);
println!("clause: {}", clause);
println!("value: {:?}", clause.eval());
assert_eq!(clause.eval(), Some(true));
y.assign(false);
println!("clause: {}", clause);
println!("value: {:?}", clause.eval());
assert_eq!(clause.eval(), Some(true));
}
}

48
src/hash_wrapper.rs

@ -5,43 +5,49 @@ use core::ops::{Deref, DerefMut};
// A type for manipulating how something is hashed.
pub struct HashWrapper<T, U, F>(T, F) where
F: Fn(&T) -> U,
U: Hash;
impl<T, U, F> HashWrapper<T, U, F> where
F: Fn(&T) -> U,
U: Hash {
pub struct HashWrapper<T, U, F>(T, F)
where
F: Fn(&T) -> U,
U: Hash;
impl<T, U, F> HashWrapper<T, U, F>
where
F: Fn(&T) -> U,
U: Hash,
{
pub fn into_innner(self) -> T {
self.0
}
}
impl<T, U, F> Hash for HashWrapper<T, U, F> where
F: Fn(&T) -> U,
U: Hash {
impl<T, U, F> Hash for HashWrapper<T, U, F>
where
F: Fn(&T) -> U,
U: Hash,
{
fn hash<H: Hasher>(&self, state: &mut H) {
self.1(&self.0).hash(state);
}
}
impl<T, U, F> Deref for HashWrapper<T, U, F> where
F: Fn(&T) -> U,
U: Hash {
impl<T, U, F> Deref for HashWrapper<T, U, F>
where
F: Fn(&T) -> U,
U: Hash,
{
type Target = T;
fn deref(&self) -> &T
{
fn deref(&self) -> &T {
&self.0
}
}
impl<T, U, F> DerefMut for HashWrapper<T, U, F> where
F: Fn(&T) -> U,
U: Hash {
fn deref_mut(&mut self) -> &mut T
{
impl<T, U, F> DerefMut for HashWrapper<T, U, F>
where
F: Fn(&T) -> U,
U: Hash,
{
fn deref_mut(&mut self) -> &mut T {
&mut self.0
}
}

3
src/main.rs

@ -3,5 +3,4 @@
pub mod clause;
pub mod hash_wrapper;
fn main() {
}
fn main() {}
Loading…
Cancel
Save