我在Alloy上做了一些工作,所以我对它有一点了解。然而,很多速记并没有真正覆盖任何地方。我想知道的是在下面的例子中:
open util/relation
abstract sig Proc { prv : lone (Proc - Remove)
}{
}
fact {acyclic[prv,Proc] // no cycles
}
sig Remove extends Proc{}
sig Begin extends Proc{}{no prv}
sig Action extends Proc{}
pred show() {}
run show for 3
我想确保最终的Proc始终是一个Begin(此时它也可以是一个Action)。
有许多方法可以手写。我在下面添加了一个,当包含它时确保最终的Proc(即不在域中的那个)将始终是Begin。
fact {
all p : Proc | p not in dom[prv] implies p in Begin
}
然而,我喜欢使用(Proc - Remove)这样的简写,例如,因为使得事情更容易阅读,这意味着删除不能链接到另一个Proc。我希望我已经解释得那么好。我认为会有一个非常明显的答案,但我不能想到它是什么。有什么想法吗?
答案 0 :(得分:1)
听起来好像你可以通过写
来实现你的目标sig Remove extends Proc{}{some prv}
sig Begin extends Proc{}{no prv}
sig Action extends Proc{}{some prv}
这确保没有Begin有prv节点,所有非Begin节点都有。
答案 1 :(得分:0)
这个怎么样
fact { ^prv.Begin = Proc - Begin }
这不是超短,但至少它不使用量词。我不确定你能不能做得更好。
在图形术语中,它基本上表示:如果您通过尽可能多地跟踪其中的所有边缘来完全展开prv
图形(即,采用prv的传递闭包,^prv
) ,然后选择指向Begin节点(^prv.Begin
)的那些边的源节点,该集必须包含除Begin节点之外的所有节点。事实上,你已经知道Begin节点没有prv,它意味着从任何非Begin节点开始,只跟随prv
链接,将到达Begin节点,链将在那里结束。这个事实不允许Action节点和这样的链。
您可以通过断言
在Alloy中检查此声明check {
// there is no non-Begin node that does not lead to a Begin node
no p: Proc-Begin | no (Begin & p.^prv)
} for 6
并检查它是否找不到任何反例。