public IEnumerable <Individual> Apply(IEnumerable <Individual> source)
        {
            var prms = ParamsProvider(this);
            var inp  = source.ToArray();

            var elite = Elitism.SelectElite(inp, prms.ElitismFraction).ToArray();

            if (elite.Length % 2 != 0)
            {
                throw new InvalidOperationException("Elitism fraction must result in an even number of individuals");
            }
            var selected = Selection.Roulette(inp, inp.Length - elite.Length);
            var crossed  = Crossover.UniformCrossoverPop(selected);
            var mutated  = Mutation.MutatePop(crossed, prms.MutationFraction, RandomValueProvider);

            var retPop = elite.Concat(mutated).ToArray();

            history.Add(CalcStats(prms, inp, retPop));
            return(retPop);
        }