All Downloads are FREE. Search and download functionalities are using the official Maven repository.

models.examples.algorithms.s_ringlead.als Maven / Gradle / Ivy

module examples/algorithms/s_ringlead

/*
 * Model of leader election on a ring.
 *
 * Each process has a unique ID, IDs are ordered. The algorithm
 * elects the process with the highest ID the leader, as follows.
 * First, each process sends its own ID to its right neighbor.
 * Then, whenever a process receives an ID, if the ID is greater
 * than the process' own ID it forwards the ID to its right
 * neighbor, otherwise does nothing. When a process receives its
 * own ID that process is the leader.
 *
 * Note: This file needs higher order quantifiers turned on.
 */

open util/ordering[State] as so
open util/ordering[Process] as po
open util/graph[Process] as graph

sig Process {
  rightNeighbor: Process
}

sig State {
  // buffer which the right neighbor can read from
  buffer: Process -> Process,
  //sends, reads: Process -> Process,
  runs: set Process,
  leader: set Process
}

fact DefineRing {
  graph/ring[rightNeighbor]
}

fact InitialState {
  no so/first.buffer
  no so/first.leader
  Process in so/first.runs
}


fact CleanupLast {
  let ls = so/last |
    no ls.runs
}

pred ValidTrans2[s, s': State] {
  all p : s.runs | VT2Helper[p,s,s']
  all p : Process - s.runs | NOP2[p,s,s']
  NoMagicMsg[s,s']

}

pred NoMagicMsg[s, s' : State] {
    // no magically appearing messages
    all p : Process, m : s'.buffer[p] |
      m in s.buffer[p] || (!NOP2[p,s,s'] &&
                            ((s = so/first && m = p) ||
                             (s != so/first && m in s.buffer[p.~rightNeighbor]
                              && m !in s'.buffer[p.~rightNeighbor] && po/gt[m,p])))
}

pred PossTrans[s, s' : State] {
  all p : Process | VT2Helper[p,s,s'] || NOP2[p,s,s']
  NoMagicMsg[s,s']
}

pred VT2Helper[p : Process, s, s' : State] {
    (
      let readable=s.buffer[p.~rightNeighbor] |
        (s = so/first) => {
          p = s'.buffer[p]
          readable in s'.buffer[p.~rightNeighbor]
          p !in s'.leader
        } else {
          (some readable) => {
           some m : set readable | {
             m !in s'.buffer[p.~rightNeighbor]
             // nothing else gets deleted
             readable - m in s'.buffer[p.~rightNeighbor]
             { m': m | po/gt[m',p] } /*m & nexts(p)*/ in s'.buffer[p]
             p in s'.leader iff (p in s.leader || p in m)
           }
          } else NOP2[p,s,s']
        }
    )
}

pred NOP2[p : Process, s,s': State] {
  p in s'.leader iff p in s.leader
  // no reads
  s.buffer[p.~rightNeighbor] in s'.buffer[p.~rightNeighbor]
  // no sends
  s'.buffer[p] in s.buffer[p]
}

pred Preconds[p : Process, s : State] {
  s = so/first || some s.buffer[p.~rightNeighbor]
}

fact TransIfPossible {
  all s : State - so/last |
    (all p : Process | NOP2[p, s, so/next[s]]) =>
      (all p : Process | !Preconds[p,s])
}

fact LegalTrans {
  all s : State - so/last |
    let s' = so/next[s] |
      ValidTrans2[s,s']
}

pred EquivStates[s, s': State] {
  s.buffer = s'.buffer
  s.leader = s'.leader
}

assert Safety {
  all s : State | lone s.leader
}

pred Legit[s : State] {
  one s.leader
}

pred BadLivenessTrace {
  all s : State | !Legit[s]
  let ls = so/last |
    some s : State - ls | {
      EquivStates[s, ls]
      Process in (so/nexts[s] + s).runs
    }
}

pred TraceWithoutLoop  {
  all t1, t2 : State | t1!=t2 => !EquivStates[t1,t2]
  all s, s' : State | (s' in (so/nexts[s] - so/next[s])) => !PossTrans[s,s']
  all s : State | !Legit[s]
}

pred AltTrans  {
  SomeLeader
}

pred SomeLeader { some State.leader }

run BadLivenessTrace for 3 but 8 State expect 0
run SomeLeader for 4 but 6 State expect 1
check Safety for 7 expect 0
// run TraceWithoutLoop for 5 but 13 State expect 1
run AltTrans for 5 but 8 State expect 1




© 2015 - 2025 Weber Informatics LLC | Privacy Policy