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

View File

@ -473,6 +473,7 @@ public class ClusterInspector : Editor {
} }
} }
private int selectedInputType = 0;
void DrawInspector(VisualElement inspectorContainer) { void DrawInspector(VisualElement inspectorContainer) {
if (inspectorContainer == null) if (inspectorContainer == null)
return; return;
@ -491,7 +492,7 @@ public class ClusterInspector : Editor {
if (this.currentNucleus == null) if (this.currentNucleus == null)
return; 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 Neuron neuroid) {
if (this.currentNucleus is MemoryCell memory) { if (this.currentNucleus is MemoryCell memory) {
} }
@ -551,6 +552,14 @@ public class ClusterInspector : Editor {
EditorGUILayout.Space(); EditorGUILayout.Space();
ConnectNucleus(this.cluster, this.currentNucleus); 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")) if (GUILayout.Button("Add Input Neuron"))
AddInputNeuron(this.currentNucleus); AddInputNeuron(this.currentNucleus);
if (GUILayout.Button("Add Input MemoryCell")) 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) { protected virtual void AddInputNeuron(INucleus nucleus) {
Neuron newNeuroid = new(this.cluster, "New neuron"); Neuron newNeuroid = new(this.cluster, "New neuron");
newNeuroid.AddReceiver(nucleus); newNeuroid.AddReceiver(nucleus);
@ -609,6 +635,13 @@ public class ClusterInspector : Editor {
BuildLayers(); 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) { protected virtual void AddInputMemoryCell(INucleus nucleus) {
MemoryCell newMemory = new(this.cluster, "New memory cell"); MemoryCell newMemory = new(this.cluster, "New memory cell");
newMemory.AddReceiver(nucleus); newMemory.AddReceiver(nucleus);

View File

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

View File

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

130
Neuron.cs
View File

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

View File

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

View File

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

View File

@ -1,8 +1,22 @@
using System;
using Unity.Mathematics; using Unity.Mathematics;
using static Unity.Mathematics.math; using static Unity.Mathematics.math;
[Serializable]
public class Selector : Neuron { public class Selector : Neuron {
public Selector(Cluster parent, string name) : base(parent, name) { } 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) { public override void UpdateStateIsolated(float3 bias) {
float3 max = bias; float3 max = bias;