lsr729
lsr729

Reputation: 832

Putting conditions on parameters in lmfit.minimize

How to put conditions on parameters while using lmfit.minimize?

from lmfit import Parameters,minimize, fit_report
import numpy as np

x = np.linspace(0,10,100)
y = 2.39645 * x**2 + np.random.normal(0, 2, 100)

def fun1(params,x,y):
    k1 = params['k1']
    k2 = params['k2']
    k3 = params['k3']
    y_fit = k1*x**2 + k2*x + k3
    return y_fit-y 

# Defining the various parameters
params = Parameters()
params.add('k1', value = 1)
params.add('k2', value = 1)
params.add('k3', value = 1)

fitted_params = minimize(fun1, params, args=(x,y,), method='least_squares')

This gives optimal k1, k2 and k3

name    value   standard error  relative error  initial value   min max vary
k1  2.42637846  0.02748469  (1.13%) 1   -inf    inf True
k2  -0.43530957 0.28403716  (65.25%)    1   -inf    inf True
k3  1.02895856  0.61456597  (59.73%)    1   -inf    inf True

I want to put constraints on k1, k2 and k3 such that: k1>k2>k3. How can I do that?

EDIT

I have introduced 2 parameters delta1 and delta2 as below-


# Defining the various parameters
params = Parameters()
params.add('k1', value = 1)
params.add('delta1', value = 1, min = 0)
params.add('k2', value = 1, expr = "k1 - delta1")
params.add('k2', value = 1)
params.add('delta2', value = 1, min = 0)
params.add('k3', value = 1, expr = "k2 - delta2")

#fitting function
fitted_params = minimize(fun1, params, args=(x,y,), method='least_squares')

#Printing parameters
fitted_params.params.pretty_print()

The new parameters are as below-

Name       Value      Min      Max   Stderr     Vary     Expr Brute_Step
delta1     1.726        0      inf     None     True     None     None
delta2  2.833e-11        0      inf     None     True     None     None
k1         2.398     -inf      inf     None     True     None     None
k2      -0.01788     -inf      inf     None     True     None     None
k3      -0.01788     -inf      inf     None    False k2 - delta2     None

We have k1>k2>k3 in new paramters, but the k2 and k2 are almost the same. Is there something can be done to avoid this, or these are the optimal solutions based on the given constrains?

Upvotes: 2

Views: 811

Answers (1)

ferdy
ferdy

Reputation: 5024

Try the following using the ref. https://lmfit.github.io/lmfit-py/constraints.html

...

# Defining the various parameters
params = Parameters()
params.add('k3', value=1)
params.add('delta1', value=1, vary=False)
params.add('k2', expr='delta1+k3')
params.add('delta2', value=1, vary=False)
params.add('k1', expr='delta2+k2')

fitted_params = minimize(fun1, params, args=(x,y,), method='least_squares')
print(fitted_params.params.pretty_print())

Typical output

Name       Value      Min      Max   Stderr     Vary     Expr Brute_Step
delta1         1     -inf      inf        0    False     None     None
delta2         1     -inf      inf        0    False     None     None
k1         2.241     -inf      inf        0    False delta2+k2     None
k2         1.241     -inf      inf 0.005612    False delta1+k3     None
k3         0.241     -inf      inf 0.005612     True     None     None

Vary delta2

# Defining the various parameters
params = Parameters()
params.add('k3', value=1)
params.add('delta1', value=1, vary=False)
params.add('k2', expr='delta1+k3')
params.add('delta2', value=0, vary=True)
params.add('k1', expr='delta2+k2')

Output

Name       Value      Min      Max   Stderr     Vary     Expr Brute_Step
delta1         1     -inf      inf        0    False     None     None
delta2     2.051     -inf      inf   0.1028     True     None     None
k1         2.363     -inf      inf   0.1028    False delta2+k2     None
k2        0.3113     -inf      inf  0.09006    False delta1+k3     None
k3       -0.6887     -inf      inf  0.09006     True     None     None

Upvotes: 1

Related Questions