80 lines
3.0 KiB
C#
80 lines
3.0 KiB
C#
using System.Collections.Generic;
|
|
using UnityEngine;
|
|
|
|
[CreateAssetMenu(menuName = "Passer/Cluster")]
|
|
public class ClusterPrefab : ScriptableObject {
|
|
|
|
// The ScriptableObject asset from which the runtime object has been created
|
|
|
|
[SerializeReference]
|
|
public List<INucleus> nuclei = new();
|
|
|
|
|
|
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) {
|
|
// inputs have no incoming synapses yet.
|
|
if (nucleus.synapses.Count == 0)
|
|
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<INucleus>();
|
|
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 (INucleus nucleus in this.nuclei)
|
|
nucleus.UpdateNuclei();
|
|
}
|
|
} |