Skip to main content

sat_rs/
notation.rs

1//! Collection of structs representing the notation used in the SAT solver
2//!
3//! * [`Literal`] - A struct representing a literal (atom)
4//! * [`Clause`] - A struct representing a clause
5//! * [`Formula`] - A struct representing a propositional formula
6use std::collections::HashMap;
7
8/// Struct representing a Literal. Also known as an atom.
9///
10/// Derives from [`Debug`] and [`Clone`].
11/// Contains a value and a boolean representing whether it is negated or not
12///
13/// # Examples
14/// ```rust
15/// use sat_rs::notation::Literal;
16///
17/// let literal = Literal::new();
18///
19/// let literal = Literal::from_value(1);
20///
21/// let literal = Literal{ value: 1, negated: false};
22/// ```
23#[derive(Debug, Clone)]
24pub struct Literal {
25    pub value: i32,
26    pub negated: bool,
27}
28
29impl Literal {
30
31    /// Creates a new [`Literal`] with value `0` and negated set to `false`
32    ///
33    /// # Examples
34    /// ```rust
35    /// use sat_rs::notation::Literal;
36    ///
37    /// let literal = Literal::new();
38    /// ```
39    #[allow(dead_code)]
40    pub fn new() -> Literal {
41        return Literal {
42            value: 0,
43            negated: false,
44        }
45    }
46
47    /// Creates a new [`Literal`] from a given value. Negated is set to `false`
48    ///
49    /// # Arguments
50    /// * `value` - An [`i32`] representing the value of the [`Literal`]
51    ///
52    /// # Examples
53    /// ```rust
54    /// use sat_rs::notation::Literal;
55    ///
56    /// let literal = Literal::from_value(1);
57    /// ```
58    #[allow(dead_code)]
59    pub fn from_value(value: i32) -> Literal {
60        return Literal {
61            value: value,
62            negated: false,
63        }
64    }
65}
66
67/// Struct representing a Clause
68///
69/// Derives from [`Debug`] and [`Clone`].
70///
71/// Contains a vector of [`Literal`]s
72///
73/// # Examples
74/// ```rust
75/// use sat_rs::notation::Literal;
76/// use sat_rs::notation::Clause;
77///
78/// let mut clause = Clause::new();
79///
80/// let p = Literal{ value: 1, negated: false};
81/// let q = Literal{ value: 2, negated: false};
82///
83/// clause.literals.push(p);
84/// clause.literals.push(q);
85/// ```
86#[derive(Debug, Clone)]
87pub struct Clause {
88    pub literals: Vec<Literal>,
89}
90
91impl Clause {
92
93    /// Creates a new [`Clause`] with an empty vector of [`Literal`]s
94    ///
95    /// # Examples
96    /// ```rust
97    /// use sat_rs::notation::Clause;
98    ///
99    /// let clause = Clause::new();
100    /// ```
101    pub fn new() -> Clause {
102        Clause {
103            literals: Vec::new(),
104        }
105    }
106}
107
108/// Struct representing a Propositional Formula
109///
110/// Derives from [`Debug`] and [`Clone`].
111///
112/// Contains a vector of [`Clause`]s, a vector of [`Literal`]s, the number of clauses and the number of variables
113#[derive(Debug, Clone)]
114pub struct Formula {
115    pub clauses: Vec<Clause>,
116    pub literals: Vec<i32>,
117    pub num_clauses: i32,
118    pub num_vars: i32,
119}
120
121
122impl Formula {
123
124    /// Creates a new [`Formula`] with an empty vector of [`Clause`]s and [`Literal`]s
125    ///
126    /// # Examples
127    /// ```rust
128    /// use sat_rs::notation::Formula;
129    ///
130    /// let formula = Formula::new();
131    /// ```
132    #[allow(dead_code)]
133    pub fn new() -> Formula {
134        Formula {
135            clauses: Vec::new(),
136            literals: Vec::new(),
137            num_clauses: 0,
138            num_vars: 0,
139        }
140    }
141
142    #[allow(dead_code)]
143    /// Evaluates a [`Formula`] given an interpretation
144    ///
145    /// # Arguments
146    /// * `interpretation` - A [`HashMap`] of [`i32`] and [`bool`] representing the interpretation
147    ///
148    /// # Examples
149    /// Assuming the CNF file is in `/bin/problem.cnf` and contains the following:
150    /// ```;
151    /// p cnf 3 1
152    /// 1 -3 0
153    /// 2 3 -1 0
154    /// ```
155    ///
156    /// ```rust
157    /// use sat_rs::cnfparser;
158    /// use std::collections::HashMap;
159    ///
160    /// let buffer = include_str!("bin/problem.cnf");
161    /// let mut formula = cnfparser::parse_cnf(&buffer);
162    ///
163    /// let mut interpretation: HashMap<i32, bool> = HashMap::new();
164    /// interpretation.insert(1, false);
165    /// interpretation.insert(2, false);
166    /// interpretation.insert(3, false);
167    ///
168    /// assert_eq!(formula.unwrap().evaluate(&interpretation), true);
169    /// ```
170    pub fn evaluate(&mut self, interpretation: &HashMap<i32, bool>) -> bool {
171        let mut value: bool = true;
172        for clause in &mut self.clauses {
173            let mut clause_value: bool = false;
174            for literal in &mut clause.literals {
175                let mut literal_value: bool = false;
176                if interpretation.contains_key(&literal.value) {
177                    literal_value = interpretation[&literal.value];
178                }
179                if literal.negated {
180                    literal_value = !literal_value;
181                }
182                if literal_value {
183                    clause_value = true;
184                    break;
185                }
186            }
187            value = value && clause_value;
188        }
189        value
190    }
191}