diff --git a/Cluster.cs b/Cluster.cs index da88e53..2a7fe34 100644 --- a/Cluster.cs +++ b/Cluster.cs @@ -104,7 +104,7 @@ public class Cluster : Nucleus { foreach (Nucleus prefabArrayNucleus in prefabReceptor.nucleiArray) { int arrayNucleusIx = GetNucleusIndex(prefabNuclei, prefabArrayNucleus); if (arrayNucleusIx >= 0) { - Nucleus clonedArrayNucleus = clonedNuclei[arrayNucleusIx]; + Neuron clonedArrayNucleus = clonedNuclei[arrayNucleusIx] as Neuron; clonedArray.nuclei[arrayIx] = clonedArrayNucleus; } else { @@ -473,12 +473,12 @@ public class Cluster : Nucleus { Debug.Log($"Update from {startNucleus.name}"); foreach (Nucleus nucleus in computeOrder) { nucleus.UpdateStateIsolated(); - if (startNucleus.trace) - Debug.Log($" {nucleus.name}[{nucleus.GetHashCode()}] = {nucleus.outputValue}"); + if (startNucleus.trace && nucleus is Neuron neuron) + Debug.Log($" {nucleus.name}[{nucleus.GetHashCode()}] = {neuron.outputValue}"); } - this.outputValue = this.defaultOutput.outputValue; - this.stale = 0; + // this.outputValue = this.defaultOutput.outputValue; + // this.stale = 0; // continue in parent this.parent?.UpdateFromNucleus(this); @@ -491,17 +491,19 @@ public class Cluster : Nucleus { //Applying the weight factors foreach (Synapse synapse in this.synapses) { - if (lengthsq(synapse.nucleus.outputValue) > 0) { - sum += synapse.weight * synapse.nucleus.outputValue; - this.stale = 0; + if (synapse.nucleus is Neuron neuron) { + if (lengthsq(neuron.outputValue) > 0) { + sum += synapse.weight * neuron.outputValue; + //this.stale = 0; + } } } foreach (Nucleus nucleus in this.sortedNuclei) nucleus.UpdateStateIsolated(); - this.outputValue = this.defaultOutput.outputValue; - this.stale = 0; + // this.outputValue = this.defaultOutput.outputValue; + // this.stale = 0; UpdateNuclei(); } diff --git a/ClusterReceptor.cs b/ClusterReceptor.cs index d6fd3bf..fb9a7bc 100644 --- a/ClusterReceptor.cs +++ b/ClusterReceptor.cs @@ -100,6 +100,8 @@ public class ClusterReceptor : Cluster, IReceptor { set { _array.nuclei = value; } } + //public ClusterReceptor[] nucleiArray; + public void AddReceptorElement(ClusterPrefab prefab) { IReceptorHelpers.AddReceptorElement(this, prefab); } @@ -116,7 +118,7 @@ public class ClusterReceptor : Cluster, IReceptor { // Clusters don't do anything, // The nuclei in them do the work // and should be called directly, not from the cluster - + // float3 sum = this.bias; // foreach (Nucleus nucleus in this.sortedNuclei) @@ -129,30 +131,31 @@ public class ClusterReceptor : Cluster, IReceptor { } public override void UpdateNuclei() { - this.stale++; - if (this.stale > staleValueForSleep && lengthsq(this.bias) > 0) { - this.bias = new float3(0, 0, 0); - this.parent.UpdateFromNucleus(this); - } + // this.stale++; + // if (this.stale > staleValueForSleep && lengthsq(this.bias) > 0) { + // this.bias = new float3(0, 0, 0); + // this.parent.UpdateFromNucleus(this); + // } foreach (Nucleus nucleus in this.clusterNuclei) nucleus.UpdateNuclei(); } public override void ProcessStimulus(Vector3 inputValue, int thingId = 0, string thingName = null) { - this._array ??= new NucleusArray(this.parent); - this._array.ProcessStimulus(thingId, inputValue, thingName); + //this._array ??= new NucleusArray(this.parent); + //this._array.ProcessStimulus(thingId, inputValue, thingName); + Debug.LogError("Process Stimulus was called on clusterreceptor without a neuron specified"); } - private Dictionary thingReceivers = new(); + private readonly Dictionary thingReceivers = new(); public virtual void ProcessStimulus(Neuron input, Vector3 inputValue, int thingId = 0, string thingName = null) { CleanupReceivers(); - inputValue = input.Activator(inputValue); + //inputValue = input.Activator(inputValue); if (!thingReceivers.TryGetValue(thingId, out ClusterReceptor selectedReceiver)) - selectedReceiver = FindReceiver(thingId, inputValue); + selectedReceiver = FindReceiver2(thingId, inputValue); if (selectedReceiver == null) return; @@ -172,18 +175,61 @@ public class ClusterReceptor : Cluster, IReceptor { selectedNeuron.ProcessStimulusDirect(inputValue); } - private ClusterReceptor FindReceiver(int thingId, float3 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()) { + // 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; + // } + + private ClusterReceptor FindReceiver2(int thingId, float3 inputValue) { // No existing nucleus for this thing - float inputMagnitude = length(inputValue); + //float inputMagnitude = length(inputValue); ClusterReceptor selectedReceiver = null; float selectedMagnitude = 0; - foreach (ClusterReceptor receiver in nucleiArray.Cast()) { + foreach (ClusterReceptor receiver in this.nucleiArray.Cast()) { if (thingReceivers.ContainsValue(receiver) == false) { // We found an unusued receiver thingReceivers.Add(thingId, receiver); return receiver; } - else if (receiver.isSleeping) { + else if (receiver.defaultOutput.isSleeping) { // A sleeping receiver is not active and can therefore always be used thingReceivers.Add(thingId, receiver); return receiver; @@ -191,15 +237,15 @@ public class ClusterReceptor : Cluster, IReceptor { else if (selectedReceiver == null) { // If we haven't found a receiver yet, just start by taking the first selectedReceiver = receiver; - selectedMagnitude = length(selectedReceiver.outputValue); + selectedMagnitude = length(selectedReceiver.defaultOutput.outputValue); } - // Look for the receiver with the lowest magnitude + // Look for the receiver with the lowest output magnitude else { - float magnitude = length(receiver.outputValue); + float magnitude = length(receiver.defaultOutput.outputValue); - if (magnitude < inputMagnitude && length(receiver.outputValue) < selectedMagnitude) { + if (length(receiver.defaultOutput.outputValue) < selectedMagnitude) { selectedReceiver = receiver; - selectedMagnitude = length(selectedReceiver.outputValue); + selectedMagnitude = length(selectedReceiver.defaultOutput.outputValue); } } } @@ -215,13 +261,13 @@ public class ClusterReceptor : Cluster, IReceptor { return selectedReceiver; } - + private void CleanupReceivers() { // Remove a thing-receiver connection when the nucleus is inactive List receiversToRemove = new(); foreach (KeyValuePair item in thingReceivers) { - if (item.Value != null && item.Value.isSleeping) - receiversToRemove.Add(item.Key); + if (item.Value != null && item.Value.defaultOutput.isSleeping) + receiversToRemove.Add(item.Key); } foreach (int thingId in receiversToRemove) { Nucleus selectedReceiver = thingReceivers[thingId]; diff --git a/Editor/ClusterInspector.cs b/Editor/ClusterInspector.cs index 2790aa8..d2c7e2d 100644 --- a/Editor/ClusterInspector.cs +++ b/Editor/ClusterInspector.cs @@ -262,9 +262,11 @@ public class ClusterInspector : Editor { if (this.currentNucleus is IReceptor receptor1) { float maxValue = 0; foreach (Nucleus nucleus in receptor1.nucleiArray) { - float value = length(nucleus.outputValue); - if (value > maxValue) - maxValue = value; + if (nucleus is Neuron neuron) { + float value = length(neuron.outputValue); + if (value > maxValue) + maxValue = value; + } } float spacing = 400f / receptor1.nucleiArray.Count(); @@ -309,7 +311,13 @@ public class ClusterInspector : Editor { Handles.color = Color.white; // The selected nucleus highlight ring Handles.DrawSolidDisc(position, Vector3.forward, size + 2); - DrawNucleus(this.currentNucleus, position, length(this.currentNucleus.outputValue), 20); + float maxValue = 1; + if (this.currentNucleus is Neuron neuron) + maxValue = length(neuron.outputValue); + else if (this.currentNucleus is Cluster cluster) + maxValue = length(cluster.defaultOutput.outputValue); + + DrawNucleus(this.currentNucleus, position, maxValue, 20); } } @@ -317,7 +325,12 @@ public class ClusterInspector : Editor { Handles.color = Color.white; // The selected nucleus highlight ring Handles.DrawSolidDisc(position, Vector3.forward, size + 2); - DrawNucleus(this.currentNucleus, position, length(this.currentNucleus.outputValue), 20); + float maxValue = 1; + if (this.currentNucleus is Neuron neuron) + maxValue = length(neuron.outputValue); + else if (this.currentNucleus is Cluster cluster) + maxValue = length(cluster.defaultOutput.outputValue); + DrawNucleus(this.currentNucleus, position, maxValue, 20); } } @@ -388,10 +401,12 @@ public class ClusterInspector : Editor { continue; drawnArrays.Add(clusterReceptor.nucleiArray); } - float value = length(synapse.nucleus.outputValue) * synapse.weight; - // Debug.Log($"{synapse.nucleus.name}: {value} {length(synapse.nucleus.outputValue)} {synapse.weight}"); - if (value > maxValue) - maxValue = value; + if (synapse.nucleus is Neuron synapseNeuron) { + float value = length(synapseNeuron.outputValue) * synapse.weight; + // Debug.Log($"{synapse.nucleus.name}: {value} {length(synapse.nucleus.outputValue)} {synapse.weight}"); + if (value > maxValue) + maxValue = value; + } neuronCount++; } @@ -419,7 +434,9 @@ public class ClusterInspector : Editor { if (Application.isPlaying) { if (maxValue == 0 || !float.IsFinite(maxValue)) maxValue = 1; - float brightness = length(synapse.nucleus.outputValue * synapse.weight) / maxValue; + float brightness = 0; + if (synapse.nucleus is Neuron synapseNeuron) + brightness = length(synapseNeuron.outputValue * synapse.weight) / maxValue; color = new Color(brightness, brightness, brightness, 1f); } if (synapse.nucleus.parent != null && synapse.nucleus.parent != this.currentNucleus.parent) { @@ -439,7 +456,9 @@ public class ClusterInspector : Editor { private void DrawNucleus(Nucleus nucleus, Vector3 position, float maxValue, float size) { Color color; if (Application.isPlaying) { - float brightness = length(nucleus.outputValue) / maxValue; + float brightness = 0; + if (nucleus is Neuron neuron) + brightness = length(neuron.outputValue) / maxValue; color = new Color(brightness, brightness, brightness, 1f); } else @@ -529,9 +548,13 @@ public class ClusterInspector : Editor { private void HandleMouseHover(Nucleus nucleus, Rect rect) { GUIContent tooltip; - tooltip = new( - $"{nucleus.name}" + - $"\nValue: {length(nucleus.outputValue)}"); + if (nucleus is Neuron neuron) { + tooltip = new( + $"{nucleus.name}" + + $"\nValue: {length(neuron.outputValue)}"); + } + else + tooltip = new($"{nucleus.name}"); Vector2 mousePosition = Event.current.mousePosition; @@ -609,8 +632,12 @@ public class ClusterInspector : Editor { } if (Application.isPlaying) { - GUIContent nameLabel = new("Output", this.currentNucleus.outputValue.ToString()); - EditorGUILayout.FloatField(nameLabel, length(this.currentNucleus.outputValue)); + if (currentNucleus is Neuron currentNeuron1) { + GUIContent nameLabel = new("Output", currentNeuron1.outputValue.ToString()); + EditorGUILayout.FloatField(nameLabel, length(currentNeuron1.outputValue)); + } + else + EditorGUILayout.LabelField(" "); } else EditorGUILayout.LabelField(" "); @@ -686,9 +713,11 @@ public class ClusterInspector : Editor { EditorGUILayout.Space(); if (Application.isPlaying) { - Vector3 value = synapse.nucleus.outputValue * synapse.weight; - GUIContent synapseValueLabel = new(synapse.nucleus.name, synapse.nucleus.outputValue.ToString()); - EditorGUILayout.FloatField(synapseValueLabel, length(synapse.nucleus.outputValue)); + if (synapse.nucleus is Neuron synapseNeuron) { + Vector3 value = synapseNeuron.outputValue * synapse.weight; + GUIContent synapseValueLabel = new(synapse.nucleus.name, synapseNeuron.outputValue.ToString()); + EditorGUILayout.FloatField(synapseValueLabel, length(synapseNeuron.outputValue)); + } } else { EditorGUILayout.BeginHorizontal(); @@ -784,8 +813,8 @@ public class ClusterInspector : Editor { EditorGUILayout.Space(); breakOnWake = EditorGUILayout.Toggle("Break on wake", breakOnWake); - if (breakOnWake) { - if (this.currentNucleus.isSleeping == false) + if (breakOnWake && this.currentNucleus is Neuron currentNeuron) { + if (currentNeuron.isSleeping == false) Debug.Break(); } trace = EditorGUILayout.Toggle("Trace", trace); @@ -802,15 +831,19 @@ public class ClusterInspector : Editor { if (this.gameObject != null) { if (this.currentNucleus is IReceptor receptor) { 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); + if (nucleus is Neuron neuron) { + Vector3 worldVector = this.gameObject.transform.TransformVector(neuron.outputValue); + Handles.color = Color.yellow; + Handles.DrawLine(this.gameObject.transform.position, this.gameObject.transform.position + worldVector); + } } } else { - Vector3 worldVector = this.gameObject.transform.TransformVector(this.currentNucleus.outputValue); - Handles.color = Color.yellow; - Handles.DrawLine(this.gameObject.transform.position, this.gameObject.transform.position + worldVector); + if (this.currentNucleus is Neuron currentNeuron) { + Vector3 worldVector = this.gameObject.transform.TransformVector(currentNeuron.outputValue); + Handles.color = Color.yellow; + Handles.DrawLine(this.gameObject.transform.position, this.gameObject.transform.position + worldVector); + } } } } @@ -825,15 +858,15 @@ public class ClusterInspector : Editor { case Nucleus.Type.MemoryCell: AddMemoryCellInput(nucleus); break; - case Nucleus.Type.Selector: - AddSelectorInput(nucleus); - break; + // case Nucleus.Type.Selector: + // AddSelectorInput(nucleus); + // break; case Nucleus.Type.Cluster: AddClusterInput(nucleus); break; - case Nucleus.Type.Pulsar: - AddPulsarInput(nucleus); - break; + // case Nucleus.Type.Pulsar: + // AddPulsarInput(nucleus); + // break; case Nucleus.Type.Receptor: AddReceptorInput(nucleus); break; @@ -855,19 +888,19 @@ public class ClusterInspector : Editor { BuildLayers(); } - protected void AddSelectorInput(Nucleus nucleus) { - Selector newSelector = new(this.prefab, "New Selector"); - newSelector.AddReceiver(nucleus); - this.currentNucleus = newSelector; - BuildLayers(); - } + // protected void AddSelectorInput(Nucleus nucleus) { + // Selector newSelector = new(this.prefab, "New Selector"); + // newSelector.AddReceiver(nucleus); + // this.currentNucleus = newSelector; + // BuildLayers(); + // } - protected void AddPulsarInput(Nucleus nucleus) { - Pulsar newPulsar = new(this.prefab, "New Pulsar"); - newPulsar.AddReceiver(nucleus); - this.currentNucleus = newPulsar; - BuildLayers(); - } + // protected void AddPulsarInput(Nucleus nucleus) { + // Pulsar newPulsar = new(this.prefab, "New Pulsar"); + // newPulsar.AddReceiver(nucleus); + // this.currentNucleus = newPulsar; + // BuildLayers(); + // } protected virtual void AddMemoryCellInput(Nucleus nucleus) { MemoryCell newMemory = new(this.prefab, "New memory cell"); diff --git a/Neuron.cs b/Neuron.cs index 92b9c7d..57abcac 100644 --- a/Neuron.cs +++ b/Neuron.cs @@ -117,6 +117,23 @@ public class Neuron : Nucleus { #endregion Serialization + protected float3 _outputValue; + public virtual float3 outputValue { + get { return _outputValue; } + set { + _outputValue = value; + if (this.isFiring) + WhenFiring?.Invoke(); + } + } + public bool isFiring => length(_outputValue) > 0.5f; + public Action WhenFiring; + + public virtual bool isSleeping => lengthsq(this.outputValue) == 0; + [NonSerialized] + public int stale = 1000; + public readonly int staleValueForSleep = 20; + // this clone the nucleus without the synapses and receivers public override Nucleus ShallowCloneTo(Cluster newParent) { Neuron clone = new(newParent, this.name); @@ -164,7 +181,8 @@ public class Neuron : Nucleus { if (receiver != null && receiver.synapses != null) receiver.synapses.RemoveAll(s => s.nucleus == nucleus); } - } else if (nucleus is Cluster cluster) { + } + else if (nucleus is Cluster cluster) { // remove all receivers for this cluster foreach (Neuron output in cluster.outputs) { foreach (Nucleus receiver in output.receivers) { @@ -197,15 +215,19 @@ public class Neuron : Nucleus { public float3 CombinatorSum() { float3 sum = this.bias; - foreach (Synapse synapse in this.synapses) - sum += synapse.weight * synapse.nucleus.outputValue; + foreach (Synapse synapse in this.synapses) { + if (synapse.nucleus is Neuron neuron) + sum += synapse.weight * neuron.outputValue; + } return sum; } public float3 CombinatorProduct() { float3 product = this.bias; - foreach (Synapse synapse in this.synapses) - product *= synapse.weight * synapse.nucleus.outputValue; + foreach (Synapse synapse in this.synapses) { + if (synapse.nucleus is Neuron neuron) + product *= synapse.weight * neuron.outputValue; + } return product; } @@ -215,12 +237,14 @@ public class Neuron : Nucleus { //Applying the weight factors foreach (Synapse synapse in this.synapses) { - float3 input = synapse.weight * synapse.nucleus.outputValue; + if (synapse.nucleus is Neuron neuron) { + float3 input = synapse.weight * neuron.outputValue; - float inputLength = length(input); - if (inputLength > maxLength) { - max = input; - maxLength = inputLength; + float inputLength = length(input); + if (inputLength > maxLength) { + max = input; + maxLength = inputLength; + } } } return max; @@ -278,7 +302,7 @@ public class Neuron : Nucleus { set { _receivers = value; } } - public virtual void AddReceiver(Nucleus receiverToAdd, float weight = 1) { + public virtual void AddReceiver(Nucleus receiverToAdd, float weight = 1) { // if (this is IReceptor receptor) { // foreach (Nucleus element in receptor.array.nuclei) { // if (element is Neuron neuron) { @@ -288,8 +312,8 @@ public class Neuron : Nucleus { // } // } // else { - this._receivers.Add(receiverToAdd); - receiverToAdd.AddSynapse(this, weight); + this._receivers.Add(receiverToAdd); + receiverToAdd.AddSynapse(this, weight); // } } @@ -313,8 +337,9 @@ public class Neuron : Nucleus { public override void ProcessStimulus(Vector3 inputValue, int thingId = 0, string thingName = null) { if (this.parent is ClusterReceptor clusterReceptor) { - clusterReceptor.ProcessStimulus(this, inputValue, thingId, thingName); - } else + clusterReceptor.ProcessStimulus(this, inputValue, thingId, thingName); + } + else ProcessStimulusDirect(inputValue, thingId, thingName); // this.stale = 0; // this.bias = inputValue; diff --git a/Nucleus.cs b/Nucleus.cs index cf4ff74..f3045c4 100644 --- a/Nucleus.cs +++ b/Nucleus.cs @@ -13,22 +13,22 @@ public abstract class Nucleus { [SerializeReference] public Cluster parent; - protected float3 _outputValue; - public virtual float3 outputValue { - get { return _outputValue; } - set { - _outputValue = value; - if (this.isFiring) - WhenFiring?.Invoke(); - } - } - public bool isFiring => length(_outputValue) > 0.5f; - public Action WhenFiring; + // protected float3 _outputValue; + // public virtual float3 outputValue { + // get { return _outputValue; } + // set { + // _outputValue = value; + // if (this.isFiring) + // WhenFiring?.Invoke(); + // } + // } + // public bool isFiring => length(_outputValue) > 0.5f; + // public Action WhenFiring; - public virtual bool isSleeping => lengthsq(this.outputValue) == 0; - [NonSerialized] - public int stale = 1000; - public readonly int staleValueForSleep = 20; + // public virtual bool isSleeping => lengthsq(this.outputValue) == 0; + // [NonSerialized] + // public int stale = 1000; + // public readonly int staleValueForSleep = 20; public bool trace = false; public abstract Nucleus ShallowCloneTo(Cluster parent); @@ -81,7 +81,7 @@ public abstract class Nucleus { } public virtual void SetBias(Vector3 inputValue) { - this.stale = 0; + //this.stale = 0; this.bias = inputValue; this.parent.UpdateFromNucleus(this); } diff --git a/NucleusArray.cs b/NucleusArray.cs index 774d0f7..9f8a172 100644 --- a/NucleusArray.cs +++ b/NucleusArray.cs @@ -69,9 +69,11 @@ public class NucleusArray { private Nucleus FindReceiver(int thingId, float3 inputValue) { // No existing nucleus for this thing float inputMagnitude = length(inputValue); - Nucleus selectedReceiver = null; + Neuron selectedReceiver = null; float selectedMagnitude = 0; - foreach (Nucleus receiver in this._nuclei) { + foreach (Nucleus nucleusReceiver in this._nuclei) { + if (nucleusReceiver is not Neuron receiver) + continue; if (thingReceivers.ContainsValue(receiver) == false) { // We found an unusued receiver thingReceivers.Add(thingId, receiver); @@ -138,7 +140,7 @@ public class NucleusArray { // Remove a thing-receiver connection when the nucleus is inactive List receiversToRemove = new(); foreach (KeyValuePair item in thingReceivers) { - if (item.Value != null && item.Value.isSleeping) + if (item.Value != null && item.Value is Neuron neuron && neuron.isSleeping) receiversToRemove.Add(item.Key); } foreach (int thingId in receiversToRemove) { diff --git a/Pulsar.cs b/Pulsar.cs index 8e2cc54..b302951 100644 --- a/Pulsar.cs +++ b/Pulsar.cs @@ -1,54 +1,54 @@ -using System; -using Unity.Mathematics; +// using System; +// using Unity.Mathematics; -/// -/// The Pulsar represents a type of neuron that operates based on -/// the product of its weighted inputs rather than the traditional summation. -/// Drawing inspiration from the concept of pulsars in astrophysics -/// —highly magnetized rotating neutron stars that emit beams of radiation— -/// the Pulsar could symbolize dynamic, focused output based on the interaction of multiple factors. -/// -/// Multiplicative Functionality: -/// Instead of summing inputs, the Pulsar takes the weighted product of its inputs. -/// This means that all inputs must be active (non-zero) for the neuron to "pulse" or activate. -/// Output Behavior: -/// The output could amplify or diminish depending on the magnitude of the inputs. -/// The product would be sensitive to small values, -/// which means that even a small input could significantly lower the overall output if multiplied. -/// Activation Mechanism: -/// The activation function can further refine the output from the product result. -/// For instance, a certain threshold could be used to determine if a pulse occurs. -/// Modeling Complex Interactions: -/// The Pulsar could be particularly beneficial for modeling situations where interactions multiply rather than add. -/// This is useful in fields such as economics (e.g., compound growth models), -/// biology (e.g., interaction of hormones), and machine learning where multiplicative relationships exist. -[Serializable] -public class Pulsar : Neuron { - public Pulsar(Cluster parent, string name) : base(parent, name) { - // To prevent mistakes, bias one (instead of zero for standard neurons) - this.bias = new float3(1, 1, 1); - } - public Pulsar(ClusterPrefab parent, string name) : base(parent, name) { - // To prevent mistakes, bias one (instead of zero for standard neurons) - this.bias = new float3(1, 1, 1); - } +// /// +// /// The Pulsar represents a type of neuron that operates based on +// /// the product of its weighted inputs rather than the traditional summation. +// /// Drawing inspiration from the concept of pulsars in astrophysics +// /// —highly magnetized rotating neutron stars that emit beams of radiation— +// /// the Pulsar could symbolize dynamic, focused output based on the interaction of multiple factors. +// /// +// /// Multiplicative Functionality: +// /// Instead of summing inputs, the Pulsar takes the weighted product of its inputs. +// /// This means that all inputs must be active (non-zero) for the neuron to "pulse" or activate. +// /// Output Behavior: +// /// The output could amplify or diminish depending on the magnitude of the inputs. +// /// The product would be sensitive to small values, +// /// which means that even a small input could significantly lower the overall output if multiplied. +// /// Activation Mechanism: +// /// The activation function can further refine the output from the product result. +// /// For instance, a certain threshold could be used to determine if a pulse occurs. +// /// Modeling Complex Interactions: +// /// The Pulsar could be particularly beneficial for modeling situations where interactions multiply rather than add. +// /// This is useful in fields such as economics (e.g., compound growth models), +// /// biology (e.g., interaction of hormones), and machine learning where multiplicative relationships exist. +// [Serializable] +// public class Pulsar : Neuron { +// public Pulsar(Cluster parent, string name) : base(parent, name) { +// // To prevent mistakes, bias one (instead of zero for standard neurons) +// this.bias = new float3(1, 1, 1); +// } +// public Pulsar(ClusterPrefab parent, string name) : base(parent, name) { +// // To prevent mistakes, bias one (instead of zero for standard neurons) +// this.bias = new float3(1, 1, 1); +// } - public override Nucleus ShallowCloneTo(Cluster newParent) { - Pulsar clone = new(newParent, this.name); - CloneFields(clone); - return clone; - } +// public override Nucleus ShallowCloneTo(Cluster newParent) { +// Pulsar clone = new(newParent, this.name); +// CloneFields(clone); +// return clone; +// } - public override void UpdateStateIsolated() { - float3 product = this.bias; +// public override void UpdateStateIsolated() { +// float3 product = this.bias; - //Applying the weight factors - foreach (Synapse synapse in this.synapses) { - float3 input = synapse.weight * synapse.nucleus.outputValue; - product *= input; - } +// //Applying the weight factors +// foreach (Synapse synapse in this.synapses) { +// float3 input = synapse.weight * synapse.nucleus.outputValue; +// product *= input; +// } - // Activation function - this.outputValue = Activator(product); - } -} \ No newline at end of file +// // Activation function +// this.outputValue = Activator(product); +// } +// } \ No newline at end of file diff --git a/Selector.cs b/Selector.cs index 320f807..ad68c3d 100644 --- a/Selector.cs +++ b/Selector.cs @@ -1,62 +1,62 @@ -using System; -using Unity.Mathematics; -using static Unity.Mathematics.math; +// 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) {} +// [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 Nucleus ShallowCloneTo(Cluster newParent) { - Selector clone = new(newParent, this.name) { - // array = this.array, - curve = this.curve, - curvePreset = this.curvePreset, - curveMax = this.curveMax, - }; - return clone; - } +// public override Nucleus ShallowCloneTo(Cluster newParent) { +// Selector clone = new(newParent, this.name) { +// // array = this.array, +// curve = this.curve, +// curvePreset = this.curvePreset, +// curveMax = this.curveMax, +// }; +// return clone; +// } - public override void UpdateStateIsolated() { //float3 bias) { - float3 max = this.bias; - float maxSqrLength = lengthsq(max); +// public override void UpdateStateIsolated() { //float3 bias) { +// float3 max = this.bias; +// float maxSqrLength = lengthsq(max); - //Applying the weight factors - foreach (Synapse synapse in this.synapses) { - float3 input = synapse.weight * synapse.nucleus.outputValue; +// //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; - maxSqrLength = inputSqrlength; - } - } +// float inputSqrlength = lengthsq(input); +// if (inputSqrlength > maxSqrLength) { +// max = input; +// maxSqrLength = inputSqrlength; +// } +// } - // Activation function - float3 result; - switch (this.curvePreset) { - case CurvePresets.Linear: - result = max; - break; - case CurvePresets.Sqrt: - result = normalize(max) * System.MathF.Sqrt(length(max)); - break; - case CurvePresets.Power: - result = normalize(max) * System.MathF.Pow(length(max), 2); - break; - case CurvePresets.Reciprocal: { - float magnitude = length(max); - if (magnitude > 0) - result = normalize(max) * (1 / magnitude); - else - result = float3(0, 0, 0); - break; - } - default: - float activatedValue = this.curve.Evaluate(length(max)); - result = normalize(max) * activatedValue; - break; - } - this.outputValue = result; - } -} \ No newline at end of file +// // Activation function +// float3 result; +// switch (this.curvePreset) { +// case CurvePresets.Linear: +// result = max; +// break; +// case CurvePresets.Sqrt: +// result = normalize(max) * System.MathF.Sqrt(length(max)); +// break; +// case CurvePresets.Power: +// result = normalize(max) * System.MathF.Pow(length(max), 2); +// break; +// case CurvePresets.Reciprocal: { +// float magnitude = length(max); +// if (magnitude > 0) +// result = normalize(max) * (1 / magnitude); +// else +// result = float3(0, 0, 0); +// break; +// } +// default: +// float activatedValue = this.curve.Evaluate(length(max)); +// result = normalize(max) * activatedValue; +// break; +// } +// this.outputValue = result; +// } +// } \ No newline at end of file