use super::*;
fn make_material_conditional(entity: &str, antecedent: &str, consequent: &str) -> LogicBuffer {
let mut nodes = Vec::new();
let ante = pred(
&mut nodes,
antecedent,
vec![
LogicalTerm::Constant(entity.to_string()),
LogicalTerm::Unspecified,
],
);
let cons = pred(
&mut nodes,
consequent,
vec![
LogicalTerm::Constant(entity.to_string()),
LogicalTerm::Unspecified,
],
);
let neg_ante = not(&mut nodes, ante);
let root = or(&mut nodes, neg_ante, cons);
LogicBuffer {
nodes,
roots: vec![root],
}
}
#[test]
fn test_material_conditional_modus_ponens() {
let kb = new_kb();
assert_buf(&kb, make_assertion("sol", "barda"));
assert_buf(&kb, make_material_conditional("sol", "barda", "tsali"));
assert!(query(&kb, make_query("sol", "tsali")));
}
#[test]
fn test_material_conditional_modus_ponens_reversed_order() {
let kb = new_kb();
assert_buf(&kb, make_material_conditional("sol", "barda", "tsali"));
assert_buf(&kb, make_assertion("sol", "barda"));
assert!(query(&kb, make_query("sol", "tsali")));
}
#[test]
fn test_material_conditional_modus_tollens() {
let kb = new_kb();
assert_buf(&kb, make_material_conditional("sol", "barda", "tsali"));
let mut neg_nodes = Vec::new();
let inner = pred(
&mut neg_nodes,
"tsali",
vec![
LogicalTerm::Constant("sol".to_string()),
LogicalTerm::Unspecified,
],
);
let root = not(&mut neg_nodes, inner);
assert_buf(
&kb,
LogicBuffer {
nodes: neg_nodes,
roots: vec![root],
},
);
assert!(query_false(&kb, make_query("sol", "barda")));
}
#[test]
fn test_material_conditional_antecedent_not_satisfied() {
let kb = new_kb();
assert_buf(&kb, make_material_conditional("sol", "barda", "tsali"));
assert!(query_false(&kb, make_query("sol", "tsali")));
}
#[test]
fn test_material_conditional_chain() {
let kb = new_kb();
assert_buf(&kb, make_assertion("sol", "tarci"));
assert_buf(&kb, make_material_conditional("sol", "tarci", "gusni"));
assert_buf(&kb, make_material_conditional("sol", "gusni", "melbi"));
assert!(query(&kb, make_query("sol", "melbi")));
}
#[test]
fn reversed_material_conditional_surface_modus_ponens() {
let kb = new_kb();
assert_buf(&kb, compile_surface("goes(Adam) | ~eats(Adam)."));
assert_buf(&kb, compile_surface("eats(Adam)."));
assert!(query(&kb, compile_surface("goes(Adam).")));
}
#[test]
fn reversed_material_conditional_surface_order_invariant() {
let kb = new_kb();
assert_buf(&kb, compile_surface("eats(Adam)."));
assert_buf(&kb, compile_surface("goes(Adam) | ~eats(Adam)."));
assert!(query(&kb, compile_surface("goes(Adam).")));
}
#[test]
fn reversed_material_conditional_surface_negative_controls() {
let kb = new_kb();
assert_buf(&kb, compile_surface("goes(Adam) | ~eats(Adam)."));
assert!(query_false(&kb, compile_surface("goes(Adam).")));
let kb2 = new_kb();
assert_buf(&kb2, compile_surface("goes(Adam) | ~eats(Adam)."));
assert_buf(&kb2, compile_surface("eats(Bel)."));
assert!(query_false(&kb2, compile_surface("goes(Adam).")));
}
#[test]
fn reversed_and_forward_spellings_behave_identically() {
let fwd = new_kb();
assert_buf(&fwd, compile_surface("~eats(Adam) | goes(Adam)."));
assert_buf(&fwd, compile_surface("eats(Adam)."));
assert!(query(&fwd, compile_surface("goes(Adam).")));
let rev = new_kb();
assert_buf(&rev, compile_surface("goes(Adam) | ~eats(Adam)."));
assert_buf(&rev, compile_surface("eats(Adam)."));
assert!(query(&rev, compile_surface("goes(Adam).")));
}
#[test]
fn reversed_arm_nonleaf_not_body_no_longer_registers_zero_condition_rule() {
let kb = new_kb();
let mut nodes = Vec::new();
let a = pred(
&mut nodes,
"gusni",
vec![
LogicalTerm::Constant("sol".to_string()),
LogicalTerm::Unspecified,
],
);
let b = pred(
&mut nodes,
"barda",
vec![
LogicalTerm::Constant("sol".to_string()),
LogicalTerm::Unspecified,
],
);
let c = pred(
&mut nodes,
"tsali",
vec![
LogicalTerm::Constant("sol".to_string()),
LogicalTerm::Unspecified,
],
);
let bc = and(&mut nodes, b, c);
let nbc = not(&mut nodes, bc);
let root = or(&mut nodes, a, nbc);
assert_buf(
&kb,
LogicBuffer {
nodes,
roots: vec![root],
},
);
assert!(query_false(&kb, make_query("sol", "gusni")));
assert_buf(&kb, make_assertion("sol", "barda"));
assert_buf(&kb, make_assertion("sol", "tsali"));
assert!(query(&kb, make_query("sol", "gusni")));
}
fn make_deontic_assertion(entity: &str, relation: &str, action: &str) -> LogicBuffer {
let mut nodes = Vec::new();
let root = pred(
&mut nodes,
relation,
vec![
LogicalTerm::Constant(entity.to_string()),
LogicalTerm::Constant(action.to_string()),
LogicalTerm::Unspecified,
],
);
LogicBuffer {
nodes,
roots: vec![root],
}
}
#[test]
fn test_deontic_obliged_assert_query() {
let kb = new_kb();
assert_buf(&kb, make_deontic_assertion("alis", "bilga", "klama"));
assert!(query(&kb, make_deontic_assertion("alis", "bilga", "klama")));
assert!(query_false(
&kb,
make_deontic_assertion("bob", "bilga", "klama")
));
}
#[test]
fn test_deontic_permits_assert_query() {
let kb = new_kb();
assert_buf(&kb, make_deontic_assertion("alis", "curmi", "klama"));
assert!(query(&kb, make_deontic_assertion("alis", "curmi", "klama")));
assert!(query_false(
&kb,
make_deontic_assertion("alis", "curmi", "tavla")
));
}
#[test]
fn test_deontic_needs_assert_query() {
let kb = new_kb();
assert_buf(&kb, make_deontic_assertion("alis", "nitcu", "klama"));
assert!(query(&kb, make_deontic_assertion("alis", "nitcu", "klama")));
assert!(query_false(
&kb,
make_deontic_assertion("alis", "nitcu", "tavla")
));
}
#[test]
fn test_deontic_universal_obligation() {
let kb = new_kb();
assert_buf(&kb, make_assertion("alis", "prenu"));
assert_buf(&kb, make_universal("prenu", "bilga"));
assert!(query(&kb, make_query("alis", "bilga")));
assert!(query_false(&kb, make_query("bob", "bilga")));
}
#[test]
fn test_deontic_conditional_chain() {
let kb = new_kb();
assert_buf(&kb, make_assertion("sol", "bilga"));
assert_buf(&kb, make_material_conditional("sol", "bilga", "nitcu"));
assert!(query(&kb, make_query("sol", "nitcu")));
}
fn permitted(nodes: &mut Vec<LogicNode>, inner: u32) -> u32 {
let id = nodes.len() as u32;
nodes.push(LogicNode::PermittedNode(inner));
id
}
#[test]
fn test_obligatory_assert_query() {
let kb = new_kb();
let mut a_nodes = Vec::new();
let inner = pred(
&mut a_nodes,
"klama",
vec![
LogicalTerm::Constant("alis".into()),
LogicalTerm::Unspecified,
],
);
let root = obligatory(&mut a_nodes, inner);
assert_buf(
&kb,
LogicBuffer {
nodes: a_nodes,
roots: vec![root],
},
);
let mut q_nodes = Vec::new();
let q_inner = pred(
&mut q_nodes,
"klama",
vec![
LogicalTerm::Constant("alis".into()),
LogicalTerm::Unspecified,
],
);
let q_root = obligatory(&mut q_nodes, q_inner);
assert!(query(
&kb,
LogicBuffer {
nodes: q_nodes,
roots: vec![q_root]
}
));
}
#[test]
fn test_permitted_assert_query() {
let kb = new_kb();
let mut a_nodes = Vec::new();
let inner = pred(
&mut a_nodes,
"klama",
vec![
LogicalTerm::Constant("alis".into()),
LogicalTerm::Unspecified,
],
);
let root = permitted(&mut a_nodes, inner);
assert_buf(
&kb,
LogicBuffer {
nodes: a_nodes,
roots: vec![root],
},
);
let mut q_nodes = Vec::new();
let q_inner = pred(
&mut q_nodes,
"klama",
vec![
LogicalTerm::Constant("alis".into()),
LogicalTerm::Unspecified,
],
);
let q_root = permitted(&mut q_nodes, q_inner);
assert!(query(
&kb,
LogicBuffer {
nodes: q_nodes,
roots: vec![q_root]
}
));
}
#[test]
fn test_obligatory_distinct_from_bare() {
let kb = new_kb();
let mut a_nodes = Vec::new();
let inner = pred(
&mut a_nodes,
"klama",
vec![
LogicalTerm::Constant("alis".into()),
LogicalTerm::Unspecified,
],
);
let root = obligatory(&mut a_nodes, inner);
assert_buf(
&kb,
LogicBuffer {
nodes: a_nodes,
roots: vec![root],
},
);
assert!(
query_false(&kb, make_query("alis", "klama")),
"ought must not imply is"
);
let mut q_nodes = Vec::new();
let q_inner = pred(
&mut q_nodes,
"klama",
vec![
LogicalTerm::Constant("alis".into()),
LogicalTerm::Unspecified,
],
);
let q_root = obligatory(&mut q_nodes, q_inner);
assert!(
query(
&kb,
LogicBuffer {
nodes: q_nodes,
roots: vec![q_root]
}
),
"the obligation itself is preserved"
);
}
#[test]
fn test_bare_does_not_imply_obligation() {
let kb = new_kb();
assert_buf(&kb, make_assertion("alis", "klama"));
let mut q_nodes = Vec::new();
let q_inner = pred(
&mut q_nodes,
"klama",
vec![
LogicalTerm::Constant("alis".into()),
LogicalTerm::Unspecified,
],
);
let q_root = obligatory(&mut q_nodes, q_inner);
assert!(
query_false(
&kb,
LogicBuffer {
nodes: q_nodes,
roots: vec![q_root]
}
),
"is must not imply ought"
);
}
#[test]
fn test_permitted_distinct_from_bare() {
let kb = new_kb();
let mut a_nodes = Vec::new();
let inner = pred(
&mut a_nodes,
"klama",
vec![
LogicalTerm::Constant("alis".into()),
LogicalTerm::Unspecified,
],
);
let root = permitted(&mut a_nodes, inner);
assert_buf(
&kb,
LogicBuffer {
nodes: a_nodes,
roots: vec![root],
},
);
assert!(
query_false(&kb, make_query("alis", "klama")),
"permitted must not imply is"
);
}