-
Notifications
You must be signed in to change notification settings - Fork 19
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
425b41e
commit 3a3a865
Showing
1 changed file
with
123 additions
and
0 deletions.
There are no files selected for viewing
123 changes: 123 additions & 0 deletions
123
lisa-sets2/src/main/scala/lisa/automation/atp/Egg.scala
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,123 @@ | ||
package lisa.automation.atp | ||
import lisa.utils.fol.FOL as F | ||
import lisa.utils.prooflib.Library | ||
import lisa.utils.prooflib.OutputManager | ||
import lisa.utils.prooflib.ProofTacticLib.* | ||
import lisa.utils.K | ||
import lisa.utils.tptp.* | ||
|
||
import java.io.* | ||
import scala.io.Source | ||
import scala.util.Failure | ||
import scala.util.Success | ||
import scala.util.Try | ||
|
||
import ProofParser.* | ||
import KernelParser.* | ||
import sys.process._ | ||
|
||
/** | ||
* Goéland is an automated theorem prover. This tactic calls the Goéland prover to solve the current sequent. | ||
* Goéland is only available on Linux yet, but proofs generated by Goéland should be kept in the library for future use. | ||
* To ensure that proofs are published and can be replayed in any system, proofs from an ATPcan only be generated in draft mode. | ||
* When in non-draft mode, the proof file should be given as an argument to the tactic (the exact file is provided by Lisa upon run without draft mode). | ||
*/ | ||
object Egg extends ProofTactic with ProofSequentTactic { | ||
private var i : Int = 0 | ||
|
||
val goelandExec = "../bin/egg-sc-tptp" | ||
|
||
class OsNotSupportedException(msg: String) extends Exception(msg) | ||
|
||
val foldername = "egg/" | ||
|
||
/** | ||
* Fetch a proof of a sequent that was previously proven by Goéland. | ||
* The file must be in SC-TPTP format. | ||
*/ | ||
def apply(using lib: Library, proof: lib.Proof)(file:String)(bot: F.Sequent): proof.ProofTacticJudgement = { | ||
val outputname = proof.owningTheorem.fullName+"_sol" | ||
try { | ||
val scproof = reconstructProof(new File(foldername+outputname+".p"))(using ProofParser.mapAtom, ProofParser.mapTerm, ProofParser.mapVariable) | ||
proof.ValidProofTactic(bot, scproof.steps, Seq()) | ||
} catch { | ||
case e: FileNotFoundException => | ||
throw FileNotFoundException("The file "+foldername+outputname+".p was not found. To produce a proof, use `by Egg`. ") | ||
case e => throw e | ||
} | ||
} | ||
|
||
|
||
/** | ||
* Solve a sequent using the Goéland automated theorem prover. | ||
* At the moment, this option is only available on Linux system. | ||
* The proof is generated and saved in a file in the `Egg` folder. | ||
*/ | ||
def apply(using lib: Library, proof: lib.Proof)(bot: F.Sequent): proof.ProofTacticJudgement = { | ||
from(using lib, proof)()(bot) | ||
} | ||
|
||
def from(using lib: Library, proof: lib.Proof)(premises: proof.Fact*)(bot: F.Sequent) = { | ||
val axioms = premises.map(proof.getSequent) | ||
solve(axioms, bot, proof.owningTheorem.fullName, lib.isDraft) match { | ||
case Success(value) => proof.ValidProofTactic(bot, value.steps, premises) | ||
case Failure(e) => e match | ||
case e: FileNotFoundException => throw new Exception("For compatibility reasons, external provers can't be called in non-draft mode" + | ||
" unless all proofs have already been generated and be available in static files. You can enable draft mode by adding `draft()` at the top of your working file.") | ||
case e: OsNotSupportedException => throw e | ||
case e => | ||
throw e | ||
} | ||
} | ||
|
||
inline def solve(axioms: Seq[F.Sequent], sequent: F.Sequent, source: String, generateProofs : Boolean): Try[K.SCProof] = | ||
solveK(axioms.map(_.underlying), sequent.underlying, source, generateProofs) | ||
|
||
|
||
/** | ||
* Solve a sequent using the Goéland automated theorem prover, and return the kernel proof. | ||
* At the moment, this option is only available on Linux systems. | ||
*/ | ||
def solveK(using line: sourcecode.Line, file: sourcecode.File)(axioms: Seq[K.Sequent], sequent: K.Sequent, source:String, generateProofs : Boolean): Try[K.SCProof] = { | ||
val filename = source | ||
val outputname = source+"_sol" | ||
val directory = File(foldername) | ||
if (directory != null) && !directory.exists() then directory.mkdirs() | ||
|
||
val freevars = (sequent.left.flatMap(_.freeVariables) ++ sequent.right.flatMap(_.freeVariables) ).toSet.map(x => x -> K.Variable(K.Identifier("X"+x.id.name, x.id.no), x.sort) ).toMap | ||
|
||
val backMap = freevars.map{ | ||
case (x: K.Variable, xx: K.Variable) => xx -> x | ||
} | ||
val r = problemToFile(foldername, filename, "question"+i, axioms, sequent, source) | ||
i += 1 | ||
|
||
if generateProofs then | ||
val OS = System.getProperty("os.name") | ||
if OS.contains("nix") || OS.contains("nux") || OS.contains("aix") then | ||
val ret = s"chmod u+x \"$goelandExec\"".! | ||
val cmd = (s"$goelandExec $foldername$filename.p $foldername$outputname.p") // TODO | ||
val res = try { | ||
cmd.!! | ||
} catch { | ||
case e: Exception => | ||
throw e | ||
} | ||
val proof = reconstructProof(new File(foldername+outputname+".p"))(using ProofParser.mapAtom, ProofParser.mapTerm, ProofParser.mapVariable) | ||
Success(proof) | ||
else if OS.contains("win") then | ||
Failure(OsNotSupportedException("The Egg automated theorem prover is not yet supported on Windows.")) | ||
else | ||
Failure(OsNotSupportedException("The Egg automated theorem prover is only supported on Linux for now.")) | ||
else | ||
if File(foldername+outputname+".p").exists() then | ||
val proof = reconstructProof(new File(foldername+outputname+".p"))(using ProofParser.mapAtom, ProofParser.mapTerm, ProofParser.mapVariable) | ||
println(OutputManager.WARNING(s"WARNING: in ${file.value}:$line, For compatibility reasons, replace `by Egg` with `by Egg(\"$foldername$outputname\")`.")) | ||
Success(proof) | ||
|
||
else Failure(Exception("For compatibility reasons, external provers can't be called in non-draft mode. You can enable draft mode by adding `draft()` at the top of your working file.")) | ||
|
||
|
||
} | ||
|
||
} |