use super::*;
#[test]
fn test_literal_unification_ground() {
let p_a = Literal::positive(TLExpr::pred("P", vec![Term::constant("a")]));
let not_p_a = Literal::negative(TLExpr::pred("P", vec![Term::constant("a")]));
let mgu = p_a.try_unify(¬_p_a);
assert!(mgu.is_some());
assert!(mgu.expect("unwrap").is_empty());
}
#[test]
fn test_literal_unification_variable() {
let p_x = Literal::positive(TLExpr::pred("P", vec![Term::var("x")]));
let not_p_a = Literal::negative(TLExpr::pred("P", vec![Term::constant("a")]));
let mgu = p_x.try_unify(¬_p_a);
assert!(mgu.is_some());
let mgu = mgu.expect("unwrap");
assert_eq!(mgu.len(), 1);
assert_eq!(mgu.apply(&Term::var("x")), Term::constant("a"));
}
#[test]
fn test_literal_unification_fails_diff_names() {
let p_x = Literal::positive(TLExpr::pred("P", vec![Term::var("x")]));
let not_q_x = Literal::negative(TLExpr::pred("Q", vec![Term::var("x")]));
let mgu = p_x.try_unify(¬_q_x);
assert!(mgu.is_none());
}
#[test]
fn test_literal_unification_fails_same_polarity() {
let p_x = Literal::positive(TLExpr::pred("P", vec![Term::var("x")]));
let p_a = Literal::positive(TLExpr::pred("P", vec![Term::constant("a")]));
let mgu = p_x.try_unify(&p_a);
assert!(mgu.is_none());
}
#[test]
fn test_literal_apply_substitution() {
let p_x = Literal::positive(TLExpr::pred("P", vec![Term::var("x")]));
let mut subst = Substitution::empty();
subst.bind("x".to_string(), Term::constant("a"));
let p_a = p_x.apply_substitution(&subst);
let expected = Literal::positive(TLExpr::pred("P", vec![Term::constant("a")]));
assert_eq!(p_a.atom, expected.atom);
assert_eq!(p_a.polarity, expected.polarity);
}
#[test]
fn test_clause_rename_variables() {
let p_x = Literal::positive(TLExpr::pred("P", vec![Term::var("x")]));
let q_x = Literal::positive(TLExpr::pred("Q", vec![Term::var("x")]));
let clause = Clause::from_literals(vec![p_x, q_x]);
let renamed = clause.rename_variables("1");
let vars = renamed.free_vars();
assert!(vars.contains("x_1"));
assert!(!vars.contains("x"));
}
#[test]
fn test_clause_apply_substitution() {
let p_x = Literal::positive(TLExpr::pred("P", vec![Term::var("x")]));
let q_y = Literal::positive(TLExpr::pred("Q", vec![Term::var("y")]));
let clause = Clause::from_literals(vec![p_x, q_y]);
let mut subst = Substitution::empty();
subst.bind("x".to_string(), Term::constant("a"));
subst.bind("y".to_string(), Term::constant("b"));
let result = clause.apply_substitution(&subst);
assert!(result.free_vars().is_empty());
}
#[test]
fn test_first_order_resolution_basic() {
let p_x = Literal::positive(TLExpr::pred("P", vec![Term::var("x")]));
let not_p_a = Literal::negative(TLExpr::pred("P", vec![Term::constant("a")]));
let c1 = Clause::unit(p_x);
let c2 = Clause::unit(not_p_a);
let prover = ResolutionProver::new();
let resolvents = prover.resolve_first_order(&c1, &c2);
assert_eq!(resolvents.len(), 1);
assert!(resolvents[0].0.is_empty()); }
#[test]
fn test_first_order_resolution_complex() {
let p_x = Literal::positive(TLExpr::pred("P", vec![Term::var("x")]));
let q_x = Literal::positive(TLExpr::pred("Q", vec![Term::var("x")]));
let c1 = Clause::from_literals(vec![p_x, q_x]);
let not_p_a = Literal::negative(TLExpr::pred("P", vec![Term::constant("a")]));
let r_a = Literal::positive(TLExpr::pred("R", vec![Term::constant("a")]));
let c2 = Clause::from_literals(vec![not_p_a, r_a]);
let prover = ResolutionProver::new();
let resolvents = prover.resolve_first_order(&c1, &c2);
assert_eq!(resolvents.len(), 1);
let resolvent = &resolvents[0].0;
assert_eq!(resolvent.len(), 2);
assert!(resolvent.free_vars().is_empty());
}
#[test]
fn test_first_order_resolution_multiple_vars() {
let p_xy = Literal::positive(TLExpr::pred("P", vec![Term::var("x"), Term::var("y")]));
let not_p_ab = Literal::negative(TLExpr::pred(
"P",
vec![Term::constant("a"), Term::constant("b")],
));
let c1 = Clause::unit(p_xy);
let c2 = Clause::unit(not_p_ab);
let prover = ResolutionProver::new();
let resolvents = prover.resolve_first_order(&c1, &c2);
assert_eq!(resolvents.len(), 1);
assert!(resolvents[0].0.is_empty());
}
#[test]
fn test_first_order_resolution_standardizing_apart() {
let p_x1 = Literal::positive(TLExpr::pred("P", vec![Term::var("x")]));
let not_p_x2 = Literal::negative(TLExpr::pred("P", vec![Term::var("x")]));
let c1 = Clause::unit(p_x1);
let c2 = Clause::unit(not_p_x2);
let prover = ResolutionProver::new();
let resolvents = prover.resolve_first_order(&c1, &c2);
assert_eq!(resolvents.len(), 1);
assert!(resolvents[0].0.is_empty());
}
#[test]
fn test_first_order_resolution_no_unifier() {
let p_a = Literal::positive(TLExpr::pred("P", vec![Term::constant("a")]));
let not_p_b = Literal::negative(TLExpr::pred("P", vec![Term::constant("b")]));
let c1 = Clause::unit(p_a);
let c2 = Clause::unit(not_p_b);
let prover = ResolutionProver::new();
let resolvents = prover.resolve_first_order(&c1, &c2);
assert_eq!(resolvents.len(), 0);
}