mmonti
mmonti

Reputation: 318

how to optimize the minimization of a vector function in python?

I have an issue: I'm trying to find the minimum of a function which depends on several parameters that I'd like to change as well. let's take as a simplified example:

import numpy as np
import scipy.optimize as opt
def f(x, a, b, c):
    f = a * x**2 + b * x + c
return f

I'd like to find the x which minimizes the function for different set of values of a, b, c, let's say for

a = [-1, 0, 1]
b = [0, 1, 2]
c = [0, 1]

ATM I have three nested loops and a minimization:

for p1 in a:
    for p2 in b:
         for p3 in c:
            y = opt.minimize(f, x0=[0, ], args=(p1, p2, p3, ))
            print(y)

which is really slow for the calculation I'm doing, but I haven't found any better so far. So, does anyone know a way or a package that would allow me to improve the efficiency?

Upvotes: 1

Views: 2945

Answers (2)

KCharlie
KCharlie

Reputation: 118

scipy.optimize.newton can do this.

Upvotes: 0

f.wue
f.wue

Reputation: 847

You could use a combination of different techniques to improve the efficiency of your script:

  1. Use itertools.product to generate every possible combination in the list a, b, c
  2. Use multiprocessingto execute the minimizations in parallel.

Other than this, i can't think of a way to optimize the efficiency of the code. As was pointed out in the comment, the constant value c has no influence on the minimization. But i'm sure the quadratic function is just an example.

I took the code of the multiprocessing part from here.

Here's the working code.

import numpy as np
import scipy.optimize as opt
import itertools
from multiprocessing import Pool

def f(x, a, b, c):
    f = a * x**2 + b * x + c
    return f

def mini(args):
    res = opt.minimize(f, x0=np.array([0]), args=args)
    return res.x

if __name__=="__main__":
    a = np.linspace(-1,2,100)
    b = np.linspace(0,2,100)
    c = [0, 1]
    args = list(itertools.product(a,b,c))
    print("Number of combos:" + str(len(args)))
    p = Pool(4)
    import time
    t0 = time.time()
    res = p.map(mini, args)
    print(time.time()-t0)

Even these 20000 combinations only need 5,28 seconds on my average laptop.

Upvotes: 5

Related Questions