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()