Alloy 在完全连接的网络中随时间在合金中填充集合
从 我有一个完全连通的图,这很好。我还加入了时间的概念。我现在正在努力解决在图形中传递数据的概念 我正在对一个系统进行建模,该系统的任务是确保每个节点都有一个插入到系统中的数据副本。我脑子里已经有了如何做到这一点的程序,但我正在努力将其翻译成合金术语 典型的算法如下所示:Alloy 在完全连接的网络中随时间在合金中填充集合,alloy,formal-methods,model-checking,Alloy,Formal Methods,Model Checking,从 我有一个完全连通的图,这很好。我还加入了时间的概念。我现在正在努力解决在图形中传递数据的概念 我正在对一个系统进行建模,该系统的任务是确保每个节点都有一个插入到系统中的数据副本。我脑子里已经有了如何做到这一点的程序,但我正在努力将其翻译成合金术语 典型的算法如下所示: For i = 0 to TIME_STEPS: For each node in {nodes}: Check all other nodes and, if necessary, provide a copy
For i = 0 to TIME_STEPS:
For each node in {nodes}:
Check all other nodes and, if necessary, provide a copy of the data
if they do not currently have it
为了简单起见,假设每个节点都有一段唯一的数据,它们必须向所有其他节点提供这段数据。因为这是完全关联的,所以应该相对简单(翻译成合金/形式逻辑对我来说有点困难)
这就是我目前的处境:
open util/ordering[Time] as TO
module rdm4
----- signatures
sig Time {}
sig DataMirror {
link: set DataMirror,
toSend: DataMirror -> Time
}
----- facts
// model network of completely connected data mirrors
fact completely_connected {
link = ~link -- symmetrical
no iden & link -- no loops
all n : DataMirror | (DataMirror - n) in n.link -- completely connected
}
// can't send to self
--fact no_self_send {
-- no d: DataMirror | d.toSend = d.link.toSend
--}
------ predicates
pred init [t: Time] {
all p: DataMirror | p.toSend.t = p
}
pred show() { }
run show for exactly 5 DataMirror, 20 Time
从我的run谓词中,您可以看到我希望在20个时间步内发送所有消息,因此每个DataMirror都应该有一组数据,该数据由5条唯一的消息组成
我非常确定我要做的是让每个DataMirror都有2个属性:
- 要发送的唯一消息(此时可能只是一个简单变量)
- 接收到的消息集(包括原始消息)
DataMirror1.starting_data = 'a'
DataMirror2.starting_data = 'b'
DataMirror3.starting_data = 'c'
DataMirror4.starting_data = 'd'
DataMirror5.starting_data = 'e'
然后,系统将在以下情况下实现:
DataMirror1.data_set = {'a', 'b', 'c', 'd', 'e'}
DataMirror2.data_set = {'a', 'b', 'c', 'd', 'e'}
DataMirror3.data_set = {'a', 'b', 'c', 'd', 'e'}
DataMirror4.data_set = {'a', 'b', 'c', 'd', 'e'}
DataMirror5.data_set = {'a', 'b', 'c', 'd', 'e'}
我为使任何正式逻辑的高级用户畏缩而提前道歉……我正试图在一次火试中了解这一点:)。你是在一个非常低的层次上建模——如果你抽象,那就更清楚了 在下面的代码中,我将文档抽象为一个简单的二进制数据。每次,所有节点都具有基准(打开)或不具有基准(关闭)。在下一步,它将传播到图中的所有邻居(不需要完整)
“低水平”可能是由于我不熟悉这种建模。感谢您的回复…我将试一试。我将避免在
节点
sig中使用附加的事实,然后必须理解和处理“隐式this”功能和“@”事物来抑制“隐式this”,因为它使您的模型变得不那么清晰。一般来说,我认为只写neights=~neights
要好得多,这对于大多数Alloy用户来说应该更容易理解。因此,在玩这个答案时……我认为这正是我想要的。简洁,帮助我更好地理解我的问题。非常感谢你!另外,@AleksandarMilicevic:我同意,我更喜欢这种符号,因为它具有对称性。谢谢你的评论。我倾向于同意更简单的neights=~neights
,但更好的做法是打开util/relation
并在事实上声明symmetric[neights]
。
open util/ordering[Time]
enum Datum{Off, On} // A simple representation of the state of each node
sig Time{state:Node->one Datum}// at each time we have a network state
abstract sig Node{
neighbours:set Node
}{
all n : neighbours| this in n.@neighbours} // symmetric
fact start{// At the start exactly one node has the datum
one n:Node|first.state[n]=On}
fact simple_change{ // in one time step all neighbours of On nodes become on
all t:Time-last |
let t_on = t.state.On |
next[t].state.On = t_on+t_on.neighbours}
run {} for 9 Time, 4 Node