* Perceptrons
@ 2022-10-16 19:48 Thangalin via ntg-context
0 siblings, 0 replies; only message in thread
From: Thangalin via ntg-context @ 2022-10-16 19:48 UTC (permalink / raw)
To: mailing list for ConTeXt users; +Cc: Thangalin
[-- Attachment #1: Type: text/plain, Size: 460 bytes --]
Okay, they aren't _real_ perceptrons, but fancy parameterized trees
connected on a hex grid, coded with MetaFun and Lua.
Big version: https://pdfhost.io/v/piuN04dSq_perceptron
If anyone is interested in the full source code, let me know.
I couldn't get "angle" to work properly. Hans, your simplifications on
the atantwo function also didn't work for all cases. There was a
single edge case that didn't determine the correct angle. Don't know
why.
Cheers!
[-- Attachment #2: perceptron-01.pdf --]
[-- Type: application/pdf, Size: 10254 bytes --]
[-- Attachment #3: perceptron-02.pdf --]
[-- Type: application/pdf, Size: 27372 bytes --]
[-- Attachment #4: perceptron.tex --]
[-- Type: text/x-tex, Size: 8749 bytes --]
\definecolor[HexGridBase][h=E0E0E0]
\definecolor[HexGridNode][h=202020]
\definecolor[HexGridEdge][h=808080]
%\definecolor[HexGridBase][h=1f50da]
%\definecolor[HexGridNode][h=00d687]
%\definecolor[HexGridEdge][h=00d687]
\startluacode
require "Graph"
-- Try to generate a different tree each run.
math.randomseed( math.modf( os.clock() * 10000000 ), os.time() )
userdata = userdata or {}
ud = userdata
-- Create a minimally spanning acyclic graph that's mostly connected.
--
-- @param r - numeric - The number of rows
-- @param c - numeric - The number of columns
-- @param m - numeric The number of edges
--
-- @return A handle to the tree instance.
function tree( r, c, m )
local graph = Graph:new()
local edges = graph:connected( r, c, m )
local source = edges[ math.random( #edges ) ]
local tree = graph:compute( source )
return tree
end
-- Extract the first pair of a vertex at the given index inside the tree.
-- No error checking is performed.
--
-- @param graph - object - The tree containing numerous edges.
-- @param index - non-negative integer - The index for the vertex pair.
--
-- @return The (x, y) pair for the first vertex comprising an edge.
function ud.vertex_a( graph, index )
u = graph[ index ].u
return { u.x, u.y }
end
-- Extract the second pair of a vertex at the given index inside the tree.
-- No error checking is performed.
--
-- @param graph - object - The tree containing numerous edges.
-- @param index - non-negative integer - The index for the vertex pair.
--
-- @return The (x, y) pair for the second vertex comprising an edge.
function ud.vertex_b( graph, index )
v = graph[ index ].v
return { v.x, v.y }
end
-- Return the number of edges in the tree.
--
-- @param graph - object - The tree containing numerous nodes.
--
-- @return The number of vertex pairs in the tree.
function ud.count( graph )
return #graph
end
\stopluacode
\startuseMPgraphic{HexGridBaseGraphic}{side}
% Set the random seed to the current second.
randomseed := lua( "os.time()" );
vardef atantwo( expr ax, ay, bx, by ) =
save theta;
dx := bx - ax;
dy := by - ay;
theta := 0;
if (dx > 0):
theta := atan( dy / dx );
elseif (dx < 0) and (dy >= 0):
theta := atan( dy / dx ) + pi;
elseif (dx < 0) and (dy < 0):
theta := atan( dy / dx ) - pi;
elseif (dx == 0) and (dy > 0):
theta := pi / 2;
elseif (dx == 0) and (dy < 0):
theta := -pi / 2;
fi;
theta
enddef;
vardef degrees( expr rad ) =
rad * 180 / pi
enddef;
vardef distance( expr ax, ay, bx, by ) =
sqrt( ((bx - ax)^2) + ((by - ay)^2) )
enddef;
% Set the number of hexagons from top to bottom.
GRID_C = 124;
% Set the number of hexagons from left to right.
GRID_R = 120;
% Set the number of pathways between nodes (higher is more complexity).
PATHWAYS = 235;
% Grid zoom level (smaller is further away).
SCALE = 5;
% Hexagon dimensions.
HEIGHT = sqrt( 3 );
HHEIGHT = HEIGHT / 2;
WIDTH = 2;
color colour_base;
color colour_node;
color colour_edge;
colour_base = \MPcolor{HexGridBase};
colour_node = \MPcolor{HexGridNode};
colour_edge = \MPcolor{HexGridEdge};
% Vertex diameters proportional to the hexagon height.
vertex_sm := HEIGHT / 12;
vertex_lg := HEIGHT / 5;
path path_ul;
path path_ur;
path path_tp;
path_ur := dir( 60 * 0 ) -- dir( 60 * 1 );
path_tp := dir( 60 * 1 ) -- dir( 60 * 2 );
path_ul := dir( 60 * 2 ) -- dir( 60 * 3 );
picture hexgrid;
picture vertices;
picture perceptrons;
picture connections;
hexgrid := nullpicture;
vertices := nullpicture;
perceptrons := nullpicture;
connections := nullpicture;
% Line width.
pickup pencircle scaled .05bp;
addto hexgrid also image(
for c = 1 upto GRID_C:
for r = 1 upto GRID_R:
offset_c := c * 3 / WIDTH;
offset_r := r * HEIGHT - (c mod 2 * HHEIGHT);
draw path_ul shifted (offset_c, offset_r) withcolor colour_base;
draw path_tp shifted (offset_c, offset_r) withcolor colour_base;
draw path_ur shifted (offset_c, offset_r) withcolor colour_base;
for i = 0 upto 2:
addto vertices also image(
draw
point i of path_tp
shifted (offset_c, offset_r)
withcolor colour_base
withpen pencircle
scaled vertex_sm;
);
endfor;
endfor;
endfor;
);
% Create the perceptron matrix.
lua( "ud.graph = tree( " &
decimal( GRID_C ) &
", " &
decimal( GRID_R ) &
", " &
decimal( PATHWAYS ) &
")"
);
edges := lua( "ud.count( ud.graph )" );
for i := 1 upto edges:
lua( "va = ud.vertex_a( ud.graph, " & decimal( i ) & ")" );
lua( "vb = ud.vertex_b( ud.graph, " & decimal( i ) & ")" );
vac := lua( "va[1]" );
var := lua( "va[2]" );
vbc := lua( "vb[1]" );
vbr := lua( "vb[2]" );
offset_ac := vac * 3 / WIDTH;
offset_ar := var * HEIGHT - (vac mod 2 * HHEIGHT);
offset_bc := vbc * 3 / WIDTH;
offset_br := vbr * HEIGHT - (vbc mod 2 * HHEIGHT);
% Draw a large nodes at the starting/ending coordinates.
addto perceptrons also image(
draw (offset_ac, offset_ar)
withcolor colour_node
withpen pencircle
scaled vertex_lg;
draw (offset_bc, offset_br)
withcolor colour_node
withpen pencircle
scaled vertex_lg;
);
addto perceptrons also image(
numeric vangle;
numeric vc;
numeric vr;
numeric sc;
numeric sr;
vi := round( degrees( atantwo( vac, var, vbc, vbr ) ) / 60 );
% Compute direction towards the first segment (to vertex of an edge).
vangle := vi * 60 * pi / 180;
% Calculate the position of the first vertex, offset from the center.
vc := offset_ac + cos( vangle );
vr := offset_ar + sin( vangle );
% Draw a line from the starting point to the subsequent vertex.
addto connections also image(
draw (offset_ac, offset_ar) -- (vc, vr)
withcolor colour_edge;
);
iterations := 1;
forever:
% Draw a circle at the subsequent vertex.
draw (vc, vr)
withcolor colour_node
withpen pencircle
scaled
if round( uniformdeviate( 3 ) ) = 0: vertex_lg else: vertex_sm; fi;
% 2 _ 1
% 3 / \ 0
% -2 \_/ -1
%
% Determine the next vertex based on smallest angle of the
% three possible vertices with respect to the line.
start := if (vi mod 2) == 1: -1 else: -2 fi;
% Ensure that at least one vertex will be selected.
nearest := infinity;
for k = start step 2 until 3:
kangle := k * 60 * pi / 180;
nc := vc + cos( kangle );
nr := vr + sin( kangle );
d := distance( offset_bc, offset_br, nc, nr );
if d < nearest:
nearest := d;
sc := nc;
sr := nr;
vi := k + 1;
fi;
endfor;
d := distance( offset_bc, offset_br, sc, sr );
iterations := iterations + 1;
if (d <= 1) and (iterations > 2) and (iterations mod 2 = 0):
draw (sc, sr)
withcolor colour_node
withpen pencircle
scaled vertex_sm;
fi;
exitif (d <= 1);
addto connections also image(
draw (vc, vr) -- (sc, sr)
withcolor colour_edge
withpen pencircle
scaled 0.05bp;
);
vc := sc;
vr := sr;
endfor;
if (d < 1) and (iterations > 2):
draw (sc, sr)
withcolor colour_node
withpen pencircle
scaled vertex_sm;
fi;
addto connections also image(
draw (offset_bc, offset_br) -- (vc, vr)
withcolor colour_edge
withpen pencircle
scaled 0.05bp;
);
);
endfor;
draw hexgrid scaled SCALE;
draw vertices scaled SCALE;
draw connections scaled SCALE;
draw perceptrons scaled SCALE;
\stopuseMPgraphic
\startuseMPgraphic{HexGridBgGraphic}
% Define the grid background colour
color gridback;
gridback := (0.15, 0.18, 0.24);
fill unitsquare
xyscaled (OverlayWidth, OverlayHeight)
withcolor gridback;
\stopuseMPgraphic
\defineoverlay[HexGridBaseGraphic][\uniqueMPgraphic{HexGridBaseGraphic}]
\defineoverlay[HexGridBgGraphic][\uniqueMPgraphic{HexGridBgGraphic}]
\setupbackgrounds[page][background={HexGridBaseGraphic}]
\starttext
\startalignment[middle]
\color[white]{GRID}
\stopalignment
\stoptext
[-- Attachment #5: Type: text/plain, Size: 496 bytes --]
___________________________________________________________________________________
If your question is of interest to others as well, please add an entry to the Wiki!
maillist : ntg-context@ntg.nl / https://www.ntg.nl/mailman/listinfo/ntg-context
webpage : https://www.pragma-ade.nl / http://context.aanhet.net
archive : https://bitbucket.org/phg/context-mirror/commits/
wiki : https://contextgarden.net
___________________________________________________________________________________
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2022-10-16 19:48 UTC | newest]
Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-10-16 19:48 Perceptrons Thangalin via ntg-context
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).