removed synapse type
This commit is contained in:
parent
145e033d4c
commit
a3d49e330f
@ -26,6 +26,7 @@ public class NanoBrain_Editor : Editor {
|
|||||||
Debug.Log($"Layercount = {this.layers.Count}");
|
Debug.Log($"Layercount = {this.layers.Count}");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#endregion Start
|
#endregion Start
|
||||||
|
|
||||||
#region Update
|
#region Update
|
||||||
@ -46,10 +47,10 @@ public class NanoBrain_Editor : Editor {
|
|||||||
return;
|
return;
|
||||||
NeuroidLayer currentLayer = new() { ix = layerIx };
|
NeuroidLayer currentLayer = new() { ix = layerIx };
|
||||||
|
|
||||||
foreach (Neuroid outputNeuroid in selectedNucleus.outputNeuroids) {
|
foreach (Neuroid outputNeuroid in selectedNucleus.receivers) {
|
||||||
if (outputNeuroid != null) {
|
if (outputNeuroid != null) {
|
||||||
AddToLayer(currentLayer, outputNeuroid);
|
AddToLayer(currentLayer, outputNeuroid);
|
||||||
Debug.Log($"layer {layerIx} nucleus {outputNeuroid.name}");
|
// Debug.Log($"layer {layerIx} nucleus {outputNeuroid.name}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (currentLayer.neuroids.Count > 0) {
|
if (currentLayer.neuroids.Count > 0) {
|
||||||
@ -60,14 +61,14 @@ public class NanoBrain_Editor : Editor {
|
|||||||
|
|
||||||
AddToLayer(currentLayer, selectedNucleus);
|
AddToLayer(currentLayer, selectedNucleus);
|
||||||
this.layers.Add(currentLayer);
|
this.layers.Add(currentLayer);
|
||||||
Debug.Log($"layer {layerIx} nucleus {selectedNucleus.name}");
|
// Debug.Log($"layer {layerIx} nucleus {selectedNucleus.name}");
|
||||||
|
|
||||||
layerIx++;
|
layerIx++;
|
||||||
currentLayer = new() { ix = layerIx };
|
currentLayer = new() { ix = layerIx };
|
||||||
|
|
||||||
foreach (Nucleus input in selectedNucleus.synapses.Keys) {
|
foreach (Nucleus input in selectedNucleus.synapses.Keys) {
|
||||||
AddToLayer(currentLayer, input);
|
AddToLayer(currentLayer, input);
|
||||||
Debug.Log($"layer {layerIx} nucleus {input.name}");
|
// Debug.Log($"layer {layerIx} nucleus {input.name}");
|
||||||
}
|
}
|
||||||
if (currentLayer.neuroids.Count > 0) {
|
if (currentLayer.neuroids.Count > 0) {
|
||||||
this.layers.Add(currentLayer);
|
this.layers.Add(currentLayer);
|
||||||
@ -110,32 +111,32 @@ public class NanoBrain_Editor : Editor {
|
|||||||
Vector2Int layerNeuroidPos = this.neuroidPositions[layerNeuroid];
|
Vector2Int layerNeuroidPos = this.neuroidPositions[layerNeuroid];
|
||||||
Vector3 parentPos = new(100 + layerNeuroidPos.x * 100, margin + layerNeuroidPos.y * spacing, 0.1f);
|
Vector3 parentPos = new(100 + layerNeuroidPos.x * 100, margin + layerNeuroidPos.y * spacing, 0.1f);
|
||||||
|
|
||||||
int i = 0;
|
//int i = 0;
|
||||||
float inputSpacing = 400f / layerNeuroid.synapses.Count;
|
float inputSpacing = 400f / layerNeuroid.synapses.Count;
|
||||||
float inputMargin = 10 + inputSpacing / 2;
|
float inputMargin = 10 + inputSpacing / 2;
|
||||||
// foreach (Synapse synapse in layerNeuroid.synapses.Values) {
|
int minStale = 10000;
|
||||||
// if (synapse.neuroid != null) {
|
foreach ((Nucleus nucleus, float weight) in layerNeuroid.synapses) {
|
||||||
// if (this.neuroidPositions.ContainsKey(synapse.neuroid)) {
|
if (this.neuroidPositions.ContainsKey(nucleus)) {
|
||||||
|
Vector2Int inputNeuroidPos = this.neuroidPositions[nucleus];
|
||||||
// Vector2Int inputNeuroidPos = this.neuroidPositions[synapse.neuroid];
|
|
||||||
foreach ((Nucleus neuroid, Synapse synapse) in layerNeuroid.synapses) {
|
|
||||||
if (neuroid != null) {
|
|
||||||
if (this.neuroidPositions.ContainsKey(neuroid)) {
|
|
||||||
Vector2Int inputNeuroidPos = this.neuroidPositions[neuroid];
|
|
||||||
if (inputNeuroidPos.x == layerNeuroidPos.x + 1) {
|
if (inputNeuroidPos.x == layerNeuroidPos.x + 1) {
|
||||||
Vector3 pos = new(100 + inputNeuroidPos.x * 100, inputMargin + inputNeuroidPos.y * inputSpacing, 0.0f);
|
Vector3 pos = new(100 + inputNeuroidPos.x * 100, inputMargin + inputNeuroidPos.y * inputSpacing, 0.0f);
|
||||||
|
|
||||||
float brightness = synapse.weight / 10.0f;
|
float brightness = weight / 10.0f;
|
||||||
Handles.color = new Color(brightness, brightness, brightness);
|
Handles.color = new Color(brightness, brightness, brightness);
|
||||||
Handles.DrawLine(parentPos, pos);
|
Handles.DrawLine(parentPos, pos);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (nucleus is Neuroid neuroid && neuroid.stale < minStale)
|
||||||
|
minStale = neuroid.stale;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
if (layerNeuroid.synapses.Count > 0 && minStale > 2 && layerNeuroid.stale < 3)
|
||||||
|
Debug.LogWarning($"Strange {minStale} is big duing update");
|
||||||
|
|
||||||
|
|
||||||
float size = 20;
|
float size = 20;
|
||||||
if (layerNeuroid.IsStale())
|
if (layerNeuroid.IsStale())
|
||||||
Handles.color = Color.black;
|
Handles.color = Color.darkCyan;
|
||||||
else {
|
else {
|
||||||
float brightness = layerNeuroid.outputValue.magnitude / maxValue;
|
float brightness = layerNeuroid.outputValue.magnitude / maxValue;
|
||||||
Handles.color = new Color(brightness, brightness, brightness);
|
Handles.color = new Color(brightness, brightness, brightness);
|
||||||
@ -154,16 +155,16 @@ public class NanoBrain_Editor : Editor {
|
|||||||
Event e = Event.current;
|
Event e = Event.current;
|
||||||
EventType et = e.GetTypeForControl(id);
|
EventType et = e.GetTypeForControl(id);
|
||||||
if (e != null && neuronRect.Contains(e.mousePosition)) {
|
if (e != null && neuronRect.Contains(e.mousePosition)) {
|
||||||
|
// Process Hover
|
||||||
HandleMouseHover(layerNeuroid, neuronRect);
|
HandleMouseHover(layerNeuroid, neuronRect);
|
||||||
// Process click
|
// Process click
|
||||||
Debug.Log($"{et}");
|
|
||||||
if (et == EventType.MouseDown && e.button == 0) {
|
if (et == EventType.MouseDown && e.button == 0) {
|
||||||
// Consume the event so the scene doesn't also handle it
|
// Consume the event so the scene doesn't also handle it
|
||||||
e.Use();
|
e.Use();
|
||||||
HandleDiscClicked(layerNeuroid);
|
HandleDiscClicked(layerNeuroid);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
i++;
|
//i++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -199,5 +200,19 @@ public class NanoBrain_Editor : Editor {
|
|||||||
BuildLayers();
|
BuildLayers();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected virtual void OnSceneGUI() {
|
||||||
|
NanoBrain brain = target as NanoBrain;
|
||||||
|
if (brain == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Debug.DrawRay(brain.transform.position, Vector3.forward, Color.magenta);
|
||||||
|
// Handles.color = Color.green;
|
||||||
|
// Handles.DrawLine(brain.transform.position, brain.transform.position + Vector3.up);
|
||||||
|
Vector3 position = brain.transform.position;
|
||||||
|
Handles.color = Color.yellow;
|
||||||
|
Vector3 worldForce = brain.transform.TransformDirection(this.currentNucleus.outputValue);
|
||||||
|
Debug.DrawRay(position, worldForce * 10, Color.yellow);
|
||||||
|
}
|
||||||
|
|
||||||
#endregion Update
|
#endregion Update
|
||||||
}
|
}
|
||||||
|
|||||||
@ -40,7 +40,7 @@ public class GraphEditorWindow : EditorWindow {
|
|||||||
return;
|
return;
|
||||||
NeuroidLayer currentLayer = new() { ix = layerIx };
|
NeuroidLayer currentLayer = new() { ix = layerIx };
|
||||||
|
|
||||||
foreach (Neuroid outputNeuroid in selectedNucleus.outputNeuroids) {
|
foreach (Neuroid outputNeuroid in selectedNucleus.receivers) {
|
||||||
if (outputNeuroid != null) {
|
if (outputNeuroid != null) {
|
||||||
AddToLayer(currentLayer, outputNeuroid);
|
AddToLayer(currentLayer, outputNeuroid);
|
||||||
Debug.Log($"layer {layerIx} nucleus {outputNeuroid.name}");
|
Debug.Log($"layer {layerIx} nucleus {outputNeuroid.name}");
|
||||||
@ -63,7 +63,8 @@ public class GraphEditorWindow : EditorWindow {
|
|||||||
// foreach (Synapse synapse in selectedNucleus.synapses.Values) {
|
// foreach (Synapse synapse in selectedNucleus.synapses.Values) {
|
||||||
// Debug.Log($"Synapse {six}");
|
// Debug.Log($"Synapse {six}");
|
||||||
// Nucleus input = synapse.neuroid;
|
// Nucleus input = synapse.neuroid;
|
||||||
foreach ((Nucleus input, Synapse synapse) in selectedNucleus.synapses) {
|
//foreach ((Nucleus input, Synapse synapse) in selectedNucleus.synapses) {
|
||||||
|
foreach ((Nucleus input, float weight) in selectedNucleus.synapses) {
|
||||||
if (input != null) {
|
if (input != null) {
|
||||||
AddToLayer(currentLayer, input);
|
AddToLayer(currentLayer, input);
|
||||||
Debug.Log($"layer {layerIx} nucleus {input.name}");
|
Debug.Log($"layer {layerIx} nucleus {input.name}");
|
||||||
@ -103,8 +104,8 @@ public class GraphEditorWindow : EditorWindow {
|
|||||||
|
|
||||||
// If the output neuroid is visited
|
// If the output neuroid is visited
|
||||||
// Note: this does not yet work for multiple outputs yet (see the use of First())
|
// Note: this does not yet work for multiple outputs yet (see the use of First())
|
||||||
if (neuroid.outputNeuroids.Count == 0 // make sure the root neuroids are processed directly
|
if (neuroid.receivers.Count == 0 // make sure the root neuroids are processed directly
|
||||||
|| (neuronVisited.Contains(neuroid.outputNeuroids.First()) && neuroid.outputNeuroids.First().layerIx == layerIx - 1)) {
|
|| (neuronVisited.Contains(neuroid.receivers.First()) && neuroid.receivers.First().layerIx == layerIx - 1)) {
|
||||||
// Add it to the next layer
|
// Add it to the next layer
|
||||||
currentLayer.neuroids.Add(neuroid);
|
currentLayer.neuroids.Add(neuroid);
|
||||||
neuroid.layerIx = layerIx;
|
neuroid.layerIx = layerIx;
|
||||||
@ -180,14 +181,16 @@ public class GraphEditorWindow : EditorWindow {
|
|||||||
// if (this.neuroidPositions.ContainsKey(synapse.neuroid)) {
|
// if (this.neuroidPositions.ContainsKey(synapse.neuroid)) {
|
||||||
|
|
||||||
// Vector2Int inputNeuroidPos = this.neuroidPositions[synapse.neuroid];
|
// Vector2Int inputNeuroidPos = this.neuroidPositions[synapse.neuroid];
|
||||||
foreach ((Nucleus neuroid, Synapse synapse) in layerNeuroid.synapses) {
|
//foreach ((Nucleus neuroid, Synapse synapse) in layerNeuroid.synapses) {
|
||||||
|
foreach ((Nucleus neuroid, float weight) in layerNeuroid.synapses) {
|
||||||
if (neuroid != null) {
|
if (neuroid != null) {
|
||||||
if (this.neuroidPositions.ContainsKey(neuroid)) {
|
if (this.neuroidPositions.ContainsKey(neuroid)) {
|
||||||
Vector2Int inputNeuroidPos = this.neuroidPositions[neuroid];
|
Vector2Int inputNeuroidPos = this.neuroidPositions[neuroid];
|
||||||
if (inputNeuroidPos.x == layerNeuroidPos.x + 1) {
|
if (inputNeuroidPos.x == layerNeuroidPos.x + 1) {
|
||||||
Vector3 pos = new(100 + inputNeuroidPos.x * 100, inputMargin + inputNeuroidPos.y * inputSpacing, 0.0f);
|
Vector3 pos = new(100 + inputNeuroidPos.x * 100, inputMargin + inputNeuroidPos.y * inputSpacing, 0.0f);
|
||||||
|
|
||||||
float brightness = synapse.weight / 10.0f;
|
//float brightness = synapse.weight / 10.0f;
|
||||||
|
float brightness = weight / 10.0f;
|
||||||
Handles.color = new Color(brightness, brightness, brightness);
|
Handles.color = new Color(brightness, brightness, brightness);
|
||||||
Handles.DrawLine(parentPos, pos);
|
Handles.DrawLine(parentPos, pos);
|
||||||
}
|
}
|
||||||
@ -274,7 +277,7 @@ public class GraphEditorWindow : EditorWindow {
|
|||||||
if (neuroid == null)
|
if (neuroid == null)
|
||||||
this.allNeuroids = new();
|
this.allNeuroids = new();
|
||||||
else
|
else
|
||||||
this.allNeuroids = neuroid.net.neuroids;
|
this.allNeuroids = neuroid.brain.neuroids;
|
||||||
|
|
||||||
|
|
||||||
Debug.Log($"Neuroncount = {this.allNeuroids.Count}");
|
Debug.Log($"Neuroncount = {this.allNeuroids.Count}");
|
||||||
|
|||||||
@ -9,7 +9,7 @@ public class NanoBrain : MonoBehaviour {
|
|||||||
return neuroid;
|
return neuroid;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Update() {
|
public void UpdateNeurons() {
|
||||||
foreach (Neuroid neuroid in neuroids) {
|
foreach (Neuroid neuroid in neuroids) {
|
||||||
neuroid.stale++;
|
neuroid.stale++;
|
||||||
if (neuroid.IsStale())
|
if (neuroid.IsStale())
|
||||||
|
|||||||
@ -1,137 +1,90 @@
|
|||||||
using System.Collections.Generic;
|
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using System.Linq;
|
|
||||||
|
|
||||||
public class Synapse {
|
|
||||||
public Synapse(Nucleus neuroid, float weight = 1.0f) {
|
|
||||||
//this.neuroid = neuroid;
|
|
||||||
this.weight = weight;
|
|
||||||
}
|
|
||||||
//public Nucleus neuroid;
|
|
||||||
public float weight;
|
|
||||||
}
|
|
||||||
|
|
||||||
// public class NeuroidNetwork {
|
|
||||||
// public List<Neuroid> neuroids = new();
|
|
||||||
|
|
||||||
// public Neuroid AddNeuron(string name) {
|
|
||||||
// Neuroid neuroid = new(this, name);
|
|
||||||
// return neuroid;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// public void Update() {
|
|
||||||
// foreach (Neuroid neuroid in neuroids) {
|
|
||||||
// neuroid.stale++;
|
|
||||||
// if (neuroid.IsStale())
|
|
||||||
// neuroid.outputValue = Vector3.zero;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
public class Neuroid : Nucleus {
|
public class Neuroid : Nucleus {
|
||||||
public int stale = 0;
|
public int stale = 0;
|
||||||
|
|
||||||
//public Vector3 outputValue;
|
|
||||||
|
|
||||||
public bool average = false;
|
public bool average = false;
|
||||||
//public bool quadratic = false;
|
|
||||||
public bool inverse = false;
|
public bool inverse = false;
|
||||||
public float exponent = 1.0f;
|
public float exponent = 1.0f;
|
||||||
|
|
||||||
//public NeuroidNetwork net;
|
public NanoBrain brain;
|
||||||
public NanoBrain net;
|
|
||||||
|
|
||||||
// public Neuroid(NeuroidNetwork net, string name) : base(name) {
|
public Neuroid(NanoBrain brain, string name) : base(name) {
|
||||||
public Neuroid(NanoBrain net, string name) : base(name) {
|
this.brain = brain;
|
||||||
this.net = net;
|
if (this.brain != null)
|
||||||
if (this.net != null)
|
this.brain.neuroids.Add(this);
|
||||||
this.net.neuroids.Add(this);
|
|
||||||
else
|
else
|
||||||
Debug.LogError("No neuroid network");
|
Debug.LogError("No neuroid network");
|
||||||
}
|
}
|
||||||
|
|
||||||
public void AddSynapse(Neuroid input) {
|
public void AddSynapse(Neuroid input) {
|
||||||
input.AddReceiver(this);
|
input.AddReceiver(this);
|
||||||
this.synapses[input] = new(input);
|
this.synapses[input] = 1.0f;
|
||||||
}
|
|
||||||
|
|
||||||
// public void AddReceiver(Neuroid receiver) {
|
|
||||||
// this.outputNeuroids.Add(receiver);
|
|
||||||
// }
|
|
||||||
|
|
||||||
public void ResetWeights() {
|
|
||||||
foreach (Synapse synapse in this.synapses.Values)
|
|
||||||
synapse.weight = 1.0f;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetWeight(Neuroid input, float weight) {
|
public void SetWeight(Neuroid input, float weight) {
|
||||||
if (this.synapses.ContainsKey(input)) {
|
this.synapses[input] = weight;
|
||||||
this.synapses[input].weight = weight;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
this.synapses[input] = new(input, weight);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void GetInputFrom(Neuroid input, float weight = 1.0f) {
|
public void GetInputFrom(Neuroid input, float weight = 1.0f) {
|
||||||
input.AddReceiver(this);
|
input.AddReceiver(this);
|
||||||
this.synapses[input] = new(input, weight);
|
this.synapses[input] = weight;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetInput(Neuroid input) {
|
public void SetInput(Neuroid input) {
|
||||||
if (this.synapses.ContainsKey(input) == false)
|
if (this.synapses.ContainsKey(input) == false)
|
||||||
this.synapses[input] = new(input);
|
this.synapses[input] = 1.0f;
|
||||||
UpdateState();
|
UpdateState();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetInput(Neuroid input, float weight) {
|
public void SetInput(Neuroid input, float weight) {
|
||||||
if (this.synapses.ContainsKey(input)) {
|
this.synapses[input] = weight;
|
||||||
Synapse synapse = this.synapses[input];
|
|
||||||
synapse.weight = weight;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
this.synapses[input] = new(input, weight);
|
|
||||||
UpdateState();
|
UpdateState();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void RemoveInputFrom(Neuroid input) {
|
public void RemoveInputFrom(Neuroid input) {
|
||||||
|
if (this.synapses.Count == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
this.synapses.Remove(input);
|
this.synapses.Remove(input);
|
||||||
if (this.synapses.Count == 0) {
|
if (this.synapses.Count == 0) {
|
||||||
// In case this was the last synapse, we reset the output because in this case no updates from synapses will follow.
|
// In case this was the last synapse, we reset the output because in this case no updates from synapses will follow.
|
||||||
this.outputValue = Vector3.zero;
|
this.outputValue = Vector3.zero;
|
||||||
foreach (Neuroid neuroid in this.outputNeuroids)
|
foreach (Neuroid neuroid in this.receivers)
|
||||||
neuroid.SetInput(this);
|
neuroid.SetInput(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual void UpdateState() {
|
public virtual void UpdateState() {
|
||||||
|
// int minStale = 10000;
|
||||||
Vector3 result = Vector3.zero;
|
Vector3 result = Vector3.zero;
|
||||||
foreach ((Nucleus nucleus, Synapse synapse) in this.synapses) {
|
foreach ((Nucleus nucleus, float weight) in this.synapses) {
|
||||||
// foreach (Synapse synapse in this.synapses.Values) {
|
if (nucleus is Neuroid neuroid && neuroid.IsStale())
|
||||||
// if (synapse.neuroid == null)
|
continue;
|
||||||
// Debug.LogWarning(" disconnected synapse");
|
|
||||||
// if (synapse.value != synapse.neuroid.outputValue)
|
|
||||||
// Debug.LogWarning("synapse value error");
|
|
||||||
// Vector3 direction = synapse.value.normalized;
|
|
||||||
// float magnitude = synapse.value.magnitude;
|
|
||||||
|
|
||||||
// Vector3 direction = synapse.neuroid.outputValue.normalized;
|
|
||||||
// float magnitude = synapse.neuroid.outputValue.magnitude;
|
|
||||||
Vector3 direction = nucleus.outputValue.normalized;
|
Vector3 direction = nucleus.outputValue.normalized;
|
||||||
float magnitude = nucleus.outputValue.magnitude;
|
float magnitude = nucleus.outputValue.magnitude;
|
||||||
|
|
||||||
magnitude = synapse.weight * Mathf.Pow(magnitude, exponent);
|
magnitude = weight * Mathf.Pow(magnitude, exponent);
|
||||||
if (inverse && magnitude > 0)
|
if (inverse && magnitude > 0)
|
||||||
magnitude = 1 / magnitude;
|
magnitude = 1 / magnitude;
|
||||||
result += direction * magnitude;
|
result += direction * magnitude;
|
||||||
|
|
||||||
|
// if (nucleus is Neuroid neuroid && neuroid.stale < minStale)
|
||||||
|
// minStale = neuroid.stale;
|
||||||
}
|
}
|
||||||
if (average && this.synapses.Count > 0)
|
if (average && this.synapses.Count > 0)
|
||||||
result /= this.synapses.Count;
|
result /= this.synapses.Count;
|
||||||
|
|
||||||
this.outputValue = result;
|
this.outputValue = result;
|
||||||
foreach (Neuroid neuroid in this.outputNeuroids)
|
|
||||||
neuroid.SetInput(this);
|
// if (minStale > 2)
|
||||||
|
// Debug.LogWarning($"Strange {minStale} is big duing update");
|
||||||
this.stale = 0;
|
this.stale = 0;
|
||||||
|
|
||||||
|
foreach (Neuroid receiver in this.receivers)
|
||||||
|
receiver.SetInput(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool IsStale() {
|
public bool IsStale() {
|
||||||
|
|||||||
@ -4,8 +4,8 @@ using UnityEngine;
|
|||||||
public class Nucleus {
|
public class Nucleus {
|
||||||
public string name;
|
public string name;
|
||||||
|
|
||||||
public readonly Dictionary<Nucleus, Synapse> synapses = new();
|
public readonly Dictionary<Nucleus, float> synapses = new();
|
||||||
public HashSet<Neuroid> outputNeuroids = new();
|
public HashSet<Neuroid> receivers = new();
|
||||||
public virtual Vector3 outputValue { get; set; }
|
public virtual Vector3 outputValue { get; set; }
|
||||||
|
|
||||||
public int layerIx;
|
public int layerIx;
|
||||||
@ -15,7 +15,9 @@ public class Nucleus {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public virtual void AddReceiver(Neuroid receiver) {
|
public virtual void AddReceiver(Neuroid receiver) {
|
||||||
this.outputNeuroids.Add(receiver);
|
//Debug.Log($"add receiver to {this} for {receiver} {receiver.GetHashCode()} {this.receivers.Count} {receiver.synapses.Count}");
|
||||||
receiver.synapses[this] = new(this);
|
this.receivers.Add(receiver);
|
||||||
|
receiver.synapses[this] = 1.0f; // new(this);
|
||||||
|
//Debug.Log($"receiver # {this.receivers.Count} synapse count {receiver.synapses.Count}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -32,7 +32,7 @@ public class Perception : Nucleus {
|
|||||||
foreach (SensoryNeuroid neuroid in sensoryNeuroids) {
|
foreach (SensoryNeuroid neuroid in sensoryNeuroids) {
|
||||||
if (neuroid != null) {
|
if (neuroid != null) {
|
||||||
neuroid.AddReceiver(receivingNeuroid);
|
neuroid.AddReceiver(receivingNeuroid);
|
||||||
receivingNeuroid.synapses[neuroid] = new(neuroid, weight);
|
receivingNeuroid.synapses[neuroid] = weight; // new(neuroid, weight);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -45,7 +45,7 @@ public class Perception : Nucleus {
|
|||||||
foreach (SensoryNeuroid neuroid in sensoryNeuroids) {
|
foreach (SensoryNeuroid neuroid in sensoryNeuroids) {
|
||||||
if (neuroid != null && neuroid.velocityNeuroid != null) {
|
if (neuroid != null && neuroid.velocityNeuroid != null) {
|
||||||
neuroid.velocityNeuroid.AddReceiver(receivingNeuroid);
|
neuroid.velocityNeuroid.AddReceiver(receivingNeuroid);
|
||||||
receivingNeuroid.synapses[neuroid] = new(neuroid);
|
receivingNeuroid.synapses[neuroid] = 1.0f; //new(neuroid);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -54,22 +54,43 @@ public class Perception : Nucleus {
|
|||||||
int availableIx = -1;
|
int availableIx = -1;
|
||||||
int leastInterestingIx = -1;
|
int leastInterestingIx = -1;
|
||||||
for (int i = 0; i < sensoryNeuroids.Length; i++) {
|
for (int i = 0; i < sensoryNeuroids.Length; i++) {
|
||||||
if (sensoryNeuroids[i] == null || sensoryNeuroids[i].IsStale())
|
if (sensoryNeuroids[i] == null)
|
||||||
availableIx = i;
|
availableIx = i;
|
||||||
else if (sensoryNeuroids[i].receptor.thingId == thingId) {
|
else if (sensoryNeuroids[i].receptor.thingId == thingId) {
|
||||||
sensoryNeuroids[i].receptor.position = localPosition;
|
sensoryNeuroids[i].receptor.position = localPosition;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (sensoryNeuroids[i] != null) {
|
if (availableIx == -1) {
|
||||||
|
if (sensoryNeuroids[i].IsStale())
|
||||||
|
leastInterestingIx = i;
|
||||||
|
else if (sensoryNeuroids[i] != null) {
|
||||||
if (leastInterestingIx == -1 || sensoryNeuroids[leastInterestingIx].receptor.position.magnitude > sensoryNeuroids[i].receptor.position.magnitude)
|
if (leastInterestingIx == -1 || sensoryNeuroids[leastInterestingIx].receptor.position.magnitude > sensoryNeuroids[i].receptor.position.magnitude)
|
||||||
leastInterestingIx = i;
|
leastInterestingIx = i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if (availableIx == -1)
|
if (availableIx == -1)
|
||||||
availableIx = leastInterestingIx;
|
availableIx = leastInterestingIx;
|
||||||
|
|
||||||
if (availableIx != -1) {
|
if (availableIx != -1) {
|
||||||
// Debug.Log($"new receptor for {thingId}");
|
if (sensoryNeuroids[availableIx] != null) {
|
||||||
|
Debug.Log($"replace receptor for {thingId} at {availableIx}");
|
||||||
|
SensoryNeuroid neuroid = sensoryNeuroids[availableIx];
|
||||||
|
neuroid.Replace(thingId);
|
||||||
|
neuroid.name = name;
|
||||||
|
foreach (Receiver receiver in positionReceivers) {
|
||||||
|
if (receiver.thingType == 0 || receiver.thingType == thingType)
|
||||||
|
receiver.neuroid.GetInputFrom(neuroid);
|
||||||
|
}
|
||||||
|
foreach (Receiver receiver in velocityReceivers) {
|
||||||
|
if (receiver.thingType == 0 || receiver.thingType == thingType)
|
||||||
|
receiver.neuroid.GetInputFrom(neuroid.velocityNeuroid);
|
||||||
|
}
|
||||||
|
neuroid.receptor.position = localPosition;
|
||||||
|
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Debug.Log($"new receptor for {thingId} at {availableIx}");
|
||||||
SensoryNeuroid neuroid = new(neuroidNet, thingId) { name = name };
|
SensoryNeuroid neuroid = new(neuroidNet, thingId) { name = name };
|
||||||
foreach (Receiver receiver in positionReceivers) {
|
foreach (Receiver receiver in positionReceivers) {
|
||||||
if (receiver.thingType == 0 || receiver.thingType == thingType)
|
if (receiver.thingType == 0 || receiver.thingType == thingType)
|
||||||
@ -84,12 +105,13 @@ public class Perception : Nucleus {
|
|||||||
neuroid.receptor.position = localPosition;
|
neuroid.receptor.position = localPosition;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void RemoveStimulus(int thingId) {
|
public void RemoveStimulus(int thingId) {
|
||||||
for (int i = 0; i < sensoryNeuroids.Length; i++) {
|
for (int i = 0; i < sensoryNeuroids.Length; i++) {
|
||||||
if (sensoryNeuroids[i] != null && sensoryNeuroids[i].receptor.thingId == thingId) {
|
if (sensoryNeuroids[i] != null && sensoryNeuroids[i].receptor.thingId == thingId) {
|
||||||
foreach (Neuroid outputNeuroid in sensoryNeuroids[i].outputNeuroids)
|
foreach (Neuroid receiver in sensoryNeuroids[i].receivers)
|
||||||
outputNeuroid.RemoveInputFrom(sensoryNeuroids[i]);
|
receiver.RemoveInputFrom(sensoryNeuroids[i]);
|
||||||
sensoryNeuroids[i] = null;
|
sensoryNeuroids[i] = null;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -40,23 +40,23 @@ public class SensoryNeuroid : Neuroid {
|
|||||||
this.AddReceiver(velocityNeuroid);
|
this.AddReceiver(velocityNeuroid);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void Replace(int thingId) {
|
||||||
|
this.name = "sensory neuroid";
|
||||||
|
this.receptor.thingId = thingId;
|
||||||
|
this.receptor.value = Vector3.zero;
|
||||||
|
this.outputValue = Vector3.zero;
|
||||||
|
this.receivers = new();
|
||||||
|
this.AddReceiver(velocityNeuroid);
|
||||||
|
}
|
||||||
|
|
||||||
public override void UpdateState() {
|
public override void UpdateState() {
|
||||||
Vector3 result = receptor.value;
|
Vector3 result = receptor.value;
|
||||||
// SensoryNeuroid normally do not have synapses...
|
//foreach ((Nucleus nucleus, Synapse synapse) in this.synapses) {
|
||||||
// foreach (Synapse synapse in this.synapses.Values) {
|
foreach ((Nucleus nucleus, float weight) in this.synapses) {
|
||||||
// if (synapse.neuroid == null)
|
|
||||||
// Debug.LogWarning(" disconnected synapse");
|
|
||||||
// // if (synapse.value != synapse.neuroid.outputValue)
|
|
||||||
// // Debug.LogWarning("synapse value error");
|
|
||||||
// // Vector3 direction = synapse.value.normalized;
|
|
||||||
// // float magnitude = synapse.value.magnitude;
|
|
||||||
|
|
||||||
// Vector3 direction = synapse.neuroid.outputValue.normalized;
|
|
||||||
// float magnitude = synapse.neuroid.outputValue.magnitude;
|
|
||||||
foreach ((Nucleus nucleus, Synapse synapse) in this.synapses) {
|
|
||||||
Vector3 direction = nucleus.outputValue.normalized;
|
Vector3 direction = nucleus.outputValue.normalized;
|
||||||
float magnitude = nucleus.outputValue.magnitude;
|
float magnitude = nucleus.outputValue.magnitude;
|
||||||
magnitude = synapse.weight * Mathf.Pow(magnitude, exponent);
|
//magnitude = synapse.weight * Mathf.Pow(magnitude, exponent);
|
||||||
|
magnitude = weight * Mathf.Pow(magnitude, exponent);
|
||||||
if (inverse)
|
if (inverse)
|
||||||
magnitude = 1 / magnitude;
|
magnitude = 1 / magnitude;
|
||||||
result += direction * magnitude;
|
result += direction * magnitude;
|
||||||
@ -65,7 +65,7 @@ public class SensoryNeuroid : Neuroid {
|
|||||||
result /= this.synapses.Count + 1;
|
result /= this.synapses.Count + 1;
|
||||||
|
|
||||||
this.outputValue = result;
|
this.outputValue = result;
|
||||||
foreach (Neuroid neuroid in this.outputNeuroids)
|
foreach (Neuroid neuroid in this.receivers)
|
||||||
neuroid.SetInput(this);
|
neuroid.SetInput(this);
|
||||||
this.stale = 0;
|
this.stale = 0;
|
||||||
}
|
}
|
||||||
@ -82,7 +82,6 @@ public class VelocityNeuroid : Neuroid {
|
|||||||
|
|
||||||
public override void UpdateState() {
|
public override void UpdateState() {
|
||||||
// Assuming only one synapse for now....
|
// Assuming only one synapse for now....
|
||||||
//Vector3 currentPosition = this.synapses.First().Value.neuroid.outputValue;
|
|
||||||
Vector3 currentPosition = this.synapses.First().Key.outputValue;
|
Vector3 currentPosition = this.synapses.First().Key.outputValue;
|
||||||
float currentValueTime = Time.time;
|
float currentValueTime = Time.time;
|
||||||
|
|
||||||
@ -92,10 +91,11 @@ public class VelocityNeuroid : Neuroid {
|
|||||||
|
|
||||||
// No activation function...
|
// No activation function...
|
||||||
this.outputValue = velocity;
|
this.outputValue = velocity;
|
||||||
foreach (Neuroid receiver in outputNeuroids)
|
foreach (Neuroid receiver in receivers)
|
||||||
receiver?.SetInput(this);
|
receiver?.SetInput(this);
|
||||||
this.stale = 0;
|
this.stale = 0;
|
||||||
|
|
||||||
this.lastValueTime = Time.time;
|
this.lastValueTime = Time.time;
|
||||||
|
this.lastPosition = currentPosition;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -52,7 +52,7 @@ public class Boid : MonoBehaviour {
|
|||||||
Vector3 localPosition = neighbour.transform.position - this.transform.position;
|
Vector3 localPosition = neighbour.transform.position - this.transform.position;
|
||||||
|
|
||||||
int thingId = neighbour.GetInstanceID();
|
int thingId = neighbour.GetInstanceID();
|
||||||
perception.ProcessStimulus(thingId, BoidType, localPosition); //, neighbour.gameObject.name);
|
perception.ProcessStimulus(thingId, BoidType, localPosition, neighbour.gameObject.name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -63,9 +63,9 @@ public class Boid : MonoBehaviour {
|
|||||||
Vector3 desiredLocalSpace = -this.transform.InverseTransformPoint(desiredWorldSpace);
|
Vector3 desiredLocalSpace = -this.transform.InverseTransformPoint(desiredWorldSpace);
|
||||||
perception.ProcessStimulus(777, BoundaryType, desiredLocalSpace, "Boundary");
|
perception.ProcessStimulus(777, BoundaryType, desiredLocalSpace, "Boundary");
|
||||||
}
|
}
|
||||||
else {
|
// else {
|
||||||
perception.RemoveStimulus(777);
|
// perception.RemoveStimulus(777);
|
||||||
}
|
// }
|
||||||
|
|
||||||
Vector3 worldForce = this.transform.TransformDirection(totalForce.outputValue);
|
Vector3 worldForce = this.transform.TransformDirection(totalForce.outputValue);
|
||||||
|
|
||||||
@ -82,7 +82,7 @@ public class Boid : MonoBehaviour {
|
|||||||
transform.rotation = Quaternion.Slerp(transform.rotation, targetRotation, Time.deltaTime * 2f); // Adjust the speed of rotation
|
transform.rotation = Quaternion.Slerp(transform.rotation, targetRotation, Time.deltaTime * 2f); // Adjust the speed of rotation
|
||||||
}
|
}
|
||||||
|
|
||||||
neuroidNet.Update();
|
neuroidNet.UpdateNeurons();
|
||||||
}
|
}
|
||||||
|
|
||||||
Vector3 ClosestPointOnBoundsSurface(Bounds b, Vector3 p) {
|
Vector3 ClosestPointOnBoundsSurface(Bounds b, Vector3 p) {
|
||||||
@ -96,18 +96,18 @@ public class Boid : MonoBehaviour {
|
|||||||
return b.center + d * m;
|
return b.center + d * m;
|
||||||
}
|
}
|
||||||
|
|
||||||
void OnDrawGizmosSelected() {
|
// void OnDrawGizmosSelected() {
|
||||||
if (sc == null)
|
// if (sc == null)
|
||||||
return;
|
// return;
|
||||||
Gizmos.DrawWireSphere(this.transform.position, sc.perceptionDistance);
|
// Gizmos.DrawWireSphere(this.transform.position, sc.perceptionDistance);
|
||||||
Gizmos.color = Color.yellow;
|
// Gizmos.color = Color.yellow;
|
||||||
Vector3 worldForce = this.transform.TransformDirection(totalForce.outputValue);
|
// Vector3 worldForce = this.transform.TransformDirection(totalForce.outputValue);
|
||||||
Gizmos.DrawRay(transform.position, worldForce * 10);
|
// Gizmos.DrawRay(transform.position, worldForce * 10);
|
||||||
// Gizmos.color = Color.magenta;
|
// // Gizmos.color = Color.magenta;
|
||||||
// Gizmos.DrawRay(transform.position, this.transform.TransformDirection(avoidance.outputValue) * 10);
|
// // Gizmos.DrawRay(transform.position, this.transform.TransformDirection(avoidance.outputValue) * 10);
|
||||||
// Debug.Log($"Avoidance {roaming.avoidance.outputValue} Roaming {roaming.output.outputValue} Total {totalForce.outputValue}");
|
// // Debug.Log($"Avoidance {roaming.avoidance.outputValue} Roaming {roaming.output.outputValue} Total {totalForce.outputValue}");
|
||||||
// Debug.Log($"WorldForce {worldForce} velocity {velocity} inertia {sc.inertia}");
|
// // Debug.Log($"WorldForce {worldForce} velocity {velocity} inertia {sc.inertia}");
|
||||||
Gizmos.color = Color.blue;
|
// Gizmos.color = Color.blue;
|
||||||
Gizmos.DrawRay(transform.position, this.velocity * 10);
|
// Gizmos.DrawRay(transform.position, this.velocity * 10);
|
||||||
}
|
// }
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user