module routing sig IP {} sig Link {from, to: Router} sig Router {ip: IP, table: IP ->? Link, nexts: set Router} sig Up extends Router {} fact { all r: Router { // router table refers only to router's links r.table[IP].from in r // nexts are routers reachable in one step r.nexts = r.table[IP].to // router doesn't forward to itself no r.table[r.ip] } no disj r1, r2: Router | r1.ip = r2.ip } fun Consistent () { // table forwards on plausible link all r: Router, i: IP | r.table[i].to in i.~ip.*~nexts } fun showme () {Consistent () && some Router} fun Inconsistent () {not Consistent ()} run showme for 1 run Inconsistent for 2 /* sig Router {distanceTo: IP ->? Int} fact { all r: Router, i: IP { let d = r.distanceTo [i], ds = r.nexts.distanceTo[i] { i = r.ip => d = Int 0, d in ds && no d': ds | int d' < int d } } } */ fun Forward (dest: IP, at, at': Router) { at' = at.table[dest].to } assert Progress { all dest: IP, at, at': Router | Consistent() && Forward (dest, at, at') => at != at' } check Progress for 4