Process clusterreceptor per thingId

This commit is contained in:
Pascal Serrarens 2026-03-03 12:19:41 +01:00
parent 3cdca017d6
commit abbce40992
3 changed files with 81 additions and 17 deletions

View File

@ -3,6 +3,7 @@ using System.Collections.Generic;
using UnityEngine; using UnityEngine;
using Unity.Mathematics; using Unity.Mathematics;
using static Unity.Mathematics.math; using static Unity.Mathematics.math;
using System.Linq;
[Serializable] [Serializable]
public class ClusterReceptor : Cluster, IReceptor { public class ClusterReceptor : Cluster, IReceptor {
@ -71,7 +72,7 @@ public class ClusterReceptor : Cluster, IReceptor {
foreach (Nucleus outputNucleus in clusterElement.clusterNuclei) { foreach (Nucleus outputNucleus in clusterElement.clusterNuclei) {
if (outputNucleus is not Neuron output) if (outputNucleus is not Neuron output)
continue; continue;
// this should be clusterElement.outputs, // this should be clusterElement.outputs,
// but outputs is not updated when correctly and may contain old data... // but outputs is not updated when correctly and may contain old data...
foreach (Nucleus receiver in output.receivers) { foreach (Nucleus receiver in output.receivers) {
@ -138,4 +139,73 @@ public class ClusterReceptor : Cluster, IReceptor {
this._array ??= new NucleusArray(this.parent); this._array ??= new NucleusArray(this.parent);
this._array.ProcessStimulus(thingId, inputValue, thingName); this._array.ProcessStimulus(thingId, inputValue, thingName);
} }
private Dictionary<int, ClusterReceptor> thingReceivers = new();
public virtual void ProcessStimulus(Neuron input, Vector3 inputValue, int thingId = 0, string thingName = null) {
inputValue = input.Activator(inputValue);
if (!thingReceivers.TryGetValue(thingId, out ClusterReceptor selectedReceiver))
selectedReceiver = FindReceiver(thingId, inputValue);
if (selectedReceiver == null)
return;
if (thingName != null) {
string baseName = selectedReceiver.name;
int colonPos = selectedReceiver.name.IndexOf(":");
if (colonPos > 0)
baseName = selectedReceiver.name[..colonPos];
selectedReceiver.name = baseName + ": " + thingName;
}
int inputIx = this.GetNucleusIndex(this.clusterNuclei, input);
if (inputIx < 0)
return;
if (selectedReceiver.clusterNuclei[inputIx] is Neuron selectedNeuron)
selectedNeuron.ProcessStimulusDirect(inputValue);
}
private ClusterReceptor FindReceiver(int thingId, float3 inputValue) {
// No existing nucleus for this thing
float inputMagnitude = length(inputValue);
ClusterReceptor selectedReceiver = null;
float selectedMagnitude = 0;
foreach (ClusterReceptor receiver in nucleiArray.Cast<ClusterReceptor>()) {
if (thingReceivers.ContainsValue(receiver) == false) {
// We found an unusued receiver
thingReceivers.Add(thingId, receiver);
return receiver;
}
else if (receiver.isSleeping) {
// A sleeping receiver is not active and can therefore always be used
thingReceivers.Add(thingId, receiver);
return receiver;
}
else if (selectedReceiver == null) {
// If we haven't found a receiver yet, just start by taking the first
selectedReceiver = receiver;
selectedMagnitude = length(selectedReceiver.outputValue);
}
// Look for the receiver with the lowest magnitude
else {
float magnitude = length(receiver.outputValue);
if (magnitude < inputMagnitude && length(receiver.outputValue) < selectedMagnitude) {
selectedReceiver = receiver;
selectedMagnitude = length(selectedReceiver.outputValue);
}
}
}
if (selectedReceiver != null) {
// Replace the receiver
// Find the thingId current associated with the receiver
int keyToRemove = thingReceivers.FirstOrDefault(r => r.Value.Equals(selectedReceiver)).Key;
if (keyToRemove != 0 || thingReceivers.ContainsKey(keyToRemove))
thingReceivers.Remove(keyToRemove);
// And add the new association
thingReceivers.Add(thingId, selectedReceiver);
}
return selectedReceiver;
}
} }

View File

@ -806,16 +806,8 @@ public class ClusterInspector : Editor {
void OnSceneGUI(SceneView sceneView) { void OnSceneGUI(SceneView sceneView) {
if (this.gameObject != null) { if (this.gameObject != null) {
// if (this.currentNucleus is ReceptorArray receptor && expandArray) { if (this.currentNucleus is IReceptor receptor) {
// foreach (Nucleus nucleus in receptor.instances) { foreach (Nucleus nucleus in receptor.nucleiArray) {
// Vector3 worldVector = this.gameObject.transform.TransformVector(nucleus.outputValue);
// Handles.color = Color.yellow;
// Handles.DrawLine(this.gameObject.transform.position, this.gameObject.transform.position + worldVector);
// }
// }
// else {
if (this.currentNucleus is Receptor receptor1) {
foreach (Nucleus nucleus in receptor1.nucleiArray) {
Vector3 worldVector = this.gameObject.transform.TransformVector(nucleus.outputValue); Vector3 worldVector = this.gameObject.transform.TransformVector(nucleus.outputValue);
Handles.color = Color.yellow; Handles.color = Color.yellow;
Handles.DrawLine(this.gameObject.transform.position, this.gameObject.transform.position + worldVector); Handles.DrawLine(this.gameObject.transform.position, this.gameObject.transform.position + worldVector);
@ -825,9 +817,7 @@ public class ClusterInspector : Editor {
Vector3 worldVector = this.gameObject.transform.TransformVector(this.currentNucleus.outputValue); Vector3 worldVector = this.gameObject.transform.TransformVector(this.currentNucleus.outputValue);
Handles.color = Color.yellow; Handles.color = Color.yellow;
Handles.DrawLine(this.gameObject.transform.position, this.gameObject.transform.position + worldVector); Handles.DrawLine(this.gameObject.transform.position, this.gameObject.transform.position + worldVector);
} }
// }
} }
} }
@ -1016,7 +1006,7 @@ public class ClusterInspector : Editor {
// so we have to change all synapses to this nucleus array elements // so we have to change all synapses to this nucleus array elements
int oldNucleusIx = subCluster.GetNucleusIndex(subCluster.clusterNuclei, synapse.nucleus); int oldNucleusIx = subCluster.GetNucleusIndex(subCluster.clusterNuclei, synapse.nucleus);
int newNucleusIx = subCluster.GetNucleusIndex(subCluster.clusterNuclei, newNucleus); int newNucleusIx = subCluster.GetNucleusIndex(subCluster.clusterNuclei, newNucleus);
foreach(Nucleus element in receptor.nucleiArray) { foreach (Nucleus element in receptor.nucleiArray) {
if (element is not ClusterReceptor clusterReceptor) if (element is not ClusterReceptor clusterReceptor)
continue; continue;
// Get the same neuron as the synapse.nucleus in a different element // Get the same neuron as the synapse.nucleus in a different element
@ -1029,14 +1019,15 @@ public class ClusterInspector : Editor {
Nucleus newElementNucleus = clusterReceptor.clusterNuclei[newNucleusIx]; Nucleus newElementNucleus = clusterReceptor.clusterNuclei[newNucleusIx];
if (newElementNucleus is not Neuron newElementNeuron) if (newElementNucleus is not Neuron newElementNeuron)
continue; continue;
oldElementNeuron.RemoveReceiver(this.currentNucleus); oldElementNeuron.RemoveReceiver(this.currentNucleus);
newElementNeuron.AddReceiver(this.currentNucleus); newElementNeuron.AddReceiver(this.currentNucleus);
// Now find the synapse which pointed to the old Neuron // Now find the synapse which pointed to the old Neuron
// Synapse synapseForUpdate = this.currentNucleus.GetSynapse(oldElementNeuron); // Synapse synapseForUpdate = this.currentNucleus.GetSynapse(oldElementNeuron);
// synapseForUpdate.nucleus = newElementNeuron; // synapseForUpdate.nucleus = newElementNeuron;
} }
} else { }
else {
// it is a neuron in a subcluster // it is a neuron in a subcluster
synapseNeuron.RemoveReceiver(this.currentNucleus); synapseNeuron.RemoveReceiver(this.currentNucleus);
newNucleus.AddReceiver(this.currentNucleus); newNucleus.AddReceiver(this.currentNucleus);

View File

@ -312,7 +312,10 @@ public class Neuron : Nucleus {
#endregion Receivers #endregion Receivers
public override void ProcessStimulus(Vector3 inputValue, int thingId = 0, string thingName = null) { public override void ProcessStimulus(Vector3 inputValue, int thingId = 0, string thingName = null) {
ProcessStimulusDirect(inputValue, thingId, thingName); if (this.parent is ClusterReceptor clusterReceptor) {
clusterReceptor.ProcessStimulus(this, inputValue, thingId, thingName);
} else
ProcessStimulusDirect(inputValue, thingId, thingName);
// this.stale = 0; // this.stale = 0;
// this.bias = inputValue; // this.bias = inputValue;
// this.parent.UpdateFromNucleus(this); // this.parent.UpdateFromNucleus(this);