Ask Your Question

Revision history [back]

click to hide/show revision 1
initial version

FWIW, I've used OpenOpt for a few things and had some success. I haven't had as much luck with the scipy optimizers, but YMMV.

One easy way to avoid the cost of multiple evaluations is to take advantage of the cached_function decorator:

def complicated(x,y,z):
    f = (x*2-y*z)**2
    g = x+y-9*z+4
    return f,g

@cached_function
def complicated_cached(x,y,z):
    f = (x*2-y*z)**2
    g = x+y-9*z+4
    return f,g

# or complicated_cached = cached_function(complicated)

def get(fn):
    a = minimize_constrained(lambda x: fn(*x)[0], 
                             lambda x: fn(*x)[1],
                             [1,1,1])
    return a

which produces a significant speedup:

sage: %timeit a = get(complicated)
25 loops, best of 3: 14.4 ms per loop
sage: %timeit b = get(complicated_cached)
625 loops, best of 3: 1.51 ms per loop

FWIW, I've used OpenOpt for a few things and had some success. I haven't had as much luck with the scipy optimizers, but YMMV.

One easy way to avoid the cost of multiple evaluations is to take advantage of the cached_function decorator:

def complicated(x,y,z):
    f = (x*2-y*z)**2
    g = x+y-9*z+4
    sleep(0.10)
    return f,g

@cached_function
def complicated_cached(x,y,z):
    f = (x*2-y*z)**2
    g = x+y-9*z+4
    sleep(0.10)
    return f,g

# or complicated_cached = cached_function(complicated)

def get(fn):
    a = minimize_constrained(lambda x: fn(*x)[0], 
                             lambda x: fn(*x)[1],
                             [1,1,1])
    return a

which produces can produce a significant speedup:speedup. (I put in the sleeps to make the one-call time longer-- originally I did multiple runs, but the caching means that I wasn't measuring what I wanted to.)

sage: %timeit time a = get(complicated)
25 loops, best of 3: 14.4 ms per loop
Time: CPU 0.06 s, Wall: 7.67 s
sage: %timeit time b = get(complicated_cached)
625 loops, best of 3: 1.51 ms per loop
Time: CPU 0.03 s, Wall: 3.83 s

FWIW, I've used OpenOpt for a few things and had some success. I haven't had as much luck with the scipy optimizers, but YMMV.

One easy way to avoid the cost of multiple evaluations is to take advantage of the cached_function decorator:

def complicated(x,y,z):
    f = (x*2-y*z)**2
    g = x+y-9*z+4
    sleep(0.10)
    return f,g

@cached_function
def complicated_cached(x,y,z):
    f = (x*2-y*z)**2
    g = x+y-9*z+4
    sleep(0.10)
    return f,g

# or complicated_cached = cached_function(complicated)

def get(fn):
    a = minimize_constrained(lambda x: fn(*x)[0], 
                             lambda x: fn(*x)[1],
                             [1,1,1])
    return a

which can produce a significant speedup. (I put in the sleeps to make the one-call time longer-- originally I did multiple runs, but the caching means that I wasn't measuring what I wanted to.)

sage: time a = get(complicated)
Time: CPU 0.06 s, Wall: 7.67 s
sage: time b = get(complicated_cached)
Time: CPU 0.03 s, Wall: 3.83 s

UPDATE:

When numpy gets involved caching the function is a little trickier, because we need an immutable key. We can get around the problem by coercing to a tuple:

def func(p):
    f = -p[0]-p[1]+50
    c_1 = p[0]-45
    c_2 = p[1]-5
    c_3 = -50*p[0]-24*p[1]+2400
    c_4 = -30*p[0]-33*p[1]+2100
    return f, c_1, c_2, c_3, c_4

func_cached = CachedFunction(func)
func_wrap = lambda x: func_cached(tuple(x))

def get2(fn):
    a = minimize_constrained(lambda x: fn(x)[0], 
                             [lambda x: fn(x)[1],lambda x: fn(x)[2],lambda x: fn(x)[3],lambda x: fn(x)[4]],
                             [2,3])

which produces:

sage: time get2(func)
Time: CPU 0.10 s, Wall: 0.10 s
sage: time get2(func_wrap)
Time: CPU 0.02 s, Wall: 0.02 s