簡體   English   中英

在 python 中查找多變量多項式的最小值/最大值

[英]Finding the minima/maxima of a multi-variable polynomial in python

我有以下多項式方程,我想找到它的局部最小值和最大值。

多項式方程

我將 function 定義如下。 It uses a flatten function to flatten the nested list, I'll include it for testing purposes (found it here http://rightfootin.blogspot.com/2006/09/more-on-python-flatten.html )

扁平化列表

from itertools import combinations
import math

def flatten(l, ltypes=(list, tuple)):
    ltype = type(l)
    l = list(l)
    i = 0
    while i < len(l):
        while isinstance(l[i], ltypes):
            if not l[i]:
                l.pop(i)
                i -= 1
                break
            else:
                l[i:i + 1] = l[i]
        i += 1
    return ltype(l)
   

我的多項式

   def poly(coefficients, factors):
  
       #quadratic terms
       constant = 1
       singles = factors
       products = [math.prod(c) for c in combinations(factors, 2)]
       squares = [f**2 for f in factors]

       sequence = flatten([constant, singles, products, squares])

       z = sum([math.prod(i) for i in zip(coefficients, sequence)])


       return z

它采用的 arguments 是一個系數列表,例如:

coefs = [12.19764959, -1.8233151, 2.50952816,-1.56344375, 1.00003828, -1.72128301, -2.54254877, -1.20377309, 5.53510616, 2.94755653, 4.83759279, -0.85507208, -0.48007208, -3.70507208, -0.27007208]

以及因子或變量值列表:

factors = [0.4714, 0.4714, -0.4714, 0.4714]

將它們插入並計算多項式的結果。 我這樣寫的原因是因為變量(因素)的數量會隨着擬合而變化,所以我想保持它的靈活性。 我現在想在 function 達到其最大值和最小值的某個范圍內(假設在 -1 和 1 之間)找到“因子”值的組合。 如果 function 是“硬編碼”的,我可以使用 scipy.optimize,但我不知道如何讓它按原樣工作。

另一種選擇是蠻力網格搜索(我目前使用),但是一旦你有超過 2 個變量,它就會非常慢,尤其是在小步長的情況下。 可能沒有真正的最小值/最大值,其中斜率 == 0 在界限內,但只要我能得到最大值和最小值就可以了。

好的,我想通了。 這是兩件非常愚蠢的事情:

  1. function 中 arguments 的順序必須顛倒,因此第一個參數(我想要優化的那個)是“因子”或 X 值,然后是系數。 這樣,可以將相同大小的數組用作 X0,並且可以將系數用作 args。

  2. 這還不夠,因為如果數組是輸入,function 將返回一個數組。 我剛剛向 function 本身添加了一個 factor = list(factors) 以將其放入正確的形狀。

新的 function:

def poly(factors, coefficients):
   
   factors = list(factors)
   
   #quadratic terms
   constant = 1
   singles = factors
   products = [math.prod(c) for c in combinations(factors, 2)]
   squares = [f**2 for f in factors]

   sequence = flatten([constant, singles, products, squares])

   z = sum([math.prod(i) for i in zip(coefficients, sequence)])


   return z

和優化:

coefs = [4.08050532, -0.47042713, -0.08200181, -0.54184481, -0.18515675, 
-0.96751856, -1.10814625, -1.7831592, 5.2763512, 2.83505438, 4.7082153, 
0.22988773, 1.06488773, -0.70011227, 1.42988773]
x0 = [0.1, 0.1, 0.1, 0.1]
minimize(poly,x0 = x0, args = coefs, bounds = ((-1,1),(-1,1),(-1,1),(-1,1)))

返回:

fun: -1.6736636102536673
hess_inv: <4x4 LbfgsInvHessProduct with dtype=float64>
jac: array([-2.10611305e-01,  2.19138777e+00, -8.16990766e+00, -1.11022302e-07])
message: 'CONVERGENCE: NORM_OF_PROJECTED_GRADIENT_<=_PGTOL'
nfev: 85
nit: 12
njev: 17
status: 0
success: True
x: array([1., -1.,1., 0.03327357])

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM