"""Repeat the following paper for `CLPSO`:
    Liang, J.J., Qin, A.K., Suganthan, P.N. and Baskar, S., 2006.
    Comprehensive learning particle swarm optimizer for global optimization of multimodal functions.
    IEEE Transactions on Evolutionary Computation, 10(3), pp.281-295.
    https://ieeexplore.ieee.org/abstract/document/1637688

    Luckily our code could repeat the data generated by the original paper *well*.
    Therefore, we argue that the repeatability of `CLPSO` could be **well-documented**.
"""
import time

import numpy as np

from pypop7.benchmarks.base_functions import sphere, ackley, rastrigin
from pypop7.optimizers.pso.clpso import CLPSO as Solver


if __name__ == '__main__':
    ndim_problem = 30

    start_run = time.time()
    problem = {'fitness_function': sphere,
               'ndim_problem': ndim_problem,
               'lower_boundary': -100 * np.ones((ndim_problem,)),
               'upper_boundary': 100 * np.ones((ndim_problem,)),
               'initial_lower_boundary': -100 * np.ones((ndim_problem,)),
               'initial_upper_boundary': 50 * np.ones((ndim_problem,))}
    options = {'max_function_evaluations': 200000,
               'seed_rng': 0,  # undefined in the original paper
               'n_individuals': 40,
               'verbose': 1e3,
               'saving_fitness': 20000}
    solver = Solver(problem, options)
    results = solver.optimize()
    print(results)  # 6.10600207e-17 vs 4.46e-14 (from the original paper)
    print('*** Runtime: {:7.5e}'.format(time.time() - start_run))

    start_run = time.time()
    problem = {'fitness_function': ackley,
               'ndim_problem': ndim_problem,
               'lower_boundary': -32.768 * np.ones((ndim_problem,)),
               'upper_boundary': 32.768 * np.ones((ndim_problem,)),
               'initial_lower_boundary': -32.768 * np.ones((ndim_problem,)),
               'initial_upper_boundary': 16 * np.ones((ndim_problem,))}
    options = {'max_function_evaluations': 200000,
               'seed_rng': 0,  # undefined in the original paper
               'n_individuals': 40,
               'm': 5,
               'verbose': 1e3,
               'saving_fitness': 20000}
    solver = Solver(problem, options)
    results = solver.optimize()
    print(results)  # 9.16746679e-11 vs 0 (from the original paper)
    print('*** Runtime: {:7.5e}'.format(time.time() - start_run))

    start_run = time.time()
    problem = {'fitness_function': rastrigin,
               'ndim_problem': ndim_problem,
               'lower_boundary': -5.12 * np.ones((ndim_problem,)),
               'upper_boundary': 5.12 * np.ones((ndim_problem,)),
               'initial_lower_boundary': -5.12 * np.ones((ndim_problem,)),
               'initial_upper_boundary': 2 * np.ones((ndim_problem,))}
    options = {'max_function_evaluations': 200000,
               'seed_rng': 0,  # undefined in the original paper
               'n_individuals': 40,
               'verbose': 1e3,
               'saving_fitness': 20000}
    solver = Solver(problem, options)
    results = solver.optimize()
    print(results)  # 3.99211331e-10 vs 4.85e-10 (from the original paper)
    print('*** Runtime: {:7.5e}'.format(time.time() - start_run))
