use asdi::edb::Attribute;
use asdi::idb::{query::Query, Atom, Term};
use asdi::Program;
pub mod common;
use common::assert_eq_by_line;
#[test]
fn test_wikipedia_example() {
let mut ancestors = Program::default();
let parent_predicate = ancestors.predicates().fetch("parent").unwrap();
{
let parent = ancestors
.add_new_extensional_relation(
parent_predicate.clone(),
vec![Attribute::string(), Attribute::string()],
)
.unwrap();
parent
.add_as_fact(["xerces".into(), "brooke".into()])
.unwrap();
parent
.add_as_fact(["brooke".into(), "damocles".into()])
.unwrap();
};
let ancestor_predicate = ancestors.predicates().fetch("ancestor").unwrap();
let var_x: Term = ancestors.variables().fetch("X").unwrap().into();
let var_y: Term = ancestors.variables().fetch("Y").unwrap().into();
let var_z: Term = ancestors.variables().fetch("Z").unwrap().into();
ancestors
.add_new_pure_rule(
ancestor_predicate.clone(),
[var_x.clone(), var_y.clone()],
[Atom::new(parent_predicate.clone(), [var_x.clone(), var_y.clone()]).into()],
)
.unwrap();
ancestors
.add_new_pure_rule(
ancestor_predicate.clone(),
[var_x.clone(), var_y.clone()],
[
Atom::new(parent_predicate, [var_x.clone(), var_z.clone()]).into(),
Atom::new(ancestor_predicate.clone(), [var_z, var_y]).into(),
],
)
.unwrap();
ancestors
.add_new_query(ancestor_predicate, ["xerces".into(), var_x])
.unwrap();
println!(">{}<", ancestors);
assert_eq_by_line(
&ancestors.to_string(),
r#".assert parent(string, string).
.infer ancestor(string, string).
parent(xerces, brooke).
parent(brooke, damocles).
ancestor(X, Y) ⟵ parent(X, Y).
ancestor(X, Y) ⟵ parent(X, Z) ∧ ancestor(Z, Y).
?- ancestor(xerces, X).
"#,
)
}
#[test]
fn test_sourceforge_example() {
const EXPECTED: &str = r#".assert edge(string, string).
.infer path(string, string).
edge(a, b).
edge(c, d).
edge(d, a).
edge(b, c).
path(X, Y) ⟵ edge(X, Y).
path(X, Y) ⟵ edge(X, Z) ∧ path(Z, Y).
?- path(X, Y).
"#;
let mut graph = Program::default();
let edge_predicate = graph.predicates().fetch("edge").unwrap();
{
let edge = graph
.add_new_extensional_relation(
edge_predicate.clone(),
vec![Attribute::string(), Attribute::string()],
)
.unwrap();
edge.add_as_fact(["a".into(), "b".into()]).unwrap();
edge.add_as_fact(["b".into(), "c".into()]).unwrap();
edge.add_as_fact(["c".into(), "d".into()]).unwrap();
edge.add_as_fact(["d".into(), "a".into()]).unwrap();
}
let path_predicate = graph.predicates().fetch("path").unwrap();
let var_x: Term = graph.variables().fetch("X").unwrap().into();
let var_y: Term = graph.variables().fetch("Y").unwrap().into();
let var_z: Term = graph.variables().fetch("Z").unwrap().into();
graph
.add_new_pure_rule(
path_predicate.clone(),
[var_x.clone(), var_y.clone()],
[Atom::new(edge_predicate.clone(), [var_x.clone(), var_y.clone()]).into()],
)
.unwrap();
graph
.add_new_pure_rule(
path_predicate.clone(),
[var_x.clone(), var_y.clone()],
[
Atom::new(edge_predicate, [var_x.clone(), var_z.clone()]).into(),
Atom::new(path_predicate.clone(), [var_z, var_y.clone()]).into(),
],
)
.unwrap();
let query = Query::new(path_predicate, vec![var_x, var_y]);
graph.add_query(query).unwrap();
println!(">>>{}<<<", EXPECTED);
println!(">>>{}<<<", graph);
assert_eq_by_line(&graph.to_string(), EXPECTED);
}
#[test]
fn test_that_syllogism() {
let mut syllogism = Program::default();
let p_human = syllogism.predicates().fetch("human").unwrap();
let human = syllogism
.add_new_extensional_relation(p_human.clone(), vec![Attribute::string()])
.unwrap();
human.add_as_fact(["Socrates".into()]).unwrap();
let var_x: Term = syllogism.variables().fetch("X").unwrap().into();
syllogism
.add_new_pure_rule(
syllogism.predicates().fetch("mortal").unwrap(),
[var_x.clone()],
[Atom::new(p_human, [var_x]).into()],
)
.unwrap();
syllogism
.add_new_query(
syllogism.predicates().fetch("mortal").unwrap(),
["Socrates".into()],
)
.unwrap();
println!("{}", syllogism);
assert_eq_by_line(
&syllogism.to_string(),
r#".assert human(string).
.infer mortal(string).
human("Socrates").
mortal(X) ⟵ human(X).
?- mortal("Socrates").
"#,
);
}