microsat/
expression.rs

1use core::panic;
2use hashbrown::{HashMap, HashSet};
3use std::cmp::{max, min, Ordering};
4use std::fmt::Debug;
5use std::sync::{Arc, RwLock};
6
7use crate::cnf::{
8    negate, to_variable, Action, ActionState, Assignment, Clause, ClauseId, Literal, Variable, CNF,
9};
10use crate::dimacs_parser::parse_dimacs;
11use crate::stack::Stack;
12
13#[derive(Clone, Copy, Debug)]
14pub enum SolverHeuristic {
15    MostLiteralOccurances,
16    MostVariableOccurances,
17    MinimizeClauseLength,
18}
19
20pub struct Expression {
21    clauses: Vec<Clause>,
22    variables: HashSet<Variable>,
23    actions: Arc<RwLock<Stack<Action>>>,
24    assignments: HashMap<Variable, bool>,
25
26    literal_to_clause: HashMap<Literal, HashSet<ClauseId>>,
27    unit_clauses: HashSet<ClauseId>,
28    pure_literals: HashSet<Literal>,
29    num_active_clauses: u16,
30    num_empty_clauses: usize,
31    max_clause_length: usize,
32    pub heuristic: SolverHeuristic,
33}
34
35impl Clone for Expression {
36    fn clone(&self) -> Self {
37        let mut new_expression = Expression::new();
38        for clause in &self.clauses {
39            new_expression.add_clause(clause.clone());
40        }
41
42        new_expression
43    }
44}
45
46impl Default for Expression {
47    fn default() -> Self {
48        Self::new()
49    }
50}
51
52impl Expression {
53    pub fn new() -> Expression {
54        Expression {
55            clauses: Vec::new(),
56            variables: HashSet::new(),
57            actions: Arc::new(RwLock::new(Stack::new(0))),
58            assignments: HashMap::new(),
59
60            literal_to_clause: HashMap::new(),
61            unit_clauses: HashSet::new(),
62            pure_literals: HashSet::new(),
63            num_active_clauses: 0,
64            num_empty_clauses: 0,
65            max_clause_length: 0,
66            heuristic: SolverHeuristic::MostLiteralOccurances,
67        }
68    }
69
70    pub fn from_clauses(clauses: Vec<Clause>) -> Expression {
71        let mut expression = Expression::new();
72        for clause in clauses {
73            expression.add_clause(clause);
74        }
75
76        expression
77    }
78
79    pub fn from_cnf_file(file_name: &str) -> Expression {
80        return parse_dimacs(file_name);
81    }
82
83    pub fn get_clauses(&self) -> Vec<Clause> {
84        self.clauses.clone()
85    }
86
87    pub fn set_heuristic(&mut self, heuristic: SolverHeuristic) {
88        self.heuristic = heuristic;
89    }
90
91    /// Softly removes a clause from the expression.
92    /// This means that the clause is not actually removed from the expression vector,
93    /// but all references to it have been removed from the literals map, so it is unreferenced.
94    fn remove_clause(&mut self, clause_id: ClauseId) {
95        // Remove all of the literals in the clause from the variable_to_clause map
96        for i in 0..self.clauses[clause_id as usize].len() {
97            let literal = unsafe { self.clauses.get_unchecked(clause_id as usize).get(i) };
98            let literal_clauses = self.literal_to_clause.get_mut(&literal).unwrap();
99
100            // If there are no more clauses that contain the literal, the negation is a pure literal
101            if literal_clauses.is_empty() {
102                // This literal has no more instances.
103                // If its negation has some number of instances, add it to the pure_literals set.
104                let negated_literal = negate(literal);
105                let negated_literal_clauses = self.literal_to_clause.get_mut(&negated_literal);
106
107                if negated_literal_clauses.is_none() || negated_literal_clauses.unwrap().is_empty()
108                {
109                    self.pure_literals.insert(negated_literal);
110                }
111            }
112        }
113
114        self.num_active_clauses -= 1;
115        self.unit_clauses.remove(&clause_id);
116        self.actions
117            .write()
118            .unwrap()
119            .push(Action::RemoveClause(clause_id));
120    }
121
122    /// Re-enables a clause that had been softly removed, so all of its literals are still present in the vector.
123    fn enable_clause(&mut self, clause_id: ClauseId) {
124        self.num_active_clauses += 1;
125
126        let clause = unsafe { &self.clauses.get_unchecked(clause_id as usize) };
127        if clause.len() == 1 {
128            self.unit_clauses.insert(clause_id);
129        }
130
131        for i in 0..clause.len() {
132            let literal = unsafe { self.clauses.get_unchecked(clause_id as usize).get(i) };
133            let should_check_pure_literal;
134            {
135                let literal_clauses = self.literal_to_clause.get_mut(&literal).unwrap();
136                literal_clauses.insert(clause_id);
137                should_check_pure_literal = literal_clauses.len() == 1;
138            }
139
140            if should_check_pure_literal {
141                // TODO: Can we avoid doing this check again? Does it do too much?
142                self.check_pure_literal(literal);
143            }
144        }
145    }
146
147    /// Removes a literal from all of the clauses that it is in
148    fn remove_literal_from_clauses(&mut self, literal: Literal) {
149        let clauses_result = self.literal_to_clause.get(&literal);
150        if clauses_result.is_none() {
151            return;
152        }
153
154        let actions = self.actions.clone();
155        let mut actions = actions.write().unwrap();
156
157        actions.push(Action::RemoveLiteralFromClausesStart());
158
159        let literal_clauses = clauses_result.unwrap();
160        for clause_id in literal_clauses {
161            let clause = &mut self.clauses[*clause_id as usize];
162            clause.remove(literal);
163
164            if clause.len() == 1 {
165                self.unit_clauses.insert(*clause_id);
166            }
167
168            if clause.is_empty() {
169                self.num_empty_clauses += 1;
170                self.unit_clauses.remove(clause_id);
171            }
172
173            actions.push(Action::RemoveLiteralFromClause(*clause_id));
174        }
175
176        actions.push(Action::RemoveLiteralFromClausesEnd(literal));
177    }
178
179    /// Removes all clauses with the specified literal.
180    fn remove_clauses_with_literal(&mut self, literal: Literal) {
181        let literal_clauses;
182        {
183            let literal_clauses_ref = self.literal_to_clause.get(&literal);
184            if literal_clauses_ref.is_none() {
185                return;
186            }
187            // TODO: Prevent cloning
188            literal_clauses = literal_clauses_ref.unwrap().clone();
189        }
190
191        for clause_id in literal_clauses {
192            self.remove_clause(clause_id);
193        }
194    }
195
196    fn check_pure_literal(&mut self, literal: Literal) {
197        let negated_literal = negate(literal);
198        let literal_clauses = self.literal_to_clause.get(&literal);
199        let has_instances = literal_clauses.is_some() && !literal_clauses.unwrap().is_empty();
200
201        let negated_literal_clauses = self.literal_to_clause.get(&negated_literal);
202        let negated_has_instances =
203            negated_literal_clauses.is_some() && !negated_literal_clauses.unwrap().is_empty();
204
205        if has_instances && !negated_has_instances {
206            self.pure_literals.insert(literal);
207            self.pure_literals.remove(&negated_literal);
208        } else if !has_instances && negated_has_instances {
209            self.pure_literals.insert(negated_literal);
210            self.pure_literals.remove(&literal);
211        } else {
212            self.pure_literals.remove(&literal);
213            self.pure_literals.remove(&negated_literal);
214        }
215    }
216
217    fn assign_variable(&mut self, variable: Variable, value: bool) {
218
219        self.assignments.insert(variable, value);
220        self.actions
221            .write()
222            .unwrap()
223            .push(Action::AssignVariable(variable));
224        let literal = if value {
225            variable as Literal
226        } else {
227            -(variable as Literal)
228        };
229        let negated_literal = negate(literal);
230        self.remove_clauses_with_literal(literal);
231        self.remove_literal_from_clauses(negated_literal);
232
233        self.pure_literals.remove(&literal);
234        self.pure_literals.remove(&negated_literal);
235    }
236
237    fn unassign_variable(&mut self, variable: Variable) {
238        self.assignments.remove(&variable);
239    }
240
241    pub fn optimize(&mut self) {
242        // Remove all of the empty clauses
243        self.actions = Arc::new(RwLock::new(Stack::new(
244            self.clauses.len() * self.max_clause_length,
245        ))); // Pre-allocate a reasonable amount of space
246    }
247
248    pub fn is_satisfied_by(&self, assignment: &Assignment) -> bool {
249        for clause in &self.clauses {
250            let mut satisfied = false;
251            for literal in clause.literals() {
252                let variable = to_variable(*literal);
253                let value = assignment.get(&variable);
254                if value.is_none() {
255                    continue;
256                }
257
258                if *value.unwrap() == (*literal > 0) {
259                    satisfied = true;
260                    break;
261                }
262            }
263
264            if !satisfied {
265                return false;
266            }
267        }
268
269        true
270    }
271
272    fn get_most_literal_occurances(&self) -> (Variable, bool) {
273        let mut max_occurances = 0;
274        let mut best_literal = 0;
275
276        for literal_clause in &self.literal_to_clause {
277            let literal = literal_clause.0;
278            if literal_clause.1.is_empty() || self.assignments.contains_key(&to_variable(*literal))
279            {
280                continue;
281            }
282
283            let occurances = literal_clause.1.len();
284            if occurances > max_occurances {
285                max_occurances = occurances;
286                best_literal = *literal;
287            }
288        }
289
290        if best_literal != 0 {
291            return (to_variable(best_literal), best_literal > 0);
292        }
293
294        panic!("No branch variable found");
295    }
296
297    fn get_most_variable_occurances(&self) -> (Variable, bool) {
298        let mut max_occurances = 0;
299        let mut best_variable = 0;
300
301        for variable in &self.variables {
302            let positive_literal = *variable as Literal;
303            let negative_literal = -positive_literal;
304
305            if self.assignments.contains_key(variable) {
306                continue;
307            }
308
309            let positive_occurances = self.literal_to_clause.get(&positive_literal).unwrap().len();
310            let negative_occurances = self.literal_to_clause.get(&negative_literal).unwrap().len();
311
312            let occurances = positive_occurances + negative_occurances;
313            if occurances > max_occurances {
314                max_occurances = occurances;
315                best_variable = *variable;
316            }
317        }
318
319        if best_variable != 0 {
320            return (best_variable, true);
321        }
322
323        panic!("No branch variable found");
324    }
325
326    const ALPHA: usize = 1;
327    const BETA: usize = 1;
328    fn get_lexicographically_maximizing_literal(&self) -> (Variable, bool) {
329        let mut best_variables = self
330            .variables
331            .iter()
332            .filter(|x| !self.assignments.contains_key(*x))
333            .collect::<Vec<&Variable>>();
334
335        for clause_size in 2..5 {
336            let mut best_heuristic_value = 0;
337            let mut new_best_variables: Vec<&Variable> = Vec::new();
338
339            for variable in best_variables {
340                let positive_literal = *variable as Literal;
341                let negative_literal = -positive_literal;
342
343                let positive_occurrences = self
344                    .literal_to_clause
345                    .get(&positive_literal)
346                    .unwrap()
347                    .iter()
348                    .filter(|clause_id| self.clauses[**clause_id as usize].len() == clause_size)
349                    .count();
350                let negative_occurences = self
351                    .literal_to_clause
352                    .get(&negative_literal)
353                    .unwrap()
354                    .iter()
355                    .filter(|clause_id| self.clauses[**clause_id as usize].len() == clause_size)
356                    .count();
357
358                let heuristic_value = Self::ALPHA * max(positive_occurrences, negative_occurences)
359                    + Self::BETA * min(positive_occurrences, negative_occurences);
360
361                match heuristic_value.cmp(&best_heuristic_value) {
362                    Ordering::Greater => {
363                        best_heuristic_value = heuristic_value;
364                        new_best_variables.clear();
365                        new_best_variables.push(variable);
366                    }
367                    Ordering::Equal => {
368                        new_best_variables.push(variable);
369                    }
370                    _ => {}
371                }
372            }
373
374            best_variables = new_best_variables;
375
376            if best_variables.len() == 1 {
377                break;
378            }
379        }
380
381        let variable = *best_variables[0];
382        let positive_literal = variable as Literal;
383        let negative_literal = -positive_literal;
384
385        let positive_occurrences = self.literal_to_clause.get(&positive_literal).unwrap().len();
386        let negative_occurrences = self.literal_to_clause.get(&negative_literal).unwrap().len();
387
388        (variable, positive_occurrences > negative_occurrences)
389    }
390}
391
392impl CNF for Expression {
393    fn add_clause(&mut self, clause: Clause) {
394        let clause_id = self.clauses.len() as ClauseId;
395
396        for literal in clause.literals() {
397            {
398                let variable: Variable = to_variable(*literal);
399                self.variables.insert(variable);
400
401                if !self.literal_to_clause.contains_key(literal) {
402                    self.literal_to_clause.insert(*literal, HashSet::new());
403                }
404
405                if !self.literal_to_clause.contains_key(&negate(*literal)) {
406                    self.literal_to_clause
407                        .insert(negate(*literal), HashSet::new());
408                }
409
410                let literal_clauses = self.literal_to_clause.get_mut(literal).unwrap();
411                literal_clauses.insert(clause_id);
412            }
413            // Check if the literal is a pure literal
414            self.check_pure_literal(*literal);
415        }
416
417        // Make sure we add it if it is a unit clause
418        if clause.len() == 1 {
419            self.unit_clauses.insert(clause_id);
420        }
421
422        if clause.len() > self.max_clause_length {
423            self.max_clause_length = clause.len();
424        }
425
426        self.clauses.push(clause);
427        self.num_active_clauses += 1;
428    }
429
430    fn remove_unit_clause(&mut self) -> Option<ClauseId> {
431        if self.unit_clauses.is_empty() {
432            return None;
433        }
434
435        let clause_id: ClauseId = *self.unit_clauses.iter().next().unwrap();
436
437        let literal = unsafe { self.clauses.get_unchecked(clause_id as usize).literals()[0] };
438
439        self.assign_variable(to_variable(literal), literal > 0);
440        Some(clause_id)
441    }
442
443    fn remove_pure_literal(&mut self) -> Option<Literal> {
444        if self.pure_literals.is_empty() {
445            return None;
446        }
447
448        let literal: Literal = *self.pure_literals.iter().next().unwrap();
449
450        self.assign_variable(to_variable(literal), literal > 0);
451        Some(literal)
452    }
453
454    fn construct_assignment(&mut self) -> Assignment {
455        let mut assignments = HashMap::new();
456
457        // Copy the existing assignments array to another one
458        for (k, v) in self.assignments.iter() {
459            assignments.insert(*k, *v);
460        }
461
462        // Assign all of the remaining variables to true
463        for variable in &self.variables {
464            if !assignments.contains_key(variable) {
465                assignments.insert(*variable, true);
466            }
467        }
468        assignments
469    }
470
471    #[inline]
472    fn is_satisfied(&self) -> bool {
473        self.num_active_clauses == 0
474    }
475
476    #[inline]
477    fn is_unsatisfiable(&self) -> bool {
478        self.num_empty_clauses > 0
479    }
480
481    fn get_branch_variable(&self) -> (Variable, bool) {
482        match self.heuristic {
483            SolverHeuristic::MostLiteralOccurances => self.get_most_literal_occurances(),
484            SolverHeuristic::MostVariableOccurances => self.get_most_variable_occurances(),
485            SolverHeuristic::MinimizeClauseLength => {
486                self.get_lexicographically_maximizing_literal()
487            }
488        }
489    }
490
491    fn branch_variable(&mut self, variable: Variable, value: bool) {
492        self.assign_variable(variable, value);
493    }
494
495    fn get_action_state(&self) -> ActionState {
496        return self.actions.read().unwrap().len();
497    }
498
499    fn restore_action_state(&mut self, state: ActionState) {
500        let actions = self.actions.clone();
501        let mut actions = actions.write().unwrap();
502        while actions.len() > state {
503            let action = actions.pop().unwrap();
504            match action {
505                Action::RemoveClause(clause_id) => self.enable_clause(clause_id),
506                Action::RemoveLiteralFromClausesEnd(literal) => {
507                    let removing_literal_clauses =
508                        self.literal_to_clause.get_mut(&literal).unwrap();
509
510                    let mut should_exit = false;
511
512                    while !should_exit {
513                        let next_action = actions.pop().unwrap();
514                        match next_action {
515                            Action::RemoveLiteralFromClause(clause_id) => {
516                                let clause =
517                                    unsafe { self.clauses.get_unchecked_mut(clause_id as usize) };
518                                clause.insert(literal);
519                                if clause.len() == 1 {
520                                    self.num_empty_clauses -= 1;
521                                    self.unit_clauses.insert(clause_id);
522                                } else if clause.len() == 2 {
523                                    self.unit_clauses.remove(&clause_id);
524                                }
525
526                                removing_literal_clauses.insert(clause_id);
527                            }
528                            Action::RemoveLiteralFromClausesStart() => {
529                                should_exit = true;
530                            }
531                            _ => panic!("Did not encounter a start literal!"),
532                        }
533                    }
534                }
535                Action::AssignVariable(variable) => {
536                    self.unassign_variable(variable);
537                }
538                _ => break,
539            }
540        }
541    }
542
543    /// Inference is possibly when there are some "Active" clauses, 
544    /// and either pure literals or unit clauses.
545    fn is_inference_possible(&self) -> bool {
546        self.num_empty_clauses == 0
547            && self.num_active_clauses > 0
548            && (!self.pure_literals.is_empty() || !self.unit_clauses.is_empty())
549    }
550}