suiron/solution_node_and_or.rs
1//! Functions to support logical And and Or operators.
2//!
3//! This module contains the functions next_solution_and() and next_solution_or(),
4//! which are called by next_solution() in solution_node.rs.
5//!
6// Cleve Lendon 2023
7
8use std::rc::Rc;
9use std::cell::RefCell;
10
11use crate::*;
12
13use super::goal::Goal;
14use super::substitution_set::*;
15
16/// Calls next_solution() on all subgoals of the And operator.
17///
18/// All subgoals must succeed for the And solution node to succeed.
19///
20/// # Arguments
21/// * [SolutionNode](../solution_node/struct.SolutionNode.html)
22/// * reference to [SolutionNode](../solution_node/struct.SolutionNode.html)
23/// # Return
24/// [SubstitutionSet](../substitution_set/type.SubstitutionSet.html) or None
25pub fn next_solution_and<'a>(sn: Rc<RefCell<SolutionNode<'a>>>)
26 -> Option<Rc<SubstitutionSet<'a>>> {
27
28 let mut sn_ref = sn.borrow_mut(); // Get a mutable reference.
29
30 // Check for the tail solution.
31 if let Some(tail_sn) = &sn_ref.tail_sn {
32 if let Some(ss) = next_solution(Rc::clone(&tail_sn)) {
33 return Some(ss);
34 }
35 }
36
37 let mut solution = match &sn_ref.head_sn {
38 None => { return None; },
39 Some(head_sn) => { next_solution(Rc::clone(&head_sn)) },
40 };
41
42 loop {
43
44 match solution {
45
46 None => { return None; },
47 Some(ss) => {
48
49 // print_ss(&ss); // For debugging.
50 match &sn_ref.operator_tail {
51 None => { return Some(ss); },
52 Some(tail) => {
53
54 if tail.len() == 0 { return Some(ss); }
55
56 // Tail solution node has to be an And solution node.
57 let tail_goal = Goal::OperatorGoal(tail.clone());
58 let tail_sn = make_solution_node(Rc::new(tail_goal),
59 sn_ref.kb, ss,
60 Rc::clone(&sn));
61 sn_ref.tail_sn = Some(Rc::clone(&tail_sn));
62 let tail_solution = next_solution(tail_sn);
63 if tail_solution.is_some() { return tail_solution; }
64 },
65 } // match
66 },
67 } // match solution
68
69 // Try another solution.
70 solution = match &sn_ref.head_sn {
71 None => { return None; },
72 Some(head_sn) => { next_solution(Rc::clone(&head_sn)) },
73 };
74
75 } // loop
76
77} // next_solution_and()
78
79/// Calls next_solution() on subgoals of the Or operator.
80///
81/// Checks subgoals until a success is found.
82///
83/// # Arguments
84/// * [SolutionNode](../solution_node/struct.SolutionNode.html)
85/// * reference to [SolutionNode](../solution_node/struct.SolutionNode.html)
86/// # Return
87/// [SubstitutionSet](../substitution_set/type.SubstitutionSet.html) or None
88pub fn next_solution_or<'a>(sn: Rc<RefCell<SolutionNode<'a>>>)
89 -> Option<Rc<SubstitutionSet<'a>>> {
90
91 let mut sn_ref = sn.borrow_mut(); // Get a mutable reference.
92
93 // Check for the tail solution.
94 if let Some(tail_sn) = &sn_ref.tail_sn {
95 return next_solution(Rc::clone(&tail_sn));
96 }
97
98 let solution = match &sn_ref.head_sn {
99 None => { return None; },
100 Some(head_sn) => { next_solution(Rc::clone(&head_sn)) },
101 };
102
103 match solution {
104 None => {
105 match &sn_ref.operator_tail {
106 None => { return solution; },
107 Some(tail) => {
108 if tail.len() == 0 { return solution; }
109 },
110 }
111 },
112 Some(_) => { return solution; },
113 }
114
115 match &sn_ref.operator_tail {
116 None => { return None; },
117 Some(tail) => {
118 let tail_goal = Goal::OperatorGoal(tail.clone());
119 let ss = Rc::clone(&sn_ref.ss);
120 let tail_sn = make_solution_node(Rc::new(tail_goal),
121 sn_ref.kb, ss,
122 Rc::clone(&sn));
123 sn_ref.tail_sn = Some(Rc::clone(&tail_sn));
124 return next_solution(tail_sn);
125 },
126 }
127
128} // next_solution_or()