gapt.proofs.Checkable.scala Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of gapt_3 Show documentation
Show all versions of gapt_3 Show documentation
General Architecture for Proof Theory
The newest version!
package gapt.proofs
import gapt.expr._
import gapt.expr.ty.{->:, TArr, TBase, TVar, Ty}
import gapt.proofs.context.Context
import gapt.proofs.context.facet.ProofNames
import gapt.proofs.context.update.Update
import gapt.proofs.lk.LKProof
import gapt.proofs.lk.rules.AndLeftRule
import gapt.proofs.lk.rules.AndRightRule
import gapt.proofs.lk.rules.BottomAxiom
import gapt.proofs.lk.rules.ContractionRule
import gapt.proofs.lk.rules.CutRule
import gapt.proofs.lk.rules.ConversionRule
import gapt.proofs.lk.rules.EqualityRule
import gapt.proofs.lk.rules.ExistsRightRule
import gapt.proofs.lk.rules.ForallLeftRule
import gapt.proofs.lk.rules.ImpLeftRule
import gapt.proofs.lk.rules.ImpRightRule
import gapt.proofs.lk.rules.InductionRule
import gapt.proofs.lk.rules.LogicalAxiom
import gapt.proofs.lk.rules.NegLeftRule
import gapt.proofs.lk.rules.NegRightRule
import gapt.proofs.lk.rules.OrLeftRule
import gapt.proofs.lk.rules.OrRightRule
import gapt.proofs.lk.rules.ProofLink
import gapt.proofs.lk.rules.ReflexivityAxiom
import gapt.proofs.lk.rules.SkolemQuantifierRule
import gapt.proofs.lk.rules.StrongQuantifierRule
import gapt.proofs.lk.rules.TopAxiom
import gapt.proofs.lk.rules.WeakeningLeftRule
import gapt.proofs.lk.rules.WeakeningRightRule
import gapt.proofs.resolution.ResolutionProof
import scala.collection.mutable
trait Checkable[-T] {
def check(obj: T)(implicit ctx: Context): Unit
}
object Checkable {
def requireDefEq(a: Expr, b: Expr)(implicit ctx: Context): Unit =
require(ctx.isDefEq(a, b), s"${ctx.normalize(a).toSigRelativeString} != ${ctx.normalize(b).toSigRelativeString}")
implicit object contextElementIsCheckable extends Checkable[Update] {
def check(elem: Update)(implicit context: Context): Unit = elem(context)
}
class ExpressionChecker(implicit ctx: Context) {
private val validTy = mutable.Set[Ty]()
def check(ty: Ty): Unit = {
if (validTy.contains(ty)) return
ty match {
case ty @ TBase(name, params) =>
require(
ctx.isType(ty),
s"Unknown base type: $name"
)
params.foreach(check)
case TVar(_) =>
case TArr(in, out) =>
check(in)
check(out)
}
validTy += ty
}
private val validExpr = mutable.Set[Expr]()
def check(expr: Expr): Unit = {
if (validExpr(expr)) return
expr match {
case c @ Const(name, _, params) =>
require(ctx.constant(name, params).contains(c), s"Unknown constant: $c")
case Var(_, t) =>
check(t)
case Abs(v, e) =>
check(v)
check(e)
case App(a, b) =>
check(a)
check(b)
}
validExpr += expr
}
}
implicit object typeIsCheckable extends Checkable[Ty] {
override def check(ty: Ty)(implicit context: Context): Unit =
new ExpressionChecker().check(ty)
}
implicit object expressionIsCheckable extends Checkable[Expr] {
def check(expr: Expr)(implicit context: Context): Unit =
new ExpressionChecker().check(expr)
}
implicit def sequentIsCheckable[T: Checkable]: Checkable[Sequent[T]] = new Checkable[Sequent[T]] {
def check(sequent: Sequent[T])(implicit context: Context) =
sequent.foreach(context.check(_))
}
implicit object lkIsCheckable extends Checkable[LKProof] {
import gapt.proofs.lk._
def check(p: LKProof)(implicit ctx: Context): Unit = {
ctx.check(p.endSequent)
p.subProofs.foreach {
case ForallLeftRule(_, _, a, t, v) => ctx.check(t)
case ExistsRightRule(_, _, a, t, v) => ctx.check(t)
case q: EqualityRule =>
ctx.check(q.replacementContext)
case q @ InductionRule(cases, formula, term) =>
ctx.check(formula)
ctx.check(term)
val Some(ctrsInCtx) = ctx.getConstructors(q.indTy.asInstanceOf[TBase]): @unchecked
val ctrsInProof = cases.map(_.constructor)
require(
ctrsInProof == ctrsInCtx,
s"Induction rule has incorrect constructors: ${ctrsInProof.mkString(", ")}\n" +
s"Expected: ${ctrsInCtx.mkString(", ")}"
)
case sk: SkolemQuantifierRule =>
val Some(skolemDef) = ctx.skolemDef(sk.skolemConst): @unchecked
Checkable.requireDefEq(skolemDef(sk.skolemArgs), sk.mainFormula)
ctx.check(sk.skolemTerm)
case StrongQuantifierRule(_, _, _, _, _) =>
case _: ReflexivityAxiom | _: LogicalAxiom =>
case ProofLink(name, sequent) =>
val declSeq = ctx.get[ProofNames].lookup(name)
require(declSeq.nonEmpty, s"Proof name $name does not exist in context")
require(declSeq.get == sequent, s"$declSeq\nis not equal to \n$sequent")
case TopAxiom | BottomAxiom
| _: NegLeftRule | _: NegRightRule
| _: AndLeftRule | _: AndRightRule
| _: OrLeftRule | _: OrRightRule
| _: ImpLeftRule | _: ImpRightRule =>
case _: ContractionRule | _: WeakeningLeftRule | _: WeakeningRightRule =>
case _: CutRule =>
case d: ConversionRule =>
requireDefEq(d.mainFormula, d.auxFormula)(ctx)
}
}
}
implicit object resolutionIsCheckable extends Checkable[ResolutionProof] {
import gapt.proofs.resolution._
def check(p: ResolutionProof)(implicit ctx: Context): Unit = {
def checkAvatarDef(comp: AvatarDefinition): Unit =
for ((df, by) <- comp.inducedDefinitions)
requireDefEq(df, by)(ctx)
p.subProofs.foreach {
case Input(sequent) => ctx.check(sequent)
case Refl(term) => ctx.check(term)
case Taut(form) => ctx.check(form)
case Defn(df, by) => require(ctx.isDefEq(df, by))
case _: WeakQuantResolutionRule =>
case q: SkolemQuantResolutionRule =>
val Some(skolemDef) = ctx.skolemDef(q.skolemConst): @unchecked
require(BetaReduction.betaNormalize(skolemDef(q.skolemArgs)) == q.subProof.conclusion(q.idx))
ctx.check(q.skolemTerm)
case DefIntro(_, _, definition, _) =>
requireDefEq(definition.what, definition.by)(ctx)
case _: PropositionalResolutionRule =>
case AvatarComponent(defn) => checkAvatarDef(defn)
case AvatarSplit(_, _, defn) => checkAvatarDef(defn)
case _: AvatarComponent | _: AvatarSplit | _: AvatarContradiction =>
case _: Flip | _: Paramod =>
case _: Resolution =>
case _: Factor =>
case _: Subst =>
}
}
}
}