【问题标题】:alloy specification problems合金规格问题
【发布时间】:2013-01-07 14:15:26
【问题描述】:

下面是我最近为手机短信完成的一个马马虎虎的合金规格。这只是基本的发短信要求,因为这是一种做法,我没有严格的要求要坚持。但是,我有一些尴尬的问题,例如为什么我不能获得超过 1 对 Name-Mobile 对?为什么 2 个 MessageSets 坚持指向一个 Name?除了问题之外,事实和谓词非常直截了当。请随意批评,因为我需要反馈来学习合金本身。

我在做以下事情时的想法;

一个消息框有 0 个或多个 MessageSet。一套只属于一个人,没有一套是免费的。每组有 1 个或多个消息,由消息行、开始和结束键和行以及光标位置组成。多条消息可以属于同一个人,但一条消息不能同时属于 2 个人。每行有 1 个或多个键,并有它们的开始键和结束键。此外,一行可能有也可能没有新行。每个键可能有也可能没有下一个键。通过触摸板按下按键。每个名字都有一个手机号码,并记录在 ContactList 中。没有两个名字可以有相同的手机,但一个人可以有多个电话号码。

谢谢。

    sig Lines{
formedOfKeys:some Keys,
lineStartKey:one Keys,
lineEndKey:one Keys,
nextLine: lone  Lines,
    }

one sig TouchPad{  pressed: set Keys }

sig Keys{ nextKey: one Keys, }

one sig MessageBox{}

    sig MessageSet{
isIn:one MessageBox,
isSetOf: one Name
    }

     sig Messages{
belongsToSet:  one MessageSet,
firstLine: one Lines,
lastLine:one Lines,
lastKey:one Keys,
firstKey: one Keys,
curserLoc: one Keys,
formedOfLines: set Lines,
sentFrom : one Name
   }

sig Name,Mobile {}

    one sig ContactList {
contact: Name, 
mobile: contact -> one Mobile
}

    fact No2NamesBelongingToMessageSetsSame{
//  all ms1,ms2:MessageSet| ms2 = ms1 implies ms1.isSetOf != ms2.isSetOf
    }

    //make it more than 2
fact NameAndMobileNumbersMatchedAndEqual{
//  #Name>2 and #Mobile>2
#Name=#Mobile
    }

    fact MessageSetBelongsToName{
all  ms:MessageSet, m:Messages |ms.isSetOf=m.sentFrom
    }

    fact AllNamesInContactList{
all c:ContactList| #c.contact =#Name
}

    fact NoLastMessageLineWithNextLine{
no l:Lines | l.nextLine not in (Messages.lastLine +Messages.firstLine)
    }

    fact NoNextKeyisSelf{
all k: Keys| k !in k.nextKey
    }

    fact NoNextLineisSelf{
all l: Lines | l !in l.nextLine
    }
    fact No2WayConnectionsBetweenLines{
all disj l1, l2: Lines | l2 in l1.nextLine implies l1 !in l2.nextLine
    }

    fact No2WayConnectionsBetweenKeys{
all disj k1, k2: Keys| k2 in k1.nextKey implies k1 !in k2.nextKey
    }

    fact MessageHasMoreThan1LineHasNextLine{
all m:Messages|#m.formedOfLines>1 implies #m.formedOfLines.nextLine>0
    }

fact LineStartInMessageLines{ all l:Lines| l.lineStartKey in l.formedOfKeys }
fact LineEndInMessageLines{ all l:Lines| l.lineEndKey in l.formedOfKeys }
fact CurserLocInMessageKeys{ all m:Messages| m.curserLoc in m.formedOfLines.formedOfKeys  }
fact FirstKeyInMessageKeys{ all m:Messages| m.firstKey in m.formedOfLines.formedOfKeys  }
fact firstLineInMessageLines{ all m:Messages| m.firstLine in m.formedOfLines }
fact MessageNextLineInMessageLines{ all m:Messages| m.formedOfLines.nextLine in m.formedOfLines }

fact MessageFirstKeyisInLineStartKeySet{ all m:Messages , l:Lines | m.firstKey in l.lineStartKey }

fact MessageLastKeyisInLineEndKeySet{ all m:Messages , l:Lines | l in m.lastLine && l.lineEndKey in m.lastLine.lineEndKey }

fact allKeysArePressed { all k:Keys | k in TouchPad.pressed }

fact NoMessageSetsWithoutMessages{ no ms:MessageSet| ms not in Messages.belongsToSet }

fact NoMessageSetWithoutBox{ no mb:MessageBox| mb not in MessageSet.isIn }

    pred nonReturnKeyPress[k: Keys, l,l':Lines, t:TouchPad]{
//key pressed in message, cursor and line info (new state =original state+1letter)
 l'.formedOfKeys= l.formedOfKeys++(t.pressed)
}

    pred deleteKeyPressed[k: Keys, l,l':Lines, t:TouchPad]{
//key deleted from line. cursor and line info (new state =original state-1key)
l'.formedOfKeys = l.formedOfKeys - (t.pressed)
}

    pred returnKeyPressed[k: Keys, l,l':Lines, t:TouchPad]{
//TODO return key pressed. cursor loc is new line's cursor loc
 l'.formedOfKeys= l.nextLine.formedOfKeys
}
    assert keyPressWorks {
    //TODO check if key press works properly
    }
    pred pressThenDeleteSame {
    all l1,l2,l3: Lines,  t:TouchPad, k: Keys|
    nonReturnKeyPress [k,l1,l2,t] && deleteKeyPressed [k,l2,l3,t]
        => l1.formedOfKeys = l3.formedOfKeys
}

    pred ReceiveThenSendSame {
all ms1,ms2,ms3, m: Messages|
    receive [m,ms1,ms2] && send [m,ms2,ms3]
        => ms1 = ms3
}

    pred findCursorLoc [l:Lines, k:lone Keys]{
//TODO I have a line and a key...How can i check where i am
}

    pred send[m, mS,mS':Messages]{
//final message set is one less than previous
mS'= mS - (m)
}

    pred receive[m, mS,mS':Messages]{
//final message set is one more than previous
mS'= mS++ (m)
}

pred AddContact [cl, cl': ContactList, n: Name, m: Mobile] {
   cl'.mobile = cl.mobile ++ (n->m)
    }

    pred RemoveContact [cl, cl': ContactList, n: Name] {
cl'.mobile = cl.mobile - (n->Mobile)
}

    pred FindContact [cl: ContactList, n: Name, m: Mobile] {
m = cl.mobile[n]
}

    assert AddingContact {
all cl, cl': ContactList, n: Name, m,m': Mobile |
    AddContact [cl,cl',n,m] && FindContact [cl',n,m'] => m = m'
}

    assert AddingThenDeleteSame {
all cl1,cl2,cl3: ContactList, n: Name, m: Mobile|
    AddContact [cl1,cl2,n,m] && RemoveContact [cl2,cl3,n]=> cl1.mobile = cl3.mobile
}

    assert pressThenDeleteSame {
all l1,l2,l3: Lines,  t:TouchPad, k: Keys|
    nonReturnKeyPress [k,l1,l2,t] && deleteKeyPressed [k,l2,l3,t]=> l1.formedOfKeys = l3.formedOfKeys
}

   assert ReceiveThenSendSame {
all ms1,ms2,ms3 , m: Messages|
    receive [m,ms1,ms2] && send [m,ms2,ms3]=> ms1 = ms3
}

//check AddingContact  expect 0
//check AddingThenDeleteSame  expect 1
//check pressThenDeleteSame  expect 0
//check ReceiveThenSendSame  expect 0

pred show{ }

run show 

//for exactly 3 Name,3 Mobile, 4 MessageSet,6 Messages, 5 Lines, 6 Keys  
//for exactly 4 MessageSet,14 Messages, 20 Lines, 40 Keys

【问题讨论】:

    标签: alloy model-checking


    【解决方案1】:

    为什么我不能获得超过 1 对姓名-手机对?

    要调试此类问题,您可以使用“unsat core”功能。首先,我将#Name > 1 添加到show 谓词中,然后从“选项”菜单中选择“MiniSat with Unsat Core”求解器,最后执行“显示”谓词。该模型是不可满足的(如预期的那样),因此返回的不是一个实例,而是一个未满足的核心,即一组相互不一致的最小公式。换句话说,未饱和核心为您提供了模型不可满足的原因,而且,如果您删除未饱和核心中的任何一个公式,模型应该变得可满足。

    在您的具体示例中,未饱和核心包含以下几行:

      contact: Name // field declaration inside the ContactList sig
    
      all c:ContactList| #c.contact =#Name
    
      #Name > 1
    

    这应该会立即告诉您为什么模型无法满足:contact 字段被声明为正好指向一个 Name;下一个强制该字段的基数等于Name原子数的约束意味着只能有1个Name原子,所以当你明确要求更多Name原子(#Name > 1)时,你会得到矛盾。

    要解决此问题,您可以将 contact 字段声明更改为 contact: set Name

    为什么 2 个 MessageSet 总是指向一个 Name?

    为了测试这一点,我在show 谓词中添加了以下约束(在如上所述修复contact 的声明之后)

    some disj ms1, ms2: MessageSet | ms1.isSetOf != ms2.isSetOf
    

    确实,模型不能令人满意。核心包含以下几行

      all  ms:MessageSet, m:Messages | ms.isSetOf = m.sentFrom
    
      no ms:MessageSet | ms not in Messages.belongsToSet 
    
      some disj ms1, ms2: MessageSet | ms1.isSetOf != ms2.isSetOf
    

    同样,问题出在哪里很明显。您希望并非所有 MessageSets 都指向相同的 Name(第 3 行),但在您的模型中,您有一个事实(第 1 行)正好相反,即所有 ms: MessageSetm: Messagesms.isSetOf 的值必须相同且等于m.sentFrom。满足这些约束的唯一方法是使用 0 Messages(所以通用量词是微不足道的),但在这种情况下,无法满足来自未饱和核心的第二行。

    【讨论】:

    • 我在 show 谓词中添加了 #Name > 1 and #Mobile > 1,但没有找到任何实例。 MessageSet 也有一个isSetOf: 关系指向one Name,但可以有多个名称,每个集合都需要指向一个名称。顺便说一句,对于 isSetof 关系中的名称,将 one 更改为 Set 并不重要
    • 我使用了您通过电子邮件发送给我的合金文件(因为您在此处发布的文件有语法错误),所以我的答案是指该模型。
    • 修复了模型,现在应该可以直接使用复制粘贴了。寄给你一份后,我又摆弄了一下。
    • 哇,谢谢。不知道有这样的选择。我将尝试使 MessageSet-Name Connections 保持应有的状态。同时,您认为如果我像 ContactList 那样个性化 Messages、MessageSet、Lines 和 Keys 签名会更好吗?例如,MessageSet 1 连接到 Messages1,2 或 Message 1 有 Line 1,2 等等
    • 好吧,如果我制作类似one sig ContactList { contact: set Name, mobile: contact -> one Mobile, sent: contact->set Messages, hasMessageSet: contact ->one MessageSet } 的东西,我如何检查每个 hasMessageSet 是否转到单独的集合。如果这样做,应该有机会更好地控制单个元素。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-12-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-11-22
    相关资源
    最近更新 更多