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>
|
<auxiliary>
|
||||||
<editor-bookmarks xmlns="http://www.netbeans.org/ns/editor-bookmarks/2" lastBookmarkId="0"/>
|
<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">
|
<open-files xmlns="http://www.netbeans.org/ns/projectui-open-files/2">
|
||||||
<group>
|
<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>
|
|
||||||
</open-files>
|
</open-files>
|
||||||
<editor-bookmarks lastBookmarkId="0" xmlns="http://www.netbeans.org/ns/editor-bookmarks/2"/>
|
<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">
|
<open-files xmlns="http://www.netbeans.org/ns/projectui-open-files/2">
|
||||||
|
@ -76,7 +76,7 @@ public class World {
|
|||||||
//graveyard.sort(creatureComp);
|
//graveyard.sort(creatureComp);
|
||||||
int x = 0;
|
int x = 0;
|
||||||
for (Creature c : graveyard) {
|
for (Creature c : graveyard) {
|
||||||
c.getBrain().mutate(5f);
|
c.getBrain().getMutatedCopy(5f);
|
||||||
if (x < creatPerGen) {
|
if (x < creatPerGen) {
|
||||||
c.setHp(100);
|
c.setHp(100);
|
||||||
creatures.add(c);
|
creatures.add(c);
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
package logic.neural;
|
package logic.neural;
|
||||||
|
|
||||||
import com.mygdx.game.Log;
|
import com.mygdx.game.Log;
|
||||||
import java.util.ArrayList;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Represents a virtual brain
|
||||||
*
|
*
|
||||||
* @author fazo
|
* @author fazo
|
||||||
*/
|
*/
|
||||||
@ -12,73 +12,119 @@ public class Brain {
|
|||||||
public static final float bias = 0.5f;
|
public static final float bias = 0.5f;
|
||||||
private Neuron[][] neurons;
|
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) {
|
public Brain(int nInputs, int nOutputs, int hiddenLayers, int neuronsPerHiddenLayer) {
|
||||||
|
// Prepare brain map
|
||||||
neurons = new Neuron[hiddenLayers + 2][];
|
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];
|
neurons[0] = new Neuron[nInputs];
|
||||||
for (int i = 0; i < nInputs; i++) {
|
neurons[hiddenLayers + 1] = new Neuron[nOutputs];
|
||||||
neurons[0][i] = new Neuron(0, bias, this);
|
|
||||||
Log.log(Log.DEBUG, "Adding Input Layer Neuron " + (i + 1));
|
|
||||||
}
|
|
||||||
// popiulate hidden layers
|
|
||||||
for (int i = 0; i < hiddenLayers; i++) {
|
for (int i = 0; i < hiddenLayers; i++) {
|
||||||
neurons[i + 1] = new Neuron[neuronsPerHiddenLayer];
|
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
|
// create neuron
|
||||||
Neuron n = new Neuron(i + 1, bias, this);
|
Neuron n = new Neuron(i, bias, this);
|
||||||
neurons[i + 1][j] = n;
|
neurons[i][j] = n;
|
||||||
Log.log(Log.DEBUG, "Adding Hidden Layer " + (i + 1) + " Neuron " + (j + 1));
|
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) {
|
public void input(float[] values) {
|
||||||
for (int i = 0; i < values.length; i++) {
|
for (int i = 0; i < values.length; i++) {
|
||||||
neurons[0][i].setOutput(values[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() {
|
public float[] compute() {
|
||||||
clearCache();
|
//clearCache(); // unnecessary if already called when changing inputs
|
||||||
float[] res = new float[neurons[neurons.length - 1].length];
|
float[] res = new float[neurons[neurons.length - 1].length];
|
||||||
for (int i = 0; i < neurons[neurons.length - 1].length; i++) {
|
for (int i = 0; i < neurons[neurons.length - 1].length; i++) {
|
||||||
Neuron n = neurons[neurons.length - 1][i];
|
res[i] = neurons[neurons.length - 1][i].compute();
|
||||||
if (n != null) {
|
|
||||||
res[i] = n.compute();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void map(float[][][] map) {
|
/**
|
||||||
// Populate with new neurons
|
* Input some values (see input function) and then compute the results.
|
||||||
for (int j = 0; j < map.length; j++) {
|
*
|
||||||
for (int i = 0; i < map[j].length; i++) {
|
* @param values
|
||||||
if (map[j] == null || map[i] == null) {
|
* @return the results of the neural network
|
||||||
continue;
|
*/
|
||||||
}
|
public float[] compute(float[] values) {
|
||||||
neurons[j][i] = new Neuron(j, bias, this);
|
input(values);
|
||||||
neurons[j][i].setWeights(map[j][i]);
|
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() {
|
public float[][][] getMap() {
|
||||||
float[][][] res = new float[neurons.length][neurons[1].length][neurons[1].length];
|
float[][][] res = new float[neurons.length][neurons[1].length][neurons[1].length];
|
||||||
for (int i = 0; i < neurons.length; i++) // layers
|
for (int i = 0; i < neurons.length; i++) // layers
|
||||||
@ -94,7 +140,13 @@ public class Brain {
|
|||||||
return res;
|
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][][];
|
float[][][] res = new float[neurons.length][][];
|
||||||
for (int i = 0; i < neurons.length; i++) // layers
|
for (int i = 0; i < neurons.length; i++) // layers
|
||||||
{
|
{
|
||||||
@ -107,6 +159,10 @@ public class Brain {
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Empties the neurons' cache. Needs to be called after changing brain
|
||||||
|
* inputs or before computing the result.
|
||||||
|
*/
|
||||||
private void clearCache() {
|
private void clearCache() {
|
||||||
for (int i = 1; i < neurons.length; i++) {
|
for (int i = 1; i < neurons.length; i++) {
|
||||||
for (int j = 0; j < neurons[i].length; j++) {
|
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() {
|
public Neuron[][] getNeurons() {
|
||||||
return neurons;
|
return neurons;
|
||||||
}
|
}
|
||||||
|
@ -57,8 +57,6 @@ public class Neuron {
|
|||||||
}
|
}
|
||||||
float a = bias * -1; // activation
|
float a = bias * -1; // activation
|
||||||
for (int i = 0; i < weights.length; i++) {
|
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)) {
|
if (cache.has(i)) {
|
||||||
try {
|
try {
|
||||||
return cache.get(i);
|
return cache.get(i);
|
||||||
@ -97,7 +95,7 @@ public class Neuron {
|
|||||||
this.bias = bias;
|
this.bias = bias;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isIsInputNeuron() {
|
public boolean isInputNeuron() {
|
||||||
return isInputNeuron;
|
return isInputNeuron;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -115,6 +113,8 @@ public class Neuron {
|
|||||||
|
|
||||||
public void setWeights(float[] weights) {
|
public void setWeights(float[] weights) {
|
||||||
this.weights = weights;
|
this.weights = weights;
|
||||||
|
// Changing the neuron makes the cache invalid
|
||||||
|
clearCache();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void 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;
|
package logic.neural;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Used by neurons to cache inputs for faster NN evaluation performance.
|
||||||
*
|
*
|
||||||
* @author fazo
|
* @author fazo
|
||||||
*/
|
*/
|
||||||
@ -14,17 +10,35 @@ public class NeuronCache {
|
|||||||
private float[] cache;
|
private float[] cache;
|
||||||
private boolean[] validity;
|
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) {
|
public NeuronCache(int size) {
|
||||||
cache = new float[size];
|
cache = new float[size];
|
||||||
validity = new boolean[size];
|
validity = new boolean[size];
|
||||||
clear();
|
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) {
|
public void put(int index, float value) {
|
||||||
validity[index] = true;
|
validity[index] = true;
|
||||||
cache[index] = value;
|
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 {
|
public float get(int index) throws Exception {
|
||||||
if (validity[index]) {
|
if (validity[index]) {
|
||||||
return cache[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) {
|
public boolean has(int index) {
|
||||||
return validity[index];
|
return validity[index];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clears cache.
|
||||||
|
*/
|
||||||
public void clear() {
|
public void clear() {
|
||||||
for (int i = 0; i < cache.length; i++) {
|
for (int i = 0; i < cache.length; i++) {
|
||||||
validity[i] = false;
|
validity[i] = false;
|
||||||
|
Loading…
Reference in New Issue
Block a user