Compare commits

...

3 commits

Author SHA1 Message Date
02d2a56931 ensure successfully functioning of simulate! with one propagator 2024-04-04 18:06:39 -04:00
d97bcfa82c add doc strings to cell and prop-net 2024-04-04 17:41:27 -04:00
369fd89e62 refactor propagator to remove remaining references to cell
now expects inputs and outputs to be lambdas that call cell/content and
cell/add-content! respectively
2024-04-04 12:38:49 -04:00
3 changed files with 92 additions and 57 deletions

View file

@ -5,10 +5,14 @@
(= content nothing)) (= content nothing))
(defprotocol ICell (defprotocol ICell
(neighbors [this]) (neighbors [this]
(content [this]) "returns all propagators the cell serves as input to")
(add-content! [this increment]) (content [this]
(new-neighbor! [this new-neighbor])) "returns current content")
(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
@ -34,7 +38,6 @@
(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,7 +3,6 @@
[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* [] #{})
@ -12,11 +11,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
(alerted-propagators [this] (get-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]
@ -30,15 +29,16 @@
;; 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
(add-propagator! [this func] propagators, if any")
"") (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,8 +52,6 @@
(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
@ -61,8 +59,9 @@
all-propagators all-propagators
propagators-ever-alerted] propagators-ever-alerted]
IPropNet IPropNet
;; introspect methods INFO - complete ;; introspect methods INFO - complete
(alerted-propagators [net] (deref-get net :alerted-propagators)) (get-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))
@ -70,8 +69,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] (deref-get (propagators net) (propagator [net prop-key] (prop-key (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))
@ -90,9 +89,23 @@
{: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]
;; (add-neighbor-to-cell! [this cell-key propagator]) (swap! (:all-propagators this) assoc prop-key (p/function->propagator func)))
;; (add-output-to-propagator! [this prop-key cell]) (add-neighbor-to-cell! [this cell-key prop-key]
;; 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))
@ -101,9 +114,14 @@
(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
@ -124,7 +142,13 @@
(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,45 +1,53 @@
(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 [this]) (inputs
(output [this]) [this]
(add-input! [this input-cell]) "returns the functions to be called to retrieve the propagators inputs")
(add-output! [this output-cell]) (output
(apply! [this])) [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
[inputs output function] [input-getters output-setter function]
IPropagator IPropagator
(inputs [this] (deref (:inputs this))) (inputs [this] (deref (:input-getters this)))
(output [this] (deref (:output this))) (output [this] (deref (:output-setter this)))
(add-input! [this input-cell] (add-input! [this input-func]
;; this is some java shenanigans prop_net.cell.Cell (do (swap! (:input-getters this) conj input-func)
(when (not (instance? prop_net.cell.Cell input-cell)) :ok))
(throw (ex-info "Input must be a cell" {:input input-cell}))) (add-output! [this output-set!]
(let [old-inputs (deref (:inputs this))] (if (no-output? (output this))
(do (swap! (:inputs this) conj input-cell) (do (reset! (:output-setter this) output-set!)
: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 already set" {:propagator this :conflict output})))) (throw (ex-info "Output cell already present" {:propagator this :conflict output}))))
;; apply will call output with the result of calling :function with all inputs
(apply! [this] (apply! [this]
(let [input-cells (deref (:inputs this)) (let [input-getters (vec (inputs this))
output-cell (deref (:outputs this))] output-set! (output this)]
(c/add-content! output-cell (apply (:function this) (output-set! (apply (:function this)
(map c/content input-cells)))))) ;; there might be a cleaner way to apply each lookup?
(map (fn [lookup] (lookup))
input-getters))))))
(defn function->propagator (defn function->propagator
[func] [func]
(map->Propagator (map->Propagator
{:inputs (atom #{}) {:input-getters (atom #{})
:output (atom c/nothing) :output-setter (atom no-output)
:function func})) :function func}))