csys: clean-up, use comprehensions instead of reduce; + synapse operation: multiply

This commit is contained in:
Helmut Merz 2026-05-20 08:02:03 +02:00
parent b5f78355fe
commit 998be76e34
3 changed files with 20 additions and 24 deletions

View file

@ -29,7 +29,8 @@ defmodule Scopes.CSys do
end end
def forward(msg, scope) do def forward(msg, scope) do
Enum.reduce(syns(scope), false, fn s, _acc -> s.(msg); true end) for s <- syns(scope), reduce: false, do: (_acc -> s.(msg))
#Enum.reduce(syns(scope), false, fn s, _acc -> s.(msg); true end)
end end
def create(_msg, scope = {state, proc, _syns, env}) do def create(_msg, scope = {state, proc, _syns, env}) do
@ -40,15 +41,13 @@ defmodule Scopes.CSys do
def connect(msg, {state, proc, syns, env}) do def connect(msg, {state, proc, syns, env}) do
data = Shape.data(msg) data = Shape.data(msg)
op = data[:op] || noop() op = data[:op] || []
syn = synapse(data[:target], op, 0) syn = synapse(data[:target], op, 0)
update({state, proc, [syn | syns], env}) update({state, proc, [syn | syns], env})
end end
# synapse operations # synapse operations
def noop(), do: fn msg -> msg end
def filter_head(pat) do def filter_head(pat) do
fn msg -> if List.starts_with?(Shape.head(msg), pat), do: msg end fn msg -> if List.starts_with?(Shape.head(msg), pat), do: msg end
end end
@ -83,13 +82,11 @@ defmodule Scopes.CSys do
# helpers # helpers
def compose(ops) do def compose(ops) do
fn msg -> Enum.reduce(ops, msg, &bind/2) end fn msg ->
end for op <- ops, reduce: msg do
nil -> nil
defp bind(op, val) do val -> op.(val)
case val do end
nil -> nil
val -> op.(val)
end end
end end
end end

View file

@ -4,13 +4,14 @@ alias Scopes.CSys
alias Scopes.Shape alias Scopes.Shape
defmodule State do defmodule State do
defstruct [:value, :threshold, :stage, :prog] defstruct [:value, :threshold, :bias, :stage, :prog]
end end
def prepare(prog, args) do def prepare(prog, args) do
state = %State{ state = %State{
value: args[:value], value: args[:bias],
threshold: args[:threshold], threshold: args[:threshold],
bias: args[:bias],
stage: :initial, stage: :initial,
prog: prog prog: prog
} }
@ -43,7 +44,7 @@ alias Scopes.CSys
{stages, transitions} {stages, transitions}
end end
def prepare_basic(args \\ [value: 0, threshold: 0]) do def prepare_basic(args \\ [threshold: 0, bias: 0]) do
prepare(basic_prog(), args) prepare(basic_prog(), args)
end end
@ -80,7 +81,7 @@ alias Scopes.CSys
if value_n >= state.threshold do if value_n >= state.threshold do
msg = Shape.create(Shape.head(msg), data: %{data | value: value_n}) msg = Shape.create(Shape.head(msg), data: %{data | value: value_n})
CSys.forward(msg, scope) || CSys.notify(msg, scope) CSys.forward(msg, scope) || CSys.notify(msg, scope)
state_n = %{state | value: 0} state_n = %{state | value: state.bias}
CSys.update(put_elem(scope, 0, state_n)) CSys.update(put_elem(scope, 0, state_n))
else else
state_n = %{state | value: value_n} state_n = %{state | value: value_n}
@ -93,7 +94,8 @@ alias Scopes.CSys
state = CSys.state(scope) state = CSys.state(scope)
value = data[:value] || state.value value = data[:value] || state.value
threshold = data[:threshold] || state.threshold threshold = data[:threshold] || state.threshold
state_n = %{state | value: value, threshold: threshold} bias = data[:bias] || state.bias
state_n = %{state | value: value, threshold: threshold, bias: bias}
CSys.update(put_elem(scope, 0, state_n)) CSys.update(put_elem(scope, 0, state_n))
end end
@ -111,13 +113,15 @@ alias Scopes.CSys
# synapse operations # synapse operations
def negate() do def multiply(n) do
fn msg -> fn msg ->
value = Shape.data(msg)[:value] || 0 value = Shape.data(msg)[:value] || 0
Shape.create(Shape.head(msg), data: %{Shape.data(msg) | value: -value}) Shape.create(Shape.head(msg), data: %{Shape.data(msg) | value: n * value})
end end
end end
def negate(), do: multiply(-1)
# helper functions # helper functions
def restart({state, _proc, syns, env}) do def restart({state, _proc, syns, env}) do

View file

@ -16,17 +16,12 @@ defmodule Scopes.CSysTest do
Shape.data(receive_select(head)) Shape.data(receive_select(head))
end end
def neg_only() do
fn msg -> if Shape.data(msg)[:value] < 0, do: msg end
end
describe "basic:" do describe "basic:" do
test "minimal-neural-net" do test "minimal-neural-net" do
_env = Environ.setup(Program.prepare_basic()) _env = Environ.setup(Program.prepare_basic())
zero = receive_data([:csys, :created]).new zero = receive_data([:csys, :created]).new
CSys.send_value(zero, 0) CSys.send_value(zero, 0)
assert 0 = receive_data().value assert 0 = receive_data().value
#CSys.send_message(zero, [:csys, :create, :pred], %{op: neg_only()})
CSys.send_message(zero, [:csys, :create, :pred], CSys.send_message(zero, [:csys, :create, :pred],
%{op: [CSys.data_only(), Program.negate()]}) %{op: [CSys.data_only(), Program.negate()]})
one = receive_data([:csys, :created]).new one = receive_data([:csys, :created]).new
@ -34,7 +29,7 @@ defmodule Scopes.CSysTest do
two = receive_data([:csys, :created]).new two = receive_data([:csys, :created]).new
Process.sleep(1) Process.sleep(1)
CSys.send_value(one, 1) CSys.send_value(one, 1)
assert receive_data().value in [-1, 1] assert receive_data().value == 1
#assert receive_data().value in [-1, 1] #assert receive_data().value in [-1, 1]
CSys.send_message(two, [:csys, :create, :pred]) CSys.send_message(two, [:csys, :create, :pred])
three = receive_data([:csys, :created]).new three = receive_data([:csys, :created]).new