Created `Genome`'s `constructor` + finished `NeuralNetwork`'s `storage` and `attributes` management (+ serialization) + now it remains the hard & cool part -> genetic algorithm

This commit is contained in:
xdrm-brackets 2016-10-26 17:15:00 +02:00
parent e739508a45
commit fd9bcefed7
11 changed files with 625 additions and 100 deletions

View File

@ -6,34 +6,49 @@
class FileManager{
/* CREATES A FILE WITH ITS NEEDED DIRECTORIES
*
* @path<String> Path of the needed file
*
* @return created<Boolean> If the file has been created successfully
*
*/
public static function create($file){
/* (0) Checks arguments */
if( !is_string($file) || is_dir($file) )
return false;
/* (1) Creates file */
try{
fclose( fopen($file, 'w') );
return true;
}catch(Exception $e){ return false; }
}
/* READS FILE'S CONTENT
*
* @file<String> File to read
*
*/
public static function read($file){
/* [1] Init driver
=========================================================*/
/* (0) Checks arguments */
if( !is_string($file) )
throw new \Error('Wrong argument for read(<String>).');
/* (1) Initializing driver on file (read-flag) */
$driver = new \SplFileObject($file, 'r');
/* [2] Read lines
=========================================================*/
/* (2) Read lines */
$read = '';
/* (1) Reads lines */
$line = 0;
while( $driver->current() ){
$read .= "\n".$driver->current();
$read .= $driver->current();
$driver->next();
}
/* [3] Returns read content
=========================================================*/
/* (2) Destroy driver */
$driver = null;
/* (3) Returns result */
return $read;
}
@ -44,19 +59,27 @@
* @file<String> File to write to
* @content<String> Content to write
*
* @return written<Boolean> Returns if the content have been written successfully
*
* @note: Creates file if it is possible with `file_put_contents()`
*
*/
public static function write($file, $content){
/* (0) Checks arguments */
if( !is_string($file) || !is_string($content) )
return false;
/* (1) Erase file */
file_put_contents($file, '');
try{
fclose( fopen($file, 'w') );
}catch(Exception $e){ return false; }
/* (2) Get driver (write-flag) */
$driver = new \SplFileObject($file, 'r+');
/* (3) Writes content */
$driver->fwrite($content);
return !is_null( $driver->fwrite($content) );
/* (4) Free driver */
$driver = null;
}
@ -65,16 +88,21 @@
* @file<String> File to append content to
* @content<String> Content to append
*
* @return append<Boolean> Returns if the content have been append successfully
*
* @note: If file doesn't exists, returns false
*
*/
public static function append($file, $content){
/* (0) Checks arguments */
if( !is_file($file) || !is_string($content) )
return false;
/* (1) Get driver (append-flag) */
$driver = new \SplFileObject($file, 'a');
/* (2) append content */
$driver->fwrite($content.PHP_EOL);
/* (3) Free driver */
$driver = null;
return !is_null( $driver->fwrite($content.PHP_EOL) );
}

View File

@ -0,0 +1,170 @@
<?php
namespace neuralnetwork\core;
use filemanager\core\FileManager;
class Genome/* implements \Serializable*/{
/************************************************
**** Constants ****
************************************************/
const MIN = 0;
const MAX = 1e9;
/************************************************
**** LOCAL ATTRIBUTES ****
************************************************/
private $layers; // Number of layers
private $neurons; // Neurons of the genome
private $synapses; // Synapses between neurons
/* CONSTRUCTOR
*
* -- RANDOM CREATION --
* @layers<int> Number of layers to manage
* @neurons<int> Number of neurons per layer
*
* -- CLONING --
* @base<Genom> Genome to clone to
*
* -- CROSS-OVER CREATION --
* @father<Genome> First parent
* @mother<Genome> Second parent
*
*
*/
public function __construct(){
/* (1) Get arguments */
$argv = func_get_args();
$argc = count($argv);
/* (2) If CrossoverCreation */
if( $argc > 1 && $argv[0] instanceof Genome && $argv[1] instanceof Genome )
$this->construct_crossover($argv[0], $argv[1]);
/* (3) If RandomCreation */
else if( $argc > 1 && abs(intval($argv[0])) === $argv[0] && abs(intval($argv[1])) === $argv[1] )
$this->construct_new($argv[0], $argv[1]);
/* (4) If InheritanceCreation (clone) */
else if( $argc > 0 && $argv[0] instanceof Genome )
$this->construct_inheritance($argv[0]);
/* (5) If no match */
else
throw new \Error('Invalid Genome constructor\'s arguments.');
}
/* BUILDS A Genome RANDOMLY WITH PARAMETERS
*
* @layers<int> The number of hidden layers to manage
* @neurons<int> The number neurons per layer
*
* @return created<Boolean> If Genome has been successfully created
*
*/
private function construct_new($layers=-1, $neurons=-1){
/* (1) Checks parameters */
if( abs(intval($layers)) !== $layers || abs(intval($neurons)) !== $neurons )
return false;
// set layers
$this->layers = $layers;
/* (2) Creating random neurons */
$this->neurons = [];
for( $i = 0 ; $i < $neurons ; $i++ )
$this->neurons[$i] = rand(self::MIN, self::MAX) / self::MAX;
/* (3) Creating random synapses */
$this->synapses = [];
for( $i = 0, $l = pow($neurons, $layers) ; $i < $l ; $i++ )
$this->synapses[$i] = rand(self::MIN, self::MAX) / self::MAX;
// Success status
return true;
}
/* BUILDS A Genome BASED ON A PARENT
*
* @parent<Genome> Parent genome to clone into children
*
* @return created<Boolean> If cloned Genome has been created successfully
*
*/
private function construct_inheritance($parent=null){
/* (1) Checks parent type */
if( !($parent instanceof Genome) )
return false;
/* (2) Clones into this Genome */
$this->layers = $parent->layers;
$this->neurons = $parent->neurons;
$this->synapses = $parent->synapses;
// Success state
return true;
}
/* BUILDS A Genome BASED ON TWO PARENTS
*
* @father<Genome> First parent ($father)
* @mother<Genome> Second parent ($mother)
*
* @return created<Boolean> If crossed-over Genome has been created successfully
*
*/
private function construct_crossover($father=null, $mother=null){
/* (1) Checks parent type */
if( !($father instanceof Genome) || !($mother instanceof Genome) )
return false;
/* (2) Checks number of layers+neurons (same species) */
if( $father->layers !== $mother->layers || count($father->neurons) !== count($mother->neurons) )
return false;
/* (3) Do random crossover for neurons */
$this->neurons = [];
for( $i = 0, $l = count($father->neurons) ; $i < $l ; $i++ )
if( rand(0,1) ) $this->neurons[$i] = $father->neurons[$i];
else $this->neurons[$i] = $mother->neurons[$i];
/* (3) Creating random synapses */
$this->synapses = [];
for( $i = 0, $l = pow(count($this->neurons), $this->layers) ; $i < $l ; $i++ )
if( rand(0,1) ) $this->synapses[$i] = $father->synapses[$i];
else $this->synapses[$i] = $mother->synapses[$i];
// Success state
return true;
}
}
/************************************************
**** USE CASE ****
************************************************/
$use_case = false;
if( $use_case ){
/* (1) Basic Creation */
$a = new Genome(2, 3); // 2 layers of 3 neurons each -> randomly filled
/* (2) Inheritance */
$b = new Genome($a); // Clone of @a
/* (3) Section Title */
$b->mutation(0.3); // @b has now mutated with a threshold of 30%
/* (4) Cross-over (father+mother) */
$c = new Genome($a, $b); // @c is a randomly-done mix of @a and @b
}
?>

View File

@ -3,39 +3,13 @@
namespace neuralnetwork\core;
use neuralnetwork\core\NeuralNetworkCore;
use filemanager\core\FileManager;
/************************************************
**** Neural Network's Facade ****
************************************************/
class NeuralNetwork{
/* CHECKS AND STORES PATHS TO STORAGE FILES
*
* @path<String> Path to storage
*
* @return files<Array> Array containing storage files' information
* @return error<NULL> Returns NULL if error
*
*/
public static function setStorage($path){
/* (1) Checks the path */
if( !preg_match("/^(?P<path>\/(?:[a-z0-9_-]+\/)*)(?P<filename>[a-z0-9_-]+)$/i", $path, $matches) )
return null;
/* (2) Checks file's existence and returns it */
return [
[
'filename' => $matches['path'].$matches['filename'] .'.nn', // will contain neural network data
'exists' => is_file($matches['path'].$matches['filename'] .'.nn')
],
[
'filename' => $matches['path'].$matches['filename'] .'.ex', // will contain samples
'exists' => is_file($matches['path'].$matches['filename'] .'.ex')
]
];
}
/* CREATES A NEW NEURAL NETWORK
*
* @generations<int> Maximum number of generations to process
@ -59,23 +33,19 @@
public static function load($storage=null){
/* (1) Checks argument */
if( is_null($storage=self::setStorage($gnr_or_storage)) )
if( is_null($storage=NeuralNetworkCore::getStorage($storage)) )
throw new Error('Wrong NeuralNetwork loader\'s argument.');
/* (2) If files doesn't exist, raise error */
if( !$storage[0]['exists'] || !$storage[1]['exists'] )
if( !$storage[0]['exists'] || !$storage[1]['exists'] || !$storage[2]['exists'] )
throw new Error('Loaded storage have file(s) missing.');
/* (3) Parses files */
$last_network = json_decode( FileManager::read($storage[0]['filename']), true);
/* (3) Unserialize last NeuralNetwork */
$last_network = FileManager::read($storage[0]['filename']);
/* (4) Creates and fill instance */
$instance = new NeuralNetworkCore($last_network['generations'], $last_network['genomes']);
$instance->setStorage($gnr_or_storage);
$instance->setFitnessEnd($last_network['fitness_end']);
$instance->setKeptGenomes($last_network['kept_genomes']);
$instance->setMutationThreshold($last_network['mutation_threshold']);
$instance->setMaxValues($last_network['max_values']);
$instance = new NeuralNetworkCore(0, 0);
$instance->unserialize($last_network);
/* (5) Returns instance */
return $instance;

View File

@ -4,7 +4,7 @@
use filemanager\core\FileManager;
class NeuralNetworkCore{
class NeuralNetworkCore implements \Serializable{
/************************************************
**** GLOBAL ATTRIBUTES ****
@ -14,6 +14,8 @@
private $kptGnm; // Number of genomes kept for each generation
private $mutThr; // Mutation threshold
private $fitEnd; // Fitness range to end process
private $numHid; // Number of hidden layer(s)
private $numNeu; // Number of neurons for each hidden layer
private $max; // max values for input and output neurons
private $storage; // path to storage
@ -28,6 +30,10 @@
/************************************************
**** Static Methods ****
************************************************/
/* RETURNS CONFIGURATION CONTENT
*
* @return config<Array> Associative array containing config content
@ -48,6 +54,36 @@
return $parsed;
}
/* RETURNS STORAGE STATUS & DATA
*
* @path<String> Path to storage
*
* @return files<Array> Array containing storage files' information
* @return error<NULL> Returns NULL if error
*
*/
public static function getStorage($path){
/* (1) Checks the path */
if( !preg_match("/^(?P<path>(?:[a-z0-9_-]+\/)*)(?P<filename>[a-z0-9_-]+)$/i", $path, $matches) )
return null;
$absolute_path = __ROOT__.self::conf()['storage_parent'].'/'.$matches['path'].$matches['filename'];
/* (2) Checks file's existence and returns it */
return [
[
'filename' => $absolute_path.'.nn', // will contain neural network data
'exists' => is_file($absolute_path.'.nn')
],[
'filename' => $absolute_path.'.ex', // will contain samples
'exists' => is_file($absolute_path.'.ex')
],[
'filename' => $absolute_path.'.ln', // will contain values & weights
'exists' => is_file($absolute_path.'.ln')
]
];
}
/* CONSTRUCTOR
*
@ -72,14 +108,17 @@
/* (2) Default attributes */
$default = self::conf()['default'];
$this->setKeptGenomes($default['genomes_kept']); // default value
$this->setMutationThreshold($default['mutation_threshold']); // default value
$this->setFitnessEnd($default['fitness_end']); // default value
$this->max = null; // default value
$this->setStorage($default['storage']); // default value
$this->setKeptGenomes($default['genomes_kept']); // default value
$this->setMutationThreshold($default['mutation_threshold']); // default value
$this->setFitnessEnd($default['fitness_end']); // default value
$this->setHiddenLayersCount($default['hidden_layers']); // default value
$this->setHiddenLayerNeuronsCount($default['layer_neurons']); // default value
$this->max = null; // default value
$this->setStorage($default['storage']); // default value
}
/************************************************
**** Attributes Setters ****
************************************************/
@ -92,26 +131,34 @@
*
*/
public function setStorage($path){
/* (1) Checks the path */
if( !preg_match("/^(?P<path>(?:[a-z0-9_-]+\/)*)(?P<filename>[a-z0-9_-]+)$/i", $path, $matches) )
/* [1] Manages storage verification
=========================================================*/
/* (1) Get storage files' information */
$storageData = self::getStorage($path);
/* (2) If doesn't exist, return FALSE */
if( is_null($storageData) )
return false;
$absolute_path = __ROOT__.self::conf()['storage_parent'].'/'.$matches['path'].$matches['filename'];
/* (3) Stores into instance */
$this->storage = $storageData;
/* (2) Checks file's existence and returns TRUE */
$this->storage = [
[
'filename' => $absolute_path.'.nn', // will contain neural network data
'exists' => is_file($absolute_path.'.nn')
],
[
'filename' => $absolute_path.'.ex', // will contain samples
'exists' => is_file($absolute_path.'.ex')
]
];
/* [2] Initializes files
=========================================================*/
/* (1) Creates directory/ies */
if( !is_dir(dirname(($this->storage[0]['filename']))) )
mkdir( dirname($this->storage[0]['filename']), 0775, true );
// Checks
if( !is_dir(dirname(($this->storage[0]['filename']))) )
throw new \Error('Error creating directory: '.dirname(($this->storage[0]['filename'])));
/* (2) Creates files */
foreach($this->storage as $file)
FileManager::create( $file['filename'] );
return true;
}
/* SET FITNESS END
@ -147,6 +194,28 @@
$this->mutThr = $mutThr;
}
/* SET NUMBER OF NEURONS PER HIDDEN LAYER
*
* @numNeu<int> Number of Neurons per hidden layer
*
*/
public function setHiddenLayerNeuronsCount($numNeu){
if( abs(intval($numNeu)) !== $numNeu ) return;
$this->numNeu = $numNeu;
}
/* SET NUMBER OF HIDDEN LAYERS
*
* @numHid<int> Number of hidden layer(s)
*
*/
public function setHiddenLayersCount($numHid){
if( abs(intval($numHid)) !== $numHid ) return;
$this->numHid = $numHid;
}
/************************************************
**** Sample Setters ****
@ -167,7 +236,6 @@
];
}
/* ADD SAMPLE TO THE NEURAL NETWORK
*
* @input<Array> Sample's input values
@ -205,7 +273,6 @@
return false;
}
/* [2] Adds values
=========================================================*/
FileManager::append( $this->storage[1]['filename'], implode(',',$input) .';'. implode(',',$output) );
@ -213,6 +280,127 @@
return true;
}
/************************************************
**** Process Methods ****
************************************************/
/* DEFINES A STORAGE FOR THE NEURAL NETWORK
*
* @path<String> [OPTIONAL] Path to storage
* @override<Boolean> If override is wanted (will erase the whole previous data)
*
*/
public function store($path=null, $override=false){
if( !is_null($path) ){
/* [1] Checks storage existence
=========================================================*/
/* (1) Get storage files' information */
$storage = self::getStorage($path);
/* (2) Checks if files doesn't exist */
if( $storage[0]['exists'] || $storage[1]['exists'] || $storage[2]['exists'] )
if( !$override )
throw new \Error('This storage already exists, you can only load() it.');
/* [2] Creates storage & its files
=========================================================*/
/* (1) Keep last storage information */
$last_storage = $this->storage;
/* (2) Replaces with new storage */
$this->setStorage($path);
}
/* [3] Stores data
=========================================================*/
/* (1) Stores NeuralNetwork state (attributes) */
FileManager::write($storage[0]['filename'], $this->serialize());
/* (2) Stores samples */
FileManager::write($storage[1]['filename'], FileManager::read($last_storage[1]['filename']));
/* (3) Stores NeuralNetwork values & weights */
FileManager::write($storage[2]['filename'], FileManager::read($last_storage[2]['filename']));
}
/* STARTS THE LEARNING ROUTINE
*
* @callback<Function> Callback function to display current state
*
*/
public function learn($callback=null){
/* [1] Manages @callback argument
=========================================================*/
if( !is_callable($callback) )
$callback = function(){};
/* [2] Creates the neural network
=========================================================*/
}
/************************************************
**** Serialization Methods ****
************************************************/
/* RETURNS A SERIALIZED VERSION OF THE NeuralNetwork
*
* @return serialized<String> Serialized representation of the NeuralNetwork
*
*/
public function serialize(){
/* (1) Initializes json */
$json = [];
/* (2) Adding attributes */
$json['maxGnr'] = $this->maxGnr;
$json['maxGnm'] = $this->maxGnm;
$json['kptGnm'] = $this->kptGnm;
$json['mutThr'] = $this->mutThr;
$json['fitEnd'] = $this->fitEnd;
$json['numHid'] = $this->numHid;
$json['numNeu'] = $this->numNeu;
$json['max'] = $this->max;
$json['storage'] = $this->storage;
/* (3) Returns serialized string */
return json_encode($json);
}
/* BUILDS THE NeuralNetwork BASED ON ITS SERIALIZED STRING
*
* @serialized<String> Serialized representation of a NeuralNetwork
*
*/
public function unserialize($serialized){
/* (1) Decodes json */
$json = json_decode($serialized, true);
/* (2) Manages json error */
if( !is_array($json) )
throw new Error('Unserialization format error.');
/* (3) Attributing json attributes */
$this->maxGnr = $json['maxGnr'];
$this->maxGnm = $json['maxGnm'];
$this->kptGnm = $json['kptGnm'];
$this->mutThr = $json['mutThr'];
$this->fitEnd = $json['fitEnd'];
$this->numHid = $json['numHid'];
$this->numNeu = $json['numNeu'];
$this->max = $json['max'];
$this->storage = $json['storage'];
}
}
@ -238,6 +426,12 @@
/* (4) Specifies that for each mutation, it must be at maximum 30% different */
$neunet->setMutationThreshold(0.4);
/* (5) Specifies the number of hidden layers */
$neunet->setHiddenLayersCount(2);
/* (6) Specifies the number of neurons per hidden layer */
$neunet->setHiddenLayerNeuronsCount(4);
/* (2) Let's learn
---------------------------------------------------------*/
@ -261,17 +455,18 @@
/* (3) What to do next ?
---------------------------------------------------------*/
/* (1) Store your data */
$neunet->store('/some/path/to/filename');
$neunet->store('/some/path/to/storage');
/* (2) [HIDDEN] will create those 2 files */
'/some/path/to/filename.nn'; // containing neural network weights
'/some/path/to/filename.ex'; // containing neural network samples
'/some/path/to/storage.nn'; // containing neural network configuration
'/somt/path/to/storage.ln'; // containing neural network learnt values & weights
'/some/path/to/storage.ex'; // containing neural network samples
/* (4) And next ?
---------------------------------------------------------*/
/* (1) Load your stored neural network */
$trainednn = NeuralNetwork::load('/some/path/to/filename');
$trainednn = NeuralNetwork::load('/some/path/to/storage');
/* (2) Use it to guess output, with well-formed input */
$guessed = $trainednn->guess([1.2, 0.9, 6.1]);

View File

@ -0,0 +1,114 @@
<?php
namespace neuralnetwork\core;
use filemanager\core\FileManager;
class NeuralNetworkCore implements \Serializable{
/************************************************
**** GLOBAL ATTRIBUTES ****
************************************************/
private $maxGnr; // Maximum generation iterations
private $maxGnm; // Maximum genomes per generation
private $kptGnm; // Number of genomes kept for each generation
private $mutThr; // Mutation threshold
private $fitEnd; // Fitness range to end process
private $numHid; // Number of hidden layer(s)
private $numNeu; // Number of neurons for each hidden layer
private $max; // max values for input and output neurons
private $storage; // path to storage
/************************************************
**** LOCAL ATTRIBUTES ****
************************************************/
private $gnr; // Current generation index
private $gmns; // Current generation's genomes
private $gnm; // Current genome index
private $fit; // Current fitness
}
/************************************************
**** USE CASE ****
************************************************/
$use_case = false;
if( $use_case ){
/* (1) Instanciate and configure neural network
---------------------------------------------------------*/
/* (1) Initialize neural network to try 100 genomes over 50 generations (max) */
$neunet = NeuralNetwork::create(100, 50);
/* (2) Specifies that a fitness greater than 0.89 will stop the neural network */
$neunet->setFitnessEnd(0.89);
/* (3) Specifies that it will keep the 2 best genomes of each generation */
$neunet->setKeptGenomes(2);
/* (4) Specifies that for each mutation, it must be at maximum 30% different */
$neunet->setMutationThreshold(0.4);
/* (5) Specifies the number of hidden layers */
$neunet->setHiddenLayersCount(2);
/* (6) Specifies the number of neurons per hidden layer */
$neunet->setHiddenLayerNeuronsCount(4);
/* (2) Let's learn
---------------------------------------------------------*/
/* (1) Set dataset sample maximum values */
$neunet->setMaxValues([2,2,7], [10, 10]);
// input output
/* (2) Setting our example dataset */
$neunet->addSample([1.9, 2, 5.3], [6, 0]);
$neunet->addSample([1.2, 1.2, 0.1], [0, 2]);
$neunet->addSample([0, 0, 0], [5, 5]);
/* (3) Launch learning routine with callback function */
$neunet->learn(function($ctx){ // callback with @ctx the current context
echo 'generation '. $ctx['generation'] .'/'. $ctx['generations'] ."\n";
echo 'genome '. $ctx['genome'] .'/'. $ctx['genomes'] ."\n";
echo 'fitness: '. $ctx['fitness'] .'/'. $ctx['fitness_end']. "\n";
});
/* (3) What to do next ?
---------------------------------------------------------*/
/* (1) Store your data */
$neunet->store('/some/path/to/storage');
/* (2) [HIDDEN] will create those 2 files */
'/some/path/to/storage.nn'; // containing neural network configuration
'/somt/path/to/storage.ln'; // containing neural network learnt values & weights
'/some/path/to/storage.ex'; // containing neural network samples
/* (4) And next ?
---------------------------------------------------------*/
/* (1) Load your stored neural network */
$trainednn = NeuralNetwork::load('/some/path/to/storage');
/* (2) Use it to guess output, with well-formed input */
$guessed = $trainednn->guess([1.2, 0.9, 6.1]);
/* (3) And correct it if needed*/
echo "1: ". $guessed[0] ."\n";
echo "2: ". $guessed[2] ."\n";
echo "is it correct ?\n";
// .. some code to manage and read correct output if it was wrong
$trainednn->addSample([1.2, 0.9, 6.1], [9, 0]);
// You can now relaunch a new neural network's learning
// or You can just add a few generations to evolve your neural network
}
?>

View File

@ -0,0 +1,8 @@
0,0,0;0
0,0,1;1
0,1,0;0
0,1,1;1
1,0,0;0
1,0,1;1
1,1,0;1
1,1,1;0

View File

@ -0,0 +1 @@
{"maxGnr":50,"maxGnm":100,"kptGnm":2,"mutThr":0.3,"fitEnd":1,"numHid":2,"numNeu":3,"max":{"input":[1,1,1],"output":[1]},"storage":[{"filename":"\/home\/xdrm-brackets\/Desktop\/git.xdrm.io\/neural-network.php\/build\/neuralnetwork\/storage\/A\/B\/C\/test.nn","exists":true},{"filename":"\/home\/xdrm-brackets\/Desktop\/git.xdrm.io\/neural-network.php\/build\/neuralnetwork\/storage\/A\/B\/C\/test.ex","exists":true},{"filename":"\/home\/xdrm-brackets\/Desktop\/git.xdrm.io\/neural-network.php\/build\/neuralnetwork\/storage\/A\/B\/C\/test.ln","exists":true}]}

View File

View File

@ -5,6 +5,8 @@
"genomes_kept": 2,
"mutation_threshold": 0.3,
"fitness_end": 1,
"storage": "_buffer"
"storage": "_buffer",
"hidden_layers": 2,
"layer_neurons": 3
}
}

View File

@ -2,28 +2,65 @@
require_once __ROOT__.'/autoloader.php';
use \neuralnetwork\core\Genome;
use \neuralnetwork\core\NeuralNetwork;
use \filemanager\core\FileManager;
function behaviour($abc){
return [($abc[0] & $abc[1]) ^ $abc[2]];
if( false && 'test_creating_dataset' ){
function behaviour($abc){
return [($abc[0] & $abc[1]) ^ $abc[2]];
}
echo "Welcome to neural-network.php\n";
echo "-----------------------------\n";
$nn = NeuralNetwork::create(50, 100);
$nn->setMaxValues([1, 1, 1], [1]);
$nn->setHiddenLayersCount(2);
$nn->setHiddenLayerNeuronsCount(3);
$d = [0, 0, 0]; $nn->addSample($d, behaviour($d));
$d = [0, 0, 1]; $nn->addSample($d, behaviour($d));
$d = [0, 1, 0]; $nn->addSample($d, behaviour($d));
$d = [0, 1, 1]; $nn->addSample($d, behaviour($d));
$d = [1, 0, 0]; $nn->addSample($d, behaviour($d));
$d = [1, 0, 1]; $nn->addSample($d, behaviour($d));
$d = [1, 1, 0]; $nn->addSample($d, behaviour($d));
$d = [1, 1, 1]; $nn->addSample($d, behaviour($d));
$nn->store('A/B/C/test', true);
}
echo "Welcome to neural-network.php\n";
echo "-----------------------------\n";
if( false && 'load_neural_network' ){
$nn = NeuralNetwork::create(50, 100);
$nn = NeuralNetwork::load('A/B/C/test');
$nn->setMaxValues([1, 1, 1], [1]);
}
$d = [0, 0, 0]; $nn->addSample($d, behaviour($d));
$d = [0, 0, 1]; $nn->addSample($d, behaviour($d));
$d = [0, 1, 0]; $nn->addSample($d, behaviour($d));
$d = [0, 1, 1]; $nn->addSample($d, behaviour($d));
$d = [1, 0, 0]; $nn->addSample($d, behaviour($d));
$d = [1, 0, 1]; $nn->addSample($d, behaviour($d));
$d = [1, 1, 0]; $nn->addSample($d, behaviour($d));
$d = [1, 1, 1]; $nn->addSample($d, behaviour($d));
if( true && 'test_genomes' ){
/* (1) Basic Creation */
$a = new Genome(2, 3); // 2 layers of 3 neurons each -> randomly filled
/* (2) Inheritance */
$b = new Genome($a); // Clone of @a
/* (3) Section Title */
// $b->mutation(0.3); // @b has now mutated with a threshold of 30%
/* (4) Cross-over (father+mother) */
$c = new Genome($a, $b); // @c is a randomly-done mix of @a and @b
}
// REWRITE TEST
// for( $a = 0, $al = 50 ; $a < $al ; $a++ )
// for( $b = 0, $bl = 20 ; $b < $bl ; $b++ ){
// print "genome $b/$bl on generation $a/$al \r";
// usleep(1000*10);
// }
?>