#![cfg_attr(docsrs, feature(doc_cfg))]
#![doc = include_str!("../README.md")]
pub mod cyclotomic;
pub mod elliptic;
pub mod factor;
pub mod fp2;
pub mod hyperelliptic;
pub mod lattice;
pub mod period;
pub mod arith;
pub mod cdcl;
pub mod cnf;
pub mod dimacs;
pub mod proof;
pub mod proof_emit;
pub mod complexity;
pub mod ait;
pub mod isogeny;
pub mod coalgebra;
pub mod groupoid;
pub mod category_collapse;
pub mod two_group;
pub mod proof_rewrite;
pub mod trace_determinism;
pub mod progress_complex;
pub mod cubical;
pub mod kan_complex;
pub mod two_type;
pub mod eilenberg_maclane;
pub mod postnikov;
pub mod steenrod;
pub mod pr;
pub mod affine;
pub mod affine_gfp;
pub mod families;
pub mod gf2;
pub mod hypercube;
pub mod census;
pub mod cofactor;
pub mod res_width;
pub mod rup;
pub mod sat;
pub mod satcli;
pub mod solve;
pub mod xor_drat;
pub mod xor_engine;
pub mod bmc;
pub mod cardinality;
pub mod counting_principle;
pub mod matching;
pub mod ordering;
pub mod parity_cardinality;
pub mod pigeonhole;
pub mod pseudo_boolean;
pub mod symmetry;
pub mod symmetry_detect;
pub mod sym_certify;
pub mod sym_dynamic;
pub mod lyapunov;
pub mod inprocess;
pub mod sdcl;
pub mod xorsat;
pub mod lll;
pub mod modp;
pub mod modm;
pub mod orbit_stability;
pub mod polycalc;
pub mod polycalc_gfp;
pub mod polycalc_zm;
pub mod sos;
pub mod permgroup;
pub mod sym_break;
pub mod hornsat;
pub mod twosat;
pub mod interval_sched;
pub mod register_alloc;
pub mod optimize;
pub mod certifier;
pub mod counterexample;
pub mod crush;
pub mod decide;
pub mod development;
pub mod discrimination;
pub mod lemma_index;
pub mod engine;
pub mod simp;
pub mod formula;
pub mod tactic;
pub mod tactic_script;
pub mod rule_search;
pub mod linarith_solve;
pub mod omega_solve;
pub mod grounding;
pub mod grid_solver;
pub mod error;
pub mod hints;
pub mod unify;
pub mod verify;
#[cfg(feature = "verification")]
pub mod oracle;
#[cfg(feature = "verification")]
mod modal_translation;
pub use engine::BackwardChainer;
pub use error::ProofError;
pub use hints::{suggest_hint, SocraticHint, SuggestedTactic};
pub use unify::Substitution;
use std::fmt;
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub enum ProofTerm {
Constant(String),
Variable(String),
Function(String, Vec<ProofTerm>),
Group(Vec<ProofTerm>),
BoundVarRef(String),
}
impl fmt::Display for ProofTerm {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
ProofTerm::Constant(s) => write!(f, "{}", s),
ProofTerm::Variable(s) => write!(f, "{}", s),
ProofTerm::Function(name, args) => {
write!(f, "{}(", name)?;
for (i, arg) in args.iter().enumerate() {
if i > 0 {
write!(f, ", ")?;
}
write!(f, "{}", arg)?;
}
write!(f, ")")
}
ProofTerm::Group(terms) => {
write!(f, "(")?;
for (i, t) in terms.iter().enumerate() {
if i > 0 {
write!(f, ", ")?;
}
write!(f, "{}", t)?;
}
write!(f, ")")
}
ProofTerm::BoundVarRef(s) => write!(f, "#{}", s),
}
}
}
#[derive(Debug, Clone, PartialEq)]
pub enum ProofExpr {
Predicate {
name: String,
args: Vec<ProofTerm>,
world: Option<String>,
},
Identity(ProofTerm, ProofTerm),
Atom(String),
And(Box<ProofExpr>, Box<ProofExpr>),
Or(Box<ProofExpr>, Box<ProofExpr>),
Implies(Box<ProofExpr>, Box<ProofExpr>),
Iff(Box<ProofExpr>, Box<ProofExpr>),
Not(Box<ProofExpr>),
ForAll {
variable: String,
body: Box<ProofExpr>,
},
Exists {
variable: String,
body: Box<ProofExpr>,
},
Modal {
domain: String,
force: f32,
flavor: String,
body: Box<ProofExpr>,
},
Counterfactual {
antecedent: Box<ProofExpr>,
consequent: Box<ProofExpr>,
},
Temporal {
operator: String,
body: Box<ProofExpr>,
},
TemporalBinary {
operator: String,
left: Box<ProofExpr>,
right: Box<ProofExpr>,
},
Lambda {
variable: String,
body: Box<ProofExpr>,
},
App(Box<ProofExpr>, Box<ProofExpr>),
NeoEvent {
event_var: String,
verb: String,
roles: Vec<(String, ProofTerm)>,
},
Ctor {
name: String,
args: Vec<ProofExpr>,
},
Match {
scrutinee: Box<ProofExpr>,
arms: Vec<MatchArm>,
},
Fixpoint {
name: String,
body: Box<ProofExpr>,
},
TypedVar {
name: String,
typename: String,
},
Hole(String),
Term(ProofTerm),
Unsupported(String),
}
#[derive(Debug, Clone, PartialEq)]
pub struct MatchArm {
pub ctor: String,
pub bindings: Vec<String>,
pub body: ProofExpr,
}
impl fmt::Display for ProofExpr {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
ProofExpr::Predicate { name, args, world } => {
write!(f, "{}", name)?;
if !args.is_empty() {
write!(f, "(")?;
for (i, arg) in args.iter().enumerate() {
if i > 0 {
write!(f, ", ")?;
}
write!(f, "{}", arg)?;
}
write!(f, ")")?;
}
if let Some(w) = world {
write!(f, " @{}", w)?;
}
Ok(())
}
ProofExpr::Identity(left, right) => write!(f, "{} = {}", left, right),
ProofExpr::Atom(s) => write!(f, "{}", s),
ProofExpr::And(left, right) => write!(f, "({} ∧ {})", left, right),
ProofExpr::Or(left, right) => write!(f, "({} ∨ {})", left, right),
ProofExpr::Implies(left, right) => write!(f, "({} → {})", left, right),
ProofExpr::Iff(left, right) => write!(f, "({} ↔ {})", left, right),
ProofExpr::Not(inner) => write!(f, "¬{}", inner),
ProofExpr::ForAll { variable, body } => write!(f, "∀{} {}", variable, body),
ProofExpr::Exists { variable, body } => write!(f, "∃{} {}", variable, body),
ProofExpr::Modal { domain, force, flavor, body } => {
write!(f, "□[{}/{}/{}]{}", domain, force, flavor, body)
}
ProofExpr::Counterfactual { antecedent, consequent } => {
write!(f, "({} □→ {})", antecedent, consequent)
}
ProofExpr::Temporal { operator, body } => write!(f, "{}({})", operator, body),
ProofExpr::TemporalBinary { operator, left, right } => {
write!(f, "TemporalBinary({}, {}, {})", operator, left, right)
}
ProofExpr::Lambda { variable, body } => write!(f, "λ{}.{}", variable, body),
ProofExpr::App(func, arg) => write!(f, "({} {})", func, arg),
ProofExpr::NeoEvent { event_var, verb, roles } => {
write!(f, "∃{}({}({})", event_var, verb, event_var)?;
for (role, term) in roles {
write!(f, " ∧ {}({}, {})", role, event_var, term)?;
}
write!(f, ")")
}
ProofExpr::Ctor { name, args } => {
write!(f, "{}", name)?;
if !args.is_empty() {
write!(f, "(")?;
for (i, arg) in args.iter().enumerate() {
if i > 0 {
write!(f, ", ")?;
}
write!(f, "{}", arg)?;
}
write!(f, ")")?;
}
Ok(())
}
ProofExpr::Match { scrutinee, arms } => {
write!(f, "match {} {{ ", scrutinee)?;
for (i, arm) in arms.iter().enumerate() {
if i > 0 {
write!(f, ", ")?;
}
write!(f, "{}", arm.ctor)?;
if !arm.bindings.is_empty() {
write!(f, "({})", arm.bindings.join(", "))?;
}
write!(f, " => {}", arm.body)?;
}
write!(f, " }}")
}
ProofExpr::Fixpoint { name, body } => write!(f, "fix {}.{}", name, body),
ProofExpr::TypedVar { name, typename } => write!(f, "{}:{}", name, typename),
ProofExpr::Unsupported(desc) => write!(f, "⟨unsupported: {}⟩", desc),
ProofExpr::Hole(name) => write!(f, "?{}", name),
ProofExpr::Term(term) => write!(f, "{}", term),
}
}
}
#[derive(Debug, Clone, PartialEq)]
pub struct InductionCase {
pub constructor: String,
pub args: Vec<InductionArg>,
}
#[derive(Debug, Clone, PartialEq)]
pub struct InductionArg {
pub name: String,
pub recursive: bool,
}
#[derive(Debug, Clone, PartialEq)]
pub enum InferenceRule {
PremiseMatch,
ModusPonens,
ModusTollens,
ConjunctionIntro,
ConjunctionElim,
DisjunctionIntro,
DisjunctionElim,
ExFalso,
ImpliesIntro,
BicondIntro,
DoubleNegation,
ClassicalReductio,
UniversalInst(String),
UniversalInstTerm(ProofTerm),
UniversalIntro { variable: String, var_type: String },
ExistentialIntro {
witness: String,
witness_type: String,
},
ModalAccess,
ModalGeneralization,
TemporalTransitivity,
TemporalInduction,
TemporalUnfolding,
EventualityProgress,
UntilInduction,
StructuralInduction {
variable: String, ind_type: String, step_var: String, },
InductionScheme {
variable: String, ind_type: String, cases: Vec<InductionCase>, },
LeTrans,
LeRefl,
LeAddMono,
LinFalse,
LeMulNonneg,
LeSub,
LtSuccLe,
LtAdd1Le,
Rewrite {
from: ProofTerm,
to: ProofTerm,
},
EqualitySymmetry,
EqualityTransitivity,
Reflexivity,
ArithDecision,
NativeDecide,
Axiom,
OracleVerification(String),
ReductioAdAbsurdum,
Contradiction,
ExistentialElim { witness: String },
CaseAnalysis { case_formula: Box<ProofExpr> },
DisjunctionCases,
}
#[derive(Debug, Clone)]
pub struct DerivationTree {
pub conclusion: ProofExpr,
pub rule: InferenceRule,
pub premises: Vec<DerivationTree>,
pub depth: usize,
pub substitution: unify::Substitution,
}
impl DerivationTree {
pub fn new(
conclusion: ProofExpr,
rule: InferenceRule,
premises: Vec<DerivationTree>,
) -> Self {
let max_depth = premises.iter().map(|p| p.depth).max().unwrap_or(0);
Self {
conclusion,
rule,
premises,
depth: max_depth + 1,
substitution: unify::Substitution::new(),
}
}
pub fn leaf(conclusion: ProofExpr, rule: InferenceRule) -> Self {
Self::new(conclusion, rule, vec![])
}
pub fn with_substitution(mut self, subst: unify::Substitution) -> Self {
self.substitution = subst;
self
}
pub fn display_tree(&self) -> String {
self.display_recursive(0)
}
fn display_recursive(&self, indent: usize) -> String {
let prefix = " ".repeat(indent);
let rule_name = match &self.rule {
InferenceRule::UniversalInst(var) => format!("UniversalInst({})", var),
InferenceRule::UniversalInstTerm(term) => format!("UniversalInst({})", term),
InferenceRule::UniversalIntro { variable, var_type } => {
format!("UniversalIntro({}:{})", variable, var_type)
}
InferenceRule::ExistentialIntro { witness, witness_type } => {
format!("∃Intro({}:{})", witness, witness_type)
}
InferenceRule::StructuralInduction { variable, ind_type, step_var } => {
format!("Induction({}:{}, step={})", variable, ind_type, step_var)
}
InferenceRule::OracleVerification(s) => format!("Oracle({})", s),
InferenceRule::Rewrite { from, to } => format!("Rewrite({} → {})", from, to),
InferenceRule::EqualitySymmetry => "EqSymmetry".to_string(),
InferenceRule::EqualityTransitivity => "EqTransitivity".to_string(),
r => format!("{:?}", r),
};
let mut output = format!("{}└─ [{}] {}\n", prefix, rule_name, self.conclusion);
for premise in &self.premises {
output.push_str(&premise.display_recursive(indent + 1));
}
output
}
}
impl fmt::Display for DerivationTree {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.display_tree())
}
}
#[derive(Debug, Clone)]
pub struct ProofGoal {
pub target: ProofExpr,
pub context: Vec<ProofExpr>,
}
impl ProofGoal {
pub fn new(target: ProofExpr) -> Self {
Self {
target,
context: Vec::new(),
}
}
pub fn with_context(target: ProofExpr, context: Vec<ProofExpr>) -> Self {
Self { target, context }
}
}