random-boolean-network/random_boolean_network.php
2020-11-14 11:17:31 +01:00

92 lines
2.3 KiB
PHP

<?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
Fri 13 Nov
*/
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);
}