use vampire_prover::{Function, Options, Predicate, Problem, ProofRes, Term, exists, forall};
fn main() {
let mult = Function::new("mult", 2);
let inv = Function::new("inv", 1);
let one = Function::constant("1");
let mul = |x: Term, y: Term| -> Term { mult.with([x, y]) };
let right_identity = forall(|x| mul(x, one).eq(x));
let right_inverse = forall(|x| {
let inv_x = inv.with(x);
mul(x, inv_x).eq(one)
});
let associativity = forall(|x| forall(|y| forall(|z| mul(mul(x, y), z).eq(mul(x, mul(y, z))))));
let h = Predicate::new("h", 1);
let h_ident = h.with(one);
let h_mul_closed = forall(|x| forall(|y| (h.with(x) & h.with(y)) >> h.with(mul(x, y))));
let h_inv_closed = forall(|x| h.with(x) >> h.with(inv.with(x)));
let h_index_2 = exists(|x| {
let not_in_h = !h.with(x);
let class = forall(|y| h.with(y) | h.with(mul(inv.with(x), y)));
not_in_h & class
});
let h_normal = forall(|x| {
let h_x = h.with(x);
let conj_x = forall(|y| {
let y_inv = inv.with(y);
h.with(mul(mul(y, x), y_inv))
});
h_x.iff(conj_x)
});
let (solution, proof) = Problem::new(Options::new())
.with_axiom(right_identity)
.with_axiom(right_inverse)
.with_axiom(associativity)
.with_axiom(h_ident)
.with_axiom(h_mul_closed)
.with_axiom(h_inv_closed)
.with_axiom(h_index_2)
.conjecture(h_normal)
.solve_and_prove();
if let Some(proof) = proof {
println!("{}", proof);
}
assert_eq!(solution, ProofRes::Proved);
}