Initial population persistence
This commit is contained in:
parent
68b43ee476
commit
5553f8994f
@ -81,6 +81,8 @@ namespace NanoBrain {
|
||||
[HideInInspector]
|
||||
public List<Nucleus> nuclei = new();
|
||||
|
||||
#region Timed Actions
|
||||
|
||||
public class TimedAction {
|
||||
public TimedAction(string neuronName, Action action, long timestamp) {
|
||||
this.neuronName = neuronName;
|
||||
@ -146,6 +148,8 @@ namespace NanoBrain {
|
||||
}
|
||||
}
|
||||
|
||||
#endregion Timed Actions
|
||||
|
||||
#region Init
|
||||
|
||||
public Cluster() {
|
||||
@ -368,6 +372,90 @@ namespace NanoBrain {
|
||||
}
|
||||
}
|
||||
|
||||
public Cluster Clone() {
|
||||
Cluster clone = new() {
|
||||
name = this.name,
|
||||
prefab = this.prefab,
|
||||
version = this.version,
|
||||
parent = this.parent
|
||||
};
|
||||
if (clone.parent != null) {
|
||||
// Do we need to clone the parent here too????
|
||||
}
|
||||
|
||||
// first clone the nuclei without their connections
|
||||
foreach (Nucleus nucleus in this.nuclei)
|
||||
nucleus.ShallowCloneTo(clone);
|
||||
|
||||
Nucleus[] clonedNuclei = clone.nuclei.ToArray();
|
||||
// Now clone the connections
|
||||
for (int nucleusIx = 0; nucleusIx < this.nuclei.Count; nucleusIx++) {
|
||||
Nucleus sourceNucleus = this.nuclei[nucleusIx];
|
||||
if (sourceNucleus is not Neuron sourceNeuron)
|
||||
continue;
|
||||
|
||||
Nucleus clonedNucleus = clonedNuclei[nucleusIx];
|
||||
if (clonedNucleus == null || clonedNucleus is not Neuron clonedNeuron)
|
||||
continue;
|
||||
|
||||
foreach (Synapse sourceSynapse in sourceNeuron.synapses) {
|
||||
Neuron synapseNeuron = sourceSynapse.neuron;
|
||||
if (synapseNeuron.parent.prefab != null && synapseNeuron.parent.prefab != clone.prefab) {
|
||||
// Neuron is in another cluster, find the cloned cluster first
|
||||
Cluster sourceCluster = synapseNeuron.parent;
|
||||
Cluster clonedCluster = clone.nuclei.Find(n => n.name == sourceCluster.name) as Cluster;
|
||||
if (clonedCluster == null)
|
||||
continue;
|
||||
|
||||
// Now find the neuron in that cloned cluster
|
||||
int neuronIx = GetNucleusIndex(sourceCluster.nuclei, sourceSynapse.neuron.name);
|
||||
if (neuronIx < 0)
|
||||
// Could not find the neuron in the prefab cluster
|
||||
continue;
|
||||
if (clonedCluster.nuclei[neuronIx] is not Neuron clonedSender)
|
||||
// Could not find the neuron in the cloned cluster
|
||||
continue;
|
||||
|
||||
clonedSender.AddReceiver(clonedNeuron, sourceSynapse.weight, sourceSynapse.trainable);
|
||||
//Debug.Log($"Add synapse {clonedCluster.name}.{clonedSender.name} -> {clonedNeuron.name} [{clonedSender.receivers.Count}]");
|
||||
}
|
||||
else {
|
||||
int ix = GetNucleusIndex(clone.prefab.cluster.nuclei, sourceSynapse.neuron);
|
||||
if (ix < 0)
|
||||
continue;
|
||||
if (clonedNuclei[ix] is not Neuron clonedSender)
|
||||
continue;
|
||||
|
||||
// Copy the receivers which will also create the synapse
|
||||
clonedSender.AddReceiver(clonedNeuron, sourceSynapse.weight, sourceSynapse.trainable);
|
||||
// Debug.Log($"Add synapse {clonedSender.name} -> {clonedNeuron.name}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach (Nucleus clonedNucleus in clonedNuclei) {
|
||||
if (clonedNucleus is not Cluster clonedCluster)
|
||||
continue;
|
||||
|
||||
List<Cluster> siblings = new() { clonedCluster };
|
||||
for (int instanceIx = 1; instanceIx < clonedCluster.instanceCount; instanceIx++) {
|
||||
// Create another sibling
|
||||
Cluster sibling = new(clonedCluster.prefab, this) {
|
||||
name = $"{clonedCluster.baseName}: {instanceIx}",
|
||||
parent = clone.parent,
|
||||
instanceCount = clone.instanceCount,
|
||||
};
|
||||
siblings.Add(sibling);
|
||||
CopyAllExternalReceivers(clonedCluster, sibling, this);
|
||||
}
|
||||
Cluster[] siblingClusters = siblings.ToArray();
|
||||
foreach (Cluster sibling in siblings)
|
||||
sibling.instances = siblingClusters;
|
||||
}
|
||||
|
||||
return clone;
|
||||
}
|
||||
|
||||
/// \copydoc NanoBrain::Nucleus::ShallowCloneTo
|
||||
public override Nucleus ShallowCloneTo(Cluster parent) {
|
||||
// Clusters should not be cloned, but instantiated from the prefab....
|
||||
@ -1011,10 +1099,10 @@ namespace NanoBrain {
|
||||
#region Serialization
|
||||
|
||||
public void Export(string path) {
|
||||
ClusterData data = new(this); //this.ToJSON();
|
||||
ClusterData data = new(this);
|
||||
string json = JsonUtility.ToJson(data, prettyPrint: true);
|
||||
|
||||
// Debug.Log($"Exporting json to {path}");
|
||||
Debug.Log($"Exporting {this.name} to {path}");
|
||||
File.WriteAllText(path, json);
|
||||
}
|
||||
|
||||
|
||||
@ -3,6 +3,9 @@ using UnityEngine;
|
||||
|
||||
namespace NanoBrain {
|
||||
public class Population {
|
||||
|
||||
# region Members
|
||||
|
||||
public class Member {
|
||||
public Member(Cluster cluster) {
|
||||
this.brain = cluster;
|
||||
@ -21,12 +24,49 @@ namespace NanoBrain {
|
||||
return newMember;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Generational update
|
||||
/// </summary>
|
||||
public virtual void Update() {
|
||||
#endregion Members
|
||||
|
||||
#region Saving
|
||||
|
||||
public enum SaveMethod {
|
||||
Average,
|
||||
Mean,
|
||||
First,
|
||||
All
|
||||
}
|
||||
public void Save(string path, SaveMethod saveMethod = SaveMethod.Average) {
|
||||
Cluster cluster = null;
|
||||
switch (saveMethod) {
|
||||
case SaveMethod.First:
|
||||
Member member = this.members[0];
|
||||
if (member == null)
|
||||
return;
|
||||
|
||||
cluster = member.brain;
|
||||
break;
|
||||
case SaveMethod.Average:
|
||||
cluster = CalculateAverageCluster();
|
||||
break;
|
||||
}
|
||||
cluster?.Export(path);
|
||||
}
|
||||
|
||||
protected Cluster CalculateAverageCluster() {
|
||||
if (members.Count <= 0)
|
||||
return null;
|
||||
|
||||
Cluster result = members[0].brain.Clone();
|
||||
for (int memberIx = 1; memberIx < members.Count; memberIx++) {
|
||||
Member member = members[memberIx];
|
||||
result.ProcessWeightsFrom(member.brain, Average);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
#endregion Saving
|
||||
|
||||
#region New Generation
|
||||
|
||||
public void NewGeneration() {
|
||||
foreach (Member member in this.members) {
|
||||
@ -118,6 +158,8 @@ namespace NanoBrain {
|
||||
return selectedMembers;
|
||||
}
|
||||
|
||||
#endregion New Generation
|
||||
|
||||
private void LogTrainableWeights(Cluster cluster) {
|
||||
string s = "";
|
||||
foreach (Nucleus nucleus in cluster.nuclei) {
|
||||
@ -131,5 +173,7 @@ namespace NanoBrain {
|
||||
}
|
||||
Debug.Log(s);
|
||||
}
|
||||
|
||||
public virtual void Update() { }
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user