Add topological evaluation order
This commit is contained in:
parent
9ae3607911
commit
b4f8e5a4d8
88
Cluster.cs
88
Cluster.cs
@ -15,41 +15,45 @@ public class Cluster : INucleus {
|
||||
set => _name = value;
|
||||
}
|
||||
|
||||
public ClusterPrefab storedPrefab;
|
||||
#region Init
|
||||
|
||||
public Cluster(ClusterPrefab prefab, Cluster parent) {
|
||||
this.prefab = prefab;
|
||||
this.name = prefab.name;
|
||||
|
||||
public Cluster(Cluster parent, ClusterPrefab realPrefab) {
|
||||
this.storedPrefab = realPrefab;
|
||||
this.parent = parent;
|
||||
this.parent?.nuclei.Add(this);
|
||||
|
||||
ClonePrefab();
|
||||
this.sortedNuclei = TopologicalSort(this.nuclei);
|
||||
}
|
||||
|
||||
public Cluster(ClusterPrefab realPrefab) {
|
||||
this.storedPrefab = realPrefab;
|
||||
this.name = realPrefab.name;
|
||||
this.cluster = null;
|
||||
if (this.cluster != null)
|
||||
this.cluster.nuclei.Add(this);
|
||||
|
||||
ClonePrefab();
|
||||
}
|
||||
|
||||
public Cluster(ClusterPrefab parent, ClusterPrefab realPrefab) {
|
||||
this.storedPrefab = realPrefab;
|
||||
//this.prefab = realPrefab.Clone();
|
||||
this.name = realPrefab.name;
|
||||
public Cluster(ClusterPrefab prefab, ClusterPrefab parent = null) {
|
||||
this.prefab = prefab;
|
||||
this.name = prefab.name;
|
||||
this.cluster = parent;
|
||||
|
||||
if (this.cluster != null)
|
||||
this.cluster.nuclei.Add(this);
|
||||
|
||||
ClonePrefab();
|
||||
this.sortedNuclei = TopologicalSort(this.nuclei);
|
||||
}
|
||||
|
||||
// public Cluster(ClusterPrefab parent, ClusterPrefab realPrefab) {
|
||||
// this.prefab = realPrefab;
|
||||
// this.name = realPrefab.name;
|
||||
// this.cluster = parent;
|
||||
// if (this.cluster != null)
|
||||
// this.cluster.nuclei.Add(this);
|
||||
|
||||
// ClonePrefab();
|
||||
// }
|
||||
|
||||
private void ClonePrefab() {
|
||||
IReceptor[] nucleiArray = this.storedPrefab.nuclei.ToArray();
|
||||
IReceptor[] nucleiArray = this.prefab.nuclei.ToArray();
|
||||
// first clone the nuclei without their connections
|
||||
foreach (IReceptor nucleus in this.storedPrefab.nuclei)
|
||||
foreach (IReceptor nucleus in this.prefab.nuclei)
|
||||
nucleus.ShallowCloneTo(this);
|
||||
IReceptor[] clonedNuclei = this.nuclei.ToArray();
|
||||
|
||||
@ -83,6 +87,43 @@ public class Cluster : INucleus {
|
||||
}
|
||||
}
|
||||
|
||||
// Sort the nuclei in a correct evaluation order
|
||||
private List<IReceptor> TopologicalSort(List<IReceptor> nodes) {
|
||||
Dictionary<IReceptor, int> inDegree = new();
|
||||
foreach (IReceptor node in nodes)
|
||||
inDegree[node] = 0; // Initialize in-degree to zero
|
||||
|
||||
// Calculate in-degrees
|
||||
foreach (IReceptor node in nodes) {
|
||||
foreach (INucleus receiver in node.receivers)
|
||||
inDegree[receiver]++;
|
||||
}
|
||||
|
||||
Queue<IReceptor> queue = new();
|
||||
foreach (IReceptor node in nodes) {
|
||||
if (inDegree[node] == 0) // Nodes with no dependencies
|
||||
queue.Enqueue(node);
|
||||
}
|
||||
|
||||
List<IReceptor> sortedOrder = new();
|
||||
while (queue.Count > 0) {
|
||||
IReceptor current = queue.Dequeue();
|
||||
sortedOrder.Add(current); // Process the node
|
||||
|
||||
foreach (INucleus receiver in current.receivers) {
|
||||
inDegree[receiver]--;
|
||||
if (inDegree[receiver] == 0) // If all dependencies resolved
|
||||
queue.Enqueue(receiver);
|
||||
}
|
||||
}
|
||||
|
||||
// Check for cycles in the graph
|
||||
if (sortedOrder.Count != nodes.Count)
|
||||
throw new InvalidOperationException("Graph is not a DAG; a cycle exists.");
|
||||
|
||||
return sortedOrder;
|
||||
}
|
||||
|
||||
public virtual IReceptor Clone() {
|
||||
Neuron clone = new(this.cluster, this.name) {
|
||||
array = this.array,
|
||||
@ -99,7 +140,7 @@ public class Cluster : INucleus {
|
||||
}
|
||||
|
||||
public IReceptor ShallowCloneTo(Cluster parent) {
|
||||
Cluster clone = new(parent, this.storedPrefab) {
|
||||
Cluster clone = new(this.prefab, parent) {
|
||||
name = this.name,
|
||||
};
|
||||
return clone;
|
||||
@ -113,11 +154,18 @@ public class Cluster : INucleus {
|
||||
return -1;
|
||||
}
|
||||
|
||||
#endregion Init
|
||||
|
||||
public ClusterPrefab prefab;
|
||||
|
||||
public ClusterPrefab cluster { get; set; }
|
||||
public Cluster parent { get; set; }
|
||||
|
||||
[SerializeReference]
|
||||
public List<IReceptor> nuclei = new();
|
||||
// the nuclei sorted using topological sorting
|
||||
// to ensure that the cluster is computer in the right order
|
||||
public List<IReceptor> sortedNuclei;
|
||||
|
||||
public List<INucleus> _inputs = null;
|
||||
public virtual List<INucleus> inputs {
|
||||
|
||||
@ -29,10 +29,6 @@ public class MemoryCell : Neuron {
|
||||
|
||||
//Applying the weight factgors
|
||||
foreach (Synapse synapse in this.synapses) {
|
||||
if (synapse.nucleus == this) {
|
||||
float deltaTime = Time.time - this.lastTime;
|
||||
synapse.weight = deltaTime;
|
||||
}
|
||||
result += synapse.weight * synapse.nucleus.outputValue;
|
||||
if (lengthsq(synapse.nucleus.outputValue) != 0)
|
||||
n++;
|
||||
|
||||
@ -154,7 +154,6 @@ public class Neuron : INucleus {
|
||||
// private bool _isSleeping = false;
|
||||
// public bool isSleeping => _isSleeping;
|
||||
public bool isSleeping => lengthsq(this.outputValue) == 0;
|
||||
public float lastTime { get; private set; }
|
||||
|
||||
public void UpdateNuclei() {
|
||||
this.stale++;
|
||||
@ -292,10 +291,6 @@ public class Neuron : INucleus {
|
||||
|
||||
//Applying the weight factgors
|
||||
foreach (Synapse synapse in this.synapses) {
|
||||
if (synapse.nucleus == this) {
|
||||
float deltaTime = Time.time - this.lastTime;
|
||||
synapse.weight = deltaTime;
|
||||
}
|
||||
sum += synapse.weight * synapse.nucleus.outputValue;
|
||||
|
||||
// Perhaps synapses should be removed when the output value goes to 0....
|
||||
@ -340,7 +335,6 @@ public class Neuron : INucleus {
|
||||
Debug.Log($"{this.parent.name}.{this.name}: {this.outputValue}");
|
||||
}
|
||||
|
||||
this.lastTime = Time.time;
|
||||
foreach (INucleus receiver in this.receivers)
|
||||
receiver.UpdateState();
|
||||
|
||||
|
||||
@ -621,7 +621,7 @@ public class ClusterInspector : Editor {
|
||||
}
|
||||
|
||||
private void OnClusterPicked(INucleus nucleus, ClusterPrefab prefab) {
|
||||
Cluster subclusterInstance = new(this.cluster, prefab);
|
||||
Cluster subclusterInstance = new(prefab, this.cluster);
|
||||
subclusterInstance.AddReceiver(nucleus);
|
||||
// This does not work somehow
|
||||
// this.currentNucleus = subclusterInstance;
|
||||
@ -630,9 +630,9 @@ public class ClusterInspector : Editor {
|
||||
|
||||
private void EditCluster(Cluster subCluster) {
|
||||
// May be used with storedPrefab...
|
||||
Selection.activeObject = subCluster.storedPrefab;
|
||||
EditorGUIUtility.PingObject(subCluster.storedPrefab);
|
||||
var editor = Editor.CreateEditor(subCluster.storedPrefab);
|
||||
Selection.activeObject = subCluster.prefab;
|
||||
EditorGUIUtility.PingObject(subCluster.prefab);
|
||||
var editor = Editor.CreateEditor(subCluster.prefab);
|
||||
}
|
||||
|
||||
// Connect to another nucleus in the same cluster
|
||||
|
||||
@ -79,7 +79,7 @@ public class NanoBrainComponent_Editor : Editor {
|
||||
});
|
||||
|
||||
if (brain != null && board != null)
|
||||
board.SetGraph(component.gameObject, brain.storedPrefab, brain.output, inspectorContainer);
|
||||
board.SetGraph(component.gameObject, brain.prefab, brain.output, inspectorContainer);
|
||||
// else
|
||||
// Debug.LogWarning(" No brain!");
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user