public NeatNetwork(NeatController controller, int inputCount, int outputCount) { this.controller = controller; age = 0; this.inputCount = inputCount; this.outputCount = outputCount; // Initialise network nodes = new List <NeatNode>(); genes = new List <NeatGene>(); geneTable = new Dictionary <Vector2Int, NeatGene>(); // The first I nodes will be inputs and the following O nodes will be outputs for (int i = 0; i < inputCount; ++i) { nodes.Add(new NeatNode(nodes.Count, NeatNode.NodeType.Input, this)); } for (int i = 0; i < outputCount; ++i) { nodes.Add(new NeatNode(nodes.Count, NeatNode.NodeType.Output, this)); } // // Avoid creation of non-essential genes (Requires testing) // // Create initial (minimal genes) connection inputs to outputs //for (int i = 0; i < inputCount; ++i) // for (int j = 0; j < outputCount; ++j) // CreateGene(i, inputCount + j); }
void OnEnable() { existingCollections = NeatController.GetExistingCollections(); existingTrees = TreeInputAgent.GetExistingTrees(); // No collections on disc so cannot load if (existingCollections.Length == 0) { populationName.gameObject.SetActive(false); treeCount.SetRange(0, MaxCharacterCount); treeCount.Value = treeCount.Max; treeCount.Interactable = false; neuralCount.SetRange(0, MaxCharacterCount); neuralCount.Value = 0; neuralCount.Interactable = false; existingCollections = new string[] { "AiArena" }; } else { populationName.gameObject.SetActive(true); treeCount.Interactable = true; neuralCount.Interactable = true; // Update displayed options populationName.ClearOptions(); List <Dropdown.OptionData> options = new List <Dropdown.OptionData>(); foreach (string collection in existingCollections) { options.Add(new Dropdown.OptionData(collection)); } populationName.AddOptions(options); } if (existingTrees.Length == 0) { existingTrees = new string[] { "Null" }; } // Update displayed options treeName.ClearOptions(); List <Dropdown.OptionData> treeOptions = new List <Dropdown.OptionData>(); foreach (string collection in existingTrees) { treeOptions.Add(new Dropdown.OptionData(collection)); } treeName.AddOptions(treeOptions); populationName.value = 0; treeName.value = 0; }
public NeatSpecies(NeatController controller, NeatNetwork representative) { this.controller = controller; this.representative = representative; colour = Color.HSVToRGB(Random.value, Random.Range(0.5f, 1.0f), Random.Range(0.5f, 1.0f)); generationsLived = 0; guid = System.Guid.NewGuid(); population = new List <NeatNetwork>(); population.Add(representative); representative.assignedSpecies = this; }
void OnEnable() { existingCollections = NeatController.GetExistingCollections(); // No collections on disc so cannot load if (existingCollections.Length == 0) { newPopulationToggle.interactable = false; } else { newPopulationToggle.interactable = true; } }
/// <summary> /// Create a copy of an existing network structure (Only structual values are copies) /// </summary> /// <param name="controller"></param> /// <param name="inputCount"></param> /// <param name="outputCount"></param> public NeatNetwork(NeatNetwork other) { this.controller = other.controller; previousFitness = other.fitness; this.age = other.age + 1; this.inputCount = other.inputCount; this.outputCount = other.outputCount; // Initialise network nodes = new List <NeatNode>(other.nodes); genes = new List <NeatGene>(other.genes); geneTable = new Dictionary <Vector2Int, NeatGene>(other.geneTable); }
/// <summary> /// Create networks /// </summary> /// <param name="collectionName">The name of the collection to load/create</param> /// <param name="count">Number of networks to create</param> public void InitialiseController(string collectionName, int count) { populationSize = count; // Load NEAT controller neatController = new NeatController(collectionName); if (!neatController.LoadNeatSettings()) { Debug.Log("Using default NEAT settings"); neatController.WriteNeatSettings(); } neatController.GenerateBasePopulation(count, NeuralInputAgent.InputCount, NeuralInputAgent.OutputCount, 1); // Use controller's runtime to start from runTime = neatController.runTime; }
public NeatSpecies(NeatController controller, XmlElement content) { this.controller = controller; population = new List <NeatNetwork>(); ReadXML(content); }
/// <summary> /// Can these 2 networks be consider the same species /// </summary> /// <returns></returns> public static bool AreSameSpecies(NeatNetwork networkA, NeatNetwork networkB) { // Construct gene table (A genes in index 0 B genes in index 1) Dictionary <int, NeatGene[]> geneTable = new Dictionary <int, NeatGene[]>(); foreach (NeatGene gene in networkA.genes) { geneTable.Add(gene.innovationId, new NeatGene[] { gene, null }); } foreach (NeatGene gene in networkB.genes) { if (geneTable.ContainsKey(gene.innovationId)) { geneTable[gene.innovationId][1] = gene; } else { geneTable.Add(gene.innovationId, new NeatGene[] { null, gene }); } } // Consider genes in order List <int> geneIds = new List <int>(geneTable.Keys); geneIds.Sort((x, y) => - x.CompareTo(y)); // Sort from last to first int excessCount = 0; int disjointCount = 0; int matchCount = 0; float matchTotalWeightDiff = 0.0f; bool checkingForExcess = true; bool checkingExcessFromA = false; // Otherwise read from B // Calculate counts by considering each gene for (int i = 0; i < geneIds.Count; ++i) { NeatGene[] genes = geneTable[geneIds[i]]; // Gene is excess if exists at hanging at end of gene list if (checkingForExcess) { // Check which side we're to read excess from if (i == 0) { checkingExcessFromA = (genes[0] != null); } if (checkingExcessFromA && genes[1] == null) { ++excessCount; } else if (!checkingExcessFromA && genes[0] == null) { ++excessCount; } // Finished reading the excess (either the network we're reading doesn't have this gene or the other network also has this gene) else { checkingForExcess = false; } } // (Can be changed above, so still check for disjoint of matching) if (!checkingForExcess) { // Matching gene if (genes[0] != null && genes[1] != null) { ++matchCount; matchTotalWeightDiff += Mathf.Abs(genes[0].weight - genes[1].weight); } // One net doesn't have this gene, so disjoint else { ++disjointCount; } } } NeatController controller = networkA.controller; // Should be the same for B float geneCount = Mathf.Max(networkA.genes.Count, networkB.genes.Count); float networkDelta = controller.excessCoefficient * (geneCount == 0 ? 0 : excessCount / geneCount) + controller.disjointCoefficient * (geneCount == 0 ? 0 : disjointCount / geneCount) + controller.weightDiffCoefficient * (matchCount == 0 ? 0 : (matchTotalWeightDiff / (float)matchCount)); // Each network can be considered under the same species, if their difference is in acceptable range return(networkDelta <= controller.speciesDeltaThreshold); }
public NeatNetwork(NeatController controller, XmlElement content) { this.controller = controller; ReadXML(content); }