Packages

A plug-and-play library for neural networks written in Gleam

Current section

Files

Jump to
gleam_synapses gen src gleam_synapses@model@draw.erl
Raw

gen/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) ->
gleam@string:concat(
[<<"<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>>]
).
-spec input_circles_svgs(integer(), integer()) -> gleam_zlists@interop:z_list(binary()).
input_circles_svgs(Max_chain_circles, Input_circles) ->
gleam_zlists:map(
gleam_zlists:take(gleam_zlists:indices(), Input_circles),
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),
gleam_zlists:map(
gleam_zlists:with_index(Output_activations),
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),
gleam_zlists:map(
gleam_zlists:with_index(
gleam_zlists:cons(
gleam_zlists:map(Hidden_activations, fun(A) -> {some, A} end),
none
)
),
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())
) -> 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} = gleam@result:map(
gleam_zlists:head(Layer_val),
fun(Neuron_val) -> gleam_zlists:count(erlang:element(3, Neuron_val)) end
),
Activations = gleam_zlists:map(
Layer_val,
fun(Neuron_val@1) ->
erlang:element(2, erlang:element(2, Neuron_val@1))
end
),
Input_circles = case Layer_order =:= 0 of
true ->
input_circles_svgs(Max_chain_circles, Prev_layer_size);
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,
gleam_zlists:append(
gleam_zlists:append(Input_circles, Hidden_circles),
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,
gleam@string:concat(
[<<"<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>>]
).
-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,
gleam_zlists:map(gleam_zlists:with_index(Weights), 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())
) -> 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),
gleam_zlists:flat_map(
gleam_zlists:with_index(Layer_val),
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()))
) -> binary().
network_svg(Network_val) ->
Num_of_layers = gleam_zlists:count(Network_val),
{ok, Max_chain_circles_float} = gleam_zlists:max(
gleam_zlists:map(
gleam_zlists:map(
gleam_zlists:with_index(Network_val),
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
),
fun gleam@int:to_float/1
)
),
Max_chain_circles = gleam@float:round(Max_chain_circles_float),
{ok, Max_abs_weight} = gleam_zlists:max(
gleam_zlists:flat_map(
Network_val,
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
)
),
Circles_svgs = gleam_zlists:flat_map(
gleam_zlists:with_index(Network_val),
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
),
Lines_svgs = gleam_zlists:flat_map(
gleam_zlists:with_index(Network_val),
fun(T@2) -> {Layer_val@3, I@2} = T@2,
layer_lines_svgs(
Max_chain_circles,
I@2,
Num_of_layers,
Max_abs_weight,
Layer_val@3
) 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),
gleam@string:concat(
[<<"<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>>]
).