next = proc (net: network, origin, destination: string) returns(string) signals(already_there, no_node(string), impossible) % effects: Takes in a network, a node of origin, and a node % of destination and returns a node adjacent to the node of % of origin that is closer to the destination node. % Signals already_there if the origin and destination % are the same. Signals no_node(string) if either of the % nodes does not exist, where string is the name of the first % nonexistent nodeencountered. Signals impossible if % the destination node cannot be reached from the node of origin. parents = ptable[string, string] table: parents:= parent$create() for node in nodes(net) do parents$insert(table, node, "") end parents$lookup(table, origin) except when not_found: signal no_node(origin) end if string$equal(origin, destination) then signal already_there end hotlist: array[string] := array[string]new() array[string]$addh(hotlist, origin) while string$empty(parents$lookup(table, destination)) if array[string]$size(hotlist) = 0 then signal impossible end temp: array[string] := array[string]$copy(hotlist) for nd in array[string]$elements(temp) do for nd_neigh in network$neighbors(net, nd) do array[string]$addh(hotlist, nd_neigh) parents$change(table, nd_neigh, nd) end array[string]$reml(hotlist) end end except when not_found: signal no_node(destination) end for node in nodes(net) do if parents$lookup(table, node) = origin then return(node) end end end next path = proc(net: network, origin, destination, string) returns(array[string]) signals(impossible, no_node(string)) % effects: Given the network net, path takes a node of % origin and a node of destination and returns an array % of node names where the index corresponds to where % the message is at a point in time. (E.g., % answer[0]=origin, answer[1]=node1, ..., answer[n]=destination temp: string answer: array[string]:= array[string]$create(0) array[string]$addh(answer, origin) while true do temp := next(net, origin, destination) array[string]$addh(answer, temp) end resignal impossible resignal no_node except when same_node: end return(answer) end path schedule = proc(net: network, am: array[message]) returns(string) % effects: Returns a human readable string % describing how to move the messages in "am" along "net" from % their origin to their destination. mgs: array[message] := array[message]$new val: string:= "" for mess in array[message]$elements(am) do org: string:= message$origin(mess) des: string:= message$destination(mess) next(net, org, des) array[message]$addh(mgs, mess) except when impossible: val:= string$concat(val, "Impossible: " || message$value(mess) || " -- No path exists between nodes " || org || " and " || des || "\n") when no_node(node): val:= string$concat(val, "Impossible: " || message$value(mess) || " node " || node || " is not in the network\n") end end temp: array[message] count: int:= 1 while true do val:= string$concat(val, "\nCycle " || count || ":\n") temp: array[message]$new() for mess, action in cycle(net, mgs) do array[message]$addh(temp, mess) val:=string$concat(val, message$value(mess) || ": " || action || "\n") end mgs:= temp count:= count + 1 end except when done: end return(val) end schedule cycle = iter(net: network, am: array[message]) yield(message, string) signals(done) % effects: For each message in "am", yields a string which % describes the movement of the message along the network % during this cycle and another message that indicates the new % message position. Signals done if all messages have reached % their destination. d: bool:= true n: network:= network$copy(net) for mess in array[message]$elements(am) do origin := message$origin(mess) destination := message$destination(mess) nd := next(n, origin, destination) d := false network$delete(n, nd, origin) val: string:= message$value(mess) yield(message$create(val, nd, destination), string$concat(origin, " -> " || nd)) except when already_there: yield(mess, "") when impossible: yield(mess, origin) end end if d then signal done end end cycle