1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
use std::fmt;
use std::hash::{Hash,Hasher};


#[derive(Eq, PartialEq, Ord, PartialOrd, Clone)]
pub struct Proposition {
    pub name: String,
    pub negation: bool,
}

impl fmt::Debug for Proposition {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "{}P:{}", if self.negation {"¬"} else {""}, self.name)
    }
}

impl Hash for Proposition {
    fn hash<H>(&self, state: &mut H) where H: Hasher {
        self.negation.hash(state);
        self.name.hash(state);
    }
}

impl Proposition {
    pub fn new(name: String, negation: bool) -> Proposition {
        Proposition {name, negation}
    }

    pub fn from_str(name: &'static str) -> Proposition {
        Proposition {name: String::from(name), negation: false}
    }

    pub fn negate(&self) -> Proposition {
        Proposition { name: self.name.clone(), negation: !self.negation }
    }

    pub fn is_negation(&self, prop: &Proposition) -> bool {
        prop.name == self.name && prop.negation == !self.negation
    }
}

#[cfg(test)]
mod proposition_test {
    use super::*;

    #[test]
    fn propositions_can_be_negated() {
        // Sanity check
        assert_eq!(Proposition::from_str("test"), Proposition::from_str("test"));
        let p1 = Proposition::from_str("test");

        assert!(false == p1.negation);
        assert!(true == Proposition::from_str("test").negate().negation);

        let p2 = Proposition::from_str("test").negate();

        assert!(
            p2.is_negation(&p1),
            format!("{:?} is not a negation of {:?}", p1, p2)
        );

        assert!(p1.is_negation(&p2));
    }

    #[test]
    fn proposition_hashing_works() {
        let set = hashset!{Proposition::from_str("caffeinated")};
        assert!(set.contains(&Proposition::from_str("caffeinated")));

        let set = hashset!{Proposition::from_str("caffeinated").negate()};
        assert!(set.contains(&Proposition::from_str("caffeinated").negate()));

        let set = hashset!{Proposition::from_str("caffeinated").negate()};
        assert!(!set.contains(&Proposition::from_str("caffeinated")));
    }

}