From c290b62637aa43cd5ecaf4641eb5dac8fcfa1cbb Mon Sep 17 00:00:00 2001 From: Pascal Serrarens Date: Wed, 4 Feb 2026 11:19:19 +0100 Subject: [PATCH] Selector is working --- Cluster.cs | 54 +++++------ Editor/ClusterInspector.cs | 35 ++++++- INucleus.cs | 5 +- MemoryCell.cs | 56 +++++------ Neuron.cs | 130 ++++++++++---------------- Receptor.cs | 2 +- Scripts/Experimental/SelectorBrain.cs | 4 +- Selector.cs | 16 +++- 8 files changed, 161 insertions(+), 141 deletions(-) diff --git a/Cluster.cs b/Cluster.cs index 130f0e2..6afd6aa 100644 --- a/Cluster.cs +++ b/Cluster.cs @@ -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++; diff --git a/Editor/ClusterInspector.cs b/Editor/ClusterInspector.cs index 8e8d4df..6d774c1 100644 --- a/Editor/ClusterInspector.cs +++ b/Editor/ClusterInspector.cs @@ -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); diff --git a/INucleus.cs b/INucleus.cs index 324896d..195e9da 100644 --- a/INucleus.cs +++ b/INucleus.cs @@ -7,6 +7,7 @@ public interface INucleus : IReceptor { // Cluster public ClusterPrefab cluster { get; } + public Cluster parent { get; } // Senders public List 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); diff --git a/MemoryCell.cs b/MemoryCell.cs index 307ac77..643b039 100644 --- a/MemoryCell.cs +++ b/MemoryCell.cs @@ -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 } diff --git a/Neuron.cs b/Neuron.cs index d6b50c0..270f830 100644 --- a/Neuron.cs +++ b/Neuron.cs @@ -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(); - } + // } } \ No newline at end of file diff --git a/Receptor.cs b/Receptor.cs index 24bf9a7..7ad1982 100644 --- a/Receptor.cs +++ b/Receptor.cs @@ -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() { diff --git a/Scripts/Experimental/SelectorBrain.cs b/Scripts/Experimental/SelectorBrain.cs index a08dc46..8b40798 100644 --- a/Scripts/Experimental/SelectorBrain.cs +++ b/Scripts/Experimental/SelectorBrain.cs @@ -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() { diff --git a/Selector.cs b/Selector.cs index 01a2411..cb8a2ec 100644 --- a/Selector.cs +++ b/Selector.cs @@ -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;