in railcab-trans-new.maude in model-checker.maude --- assumptions of update --- 1. current state should be preserved --- 2. new functionalities should be initialized --- Critera of correct update --- 1. it should finally reach an updatable state, otherwise, it must be braked --- 2. after being updated, system should satisfy desired properties --- In this example, the problem is --- a. when railcab is crossing the intersection, gate must be closed. --- b. when railcab can cross the intersection (when gate is closed and railcab --- is granted to cross, it must cross) mod RAILCAB-UPDATE is inc RAILCAB-NEW . inc RAILCAB-OLD . sort ONState . subsort OldState NewState < ONState . var LOC : Location . var T : Status . vars CH1 CH2 : QMsg . var B : Bool . var S : Signal . var L : Label . op convert : QMsg -> QMsgNew . eq convert(empty) = emptyNew . eq convert(M:Msg & Q:QMsg) = (M:Msg && convert(Q:QMsg)) . --- this is a bad update --- it violates the second property crl [update-1] : (loc-o: LOC:Location) (rStatus-o: running) (pass-o: S:Signal) (channel1-o: CH1:QMsg) (channel2-o: CH2:QMsg) (conLoc-O: L:Label) (gate-o: B) => (loc-n: LOC), (rStatus-n: running), (pass-n: S), (channel1-n: convert(CH1)), (channel2-n: convert(CH2)), (conLoc-N: L), (gate-n: B), (appResult: (if B then grant else reject fi)) if not (LOC = noReturn) . endm mod PREDICATE is including MODEL-CHECKER . inc RAILCAB-UPDATE . subsort ONState < State . op @noReturn : -> Prop . op updated : -> Prop . op braked : -> Prop . eq (rStatus-o: eBraked) OS:OldState |= braked = true . eq (loc-n: noReturn), NS:NewState |= @noReturn = true . eq NS:NewState |= updated = true . eq S:State |= P:Prop = false [owise] . op fair : -> Formula . op updatable : -> Prop . var L : Location . --- define the condition of updatable state ceq (loc-o: L) (rStatus-o: running) OS:OldState |= updatable = true if not (L = noReturn) . eq fair = (updatable -> (O updated)) . op closedGate : -> Prop . eq (gate-n: true), NS:NewState |= closedGate = true . endm eof --- formula of the properties --- 1. Updatability, <> updatable or <> braked red modelCheck(init-o, (<> updatable) \/ (<> braked)) . --- it is true --- a. [](@noReturn -> closedGate) red modelCheck(init-o, [] (@noReturn -> closedGate)) . --- a counterexample is found --- update happens when railcab is at the leBrake, conLoc-O is s4. --- railcab just crossed the intersection, but controller has not --- closed the gate yet. So, appResult is \emph{grant} after update, but --- a reqMsg has not been responded by the controller. --- The controller first opens the gate it is still at s4. --- Responds to the railcab and sends a grant message. So, pass is \emph{grant}. --- The railcab can cross but the gate is still open. --- This example shows the condition of updating is too weak. result ModelCheckResult: counterexample({loc-o: endOfTS channel1-o: empty channel2-o: empty rStatus-o: running conLoc-O: s1 gate-o: false pass-o: unknown,'sendReq} {loc-o: lastBrake channel1-o: reqMsg channel2-o: empty rStatus-o: running conLoc-O: s1 gate-o: false pass-o: unknown,'move2LEB2} { loc-o: leBrake channel1-o: reqMsg channel2-o: empty rStatus-o: running conLoc-O: s1 gate-o: false pass-o: unknown,'recReq} {loc-o: leBrake channel1-o: empty channel2-o: empty rStatus-o: running conLoc-O: s2 gate-o: false pass-o: unknown,'sendResp2} {loc-o: leBrake channel1-o: empty channel2-o: respMsg(grant) rStatus-o: running conLoc-O: s3 gate-o: false pass-o: unknown,'recResp} {loc-o: leBrake channel1-o: empty channel2-o: empty rStatus-o: running conLoc-O: s3 gate-o: false pass-o: grant,'move2nr} {loc-o: noReturn channel1-o: empty channel2-o: empty rStatus-o: running conLoc-O: s3 gate-o: false pass-o: grant,'closeGate} {loc-o: noReturn channel1-o: empty channel2-o: empty rStatus-o: running conLoc-O: s1 gate-o: true pass-o: grant,'pass} {loc-o: opposite channel1-o: empty channel2-o: empty rStatus-o: running conLoc-O: s1 gate-o: true pass-o: grant,'sendPass} {loc-o: endOfTS channel1-o: passed channel2-o: empty rStatus-o: running conLoc-O: s1 gate-o: true pass-o: unknown,'sendReq} {loc-o: lastBrake channel1-o: (reqMsg & passed) channel2-o: empty rStatus-o: running conLoc-O: s1 gate-o: true pass-o: unknown,'move2LEB2} {loc-o: leBrake channel1-o: (reqMsg & passed) channel2-o: empty rStatus-o: running conLoc-O: s1 gate-o: true pass-o: unknown,'getPass} {loc-o: leBrake channel1-o: reqMsg channel2-o: empty rStatus-o: running conLoc-O: s4 gate-o: true pass-o: unknown,'update-1} {loc-n: leBrake,channel1-n: reqMsg, channel2-n: emptyNew,rStatus-n: running,conLoc-N: s4,gate-n: true,pass-n: unknown,appResult: grant,'eBrake2} {loc-n: leBrake,channel1-n: reqMsg, channel2-n: emptyNew,rStatus-n: eBraked,conLoc-N: s4,gate-n: true,pass-n: unknown,appResult: grant,'open} {loc-n: leBrake,channel1-n: reqMsg, channel2-n: emptyNew,rStatus-n: eBraked,conLoc-N: s1,gate-n: false,pass-n: unknown,appResult: grant,'recReq} {loc-n: leBrake,channel1-n: emptyNew, channel2-n: emptyNew,rStatus-n: eBraked,conLoc-N: s2,gate-n: false,pass-n: unknown,appResult: grant,'sendResp2} {loc-n: leBrake,channel1-n: emptyNew, channel2-n: respMsg(grant),rStatus-n: eBraked,conLoc-N: s3,gate-n: false, pass-n: unknown,appResult: grant,'recResp} {loc-n: leBrake,channel1-n: emptyNew,channel2-n: emptyNew,rStatus-n: eBraked,conLoc-N: s3,gate-n: false,pass-n: grant,appResult: grant,'toRun2} {loc-n: leBrake,channel1-n: emptyNew,channel2-n: emptyNew,rStatus-n: running,conLoc-N: s3,gate-n: false,pass-n: grant,appResult: grant,'move2nr} {loc-n: noReturn,channel1-n: emptyNew,channel2-n: emptyNew,rStatus-n: running,conLoc-N: s3,gate-n: false,pass-n: grant,appResult: grant,'closeGate-N}, {loc-n: noReturn, channel1-n: emptyNew,channel2-n: emptyNew,rStatus-n: running,conLoc-N: s1, gate-n: true,pass-n: grant,appResult: grant,'pass-n} {loc-n: opposite, channel1-n: emptyNew,channel2-n: emptyNew,rStatus-n: running,conLoc-N: s1, gate-n: true,pass-n: grant,appResult: grant,'sendPass} {loc-n: endOfTS, channel1-n: passed,channel2-n: emptyNew,rStatus-n: running,conLoc-N: s1, gate-n: true,pass-n: unknown,appResult: unknown,'sendReq} {loc-n: appCross, channel1-n: (reqMsg && passed),channel2-n: emptyNew,rStatus-n: running, conLoc-N: s1,gate-n: true,pass-n: unknown,appResult: unknown,'sendApp} { loc-n: lastBrake,channel1-n: (chkMsg && reqMsg && passed),channel2-n: emptyNew,rStatus-n: running,conLoc-N: s1,gate-n: true,pass-n: unknown, appResult: unknown,'move2LEB2} {loc-n: leBrake,channel1-n: (chkMsg && reqMsg && passed),channel2-n: emptyNew,rStatus-n: running,conLoc-N: s1, gate-n: true,pass-n: unknown,appResult: unknown,'eBrake2} {loc-n: leBrake, channel1-n: (chkMsg && reqMsg && passed),channel2-n: emptyNew,rStatus-n: eBraked,conLoc-N: s1,gate-n: true,pass-n: unknown,appResult: unknown, 'getPass-N} {loc-n: leBrake,channel1-n: (chkMsg && reqMsg),channel2-n: emptyNew,rStatus-n: eBraked,conLoc-N: s4,gate-n: true,pass-n: unknown, appResult: unknown,'open} {loc-n: leBrake,channel1-n: (chkMsg && reqMsg), channel2-n: emptyNew,rStatus-n: eBraked,conLoc-N: s1,gate-n: false,pass-n: unknown,appResult: unknown,'recReq} {loc-n: leBrake,channel1-n: chkMsg, channel2-n: emptyNew,rStatus-n: eBraked,conLoc-N: s2,gate-n: false,pass-n: unknown,appResult: unknown,'sendResp2} {loc-n: leBrake,channel1-n: chkMsg, channel2-n: respMsg(grant),rStatus-n: eBraked,conLoc-N: s3,gate-n: false, pass-n: unknown,appResult: unknown,'recResp} {loc-n: leBrake,channel1-n: chkMsg,channel2-n: emptyNew,rStatus-n: eBraked,conLoc-N: s3,gate-n: false, pass-n: grant,appResult: unknown,'closeGate-N} {loc-n: leBrake,channel1-n: chkMsg,channel2-n: emptyNew,rStatus-n: eBraked,conLoc-N: s1,gate-n: true, pass-n: grant,appResult: unknown,'recAppMsg} {loc-n: leBrake,channel1-n: emptyNew,channel2-n: emptyNew,rStatus-n: eBraked,conLoc-N: s5,gate-n: true, pass-n: grant,appResult: unknown,'sendAppVal} {loc-n: leBrake,channel1-n: emptyNew,channel2-n: gateMsg(true),rStatus-n: eBraked,conLoc-N: s1,gate-n: true,pass-n: grant,appResult: unknown,'recApp1} {loc-n: leBrake,channel1-n: emptyNew,channel2-n: emptyNew,rStatus-n: eBraked,conLoc-N: s1,gate-n: true, pass-n: grant,appResult: grant,'toRun2} {loc-n: leBrake,channel1-n: emptyNew,channel2-n: emptyNew,rStatus-n: running,conLoc-N: s1,gate-n: true, pass-n: grant,appResult: grant,'move2nr})