random-boolean-network/random_boolean_network.php

94 lines
2.4 KiB
PHP
Raw Normal View History

2020-11-14 11:16:17 +01:00
<?php
/*
Random boolean network in PHP (7.4+).
Inspired by the Computerphile Video: https://www.youtube.com/watch?v=mCML2B94rUg
The use of random_int combined with modulo leads to better randomness entropy.
Formally correct as the relations with other cells are bitshifted in the right order.
Not that it matters, as it's randomly chosen, but done anyway for the sake of repeatability.
Joop Schilder
Sat 14 Nov 01:30
One of the nights that I shall remember as if it were me who was in control of my brain.
*/
const NUM_NODES = 20;
const NUM_CONNECTIONS = 3;
const NUM_GENERATIONS = 20;
const CHAR_ON_ZERO = '0';
const CHAR_ON_ONE = ' ';
const TRUTH_TABLE_SIZE = (1 << NUM_CONNECTIONS);
$truth_table = [];
for ($i = 0; $i < TRUTH_TABLE_SIZE; $i++) {
$truth_table[$i] = random_int(0, 100) % 2;
}
$nodes = [];
for ($i = 0; $i < NUM_NODES; $i++) {
$nodes[$i] = random_int(0, 100) % 2;
}
$connections = [];
for ($i = 0; $i < NUM_NODES; $i++) {
for ($j = 0; $j < NUM_CONNECTIONS; $j++) {
$connections[$i][$j] = random_int(0, 2000) % 20;
}
}
function print_generation(int $g, array $nodes): void
{
printf("G%5d %s\n", $g, format_nodes($nodes));
}
function print_truth_table(array $truth_table): void
{
print("Truth table:\n");
for($i = 0; $i < TRUTH_TABLE_SIZE; $i++) {
printf("[%s] => %d\n", str_pad(decbin($i), NUM_CONNECTIONS, '0', STR_PAD_LEFT), $truth_table[$i]);
}
}
function print_connections(array $connections): void
{
print("Connections:\n");
for ($i = 0; $i < NUM_NODES; $i++) {
printf("[%3d] => [%s]\n", $i, implode(', ', $connections[$i]));
}
}
function format_nodes(array $nodes): string
{
return implode(' ', array_map(fn($i): string => $i == 0 ? CHAR_ON_ZERO : CHAR_ON_ONE, $nodes));
}
function propagate(array $nodes, array &$connections, array &$truth_table): array
{
$next_nodes = [];
for ($i = 0; $i < NUM_NODES; $i++) {
$tt_index = 0;
for ($j = 0; $j < NUM_CONNECTIONS; $j++) {
$tt_index += $nodes[$connections[$i][$j]] << (NUM_CONNECTIONS - 1 - $j);
}
$next_nodes[$i] = $truth_table[$tt_index];
}
return $next_nodes;
}
print_truth_table($truth_table);
print("\n");
print_connections($connections);
print("\n");
print_generation(0, $nodes);
for ($i = 0; $i < NUM_GENERATIONS; $i++) {
$nodes = propagate($nodes, $connections, $truth_table);
print_generation($i, $nodes);
}