gapt.formats.llk.LLKExporter.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.formats.llk
import gapt.proofs._
import gapt.expr._
import gapt.expr.formula.All
import gapt.expr.formula.And
import gapt.expr.formula.Atom
import gapt.expr.formula.Ex
import gapt.expr.formula.Imp
import gapt.expr.formula.Neg
import gapt.expr.formula.NonLogicalConstant
import gapt.expr.formula.Or
import gapt.expr.formula.constants.EqC
import gapt.expr.formula.constants.LogicalConstant
import gapt.expr.formula.hol.HOLFunction
import gapt.expr.ty.{->:, TArr, Ti, To, Ty}
import gapt.proofs.lk._
import gapt.proofs.lk.rules.AndLeftRule
import gapt.proofs.lk.rules.AndRightRule
import gapt.proofs.lk.rules.ContractionLeftRule
import gapt.proofs.lk.rules.ContractionRightRule
import gapt.proofs.lk.rules.CutRule
import gapt.proofs.lk.rules.ConversionLeftRule
import gapt.proofs.lk.rules.ConversionRightRule
import gapt.proofs.lk.rules.EqualityLeftRule
import gapt.proofs.lk.rules.EqualityRightRule
import gapt.proofs.lk.rules.ExistsLeftRule
import gapt.proofs.lk.rules.ExistsRightRule
import gapt.proofs.lk.rules.ExistsSkLeftRule
import gapt.proofs.lk.rules.ForallLeftRule
import gapt.proofs.lk.rules.ForallRightRule
import gapt.proofs.lk.rules.ForallSkRightRule
import gapt.proofs.lk.rules.ImpLeftRule
import gapt.proofs.lk.rules.ImpRightRule
import gapt.proofs.lk.rules.InitialSequent
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.WeakeningLeftRule
import gapt.proofs.lk.rules.WeakeningRightRule
object LatexLLKExporter extends LLKExporter(true)
object LLKExporter extends LLKExporter(false)
class LLKExporter(val expandTex: Boolean) {
val emptyTypeMap = Map[String, Ty]()
private val nLine = sys.props("line.separator")
def apply(db: ExtendedProofDatabase, escape_latex: Boolean) = {
val types0 = db.eproofs.foldLeft((emptyTypeMap, emptyTypeMap))((t, p) =>
getTypes(p._2, t._1, t._2)
)
val types1 = db.axioms.foldLeft(types0)((m, fs) => getTypes(fs, m._1, m._2))
val (vtypes, ctypes) = db.eproofs.keySet.foldLeft(types1)((m, x) => getTypes(x, m._1, m._2))
val sb = new StringBuilder()
sb.append(generateDeclarations(vtypes, ctypes))
sb.append(nLine + nLine)
for (p <- db.eproofs) {
sb.append(generateProof(p._2, "", escape_latex))
sb.append(nLine)
sb.append("\\CONTINUEWITH{" + toLatexString.getFormulaString(p._1, true, escape_latex) + "}")
sb.append(nLine)
}
sb.toString()
}
def apply(lkp: LKProof, escape_latex: Boolean) = {
val (vtypes, ctypes) = getTypes(lkp, emptyTypeMap, emptyTypeMap)
val declarations = generateDeclarations(vtypes, ctypes)
val proofs = generateProof(lkp, "", escape_latex)
declarations + nLine + "\\CONSTDEC{THEPROOF}{o}" + nLine + nLine + proofs + "\\CONTINUEWITH{THEPROOF}"
}
def generateDeclarations(vars: Map[String, Ty], consts: Map[String, Ty]): String = {
val svars = vars.foldLeft(Map[String, String]())((map, p) => {
val vname = toLatexString.nameToLatexString(p._1.toString)
if (map contains vname) throw new Exception("Two different kinds of symbol share the same name!")
map + ((vname, getTypeString(p._2)))
})
val sconsts = consts.foldLeft(Map[String, String]())((map, p) => {
val vname = toLatexString.nameToLatexString(p._1.toString)
if (map contains vname) throw new Exception("Two different kinds of symbol share the same name!")
map + ((vname, getTypeString(p._2)))
}).filterNot(_._1 == "=")
/*
val sdefs = defs.foldLeft(Map[String, String]())((map, p) => {
val w = "[a-zA-Z0-9]+"
val re= ("("+w+")\\[("+w+"(,"+w+")*"+")\\]").r
val vname = toLatexString.nameToLatexString(p._1.toString, false)
if (map contains vname) throw new Exception("Two different kinds of symbol share the same name!")
map + ((vname, getTypeString(p._2)))
})*/
val rvmap = svars.foldLeft(Map[String, List[String]]())((map, p) => {
val (name, expt) = p
if (map contains expt)
map + ((expt, name :: map(expt)))
else
map + ((expt, name :: Nil))
})
val rcmap = sconsts.foldLeft(Map[String, List[String]]())((map, p) => {
val (name, expt) = p
if (map contains expt)
map + ((expt, name :: map(expt)))
else
map + ((expt, name :: Nil))
})
val sv = rvmap.map(x => "\\VARDEC{" + x._2.mkString(", ") + "}{" + x._1 + "}")
val sc = rcmap.map(x => "\\CONSTDEC{" + x._2.mkString(", ") + "}{" + x._1 + "}")
sv.mkString(nLine) + nLine + sc.mkString(nLine)
}
def getTypes(p: LKProof, vacc: Map[String, Ty], cacc: Map[String, Ty]): (Map[String, Ty], Map[String, Ty]) = {
val formulas = for (subProof <- p.subProofs; formula <- subProof.endSequent.elements) yield formula
formulas.foldLeft((vacc, cacc))((map, f) =>
getTypes(f, map._1, map._2)
)
}
def getTypes(p: HOLSequent, vacc: Map[String, Ty], cacc: Map[String, Ty]): (Map[String, Ty], Map[String, Ty]) = {
p.formulas.foldLeft((vacc, cacc))((m, f) => getTypes(f, m._1, m._2))
}
def getTypes(exp: Expr, vmap: Map[String, Ty], cmap: Map[String, Ty]): (Map[String, Ty], Map[String, Ty]) =
exp match {
case Var(name, exptype) =>
if (vmap.contains(name)) {
if (vmap(name) != exptype) throw new Exception(
"Symbol clash for " + name + " " + vmap(name) + " != " + exptype
)
(vmap, cmap)
} else {
(vmap + ((name, exptype)), cmap)
}
case EqC(_) => (vmap, cmap)
case NonLogicalConstant(name, exptype, _) =>
if (cmap.contains(name)) {
if (cmap(name) != exptype) throw new Exception(
"Symbol clash for " + name + " " + cmap(name) + " != " + exptype
)
(vmap, cmap)
} else {
(vmap, cmap + ((name, exptype)))
}
case App(s, t) =>
val (vm, cm) = getTypes(t, vmap, cmap)
getTypes(s, vm, cm)
case Abs(x, t) =>
val (vm, cm) = getTypes(t, vmap, cmap)
getTypes(x, vm, cm)
case _: LogicalConstant =>
(vmap, cmap)
}
def getTypeString(t: Ty, outermost: Boolean = true): String = (t: @unchecked) match {
case Ti => "i"
case To => "o"
case TArr(t1, t2) =>
val s = getTypeString(t1, false) + ">" + getTypeString(t2, false)
if (outermost) s else "(" + s + ")"
}
def fsequentString(fs: HOLSequent, escape_latex: Boolean): String =
fs.antecedent.map(toLatexString.getFormulaString(_, true, escape_latex)).mkString("{", ",", "}") +
fs.succedent.map(toLatexString.getFormulaString(_, true, escape_latex)).mkString("{", ",", "}")
def generateProof(p: LKProof, s: String, escape_latex: Boolean): String = p match {
case InitialSequent(root) =>
"\\AX" + fsequentString(p.endSequent, escape_latex) + nLine + s
// unary rules
case NegLeftRule(p1, _) =>
generateProof(p1, "\\NEGL" + fsequentString(p.endSequent, escape_latex) + nLine + s, escape_latex)
case NegRightRule(p1, _) =>
generateProof(p1, "\\NEGR" + fsequentString(p.endSequent, escape_latex) + nLine + s, escape_latex)
case AndLeftRule(p1, _, _) =>
generateProof(p1, "\\ANDL" + fsequentString(p.endSequent, escape_latex) + nLine + s, escape_latex)
case OrRightRule(p1, _, _) =>
generateProof(p1, "\\ORR" + fsequentString(p.endSequent, escape_latex) + nLine + s, escape_latex)
case ImpRightRule(p1, _, _) =>
generateProof(p1, "\\IMPR" + fsequentString(p.endSequent, escape_latex) + nLine + s, escape_latex)
// binary rules
case AndRightRule(p1, _, p2, _) =>
generateProof(
p1,
generateProof(
p2,
"\\ANDR" + fsequentString(p.endSequent, escape_latex) + nLine +
s,
escape_latex
),
escape_latex
)
case OrLeftRule(p1, _, p2, _) =>
generateProof(
p1,
generateProof(
p2,
"\\ORL" + fsequentString(p.endSequent, escape_latex) + nLine +
s,
escape_latex
),
escape_latex
)
case ImpLeftRule(p1, _, p2, _) =>
generateProof(
p1,
generateProof(
p2,
"\\IMPL" + fsequentString(p.endSequent, escape_latex) + nLine +
s,
escape_latex
),
escape_latex
)
// structural rules
case CutRule(p1, _, p2, _) =>
generateProof(
p1,
generateProof(
p2,
"\\CUT" + fsequentString(p.endSequent, escape_latex) + nLine +
s,
escape_latex
),
escape_latex
)
case WeakeningLeftRule(p1, _) =>
generateProof(p1, "\\WEAKL" + fsequentString(p.endSequent, escape_latex) + nLine + s, escape_latex)
case WeakeningRightRule(p1, _) =>
generateProof(p1, "\\WEAKR" + fsequentString(p.endSequent, escape_latex) + nLine + s, escape_latex)
case ContractionLeftRule(p1, _, _) =>
generateProof(p1, "\\CONTRL" + fsequentString(p.endSequent, escape_latex) + nLine + s, escape_latex)
case ContractionRightRule(p1, _, _) =>
generateProof(p1, "\\CONTRR" + fsequentString(p.endSequent, escape_latex) + nLine + s, escape_latex)
// quantifier rules
case ForallLeftRule(p1, aux, main, term, qv) =>
generateProof(
p1,
"\\ALLL{" + toLatexString.getFormulaString(term, true, escape_latex) + "}" +
fsequentString(p.endSequent, escape_latex) + nLine + s,
escape_latex
)
case ForallRightRule(p1, main, eigenvar, qv) =>
generateProof(
p1,
"\\ALLR{" + toLatexString.getFormulaString(eigenvar, true, escape_latex) + "}" +
fsequentString(p.endSequent, escape_latex) + nLine + s,
escape_latex
)
case ExistsLeftRule(p1, main, eigenvar, qv) =>
generateProof(
p1,
"\\EXL{" + toLatexString.getFormulaString(eigenvar, true, escape_latex) + "}" +
fsequentString(p.endSequent, escape_latex) + nLine + s,
escape_latex
)
case ExistsRightRule(p1, aux, main, term, qv) =>
generateProof(
p1,
"\\EXR{" + toLatexString.getFormulaString(term, true, escape_latex) + "}" +
fsequentString(p.endSequent, escape_latex) + nLine + s,
escape_latex
)
// equality rules
case EqualityLeftRule(p1, _, _, _) =>
generateProof(p1, "\\UEQL" + fsequentString(p.endSequent, escape_latex) + nLine + s, escape_latex)
case EqualityRightRule(p1, _, _, _) =>
generateProof(p1, "\\UEQR" + fsequentString(p.endSequent, escape_latex) + nLine + s, escape_latex)
// definition rules
case ConversionLeftRule(p1, _, _) =>
generateProof(p1, "\\DEF" + fsequentString(p.endSequent, escape_latex) + nLine + s, escape_latex)
case ConversionRightRule(p1, _, _) =>
generateProof(p1, "\\DEF" + fsequentString(p.endSequent, escape_latex) + nLine + s, escape_latex)
// TODO: this is only a way to write out the proof, but it cannot be read back in
// (labels are not handled by llk so far)
case ExistsSkLeftRule(p1, aux, main, term) =>
generateProof(
p1,
"\\EXSKL{" + toLatexString.getFormulaString(term, true, escape_latex) + "}"
+ fsequentString(p.endSequent, escape_latex) + nLine + s,
escape_latex
)
/*
case ExistsSkRightRule( p1, aux, main, term ) =>
generateProof( p1, "\\EXSKR{" + toLatexString.getFormulaString( term, true, escape_latex ) + "}"
+ fsequentString( p.endSequent, escape_latex ) + nLine + s, escape_latex )
case ForallSkLeftRule( p1, aux, main, term ) =>
generateProof( p1, "\\ALLSKL{" + toLatexString.getFormulaString( term, true, escape_latex ) + "}"
+ fsequentString( p.endSequent, escape_latex ) + nLine + s, escape_latex )
*/
case ForallSkRightRule(p1, aux, main, term) =>
generateProof(
p1,
"\\ALLSKR{" + toLatexString.getFormulaString(term, true, escape_latex) + "}"
+ fsequentString(p.endSequent, escape_latex) + nLine + s,
escape_latex
)
}
}
/**
* This is a prover9 style formatting which can be parsed by LLK.
*/
object toLLKString {
def apply(e: Expr) = toLatexString.getFormulaString(e, true, false)
}
/**
* This is a Latex formatting which can be parsed by LLK.
*/
object toLatexString {
def apply(e: Expr) = getFormulaString(e, true, true)
def getFormulaString(f: Expr, outermost: Boolean = true, escape_latex: Boolean): String = f match {
case All(x, t) =>
val op = if (escape_latex) "\\forall" else "all"
op + " " + getFormulaString(x.asInstanceOf[Var], false, escape_latex) +
" " + getFormulaString(t, false, escape_latex)
case Ex(x, t) =>
val op = if (escape_latex) "\\exists" else "exists"
op + " " + getFormulaString(x.asInstanceOf[Var], false, escape_latex) +
" " + getFormulaString(t, false, escape_latex)
case Neg(t1) =>
val op = if (escape_latex) "\\neg" else "-"
val str = " " + op + " " + getFormulaString(t1, false, escape_latex)
if (outermost) str else "(" + str + ")"
case And(t1, t2) =>
val op = if (escape_latex) "\\land" else "&"
val str = getFormulaString(t1, false, escape_latex) + " " + op + " " +
getFormulaString(t2, false, escape_latex)
if (outermost) str else "(" + str + ")"
case Or(t1, t2) =>
val op = if (escape_latex) "\\lor" else "|"
val str = getFormulaString(t1, false, escape_latex) + " " + op + " " +
getFormulaString(t2, false, escape_latex)
if (outermost) str else "(" + str + ")"
case Imp(t1, t2) =>
val op = if (escape_latex) "\\rightarrow" else "->"
val str = getFormulaString(t1, false, escape_latex) + " " + op + " " +
getFormulaString(t2, false, escape_latex)
if (outermost) str else "(" + str + ")"
case Var(v, _) => v.toString
case Const(c, _, _) => c.toString
case Atom(f, args) =>
val sym = f match {
case Const(x, _, _) => x
case Var(x, _) => x
}
val str: String =
if (args.length == 2 && sym.toString.matches("""(<|>|\\leq|\\geq|=|>=|<=)""")) {
val str = getFormulaString(args(0), false, escape_latex) + " " +
toLatexString.nameToLatexString(sym.toString) + " " +
getFormulaString(args(1), false, escape_latex)
if (outermost) str else "(" + str + ")"
} else
toLatexString.nameToLatexString(sym.toString) + (
if (args.isEmpty) " "
else args.map(getFormulaString(_, false, escape_latex)).mkString("(", ", ", ")")
)
// if (outermost) str else "(" + str + ")"
str
case HOLFunction(f, args) =>
val sym = f match {
case Const(x, _, _) => x
case Var(x, _) => x
}
if (args.length == 2 && sym.toString.matches("""[+\-*/]"""))
"(" + getFormulaString(args(0), false, escape_latex) + " " + sym.toString + " " +
getFormulaString(args(1), false, escape_latex) + ")"
else {
if (args.isEmpty)
toLatexString.nameToLatexString(sym.toString)
else
toLatexString.nameToLatexString(sym.toString) + (
if (args.isEmpty) " "
else args.map(getFormulaString(_, false, escape_latex)).mkString("(", ", ", ")")
)
}
// these cases need to be below the quantifiers and function/atom, since the latter are less general than abs/app
case Abs(x, t) =>
"(\\lambda " + getFormulaString(x.asInstanceOf[Var], false, escape_latex) + " " +
getFormulaString(t, false, escape_latex) + ")"
case App(s, t) =>
if (escape_latex)
"\\apply{ " + getFormulaString(s, false, escape_latex) + " " +
getFormulaString(t, false, escape_latex) + "}"
else
"(@ " + getFormulaString(s, false, escape_latex) + " " + getFormulaString(t, false, escape_latex) + ")"
}
def nameToLatexString(s: String, escapebrack: Boolean = true): String = {
val s1 = UnicodeToLatex.nameToLatexString(s)
// val s2 = if (escapebrack) s1.replaceAll("\\[","(").replaceAll("\\]",")") else s1
val s2 = if (s == "!=") "\\neq" else s1
val s3 = if (s2 != "-") s2.replaceAll("-", "") else s2
s3
}
}