Skip to main content

Formula

Struct Formula 

Source
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

Source

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 representation
Source

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]);
Source

pub fn new_eq(lhs: Term, rhs: Term) -> Self

Creates an equality formula between two terms.

This is typically called via Term::eq rather than directly.

§Examples
use vampire_prover::{Function, Formula};

let x = Function::constant("x");
let y = Function::constant("y");

let eq = Formula::new_eq(x, y);
Source

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),
]);
Source

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),
]);
Source

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));
Source

pub fn new_true() -> Self

Creates the true (tautology) formula.

§Examples
use vampire_prover::Formula;

let t = Formula::new_true();
Source

pub fn new_false() -> Self

Creates the false (contradiction) formula.

§Examples
use vampire_prover::Formula;

let f = Formula::new_false();
Source

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 quantify
  • f - 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));
Source

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 quantify
  • f - 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));
Source

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));
Source

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?
examples/bench_index2.rs (line 164)
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
Hide additional examples
examples/group2.rs (line 53)
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).

§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§

type Output = Formula

The resulting type after applying the & operator.
Source§

fn bitand(self, rhs: Self) -> Self::Output

Performs the & operation. Read more
Source§

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§

type Output = Formula

The resulting type after applying the | operator.
Source§

fn bitor(self, rhs: Self) -> Self::Output

Performs the | operation. Read more
Source§

impl Clone for Formula

Source§

fn clone(&self) -> Formula

Returns a duplicate of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for Formula

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Display for Formula

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Hash for Formula

Source§

fn hash<H: Hasher>(&self, state: &mut H)

Feeds this value into the given Hasher. Read more
1.3.0 · Source§

fn hash_slice<H>(data: &[Self], state: &mut H)
where H: Hasher, Self: Sized,

Feeds a slice of this type into the given Hasher. Read more
Source§

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§

type Output = Formula

The resulting type after applying the ! operator.
Source§

fn not(self) -> Self::Output

Performs the unary ! operation. Read more
Source§

impl PartialEq for Formula

Source§

fn eq(&self, other: &Self) -> bool

Tests for self and other values to be equal, and is used by ==.
1.0.0 · Source§

fn ne(&self, other: &Rhs) -> bool

Tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.
Source§

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);
Source§

type Output = Formula

The resulting type after applying the >> operator.
Source§

fn shr(self, rhs: Self) -> Self::Output

Performs the >> operation. Read more
Source§

impl Copy for Formula

Source§

impl Eq for Formula

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T> ToString for T
where T: Display + ?Sized,

Source§

fn to_string(&self) -> String

Converts the given value to a String. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.