3

I have a function of the form

def tmp(x,n):
    R, s, a, T = x[0], x[1], x[2], x[3]

which returns a float, after a long block of calculations.

I need to minimize this function and for that I used the scipy.optimize.minimize():

minimize(tmp,[0,0,3,60000], args=(n,),tol =1e-15)

The above code looks for the minimum of the function tmp() with the starting values as shown.

Now I need to minimize the same function tmp, but keeping the variables R,T out of the minimization, as parameters. In other words I want the function to be written like:

def tmp(x,n,R,T):
        s, a = x[0], x[1]

How is it possible to create a function like the above without editing my first function?

milia
  • 521
  • 8
  • 20

4 Answers4

1

By default it isn't possible. You need to give tmp(x,n,R,T) a different name.

It's possible though, using the multimethod library

Magnun Leno
  • 2,728
  • 20
  • 29
  • Thanks, I'll have a look at the multimethod library. I'm trying to avoid rewriting tmp as a new function because that'll mean I'll have to copy many blocks of code, something which seems pointless to me. – milia Jun 12 '14 at 13:40
  • You can use default arguments def `tmp(x,n,R=None,T=None):`. Based on the values of `R` and `T` you proceed differently. – Magnun Leno Jun 12 '14 at 15:31
  • If I do that I'll have to change the first function and I'd like to keep them both.. – milia Jun 12 '14 at 16:15
  • Ok, then stick with multimethods. – Magnun Leno Jun 12 '14 at 16:18
1

The answer I have found to this problem is to use lmfit which allows you to easily hold some parameters fixed while minimizing on the others.

Here is a simple example where the function is minimized with respect to the second two parameters while the first one is held fixed :

import lmfit

p = lmfit.Parameters()
p.add_many(('param1',1.0,False,0,1)
           ,('param2',1.0,True,0,1)
           ,('param3',3.,True,10,30))


def function(p) :
    return (1-p['param1']) + (2-p['param2'])**2 + (1-p['param3'])**3

best_fit_result = lmfit.minimize(function,p,method='Nelder')

print(best_fit_result.params)
RBM
  • 51
  • 5
  • While this link may answer the question, it is better to include the essential parts of the answer here and provide the link for reference. Link-only answers can become invalid if the linked page changes. - [From Review](/review/late-answers/33464907) – Vickel Dec 24 '22 at 01:57
0

Not knowing what ist going on in your function makes it difficult to test something... Where do you define R, s, a and T...inside the function?

couldn´t you write a function like:

def tmp(x,n,cons):
       if cons is False:#case 1
           R, s, a, T = x[0], x[1], x[2], x[3]
       elif cons is True:#case 2
           R=0 #change them if you want 
           T=60000
           s, a = x[0], x[1]
       #your calculations
       #...

than you have to remember (!) that your "minimize" has to look like that for case one:

minimize(tmp,[0,0,3,60000], args=(n,cons),tol =1e-15)#where args is (2,False) for example

and like this for case 2:

minimize(tmp,[0,3], args=(n,cons),tol =1e-15)#where args is (2,True)
www.pieronigro.de
  • 840
  • 2
  • 12
  • 30
  • Thanks, this looks more like what I had in mind. I define R,s,a,T inside tmp(x,n) just after the definition line, as shown in my first post. Hopefully this will work. Sorry but I can't post the whole function here (a 36x36 system of differential equations) since it's for a client I'm working with. – milia Jun 12 '14 at 16:16
0

This is an old question, but I came across the problem and found an alternate solution. You can define a "mask" function that you can use to reassemble your scalar function's "feed" vector. E.g.

import numpy as np
from scipy.optimize import minimize

def test_fun(x):
    return (x[0] - 1)**2 + (x[1] - 2)**2 + (x[2] - 3)**2

def mask_fun(x, x0, mask):
    x_re = np.zeros(len(mask))
    x_re[mask > 0] = x
    x_re[mask == 0] = x0
    return test_fun(x_re)

mask = np.array([1, 1, 1])  # ones to estimate, zero for known/apriori
x_est = np.array([1., 2., 3.])
x_in = x_est[mask > 0]
x_param = x_est[mask == 0]

minimize(mask_fun, x_in, args=(x_param, mask))
Andrew Holmgren
  • 1,225
  • 1
  • 11
  • 18