由于scipy SLSQP中不受干扰的约束导致的数学域错误最小化

时间:2016-11-02 04:25:37

标签: python scipy mathematical-optimization

考虑一个简单的问题:

max log(x)
subject to x >= 1e-4

使用scipy.optimize.minimize解决问题:

import numpy as np
from scipy.optimize import minimize
from math import log

def func(x):
    return log(x[0])

def func_deriv(x):
    return np.array([1 / x[0]])

cons = ({'type': 'ineq',
         'fun' : lambda x: x[0] - 1e-4,
         'jac' : lambda x: np.array([1])})
minimize(func, [1.0], jac=func_deriv, constraints=cons, method='SLSQP')

脚本遇到ValueError,因为log(x)的评估结果为负x。即使不满足约束,似乎也会评估函数值。

我了解在bounds中使用minimize()可以避免此问题,但这只是我原始问题的简化。在我的原始问题中,约束x >= 1e-4无法轻易地表示为x的范围,而是g(x) >= C形式,因此bounds无效。

1 个答案:

答案 0 :(得分:0)

如果我们只关心x > ε的函数值,则可以定义扩展域的安全函数。

log函数为例。可以用另一个三次函数扩展log,同时使桥点ε平滑:

safe_log(x) = log(x) if x > ε else a * (x - b)**3

要计算ab,我们必须满足:

log(ε) = a * (ε - b)**3
1 / ε = 3 * a * (ε - b)**2

因此safe_log函数:

eps = 1e-3

def safe_log(x):
    if x > eps:
        return log(x)
    logeps = log(eps)
    a = 1 / (3 * eps * (3 * logeps * eps)**2)
    b = eps * (1 - 3 * logeps)
    return a * (x - b)**3

它看起来像这样:

Plot of safe_log(x)