pub struct Formula { /* private fields */ }Expand description
A formula in first-order logic.
Formulas are logical statements that can be true or false. They include:
- Atomic formulas: predicates and equalities
- Logical connectives: AND (
&), OR (|), NOT (!), implication (>>), biconditional - Quantifiers: universal (
∀) and existential (∃)
§Examples
use vampire_prover::{Function, Predicate, forall};
let p = Predicate::new("P", 1);
let q = Predicate::new("Q", 1);
let x = Function::constant("x");
// Atomic formula
let px = p.with(x);
let qx = q.with(x);
// Conjunction: P(x) ∧ Q(x)
let both = px & qx;
// Disjunction: P(x) ∨ Q(x)
let either = px | qx;
// Implication: P(x) → Q(x)
let implies = px >> qx;
// Negation: ¬P(x)
let not_px = !px;
// Universal quantification: ∀x. P(x)
let all = forall(|x| p.with(x));Implementations§
Source§impl Formula
impl Formula
Sourcepub fn to_string(&self) -> String
pub fn to_string(&self) -> String
Converts this formula to a string representation.
§Panics
Panics if the underlying C API fails (which should never happen in normal use).
§Examples
use vampire_prover::{Function, Predicate};
let p = Predicate::new("P", 1);
let x = Function::constant("x");
let formula = p.with(x);
println!("{}", formula.to_string()); // Prints the vampire string representationSourcepub fn new_predicate(pred: Predicate, args: &[Term]) -> Self
pub fn new_predicate(pred: Predicate, args: &[Term]) -> Self
Creates an atomic formula by applying a predicate to arguments.
This is typically called via Predicate::with rather than directly.
§Panics
Panics if the number of arguments does not match the predicate’s arity.
§Examples
use vampire_prover::{Function, Predicate, Formula};
let mortal = Predicate::new("mortal", 1);
let socrates = Function::constant("socrates");
let formula = Formula::new_predicate(mortal, &[socrates]);Sourcepub fn new_and(formulas: &[Formula]) -> Self
pub fn new_and(formulas: &[Formula]) -> Self
Creates a conjunction (AND) of multiple formulas.
For two formulas, the & operator is more convenient.
§Examples
use vampire_prover::{Function, Predicate, Formula};
let p = Predicate::new("P", 1);
let q = Predicate::new("Q", 1);
let r = Predicate::new("R", 1);
let x = Function::constant("x");
// P(x) ∧ Q(x) ∧ R(x)
let all_three = Formula::new_and(&[
p.with(x),
q.with(x),
r.with(x),
]);Sourcepub fn new_or(formulas: &[Formula]) -> Self
pub fn new_or(formulas: &[Formula]) -> Self
Creates a disjunction (OR) of multiple formulas.
For two formulas, the | operator is more convenient.
§Examples
use vampire_prover::{Function, Predicate, Formula};
let p = Predicate::new("P", 1);
let q = Predicate::new("Q", 1);
let r = Predicate::new("R", 1);
let x = Function::constant("x");
// P(x) ∨ Q(x) ∨ R(x)
let any = Formula::new_or(&[
p.with(x),
q.with(x),
r.with(x),
]);Sourcepub fn new_not(formula: Formula) -> Self
pub fn new_not(formula: Formula) -> Self
Creates a negation (NOT) of a formula.
The ! operator is more convenient than calling this directly.
§Examples
use vampire_prover::{Function, Predicate, Formula};
let p = Predicate::new("P", 1);
let x = Function::constant("x");
let not_p = Formula::new_not(p.with(x));Sourcepub fn new_true() -> Self
pub fn new_true() -> Self
Creates the true (tautology) formula.
§Examples
use vampire_prover::Formula;
let t = Formula::new_true();Sourcepub fn new_false() -> Self
pub fn new_false() -> Self
Creates the false (contradiction) formula.
§Examples
use vampire_prover::Formula;
let f = Formula::new_false();Sourcepub fn new_forall(var: u32, f: Formula) -> Self
pub fn new_forall(var: u32, f: Formula) -> Self
Creates a universally quantified formula.
The forall helper function provides a more ergonomic interface.
§Arguments
var- The index of the variable to quantifyf- The formula body
§Examples
use vampire_prover::{Function, Predicate, Formula, Term};
let p = Predicate::new("P", 1);
let x = Term::new_var(0);
// ∀x. P(x)
let all_p = Formula::new_forall(0, p.with(x));Sourcepub fn new_exists(var: u32, f: Formula) -> Self
pub fn new_exists(var: u32, f: Formula) -> Self
Creates an existentially quantified formula.
The exists helper function provides a more ergonomic interface.
§Arguments
var- The index of the variable to quantifyf- The formula body
§Examples
use vampire_prover::{Function, Predicate, Formula, Term};
let p = Predicate::new("P", 1);
let x = Term::new_var(0);
// ∃x. P(x)
let some_p = Formula::new_exists(0, p.with(x));Sourcepub fn imp(&self, rhs: Formula) -> Self
pub fn imp(&self, rhs: Formula) -> Self
Creates an implication from this formula to another.
The >> operator is more convenient than calling this directly.
§Arguments
rhs- The consequent (right-hand side) of the implication
§Examples
use vampire_prover::{Function, Predicate};
let p = Predicate::new("P", 1);
let q = Predicate::new("Q", 1);
let x = Function::constant("x");
// P(x) → Q(x)
let implication = p.with(x).imp(q.with(x));Sourcepub fn iff(&self, rhs: Formula) -> Self
pub fn iff(&self, rhs: Formula) -> Self
Creates a biconditional (if and only if) between this formula and another.
A biconditional P ↔ Q is true when both formulas have the same truth value.
§Arguments
rhs- The right-hand side of the biconditional
§Examples
use vampire_prover::{Function, Predicate, forall};
let even = Predicate::new("even", 1);
let div_by_2 = Predicate::new("divisible_by_2", 1);
// ∀x. even(x) ↔ divisible_by_2(x)
let equiv = forall(|x| {
even.with(x).iff(div_by_2.with(x))
});Examples found in repository?
113fn run_proof(i: usize) -> ProofRes {
114 // Prove that every subgroup of index 2 is normal.
115 let mult = Function::new(&format!("mult{i}"), 2);
116 let inv = Function::new(&format!("inv{i}"), 1);
117 let one = Function::constant(&format!("1{i}"));
118
119 // Helper to make multiplication more readable
120 let mul = |x: Term, y: Term| -> Term { mult.with(&[x, y]) };
121
122 // Group Axiom 1: Right identity - ∀x. x * 1 = x
123 let right_identity = forall(|x| mul(x, one).eq(x));
124
125 // Group Axiom 2: Right inverse - ∀x. x * inv(x) = 1
126 let right_inverse = forall(|x| {
127 let inv_x = inv.with(&[x]);
128 mul(x, inv_x).eq(one)
129 });
130
131 // Group Axiom 3: Associativity - ∀x,y,z. (x * y) * z = x * (y * z)
132 let associativity = forall(|x| forall(|y| forall(|z| mul(mul(x, y), z).eq(mul(x, mul(y, z))))));
133
134 // Describe the subgroup
135 let h = Predicate::new("h", 1);
136
137 // Any subgroup contains the identity
138 let h_ident = h.with(&[one]);
139
140 // And is closed under multiplication
141 let h_mul_closed =
142 forall(|x| forall(|y| (h.with(&[x]) & h.with(&[y])) >> h.with(&[mul(x, y)])));
143
144 // And is closed under inverse
145 let h_inv_closed = forall(|x| h.with(&[x]) >> h.with(&[inv.with(&[x])]));
146
147 // H specifically is of order 2
148 let h_index_2 = exists(|x| {
149 // an element not in H
150 let not_in_h = !h.with(&[x]);
151 // but everything is in H or x H
152 let class = forall(|y| h.with(&[y]) | h.with(&[mul(inv.with(&[x]), y)]));
153
154 not_in_h & class
155 });
156
157 // Conjecture: H is normal
158 let h_normal = forall(|x| {
159 let h_x = h.with(&[x]);
160 let conj_x = forall(|y| {
161 let y_inv = inv.with(&[y]);
162 h.with(&[mul(mul(y, x), y_inv)])
163 });
164 h_x.iff(conj_x)
165 });
166
167 Problem::new(Options::new())
168 .with_axiom(right_identity)
169 .with_axiom(right_inverse)
170 .with_axiom(associativity)
171 .with_axiom(h_ident)
172 .with_axiom(h_mul_closed)
173 .with_axiom(h_inv_closed)
174 .with_axiom(h_index_2)
175 .conjecture(h_normal)
176 .solve()
177}More examples
3fn main() {
4 // Prove that every subgroup of index 2 is normal.
5 let mult = Function::new("mult", 2);
6 let inv = Function::new("inv", 1);
7 let one = Function::constant("1");
8
9 // Helper to make multiplication more readable
10 let mul = |x: Term, y: Term| -> Term { mult.with([x, y]) };
11
12 // Group Axiom 1: Right identity - ∀x. x * 1 = x
13 let right_identity = forall(|x| mul(x, one).eq(x));
14
15 // Group Axiom 2: Right inverse - ∀x. x * inv(x) = 1
16 let right_inverse = forall(|x| {
17 let inv_x = inv.with(x);
18 mul(x, inv_x).eq(one)
19 });
20
21 // Group Axiom 3: Associativity - ∀x,y,z. (x * y) * z = x * (y * z)
22 let associativity = forall(|x| forall(|y| forall(|z| mul(mul(x, y), z).eq(mul(x, mul(y, z))))));
23
24 // Describe the subgroup
25 let h = Predicate::new("h", 1);
26
27 // Any subgroup contains the identity
28 let h_ident = h.with(one);
29
30 // And is closed under multiplication
31 let h_mul_closed = forall(|x| forall(|y| (h.with(x) & h.with(y)) >> h.with(mul(x, y))));
32
33 // And is closed under inverse
34 let h_inv_closed = forall(|x| h.with(x) >> h.with(inv.with(x)));
35
36 // H specifically is of order 2
37 let h_index_2 = exists(|x| {
38 // an element not in H
39 let not_in_h = !h.with(x);
40 // but everything is in H or x H
41 let class = forall(|y| h.with(y) | h.with(mul(inv.with(x), y)));
42
43 not_in_h & class
44 });
45
46 // Conjecture: H is normal
47 let h_normal = forall(|x| {
48 let h_x = h.with(x);
49 let conj_x = forall(|y| {
50 let y_inv = inv.with(y);
51 h.with(mul(mul(y, x), y_inv))
52 });
53 h_x.iff(conj_x)
54 });
55
56 let (solution, proof) = Problem::new(Options::new())
57 .with_axiom(right_identity)
58 .with_axiom(right_inverse)
59 .with_axiom(associativity)
60 .with_axiom(h_ident)
61 .with_axiom(h_mul_closed)
62 .with_axiom(h_inv_closed)
63 .with_axiom(h_index_2)
64 .conjecture(h_normal)
65 .solve_and_prove();
66
67 if let Some(proof) = proof {
68 println!("{}", proof);
69 }
70
71 assert_eq!(solution, ProofRes::Proved);
72}Trait Implementations§
Source§impl BitAnd for Formula
Implements the & operator for conjunction (AND).
impl BitAnd for Formula
Implements the & operator for conjunction (AND).
§Examples
use vampire_prover::{Function, Predicate};
let p = Predicate::new("P", 1);
let q = Predicate::new("Q", 1);
let x = Function::constant("x");
// P(x) ∧ Q(x)
let both = p.with(x) & q.with(x);Source§impl BitOr for Formula
Implements the | operator for disjunction (OR).
impl BitOr for Formula
Implements the | operator for disjunction (OR).
§Examples
use vampire_prover::{Function, Predicate};
let p = Predicate::new("P", 1);
let q = Predicate::new("Q", 1);
let x = Function::constant("x");
// P(x) ∨ Q(x)
let either = p.with(x) | q.with(x);Source§impl Not for Formula
Implements the ! operator for negation (NOT).
impl Not for Formula
Implements the ! operator for negation (NOT).
§Examples
use vampire_prover::{Function, Predicate};
let p = Predicate::new("P", 1);
let x = Function::constant("x");
// ¬P(x)
let not_p = !p.with(x);Source§impl Shr for Formula
Implements the >> operator for implication.
impl Shr for Formula
Implements the >> operator for implication.
§Examples
use vampire_prover::{Function, Predicate};
let p = Predicate::new("P", 1);
let q = Predicate::new("Q", 1);
let x = Function::constant("x");
// P(x) → Q(x)
let implies = p.with(x) >> q.with(x);