Compare commits

..

No commits in common. "02d2a569312a14ad33c9eff95b983715b0a5af38" and "35e86859e80b3cdd6bb1b9fe706f15d3329ec2a7" have entirely different histories.

3 changed files with 57 additions and 92 deletions

View file

@ -5,14 +5,10 @@
(= content nothing)) (= content nothing))
(defprotocol ICell (defprotocol ICell
(neighbors [this] (neighbors [this])
"returns all propagators the cell serves as input to") (content [this])
(content [this] (add-content! [this increment])
"returns current content") (new-neighbor! [this new-neighbor]))
(add-content! [this increment]
"adds content to cell if none is present")
(new-neighbor! [this new-neighbor]
"adds a new propagator as a neighbor to the cell"))
(defrecord Cell (defrecord Cell
[neighbors [neighbors
@ -38,6 +34,7 @@
(let [old-neighbors (deref (:neighbors this))] (let [old-neighbors (deref (:neighbors this))]
(do (swap! (:neighbors this) conj new-neighbor) (do (swap! (:neighbors this) conj new-neighbor)
;; add input ;; add input
;;(alert-propagator new-neighbor)
:ok)))) :ok))))
;; returns an initialized cell ;; returns an initialized cell

View file

@ -3,6 +3,7 @@
[prop-net.cell :as c])) [prop-net.cell :as c]))
;; currently not implementing abort semantics ;; currently not implementing abort semantics
(defn- alerted-propagators* [] #{}) (defn- alerted-propagators* [] #{})
(defn- cells* [] {}) (defn- cells* [] {})
(defn- propagators-ever-alerted* [] #{}) (defn- propagators-ever-alerted* [] #{})
@ -11,11 +12,11 @@
(defprotocol IPropNet (defprotocol IPropNet
"A Naive Scalar Propagation Network. Add Cells and Propagators, wire them "A Naive Scalar Propagation Network. Add Cells and Propagators, wire them
together and run. Cells should update based on wiring" together and run. Cells should update based on wiring"
;; -- introspect methods ;; introspect methods
(get-alerted-propagators [this] (alerted-propagators [this]
"returns the keys of all propagators to be alerted on next scheduler cycle") "")
(propagators-ever-alerted [this] (propagators-ever-alerted [this]
"returns the keys of all propagators alerted since last scheduler initialization") "")
(get-cells [this] (get-cells [this]
"returns hash-map of all cells in network") "returns hash-map of all cells in network")
(propagators [this] (propagators [this]
@ -29,16 +30,15 @@
;; mutation methods ;; mutation methods
(add-cell! [this cell-key] (add-cell! [this cell-key]
"create a cell associated with a given key") "")
(add-content-to-cell! [this cell-key content] (add-content-to-cell! [this cell-key content]
"add content to a cell at the given key, alerting the cell's neighboring "")
propagators, if any") (add-propagator! [this func]
(add-propagator! [this prop-key func] "")
"create a propagator from the given function and associate it with the given key")
(add-neighbor-to-cell! [this cell-key prop-key] (add-neighbor-to-cell! [this cell-key prop-key]
"give the cell of the given cellkey a new neighbor of the given propagator key") "")
(add-output-to-propagator! [this prop-key cell-key] (add-output-to-propagator! [this prop-key cell-key]
"wire the output of a given propagator to the set-content! function of a given cell") "")
;; run methods ;; run methods
(initialize-scheduler! [this] (initialize-scheduler! [this]
@ -52,6 +52,8 @@
(defn- deref-get [rec key] (deref (key rec))) (defn- deref-get [rec key] (deref (key rec)))
;; TODO re-implementing with reference to PropNet
;; children should not make calls on each other, only return things to do?
(defrecord PropNet (defrecord PropNet
[alerted-propagators [alerted-propagators
last-value-of-run last-value-of-run
@ -59,9 +61,8 @@
all-propagators all-propagators
propagators-ever-alerted] propagators-ever-alerted]
IPropNet IPropNet
;; introspect methods INFO - complete ;; introspect methods INFO - complete
(get-alerted-propagators [net] (deref-get net :alerted-propagators)) (alerted-propagators [net] (deref-get net :alerted-propagators))
(propagators-ever-alerted [net] (deref-get net :propagators-ever-alerted)) (propagators-ever-alerted [net] (deref-get net :propagators-ever-alerted))
(get-cells [net] (deref-get net :cells)) (get-cells [net] (deref-get net :cells))
(propagators [net] (deref-get net :all-propagators)) (propagators [net] (deref-get net :all-propagators))
@ -69,8 +70,8 @@
(cell-key (get-cells net))) (cell-key (get-cells net)))
(cell-content [net cell-key] (deref-get (get-cell net cell-key) (cell-content [net cell-key] (deref-get (get-cell net cell-key)
:content)) :content))
(propagator [net prop-key] (prop-key (propagators net))) (propagator [net prop-key] (deref-get (propagators net)
prop-key))
;; mutation methods ;; mutation methods
(add-cell! [net cell-key] (add-cell! [net cell-key]
(swap! (:cells net) assoc cell-key (c/make-cell)) (swap! (:cells net) assoc cell-key (c/make-cell))
@ -89,23 +90,9 @@
{:cell cur-cell}))) {:cell cur-cell})))
(catch Exception e (catch Exception e
(prn e))))) (prn e)))))
(add-propagator! [this prop-key func] ;; (add-propagator! [this prop-key func])
(swap! (:all-propagators this) assoc prop-key (p/function->propagator func))) ;; (add-neighbor-to-cell! [this cell-key propagator])
(add-neighbor-to-cell! [this cell-key prop-key] ;; (add-output-to-propagator! [this prop-key cell])
;; cell only needs to have its neighbors
;; c/new-neighbor! prop-key
(c/new-neighbor! (get-cell this cell-key) prop-key)
;; propagator needs to have the c/content wrapped in a lambda and have that added to its inputs
(p/add-input! (propagator this prop-key) (fn [] (c/content (get-cell this cell-key))))
:ok
)
(add-output-to-propagator! [this prop-key cell-key]
(let [output-setter
;; need to add content from the net in order to alert propagators
;; further down the network
(fn [new-content] (add-content-to-cell! this cell-key new-content))]
(p/add-output! (propagator this prop-key)
output-setter)))
;; run methods ;; run methods
(last-value-of-run [net] (deref-get net :last-value-of-run)) (last-value-of-run [net] (deref-get net :last-value-of-run))
@ -114,14 +101,9 @@
(reset! (:last-value-of-run this) done) (reset! (:last-value-of-run this) done)
(reset! (:propagators-ever-alerted this) propagators-ever-alerted*) (reset! (:propagators-ever-alerted this) propagators-ever-alerted*)
:ok) :ok)
(simulate! [net] ;; (simulate! [net])
(run! (fn [prop-key]
(do (swap! (:alerted-propagators net) disj prop-key)
(p/apply! (propagator net prop-key))))
(vec (get-alerted-propagators net))))
;; (halt! [net]) ;; (halt! [net])
) )
;; returns a propnet ;; returns a propnet
(defn make-prop-net [] (defn make-prop-net []
(map->PropNet (map->PropNet
@ -142,13 +124,7 @@
(add-cell! this-net :5) (add-cell! this-net :5)
(add-cell! this-net :c*9) (add-cell! this-net :c*9)
(add-cell! this-net :9) (add-cell! this-net :9)
(add-cell! this-net :32+5)
(add-propagator! this-net :plusser +)
(add-neighbor-to-cell! this-net :32 :plusser)
(add-content-to-cell! this-net :32 32) (add-content-to-cell! this-net :32 32)
(add-neighbor-to-cell! this-net :5 :plusser)
(add-content-to-cell! this-net :5 5)
(add-output-to-propagator! this-net :plusser :32+5)
this-net)) this-net))
(defn -main [] (defn -main []

View file

@ -1,53 +1,45 @@
(ns prop-net.propagator) (ns prop-net.propagator
(:require [prop-net.cell :as c]))
(def ^:private no-output [])
(defn- no-output? [output]
(= output no-output))
(defprotocol IPropagator (defprotocol IPropagator
(inputs (inputs [this])
[this] (output [this])
"returns the functions to be called to retrieve the propagators inputs") (add-input! [this input-cell])
(output (add-output! [this output-cell])
[this] (apply! [this]))
"returns the function to be called to set the result content of output cell")
(add-input!
[this input-lookup]
"add an input function to retrieve the content of a cell")
(add-output!
[this output-set!]
"add an output function to set the content of a cell")
(apply!
[this]
"applies the propagator function to results of all input-lookup
calls and calls the output function with the result"))
(defrecord Propagator (defrecord Propagator
[input-getters output-setter function] [inputs output function]
IPropagator IPropagator
(inputs [this] (deref (:input-getters this))) (inputs [this] (deref (:inputs this)))
(output [this] (deref (:output-setter this))) (output [this] (deref (:output this)))
(add-input! [this input-func] (add-input! [this input-cell]
(do (swap! (:input-getters this) conj input-func) ;; this is some java shenanigans prop_net.cell.Cell
:ok)) (when (not (instance? prop_net.cell.Cell input-cell))
(add-output! [this output-set!] (throw (ex-info "Input must be a cell" {:input input-cell})))
(if (no-output? (output this)) (let [old-inputs (deref (:inputs this))]
(do (reset! (:output-setter this) output-set!) (do (swap! (:inputs this) conj input-cell)
:ok)))
(add-output! [this output-cell]
;; TODO for some reason instance? is not evaluating to true here, but types should really be checked
;; from the net itself
;; (when (not (instance? prop_net.cell.Cell output-cell))
;; (throw (ex-info "Output must be a cell" {:output output-cell
;; :type (type output-cell)})))
(if (c/nothing? (deref (:output this)))
(do (reset! (:output this) output-cell)
:ok) :ok)
(throw (ex-info "Output cell already present" {:propagator this :conflict output})))) (throw (ex-info "Output already set" {:propagator this :conflict output}))))
;; apply will call output with the result of calling :function with all inputs
(apply! [this] (apply! [this]
(let [input-getters (vec (inputs this)) (let [input-cells (deref (:inputs this))
output-set! (output this)] output-cell (deref (:outputs this))]
(output-set! (apply (:function this) (c/add-content! output-cell (apply (:function this)
;; there might be a cleaner way to apply each lookup? (map c/content input-cells))))))
(map (fn [lookup] (lookup))
input-getters))))))
(defn function->propagator (defn function->propagator
[func] [func]
(map->Propagator (map->Propagator
{:input-getters (atom #{}) {:inputs (atom #{})
:output-setter (atom no-output) :output (atom c/nothing)
:function func})) :function func}))