Viewer for multi-clusters
This commit is contained in:
parent
04010903f5
commit
af0ba68bd8
@ -22,6 +22,8 @@ namespace NanoBrain {
|
||||
}
|
||||
//protected Nucleus currentNucleus;
|
||||
protected Nucleus selectedOutput;
|
||||
// Only used when selecting a synapse to a multi-cluster
|
||||
protected Nucleus selectedSynapseNeuron;
|
||||
|
||||
protected GameObject gameObject;
|
||||
private bool expandArray = false;
|
||||
@ -382,6 +384,10 @@ namespace NanoBrain {
|
||||
}
|
||||
|
||||
protected void DrawSynapses(Nucleus nucleus, Vector3 parentPos, float size) {
|
||||
if (this.selectedSynapseNeuron != null) {
|
||||
DrawClusterSynapses(this.selectedSynapseNeuron, parentPos, size);
|
||||
return;
|
||||
}
|
||||
if (nucleus == null)
|
||||
return;
|
||||
|
||||
@ -389,15 +395,19 @@ namespace NanoBrain {
|
||||
// This is used to 'scale' the output value colors of the nuclei
|
||||
float maxValue = 0;
|
||||
int neuronCount = 0;
|
||||
List<Neuron> drawnNeurons = new();
|
||||
List<string> drawnNeuronNames = new();
|
||||
foreach (Synapse synapse in nucleus.synapses) {
|
||||
if (synapse.neuron == null)
|
||||
continue;
|
||||
|
||||
// Count multiple synapses to the same neuron only once
|
||||
if (drawnNeurons.Contains(synapse.neuron))
|
||||
string neuronName = synapse.neuron.name;
|
||||
if (synapse.neuron.parent != null)
|
||||
neuronName = synapse.neuron.parent.baseName + "." + neuronName;
|
||||
|
||||
if (drawnNeuronNames.Contains(neuronName))
|
||||
continue;
|
||||
drawnNeurons.Add(synapse.neuron);
|
||||
drawnNeuronNames.Add(neuronName);
|
||||
|
||||
float value = synapse.neuron.outputMagnitude * synapse.weight;
|
||||
if (value > maxValue)
|
||||
@ -411,15 +421,20 @@ namespace NanoBrain {
|
||||
float margin = 10 + spacing / 2;
|
||||
|
||||
int row = 0;
|
||||
drawnNeurons = new();
|
||||
//List<Neuron> drawnNeurons = new();
|
||||
drawnNeuronNames = new();
|
||||
foreach (Synapse synapse in nucleus.synapses) {
|
||||
if (synapse.neuron is null)
|
||||
continue;
|
||||
|
||||
// Draw multiple synapses to the same neuron only once
|
||||
if (drawnNeurons.Contains(synapse.neuron))
|
||||
string neuronName = synapse.neuron.name;
|
||||
if (synapse.neuron.parent != null)
|
||||
neuronName = synapse.neuron.parent.baseName + "." + neuronName;
|
||||
|
||||
if (drawnNeuronNames.Contains(neuronName))
|
||||
continue;
|
||||
drawnNeurons.Add(synapse.neuron);
|
||||
drawnNeuronNames.Add(neuronName);
|
||||
|
||||
Vector3 pos = new(250, margin + row * spacing, 0.0f);
|
||||
DrawEdge(parentPos, pos);
|
||||
@ -437,6 +452,37 @@ namespace NanoBrain {
|
||||
}
|
||||
}
|
||||
|
||||
protected void DrawClusterSynapses(Nucleus nucleus, Vector3 parentPos, float size) {
|
||||
if (nucleus == null || nucleus.parent == null || nucleus.parent.siblingClusters == null)
|
||||
return;
|
||||
|
||||
// Hack to disable showing labels
|
||||
expandArray = true;
|
||||
|
||||
// Determine the spacing of the nuclei in the layer
|
||||
float spacing = 400f / nucleus.parent.instanceCount;
|
||||
float margin = 10 + spacing / 2;
|
||||
|
||||
int row = 0;
|
||||
foreach (Cluster sibling in nucleus.parent.siblingClusters) {
|
||||
Nucleus siblingNucleus = sibling.GetNucleus(nucleus.name);
|
||||
Vector3 position = new(250, margin + row * spacing, 0.0f);
|
||||
DrawEdge(parentPos, position);
|
||||
Color color = Color.black;
|
||||
DrawNucleus(siblingNucleus, position, size, color);
|
||||
GUIStyle style = new(EditorStyles.label) {
|
||||
alignment = TextAnchor.UpperCenter,
|
||||
normal = { textColor = Color.white },
|
||||
fontStyle = FontStyle.Bold,
|
||||
};
|
||||
Vector3 labelPos = position - Vector3.down * (size + 5); // below neuron
|
||||
string name = $"{sibling.baseName}.{nucleus.name}";
|
||||
Handles.Label(labelPos, name, style);
|
||||
row++;
|
||||
}
|
||||
expandArray = false;
|
||||
}
|
||||
|
||||
protected void DrawOutputs(Vector2 parentPos, float size) {
|
||||
// Determine the maximum value in this layer
|
||||
// This is used to 'scale' the output value colors of the nuclei
|
||||
@ -536,7 +582,7 @@ namespace NanoBrain {
|
||||
else if (nucleus is Cluster cluster)
|
||||
DrawCluster(cluster, position, color, size);
|
||||
|
||||
if (expandArray == false || nucleus != currentNucleus) {
|
||||
if (expandArray == false) {// || nucleus != currentNucleus) {
|
||||
// put name below nucleus
|
||||
Vector3 labelPos = position - Vector3.down * (size + 5); // below neuron
|
||||
style.alignment = TextAnchor.UpperCenter;
|
||||
@ -730,24 +776,33 @@ namespace NanoBrain {
|
||||
|
||||
protected void OnNeuronClick(Nucleus nucleus) {
|
||||
if (nucleus == this.currentNucleus) {
|
||||
if (Application.isPlaying) {
|
||||
if (nucleus is Cluster)
|
||||
expandArray = !expandArray;
|
||||
else
|
||||
expandArray = false;
|
||||
}
|
||||
else {
|
||||
this.selectedSynapseNeuron = null;
|
||||
// if (Application.isPlaying) {
|
||||
// if (nucleus is Cluster)
|
||||
// expandArray = !expandArray;
|
||||
// else
|
||||
// expandArray = false;
|
||||
// }
|
||||
// else {
|
||||
if (nucleus is Cluster cluster)
|
||||
OnClusterClick(cluster);
|
||||
}
|
||||
// }
|
||||
}
|
||||
else if (nucleus.parent != null && this.currentNucleus != null && nucleus.parent != this.currentNucleus.parent) {
|
||||
// We go to a different cluster
|
||||
if (Application.isPlaying) {
|
||||
this.currentNucleus = nucleus;
|
||||
if (this.currentNucleus is Neuron neuron && neuron.receivers.Count == 0)
|
||||
this.selectedOutput = this.currentNucleus;
|
||||
expandArray = false;
|
||||
if (this.selectedSynapseNeuron == null && nucleus.parent.instanceCount > 1) {
|
||||
this.selectedSynapseNeuron = nucleus;
|
||||
expandArray = false;
|
||||
}
|
||||
else {
|
||||
this.currentNucleus = nucleus;
|
||||
if (this.currentNucleus is Neuron neuron && neuron.receivers.Count == 0)
|
||||
this.selectedOutput = this.currentNucleus;
|
||||
this.selectedSynapseNeuron = null;
|
||||
expandArray = false;
|
||||
}
|
||||
|
||||
}
|
||||
else {
|
||||
// select the cluster, not the neuron in the cluster
|
||||
|
||||
@ -171,20 +171,23 @@ namespace NanoBrain {
|
||||
if (clonedNucleus is not Cluster clonedCluster)
|
||||
continue;
|
||||
|
||||
// if (clonedCluster.instanceCount <= 1)
|
||||
// continue;
|
||||
|
||||
List<Cluster> siblings = new() {
|
||||
clonedCluster
|
||||
};
|
||||
for (int instanceIx = 1; instanceIx < clonedCluster.instanceCount; instanceIx++) {
|
||||
//ClusterPrefab prefabCluster = clonedCluster.prefab;
|
||||
// Create another sibling
|
||||
Debug.Log($"create {clonedCluster.prefab.name} sibling");
|
||||
Cluster sibling = new(clonedCluster.prefab, this) {
|
||||
name = this.name,
|
||||
name = $"{clonedCluster.baseName}: {instanceIx}",
|
||||
clusterPrefab = this.clusterPrefab,
|
||||
instanceCount = this.instanceCount,
|
||||
};
|
||||
RestoreAllExternalReceivers(clonedCluster, clonedCluster.prefab, this);
|
||||
siblings.Add(sibling);
|
||||
CopyAllExternalReceivers(clonedCluster, sibling, clonedCluster.prefab, this);
|
||||
}
|
||||
Cluster[] siblingClusters = siblings.ToArray();
|
||||
foreach (Cluster sibling in siblings)
|
||||
sibling.siblingClusters = siblingClusters;
|
||||
}
|
||||
}
|
||||
/*
|
||||
@ -411,45 +414,37 @@ namespace NanoBrain {
|
||||
return clone;
|
||||
}
|
||||
|
||||
private static void RestoreAllExternalReceivers(Cluster clonedCluster, ClusterPrefab prefabParent, Cluster clonedParent) {
|
||||
private static void CopyAllExternalReceivers(Cluster sourceCluster, Cluster sibling, ClusterPrefab prefabParent, Cluster clonedParent) {
|
||||
|
||||
for (int nucleusIx = 0; nucleusIx < sourceCluster.clusterNuclei.Count; nucleusIx++) {
|
||||
Nucleus sourceNucleus = sourceCluster.clusterNuclei[nucleusIx];
|
||||
if (sourceNucleus is not Neuron sourceNeuron)
|
||||
continue;
|
||||
|
||||
// int clonedClusterIx = GetNucleusIndex(clonedParent.clusterNuclei, clonedCluster);
|
||||
// if (prefabParent.nuclei[clonedClusterIx] is not Cluster sourceCluster)
|
||||
// return;
|
||||
if (sibling.clusterNuclei[nucleusIx] is not Neuron clonedNeuron)
|
||||
continue;
|
||||
|
||||
// for (int nucleusIx = 0; nucleusIx < sourceCluster.clusterNuclei.Count; nucleusIx++) {
|
||||
// Nucleus sourceNucleus = sourceCluster.clusterNuclei[nucleusIx];
|
||||
// if (sourceNucleus is not Neuron sourceNeuron)
|
||||
// continue;
|
||||
// copy the receivers (and thus synapses) from the source to the sibling
|
||||
foreach (Nucleus receiver in sourceNeuron.receivers) {
|
||||
int ix = GetNucleusIndex(clonedParent.clusterNuclei, receiver);
|
||||
if (ix < 0 || ix >= clonedParent.clusterNuclei.Count)
|
||||
continue;
|
||||
|
||||
// if (clonedCluster.clusterNuclei[nucleusIx] is not Neuron clonedNeuron)
|
||||
// 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 == sourceNucleus) {
|
||||
weight = synapse.weight;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// // copy the receivers (and thus synapses) from the source to the clone
|
||||
// foreach (Nucleus receiver in sourceNeuron.receivers) {
|
||||
// int ix = GetNucleusIndex(prefabParent.nuclei, receiver);
|
||||
// if (ix < 0 || ix >= clonedParent.clusterNuclei.Count)
|
||||
// continue;
|
||||
|
||||
// Nucleus clonedReceiver = clonedParent.clusterNuclei[ix];
|
||||
|
||||
// // Find the synapse for the weight
|
||||
// float weight = 1;
|
||||
// foreach (Synapse synapse in receiver.synapses) {
|
||||
// // Find the weight for this synapse
|
||||
// if (synapse.neuron == sourceNucleus) {
|
||||
// weight = synapse.weight;
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
|
||||
// clonedNeuron.AddReceiver(clonedReceiver, weight);
|
||||
// Debug.Log($"external: {clonedReceiver.name} receives from {clonedNeuron.name} {clonedNeuron.GetHashCode()}");
|
||||
// }
|
||||
// }
|
||||
|
||||
|
||||
clonedNeuron.AddReceiver(receiver, weight);
|
||||
Debug.Log($"external: {receiver.name} receives from {clonedNeuron.name} {clonedNeuron.GetHashCode()}");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
protected int GetNucleusIndex(Nucleus[] nuclei, Nucleus nucleus) {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user