use crate::{Formula, Sequent};
#[derive(Clone, Debug)]
pub struct Proof {
pub conclusion: Sequent,
pub rule: Rule,
pub premises: Vec<Proof>,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum Rule {
Axiom,
Cut(Formula),
OneIntro,
BottomIntro,
TensorIntro,
ParIntro,
TopIntro,
WithIntro,
PlusIntroLeft,
PlusIntroRight,
OfCourseIntro,
WhyNotIntro,
Weakening,
Contraction,
Dereliction,
FocusPositive(usize),
FocusNegative(usize),
Blur,
}
impl Proof {
pub fn cut_count(&self) -> usize {
let self_cuts = if matches!(self.rule, Rule::Cut(_)) {
1
} else {
0
};
let premise_cuts: usize = self.premises.iter().map(|p| p.cut_count()).sum();
self_cuts + premise_cuts
}
pub fn is_cut_free(&self) -> bool {
self.cut_count() == 0
}
pub fn depth(&self) -> usize {
if self.premises.is_empty() {
1
} else {
1 + self.premises.iter().map(|p| p.depth()).max().unwrap_or(0)
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_cut_count() {
let axiom = Proof {
conclusion: Sequent::new(vec![]),
rule: Rule::Axiom,
premises: vec![],
};
assert_eq!(axiom.cut_count(), 0);
assert!(axiom.is_cut_free());
}
#[test]
fn test_depth() {
let leaf = Proof {
conclusion: Sequent::new(vec![]),
rule: Rule::Axiom,
premises: vec![],
};
assert_eq!(leaf.depth(), 1);
let with_premise = Proof {
conclusion: Sequent::new(vec![]),
rule: Rule::BottomIntro,
premises: vec![leaf],
};
assert_eq!(with_premise.depth(), 2);
}
}