NucleusArray cloning seems to work

This commit is contained in:
Pascal Serrarens 2026-02-05 12:16:37 +01:00
parent 3cc5f56f61
commit 16f0c3d3bf
5 changed files with 241 additions and 84 deletions

View File

@ -61,8 +61,8 @@ public class Cluster : INucleus {
// Now clone the connections
for (int nucleusIx = 0; nucleusIx < nuclei.Length; nucleusIx++) {
IReceptor receptor = nuclei[nucleusIx];
IReceptor clonedSender = clonedNuclei[nucleusIx];
if (clonedSender == null)
IReceptor clonedReceptor = clonedNuclei[nucleusIx];
if (clonedReceptor == null)
continue;
// Copy the receivers, which will also create the synapses
@ -76,27 +76,49 @@ public class Cluster : INucleus {
// Find the synapse for the weight
float weight = 1;
NucleusArray nucleusArray = null;
//NucleusArray clonedNucleusArray = null;
foreach (Synapse synapse in receiver.synapses) {
// Find the weight for this synapse
if (synapse.nucleus == receptor)
weight = synapse.weight;
if (synapse.nucleus is INucleus synapseNucleus) {
if (synapseNucleus.array != null && synapseNucleus.array.nuclei.Length > 0) {
if (nucleusArray == null) {
// copy the array
nucleusArray = new NucleusArray(synapseNucleus.array.nuclei.Length, "array");
for (int arrayIx = 0; arrayIx < synapseNucleus.array.nuclei.Length; arrayIx++) {
IReceptor arrayNucleus = synapseNucleus.array.nuclei[arrayIx];
int ix2 = GetNucleusIndex(nuclei, arrayNucleus);
nucleusArray.nuclei[arrayIx] = clonedNuclei[ix2];
}
}
synapseNucleus.array = nucleusArray;
}
}
// if (synapse.nucleus is INucleus synapseNucleus) {
// if (synapseNucleus.array != null && synapseNucleus.array.nuclei.Length > 0) {
// Debug.Log("Clone: Nucleus array");
// if (clonedNucleusArray == null) {
// // copy the array
// clonedNucleusArray = new NucleusArray(synapseNucleus.array.nuclei.Length, "array");
// for (int arrayIx = 0; arrayIx < synapseNucleus.array.nuclei.Length; arrayIx++) {
// IReceptor arrayNucleus = synapseNucleus.array.nuclei[arrayIx];
// int ix2 = GetNucleusIndex(nuclei, arrayNucleus);
// clonedNucleusArray.nuclei[arrayIx] = clonedNuclei[ix2];
// }
// }
// synapseNucleus.array = clonedNucleusArray;
// }
// }
}
clonedSender.AddReceiver(clonedReceiver, weight);
clonedReceptor.AddReceiver(clonedReceiver, weight);
// Nucleus clonedNucleus = clonedReceptor as Nucleus;
// if (clonedNucleus is not null) {
// Synapse clonedSynapse = clonedNucleus.GetSynapse(clonedReceiver);
// if (clonedSynapse.nucleus is INucleus synapseNucleus) {
// if (synapseNucleus.array != null && synapseNucleus.array.nuclei.Length > 0) {
// Debug.Log("Clone: Nucleus array");
// if (clonedNucleusArray == null) {
// // copy the array
// clonedNucleusArray = new NucleusArray(synapseNucleus.array.nuclei.Length, "array");
// for (int arrayIx = 0; arrayIx < synapseNucleus.array.nuclei.Length; arrayIx++) {
// IReceptor arrayNucleus = synapseNucleus.array.nuclei[arrayIx];
// int ix2 = GetNucleusIndex(nuclei, arrayNucleus);
// clonedNucleusArray.nuclei[arrayIx] = clonedNuclei[ix2];
// }
// }
// synapseNucleus.array = clonedNucleusArray;
// }
// }
// }
}
// if (receptor is INucleus nucleus) {
@ -113,6 +135,34 @@ public class Cluster : INucleus {
// }
// }
}
for (int nucleusIx = 0; nucleusIx < nuclei.Length; nucleusIx++) {
IReceptor prefabReceptor = nuclei[nucleusIx];
if (prefabReceptor is not INucleus prefabNucleus)
continue;
if (prefabNucleus.array == null || prefabNucleus.array.nuclei == null || prefabNucleus.array.nuclei.Length == 0)
continue;
INucleus clonedNucleus = clonedNuclei[nucleusIx] as INucleus;
if (prefabNucleus == prefabNucleus.array.nuclei[0]) {
// We clone the array only for the first entry
NucleusArray clonedArray = new(prefabNucleus.array.nuclei.Length, "array");
int arrayIx = 0;
foreach (IReceptor prefabArrayNucleus in prefabNucleus.array.nuclei) {
int arrayNucleusIx = GetNucleusIndex(nuclei, prefabArrayNucleus);
IReceptor clonedArrayNucleus = clonedNuclei[arrayNucleusIx];
clonedArray.nuclei[arrayIx] = clonedArrayNucleus;
arrayIx++;
}
clonedNucleus.array = clonedArray;
}
else {
// The others will refer to the array created for the first nucleus in the array
int firstNucleusIx = GetNucleusIndex(nuclei, prefabNucleus.array.nuclei[0]);
INucleus clonedFirstNucleus = clonedNuclei[firstNucleusIx] as INucleus;
clonedNucleus.array = clonedFirstNucleus.array;
}
}
}
// Sort the nuclei in a correct evaluation order

128
Neuron.cs
View File

@ -7,7 +7,7 @@ using Unity.Mathematics;
using static Unity.Mathematics.math;
[Serializable]
public class Neuron : INucleus {
public class Neuron : Nucleus, INucleus {
public Neuron(Cluster parent, string name) {
this.parent = parent;
@ -24,30 +24,30 @@ public class Neuron : INucleus {
// Debug.LogError("No neuroid network");
}
[SerializeField]
protected string _name;
public virtual string name {
get => _name;
set => _name = value;
}
// [SerializeField]
// protected string _name;
// public virtual string name {
// get => _name;
// set => _name = value;
// }
[SerializeField]
private List<Synapse> _synapses = new();
public List<Synapse> synapses => _synapses;
// [SerializeField]
// private List<Synapse> _synapses = new();
// public List<Synapse> synapses => _synapses;
[SerializeReference]
private List<INucleus> _receivers = new();
public List<INucleus> receivers {
get { return _receivers; }
set { _receivers = value; }
}
// [SerializeReference]
// private List<INucleus> _receivers = new();
// public List<INucleus> receivers {
// get { return _receivers; }
// set { _receivers = value; }
// }
[SerializeReference]
private NucleusArray _array;
public NucleusArray array {
get { return _array; }
set { _array = value; }
}
// [SerializeReference]
// private NucleusArray _array;
// public NucleusArray array {
// get { return _array; }
// set { _array = value; }
// }
#region Serialization
@ -102,8 +102,8 @@ public class Neuron : INucleus {
#region Runtime state (not serialized)
public ClusterPrefab cluster { get; set; }
public Cluster parent { get; set; }
// public ClusterPrefab cluster { get; set; }
// public Cluster parent { get; set; }
#region Activation
@ -153,35 +153,35 @@ public class Neuron : INucleus {
#endregion Activation
protected float3 _outputValue;
public virtual float3 outputValue {
get { return _outputValue; }
set {
this.stale = 0;
// this._isSleeping = false;
_outputValue = value;
}
}
// protected float3 _outputValue;
// public virtual float3 outputValue {
// get { return _outputValue; }
// set {
// this.stale = 0;
// // this._isSleeping = false;
// _outputValue = value;
// }
// }
[NonSerialized]
private int stale = 1000;
// [NonSerialized]
// private int stale = 1000;
// private bool _isSleeping = false;
// public bool isSleeping => _isSleeping;
public bool isSleeping => lengthsq(this.outputValue) == 0;
// public bool isSleeping => lengthsq(this.outputValue) == 0;
public void UpdateNuclei() {
this.stale++;
// this._isSleeping = this.stale > 2;
// if (isSleeping)
if (this.stale > 2)
_outputValue = Vector3.zero;
}
// public void UpdateNuclei() {
// this.stale++;
// // this._isSleeping = this.stale > 2;
// // if (isSleeping)
// if (this.stale > 2)
// _outputValue = Vector3.zero;
// }
#endregion Runtime state
// this clone the nucleus without the synapses and receivers
public virtual IReceptor ShallowCloneTo(Cluster newParent) {
public override IReceptor ShallowCloneTo(Cluster newParent) {
Neuron clone = new(newParent, this.name) {
array = null,
curve = this.curve,
@ -192,7 +192,7 @@ public class Neuron : INucleus {
return clone;
}
public virtual IReceptor Clone() {
public override IReceptor Clone() {
Neuron clone = new(this.cluster, this.name) {
array = this.array,
curve = this.curve,
@ -213,22 +213,22 @@ public class Neuron : INucleus {
return clone;
}
public virtual void AddReceiver(INucleus receivingNucleus, float weight = 1) {
this._receivers.Add(receivingNucleus);
receivingNucleus.AddSynapse(this, weight);
}
// public virtual void AddReceiver(INucleus receivingNucleus, float weight = 1) {
// this._receivers.Add(receivingNucleus);
// receivingNucleus.AddSynapse(this, weight);
// }
public void RemoveReceiver(INucleus receiverNucleus) {
this._receivers.RemoveAll(receiver => receiver == receiverNucleus);
receiverNucleus.synapses.RemoveAll(synapse => synapse.nucleus == this);
}
// public void RemoveReceiver(INucleus receiverNucleus) {
// this._receivers.RemoveAll(receiver => receiver == receiverNucleus);
// receiverNucleus.synapses.RemoveAll(synapse => synapse.nucleus == this);
// }
public static void Delete(INucleus nucleus) {
foreach (Synapse synapse in nucleus.synapses) {
if (synapse.nucleus is Neuron synapse_nucleus) {
if (synapse_nucleus._receivers.Count > 1) {
if (synapse_nucleus.receivers.Count > 1) {
// there is another nucleus feeding into this input nucleus
synapse_nucleus._receivers.RemoveAll(r => r == nucleus);
synapse_nucleus.receivers.RemoveAll(r => r == nucleus);
}
else {
// No other links, delete it.
@ -247,11 +247,11 @@ public class Neuron : INucleus {
}
}
public Synapse AddSynapse(IReceptor sendingNucleus, float weight = 1.0f) {
Synapse synapse = new(sendingNucleus, weight);
this.synapses.Add(synapse);
return synapse;
}
// public Synapse AddSynapse(IReceptor sendingNucleus, float weight = 1.0f) {
// Synapse synapse = new(sendingNucleus, weight);
// this.synapses.Add(synapse);
// return synapse;
// }
// public virtual void UpdateState() {
// //UpdateState(new float3(0, 0, 0));
@ -296,10 +296,10 @@ public class Neuron : INucleus {
// UpdateResult(result);
// }
public virtual void UpdateStateIsolated() {
UpdateStateIsolated(new float3(0, 0, 0));
}
public virtual void UpdateStateIsolated(float3 bias) {
// public virtual void UpdateStateIsolated() {
// UpdateStateIsolated(new float3(0, 0, 0));
// }
public override void UpdateStateIsolated(float3 bias) {
float3 sum = bias;
int n = 0;

105
Nucleus.cs Normal file
View File

@ -0,0 +1,105 @@
using System;
using System.Collections.Generic;
using UnityEngine;
using Unity.Mathematics;
using static Unity.Mathematics.math;
public abstract class Nucleus : IReceptor {
[SerializeField]
protected string _name;
public virtual string name {
get => _name;
set => _name = value;
}
//[Obsolete]
public ClusterPrefab cluster { get; set; }
public Cluster parent { get; set; }
protected float3 _outputValue;
public virtual float3 outputValue {
get { return _outputValue; }
set {
this.stale = 0;
// this._isSleeping = false;
_outputValue = value;
}
}
public bool isSleeping => lengthsq(this.outputValue) == 0;
[NonSerialized]
private int stale = 1000;
// Cannot clone an abstract nucleus...
public virtual IReceptor ShallowCloneTo(Cluster parent) { return null; }
// Cannot clone an abstract nucleus...
public virtual IReceptor Clone() { return null; }
#region Synapses
[SerializeField]
private List<Synapse> _synapses = new();
public List<Synapse> synapses => _synapses;
public Synapse AddSynapse(IReceptor sendingNucleus, float weight = 1.0f) {
Synapse synapse = new(sendingNucleus, weight);
this.synapses.Add(synapse);
return synapse;
}
public Synapse GetSynapse(INucleus sender) {
foreach (Synapse synapse in this.synapses)
if (synapse.nucleus == sender)
return synapse;
return null;
}
#endregion Synapses
#region Receivers
[SerializeReference]
private List<INucleus> _receivers = new();
public List<INucleus> receivers {
get { return _receivers; }
set { _receivers = value; }
}
public virtual void AddReceiver(INucleus receivingNucleus, float weight = 1) {
this._receivers.Add(receivingNucleus);
receivingNucleus.AddSynapse(this, weight);
}
public void RemoveReceiver(INucleus receiverNucleus) {
this._receivers.RemoveAll(receiver => receiver == receiverNucleus);
receiverNucleus.synapses.RemoveAll(synapse => synapse.nucleus == this);
}
#endregion Receivers
[SerializeReference]
private NucleusArray _array;
public NucleusArray array {
get { return _array; }
set { _array = value; }
}
#region Update
public virtual void UpdateStateIsolated() {
UpdateStateIsolated(new float3(0, 0, 0));
}
public virtual void UpdateStateIsolated(float3 bias) {
}
public void UpdateNuclei() {
this.stale++;
if (this.stale > 2)
_outputValue = Vector3.zero;
}
#endregion Update
}

2
Nucleus.cs.meta Normal file
View File

@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 4310eea6ab77628b085387a226c1c386

View File

@ -9,8 +9,8 @@ public class SelectorBrain : NanoBrain {
public Receptor receptor2;
protected void Awake() {
receptor1 = Receptor.CreateReceptor(this.brain, "Selector");
receptor2 = Receptor.CreateReceptor(this.brain, "Selector");
receptor1 = new Receptor(this.brain, "Receptor", "Selector");
receptor2 = new Receptor(this.brain, "Receptor", "Selector");
}
protected void Update() {