use std::borrow::{Borrow, BorrowMut};
use std::cell::{Cell, RefCell};
use std::collections::{HashMap, HashSet};
use std::fmt::{Debug, Error, Formatter};
use std::ops::{Index, IndexMut};
use std::rc::Rc;
use either;
use generational_arena::Arena;
use generational_indextree::Arena as TreeArena;
use phreak_facts::{FactAttribute, FactObject, Store, Value};
use phreak_rules::ProductionCallback;
use crate::actions::{AlphaNodeId, BetaNodeId, SegmentId};
use crate::betanode::*;
use crate::condition::{Condition, NccCondition};
use crate::jointest::{get_join_tests_from_condition, JoinNodeTest};
use crate::memory::WmeMatch;
use crate::nodes::alphanode::AlphaNode;
use crate::nodes::classnode::ClassNode;
use crate::segment::Segment;
use crate::token::*;
use either::Either;
pub struct Phreak {
classes: HashMap<String, ClassNode>,
alphanodes: Arena<AlphaNode>,
betanodes: TreeArena<BetaNode>,
segments: TreeArena<Segment>,
root_node: BetaNodeId,
facts_store: Store,
tokens: RefCell<TreeArena<Token>>,
processing_stack: RefCell<Vec<StackAction>>,
nil_fact: Rc<FactAttribute>,
fact_counter: Cell<u64>,
}
pub struct Production {
id: BetaNodeId,
}
impl From<BetaNodeId> for Production {
fn from(id: BetaNodeId) -> Self {
Production { id }
}
}
impl Phreak {
pub fn new() -> Self {
let classes = Default::default();
let alphanodes = Arena::new();
let mut betanodes = TreeArena::new();
let mut segments = TreeArena::new();
let mut tokens = TreeArena::new();
let nil_fact = Rc::new(FactAttribute(Value::new(), Value::new(), Value::new()));
let root_segment_id = segments.new_node(Segment::new());
let root_node = betanodes.new_node(BetaNode::new_rootnode(root_segment_id));
let root_token = tokens.new_node(Token::new(nil_fact.clone(), root_node));
betanodes[root_node].borrow_mut().get_mut().set_root_token(root_token);
let root_segment_mut = segments.get_mut(root_segment_id).unwrap().get_mut();
root_segment_mut.push_node(root_node, true, &mut betanodes);
root_segment_mut.node_linked.borrow_mut().set(0, true);
let facts_store = Store::new();
Phreak {
classes,
alphanodes,
betanodes,
segments,
root_node,
facts_store,
tokens: RefCell::new(tokens),
processing_stack: RefCell::new(Vec::new()),
nil_fact,
fact_counter: Cell::new(0),
}
}
pub fn add_production(&mut self, conditions: &[Condition], callback: Box<dyn ProductionCallback>) -> Production {
let current_node = self.root_node;
let bottom_of_subnetwork_id = self.build_or_share_network_for_conditions(current_node, conditions, &[]);
Production::from(self.build_production(bottom_of_subnetwork_id, callback))
}
pub fn remove_production(_production: Production) { unimplemented!("need recursive delete from production towards first shared node") }
pub fn add_facts(&self, facts_array: &[FactObject]) {
let mut mutated = HashSet::new();
let mut counter = self.fact_counter.get();
for facts in facts_array {
println!("-=-=-=-=-=-=-=-=-=-=- add_facts {:?}", facts);
match self.classes.get(facts.get_name()) {
None => {}
Some(cl) => {
let returnset = cl.add_facts(facts, &self.alphanodes, counter, &self.segments);
for idx in returnset {
mutated.insert(idx);
}
}
}
}
counter += 1;
self.fact_counter.set(counter);
self.process(mutated);
}
pub fn remove_facts(&self, facts_array: &[FactObject]) {
let mut mutated = HashSet::new();
let mut counter = self.fact_counter.get();
for facts in facts_array {
println!("-=-=-=-=-=-=-=-=-=-=- remove_facts {:?}", facts);
match self.classes.get(facts.get_name()) {
None => {}
Some(cl) => {
let returnset = cl.remove_facts(facts, &self.alphanodes, counter, &self.segments);
for idx in returnset {
mutated.insert(idx);
}
}
}
}
counter += 1;
self.fact_counter.set(counter);
self.process(mutated);
}
fn process_tree_structure(&self) {
self.cleanup();
self.process(HashSet::new());
}
fn cleanup(&self) {
for (_, alphanode) in self.alphanodes.iter() {
alphanode.cell.borrow_mut().items.cleanup();
}
for betanode in self.betanodes.iter() {
betanode.get().borrow().cleanup();
}
}
fn process(&self, mutated: HashSet<AlphaNodeId>) {
{
let stack = &mut *self.processing_stack.borrow_mut();
stack.push(StackAction::ProcessSegment(self.get_rootsegment_id()));
for alpha in mutated.iter() {
stack.push(StackAction::ProcessAlphaNode(*alpha));
self.alphanodes.get(*alpha).unwrap().process_pending(&self.alphanodes, &self.betanodes, &self.segments);
}
}
self.process_actions();
}
pub(crate) fn get_root_node(&self) -> &BetaNode {
self.betanodes.get(self.root_node).unwrap().get()
}
fn process_actions(&self) {
let stack = &mut *self.processing_stack.borrow_mut();
while let Some(action) = stack.pop() {
println!("=== Stack.pop( {:?} )", &action);
match action {
StackAction::ProcessClassNode(_) => {}
StackAction::ProcessAlphaNode(alpha_id) => {
self.alphanodes.get(alpha_id).unwrap()
.process_pending(&self.alphanodes, &self.betanodes, &self.segments);
}
StackAction::ProcessBetaNode(beta_id) => {
let node = self.betanodes.get(beta_id).unwrap().get();
node.cleanup();
self.betanodes.get(beta_id).unwrap().get()
.process_actions(beta_id,
&self.alphanodes,
&self.betanodes,
&self.segments,
&mut self.tokens.borrow_mut(),
&self.nil_fact,
);
}
StackAction::ProcessSegment(segment_id) => {
let segment = self.segments.get(segment_id).unwrap().get();
for child_id in segment_id.reverse_children(&self.segments) {
stack.push(StackAction::ProcessSegment(child_id));
}
if !segment.calculate_needs_processing() {
println!("OPTIMIZE: no need to process");
continue;
}
let mut reversed = segment.betanodes.clone();
reversed.reverse();
for node_id in reversed.iter() {
stack.push(StackAction::ProcessBetaNode(*node_id));
}
}
}
}
}
}
impl Phreak {
pub(crate) fn dump_structure(&self) {
println!("Phreak {{");
let mut stack = Vec::new();
stack.push(("".to_owned(), self.root_node));
while !stack.is_empty() {
let (tabs, node) = stack.pop().unwrap();
for child in node.reverse_children(&self.betanodes) {
let mut x = String::from("\t");
x.push_str(&tabs);
stack.push((x, child));
}
println!("{} <{}> {:?}", tabs, node, self.betanodes.index(node).get());
}
println!("}}");
}
pub(crate) fn dump_segment_structure(&self) {
println!("Phreak {{ segments: ");
let mut stack = Vec::new();
let rootnode = &self.betanodes[self.root_node];
match rootnode.get() {
BetaNode::RootNode(rn) => {
stack.push(("".to_owned(), rn.segment));
}
_ => { unreachable!(); }
}
while !stack.is_empty() {
let (tabs, segment_id) = stack.pop().unwrap();
for child in segment_id.reverse_children(&self.segments) {
let mut x = String::from("\t");
x.push_str(&tabs);
stack.push((x, child));
}
println!("{} <{}> {:?}", tabs, segment_id, &self.segments[segment_id]);
}
println!("}}");
}
}
impl Debug for Phreak {
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> {
write!(f, "Phreak{{ {:?} }}", self.tokens.borrow())
}
}
impl Phreak {
fn new_segment(&mut self, parent_id: SegmentId) -> SegmentId {
let s = self.segments.new_node(Segment::new());
parent_id.append(s, &mut self.segments);
s
}
fn get_segment_id(&self, node: BetaNodeId) -> SegmentId {
self.betanodes.index(node).get().get_segment()
}
fn get_segment(&self, node: BetaNodeId) -> &Segment {
self.segments.index(self.get_segment_id(node)).get()
}
fn get_segment_mut(&mut self, node: BetaNodeId) -> &mut Segment {
self.segments.index_mut(self.get_segment_id(node)).get_mut()
}
fn move_segment_members_at(&mut self, origin: SegmentId, destination: SegmentId, node: BetaNodeId) {
let index;
println!("+before {:?} {:?}", &self.segments[origin].get().betanodes, &self.segments[destination].get().betanodes);
println!(" link {} {}", &self.segments[origin].get().node_linked.borrow(), &self.segments[destination].get().node_linked.borrow());
println!(" mod {} {}", &self.segments[origin].get().node_modified.borrow(), &self.segments[destination].get().node_modified.borrow());
let origin_segment = self.segments[origin].get_mut();
if let Some(r) = origin_segment.betanodes.iter().position(
|item| node.eq(item)) {
index = r;
} else {
panic!("node {:?} should be in origin {:?} {:?}", node, origin, origin_segment);
}
let mut r = origin_segment.betanodes.split_off(index);
let mut r1 = origin_segment.node_linked.borrow_mut().split_off(index);
let mut r2 = origin_segment.node_modified.borrow_mut().split_off(index);
let segment_mut = self.segments[destination].get_mut();
segment_mut.betanodes.append(&mut r);
segment_mut.node_linked.borrow_mut().append(&mut r1);
segment_mut.node_modified.borrow_mut().append(&mut r2);
for (index, node_id) in self.segments[destination].get().betanodes.iter().enumerate() {
let betanode = self.betanodes[*node_id].get_mut();
betanode.set_segment(destination);
betanode.set_segment_index(index);
}
println!("+after {:?} {:?}", &self.segments[origin].get().betanodes, &self.segments[destination].get().betanodes);
println!(" link {} {}", &self.segments[origin].get().node_linked.borrow(), &self.segments[destination].get().node_linked.borrow());
println!(" mod {} {}", &self.segments[origin].get().node_modified.borrow(), &self.segments[destination].get().node_modified.borrow());
}
fn get_rootsegment_id(&self) -> SegmentId {
self.get_segment_id(self.root_node)
}
fn split_segment_after_parentnode_if_required(&mut self, count: usize, parent_id: BetaNodeId) -> SegmentId {
let parent_segment = self.get_segment_id(parent_id);
if count == 1 {
let child_segment = self.new_segment(parent_segment);
let mut children = parent_id.children(&self.betanodes);
let child: BetaNodeId = children.next().unwrap();
self.move_segment_members_at(
parent_segment,
child_segment,
child,
);
self.new_segment(parent_segment)
} else if count > 1 {
self.new_segment(parent_segment)
} else {
parent_segment
}
}
}
impl Phreak {
fn build_or_share_classnode(&mut self, class: &str) -> &mut ClassNode {
self.classes.entry(class.to_owned()).or_insert_with(
|| ClassNode::new()
)
}
fn build_or_share_alphanode(&mut self, class: &str, wme: WmeMatch) -> (bool, AlphaNodeId) {
let cl = self.classes
.get_mut(&class.to_owned())
.expect("class should already be created");
if let Some(node) = cl.alphanodes.get(&wme) {
return (false, *node);
}
let node_id = self.alphanodes.insert(AlphaNode::new(None));
cl.alphanodes.insert(wme, node_id);
(true, node_id)
}
fn node_share_betamemory(&self, parent_id: BetaNodeId) -> either::Either<BetaNodeId, usize> {
let mut count = 0;
for child_id in parent_id.children(&self.betanodes) {
if self.betanodes.index(child_id).get().is_memorynode() {
return either::Left(child_id);
}
count += 1
}
either::Right(count)
}
fn node_new_production(&mut self, parent_id: BetaNodeId, segment_id: SegmentId, callback: Box<dyn ProductionCallback>) -> BetaNodeId {
let production_id = self.betanodes.new_node(BetaNode::new_productionnode(segment_id, callback));
parent_id.prepend(production_id, &mut self.betanodes);
let segment =
self.segments.index_mut(segment_id).get_mut();
segment.push_node(production_id, true, &mut self.betanodes);
BetaNode::init_new_node(production_id,
&mut self.betanodes,
&self.alphanodes,
&mut self.tokens.borrow_mut(),
&self.segments,
&self.nil_fact,
);
production_id
}
fn node_new_betamemory(&mut self, parent_id: BetaNodeId, segment_id: SegmentId) -> BetaNodeId {
let betamemory_id = self.betanodes.new_node(BetaNode::new_memorynode(segment_id));
parent_id.prepend(betamemory_id, &mut self.betanodes);
self.segments.index_mut(segment_id).get_mut()
.push_node(betamemory_id, true, &mut self.betanodes);
BetaNode::init_new_node(
betamemory_id,
&mut self.betanodes,
&self.alphanodes,
&mut self.tokens.borrow_mut(),
&self.segments,
&self.nil_fact,
);
betamemory_id
}
fn build_or_share_betamemory(&mut self, parent_id: BetaNodeId) -> BetaNodeId {
match self.node_share_betamemory(parent_id) {
either::Left(child_id) => child_id,
either::Right(count) => {
let leaf_segment = self.split_segment_after_parentnode_if_required(count, parent_id);
println!("creating a new betamemory in segment {:?}, {:?}", leaf_segment, self.segments.index(leaf_segment));
self.node_new_betamemory(parent_id, leaf_segment)
}
}
}
fn node_share_joinnode(&self, parent_id: BetaNodeId,
amem_id: AlphaNodeId,
tests: &Vec<JoinNodeTest>,
) -> either::Either<BetaNodeId, usize> {
let mut count = 0;
for child_id in parent_id.children(&self.betanodes) {
let child = self.betanodes.get(child_id).unwrap().get();
if let BetaNode::JoinNode(jn) = child {
if (jn.amem == amem_id) & jn.tests.eq(tests) {
println!("shared joinnode {:?}", child_id);
return either::Left(child_id);
}
}
count = count + 1;
}
either::Right(count)
}
fn node_new_joinnode(&mut self, parent_id: BetaNodeId,
amem_id: AlphaNodeId,
tests: Vec<JoinNodeTest>,
segment_id: SegmentId,
) -> BetaNodeId {
let joinnode_id = self.betanodes.new_node(BetaNode::new_joinnode(amem_id, tests, segment_id));
self.alphanodes[amem_id].cell.borrow_mut().items.cleanup();
self.segments.get_mut(segment_id).unwrap().get_mut()
.push_node(joinnode_id,
!self.alphanodes[amem_id].cell.borrow().items.is_empty(),
&mut self.betanodes,
);
parent_id.prepend(joinnode_id, &mut self.betanodes);
let a = self.alphanodes.get_mut(amem_id).unwrap();
a.children.push_front(Either::Right(joinnode_id));
BetaNode::init_new_node(
joinnode_id,
&mut self.betanodes,
&self.alphanodes,
&mut self.tokens.borrow_mut(),
&self.segments,
&self.nil_fact,
);
joinnode_id
}
fn build_or_share_join_node(&mut self, parent_id: BetaNodeId,
amem_id: AlphaNodeId,
tests: Vec<JoinNodeTest>,
) -> BetaNodeId {
match self.node_share_joinnode(parent_id, amem_id, &tests) {
either::Left(child_id) => child_id,
either::Right(count) => {
let leaf_segment = self.split_segment_after_parentnode_if_required(count, parent_id);
println!("creating a new joinnode in segment {}, {:?}", leaf_segment, self.segments.get(leaf_segment));
self.node_new_joinnode(parent_id, amem_id, tests, leaf_segment)
}
}
}
fn node_new_negativenode(&mut self, parent_id: BetaNodeId,
amem_id: AlphaNodeId,
tests: Vec<JoinNodeTest>,
segment_id: SegmentId,
) -> BetaNodeId {
let negativenode_id = self.betanodes.new_node(BetaNode::new_negativenode(amem_id, tests, segment_id));
self.segments.get_mut(segment_id).unwrap().get_mut().push_node(
negativenode_id,
true,
&mut self.betanodes,
);
parent_id.prepend(negativenode_id, &mut self.betanodes);
let a = self.alphanodes.get_mut(amem_id).unwrap();
a.children.push_front(Either::Right(negativenode_id));
BetaNode::init_new_node(
negativenode_id,
&mut self.betanodes,
&self.alphanodes,
&mut self.tokens.borrow_mut(),
&self.segments,
&self.nil_fact,
);
negativenode_id
}
fn build_or_share_negativenode(&mut self, parent_id: BetaNodeId,
amem_id: AlphaNodeId,
tests: Vec<JoinNodeTest>,
) -> BetaNodeId {
let mut count = 0;
for _ in parent_id.children(&self.betanodes) { count = count + 1; }
let leaf_segment = self.split_segment_after_parentnode_if_required(count, parent_id);
println!("creating a new negativenode in segment {}, {:?}", leaf_segment, self.segments.get(leaf_segment));
self.node_new_negativenode(parent_id, amem_id, tests, leaf_segment)
}
fn build_production(&mut self, parent_id: BetaNodeId, callback: Box<dyn ProductionCallback>) -> BetaNodeId {
let leaf_segment = self.split_segment_after_parentnode_if_required(
parent_id.children(&self.betanodes).count(),
parent_id);
self.node_new_production(parent_id, leaf_segment, callback)
}
fn node_new_ncc_pair(
&mut self,
number_of_conjuncts: usize,
segment_id_for_ncc: SegmentId,
segment_id_for_ncp: SegmentId,
) -> (BetaNodeId, BetaNodeId) {
debug_assert_ne!(segment_id_for_ncc, segment_id_for_ncp);
let ncc = self.betanodes.new_node(BetaNode::new_nccnode(self.root_node, segment_id_for_ncc));
let ncp = self.betanodes.new_node(BetaNode::new_nccpartnernode(ncc, segment_id_for_ncp, number_of_conjuncts));
self.segments[segment_id_for_ncc].get_mut().push_node(ncc, true, &mut self.betanodes);
self.segments[segment_id_for_ncp].get_mut().push_node(ncp, true, &mut self.betanodes);
if let BetaNode::NccNode(data) = self.betanodes[ncc].get_mut() {
data.ncp = ncp;
}
(ncc, ncp)
}
fn build_or_share_ncc_nodes(
&mut self,
parent_id: BetaNodeId,
cond: &NccCondition,
earlier: &[&Condition],
) -> BetaNodeId {
let number_of_conjuncts = cond.children.len();
let bottom_of_subnetwork_id =
self.build_or_share_network_for_conditions(parent_id, &cond.children, earlier);
let mut count = 0;
{
let parent = self.betanodes[parent_id].get();
for child in parent_id.children(&self.betanodes) {
count = count + 1;
if let BetaNode::NccNode(ncc) = parent {
if ncc.ncp == bottom_of_subnetwork_id {
return child;
}
}
}
}
let ncc_segment = self.split_segment_after_parentnode_if_required(count, parent_id);
let leaf_segment_id = self.split_segment_after_parentnode_if_required(
bottom_of_subnetwork_id.children(&self.betanodes).count(),
bottom_of_subnetwork_id,
);
let (ncc_id, partner_id) = self.node_new_ncc_pair(number_of_conjuncts, ncc_segment, leaf_segment_id);
parent_id.append(ncc_id, &mut self.betanodes);
bottom_of_subnetwork_id.prepend(partner_id, &mut self.betanodes);
ncc_id
}
fn build_or_share_network_for_conditions(
&mut self,
parent_id: BetaNodeId,
conditions: &[Condition],
earlier: &[&Condition],
) -> BetaNodeId {
let mut current_node: BetaNodeId = parent_id;
let mut conditions_higher_up = Vec::from(earlier);
for condition in conditions {
match condition {
Condition::Positive(cond) => {
self.build_or_share_classnode(&cond.class);
if self.betanodes[current_node].get().is_joinnode() {
current_node = self.build_or_share_betamemory(current_node);
}
let tests = get_join_tests_from_condition(&condition, &conditions_higher_up);
let wme = WmeMatch::from(cond);
let am = self.build_or_share_alphanode(&cond.class, wme);
current_node = self.build_or_share_join_node(current_node, am.1, tests);
}
Condition::Negative(cond) => {
self.build_or_share_classnode(&cond.class);
if self.betanodes[current_node].get().is_joinnode() {
current_node = self.build_or_share_betamemory(current_node);
}
let tests = get_join_tests_from_condition(&condition, &conditions_higher_up);
let wme = WmeMatch::from(cond);
let am = self.build_or_share_alphanode(&cond.class, wme);
current_node = self.build_or_share_negativenode(current_node, am.1, tests);
}
Condition::Ncc(cond) => {
current_node = self.build_or_share_ncc_nodes(current_node, cond, &conditions_higher_up)
}
}
conditions_higher_up.push(condition);
}
current_node
}
}
#[cfg(test)]
mod tests {
use std::cell::Cell;
use std::sync::Arc;
use phreak_facts::FactsBuilder;
use phreak_rules::{PrintCallBack, ProductionCallback};
use test_case::test_case;
use crate::jointest::JoinTestField;
use crate::memory::Memory;
use crate::segment::print_segment_tree;
use crate::traits::Actionable;
use super::*;
use crate::predicates;
#[derive(Debug)]
struct CountCallback { counter: Arc<Cell<usize>> }
impl ProductionCallback for CountCallback {
fn activate(&self) {
self.counter.replace(self.counter.take() + 1);
}
fn deactivate(&self) {
self.counter.replace(self.counter.take() - 1);
}
}
fn ball(id: &str, color: &str) -> FactObject {
FactsBuilder::new("Ball".to_owned())
.add_attributes(id.to_owned(), "object".to_owned(), "ball".to_owned())
.add_attributes(id.to_owned(), "color".to_owned(), color.to_owned())
.build()
}
#[allow(unused_variables)]
fn helper_build_network_join_two_facts(p: &mut Phreak, callback: Box<dyn ProductionCallback>) {
let cl = p.build_or_share_classnode("Plane");
let a1 = p.build_or_share_alphanode("Plane", WmeMatch::new(
Memory::Any,
Memory::Value("name".to_owned()),
Memory::Value("spitfire".to_owned()),
));
let a2 = p.build_or_share_alphanode("Plane", WmeMatch::new(
Memory::Any,
Memory::Value("color".to_owned()),
Memory::Value("black".to_owned()),
));
let cl = p.classes.get("Plane").unwrap();
let j1 = p.build_or_share_join_node(p.root_node, a1.1, vec!());
let m = p.build_or_share_betamemory(j1);
let j2 = p.build_or_share_join_node(m, a2.1,
vec!(JoinNodeTest {
f1: JoinTestField::Field1,
condition_number_of_arg2: 1,
f2: JoinTestField::Field1,
predicate: predicates::TestCondition::Equal(predicates::Eq)
}));
let p1 = p.build_production(j2, callback);
}
#[allow(unused_variables)]
fn helper_build_network_balls(p: &mut Phreak, callbacks: [Box<dyn ProductionCallback>; 2]) {
let [callback1, callback2] = callbacks;
let cl = p.build_or_share_classnode("Ball");
let a1 = p.build_or_share_alphanode("Ball", WmeMatch::new(
Memory::Any,
Memory::Value("color".to_owned()),
Memory::Value("blue".to_owned()),
));
let a2 = p.build_or_share_alphanode("Ball", WmeMatch::new(
Memory::Any,
Memory::Value("size".to_owned()),
Memory::Value("medium".to_owned()),
));
let a3 = p.build_or_share_alphanode("Ball", WmeMatch::new(
Memory::Any,
Memory::Value("color".to_owned()),
Memory::Value("red".to_owned()),
));
let cl = p.classes.get("Ball").unwrap();
let j1 = p.build_or_share_join_node(p.root_node, a1.1, vec!());
let j2 = p.build_or_share_join_node(p.root_node, a2.1, vec!());
let m = p.build_or_share_betamemory(j2);
let j3 = p.build_or_share_join_node(m, a3.1,
vec!(JoinNodeTest {
f1: JoinTestField::Field1,
condition_number_of_arg2: 1,
f2: JoinTestField::Field1,
predicate: predicates::TestCondition::Equal(predicates::Eq)
}));
let p1 = p.build_production(j1, callback1);
let p2 = p.build_production(j3, callback2);
}
#[allow(unused_variables)]
fn helper_build_network_join_two_related_facts1(p: &mut Phreak, callback: Box<dyn ProductionCallback>) {
let cl = p.build_or_share_classnode("Plane");
let a1 = p.build_or_share_alphanode("Plane", WmeMatch::new(
Memory::Any,
Memory::Value("name".to_owned()),
Memory::Value("messerschmitt".to_owned()),
));
let a2 = p.build_or_share_alphanode("Plane", WmeMatch::new(
Memory::Any,
Memory::Value("color".to_owned()),
Memory::Value("black".to_owned()),
));
let cl = p.classes.get("Plane").unwrap();
let j1 = p.build_or_share_join_node(p.root_node, a1.1, vec!());
let m = p.build_or_share_betamemory(j1);
let j2 = p.build_or_share_join_node(m, a2.1,
vec!(JoinNodeTest {
f1: JoinTestField::Field1,
condition_number_of_arg2: 1,
f2: JoinTestField::Field1,
predicate: predicates::TestCondition::Equal(predicates::Eq)
}));
let p1 = p.build_production(j2, callback);
}
#[allow(unused_variables)]
fn helper_build_network_join_two_related_facts2(p: &mut Phreak, callback: Box<dyn ProductionCallback>) {
let cl = p.build_or_share_classnode("Plane");
let a1 = p.build_or_share_alphanode("Plane", WmeMatch::new(
Memory::Any,
Memory::Value("name".to_owned()),
Memory::Value("spitfire".to_owned()),
));
let a2 = p.build_or_share_alphanode("Plane", WmeMatch::new(
Memory::Any,
Memory::Value("color".to_owned()),
Memory::Value("red".to_owned()),
));
let cl = p.classes.get("Plane").unwrap();
let j1 = p.build_or_share_join_node(p.root_node, a1.1, vec!());
let m = p.build_or_share_betamemory(j1);
let j2 = p.build_or_share_join_node(m, a2.1,
vec!(JoinNodeTest {
f1: JoinTestField::Field1,
condition_number_of_arg2: 1,
f2: JoinTestField::Field1,
predicate: predicates::TestCondition::Equal(predicates::Eq)
}));
let p1 = p.build_production(j2, callback);
}
#[test]
fn test_build_network() {
let mut p = Phreak::new();
helper_build_network_join_two_facts(&mut p, Box::new(PrintCallBack {}));
assert_eq!(p.classes.len(), 1);
assert_eq!(p.alphanodes.len(), 2);
assert_eq!(p.betanodes.count(), 5);
assert_eq!(p.segments.count(), 1);
let segment = p.segments[p.get_rootsegment_id()].get();
assert_eq!(segment.betanodes.len(), 5);
assert_eq!(segment.node_linked.borrow().len(), segment.betanodes.len());
assert_eq!(segment.node_modified.borrow().len(), segment.betanodes.len());
p.dump_structure();
p.dump_segment_structure();
p.process_tree_structure();
}
#[test_case(
vec ! (
FactsBuilder::new("Plane".to_owned())
.add_attributes("1".to_owned(), "name".to_owned(), "spitfire".to_owned())
.add_attributes("1".to_owned(), "color".to_owned(), "black".to_owned())
.build()).as_slice() => 1; "one join"
)]
#[test_case(
vec ! (
FactsBuilder::new("Plane".to_owned())
.add_attributes("1".to_owned(), "name".to_owned(), "spitfire".to_owned())
.add_attributes("1".to_owned(), "color".to_owned(), "black".to_owned())
.build(),
FactsBuilder::new("Plane".to_owned())
.add_attributes("2".to_owned(), "name".to_owned(), "spitfire".to_owned())
.add_attributes("2".to_owned(), "color".to_owned(), "black".to_owned())
.build(),
).as_slice() => 2; "two at once"
)]
#[test_case(
vec ! (
FactsBuilder::new("Plane".to_owned())
.add_attributes("1".to_owned(), "name".to_owned(), "messerschmitt".to_owned())
.add_attributes("1".to_owned(), "color".to_owned(), "black".to_owned())
.build()).as_slice() => 0; "one not to join for field1"
)]
#[test_case(
vec ! (
FactsBuilder::new("Plane".to_owned())
.add_attributes("1".to_owned(), "name".to_owned(), "spitfire".to_owned())
.add_attributes("1".to_owned(), "color".to_owned(), "red".to_owned())
.build()).as_slice() => 0; "one not to join for field2"
)]
#[test_case(
vec ! (
FactsBuilder::new("Plane".to_owned())
.add_attributes("1".to_owned(), "name".to_owned(), "spitfire".to_owned())
.add_attributes("1".to_owned(), "color".to_owned(), "black".to_owned())
.build(),
FactsBuilder::new("Plane".to_owned())
.add_attributes("2".to_owned(), "name".to_owned(), "spitfire".to_owned())
.add_attributes("2".to_owned(), "color".to_owned(), "red".to_owned())
.build(),
FactsBuilder::new("Plane".to_owned())
.add_attributes("3".to_owned(), "name".to_owned(), "spitfire".to_owned())
.add_attributes("3".to_owned(), "color".to_owned(), "black".to_owned())
.build(),
FactsBuilder::new("Plane".to_owned())
.add_attributes("4".to_owned(), "name".to_owned(), "messerschmitt".to_owned())
.add_attributes("4".to_owned(), "color".to_owned(), "black".to_owned())
.build(),
).as_slice() => 2; "mixed"
)]
fn test_facts_join(arr: &[FactObject]) -> usize {
let mut p = Phreak::new();
let counter1: Arc<Cell<usize>> = Arc::new(Cell::new(0));
helper_build_network_join_two_facts(&mut p, Box::new(CountCallback { counter: counter1.clone() }));
p.process_tree_structure();
assert_eq!(counter1.get(), 0);
p.add_facts(arr);
counter1.get()
}
#[test_case(
vec ! (
FactsBuilder::new("Plane".to_owned())
.add_attributes("1".to_owned(), "name".to_owned(), "spitfire".to_owned())
.add_attributes("1".to_owned(), "color".to_owned(), "black".to_owned())
.build()).as_slice() => (1, 0, 0)
)]
#[test_case(
vec ! (
FactsBuilder::new("Plane".to_owned())
.add_attributes("1".to_owned(), "name".to_owned(), "spitfire".to_owned())
.add_attributes("1".to_owned(), "color".to_owned(), "red".to_owned())
.build()).as_slice() => (0, 0, 1)
)]
#[test_case(
vec ! (
FactsBuilder::new("Plane".to_owned())
.add_attributes("1".to_owned(), "name".to_owned(), "spitfire".to_owned())
.add_attributes("1".to_owned(), "color".to_owned(), "red".to_owned())
.build(),
FactsBuilder::new("Plane".to_owned())
.add_attributes("2".to_owned(), "name".to_owned(), "spitfire".to_owned())
.add_attributes("2".to_owned(), "color".to_owned(), "green".to_owned())
.build(),
FactsBuilder::new("Plane".to_owned())
.add_attributes("3".to_owned(), "name".to_owned(), "spitfire".to_owned())
.add_attributes("3".to_owned(), "color".to_owned(), "black".to_owned())
.build(),
FactsBuilder::new("Plane".to_owned())
.add_attributes("4".to_owned(), "name".to_owned(), "spitfire".to_owned())
.add_attributes("4".to_owned(), "color".to_owned(), "red".to_owned())
.build(),
FactsBuilder::new("Plane".to_owned())
.add_attributes("5".to_owned(), "name".to_owned(), "messerschmitt".to_owned())
.add_attributes("5".to_owned(), "color".to_owned(), "black".to_owned())
.build(),
).as_slice() => (1, 1, 2)
)]
fn test_facts_join_complex(arr: &[FactObject]) -> (usize, usize, usize) {
let mut p = Phreak::new();
let counter1: Arc<Cell<usize>> = Arc::new(Cell::new(0));
let counter2: Arc<Cell<usize>> = Arc::new(Cell::new(0));
let counter3: Arc<Cell<usize>> = Arc::new(Cell::new(0));
helper_build_network_join_two_facts(&mut p, Box::new(CountCallback { counter: counter1.clone() }));
helper_build_network_join_two_related_facts1(&mut p, Box::new(CountCallback { counter: counter2.clone() }));
helper_build_network_join_two_related_facts2(&mut p, Box::new(CountCallback { counter: counter3.clone() }));
p.process_tree_structure();
assert_eq!(counter1.get(), 0);
p.add_facts(arr);
(counter1.get(), counter2.get(), counter3.get())
}
#[test_case(
vec ! (
FactsBuilder::new("Plane".to_owned())
.add_attributes("1".to_owned(), "name".to_owned(), "spitfire".to_owned())
.build(),
FactsBuilder::new("Plane".to_owned())
.add_attributes("1".to_owned(), "color".to_owned(), "black".to_owned())
.build(),
).as_slice() => vec ! (0, 1); "incremental processing"
)]
fn test_incremental(arr: &[FactObject]) -> Vec<usize> {
let mut p = Phreak::new();
let counter1: Arc<Cell<usize>> = Arc::new(Cell::new(0));
helper_build_network_join_two_facts(&mut p, Box::new(CountCallback { counter: counter1.clone() }));
p.process_tree_structure();
let mut answers = vec!();
for fact in arr {
println!("+++ iteration started");
p.add_facts(&[fact.clone()]);
println!("+++ iteration complete");
answers.push(counter1.get());
}
answers
}
#[test_case(
vec ! (
FactsBuilder::new("Ball".to_owned())
.add_attributes("3".to_owned(), "color".to_owned(), "blue".to_owned())
.add_attributes("3".to_owned(), "size".to_owned(), "medium".to_owned())
.build(),
).as_slice() => vec ! (
(1, 0), (0, 0),
); "mirrored add and remove single"
)]
#[test_case(
vec ! (
FactsBuilder::new("Ball".to_owned())
.add_attributes("1".to_owned(), "color".to_owned(), "green".to_owned())
.add_attributes("1".to_owned(), "size".to_owned(), "large".to_owned())
.build(),
FactsBuilder::new("Ball".to_owned())
.add_attributes("2".to_owned(), "color".to_owned(), "yellow".to_owned())
.add_attributes("2".to_owned(), "size".to_owned(), "small".to_owned())
.build(),
FactsBuilder::new("Ball".to_owned())
.add_attributes("3".to_owned(), "color".to_owned(), "red".to_owned())
.add_attributes("3".to_owned(), "size".to_owned(), "medium".to_owned())
.build(),
FactsBuilder::new("Ball".to_owned())
.add_attributes("4".to_owned(), "color".to_owned(), "blue".to_owned())
.add_attributes("4".to_owned(), "size".to_owned(), "tiny".to_owned())
.build(),
FactsBuilder::new("Ball".to_owned())
.add_attributes("5".to_owned(), "color".to_owned(), "green".to_owned())
.add_attributes("5".to_owned(), "size".to_owned(), "small".to_owned())
.build(),
FactsBuilder::new("Ball".to_owned())
.add_attributes("6".to_owned(), "color".to_owned(), "red".to_owned())
.add_attributes("6".to_owned(), "size".to_owned(), "medium".to_owned())
.build(),
FactsBuilder::new("Ball".to_owned())
.add_attributes("7".to_owned(), "color".to_owned(), "blue".to_owned())
.add_attributes("7".to_owned(), "size".to_owned(), "medium".to_owned())
.build(),
).as_slice() => vec ! (
(0, 0), (0, 0), (0, 1), (1, 1), (1, 1), (1, 2), (2, 2),
(1, 2), (1, 1), (1, 1), (0, 1), (0, 0), (0, 0), (0, 0),
); "mirrored add and remove sequence"
)]
#[test_case(
vec ! (
FactsBuilder::new("Ball".to_owned())
.add_attributes("1".to_owned(), "color".to_owned(), "blue".to_owned())
.add_attributes("1".to_owned(), "size".to_owned(), "medium".to_owned())
.build(),
FactsBuilder::new("Ball".to_owned())
.add_attributes("2".to_owned(), "color".to_owned(), "blue".to_owned())
.add_attributes("2".to_owned(), "size".to_owned(), "medium".to_owned())
.build(),
).as_slice() => vec ! (
(1, 0), (2, 0),
(1, 0), (0, 0),
); "mirrored add and remove duplicate single condition match"
)]
#[test_case(
vec ! (
FactsBuilder::new("Ball".to_owned())
.add_attributes("1".to_owned(), "color".to_owned(), "red".to_owned())
.add_attributes("1".to_owned(), "size".to_owned(), "medium".to_owned())
.build(),
FactsBuilder::new("Ball".to_owned())
.add_attributes("2".to_owned(), "color".to_owned(), "red".to_owned())
.add_attributes("2".to_owned(), "size".to_owned(), "medium".to_owned())
.build(),
).as_slice() => vec ! (
(0, 1), (0, 2),
(0, 1), (0, 0),
); "mirrored add and remove duplicate double condition match"
)]
#[test_case(
vec ! (
FactsBuilder::new("Ball".to_owned())
.add_attributes("1".to_owned(), "size".to_owned(), "medium".to_owned())
.add_attributes("1".to_owned(), "color".to_owned(), "red".to_owned())
.build(),
FactsBuilder::new("Ball".to_owned())
.add_attributes("2".to_owned(), "size".to_owned(), "medium".to_owned())
.add_attributes("2".to_owned(), "color".to_owned(), "red".to_owned())
.build(),
).as_slice() => vec ! (
(0, 1), (0, 2),
(0, 1), (0, 0),
); "mirrored add and remove duplicate double condition match, other fact order"
)]
fn test_add_and_remove_facts(arr: &[FactObject]) -> Vec<(usize, usize)> {
let mut p = Phreak::new();
let counter1: Arc<Cell<usize>> = Arc::new(Cell::new(0));
let counter2: Arc<Cell<usize>> = Arc::new(Cell::new(0));
helper_build_network_balls(&mut p, [
Box::new(CountCallback { counter: counter1.clone() }),
Box::new(CountCallback { counter: counter2.clone() }),
]);
p.process_tree_structure();
print_betanetwork_tree(p.root_node, &p.tokens.borrow(), &p.betanodes);
let mut answers = vec!();
for fact in arr {
p.add_facts(&[fact.clone()]);
print_betanetwork_tree(p.root_node, &p.tokens.borrow(), &p.betanodes);
answers.push((counter1.get(), counter2.get()));
}
for fact in arr.iter().rev() {
p.remove_facts(&[fact.clone()]);
print_betanetwork_tree(p.root_node, &p.tokens.borrow(), &p.betanodes);
answers.push((counter1.get(), counter2.get()));
}
answers
}
#[allow(unused_variables)]
fn helper_build_network_single_negative_node(p: &mut Phreak, callback: Box<dyn ProductionCallback>) {
let cl = p.build_or_share_classnode("Ball");
let a1 = p.build_or_share_alphanode("Ball", WmeMatch::new(
Memory::Any,
Memory::Value("color".to_owned()),
Memory::Value("red".to_owned()),
));
let cl = p.classes.get("Ball").unwrap();
let n1 = p.build_or_share_negativenode(p.root_node, a1.1, vec!());
let p1 = p.build_production(n1, callback);
}
#[allow(unused_variables)]
fn helper_build_network_two_negative_nodes(p: &mut Phreak, callback: Box<dyn ProductionCallback>) {
let cl = p.build_or_share_classnode("Ball");
let a0 = p.build_or_share_alphanode("Ball", WmeMatch::new(
Memory::Any,
Memory::Value("color".to_owned()),
Memory::Any,
));
let a1 = p.build_or_share_alphanode("Ball", WmeMatch::new(
Memory::Any,
Memory::Value("color".to_owned()),
Memory::Value("red".to_owned()),
));
let a2 = p.build_or_share_alphanode("Ball", WmeMatch::new(
Memory::Any,
Memory::Value("color".to_owned()),
Memory::Value("blue".to_owned()),
));
let cl = p.classes.get("Ball").unwrap();
let n0 = p.build_or_share_join_node(p.root_node, a0.1, vec!());
let mem = p.build_or_share_betamemory(n0);
let n1 = p.build_or_share_negativenode(mem, a1.1, vec!(
JoinNodeTest {
f1: JoinTestField::Field1,
condition_number_of_arg2: 1,
f2: JoinTestField::Field1,
predicate: predicates::TestCondition::Equal(predicates::Eq)
}
));
let n2 = p.build_or_share_negativenode(
n1, a2.1,
vec!(JoinNodeTest {
f1: JoinTestField::Field1,
condition_number_of_arg2: 2,
f2: JoinTestField::Field1,
predicate: predicates::TestCondition::Equal(predicates::Eq)
}),
);
let p1 = p.build_production(n2, callback);
}
#[test_case(
vec ! (
FactsBuilder::new("Ball".to_owned())
.add_attributes("1".to_owned(), "color".to_owned(), "red".to_owned())
.add_attributes("1".to_owned(), "size".to_owned(), "medium".to_owned())
.build(),
).as_slice() => vec ! (
1, 0, 1
); "single_negative_conjunct_add_one_fact"
)]
#[test_case(
vec ! (
FactsBuilder::new("Ball".to_owned())
.add_attributes("1".to_owned(), "color".to_owned(), "yellow".to_owned())
.add_attributes("1".to_owned(), "size".to_owned(), "medium".to_owned())
.build(),
FactsBuilder::new("Ball".to_owned())
.add_attributes("2".to_owned(), "color".to_owned(), "red".to_owned())
.add_attributes("2".to_owned(), "size".to_owned(), "small".to_owned())
.build(),
FactsBuilder::new("Ball".to_owned())
.add_attributes("3".to_owned(), "color".to_owned(), "blue".to_owned())
.add_attributes("3".to_owned(), "size".to_owned(), "large".to_owned())
.build(),
).as_slice() => vec ! (
1, 1, 0, 0, 0, 1, 1
); "single_negative_conjunct_add_multiple_fact"
)]
fn test_single_negative_conjunct_add_fact(arr: &[FactObject]) -> Vec<usize> {
let mut p = Phreak::new();
let counter1: Arc<Cell<usize>> = Arc::new(Cell::new(0));
helper_build_network_single_negative_node(
&mut p,
Box::new(CountCallback { counter: counter1.clone() }),
);
p.process_tree_structure();
print_betanetwork_tree(p.root_node, &p.tokens.borrow(), &p.betanodes);
let mut answers = vec!();
answers.push(counter1.get());
for fact in arr {
p.add_facts(&[fact.clone()]);
print_betanetwork_tree(p.root_node, &p.tokens.borrow(), &p.betanodes);
answers.push(counter1.get());
}
for fact in arr.iter().rev() {
p.remove_facts(&[fact.clone()]);
answers.push(counter1.get());
}
answers
}
#[test_case(
vec ! (
FactsBuilder::new("Ball".to_owned())
.add_attributes("1".to_owned(), "color".to_owned(), "red".to_owned())
.add_attributes("1".to_owned(), "size".to_owned(), "medium".to_owned())
.build(),
FactsBuilder::new("Ball".to_owned())
.add_attributes("2".to_owned(), "color".to_owned(), "blue".to_owned())
.add_attributes("2".to_owned(), "size".to_owned(), "small".to_owned())
.build(),
FactsBuilder::new("Ball".to_owned())
.add_attributes("3".to_owned(), "color".to_owned(), "green".to_owned())
.add_attributes("3".to_owned(), "size".to_owned(), "large".to_owned())
.build(),
FactsBuilder::new("Ball".to_owned())
.add_attributes("4".to_owned(), "color".to_owned(), "blue".to_owned())
.add_attributes("4".to_owned(), "size".to_owned(), "medium".to_owned())
.build(),
FactsBuilder::new("Ball".to_owned())
.add_attributes("5".to_owned(), "color".to_owned(), "yellow".to_owned())
.add_attributes("5".to_owned(), "size".to_owned(), "small".to_owned())
.build(),
FactsBuilder::new("Ball".to_owned())
.add_attributes("6".to_owned(), "color".to_owned(), "red".to_owned())
.add_attributes("6".to_owned(), "size".to_owned(), "small".to_owned())
.build(),
).as_slice() => vec ! (
0, 0, 0, 1, 1, 2, 2
); "two_negative_conjuncts_add_facts"
)]
fn test_two_negative_conjunct_add_fact(arr: &[FactObject]) -> Vec<usize> {
let mut p = Phreak::new();
let counter1: Arc<Cell<usize>> = Arc::new(Cell::new(0));
helper_build_network_two_negative_nodes(
&mut p,
Box::new(CountCallback { counter: counter1.clone() }),
);
p.process_tree_structure();
print_betanetwork_tree(p.root_node, &p.tokens.borrow(), &p.betanodes);
let mut answers = vec!();
answers.push(counter1.get());
for fact in arr {
println!("ADD FACT {:?}", fact);
p.add_facts(&[fact.clone()]);
print_betanetwork_tree(p.root_node, &p.tokens.borrow(), &p.betanodes);
answers.push(counter1.get());
}
answers
}
#[test_case(
vec ! (
FactsBuilder::new("Ball".to_owned())
.add_attributes("1".to_owned(), "color".to_owned(), "red".to_owned())
.add_attributes("1".to_owned(), "size".to_owned(), "medium".to_owned())
.build(),
FactsBuilder::new("Ball".to_owned())
.add_attributes("2".to_owned(), "color".to_owned(), "blue".to_owned())
.add_attributes("2".to_owned(), "size".to_owned(), "small".to_owned())
.build(),
FactsBuilder::new("Ball".to_owned())
.add_attributes("3".to_owned(), "color".to_owned(), "green".to_owned())
.add_attributes("3".to_owned(), "size".to_owned(), "large".to_owned())
.build(),
FactsBuilder::new("Ball".to_owned())
.add_attributes("4".to_owned(), "color".to_owned(), "blue".to_owned())
.add_attributes("4".to_owned(), "size".to_owned(), "medium".to_owned())
.build(),
FactsBuilder::new("Ball".to_owned())
.add_attributes("5".to_owned(), "color".to_owned(), "yellow".to_owned())
.add_attributes("5".to_owned(), "size".to_owned(), "small".to_owned())
.build(),
FactsBuilder::new("Ball".to_owned())
.add_attributes("6".to_owned(), "color".to_owned(), "red".to_owned())
.add_attributes("6".to_owned(), "size".to_owned(), "small".to_owned())
.build(),
).as_slice() => vec ! (
0, 0, 0, 1, 1, 2, 2, 2, 1, 1, 0, 0, 0
); "two_negative_conjuncts_add_remove_facts"
)]
fn test_two_negative_conjunct_add_and_remove_fact(arr: &[FactObject]) -> Vec<usize> {
let mut p = Phreak::new();
let counter1: Arc<Cell<usize>> = Arc::new(Cell::new(0));
helper_build_network_two_negative_nodes(
&mut p,
Box::new(CountCallback { counter: counter1.clone() }),
);
p.process_tree_structure();
print_betanetwork_tree(p.root_node, &p.tokens.borrow(), &p.betanodes);
let mut answers = vec!();
answers.push(counter1.get());
for fact in arr {
println!("ADD FACT {:?}", fact);
p.add_facts(&[fact.clone()]);
print_betanetwork_tree(p.root_node, &p.tokens.borrow(), &p.betanodes);
answers.push(counter1.get());
}
for fact in arr.iter().rev() {
println!("REMOVE FACT {:?}", fact);
p.remove_facts(&[fact.clone()]);
print_betanetwork_tree(p.root_node, &p.tokens.borrow(), &p.betanodes);
answers.push(counter1.get());
}
answers
}
#[test]
fn test_two_negative_conjunct_remove_fact() {
let mut p = Phreak::new();
let counter1: Arc<Cell<usize>> = Arc::new(Cell::new(0));
helper_build_network_two_negative_nodes(
&mut p,
Box::new(CountCallback { counter: counter1.clone() }),
);
p.process_tree_structure();
let yellow =
FactsBuilder::new("Ball".to_owned())
.add_attributes("1".to_owned(), "color".to_owned(), "yellow".to_owned())
.build();
let red = FactsBuilder::new("Ball".to_owned())
.add_attributes("1".to_owned(), "color".to_owned(), "red".to_owned())
.build();
let blue = FactsBuilder::new("Ball".to_owned())
.add_attributes("1".to_owned(), "color".to_owned(), "blue".to_owned())
.build();
print_betanetwork_tree(p.root_node, &p.tokens.borrow(), &p.betanodes);
assert_eq!(counter1.get(), 0);
p.add_facts(&[yellow.clone()]);
print_betanetwork_tree(p.root_node, &p.tokens.borrow(), &p.betanodes);
assert_eq!(counter1.get(), 1);
p.add_facts(&[red.clone()]);
print_betanetwork_tree(p.root_node, &p.tokens.borrow(), &p.betanodes);
assert_eq!(counter1.get(), 0);
p.add_facts(&[blue.clone()]);
print_betanetwork_tree(p.root_node, &p.tokens.borrow(), &p.betanodes);
assert_eq!(counter1.get(), 0);
p.remove_facts(&[red.clone()]);
print_betanetwork_tree(p.root_node, &p.tokens.borrow(), &p.betanodes);
assert_eq!(counter1.get(), 0);
p.remove_facts(&[blue.clone()]);
print_betanetwork_tree(p.root_node, &p.tokens.borrow(), &p.betanodes);
assert_eq!(counter1.get(), 1);
p.remove_facts(&[yellow.clone()]);
print_betanetwork_tree(p.root_node, &p.tokens.borrow(), &p.betanodes);
assert_eq!(counter1.get(), 0);
}
#[allow(unused_variables)]
fn helper_build_network_two_negative_conjuncts(p: &mut Phreak, callback: Box<dyn ProductionCallback>) {
let cl = p.build_or_share_classnode("Ball");
let a0 = p.build_or_share_alphanode("Ball", WmeMatch::new(
Memory::Any,
Memory::Value("color".to_owned()),
Memory::Any,
));
let a1 = p.build_or_share_alphanode("Ball", WmeMatch::new(
Memory::Any,
Memory::Value("color".to_owned()),
Memory::Value("red".to_owned()),
));
let a2 = p.build_or_share_alphanode("Ball", WmeMatch::new(
Memory::Any,
Memory::Value("color".to_owned()),
Memory::Value("blue".to_owned()),
));
let cl = p.classes.get("Ball").unwrap();
let n0 = p.build_or_share_join_node(p.root_node, a0.1, vec!());
let mem = p.build_or_share_betamemory(n0);
let n1 = p.build_or_share_join_node(mem, a1.1, vec!(
JoinNodeTest {
f1: JoinTestField::Field1,
condition_number_of_arg2: 1,
f2: JoinTestField::Field1,
predicate: predicates::TestCondition::Equal(predicates::Eq)
}
));
println!("-- SEGMENTS {:?}", p.segments);
let ncc1_segment_id = p.split_segment_after_parentnode_if_required(1, mem);
let n1_segment_id = p.betanodes[n1].get().get_segment();
println!("-- SEGMENTS {:?}", p.segments);
assert_ne!(n1_segment_id, ncc1_segment_id);
assert_ne!(n1_segment_id, p.get_rootsegment_id());
println!("-- ncc1_segment_id {:?}", ncc1_segment_id);
println!("-- n1_segment_id {:?}", n1_segment_id);
let (ncc1, ncp1) = p.node_new_ncc_pair(1, ncc1_segment_id, n1_segment_id);
n1.prepend(ncp1, &mut p.betanodes);
mem.append(ncc1, &mut p.betanodes);
println!("-- SEGMENTS {:?}", p.segments);
let n2 = p.build_or_share_join_node(
ncc1, a2.1,
vec!(JoinNodeTest {
f1: JoinTestField::Field1,
condition_number_of_arg2: 2,
f2: JoinTestField::Field1,
predicate: predicates::TestCondition::Equal(predicates::Eq)
}),
);
println!("-- SEGMENTS {:?}", p.segments);
let ncc2_segment_id = p.split_segment_after_parentnode_if_required(1, ncc1);
let n2_segment_id = p.betanodes[n2].get().get_segment();
let (ncc2, ncp2) = p.node_new_ncc_pair(1, ncc2_segment_id, n2_segment_id);
n2.prepend(ncp2, &mut p.betanodes);
ncc1.append(ncc2, &mut p.betanodes);
let p1 = p.build_production(ncc2, callback);
}
#[test]
fn test_two_negative_multi_conjunct_remove_fact() {
let mut p = Phreak::new();
let counter1: Arc<Cell<usize>> = Arc::new(Cell::new(0));
helper_build_network_two_negative_conjuncts(
&mut p,
Box::new(CountCallback { counter: counter1.clone() }),
);
p.process_tree_structure();
print_betanetwork_tree(p.root_node, &p.tokens.borrow(), &p.betanodes);
assert_eq!(counter1.get(), 0);
p.add_facts(&[ball("1", "yellow")]);
print_betanetwork_tree(p.root_node, &p.tokens.borrow(), &p.betanodes);
assert_eq!(counter1.get(), 1);
p.add_facts(&[ball("1", "red")]);
print_betanetwork_tree(p.root_node, &p.tokens.borrow(), &p.betanodes);
assert_eq!(counter1.get(), 0);
p.add_facts(&[ball("1", "blue")]);
print_betanetwork_tree(p.root_node, &p.tokens.borrow(), &p.betanodes);
assert_eq!(counter1.get(), 0);
p.remove_facts(&[ball("1", "red")]);
print_betanetwork_tree(p.root_node, &p.tokens.borrow(), &p.betanodes);
assert_eq!(counter1.get(), 0);
p.remove_facts(&[ball("1", "blue")]);
print_betanetwork_tree(p.root_node, &p.tokens.borrow(), &p.betanodes);
assert_eq!(counter1.get(), 1);
p.remove_facts(&[ball("1", "yellow")]);
print_betanetwork_tree(p.root_node, &p.tokens.borrow(), &p.betanodes);
assert_eq!(counter1.get(), 0);
}
#[test]
fn test_two_negative_multi_conjunct_add_and_remove_one_fact() {
let mut p = Phreak::new();
let counter1: Arc<Cell<usize>> = Arc::new(Cell::new(0));
helper_build_network_two_negative_conjuncts(
&mut p,
Box::new(CountCallback { counter: counter1.clone() }),
);
p.process_tree_structure();
print_betanetwork_tree(p.root_node, &p.tokens.borrow(), &p.betanodes);
assert_eq!(counter1.get(), 0);
p.add_facts(&[ball("1", "red")]);
print_betanetwork_tree(p.root_node, &p.tokens.borrow(), &p.betanodes);
assert_eq!(counter1.get(), 0);
p.remove_facts(&[ball("1", "red")]);
print_betanetwork_tree(p.root_node, &p.tokens.borrow(), &p.betanodes);
assert_eq!(counter1.get(), 0);
p.add_facts(&[ball("1", "yellow")]);
print_betanetwork_tree(p.root_node, &p.tokens.borrow(), &p.betanodes);
assert_eq!(counter1.get(), 1);
p.remove_facts(&[ball("1", "yellow")]);
print_betanetwork_tree(p.root_node, &p.tokens.borrow(), &p.betanodes);
assert_eq!(counter1.get(), 0);
p.add_facts(&[ball("1", "blue")]);
print_betanetwork_tree(p.root_node, &p.tokens.borrow(), &p.betanodes);
assert_eq!(counter1.get(), 0);
p.remove_facts(&[ball("1", "blue")]);
print_betanetwork_tree(p.root_node, &p.tokens.borrow(), &p.betanodes);
assert_eq!(counter1.get(), 0);
}
#[test]
fn test_root_negative() {
let mut p = Phreak::new();
let counter1: Arc<Cell<usize>> = Arc::new(Cell::new(0));
let cl = p.build_or_share_classnode("Ball");
let a0 = p.build_or_share_alphanode("Ball", WmeMatch::new(
Memory::Any,
Memory::Value("color".to_owned()),
Memory::Value("black".to_owned()),
));
let cl = p.classes.get("Ball").unwrap();
let n1 = p.build_or_share_negativenode(p.root_node, a0.1, vec!());
let p1 = p.build_production(n1, Box::new(CountCallback { counter: counter1.clone() }));
p.process_tree_structure();
print_betanetwork_tree(p.root_node, &p.tokens.borrow(), &p.betanodes);
assert_eq!(counter1.get(), 1);
p.add_facts(&[ball("1", "red")]);
print_betanetwork_tree(p.root_node, &p.tokens.borrow(), &p.betanodes);
assert_eq!(counter1.get(), 1);
p.add_facts(&[ball("2", "black")]);
print_betanetwork_tree(p.root_node, &p.tokens.borrow(), &p.betanodes);
assert_eq!(counter1.get(), 0);
p.remove_facts(&[ball("1", "red")]);
print_betanetwork_tree(p.root_node, &p.tokens.borrow(), &p.betanodes);
assert_eq!(counter1.get(), 0);
p.remove_facts(&[ball("2", "black")]);
print_betanetwork_tree(p.root_node, &p.tokens.borrow(), &p.betanodes);
assert_eq!(counter1.get(), 1);
}
#[test]
fn test_matrix_1() {
let mut p = Phreak::new();
let counter1: Arc<Cell<usize>> = Arc::new(Cell::new(0));
let r = p.root_node;
let p1 = p.build_production(r, Box::new(CountCallback { counter: counter1.clone() }));
p.process_tree_structure();
print_betanetwork_tree(r, &p.tokens.borrow(), &p.betanodes);
assert_eq!(counter1.get(), 1);
}
#[test]
fn test_matrix_2() {
let mut p = Phreak::new();
let counter1: Arc<Cell<usize>> = Arc::new(Cell::new(0));
let r = p.root_node;
let cl = p.build_or_share_classnode("Ball");
let a0 = p.build_or_share_alphanode("Ball", WmeMatch::new(
Memory::Any,
Memory::Value("color".to_owned()),
Memory::Value("black".to_owned()),
));
let cl = p.classes.get("Ball").unwrap();
let j1 = p.build_or_share_join_node(r, a0.1, vec!());
let p1 = p.build_production(j1, Box::new(CountCallback { counter: counter1.clone() }));
p.process_tree_structure();
print_betanetwork_tree(r, &p.tokens.borrow(), &p.betanodes);
assert_eq!(counter1.get(), 0);
p.add_facts(&[ball("1", "red")]);
print_betanetwork_tree(r, &p.tokens.borrow(), &p.betanodes);
assert_eq!(counter1.get(), 0);
p.add_facts(&[ball("2", "black")]);
print_betanetwork_tree(r, &p.tokens.borrow(), &p.betanodes);
assert_eq!(counter1.get(), 1);
}
#[test]
fn test_matrix_3() {
let mut p = Phreak::new();
let counter1: Arc<Cell<usize>> = Arc::new(Cell::new(0));
let r = p.root_node;
let cl = p.build_or_share_classnode("Ball");
let a0 = p.build_or_share_alphanode("Ball", WmeMatch::new(
Memory::Any,
Memory::Value("color".to_owned()),
Memory::Value("black".to_owned()),
));
let a1 = p.build_or_share_alphanode("Ball", WmeMatch::new(
Memory::Any,
Memory::Value("object".to_owned()),
Memory::Value("ball".to_owned()),
));
let cl = p.classes.get("Ball").unwrap();
let j1 = p.build_or_share_join_node(r, a0.1, vec!());
let m1 = p.build_or_share_betamemory(j1);
let j2 = p.build_or_share_join_node(m1, a1.1, vec!(
JoinNodeTest { f1: JoinTestField::Field1, condition_number_of_arg2: 1, f2: JoinTestField::Field1, predicate: predicates::TestCondition::Equal(predicates::Eq) }
));
let p1 = p.build_production(j2, Box::new(CountCallback { counter: counter1.clone() }));
p.process_tree_structure();
print_betanetwork_tree(r, &p.tokens.borrow(), &p.betanodes);
assert_eq!(counter1.get(), 0);
p.add_facts(&[ball("1", "red")]);
print_betanetwork_tree(r, &p.tokens.borrow(), &p.betanodes);
assert_eq!(counter1.get(), 0);
p.add_facts(&[ball("2", "black")]);
print_betanetwork_tree(r, &p.tokens.borrow(), &p.betanodes);
assert_eq!(counter1.get(), 1);
p.add_facts(&[ball("3", "black")]);
print_betanetwork_tree(r, &p.tokens.borrow(), &p.betanodes);
assert_eq!(counter1.get(), 2);
p.remove_facts(&[ball("2", "black")]);
print_betanetwork_tree(r, &p.tokens.borrow(), &p.betanodes);
assert_eq!(counter1.get(), 1);
p.remove_facts(&[ball("1", "red")]);
print_betanetwork_tree(r, &p.tokens.borrow(), &p.betanodes);
assert_eq!(counter1.get(), 1);
p.remove_facts(&[ball("3", "black")]);
print_betanetwork_tree(r, &p.tokens.borrow(), &p.betanodes);
assert_eq!(counter1.get(), 0);
}
#[test]
fn test_matrix_4() {
let mut p = Phreak::new();
let counter1: Arc<Cell<usize>> = Arc::new(Cell::new(0));
let r = p.root_node;
let cl = p.build_or_share_classnode("Ball");
let a0 = p.build_or_share_alphanode("Ball", WmeMatch::new(
Memory::Any,
Memory::Value("color".to_owned()),
Memory::Value("black".to_owned()),
));
let cl = p.classes.get("Ball").unwrap();
let n1 = p.build_or_share_negativenode(r, a0.1, vec!());
let p1 = p.build_production(n1, Box::new(CountCallback { counter: counter1.clone() }));
p.process_tree_structure();
print_betanetwork_tree(r, &p.tokens.borrow(), &p.betanodes);
assert_eq!(counter1.get(), 1);
p.add_facts(&[ball("1", "red")]);
print_betanetwork_tree(r, &p.tokens.borrow(), &p.betanodes);
assert_eq!(counter1.get(), 1);
p.add_facts(&[ball("2", "black")]);
print_betanetwork_tree(r, &p.tokens.borrow(), &p.betanodes);
assert_eq!(counter1.get(), 0);
p.add_facts(&[ball("3", "black")]);
print_betanetwork_tree(r, &p.tokens.borrow(), &p.betanodes);
assert_eq!(counter1.get(), 0);
p.remove_facts(&[ball("1", "red")]);
print_betanetwork_tree(r, &p.tokens.borrow(), &p.betanodes);
assert_eq!(counter1.get(), 0);
p.remove_facts(&[ball("2", "black")]);
print_betanetwork_tree(r, &p.tokens.borrow(), &p.betanodes);
assert_eq!(counter1.get(), 0);
p.remove_facts(&[ball("3", "black")]);
print_betanetwork_tree(r, &p.tokens.borrow(), &p.betanodes);
assert_eq!(counter1.get(), 1);
}
#[test]
fn test_matrix_5() {
let mut p = Phreak::new();
let counter1: Arc<Cell<usize>> = Arc::new(Cell::new(0));
let r = p.root_node;
let cl = p.build_or_share_classnode("Ball");
let a0 = p.build_or_share_alphanode("Ball", WmeMatch::new(
Memory::Any,
Memory::Value("color".to_owned()),
Memory::Value("black".to_owned()),
));
let a1 = p.build_or_share_alphanode("Ball", WmeMatch::new(
Memory::Any,
Memory::Value("color".to_owned()),
Memory::Value("yellow".to_owned()),
));
let a2 = p.build_or_share_alphanode("Ball", WmeMatch::new(
Memory::Any,
Memory::Value("color".to_owned()),
Memory::Value("blue".to_owned()),
));
let cl = p.classes.get("Ball").unwrap();
let j1 = p.build_or_share_join_node(r, a0.1, vec!());
let m1 = p.build_or_share_betamemory(j1);
let n1 = p.build_or_share_negativenode(m1, a1.1, vec!());
let j2 = p.build_or_share_join_node(n1, a2.1, vec!());
let p1 = p.build_production(j2, Box::new(CountCallback { counter: counter1.clone() }));
p.process_tree_structure();
print_betanetwork_tree(r, &p.tokens.borrow(), &p.betanodes);
assert_eq!(counter1.get(), 0);
p.add_facts(&[ball("1", "black")]);
print_betanetwork_tree(r, &p.tokens.borrow(), &p.betanodes);
assert_eq!(counter1.get(), 0);
p.add_facts(&[ball("2", "yellow")]);
print_betanetwork_tree(r, &p.tokens.borrow(), &p.betanodes);
assert_eq!(counter1.get(), 0);
p.add_facts(&[ball("3", "blue")]);
print_betanetwork_tree(r, &p.tokens.borrow(), &p.betanodes);
assert_eq!(counter1.get(), 0);
p.remove_facts(&[ball("2", "yellow")]);
print_betanetwork_tree(r, &p.tokens.borrow(), &p.betanodes);
assert_eq!(counter1.get(), 1);
p.remove_facts(&[ball("3", "blue")]);
print_betanetwork_tree(r, &p.tokens.borrow(), &p.betanodes);
assert_eq!(counter1.get(), 0);
p.remove_facts(&[ball("1", "black")]);
print_betanetwork_tree(r, &p.tokens.borrow(), &p.betanodes);
assert_eq!(counter1.get(), 0);
}
#[test]
fn test_matrix_6() {
let mut p = Phreak::new();
let counter1: Arc<Cell<usize>> = Arc::new(Cell::new(0));
let r = p.root_node;
let cl = p.build_or_share_classnode("Ball");
let a0 = p.build_or_share_alphanode("Ball", WmeMatch::new(
Memory::Any,
Memory::Value("color".to_owned()),
Memory::Value("black".to_owned()),
));
let a1 = p.build_or_share_alphanode("Ball", WmeMatch::new(
Memory::Any,
Memory::Value("color".to_owned()),
Memory::Value("yellow".to_owned()),
));
let cl = p.classes.get("Ball").unwrap();
let n1 = p.build_or_share_negativenode(r, a0.1, vec!());
let n2 = p.build_or_share_negativenode(n1, a1.1, vec!());
let p1 = p.build_production(n2, Box::new(CountCallback { counter: counter1.clone() }));
p.process_tree_structure();
print_betanetwork_tree(r, &p.tokens.borrow(), &p.betanodes);
assert_eq!(counter1.get(), 1);
p.add_facts(&[ball("1", "black")]);
print_betanetwork_tree(r, &p.tokens.borrow(), &p.betanodes);
assert_eq!(counter1.get(), 0);
p.add_facts(&[ball("2", "yellow")]);
print_betanetwork_tree(r, &p.tokens.borrow(), &p.betanodes);
assert_eq!(counter1.get(), 0);
p.remove_facts(&[ball("2", "yellow")]);
print_betanetwork_tree(r, &p.tokens.borrow(), &p.betanodes);
assert_eq!(counter1.get(), 0);
p.remove_facts(&[ball("1", "black")]);
print_betanetwork_tree(r, &p.tokens.borrow(), &p.betanodes);
assert_eq!(counter1.get(), 1);
p.add_facts(&[ball("2", "yellow")]);
print_betanetwork_tree(r, &p.tokens.borrow(), &p.betanodes);
assert_eq!(counter1.get(), 0);
p.add_facts(&[ball("1", "black")]);
print_betanetwork_tree(r, &p.tokens.borrow(), &p.betanodes);
assert_eq!(counter1.get(), 0);
}
fn init_new_node_for_test(node_id: BetaNodeId, p: &mut Phreak) {
let node = &p.betanodes[node_id];
match node.get() {
BetaNode::NcpNode(data) => {
data.init_new_node(node_id, node, p.tokens.get_mut(), &p.segments, &p.betanodes, &p.alphanodes, &p.nil_fact)
}
BetaNode::NccNode(data) => {
data.init_new_node(node_id, node, p.tokens.get_mut(), &p.segments, &p.betanodes, &p.alphanodes, &p.nil_fact)
}
_ => { unimplemented!() }
}
}
#[test]
fn test_matrix_7() {
let mut p = Phreak::new();
let counter1: Arc<Cell<usize>> = Arc::new(Cell::new(0));
let r = p.root_node;
let cl = p.build_or_share_classnode("Ball");
let a0 = p.build_or_share_alphanode("Ball", WmeMatch::new(
Memory::Any,
Memory::Value("color".to_owned()),
Memory::Value("black".to_owned()),
));
let cl = p.classes.get("Ball").unwrap();
let j1 = p.build_or_share_join_node(r, a0.1, vec!());
let n1_segment_id = p.split_segment_after_parentnode_if_required(1, r);
let j1_segment_id = p.betanodes[j1].get().get_segment();
let (n1, ncp1) = p.node_new_ncc_pair(1, n1_segment_id, j1_segment_id);
j1.prepend(ncp1, &mut p.betanodes);
r.append(n1, &mut p.betanodes);
init_new_node_for_test(ncp1, &mut p);
init_new_node_for_test(n1, &mut p);
let p1 = p.build_production(n1, Box::new(CountCallback { counter: counter1.clone() }));
p.process_tree_structure();
print_betanetwork_tree(r, &p.tokens.borrow(), &p.betanodes);
assert_eq!(counter1.get(), 1);
p.add_facts(&[ball("1", "black")]);
print_betanetwork_tree(r, &p.tokens.borrow(), &p.betanodes);
assert_eq!(counter1.get(), 0);
p.remove_facts(&[ball("1", "black")]);
print_betanetwork_tree(r, &p.tokens.borrow(), &p.betanodes);
assert_eq!(counter1.get(), 1);
}
#[test]
fn test_matrix_8() {
let mut p = Phreak::new();
let counter1: Arc<Cell<usize>> = Arc::new(Cell::new(0));
let r = p.root_node;
let cl = p.build_or_share_classnode("Ball");
let a0 = p.build_or_share_alphanode("Ball", WmeMatch::new(
Memory::Any,
Memory::Value("color".to_owned()),
Memory::Value("black".to_owned()),
));
let a1 = p.build_or_share_alphanode("Ball", WmeMatch::new(
Memory::Any,
Memory::Value("color".to_owned()),
Memory::Value("yellow".to_owned()),
));
let cl = p.classes.get("Ball").unwrap();
let j1 = p.build_or_share_join_node(r, a0.1, vec!());
let n1_segment_id = p.split_segment_after_parentnode_if_required(1, r);
let j1_segment_id = p.betanodes[j1].get().get_segment();
let (n1, ncp1) = p.node_new_ncc_pair(1, n1_segment_id, j1_segment_id);
j1.prepend(ncp1, &mut p.betanodes);
r.append(n1, &mut p.betanodes);
init_new_node_for_test(ncp1, &mut p);
init_new_node_for_test(n1, &mut p);
let j2 = p.build_or_share_join_node(n1, a1.1, vec!());
let n2_segment_id = p.split_segment_after_parentnode_if_required(1, n1);
let j2_segment_id = p.betanodes[j2].get().get_segment();
let (n2, ncp2) = p.node_new_ncc_pair(1, n2_segment_id, j2_segment_id);
j2.prepend(ncp2, &mut p.betanodes);
n1.append(n2, &mut p.betanodes);
init_new_node_for_test(ncp2, &mut p);
init_new_node_for_test(n2, &mut p);
let p1 = p.build_production(n2, Box::new(CountCallback { counter: counter1.clone() }));
p.process_tree_structure();
print_betanetwork_tree(r, &p.tokens.borrow(), &p.betanodes);
assert_eq!(counter1.get(), 1);
p.add_facts(&[ball("1", "black")]);
print_betanetwork_tree(r, &p.tokens.borrow(), &p.betanodes);
assert_eq!(counter1.get(), 0);
p.add_facts(&[ball("2", "yellow")]);
print_betanetwork_tree(r, &p.tokens.borrow(), &p.betanodes);
assert_eq!(counter1.get(), 0);
p.remove_facts(&[ball("2", "yellow")]);
print_betanetwork_tree(r, &p.tokens.borrow(), &p.betanodes);
assert_eq!(counter1.get(), 0);
p.remove_facts(&[ball("1", "black")]);
print_betanetwork_tree(r, &p.tokens.borrow(), &p.betanodes);
assert_eq!(counter1.get(), 1);
p.add_facts(&[ball("2", "yellow")]);
print_betanetwork_tree(r, &p.tokens.borrow(), &p.betanodes);
assert_eq!(counter1.get(), 0);
p.add_facts(&[ball("1", "black")]);
print_betanetwork_tree(r, &p.tokens.borrow(), &p.betanodes);
assert_eq!(counter1.get(), 0);
}
#[test]
fn test_matrix_9() {
let mut p = Phreak::new();
let counter1: Arc<Cell<usize>> = Arc::new(Cell::new(0));
let r = p.root_node;
let cl = p.build_or_share_classnode("Ball");
let a0 = p.build_or_share_alphanode("Ball", WmeMatch::new(
Memory::Any,
Memory::Value("color".to_owned()),
Memory::Value("black".to_owned()),
));
let a1 = p.build_or_share_alphanode("Ball", WmeMatch::new(
Memory::Any,
Memory::Value("color".to_owned()),
Memory::Value("yellow".to_owned()),
));
let cl = p.classes.get("Ball").unwrap();
let n1 = p.build_or_share_negativenode(r, a0.1, vec!());
let j2 = p.build_or_share_join_node(n1, a1.1, vec!());
let n2_segment_id = p.split_segment_after_parentnode_if_required(1, n1);
let j2_segment_id = p.betanodes[j2].get().get_segment();
let (n2, ncp2) = p.node_new_ncc_pair(1, n2_segment_id, j2_segment_id);
j2.prepend(ncp2, &mut p.betanodes);
n1.append(n2, &mut p.betanodes);
init_new_node_for_test(ncp2, &mut p);
init_new_node_for_test(n2, &mut p);
let p1 = p.build_production(n2, Box::new(CountCallback { counter: counter1.clone() }));
p.process_tree_structure();
print_betanetwork_tree(r, &p.tokens.borrow(), &p.betanodes);
assert_eq!(counter1.get(), 1);
p.add_facts(&[ball("1", "black")]);
print_betanetwork_tree(r, &p.tokens.borrow(), &p.betanodes);
assert_eq!(counter1.get(), 0);
p.add_facts(&[ball("2", "yellow")]);
print_betanetwork_tree(r, &p.tokens.borrow(), &p.betanodes);
assert_eq!(counter1.get(), 0);
p.remove_facts(&[ball("2", "yellow")]);
print_betanetwork_tree(r, &p.tokens.borrow(), &p.betanodes);
assert_eq!(counter1.get(), 0);
p.remove_facts(&[ball("1", "black")]);
print_betanetwork_tree(r, &p.tokens.borrow(), &p.betanodes);
assert_eq!(counter1.get(), 1);
p.add_facts(&[ball("2", "yellow")]);
print_betanetwork_tree(r, &p.tokens.borrow(), &p.betanodes);
assert_eq!(counter1.get(), 0);
p.add_facts(&[ball("1", "black")]);
print_betanetwork_tree(r, &p.tokens.borrow(), &p.betanodes);
assert_eq!(counter1.get(), 0);
}
#[test]
fn test_matrix_10() {
let mut p = Phreak::new();
let counter1: Arc<Cell<usize>> = Arc::new(Cell::new(0));
let r = p.root_node;
let cl = p.build_or_share_classnode("Ball");
let a0 = p.build_or_share_alphanode("Ball", WmeMatch::new(
Memory::Any,
Memory::Value("color".to_owned()),
Memory::Value("black".to_owned()),
));
let cl = p.classes.get("Ball").unwrap();
let n1 = p.build_or_share_negativenode(r, a0.1, vec!());
let n2_segment_id = p.split_segment_after_parentnode_if_required(1, r);
let j2_segment_id = p.betanodes[n1].get().get_segment();
let (n2, ncp2) = p.node_new_ncc_pair(1, n2_segment_id, j2_segment_id);
n1.prepend(ncp2, &mut p.betanodes);
r.append(n2, &mut p.betanodes);
init_new_node_for_test(ncp2, &mut p);
init_new_node_for_test(n2, &mut p);
let p1 = p.build_production(n2, Box::new(CountCallback { counter: counter1.clone() }));
p.process_tree_structure();
print_betanetwork_tree(r, &p.tokens.borrow(), &p.betanodes);
assert_eq!(counter1.get(), 0);
p.add_facts(&[ball("1", "black")]);
print_betanetwork_tree(r, &p.tokens.borrow(), &p.betanodes);
assert_eq!(counter1.get(), 1);
p.remove_facts(&[ball("1", "black")]);
print_betanetwork_tree(r, &p.tokens.borrow(), &p.betanodes);
assert_eq!(counter1.get(), 0);
}
#[test]
fn test_matrix_11() {
let mut p = Phreak::new();
let counter1: Arc<Cell<usize>> = Arc::new(Cell::new(0));
let r = p.root_node;
let cl = p.build_or_share_classnode("Ball");
let a0 = p.build_or_share_alphanode("Ball", WmeMatch::new(
Memory::Any,
Memory::Value("color".to_owned()),
Memory::Value("black".to_owned()),
));
let a1 = p.build_or_share_alphanode("Ball", WmeMatch::new(
Memory::Any,
Memory::Value("color".to_owned()),
Memory::Value("yellow".to_owned()),
));
let cl = p.classes.get("Ball").unwrap();
let j1 = p.build_or_share_join_node(r, a0.1, vec!());
let n1_segment_id = p.split_segment_after_parentnode_if_required(1, r);
let j1_segment_id = p.betanodes[j1].get().get_segment();
let (n1, ncp1) = p.node_new_ncc_pair(1, n1_segment_id, j1_segment_id);
j1.prepend(ncp1, &mut p.betanodes);
r.append(n1, &mut p.betanodes);
init_new_node_for_test(ncp1, &mut p);
init_new_node_for_test(n1, &mut p);
let n2 = p.build_or_share_negativenode(n1, a1.1, vec!());
let p1 = p.build_production(n2, Box::new(CountCallback { counter: counter1.clone() }));
p.process_tree_structure();
print_segment_tree(p.betanodes[p.root_node].get().get_segment(), &p.segments);
print_betanetwork_tree(r, &p.tokens.borrow(), &p.betanodes);
assert_eq!(counter1.get(), 1);
p.add_facts(&[ball("1", "black")]);
print_betanetwork_tree(r, &p.tokens.borrow(), &p.betanodes);
assert_eq!(counter1.get(), 0);
p.add_facts(&[ball("2", "yellow")]);
print_betanetwork_tree(r, &p.tokens.borrow(), &p.betanodes);
assert_eq!(counter1.get(), 0);
p.remove_facts(&[ball("2", "yellow")]);
print_betanetwork_tree(r, &p.tokens.borrow(), &p.betanodes);
assert_eq!(counter1.get(), 0);
p.remove_facts(&[ball("1", "black")]);
print_betanetwork_tree(r, &p.tokens.borrow(), &p.betanodes);
assert_eq!(counter1.get(), 1);
p.add_facts(&[ball("2", "yellow")]);
print_betanetwork_tree(r, &p.tokens.borrow(), &p.betanodes);
assert_eq!(counter1.get(), 0);
p.add_facts(&[ball("1", "black")]);
print_betanetwork_tree(r, &p.tokens.borrow(), &p.betanodes);
assert_eq!(counter1.get(), 0);
}
#[test]
fn test_conditions() {
let mut p = Phreak::new();
let counter1: Arc<Cell<usize>> = Arc::new(Cell::new(0));
let r = p.root_node;
let cl = p.build_or_share_classnode("Ball");
let a0 = p.build_or_share_alphanode("Ball", WmeMatch::new(
Memory::Any,
Memory::Value("color".to_owned()),
Memory::Value("black".to_owned()),
));
}
}