180 likes | 327 Vues
This document presents a comprehensive pseudocode adaptation for a distributed algorithm to find the Minimum Spanning Tree (MST), based on the work of Gallagher, Humblet, and Spira (1983) and enhanced by Kenneth J. Goldman in September 2002. The adaptation introduces concepts like node statuses (SLEEPING, SEARCHING, FOUND), levels, and edge classifications. It details the message types and their purposes within the protocol, including actions such as initiating searches, testing edges, and reporting costs back up the tree. This adaptation serves as a guide for implementing a distributed MST algorithm.
E N D
Distributed Minimum Spanning TreeGallagher, Humblet, Spira (1983) pseudocode adaptation by Kenneth J. Goldman September 2002
Two integers: • status: SLEEPING, SEARCHING, or FOUND (initially SLEEPING) • level: the level number of this fragment (initially 0) • Three lists of incident edges: • basicEdges (initially all incident edges, sorted lowest to highest cost) • rejectedEdges (edges determined not to be in the MST, initially empty) • branchEdges (edges in the MST, initially empty) • Three nodes: • core: the root of the fragment (initially yourself) • parent: the parent node in t (initially null) • minChild: the child reporting the minimum edge so far (initially null) • Additional bookkeeping: • deferredTests: a list of pending Test messages (initially empty) • mwoe: int cost of minimum weight outgoing edge found so far Process State
Protocol Message Types • Wakeup -- starts the protocol at a sleeping node • Initiate(core,level) -- broadcast new core/level and start MWOE search in a fragment • Test(core,level) -- sent on edge E to see if E leads to another fragment • Accept -- response to a Test message indicating a different fragment • Reject -- response to a Test message indicating the same fragment • Report(cost) -- sent up the tree to inform parent of MWOE of subtree • ChangeRoot -- sent from core toward MWOE of fragment, tells the node with the MWOE to connect across it • Connect(core,level) -- sent over MWOE to combine fragments • Inform(core,level) -- broadcast new core/level to an absorbed fragment • AllDone -- broadcast from core to inform nodes of termination
Protocol Message Contents • Each message contains: • Integer type (WAKEUP, INITIATE, TEST, ACCEPT, REJECT, etc.) • The sender node name • Data fields (depending on message, some are omitted): • core – a node name (the core of the sending node’s fragment) • level –an integer (the level number of sending node’s fragment) • cost – an integer (the cost of an edge in the subtree)
M = Wakeup() if SLEEPING // MWOE is the lowest cost basic edge Edge E = the first edge in basicEdges; send "Connect(core,level)" over E; Note: If the node is not sleeping, M is ignored.
M = Initiate(core,level) over E status = SEARCHING; this.core = M.core; this.level = M.level; processDeferredTests(); // when level increases parent = M.sender; mwoe = INFINITY; minChild = null; let waitingForReport contain all branch edges (besides E, if sender != self) send "Initiate(core,level)" over all branch edges (besides E, if sender != self) while (there are basicEdges and mwoe > cost(first basicEdge)) { send "Test(core,level)" over first basicEdge wait for a response (Accept or Reject) }
When Initiate loop is completed and waitingForReport is empty if (parent != self) { status = FOUND; send "Report(mwoe)" to parent; } else if (mwoe < INFINITY) { send "ChangeRoot" to self; } else { send "AllDone" on all branchEdges; }
M = Test(core,level) over E if (this.core == core) // in same fragment send back "Reject" along E; else if (this.level >= level) // another fragment send back "Accept" along E; else // don't know yet put the message into deferredTests;
processDeferredTests() for each message M in deferredTests { if (this.core == M.core) { send "Reject" to M.sender; remove M from deferredTests; } else if (this.level >= level) { send "Accept" to M.sender; remove M from deferredTests; } } Note: This is called whenever the level increases.
M = Accept() over E if (cost(E) < mwoe) { minChild = null; mwoe = cost(E); } Note: Sender is in a different fragment.
M = Reject() over E move E brom basicEdge to rejectedEdges; Note: Sender is already in the same fragment, so E must be an internal edge (not a tree edge).
M = Report(cost) over E remove E from waitingForReport; if (cost < mwoe) { minChild = other endpoint of E; mwoe = cost; }
M = ChangeRoot() over E status = FOUND; if (minChild != null) { send "ChangeRoot" to minChild; } else { move first basicEdge to branchEdge; send "Connect(core,level)" across that edge; }
M = Connect(core,level) over E move E from basicEdges to branchEdges; if (this.level > M.level) { // ABSORB the other if (status == FOUND) // already have MWOE send Inform(core,level) over E; else { // status is SEARCHING add E to waitingForReport; send Initiate(core,level) over E; } } else {// equal levels, so MERGE with the other this.core = maximum end point of E (neighbor) this.level++; processDeferredTests(); // since level changed if (this.core == this) // WE'RE THE NEW CORE send Initiate(this.core,this.level) to self; }
M = Inform(core,level) over E this.core = core; this.level = level; processDeferredTests(); send "Inform(core,level)" over all other branch edges (besides E);
M = AllDone() over E send "AllDone" along all tree edges besides E; The algorithm is finished at this point… Use branchEdges as the edges of the tree. Use the core as the root of the tree.