我想在Inox求解器界面中建模以下Scala层次结构:
abstract class Element()
abstract class nonZero() extends Element
final case class Zero() extends Element
final case class One() extends nonZero()
final case class notOne() extends nonZero()
如何为nonZero建模?
如果我将其建模为构造函数
def mkConstructor(id: Identifier, flags: Flag*)
(tParamNames: String*)
(sort: Option[Identifier])
(fieldBuilder: Seq[TypeParameter] => Seq[ValDef]) = {
val tParams = tParamNames map TypeParameter.fresh
val tParamDefs = tParams map (TypeParameterDef(_))
val fields = fieldBuilder(tParams)
new ADTConstructor(id, tParamDefs, sort, fields, flags.toSet)
}
然后我无法指定它有其他构造函数扩展它。如果我把它建模为一种类型:
def mkSort(id: Identifier, flags: Flag*)
(tParamNames: String*)
(cons: Seq[Identifier]) = {
val tParams = tParamNames map TypeParameter.fresh
val tParamDefs = tParams map (TypeParameterDef(_))
new ADTSort(id, tParamDefs, cons, flags.toSet)
}
然后我不能指定它是Element的子类型。
为什么我需要
我需要这个层次结构,因为我需要声明属性:
字段的非零元素集合,一个,反向和 乘以非零元素形成一个组。
然后我需要一些机制来生成一个类型来限制排序的构造函数,在这种情况下,将Element
的构造函数限制为One
和notZeroOne()
。在那种情况下,我会建模:
abstract class Element()
final case class Zero() extends Element
final case class One() extends Element()
final case class notZeroOne() extends Element()
对此最干净的解决方案是什么?
答案 0 :(得分:1)
不幸的是,"类层次结构" Inox仅限于具有一系列具体构造函数的单个抽象父级(构造函数之间不可进行子类型化)。此限制反映了对基础SMT求解器支持的代数数据类型理论的限制。
如果要在非零元素上声明属性,为什么不使用(elem !== Zero()) ==> someProperty
形式的含义?请注意,通常,您可以通过详尽枚举允许的构造函数的具体谓词来模拟上面提出的nonZero()
类型。例如,
def nonZero(e: Expr): Expr = e.isInstOf(T(one)()) || e.isInstOf(T(notOne)())
然后,您可以使用nonZero(e) ==> property(e)
来声明非零元素的属性。