我想将抽象关键字语义编码为Alloy中的约束(请耐心,我需要这样做是有原因的!:))。如果我有以下代码:
abstract sig A {}
sig a1 extends A{}
sig a2 extends A{}
我认为它的含义如下(我希望我是对的!):
sig A {}
sig a1 in A{}
sig a2 in A{}
fact {
A=a1+a2 //A is nothing other than a1 and a2
a1 & a2 = none // a1 and a1 are disjoint
}
所以上面的两个签名是相等的(即,在语义上是相等的):
我渴望使用Alloy提供的抽象关键字来简化生活,但是当我使A成为sig O的子集并使用抽象关键字:
时,问题出现了。sig O{}
abstract sig A in O{}
sig a1 extends A{}
sig a2 extends A{}
以上语法返回错误!Alloy抱怨:"子集签名不能抽象",所以我的第一个问题是:为什么Alloy不允许这个?
我没有停下来编码抽象的关键字语义(如上所述),并得出以下代码:
sig O{}
sig A in O{}
sig a1 in A{}
sig a2 in A{}
fact {
A=a1+a2 // A can not be independently instantiated
a1 & a2 = none // a1 and a2 are disjoint
}
这工作,一切都很好:)
现在,如果我想将a3添加到Alloy规格中,我需要按如下方式调整规格:
sig O{}
sig A in O{}
sig a1 in A{}
sig a2 in A{}
sig a3 in A{}
fact {
A=a1+a2+3
a1 & a2 = none
a1 & a3 = none
a2 & a3 = none
}
但是,正如您通过比较上面的两个规范所看到的,如果我想继续这样做,并以类似的方式添加a4到我的规范中,我需要更多地更改事实部分,这仍然很麻烦!实际上ai &Aj =none (for i=1..n)表达式是非单调递增的!例如,添加a4迫使我添加多个约束:
fact {
A=a1+a2+3 +a4
a1 & a2 = none
a1 & a3 = none
a1 & a4 = none
a2 & a3 = none
a2 & a4 = none
a3 & a4 = none
}
所以我的第二个问题:是否有任何解决方法(或可能更简单的方法)来做到这一点?
任何评论都是赞赏的。谢谢:)
关于Q1(为什么Alloy不允许扩展子集签名?):我不知道。
关于Q2(是否有解决方案):最简单的解决方案是使a1…可以是A的子签名(扩展),并找到另一种方法来建立A与O的关系。在您给出的简单示例中,O没有子类型,因此只需将A in O
更改为A extends O
即可。
如果O已经被你没有展示给我们的其他签名分区了,那么这个解决方案就不起作用了;在没有更多细节的情况下,很难说什么会起作用。(理想情况下,你需要一个最小的完整的工作示例来说明难度:你给出的示例是最小的,并且说明了一个难度,但它们不能说明为什么a不能是o的扩展)
(附录)
在评论中,你说
我在O中使用A而不是A extends O的原因是O中还有另一个签名C,这里没有显示。A和C不一定不相交,所以这就是我认为我必须在中使用而不是extend来定义它们是o的子集的原因。
细节决定成败,但结论不是由前提得出的。如果A和C都扩展O,它们将不相交,但如果一个使用扩展,另一个在中使用,它们不会自动不相交。因此,如果您希望A和C都是O的子集,并且A由几个其他签名划分,则可以这样做(除非存在尚未提到的其他约束)。
sig O {}
abstract sig A extends O {}
sig a1, a2 extends A {}
sig a3, a4 extends A {}
sig C in O {}