import numpy as np
import sys
import statistics
import time

def _aritmetics_crossover(population, size):
    newPopulation = []
    while len(newPopulation) != (size - 2):
        t = np.random.uniform(0, 1, size=1)
        #t = np.random.randint(0, 1)
        parent1 = population[np.random.randint(len(population))]
        parent2 = population[np.random.randint(len(population))]
        offspring1 = t*parent1 + (1 - t)*parent2
        parent1 = population[np.random.randint(len(population))]
        parent2 = population[np.random.randint(len(population))]
        offspring2 = (1 - t)*parent1 + t*parent2
        newPopulation.append(offspring1)
        newPopulation.append(offspring2)
    return np.asarray(newPopulation)

def _selection_elitism(population, size, fitness_func):
    elite = []
    pop, solution = np.array(fitness_func(population))
    sort_x = solution.argsort()
    def sort(solution, sort_x):
        sort_y = []
        for index, sol in enumerate(solution):
            sort_solution_x = sol[sort_x[index]]
            sort_y.append(sort_solution_x[-1])
        return sort_y
    sort_xy = np.asarray(sort(solution, sort_x))
    final_sort = sort_xy.argsort()
    elite.append(population[final_sort[size - 2]])
    elite.append(population[final_sort[size - 1]])
    return elite

def _mutation(population, size):
    D = population
    A = np.random.random(size=(len(D), size)) < 0.001
    Z = np.random.random(size=(len(D), size))
    D = (np.logical_not(A) * D) + (A * Z)
    return D

class Population:
    def __init__(self, chromozomes, fitness):
        self.Chromozomes = chromozomes
        self.Fitness = fitness

class Benchmark:
    @staticmethod
    def run(func):
        timings = []
        for i in range(100):
            start = time.time()
            func()
            seconds = time.time() - start
            timings.append(seconds)
            mean = statistics.mean(timings)
            print("{} {:3.2f} {:3.2f}".format(1 + i, mean,statistics.stdev(timings, mean) if i > 1 else 0))