Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Yices #46

Merged
merged 13 commits into from
Feb 14, 2023
Prev Previous commit
Next Next commit
KSMT expressions fixes
  • Loading branch information
Bupaheh committed Feb 13, 2023
commit c5bb95132fd76cb663861b269f80358036016d4a
Original file line number Diff line number Diff line change
Expand Up @@ -14,32 +14,30 @@ import org.ksmt.sort.KArraySort
import org.ksmt.sort.KBoolSort
import org.ksmt.sort.KSort
import org.ksmt.utils.mkFreshConstDecl
import org.ksmt.utils.uncheckedCast

class KDeclSubstitutor(ctx: KContext) : KNonRecursiveTransformer(ctx) {
Bupaheh marked this conversation as resolved.
Show resolved Hide resolved
private val substitution = hashMapOf<KDecl<*>, KDecl<*>>()

fun <T: KSort> substitute(from: KDecl<T>, to: KDecl<T>) {
fun <T : KSort> substitute(from: KDecl<T>, to: KDecl<T>) {
substitution[from] = to
}

@Suppress("UNCHECKED_CAST")
private fun <T : KSort> transformDecl(decl: KDecl<T>): KDecl<T> =
(substitution[decl] as? KDecl<T>) ?: decl
(substitution[decl].uncheckedCast()) ?: decl

@Suppress("UNCHECKED_CAST")
override fun <T : KSort> transformApp(expr: KApp<T, *>): KExpr<T> =
transformAppAfterArgsTransformed(expr as KApp<T, KExpr<KSort>>) { transformedArgs ->
override fun <T : KSort, A : KSort> transformApp(expr: KApp<T, A>): KExpr<T> =
transformAppAfterArgsTransformed(expr) { transformedArgs ->
val transformedDecl = transformDecl(expr.decl)

ctx.mkApp(transformedDecl, transformedArgs)
}

@Suppress("UNCHECKED_CAST")
override fun <D : KSort, R : KSort> transform(
expr: KArrayLambda<D, R>
): KExpr<KArraySort<D, R>> = with(expr) {
transformQuantifierAfterBodyTransformed(body, listOf(indexVarDecl)) { transformedBody, transformedBounds ->
ctx.mkArrayLambda(transformedBounds.single() as KDecl<D>, transformedBody)
ctx.mkArrayLambda(transformedBounds.single().uncheckedCast(), transformedBody)
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import org.ksmt.decl.KDecl
import org.ksmt.expr.KExpr
import org.ksmt.sort.KSort
import org.ksmt.utils.NativeLibraryLoader
import org.ksmt.utils.uncheckedCast

open class KYicesContext : AutoCloseable {
private var isClosed = false
Expand All @@ -26,9 +27,8 @@ open class KYicesContext : AutoCloseable {

fun findConvertedDecl(decl: YicesTerm): KDecl<*>? = yicesDecls[decl]

@Suppress("UNCHECKED_CAST")
fun <K: KExpr<*>> substituteDecls(expr: K, transform: (K) -> K): K =
transformed.getOrPut(expr) { transform(expr) } as K
transformed.getOrPut(expr) { transform(expr) }.uncheckedCast()

open fun internalizeExpr(expr: KExpr<*>, internalizer: (KExpr<*>) -> YicesTerm): YicesTerm =
internalize(expressions, yicesExpressions, expr, internalizer)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,9 @@ import org.ksmt.sort.KBvSort
import org.ksmt.sort.KIntSort
import org.ksmt.sort.KRealSort
import org.ksmt.sort.KSort
import org.ksmt.utils.asExpr
import org.ksmt.utils.mkConst
import org.ksmt.utils.mkFreshConst
import org.ksmt.utils.uncheckedCast
import java.util.LinkedList
import java.util.Queue
import kotlin.collections.HashSet
Expand Down Expand Up @@ -62,7 +62,7 @@ open class KYicesExprConverter(
mkArrayLambda(indexDecl.decl, mkIntToReal(expr.select(indexDecl)))
}

@Suppress("UNCHECKED_CAST", "ComplexMethod")
@Suppress("ComplexMethod")
override fun findConvertedNative(expr: YicesTerm): KExpr<*>? = with(ctx) {
val convertedExpr = yicesCtx.findConvertedExpr(expr)

Expand All @@ -76,19 +76,19 @@ open class KYicesExprConverter(
val exprSort = convertedExpr.sort

return when {
argType is KIntSort && exprSort is KRealSort -> castToInt(convertedExpr as KExpr<KRealSort>)
argType is KRealSort && exprSort is KIntSort -> castToReal(convertedExpr as KExpr<KIntSort>)
argType is KIntSort && exprSort is KRealSort -> castToInt(convertedExpr.uncheckedCast())
argType is KRealSort && exprSort is KIntSort -> castToReal(convertedExpr.uncheckedCast())
argType is KArraySort<*, *>
&& argType.range is KIntSort
&& exprSort is KArraySort<*, *>
&& exprSort.range is KRealSort ->
castArrayRangeToInt(convertedExpr as KExpr<KArraySort<*, KRealSort>>)
castArrayRangeToInt(convertedExpr.uncheckedCast<_, KExpr<KArraySort<*, KRealSort>>>())

argType is KArraySort<*, *>
&& argType.range is KRealSort
&& exprSort is KArraySort<*, *>
&& exprSort.range is KIntSort ->
castArrayRangeToReal(convertedExpr as KExpr<KArraySort<*, KIntSort>>)
castArrayRangeToReal(convertedExpr.uncheckedCast<_, KExpr<KArraySort<*, KIntSort>>>())

else -> error("Invalid state")
}
Expand Down Expand Up @@ -319,7 +319,7 @@ open class KYicesExprConverter(
mkIte(condition, mkFloor(div), mkCeil(div))
}

@Suppress("UNCHECKED_CAST", "LongMethod", "ComplexMethod")
@Suppress("LongMethod", "ComplexMethod")
private fun convertComposite(expr: YicesTerm) = with(ctx) {
val yicesArgs = Terms.children(expr).toTypedArray()
val numChildren = Terms.numChildren(expr)
Expand Down Expand Up @@ -361,7 +361,7 @@ open class KYicesExprConverter(
check(yicesArgs.size == 2)
argTypes.add(funcDecl.sort.toArraySort().domain)
expr.convert(yicesArgs.drop(1).toTypedArray()) { index: KExpr<KSort> ->
mkArraySelect(funcDecl.apply() as KExpr<KArraySort<*, *>>, index)
mkArraySelect(funcDecl.apply().uncheckedCast(), index)
}
} else {
argTypes.addAll(funcDecl.argSorts)
Expand Down Expand Up @@ -448,80 +448,80 @@ open class KYicesExprConverter(
Constructor.BV_SGE_ATOM -> expr.convert(yicesArgs, ::mkBvSignedGreaterOrEqualExpr)
Constructor.ARITH_GE_ATOM -> {
setArithArgTypes(yicesArgs)
expr.convert<KBoolSort, KArithSort<*>, KArithSort<*>>(yicesArgs, ::mkArithGe)
expr.convert(yicesArgs, ::mkArithGe)
}
Constructor.ABS -> {
expr.convert(yicesArgs) { x: KExpr<KArithSort<*>> ->
expr.convert(yicesArgs) { x: KExpr<KArithSort> ->
val isReal = x.sort == realSort
val condition = if (isReal)
mkArithGe(x as KExpr<KRealSort>, mkRealNum(0))
mkArithGe(x.uncheckedCast(), mkRealNum(0))
else
mkArithGe(x as KExpr<KIntSort>, mkIntNum(0))
mkArithGe(x.uncheckedCast(), mkIntNum(0))

mkIte(condition, x, mkArithUnaryMinus(x))
}
}
Constructor.CEIL -> {
expr.convert(yicesArgs) { x: KExpr<KArithSort<*>> ->
if(x.sort == intSort)
expr.convert(yicesArgs) { x: KExpr<KArithSort> ->
if (x.sort == intSort)
x
else
mkCeil(x as KExpr<KRealSort>)
mkCeil(x.uncheckedCast())
}
}
Constructor.FLOOR -> {
expr.convert(yicesArgs) { x: KExpr<KArithSort<*>> ->
if(x.sort == intSort)
expr.convert(yicesArgs) { x: KExpr<KArithSort> ->
if (x.sort == intSort)
x
else
mkFloor(x as KExpr<KRealSort>)
mkFloor(x.uncheckedCast())
}
}
Constructor.RDIV -> {
argTypes.addAll(List(numChildren) { realSort })
expr.convert<KArithSort<*>, KArithSort<*>, KArithSort<*>>(yicesArgs, ::mkArithDiv)
expr.convert(yicesArgs, ::mkArithDiv)
}
Constructor.IDIV -> {
setArithArgTypes(yicesArgs)
expr.convert(yicesArgs) { arg0: KExpr<KArithSort<*>>, arg1: KExpr<KArithSort<*>> ->
expr.convert(yicesArgs) { arg0: KExpr<KArithSort>, arg1: KExpr<KArithSort> ->
check(arg0.sort == arg1.sort)
if (arg0.sort is KIntSort)
mkArithDiv(arg0.asExpr(intSort), arg1.asExpr(intSort))
mkArithDiv(arg0.uncheckedCast(), arg1.uncheckedCast())
else
mkIDiv(arg0.asExpr(realSort), arg1.asExpr(realSort))
mkIDiv(arg0.uncheckedCast(), arg1.uncheckedCast())
}
}
Constructor.IMOD -> {
setArithArgTypes(yicesArgs)
expr.convert(yicesArgs) { arg0: KExpr<KArithSort<*>>, arg1: KExpr<KArithSort<*>> ->
expr.convert(yicesArgs) { arg0: KExpr<KArithSort>, arg1: KExpr<KArithSort> ->
check(arg0.sort == arg1.sort)
if (arg0.sort is KIntSort) {
mkIntMod(arg0.asExpr(intSort), arg1.asExpr(intSort))
mkIntMod(arg0.uncheckedCast(), arg1.uncheckedCast())
} else {
val div = mkIntToReal(mkIDiv(arg0.asExpr(realSort), arg1.asExpr(realSort)))
val mul = mkArithMul(arg1, div.asExpr(realSort))
val div = mkIntToReal(mkIDiv(arg0.uncheckedCast(), arg1.uncheckedCast()))
val mul = mkArithMul(arg1, div.uncheckedCast())

mkArithSub(arg0, mul)
}
}
}
Constructor.IS_INT_ATOM -> {
setArithArgTypes(yicesArgs)
expr.convert(yicesArgs) { arg: KExpr<KArithSort<*>> ->
expr.convert(yicesArgs) { arg: KExpr<KArithSort> ->
if (arg.sort is KIntSort)
true.expr
else
mkRealIsInt(arg.asExpr(realSort))
mkRealIsInt(arg.uncheckedCast())
}
}
Constructor.DIVIDES_ATOM -> {
setArithArgTypes(yicesArgs)
expr.convert(yicesArgs) { arg0: KExpr<KArithSort<*>>, arg1: KExpr<KArithSort<*>> ->
expr.convert(yicesArgs) { arg0: KExpr<KArithSort>, arg1: KExpr<KArithSort> ->
check(arg0.sort == arg1.sort)
if (arg0.sort is KIntSort)
mkIntRem(arg1.asExpr(intSort), arg0.asExpr(intSort)) eq mkIntNum(0)
mkIntRem(arg1.uncheckedCast(), arg0.uncheckedCast()) eq mkIntNum(0)
else
mkRealIsInt(mkArithDiv(arg1.asExpr(realSort), arg0.asExpr(realSort)))
mkRealIsInt(mkArithDiv(arg1.uncheckedCast(), arg0.uncheckedCast()))
}
}
Constructor.ARITH_ROOT_ATOM -> TODO("ARITH_ROOT conversion is not supported")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,7 @@ import org.ksmt.sort.KBv64Sort
import org.ksmt.sort.KBv8Sort
import org.ksmt.sort.KIntSort
import org.ksmt.utils.mkFreshConstDecl
import org.ksmt.utils.uncheckedCast
import java.math.BigInteger

open class KYicesExprInternalizer(
Expand Down Expand Up @@ -255,7 +256,7 @@ open class KYicesExprInternalizer(
}

override fun transform(expr: KBitVecCustomValue): KExpr<KBvSort> = with(expr) {
transform { Terms.parseBvBin(binaryStringValue) }
transform { Terms.parseBvBin(stringValue) }
}

override fun <T : KBvSort> transform(expr: KBvNotExpr<T>): KExpr<T> = with(expr) {
Expand Down Expand Up @@ -654,7 +655,6 @@ open class KYicesExprInternalizer(
transform { function.internalizeDecl() }
}

@Suppress("UNCHECKED_CAST")
override fun <D : KSort, R : KSort> transform(expr: KArrayLambda<D, R>): KExpr<KArraySort<D, R>> {
val transformedExpr = yicesCtx.substituteDecls(expr) { term ->
with(term) {
Expand All @@ -675,15 +675,15 @@ open class KYicesExprInternalizer(
}
}

override fun <T : KArithSort<T>> transform(expr: KAddArithExpr<T>): KExpr<T> = with(expr) {
override fun <T : KArithSort> transform(expr: KAddArithExpr<T>): KExpr<T> = with(expr) {
transformList(args) { args: Array<YicesTerm> -> Terms.add(args.toList()) }
}

override fun <T : KArithSort<T>> transform(expr: KMulArithExpr<T>): KExpr<T> = with(expr) {
override fun <T : KArithSort> transform(expr: KMulArithExpr<T>): KExpr<T> = with(expr) {
transformList(args) { args: Array<YicesTerm> -> Terms.mul(args.toList()) }
}

override fun <T : KArithSort<T>> transform(expr: KSubArithExpr<T>): KExpr<T> = with(expr) {
override fun <T : KArithSort> transform(expr: KSubArithExpr<T>): KExpr<T> = with(expr) {
transformList(args) { args: Array<YicesTerm> ->
if (args.size == 1)
args.first()
Expand All @@ -692,11 +692,11 @@ open class KYicesExprInternalizer(
}
}

override fun <T : KArithSort<T>> transform(expr: KUnaryMinusArithExpr<T>): KExpr<T> = with(expr) {
override fun <T : KArithSort> transform(expr: KUnaryMinusArithExpr<T>): KExpr<T> = with(expr) {
transform(arg, Terms::neg)
}

override fun <T : KArithSort<T>> transform(expr: KDivArithExpr<T>): KExpr<T> = with(expr) {
override fun <T : KArithSort> transform(expr: KDivArithExpr<T>): KExpr<T> = with(expr) {
transform(lhs, rhs) { lhs: YicesTerm, rhs: YicesTerm ->
when (sort) {
is KIntSort -> Terms.idiv(lhs, rhs)
Expand All @@ -705,23 +705,23 @@ open class KYicesExprInternalizer(
}
}

override fun <T : KArithSort<T>> transform(expr: KPowerArithExpr<T>): KExpr<T> = with(expr) {
override fun <T : KArithSort> transform(expr: KPowerArithExpr<T>): KExpr<T> = with(expr) {
transform(lhs, rhs, Terms::power)
}

override fun <T : KArithSort<T>> transform(expr: KLtArithExpr<T>): KExpr<KBoolSort> = with(expr) {
override fun <T : KArithSort> transform(expr: KLtArithExpr<T>): KExpr<KBoolSort> = with(expr) {
transform(lhs, rhs, Terms::arithLt)
}

override fun <T : KArithSort<T>> transform(expr: KLeArithExpr<T>): KExpr<KBoolSort> = with(expr) {
override fun <T : KArithSort> transform(expr: KLeArithExpr<T>): KExpr<KBoolSort> = with(expr) {
transform(lhs, rhs, Terms::arithLeq)
}

override fun <T : KArithSort<T>> transform(expr: KGtArithExpr<T>): KExpr<KBoolSort> = with(expr) {
override fun <T : KArithSort> transform(expr: KGtArithExpr<T>): KExpr<KBoolSort> = with(expr) {
transform(lhs, rhs, Terms::arithGt)
}

override fun <T : KArithSort<T>> transform(expr: KGeArithExpr<T>): KExpr<KBoolSort> = with(expr) {
override fun <T : KArithSort> transform(expr: KGeArithExpr<T>): KExpr<KBoolSort> = with(expr) {
transform(lhs, rhs, Terms::arithGeq)
}

Expand Down Expand Up @@ -785,7 +785,6 @@ open class KYicesExprInternalizer(
}
}

@Suppress("UNCHECKED_CAST")
private inline fun <T: KQuantifier> internalizeQuantifier(
expr: T,
crossinline constructor: (KExpr<KBoolSort>, List<KDecl<*>>) -> T,
Expand All @@ -797,7 +796,7 @@ open class KYicesExprInternalizer(
val newBounds = bounds.map { it.sort.mkFreshConstDecl(it.name) }
val transformer = KDeclSubstitutor(ctx).apply {
bounds.zip(newBounds).forEach { (bound, newBound) ->
substitute(bound as KDecl<KSort>, newBound)
substitute(bound.uncheckedCast(), newBound)
}
}

Expand Down
14 changes: 6 additions & 8 deletions ksmt-yices/src/main/kotlin/org/ksmt/solver/yices/KYicesModel.kt
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,9 @@ import org.ksmt.sort.KIntSort
import org.ksmt.sort.KRealSort
import org.ksmt.sort.KSort
import org.ksmt.sort.KUninterpretedSort
import org.ksmt.utils.asExpr
import org.ksmt.utils.mkConst
import org.ksmt.utils.mkFreshConstDecl
import org.ksmt.utils.uncheckedCast

class KYicesModel(
private val model: Model,
Expand Down Expand Up @@ -52,7 +52,6 @@ class KYicesModel(
return KModelEvaluator(ctx, this, isComplete).apply(expr)
}

@Suppress("UNCHECKED_CAST")
private fun getValue(yval: YVal, sort: KSort): KExpr<*> = with(ctx) {
return when (sort) {
is KBoolSort -> model.boolValue(yval).expr
Expand All @@ -71,7 +70,7 @@ class KYicesModel(

funcInterpretationsToDo.add(Pair(yval, funcDecl))

mkFunctionAsArray<KSort, KSort>(funcDecl).asExpr(sort)
mkFunctionAsArray<KSort, KSort>(funcDecl).uncheckedCast()
}
else -> error("Unsupported sort $sort")
}
Expand All @@ -80,7 +79,7 @@ class KYicesModel(
private fun <T: KSort> functionInterpretation(yval: YVal, decl: KFuncDecl<T>): KModel.KFuncInterp<T> {
val functionChildren = model.expandFunction(yval)
val default = if (yval.tag != YValTag.UNKNOWN)
getValue(functionChildren.value, decl.sort).asExpr(decl.sort)
getValue(functionChildren.value, decl.sort).uncheckedCast<_, KExpr<T>>()
else
null

Expand All @@ -89,7 +88,7 @@ class KYicesModel(
val args = entry.vector.zip(decl.argSorts).map { (arg, sort) ->
getValue(arg, sort)
}
val res = getValue(entry.value, decl.sort).asExpr(decl.sort)
val res = getValue(entry.value, decl.sort).uncheckedCast<_, KExpr<T>>()

KModel.KFuncInterpEntry(args, res)
}
Expand All @@ -102,7 +101,6 @@ class KYicesModel(
)
}

@Suppress("UNCHECKED_CAST")
override fun <T : KSort> interpretation(decl: KDecl<T>): KModel.KFuncInterp<T>? = with(ctx) {
interpretations.getOrPut(decl) {
if (decl !in declarations) return@with null
Expand All @@ -116,7 +114,7 @@ class KYicesModel(
decl = decl,
vars = emptyList(),
entries = emptyList(),
default = getValue(yval, sort).asExpr(sort)
default = getValue(yval, sort).uncheckedCast()
)
is KFuncDecl<T> -> functionInterpretation(yval, decl)
else -> error("Unexpected declaration $decl")
Expand All @@ -129,7 +127,7 @@ class KYicesModel(
}

result
} as? KModel.KFuncInterp<T>
}.uncheckedCast<_, KModel.KFuncInterp<T>?>()
}

override fun detach(): KModel {
Expand Down