import numpy as np
import math
import operator

from functools import reduce


def griewank(d):
    sumatory = 1.0 / 4000 * np.sum([(x**2) for x in d])
    product = np.prod([np.cos(x / np.sqrt(i+1.0)) for i, x in enumerate(d)])

    return 1 + sumatory - product

def sphere(d):
    return np.sum([x**2 for x in d])

def ackley(d, *, a=20, b=0.2, c=2*np.pi):
    sum_part1 = np.sum([x**2 for x in d])
    part1 = -1.0 * a * np.exp(-1.0 * b * np.sqrt((1.0/len(d)) * sum_part1))

    sum_part2 = np.sum([np.cos(c * x) for x in d])
    part2 = -1.0 * np.exp((1.0 / len(d)) * sum_part2)

    return a + np.exp(1) + part1 + part2

def rastrigin(d):
    sum_i = np.sum([x**2 - 10*np.cos(2 * np.pi * x) for x in d])
    return 10 * len(d) + sum_i
