NanoBrain-unitypackage/ClusterPrefab.cs

84 lines
3.1 KiB
C#

using System.Collections.Generic;
using UnityEngine;
[CreateAssetMenu(menuName = "Passer/Cluster")]
public class ClusterPrefab : ScriptableObject {
//public virtual Cluster cluster {get;set;}
// The ScriptableObject asset from which the runtime object has been created
//public Cluster asset;
[SerializeReference]
public List<IReceptor> nuclei = new();
// public List<Cluster> subClusters = new();
// public void AddSubCluster(ClusterInstance subCluster) {
// this.nuclei.Add(subCluster);
// }
public virtual INucleus output => this.nuclei[0] as INucleus;
public List<INucleus> _inputs = null;
public virtual List<INucleus> inputs {
get {
if (this._inputs == null) {
this._inputs = new();
foreach (IReceptor receptor in this.nuclei) {
if (receptor is INucleus nucleus)
this._inputs.Add(nucleus);
}
}
return this._inputs;
}
}
// Call this function to ensure that there is at least one nucleus
// This is an invariant and should be ensured before the nucleus is used
// because output requires it.
public void EnsureInitialization() {
nuclei ??= new List<IReceptor>();
if (nuclei.Count == 0)
new Neuron(this, "Output"); // Every cluster should have at least 1 neuron
}
public void GarbageCollection() {
HashSet<INucleus> visitedNuclei = new();
MarkNuclei(visitedNuclei, this.output);
//Debug.Log($"Garbage collection found {visitedNuclei.Count} Nuclei");
this.nuclei.RemoveAll(nucleus => nucleus is INucleus n && visitedNuclei.Contains(n) == false);
}
public void MarkNuclei(HashSet<INucleus> visitedNuclei, INucleus nucleus) {
if (nucleus is null)
return;
visitedNuclei.Add(nucleus);
if (nucleus.synapses != null) {
HashSet<Synapse> visitedSynapses = new();
foreach (Synapse synapse in nucleus.synapses) {
if (synapse != null && synapse.nucleus != null) {
visitedSynapses.Add(synapse);
if (synapse.nucleus is INucleus synapse_nucleus)
MarkNuclei(visitedNuclei, synapse_nucleus);
}
}
nucleus.synapses.RemoveAll(synapse => visitedSynapses.Contains(synapse) == false);
}
if (nucleus.receivers != null) {
HashSet<INucleus> visitedReceivers = new();
foreach (INucleus receiver in nucleus.receivers) {
if (receiver != null && receiver != null) {
visitedReceivers.Add(receiver);
visitedNuclei.Add(receiver);
}
}
nucleus.receivers.RemoveAll(receiver => visitedReceivers.Contains(receiver) == false);
}
}
public virtual void UpdateNuclei() {
foreach (IReceptor nucleus in this.nuclei)
nucleus.UpdateNuclei();
}
}