Current section
Files
Jump to
Current section
Files
src/gleam_synapses@model@draw.erl
-module(gleam_synapses@model@draw).
-compile(no_auto_import).
-export([network_svg/1]).
-spec circle_vertical_distance() -> float().
circle_vertical_distance() ->
400.0 * 0.02.
-spec circle_horizontal_distance() -> float().
circle_horizontal_distance() ->
400.0 * 0.15.
-spec circle_radius() -> float().
circle_radius() ->
400.0 * 0.03.
-spec circle_stroke_width() -> float().
circle_stroke_width() ->
400.0 / 150.0.
-spec line_stroke_width() -> float().
line_stroke_width() ->
400.0 / 300.0.
-spec activation_name_to_stroke(binary()) -> binary().
activation_name_to_stroke(Activ_name) ->
case Activ_name of
<<"sigmoid"/utf8>> ->
<<"blue"/utf8>>;
<<"identity"/utf8>> ->
<<"orange"/utf8>>;
<<"tanh"/utf8>> ->
<<"yellow"/utf8>>;
<<"leakyReLU"/utf8>> ->
<<"pink"/utf8>>
end.
-spec layer_width(integer()) -> float().
layer_width(Num_of_circles) ->
Num_of_circles_float = gleam@int:to_float(Num_of_circles),
circle_vertical_distance() + (Num_of_circles_float * ((2.0 * circle_radius()) + circle_vertical_distance(
))).
-spec circle_cx(integer()) -> float().
circle_cx(Chain_order) ->
Chain_order_float = gleam@int:to_float(Chain_order),
circle_horizontal_distance() + (Chain_order_float * circle_horizontal_distance(
)).
-spec circle_cy(integer(), integer(), integer()) -> float().
circle_cy(Max_chain_circles, Num_of_chain_circles, Circle_order) ->
Current_layer_width = layer_width(Num_of_chain_circles),
Max_layer_width = layer_width(Max_chain_circles),
Layer_y = 0.5 * (Max_layer_width - Current_layer_width),
Circle_order_float = gleam@int:to_float(Circle_order),
Layer_y + ((Circle_order_float + 1.0) * ((2.0 * circle_radius()) + circle_vertical_distance(
))).
-spec circle_svg(float(), float(), binary()) -> binary().
circle_svg(X, Y, Stroke_val) ->
_pipe = [<<"<circle cx=\""/utf8>>,
gleam@float:to_string(X),
<<"\" cy=\""/utf8>>,
gleam@float:to_string(Y),
<<"\" r=\""/utf8>>,
gleam@float:to_string(circle_radius()),
<<"\" stroke=\""/utf8>>,
Stroke_val,
<<"\" stroke-width=\""/utf8>>,
gleam@float:to_string(circle_stroke_width()),
<<"\" fill=\""/utf8>>,
<<"white"/utf8>>,
<<"\"></circle>"/utf8>>],
gleam@string:concat(_pipe).
-spec input_circles_svgs(integer(), integer()) -> gleam_zlists@interop:z_list(binary()).
input_circles_svgs(Max_chain_circles, Input_circles) ->
_pipe = gleam_zlists:indices(),
_pipe@1 = gleam_zlists:take(_pipe, Input_circles),
gleam_zlists:map(
_pipe@1,
fun(I) ->
Stroke_val = case I =:= 0 of
true ->
<<"black"/utf8>>;
false ->
<<"brown"/utf8>>
end,
circle_svg(
circle_cx(0),
circle_cy(Max_chain_circles, Input_circles, I),
Stroke_val
)
end
).
-spec output_circles_svgs(
integer(),
integer(),
gleam_zlists@interop:z_list(binary())
) -> gleam_zlists@interop:z_list(binary()).
output_circles_svgs(Max_chain_circles, Output_chain_order, Output_activations) ->
Num_of_activations = gleam_zlists:count(Output_activations),
_pipe = Output_activations,
_pipe@1 = gleam_zlists:with_index(_pipe),
gleam_zlists:map(
_pipe@1,
fun(T) ->
{Activ, I} = T,
circle_svg(
circle_cx(Output_chain_order),
circle_cy(Max_chain_circles, Num_of_activations, I),
activation_name_to_stroke(Activ)
)
end
).
-spec hidden_circles_svgs(
integer(),
integer(),
gleam_zlists@interop:z_list(binary())
) -> gleam_zlists@interop:z_list(binary()).
hidden_circles_svgs(Max_chain_circles, Hidden_chain_order, Hidden_activations) ->
Num_of_activations = gleam_zlists:count(Hidden_activations),
_pipe = Hidden_activations,
_pipe@1 = gleam_zlists:map(_pipe, fun(A) -> {some, A} end),
_pipe@2 = gleam_zlists:cons(_pipe@1, none),
_pipe@3 = gleam_zlists:with_index(_pipe@2),
gleam_zlists:map(
_pipe@3,
fun(T) ->
{Maybe_activ, I} = T,
Stroke_val = case Maybe_activ of
{some, Activ} ->
activation_name_to_stroke(Activ);
none ->
<<"black"/utf8>>
end,
circle_svg(
circle_cx(Hidden_chain_order),
circle_cy(Max_chain_circles, Num_of_activations + 1, I),
Stroke_val
)
end
).
-spec layer_circles_svgs(
integer(),
integer(),
integer(),
gleam_zlists@interop:z_list(gleam_synapses@model@net_elems@neuron@neuron:neuron())
) -> gleam_zlists@interop:z_list(binary()).
layer_circles_svgs(Max_chain_circles, Layer_order, Num_of_layers, Layer_val) ->
Is_last_layer = Layer_order =:= (Num_of_layers - 1),
{ok, Prev_layer_size@1} = case begin
_pipe = Layer_val,
_pipe@1 = gleam_zlists:head(_pipe),
gleam@result:map(
_pipe@1,
fun(Neuron_val) ->
gleam_zlists:count(erlang:element(3, Neuron_val))
end
)
end of
{ok, Prev_layer_size} -> {ok, Prev_layer_size};
_try ->
erlang:error(#{gleam_error => assert,
message => <<"Assertion pattern match failed"/utf8>>,
value => _try,
module => <<"gleam_synapses/model/draw"/utf8>>,
function => <<"layer_circles_svgs"/utf8>>,
line => 174})
end,
Activations = gleam_zlists:map(
Layer_val,
fun(Neuron_val@1) ->
gleam_synapses@model@net_elems@activation@activation_serialized:serialized(
erlang:element(2, Neuron_val@1)
)
end
),
Input_circles = case Layer_order =:= 0 of
true ->
input_circles_svgs(Max_chain_circles, Prev_layer_size@1);
false ->
gleam_zlists:new()
end,
Hidden_circles = case Is_last_layer of
true ->
gleam_zlists:new();
false ->
hidden_circles_svgs(Max_chain_circles, Layer_order + 1, Activations)
end,
Output_circles = case Is_last_layer of
true ->
output_circles_svgs(Max_chain_circles, Layer_order + 1, Activations);
false ->
gleam_zlists:new()
end,
_pipe@2 = Input_circles,
_pipe@3 = gleam_zlists:append(_pipe@2, Hidden_circles),
gleam_zlists:append(_pipe@3, Output_circles).
-spec line_svg(
integer(),
integer(),
integer(),
integer(),
integer(),
integer(),
float(),
float()
) -> binary().
line_svg(
Max_chain_circles,
Base_chain_order,
Num_of_circles_in_base_chain,
Num_of_circles_in_target_chain,
Base_circle_order,
Target_circle_order,
Weight,
Max_abs_weight
) ->
Alpha = case Max_abs_weight of
0.0 -> 0.0;
Gleam@denominator -> gleam@float:absolute_value(Weight) / Gleam@denominator
end,
X1_val = circle_cx(Base_chain_order),
Y1_val = circle_cy(
Max_chain_circles,
Num_of_circles_in_base_chain,
Base_circle_order
),
X2_val = circle_cx(Base_chain_order + 1),
Y2_val = circle_cy(
Max_chain_circles,
Num_of_circles_in_target_chain,
Target_circle_order
),
Stroke_val = case Weight > 0.0 of
true ->
<<"lawngreen"/utf8>>;
false ->
<<"palevioletred"/utf8>>
end,
_pipe = [<<"<line stroke-opacity=\""/utf8>>,
gleam@float:to_string(Alpha),
<<"\" x1=\""/utf8>>,
gleam@float:to_string(X1_val),
<<"\" y1=\""/utf8>>,
gleam@float:to_string(Y1_val),
<<"\" x2=\""/utf8>>,
gleam@float:to_string(X2_val),
<<"\" y2=\""/utf8>>,
gleam@float:to_string(Y2_val),
<<"\" stroke=\""/utf8>>,
Stroke_val,
<<"\" stroke-width=\""/utf8>>,
gleam@float:to_string(line_stroke_width()),
<<"\"></line>"/utf8>>],
gleam@string:concat(_pipe).
-spec neuron_lines_svgs(
integer(),
integer(),
integer(),
integer(),
integer(),
float(),
gleam_zlists@interop:z_list(float())
) -> gleam_zlists@interop:z_list(binary()).
neuron_lines_svgs(
Max_chain_circles,
Layer_size,
Layer_order,
Num_of_layers,
Neuron_order_in_layer,
Max_abs_weight,
Weights
) ->
Is_output_layer = Layer_order =:= (Num_of_layers - 1),
Num_of_circles_in_base_chain = gleam_zlists:count(Weights),
Num_of_circles_in_target_chain = case Is_output_layer of
true ->
Layer_size;
false ->
Layer_size + 1
end,
Target_circle_order = case Is_output_layer of
true ->
Neuron_order_in_layer;
false ->
Neuron_order_in_layer + 1
end,
_pipe = Weights,
_pipe@1 = gleam_zlists:with_index(_pipe),
gleam_zlists:map(
_pipe@1,
fun(T) ->
{W, I} = T,
line_svg(
Max_chain_circles,
Layer_order,
Num_of_circles_in_base_chain,
Num_of_circles_in_target_chain,
I,
Target_circle_order,
W,
Max_abs_weight
)
end
).
-spec layer_lines_svgs(
integer(),
integer(),
integer(),
float(),
gleam_zlists@interop:z_list(gleam_synapses@model@net_elems@neuron@neuron:neuron())
) -> gleam_zlists@interop:z_list(binary()).
layer_lines_svgs(
Max_chain_circles,
Layer_order,
Num_of_layers,
Max_abs_weight,
Layer_val
) ->
Num_of_neurons = gleam_zlists:count(Layer_val),
_pipe = Layer_val,
_pipe@1 = gleam_zlists:with_index(_pipe),
gleam_zlists:flat_map(
_pipe@1,
fun(T) ->
{Neuron, I} = T,
neuron_lines_svgs(
Max_chain_circles,
Num_of_neurons,
Layer_order,
Num_of_layers,
I,
Max_abs_weight,
erlang:element(3, Neuron)
)
end
).
-spec network_svg(
gleam_zlists@interop:z_list(gleam_zlists@interop:z_list(gleam_synapses@model@net_elems@neuron@neuron:neuron()))
) -> binary().
network_svg(Network_val) ->
Num_of_layers = gleam_zlists:count(Network_val),
{ok, Max_chain_circles_float@1} = case begin
_pipe = Network_val,
_pipe@1 = gleam_zlists:with_index(_pipe),
_pipe@2 = gleam_zlists:map(
_pipe@1,
fun(T) ->
{Layer_val, I} = T,
case I =:= (Num_of_layers - 1) of
true ->
gleam_zlists:count(Layer_val) + 1;
false ->
gleam_zlists:count(Layer_val)
end
end
),
_pipe@3 = gleam_zlists:map(_pipe@2, fun gleam@int:to_float/1),
gleam_zlists:max(_pipe@3)
end of
{ok, Max_chain_circles_float} -> {ok, Max_chain_circles_float};
_try ->
erlang:error(#{gleam_error => assert,
message => <<"Assertion pattern match failed"/utf8>>,
value => _try,
module => <<"gleam_synapses/model/draw"/utf8>>,
function => <<"network_svg"/utf8>>,
line => 314})
end,
Max_chain_circles = gleam@float:round(Max_chain_circles_float@1),
{ok, Max_abs_weight@1} = case begin
_pipe@4 = Network_val,
_pipe@5 = gleam_zlists:flat_map(
_pipe@4,
fun(Layer_val@1) ->
gleam_zlists:flat_map(
Layer_val@1,
fun(Neuron_val) ->
gleam_zlists:map(
erlang:element(3, Neuron_val),
fun(W) -> gleam@float:absolute_value(W) end
)
end
)
end
),
gleam_zlists:max(_pipe@5)
end of
{ok, Max_abs_weight} -> {ok, Max_abs_weight};
_try@1 ->
erlang:error(#{gleam_error => assert,
message => <<"Assertion pattern match failed"/utf8>>,
value => _try@1,
module => <<"gleam_synapses/model/draw"/utf8>>,
function => <<"network_svg"/utf8>>,
line => 327})
end,
Circles_svgs = begin
_pipe@6 = Network_val,
_pipe@7 = gleam_zlists:with_index(_pipe@6),
gleam_zlists:flat_map(
_pipe@7,
fun(T@1) ->
{Layer_val@2, I@1} = T@1,
layer_circles_svgs(
Max_chain_circles,
I@1,
Num_of_layers,
Layer_val@2
)
end
)
end,
Lines_svgs = begin
_pipe@8 = Network_val,
_pipe@9 = gleam_zlists:with_index(_pipe@8),
gleam_zlists:flat_map(
_pipe@9,
fun(T@2) ->
{Layer_val@3, I@2} = T@2,
layer_lines_svgs(
Max_chain_circles,
I@2,
Num_of_layers,
Max_abs_weight@1,
Layer_val@3
)
end
)
end,
W@1 = circle_cx(Num_of_layers + 1),
H = circle_cy(Max_chain_circles, Max_chain_circles, Max_chain_circles),
Net_svgs = gleam_zlists:append(Lines_svgs, Circles_svgs),
_pipe@10 = [<<"<svg width=\""/utf8>>,
gleam@float:to_string(W@1),
<<"\" height=\""/utf8>>,
gleam@float:to_string(H),
<<"\">"/utf8>>,
gleam_zlists:reduce(
Net_svgs,
<<""/utf8>>,
fun(X, Acc) -> gleam@string:append(Acc, X) end
),
<<"</svg>"/utf8>>],
gleam@string:concat(_pipe@10).