Make your own free website on Tripod.com

Answer 1A

Abstract

The number of times that a node can improve the maintained path to the root is at most the difference between the shortest path from that node to the root and the longest path from that node to the root.

Proof

Each node sends updates to all neighbors (except the sender) when it receives an update with a shorter path than it has ever received. The paths may be received in decreasing order of lengths, and therefore the total number of messages is no more than:

Answer 1B

Abstract

The number of times that a node can improve the maintained path to the root is at most the number of different paths from that node to the root. This is because the link weights may be unique, and so can be the path weights.

Proof

Each node sends updates to all neighbors (except the sender) when it receives an update with a lesser weight path than it has ever received. The paths may be received in decreasing order of weights, and therefore the total number of messages is no more than:

 

Answer 2

Abstract

If the processors do not know n, then for the input X0(2t+1)||X1(2t+1) (where t is greater than the locality of computing f(X0) and f(X1) ), there is a node to which the ring looks locally the same as X0, and there is a node to which the ring looks locally the same as X1. Therefore, f(X0) must equal f(X1).

Proof

We will prove for a synchronous ring, and the result for an asynchronous ring will follow.

Assume by way of contradiction that f is non-constant. That is, there are two inputs, X0 and X1, of lengths n0 and n1, for which f(X0)=0, f(X1)=1, respectively. Let the time (number of rounds) after which all processors halt on any of the two inputs be at most t. Then the locality of computing f(X0) is at most t, and so is the locality of computing f(X1). This means (since f is cyclic) the output of each processor depends on the input of itself and of processors at most t hops away. Let Y be some input of length m and let X2 be the input X0^(2t+1)||Y||X1^(2t+1). Then the output of processor 1 when computing f(X0) is identical to the output of processor tn0+1 when computing f(X2), since the inputs of the processor under discussion and processors t hops away from it in the computation of f(X0) are the same as in the computation of f(X2). The same argument applies to the output of processor 1 when computing f(X1) and the output of processor 2tn0+m+tn1+2 when computing f(X2). It follows that two processors that compute f(X2) output different values – a contradiction.

Answer 3

Abstract

A deterministic algorithm cannot break symmetry in an initial configuration in which half of the processors have one of their incident links leading towards the successor processor and their other incident link leading towards the predecessor processor and the other half of the processors in the reverse direction, and achieve an asymmetric markings as output.

Proof

We will prove for a synchronous ring, and the result for an asynchronous ring will follow.

Assume, by way of contradiction, that such algorithm exists for an even n. Let  such that  if processor i has one of its incident links leading to processor (i+1)(mod n) and the other leading to processor (i-1)(mod n), and  otherwise (1<=i<=n).

We first prove, by induction on k, that if there are i, j, k (1<=i,j<=n, k>=0), such that the following 2k+1 equations hold:

Then at round k, processor i enters the same state as processor j:

For k=1, processors i and j receive no messages at round 1. Since all processors are identical, processors i and j start in the same initial state. Therefore, at round 1 they will enter the same state. Assume that if there are i, j, k such that the 2k+1 equation hold then at round k, processor i enters the same state as processor j. If there are i, j, k+1 such that 2k+3 equation hold, it follows that at round k, processor (i-1)(mod n) enters the same state as (j-1)(mod n), processor i enters the same state as processor j, and processor (i+1)(mod n) enters the same state as processor (j+1)(mod n). This means that at round k processor (i-1)(mod n) and processor (j-1)(mod n) send the same messages, and so do processor (i+1)(mod n) and processor (i+1)(mod n). As results, at round k processors i and j receive the same messages from the same directions (from their respective points of view), and therefore processors i and j enter the same state at round k+1.

If X=1^(n/2)||0^(n/2), then the condition holds for i=1,j=n,k=n/2, which means that it holds for any k, including k>t – where t is the locality of the algorithm. Therefore, processors 1 and n will both output the same markings, although their links are opposite.

Answer 4A

Abstract

Such algorithm exists. The algorithm creates segments of nodes with the same orientation. When two nodes that belong to segments with opposite orientation discover that they are neighbors, the node that belongs to the shorter segment switches its orientation and joins the longer segment. The algorithm solves ties using the symmetry breaking markings.

Pseudo Code

 

UPON RECEIVING WAKE

 

if state != awake

then    mark my incident links arbitrarily

        state <-- awake

        left_segment <-- -1

        my_segment <-- 1

        send WAKE on the link marked L

        send RIGHT(my_segment) on the link marked R

 

 

UPON RECEIVING RIGHT(length) ON l

 

if state = awake

then    if l is marked R

        then    if (length > my_segment) OR

                        (

                                (length = my_segment) AND

                                l's head is not towards me

                        )

                then    if (my_segment = 1) AND

                                (

                                        (left_segment > length) OR

                                        (

                                                (left_segment =

                                                        length) AND

                                                l's head is

                                                        towards me

                                        )

                                )

                        then    my_segment <-- left_segment

                                send RIGHT(my_segment) on the link

                                        marked R

                        else    switch L and R markings

                                my_segment <-- length + 1

                                send RIGHT(my_segment) on the link

                                        marked R

        else    left_segment <-- length + 1

else    mark l as L and the other link as R

        my_segment <- length + 1

        send RIGHT(my_segment) on the link marked R

 

Answer 4B

Abstract

When a node invites its right neighbor to join its segment, the node tosses a fair coin and sends the result with the invitation. If the neighbor needs to break symmetry, it tosses its own coin and compares the two results. If they are equal, another round of the coin tossing is performed, until exactly one of the nodes gets "1" and captures the other.

Pseudo Code

 

UPON RECEIVING WAKE

 

if state != awake

then    mark my incident links arbitrarily

        state <-- awake

        left_segment <-- -1

        my_segment <-- 1

        send WAKE on the link marked L

        send RIGHT(my_segment, coin_toss()) on the link marked R

 

 

UPON RECEIVING RIGHT(length, other_coin) ON l

 

my_coin <-- coin_toss()

if state = awake

then    if l is marked R

        then    if (length > my_segment) OR

                        (

                                (length = my_segment) AND

                                (my_coin < other_coin)

                        )

                then    if (my_segment = 1) AND

                                (

                                        (left_segment > length) OR

                                        (

                                                (left_segment =

                                                        length) AND

                                                (my_coin >

                                                        other_coin)

                                        )

                                )

                        then    my_segment <-- left_segment

                                send RIGHT(my_segment, 2)

                                        on the link marked R

                        else    switch L and R markings

                                my_segment <-- length + 1

                                send RIGHT(my_segment, coin_toss())

                                        on the link marked R

                else    if (my_length = length) AND

                           (my_coin = other_coin)

                        then    send TRY_AGAIN on the link marked R

        else    left_segment <-- length + 1

else    mark l as L and the other link as R

úéáú è÷ñè: Continued on the next page
        my_segment <- length + 1

        send RIGHT(my_segment, coin_toss()) on the link marked R

 

 

UPON RECEIVING TRY_AGAIN

 

send RIGHT(my_segment, coin_toss()) on the link marked R

 

Answer 5A

Abstract

Each node sends a token on a non-traversed link. When the node receives the token over that link, the sub-graph that is reachable from that link has been traversed, and the node sends the token on the next non-traversed link, or (if none exists) on the link on which it first received the token. In order to visit all the nodes the token must traverse all the links of the network, since there might have been a node on the center of any non-traversed link, causing the algorithm to fail.

Pseudo Code

 

root

 

if there is a non-traversed

     link l

then state <-- active

     activelink <-- l

     send Token on l

else finished global

 

 

 

any other node

UPON RECEIVING TOKEN ON l

 

if activelink = l

then mark l traversed

     if there is a non-traversed

          link r

     then activelink = r

          send Token on r

     else finished global

else mark l traversed

     send Token on l

UPON RECEIVING TOKEN ON l

 

if parent = nil

then state <-- active

     parent <-- l

if (parent = l) or

     activelink = l

then mark l traversed

     if there is a non-traversed

          link r

     Then activelink <-- r

          send Token on r

     else send Token on parent

else mark l traversed

     send Token on l

Message Complexity

Each node sends exactly one token on each incident link, since tokens are only sent on the following kinds of links:

1.      The parent link: Each node has at most one such link, and if it has one:

1.1.   This link is marked.

1.2.   The node eventually sends a token on that link.

1.3.   The node sends no more tokens afterwards.

2.      Non-marked links: Initially, all the links are not marked. Each node eventually sends a token over each such link, and when it does, that link is marked before the next token is sent.

Time complexity

There is always exactly one token in transit.

Answer 5B

Abstract

Each node first sends the Token on all forward links simultaneously. This prevents neighbors from spending time on traversing links that are not part of the tree.

Pseudo Code

 

root

 

send Token on all links

mark all links as pending

if there are no links

then finished global

 

 

any other node

UPON RECEIVING TOKEN ON l

 

if l is pending

     then mark l as ready

if there are no pending links

then if there is a ready

     link r

     then mark r as traversed

          send Token on r

     else finished global

UPON RECEIVING TOKEN ON l

 

if l is unmarked

then mark l as traversed

     send Token on l

     if parent = nil

     then parent <-- l

else if l = parent

     then mark all unmarked links

               as pending

          send Token on all

               pending links

     else if l is pending

          then mark l as ready

          if there are no pending

               links

          then if there is a

                    ready link r

               then mark l as

                        traversed

                    send Token

                        on r

               else send Token

                        on parent

Answer 5C

Abstract

If a node that has an active link receives the token from a neighbor other than its parent, then the path of active links leads to the sender. The token backtracks on that path, and the nodes it passes through mark this path as a candidate path towards a node that has an active link. If a node that has no active links receives the token, then there is a path of marked links from it to a node that does have an active link.

I have provided a solution assuming that nodes have no unique ids.

Pseudo Code

 

Initially

state <-- unvisited

parent <-- nil

initiator <-- false

relay <-- false

FirstTime <-- true

 

root

 

if there is a non-traversed link l

then state <-- active

     Participated_in_backtracking <-- false

     activelink <-- l

     Token.direction <-- forward

     send Token on activelink

else finished global

 

all nodes

 

úéáú è÷ñè: Continued on the next page
UPON RECEIVING TOKEN ON l

 

if state != active

then Participated_in_backtracking <-- false

     parent <-- l

     pick a non-traversed link r

     activelink <-- r

     send Token on activelink

else If Token.direction = forward

     then Token.direction <-- backtrack

          initiator <-- true

          Token.ParityBitRelayWinner = (0|0|false|false)

          if activelink != nil

          then send Token on activelink

          else send Token on markedlink

     else if activelink != nil

          then if not Participated_in_backtracking AND

                    (l = parent)

               then Token.New_candidate <-- true

                    Participated_in_backtracking <-- true

               if Token.New_candidate

               then markedlink <-- activelink

          if initiator

          then if not Token.Relay AND not FirstTime

               then Token.ParityBitRelayWinner = (0|0|false|true)

                    initiator <-- false

                    relay <-- false

                    FirstTime <-- false

               else Token.ParityBitRelayWinner =

                         (Token.Bit|0|false|false)

          else if relay

               then if Token.winner

                    then initiator <-- false

                         relay <-- false

                         FirstTime <-- false

               else if Token.winner

                    then initiator <-- false

                         relay <-- false

                         FirstTime <-- false

                         Token.New_candidate <-- false

                         if there is a non-traversed link r

                         then activelink <-- r

                              Token.direction = forward

                         else

                              activelink <-- nil

                              if parent = nil

                              then finished global

                              else initiator <-- true

                              Token.ParityBitRelayWinner =

                                   (0|0|false|false)

                    else if not FirstTime AND

                              (parity != Token.parity)

                         then relay <-- true

                              Token.Relay = true

                         else FirstTime <-- false

                              Token.Bit = !Token.Bit

                              parity <-- Token.Bit

          if activelink != nil

          then send Token on activelink

          else send Token on markedlink

Answer 6

Abstract

The initiators are like cores in Gallager's algorithm: each one starts at level zero and sends a traverse token that marks lower level nodes with the initiator's id and level.

A token that encounters a node with a higher level mark vanishes.

A token that encounters a node with the same level mark either waits until the token that marked that node backtracks or proceeds towards that token, depending on the ids. Eventually the two tokens meet and vanish, and the node in which they met becomes an initiator in a higher level.

Exactly one initiator completes a full traversal and issues another traversal to announce its election.

Pseudo Code

 

 

UPON RECEIVING WAKE

 

if owner = nil

then if there is a non-traversed link l

     then level <-- 0

          owner <-- my_id

          Token.level <-- level

          Token.id <-- owner

          active_link <-- l

          send Token on l

 

 

UPON RECEIVING TOKEN ON l

 

mark l traversed

if (level = Token.level) and

     (owner = Token.id) and

     waiting

then Token.level++

     Token.id = my_id

     parent <-- nil

else if (level < Token.level)

     then parent <-- l

if (level < Token.level)

then level <-- Token.level

     owner <-- Token.id

     waiting <-- false

     clear link markings

if level = Token.level

then if owner = Token.id

     then if l != active_link

          then mark l traversed

úéáú è÷ñè: Continued on the next page
               send Token on l

          else mark l traversed

               if there is a non-traversed link r

               then active_link <-- r

                    send Token on r

               else if parent != nil

                    then send Token on parent

                         if Token.leader then

                              finished - The leader is owner

                    else clear link markings

                         if Token.leader or

                              there are no incident links

                         then finished - I am the leader

                         else Token.leader <-- true

                              choose a non-traversed link s

                              active_link <-- s

                              send Token on s

     else if (owner > Token.id) OR chased

          then waiting <-- true

          else Token.chased_id <-- owner

               send Token on active_link