我在Alloy中有以下规范:
sig A {}
sig Q{isA: one A}
fact {
all c1,c2:Q | c1.isA=c2.isA => c1=c2 // injective mapping
all a1:A | some c1:Q | c1.isA=a1 //surjective
}
在我的模型中,上述事实在不同的签名之间重复相似。我试图把它当作一个单独的模块,所以我创建了一个模块如下:
module library/copy [A,Q]
fact {
all c1,c2:Q | c1.isA=c2.isA => c1=c2 // injective mapping
all a1:A | some c1:Q | c1.isA=a1 //surjective
}
然后我试着用它吼叫:
module family
open library/copy [Person,QP]
sig Person {}
sig QP{isA:Person}
run {} for 4
但是合金抱怨“名字”是“无法找到”。在模块中。
我的做法有什么问题?为什么合金会抱怨?
答案 0 :(得分:2)
Alloy中的模块被视为独立单元(即,模块只能访问该模块本身定义的内容以及在该模块中明确打开的模块),因此在编译" copy"模块,isA
确实是未定义的。理论上的解决方案是另外参数化"复制"模块由isA
关系,但在Alloy模块参数中只能是sigs。
您的问题的一个可能的解决方案是在模块" copy"中定义抽象sigs A
和Q
,然后在其他模块中定义扩展{{1}的具体sig }和A
,例如
<强> copy.als 强>:
Q
<强> family.als 强>:
module library/copy
abstract sig A {}
abstract sig Q {isA: one A}
fact {
all c1,c2:Q | c1.isA=c2.isA => c1=c2 // injective mapping
all a1:A | some c1:Q | c1.isA=a1 //surjective
}
使用继承来实现这种代码重用在概念上并不理想,但在实践中通常已经足够好了,我无法想到在Alloy中采用另一种方法。
答案 1 :(得分:2)
在我之前的回答中,我试图解决你的问题,同样在不同的签名和#34;点,也就是说,我认为你的主要目标是有一个模块以某种方式强制在与参数isA
相关联的sig中有一个名为Q
的字段,并且isA
都是内射和满射。我现在意识到你可能想要的是可重用的谓词,断言给定的二元关系是单射的/投射的;这可以在Alloy中实现:
<强>库/ copy.als 强>
module copy [Domain, Range]
pred inj[rel: Domain -> Range] {
all c1,c2: Domain | c1.rel=c2.rel => c1=c2 // injective mapping
}
pred surj[rel: Domain -> Range] {
all a1: Range | some c1: Domain | c1.rel=a1 //surjective
}
<强> family.als 强>
open copy[QP, Person]
sig Person {}
sig QP{isA:Person}
fact {
inj[isA]
surj[isA]
}
run {} for 4
实际上,您可以打开内置的util/relation
模块并使用injective
和sujective
谓词来实现同样的目的,例如:
<强> family.als 强>
open util/relation
sig Person {}
sig QP{isA:Person}
fact {
injective[isA, Person]
surjective[isA, Person]
}
run {} for 4
您可以打开util/relation
文件(File -> Open Sample Models
)并查看实现这两个谓词的其他方法。然后你甚至可以检查你的主观/投射主张方式是否等同于内置方式:
open copy[QP, Person]
open util/relation
sig Person {}
sig QP{isA:Person}
check {
inj[isA] <=> injective[isA, Person]
surj[isA] <=> surjective[isA, Person]
} for 4 expect 0 // no counterexample is expected to be found