[1]:
import numpy as np
import time
from scipy.optimize import differential_evolution, minimize, dual_annealing
import matplotlib.pyplot as plt
import concurrent.futures
import threading, multiprocessing

import sys
sys.path.append("../")
import minionpy as mpy
import minionpy.test_functions as mpytest
import time

Minimizing Basic Functions

In this section, we minimize basic functions such as Sphere, Rosenbrock, and Rastrigin. The search space is shifted to prevent algorithms from converging near the origin, as some algorithms tend to favor that region.

[2]:
def sphere(x) :
    x =np.asarray(x)-1
    return 100+np.sum(x**2)

def rosenbrock(x):
    #if x[0]<-1 or x[0]>1 : print(x, "bound violated")
    x = np.asarray(x)-5.0
    return 100+np.sum(100 * (x[1:] - x[:-1]**2)**2 + (1 - x[:-1])**2)

def rastrigin(x):
    x = np.asarray(x)-1.0
    A = 10
    return 100+A * len(x) + np.sum(x**2 - A * np.cos(2 * np.pi * x))

#remember that in minion, objective function must be vectorized. Suppose you want to
func = rosenbrock
def objective_function(X) :
    """
    Here, X is a list of x, where x is an input vector.
    """
    return [func(x) for x in X]

#Now minimize the function using minion
dimension = 5 #set dimension of the problem
maxevals = 1000 #number of function calls
x0 = [[0.0]*dimension] # initial guesses

min = mpy.Minimizer(func=objective_function, x0=x0, bounds=[(-1, 1)]*dimension, algo="ARRDE", relTol=0.0,
                    maxevals=10000, callback=None, seed=None, options={"minimum_population_size":4})
result = min.optimize()
print("The minimum of the function is ", "\n\t x : ", result.x, "\n\t f(x) : ", result.fun)
The minimum of the function is
         x :  [0.9999999999999998, 0.9999999999999996, 0.9999999999999997, 1.0, 0.9999999999999999]
         f(x) :  160200.0

Using Basic Test Functions

Minionpy provides a variety of test functions for evaluating optimization algorithms. The dictionary testFunctionDict below contains some of the fundamental functions available. Many of these functions have a global minimum at the origin, which can be problematic since some algorithms naturally converge toward it. To address this issue, CEC benchmark functions apply rotation and shifting to these basic functions, making them more representative of real-world optimization scenarios.

The test functions in minionpy.test_functions are vectorized by default. They accept input as a 2D NumPy array.

[3]:
testFunctionDict = {
    "sphere" : mpytest.sphere,
    "rosenbrock" : mpytest.rosenbrock,
    "rastrigin" : mpytest.rastrigin,
    "schaffer2" : mpytest.schaffer2,
    "griewank" : mpytest.griewank,
    "ackley" : mpytest.ackley,
    "zakharov" : mpytest.zakharov,
    "bent_cigar" : mpytest.bent_cigar,
    "levy" : mpytest.levy,
    "discus" : mpytest.discus,
    "drop_wave" : mpytest.drop_wave,
    "goldstein_price" : mpytest.goldstein_price,
    "exponential" : mpytest.exponential,
    "quartic" : mpytest.quartic,
    "hybrid_composition1" : mpytest.hybrid_composition1,
    "hybrid_composition2" : mpytest.hybrid_composition2,
    "hybrid_composition3" : mpytest.hybrid_composition3,
    "happy_cat"  : mpytest.happy_cat,
    "michalewics" : mpytest.michalewicz,
    "scaffer6" : mpytest.scaffer6,
    "hcf" : mpytest.hcf,
    "grie_rosen" : mpytest.grie_rosen,
    "dixon_price" : mpytest.dixon_price,
    "eosom" : mpytest.easom,
    "hgbat" : mpytest.hgbat,
    "styblinski_tang" : mpytest.styblinski_tang,
    "step" : mpytest.step,
    "weierstrass" : mpytest.weierstrass,
    "sum_squares" : mpytest.sum_squares
}

The performance of different algorithms to minimize these functions can be compared as shown below.

[4]:
dimension = 10
maxevals = 10000
np.random.seed(1)
shift = 10 * np.random.rand(dimension)  # Shift randomly
bounds = [(-10, 10)] * dimension
x0 = [10 * np.random.rand(dimension)] # Initial guesses
np.random.seed(None)

for func_name in testFunctionDict:
    #if func_name not in ["schaffer2", "ackley", "rastrigin", "rosenbrock"]:
    #    continue  # Minimize only these functions; comment this line to compare all test functions

    print(f"Function: {func_name}")

    N = 0

    def objective_function(X):
        """Shifted objective function for minimization."""
        global N
        X = np.array(X) - shift  # Shift the space
        N += len(X)
        return testFunctionDict[func_name](X)

    def objective_function_scipy(X):
        """Objective function for SciPy optimizers."""
        global N
        N += 1
        return testFunctionDict[func_name]([X])[0]

    algoList = [
        "DE", "ABC", "LSHADE", "LSHADE_cnEpSin", "JADE", "jSO", "j2020", "LSRTDE", "NLSHADE_RSP",
        "ARRDE", "GWO_DE", "NelderMead", "DA", "L_BFGS_B", "PSO", "DMSPSO", "SPSO2011", "CMAES", "BIPOP_aCMAES"
    ]


    for algo in algoList:
        t_start = time.time()
        N = 0
        result = mpy.Minimizer(
            func=objective_function, x0=x0, bounds=bounds, algo=algo,
            relTol=0.0, maxevals=maxevals, callback=None, seed=None,
            options={"population_size": 0}
        ).optimize()
        elapsed_time = time.time() - t_start
        print(f"\tAlgorithm: {algo:<18} f(x): {result.fun:<15.8g} Elapsed: {elapsed_time:.3f} s")

    # Compare to SciPy algorithms
    algorithms_scipy = [
        ("Scipy Nelder-Mead", minimize, {"x0": x0[0], "method": "Nelder-Mead",
                                         "bounds": bounds, "options": {"maxfev": maxevals, "adaptive": True}}),
        ("Scipy L-BFGS-B", minimize, {"x0": x0[0], "method": "L-BFGS-B",
                                      "options": {"maxfun": maxevals}, "bounds": bounds}),
        ("Scipy DA", dual_annealing, {"bounds": bounds, "maxfun": maxevals, "x0": x0[0], "no_local_search": False})
    ]

    for name, func, kwargs in algorithms_scipy:
        t_start = time.time()
        N = 0
        result = func(objective_function_scipy, **kwargs)
        elapsed_time = time.time() - t_start
        print(f"\tAlgorithm: {name:<18} f(x): {result.fun:<15.8g} Elapsed: {elapsed_time:.3f} s")

    print("")

Function: sphere
        Algorithm: DE                 f(x): 6.4594316e-07   Elapsed: 0.024 s
        Algorithm: ABC                f(x): 1.0122429e-06   Elapsed: 0.015 s
        Algorithm: LSHADE             f(x): 4.8582737e-10   Elapsed: 0.029 s
        Algorithm: LSHADE_cnEpSin     f(x): 6.3487577e-11   Elapsed: 0.023 s
        Algorithm: JADE               f(x): 9.2561239e-17   Elapsed: 0.024 s
        Algorithm: jSO                f(x): 3.23311e-11     Elapsed: 0.029 s
        Algorithm: j2020              f(x): 2.5152134e-12   Elapsed: 0.096 s
        Algorithm: LSRTDE             f(x): 7.735322e-11    Elapsed: 0.015 s
        Algorithm: NLSHADE_RSP        f(x): 3.8201629e-10   Elapsed: 0.016 s
        Algorithm: ARRDE              f(x): 2.2758254e-25   Elapsed: 0.024 s
        Algorithm: GWO_DE             f(x): 3.8637342e-06   Elapsed: 0.016 s
        Algorithm: NelderMead         f(x): 4.6709368e-30   Elapsed: 0.031 s
        Algorithm: DA                 f(x): 4.7770251e-15   Elapsed: 0.066 s
        Algorithm: L_BFGS_B           f(x): 8.5184112e-31   Elapsed: 0.000 s
        Algorithm: PSO                f(x): 2.4934109e-16   Elapsed: 0.015 s
        Algorithm: DMSPSO             f(x): 1.0116816e-15   Elapsed: 0.013 s
        Algorithm: SPSO2011           f(x): 9.646589e-09    Elapsed: 0.018 s
        Algorithm: CMAES              f(x): 2.8681543e-13   Elapsed: 0.008 s
        Algorithm: BIPOP_aCMAES       f(x): 8.7623091e-11   Elapsed: 0.008 s
        Algorithm: Scipy Nelder-Mead  f(x): 5.8359322e-09   Elapsed: 0.034 s
        Algorithm: Scipy L-BFGS-B     f(x): 6.9420299e-12   Elapsed: 0.004 s
        Algorithm: Scipy DA           f(x): 2.4294687e-16   Elapsed: 0.280 s

Function: rosenbrock
        Algorithm: DE                 f(x): 5.8036054       Elapsed: 0.016 s
        Algorithm: ABC                f(x): 4.4393332       Elapsed: 0.014 s
        Algorithm: LSHADE             f(x): 2.7117536       Elapsed: 0.026 s
        Algorithm: LSHADE_cnEpSin     f(x): 2.7873194       Elapsed: 0.026 s
        Algorithm: JADE               f(x): 2.3302768       Elapsed: 0.022 s
        Algorithm: jSO                f(x): 4.2779572       Elapsed: 0.027 s
        Algorithm: j2020              f(x): 6.2863117       Elapsed: 0.137 s
        Algorithm: LSRTDE             f(x): 5.5999934       Elapsed: 0.016 s
        Algorithm: NLSHADE_RSP        f(x): 4.9742818       Elapsed: 0.018 s
        Algorithm: ARRDE              f(x): 2.9238755       Elapsed: 0.025 s
        Algorithm: GWO_DE             f(x): 7.5983039       Elapsed: 0.016 s
        Algorithm: NelderMead         f(x): 3.1653044e-27   Elapsed: 0.067 s
        Algorithm: DA                 f(x): 1.2793334e-09   Elapsed: 0.112 s
        Algorithm: L_BFGS_B           f(x): 2.7409974e-12   Elapsed: 0.005 s
        Algorithm: PSO                f(x): 4.0906843       Elapsed: 0.014 s
        Algorithm: DMSPSO             f(x): 3.2080645       Elapsed: 0.018 s
        Algorithm: SPSO2011           f(x): 6.3594034       Elapsed: 0.020 s
        Algorithm: CMAES              f(x): 0.1977988       Elapsed: 0.026 s
        Algorithm: BIPOP_aCMAES       f(x): 8.3126645e-11   Elapsed: 0.027 s
        Algorithm: Scipy Nelder-Mead  f(x): 8.9958364e-09   Elapsed: 0.064 s
        Algorithm: Scipy L-BFGS-B     f(x): 1.1061741e-10   Elapsed: 0.012 s
        Algorithm: Scipy DA           f(x): 6.1826579e-11   Elapsed: 0.318 s

Function: rastrigin
        Algorithm: DE                 f(x): 15.91933        Elapsed: 0.016 s
        Algorithm: ABC                f(x): 0.0020894837    Elapsed: 0.014 s
        Algorithm: LSHADE             f(x): 2.8265663       Elapsed: 0.026 s
        Algorithm: LSHADE_cnEpSin     f(x): 1.2984332       Elapsed: 0.019 s
        Algorithm: JADE               f(x): 0.0005493625    Elapsed: 0.022 s
        Algorithm: jSO                f(x): 2.7930212       Elapsed: 0.029 s
        Algorithm: j2020              f(x): 0.99495906      Elapsed: 0.131 s
        Algorithm: LSRTDE             f(x): 22.064574       Elapsed: 0.016 s
        Algorithm: NLSHADE_RSP        f(x): 2.2162852       Elapsed: 0.019 s
        Algorithm: ARRDE              f(x): 1.9899388       Elapsed: 0.027 s
        Algorithm: GWO_DE             f(x): 3.2014875       Elapsed: 0.017 s
        Algorithm: NelderMead         f(x): 102.47964       Elapsed: 0.020 s
        Algorithm: DA                 f(x): 2.9848772       Elapsed: 0.097 s
        Algorithm: L_BFGS_B           f(x): 102.47964       Elapsed: 0.001 s
        Algorithm: PSO                f(x): 13.929397       Elapsed: 0.016 s
        Algorithm: DMSPSO             f(x): 13.015082       Elapsed: 0.021 s
        Algorithm: SPSO2011           f(x): 19.370493       Elapsed: 0.028 s
        Algorithm: CMAES              f(x): 5.9697543       Elapsed: 0.080 s
        Algorithm: BIPOP_aCMAES       f(x): 10.944545       Elapsed: 0.047 s
        Algorithm: Scipy Nelder-Mead  f(x): 254.70399       Elapsed: 0.032 s
        Algorithm: Scipy L-BFGS-B     f(x): 237.78983       Elapsed: 0.004 s
        Algorithm: Scipy DA           f(x): 6.3948846e-14   Elapsed: 0.356 s

Function: schaffer2
        Algorithm: DE                 f(x): 0.17246644      Elapsed: 0.224 s
        Algorithm: ABC                f(x): 0.16649813      Elapsed: 0.194 s
        Algorithm: LSHADE             f(x): 0.28156973      Elapsed: 0.222 s
        Algorithm: LSHADE_cnEpSin     f(x): 0.41557792      Elapsed: 0.202 s
        Algorithm: JADE               f(x): 0.23437661      Elapsed: 0.199 s
        Algorithm: jSO                f(x): 0.26111586      Elapsed: 0.209 s
        Algorithm: j2020              f(x): 0.43476573      Elapsed: 0.253 s
        Algorithm: LSRTDE             f(x): 0.92118071      Elapsed: 0.208 s
        Algorithm: NLSHADE_RSP        f(x): 0.18376438      Elapsed: 0.194 s
        Algorithm: ARRDE              f(x): 0.13212947      Elapsed: 0.209 s
        Algorithm: GWO_DE             f(x): 0.56071983      Elapsed: 0.192 s
        Algorithm: NelderMead         f(x): 0.18775994      Elapsed: 0.117 s
        Algorithm: DA                 f(x): 1.2267964e-14   Elapsed: 0.255 s
        Algorithm: L_BFGS_B           f(x): 0.18775994      Elapsed: 0.025 s
        Algorithm: PSO                f(x): 0.17015076      Elapsed: 0.198 s
        Algorithm: DMSPSO             f(x): 0.14245968      Elapsed: 0.190 s
        Algorithm: SPSO2011           f(x): 0.89992984      Elapsed: 0.200 s
        Algorithm: CMAES              f(x): 0.47136894      Elapsed: 0.201 s
        Algorithm: BIPOP_aCMAES       f(x): 0.54929968      Elapsed: 0.234 s
        Algorithm: Scipy Nelder-Mead  f(x): 0.38943872      Elapsed: 0.072 s
        Algorithm: Scipy L-BFGS-B     f(x): 0.38943873      Elapsed: 0.020 s
        Algorithm: Scipy DA           f(x): 0.087443189     Elapsed: 0.436 s

Function: griewank
        Algorithm: DE                 f(x): 0.039382435     Elapsed: 0.017 s
        Algorithm: ABC                f(x): 0.012211673     Elapsed: 0.018 s
        Algorithm: LSHADE             f(x): 0.041705992     Elapsed: 0.027 s
        Algorithm: LSHADE_cnEpSin     f(x): 0.0024145917    Elapsed: 0.021 s
        Algorithm: JADE               f(x): 0.044212076     Elapsed: 0.023 s
        Algorithm: jSO                f(x): 0.032435159     Elapsed: 0.032 s
        Algorithm: j2020              f(x): 0.017241088     Elapsed: 0.169 s
        Algorithm: LSRTDE             f(x): 0.0073966469    Elapsed: 0.017 s
        Algorithm: NLSHADE_RSP        f(x): 0.025184437     Elapsed: 0.029 s
        Algorithm: ARRDE              f(x): 0.0073960405    Elapsed: 0.032 s
        Algorithm: GWO_DE             f(x): 0.019931597     Elapsed: 0.018 s
        Algorithm: NelderMead         f(x): 0.02461003      Elapsed: 0.032 s
        Algorithm: DA                 f(x): 0.07529705      Elapsed: 0.095 s
        Algorithm: L_BFGS_B           f(x): 0.02461003      Elapsed: 0.002 s
        Algorithm: PSO                f(x): 0.078792042     Elapsed: 0.015 s
        Algorithm: DMSPSO             f(x): 0.017226294     Elapsed: 0.015 s
        Algorithm: SPSO2011           f(x): 0.045022134     Elapsed: 0.018 s
        Algorithm: CMAES              f(x): 1.956213e-13    Elapsed: 0.010 s
        Algorithm: BIPOP_aCMAES       f(x): 7.4974693e-11   Elapsed: 0.008 s
        Algorithm: Scipy Nelder-Mead  f(x): 0.046729411     Elapsed: 0.040 s
        Algorithm: Scipy L-BFGS-B     f(x): 0.024637062     Elapsed: 0.014 s
        Algorithm: Scipy DA           f(x): 0.019697357     Elapsed: 0.361 s

Function: ackley
        Algorithm: DE                 f(x): 2.4158131e-05   Elapsed: 0.017 s
        Algorithm: ABC                f(x): 0.0017400868    Elapsed: 0.017 s
        Algorithm: LSHADE             f(x): 0.0001666456    Elapsed: 0.028 s
        Algorithm: LSHADE_cnEpSin     f(x): 9.7505205e-06   Elapsed: 0.022 s
        Algorithm: JADE               f(x): 8.8892138e-10   Elapsed: 0.024 s
        Algorithm: jSO                f(x): 1.094312e-05    Elapsed: 0.031 s
        Algorithm: j2020              f(x): 1.3658807e-10   Elapsed: 0.218 s
        Algorithm: LSRTDE             f(x): 5.2449461e-06   Elapsed: 0.018 s
        Algorithm: NLSHADE_RSP        f(x): 3.4322147e-05   Elapsed: 0.026 s
        Algorithm: ARRDE              f(x): 5.8943961e-12   Elapsed: 0.031 s
        Algorithm: GWO_DE             f(x): 0.0033328706    Elapsed: 0.018 s
        Algorithm: NelderMead         f(x): 9.0738777       Elapsed: 0.032 s
        Algorithm: DA                 f(x): 9.2588487e-08   Elapsed: 0.104 s
        Algorithm: L_BFGS_B           f(x): 9.4529928       Elapsed: 0.001 s
        Algorithm: PSO                f(x): 5.102173e-08    Elapsed: 0.016 s
        Algorithm: DMSPSO             f(x): 1.3402275e-08   Elapsed: 0.016 s
        Algorithm: SPSO2011           f(x): 8.8838955e-05   Elapsed: 0.019 s
        Algorithm: CMAES              f(x): 6.6835426e-13   Elapsed: 0.019 s
        Algorithm: BIPOP_aCMAES       f(x): 5.9202865e-11   Elapsed: 0.016 s
        Algorithm: Scipy Nelder-Mead  f(x): 12.719749       Elapsed: 0.028 s
        Algorithm: Scipy L-BFGS-B     f(x): 12.719749       Elapsed: 0.004 s
        Algorithm: Scipy DA           f(x): 1.8047509e-08   Elapsed: 0.384 s

Function: zakharov
        Algorithm: DE                 f(x): 0.0050356294    Elapsed: 0.018 s
        Algorithm: ABC                f(x): 16.031338       Elapsed: 0.017 s
        Algorithm: LSHADE             f(x): 7.2962653e-06   Elapsed: 0.028 s
        Algorithm: LSHADE_cnEpSin     f(x): 1.5206326e-10   Elapsed: 0.021 s
        Algorithm: JADE               f(x): 5.1068813e-10   Elapsed: 0.026 s
        Algorithm: jSO                f(x): 5.8762452e-06   Elapsed: 0.030 s
        Algorithm: j2020              f(x): 0.087694588     Elapsed: 0.233 s
        Algorithm: LSRTDE             f(x): 6.1099831e-09   Elapsed: 0.019 s
        Algorithm: NLSHADE_RSP        f(x): 0.0057944557    Elapsed: 0.023 s
        Algorithm: ARRDE              f(x): 9.8684862e-14   Elapsed: 0.031 s
        Algorithm: GWO_DE             f(x): 0.0066427977    Elapsed: 0.018 s
        Algorithm: NelderMead         f(x): 9.5208937e-30   Elapsed: 0.072 s
        Algorithm: DA                 f(x): 3.5494939e-13   Elapsed: 0.175 s
        Algorithm: L_BFGS_B           f(x): 6.7711304e-15   Elapsed: 0.003 s
        Algorithm: PSO                f(x): 4.9073152e-09   Elapsed: 0.016 s
        Algorithm: DMSPSO             f(x): 1.1826456e-08   Elapsed: 0.018 s
        Algorithm: SPSO2011           f(x): 0.005796406     Elapsed: 0.020 s
        Algorithm: CMAES              f(x): 2.1307953e-13   Elapsed: 0.015 s
        Algorithm: BIPOP_aCMAES       f(x): 9.4183389e-11   Elapsed: 0.011 s
        Algorithm: Scipy Nelder-Mead  f(x): 7.6416259e-09   Elapsed: 0.086 s
        Algorithm: Scipy L-BFGS-B     f(x): 7.2717586e-14   Elapsed: 0.010 s
        Algorithm: Scipy DA           f(x): 1.465953e-14    Elapsed: 0.432 s

Function: bent_cigar
        Algorithm: DE                 f(x): 26.191855       Elapsed: 0.015 s
        Algorithm: ABC                f(x): 0.046922887     Elapsed: 0.013 s
        Algorithm: LSHADE             f(x): 0.0019367317    Elapsed: 0.026 s
        Algorithm: LSHADE_cnEpSin     f(x): 1.2389598e-05   Elapsed: 0.018 s
        Algorithm: JADE               f(x): 9.7328981e-11   Elapsed: 0.020 s
        Algorithm: jSO                f(x): 5.8346178e-05   Elapsed: 0.026 s
        Algorithm: j2020              f(x): 2.4960754e-10   Elapsed: 0.112 s
        Algorithm: LSRTDE             f(x): 4.5403445e-08   Elapsed: 0.016 s
        Algorithm: NLSHADE_RSP        f(x): 0.000367709     Elapsed: 0.017 s
        Algorithm: ARRDE              f(x): 5.5363714e-17   Elapsed: 0.023 s
        Algorithm: GWO_DE             f(x): 0.45505858      Elapsed: 0.015 s
        Algorithm: NelderMead         f(x): 7.6172326e-24   Elapsed: 0.042 s
        Algorithm: DA                 f(x): 6.9255571e-09   Elapsed: 0.049 s
        Algorithm: L_BFGS_B           f(x): 9.8449067e-16   Elapsed: 0.001 s
        Algorithm: PSO                f(x): 7.7289154e-08   Elapsed: 0.012 s
        Algorithm: DMSPSO             f(x): 1.2876138e-10   Elapsed: 0.014 s
        Algorithm: SPSO2011           f(x): 5.9650724       Elapsed: 0.017 s
        Algorithm: CMAES              f(x): 8.0029119e-07   Elapsed: 0.022 s
        Algorithm: BIPOP_aCMAES       f(x): 9.6219973e-11   Elapsed: 0.015 s
        Algorithm: Scipy Nelder-Mead  f(x): 98.947303       Elapsed: 0.030 s
        Algorithm: Scipy L-BFGS-B     f(x): 2.0992475e-10   Elapsed: 0.013 s
        Algorithm: Scipy DA           f(x): 2.2982927e-10   Elapsed: 0.293 s

Function: levy
        Algorithm: DE                 f(x): 2.2725093       Elapsed: 0.020 s
        Algorithm: ABC                f(x): 4.5570952e-07   Elapsed: 0.020 s
        Algorithm: LSHADE             f(x): 1.0829658e-08   Elapsed: 0.030 s
        Algorithm: LSHADE_cnEpSin     f(x): 3.5374864e-12   Elapsed: 0.024 s
        Algorithm: JADE               f(x): 7.3493567e-16   Elapsed: 0.028 s
        Algorithm: jSO                f(x): 1.1177129e-09   Elapsed: 0.032 s
        Algorithm: j2020              f(x): 0.089528264     Elapsed: 0.280 s
        Algorithm: LSRTDE             f(x): 3.2525454e-13   Elapsed: 0.021 s
        Algorithm: NLSHADE_RSP        f(x): 7.7868421e-09   Elapsed: 0.025 s
        Algorithm: ARRDE              f(x): 2.6161962e-22   Elapsed: 0.034 s
        Algorithm: GWO_DE             f(x): 5.2462578e-06   Elapsed: 0.021 s
        Algorithm: NelderMead         f(x): 2.3300009       Elapsed: 0.075 s
        Algorithm: DA                 f(x): 4.5034896e-15   Elapsed: 0.216 s
        Algorithm: L_BFGS_B           f(x): 0.1790565       Elapsed: 0.002 s
        Algorithm: PSO                f(x): 5.9713608e-16   Elapsed: 0.018 s
        Algorithm: DMSPSO             f(x): 1.5690238e-14   Elapsed: 0.019 s
        Algorithm: SPSO2011           f(x): 5.5242815e-07   Elapsed: 0.022 s
        Algorithm: CMAES              f(x): 3.0082245e-13   Elapsed: 0.013 s
        Algorithm: BIPOP_aCMAES       f(x): 7.6630845e-11   Elapsed: 0.010 s
        Algorithm: Scipy Nelder-Mead  f(x): 10.612364       Elapsed: 0.089 s
        Algorithm: Scipy L-BFGS-B     f(x): 5.6358232       Elapsed: 0.022 s
        Algorithm: Scipy DA           f(x): 1.5327518e-12   Elapsed: 0.501 s

Function: discus
        Algorithm: DE                 f(x): 6.5433889e-17   Elapsed: 0.014 s
        Algorithm: ABC                f(x): 8.5312468e-05   Elapsed: 0.012 s
        Algorithm: LSHADE             f(x): 3.4177328e-07   Elapsed: 0.025 s
        Algorithm: LSHADE_cnEpSin     f(x): 5.5745866e-11   Elapsed: 0.018 s
        Algorithm: JADE               f(x): 3.5753523e-16   Elapsed: 0.020 s
        Algorithm: jSO                f(x): 5.8742102e-09   Elapsed: 0.027 s
        Algorithm: j2020              f(x): 9.1398502e-13   Elapsed: 0.111 s
        Algorithm: LSRTDE             f(x): 4.2485466e-13   Elapsed: 0.016 s
        Algorithm: NLSHADE_RSP        f(x): 5.5939541e-11   Elapsed: 0.016 s
        Algorithm: ARRDE              f(x): 1.9951317e-21   Elapsed: 0.024 s
        Algorithm: GWO_DE             f(x): 4.7217992e-05   Elapsed: 0.015 s
        Algorithm: NelderMead         f(x): 2.5838254e-24   Elapsed: 0.112 s
        Algorithm: DA                 f(x): 4.1855874e-13   Elapsed: 0.050 s
        Algorithm: L_BFGS_B           f(x): 3.6369399e-13   Elapsed: 0.002 s
        Algorithm: PSO                f(x): 2.0870329e-12   Elapsed: 0.012 s
        Algorithm: DMSPSO             f(x): 9.7306774e-14   Elapsed: 0.013 s
        Algorithm: SPSO2011           f(x): 102.02634       Elapsed: 0.016 s
        Algorithm: CMAES              f(x): 1.904148e-13    Elapsed: 0.016 s
        Algorithm: BIPOP_aCMAES       f(x): 9.214248e-11    Elapsed: 0.012 s
        Algorithm: Scipy Nelder-Mead  f(x): 7.8818509e-09   Elapsed: 0.114 s
        Algorithm: Scipy L-BFGS-B     f(x): 7.8454908e-12   Elapsed: 0.010 s
        Algorithm: Scipy DA           f(x): 1.5357412e-07   Elapsed: 0.305 s

Function: drop_wave
        Algorithm: DE                 f(x): -1              Elapsed: 0.012 s
        Algorithm: ABC                f(x): -0.99400969     Elapsed: 0.030 s
        Algorithm: LSHADE             f(x): -0.99997043     Elapsed: 0.043 s
        Algorithm: LSHADE_cnEpSin     f(x): -1              Elapsed: 0.036 s
        Algorithm: JADE               f(x): -0.99999995     Elapsed: 0.038 s
        Algorithm: jSO                f(x): -1              Elapsed: 0.044 s
        Algorithm: j2020              f(x): -1              Elapsed: 0.086 s
        Algorithm: LSRTDE             f(x): -1              Elapsed: 0.025 s
        Algorithm: NLSHADE_RSP        f(x): -1              Elapsed: 0.033 s
        Algorithm: ARRDE              f(x): -1              Elapsed: 0.041 s
        Algorithm: GWO_DE             f(x): -1              Elapsed: 0.035 s
        Algorithm: NelderMead         f(x): -1              Elapsed: 0.009 s
        Algorithm: DA                 f(x): -0.93624533     Elapsed: 0.045 s
        Algorithm: L_BFGS_B           f(x): -0.93624533     Elapsed: 0.001 s
        Algorithm: PSO                f(x): -1              Elapsed: 0.030 s
        Algorithm: DMSPSO             f(x): -1              Elapsed: 0.031 s
        Algorithm: SPSO2011           f(x): -1              Elapsed: 0.034 s
        Algorithm: CMAES              f(x): -0.93709275     Elapsed: 0.036 s
        Algorithm: BIPOP_aCMAES       f(x): -0.32690614     Elapsed: 0.000 s
        Algorithm: Scipy Nelder-Mead  f(x): -0.053939199    Elapsed: 0.011 s
        Algorithm: Scipy L-BFGS-B     f(x): -0.060920875    Elapsed: 0.002 s
        Algorithm: Scipy DA           f(x): -0.93624533     Elapsed: 0.282 s

Function: goldstein_price
        Algorithm: DE                 f(x): 3               Elapsed: 0.016 s
        Algorithm: ABC                f(x): 8.4987029       Elapsed: 0.027 s
        Algorithm: LSHADE             f(x): 3               Elapsed: 0.042 s
        Algorithm: LSHADE_cnEpSin     f(x): 3               Elapsed: 0.033 s
        Algorithm: JADE               f(x): 3               Elapsed: 0.035 s
        Algorithm: jSO                f(x): 3               Elapsed: 0.040 s
        Algorithm: j2020              f(x): 3               Elapsed: 0.083 s
        Algorithm: LSRTDE             f(x): 3               Elapsed: 0.025 s
        Algorithm: NLSHADE_RSP        f(x): 3               Elapsed: 0.028 s
        Algorithm: ARRDE              f(x): 3               Elapsed: 0.038 s
        Algorithm: GWO_DE             f(x): 3               Elapsed: 0.031 s
        Algorithm: NelderMead         f(x): 3               Elapsed: 0.009 s
        Algorithm: DA                 f(x): 3               Elapsed: 0.062 s
        Algorithm: L_BFGS_B           f(x): 3               Elapsed: 0.002 s
        Algorithm: PSO                f(x): 3               Elapsed: 0.031 s
        Algorithm: DMSPSO             f(x): 3               Elapsed: 0.028 s
        Algorithm: SPSO2011           f(x): 3.0000028       Elapsed: 0.031 s
        Algorithm: CMAES              f(x): 3               Elapsed: 0.034 s
        Algorithm: BIPOP_aCMAES       f(x): 3               Elapsed: 0.044 s
        Algorithm: Scipy Nelder-Mead  f(x): 84              Elapsed: 0.015 s
        Algorithm: Scipy L-BFGS-B     f(x): 3               Elapsed: 0.006 s
        Algorithm: Scipy DA           f(x): 3               Elapsed: 0.283 s

Function: exponential
        Algorithm: DE                 f(x): -1              Elapsed: 0.012 s
        Algorithm: ABC                f(x): -0.99999972     Elapsed: 0.013 s
        Algorithm: LSHADE             f(x): -0.99999999     Elapsed: 0.026 s
        Algorithm: LSHADE_cnEpSin     f(x): -1              Elapsed: 0.021 s
        Algorithm: JADE               f(x): -1              Elapsed: 0.020 s
        Algorithm: jSO                f(x): -1              Elapsed: 0.028 s
        Algorithm: j2020              f(x): -1              Elapsed: 0.115 s
        Algorithm: LSRTDE             f(x): -1              Elapsed: 0.014 s
        Algorithm: NLSHADE_RSP        f(x): -1              Elapsed: 0.017 s
        Algorithm: ARRDE              f(x): -1              Elapsed: 0.024 s
        Algorithm: GWO_DE             f(x): -0.99999861     Elapsed: 0.015 s
        Algorithm: NelderMead         f(x): -1              Elapsed: 0.021 s
        Algorithm: DA                 f(x): -6.4343732e-10  Elapsed: 0.107 s
        Algorithm: L_BFGS_B           f(x): -1.609051e-22   Elapsed: 0.000 s
        Algorithm: PSO                f(x): -1              Elapsed: 0.013 s
        Algorithm: DMSPSO             f(x): -1              Elapsed: 0.015 s
        Algorithm: SPSO2011           f(x): -1              Elapsed: 0.017 s
        Algorithm: CMAES              f(x): -8.2953178e-25  Elapsed: 0.000 s
        Algorithm: BIPOP_aCMAES       f(x): -4.7836671e-18  Elapsed: 0.000 s
        Algorithm: Scipy Nelder-Mead  f(x): -1              Elapsed: 0.034 s
        Algorithm: Scipy L-BFGS-B     f(x): -5.2446221e-54  Elapsed: 0.001 s
        Algorithm: Scipy DA           f(x): -8.4503699e-12  Elapsed: 0.325 s

Function: quartic
        Algorithm: DE                 f(x): 0.009943409     Elapsed: 0.021 s
        Algorithm: ABC                f(x): 0.054496823     Elapsed: 0.019 s
        Algorithm: LSHADE             f(x): 0.0017695069    Elapsed: 0.032 s
        Algorithm: LSHADE_cnEpSin     f(x): 0.0022572815    Elapsed: 0.026 s
        Algorithm: JADE               f(x): 0.0065914268    Elapsed: 0.026 s
        Algorithm: jSO                f(x): 0.0055610006    Elapsed: 0.041 s
        Algorithm: j2020              f(x): 0.0031824399    Elapsed: 0.177 s
        Algorithm: LSRTDE             f(x): 0.021650487     Elapsed: 0.022 s
        Algorithm: NLSHADE_RSP        f(x): 0.0050619586    Elapsed: 0.025 s
        Algorithm: ARRDE              f(x): 0.0087228958    Elapsed: 0.032 s
        Algorithm: GWO_DE             f(x): 0.0031042237    Elapsed: 0.022 s
        Algorithm: NelderMead         f(x): 3.2231466       Elapsed: 0.104 s
        Algorithm: DA                 f(x): 0.0022227683    Elapsed: 0.061 s
        Algorithm: L_BFGS_B           f(x): 0.017609036     Elapsed: 0.008 s
        Algorithm: PSO                f(x): 0.0075577947    Elapsed: 0.017 s
        Algorithm: DMSPSO             f(x): 0.0054908702    Elapsed: 0.018 s
        Algorithm: SPSO2011           f(x): 0.010998981     Elapsed: 0.023 s
        Algorithm: CMAES              f(x): 0.0048703297    Elapsed: 0.011 s
        Algorithm: BIPOP_aCMAES       f(x): 0.0061883551    Elapsed: 0.008 s
        Algorithm: Scipy Nelder-Mead  f(x): 2.7828721       Elapsed: 0.233 s
        Algorithm: Scipy L-BFGS-B     f(x): 50784.288       Elapsed: 0.009 s
        Algorithm: Scipy DA           f(x): 0.20264968      Elapsed: 0.309 s

Function: hybrid_composition1
        Algorithm: DE                 f(x): 46.013054       Elapsed: 0.019 s
        Algorithm: ABC                f(x): 38.463758       Elapsed: 0.020 s
        Algorithm: LSHADE             f(x): 8.9683166       Elapsed: 0.029 s
        Algorithm: LSHADE_cnEpSin     f(x): 8.9683085       Elapsed: 0.024 s
        Algorithm: JADE               f(x): 8.9683084       Elapsed: 0.026 s
        Algorithm: jSO                f(x): 8.9683085       Elapsed: 0.032 s
        Algorithm: j2020              f(x): 99.70699        Elapsed: 0.238 s
        Algorithm: LSRTDE             f(x): 8.9683084       Elapsed: 0.020 s
        Algorithm: NLSHADE_RSP        f(x): 8.9683102       Elapsed: 0.025 s
        Algorithm: ARRDE              f(x): 8.9683084       Elapsed: 0.034 s
        Algorithm: GWO_DE             f(x): 8.9729914       Elapsed: 0.020 s
        Algorithm: NelderMead         f(x): 8.9683084       Elapsed: 0.049 s
        Algorithm: DA                 f(x): 47.137176       Elapsed: 0.173 s
        Algorithm: L_BFGS_B           f(x): 129.896         Elapsed: 0.002 s
        Algorithm: PSO                f(x): 8.9683084       Elapsed: 0.017 s
        Algorithm: DMSPSO             f(x): 8.9683084       Elapsed: 0.021 s
        Algorithm: SPSO2011           f(x): 8.9683126       Elapsed: 0.021 s
        Algorithm: CMAES              f(x): 8.9683084       Elapsed: 0.028 s
        Algorithm: BIPOP_aCMAES       f(x): 8.9683084       Elapsed: 0.050 s
        Algorithm: Scipy Nelder-Mead  f(x): 81.481178       Elapsed: 0.057 s
        Algorithm: Scipy L-BFGS-B     f(x): 49.451818       Elapsed: 0.011 s
        Algorithm: Scipy DA           f(x): 8.9683084       Elapsed: 0.482 s

Function: hybrid_composition2
        Algorithm: DE                 f(x): 1.938007e-05    Elapsed: 0.024 s
        Algorithm: ABC                f(x): 0.0039226331    Elapsed: 0.026 s
        Algorithm: LSHADE             f(x): 0.00032435022   Elapsed: 0.035 s
        Algorithm: LSHADE_cnEpSin     f(x): 1.5269293e-05   Elapsed: 0.029 s
        Algorithm: JADE               f(x): 3.0408034e-08   Elapsed: 0.033 s
        Algorithm: jSO                f(x): 8.890085e-05    Elapsed: 0.037 s
        Algorithm: j2020              f(x): 1.0230618e-11   Elapsed: 0.419 s
        Algorithm: LSRTDE             f(x): 4.3133943e-06   Elapsed: 0.027 s
        Algorithm: NLSHADE_RSP        f(x): 2.5255503e-05   Elapsed: 0.033 s
        Algorithm: ARRDE              f(x): 1.6645973e-13   Elapsed: 0.044 s
        Algorithm: GWO_DE             f(x): 0.0060479569    Elapsed: 0.024 s
        Algorithm: NelderMead         f(x): 2.1270735       Elapsed: 0.145 s
        Algorithm: DA                 f(x): 2.4179538e-07   Elapsed: 0.256 s
        Algorithm: L_BFGS_B           f(x): 2.1694175e-08   Elapsed: 0.012 s
        Algorithm: PSO                f(x): 2.8875353e-07   Elapsed: 0.023 s
        Algorithm: DMSPSO             f(x): 2.0066391e-07   Elapsed: 0.023 s
        Algorithm: SPSO2011           f(x): 0.00062779798   Elapsed: 0.025 s
        Algorithm: CMAES              f(x): 5.7029468e-13   Elapsed: 0.031 s
        Algorithm: BIPOP_aCMAES       f(x): 9.3565631e-11   Elapsed: 0.027 s
        Algorithm: Scipy Nelder-Mead  f(x): 9.7571206       Elapsed: 0.169 s
        Algorithm: Scipy L-BFGS-B     f(x): 6.6176766e-08   Elapsed: 0.093 s
        Algorithm: Scipy DA           f(x): 6.0014141e-08   Elapsed: 0.626 s

Function: hybrid_composition3
        Algorithm: DE                 f(x): 3.4767541       Elapsed: 0.033 s
        Algorithm: ABC                f(x): 53.301817       Elapsed: 0.041 s
        Algorithm: LSHADE             f(x): 1.2839623       Elapsed: 0.042 s
        Algorithm: LSHADE_cnEpSin     f(x): 1.2839526       Elapsed: 0.040 s
        Algorithm: JADE               f(x): 1.3071985       Elapsed: 0.045 s
        Algorithm: jSO                f(x): 1.2839527       Elapsed: 0.047 s
        Algorithm: j2020              f(x): 1.3412612       Elapsed: 0.553 s
        Algorithm: LSRTDE             f(x): 1.2839526       Elapsed: 0.030 s
        Algorithm: NLSHADE_RSP        f(x): 1.2919624       Elapsed: 0.044 s
        Algorithm: ARRDE              f(x): 1.2839534       Elapsed: 0.054 s
        Algorithm: GWO_DE             f(x): 1.2913111       Elapsed: 0.031 s
        Algorithm: NelderMead         f(x): 34.881183       Elapsed: 0.154 s
        Algorithm: DA                 f(x): 4.2578964       Elapsed: 0.313 s
        Algorithm: L_BFGS_B           f(x): 2.3887651       Elapsed: 0.009 s
        Algorithm: PSO                f(x): 1.2839526       Elapsed: 0.030 s
        Algorithm: DMSPSO             f(x): 1.2839526       Elapsed: 0.032 s
        Algorithm: SPSO2011           f(x): 1.3137448       Elapsed: 0.039 s
        Algorithm: CMAES              f(x): 1.2839526       Elapsed: 0.052 s
        Algorithm: BIPOP_aCMAES       f(x): 1.2839526       Elapsed: 0.071 s
        Algorithm: Scipy Nelder-Mead  f(x): 95.146651       Elapsed: 0.367 s
        Algorithm: Scipy L-BFGS-B     f(x): 17.427019       Elapsed: 0.060 s
        Algorithm: Scipy DA           f(x): 90.688619       Elapsed: 0.777 s

Function: happy_cat
        Algorithm: DE                 f(x): 0.23591693      Elapsed: 0.017 s
        Algorithm: ABC                f(x): 0.15177649      Elapsed: 0.017 s
        Algorithm: LSHADE             f(x): 0.10854896      Elapsed: 0.027 s
        Algorithm: LSHADE_cnEpSin     f(x): 0.055524206     Elapsed: 0.085 s
        Algorithm: JADE               f(x): 0.092597895     Elapsed: 0.025 s
        Algorithm: jSO                f(x): 0.076913426     Elapsed: 0.030 s
        Algorithm: j2020              f(x): 0.19970891      Elapsed: 0.212 s
        Algorithm: LSRTDE             f(x): 0.068197151     Elapsed: 0.017 s
        Algorithm: NLSHADE_RSP        f(x): 0.15832575      Elapsed: 0.021 s
        Algorithm: ARRDE              f(x): 0.074841347     Elapsed: 0.030 s
        Algorithm: GWO_DE             f(x): 0.038752403     Elapsed: 0.017 s
        Algorithm: NelderMead         f(x): 0.67618088      Elapsed: 0.040 s
        Algorithm: DA                 f(x): 0.33583457      Elapsed: 0.141 s
        Algorithm: L_BFGS_B           f(x): 0.31691389      Elapsed: 0.010 s
        Algorithm: PSO                f(x): 0.090518555     Elapsed: 0.016 s
        Algorithm: DMSPSO             f(x): 0.096716547     Elapsed: 0.017 s
        Algorithm: SPSO2011           f(x): 0.067817495     Elapsed: 0.020 s
        Algorithm: CMAES              f(x): 0.076208409     Elapsed: 0.025 s
        Algorithm: BIPOP_aCMAES       f(x): 0.079961817     Elapsed: 0.043 s
        Algorithm: Scipy Nelder-Mead  f(x): 1.4407279       Elapsed: 0.039 s
        Algorithm: Scipy L-BFGS-B     f(x): 0.005875464     Elapsed: 0.034 s
        Algorithm: Scipy DA           f(x): 0.16471355      Elapsed: 0.400 s

Function: michalewics
        Algorithm: DE                 f(x): -8.5815331      Elapsed: 0.024 s
        Algorithm: ABC                f(x): -8.4621134      Elapsed: 0.022 s
        Algorithm: LSHADE             f(x): -8.9894813      Elapsed: 0.034 s
        Algorithm: LSHADE_cnEpSin     f(x): -8.5499938      Elapsed: 0.027 s
        Algorithm: JADE               f(x): -9.2283196      Elapsed: 0.029 s
        Algorithm: jSO                f(x): -5.7529628      Elapsed: 0.037 s
        Algorithm: j2020              f(x): -9.1168324      Elapsed: 0.169 s
        Algorithm: LSRTDE             f(x): -8.0371607      Elapsed: 0.024 s
        Algorithm: NLSHADE_RSP        f(x): -7.9501799      Elapsed: 0.026 s
        Algorithm: ARRDE              f(x): -9.6741515      Elapsed: 0.035 s
        Algorithm: GWO_DE             f(x): -4.6689961      Elapsed: 0.026 s
        Algorithm: NelderMead         f(x): -3.6164748      Elapsed: 0.135 s
        Algorithm: DA                 f(x): -9.7854984      Elapsed: 0.083 s
        Algorithm: L_BFGS_B           f(x): -2.6919883      Elapsed: 0.006 s
        Algorithm: PSO                f(x): -8.1938975      Elapsed: 0.020 s
        Algorithm: DMSPSO             f(x): -4.5521755      Elapsed: 0.021 s
        Algorithm: SPSO2011           f(x): -4.9307636      Elapsed: 0.025 s
        Algorithm: CMAES              f(x): -8.0447463      Elapsed: 0.030 s
        Algorithm: BIPOP_aCMAES       f(x): -1.7133756      Elapsed: 0.000 s
        Algorithm: Scipy Nelder-Mead  f(x): -4.2489914      Elapsed: 0.054 s
        Algorithm: Scipy L-BFGS-B     f(x): -3.2901102      Elapsed: 0.021 s
        Algorithm: Scipy DA           f(x): -9.7935582      Elapsed: 0.349 s

Function: scaffer6
        Algorithm: DE                 f(x): 0.25249219      Elapsed: 0.192 s
        Algorithm: ABC                f(x): 0.18213552      Elapsed: 0.200 s
        Algorithm: LSHADE             f(x): 0.36538531      Elapsed: 0.207 s
        Algorithm: LSHADE_cnEpSin     f(x): 0.46483694      Elapsed: 0.199 s
        Algorithm: JADE               f(x): 0.15600834      Elapsed: 0.202 s
        Algorithm: jSO                f(x): 1.0107057       Elapsed: 0.206 s
        Algorithm: j2020              f(x): 0.44059681      Elapsed: 0.256 s
        Algorithm: LSRTDE             f(x): 0.83658298      Elapsed: 0.189 s
        Algorithm: NLSHADE_RSP        f(x): 0.19632212      Elapsed: 0.203 s
        Algorithm: ARRDE              f(x): 0.14238011      Elapsed: 0.211 s
        Algorithm: GWO_DE             f(x): 0.17940201      Elapsed: 0.203 s
        Algorithm: NelderMead         f(x): 0.18775994      Elapsed: 0.121 s
        Algorithm: DA                 f(x): 0.087443189     Elapsed: 0.241 s
        Algorithm: L_BFGS_B           f(x): 0.18775994      Elapsed: 0.023 s
        Algorithm: PSO                f(x): 0.11495147      Elapsed: 0.198 s
        Algorithm: DMSPSO             f(x): 0.32037117      Elapsed: 0.198 s
        Algorithm: SPSO2011           f(x): 0.45037912      Elapsed: 0.198 s
        Algorithm: CMAES              f(x): 0.42270187      Elapsed: 0.203 s
        Algorithm: BIPOP_aCMAES       f(x): 0.71153887      Elapsed: 0.215 s
        Algorithm: Scipy Nelder-Mead  f(x): 0.38943872      Elapsed: 0.065 s
        Algorithm: Scipy L-BFGS-B     f(x): 0.38943873      Elapsed: 0.020 s
        Algorithm: Scipy DA           f(x): 0.087443196     Elapsed: 0.420 s

Function: hcf
        Algorithm: DE                 f(x): 0.016643025     Elapsed: 0.015 s
        Algorithm: ABC                f(x): 0.003200968     Elapsed: 0.013 s
        Algorithm: LSHADE             f(x): 0.00054574173   Elapsed: 0.025 s
        Algorithm: LSHADE_cnEpSin     f(x): 2.6345598e-05   Elapsed: 0.021 s
        Algorithm: JADE               f(x): 1.3453768e-09   Elapsed: 0.023 s
        Algorithm: jSO                f(x): 1.5143254e-05   Elapsed: 0.029 s
        Algorithm: j2020              f(x): 3.4540466e-08   Elapsed: 0.156 s
        Algorithm: LSRTDE             f(x): 1.5193954e-06   Elapsed: 0.015 s
        Algorithm: NLSHADE_RSP        f(x): 6.0449993e-06   Elapsed: 0.019 s
        Algorithm: ARRDE              f(x): 2.1678124e-13   Elapsed: 0.025 s
        Algorithm: GWO_DE             f(x): 0.0042892428    Elapsed: 0.015 s
        Algorithm: NelderMead         f(x): 2.358758        Elapsed: 0.137 s
        Algorithm: DA                 f(x): 1.3036637e-07   Elapsed: 0.082 s
        Algorithm: L_BFGS_B           f(x): 5.4877386e-09   Elapsed: 0.006 s
        Algorithm: PSO                f(x): 3.6716305e-08   Elapsed: 0.013 s
        Algorithm: DMSPSO             f(x): 6.7345107e-08   Elapsed: 0.014 s
        Algorithm: SPSO2011           f(x): 0.00076268558   Elapsed: 0.016 s
        Algorithm: CMAES              f(x): 6.6431452e-13   Elapsed: 0.016 s
        Algorithm: BIPOP_aCMAES       f(x): 6.2473238e-11   Elapsed: 0.014 s
        Algorithm: Scipy Nelder-Mead  f(x): 9.2898681       Elapsed: 0.104 s
        Algorithm: Scipy L-BFGS-B     f(x): 3.9901546e-08   Elapsed: 0.038 s
        Algorithm: Scipy DA           f(x): 6.6041994e-08   Elapsed: 0.316 s

Function: grie_rosen
        Algorithm: DE                 f(x): 9.0927885       Elapsed: 0.016 s
        Algorithm: ABC                f(x): 4.9093932       Elapsed: 0.015 s
        Algorithm: LSHADE             f(x): 4.285257        Elapsed: 0.025 s
        Algorithm: LSHADE_cnEpSin     f(x): 1.9765677       Elapsed: 0.029 s
        Algorithm: JADE               f(x): 5.1477162       Elapsed: 0.024 s
        Algorithm: jSO                f(x): 5.6576765       Elapsed: 0.029 s
        Algorithm: j2020              f(x): 1.0790723       Elapsed: 0.149 s
        Algorithm: LSRTDE             f(x): 5.9652161       Elapsed: 0.017 s
        Algorithm: NLSHADE_RSP        f(x): 3.8337539       Elapsed: 0.020 s
        Algorithm: ARRDE              f(x): 4.0831197       Elapsed: 0.026 s
        Algorithm: GWO_DE             f(x): 7.7043076       Elapsed: 0.017 s
        Algorithm: NelderMead         f(x): 1               Elapsed: 0.063 s
        Algorithm: DA                 f(x): 1               Elapsed: 0.102 s
        Algorithm: L_BFGS_B           f(x): 1               Elapsed: 0.005 s
        Algorithm: PSO                f(x): 4.5445269       Elapsed: 0.014 s
        Algorithm: DMSPSO             f(x): 8.014341        Elapsed: 0.015 s
        Algorithm: SPSO2011           f(x): 7.951165        Elapsed: 0.017 s
        Algorithm: CMAES              f(x): 1.0465555       Elapsed: 0.023 s
        Algorithm: BIPOP_aCMAES       f(x): 1               Elapsed: 0.024 s
        Algorithm: Scipy Nelder-Mead  f(x): 1               Elapsed: 0.067 s
        Algorithm: Scipy L-BFGS-B     f(x): 1               Elapsed: 0.017 s
        Algorithm: Scipy DA           f(x): 1               Elapsed: 0.348 s

Function: dixon_price
        Algorithm: DE                 f(x): 0.66666667      Elapsed: 0.016 s
        Algorithm: ABC                f(x): 0.70458522      Elapsed: 0.018 s
        Algorithm: LSHADE             f(x): 0.66670683      Elapsed: 0.030 s
        Algorithm: LSHADE_cnEpSin     f(x): 0.66666667      Elapsed: 0.021 s
        Algorithm: JADE               f(x): 0.66666673      Elapsed: 0.023 s
        Algorithm: jSO                f(x): 0.66666667      Elapsed: 0.028 s
        Algorithm: j2020              f(x): 0.063672199     Elapsed: 0.159 s
        Algorithm: LSRTDE             f(x): 0.66666681      Elapsed: 0.017 s
        Algorithm: NLSHADE_RSP        f(x): 0.66666667      Elapsed: 0.019 s
        Algorithm: ARRDE              f(x): 0.066966468     Elapsed: 0.027 s
        Algorithm: GWO_DE             f(x): 0.66738397      Elapsed: 0.017 s
        Algorithm: NelderMead         f(x): 0.66666667      Elapsed: 0.122 s
        Algorithm: DA                 f(x): 0.66666667      Elapsed: 0.166 s
        Algorithm: L_BFGS_B           f(x): 0.66666667      Elapsed: 0.003 s
        Algorithm: PSO                f(x): 0.66666667      Elapsed: 0.019 s
        Algorithm: DMSPSO             f(x): 0.66666667      Elapsed: 0.016 s
        Algorithm: SPSO2011           f(x): 0.66701749      Elapsed: 0.018 s
        Algorithm: CMAES              f(x): 0.66666667      Elapsed: 0.016 s
        Algorithm: BIPOP_aCMAES       f(x): 0.66666667      Elapsed: 0.015 s
        Algorithm: Scipy Nelder-Mead  f(x): 0.66666667      Elapsed: 0.083 s
        Algorithm: Scipy L-BFGS-B     f(x): 0.66666667      Elapsed: 0.015 s
        Algorithm: Scipy DA           f(x): 0.66666667      Elapsed: 0.391 s

Function: eosom
        Algorithm: DE                 f(x): -0.0090056781   Elapsed: 0.027 s
        Algorithm: ABC                f(x): -0.0090054897   Elapsed: 0.038 s
        Algorithm: LSHADE             f(x): -0.0090056781   Elapsed: 0.053 s
        Algorithm: LSHADE_cnEpSin     f(x): -0.0090056781   Elapsed: 0.042 s
        Algorithm: JADE               f(x): -0.0090056781   Elapsed: 0.033 s
        Algorithm: jSO                f(x): -0.0090056781   Elapsed: 0.051 s
        Algorithm: j2020              f(x): -0.0090056781   Elapsed: 0.091 s
        Algorithm: LSRTDE             f(x): -0.0090056781   Elapsed: 0.026 s
        Algorithm: NLSHADE_RSP        f(x): -0.0090056781   Elapsed: 0.035 s
        Algorithm: ARRDE              f(x): -0.0090056781   Elapsed: 0.045 s
        Algorithm: GWO_DE             f(x): -0.0090056781   Elapsed: 0.038 s
        Algorithm: NelderMead         f(x): -7.8737549e-14  Elapsed: 0.012 s
        Algorithm: DA                 f(x): -0.0090056781   Elapsed: 0.087 s
        Algorithm: L_BFGS_B           f(x): 2.8026392e-10   Elapsed: 0.000 s
        Algorithm: PSO                f(x): -0.0090056781   Elapsed: 0.034 s
        Algorithm: DMSPSO             f(x): -0.0090056781   Elapsed: 0.034 s
        Algorithm: SPSO2011           f(x): -0.0090056781   Elapsed: 0.038 s
        Algorithm: CMAES              f(x): -0.0090056781   Elapsed: 0.042 s
        Algorithm: BIPOP_aCMAES       f(x): -8.1207696e-09  Elapsed: 0.000 s
        Algorithm: Scipy Nelder-Mead  f(x): -0.0090056781   Elapsed: 0.011 s
        Algorithm: Scipy L-BFGS-B     f(x): -1.4567312e-07  Elapsed: 0.001 s
        Algorithm: Scipy DA           f(x): -0.009005677    Elapsed: 0.284 s

Function: hgbat
        Algorithm: DE                 f(x): 0.50000754      Elapsed: 0.016 s
        Algorithm: ABC                f(x): 0.51557989      Elapsed: 0.015 s
        Algorithm: LSHADE             f(x): 0.50010291      Elapsed: 0.026 s
        Algorithm: LSHADE_cnEpSin     f(x): 0.50000301      Elapsed: 0.022 s
        Algorithm: JADE               f(x): 0.50000001      Elapsed: 0.024 s
        Algorithm: jSO                f(x): 0.50001693      Elapsed: 0.030 s
        Algorithm: j2020              f(x): 0.50000009      Elapsed: 0.208 s
        Algorithm: LSRTDE             f(x): 0.50000148      Elapsed: 0.017 s
        Algorithm: NLSHADE_RSP        f(x): 0.5000157       Elapsed: 0.021 s
        Algorithm: ARRDE              f(x): 0.50000217      Elapsed: 0.028 s
        Algorithm: GWO_DE             f(x): 0.50186633      Elapsed: 0.020 s
        Algorithm: NelderMead         f(x): 0.5             Elapsed: 0.057 s
        Algorithm: DA                 f(x): 0.50000007      Elapsed: 0.113 s
        Algorithm: L_BFGS_B           f(x): 0.5000013       Elapsed: 0.003 s
        Algorithm: PSO                f(x): 0.5000001       Elapsed: 0.014 s
        Algorithm: DMSPSO             f(x): 0.50000008      Elapsed: 0.015 s
        Algorithm: SPSO2011           f(x): 0.50010615      Elapsed: 0.018 s
        Algorithm: CMAES              f(x): 0.5             Elapsed: 0.023 s
        Algorithm: BIPOP_aCMAES       f(x): 0.5             Elapsed: 0.043 s
        Algorithm: Scipy Nelder-Mead  f(x): 0.5000703       Elapsed: 0.046 s
        Algorithm: Scipy L-BFGS-B     f(x): 0.50000001      Elapsed: 0.030 s
        Algorithm: Scipy DA           f(x): 0.50000002      Elapsed: 0.387 s

Function: styblinski_tang
        Algorithm: DE                 f(x): -349.2515       Elapsed: 0.022 s
        Algorithm: ABC                f(x): -391.66154      Elapsed: 0.021 s
        Algorithm: LSHADE             f(x): -391.65991      Elapsed: 0.033 s
        Algorithm: LSHADE_cnEpSin     f(x): -391.66165      Elapsed: 0.026 s
        Algorithm: JADE               f(x): -377.52494      Elapsed: 0.030 s
        Algorithm: jSO                f(x): -391.66166      Elapsed: 0.035 s
        Algorithm: j2020              f(x): -391.66166      Elapsed: 0.156 s
        Algorithm: LSRTDE             f(x): -391.66166      Elapsed: 0.023 s
        Algorithm: NLSHADE_RSP        f(x): -391.66165      Elapsed: 0.026 s
        Algorithm: ARRDE              f(x): -391.66166      Elapsed: 0.033 s
        Algorithm: GWO_DE             f(x): -391.66157      Elapsed: 0.024 s
        Algorithm: NelderMead         f(x): -306.84134      Elapsed: 0.034 s
        Algorithm: DA                 f(x): -391.66166      Elapsed: 0.096 s
        Algorithm: L_BFGS_B           f(x): -320.97806      Elapsed: 0.001 s
        Algorithm: PSO                f(x): -363.38822      Elapsed: 0.029 s
        Algorithm: DMSPSO             f(x): -391.66166      Elapsed: 0.023 s
        Algorithm: SPSO2011           f(x): -375.97974      Elapsed: 0.024 s
        Algorithm: CMAES              f(x): -349.2515       Elapsed: 0.017 s
        Algorithm: BIPOP_aCMAES       f(x): -43.926384      Elapsed: 0.000 s
        Algorithm: Scipy Nelder-Mead  f(x): -250.29447      Elapsed: 0.050 s
        Algorithm: Scipy L-BFGS-B     f(x): -292.70462      Elapsed: 0.006 s
        Algorithm: Scipy DA           f(x): -391.66166      Elapsed: 0.337 s

Function: step
        Algorithm: DE                 f(x): 0               Elapsed: 0.014 s
        Algorithm: ABC                f(x): 0               Elapsed: 0.012 s
        Algorithm: LSHADE             f(x): 0               Elapsed: 0.024 s
        Algorithm: LSHADE_cnEpSin     f(x): 0               Elapsed: 0.017 s
        Algorithm: JADE               f(x): 0               Elapsed: 0.021 s
        Algorithm: jSO                f(x): 0               Elapsed: 0.026 s
        Algorithm: j2020              f(x): 0               Elapsed: 0.101 s
        Algorithm: LSRTDE             f(x): 0               Elapsed: 0.018 s
        Algorithm: NLSHADE_RSP        f(x): 0               Elapsed: 0.016 s
        Algorithm: ARRDE              f(x): 0               Elapsed: 0.023 s
        Algorithm: GWO_DE             f(x): 0               Elapsed: 0.015 s
        Algorithm: NelderMead         f(x): 98              Elapsed: 0.002 s
        Algorithm: DA                 f(x): 0               Elapsed: 0.092 s
        Algorithm: L_BFGS_B           f(x): 103             Elapsed: 0.000 s
        Algorithm: PSO                f(x): 0               Elapsed: 0.011 s
        Algorithm: DMSPSO             f(x): 0               Elapsed: 0.012 s
        Algorithm: SPSO2011           f(x): 0               Elapsed: 0.016 s
        Algorithm: CMAES              f(x): 0               Elapsed: 0.003 s
        Algorithm: BIPOP_aCMAES       f(x): 0               Elapsed: 0.001 s
        Algorithm: Scipy Nelder-Mead  f(x): 256             Elapsed: 0.011 s
        Algorithm: Scipy L-BFGS-B     f(x): 256             Elapsed: 0.001 s
        Algorithm: Scipy DA           f(x): 0               Elapsed: 0.297 s

Function: weierstrass
        Algorithm: DE                 f(x): 3.9136649       Elapsed: 1.006 s
        Algorithm: ABC                f(x): 2.3385699       Elapsed: 1.012 s
        Algorithm: LSHADE             f(x): 1.697586        Elapsed: 0.980 s
        Algorithm: LSHADE_cnEpSin     f(x): 2.3747279       Elapsed: 1.051 s
        Algorithm: JADE               f(x): 0.62136377      Elapsed: 1.112 s
        Algorithm: jSO                f(x): 5.4126659       Elapsed: 1.567 s
        Algorithm: j2020              f(x): 3.0273366       Elapsed: 1.165 s
        Algorithm: LSRTDE             f(x): 6.1535828       Elapsed: 0.958 s
        Algorithm: NLSHADE_RSP        f(x): 2.4954729       Elapsed: 1.008 s
        Algorithm: ARRDE              f(x): 0.79719085      Elapsed: 1.010 s
        Algorithm: GWO_DE             f(x): 8.0630304       Elapsed: 0.992 s
        Algorithm: NelderMead         f(x): 16.331325       Elapsed: 0.170 s
        Algorithm: DA                 f(x): 7.5268862       Elapsed: 0.902 s
        Algorithm: L_BFGS_B           f(x): 17.260631       Elapsed: 0.571 s
        Algorithm: PSO                f(x): 0.024844903     Elapsed: 0.907 s
        Algorithm: DMSPSO             f(x): 2.7785439       Elapsed: 0.917 s
        Algorithm: SPSO2011           f(x): 10.019956       Elapsed: 0.897 s
        Algorithm: CMAES              f(x): 0.0019573283    Elapsed: 0.914 s
        Algorithm: BIPOP_aCMAES       f(x): 10.027648       Elapsed: 0.931 s
        Algorithm: Scipy Nelder-Mead  f(x): 6.4472257       Elapsed: 0.148 s
        Algorithm: Scipy L-BFGS-B     f(x): 16.582908       Elapsed: 0.166 s
        Algorithm: Scipy DA           f(x): 3.9593389       Elapsed: 1.191 s

Function: sum_squares
        Algorithm: DE                 f(x): 2.8608641e-05   Elapsed: 0.013 s
        Algorithm: ABC                f(x): 1.7911789e-06   Elapsed: 0.012 s
        Algorithm: LSHADE             f(x): 8.4431439e-08   Elapsed: 0.026 s
        Algorithm: LSHADE_cnEpSin     f(x): 9.2480663e-11   Elapsed: 0.018 s
        Algorithm: JADE               f(x): 3.3212172e-18   Elapsed: 0.019 s
        Algorithm: jSO                f(x): 6.4938347e-10   Elapsed: 0.024 s
        Algorithm: j2020              f(x): 1.8269335e-12   Elapsed: 0.118 s
        Algorithm: LSRTDE             f(x): 1.8604918e-10   Elapsed: 0.016 s
        Algorithm: NLSHADE_RSP        f(x): 1.1120999e-10   Elapsed: 0.019 s
        Algorithm: ARRDE              f(x): 3.0589539e-24   Elapsed: 0.027 s
        Algorithm: GWO_DE             f(x): 1.9931301e-05   Elapsed: 0.022 s
        Algorithm: NelderMead         f(x): 8.310147e-30    Elapsed: 0.044 s
        Algorithm: DA                 f(x): 2.1728419e-14   Elapsed: 0.082 s
        Algorithm: L_BFGS_B           f(x): 5.0791404e-13   Elapsed: 0.001 s
        Algorithm: PSO                f(x): 2.1701935e-14   Elapsed: 0.013 s
        Algorithm: DMSPSO             f(x): 1.4260877e-14   Elapsed: 0.016 s
        Algorithm: SPSO2011           f(x): 8.9292414e-06   Elapsed: 0.016 s
        Algorithm: CMAES              f(x): 2.6773219e-13   Elapsed: 0.009 s
        Algorithm: BIPOP_aCMAES       f(x): 9.9939703e-11   Elapsed: 0.007 s
        Algorithm: Scipy Nelder-Mead  f(x): 1.6899228e-08   Elapsed: 0.033 s
        Algorithm: Scipy L-BFGS-B     f(x): 1.8569864e-11   Elapsed: 0.004 s
        Algorithm: Scipy DA           f(x): 3.4901676e-10   Elapsed: 0.305 s

Minimizing Expensive Functions with Multithreading/Multiprocessing

When the objective function is expensive to evaluate, multithreading can be used to speed up the calculation of the vectorized objective function. However, this requires that the objective function is thread-safe.

If the objective function is not thread-safe, then multiprocessing can be used instead. This approach allows parallel execution across separate processes, which avoids the potential issues with thread safety.

Example to vectorize a thread-safe function using multithreading and multiprocessing

If the function is thread-safe to call cuncurrently, then we can safely use concurrent.futures.ThreadPoolExecutor (for multithreading) or concurrent.futures.ProcessPoolExecutor (for multiproceesing) directly.

[5]:
# Function to minimize (expensive to evaluate)
def func(x):
    ret = rosenbrock(x)
    time.sleep(0.01)  # Simulate expensive computation
    return ret

# Parallel execution setup
Nthreads = 8
use_threads = True  # Toggle between ThreadPoolExecutor and ProcessPoolExecutor

if use_threads:
    executor = concurrent.futures.ThreadPoolExecutor(max_workers=Nthreads)
else:
    executor = concurrent.futures.ProcessPoolExecutor(max_workers=Nthreads)

def objective_function(X):
    return list(executor.map(func, X))  # Batch evaluation in parallel

# Optimization problem settings
dimension = 10
maxevals = 1000
x0 = [[3.0] * dimension]
bounds = [(-10, 10)] * dimension

# List of algorithms to test
algorithms = {
    "ARRDE": {"options": None},
    "L_BFGS_B": {"options": {"func_noise_ratio": 0.0, "N_points_derivative": 1}},
    "DA": {"options": None}
}

print("\nOptimization Results:")
print("=" * 100)

# Run optimizations using Minion
for algo, settings in algorithms.items():
    start_time = time.time()
    minimizer = mpy.Minimizer(
        func=objective_function,
        x0=x0,
        bounds=bounds,
        algo=algo,
        relTol=0.0,
        maxevals=maxevals,
        callback=None,
        seed=None,
        options=settings["options"]
    )
    result = minimizer.optimize()
    elapsed = time.time() - start_time

    print(f"Algo : {algo:<30} | f(x) = {result.fun:<20.8g} | Elapsed: {elapsed:.2f} sec")

# Compare with SciPy optimizers (without multithreading)
for algo, opt_func in [
    ("Scipy Dual Annealing", dual_annealing),
    ("Scipy L-BFGS-B", minimize)
]:
    start_time = time.time()
    if algo == "Scipy Dual Annealing":
        result = opt_func(func, bounds=bounds, maxfun=maxevals, no_local_search=False, x0=x0[0])
    else:
        result = opt_func(func, x0=x0[0], method="L-BFGS-B", options={"maxfun": maxevals}, bounds=bounds)

    elapsed = time.time() - start_time
    print(f"Algo : {algo:<30} | f(x) = {result.fun:<20.8g} | Elapsed: {elapsed:.2f} sec")

print("=" * 100)

# Shutdown executor gracefully
executor.shutdown()



Optimization Results:
====================================================================================================
Algo : ARRDE                          | f(x) = 112.52055            | Elapsed: 1.62 sec
Algo : L_BFGS_B                       | f(x) = 100                  | Elapsed: 1.68 sec
Algo : DA                             | f(x) = 100                  | Elapsed: 3.70 sec
Algo : Scipy Dual Annealing           | f(x) = 100                  | Elapsed: 10.34 sec
Algo : Scipy L-BFGS-B                 | f(x) = 100                  | Elapsed: 4.42 sec
====================================================================================================

The algorithms implemented in Minion (ARRDE, L-BFGS-B, and Dual Annealing) significantly outperform their SciPy counterparts in speed. This performance improvement stems from Minion’s efficient numerical derivative computation, which batches function evaluations—an approach that greatly benefits minion’s L-BFGS-B and Dual Annealing. Note that dual annealing use L-BFGS-B for local search.


Using minionpy.Thread_Parallel to vectorize non-thread-safe member function

In the previous example, we demonstrated how to minimize a thread-safe function. However, in real-world scenarios, the objective function is often a method of a class, and class methods are typically not thread-safe. In this example, we demonstrate how to minimize a non-thread-safe function using the Thread_Parallel class. This approach ensures proper parallelization even when the objective function modifies internal state, which can lead to race conditions in a multi-threaded environment.

1. Define the Class with objective_function

First, define a class that includes the objective_function. This function should accept a list of floats as input and return a single float as the output. In this example, the objective_function modifies an internal state, which makes it non-thread-safe. We will show how the minionpy Thread_Parallel class manages the parallel execution of such functions while ensuring thread isolation.

[6]:
class Objective :
    """
    This illustrate a class with a non-thread-safe self.objective_function
    """
    def __init__ (self, b) :
        self.A=None  # There is a now class member that will be modified when self.objective_function is called.
        self.b = b

    def update_A(self, x) :
        self.A = self.b*np.sin(x) #modify self.A
        time.sleep(0.05)  #simulate an expensive function

    def objective_function(self, x) :
        self.update_A(x)
        ret = np.sum(self.A*x)
        #print(x, ret)
        return ret

2. Define the Thread_Parallel object

[7]:
# Here, we vectorize `Objective.objective_function` using 8 threads, with the `b` parameter in the Objective class constructor set to `0.2`.
t_parallel = mpy.Thread_Parallel(8, Objective, 0.2)

#You can test the vectorization as follows :
X = np.random.rand(8, 8) #randomly creates 6 vectors of dimension 8
start = time.time()
res = t_parallel(X)
print("Vectorization using Thread_Parallel : \n\t", res)
print("Elapsed  : ", time.time()-start, "\n")

obj=Objective(b=0.2)
start = time.time()
res2 = [obj.objective_function(x) for x in X]
print("Calling the function sequentially : \n\t", res2)
print("Elapsed  : ", time.time()-start, "\n")

#test if res and res2 are exactly the same
print(np.array(res).all() == np.array(res2).all())
Vectorization using Thread_Parallel :
         [0.5661370676468356, 0.7775659672127234, 0.4229914027614482, 0.5303959761143511, 0.3761453211372047, 0.5522159710759306, 0.38951343396507465, 0.556718173281366]
Elapsed  :  0.05110669136047363

Calling the function sequentially :
         [0.5661370676468356, 0.7775659672127234, 0.4229914027614482, 0.5303959761143511, 0.3761453211372047, 0.5522159710759306, 0.38951343396507465, 0.556718173281366]
Elapsed  :  0.40199875831604004

True

3. Minimize using one of minionpy algorithms

[8]:
dimension = 8 #set dimension of the problem
maxevals = 1000 #number of function calls
x0 = [[3.0]*dimension] # initial guess
bounds = [(-10, 10)]*dimension
algo = "ARRDE"

now = time.time()
min = mpy.Minimizer(func=t_parallel, x0=x0, bounds=bounds, algo=algo, relTol=0.0,
                     maxevals=maxevals, callback=None, seed=None, options={"population_size": 0})
result = min.optimize()
elapsed= time.time()-now
print("Algo : ",algo, "\n\t x : ", result.x, "\n\t f(x) : ", result.fun, "\n\t Elapsed: ", elapsed, " seconds\n")
print("Test function value  : ", Objective(b=0.2).objective_function(np.asarray(result.x)))
Algo :  ARRDE
         x :  [-4.8745482242483, 4.2532696314673295, 4.636776364023326, -4.935053006852719, -4.893801687256062, 4.2541727836417795, -4.5347783796462, 5.555873294650024]
         f(x) :  -6.969264085741495
         Elapsed:  7.983117580413818  seconds

Test function value  :  -6.969264085741495

We can observe that the minimum found by the ARRDE algorithm corresponds to the correct function value. But what happens if we use ThreadPoolExecutor without considering the thread-safety of the objective_function method?

[9]:
obj = Objective(b=0.2)
executor = concurrent.futures.ThreadPoolExecutor(max_workers=8)

def vectorize_obj(X) :
    ret = list(executor.map(obj.objective_function, np.asarray(X)))
    return ret

now = time.time()
min = mpy.Minimizer(func=vectorize_obj, x0=x0, bounds=bounds, algo=algo, relTol=0.0, maxevals=maxevals, callback=None, seed=None, options=None)
result = min.optimize()
elapsed= time.time()-now
print("Algo : ",algo, "\n\t x : ", result.x, "\n\t f(x) : ", result.fun, "\n\t Elapsed: ", elapsed, " seconds\n")
print("Test function value  :", obj.objective_function(np.asarray(result.x)))
executor.shutdown(wait=True)
Algo :  ARRDE
         x :  [-4.9085261023046725, 9.855798668604562, 5.326274488405682, -9.870938023916791, -6.328512976971076, -9.748500557841409, -9.603724177180414, 9.362136235173324]
         f(x) :  -7.418963223826018
         Elapsed:  7.983393907546997  seconds

Test function value  : -4.296564752042263

We can see that the function value of the minimum is not the same as the actual function value.

Using multiprocessing for non-thread-safe functions using minionpy.Process_Parallel

If multiprocessing is preferred over multithreading—whether to bypass the Global Interpreter Lock (GIL) or to ensure clean separation of data during objective function vectorization—minionpy provides the Process_Parallel feature. It follows the same usage rules as Thread_Parallel. When using Process_Parallel, a predefined number of reusable processes are created, each with its own instance of the class object.

[10]:
p_parallel = mpy.Process_Parallel(8, Objective, 0.2)

#You can test the vectorization as follows :
start = time.time()
X = np.random.rand(8, 6) #randomly creates 6 vectors of dimension 8
res = p_parallel(X)
print("Vectorization using Process_Parallel : \n\t", res)
print("Elapsed  : ", time.time()-start, "\n")

obj=Objective(b=0.2)
start = time.time()
res2 = [obj.objective_function(x) for x in X]
print("Calling the function sequentially : \n\t", res2)
print("Elapsed  : ", time.time()-start, "\n")

#test if res and res2 are exactly the same
print(np.array(res).all() == np.array(res2).all())
Vectorization using Process_Parallel :
         [0.5304442646984987, 0.20451016023783655, 0.10655265370931162, 0.2714407459077475, 0.2980790126820181, 0.315356307197812, 0.19289203891937706, 0.440687150822349]
Elapsed  :  0.12279987335205078

Calling the function sequentially :
         [0.5304442646984987, 0.20451016023783655, 0.10655265370931162, 0.2714407459077475, 0.2980790126820181, 0.315356307197812, 0.19289203891937706, 0.440687150822349]
Elapsed  :  0.4028041362762451

True
[11]:
dimension = 8 #set dimension of the problem
maxevals = 1000 #number of function calls
x0 = [[3.0]*dimension] # initial guess
bounds = [(-10, 10)]*dimension
algo = "ARRDE"

now = time.time()
min = mpy.Minimizer(func=p_parallel, x0=x0, bounds=bounds, algo=algo, relTol=0.0,
                     maxevals=maxevals, callback=None, seed=None, options={"population_size": 0})
result = min.optimize()
elapsed= time.time()-now
print("Algo : ",algo, "\n\t x : ", result.x, "\n\t f(x) : ", result.fun, "\n\t Elapsed: ", elapsed, " seconds\n")
print("Test function value  : ", Objective(b=0.2).objective_function(np.asarray(result.x)))
Algo :  ARRDE
         x :  [-5.292044833018368, 4.166986458579692, 4.488022614476481, 5.0228088678480765, 5.23266594020464, -4.826695879758527, -1.209896518319117, 4.336840773972577]
         f(x) :  -5.877285885951624
         Elapsed:  8.18626880645752  seconds

Test function value  :  -5.877285885951624

Algorithm Comparisons Using CEC Benchmark Problems

We can compare the performance of different optimization algorithms by evaluating them on benchmark problems from the Congress on Evolutionary Computation (CEC) competition. The Minion library provides implementations of benchmark problems from the following CEC years: 2011, 2014, 2017, 2019, 2020, and 2022.

  • CEC2014 and CEC2017: These benchmarks contain 30 problems, implemented for dimensions 10, 20, 30, 50, and 100.

  • CEC2019: This set includes 10 problems with varying dimensions.

  • CEC2020: It contains 10 problems with dimensions 5, 10, 15, and 20.

  • CEC2022: This set consists of 12 problems with dimensions 10 and 20.

CEC problems typically include a variety of function types:

  • Basic functions (e.g., Rosenbrock, Rastrigin),

  • Hybrid functions (new functions constructed by combining basic functions, where each component is evaluated using a different basic function),

  • Composite functions (linear combinations of basic functions, where the coefficients are also functions of the input vector).

These functions are often shifted and rotated to introduce additional complexity.

CEC2011 consists of a set of real-world problems, idealized and simplified for the competition. It contains 22 problems of varying dimensions. Note that, for CEC2011, MATLAB must be installed on the system. An example of how to minimize CEC2011 problems can be found in examples/cec_11.py.

[12]:
import threading
import concurrent.futures

# This script minimizes CEC benchmark problems, repeated for NRuns times.

# Global results variable
results = []
results_lock = threading.Lock()

def test_optimization(func, bounds, dimension, func_name, Nmaxeval, seed):
    """Runs optimization algorithms on a given function and stores the results."""
    global results
    result = {
        "Dimensions": dimension,
        "Function": func_name
    }

    bounds_list = [bounds] * dimension
    x0 = [[0.0 for _ in range(dimension)]]

    print(f"\nRunning optimization for {func_name} (Dimension: {dimension})")
    print("=" * 60)

    for algo in algos:
        res = mpy.Minimizer(
            func, bounds_list, x0=x0, relTol=0.0, algo=algo,
            maxevals=Nmaxeval, callback=None, seed=None,
            options={
                "population_size"   : 0, #2*dimension,
                "func_noise_ratio"  :  0.0,
                "N_points_derivative": 1,
                "bound_strategy" : "none"
                }
        ).optimize()
        result[algo] = res.fun
        print(f"  {algo:<15} f(x): {res.fun:<20.8g}")

    def func_scipy(par):
        return func([par])[0]

    # SciPy Optimizers
    scipy_algorithms = [
        ("Scipy L-BFGS-B", minimize, {"x0": x0[0], "method": "L-BFGS-B", "options": {"maxfun": Nmaxeval}, "bounds": bounds_list}),
         ("Scipy Nelder-Mead", minimize, {"x0": x0[0], "method": "Nelder-Mead", "bounds": bounds_list, "options": {"maxfev": Nmaxeval, "adaptive": True}}),
        ("Scipy DA", dual_annealing, {"bounds": bounds_list, "maxfun": Nmaxeval, "no_local_search": False, "x0": x0[0]}),
    ]

    for name, func_opt, kwargs in scipy_algorithms:
        res = func_opt(func_scipy, **kwargs)
        result[name] = res.fun
        print(f"  {name:<15} f(x): {res.fun:<20.8g}")

    with results_lock:
        results.append(result)

    print("-" * 60)

def run_test_optimization(j, dim, year=2017, seed=None):
    """Runs the optimization for a specific function and CEC benchmark year."""
    cec_func_classes = {
        2014: mpy.CEC2014Functions,
        2017: mpy.CEC2017Functions,
        2019: mpy.CEC2019Functions,
        2020: mpy.CEC2020Functions,
        2022: mpy.CEC2022Functions
    }

    if year not in cec_func_classes:
        raise Exception("Unknown CEC year.")

    cec_func = cec_func_classes[year](function_number=j, dimension=dim)
    test_optimization(cec_func, (-100, 100), dim, f"func_{j}", Nmaxeval, seed)

# List of algorithms to be tested
algos = [
      "DE", "ABC", "LSHADE", "LSHADE_cnEpSin", "JADE", "jSO", "j2020", "LSRTDE", "NLSHADE_RSP",
        "ARRDE", "GWO_DE", "NelderMead", "DA", "L_BFGS_B", "PSO", "DMSPSO", "SPSO2011", "CMAES", "BIPOP_aCMAES"
]

Nmaxeval = 200000  # Maximum number of function evaluations
dimension = 20
NRuns = 1  # Number of repetitions
year = 2022  # CEC benchmark year

# Function numbers for each CEC year
func_numbers_dict = {
    2022: list(range(1, 13)),
    2020: list(range(1, 11)),
    2019: list(range(1, 11)),
    2017: list(range(1, 31)),
    2014: list(range(1, 31)),
}
func_numbers = func_numbers_dict[year]

# Run optimizations using multi-threading
with concurrent.futures.ThreadPoolExecutor(max_workers=1) as executor:
    futures = [
        executor.submit(run_test_optimization, j, dimension, year, k)
        for k in range(NRuns)
        for j in func_numbers
    ]
    concurrent.futures.wait(futures)

    for f in futures:
        f.result()



Running optimization for func_1 (Dimension: 20)
============================================================
  DE              f(x): 300
  ABC             f(x): 42484.882
  LSHADE          f(x): 300
  LSHADE_cnEpSin  f(x): 300
  JADE            f(x): 300
  jSO             f(x): 300
  j2020           f(x): 300.00003
  LSRTDE          f(x): 300
  NLSHADE_RSP     f(x): 300
  ARRDE           f(x): 300
  GWO_DE          f(x): 302.76135
  NelderMead      f(x): 300
  DA              f(x): 300
  L_BFGS_B        f(x): 300
  PSO             f(x): 300
  DMSPSO          f(x): 300
  SPSO2011        f(x): 300
  CMAES           f(x): 300
  BIPOP_aCMAES    f(x): 300
  Scipy L-BFGS-B  f(x): 300
  Scipy Nelder-Mead f(x): 300
  Scipy DA        f(x): 300
------------------------------------------------------------

Running optimization for func_2 (Dimension: 20)
============================================================
  DE              f(x): 447.55901
  ABC             f(x): 407.15048
  LSHADE          f(x): 400
  LSHADE_cnEpSin  f(x): 400
  JADE            f(x): 400
  jSO             f(x): 400
  j2020           f(x): 417.14573
  LSRTDE          f(x): 444.89547
  NLSHADE_RSP     f(x): 406.39281
  ARRDE           f(x): 401.54981
  GWO_DE          f(x): 415.17322
  NelderMead      f(x): 403.98662
  DA              f(x): 419.41087
  L_BFGS_B        f(x): 449.08448
  PSO             f(x): 400.02232
  DMSPSO          f(x): 400.38118
  SPSO2011        f(x): 449.08461
  CMAES           f(x): 449.08448
  BIPOP_aCMAES    f(x): 400
  Scipy L-BFGS-B  f(x): 449.08448
  Scipy Nelder-Mead f(x): 449.08451
  Scipy DA        f(x): 449.08448
------------------------------------------------------------

Running optimization for func_3 (Dimension: 20)
============================================================
  DE              f(x): 614.63684
  ABC             f(x): 600
  LSHADE          f(x): 600
  LSHADE_cnEpSin  f(x): 600
  JADE            f(x): 600
  jSO             f(x): 600
  j2020           f(x): 600
  LSRTDE          f(x): 600
  NLSHADE_RSP     f(x): 600
  ARRDE           f(x): 600
  GWO_DE          f(x): 600
  NelderMead      f(x): 668.52549
  DA              f(x): 600.00018
  L_BFGS_B        f(x): 668.52549
  PSO             f(x): 602.1189
  DMSPSO          f(x): 603.30578
  SPSO2011        f(x): 600.74689
  CMAES           f(x): 600.0014
  BIPOP_aCMAES    f(x): 600
  Scipy L-BFGS-B  f(x): 668.5255
  Scipy Nelder-Mead f(x): 668.01149
  Scipy DA        f(x): 600.00025
------------------------------------------------------------

Running optimization for func_4 (Dimension: 20)
============================================================
  DE              f(x): 855.74959
  ABC             f(x): 903.25862
  LSHADE          f(x): 815.61138
  LSHADE_cnEpSin  f(x): 806.08713
  JADE            f(x): 810.98604
  jSO             f(x): 805.9698
  j2020           f(x): 816.60306
  LSRTDE          f(x): 803.97984
  NLSHADE_RSP     f(x): 860.76871
  ARRDE           f(x): 808.95884
  GWO_DE          f(x): 816.91429
  NelderMead      f(x): 890.54093
  DA              f(x): 882.58133
  L_BFGS_B        f(x): 890.54093
  PSO             f(x): 869.64682
  DMSPSO          f(x): 865.66707
  SPSO2011        f(x): 816.28376
  CMAES           f(x): 811.9395
  BIPOP_aCMAES    f(x): 815.91933
  Scipy L-BFGS-B  f(x): 890.54093
  Scipy Nelder-Mead f(x): 883.57629
  Scipy DA        f(x): 890.54093
------------------------------------------------------------

Running optimization for func_5 (Dimension: 20)
============================================================
  DE              f(x): 997.54474
  ABC             f(x): 3323.5121
  LSHADE          f(x): 900
  LSHADE_cnEpSin  f(x): 900
  JADE            f(x): 900
  jSO             f(x): 900
  j2020           f(x): 900
  LSRTDE          f(x): 900
  NLSHADE_RSP     f(x): 900
  ARRDE           f(x): 900
  GWO_DE          f(x): 900
  NelderMead      f(x): 2456.1107
  DA              f(x): 3071.5902
  L_BFGS_B        f(x): 2458.8608
  PSO             f(x): 1440.6716
  DMSPSO          f(x): 905.12867
  SPSO2011        f(x): 900.54385
  CMAES           f(x): 900
  BIPOP_aCMAES    f(x): 900.99818
  Scipy L-BFGS-B  f(x): 2458.8608
  Scipy Nelder-Mead f(x): 2457.1933
  Scipy DA        f(x): 2561.3842
------------------------------------------------------------

Running optimization for func_6 (Dimension: 20)
============================================================
  DE              f(x): 1971.8282
  ABC             f(x): 5574.1072
  LSHADE          f(x): 1806.1336
  LSHADE_cnEpSin  f(x): 1800.3056
  JADE            f(x): 1898.8808
  jSO             f(x): 1800.4832
  j2020           f(x): 1901.664
  LSRTDE          f(x): 1800.4834
  NLSHADE_RSP     f(x): 1887.2841
  ARRDE           f(x): 1841.3002
  GWO_DE          f(x): 11668.098
  NelderMead      f(x): 1844.2033
  DA              f(x): 1808.1163
  L_BFGS_B        f(x): 1909.0077
  PSO             f(x): 3848.7742
  DMSPSO          f(x): 10168.1
  SPSO2011        f(x): 4657.2054
  CMAES           f(x): 1806.9352
  BIPOP_aCMAES    f(x): 1859.0192
  Scipy L-BFGS-B  f(x): 1872.5365
  Scipy Nelder-Mead f(x): 2054.1894
  Scipy DA        f(x): 1814.9411
------------------------------------------------------------

Running optimization for func_7 (Dimension: 20)
============================================================
  DE              f(x): 2027.7862
  ABC             f(x): 2033.9782
  LSHADE          f(x): 2025.7557
  LSHADE_cnEpSin  f(x): 2021.0581
  JADE            f(x): 2024.9837
  jSO             f(x): 2022.072
  j2020           f(x): 2023.9772
  LSRTDE          f(x): 2001.3071
  NLSHADE_RSP     f(x): 2021.717
  ARRDE           f(x): 2023.3001
  GWO_DE          f(x): 2036.9376
  NelderMead      f(x): 2526.423
  DA              f(x): 2112.0289
  L_BFGS_B        f(x): 2527.3806
  PSO             f(x): 2070.0527
  DMSPSO          f(x): 2060.1259
  SPSO2011        f(x): 2047.5546
  CMAES           f(x): 2063.0947
  BIPOP_aCMAES    f(x): 2021.6167
  Scipy L-BFGS-B  f(x): 2545.9195
  Scipy Nelder-Mead f(x): 2617.3528
  Scipy DA        f(x): 2092.0307
------------------------------------------------------------

Running optimization for func_8 (Dimension: 20)
============================================================
  DE              f(x): 2238.4151
  ABC             f(x): 2223.2242
  LSHADE          f(x): 2222.6411
  LSHADE_cnEpSin  f(x): 2216.5047
  JADE            f(x): 2221.7319
  jSO             f(x): 2224.0222
  j2020           f(x): 2223.5503
  LSRTDE          f(x): 2224.9593
  NLSHADE_RSP     f(x): 2221.0833
  ARRDE           f(x): 2222.3926
  GWO_DE          f(x): 2230.2027
  NelderMead      f(x): 2636.8799
  DA              f(x): 2381.8641
  L_BFGS_B        f(x): 2991.1908
  PSO             f(x): 2222.561
  DMSPSO          f(x): 2222.4891
  SPSO2011        f(x): 2227.6319
  CMAES           f(x): 2220.3577
  BIPOP_aCMAES    f(x): 2220.64
  Scipy L-BFGS-B  f(x): 2933.0533
  Scipy Nelder-Mead f(x): 2890.3671
  Scipy DA        f(x): 2221.8949
------------------------------------------------------------

Running optimization for func_9 (Dimension: 20)
============================================================
  DE              f(x): 2465.3437
  ABC             f(x): 2480.7875
  LSHADE          f(x): 2465.3435
  LSHADE_cnEpSin  f(x): 2465.3435
  JADE            f(x): 2465.3435
  jSO             f(x): 2465.3435
  j2020           f(x): 2465.3435
  LSRTDE          f(x): 2480.7813
  NLSHADE_RSP     f(x): 2465.3435
  ARRDE           f(x): 2465.3435
  GWO_DE          f(x): 2465.3435
  NelderMead      f(x): 2465.3435
  DA              f(x): 2467.4003
  L_BFGS_B        f(x): 2480.7813
  PSO             f(x): 2465.3435
  DMSPSO          f(x): 2465.3435
  SPSO2011        f(x): 2480.804
  CMAES           f(x): 2480.7813
  BIPOP_aCMAES    f(x): 2465.3435
  Scipy L-BFGS-B  f(x): 2480.7813
  Scipy Nelder-Mead f(x): 2480.8289
  Scipy DA        f(x): 2480.7813
------------------------------------------------------------

Running optimization for func_10 (Dimension: 20)
============================================================
  DE              f(x): 2500.5172
  ABC             f(x): 2400.1877
  LSHADE          f(x): 2400.4037
  LSHADE_cnEpSin  f(x): 2500.2849
  JADE            f(x): 2500.4683
  jSO             f(x): 2500.3194
  j2020           f(x): 2400.1874
  LSRTDE          f(x): 2500.3617
  NLSHADE_RSP     f(x): 2500.4406
  ARRDE           f(x): 2400.0625
  GWO_DE          f(x): 2618.8727
  NelderMead      f(x): 6169.0617
  DA              f(x): 2425.1178
  L_BFGS_B        f(x): 6109.5459
  PSO             f(x): 3083.2547
  DMSPSO          f(x): 2632.1121
  SPSO2011        f(x): 2500.3924
  CMAES           f(x): 3359.1873
  BIPOP_aCMAES    f(x): 2500.6549
  Scipy L-BFGS-B  f(x): 6287.3523
  Scipy Nelder-Mead f(x): 5683.4727
  Scipy DA        f(x): 2400.0937
------------------------------------------------------------

Running optimization for func_11 (Dimension: 20)
============================================================
  DE              f(x): 3023.9238
  ABC             f(x): 2672.2987
  LSHADE          f(x): 2900
  LSHADE_cnEpSin  f(x): 3000
  JADE            f(x): 3000
  jSO             f(x): 2900
  j2020           f(x): 2905.675
  LSRTDE          f(x): 3000
  NLSHADE_RSP     f(x): 2900
  ARRDE           f(x): 2900
  GWO_DE          f(x): 3000
  NelderMead      f(x): 3000
  DA              f(x): 2900
  L_BFGS_B        f(x): 2900
  PSO             f(x): 2900
  DMSPSO          f(x): 2900
  SPSO2011        f(x): 2900
  CMAES           f(x): 2900
  BIPOP_aCMAES    f(x): 2900
  Scipy L-BFGS-B  f(x): 2900
  Scipy Nelder-Mead f(x): 2900.0004
  Scipy DA        f(x): 2900
------------------------------------------------------------

Running optimization for func_12 (Dimension: 20)
============================================================
  DE              f(x): 2892.4733
  ABC             f(x): 2947.1646
  LSHADE          f(x): 2900.0039
  LSHADE_cnEpSin  f(x): 2900.004
  JADE            f(x): 2900.0041
  jSO             f(x): 2900.0038
  j2020           f(x): 2900.0042
  LSRTDE          f(x): 2933.6674
  NLSHADE_RSP     f(x): 2900.004
  ARRDE           f(x): 2900.0043
  GWO_DE          f(x): 2900.004
  NelderMead      f(x): 5490.2128
  DA              f(x): 2900.0049
  L_BFGS_B        f(x): 5113.3733
  PSO             f(x): 2893.2191
  DMSPSO          f(x): 2900.0048
  SPSO2011        f(x): 2940.0228
  CMAES           f(x): 2963.1768
  BIPOP_aCMAES    f(x): 2900.0048
  Scipy L-BFGS-B  f(x): 3382.9172
  Scipy Nelder-Mead f(x): 5108.8009
  Scipy DA        f(x): 3059.5899
------------------------------------------------------------

Example of using minion/py in curve fitting problems

Here, an example of using minion to minimize an objective function related to a curve fitting problem is demonstrated. The idea is first to define the data generation model, generate the data, fit the model, and report the result.

Polynomial Fitting Problems

In this problem, we try fit a polynomial from a set of data. Specifically, a set of points (\(\{(x_i, y_i) \mid i = 1, 2, \dots, N\}\)) with \(x \in [0, 1]\) is generated according to:

\[f(x, a) = \sum_{j=0}^{D-1} a_j x^j\]

Given the coefficients \(a_j\) that generate the data, the goal is to reproduce the data points by minimizing the objective function:

\[L = \frac{1}{N}\sum_{i=1}^N \left(y_i - f(x_i, a)\right)^2\]
[13]:
# Step 1: Generate Data Points from a Polynomial
dimension = 10  # Number of free parameters (polynomial degree is dimension - 1)
np.random.seed(8)  # For reproducibility

# True polynomial coefficients (random values)
true_coefficients = [np.random.uniform(-1.0, 1.0) * (1.0 ** i) for i in range(dimension)]

# Generate data points
x_data = np.linspace(0.0, 1, dimension + 10)
y_data = np.polyval(true_coefficients, x_data)

# Step 2: Define the Polynomial Model
def polynomial_model(x, coefficients):
    """Evaluate a polynomial at x given the coefficients."""
    return np.polyval(coefficients, x)

# Step 3: Define the Objective Function
def objective_function(coefficients):
    """Compute the mean squared error between the polynomial model and data points."""
    y_pred = polynomial_model(x_data, coefficients)
    return np.mean((y_data - y_pred) ** 2)

def objective_function_vect(X):
    """Vectorized version of the objective function for batch optimization."""
    return [objective_function(x) for x in X]

# Optimization Settings
bounds = [(-10, 10)] * dimension
Nmaxeval = 20000
algos = [
      "DE", "ABC", "LSHADE", "LSHADE_cnEpSin", "JADE", "jSO", "j2020", "LSRTDE", "NLSHADE_RSP",
        "ARRDE", "GWO_DE",  "NelderMead", "DA", "L_BFGS_B", "PSO", "DMSPSO", "SPSO2011", "CMAES", "BIPOP_aCMAES"
]

# Step 4: Minimize the Objective Function and Plot Results
plt.figure(figsize=(6, 4))
plt.scatter(x_data, y_data, label="Data Points", color="black", marker="o", zorder=3)

x0 = [[0.0 for _ in range(dimension)]]

print("\nOptimization Results:")
print("=" * 50)

# Run Optimization with Custom Algorithms
for algo in algos:
    res = mpy.Minimizer(
        objective_function_vect, bounds, x0=x0, relTol=0.0,
        algo=algo, maxevals=Nmaxeval, callback=None, seed=0,
        options={
            "population_size": 0,
            "func_noise_ratio"  :  0.0,
            "N_points_derivative": 1}
    ).optimize()

    print(f"{algo:<30}: f(x) = {res.fun:<20.8g}")
    plt.plot(x_data, polynomial_model(x_data, res.x), label=algo, linewidth=1.2, alpha=0.7)

# Run SciPy Optimizers
scipy_algorithms = [
    ("Scipy Dual Annealing (DA)", dual_annealing, {"bounds": bounds, "maxfun": Nmaxeval, "no_local_search": False, "x0": x0[0]}),
    ("Scipy L-BFGS-B", minimize, {"x0": x0[0], "bounds": bounds, "method": "L-BFGS-B", "options": {"maxfun": Nmaxeval}}),
    ("Scipy Nelder-Mead", minimize, {"x0": x0[0], "bounds": bounds, "method": "Nelder-Mead", "options": {"maxfev": Nmaxeval, "adaptive": True}}),
]

for name, func_opt, kwargs in scipy_algorithms:
    res = func_opt(objective_function, **kwargs)
    print(f"{name:<30}: f(x) = {res.fun:<20.8g}")
    plt.plot(x_data, polynomial_model(x_data, res.x), label=name, linewidth=1.2, alpha=0.7)

print("=" * 50)

# Plot Formatting
plt.legend(loc="upper left", bbox_to_anchor=(1, 1), fontsize=9)
plt.title("Polynomial Fit")
plt.xlabel("x")
plt.ylabel("y")
plt.grid(True, linestyle="--", alpha=0.6)
plt.show()



Optimization Results:
==================================================
DE                            : f(x) = 3.4676234e-07
ABC                           : f(x) = 0.0056994221
LSHADE                        : f(x) = 4.0557789e-10
LSHADE_cnEpSin                : f(x) = 3.3043359e-14
JADE                          : f(x) = 5.251496e-08
jSO                           : f(x) = 9.774338e-11
j2020                         : f(x) = 8.4535903e-05
LSRTDE                        : f(x) = 1.4773705e-12
NLSHADE_RSP                   : f(x) = 7.1946723e-06
ARRDE                         : f(x) = 4.2782791e-09
GWO_DE                        : f(x) = 1.2315456e-05
NelderMead                    : f(x) = 4.0539659e-15
DA                            : f(x) = 2.521779e-05
L_BFGS_B                      : f(x) = 7.2866825e-07
PSO                           : f(x) = 3.5313431e-05
DMSPSO                        : f(x) = 2.6368825e-05
SPSO2011                      : f(x) = 0.00054992829
CMAES                         : f(x) = 8.5261952e-12
BIPOP_aCMAES                  : f(x) = 9.9424922e-11
Scipy Dual Annealing (DA)     : f(x) = 7.3242064e-07
Scipy L-BFGS-B                : f(x) = 7.3242064e-07
Scipy Nelder-Mead             : f(x) = 2.1676521e-11
==================================================
../_images/minionpy_minimizer_29_1.png

Gaussian Mixture Model Fitting Problems

Thsi time, the model is given by the sum of Gaussian functions:

\[f(x, a, b, c) = \sum_{j=1}^{D/3} \frac{a_j}{\sum_{k=1}^{D/3} a_k} \frac{1}{b_j \sqrt{2\pi}} \exp\left[-\frac{1}{2} \frac{(x-c_j)^2}{b_j^2}\right]\]

Here, \(f(x, a, b, c)\) is normalized to represent a probability distribution. The data points are generated using predefined values of \(a_j\), \(b_j\), and \(c_j\) within the interval \(x \in [-20, 20]\). The objective function is the same as in the case of polynomial fitting.

[14]:
import numpy as np
import matplotlib.pyplot as plt
from scipy.optimize import minimize, dual_annealing
import concurrent.futures

# Step 1: Generate Data Points from a Gaussian Mixture Model (GMM)
np.random.seed(5)  # For reproducibility

num_gauss = 5  # Number of Gaussians
true_centers = 10 * (-1 + 2 * np.random.random(num_gauss))  # Random center positions
true_widths = np.random.rand(num_gauss) + 1.0  # Widths (variances)
true_coeffs = 2.0 * np.random.rand(num_gauss)  # Coefficients

dimension = num_gauss * 3  # Total number of free parameters

# Define a Gaussian function
def gauss(x, center, width):
    """Compute a Gaussian value at x given center and width."""
    return (1.0 / (2.0 * np.pi * width ** 2)) * 0.5 * np.exp(-((x - center) ** 2) / (2 * width ** 2))

# Define the Gaussian Mixture Model (GMM)
def gmm(x, centers, widths, coeffs):
    """Evaluate the Gaussian Mixture Model (GMM) at x."""
    result = np.zeros_like(x)
    coeffs = np.array(coeffs)
    norm_coeff = coeffs / np.sum(coeffs)  # Normalize coefficients
    for i in range(len(centers)):
        result += norm_coeff[i] * gauss(x, centers[i], widths[i])
    return result

# Generate synthetic data
x_data = np.linspace(-20, 20, dimension + 10)
y_data = gmm(x_data, true_centers, true_widths, true_coeffs)

# Step 2: Define the Model for Fitting
def gmm_model(x, params):
    """Compute GMM model values for given parameters."""
    num_gauss = len(params) // 3
    centers = params[:num_gauss]
    widths = params[num_gauss:2*num_gauss]
    coeffs = params[2*num_gauss:]
    return gmm(x, centers, widths, coeffs)

# Step 3: Define the Objective Function
def objective_function(params):
    """Compute the mean squared error between model and data."""
    y_pred = gmm_model(x_data, params)
    return np.mean((y_data - y_pred) ** 2)

# Parallelized objective function
executor = concurrent.futures.ThreadPoolExecutor(max_workers=8)

def objective_function_vect(params):
    """Vectorized version of objective function using multithreading."""
    return list(executor.map(objective_function, params))

# Optimization Settings
bounds = [(-10, 10)] * dimension
Nmaxeval = 10000
algos = [
    "DE", "ABC", "LSHADE", "LSHADE_cnEpSin", "JADE", "jSO", "j2020", "LSRTDE", "NLSHADE_RSP",
        "ARRDE", "GWO_DE", "NelderMead", "DA", "L_BFGS_B", "PSO", "DMSPSO", "SPSO2011", "CMAES", "BIPOP_aCMAES"
]

x0 = [[1.0 for _ in range(dimension)]]

# Step 4: Minimize the Objective Function and Plot Results
plt.figure(figsize=(6, 4))
plt.scatter(x_data, y_data, label="Data", color="black", marker="o", zorder=3)

print("\nOptimization Results:")
print("=" * 60)

# Run Optimization with Custom Algorithms
for algo in algos:
    res = mpy.Minimizer(
        objective_function_vect, bounds, x0=x0, relTol=0.0,
        algo=algo, maxevals=Nmaxeval, callback=None, seed=None,
        options={"population_size": 0}
    ).optimize()

    print(f"{algo:<30}: f(x) = {res.fun:<20.8g}")
    plt.plot(x_data, gmm_model(x_data, res.x), label=algo, linewidth=1.2, alpha=0.7)

# Run SciPy Optimizers
scipy_algorithms = [
    ("Scipy L-BFGS-B", minimize, {"x0": x0[0], "bounds": bounds, "method": "L-BFGS-B", "options": {"maxfun": Nmaxeval}}),
    ("Scipy Dual Annealing", dual_annealing, {"x0": x0[0],"bounds": bounds, "maxfun": Nmaxeval, "no_local_search": False}),
    ("Scipy Nelder-Mead", minimize, {"x0": x0[0],  "bounds": bounds,"method": "Nelder-Mead", "options": {"maxfev": Nmaxeval, "adaptive": True}}),
]

for name, func_opt, kwargs in scipy_algorithms:
    res = func_opt(objective_function, **kwargs)
    print(f"{name:<30}: f(x) = {res.fun:<20.8g}")
    plt.plot(x_data, gmm_model(x_data, res.x), label=name, linewidth=1.2, alpha=0.7)

print("=" * 60)

# Plot Formatting
plt.legend(loc="upper left", bbox_to_anchor=(1, 1), fontsize=9)
plt.title("Gaussian Mixture Model Fit")
plt.xlabel("x")
plt.ylabel("y")
plt.grid(True, linestyle="--", alpha=0.6)
plt.show()

executor.shutdown()



Optimization Results:
============================================================
DE                            : f(x) = 5.7291499e-09
ABC                           : f(x) = 7.1340783e-07
LSHADE                        : f(x) = 1.0475381e-06
LSHADE_cnEpSin                : f(x) = 4.3458431e-07
JADE                          : f(x) = 3.621201e-06
jSO                           : f(x) = 1.5717409e-06
j2020                         : f(x) = 1.5987436e-06
LSRTDE                        : f(x) = 4.9046081e-06
NLSHADE_RSP                   : f(x) = 5.398718e-07
ARRDE                         : f(x) = 1.4614777e-06
GWO_DE                        : f(x) = 3.3096941e-08
NelderMead                    : f(x) = 7.3549528e-09
DA                            : f(x) = 3.0671579e-08
L_BFGS_B                      : f(x) = 1.4374531e-05
PSO                           : f(x) = 7.9250982e-09
DMSPSO                        : f(x) = 5.430383e-09
SPSO2011                      : f(x) = 3.4595187e-06
CMAES                         : f(x) = 8.0375181e-09
BIPOP_aCMAES                  : f(x) = 9.427549e-11
Scipy L-BFGS-B                : f(x) = 2.4100192e-05
Scipy Dual Annealing          : f(x) = 6.1466906e-06
Scipy Nelder-Mead             : f(x) = 4.1184114e-09
============================================================
../_images/minionpy_minimizer_31_1.png

More complex fitting problem: CT18 PDFs Fitting

Here, we provide a slightly more challenging curve fitting problem. The task is to reproduce the CT18 parton distribution functions (PDFs) \cite{Hou:2019efy}. The parameterization for valence up-quark (\(u_v\)), valence down-quark (\(d_v\)), gluon, anti-\(u\) (\(\bar{u}\)), anti-\(d\) (\(\bar{d}\)), and strange quark (\(s\)) PDFs at the initial scale is given by:

\[f_i(x) = a_0 x^{a_1-1} (1-x)^{a_2} P_i(y, a_3, a_4, \dots), \quad i \in \{u_v, d_v, g, \bar{u}, \bar{d}, s\}\]

Here, \(P_i(y)\) is a Bernstein polynomial of degree 4, 3, or 5, depending on the specific PDF. The variable \(y\) is defined as \(y = \sqrt{x}\) for \(u_v\), \(d_v\), and \(g\), and as \(y = (1 - (1 - \sqrt{x}))^{a_3}\) for the sea quarks. The objective function is:

\[L = \sum_i \frac{1}{N} \sum_{j=1}^N \left(y_j - f_i(x_j)\right)^2\]

where \(i \in \{u_v, d_v, g, \bar{u}, \bar{d}, s\}\). The dimensionality of this problem is \(D = 47\).

[15]:
class CT18PDFs :
    def __init__(self) :
        self.parameters = {
            "uv_0" : 3.385, "uv_1" : 0.763, "uv_2" : 3.036, "uv_3" : 1.502, "uv_4" : -0.147,"uv_5" : 1.671, "uv_6" : 0.,
            "dv_0" : 0.490, "dv_1" : 0.763, "dv_2" : 3.036, "dv_3" : 2.615, "dv_4" : 1.828,"dv_5" : 2.721, "dv_6" : 0.,
            "g_0" : 2.690, "g_1" : 0.531, "g_2" : 3.148, "g_3" : 3.032, "g_4" : -1.705, "g_5" : 1.354,
            "ubar_0" : 0.414, "ubar_1" : -0.022, "ubar_2" : 7.737, "ubar_3" : 4.0, "ubar_4" : 0.618,"ubar_5" : 0.195, "ubar_6" : 0.871, "ubar_7" : 0.267,"ubar_8" : 0.733,
            "dbar_0" : 0.414, "dbar_1" : -0.022, "dbar_2" : 7.737, "dbar_3" : 4.0, "dbar_4" : 0.292,"dbar_5" : 0.647, "dbar_6" : 0.474, "dbar_7" : 0.741,"dbar_8" :1.0,
            "s_0" : 0.288, "s_1" : -0.022, "s_2" : 10.31, "s_3" : 4.0, "s_4" : 0.466,"s_5" : 0.466, "s_6" : 0.225, "s_7" : 0.225,"s_8" : 1.0,
        }
        self.xlist = np.linspace(1e-3, 0.8, 50)
        self.paramNames = list(self.parameters.keys())
        self.originalData = self.getData()

    def uv(self, x) :
        a0 = self.parameters["uv_0"]
        a1 = self.parameters["uv_1"]
        a2 = self.parameters["uv_2"]
        a3 = self.parameters["uv_3"]
        a4 = self.parameters["uv_4"]
        a5 = self.parameters["uv_5"]
        a6 = self.parameters["uv_6"]
        y= np.sqrt(x)
        P = np.sinh(a3)*(1-y)**4 + np.sinh(a4) *4*y*(1-y)**3 + np.sinh(a5) *6*y**2*(1-y)**2 + np.sinh(a6) *4*y**3*(1-y) + y**4
        return a0 * x**(a1-1)*(1-x)**a2*P

    def dv(self, x) :
        a0 = self.parameters["dv_0"]
        a1 = self.parameters["dv_1"]
        a2 = self.parameters["dv_2"]
        a3 = self.parameters["dv_3"]
        a4 = self.parameters["dv_4"]
        a5 = self.parameters["dv_5"]
        a6 = self.parameters["dv_6"]
        y= np.sqrt(x)
        P = np.sinh(a3)*(1-y)**4 + np.sinh(a4) *4*y*(1-y)**3 + np.sinh(a5) *6*y**2*(1-y)**2 + np.sinh(a6) *4*y**3*(1-y) + y**4
        return a0 * x**(a1-1)*(1-x)**a2*P

    def g(self, x) :
        a0 = self.parameters["g_0"]
        a1 = self.parameters["g_1"]
        a2 = self.parameters["g_2"]
        a3 = self.parameters["g_3"]
        a4 = self.parameters["g_4"]
        a5 = self.parameters["g_5"]
        y= np.sqrt(x)
        P = np.sinh(a3)*(1-y)**3 + np.sinh(a4) *3*y*(1-y)**2 + np.sinh(a5) *3*y**2*(1-y)  + y**3
        return a0 * x**(a1-1)*(1-x)**a2*P

    def ubar(self, x) :
        a0 = self.parameters["ubar_0"]
        a1 = self.parameters["ubar_1"]
        a2 = self.parameters["ubar_2"]
        a3 = self.parameters["ubar_3"]
        a4 = self.parameters["ubar_4"]
        a5 = self.parameters["ubar_5"]
        a6 = self.parameters["ubar_6"]
        a7 = self.parameters["ubar_7"]
        a8 = self.parameters["ubar_8"]
        y= 1-(1-np.sqrt(x))**a3
        P = (1-y)**5 + a4 * 5*y*(1-y)**4 + a5 * 10*y**2*(1-y)**3 +  a6 * 10*y**3*(1-y)**2 +  a7 * 5*y**4*(1-y)+  a8 * 5*y**5
        return a0 * x**(a1-1)*(1-x)**a2*P

    def dbar(self, x) :
        a0 = self.parameters["dbar_0"]
        a1 = self.parameters["dbar_1"]
        a2 = self.parameters["dbar_2"]
        a3 = self.parameters["dbar_3"]
        a4 = self.parameters["dbar_4"]
        a5 = self.parameters["dbar_5"]
        a6 = self.parameters["dbar_6"]
        a7 = self.parameters["dbar_7"]
        a8 = self.parameters["dbar_8"]
        y= 1-(1-np.sqrt(x))**a3
        P = (1-y)**5 + a4 * 5*y*(1-y)**4 + a5 * 10*y**2*(1-y)**3 +  a6 * 10*y**3*(1-y)**2 +  a7 * 5*y**4*(1-y)+  a8 * 5*y**5
        return a0 * x**(a1-1)*(1-x)**a2*P

    def s(self, x) :
        a0 = self.parameters["s_0"]
        a1 = self.parameters["s_1"]
        a2 = self.parameters["s_2"]
        a3 = self.parameters["s_3"]
        a4 = self.parameters["s_4"]
        a5 = self.parameters["s_5"]
        a6 = self.parameters["s_6"]
        a7 = self.parameters["s_7"]
        a8 = self.parameters["s_8"]
        y= 1-(1-np.sqrt(x))**a3
        P = (1-y)**5 + a4 * 5*y*(1-y)**4 + a5 * 10*y**2*(1-y)**3 +  a6 * 10*y**3*(1-y)**2 +  a7 * 5*y**4*(1-y)+  a8 * 5*y**5
        return a0 * x**(a1-1)*(1-x)**a2*P

    def u(self, x) : return self.uv(x)+self.ubar(x)
    def d(self, x) : return self.dv(x)+self.dbar(x)

    def setParameter(self, pars) :
        assert(len(pars)==len(self.parameters))
        self.parameters= dict(zip(self.paramNames, pars))

    def getData(self) :
        x= self.xlist
        return [ x*self.u(self.xlist), x*self.ubar(self.xlist), x*self.d(self.xlist), x*self.dbar(self.xlist), x*self.g(self.xlist), x*self.s(self.xlist)]

    def objective_function(self, params):
        self.setParameter(params)
        data = self.getData()
        ret =0
        for do, d in zip(self.originalData, data) :
            ret = ret + np.sum((do-d)**2)
        return ret
[16]:
ct18 = CT18PDFs()
data = ct18.getData()
# Create a 3x2 grid of subplots
fig, axes = plt.subplots(2, 3, figsize=(10, 5))

# List of labels for each plot
labels = ["u", "ubar", "d", "dbar", "g", "s"]

# Plotting each function in its corresponding subplot
for i, ax in enumerate(axes.flatten()):
    ax.plot(ct18.xlist, data[i], label=labels[i])
    ax.set_xlim(0.1, 0.8)
    ax.set_xlabel("x")
    if (i%3 == 0):
        ax.set_ylabel(r"$xf(x)$")
    ax.legend()
plt.subplots_adjust(hspace=0.15, wspace=0.17)
plt.show()

../_images/minionpy_minimizer_34_0.png
[17]:
# Step 1: Define Problem Dimensions and Settings
dimension = 47
print("Dimension:", dimension)

bounds = [(-10, 10)] * dimension
Nmaxeval = 100000
x0 = [[1.0] * dimension]  # Initial guess

# Step 2: Set Up Parallel Execution for CT18PDFs
t_parallel = mpy.Thread_Parallel(4, CT18PDFs)  # Vectorize using 4 threads

# Step 3: Define Optimization Algorithms
algos = [
   "DE", "ABC", "LSHADE", "LSHADE_cnEpSin", "JADE", "jSO", "j2020", "LSRTDE", "NLSHADE_RSP",
        "ARRDE", "GWO_DE", "NelderMead", "DA", "L_BFGS_B", "PSO", "DMSPSO", "SPSO2011", "CMAES", "BIPOP_aCMAES"
]

# Step 4: Run Optimization and Collect Results
results = {}

print("\nOptimization Results:")
print("=" * 60)

for algo in algos:
    res = mpy.Minimizer(
        t_parallel, bounds, x0=x0, algo=algo, relTol=0.0,
        maxevals=Nmaxeval, callback=None, seed=None,
        options={
            "population_size": 0,
            "func_noise_ratio"  :  0.0,
            "N_points_derivative": 1
        }
    ).optimize()

    print(f"{algo:<30}: f(x) = {res.fun:<20.8g}")
    results[algo] = res

# Step 5: Run SciPy Optimizers
scipy_algorithms = [
    ("Scipy L-BFGS-B", minimize, {"x0": x0[0], "bounds": bounds, "method": "L-BFGS-B", "options": {"maxfun": Nmaxeval}}),
    ("Scipy Dual Annealing", dual_annealing, {"x0": x0[0],"bounds": bounds, "maxfun": Nmaxeval, "no_local_search": False}),
    ("Scipy Nelder-Mead", minimize, {"x0": x0[0],  "bounds": bounds,"method": "Nelder-Mead", "options": {"maxfev": Nmaxeval, "adaptive": True}}),
]

for name, func_opt, kwargs in scipy_algorithms:
    res = func_opt(ct18.objective_function, **kwargs)
    print(f"{name:<30}: f(x) = {res.fun:<20.8g}")
    results[name] = res

print("=" * 60)

# Step 6: Plot Results
fig, axes = plt.subplots(2, 3, figsize=(12, 6))
labels = ["u-data", "ubar-data", "d-data", "dbar-data", "g-data", "s-data"]

# Plot each dataset in its corresponding subplot
for i, ax in enumerate(axes.flatten()):
    ax.plot(ct18.xlist, data[i], label=labels[i], color="black", linestyle="dotted", linewidth=1.2)

    # Overlay model predictions for selected algorithms
    for algo in ["ARRDE", "DA", "Scipy Dual Annealing", "L_BFGS_B"]:
        ct18.setParameter(results[algo].x)
        theo = ct18.getData()
        ax.plot(ct18.xlist, theo[i], label=algo, linewidth=1.2, alpha=0.8)

    ax.set_xlim(0.1, 0.8)
    ax.set_xlabel("x")
    if i % 3 == 0:
        ax.set_ylabel(r"$xf(x)$")
    ax.legend(fontsize=9)

plt.tight_layout()
plt.show()


Dimension: 47

Optimization Results:
============================================================
DE                            : f(x) = 0.19269741
ABC                           : f(x) = 9.2305563
LSHADE                        : f(x) = 5.0262623
LSHADE_cnEpSin                : f(x) = 0.34919775
JADE                          : f(x) = 4.6637756
jSO                           : f(x) = 0.78116151
j2020                         : f(x) = 9.9470365
LSRTDE                        : f(x) = 0.39744395
NLSHADE_RSP                   : f(x) = 1.0981858
ARRDE                         : f(x) = 1.2748372
GWO_DE                        : f(x) = 1.8577235
NelderMead                    : f(x) = 0.072777402
DA                            : f(x) = 0.13416323
L_BFGS_B                      : f(x) = 0.019077562
PSO                           : f(x) = 0.055286483
DMSPSO                        : f(x) = 0.327826
SPSO2011                      : f(x) = 3.9963909
CMAES                         : f(x) = 1.0687989
BIPOP_aCMAES                  : f(x) = 0.47659189
Scipy L-BFGS-B                : f(x) = 0.016397197
Scipy Dual Annealing          : f(x) = 0.91439194
Scipy Nelder-Mead             : f(x) = 0.072777402
============================================================
../_images/minionpy_minimizer_35_1.png