;;;; -*- Scheme -*- ;; ;; Beacons example for HLSIM ;; ;; David DeRoure June 12 1997, revised Sep 10 1997 ;; dder@martigny.ai.mit.edu ;; ;; This file should be compiled with (cps "beacons1") followed by ;; (cbf "beacons1"). It uses definitions in beacons1d.scm. See ;; beacons1s.scm for simulation setup. See the HLSIM documentation ;; for further details. ;; ;; "Source" processors each transmit a message with an id, a color ;; and a hop count. Each waits for a period of time and then transmits ;; another message with a different id, color and smaller hop count. ;; ;; All of the processors rebroadcast (propagate) received messages, with ;; the same id and color but with the hop count decremented by 1, UNLESS ;; (a) the element has already rebroadcast that message, or (b) the hop ;; count in the received message is 0. The color of the element changes ;; to the color of the message it is rebroadcasting. When a processor ;; detects a collision, it flashes white. ;; ;; The result is a series of colored regions emanating from the originating ;; processors, of decreasing size. If the average neighborhood density ;; is high enough (e.g. > 10), a predictable "target" pattern emerges. ;; With lower density the behavior is less predictable, especially if ;; the time interval is such that one message can catch up with the ;; previous one. ;; ;; To see the neighborhood density effects in one simulation, try using ;; a simulation with mean neighborhood density that varies across the ;; space, e.g. by using (expt (random 1.0) 0.4) in place of (random 1.0) ;; for X and/or Y in make-sim/1 (you can do this with make-sim/f). (declare (usual-integrations)) ;; Every processor has an id (not the processor number, as that would ;; be cheating) (define my-processor-id (random 1000000)) ;; The make-new-message-id procedure, used only by sources, generates the ;; next message id. On any one source, each id returned by this procedure ;; must be unique, and this is achieved here with a sequence of contiguous ;; integers. Instead of making id "global" (as with my-processor-id above ;; or messages-received below), a closure is used (to show this works too). (define make-new-message-id (let ((id 0)) (lambda () (set! id (1+ id)) id))) ;; When a message arrives, the messages-received table is ;; checked by new-message? to see if a message from the same ;; source and with the same id has arrived before. (define messages-received (make-table)) ;; This processor should originate messages if its processor ;; number is in the list of source processors. This list ;; is kept in a slot in the simulation, so that the numbers can ;; be set outside this file (where the simulation is set up) - see ;; comments at end for example. (define (source?) (member (processor-number) (simulation.get (the-simulation) 'source-processors))) ;; The initial color of this processor depends whether it's a source. ;; (If sources are also propagators, they will often lose their color ;; during the simulation.) (define my-color (if (source?) "cyan" "blue")) ;; The code for sources. It sends 4 messages, each ;; 5000 time units apart, with hop counts of 36, 25, 16 and 9. (define (source) (broadcast (make-message my-processor-id (make-new-message-id) 36 "orange")) (wait (make-timeout-event 5000)) (broadcast (make-message my-processor-id (make-new-message-id) 25 "green")) (wait (make-timeout-event 5000)) (broadcast (make-message my-processor-id (make-new-message-id) 16 "red")) (wait (make-timeout-event 5000)) (broadcast (make-message my-processor-id (make-new-message-id) 9 "yellow"))) ;; The loop for propagators (which will be every processor, including the ;; sources). Increasing the delay after a collision to more that 100 ;; can cause some subsequent messages to be ignored; using a random ;; number can avoid the pulsating effect. (define primitive-message-event (make-event)) (define (propagator-loop) (select (global-timeout 'done) (primitive-message-event => (lambda (message) (event.clear! primitive-message-event) (if (eq? message 'collision) (begin (color-me "white") (wait (make-timeout-event (random 300))) (color-me my-color)) (if (and (new-message? message messages-received) (> (message-ttl message) 0)) (begin (broadcast (make-message (message-source message) (message-id message) (-1+ (message-ttl message)) (message-color message))) (set! my-color (message-color message)) (color-me my-color)))) (propagator-loop))))) ;; Run the loop (define global-timeout (make-timeout-event 25000)) (color-me my-color) ;(if (source?) ; (source) ; (propagator-loop)) ;; To make the sources behave as propagators also, use (if (source?) (parallel (source) (propagator-loop)) (propagator-loop)) ;; end of beacons1.scm