private IEnumerator Evaluate(GeneticEquation equation, Candidate candidate)
        {
            var expression = equation.expression.Copy() as Expression;

            if (expression == null)
            {
                yield break;
            }

            m_CurrentlyEvaluatedCandidate  = candidate;
            m_CurrentlyEvaluatedExpression = expression;

            foreach (var chromosome in candidate.chromosomes)
            {
                foreach (var variable in expression.GetVariables())
                {
                    if (chromosome.name == variable.stringValue)
                    {
                        variable.value = chromosome.value;
                    }
                }
            }

            var fitnessEvaluation = expression.Copy() as Expression;

            yield return(expression.Evaluate());

            var result = expression.expressionObjects.First() as Variable;

            equation.solved = (bool)result.value;
            if (equation.solved)
            {
                candidate.fitness = 1f;

                equation.solvingCandidate = candidate;
            }
            else
            {
                if (fitnessEvaluation == null)
                {
                    yield break;
                }

                var expressions = fitnessEvaluation.expressionObjects.OfType <Expression>().ToList();

                var trueClauses = 0f;
                foreach (var expr in expressions)
                {
                    var enumerator = expr.Evaluate();
                    while (enumerator.MoveNext())
                    {
                    }

                    var evaluation = expr.expressionObjects.First() as Variable;
                    if (evaluation == null)
                    {
                        continue;
                    }

                    if ((bool)evaluation.value)
                    {
                        ++trueClauses;
                    }
                }

                candidate.fitness = trueClauses / expressions.Count;
            }
        }
        private IEnumerator RunSolver()
        {
            foreach (var parseCNF in m_ParseCNFs)
            {
                m_CurrentGeneticEquation = new GeneticEquation {
                    expression = parseCNF.expression
                };

                var initialGeneration = new Generation();

                for (var i = 0; i < Random.Range(15, 25); ++i)
                {
                    initialGeneration.candidates.Add(new Candidate());
                }

                var sortedVariables =
                    parseCNF.expression.GetVariables().OrderBy(variable => variable.stringValue).ToList();

                foreach (var candidate in initialGeneration.candidates)
                {
                    foreach (var variable in sortedVariables)
                    {
                        candidate.chromosomes.Add(new Chromosome
                        {
                            value = Random.Range(0, 2) == 1,
                            name  = variable.stringValue,
                        });
                    }
                }

                ++m_CurrentGeneticEquation.generations;
                m_CurrentGeneticEquation.currentGeneration = initialGeneration;

                while (!m_CurrentGeneticEquation.solved)
                {
                    foreach (var candidate in m_CurrentGeneticEquation.currentGeneration.candidates)
                    {
                        if (m_CurrentGeneticEquation.solved)
                        {
                            continue;
                        }

                        yield return(Evaluate(m_CurrentGeneticEquation, candidate));
                    }

                    if (m_CurrentGeneticEquation.solved)
                    {
                        continue;
                    }

                    Generation newGeneration = null;
                    switch (m_PopulationGenerationType)
                    {
                    case PopulationGenerationType.DoubleCrossover:
                        newGeneration = DoubleCrossover();
                        break;

                    case PopulationGenerationType.BasicInheritance:
                        newGeneration = BasicInheritance();
                        break;

                    case PopulationGenerationType.SurvivalOfTheFittest:
                        newGeneration = SurvivalOfTheFittest();
                        break;

                    default:
                        break;
                    }

                    m_CurrentGeneticEquation.currentGeneration = newGeneration;

                    ++m_CurrentGeneticEquation.generations;

                    yield return(null);
                }
                yield return(new WaitForSeconds(3f));
            }
        }