3

I am using lmfit in Python to fit some data, which includes fitting the variables a, b, and c. I need to ensure that a < b < c. I found http://cars9.uchicago.edu/software/python/lmfit_MinimizerResult/constraints.html which talks about constraints needing to be defined as inequalities and setting up dummy variables. For example, if I wanted a + b <= 10, I could do:

pars.add('a',     value = 5, vary=True)
pars.add('delta', value = 5, max=10, vary=True)
pars.add('b',     expr='delta-a')

And this would ensure that a + b <= 10.

I suppose that I would need c - b > 0 and b - a > 0 (or alternatively a - b < 0 and b - c < 0), but I'm not sure how to code this.

ChemPaul
  • 45
  • 5

1 Answers1

3

Following the hint from the doc you link to, an inequality constraint of x > y should be translated to x = y + something where something has a lower bound of 0.

So, applying that approach twice, I think this should do what you want:

from lmfit import Parameters
params = Parameters()
params.add('a', value=5, vary=True)
params.add('b_minus_a', value=1,  vary=True, min=0)
params.add('c_minus_b', value=1,  vary=True, min=0)
params.add('b', expr='a + b_minus_a')
params.add('c', expr='b + c_minus_b')

That still uses three variables (a, b_minus_a, and c_minus_b) and imposes the inequality constraints, with the caveat the differences could actually be 0. With floating point numbers, that's usually sufficient, but depending on the scale of the variables, you could change 0 to something like 1.e-12.

M Newville
  • 7,486
  • 2
  • 16
  • 29
  • Ah, yes, that makes sense. I will give this a try tomorrow morning when I get back to my regular computer. – ChemPaul Apr 20 '18 at 01:55
  • I've a similar situation except only need to bound 1 parameter as being less than another, such that b < 0.2*a, but otherwise b should be able to vary freely, but it seems that it is locked to being exactly 0.2*a, where I've set `params.add(name="b", expr='0.2*a + b_minus_a')`, is it just that my fitting actually just wants b to be higher so its hitting the ceiling as it were, or is it actually trapped at that value? This seems to be the case regardless of the multiplier so I suspect it has hit the caveat you mentioned. Can i force it to explore more? – ch4rl1e97 Aug 25 '20 at 17:45