给定一些约束,最小化两个列表元素的峰值差异

问题描述

我想使用 scipy.optimize.minimize 方法最小化 list1[i] - list2[i] 的峰值差异。 list1 和 list2 中的元素是浮点数。

例如:

list1 = [50,50.5,52,53,55,55.5,56,57,60,61]

鉴于我有两个约束,如何最小化 list1[i] - list2[i]:

1. list2 = list1[0]

2. list2[i+1]-list2[i]

基本上list2中两个连续的元素之间的间隔不能超过1.5,list2的第一个元素就是list1的第一个元素。

也许除了 scipy.optimize.minimize 之外还有另一种方法,但我不知道该怎么做。 我认为 list2 的最佳值可能是: list2 = [50,54.5,58.5,60]

在这种情况下,峰值差为 1.5。 但也许算法会找到一个更优的解决方案,其中 list1 和 list2 的元素之间的差异更小。

这是我尝试过但失败的方法:

import numpy as np
from scipy.optimize import minimize

list1 = [50,61]
list2 = [list1[0]]

#Define objective
def peakDifference(*args):
    global list2
    peak_error = []
    for list1_i,list2_i in zip(list1,list2):
        peak_error.append(list1_i-list2_i)
    return max(peak_error)

peak_error = peakDifference()

#Define constraints
def constraint1(*args):
    for x in range(len(list2) - 1):
        return list2[x+1] - list2[x] - 1.5

con1 = {'type': 'ineq','fun': constraint1}

#Optimize
sol = minimize(peakDifference,list2,constraints=con1)



Traceback (most recent call last):   File "C:/Users/JumpStart/PycharmProjects/anglesimulation/venv/asdfgh.py",line 27,in <module>
    sol = minimize(peakDifference,constraints=con1)   File "C:\Users\JumpStart\anaconda3\lib\site-packages\scipy\optimize\_minimize.py",line 625,in minimize
    return _minimize_slsqp(fun,x0,args,jac,bounds,File "C:\Users\JumpStart\anaconda3\lib\site-packages\scipy\optimize\slsqp.py",line 412,in _minimize_slsqp
    a = _eval_con_normals(x,cons,la,n,m,meq,mieq)   File "C:\Users\JumpStart\anaconda3\lib\site-packages\scipy\optimize\slsqp.py",line 486,in _eval_con_normals
    a_ieq = vstack([con['jac'](x,*con['args'])   File "C:\Users\JumpStart\anaconda3\lib\site-packages\scipy\optimize\slsqp.py",in <listcomp>
    a_ieq = vstack([con['jac'](x,line 284,in cjac
    return approx_derivative(fun,x,method='2-point',File "C:\Users\JumpStart\anaconda3\lib\site-packages\scipy\optimize\_numdiff.py",line 426,in approx_derivative
    return _dense_difference(fun_wrapped,f0,h,line 497,in _dense_difference
    df = fun(x) - f0 TypeError: unsupported operand type(s) for -: 'NoneType' and 'NoneType'

Process finished with exit code 1

解决方法

自然语言处理模型

这是 NLP 模型的“工作”版本。该模型无法通过这种方式可靠地求解,因为它是不可微的。

import numpy as np
from scipy.optimize import minimize

list1 = np.array([50,50.5,52,53,55,55.5,56,57,60,61])
list1_0 = list1[0]
n = len(list1)

# our x variable will have one element less (first element is fixed)
list1x  = np.delete(list1,0)  # version with 1st element dropped
nx = len(list1x)

# objective function
# minimize the the maximum difference
# Notes:
#   - x excludes first element (they are the same by definition)
#   - this is non-differentiable so likely to be non-optimal
def maxDifference(x):
    return np.max(np.abs(list1x - x))

# n-1 constraints
def constraint1(x):
    return  1.5 - np.diff(np.insert(x,list1_0),1)

con1 = {'type': 'ineq','fun': constraint1}

#Optimize
x = 55*np.ones(nx)  # initial value
sol = minimize(maxDifference,x,constraints=con1)
sol

# optimal is: x = [51.25,51.25,52.75,54.25,54.75,56.25,57.75,59.25,60.25]
# obj = 0.75 

结果是:

     fun: 5.0
     jac: array([0.,0.,0.])
 message: 'Optimization terminated successfully'
    nfev: 20
     nit: 2
    njev: 2
  status: 0
 success: True
       x: array([51.5,53.,54.5,55.,56. ])

这不是最优的:目标是 5(而不是 0.75)。

LP 模型

LP 模型将找到经过验证的最佳解决方案。那可靠得多。例如:

import pulp as lp

list1 = [50,61]
n = len(list1)

model = pulp.LpProblem("Min_difference",pulp.LpMinimize)
x = lp.LpVariable.dicts("x",(i for i in range(n)))
z = lp.LpVariable("z")

# objective
model += z

# constraints
for i in range(n):
    model += z >= x[i]-list1[i]
    model += z >= list1[i]-x[i]
    
for i in range(n-1):
    model += x[i+1] - x[i] <= 1.5
    
model += x[0] == list1[0]

model.solve()
print(lp.LpStatus[model.status])
print("obj:",z.varValue)
print([x[i].varValue for i in range(n)])

这表明:

Optimal
obj: 0.75
[50.0,53.75,55.25,56.75,60.25]

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...