internal static LogicalNetwork CreateNetwork(LogicalNetworkFactory factory, IEnumerable<LogicalNetworkGene> geneSequence)
        {
            int nodeIndex = 0;
            int lastNodeIndex = -1;
            var uppers = new List<LogicalConnectionGene>();
            var lowers = new List<LogicalConnectionGene>();

            foreach (var gene in geneSequence)
            {
                var connGene = gene as LogicalConnectionGene;
                if (connGene != null)
                {
                    if (connGene.IsUpper) uppers.Add(connGene); else lowers.Add(connGene);
                }
                else
                {
                    var nodeGene = (LogicalNodeGene)gene;
                    nodeIndex = nodeGene.Index;
                    foreach (var ucg in uppers)
                    {
                        int uni = nodeIndex + ucg.Index;
                        if (uni >= 0)
                        {
                            var connIndex = new ConnectionIndex(uni, nodeIndex);
                            factory.TryAddConnectionFactory(connIndex, new Factory<ComputationalConnection<bool>>(ucg.CreateConnection));
                        }
                    }
                    if (lastNodeIndex != -1)
                    {
                        foreach (var lcg in lowers)
                        {
                            int lni = lastNodeIndex + lcg.Index;
                            if (lni >= 0)
                            {
                                var connIndex = new ConnectionIndex(lastNodeIndex, lni);
                                factory.TryAddConnectionFactory(connIndex, new Factory<ComputationalConnection<bool>>(lcg.CreateConnection));
                            }
                        }
                    }
                    factory.TryAddNodeFactory(nodeIndex, new Factory<ComputationalNode<bool>>(nodeGene.CreateNode));
                    lastNodeIndex = nodeIndex;
                    uppers.Clear();
                    lowers.Clear();
                }
            }

            var network = new LogicalNetwork(factory);
            return network;
        }
        internal static LogicalNetworEntity Create(
            DNA<LogicalNetworkGene> dna,
            IEnumerable<LogicalNetworkGene> dominantGeneSequence,
            GateTypeEvolutionMethod evolutionMethod,
            TruthTable truthTableToSolve,
            LogicGateTypes gateTypeRestrictions)
        {
            Contract.Requires(dna != null);
            Contract.Requires(dominantGeneSequence != null);
            Contract.Requires(truthTableToSolve != null);
            Contract.Requires(gateTypeRestrictions != null);
            
            LogicalNetworkFactory factory;
            if (evolutionMethod == GateTypeEvolutionMethod.Restrict)
            {
                factory = new LogicalNetworkFactory(truthTableToSolve.InputInterfaceLength, truthTableToSolve.OutputInterfaceLength, gateTypeRestrictions);
            }
            else // Evolve
            {
                factory = new LogicalNetworkFactory(truthTableToSolve.InputInterfaceLength, truthTableToSolve.OutputInterfaceLength);
            }

            var network = LogicalNetworkDNADecoder.CreateNetwork(factory, dominantGeneSequence);

            int numOfNAGates = 0;
            if (evolutionMethod == GateTypeEvolutionMethod.Evolve && gateTypeRestrictions != null)
            {
                foreach (var entry in network.EntryArray)
                {
                    var gate = entry.NodeEntry.Node as LogicGate;
                    if (gate != null)
                    {
                        var type = new LogicGateType(gate.Operation, entry.UpperConnectionEntryArray.Length);
                        if (!gateTypeRestrictions.Contains(type)) numOfNAGates++;
                    }
                }
            }

            int errors = new TruthTableComputation(network).ComputeError(truthTableToSolve);

            return new LogicalNetworEntity(dna, network, errors, numOfNAGates);
        }