public NetModel Breed(BatchModel family, NetModel mother, NetModel father)
        {
            var rnd = new Random();

            // Mother should always be fitter then father
            if (mother.FitnessScore < father.FitnessScore)
            {
                return(Breed(family, father, mother));
            }

            // Quick rules for how offspring is generated
            // If both parents have the same innovation then take a random one
            // If fittest parent have innovation then take it.
            // Otherwise skip.

            // As we only care for fittest parents innovation range
            // we can ignore the range of weaker one.
            // - In first check we have ensured that mother is always the fittest one.
            var range   = _netNeatController.GetInnovationRange(mother);
            var parents = new NetModel[2] {
                mother, father
            };

            // Each connection has an innovation id, thus we can
            // Create array where each connection is stored in cell
            // based on its innovations id.
            // We store connections id in table.
            var table = new int[2, range.max - range.min + 1];

            for (var i = 0; i < 2; i++)
            {
                for (var x = 0; x < table.GetLength(1); x++)
                {
                    table[i, x] = -1;
                }
            }

            for (var p = 0; p < 2; p++)
            {
                for (var c = 0; c < parents[p].Connections.Count; c++)
                {
                    var column = parents[p].Connections[c].InnovationId - range.min;
                    // Father can go outside range.
                    if (column < 0 || column >= table.GetLength(1))
                    {
                        continue;
                    }

                    table[p, column] = c;
                }
            }

            var child = _netController.New(family, false);

            // Populates child with connections
            for (var c = 0; c < range.max - range.min + 1; c++)
            {
                // Disjoint on mother, thus we don't care about the connection
                if (table[0, c] == -1)
                {
                    continue;
                }

                // If both are empty skip
                if (table[0, c] == -1 && table[1, c] == -1)
                {
                    continue;
                }

                if (table[0, c] != -1 && table[1, c] != -1)
                {
                    // Adds random connection to child
                    var parentId = rnd.Next(0, 2);
                    _netController.AddConnection(ref child, parents[parentId].Connections[table[parentId, c]]);
                    continue;
                }

                // If disjoint on father, then add mother connection
                _netController.AddConnection(ref child, mother.Connections[table[0, c]]);
            }

            // Populates child with nodes
            var initializedNodeIds = new HashSet <int>();

            foreach (var node in child.Nodes)
            {
                initializedNodeIds.Add(node.InnovationId);
            }

            foreach (var connection in child.Connections)
            {
                // If child doesn't contain node then add it to network and initializedNode set
                var currentIds = new[] { connection.ToId, connection.FromId };
                foreach (var currentId in currentIds)
                {
                    if (initializedNodeIds.Contains(currentId))
                    {
                        continue;
                    }

                    _netController.AddNode(ref child, new NodeModel
                    {
                        InnovationId = currentId
                    });
                    initializedNodeIds.Add(currentId);
                }
            }

            return(child);
        }
        public void PopulateNextGeneration(ref GnnModel gnnModel)
        {
            gnnModel.UnsignedNetworks = new List <NetModel>();
            _batchController.IncreaseGeneration(gnnModel.ActiveBatchModel);

            #region Adds survivors to next generation

            // Adds survivors of each specie to the next generation
            foreach (var specie in gnnModel.Species)
            {
                // Calculates how many networks keep
                var keepAlive = (int)(specie.Members.Count * Config.KeepPerSpecies);

                // We want at-least one survivor per specie.
                if (keepAlive <= 0)
                {
                    keepAlive = 1;
                }

                // Ads them to next gen.
                for (var i = 0; i < keepAlive; i++)
                {
                    gnnModel.UnsignedNetworks.Add(specie.Members[i]);
                    specie.Members[i].Enabled = true;
                    _netController.Save(specie.Members[i]);
                }

                // Disables old networks
                for (var i = keepAlive; i < specie.Members.Count; i++)
                {
                    specie.Members[i].Enabled = false;
                    _netController.Save(specie.Members[i]);
                }
            }
            #endregion

            #region Populates empty spaces with offspings

            // Populates rest of generation with offspring of survivors
            var networksToAdd = Config.NetworkCountPerPopulation - gnnModel.UnsignedNetworks.Count;
            for (var i = 0; i < networksToAdd; i++)
            {
                var specie = GetRandomSpeciesModel(gnnModel);

                var mother = _speciesController.GetRandomNetModel(specie);
                var father = _speciesController.GetRandomNetModel(specie);

                var child = _breedingController.Breed(gnnModel.ActiveBatchModel, mother, father);

                _mutationController.MutateWithBatch(ref child, 1);  // Add node mutation
                _mutationController.MutateWithBatch(ref child, 2);  // Add connection mutation
                _mutationController.MutateWithBatch(ref child, 3);  // Connections weight mutation

                // If mutation caused dysfunction replace network with new one
                if (IsBroken(child))
                {
                    _netController.Kill(child);
                    child = _netController.New(gnnModel.ActiveBatchModel);
                }

                // Orders
                child.Connections = child.Connections.OrderBy(c => c.InnovationId).ToList();
                child.Nodes       = child.Nodes.OrderBy(n => n.InnovationId).ToList();
                child.Enabled     = true;
                _netController.Save(child);
                gnnModel.UnsignedNetworks.Add(child);
            }
            #endregion

            // Rebuilds batch from db (Why? Because innovation table has changed)
            gnnModel.ActiveBatchModel = _batchController.Load(gnnModel.ActiveBatchModel.Id);
        }