public async Task <Genome> Epoch(IEnumerable <Local> locals)
        {
            if (new Delegate[] { Fitness, Mutation, Crossover, Selection, }.Any(e => e == null))
            {
                throw new Exception("GA cant run without all operators");
            }

            var config = new GASettings();

            var crossOverRate = config.CrossoverRate;
            var mutationRate  = config.MutationRate;

            locals = EnumerableEx.Return(locals.First()).Concat(locals.Skip(1).Shuffle());

            var population = await Enumerable.Range(0, settings.PopulationSize)
                             .Select(_ => new Genome(locals))
                             .ToObservable()
                             .Select(n => Observable.FromAsync(_ => n.CalcRoutesAsync(routeService.CalcFullRoute)))
                             .Merge(ParallelQuantity)
                             .Select(e => e.CalcFitness(Fitness))
                             .ToList();



            var lastGen = await
                          GetNewPopulationCollectionAsync(population, crossOverRate, mutationRate)
                          .ToObservable()
                          .SelectMany(n => Observable.FromAsync(_ => n))
                          .Take(settings.GenerationLimit)
                          .LastAsync()
            ;


            return(lastGen.OrderBy(e => e.Fitness).First());
        }
 public GeneticAlgorithmFinder(
     FitnessDelegate fitnessDelegate,
     MutationDelegate mutationDelegate,
     CrossOverDelegate crossOverDelegate,
     SelectionDelegate selectionDelegate,
     IRouteService routeService,
     GASettings gASettings
     )
 {
     Fitness           = fitnessDelegate;
     Mutation          = mutationDelegate;
     Crossover         = crossOverDelegate;
     Selection         = selectionDelegate;
     settings          = gASettings;
     this.routeService = routeService;
 }