adding functions for displaying graphs of propagator networks
[propagator.git] / propagator.org
blob4821fdc9b2fcef9f06bda11ba20e13e8bcfc7d96
1 #+TITLE: Concurrent Propagator System
2 #+OPTIONS: num:nil ^:nil
3 #+LaTeX_CLASS: normal
5 * code
6   :PROPERTIES:
7   :tangle:   src/propagator.clj
8   :END:
9 #+begin_src clojure
10   (ns
11       #^{:author "Eric Schulte",
12          :license "GPLV3",
13          :doc "Simple concurrent propagator system."}
14     propagator
15     (:use clojure.contrib.repl-utils clojure.contrib.math))
16   
17   (defmacro cell "Define a new cell."
18     [name state]
19     `(def ~name (agent ~state)))
20   
21   (defmacro propagator "Define a new propagator."
22     [name in-cells out-cells & body]
23     `(do
24        (defn ~(with-meta name
25                 (assoc (meta name)
26                   :in-cells in-cells :out-cells out-cells))
27          ~in-cells ~@body)
28        (doseq [cell# ~in-cells] (add-neighbor cell# ~name))
29        ~name))
30   
31   (defn set-cell "Set the value of a cell" [cell value]
32     (send cell (fn [_] value)))
33   
34   (defmacro run-propagator
35     "Run a propagator, first collect the most recent values from all
36   cells associated with the propagator, then evaluate."
37     [propagator]
38     `(let [results# (apply ~propagator (map deref (:in-cells ^#'~propagator)))]
39        (doseq [cell# (:out-cells ^#'~propagator)]
40          (when (not (= @cell# results#))
41            (send cell# (fn [_#] results#))))
42        results#))
43   
44   (defmacro add-neighbor "Add a neighbor to the given cell."
45     [cell neighbor]
46     `(add-watcher
47       ~cell :send
48       (agent nil :validator (fn [_#] (do (future (run-propagator ~neighbor)) true)))
49       (fn [_# _#])))
50 #+end_src
51 * extensions
52 ** graphs of the propagator network
53 #+begin_src clojure
54   (use 'vijual)
55   (import '(javax.swing JFrame JPanel)
56           '(java.awt Color Graphics)
57           '(java.awt.image BufferedImage))
58   
59   (def dim [300 300])
60   
61   (defn view "Display a graph generated by vijual" [img]
62     (let [mult 1.5
63           width (* (.getWidth img) mult)
64           height (* (.getHeight img) mult)
65           offset 50
66           frame (JFrame.)
67           panel (doto (proxy [JPanel] []
68                         (paint [g]
69                                (.drawImage g img offset offset nil))))]
70       (doto frame (.add panel) .pack (.setSize (+ offset width) (+ offset height)).show)))
71 #+end_src
73 * usage
74 ** doubling a number -- simplest
75 #+begin_src clojure
76   (cell in 0)
77   (cell out 0)
78   (propagator doubler [in] [out] (* 2 in))
79   ;; then any updates to in
80   (set-cell in 1)
81   ;; will propagate to out
82   @out
83 #+end_src
85 ** square roots -- heron
86 results in errors...
88 #+begin_src clojure
89   (cell guess 1)
90   (cell x 9)
91   (cell done false)
92   (cell margin 0.1)
93   
94   (propagator enough [x guess] [done]
95     (if (< (abs (- (* guess guess) x)) @margin) true false))
96   
97   (propagator heron [x guess] [guess]
98     (if (enough x guess)
99       guess
100       (/ (+ guess (/ x guess)) 2.0)))
101 #+end_src
103 * notes
104 ** look at mutable data stores
105 - http://clojure.org/agents
106 - http://clojure.org/atoms
107 - http://clojure.org/refs
109 most definitely will use agents, functions to set their values are
110 applied to them with send (or send-off if potentially I/O bound), they
111 support validators, and they can be set to run actions (i.e. alert
112 propagators) as part of their update cycle (with add-watcher).
114 ** design to permit distribution across multiple machines
115 it should be possible to wrap these mutable items including
116 - network connections from other machines
117 - hardware (timers, I/O devices, etc...)
119 in cells, so that the propagator system remains "pure"