Level 1 Counting machines by message passing
A cluster of machines is wired as a tree. Each machine knows only its own id, its parent's id (None for the root) and its children's ids. A machine can talk only to its parent and its children, and only by sending messages that are delivered asynchronously: later, in any order, interleaved with everyone else's messages.
Write the class that runs on each machine:
class Node:
def __init__(self, node_id, parent, children, network): ...
def receive_message(self, from_id, message): ...
def tick(self): ... # used from level 3; leave it empty for now
The test harness gives you network, which has two methods:
network.send(self.node_id, to_id, message)queues a message for a neighbour. The message must be astr, and you choose the format. Sending doesn't deliver anything right away. The harness delivers queued messages one at a time, in a random order, by callingreceive_message(from_id, message)on the receiver.network.report(self.node_id, result)announces a final answer. It's the "print" of this problem.
Task. The harness starts a count by calling receive_message(None, "count") on the root (from_id=None means the message came from outside the cluster). Eventually the root must call network.report(root_id, n) exactly once, where n is the number of machines. No other machine reports.
- Every machine counts itself plus whatever its children report back. A leaf answers straight away.
- A request going down and an answer coming up are different kinds of messages, so encode the difference in your format.
- A count can be started again after one has finished, and it must give the right answer again. Reset or scope your state.
r receive_message(None, "count") at r
/ \ r -> a, r -> b (requests)
a b b -> x (request)
| a -> r "1"; x -> b "1"; b -> r "2" (answers, in any order)
x r reports 4
A node may have tens of thousands of children, so tracking who has answered must be O(1) per answer.