在合金的链表中插入和删除

时间:2013-04-21 07:57:49

标签: list alloy

我使用合金创建了一个简单版本的链表。现在我想创建一个链表,我可以在其中执行插入和删除。我刚开始用合金编码。目前我在使用函数和实用程序等复杂操作时遇到了麻烦。如果我能得到一些如何使用实用程序和函数以及如何在合金中实际执行插入和删除的示例。我很感激你的帮助。

sig node{}

sig linked
{
  ele:set node,
  link:ele->lone ele,   
  head:lone ele
}{
  node = ele
  all x:ele | x in head.*link && head not in x.link && #x.link <=1 
}

fact{
  all  l:linked| all  e:l.ele| e->e not  in l.link //no self loop
}

fact
{
  all  l:linked|no e : l.ele | (e  in e.^(l.link )) //acyclic
}

pred a (l:linked,x:node)
{
  x in l.ele    
}

run a for 6 node,1 linked

2 个答案:

答案 0 :(得分:2)

你的方法有点混乱,可能会简单得多。我会这样做

sig Node{
    next : lone Node
}

one sig Head in Node {}                     -- head node is still a node

fact{
    all n : Node | n not in n.^next         -- no cycles
    no next.Head                            -- no node points to Head
    all n : Node - Head | some next.n       -- for all other nodes, there has to be someone pointing to them
}

run {} for 10

这个模型是静态的,为了使模型动态化,你需要了解de的概念。我建议您阅读由Alloy的作者撰写的Software Abstractions。链表的动态方法太复杂了,你现在不能理解,你应该做一些简单的练习。

状态的基本概念是(基于书中address book示例的练习):

静态示例:

sig State {}

abstract sig Target {}

sig Email extends Target {}

abstract sig Name extends Email {
    name : set State,
    addr : Target some -> State
}

sig Group, Alias extends Name {}

fact {
    all a : Alias | lone a.addr
    no n : Name | n in n.^addr
}

run {}

动态示例,在本地状态成语(=表达状态的方式,还有全局状态习语和事件习语)。看一下谓词

open util/ordering[State]
sig State {}

abstract sig Target {}

sig Email extends Target {}

abstract sig Name extends Email {
    name : set State,
    addr : Target -> State
}

sig Group, Alias extends Name {}

fact {
    all s : State {
        all a : Alias & name.s | lone a.addr.s
        no n : name.s | n in n.^(addr.s)
        addr.s in name.s -> Target
        addr.s :> Name in Name -> name.s
    }
}

run {} for 3 but exactly 1 State

-- adding a name n, for a given pre state s and post state s'
pred addName [n : Name, s,s' : State] {

    -- the name must not exist in the pre state
    n not in name.s    

    -- the relation names in the post state is what is was
    -- in the pre state in addition to the new name
    name.s' = name.s + n  

    -- the address relation stays the same    
    addr.s' = addr.s
}

run addName for 3 but 2 State

pred addTarget [n : Name, t : Target, s,s' : State] {
    t not in n.addr.s
    name.s' = name.s
    addr.s' = addr.s + n->t
}

run addTarget for 3 but 2 State

您还可以查看以下slides

答案 1 :(得分:1)

您无需使模型“动态”以模拟插入和删除等操作。看看这个主题(doubly-linked-list-in-alloy),我在那里给出了如何为双向链接列表建模反向操作的答案,然后让我们知道这是否有用。您将看到的基本思想是创建一个谓词,该谓词接受前置状态和后置状态的参数,并断言两者是如何相关的。例如,您的插入谓词可能看起来像

// l - list in the pre-state
// x - node to be inserted
// l' - list in the post-state
pred insert (l: linked, x: node, l': linked) {
  l'.ele = l.ele + x
  ...
}