1use crate::solvers::SolversError as ExecutionError;
8use crate::solvers::{SolverConfig, SolverResult, SolverState};
9
10#[repr(C)]
12pub struct ForwardChainingDefeasible {
13 pub rule_base: [DefeasibleRule; 100],
15 pub facts: [Fact; 50],
17 pub inference_queue: [usize; 50],
19 pub queue_head: u8,
21 pub queue_tail: u8,
22 pub conflict_state: ConflictState,
24 pub config: SolverConfig,
26 pub solver_state: SolverState,
28}
29
30#[repr(C)]
32pub struct BoundedSatSolver {
33 pub clauses: [Clause; 50],
35 pub assignments: [VariableAssignment; 20],
37 pub decision_stack: [Decision; 20],
39 pub propagation_queue: [u8; 20],
41 pub assignment_level: u8,
43 pub conflict_clause: Option<Clause>,
45 pub config: SolverConfig,
47 pub solver_state: SolverState,
49}
50
51#[repr(C)]
53#[derive(Clone, Copy)]
54pub struct DefeasibleRule {
55 pub id: u32,
57 pub rule_type: RuleType,
59 pub antecedents: [Literal; 5],
61 pub consequent: Literal,
63 pub priority: u16,
65 pub active: bool,
67 pub fire_count: u32,
69}
70
71#[repr(C)]
73#[derive(Clone, Copy)]
74pub struct Fact {
75 pub id: u32,
77 pub literal: Literal,
79 pub supporting_rules: [u32; 3],
81 pub defeated: bool,
83 pub confidence: f64,
85}
86
87#[repr(C)]
89#[derive(Clone, Copy)]
90pub struct Clause {
91 pub id: u32,
93 pub literals: [Literal; 5],
95 pub num_literals: u8,
97 pub learned: bool,
99 pub activity: f64,
101}
102
103#[repr(C)]
105#[derive(Clone, Copy)]
106pub struct Literal {
107 pub variable: u8,
109 pub negated: bool,
111}
112
113#[repr(C)]
115#[derive(Clone, Copy)]
116pub struct VariableAssignment {
117 pub value: AssignmentValue,
119 pub level: u8,
121 pub antecedent: Option<u32>,
123}
124
125#[repr(C)]
127#[derive(Clone, Copy)]
128pub struct Decision {
129 pub variable: u8,
131 pub value: AssignmentValue,
133 pub level: u8,
135}
136
137#[repr(C)]
139#[derive(Clone, Copy)]
140pub struct ConflictState {
141 pub conflicts: [Conflict; 10],
143 pub num_conflicts: u8,
145 pub resolution_strategy: ResolutionStrategy,
147}
148
149#[repr(C)]
151#[derive(Clone, Copy)]
152pub struct Conflict {
153 pub facts: [u32; 3],
155 pub rules: [u32; 3],
157 pub conflict_type: ConflictType,
159}
160
161#[repr(C)]
163#[derive(Clone, Copy)]
164pub struct DefeasibleState {
165 pub iteration: u32,
167 pub num_facts: u16,
169 pub rules_fired: u16,
171 pub converged: bool,
173}
174
175#[repr(C)]
177#[derive(Clone, Copy)]
178pub struct SatState {
179 pub iteration: u32,
181 pub num_decisions: u16,
183 pub num_propagations: u16,
185 pub satisfiable: Option<bool>,
187}
188
189#[repr(u8)]
191#[derive(Clone, Copy)]
192pub enum RuleType {
193 Strict = 0,
194 Defeasible = 1,
195 Defeater = 2,
196}
197
198#[repr(u8)]
200#[derive(Clone, Copy, PartialEq)]
201pub enum AssignmentValue {
202 False = 0,
203 True = 1,
204 Unassigned = 2,
205}
206
207#[repr(u8)]
209#[derive(Clone, Copy)]
210pub enum ConflictType {
211 Contradiction = 0,
212 Defeat = 1,
213 Preference = 2,
214}
215
216#[repr(u8)]
218#[derive(Clone, Copy)]
219pub enum ResolutionStrategy {
220 Priority = 0,
221 Specificity = 1,
222 Recency = 2,
223}
224
225impl ForwardChainingDefeasible {
226 pub fn new(config: SolverConfig) -> Self {
228 Self {
229 rule_base: [DefeasibleRule::default(); 100],
230 facts: [Fact::default(); 50],
231 inference_queue: [0; 50],
232 queue_head: 0,
233 queue_tail: 0,
234 conflict_state: ConflictState::default(),
235 config,
236 solver_state: SolverState::default(),
237 }
238 }
239
240 pub fn add_rule(&mut self, rule: DefeasibleRule) -> SolverResult<()> {
242 for i in 0..100 {
244 if self.rule_base[i].id == 0 {
245 self.rule_base[i] = rule;
246 return Ok(());
247 }
248 }
249
250 Err(ExecutionError::CapacityExceeded)
251 }
252
253 pub fn add_fact(&mut self, fact: Fact) -> SolverResult<()> {
255 for i in 0..50 {
257 if self.facts[i].id == 0 {
258 self.facts[i] = fact;
259
260 self.queue_inference(i as u8);
262
263 return Ok(());
264 }
265 }
266
267 Err(ExecutionError::CapacityExceeded)
268 }
269
270 pub fn infer(&mut self) -> SolverResult<DefeasibleState> {
272 self.solver_state.iteration = 0;
273 self.solver_state.converged = false;
274
275 while !self.queue_empty() && self.solver_state.iteration < self.config.max_iterations {
276 let fact_index = self.queue_dequeue();
278
279 self.find_applicable_rules(fact_index)?;
281
282 self.apply_rules()?;
284
285 self.resolve_conflicts()?;
287
288 self.solver_state.iteration += 1;
289 }
290
291 self.solver_state.converged = self.queue_empty();
293
294 Ok(DefeasibleState {
295 iteration: self.solver_state.iteration,
296 num_facts: self.count_facts(),
297 rules_fired: self.count_rules_fired(),
298 converged: self.solver_state.converged,
299 })
300 }
301
302 fn queue_inference(&mut self, fact_index: u8) {
304 if ((self.queue_tail + 1) % 50) != self.queue_head {
305 self.inference_queue[self.queue_tail as usize] = fact_index as usize;
306 self.queue_tail = (self.queue_tail + 1) % 50;
307 }
308 }
309
310 fn queue_dequeue(&mut self) -> u8 {
312 if self.queue_head != self.queue_tail {
313 let fact_index = self.inference_queue[self.queue_head as usize];
314 self.queue_head = (self.queue_head + 1) % 50;
315 fact_index as u8
316 } else {
317 0
318 }
319 }
320
321 fn queue_empty(&self) -> bool {
323 self.queue_head == self.queue_tail
324 }
325
326 fn find_applicable_rules(&mut self, fact_index: u8) -> SolverResult<()> {
328 let fact_literal = self.facts[fact_index as usize].literal; let mut rules_to_fire = [false; 100];
332
333 for i in 0..100 {
334 if self.rule_base[i].id == 0 || !self.rule_base[i].active {
335 continue;
336 }
337
338 for j in 0..5 {
339 if self.rule_base[i].antecedents[j].variable == 0 {
340 break; }
342
343 let antecedent = self.rule_base[i].antecedents[j]; if self.literals_match(&antecedent, &fact_literal) {
345 self.rule_base[i].fire_count += 1;
346
347 let rule_copy = self.rule_base[i]; if self.antecedents_satisfied(&rule_copy) {
349 rules_to_fire[i] = true;
350 }
351 }
352 }
353 }
354
355 for i in 0..100 {
356 if rules_to_fire[i] {
357 self.fire_rule(i)?;
358 }
359 }
360
361 Ok(())
362 }
363
364 fn literals_match(&self, lit1: &Literal, lit2: &Literal) -> bool {
366 lit1.variable == lit2.variable && lit1.negated == lit2.negated
367 }
368
369 fn antecedents_satisfied(&self, rule: &DefeasibleRule) -> bool {
371 for i in 0..5 {
372 if rule.antecedents[i].variable == 0 {
373 break; }
375
376 let mut satisfied = false;
377 for j in 0..50 {
378 if self.facts[j].id == 0 {
379 continue;
380 }
381
382 if self.literals_match(&rule.antecedents[i], &self.facts[j].literal)
383 && !self.facts[j].defeated
384 {
385 satisfied = true;
386 break;
387 }
388 }
389
390 if !satisfied {
391 return false;
392 }
393 }
394
395 true
396 }
397
398 fn fire_rule(&mut self, rule_index: usize) -> SolverResult<()> {
400 let rule = &self.rule_base[rule_index];
401
402 let new_fact = Fact {
404 id: rule.consequent.variable as u32 + 1000, literal: rule.consequent,
406 supporting_rules: [rule.id, 0, 0],
407 defeated: false,
408 confidence: rule.priority as f64 / 1000.0,
409 };
410
411 self.add_fact(new_fact)?;
413
414 Ok(())
415 }
416
417 fn apply_rules(&mut self) -> SolverResult<()> {
419 for i in 0..50 {
421 if self.facts[i].id == 0 {
422 continue;
423 }
424
425 for j in i + 1..50 {
426 if self.facts[j].id == 0 {
427 continue;
428 }
429
430 if self.facts[i].literal.variable == self.facts[j].literal.variable
432 && self.facts[i].literal.negated != self.facts[j].literal.negated
433 {
434 self.add_conflict(i, j, ConflictType::Contradiction)?;
436 }
437 }
438 }
439
440 Ok(())
441 }
442
443 fn add_conflict(
445 &mut self,
446 fact1: usize,
447 fact2: usize,
448 conflict_type: ConflictType,
449 ) -> SolverResult<()> {
450 if self.conflict_state.num_conflicts < 10 {
451 let conflict = Conflict {
452 facts: [self.facts[fact1].id, self.facts[fact2].id, 0],
453 rules: [0, 0, 0],
454 conflict_type,
455 };
456
457 self.conflict_state.conflicts[self.conflict_state.num_conflicts as usize] = conflict;
458 self.conflict_state.num_conflicts += 1;
459 }
460
461 Ok(())
462 }
463
464 fn resolve_conflicts(&mut self) -> SolverResult<()> {
466 for i in 0..self.conflict_state.num_conflicts as usize {
467 let conflict = self.conflict_state.conflicts[i]; match conflict.conflict_type {
470 ConflictType::Contradiction => {
471 self.resolve_contradiction(&conflict)?;
472 }
473 ConflictType::Defeat => {
474 self.resolve_defeat(&conflict)?;
475 }
476 ConflictType::Preference => {
477 self.resolve_preference(&conflict)?;
478 }
479 }
480 }
481
482 Ok(())
483 }
484
485 fn resolve_contradiction(&mut self, conflict: &Conflict) -> SolverResult<()> {
487 let mut fact1_idx = 0;
489 let mut fact2_idx = 0;
490 let mut fact1_confidence = 0.0;
491 let mut fact2_confidence = 0.0;
492
493 for i in 0..50 {
494 if self.facts[i].id == 0 {
495 continue;
496 }
497
498 if self.facts[i].id == conflict.facts[0] {
499 fact1_idx = i;
500 fact1_confidence = self.facts[i].confidence;
501 }
502 if self.facts[i].id == conflict.facts[1] {
503 fact2_idx = i;
504 fact2_confidence = self.facts[i].confidence;
505 }
506 }
507
508 if fact1_confidence < fact2_confidence {
510 self.facts[fact1_idx].defeated = true;
511 } else {
512 self.facts[fact2_idx].defeated = true;
513 }
514
515 Ok(())
516 }
517
518 fn resolve_defeat(&mut self, _conflict: &Conflict) -> SolverResult<()> {
520 Ok(())
523 }
524
525 fn resolve_preference(&mut self, _conflict: &Conflict) -> SolverResult<()> {
527 Ok(())
530 }
531
532 fn count_facts(&self) -> u16 {
534 let mut count = 0;
535 for i in 0..50 {
536 if self.facts[i].id != 0 && !self.facts[i].defeated {
537 count += 1;
538 }
539 }
540 count
541 }
542
543 fn count_rules_fired(&self) -> u16 {
545 let mut count = 0;
546 for i in 0..100 {
547 if self.rule_base[i].id != 0 && self.rule_base[i].fire_count > 0 {
548 count += 1;
549 }
550 }
551 count
552 }
553
554 pub fn get_facts(&self) -> &[Fact; 50] {
556 &self.facts
557 }
558}
559
560impl BoundedSatSolver {
561 pub fn new(config: SolverConfig) -> Self {
563 Self {
564 clauses: [Clause::default(); 50],
565 assignments: [VariableAssignment::default(); 20],
566 decision_stack: [Decision::default(); 20],
567 propagation_queue: [0; 20],
568 assignment_level: 0,
569 conflict_clause: None,
570 config,
571 solver_state: SolverState::default(),
572 }
573 }
574
575 pub fn add_clause(&mut self, clause: Clause) -> SolverResult<()> {
577 for i in 0..50 {
579 if self.clauses[i].id == 0 {
580 self.clauses[i] = clause;
581 return Ok(());
582 }
583 }
584
585 Err(ExecutionError::CapacityExceeded)
586 }
587
588 pub fn solve(&mut self) -> SolverResult<SatState> {
590 self.solver_state.iteration = 0;
591 self.solver_state.set_satisfiable(None);
592
593 for i in 0..20 {
595 self.assignments[i] = VariableAssignment::default();
596 }
597
598 if self.dpll_algorithm()? {
600 self.solver_state.set_satisfiable(Some(true));
601 } else {
602 self.solver_state.set_satisfiable(Some(false));
603 }
604
605 Ok(SatState {
606 iteration: self.solver_state.iteration,
607 num_decisions: self.assignment_level as u16,
608 num_propagations: self.count_propagations(),
609 satisfiable: self.solver_state.satisfiable(),
610 })
611 }
612
613 fn dpll_algorithm(&mut self) -> SolverResult<bool> {
615 if !self.unit_propagate()? {
617 return Ok(false); }
619
620 if self.all_variables_assigned() {
622 return Ok(true); }
624
625 let var = self.choose_unassigned_variable()?;
627
628 self.assign_variable(var, AssignmentValue::True, None)?;
630 if self.dpll_algorithm()? {
631 return Ok(true);
632 }
633
634 self.backtrack()?;
636
637 self.assign_variable(var, AssignmentValue::False, None)?;
639 if self.dpll_algorithm()? {
640 return Ok(true);
641 }
642
643 self.backtrack()?;
645
646 Ok(false)
647 }
648
649 fn unit_propagate(&mut self) -> SolverResult<bool> {
651 let mut propagated = true;
652
653 while propagated {
654 propagated = false;
655
656 for i in 0..50 {
658 if self.clauses[i].id == 0 {
659 continue;
660 }
661
662 if let Some(unit_literal) = self.is_unit_clause(i)? {
663 let value = if unit_literal.negated {
665 AssignmentValue::False
666 } else {
667 AssignmentValue::True
668 };
669
670 self.assign_variable(unit_literal.variable, value, Some(self.clauses[i].id))?;
671 propagated = true;
672 }
673 }
674 }
675
676 Ok(true)
677 }
678
679 fn is_unit_clause(&self, clause_index: usize) -> SolverResult<Option<Literal>> {
681 let clause = &self.clauses[clause_index];
682 let mut unassigned_count = 0;
683 let mut unit_literal = None;
684
685 for i in 0..clause.num_literals as usize {
686 let literal = clause.literals[i];
687 let assignment = &self.assignments[literal.variable as usize];
688
689 match assignment.value {
690 AssignmentValue::Unassigned => {
691 unassigned_count += 1;
692 unit_literal = Some(literal);
693 }
694 AssignmentValue::True => {
695 if !literal.negated {
696 return Ok(None); }
698 }
699 AssignmentValue::False => {
700 if literal.negated {
701 return Ok(None); }
703 }
704 }
705 }
706
707 if unassigned_count == 1 {
708 Ok(unit_literal)
709 } else if unassigned_count == 0 {
710 Err(ExecutionError::Unsatisfiable)
711 } else {
712 Ok(None)
713 }
714 }
715
716 fn assign_variable(
718 &mut self,
719 var: u8,
720 value: AssignmentValue,
721 antecedent: Option<u32>,
722 ) -> SolverResult<()> {
723 self.assignments[var as usize] = VariableAssignment {
724 value,
725 level: self.assignment_level,
726 antecedent,
727 };
728
729 for i in 0..20 {
731 if self.propagation_queue[i] == 0 {
732 self.propagation_queue[i] = var;
733 break;
734 }
735 }
736
737 Ok(())
738 }
739
740 fn all_variables_assigned(&self) -> bool {
742 for i in 0..20 {
743 if self.assignments[i].value == AssignmentValue::Unassigned {
744 return false;
745 }
746 }
747 true
748 }
749
750 fn choose_unassigned_variable(&self) -> SolverResult<u8> {
752 for i in 0..20 {
753 if self.assignments[i].value == AssignmentValue::Unassigned {
754 return Ok(i as u8);
755 }
756 }
757 Err(ExecutionError::InvalidParameters)
758 }
759
760 fn backtrack(&mut self) -> SolverResult<()> {
762 if self.assignment_level == 0 {
763 return Err(ExecutionError::BacktrackFailed);
764 }
765
766 for i in 0..20 {
768 if self.assignments[i].level == self.assignment_level {
769 self.assignments[i] = VariableAssignment::default();
770 }
771 }
772
773 self.assignment_level -= 1;
774
775 Ok(())
776 }
777
778 fn count_propagations(&self) -> u16 {
780 let mut count = 0;
781 for i in 0..20 {
782 if self.assignments[i].antecedent.is_some() {
783 count += 1;
784 }
785 }
786 count
787 }
788
789 pub fn get_assignments(&self) -> &[VariableAssignment; 20] {
791 &self.assignments
792 }
793}
794
795impl Default for DefeasibleRule {
796 fn default() -> Self {
797 Self {
798 id: 0,
799 rule_type: RuleType::Strict,
800 antecedents: [Literal::default(); 5],
801 consequent: Literal::default(),
802 priority: 0,
803 active: true,
804 fire_count: 0,
805 }
806 }
807}
808
809impl Default for Fact {
810 fn default() -> Self {
811 Self {
812 id: 0,
813 literal: Literal::default(),
814 supporting_rules: [0, 0, 0],
815 defeated: false,
816 confidence: 0.0,
817 }
818 }
819}
820
821impl Default for Clause {
822 fn default() -> Self {
823 Self {
824 id: 0,
825 literals: [Literal::default(); 5],
826 num_literals: 0,
827 learned: false,
828 activity: 0.0,
829 }
830 }
831}
832
833impl Default for Literal {
834 fn default() -> Self {
835 Self {
836 variable: 0,
837 negated: false,
838 }
839 }
840}
841
842impl Default for VariableAssignment {
843 fn default() -> Self {
844 Self {
845 value: AssignmentValue::Unassigned,
846 level: 0,
847 antecedent: None,
848 }
849 }
850}
851
852impl Default for Decision {
853 fn default() -> Self {
854 Self {
855 variable: 0,
856 value: AssignmentValue::Unassigned,
857 level: 0,
858 }
859 }
860}
861
862impl Default for ConflictState {
863 fn default() -> Self {
864 Self {
865 conflicts: [Conflict::default(); 10],
866 num_conflicts: 0,
867 resolution_strategy: ResolutionStrategy::Priority,
868 }
869 }
870}
871
872impl Default for Conflict {
873 fn default() -> Self {
874 Self {
875 facts: [0, 0, 0],
876 rules: [0, 0, 0],
877 conflict_type: ConflictType::Contradiction,
878 }
879 }
880}
881
882impl Default for DefeasibleState {
883 fn default() -> Self {
884 Self {
885 iteration: 0,
886 num_facts: 0,
887 rules_fired: 0,
888 converged: false,
889 }
890 }
891}
892
893impl Default for SatState {
894 fn default() -> Self {
895 Self {
896 iteration: 0,
897 num_decisions: 0,
898 num_propagations: 0,
899 satisfiable: None,
900 }
901 }
902}
903
904impl Default for ForwardChainingDefeasible {
905 fn default() -> Self {
906 Self::new(SolverConfig::default())
907 }
908}
909
910impl Default for BoundedSatSolver {
911 fn default() -> Self {
912 Self::new(SolverConfig::default())
913 }
914}
915
916#[cfg(test)]
917mod tests {
918 use super::*;
919
920 #[test]
921 fn test_defeasible_reasoning() {
922 let mut solver = ForwardChainingDefeasible::new(SolverConfig::default());
923
924 let rule = DefeasibleRule {
926 id: 1,
927 rule_type: RuleType::Strict,
928 antecedents: [
929 Literal {
930 variable: 1,
931 negated: false,
932 },
933 Literal {
934 variable: 0,
935 negated: false,
936 },
937 Literal {
938 variable: 0,
939 negated: false,
940 },
941 Literal {
942 variable: 0,
943 negated: false,
944 },
945 Literal {
946 variable: 0,
947 negated: false,
948 },
949 ],
950 consequent: Literal {
951 variable: 2,
952 negated: false,
953 },
954 priority: 100,
955 active: true,
956 fire_count: 0,
957 };
958
959 solver.add_rule(rule).unwrap();
960
961 let fact = Fact {
963 id: 100,
964 literal: Literal {
965 variable: 1,
966 negated: false,
967 },
968 supporting_rules: [0, 0, 0],
969 defeated: false,
970 confidence: 1.0,
971 };
972
973 solver.add_fact(fact).unwrap();
974
975 let result = solver.infer();
977 assert!(result.is_ok());
978
979 let state = result.unwrap();
980 assert!(state.num_facts >= 2); assert!(state.rules_fired >= 1);
982 }
983
984 #[test]
985 fn test_sat_solver() {
986 let mut solver = BoundedSatSolver::new(SolverConfig::default());
987
988 let clause = Clause {
990 id: 1,
991 literals: [
992 Literal {
993 variable: 1,
994 negated: false,
995 },
996 Literal {
997 variable: 2,
998 negated: false,
999 },
1000 Literal {
1001 variable: 3,
1002 negated: true,
1003 },
1004 Literal {
1005 variable: 0,
1006 negated: false,
1007 },
1008 Literal {
1009 variable: 0,
1010 negated: false,
1011 },
1012 ],
1013 num_literals: 3,
1014 learned: false,
1015 activity: 0.0,
1016 };
1017
1018 solver.add_clause(clause).unwrap();
1019
1020 let result = solver.solve();
1022 assert!(result.is_ok());
1023
1024 let state = result.unwrap();
1025 assert!(state.satisfiable.is_some());
1026 }
1027
1028 #[test]
1029 fn test_zero_allocation_guarantee() {
1030 }
1037}