Moved activation function to after weight application
This commit is contained in:
parent
b9b942760b
commit
600ecd5406
@ -48,7 +48,7 @@ public class Neuroid : Nucleus {
|
||||
public float exponent = 1.0f;
|
||||
|
||||
|
||||
public Neuroid(NanoBrainObj brain, string name) : base(name) {
|
||||
public Neuroid(NanoBrain brain, string name) : base(name) {
|
||||
this.brain = brain;
|
||||
if (this.brain != null) {
|
||||
this.brain.nuclei.Add(this);
|
||||
@ -75,20 +75,40 @@ public class Neuroid : Nucleus {
|
||||
}
|
||||
|
||||
public override void UpdateState() {
|
||||
Vector3 result = Vector3.zero;
|
||||
Vector3 sum = Vector3.zero;
|
||||
int n = 0;
|
||||
|
||||
//Applying the weight factgors
|
||||
foreach (Synapse synapse in this.synapses) {
|
||||
Vector3 outputValue = synapse.nucleus.outputValue;
|
||||
// As this is the activation function, it should be evaluated in the synapse.nucleus...
|
||||
float activatedValue = curve.Evaluate(outputValue.magnitude);
|
||||
float magnitude = synapse.weight * activatedValue;
|
||||
float magnitude = synapse.weight * outputValue.magnitude;
|
||||
|
||||
result += magnitude * outputValue.normalized;
|
||||
sum += magnitude * outputValue.normalized;
|
||||
n++;
|
||||
}
|
||||
if (average)
|
||||
result /= n;
|
||||
sum /= n;
|
||||
|
||||
// Activation function
|
||||
Vector3 result;
|
||||
switch (this.curvePreset) {
|
||||
case CurvePresets.Linear:
|
||||
result = sum;
|
||||
break;
|
||||
case CurvePresets.Sqrt:
|
||||
result = sum.normalized * System.MathF.Sqrt(sum.magnitude);
|
||||
break;
|
||||
case CurvePresets.Power:
|
||||
result = sum.normalized * System.MathF.Pow(sum.magnitude, 2);
|
||||
break;
|
||||
case CurvePresets.Reciprocal:
|
||||
result = sum.normalized * (1 / sum.magnitude);
|
||||
break;
|
||||
default:
|
||||
float activatedValue = this.curve.Evaluate(sum.magnitude);
|
||||
result = sum.normalized * activatedValue;
|
||||
break;
|
||||
}
|
||||
UpdateResult(result);
|
||||
}
|
||||
|
||||
|
||||
@ -26,7 +26,7 @@ public class Nucleus {
|
||||
[SerializeField]
|
||||
protected string nucleusType;
|
||||
|
||||
public virtual void Rebuild(NanoBrainObj brain) {
|
||||
public virtual void Rebuild(NanoBrain brain) {
|
||||
if (this.synapses != null) {
|
||||
foreach (Synapse synapse in synapses)
|
||||
synapse.Rebuild(brain);
|
||||
@ -43,7 +43,7 @@ public class Nucleus {
|
||||
}
|
||||
}
|
||||
|
||||
public static Nucleus RebuildType(NanoBrainObj brain, Nucleus nucleus) {
|
||||
public static Nucleus RebuildType(NanoBrain brain, Nucleus nucleus) {
|
||||
if (string.IsNullOrEmpty(nucleus.nucleusType) == false) {
|
||||
Type nucleusType = Type.GetType(nucleus.nucleusType);
|
||||
if (nucleusType != null) {
|
||||
@ -62,7 +62,7 @@ public class Nucleus {
|
||||
|
||||
#region Runtime state (not serialized)
|
||||
|
||||
public NanoBrainObj brain { get; set; }
|
||||
public NanoBrain brain { get; set; }
|
||||
|
||||
private Vector3 _outputValue;
|
||||
public Vector3 outputValue
|
||||
@ -154,11 +154,11 @@ public class Nucleus {
|
||||
public virtual void UpdateState() { }
|
||||
|
||||
public void UpdateResult(Vector3 result) {
|
||||
// float d = Vector3.Distance(result, this.outputValue);
|
||||
// if (d < 0.1f) {
|
||||
// //Debug.Log($"insignificant update: {d}");
|
||||
// return;
|
||||
// }
|
||||
float d = Vector3.Distance(result, this.outputValue);
|
||||
if (d < 0.5f) {
|
||||
//Debug.Log($"insignificant update: {d}");
|
||||
return;
|
||||
}
|
||||
|
||||
this.outputValue = result;
|
||||
foreach (Receiver receiver in this.receivers)
|
||||
@ -181,8 +181,8 @@ public class Synapse {
|
||||
Reciprocal,
|
||||
Custom
|
||||
}
|
||||
public CurvePresets curvePreset;
|
||||
public AnimationCurve curve;
|
||||
// public CurvePresets curvePreset;
|
||||
// public AnimationCurve curve;
|
||||
public float curveMax = 1.0f;
|
||||
|
||||
public Synapse(Nucleus nucleus, float weight) {
|
||||
@ -191,7 +191,7 @@ public class Synapse {
|
||||
this.weight = weight;
|
||||
}
|
||||
|
||||
public void Rebuild(NanoBrainObj brain) {
|
||||
public void Rebuild(NanoBrain brain) {
|
||||
if (brain == null) {
|
||||
return;
|
||||
}
|
||||
@ -211,30 +211,30 @@ public class Synapse {
|
||||
Debug.LogError($"Synapse deserialization error: could not find nucleus with id {this.nucleusId}");
|
||||
}
|
||||
|
||||
public AnimationCurve GenerateCurve() {
|
||||
switch (this.curvePreset) {
|
||||
case CurvePresets.Linear:
|
||||
this.curveMax = this.weight;
|
||||
return Presets.Linear(this.weight);
|
||||
case CurvePresets.Power:
|
||||
this.curveMax = this.weight;
|
||||
return Presets.Power(2.0f, this.weight);
|
||||
case CurvePresets.Sqrt:
|
||||
this.curveMax = this.weight;
|
||||
return Presets.Power(0.5f, this.weight);
|
||||
case CurvePresets.Reciprocal:
|
||||
this.curveMax = 1 / 0.01f * this.weight;
|
||||
return Presets.Reciprocal(this.weight);
|
||||
default:
|
||||
this.curveMax = weight;
|
||||
return AnimationCurve.Constant(0, 1, weight);
|
||||
}
|
||||
}
|
||||
// public AnimationCurve GenerateCurve() {
|
||||
// switch (this.curvePreset) {
|
||||
// case CurvePresets.Linear:
|
||||
// this.curveMax = this.weight;
|
||||
// return Presets.Linear(this.weight);
|
||||
// case CurvePresets.Power:
|
||||
// this.curveMax = this.weight;
|
||||
// return Presets.Power(2.0f, this.weight);
|
||||
// case CurvePresets.Sqrt:
|
||||
// this.curveMax = this.weight;
|
||||
// return Presets.Power(0.5f, this.weight);
|
||||
// case CurvePresets.Reciprocal:
|
||||
// this.curveMax = 1 / 0.01f * this.weight;
|
||||
// return Presets.Reciprocal(this.weight);
|
||||
// default:
|
||||
// this.curveMax = weight;
|
||||
// return AnimationCurve.Constant(0, 1, weight);
|
||||
// }
|
||||
// }
|
||||
|
||||
public static class Presets {
|
||||
private const int samples = 32;
|
||||
public static AnimationCurve Linear(float weight) {
|
||||
return AnimationCurve.Linear(0f, 0f, 1f, weight);
|
||||
return AnimationCurve.Linear(0f, 0f, 1000f, weight * 1000);
|
||||
}
|
||||
public static AnimationCurve Power(float exponent, float weight) {
|
||||
// build keyframes
|
||||
@ -287,7 +287,7 @@ public class Receiver {
|
||||
this.nucleusId = nucleus.id;
|
||||
}
|
||||
|
||||
public bool Rebuild(NanoBrainObj brain) {
|
||||
public bool Rebuild(NanoBrain brain) {
|
||||
if (brain == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -14,7 +14,7 @@ public class Perceptoid : Neuroid {
|
||||
public int thingType;
|
||||
public int thingId;
|
||||
|
||||
public override void Rebuild(NanoBrainObj brain) {
|
||||
public override void Rebuild(NanoBrain brain) {
|
||||
base.Rebuild(brain);
|
||||
this.receptor = Receptor.GetReceptor(brain, thingType);
|
||||
this.receptor.perceptei.Add(this);
|
||||
@ -48,7 +48,7 @@ public class Perceptoid : Neuroid {
|
||||
|
||||
#endregion Serialization
|
||||
|
||||
public Perceptoid(NanoBrainObj brain, int thingType, string name = "sensor") : base(name) {
|
||||
public Perceptoid(NanoBrain brain, int thingType, string name = "sensor") : base(name) {
|
||||
this.brain = brain;
|
||||
if (this.brain != null) {
|
||||
this.brain.perceptei.Add(this);
|
||||
@ -80,7 +80,7 @@ public class Perceptoid : Neuroid {
|
||||
}
|
||||
|
||||
|
||||
public static Perceptoid GetPerception(NanoBrainObj brain, int thingType = 0) {
|
||||
public static Perceptoid GetPerception(NanoBrain brain, int thingType = 0) {
|
||||
foreach (Nucleus nucleus in brain.nuclei) {
|
||||
if (nucleus is Perceptoid perceptoid && (thingType == 0 || perceptoid.receptor.thingType == thingType))
|
||||
return perceptoid;
|
||||
|
||||
@ -22,13 +22,13 @@ public class Receptor {
|
||||
public float distanceResolution = 0.1f;
|
||||
public float directionResolution = 5;
|
||||
|
||||
public Receptor(NanoBrainObj brain, int thingType) {
|
||||
public Receptor(NanoBrain brain, int thingType) {
|
||||
this.thingType = thingType;
|
||||
//this.perceptei.Add(perceptoid);
|
||||
brain.receptors.Add(this);
|
||||
}
|
||||
|
||||
public static Receptor GetReceptor(NanoBrainObj brain, int thingType) {
|
||||
public static Receptor GetReceptor(NanoBrain brain, int thingType) {
|
||||
foreach (Receptor receptor in brain.receptors) {
|
||||
if (thingType == 0 || receptor.thingType == thingType)
|
||||
return receptor;
|
||||
@ -38,9 +38,6 @@ public class Receptor {
|
||||
}
|
||||
|
||||
public virtual void ProcessStimulus(int thingId, Vector3 newLocalPositionVector) {
|
||||
//Spherical newLocalPosition = Spherical.FromVector3(newLocalPositionVector);
|
||||
|
||||
Vector3 previousLocalPosition = this.localPosition;
|
||||
this.localPosition = newLocalPositionVector;
|
||||
|
||||
Perceptoid selectedPerceptoid = null;
|
||||
@ -50,16 +47,6 @@ public class Receptor {
|
||||
selectedPerceptoid = perceptoid;
|
||||
// Do not look any further
|
||||
|
||||
// // This does not do a lot....
|
||||
// float deltaDistance = newLocalPosition.distance - previousLocalPosition.distance;
|
||||
// // See if the change is significant
|
||||
// AngleFloat deltaDirection = Direction.UnsignedAngle(newLocalPosition.direction, previousLocalPosition.direction);
|
||||
// if (deltaDistance < this.distanceResolution && deltaDirection.inDegrees < directionResolution) {
|
||||
// // The difference is not significant we don't process this data.
|
||||
// this.localPosition = previousLocalPosition;
|
||||
// return;
|
||||
// }
|
||||
// This is now also handled by the UpdateState Spherical.Distance
|
||||
break;
|
||||
}
|
||||
else if (perceptoid.isSleeping) {
|
||||
|
||||
@ -20,7 +20,7 @@ public class NanoBrainComponent_Editor : Editor {
|
||||
|
||||
public override VisualElement CreateInspectorGUI() {
|
||||
//NanoBrainComponent component = target as NanoBrainComponent;
|
||||
NanoBrainObj brain = Application.isPlaying ? component.brain : component.defaultBrain;
|
||||
NanoBrain brain = Application.isPlaying ? component.brain : component.defaultBrain;
|
||||
|
||||
if (Application.isPlaying == false)
|
||||
serializedObject.Update();
|
||||
|
||||
@ -11,7 +11,7 @@ public class NucleusLayer {
|
||||
}
|
||||
|
||||
public class NanoBrainEditor : EditorWindow {
|
||||
public NanoBrainObj brain;
|
||||
public NanoBrain brain;
|
||||
|
||||
public static VisualElement inspectorContainer;
|
||||
|
||||
@ -20,7 +20,7 @@ public class NanoBrainEditor : EditorWindow {
|
||||
GetWindow<NanoBrainEditor>("NanoBrain Editor");
|
||||
}
|
||||
|
||||
public static void Open(NanoBrainObj asset) {
|
||||
public static void Open(NanoBrain asset) {
|
||||
NanoBrainEditor editor = GetWindow<NanoBrainEditor>("NanoBrain Editor");
|
||||
editor.brain = asset;
|
||||
editor.Show();
|
||||
@ -69,7 +69,7 @@ public class NanoBrainEditor : EditorWindow {
|
||||
}
|
||||
|
||||
public class GraphBoardView : VisualElement {
|
||||
NanoBrainObj brain;
|
||||
NanoBrain brain;
|
||||
SerializedObject serializedBrain;
|
||||
Nucleus currentNucleus;
|
||||
private List<NeuroidLayer> layers = new();
|
||||
@ -99,7 +99,7 @@ public class GraphBoardView : VisualElement {
|
||||
RegisterCallback<MouseUpEvent>(OnMouseUp);
|
||||
}
|
||||
|
||||
public void SetGraph(NanoBrainObj brain, Nucleus nucleus) {
|
||||
public void SetGraph(NanoBrain brain, Nucleus nucleus) {
|
||||
this.brain = brain;
|
||||
this.serializedBrain = new SerializedObject(brain);
|
||||
this.currentNucleus = nucleus;
|
||||
@ -473,9 +473,9 @@ public class GraphNodeWrapper : ScriptableObject {
|
||||
public string title;
|
||||
public Vector2 position;
|
||||
Nucleus node;
|
||||
NanoBrainObj graph; // needed to write back and mark dirty
|
||||
NanoBrain graph; // needed to write back and mark dirty
|
||||
|
||||
public GraphNodeWrapper Init(Nucleus node, NanoBrainObj graphAsset) {
|
||||
public GraphNodeWrapper Init(Nucleus node, NanoBrain graphAsset) {
|
||||
this.node = node;
|
||||
this.graph = graphAsset;
|
||||
this.title = " A " + node.name;
|
||||
@ -499,7 +499,7 @@ public static class OpenAssetHandler {
|
||||
// Called when an asset is double-clicked or opened.
|
||||
[OnOpenAsset]
|
||||
public static bool OpenMyScriptableObject(int instanceID, int line) {
|
||||
NanoBrainObj obj = EditorUtility.EntityIdToObject(instanceID) as NanoBrainObj;
|
||||
NanoBrain obj = EditorUtility.EntityIdToObject(instanceID) as NanoBrain;
|
||||
if (obj != null) {
|
||||
NanoBrainEditor.Open(obj);
|
||||
return true; // handled
|
||||
|
||||
@ -5,7 +5,7 @@ using UnityEditor;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UIElements;
|
||||
|
||||
[CustomEditor(typeof(NanoBrainObj))]
|
||||
[CustomEditor(typeof(NanoBrain))]
|
||||
public class NanoBrainInspector : Editor {
|
||||
protected static VisualElement mainContainer;
|
||||
protected static VisualElement inspectorContainer;
|
||||
@ -15,7 +15,7 @@ public class NanoBrainInspector : Editor {
|
||||
#region Start
|
||||
|
||||
public override VisualElement CreateInspectorGUI() {
|
||||
NanoBrainObj brain = target as NanoBrainObj;
|
||||
NanoBrain brain = target as NanoBrain;
|
||||
|
||||
serializedObject.Update();
|
||||
|
||||
@ -72,7 +72,7 @@ public class NanoBrainInspector : Editor {
|
||||
}
|
||||
|
||||
public class GraphView : VisualElement {
|
||||
NanoBrainObj brain;
|
||||
NanoBrain brain;
|
||||
SerializedObject serializedBrain;
|
||||
Nucleus currentNucleus;
|
||||
GameObject gameObject;
|
||||
@ -103,7 +103,7 @@ public class NanoBrainInspector : Editor {
|
||||
RegisterCallback<MouseUpEvent>(OnMouseUp);
|
||||
}
|
||||
|
||||
public void SetGraph(GameObject gameObject, NanoBrainObj brain, Nucleus nucleus, VisualElement inspectorContainer) {
|
||||
public void SetGraph(GameObject gameObject, NanoBrain brain, Nucleus nucleus, VisualElement inspectorContainer) {
|
||||
this.gameObject = gameObject;
|
||||
this.brain = brain;
|
||||
if (Application.isPlaying == false)
|
||||
|
||||
@ -1,15 +1,15 @@
|
||||
using UnityEngine;
|
||||
|
||||
public class NanoBrainComponent : MonoBehaviour {
|
||||
public NanoBrainObj defaultBrain;
|
||||
private NanoBrainObj brainInstance;
|
||||
public NanoBrain defaultBrain;
|
||||
private NanoBrain brainInstance;
|
||||
|
||||
public Nucleus root {
|
||||
get {
|
||||
return brainInstance.root;
|
||||
}
|
||||
}
|
||||
public NanoBrainObj brain {
|
||||
public NanoBrain brain {
|
||||
get {
|
||||
if (brainInstance == null && defaultBrain != null) {
|
||||
brainInstance = Instantiate(defaultBrain);
|
||||
|
||||
@ -3,7 +3,7 @@ using UnityEngine;
|
||||
using LinearAlgebra;
|
||||
|
||||
[CreateAssetMenu(menuName = "Passer/NanoBrain")]
|
||||
public class NanoBrainObj : ScriptableObject, ISerializationCallbackReceiver {
|
||||
public class NanoBrain : ScriptableObject, ISerializationCallbackReceiver {
|
||||
|
||||
public string title;
|
||||
public int count;
|
||||
@ -21,7 +21,7 @@ public class NanoBrainObj : ScriptableObject, ISerializationCallbackReceiver {
|
||||
|
||||
// public Perception perception;
|
||||
|
||||
public NanoBrainObj() {
|
||||
public NanoBrain() {
|
||||
this.root = new Neuroid(this, "Root");
|
||||
// this.perception = new Perception(this);
|
||||
}
|
||||
|
||||
@ -375,10 +375,10 @@ MonoBehaviour:
|
||||
m_EditorClassIdentifier: Assembly-CSharp::SwarmControl
|
||||
speed: 1
|
||||
inertia: 0.7
|
||||
alignmentForce: 2
|
||||
cohesionForce: 4
|
||||
alignmentForce: 0.5
|
||||
cohesionForce: 2.2
|
||||
separationForce: -5
|
||||
avoidanceForce: 5
|
||||
avoidanceForce: 1
|
||||
separationDistance: 0.3
|
||||
perceptionDistance: 2
|
||||
boundaryForce: 5
|
||||
|
||||
@ -10,9 +10,9 @@ public class SwarmControl_Editor : Editor {
|
||||
|
||||
if (EditorGUI.EndChangeCheck()) {
|
||||
SwarmControl swarmControl = (SwarmControl)target;
|
||||
NanoBrainObj[] nanoBrains = FindObjectsByType<NanoBrainObj>(FindObjectsSortMode.None);
|
||||
NanoBrain[] nanoBrains = FindObjectsByType<NanoBrain>(FindObjectsSortMode.None);
|
||||
|
||||
foreach (NanoBrainObj brain in nanoBrains) {
|
||||
foreach (NanoBrain brain in nanoBrains) {
|
||||
UpdateWeight(brain, "Avoidance", swarmControl.avoidanceForce);
|
||||
UpdateWeight(brain, "Cohesion", swarmControl.cohesionForce);
|
||||
UpdateWeight(brain, "Separation", swarmControl.separationForce);
|
||||
@ -22,7 +22,7 @@ public class SwarmControl_Editor : Editor {
|
||||
}
|
||||
}
|
||||
|
||||
protected void UpdateWeight(NanoBrainObj brain, string name, float weight) {
|
||||
protected void UpdateWeight(NanoBrain brain, string name, float weight) {
|
||||
Nucleus root = brain.root;
|
||||
foreach (Synapse synapse in root.synapses) {
|
||||
if (synapse.nucleus.name == name) {
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Binary file not shown.
Loading…
x
Reference in New Issue
Block a user