multi-cluster calculation fix
This commit is contained in:
parent
af0ba68bd8
commit
7ef8e42e09
@ -70,7 +70,7 @@ namespace NanoBrain {
|
||||
get => base.currentNucleus;
|
||||
set {
|
||||
base.currentNucleus = value;
|
||||
this.currentPrefabNucleus = this.prefab.GetNucleus(value.name);
|
||||
this.currentPrefabNucleus = value != null ? this.prefab.GetNucleus(value.name) : null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -402,7 +402,7 @@ namespace NanoBrain {
|
||||
|
||||
// Count multiple synapses to the same neuron only once
|
||||
string neuronName = synapse.neuron.name;
|
||||
if (synapse.neuron.parent != null)
|
||||
if (synapse.neuron.parent != null)
|
||||
neuronName = synapse.neuron.parent.baseName + "." + neuronName;
|
||||
|
||||
if (drawnNeuronNames.Contains(neuronName))
|
||||
@ -429,7 +429,7 @@ namespace NanoBrain {
|
||||
|
||||
// Draw multiple synapses to the same neuron only once
|
||||
string neuronName = synapse.neuron.name;
|
||||
if (synapse.neuron.parent != null)
|
||||
if (synapse.neuron.parent != null)
|
||||
neuronName = synapse.neuron.parent.baseName + "." + neuronName;
|
||||
|
||||
if (drawnNeuronNames.Contains(neuronName))
|
||||
@ -459,17 +459,30 @@ namespace NanoBrain {
|
||||
// Hack to disable showing labels
|
||||
expandArray = true;
|
||||
|
||||
float maxValue = 0;
|
||||
foreach (Cluster sibling in nucleus.parent.siblingClusters) {
|
||||
Neuron siblingNeuron = sibling.GetNucleus(nucleus.name) as Neuron;
|
||||
float value = siblingNeuron.outputMagnitude; // no need to add weight as they are all the same
|
||||
if (value > maxValue)
|
||||
maxValue = value;
|
||||
}
|
||||
|
||||
// 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);
|
||||
Neuron siblingNeuron = sibling.GetNucleus(nucleus.name) as Neuron;
|
||||
Vector3 position = new(250, margin + row * spacing, 0.0f);
|
||||
DrawEdge(parentPos, position);
|
||||
Color color = Color.black;
|
||||
DrawNucleus(siblingNucleus, position, size, color);
|
||||
if (Application.isPlaying) {
|
||||
if (maxValue == 0 || !float.IsFinite(maxValue))
|
||||
maxValue = 1;
|
||||
float brightness = siblingNeuron.outputMagnitude / maxValue;
|
||||
color = new Color(brightness, brightness, brightness, 1f);
|
||||
} DrawNucleus(siblingNeuron, position, size, color);
|
||||
GUIStyle style = new(EditorStyles.label) {
|
||||
alignment = TextAnchor.UpperCenter,
|
||||
normal = { textColor = Color.white },
|
||||
@ -784,8 +797,8 @@ namespace NanoBrain {
|
||||
// expandArray = false;
|
||||
// }
|
||||
// else {
|
||||
if (nucleus is Cluster cluster)
|
||||
OnClusterClick(cluster);
|
||||
if (nucleus is Cluster cluster)
|
||||
OnClusterClick(cluster);
|
||||
// }
|
||||
}
|
||||
else if (nucleus.parent != null && this.currentNucleus != null && nucleus.parent != this.currentNucleus.parent) {
|
||||
|
||||
@ -414,7 +414,7 @@ namespace NanoBrain {
|
||||
return clone;
|
||||
}
|
||||
|
||||
private static void CopyAllExternalReceivers(Cluster sourceCluster, Cluster sibling, 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];
|
||||
@ -444,7 +444,7 @@ namespace NanoBrain {
|
||||
Debug.Log($"external: {receiver.name} receives from {clonedNeuron.name} {clonedNeuron.GetHashCode()}");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
protected int GetNucleusIndex(Nucleus[] nuclei, Nucleus nucleus) {
|
||||
@ -539,6 +539,7 @@ namespace NanoBrain {
|
||||
return cluster;
|
||||
|
||||
Cluster selectedCluster = SelectCluster();
|
||||
selectedCluster.name = baseName + ": " + thingName;
|
||||
thingClusters[thingId] = selectedCluster;
|
||||
return selectedCluster;
|
||||
}
|
||||
@ -615,22 +616,33 @@ namespace NanoBrain {
|
||||
|
||||
public Dictionary<Nucleus, List<Nucleus>> computeOrders = new();
|
||||
private void ComputeOrders() {
|
||||
foreach (Nucleus input in this._inputs)
|
||||
computeOrders[input] = TopologicalSort2(input);
|
||||
foreach (Nucleus nucleus in this.clusterNuclei) {
|
||||
// if (nucleus is Cluster cluster) {
|
||||
// List<Synapse> synapses = this.CollectSynapsesTo(cluster);
|
||||
// foreach (Synapse synapse in synapses) {
|
||||
// computeOrders[synapse.neuron] = TopologicalSort2(synapse.neuron);
|
||||
// Debug.Log($"{this.baseName}: Order for {cluster.baseName}.{synapse.neuron.name}");
|
||||
// }
|
||||
// // List<Nucleus> receivers = cluster.CollectReceivers();
|
||||
// // foreach (Nucleus receiver in receivers)
|
||||
// // computeOrders[receiver] = TopologicalSort2(receiver);
|
||||
// }
|
||||
// else {
|
||||
computeOrders[nucleus] = TopologicalSort2(nucleus);
|
||||
Debug.Log($"{this.baseName} Order for {nucleus.name}");
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
private List<Nucleus> TopologicalSort2(Nucleus startNode) {
|
||||
Dictionary<Nucleus, int> inDegree = new();
|
||||
HashSet<Nucleus> visited = new();
|
||||
|
||||
// Initialize in-degrees and mark all nodes as unvisited
|
||||
foreach (Nucleus node in this.clusterNuclei)
|
||||
inDegree[node] = 0;
|
||||
//HashSet<Nucleus> visited = new();
|
||||
|
||||
// Calculate in-degrees for all nodes reachable from the start node
|
||||
Queue<Nucleus> queue = new Queue<Nucleus>();
|
||||
Queue<Nucleus> queue = new();
|
||||
queue.Enqueue(startNode);
|
||||
visited.Add(startNode);
|
||||
//visited.Add(startNode);
|
||||
inDegree[startNode] = 0;
|
||||
|
||||
while (queue.Count > 0) {
|
||||
Nucleus current = queue.Dequeue();
|
||||
@ -640,25 +652,24 @@ namespace NanoBrain {
|
||||
else if (current is Cluster cluster)
|
||||
receivers = cluster.CollectReceivers();
|
||||
|
||||
// if (current is Neuron neuron) {
|
||||
foreach (Nucleus receiver in receivers) {
|
||||
if (!visited.Contains(receiver)) {
|
||||
visited.Add(receiver);
|
||||
if (!inDegree.ContainsKey(receiver)) {
|
||||
//visited.Add(receiver);
|
||||
inDegree[receiver] = 0;
|
||||
queue.Enqueue(receiver);
|
||||
}
|
||||
inDegree[receiver]++;
|
||||
}
|
||||
// }
|
||||
}
|
||||
|
||||
// Perform topological sort on all reachable nodes
|
||||
queue.Clear();
|
||||
foreach (Nucleus node in visited) {
|
||||
foreach (Nucleus node in inDegree.Keys) {
|
||||
if (inDegree[node] == 0)
|
||||
queue.Enqueue(node);
|
||||
}
|
||||
|
||||
List<Nucleus> sortedOrder = new List<Nucleus>();
|
||||
List<Nucleus> sortedOrder = new();
|
||||
while (queue.Count > 0) {
|
||||
Nucleus current = queue.Dequeue();
|
||||
sortedOrder.Add(current); // Process the node
|
||||
@ -669,21 +680,18 @@ namespace NanoBrain {
|
||||
else if (current is Cluster cluster)
|
||||
receivers = cluster.CollectReceivers();
|
||||
|
||||
//if (current is Neuron neuron) {
|
||||
|
||||
foreach (Nucleus receiver in receivers) {
|
||||
if (visited.Contains(receiver)) {
|
||||
if (inDegree.ContainsKey(receiver)) {
|
||||
inDegree[receiver]--;
|
||||
if (inDegree[receiver] == 0) // If all dependencies resolved
|
||||
queue.Enqueue(receiver);
|
||||
}
|
||||
}
|
||||
//}
|
||||
}
|
||||
|
||||
// Check for cycles in the graph
|
||||
if (sortedOrder.Count != visited.Count)
|
||||
throw new InvalidOperationException("Graph is not a DAG; a cycle exists.");
|
||||
// if (sortedOrder.Count != visited.Count)
|
||||
// throw new InvalidOperationException("Graph is not a DAG; a cycle exists.");
|
||||
|
||||
return sortedOrder;
|
||||
}
|
||||
@ -782,7 +790,7 @@ namespace NanoBrain {
|
||||
// Debug.Log($"output {receiver.name}");
|
||||
// Only add receivers outside this cluster
|
||||
if (receiver.clusterPrefab != this.prefab) {
|
||||
if (removeDuplicates && receivers.Contains(receiver) == false)
|
||||
if (removeDuplicates == false || receivers.Contains(receiver) == false)
|
||||
// Debug.Log($" YES");
|
||||
receivers.Add(receiver);
|
||||
}
|
||||
@ -806,6 +814,19 @@ namespace NanoBrain {
|
||||
}
|
||||
return connections;
|
||||
}
|
||||
public List<Synapse> CollectSynapsesTo(Cluster otherCluster) {
|
||||
List<Synapse> collectedSynapses = new();
|
||||
|
||||
foreach (Nucleus nucleus in this.clusterNuclei) {
|
||||
if (nucleus is not Neuron neuron)
|
||||
continue;
|
||||
foreach (Synapse synapse in nucleus.synapses) {
|
||||
if (synapse.neuron.parent == otherCluster)
|
||||
collectedSynapses.Add(synapse);
|
||||
}
|
||||
}
|
||||
return collectedSynapses;
|
||||
}
|
||||
|
||||
public void MoveReceivers(Cluster newCluster) {
|
||||
Debug.Log($"Move receivers for {this.name} to {newCluster.name}");
|
||||
@ -841,23 +862,31 @@ namespace NanoBrain {
|
||||
// no bias+synapse input state calculation for now...
|
||||
|
||||
if (this.computeOrders.ContainsKey(startNucleus) == false) {
|
||||
//Debug.LogError($"{this.name} compute orders does not contain an order for {startNucleus.name}");
|
||||
Debug.LogError($"{this.name} compute orders does not contain an order for {startNucleus.name}");
|
||||
return;
|
||||
}
|
||||
|
||||
List<Nucleus> computeOrder = this.computeOrders[startNucleus];
|
||||
if (startNucleus.trace)
|
||||
Debug.Log($"Update from {startNucleus.name}");
|
||||
//if (startNucleus.trace)
|
||||
Debug.Log($"Update from {startNucleus.name}");
|
||||
foreach (Nucleus nucleus in computeOrder) {
|
||||
if (nucleus is not Cluster) {
|
||||
nucleus.UpdateStateIsolated();
|
||||
if (startNucleus.trace && nucleus is Neuron neuron)
|
||||
Debug.Log($" {nucleus.name}[{nucleus.GetHashCode()}]"); // = {neuron.outputValue}");
|
||||
//if (startNucleus.trace && nucleus is Neuron neuron)
|
||||
Debug.Log($" {nucleus.name}");
|
||||
if (nucleus is Neuron neuron) {
|
||||
foreach (Nucleus receiver in neuron.receivers) {
|
||||
if (receiver.parent != this) {
|
||||
Debug.Log($" External: {receiver.parent.name}.{receiver.name}");
|
||||
receiver.parent.UpdateFromNucleus(receiver);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// continue in parent
|
||||
this.parent?.UpdateFromNucleus(this);
|
||||
//this.parent?.UpdateFromNucleus(this);
|
||||
|
||||
UpdateNuclei();
|
||||
}
|
||||
|
||||
@ -29,11 +29,7 @@ namespace NanoBrain {
|
||||
this.weight = weight;
|
||||
}
|
||||
|
||||
public bool isSleeping {
|
||||
get {
|
||||
return this.neuron.isSleeping;
|
||||
}
|
||||
}
|
||||
public bool isSleeping => this.neuron.isSleeping;
|
||||
}
|
||||
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user