Skip to content

Commit 0799347

Browse files
Update TPTP problem solver code
1 parent b1b6308 commit 0799347

File tree

3 files changed

+100
-63
lines changed

3 files changed

+100
-63
lines changed

lisa-examples/src/main/scala/TPTPSolver.scala

Lines changed: 79 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -2,71 +2,108 @@ import scala.concurrent.duration._
22
import scala.concurrent.ExecutionContext.Implicits.global
33
import scala.concurrent._
44
import java.util.concurrent.CancellationException
5+
import java.io.File
56

6-
import lisa.utils.tptp.Example.*
7-
import lisa.utils.tptp.KernelParser.annotatedFormulaToKernel
8-
import lisa.utils.tptp.KernelParser.parseToKernel
9-
import lisa.utils.tptp.KernelParser.problemToSequent
10-
import lisa.utils.tptp.ProblemGatherer.getPRPproblems
7+
import lisa.utils.tptp.*
8+
import lisa.utils.tptp.KernelParser.*
9+
import lisa.utils.tptp.KernelParser.getProblemInfos
10+
import lisa.utils.tptp.ProblemGatherer.*
1111
import lisa.utils.ProofsConverter.*
12+
import lisa.kernel.proof.SCProof
13+
import java.io.FileWriter
14+
import lisa.kernel.proof.SequentCalculus.Sequent
1215

1316
object TPTPSolver extends lisa.Main {
1417
try {
15-
println("Fetching problems from TPTP library...")
16-
val probs = getPRPproblems
18+
val spc = Seq("PRP", "FOF") // type of problems we want to extract and solve
19+
// val spc = Seq("PRP", "FOF", "CNF") // almost no CNF problems are solved by Tableau, TODO: investigate why
1720

18-
println("Number of problems found: " + probs.size)
21+
// val d = new File(TPTPProblemPath)
22+
// val libraries = d.listFiles.filter(_.isDirectory)
23+
// val probfiles = libraries.flatMap(_.listFiles).filter(_.isFile)
24+
25+
val d = new File(TPTPProblemPath + "SYN/")
26+
val probfiles = d.listFiles.filter(_.isFile)
1927

2028
// We limit the execution time to solve each problem
21-
val timeoutTableau = 1.second
22-
val timeoutTautology = 1.second
29+
val timeoutTableau = .2.second
30+
val timeoutTautology = .2.second
2331

24-
var tableauProofs = List[Option[SCProof]]()
25-
var tautologyProofs = List[Option[SCProof]]()
32+
var problems = List[Problem]()
33+
var tableauProofs = List[SolverResult]()
34+
var tautologyProofs = List[SolverResult]()
2635

27-
for ((p, i) <- probs.zipWithIndex) {
36+
for ((probfile, i) <- probfiles.zipWithIndex) {
2837
// Progress bar
29-
if ((i + 1) % 10 == 0 || i + 1 == probs.size) {
38+
if ((i + 1) % 10 == 0 || i + 1 == probfiles.size) {
3039
val pbarLength = 30
31-
var pbarContent = "=" * (((i + 1) * pbarLength) / probs.size)
40+
var pbarContent = "=" * (((i + 1) * pbarLength) / probfiles.size)
3241
pbarContent += " " * (pbarLength - pbarContent.length)
3342
print("[" + pbarContent + "]")
34-
print(" -- Processed " + (i + 1) + "/" + probs.size)
35-
print(" -- " + tableauProofs.count(_.isDefined) + " solved by Tableau")
36-
println(" -- " + tautologyProofs.count(_.isDefined) + " solved by Tautology")
43+
print(" -- " + (i + 1) + "/" + probfiles.size + " processed files")
44+
print(" -- " + problems.size + " extracted problems")
45+
print(" -- Tableau: " + tableauProofs.count(_.isInstanceOf[Solved]) + " solved")
46+
println(" -- Tautology: " + tautologyProofs.count(_.isInstanceOf[Solved]) + " solved")
3747
}
3848

39-
val seq = problemToSequent(p)
40-
41-
// Attempting proof by Tableau
42-
val (futureTableau, cancelTableau) = Future.interruptibly { Tableau.solve(seq) }
43-
tableauProofs = tableauProofs :+ (
44-
try Await.result(futureTableau, timeoutTableau)
45-
catch
46-
case _ =>
47-
cancelTableau()
48-
None
49-
)
50-
51-
// Attempting proof by Tautology
52-
val (futureTautology, cancelTautology) = Future.interruptibly {
53-
Tautology.solveSequent(seq) match
54-
case Left(proof) => Some(proof)
55-
case _ => None
49+
// Try to extract the problem
50+
try {
51+
val md = getProblemInfos(probfile)
52+
if (md.spc.exists(spc.contains)) {
53+
val p = problemToKernel(probfile, md)
54+
problems = problems :+ p
55+
val seq = problemToSequent(p)
56+
57+
// Attempting proof by Tableau
58+
tableauProofs = tableauProofs :+ solveProblem(p, timeoutTableau, Tableau.solve)
59+
60+
// Attempting proof by Tautology
61+
def tautologySolver(s: lisa.utils.K.Sequent): Option[SCProof] = Tautology.solveSequent(s) match
62+
case Left(proof) => Some(proof)
63+
case _ => None
64+
tautologyProofs = tautologyProofs :+ solveProblem(p, timeoutTautology, tautologySolver)
65+
}
66+
} catch {
67+
case _ => ()
5668
}
57-
tautologyProofs = tautologyProofs :+ (
58-
try Await.result(futureTautology, timeoutTautology)
59-
catch
60-
case _ =>
61-
cancelTautology()
62-
None
63-
)
69+
6470
}
6571
} catch {
6672
case error: NullPointerException => println("You can download the tptp library at http://www.tptp.org/ and put it in main/resources")
6773
}
6874
}
6975

76+
sealed trait SolverResult
77+
case class Solved(proof: SCProof) extends SolverResult
78+
case object Unsolved extends SolverResult
79+
case object Timeout extends SolverResult
80+
case object Error extends SolverResult
81+
82+
def solveProblem(problem: Problem, timeout: FiniteDuration, solver: Sequent => Option[SCProof]): SolverResult = {
83+
val seq = problemToSequent(problem)
84+
val (futureSolver, cancelSolver) = Future.interruptibly { solver(seq) }
85+
try
86+
Await.result(futureSolver, timeout) match
87+
case Some(proof) => Solved(proof)
88+
case None => Unsolved
89+
catch
90+
case e: TimeoutException =>
91+
cancelSolver()
92+
Timeout
93+
case _ =>
94+
cancelSolver()
95+
Error
96+
}
97+
98+
def writeProof(problem: Problem, proof: SCProof, path: String): Unit = {
99+
// TODO
100+
val file = new File(path + problem.name + ".sc")
101+
val bw = new FileWriter(file)
102+
val proofCode = scproof2code(proof)
103+
bw.write(proof.toString)
104+
bw.close()
105+
}
106+
70107
final class Interrupt extends (() => Boolean) {
71108
// We need a state-machine to track the progress.
72109
// It can have the following states:

lisa-utils/src/main/scala/lisa/utils/tptp/KernelParser.scala

Lines changed: 6 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ import Parser.TPTPParseException
1919

2020
object KernelParser {
2121

22-
private case class ProblemMetadata(file: String, domain: String, problem: String, status: String, spc: Seq[String])
22+
case class ProblemMetadata(file: String, domain: String, problem: String, status: String, spc: Seq[String])
2323

2424
/**
2525
* @param formula A formula in the tptp language
@@ -107,13 +107,8 @@ object KernelParser {
107107
}
108108
}
109109

110-
private def problemToKernel(problemFile: File, md: ProblemMetadata): Problem = {
110+
def problemToKernel(problemFile: File, md: ProblemMetadata): Problem = {
111111
val file = io.Source.fromFile(problemFile)
112-
val pattern = "SPC\\s*:\\s*[A-z]{3}(_[A-z]{3})*".r
113-
val g = file.getLines()
114-
115-
def search(): String = pattern.findFirstIn(g.next()).getOrElse(search())
116-
117112
val i = Parser.problem(file)
118113
val sq = i.formulas map {
119114
case TPTP.FOFAnnotated(name, role, formula, annotations) =>
@@ -208,13 +203,9 @@ object KernelParser {
208203
println("\t[" + pbarContent + "] (" + (i + 1) + " / " + probfiles.size + ") " + d.getName())
209204
}
210205

211-
try {
212-
val md = getProblemInfos(p)
213-
if (md.spc.exists(spc.contains)) current :+ problemToKernel(p, md)
214-
else current
215-
} catch {
216-
case _ => current
217-
}
206+
val md = getProblemInfos(p)
207+
if (md.spc.exists(spc.contains)) current :+ problemToKernel(p, md)
208+
else current
218209
})
219210
r
220211
}
@@ -223,7 +214,7 @@ object KernelParser {
223214
* @param file a file containing a tptp problem
224215
* @return the metadata info (file name, domain, problem, status and spc) in the file
225216
*/
226-
private def getProblemInfos(file: File): ProblemMetadata = {
217+
def getProblemInfos(file: File): ProblemMetadata = {
227218
val pattern = "((File)|(Domain)|(Problem)|(Status)|(SPC))\\s*:.*".r
228219
val s = io.Source.fromFile(file)
229220
val g = s.getLines()

lisa-utils/src/main/scala/lisa/utils/tptp/ProblemGatherer.scala

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,23 @@ package lisa.utils.tptp
33
import lisa.utils.tptp.KernelParser.*
44

55
object ProblemGatherer {
6+
// Path to the TPTP problems directory
7+
// val path = getClass.getResource("/TPTP/Problems/").getPath
8+
val TPTPProblemPath = "/home/auguste/Documents/EPFL/PhD/Projects/TPTP-v8.2.0/Problems/"
69

710
/**
8-
* The tptp library needs to be included in main/resources. It can be found at http://www.tptp.org/
9-
* @return sequence of tptp problems with the PRP (propositional) tag.
11+
* @return sequence of tptp problems in the library lib with the tags in spc.
12+
*/
13+
def getLibProblems(spc: Seq[String], lib: String): Seq[Problem] = gatherFormulas(spc, TPTPProblemPath + lib + "/")
14+
15+
/**
16+
* This takes up to several minutes to run.
17+
* @return sequence of all tptp problems with the tags in spc.
1018
*/
11-
def getPRPproblems: Seq[Problem] = {
12-
val path = getClass.getResource("/TPTP/Problems/SYN/").getPath
13-
gatherFormulas(Seq("PRP"), path)
14-
}
19+
def getAllProblems(spc: Seq[String]): Seq[Problem] = gatherAllTPTPFormulas(spc, TPTPProblemPath).flatten
1520

21+
/**
22+
* @return sequence of tptp problems with the PRP (propositional) tag.
23+
*/
24+
def getPRPproblems: Seq[Problem] = getLibProblems(Seq("PRP"), "SYN")
1625
}

0 commit comments

Comments
 (0)