Skip to content

Commit b1b6308

Browse files
Add TPTPSolver class for solving problems from TPTP library using Tableau tactic
1 parent 392b1d6 commit b1b6308

File tree

1 file changed

+141
-0
lines changed

1 file changed

+141
-0
lines changed
Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
1+
import scala.concurrent.duration._
2+
import scala.concurrent.ExecutionContext.Implicits.global
3+
import scala.concurrent._
4+
import java.util.concurrent.CancellationException
5+
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
11+
import lisa.utils.ProofsConverter.*
12+
13+
object TPTPSolver extends lisa.Main {
14+
try {
15+
println("Fetching problems from TPTP library...")
16+
val probs = getPRPproblems
17+
18+
println("Number of problems found: " + probs.size)
19+
20+
// We limit the execution time to solve each problem
21+
val timeoutTableau = 1.second
22+
val timeoutTautology = 1.second
23+
24+
var tableauProofs = List[Option[SCProof]]()
25+
var tautologyProofs = List[Option[SCProof]]()
26+
27+
for ((p, i) <- probs.zipWithIndex) {
28+
// Progress bar
29+
if ((i + 1) % 10 == 0 || i + 1 == probs.size) {
30+
val pbarLength = 30
31+
var pbarContent = "=" * (((i + 1) * pbarLength) / probs.size)
32+
pbarContent += " " * (pbarLength - pbarContent.length)
33+
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")
37+
}
38+
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
56+
}
57+
tautologyProofs = tautologyProofs :+ (
58+
try Await.result(futureTautology, timeoutTautology)
59+
catch
60+
case _ =>
61+
cancelTautology()
62+
None
63+
)
64+
}
65+
} catch {
66+
case error: NullPointerException => println("You can download the tptp library at http://www.tptp.org/ and put it in main/resources")
67+
}
68+
}
69+
70+
final class Interrupt extends (() => Boolean) {
71+
// We need a state-machine to track the progress.
72+
// It can have the following states:
73+
// a null reference means execution has not started.
74+
// a Thread reference means that the execution has started but is not done.
75+
// a this reference means that it is already cancelled or is already too late.
76+
private[this] final var state: AnyRef = null
77+
78+
/**
79+
* This is the signal to cancel the execution of the logic.
80+
* Returns whether the cancellation signal was successully issued or not.
81+
*/
82+
override final def apply(): Boolean = this.synchronized {
83+
state match {
84+
case null =>
85+
state = this
86+
true
87+
case _: this.type => false
88+
case t: Thread =>
89+
state = this
90+
// t.interrupt()
91+
t.stop()
92+
true
93+
}
94+
}
95+
96+
// Initializes right before execution of logic and
97+
// allows to not run the logic at all if already cancelled.
98+
private[this] final def enter(): Boolean =
99+
this.synchronized {
100+
state match {
101+
case _: this.type => false
102+
case null =>
103+
state = Thread.currentThread
104+
true
105+
}
106+
}
107+
108+
// Cleans up after the logic has executed
109+
// Prevents cancellation to occur "too late"
110+
private[this] final def exit(): Boolean =
111+
this.synchronized {
112+
state match {
113+
case _: this.type => false
114+
case t: Thread =>
115+
state = this
116+
true
117+
}
118+
}
119+
120+
/**
121+
* Executes the suplied block of logic and returns the result.
122+
* Throws CancellationException if the block was interrupted.
123+
*/
124+
def interruptibly[T](block: => T): T =
125+
if (enter()) {
126+
try block
127+
catch {
128+
case ie: InterruptedException => throw new CancellationException()
129+
} finally {
130+
if (!exit() && Thread.interrupted())
131+
() // If we were interrupted and flag was not cleared
132+
}
133+
} else throw new CancellationException()
134+
}
135+
136+
implicit class FutureInterrupt(val future: Future.type) extends AnyVal {
137+
def interruptibly[T](block: => T)(implicit ec: ExecutionContext): (Future[T], () => Boolean) = {
138+
val interrupt = new Interrupt()
139+
(Future(interrupt.interruptibly(block))(ec), interrupt)
140+
}
141+
}

0 commit comments

Comments
 (0)