Pulsar neuron and firing actions
This commit is contained in:
parent
fd7359acd0
commit
6f67def8e6
@ -678,24 +678,46 @@ public class ClusterInspector : Editor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected virtual void AddInput(Nucleus.Type selectedType, Nucleus nucleus) {
|
||||||
|
switch (selectedType) {
|
||||||
|
case Nucleus.Type.Neuron:
|
||||||
|
AddNeuronInput(nucleus);
|
||||||
|
break;
|
||||||
|
case Nucleus.Type.MemoryCell:
|
||||||
|
AddMemoryCellInput(nucleus);
|
||||||
|
break;
|
||||||
|
case Nucleus.Type.Selector:
|
||||||
|
AddSelectorInput(nucleus);
|
||||||
|
break;
|
||||||
|
case Nucleus.Type.Cluster:
|
||||||
|
AddClusterInput(nucleus);
|
||||||
|
break;
|
||||||
|
case Nucleus.Type.Pulsar:
|
||||||
|
AddPulsarInput(nucleus);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
protected virtual void AddInput(int selectedInputType, Nucleus nucleus) {
|
protected virtual void AddInput(int selectedInputType, Nucleus nucleus) {
|
||||||
switch (selectedInputType) {
|
switch (selectedInputType) {
|
||||||
case 0: // Neuron
|
case 0: // Neuron
|
||||||
AddInputNeuron(nucleus);
|
AddNeuronInput(nucleus);
|
||||||
break;
|
break;
|
||||||
case 1: // MemoryCell
|
case 1: // MemoryCell
|
||||||
AddInputMemoryCell(nucleus);
|
AddMemoryCellInput(nucleus);
|
||||||
break;
|
break;
|
||||||
case 2: // Selector
|
case 2: // Selector
|
||||||
AddSelectorInput(nucleus);
|
AddSelectorInput(nucleus);
|
||||||
break;
|
break;
|
||||||
case 3: // Cluster
|
case 3: // Cluster
|
||||||
AddCluster(nucleus);
|
AddClusterInput(nucleus);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected virtual void AddInputNeuron(Nucleus nucleus) {
|
protected virtual void AddNeuronInput(Nucleus nucleus) {
|
||||||
//Neuron newNeuroid = new(this.cluster, "New neuron");
|
//Neuron newNeuroid = new(this.cluster, "New neuron");
|
||||||
Neuron newNeuroid = new(this.prefab, "New neuron");
|
Neuron newNeuroid = new(this.prefab, "New neuron");
|
||||||
newNeuroid.AddReceiver(nucleus);
|
newNeuroid.AddReceiver(nucleus);
|
||||||
@ -725,14 +747,21 @@ public class ClusterInspector : Editor {
|
|||||||
BuildLayers();
|
BuildLayers();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected virtual void AddInputMemoryCell(Nucleus nucleus) {
|
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");
|
MemoryCell newMemory = new(this.prefab, "New memory cell");
|
||||||
newMemory.AddReceiver(nucleus);
|
newMemory.AddReceiver(nucleus);
|
||||||
this.currentNucleus = newMemory;
|
this.currentNucleus = newMemory;
|
||||||
BuildLayers();
|
BuildLayers();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected virtual void AddCluster(Nucleus nucleus) {
|
protected virtual void AddClusterInput(Nucleus nucleus) {
|
||||||
ClusterPickerWindow.ShowPicker(brain => OnClusterPicked(nucleus, brain), "Select Cluster");
|
ClusterPickerWindow.ShowPicker(brain => OnClusterPicked(nucleus, brain), "Select Cluster");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -777,11 +806,13 @@ public class ClusterInspector : Editor {
|
|||||||
if (cluster == null)
|
if (cluster == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
string[] options = { "Neuron", "MemoryCell", "Selector", "Cluster" };
|
//string[] options = { "Neuron", "MemoryCell", "Selector", "Cluster" };
|
||||||
int selectedInputType = -1;
|
//int selectedInputType = -1;
|
||||||
selectedInputType = EditorGUILayout.Popup("Add", selectedInputType, options);
|
//selectedInputType = EditorGUILayout.Popup("Add", selectedInputType, options);
|
||||||
if (selectedInputType >= 0)
|
//if (selectedInputType >= 0)
|
||||||
AddInput(selectedInputType, this.currentNucleus);
|
Nucleus.Type selectedType = (Nucleus.Type)EditorGUILayout.EnumPopup("Add", Nucleus.Type.None);
|
||||||
|
if (selectedType != Nucleus.Type.None)
|
||||||
|
AddInput(selectedType, this.currentNucleus);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected virtual void DisconnectNucleus(Neuron nucleus) {
|
protected virtual void DisconnectNucleus(Neuron nucleus) {
|
||||||
|
|||||||
72
Neuron.cs
72
Neuron.cs
@ -129,29 +129,33 @@ public class Neuron : Nucleus {
|
|||||||
|
|
||||||
// this clone the nucleus without the synapses and receivers
|
// this clone the nucleus without the synapses and receivers
|
||||||
public override Nucleus ShallowCloneTo(Cluster newParent) {
|
public override Nucleus ShallowCloneTo(Cluster newParent) {
|
||||||
Neuron clone = new(newParent, this.name) {
|
Neuron clone = new(newParent, this.name);
|
||||||
array = null,
|
// {
|
||||||
bias = this.bias,
|
// array = null,
|
||||||
curve = this.curve,
|
// bias = this.bias,
|
||||||
curvePreset = this.curvePreset,
|
// curve = this.curve,
|
||||||
curveMax = this.curveMax,
|
// curvePreset = this.curvePreset,
|
||||||
average = this.average
|
// curveMax = this.curveMax,
|
||||||
};
|
// average = this.average
|
||||||
|
// };
|
||||||
|
CloneFields(clone);
|
||||||
return clone;
|
return clone;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override Nucleus Clone(ClusterPrefab prefab) {
|
public override Nucleus Clone(ClusterPrefab prefab) {
|
||||||
Neuron clone = new(prefab, this.name) {
|
Neuron clone = new(prefab, this.name);
|
||||||
//Neuron clone = new(this.parent, this.name) {
|
// {
|
||||||
array = this.array,
|
// //Neuron clone = new(this.parent, this.name) {
|
||||||
curve = this.curve,
|
// array = this.array,
|
||||||
curvePreset = this.curvePreset,
|
// curve = this.curve,
|
||||||
curveMax = this.curveMax,
|
// curvePreset = this.curvePreset,
|
||||||
average = this.average
|
// curveMax = this.curveMax,
|
||||||
};
|
// average = this.average
|
||||||
|
// };
|
||||||
// if (clone.cluster != null)
|
// if (clone.cluster != null)
|
||||||
// clone.cluster.nuclei.Add(clone);
|
// clone.cluster.nuclei.Add(clone);
|
||||||
|
|
||||||
|
CloneFields(clone);
|
||||||
foreach (Synapse synapse in this.synapses) {
|
foreach (Synapse synapse in this.synapses) {
|
||||||
Synapse clonedSynapse = clone.AddSynapse(synapse.nucleus);
|
Synapse clonedSynapse = clone.AddSynapse(synapse.nucleus);
|
||||||
clonedSynapse.weight = synapse.weight;
|
clonedSynapse.weight = synapse.weight;
|
||||||
@ -162,6 +166,15 @@ public class Neuron : Nucleus {
|
|||||||
return clone;
|
return clone;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected virtual void CloneFields(Neuron clone) {
|
||||||
|
clone.array = null;
|
||||||
|
clone.bias = this.bias;
|
||||||
|
clone.curve = this.curve;
|
||||||
|
clone.curvePreset = this.curvePreset;
|
||||||
|
clone.curveMax = this.curveMax;
|
||||||
|
clone.average = this.average;
|
||||||
|
}
|
||||||
|
|
||||||
public static void Delete(Nucleus nucleus) {
|
public static void Delete(Nucleus nucleus) {
|
||||||
foreach (Synapse synapse in nucleus.synapses) {
|
foreach (Synapse synapse in nucleus.synapses) {
|
||||||
if (synapse.nucleus is Neuron synapse_nucleus) {
|
if (synapse.nucleus is Neuron synapse_nucleus) {
|
||||||
@ -205,32 +218,37 @@ public class Neuron : Nucleus {
|
|||||||
sum /= n;
|
sum /= n;
|
||||||
|
|
||||||
// Activation function
|
// Activation function
|
||||||
|
float3 result = Activation(sum);
|
||||||
|
if (this.stale > staleValueForSleep)
|
||||||
|
this.outputValue = new float3(0, 0, 0);
|
||||||
|
else
|
||||||
|
this.outputValue = result;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected float3 Activation(float3 input) {
|
||||||
float3 result = Vector3.zero;
|
float3 result = Vector3.zero;
|
||||||
switch (this.curvePreset) {
|
switch (this.curvePreset) {
|
||||||
case CurvePresets.Linear:
|
case CurvePresets.Linear:
|
||||||
result = sum;
|
result = input;
|
||||||
break;
|
break;
|
||||||
case CurvePresets.Sqrt:
|
case CurvePresets.Sqrt:
|
||||||
result = normalize(sum) * System.MathF.Sqrt(length(sum));
|
result = normalize(input) * System.MathF.Sqrt(length(input));
|
||||||
break;
|
break;
|
||||||
case CurvePresets.Power:
|
case CurvePresets.Power:
|
||||||
result = normalize(sum) * System.MathF.Pow(length(sum), 2);
|
result = normalize(input) * System.MathF.Pow(length(input), 2);
|
||||||
break;
|
break;
|
||||||
case CurvePresets.Reciprocal: {
|
case CurvePresets.Reciprocal: {
|
||||||
float magnitude = length(sum);
|
float magnitude = length(input);
|
||||||
if (magnitude > 0)
|
if (magnitude > 0)
|
||||||
result = normalize(sum) * (1 / magnitude);
|
result = normalize(input) * (1 / magnitude);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
float activatedValue = this.curve.Evaluate(length(sum));
|
float activatedValue = this.curve.Evaluate(length(input));
|
||||||
result = normalize(sum) * activatedValue;
|
result = normalize(input) * activatedValue;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (this.stale > staleValueForSleep)
|
return result;
|
||||||
this.outputValue = new float3(0,0,0);
|
|
||||||
else
|
|
||||||
this.outputValue = result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual void ProcessStimulus(Vector3 inputValue, string thingName = null) {
|
public virtual void ProcessStimulus(Vector3 inputValue, string thingName = null) {
|
||||||
|
|||||||
18
Nucleus.cs
18
Nucleus.cs
@ -6,12 +6,6 @@ using static Unity.Mathematics.math;
|
|||||||
|
|
||||||
[Serializable]
|
[Serializable]
|
||||||
public abstract class Nucleus {
|
public abstract class Nucleus {
|
||||||
// [SerializeField]
|
|
||||||
// protected string _name;
|
|
||||||
// public virtual string name {
|
|
||||||
// get => _name;
|
|
||||||
// set => _name = value;
|
|
||||||
// }
|
|
||||||
public string name;
|
public string name;
|
||||||
|
|
||||||
//[Obsolete]
|
//[Obsolete]
|
||||||
@ -26,9 +20,12 @@ public abstract class Nucleus {
|
|||||||
//this.stale = 0;
|
//this.stale = 0;
|
||||||
// this._isSleeping = false;
|
// this._isSleeping = false;
|
||||||
_outputValue = value;
|
_outputValue = value;
|
||||||
|
if (this.isFiring)
|
||||||
|
WhenFiring?.Invoke();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
public bool isFiring => length(_outputValue) > 0.5f;
|
public bool isFiring => length(_outputValue) > 0.5f;
|
||||||
|
public Action WhenFiring;
|
||||||
|
|
||||||
public bool isSleeping => lengthsq(this.outputValue) == 0;
|
public bool isSleeping => lengthsq(this.outputValue) == 0;
|
||||||
[NonSerialized]
|
[NonSerialized]
|
||||||
@ -38,6 +35,15 @@ public abstract class Nucleus {
|
|||||||
public abstract Nucleus ShallowCloneTo(Cluster parent);
|
public abstract Nucleus ShallowCloneTo(Cluster parent);
|
||||||
public abstract Nucleus Clone(ClusterPrefab prefab);
|
public abstract Nucleus Clone(ClusterPrefab prefab);
|
||||||
|
|
||||||
|
public enum Type {
|
||||||
|
None,
|
||||||
|
Neuron,
|
||||||
|
MemoryCell,
|
||||||
|
Selector,
|
||||||
|
Cluster,
|
||||||
|
Pulsar
|
||||||
|
}
|
||||||
|
|
||||||
#region Synapses
|
#region Synapses
|
||||||
|
|
||||||
public Vector3 bias = Vector3.zero;
|
public Vector3 bias = Vector3.zero;
|
||||||
|
|||||||
54
Pulsar.cs
Normal file
54
Pulsar.cs
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
using System;
|
||||||
|
using Unity.Mathematics;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 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.
|
||||||
|
/// </summary>
|
||||||
|
/// 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 void UpdateStateIsolated(float3 _bias) {
|
||||||
|
float3 product = this.bias;
|
||||||
|
|
||||||
|
//Applying the weight factors
|
||||||
|
foreach (Synapse synapse in this.synapses) {
|
||||||
|
float3 input = synapse.weight * synapse.nucleus.outputValue;
|
||||||
|
product *= input;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Activation function
|
||||||
|
this.outputValue = Activation(product);
|
||||||
|
}
|
||||||
|
}
|
||||||
2
Pulsar.cs.meta
Normal file
2
Pulsar.cs.meta
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 46bd155173053a01585411c3e07f85d4
|
||||||
Loading…
x
Reference in New Issue
Block a user