约束优化,其中约束作为目标函数的一部分进行计算

2024-10-02 00:41:41 发布

您现在位置:Python中文网/ 问答频道 /正文

我做了一个函数f,它需要很长时间才能运行。约束在f的例程末尾计算。如何在不计算f两次的情况下将这些约束返回给cobyla?在

import numpy as np
from scipy.optimize import fmin_cobyla as mini
def f(x, returncons=True):
    if returncons: return x[1] - x[0]
    else: return (x[0] - 2)**2 + 4 * (x[1] -x[0]**2)**2

x_opt = mini(f, [1., 1.], args=(False,), cons=f)

Tags: 函数fromimportnumpyreturnasnp情况
1条回答
网友
1楼 · 发布于 2024-10-02 00:41:41

LRU缓存

这是实现paulpanzer的建议,它依赖于python3的特性@lru_cache。我们不能直接将这个decorator应用于目标函数,因为它接收一个NumPy数组,它是可变的,因此不能散列。所以我们需要两个函数:

  • func_with_cons计算给定标量参数的目标和约束。在
  • f调用func_with_cons,并根据returncons参数返回目标或约束。在

注意,我们在调用fmin_cobyla时需要consargs参数,因为没有它,相同的额外参数args将传递给约束函数。在

from scipy.optimize import fmin_cobyla as mini
from functools import lru_cache

@lru_cache(maxsize=32)
def func_with_cons(x0, x1):
    return (x0 - 2)**2 + 4 * (x1 -x0**2)**2, x0 - x1

def f(x, returncons=True):
    value, cons = func_with_cons(x[0], x[1])
    return cons if returncons else value

func_with_cons.cache_clear()
x_opt = mini(f, (1., 1.), cons=f, args=(False,), consargs=())
print(x_opt)
print(func_with_cons.cache_info())

输出:

^{pr2}$

所以,缓存起作用了。我将约束从x1-x0更改为x0-x1,以证明它也有效(原始约束x1-x0是由该函数的全局最小值满足的,因此它不会对结果产生任何影响)。在

缓存大小可以小得多:使用maxsize=2我们将有40次命中(而上面的大小是41次)。在

全局变量

这是在执行雅各布·洛文的建议。函数f将约束存储在一个全局变量中,cons从中检索约束。全局函数的使用有明显的缺点,但是同样,这在Python2.7中是可行的。在

def f(x):
    global stored_cons
    stored_cons = x[0] - x[1]
    return (x[0] - 2)**2 + 4 * (x[1] -x[0]**2)**2

def cons(x):
    return stored_cons

x0 = [1., 1.] 
f(x0)  # called to initialize stored_cons        
x_opt = mini(f, x0, cons=cons) 

这将返回[ 1.14491021, 1.14491021],因为约束不允许全局最小值[2,4]。在

相关问题 更多 >

    热门问题