xxxxxxxxxx
/******************
Code by Swiss
Original link:
https://openprocessing.org/sketch/1360946
Author links:
http://twitter.com/planet403
https://journal.social/
Inspirations:
https://slackermanz.com/understanding-multiple-neighborhood-cellular-automata/
https://distill.pub/selforg/2021/textures/
https://znah.net/hexells/
******************/
const DIM = 600,
STEP = 10,
SIZE = Math.floor(DIM / STEP),
CELLS = SIZE * SIZE;
let grid = [];
let indexer = [0, 1];
let coords = [];
let peers = [];
let peers2 = [];
let colormap;
let layer1_values = [];
let layer2_values = [];
let layer1_weights = [];
let layer2_weights = [];
function setup()
{
createCanvas(DIM, DIM);
colorMode(RGB, 1, 1, 1);
noStroke();
colormap = new ColorMap();
initWeights();
initGrids();
initCoords();
initPeers();
}
function mouseClicked()
{
initWeights();
initGrids();
}
function keyPressed()
{
if (key == ' ')
{
initWeights();
initGrids();
}
}
function initGrids()
{
//read and write grids
grid[0] = []; //read
grid[1] = []; //write
grid[2] = []; //lerp
for(let i = 0; i < SIZE; i++)
{
grid[0][i] = [];
grid[1][i] = [];
grid[2][i] = [];
for(let j = 0; j < SIZE; j++)
{
let d = dist(i, j, SIZE/2, SIZE/2);
let n = noise(i, j);
let val = random(1);//(d > SIZE / 4) ? 0 : (n < 0.2 || n > 0.8) ? random(1) : 0;
grid[0][i][j] = val;
grid[1][i][j] = 0;
grid[2][i][j] = val;
}
}
}
function initWeights()
{
//layer1_weights = [9.609624671566298,-6.9988928382001925,-6.031103286368422,-8.142795531203628,2.786993216626188,-8.939395609378803,2.062719355754062,8.663731748871186,4.7892017085981475,9.53930536002613,-2.9348871370187046,1.2109760936032075,1.7800218160292314,5.619809316925721,1.3665097985296057,-0.21965224633518687,4.8689373035096075,-1.7488988209558123,4.070003962524535,5.064051424421798,9.329289231808623,8.098957092203062,-4.644734074365102,-9.395008938419416,-1.2593861219894897,-0.8202597697059701,-7.575662085689991,0.8755704922479435,-6.20048369633754,3.917470068692147,2.3455240997674345,-7.176167890279426,-9.223037475554134,-8.783909955376735,7.8581854976303305,1.8525230577320073,-7.299148275562266,7.273207681609513,0.9420620232577015,-2.0465226018872418,1.4560186432354527,1.8161520391620591,6.820137079922329,-7.683683952012386,0.7877951953271491,8.179589500714886,6.182419485601013,4.663645291063201];
//layer2_weights = [-6.071438129493099,3.7760668404335984,0.6658030543445328,1.6665212578700217,-3.9698021021238894,1.4290649648213005,-2.3762399056833994,-1.5645346776581235,-5.7618993862818835,7.430192258810084,6.766853926019056,5.764500501680917,7.017685831788171];
//
//layer1_weights = [10.920051129637162,-6.991349191256206,-6.532824796513353,-6.266612924779917,1.9855038796214672,-8.215869364535877,2.641447894986429,7.165373125413817,3.7401594566831893,8.32348106805982,-1.421531111404596,1.7396125171025116,1.7066193550974633,6.358677775587709,0.6598772185188633,-0.43964879865552353,3.2501151101072487,-1.7488988209558123,4.62652080574633,4.869815780193898,10.248316199289725,9.083329499382254,-4.644734074365102,-10.039442887599273,-1.0544883993131497,-1.5887249086728046,-8.304698455502756,1.1875754001186225,-5.020211455328898,3.926952221079682,3.821689584670673,-7.566367567420777,-9.758622953216403,-8.783909955376735,8.040710046631048,1.8525230577320073,-4.4472814087145345,7.981851369743959,0.9420620232577015,-2.5632939343705305,1.7374715828931024,0.382484035947094,7.057595781828377,-8.715937742982906,0.8915560085690521,7.703449611113115,7.9842345312677905,6.266434323037144];
//layer2_weights = [-4.9050814003892365,4.198691979495827,2.1093946951434965,-0.029358011588745292,-2.4558418341679955,1.1561140503783616,-2.0140615350845095,-1.1776746246807934,-4.850036046471002,6.777447137934278,7.661831387659872,6.752770917876691,7.283691199480506];
//
//layer1_weights = [10.920051129637162,-6.991349191256206,-6.532824796513353,-6.266612924779917,1.9855038796214672,-8.215869364535877,2.913092729426837,7.165373125413817,3.7401594566831893,8.32348106805982,-1.4578293967454203,1.7396125171025116,2.1529959225945348,6.611969924270307,0.6598772185188633,-0.43964879865552353,3.4596520723079363,-1.9432823112943622,4.62652080574633,4.869815780193898,10.248316199289725,9.083329499382254,-4.644734074365102,-9.944958415424956,-1.0544883993131497,-1.797289077378799,-7.8359120688803365,1.0012744353575738,-5.483399414336014,3.4767442591262796,3.6662689903055123,-7.071828139401104,-9.551965800136614,-8.418859197317484,8.040710046631048,1.8525230577320073,-4.537144481507889,7.747260335215446,1.0894528688016873,-2.5632939343705305,1.4150605002626582,0.4300706080117529,7.393274787748762,-8.715937742982906,0.8915560085690521,7.676246612787261,7.9842345312677905,6.266434323037144];
//layer2_weights = [-4.664923642644839,4.198691979495827,2.1093946951434965,-0.029358011588745292,-2.4558418341679955,1.1561140503783616,-2.1953799614577876,-1.1776746246807934,-5.131357959600834,6.777447137934278,7.294006941999141,6.358086200730302,7.283691199480506];
//petri dish
//layer1_weights = [11.03234806685014,-6.882420393076358,-6.472697193683041,-6.225740538860715,1.9855038796214672,-8.215869364535877,2.913092729426837,7.165373125413817,3.7401594566831893,8.32348106805982,-1.288328659409912,1.7266945865095735,2.243431797439369,6.611969924270307,0.6598772185188633,-0.285367946316581,3.624890623380968,-1.9432823112943622,4.634654835419478,4.869815780193898,10.227980856413296,9.204566665230162,-4.644734074365102,-9.944958415424956,-1.0544883993131497,-1.797289077378799,-7.8359120688803365,0.8522052344726476,-5.519535768998148,3.4767442591262796,3.6662689903055123,-6.846761929751162,-9.551965800136614,-8.418859197317484,7.918839696420882,2.0379889547792214,-4.423333949195894,7.747260335215446,1.1849968620307927,-2.5632939343705305,1.4150605002626582,0.4580694927317549,7.393274787748762,-8.520344139291478,0.8915560085690521,7.810115964794862,7.77747968589598,6.111766357938148];
//layer2_weights = [-4.525384394391014,4.421196348692869,2.1093946951434965,0.18883351754009903,-2.4558418341679955,1.0774966938438837,-2.1953799614577876,-1.1776746246807934,-5.207194342974382,6.777447137934278,7.173866447311249,6.358086200730302,7.283691199480506];
layer1_weights = [10.973058626415716,-6.882420393076358,-6.472697193683041,-6.225740538860715,1.9855038796214672,-8.311172029731155,2.913092729426837,7.165373125413817,3.7388418791459257,8.32348106805982,-1.3621789601004946,1.7338018041002154,2.190137906213837,6.5666361569174505,0.6598772185188633,-0.23700594708888625,3.624890623380968,-1.9432823112943622,4.602413773576723,4.781895348175026,10.227980856413296,9.204566665230162,-4.644734074365102,-9.944958415424956,-0.9639914216029231,-1.6974928320798741,-7.8359120688803365,0.9280999039871425,-5.559501492937156,3.4767442591262796,3.6662689903055123,-6.942929980654792,-9.551965800136614,-8.49015825444981,7.918839696420882,2.1179018161737178,-4.430117688554398,7.747260335215446,1.1849968620307927,-2.5650701627679644,1.4150605002626582,0.4580694927317549,7.393274787748762,-8.485593839289292,0.8915560085690521,7.810115964794862,7.77747968589598,6.111766357938148];
layer2_weights = [-4.465715849452671,4.421196348692869,2.2020236109608264,0.21264902315756426,-2.4558418341679955,0.9805381885297899,-2.11202564931822,-1.1776746246807934,-5.207194342974382,6.86710793316994,7.264028310013627,6.358086200730302,7.214597870604088];
/*
for(let i = 0; i < 4 * 12; i++)
{
layer1_weights[i] += random(1) < 0.5 ? 0 : random(-0.1,0.1);
}
for(let i = 0; i < (12 + 1); i++)
{
layer2_weights[i] += random(1) < 0.5 ? 0 : random(-0.1,0.1);
}
*/
/*
for(let i = 0; i < 4 * 12; i++)
{
layer1_weights[i] = random(-10,10);
}
for(let i = 0; i < (12 + 1); i++)
{
layer2_weights[i] = random(-10,10);
}
*/
//print(layer1_weights.join());
//print(layer2_weights.join());
//print("---------------");
}
function initCoords()
{
for(let i = 0; i < SIZE; i++)
{
for(let j = 0; j < SIZE; j++)
{
coords.push([i,j]);
}
}
}
function initPeers()
{
for(let x = -1; x <= 1; x++)
{
for(let y = -1; y <= 1; y++)
{
if(x == 0 && y == 0) continue;
peers.push([x, y]);
}
}
for(let x = -2; x <= 2; x++)
{
for(let y = -2; y <= 2; y++)
{
if(abs(x) != 2 && abs(y) != 2) continue; //second ring around cell
peers2.push([x, y]);
}
}
}
function draw()
{
for(let i = 0; i < SIZE; i++)
{
for(let j = 0; j < SIZE; j++)
{
let val = grid[2][i][j];
let colour = colormap.getColor( val);
fill(colour);
square(i * STEP, j * STEP, STEP);
if(dist(mouseX / width * SIZE, mouseY / width * SIZE, i, j) < SIZE / 10)
{
grid[indexer[0]][i][j] = random(1);
}
}
}
updateGridsNeural();
updateGridsNeural();
}
function updateGridsNeural()
{
let self = 0;
let nh1 = 0;
let nh2 = 0;
for(let coord of coords) //for each cell
{
self = grid[indexer[0]][coord[0]][coord[1]];
//neighborhood 1
nh1 = 0;
for(let peer of peers)
{
let i = (coord[0] + peer[0] + SIZE) % SIZE;
let j = (coord[1] + peer[1] + SIZE) % SIZE;
nh1 += grid[indexer[0]][i][j];
}
//neighborhood 2
nh2 = 0;
for(let peer of peers2)
{
let i = (coord[0] + peer[0] + SIZE) % SIZE;
let j = (coord[1] + peer[1] + SIZE) % SIZE;
nh2 += grid[indexer[0]][i][j];
}
//layer 1
for(let i = 0; i < 12; i++)
{
layer1_values[i] = 1 / (1 + exp(layer1_weights[4 * i + 0] * self +
layer1_weights[4 * i + 1] * nh1 +
layer1_weights[4 * i + 2] * nh2 +
layer1_weights[4 * i + 3] * 1));
}
//output
let cross_product = 0;
for(let i = 0; i < layer1_values.length; i++)
{
cross_product += layer1_values[i] * layer2_weights[i];
}
cross_product += layer2_weights[layer1_values.length]; //bias
let output = 1 / (1 + exp( cross_product ));
//let amt = 0.04 * output;
//output = constrain(output + amt * (random(1) > 0.5 ? 1 : -1), 0, 1);
//let d = 0.045 * dist(coord[0], coord[1], SIZE/2, SIZE/2);
//if(d > 1) output /= (d * d);
grid[indexer[1]][coord[0]][coord[1]] = output;
if(indexer[0] == 0)
{
grid[2][coord[0]][coord[1]] = lerp(grid[2][coord[0]][coord[1]], output, 0.5); //lerp the accumulated value
}
}
indexer[0] = 1 - indexer[0];
indexer[1] = 1 - indexer[1];
}