-
Notifications
You must be signed in to change notification settings - Fork 18
/
improveSolutionLK.scala
134 lines (115 loc) · 5.64 KB
/
improveSolutionLK.scala
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
package gapt.cutintro
import gapt.expr._
import gapt.expr.formula.hol.lcomp
import gapt.proofs.resolution.{ forgetfulPropParam, forgetfulPropResolve }
import gapt.proofs.{ FOLClause, HOLClause, HOLSequent, RichFOLSequent, Sequent }
import gapt.provers.Prover
import gapt.provers.Session._
import cats.implicits._
import gapt.expr.formula.And
import gapt.expr.formula.Formula
import gapt.expr.formula.fol.FOLFormula
import gapt.expr.subst.FOLSubstitution
import gapt.expr.subst.Substitution
import gapt.expr.util.freeVariables
import gapt.expr.util.rename
import gapt.logic.hol.CNFp
import gapt.logic.hol.simplifyPropositional
import scala.collection.mutable
object improveSolutionLK {
/**
* Improves the cut-formulas in an EHS by performing forgetful resolution and paramodulation on them.
*
* Maintains the invariant that the cut-formulas can be realized in an LK proof.
*/
def apply( ehs: SolutionStructure, prover: Prover, hasEquality: Boolean,
forgetOne: Boolean = false,
minimizeBack: Boolean = false ): SolutionStructure = {
val formulasInImprovement = ehs.formulas.to( mutable.Seq )
for ( i <- formulasInImprovement.indices.reverse ) {
val eigenVariablesInScope = for ( ( evs, j ) <- ehs.sehs.eigenVariables.zipWithIndex; ev <- evs if i < j ) yield ev
val availableInstances = ehs.endSequentInstances filter { inst => freeVariables( inst ) subsetOf eigenVariablesInScope.toSet }
val availableCutFormulas = for ( ( cf, j ) <- formulasInImprovement.zipWithIndex if i < j ) yield cf
val context = availableInstances :++ availableCutFormulas
val instances = ehs.sehs.ss( i ) match {
case ( ev, instanceTerms ) =>
for ( terms <- instanceTerms ) yield FOLSubstitution( ev zip terms )
}
formulasInImprovement( i ) =
improve( context, formulasInImprovement( i ),
instances.toSet, prover, hasEquality, forgetOne ).
asInstanceOf[FOLFormula]
}
if ( minimizeBack && formulasInImprovement.size == 1 ) {
formulasInImprovement( 0 ) = improveBack( ehs.endSequentInstances, formulasInImprovement( 0 ), prover )
}
ehs.copy( formulas = formulasInImprovement.toSeq )
}
/**
* Improves a formula with regard to its logical complexity by taking consequences under the constraint that the following sequent is valid:
*
* instances(0)(formula) +: ... +: instances(n)(formula) +: context
*
* @param context A sequent.
* @param start Existing solution of the constraint.
* @param instances List of substitutions, the intended usage are the instances of a cut-formula in an EHS.
* @param prover Prover to check the validity of the constraint.
* @param hasEquality If set to true, use forgetful paramodulation in addition to resolution.
*/
def improve( context: HOLSequent, start: Formula, instances: Set[Substitution], prover: Prover,
hasEquality: Boolean, forgetOne: Boolean ): Formula = {
val names = containedNames( instances ) ++ containedNames( start ) ++ containedNames( context.elements )
val nameGen = rename.awayFrom( names )
val grounding = Substitution( for ( v <- freeVariables( start +: context.elements ) ++ instances.flatMap( _.range ) )
yield v -> Const( nameGen.fresh( v.name ), v.ty ) )
val groundInstances = instances.map( grounding.compose )
val isSolution = mutable.Map[Set[HOLClause], Boolean]()
def checkSolution( cnf: Set[HOLClause] ): Session[Unit] = when( !isSolution.contains( cnf ) ) {
val clauses = for ( inst <- groundInstances; clause <- cnf ) yield inst( clause.toDisjunction )
withScope( assert( clauses.toList ) *> checkUnsat ).flatMap { isSolOrUnknown =>
val isSol = isSolOrUnknown.getOrElse( false )
isSolution( cnf ) = isSol
when( isSol ) {
forgetfulPropResolve( cnf ).toList.traverse_( checkSolution ) *>
when( hasEquality ) { forgetfulPropParam( cnf ).toList.traverse_( checkSolution ) } *>
when( forgetOne ) { cnf.toList.traverse_( c => checkSolution( cnf - c ) ) }
}
}
}
prover.runSession {
declareSymbolsIn( names ++ containedNames( grounding ) ) *>
assert( grounding( context.toNegConjunction ) ) *>
checkSolution( CNFp( start ).map { _.distinct.sortBy { _.hashCode } } )
}
val solutions = isSolution collect {
case ( cnf, true ) => simplifyPropositional( And( cnf map { _.toImplication } ) )
}
solutions minBy { lcomp( _ ) }
}
/**
* Improves a formula with regard to its logical complexity by taking backwards consequences under the constraint that the following sequent is valid:
*
* context :+ formula
*
* @param context A sequent.
* @param start Existing solution of the constraint.
* @param prover Prover to check the validity of the constraint.
*/
private def improveBack( context: Sequent[FOLFormula], start: FOLFormula, prover: Prover ): FOLFormula =
simplifyPropositional( And( CNFp( start ) map { improveBack( context, _, prover ).toImplication } ) )
private def improveBack( context: Sequent[FOLFormula], start: FOLClause, prover: Prover ): FOLClause = {
val isSolution = mutable.Map[FOLClause, Boolean]()
def checkSolution( clause: FOLClause ): Unit =
if ( !isSolution.contains( clause ) ) {
val condition = context :+ clause.toDisjunction
if ( prover isValid condition ) {
isSolution( clause ) = true
for ( a <- clause.indices ) checkSolution( clause delete a )
} else {
isSolution( clause ) = false
}
}
checkSolution( start )
isSolution collect { case ( clause, true ) => clause } minBy { _.size }
}
}