@@ -25,8 +25,12 @@ import kotlin.time.DurationUnit
2525open class KZ3Solver (private val ctx : KContext ) : KSolver<KZ3SolverConfiguration> {
2626 private val z3Ctx = KZ3Context (ctx)
2727 private val solver = createSolver()
28+
2829 private var lastCheckStatus = KSolverStatus .UNKNOWN
2930 private var lastReasonOfUnknown: String? = null
31+ private var lastModel: KZ3Model ? = null
32+ private var lastUnsatCore: List <KExpr <KBoolSort >>? = null
33+
3034 private var currentScope: UInt = 0u
3135
3236 @Suppress(" LeakingThis" )
@@ -104,7 +108,20 @@ open class KZ3Solver(private val ctx: KContext) : KSolver<KZ3SolverConfiguration
104108 ctx.ensureContextMatch(assumptions)
105109
106110 val z3Assumptions = with (exprInternalizer) {
107- LongArray (assumptions.size) { assumptions[it].internalizeExpr() }
111+ LongArray (assumptions.size) {
112+ val assumption = assumptions[it]
113+
114+ /* *
115+ * Assumptions are trivially unsat and no check-sat is required.
116+ * */
117+ if (assumption == ctx.falseExpr) {
118+ lastUnsatCore = listOf (ctx.falseExpr)
119+ lastCheckStatus = KSolverStatus .UNSAT
120+ return KSolverStatus .UNSAT
121+ }
122+
123+ assumption.internalizeExpr()
124+ }
108125 }
109126
110127 solver.updateTimeout(timeout)
@@ -116,19 +133,28 @@ open class KZ3Solver(private val ctx: KContext) : KSolver<KZ3SolverConfiguration
116133 require(lastCheckStatus == KSolverStatus .SAT ) {
117134 " Model are only available after SAT checks, current solver status: $lastCheckStatus "
118135 }
119- val model = solver.model
120136
121- KZ3Model (model, ctx, z3Ctx, exprInternalizer)
137+ val model = lastModel ? : KZ3Model (
138+ model = solver.model,
139+ ctx = ctx,
140+ z3Ctx = z3Ctx,
141+ internalizer = exprInternalizer
142+ )
143+ lastModel = model
144+
145+ model
122146 }
123147
124148 override fun unsatCore (): List <KExpr <KBoolSort >> = z3Try {
125149 require(lastCheckStatus == KSolverStatus .UNSAT ) { " Unsat cores are only available after UNSAT checks" }
126150
127- val unsatCore = solver.solverGetUnsatCore()
128-
129- with (exprConverter) {
130- unsatCore.map { trackedAssertions.get(it) ? : it.convertExpr() }
151+ val unsatCore = lastUnsatCore ? : with (exprConverter) {
152+ val solverUnsatCore = solver.solverGetUnsatCore()
153+ solverUnsatCore.map { trackedAssertions.get(it) ? : it.convertExpr() }
131154 }
155+ lastUnsatCore = unsatCore
156+
157+ unsatCore
132158 }
133159
134160 override fun reasonOfUnknown (): String = z3Try {
@@ -173,6 +199,8 @@ open class KZ3Solver(private val ctx: KContext) : KSolver<KZ3SolverConfiguration
173199 private fun invalidateSolverState () {
174200 lastReasonOfUnknown = null
175201 lastCheckStatus = KSolverStatus .UNKNOWN
202+ lastModel = null
203+ lastUnsatCore = null
176204 }
177205
178206 private inline fun z3TryCheck (body : () -> KSolverStatus ): KSolverStatus = try {
0 commit comments