Proper Treatment 正當作法/ cs504/ 2008/ Modular, interactive streams of discrete events
2009-01-18 23:57

Below is a function to print the numbers at the fringe of a tree.

(define (print-fringe tree)
  (if (number? tree)
      (begin (write tree)
             (newline))
      (begin (print-fringe (first tree))
             (print-fringe (second tree)))))

Below is a function to sum the numbers at the fringe of a tree.

(define (sum-tree tree)
  (if (number? tree)
      tree
      (+ (sum-tree (first tree))
         (sum-tree (second tree)))))

The organization of both functions is directed in the same way by the definition of the type of trees: “tree = number + tree × tree”. (Some people write “=” as “::=”. Some people write “+” as one of “∨|∪⊎⊍⊔⨿”. Some people write “×” as “∧” or just juxtaposition.)

Our transformation from a fell-swoop program to a state-transition program (put differently, from a program to an abstract state machine) is uncreative about how to represent the state: a state is always a list of procedure calls yet to return. The advantage of this uncreativity is that the transformation is systematic and always works. But another representation of states, accompanied by the corresponding transition function, can be more efficient. For example, if we try to track the recursive calls to the sum-list function below using the systematic transformation, the state would consist of two lists of numbers: the current argument l and the pending numbers (first l) waiting for +.

(define (sum-list l)
  (if (empty? l)
      0
      (+ (first l)
         (sum-list (rest l)))))

Being creative, we can represent the latter list of numbers more efficiently by its sum instead.

Your fringe-enumerating state-transition program should consume the same amount of time and space as your fringe-enumerating fell-swoop program. (By “same” I mean within a linear constant factor.) Does it? Try randomly generated large trees of various shapes. (The procedure for randomly generating a tree, like the procedure for enumerating the fringe of a tree and like most other operations on trees, should be organized as directed by the tree type.)

For mental hygiene, distinguish between trees and states. Along with their transition function, states are an abstract data type: all you can do to a state is to pass it to the transition function. A state along with its transition function can be thought of as a stream. Operations such as concatenation and interleaving can operate on streams no matter how they represent states internally. The control flow among streams and the type polymorphism of stream operations illustrate a general notion of modularity. The type of a stream characterizes the set of interaction transcripts allowed.

The general algorithm for discrete event simulation can be explained in two ways, depending on whether there are coherent threads (subsequences) of events over time that can be thought of as processes.

  1. Keep track of a set of running processes. In each round, query each running process to find out when its next event happens. Execute the earliest next event, which changes the state (and thus next event) of that process and perhaps other processes as well.

  2. Keep track of a set, or rather a queue sorted by time, of pending events. In each round, remove the earliest pending event and execute it, which may create and/or remove pending events.

Note that the set of running processes or pending events is not the transcript of events that the simulation actually executes.

Because the simulation is generative, it forces us to specify the causal structure of how the world works. For example, it forces us to answer the question “will the party end early if the police comes?” by imagining, for instance, that the police comes to arrest the person responsible for turning the lights on to end the party, thereby actually making the party end later than originally scheduled.

A discrete simulation can be generalized to a hybrid simulation (hybrid, that is, between discrete and continuous) using calculus and computational geometry algorithms.