|
1 | 1 | (ns net.n01se.hassle.xfnet
|
| 2 | + (:require [net.n01se.hassle.net :as net]) |
2 | 3 | (:require [net.n01se.hassle.transducers :as t]))
|
3 | 4 |
|
4 |
| -(defn normalize-inputs [inputs] |
5 |
| - (if (set? inputs) |
6 |
| - (mapcat normalize-inputs inputs) |
7 |
| - (if (nil? inputs) |
8 |
| - (list) |
9 |
| - (list inputs)))) |
10 |
| - |
11 |
| -(defn normalize-net |
12 |
| - [label trees] |
13 |
| - (letfn [(walk-trees [net-map trees super-path] |
14 |
| - (reduce |
15 |
| - (fn [net-map [tree-type id sub-trees xf label]] |
16 |
| - (let [node-path [tree-type id]] |
17 |
| - (cond-> net-map |
18 |
| - (not (nil? xf)) |
19 |
| - (assoc-in (conj node-path :xf) xf) |
20 |
| - |
21 |
| - (not (nil? label)) |
22 |
| - (assoc-in (conj node-path :label) label) |
23 |
| - |
24 |
| - (not (or (= tree-type :output) (nil? super-path))) |
25 |
| - (-> (update-in (conj node-path :outputs) (fnil conj #{}) super-path) |
26 |
| - (update-in (conj super-path :inputs) (fnil conj #{}) node-path)) |
27 |
| - |
28 |
| - true |
29 |
| - (walk-trees sub-trees node-path)))) |
30 |
| - net-map |
31 |
| - (normalize-inputs trees)))] |
32 |
| - (walk-trees {:label label} trees nil))) |
33 |
| - |
34 |
| -(defn postwalk [net-xf roots update-fn] |
35 |
| - (let [orig-net-map (net-xf) |
36 |
| - kids (case roots :input :outputs :inputs) |
37 |
| - root-paths (for [k (-> orig-net-map roots keys)] |
38 |
| - [roots k])] |
39 |
| - |
40 |
| - (letfn [(update-node [net-map path] |
41 |
| - (update-in |
42 |
| - net-map path |
43 |
| - (fn [node] |
44 |
| - (update-fn |
45 |
| - path node |
46 |
| - (for [kid-path (kids node)] |
47 |
| - (get-in net-map kid-path)))))) |
48 |
| - |
49 |
| - (visit-node [net-map path] |
50 |
| - (if (-> net-map meta ::visited (contains? path)) |
51 |
| - net-map |
52 |
| - (-> net-map |
53 |
| - (vary-meta update ::visited conj path) |
54 |
| - (visit-nodes (get-in net-map (conj path kids))) |
55 |
| - (update-node path)))) |
56 |
| - |
57 |
| - (visit-nodes [net-map paths] |
58 |
| - (reduce visit-node net-map paths))] |
59 |
| - |
60 |
| - (-> orig-net-map |
61 |
| - (vary-meta assoc ::visited #{}) |
62 |
| - (visit-nodes root-paths))))) |
63 |
| - |
64 |
| -(defn assert-no-outputs [inputs] |
65 |
| - (assert (->> inputs normalize-inputs (map first) (every? #{:input :node})) |
66 |
| - "Output nodes are not allowed as inputs") |
67 |
| - inputs) |
68 |
| - |
69 | 5 | (defn match-tags
|
70 | 6 | ([xf-map xs] (sequence (match-tags xf-map) xs))
|
71 | 7 | ([xf-map] (t/multiplex (map (fn [[k xf]]
|
|
77 | 13 | ([net-xf xs] (sequence (make-net-xf net-xf) xs))
|
78 | 14 | ([net-xf]
|
79 | 15 | (-> net-xf
|
80 |
| - (postwalk |
| 16 | + (net/postwalk |
81 | 17 | :input
|
82 | 18 | (fn [[node-type node-id] {:keys [xf inputs outputs]} output-xfs]
|
83 | 19 | (let [output-xfs' (if (empty? output-xfs) [identity] output-xfs)
|
|
93 | 29 | (defn net
|
94 | 30 | ([label net-tree xs] (sequence (net net-tree) xs))
|
95 | 31 | ([label net-tree]
|
96 |
| - (let [net-map (normalize-net label net-tree)] |
| 32 | + (let [net-map (net/normalize-net label net-tree)] |
97 | 33 | ^:xfn
|
98 | 34 | (fn transducer
|
99 | 35 | ([] net-map)
|
100 | 36 | ([rf] ((make-net-xf transducer) rf))))))
|
101 | 37 |
|
102 |
| -(defn input [k] (list :input k #{})) |
103 |
| -(defn output [k inputs] (list :output k (assert-no-outputs inputs))) |
104 |
| - |
105 |
| -(defn node* [label xf inputs] |
106 |
| - (list :node |
107 |
| - (gensym 'n) |
108 |
| - (assert-no-outputs inputs) |
109 |
| - xf |
110 |
| - label)) |
111 |
| - |
112 | 38 | (defmacro node [xf inputs]
|
113 | 39 | (let [label (if (sequential? xf)
|
114 | 40 | (if (symbol? (first xf))
|
|
122 | 48 | (str xf))]
|
123 | 49 | `(node* '~label ~xf ~inputs)))
|
124 | 50 |
|
125 |
| -(defn embed [net-xf input-map] |
126 |
| - (-> net-xf |
127 |
| - (postwalk |
128 |
| - :output |
129 |
| - (fn [[node-type node-id] {xf :xf label :label} input-xfs] |
130 |
| - (condp = node-type |
131 |
| - :input (input-map node-id) |
132 |
| - :node (node* label xf (set input-xfs)) |
133 |
| - :output (set input-xfs)))) |
134 |
| - :output)) |
135 |
| - |
136 | 51 | (defrecord Passive [x]
|
137 | 52 | clojure.lang.IDeref
|
138 | 53 | (deref [_] x))
|
|
157 | 72 | ;; The nodes defined here are mislabeled for readability. Short term fix.
|
158 | 73 | ;; Longer term, join should be represented as a subnet.
|
159 | 74 | (let [active-inputs? (mapv active? inputs)]
|
160 |
| - (node* |
| 75 | + (net/node* |
161 | 76 | 'join
|
162 | 77 | (t/join-index-tags active-inputs?)
|
163 | 78 | (->> inputs
|
164 | 79 | (map active)
|
165 | 80 | (map-indexed
|
166 |
| - #(node* (if (active-inputs? %1) 'active 'passive) |
167 |
| - (t/tag %1) |
168 |
| - %2)) |
| 81 | + #(net/node* |
| 82 | + (if (active-inputs? %1) 'active 'passive) |
| 83 | + (t/tag %1) |
| 84 | + %2)) |
169 | 85 | set))))
|
170 | 86 |
|
171 |
| -;; printing/debugging |
172 |
| -(defn compact-net-map [net-map] |
173 |
| - (letfn [(compact-paths [paths] (map second paths))] |
174 |
| - (concat |
175 |
| - (map (fn [[k {:keys [outputs]}]] |
176 |
| - [k :outputs (compact-paths outputs)]) |
177 |
| - (:input net-map)) |
178 |
| - (map (fn [[k {:keys [outputs inputs]}]] |
179 |
| - [k :outputs (compact-paths outputs) :inputs (compact-paths inputs)]) |
180 |
| - (:node net-map)) |
181 |
| - (map (fn [[k {:keys [inputs]}]] |
182 |
| - [k :inputs (compact-paths inputs)]) |
183 |
| - (:output net-map))))) |
184 |
| - |
185 |
| -(defn pr-net [net-xf] |
186 |
| - (compact-net-map (net-xf))) |
| 87 | +;; Re-export these for now |
| 88 | +(def input net/input) |
| 89 | +(def output net/output) |
| 90 | +(def node* net/node*) |
| 91 | +(def embed net/embed) |
| 92 | +(def postwalk net/postwalk) |
0 commit comments