mirror of
https://github.com/fazo96/AIrium.git
synced 2025-01-10 09:34:20 +01:00
added some docs, refactored some code
This commit is contained in:
parent
3181272cae
commit
89edaf5b84
@ -4,14 +4,7 @@
|
||||
<auxiliary>
|
||||
<editor-bookmarks xmlns="http://www.netbeans.org/ns/editor-bookmarks/2" lastBookmarkId="0"/>
|
||||
<open-files xmlns="http://www.netbeans.org/ns/projectui-open-files/2">
|
||||
<group>
|
||||
<file>file:/home/fazo/Documents/Git/AIrium/core/src/logic/neural/NeuralConnection.java</file>
|
||||
<file>file:/home/fazo/Documents/Git/AIrium/core/src/com/mygdx/game/Game.java</file>
|
||||
<file>file:/home/fazo/Documents/Git/AIrium/core/src/logic/neural/Neuron.java</file>
|
||||
<file>file:/home/fazo/Documents/Git/AIrium/core/src/logic/Creature.java</file>
|
||||
<file>file:/home/fazo/Documents/Git/AIrium/core/src/logic/neural/Brain.java</file>
|
||||
<file>file:/home/fazo/Documents/Git/AIrium/core/src/logic/World.java</file>
|
||||
</group>
|
||||
<group/>
|
||||
</open-files>
|
||||
<editor-bookmarks lastBookmarkId="0" xmlns="http://www.netbeans.org/ns/editor-bookmarks/2"/>
|
||||
<open-files xmlns="http://www.netbeans.org/ns/projectui-open-files/2">
|
||||
|
@ -76,7 +76,7 @@ public class World {
|
||||
//graveyard.sort(creatureComp);
|
||||
int x = 0;
|
||||
for (Creature c : graveyard) {
|
||||
c.getBrain().mutate(5f);
|
||||
c.getBrain().getMutatedCopy(5f);
|
||||
if (x < creatPerGen) {
|
||||
c.setHp(100);
|
||||
creatures.add(c);
|
||||
|
@ -1,9 +1,9 @@
|
||||
package logic.neural;
|
||||
|
||||
import com.mygdx.game.Log;
|
||||
import java.util.ArrayList;
|
||||
|
||||
/**
|
||||
* Represents a virtual brain
|
||||
*
|
||||
* @author fazo
|
||||
*/
|
||||
@ -12,73 +12,119 @@ public class Brain {
|
||||
public static final float bias = 0.5f;
|
||||
private Neuron[][] neurons;
|
||||
|
||||
/**
|
||||
* Create a new brain with a random map (mind) with given number of neurons
|
||||
*
|
||||
* @param nInputs the number of input neurons (at least 1)
|
||||
* @param nOutputs the number of output neurons (at least 1)
|
||||
* @param hiddenLayers how many hidden layers of neurons (at least 1)
|
||||
* @param neuronsPerHiddenLayer how many neurons per hidden layer (at least
|
||||
* 1)
|
||||
*/
|
||||
public Brain(int nInputs, int nOutputs, int hiddenLayers, int neuronsPerHiddenLayer) {
|
||||
// Prepare brain map
|
||||
neurons = new Neuron[hiddenLayers + 2][];
|
||||
populate(nInputs, nOutputs, hiddenLayers, neuronsPerHiddenLayer);
|
||||
}
|
||||
|
||||
private void populate(int nInputs, int nOutputs, int hiddenLayers, int neuronsPerHiddenLayer) {
|
||||
// Create input neurons
|
||||
neurons[0] = new Neuron[nInputs];
|
||||
for (int i = 0; i < nInputs; i++) {
|
||||
neurons[0][i] = new Neuron(0, bias, this);
|
||||
Log.log(Log.DEBUG, "Adding Input Layer Neuron " + (i + 1));
|
||||
}
|
||||
// popiulate hidden layers
|
||||
neurons[hiddenLayers + 1] = new Neuron[nOutputs];
|
||||
for (int i = 0; i < hiddenLayers; i++) {
|
||||
neurons[i + 1] = new Neuron[neuronsPerHiddenLayer];
|
||||
for (int j = 0; j < neuronsPerHiddenLayer; j++) {
|
||||
}
|
||||
// Randomize brain
|
||||
initialize();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new brain using given brain map (mind)
|
||||
*
|
||||
* @param brainMap the brain map (mind) to use
|
||||
*/
|
||||
public Brain(float[][][] brainMap) {
|
||||
neurons = new Neuron[brainMap.length][];
|
||||
for (int i = 0; i < brainMap.length; i++) { // for each layer
|
||||
neurons[i] = new Neuron[brainMap[i].length];
|
||||
for (int j = 0; j < brainMap[i].length; j++) { // for each neuron
|
||||
neurons[i][j] = new Neuron(i, bias, this, brainMap[i][j]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply a new brain map (mind) to this brain
|
||||
*
|
||||
* @param brainMap the new brain map to apply
|
||||
*/
|
||||
public void remap(float[][][] brainMap) {
|
||||
for (int i = 0; i < brainMap.length; i++) { // for each layer
|
||||
for (int j = 0; j < brainMap[i].length; j++) { // for each neuron
|
||||
if (neurons[i][j] == null) {
|
||||
neurons[i][j] = new Neuron(j, bias, this, brainMap[i][j]);
|
||||
} else {
|
||||
neurons[i][j].setWeights(brainMap[i][j]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Populate the brain with brand new random neurons
|
||||
*/
|
||||
private void initialize() {
|
||||
// init hidden layers
|
||||
for (int i = 0; i < neurons.length; i++) {
|
||||
for (int j = 0; j < neurons[i].length; j++) {
|
||||
// create neuron
|
||||
Neuron n = new Neuron(i + 1, bias, this);
|
||||
neurons[i + 1][j] = n;
|
||||
Log.log(Log.DEBUG, "Adding Hidden Layer " + (i + 1) + " Neuron " + (j + 1));
|
||||
Neuron n = new Neuron(i, bias, this);
|
||||
neurons[i][j] = n;
|
||||
Log.log(Log.DEBUG, "Adding Layer " + (i + 1) + " Neuron " + (j + 1));
|
||||
}
|
||||
}
|
||||
// populate output layer
|
||||
neurons[hiddenLayers + 1] = new Neuron[nOutputs];
|
||||
for (int i = 0; i < nOutputs; i++) {
|
||||
// add neuron
|
||||
Neuron n = new Neuron(hiddenLayers + 1, bias, this);
|
||||
neurons[hiddenLayers + 1][i] = n;
|
||||
Log.log(Log.DEBUG, "Adding Output Layer Neuron " + (i + 1));
|
||||
}
|
||||
}
|
||||
|
||||
private float randWeight() {
|
||||
return (float) Math.random() * 5 - 2.5f;
|
||||
}
|
||||
|
||||
/**
|
||||
* Give some input to the brain
|
||||
*
|
||||
* @param values the array of input. Its length must match the number of
|
||||
* input neurons of this brain
|
||||
*/
|
||||
public void input(float[] values) {
|
||||
for (int i = 0; i < values.length; i++) {
|
||||
neurons[0][i].setOutput(values[i]);
|
||||
}
|
||||
clearCache();
|
||||
}
|
||||
|
||||
/**
|
||||
* Compute output of the brain starting from given input
|
||||
*
|
||||
* @return an array as long as the number of output neurons, containing the
|
||||
* result
|
||||
*/
|
||||
public float[] compute() {
|
||||
clearCache();
|
||||
//clearCache(); // unnecessary if already called when changing inputs
|
||||
float[] res = new float[neurons[neurons.length - 1].length];
|
||||
for (int i = 0; i < neurons[neurons.length - 1].length; i++) {
|
||||
Neuron n = neurons[neurons.length - 1][i];
|
||||
if (n != null) {
|
||||
res[i] = n.compute();
|
||||
}
|
||||
res[i] = neurons[neurons.length - 1][i].compute();
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
public void map(float[][][] map) {
|
||||
// Populate with new neurons
|
||||
for (int j = 0; j < map.length; j++) {
|
||||
for (int i = 0; i < map[j].length; i++) {
|
||||
if (map[j] == null || map[i] == null) {
|
||||
continue;
|
||||
}
|
||||
neurons[j][i] = new Neuron(j, bias, this);
|
||||
neurons[j][i].setWeights(map[j][i]);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Input some values (see input function) and then compute the results.
|
||||
*
|
||||
* @param values
|
||||
* @return the results of the neural network
|
||||
*/
|
||||
public float[] compute(float[] values) {
|
||||
input(values);
|
||||
return compute();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a brainMap that represents this brain's mind
|
||||
*
|
||||
* @return a tridimensional floating point number array representing a full
|
||||
* mind
|
||||
*/
|
||||
public float[][][] getMap() {
|
||||
float[][][] res = new float[neurons.length][neurons[1].length][neurons[1].length];
|
||||
for (int i = 0; i < neurons.length; i++) // layers
|
||||
@ -94,7 +140,13 @@ public class Brain {
|
||||
return res;
|
||||
}
|
||||
|
||||
public float[][][] mutate(float mutationFactor) {
|
||||
/**
|
||||
* Get a map of this brain's mind.. with a mutation
|
||||
*
|
||||
* @param mutationFactor the highest this number, the bigger the mutation
|
||||
* @return a mutated brain map of this brain's mind
|
||||
*/
|
||||
public float[][][] getMutatedMap(float mutationFactor) {
|
||||
float[][][] res = new float[neurons.length][][];
|
||||
for (int i = 0; i < neurons.length; i++) // layers
|
||||
{
|
||||
@ -107,6 +159,10 @@ public class Brain {
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* Empties the neurons' cache. Needs to be called after changing brain
|
||||
* inputs or before computing the result.
|
||||
*/
|
||||
private void clearCache() {
|
||||
for (int i = 1; i < neurons.length; i++) {
|
||||
for (int j = 0; j < neurons[i].length; j++) {
|
||||
@ -115,6 +171,11 @@ public class Brain {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an array with pointers to all this brain's neurons.
|
||||
*
|
||||
* @return bidimensional array with first index representing the layer.
|
||||
*/
|
||||
public Neuron[][] getNeurons() {
|
||||
return neurons;
|
||||
}
|
||||
|
@ -57,8 +57,6 @@ public class Neuron {
|
||||
}
|
||||
float a = bias * -1; // activation
|
||||
for (int i = 0; i < weights.length; i++) {
|
||||
//if(brain == null) System.out.println("BRAINS NULL"); else if(brain.getNeurons() == null) System.out.println("NEURONS NULL");
|
||||
//System.out.println(Arrays.toString(brain.getNeurons()));
|
||||
if (cache.has(i)) {
|
||||
try {
|
||||
return cache.get(i);
|
||||
@ -97,7 +95,7 @@ public class Neuron {
|
||||
this.bias = bias;
|
||||
}
|
||||
|
||||
public boolean isIsInputNeuron() {
|
||||
public boolean isInputNeuron() {
|
||||
return isInputNeuron;
|
||||
}
|
||||
|
||||
@ -115,6 +113,8 @@ public class Neuron {
|
||||
|
||||
public void setWeights(float[] weights) {
|
||||
this.weights = weights;
|
||||
// Changing the neuron makes the cache invalid
|
||||
clearCache();
|
||||
}
|
||||
|
||||
public void clearCache() {
|
||||
|
@ -1,11 +1,7 @@
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package logic.neural;
|
||||
|
||||
/**
|
||||
* Used by neurons to cache inputs for faster NN evaluation performance.
|
||||
*
|
||||
* @author fazo
|
||||
*/
|
||||
@ -14,17 +10,35 @@ public class NeuronCache {
|
||||
private float[] cache;
|
||||
private boolean[] validity;
|
||||
|
||||
/**
|
||||
* Create a new empty input cache with given size.
|
||||
*
|
||||
* @param size how many inputs the requiring neuron has.
|
||||
*/
|
||||
public NeuronCache(int size) {
|
||||
cache = new float[size];
|
||||
validity = new boolean[size];
|
||||
clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* Put a value in the cache.
|
||||
*
|
||||
* @param index the index of the value
|
||||
* @param value the value itself
|
||||
*/
|
||||
public void put(int index, float value) {
|
||||
validity[index] = true;
|
||||
cache[index] = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read a value from the cache.
|
||||
*
|
||||
* @param index the index of the value
|
||||
* @return the value required
|
||||
* @throws Exception if value not stored or declared invalid
|
||||
*/
|
||||
public float get(int index) throws Exception {
|
||||
if (validity[index]) {
|
||||
return cache[index];
|
||||
@ -33,10 +47,19 @@ public class NeuronCache {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if required value is present and valid in the cache.
|
||||
*
|
||||
* @param index which value to check
|
||||
* @return true if has given value
|
||||
*/
|
||||
public boolean has(int index) {
|
||||
return validity[index];
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears cache.
|
||||
*/
|
||||
public void clear() {
|
||||
for (int i = 0; i < cache.length; i++) {
|
||||
validity[i] = false;
|
||||
|
Loading…
Reference in New Issue
Block a user