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 fn remove_clause(&mut self, clause_id: ClauseId) {
95 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 literal_clauses.is_empty() {
102 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 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 self.check_pure_literal(literal);
143 }
144 }
145 }
146
147 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 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 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 self.actions = Arc::new(RwLock::new(Stack::new(
244 self.clauses.len() * self.max_clause_length,
245 ))); }
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 self.check_pure_literal(*literal);
415 }
416
417 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 for (k, v) in self.assignments.iter() {
459 assignments.insert(*k, *v);
460 }
461
462 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 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}