WIP cluster references/instance
This commit is contained in:
parent
04bab9264f
commit
d583e67e39
@ -7,7 +7,7 @@ using UnityEngine.UIElements;
|
|||||||
namespace NanoBrain {
|
namespace NanoBrain {
|
||||||
|
|
||||||
[CustomEditor(typeof(Brain))]
|
[CustomEditor(typeof(Brain))]
|
||||||
public class NanoBrainComponent_Editor : Editor {
|
public class Brain_Editor : Editor {
|
||||||
protected static VisualElement mainContainer;
|
protected static VisualElement mainContainer;
|
||||||
protected static VisualElement inspectorContainer;
|
protected static VisualElement inspectorContainer;
|
||||||
|
|
||||||
@ -24,7 +24,7 @@ namespace NanoBrain {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public override VisualElement CreateInspectorGUI() {
|
public override VisualElement CreateInspectorGUI() {
|
||||||
Cluster brain = component.brain;
|
Cluster brain = component.InitializeBrain();
|
||||||
|
|
||||||
if (Application.isPlaying == false)
|
if (Application.isPlaying == false)
|
||||||
serializedObject.Update();
|
serializedObject.Update();
|
||||||
@ -47,6 +47,7 @@ namespace NanoBrain {
|
|||||||
root.Add(brainField);
|
root.Add(brainField);
|
||||||
//}
|
//}
|
||||||
|
|
||||||
|
|
||||||
if (brain != null)
|
if (brain != null)
|
||||||
CreateViewer(root, brain.prefab, brain.defaultOutput, component.gameObject);
|
CreateViewer(root, brain.prefab, brain.defaultOutput, component.gameObject);
|
||||||
|
|
||||||
|
|||||||
@ -8,7 +8,7 @@ using UnityEngine.UIElements;
|
|||||||
namespace NanoBrain {
|
namespace NanoBrain {
|
||||||
|
|
||||||
[CustomEditor(typeof(ClusterPrefab))]
|
[CustomEditor(typeof(ClusterPrefab))]
|
||||||
public class ClusterInspector : ClusterViewer {
|
public class ClusterEditor : ClusterViewer {
|
||||||
|
|
||||||
public override VisualElement CreateInspectorGUI() {
|
public override VisualElement CreateInspectorGUI() {
|
||||||
ClusterPrefab prefab = target as ClusterPrefab;
|
ClusterPrefab prefab = target as ClusterPrefab;
|
||||||
@ -18,13 +18,13 @@ namespace NanoBrain {
|
|||||||
serializedObject.Update();
|
serializedObject.Update();
|
||||||
|
|
||||||
VisualElement root = new();
|
VisualElement root = new();
|
||||||
CreateInspector(root, prefab, prefab.output, null);
|
CreateEditor(root, prefab, prefab.output, null);
|
||||||
|
|
||||||
serializedObject.ApplyModifiedProperties();
|
serializedObject.ApplyModifiedProperties();
|
||||||
return root;
|
return root;
|
||||||
}
|
}
|
||||||
|
|
||||||
public GraphView CreateInspector(VisualElement root, ClusterPrefab cluster, Nucleus output, GameObject gameObject) {
|
public GraphView CreateEditor(VisualElement root, ClusterPrefab cluster, Nucleus output, GameObject gameObject) {
|
||||||
root.style.paddingLeft = 0;
|
root.style.paddingLeft = 0;
|
||||||
root.style.paddingRight = 0;
|
root.style.paddingRight = 0;
|
||||||
root.style.paddingTop = 0;
|
root.style.paddingTop = 0;
|
||||||
@ -42,7 +42,6 @@ namespace NanoBrain {
|
|||||||
graphContainer.style.width = 300;
|
graphContainer.style.width = 300;
|
||||||
graphContainer.style.overflow = Overflow.Hidden;
|
graphContainer.style.overflow = Overflow.Hidden;
|
||||||
|
|
||||||
|
|
||||||
VisualElement inspectorContainer = new() {
|
VisualElement inspectorContainer = new() {
|
||||||
name = "inspector",
|
name = "inspector",
|
||||||
style = {
|
style = {
|
||||||
@ -57,7 +56,7 @@ namespace NanoBrain {
|
|||||||
mainContainer.Add(inspectorContainer);
|
mainContainer.Add(inspectorContainer);
|
||||||
root.Add(mainContainer);
|
root.Add(mainContainer);
|
||||||
|
|
||||||
graphContainer.SetGraph(gameObject, output, inspectorContainer, this);
|
graphContainer.SetGraph(gameObject, output, inspectorContainer);
|
||||||
|
|
||||||
return graphContainer;
|
return graphContainer;
|
||||||
}
|
}
|
||||||
@ -83,11 +82,9 @@ namespace NanoBrain {
|
|||||||
this.currentNucleus = newOutput;
|
this.currentNucleus = newOutput;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetGraph(GameObject gameObject, Nucleus nucleus, VisualElement inspectorContainer, ClusterInspector editor) {
|
public void SetGraph(GameObject gameObject, Nucleus nucleus, VisualElement inspectorContainer) {
|
||||||
this.gameObject = gameObject;
|
this.gameObject = gameObject;
|
||||||
this.currentEditor = editor;
|
|
||||||
|
|
||||||
//this.cluster = brain;
|
|
||||||
if (Application.isPlaying == false)
|
if (Application.isPlaying == false)
|
||||||
this.serializedBrain = new SerializedObject(this.prefab);
|
this.serializedBrain = new SerializedObject(this.prefab);
|
||||||
this.currentNucleus = nucleus;
|
this.currentNucleus = nucleus;
|
||||||
@ -96,7 +93,7 @@ namespace NanoBrain {
|
|||||||
OnOutputChanged(outputsPopup.choices[0]);
|
OnOutputChanged(outputsPopup.choices[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Rebuild(VisualElement inspectorContainer) {
|
private void Rebuild(VisualElement inspectorContainer) {
|
||||||
BuildLayers();
|
BuildLayers();
|
||||||
|
|
||||||
if (this.currentNucleus == null) {
|
if (this.currentNucleus == null) {
|
||||||
@ -121,6 +118,11 @@ namespace NanoBrain {
|
|||||||
|
|
||||||
// create a SerializedObject wrapper so Unity inspector controls work (and Undo)
|
// create a SerializedObject wrapper so Unity inspector controls work (and Undo)
|
||||||
SerializedObject so = new(prefabAsset);
|
SerializedObject so = new(prefabAsset);
|
||||||
|
|
||||||
|
foreach (Nucleus nucleus in this.prefab.nuclei) {
|
||||||
|
nucleus.Initialize();
|
||||||
|
}
|
||||||
|
|
||||||
this.inspectorIMGUIContainer = new IMGUIContainer(() => InspectorHandler(so));
|
this.inspectorIMGUIContainer = new IMGUIContainer(() => InspectorHandler(so));
|
||||||
|
|
||||||
inspectorContainer.Add(inspectorIMGUIContainer);
|
inspectorContainer.Add(inspectorIMGUIContainer);
|
||||||
@ -257,7 +259,6 @@ namespace NanoBrain {
|
|||||||
}
|
}
|
||||||
trace = EditorGUILayout.Toggle("Trace", trace);
|
trace = EditorGUILayout.Toggle("Trace", trace);
|
||||||
this.currentNucleus.trace = trace;
|
this.currentNucleus.trace = trace;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void SynapsesInspector(ref bool anythingChanged) {
|
protected void SynapsesInspector(ref bool anythingChanged) {
|
||||||
@ -319,19 +320,27 @@ namespace NanoBrain {
|
|||||||
else {
|
else {
|
||||||
EditorGUILayout.BeginHorizontal();
|
EditorGUILayout.BeginHorizontal();
|
||||||
|
|
||||||
if (synapse.neuron.parent != null && synapse.neuron.parent != this.currentNucleus) {
|
if (synapse.neuron.clusterPrefab != this.currentNucleus.clusterPrefab) {
|
||||||
// If it is a cluster
|
// If it is a cluster
|
||||||
GUIStyle labelStyle = new(GUI.skin.label);
|
GUIStyle labelStyle = new(GUI.skin.label);
|
||||||
float labelWidth = 200;
|
float labelWidth = 200;
|
||||||
if (synapse.neuron.clusterPrefab != null) {
|
if (synapse.neuron.clusterPrefab != null) {
|
||||||
labelWidth = labelStyle.CalcSize(new GUIContent($"{synapse.neuron.parent.baseName}.")).x;
|
labelWidth = labelStyle.CalcSize(new GUIContent($"{synapse.neuron.clusterPrefab.name}.")).x;
|
||||||
GUILayout.Label($"{synapse.neuron.parent.baseName}", GUILayout.Width(labelWidth));
|
GUILayout.Label($"{synapse.neuron.clusterPrefab.name}", GUILayout.Width(labelWidth));
|
||||||
}
|
}
|
||||||
string[] options = synapse.neuron.parent.clusterNuclei.Select(n => n.name).ToArray();
|
//string[] options = synapse.neuron.parent.clusterNuclei.Select(n => n.name).ToArray();
|
||||||
|
string[] options = synapse.neuron.clusterPrefab.nuclei.Select(n => n.name).ToArray();
|
||||||
int selectedIndex = System.Array.IndexOf(options, synapse.neuron.name);
|
int selectedIndex = System.Array.IndexOf(options, synapse.neuron.name);
|
||||||
int newIndex = EditorGUILayout.Popup(selectedIndex, options);
|
int newIndex = EditorGUILayout.Popup(selectedIndex, options);
|
||||||
if (newIndex != selectedIndex && synapse.neuron.parent.clusterNuclei[newIndex] is Neuron newNeuron)
|
// if (newIndex != selectedIndex && synapse.neuron.clusterPrefab.nuclei[newIndex] is Neuron newNeuron)
|
||||||
|
// ChangeSynapse(synapse, newNeuron);
|
||||||
|
if (newIndex != selectedIndex) {
|
||||||
|
// It shall be ensured that the parent.clusterNuclei and
|
||||||
|
// clusterPrefab.nuclei contain the same neurons in the same order....
|
||||||
|
Nucleus selectedNucleus = synapse.neuron.parent.clusterNuclei[newIndex];
|
||||||
|
Neuron newNeuron = selectedNucleus as Neuron;
|
||||||
ChangeSynapse(synapse, newNeuron);
|
ChangeSynapse(synapse, newNeuron);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
GUILayout.Label(synapse.neuron.name);
|
GUILayout.Label(synapse.neuron.name);
|
||||||
@ -9,7 +9,6 @@ namespace NanoBrain {
|
|||||||
|
|
||||||
public class ClusterViewer : Editor {
|
public class ClusterViewer : Editor {
|
||||||
|
|
||||||
//public static ClusterViewer previousEditor;
|
|
||||||
public static ClusterPrefab previousPrefab;
|
public static ClusterPrefab previousPrefab;
|
||||||
|
|
||||||
public class GraphView : VisualElement {
|
public class GraphView : VisualElement {
|
||||||
@ -29,9 +28,6 @@ namespace NanoBrain {
|
|||||||
protected IMGUIContainer graphContainer;
|
protected IMGUIContainer graphContainer;
|
||||||
protected readonly PopupField<string> outputsPopup;
|
protected readonly PopupField<string> outputsPopup;
|
||||||
|
|
||||||
public ClusterInspector currentEditor;
|
|
||||||
//public ClusterViewer previousEditor;
|
|
||||||
|
|
||||||
public enum Mode {
|
public enum Mode {
|
||||||
Focus,
|
Focus,
|
||||||
Full
|
Full
|
||||||
@ -93,8 +89,8 @@ namespace NanoBrain {
|
|||||||
RegisterCallback<DetachFromPanelEvent>(evt => Unsubscribe());
|
RegisterCallback<DetachFromPanelEvent>(evt => Unsubscribe());
|
||||||
}
|
}
|
||||||
|
|
||||||
protected virtual void OnModeChange(ChangeEvent<System.Enum> evt) {
|
protected virtual void OnModeChange(ChangeEvent<System.Enum> changeEvent) {
|
||||||
mode = (Mode)evt.newValue;
|
this.mode = (Mode)changeEvent.newValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected virtual void OnOutputChanged(string outputName) {
|
protected virtual void OnOutputChanged(string outputName) {
|
||||||
@ -441,8 +437,6 @@ namespace NanoBrain {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void DrawSynapses(Nucleus nucleus, Vector3 parentPos, float size) {
|
private void DrawSynapses(Nucleus nucleus, Vector3 parentPos, float size) {
|
||||||
int nodeCount = nucleus.synapses.Count;
|
|
||||||
|
|
||||||
// Determine the maximum value in this layer
|
// Determine the maximum value in this layer
|
||||||
// This is used to 'scale' the output value colors of the nuclei
|
// This is used to 'scale' the output value colors of the nuclei
|
||||||
float maxValue = 0;
|
float maxValue = 0;
|
||||||
@ -452,7 +446,7 @@ namespace NanoBrain {
|
|||||||
if (synapse.neuron == null)
|
if (synapse.neuron == null)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// Draw multiple synapses to the same neuron only once
|
// Count multiple synapses to the same neuron only once
|
||||||
if (drawnNeurons.Contains(synapse.neuron))
|
if (drawnNeurons.Contains(synapse.neuron))
|
||||||
continue;
|
continue;
|
||||||
drawnNeurons.Add(synapse.neuron);
|
drawnNeurons.Add(synapse.neuron);
|
||||||
@ -474,6 +468,7 @@ namespace NanoBrain {
|
|||||||
if (synapse.neuron is null)
|
if (synapse.neuron is null)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
// Draw multiple synapses to the same neuron only once
|
||||||
if (drawnNeurons.Contains(synapse.neuron))
|
if (drawnNeurons.Contains(synapse.neuron))
|
||||||
continue;
|
continue;
|
||||||
drawnNeurons.Add(synapse.neuron);
|
drawnNeurons.Add(synapse.neuron);
|
||||||
@ -485,8 +480,7 @@ namespace NanoBrain {
|
|||||||
if (Application.isPlaying) {
|
if (Application.isPlaying) {
|
||||||
if (maxValue == 0 || !float.IsFinite(maxValue))
|
if (maxValue == 0 || !float.IsFinite(maxValue))
|
||||||
maxValue = 1;
|
maxValue = 1;
|
||||||
float brightness = 0;
|
float brightness = synapse.neuron.outputMagnitude * synapse.weight / maxValue;
|
||||||
brightness = synapse.neuron.outputMagnitude * synapse.weight / maxValue;
|
|
||||||
color = new Color(brightness, brightness, brightness, 1f);
|
color = new Color(brightness, brightness, brightness, 1f);
|
||||||
}
|
}
|
||||||
DrawNucleus(synapse.neuron, pos, size, color);
|
DrawNucleus(synapse.neuron, pos, size, color);
|
||||||
@ -731,7 +725,7 @@ namespace NanoBrain {
|
|||||||
Selection.activeObject = subCluster.prefab;
|
Selection.activeObject = subCluster.prefab;
|
||||||
EditorGUIUtility.PingObject(subCluster.prefab);
|
EditorGUIUtility.PingObject(subCluster.prefab);
|
||||||
ClusterViewer.previousPrefab = this.prefab;
|
ClusterViewer.previousPrefab = this.prefab;
|
||||||
ClusterInspector newEditor = CreateEditor(subCluster.prefab) as ClusterInspector;
|
ClusterEditor newEditor = CreateEditor(subCluster.prefab) as ClusterEditor;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion Graph
|
#endregion Graph
|
||||||
|
|||||||
@ -20,17 +20,24 @@ namespace NanoBrain {
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public Cluster brain {
|
public Cluster brain {
|
||||||
get {
|
get {
|
||||||
if (brainInstance == null && brainPrefab != null) {
|
// if (brainInstance == null && brainPrefab != null) {
|
||||||
brainInstance = new Cluster(brainPrefab) {
|
// brainInstance = new Cluster(brainPrefab) {
|
||||||
name = brainPrefab.name
|
// name = brainPrefab.name
|
||||||
};
|
// };
|
||||||
} else if (brainInstance != null && brainPrefab == null) {
|
// } else if (brainInstance != null && brainPrefab == null) {
|
||||||
brainInstance = null;
|
// brainInstance = null;
|
||||||
}
|
// }
|
||||||
return brainInstance;
|
return brainInstance;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Cluster InitializeBrain() {
|
||||||
|
brainInstance = new Cluster(brainPrefab) {
|
||||||
|
name = brainPrefab.name
|
||||||
|
};
|
||||||
|
return brainInstance;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Update the weight for all Synapses coming from the Neuron with the given name
|
/// Update the weight for all Synapses coming from the Neuron with the given name
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@ -17,6 +17,8 @@ namespace NanoBrain {
|
|||||||
public class Cluster : Nucleus {
|
public class Cluster : Nucleus {
|
||||||
// It may be that clusters will not be nuclei anymore in the future....
|
// It may be that clusters will not be nuclei anymore in the future....
|
||||||
|
|
||||||
|
public ClusterPrefab prefab;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The base name of the cluster. I don't think this is actively used at this moment
|
/// The base name of the cluster. I don't think this is actively used at this moment
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -36,6 +38,12 @@ namespace NanoBrain {
|
|||||||
public int instanceCount = 1;
|
public int instanceCount = 1;
|
||||||
public Dictionary<int, Cluster> thingClusters = new();
|
public Dictionary<int, Cluster> thingClusters = new();
|
||||||
|
|
||||||
|
[SerializeReference]
|
||||||
|
public List<Nucleus> clusterNuclei = new();
|
||||||
|
// the nuclei sorted using topological sorting
|
||||||
|
// to ensure that the cluster is computer in the right order
|
||||||
|
public List<Nucleus> sortedNuclei;
|
||||||
|
|
||||||
#region Init
|
#region Init
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -79,8 +87,9 @@ namespace NanoBrain {
|
|||||||
/// Where which the clone be found???
|
/// Where which the clone be found???
|
||||||
private void ClonePrefab() {
|
private void ClonePrefab() {
|
||||||
Nucleus[] prefabNuclei = this.prefab.nuclei.ToArray();
|
Nucleus[] prefabNuclei = this.prefab.nuclei.ToArray();
|
||||||
|
|
||||||
// first clone the nuclei without their connections
|
// first clone the nuclei without their connections
|
||||||
foreach (Nucleus nucleus in this.prefab.nuclei) {
|
foreach (Nucleus nucleus in prefabNuclei) {
|
||||||
nucleus.ShallowCloneTo(this);
|
nucleus.ShallowCloneTo(this);
|
||||||
}
|
}
|
||||||
Nucleus[] clonedNuclei = this.clusterNuclei.ToArray();
|
Nucleus[] clonedNuclei = this.clusterNuclei.ToArray();
|
||||||
@ -95,110 +104,152 @@ namespace NanoBrain {
|
|||||||
if (clonedNucleus == null || clonedNucleus is not Neuron clonedNeuron)
|
if (clonedNucleus == null || clonedNucleus is not Neuron clonedNeuron)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// Copy the receivers, which will also create the synapses
|
foreach (Synapse prefabSynapse in prefabNeuron.synapses) {
|
||||||
// Clusters do not have receivers...
|
Neuron synapseNeuron = prefabSynapse.neuron;
|
||||||
foreach (Nucleus receiver in prefabNeuron.receivers.ToArray()) {
|
if (synapseNeuron.parent is not null && synapseNeuron.clusterPrefab != this.clusterPrefab) {
|
||||||
int ix = GetNucleusIndex(prefabNuclei, receiver);
|
// Neuron is in another cluster, find the cloned cluster first
|
||||||
if (ix < 0)
|
Cluster prefabCluster = synapseNeuron.parent;
|
||||||
continue;
|
int clusterIx = GetNucleusIndex(prefabNuclei, prefabCluster);
|
||||||
|
if (clusterIx < 0)
|
||||||
if (clonedNuclei[ix] is not Nucleus clonedReceiver)
|
// Could not find the cluster in the prefab
|
||||||
continue;
|
continue;
|
||||||
|
if (clonedNuclei[clusterIx] is not Cluster clonedCluster)
|
||||||
// Find the synapse for the weight
|
// Could not find the cloned cluster
|
||||||
float weight = 1;
|
|
||||||
foreach (Synapse synapse in receiver.synapses) {
|
|
||||||
// Find the weight for this synapse
|
|
||||||
if (synapse.neuron == prefabNucleus) {
|
|
||||||
weight = synapse.weight;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
clonedNeuron.AddReceiver(clonedReceiver, weight);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Copy the siblings for clusters
|
|
||||||
for (int nucleusIx = 0; nucleusIx < prefabNuclei.Length; nucleusIx++) {
|
|
||||||
Nucleus prefabNucleus = prefabNuclei[nucleusIx];
|
|
||||||
if (prefabNucleus is not Cluster prefabCluster)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (prefabCluster.siblingClusters == null || prefabCluster.siblingClusters.Length == 0)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
Cluster clonedNucleus = clonedNuclei[nucleusIx] as Cluster;
|
|
||||||
if (prefabCluster == prefabCluster.siblingClusters[0]) {
|
|
||||||
// We clone the array only for the first entry
|
|
||||||
//NucleusArray clonedArray = new(prefabReceptor.nucleiArray.Length);
|
|
||||||
Cluster[] clonedArray = new Cluster[prefabCluster.siblingClusters.Length];
|
|
||||||
int arrayIx = 0;
|
|
||||||
foreach (Cluster prefabArrayNucleus in prefabCluster.siblingClusters) {
|
|
||||||
int arrayNucleusIx = GetNucleusIndex(prefabNuclei, prefabArrayNucleus);
|
|
||||||
if (arrayNucleusIx >= 0) {
|
|
||||||
Cluster clonedArrayNucleus = clonedNuclei[arrayNucleusIx] as Cluster;
|
|
||||||
clonedArray[arrayIx] = clonedArrayNucleus;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
Debug.LogError($" Could not find prefab nucleus {prefabNucleus.name} in the clones");
|
|
||||||
}
|
|
||||||
arrayIx++;
|
|
||||||
}
|
|
||||||
clonedNucleus.siblingClusters = clonedArray;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
// The others will refer to the array created for the first nucleus in the array
|
|
||||||
int firstNucleusIx = GetNucleusIndex(prefabNuclei, prefabCluster.siblingClusters[0]);
|
|
||||||
Cluster clonedFirstNucleus = clonedNuclei[firstNucleusIx] as Cluster;
|
|
||||||
clonedNucleus.siblingClusters = clonedFirstNucleus.siblingClusters;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Collect the subclusters
|
|
||||||
List<Cluster> subClusters = new();
|
|
||||||
foreach (Nucleus nucleus in prefabNuclei) {
|
|
||||||
foreach (Synapse synapse in nucleus.synapses) {
|
|
||||||
Nucleus synapseNucleus = synapse.neuron;
|
|
||||||
if (synapseNucleus is not Cluster subCluster)
|
|
||||||
continue;
|
|
||||||
if (subClusters.Contains(subCluster))
|
|
||||||
continue;
|
|
||||||
subClusters.Add(subCluster);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Create the subcluster instances
|
|
||||||
foreach (Cluster subCluster in subClusters) {
|
|
||||||
for (int ix = 0; ix < subCluster.instanceCount; ix++) {
|
|
||||||
// create the new instance
|
|
||||||
Cluster clusterInstance = new(subCluster.prefab);
|
|
||||||
// connect it
|
|
||||||
foreach ((Neuron sender, Nucleus receiver) in subCluster.CollectConnections()) {
|
|
||||||
int receiverIx = GetNucleusIndex(prefabNuclei, receiver);
|
|
||||||
if (receiverIx < 0)
|
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (clonedNuclei[receiverIx] is not Nucleus clonedReceiver)
|
// Now find the neuron in that cloned cluster
|
||||||
|
int neuronIx = GetNucleusIndex(prefabCluster.prefab.nuclei, prefabSynapse.neuron);
|
||||||
|
if (neuronIx < 0)
|
||||||
|
// Could not find the neuron in the prefab cluster
|
||||||
|
continue;
|
||||||
|
if (clonedCluster.clusterNuclei[neuronIx] is not Neuron clonedSender)
|
||||||
|
// Could not find the neuron in the cloned cluster
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// Find the synapse for the weight
|
clonedSender.AddReceiver(clonedNeuron, prefabSynapse.weight);
|
||||||
float weight = 1;
|
}
|
||||||
foreach (Synapse synapse in receiver.synapses) {
|
else {
|
||||||
// Find the weight for this synapse
|
int ix = GetNucleusIndex(prefabNuclei, prefabSynapse.neuron);
|
||||||
if (synapse.neuron == sender) {
|
if (ix < 0)
|
||||||
weight = synapse.weight;
|
continue;
|
||||||
break;
|
if (clonedNuclei[ix] is not Neuron clonedSender)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// Copy the receivers which will also create the synapse
|
||||||
|
clonedSender.AddReceiver(clonedNeuron, prefabSynapse.weight);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// // Copy the receivers, which will also create the synapses
|
||||||
|
// foreach (Nucleus receiver in prefabNeuron.receivers.ToArray()) {
|
||||||
|
// int ix = GetNucleusIndex(prefabNuclei, receiver);
|
||||||
|
// if (ix < 0)
|
||||||
|
// continue;
|
||||||
|
|
||||||
|
// if (clonedNuclei[ix] is not Nucleus clonedReceiver)
|
||||||
|
// continue;
|
||||||
|
|
||||||
|
// // Find the synapse for the weight
|
||||||
|
// float weight = 1;
|
||||||
|
// foreach (Synapse synapse in receiver.synapses) {
|
||||||
|
// // Find the weight for this synapse
|
||||||
|
// if (synapse.neuron == prefabNucleus) {
|
||||||
|
// weight = synapse.weight;
|
||||||
|
// break;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// clonedNeuron.AddReceiver(clonedReceiver, weight);
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
// Copy the siblings for clusters
|
||||||
|
for (int nucleusIx = 0; nucleusIx < prefabNuclei.Length; nucleusIx++) {
|
||||||
|
Nucleus prefabNucleus = prefabNuclei[nucleusIx];
|
||||||
|
if (prefabNucleus is not Cluster prefabCluster)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (prefabCluster.siblingClusters == null || prefabCluster.siblingClusters.Length == 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
Cluster clonedNucleus = clonedNuclei[nucleusIx] as Cluster;
|
||||||
|
if (prefabCluster == prefabCluster.siblingClusters[0]) {
|
||||||
|
// We clone the array only for the first entry
|
||||||
|
//NucleusArray clonedArray = new(prefabReceptor.nucleiArray.Length);
|
||||||
|
Cluster[] clonedArray = new Cluster[prefabCluster.siblingClusters.Length];
|
||||||
|
int arrayIx = 0;
|
||||||
|
foreach (Cluster prefabArrayNucleus in prefabCluster.siblingClusters) {
|
||||||
|
int arrayNucleusIx = GetNucleusIndex(prefabNuclei, prefabArrayNucleus);
|
||||||
|
if (arrayNucleusIx >= 0) {
|
||||||
|
Cluster clonedArrayNucleus = clonedNuclei[arrayNucleusIx] as Cluster;
|
||||||
|
clonedArray[arrayIx] = clonedArrayNucleus;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Debug.LogError($" Could not find prefab nucleus {prefabNucleus.name} in the clones");
|
||||||
|
}
|
||||||
|
arrayIx++;
|
||||||
|
}
|
||||||
|
clonedNucleus.siblingClusters = clonedArray;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// The others will refer to the array created for the first nucleus in the array
|
||||||
|
int firstNucleusIx = GetNucleusIndex(prefabNuclei, prefabCluster.siblingClusters[0]);
|
||||||
|
Cluster clonedFirstNucleus = clonedNuclei[firstNucleusIx] as Cluster;
|
||||||
|
clonedNucleus.siblingClusters = clonedFirstNucleus.siblingClusters;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (clusterInstance.GetNucleus(sender.name) is not Neuron clonedSender)
|
/*
|
||||||
continue;
|
// Collect the subclusters
|
||||||
|
List<Cluster> subClusters = new();
|
||||||
|
foreach (Nucleus nucleus in prefabNuclei) {
|
||||||
|
foreach (Synapse synapse in nucleus.synapses) {
|
||||||
|
Nucleus synapseNucleus = synapse.neuron;
|
||||||
|
Cluster subCluster = synapseNucleus.parent;
|
||||||
|
if (subCluster is null ||
|
||||||
|
synapseNucleus.clusterPrefab == this.clusterPrefab) {
|
||||||
|
|
||||||
clonedSender.AddReceiver(clonedReceiver, weight);
|
continue;
|
||||||
}
|
}
|
||||||
}
|
// if (synapseNucleus is not Cluster subCluster)
|
||||||
}
|
// continue;
|
||||||
|
if (subClusters.Contains(subCluster))
|
||||||
|
continue;
|
||||||
|
subClusters.Add(subCluster);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Create the subcluster instances
|
||||||
|
foreach (Cluster subCluster in subClusters) {
|
||||||
|
for (int ix = 0; ix < subCluster.instanceCount; ix++) {
|
||||||
|
// create the new instance
|
||||||
|
Cluster clusterInstance = new(subCluster.prefab);
|
||||||
|
// connect it
|
||||||
|
foreach ((Neuron sender, Nucleus receiver) in subCluster.CollectConnections()) {
|
||||||
|
int receiverIx = GetNucleusIndex(prefabNuclei, receiver);
|
||||||
|
if (receiverIx < 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (clonedNuclei[receiverIx] is not Nucleus clonedReceiver)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// Find the synapse for the weight
|
||||||
|
float weight = 1;
|
||||||
|
foreach (Synapse synapse in receiver.synapses) {
|
||||||
|
// Find the weight for this synapse
|
||||||
|
if (synapse.neuron == sender) {
|
||||||
|
weight = synapse.weight;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (clusterInstance.GetNucleus(sender.name) is not Neuron clonedSender)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
clonedSender.AddReceiver(clonedReceiver, weight);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
foreach (Nucleus nucleus in this.clusterNuclei) {
|
foreach (Nucleus nucleus in this.clusterNuclei) {
|
||||||
if (nucleus is Cluster clonedSubCluster)
|
if (nucleus is Cluster clonedSubCluster)
|
||||||
@ -477,14 +528,8 @@ namespace NanoBrain {
|
|||||||
|
|
||||||
#endregion ClusterArray
|
#endregion ClusterArray
|
||||||
|
|
||||||
public ClusterPrefab prefab;
|
|
||||||
|
|
||||||
|
|
||||||
[SerializeReference]
|
|
||||||
public List<Nucleus> clusterNuclei = new();
|
|
||||||
// the nuclei sorted using topological sorting
|
|
||||||
// to ensure that the cluster is computer in the right order
|
|
||||||
public List<Nucleus> sortedNuclei;
|
|
||||||
//public Dictionary<string, Nucleus> nucleiDict = new();
|
//public Dictionary<string, Nucleus> nucleiDict = new();
|
||||||
|
|
||||||
public List<Nucleus> _inputs = null;
|
public List<Nucleus> _inputs = null;
|
||||||
|
|||||||
@ -59,6 +59,8 @@ public abstract class Nucleus {
|
|||||||
//ClusterArray,
|
//ClusterArray,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public virtual void Initialize() {}
|
||||||
|
|
||||||
#region Synapses
|
#region Synapses
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user