Reputation: 832
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
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())
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
# 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')
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