COByLA不终止

时间:2019-02-20 12:58:00

标签: python scipy

我有一个对cobyla的函数调用,它不会终止。 我想在给定的orthant中找到一些(多元)多项式的局部最小值。 我可以重现的最小示例如下。

import numpy as np
import scipy.optimize

A = np.array([[ 0,  0,  0,  0,  0,  0,  0,  2,  2,  2,  2,  6, 12,  4,  2,  2,  2,  2,  2,  2,  2,  2,  2,  3,  2,  3,  3,  3,  1,  2],
              [ 0,  0,  2,  2,  2,  4, 10,  0,  4,  4, 12,  4,  0,  2,  4,  0,  3,  4,  3,  3,  2,  3,  3,  4,  3,  2,  3,  3,  4,  3],
              [ 0,  4,  0,  6, 10, 10,  4,  4,  4,  8,  2,  0,  4,  2,  4,  2,  4,  4,  3,  4,  3,  5,  3,  4,  4,  4,  3,  4,  4,  4],
              [ 0,  0,  6,  0,  0,  6,  2, 12, 10,  0,  2,  8,  0,  8,  4,  2,  5,  3,  5,  3,  3,  4,  4,  4,  2,  3,  4,  4,  3,  4]])
b = np.array([ 3.81330727e+00,  1.30927853e+00,  1.89829563e+00,  1.55301205e+00,  2.05509780e+00,  4.72913144e+00,  8.64125139e+00,  6.78452109e+00,  1.97505381e+01,  8.10184002e+00,  8.56817472e+00, 1.76581791e+00,  6.90448362e+00,  8.44460914e-02,  1.52023325e+00, -1.97710183e+00, -1.66933212e-01, -2.71655065e-01, -2.03262146e+00, -6.74143747e-01, -1.53382538e+00, -9.94362458e-01, 1.86147837e-01, -6.23838626e-01,  1.04835921e+00,  3.49272629e-01, -6.47927068e-01, -4.69780766e-01,  1.48099164e-02,  3.61251102e-01])

x0 = np.array([  3.75422451,  -4.13253284, -46.27451838, -29.48396097])

def f(x):
  return np.dot(np.prod(np.power(x,A.T),axis = 1),b)

res = scipy.optimize.fmin_cobyla(f, x0, lambda x: x*np.array([1,-1,-1,-1]), disp = 3)

然后,代码的最后一行不会终止。 即使达到最大显示级别,我也不会获得一行输出。 更糟糕的是,Ctrl+C不会终止IPython中的计算(我假设代码停留在Fortran中)。

如何避免这个问题?

1 个答案:

答案 0 :(得分:0)

我相信您描述约束的方式存在问题。

我尝试了以下两种形式的代码,并且可以使用:

import numpy as np
import scipy.optimize

A = np.array([[ 0,  0,  0,  0,  0,  0,  0,  2,  2,  2,  2,  6, 12,  4,  2,  2,  2,  2,  2,  2,  2,  2,  2,  3,  2,  3,  3,  3,  1,  2],
              [ 0,  0,  2,  2,  2,  4, 10,  0,  4,  4, 12,  4,  0,  2,  4,  0,  3,  4,  3,  3,  2,  3,  3,  4,  3,  2,  3,  3,  4,  3],
              [ 0,  4,  0,  6, 10, 10,  4,  4,  4,  8,  2,  0,  4,  2,  4,  2,  4,  4,  3,  4,  3,  5,  3,  4,  4,  4,  3,  4,  4,  4],
              [ 0,  0,  6,  0,  0,  6,  2, 12, 10,  0,  2,  8,  0,  8,  4,  2,  5,  3,  5,  3,  3,  4,  4,  4,  2,  3,  4,  4,  3,  4]])
b = np.array([ 3.81330727e+00,  1.30927853e+00,  1.89829563e+00,  1.55301205e+00,  2.05509780e+00,  4.72913144e+00,  8.64125139e+00,  \
6.78452109e+00,  1.97505381e+01,  8.10184002e+00,  8.56817472e+00, 1.76581791e+00,  6.90448362e+00,  8.44460914e-02,  1.52023325e+00, \
-1.97710183e+00, -1.66933212e-01, -2.71655065e-01, -2.03262146e+00, -6.74143747e-01, -1.53382538e+00, -9.94362458e-01, 1.86147837e-01, \
-6.23838626e-01,  1.04835921e+00,  3.49272629e-01, -6.47927068e-01, -4.69780766e-01,  1.48099164e-02,  3.61251102e-01])

x0 = np.array([  3.75422451,  -4.13253284, -46.27451838, -29.48396097])

def fun(x):
  return np.dot(np.prod(np.power(x,A.T),axis = 1),b)

def constraint_func(x_in):
    factor = np.array([1,-1,-1,-1])
    constraints_list = []
    for i in range(len(x_in)):
        constraints_list.append({lambda x: x[i]*factor[i]})

res = scipy.optimize.fmin_cobyla(fun, x0, constraint_func, disp = 3)

使用Scipy库的另一个功能的另一种方法:

import numpy as np
import scipy.optimize

A = np.array([[ 0,  0,  0,  0,  0,  0,  0,  2,  2,  2,  2,  6, 12,  4,  2,  2,  2,  2,  2,  2,  2,  2,  2,  3,  2,  3,  3,  3,  1,  2],
              [ 0,  0,  2,  2,  2,  4, 10,  0,  4,  4, 12,  4,  0,  2,  4,  0,  3,  4,  3,  3,  2,  3,  3,  4,  3,  2,  3,  3,  4,  3],
              [ 0,  4,  0,  6, 10, 10,  4,  4,  4,  8,  2,  0,  4,  2,  4,  2,  4,  4,  3,  4,  3,  5,  3,  4,  4,  4,  3,  4,  4,  4],
              [ 0,  0,  6,  0,  0,  6,  2, 12, 10,  0,  2,  8,  0,  8,  4,  2,  5,  3,  5,  3,  3,  4,  4,  4,  2,  3,  4,  4,  3,  4]])
b = np.array([ 3.81330727e+00,  1.30927853e+00,  1.89829563e+00,  1.55301205e+00,  2.05509780e+00,  4.72913144e+00,  8.64125139e+00,  \
6.78452109e+00,  1.97505381e+01,  8.10184002e+00,  8.56817472e+00, 1.76581791e+00,  6.90448362e+00,  8.44460914e-02,  1.52023325e+00, \
-1.97710183e+00, -1.66933212e-01, -2.71655065e-01, -2.03262146e+00, -6.74143747e-01, -1.53382538e+00, -9.94362458e-01, 1.86147837e-01, \
-6.23838626e-01,  1.04835921e+00,  3.49272629e-01, -6.47927068e-01, -4.69780766e-01,  1.48099164e-02,  3.61251102e-01])

x0 = np.array([  3.75422451,  -4.13253284, -46.27451838, -29.48396097])

def fun(x):
  return np.dot(np.prod(np.power(x,A.T),axis = 1),b)

def constraint_func(x_in):
    factor = np.array([1,-1,-1,-1])
    constraints_list = []
    for i in range(len(x_in)):
        constraints_list.append({'type': 'ineq', 'fun': lambda x: x[i]*factor[i]})
    return constraints_list

constraints = constraint_func(x0)

res = scipy.optimize.minimize(fun, x0, method='COBYLA', constraints= constraints)
print(res)