Selector is working

This commit is contained in:
Pascal Serrarens 2026-02-04 11:19:19 +01:00
parent 25cd5aefd0
commit c290b62637
8 changed files with 161 additions and 141 deletions

View File

@ -258,27 +258,27 @@ public class Cluster : INucleus {
#region Update
public virtual void UpdateState() {
UpdateState(new float3(0, 0, 0));
}
// public virtual void UpdateState() {
// UpdateState(new float3(0, 0, 0));
// }
public void UpdateState(float3 bias) {
float3 sum = bias; // new(0, 0, 0);
// public void UpdateState(float3 bias) {
// float3 sum = bias; // new(0, 0, 0);
//Applying the weight factors
foreach (Synapse synapse in this.synapses) {
sum += synapse.weight * synapse.nucleus.outputValue;
}
// //Applying the weight factors
// foreach (Synapse synapse in this.synapses) {
// sum += synapse.weight * synapse.nucleus.outputValue;
// }
//this.inputs[0].UpdateState(sum);
this.inputs[0].UpdateStateIsolated(sum);
foreach (IReceptor receptor in this.sortedNuclei) {
if (receptor is INucleus nucleus && nucleus != this.inputs[0])
nucleus.UpdateStateIsolated();
}
// //this.inputs[0].UpdateState(sum);
// this.inputs[0].UpdateStateIsolated(sum);
// foreach (IReceptor receptor in this.sortedNuclei) {
// if (receptor is INucleus nucleus && nucleus != this.inputs[0])
// nucleus.UpdateStateIsolated();
// }
UpdateResult(this.output.outputValue);
}
// UpdateResult(this.output.outputValue);
// }
public void UpdateStateIsolated() {
float3 bias = new(0,0,0);
@ -301,17 +301,17 @@ public class Cluster : INucleus {
this.outputValue = this.output.outputValue;
}
public virtual void UpdateResult(Vector3 result) {
// float d = Vector3.Distance(result, this.outputValue);
// if (d < 0.5f) {
// //Debug.Log($"insignificant update: {d}");
// return;
// }
// public virtual void UpdateResult(Vector3 result) {
// // float d = Vector3.Distance(result, this.outputValue);
// // if (d < 0.5f) {
// // //Debug.Log($"insignificant update: {d}");
// // return;
// // }
this.outputValue = result;
foreach (INucleus receiver in this.receivers)
receiver.UpdateState();
}
// this.outputValue = result;
// foreach (INucleus receiver in this.receivers)
// receiver.UpdateState();
// }
public void UpdateNuclei() {
this.stale++;

View File

@ -473,6 +473,7 @@ public class ClusterInspector : Editor {
}
}
private int selectedInputType = 0;
void DrawInspector(VisualElement inspectorContainer) {
if (inspectorContainer == null)
return;
@ -491,7 +492,7 @@ public class ClusterInspector : Editor {
if (this.currentNucleus == null)
return;
this.currentNucleus.name = EditorGUILayout.TextField(this.currentNucleus.name);
this.currentNucleus.name = EditorGUILayout.TextField(this.currentNucleus.GetType().ToString(), this.currentNucleus.name);
if (this.currentNucleus is Neuron neuroid) {
if (this.currentNucleus is MemoryCell memory) {
}
@ -551,6 +552,14 @@ public class ClusterInspector : Editor {
EditorGUILayout.Space();
ConnectNucleus(this.cluster, this.currentNucleus);
EditorGUILayout.BeginHorizontal();
if (GUILayout.Button("Add Input"))
AddInput(selectedInputType, this.currentNucleus);
string[] options = { "Neuron", "MemoryCell", "Selector", "Cluster" };
selectedInputType = EditorGUILayout.Popup(selectedInputType, options);
EditorGUILayout.EndHorizontal();
if (GUILayout.Button("Add Input Neuron"))
AddInputNeuron(this.currentNucleus);
if (GUILayout.Button("Add Input MemoryCell"))
@ -587,6 +596,23 @@ public class ClusterInspector : Editor {
}
}
protected virtual void AddInput(int selectedInputType, INucleus nucleus) {
switch (selectedInputType) {
case 0: // Neuron
AddInputNeuron(nucleus);
break;
case 1: // MemoryCell
AddInputMemoryCell(nucleus);
break;
case 2: // Selector
AddSelectorInput(nucleus);
break;
case 3: // Cluster
AddCluster(nucleus);
break;
}
}
protected virtual void AddInputNeuron(INucleus nucleus) {
Neuron newNeuroid = new(this.cluster, "New neuron");
newNeuroid.AddReceiver(nucleus);
@ -609,6 +635,13 @@ public class ClusterInspector : Editor {
BuildLayers();
}
protected void AddSelectorInput(INucleus nucleus) {
Selector newSelector = new(this.cluster, "New Selector");
newSelector.AddReceiver(nucleus);
this.currentNucleus = newSelector;
BuildLayers();
}
protected virtual void AddInputMemoryCell(INucleus nucleus) {
MemoryCell newMemory = new(this.cluster, "New memory cell");
newMemory.AddReceiver(nucleus);

View File

@ -7,6 +7,7 @@ public interface INucleus : IReceptor {
// Cluster
public ClusterPrefab cluster { get; }
public Cluster parent { get; }
// Senders
public List<Synapse> synapses { get; }
@ -18,8 +19,8 @@ public interface INucleus : IReceptor {
#region dynamic state
public void UpdateState();
public void UpdateState(float3 inputValue);
// public void UpdateState();
// public void UpdateState(float3 inputValue);
public void UpdateStateIsolated();
public void UpdateStateIsolated(float3 inputValue);

View File

@ -29,23 +29,23 @@ public class MemoryCell : Neuron, INucleus {
private float3 _memorizedValue;
private float _memorizedTime;
public override void UpdateState(float3 bias) {
// A memorycell does not have an activation function
float3 result = bias;
int n = 0;
// public override void UpdateState(float3 bias) {
// // A memorycell does not have an activation function
// float3 result = bias;
// int n = 0;
//Applying the weight factgors
foreach (Synapse synapse in this.synapses) {
result += synapse.weight * synapse.nucleus.outputValue;
if (lengthsq(synapse.nucleus.outputValue) != 0)
n++;
}
// //Applying the weight factgors
// foreach (Synapse synapse in this.synapses) {
// result += synapse.weight * synapse.nucleus.outputValue;
// if (lengthsq(synapse.nucleus.outputValue) != 0)
// n++;
// }
if (this.average)
result /= n;
// if (this.average)
// result /= n;
UpdateResult(result);
}
// UpdateResult(result);
// }
public override void UpdateStateIsolated() {
float3 bias = new(0, 0, 0);
@ -73,22 +73,22 @@ public class MemoryCell : Neuron, INucleus {
this._memorizedTime = Time.time;
}
public override void UpdateResult(Vector3 result) {
// output value is the previous value
// if (this.deltaValue) {
// float deltaTime = Time.time - this._memorizedTime;
// this._outputValue = this._memorizedValue * deltaTime;
// }
//else
this.outputValue = this._memorizedValue;
// public override void UpdateResult(Vector3 result) {
// // output value is the previous value
// // if (this.deltaValue) {
// // float deltaTime = Time.time - this._memorizedTime;
// // this._outputValue = this._memorizedValue * deltaTime;
// // }
// //else
// this.outputValue = this._memorizedValue;
// Store the result for the next time
this._memorizedValue = result;
this._memorizedTime = Time.time;
// // Store the result for the next time
// this._memorizedValue = result;
// this._memorizedTime = Time.time;
foreach (INucleus receiver in this.receivers)
receiver.UpdateState();
}
// foreach (INucleus receiver in this.receivers)
// receiver.UpdateState();
// }
#endregion State
}

130
Neuron.cs
View File

@ -191,35 +191,7 @@ public class Neuron : INucleus {
};
return clone;
}
public virtual IReceptor ShallowCloneTo(ClusterPrefab newParent) {
Neuron clone = new(newParent, this.name) {
array = this.array,
curve = this.curve,
curvePreset = this.curvePreset,
curveMax = this.curveMax,
average = this.average
};
return clone;
}
public virtual IReceptor CloneTo(ClusterPrefab parent) {
Neuron clone = new(parent, this.name) {
array = this.array,
curve = this.curve,
curvePreset = this.curvePreset,
curveMax = this.curveMax,
average = this.average
};
foreach (Synapse synapse in this.synapses) {
Synapse clonedSynapse = clone.AddSynapse(synapse.nucleus);
clonedSynapse.weight = synapse.weight;
}
foreach (INucleus receiver in this.receivers) {
clone.AddReceiver(receiver);
}
return clone;
}
public virtual IReceptor Clone() {
Neuron clone = new(this.cluster, this.name) {
array = this.array,
@ -281,48 +253,48 @@ public class Neuron : INucleus {
return synapse;
}
public virtual void UpdateState() {
//UpdateState(new float3(0, 0, 0));
this.parent?.UpdateState();
}
// public virtual void UpdateState() {
// //UpdateState(new float3(0, 0, 0));
// this.parent?.UpdateState();
// }
public virtual void UpdateState(float3 inputValue) {
float3 sum = inputValue;
int n = 0;
// public virtual void UpdateState(float3 inputValue) {
// float3 sum = inputValue;
// int n = 0;
//Applying the weight factgors
foreach (Synapse synapse in this.synapses) {
sum += synapse.weight * synapse.nucleus.outputValue;
// //Applying the weight factgors
// foreach (Synapse synapse in this.synapses) {
// sum += synapse.weight * synapse.nucleus.outputValue;
// Perhaps synapses should be removed when the output value goes to 0....
if (lengthsq(synapse.nucleus.outputValue) != 0)
n++;
}
if (this.average && n > 0)
sum /= n;
// // Perhaps synapses should be removed when the output value goes to 0....
// if (lengthsq(synapse.nucleus.outputValue) != 0)
// n++;
// }
// if (this.average && n > 0)
// sum /= n;
// Activation function
Vector3 result;
switch (this.curvePreset) {
case CurvePresets.Linear:
result = sum;
break;
case CurvePresets.Sqrt:
result = normalize(sum) * System.MathF.Sqrt(length(sum));
break;
case CurvePresets.Power:
result = normalize(sum) * System.MathF.Pow(length(sum), 2);
break;
case CurvePresets.Reciprocal:
result = normalize(sum) * (1 / length(sum));
break;
default:
float activatedValue = this.curve.Evaluate(length(sum));
result = normalize(sum) * activatedValue;
break;
}
UpdateResult(result);
}
// // Activation function
// Vector3 result;
// switch (this.curvePreset) {
// case CurvePresets.Linear:
// result = sum;
// break;
// case CurvePresets.Sqrt:
// result = normalize(sum) * System.MathF.Sqrt(length(sum));
// break;
// case CurvePresets.Power:
// result = normalize(sum) * System.MathF.Pow(length(sum), 2);
// break;
// case CurvePresets.Reciprocal:
// result = normalize(sum) * (1 / length(sum));
// break;
// default:
// float activatedValue = this.curve.Evaluate(length(sum));
// result = normalize(sum) * activatedValue;
// break;
// }
// UpdateResult(result);
// }
public virtual void UpdateStateIsolated() {
UpdateStateIsolated(new float3(0, 0, 0));
@ -368,20 +340,20 @@ public class Neuron : INucleus {
this.outputValue = result;
}
public virtual void UpdateResult(Vector3 result) {
// float d = Vector3.Distance(result, this.outputValue);
// if (d < 0.5f) {
// //Debug.Log($"insignificant update: {d}");
// return;
// }
// public virtual void UpdateResult(Vector3 result) {
// // float d = Vector3.Distance(result, this.outputValue);
// // if (d < 0.5f) {
// // //Debug.Log($"insignificant update: {d}");
// // return;
// // }
this.outputValue = result;
if (lengthsq(outputValue) != 0) {
Debug.Log($"{this.parent.name}.{this.name}: {this.outputValue}");
}
// this.outputValue = result;
// if (lengthsq(outputValue) != 0) {
// Debug.Log($"{this.parent.name}.{this.name}: {this.outputValue}");
// }
foreach (INucleus receiver in this.receivers)
receiver.UpdateState();
// foreach (INucleus receiver in this.receivers)
// receiver.UpdateState();
}
// }
}

View File

@ -179,7 +179,7 @@ public class Receptor : IReceptor {
thingIds[selectedReceiverIx] = thingId;
// if (thingName != null)
// selectedReceiver.nucleus.name = selectedReceiver.nucleus.baseName + " " + thingName;
selectedReceiver.UpdateState();
selectedReceiver.parent.UpdateStateIsolated();
}
public void UpdateNuclei() {

View File

@ -9,8 +9,8 @@ public class SelectorBrain : NanoBrain {
public Receptor receptor2;
protected void Awake() {
receptor1 = Receptor.CreateReceptor(this.brain, "Input 1");
receptor2 = Receptor.CreateReceptor(this.brain, "Input 2");
receptor1 = Receptor.CreateReceptor(this.brain, "Selector");
receptor2 = Receptor.CreateReceptor(this.brain, "Selector");
}
protected void Update() {

View File

@ -1,8 +1,22 @@
using System;
using Unity.Mathematics;
using static Unity.Mathematics.math;
[Serializable]
public class Selector : Neuron {
public Selector(Cluster parent, string name) : base(parent, name) { }
public Selector(ClusterPrefab parent, string name) : base(parent, name) {}
public override IReceptor ShallowCloneTo(Cluster newParent) {
Selector clone = new(newParent, this.name) {
array = this.array,
curve = this.curve,
curvePreset = this.curvePreset,
curveMax = this.curveMax,
average = this.average
};
return clone;
}
public override void UpdateStateIsolated(float3 bias) {
float3 max = bias;
@ -11,7 +25,7 @@ public class Selector : Neuron {
//Applying the weight factors
foreach (Synapse synapse in this.synapses) {
float3 input = synapse.weight * synapse.nucleus.outputValue;
float inputSqrlength = lengthsq(input);
if (inputSqrlength > maxSqrLength) {
max = input;