Search code examples
pythonscipy-optimize

How to pass multiple constants and variables to Scipy Optimize?


I am trying to fit model data (calculated from eR) to my experimental data e_exp. I am not quite sure how to pass constants and variables to func.

import numpy as np
import math
from scipy.optimize import curve_fit, least_squares, minimize

f_exp     = np.array([1, 1.6, 2.7, 4.4, 7.3, 12, 20, 32, 56, 88, 144, 250000])
e_exp     = np.array([7.15, 7.30, 7.20, 7.25, 7.26, 7.28, 7.32, 7.25, 7.35, 7.34, 7.37, 13.55])

ezero     = np.min(e_exp)
einf      = np.max(e_exp)

ig_fc     = 500
ig_alpha  = 0.35

def CCER(einf, ezero, f_exp, fc, alpha):
    x  = [np.log(_ / ig_fc) for _ in f_exp]
    eR = [ezero + 1/2 * (einf - ezero) * (1 + np.sinh((1 - ig_alpha) * _) / (np.cosh((1 - ig_alpha) * _) + np.sin(1/2 * ig_alpha * math.pi))) for _ in x]
    return eR

def func(z):
    return np.sum((CCER(z[0], z[1], z[2], z[3], z[4], z[5]) - e_exp) ** 2)

res = minimize(func, (ig_fc, ig_alpha), method='SLSQP')

einf, ezero, and f_exp are all constant plus the variables I need to optimize are ig_fc and ig_alpha, in which ig stands for initial guess.

How can I make this work?

I am also not sure which of the optimization algorithms from scipy are best suited for my problem (be it curve_fit, least_squares or minimize).


Solution

  • I believe what you want is the following:

    def CCER(x, fc, alpha):
        y = np.log(x/fc)
        eR = ezero + 1/2 * (einf - ezero) * (1 + np.sinh((1 - alpha) * y) / (np.cosh((1 - alpha) * y) + np.sin(1/2 * alpha * math.pi)))
        return eR
    
    res = curve_fit(CCER, f_exp, e_exp, p0=(ig_fc, ig_alpha))
    

    You're passing the first value to CCER as an argument, the two remaining ones (fc and alpha) are then treated as optimizable parameters. All fixed parameters will be read from the outer scope - no need to pass them explicitly to the function here.

    Finally, in curve_fit you only need to pass an array of inputs (f_exp) and corresponding outputs (e_exp), as well as - possibly - a tuple of initial guesses p0.