0

以下は、私が最近携帯電話のテキストメッセージ用に完成させたまあまあの合金仕様です。それは単なる基本的なテキストメッセージの要件であり、それは慣習であるため、私は守るべき厳格な要件はありません。ただし、Name-Mobileペアのペアを1つしか取得できないなど、いくつかの厄介な問題があります。2つのメッセージセットが一貫して1つの名前を指しているのはなぜですか?質問を除いて、事実と述語は非常に単純です。合金自体を学ぶためのフィードバックが必要ですので、十分に批判してください。

以下のことをしているときに私が心に留めていたこと;

1つのメッセージボックスに0個以上のメッセージセットがあります。セットは1人のみに属し、セットは無料ではありません。各セットには、メッセージ行、開始キーと終了キー、行、およびカーソル位置で構成される1つ以上のメッセージがあります。複数のメッセージが同じ人に属することはできますが、同時に2人に属することはできません。各行には1つ以上のキーがあり、開始キーと終了キーがあります。また、行には新しい行がある場合とない場合があります。各キーには、次のキーがある場合とない場合があります。キーはタッチパッドを介して押されます。すべての名前には携帯電話番号があり、ContactListに記録されます。2人の名前が同じ携帯電話を持つことはできませんが、人は複数の電話番号を持つことができます。

ありがとう。

    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
4

1 に答える 1

2

Name-Mobileペアのペアを1つ以上取得できないのはなぜですか?

このような問題をデバッグするには、「unsatcore」機能を使用できます。まず、述語に追加#Name > 1し、[showオプション]メニューから[MiniSat with Unsat Core]ソルバーを選択し、最後に[show]述語を実行しました。モデルは(予想どおり)満足のいくものではなかったため、インスタンスの代わりに、不飽和のコアが返されました。つまり、相互に矛盾する最小限の式のセットが返されました。つまり、unsatコアは、モデルが充足できない理由を示します。また、unsatコアの式のいずれかを削除すると、モデルは充足可能になるはずです。

具体的な例では、unsatコアに次の行が含まれています。

  contact: Name // field declaration inside the ContactList sig

  all c:ContactList| #c.contact =#Name

  #Name > 1

これにより、モデルが満たされない理由がすぐにわかります。contactフィールドは正確に1つを指すように宣言されていNameます。そのフィールドのカーディナリティをNameアトムの数と等しくするように強制する次の制約は、アトムが1つしかないことを意味するNameため、明示的にさらにNameアトム(#Name > 1)を要求すると、矛盾が生じます。

これを修正するには、contactフィールド宣言をに変更しますcontact: set Name

2つのメッセージセットが一貫して1つの名前を指しているのはなぜですか?

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

繰り返しますが、問題が何であるかはかなり明白です。すべてMessageSetのsが同じName(3行目)を指しているわけではありませんが、モデルには正反対のファクト(1行目)があります。つまり、すべてms: MessageSetm: Messages、の値はms.isSetOf同じで、に等しくなければなりませんm.sentFrom。これらの制約を満たす唯一の方法は0にすることですMessages(したがって、全称記号は自明に真です)が、その場合、不飽和コアからの2行目は満たすことができません。

于 2013-01-07T15:52:28.460 に答える