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