103 lines
3.7 KiB
C#
103 lines
3.7 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
|
|
public string hello = "hello";
|
|
|
|
[SerializeReference]
|
|
public List<Nucleus> nuclei = new();
|
|
|
|
|
|
public virtual Nucleus output => this.nuclei[0] as Nucleus;
|
|
|
|
public List<Nucleus> _inputs = null;
|
|
public virtual List<Nucleus> inputs {
|
|
get {
|
|
if (this._inputs == null) {
|
|
this._inputs = new();
|
|
foreach (Nucleus receptor in this.nuclei) {
|
|
if (receptor is Nucleus nucleus) {
|
|
// inputs have no incoming synapses yet.
|
|
if (nucleus.synapses.Count == 0)
|
|
this._inputs.Add(nucleus);
|
|
}
|
|
}
|
|
}
|
|
return this._inputs;
|
|
}
|
|
}
|
|
private List<Nucleus> _outputs = null;
|
|
public List<Nucleus> outputs {
|
|
get {
|
|
if (this._outputs == null)
|
|
RefreshOutputs();
|
|
return this._outputs;
|
|
}
|
|
}
|
|
public void RefreshOutputs() {
|
|
this._outputs = new();
|
|
foreach (Nucleus nucleus in this.nuclei) {
|
|
if (nucleus.receivers.Count == 0)
|
|
this._outputs.Add(nucleus);
|
|
}
|
|
}
|
|
|
|
public Nucleus GetNucleus(string nucleusName) {
|
|
foreach (Nucleus nucleus in this.nuclei) {
|
|
if (nucleus.name == nucleusName)
|
|
return nucleus;
|
|
}
|
|
return null;
|
|
}
|
|
|
|
// 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<Nucleus>();
|
|
if (nuclei.Count == 0)
|
|
new Neuron(this, "Output"); // Every cluster should have at least 1 neuron
|
|
}
|
|
|
|
public void GarbageCollection() {
|
|
HashSet<Nucleus> visitedNuclei = new();
|
|
MarkNuclei(visitedNuclei, this.output);
|
|
//Debug.Log($"Garbage collection found {visitedNuclei.Count} Nuclei");
|
|
this.nuclei.RemoveAll(nucleus => nucleus is Nucleus n && visitedNuclei.Contains(n) == false);
|
|
}
|
|
|
|
public void MarkNuclei(HashSet<Nucleus> visitedNuclei, Nucleus 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 Nucleus synapse_nucleus)
|
|
MarkNuclei(visitedNuclei, synapse_nucleus);
|
|
}
|
|
}
|
|
nucleus.synapses.RemoveAll(synapse => visitedSynapses.Contains(synapse) == false);
|
|
}
|
|
if (nucleus.receivers != null) {
|
|
HashSet<Nucleus> visitedReceivers = new();
|
|
foreach (Nucleus 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 (Nucleus nucleus in this.nuclei)
|
|
nucleus.UpdateNuclei();
|
|
}
|
|
} |