Func <double, double> NodeFunc(NodeGene nodeGene)
        {
            switch (nodeGene.FunctionType)
            {
            case FunctionType.Identity:
                return(x => x);

            case FunctionType.Heaviside:
                return(x => x > 0 ? 1 : 0);

            case FunctionType.Sigmoid:
                return(x => 1 / (1 + Exp(-4.9 * x)));

            case FunctionType.Sin:
                return(Sin);

            case FunctionType.Exponent:
                return(Exp);

            case FunctionType.Log:
                return(x => x <= 0 ? 0 : Log(x));
            }

            throw new ArgumentException();
        }
        public Chromosome MutateAddNode(
            Func <int, int> chooseEdgeGeneTypeIndex,
            NodeGene newNodeGene
            ) =>
        Change((e, n) => {
            var enabledEdges = EdgeGenes.Where(edge => edge.Value.IsEnabled).Select(edge => edge.Key).ToImmutableList();
            if (enabledEdges.Count == 0)
            {
                return;
            }

            var edgeGeneType    = enabledEdges.ElementAt(chooseEdgeGeneTypeIndex(enabledEdges.Count));
            var edgeGene        = EdgeGenes[edgeGeneType];
            e[edgeGeneType]     = edgeGene.Disable();
            var newNodeGeneType = new NodeGeneType(NodeGeneType.InnovationIdByParents(edgeGeneType.From, edgeGeneType.To, newNodeGene));
            n[newNodeGeneType]  = newNodeGene;
            e[new EdgeGeneType(edgeGeneType.From, newNodeGeneType)] = new EdgeGene(1, true);
            e[new EdgeGeneType(newNodeGeneType, edgeGeneType.To)]   = new EdgeGene(edgeGene.Weight, true);
        });
 public static string InnovationIdByParents(NodeGeneType a, NodeGeneType b, NodeGene nodeGene) =>
 Hash(a.InnovationId + b.InnovationId + nodeGene.GetHashCode());