SciPy, optimasi karo kahanan

SciPy, optimasi karo kahanan

SciPy (diucapake sai pie) minangka paket matematika basis numpy sing uga kalebu perpustakaan C lan Fortran. SciPy ngowahi sesi Python interaktif sampeyan dadi lingkungan ilmu data lengkap kaya MATLAB, IDL, Octave, R, utawa SciLab.

Ing artikel iki, kita bakal katon ing Techniques dhasar saka program matématika - mecahaken masalah Optimization kondisional kanggo fungsi skalar saka sawetara variabel nggunakake paket scipy.optimize. Algoritma optimasi tanpa watesan wis dibahas ing artikel pungkasan. Bantuan luwih rinci lan up-to-date ing fungsi scipy tansah bisa dipikolehi nggunakake printah bantuan (), Shift + Tab utawa ing dokumentasi resmi.

Pambuka

Antarmuka umum kanggo ngrampungake masalah optimasi kondisional lan tanpa watesan ing paket scipy.optimize diwenehake dening fungsi kasebut. minimize(). Nanging, dingerteni yen ora ana cara universal kanggo ngrampungake kabeh masalah, mula pilihan metode sing nyukupi, kaya biasane, ana ing pundhak peneliti.
Algoritma optimasi sing cocog ditemtokake nggunakake argumen fungsi minimize(..., method="").
Kanggo optimasi kondisional fungsi saka sawetara variabel, implementasine saka cara ing ngisor iki kasedhiya:

  • trust-constr - nelusuri minimal lokal ing wilayah kapercayan. Artikel Wiki, artikel ing Habré;
  • SLSQP - pemrograman kuadrat urutan kanthi kendala, metode Newtonian kanggo ngrampungake sistem Lagrange. Artikel Wiki.
  • TNC - Dipotong Newton Watesan, nomer winates saka iterasi, apik kanggo fungsi nonlinear karo nomer akeh variabel bebas. Artikel Wiki.
  • L-BFGS-B - cara saka tim Broyden-Fletcher-Goldfarb-Shanno, diimplementasikake kanthi konsumsi memori sing suda amarga ngemot sebagian vektor saka matriks Hessian. Artikel Wiki, artikel ing Habré.
  • COBYLA - Optimasi Watesan MARE Miturut Perkiraan Linear, optimasi sing dibatasi kanthi perkiraan linear (tanpa pitungan gradien). Artikel Wiki.

Gumantung ing metode sing dipilih, kahanan lan watesan kanggo ngrampungake masalah kasebut beda-beda:

  • obyek kelas Bounds kanggo metode L-BFGS-B, TNC, SLSQP, trust-constr;
  • dhaftar (min, max) kanggo cara padha L-BFGS-B, TNC, SLSQP, dateng-constr;
  • obyek utawa dhaptar obyek LinearConstraint, NonlinearConstraint kanggo COBYLA, SLSQP, cara kepercayaan-constr;
  • kamus utawa daftar kamus {'type':str, 'fun':callable, 'jac':callable,opt, 'args':sequence,opt} kanggo COBYLA, metode SLSQP.

Rangka artikel:
1) Coba nggunakake algoritma optimasi kondisional ing wilayah kepercayaan (metode = "trust-constr") kanthi watesan sing ditemtokake minangka obyek Bounds, LinearConstraint, NonlinearConstraint ;
2) Coba pemrograman sekuensial nggunakake metode kuadrat paling sithik (metode = "SLSQP") kanthi watesan sing ditemtokake ing wangun kamus {'type', 'fun', 'jac', 'args'};
3) Analisis conto optimasi produk sing diprodhuksi nggunakake conto studio web.

Conditional optimization method="trust-constr"

Implementasine metode trust-constr adhedhasar EQSQP kanggo masalah karo alangan saka wangun kesetaraan lan ing TRIP kanggo masalah karo alangan ing wangun inequalities. Loro-lorone cara dileksanakake dening algoritma kanggo nemokake minimal lokal ing wilayah kapercayan lan uga cocog kanggo masalah gedhe-ukuran.

Formulasi matematika saka masalah nemokake minimal ing wangun umum:

SciPy, optimasi karo kahanan

SciPy, optimasi karo kahanan

SciPy, optimasi karo kahanan

Kanggo watesan kesetaraan sing ketat, wates ngisor disetel padha karo wates ndhuwur SciPy, optimasi karo kahanan.
Kanggo watesan siji arah, watesan ndhuwur utawa ngisor disetel np.inf kanthi tandha sing cocog.
Dadi perlu kanggo nemokake minimal fungsi Rosenbrock sing dikenal saka rong variabel:

SciPy, optimasi karo kahanan

Ing kasus iki, watesan ing ngisor iki disetel ing domain definisi:

SciPy, optimasi karo kahanan

SciPy, optimasi karo kahanan

SciPy, optimasi karo kahanan

SciPy, optimasi karo kahanan

SciPy, optimasi karo kahanan

SciPy, optimasi karo kahanan

Ing kasus kita, ana solusi unik ing titik kasebut SciPy, optimasi karo kahanan, sing mung watesan pisanan lan papat sing bener.
Ayo liwat watesan saka ngisor menyang ndhuwur lan ndeleng carane kita bisa nulis ing scipy.
Watesan SciPy, optimasi karo kahanan и SciPy, optimasi karo kahanan ayo netepake nggunakake obyek Bounds.

from scipy.optimize import Bounds
bounds = Bounds ([0, -0.5], [1.0, 2.0])

Watesan SciPy, optimasi karo kahanan и SciPy, optimasi karo kahanan Ayo ditulis ing wangun linear:

SciPy, optimasi karo kahanan

Ayo nemtokake watesan kasebut minangka obyek LinearConstraint:

import numpy as np
from scipy.optimize import LinearConstraint
linear_constraint = LinearConstraint ([[1, 2], [2, 1]], [-np.inf, 1], [1, 1])

Lan pungkasane watesan nonlinier ing wangun matriks:

SciPy, optimasi karo kahanan

Kita nemtokake matriks Jacobian kanggo kendala iki lan kombinasi linear saka matriks Hessian kanthi vektor arbitrer. SciPy, optimasi karo kahanan:

SciPy, optimasi karo kahanan

SciPy, optimasi karo kahanan

Saiki kita bisa nemtokake watesan nonlinear minangka obyek NonlinearConstraint:

from scipy.optimize import NonlinearConstraint

def cons_f(x):
     return [x[0]**2 + x[1], x[0]**2 - x[1]]

def cons_J(x):
     return [[2*x[0], 1], [2*x[0], -1]]

def cons_H(x, v):
     return v[0]*np.array([[2, 0], [0, 0]]) + v[1]*np.array([[2, 0], [0, 0]])

nonlinear_constraint = NonlinearConstraint(cons_f, -np.inf, 1, jac=cons_J, hess=cons_H)

Yen ukurane gedhe, matriks uga bisa ditemtokake ing wangun jarang:

from scipy.sparse import csc_matrix

def cons_H_sparse(x, v):
     return v[0]*csc_matrix([[2, 0], [0, 0]]) + v[1]*csc_matrix([[2, 0], [0, 0]])

nonlinear_constraint = NonlinearConstraint(cons_f, -np.inf, 1,
                                            jac=cons_J, hess=cons_H_sparse)

utawa minangka obyek LinearOperator:

from scipy.sparse.linalg import LinearOperator

def cons_H_linear_operator(x, v):
    def matvec(p):
        return np.array([p[0]*2*(v[0]+v[1]), 0])
    return LinearOperator((2, 2), matvec=matvec)

nonlinear_constraint = NonlinearConstraint(cons_f, -np.inf, 1,
                                jac=cons_J, hess=cons_H_linear_operator)

Nalika ngitung matriks Hessian SciPy, optimasi karo kahanan mbutuhake akèh gaweyan, sampeyan bisa nggunakake kelas HessianUpdateStrategy. Sastranegara ing ngisor iki kasedhiya: BFGS и SR1.

from scipy.optimize import BFGS

nonlinear_constraint = NonlinearConstraint(cons_f, -np.inf, 1, jac=cons_J, hess=BFGS())

Hessian uga bisa diwilang nggunakake beda-beda winates:

nonlinear_constraint = NonlinearConstraint (cons_f, -np.inf, 1, jac = cons_J, hess = '2-point')

Matriks Jacobian kanggo kendala uga bisa diwilang nggunakake beda wates. Nanging, ing kasus iki matriks Hessian ora bisa diwilang nggunakake beda wates. Hessian kudu ditetepake minangka fungsi utawa nggunakake kelas HessianUpdateStrategy.

nonlinear_constraint = NonlinearConstraint (cons_f, -np.inf, 1, jac = '2-point', hess = BFGS ())

Solusi kanggo masalah optimasi katon kaya iki:

from scipy.optimize import minimize
from scipy.optimize import rosen, rosen_der, rosen_hess, rosen_hess_prod

x0 = np.array([0.5, 0])
res = minimize(rosen, x0, method='trust-constr', jac=rosen_der, hess=rosen_hess,
                constraints=[linear_constraint, nonlinear_constraint],
                options={'verbose': 1}, bounds=bounds)
print(res.x)

`gtol` termination condition is satisfied.
Number of iterations: 12, function evaluations: 8, CG iterations: 7, optimality: 2.99e-09, constraint violation: 1.11e-16, execution time: 0.033 s.
[0.41494531 0.17010937]

Yen perlu, fungsi kanggo ngitung Hessian bisa ditetepake nggunakake kelas LinearOperator

def rosen_hess_linop(x):
    def matvec(p):
        return rosen_hess_prod(x, p)
    return LinearOperator((2, 2), matvec=matvec)

res = minimize(rosen, x0, method='trust-constr', jac=rosen_der, hess=rosen_hess_linop,
                 constraints=[linear_constraint, nonlinear_constraint],
                 options={'verbose': 1}, bounds=bounds)

print(res.x)

utawa produk saka Hessian lan vektor kasepakatan liwat parameter hessp:

res = minimize(rosen, x0, method='trust-constr', jac=rosen_der, hessp=rosen_hess_prod,
                constraints=[linear_constraint, nonlinear_constraint],
                options={'verbose': 1}, bounds=bounds)
print(res.x)

Utawa, turunan pisanan lan kaloro saka fungsi sing dioptimalake bisa dikira-kira. Contone, Hessian bisa dikira nggunakake fungsi kasebut SR1 (perkiraan kuasi-Newtonian). Gradien bisa dikira-kira kanthi beda-beda sing winates.

from scipy.optimize import SR1
res = minimize(rosen, x0, method='trust-constr',  jac="2-point", hess=SR1(),
               constraints=[linear_constraint, nonlinear_constraint],
               options={'verbose': 1}, bounds=bounds)
print(res.x)

Metode optimasi kondisional = "SLSQP"

Metode SLSQP dirancang kanggo ngatasi masalah minimalake fungsi ing wangun:

SciPy, optimasi karo kahanan

SciPy, optimasi karo kahanan

SciPy, optimasi karo kahanan

SciPy, optimasi karo kahanan

Ngendi SciPy, optimasi karo kahanan и SciPy, optimasi karo kahanan - set indeks ekspresi sing njlèntrèhaké watesan ing wangun podo utawa inequalities. SciPy, optimasi karo kahanan - set wates ngisor lan ndhuwur kanggo domain definisi fungsi.

Watesan linear lan nonlinear diterangake ing wangun kamus kanthi tombol type, fun и jac.

ineq_cons = {'type': 'ineq',
             'fun': lambda x: np.array ([1 - x [0] - 2 * x [1],
                                          1 - x [0] ** 2 - x [1],
                                          1 - x [0] ** 2 + x [1]]),
             'jac': lambda x: np.array ([[- 1.0, -2.0],
                                          [-2 * x [0], -1.0],
                                          [-2 * x [0], 1.0]])
            }

eq_cons = {'type': 'eq',
           'fun': lambda x: np.array ([2 * x [0] + x [1] - 1]),
           'jac': lambda x: np.array ([2.0, 1.0])
          }

Panelusuran minimal ditindakake kaya ing ngisor iki:

x0 = np.array([0.5, 0])
res = minimize(rosen, x0, method='SLSQP', jac=rosen_der,
               constraints=[eq_cons, ineq_cons], options={'ftol': 1e-9, 'disp': True},
               bounds=bounds)

print(res.x)

Optimization terminated successfully.    (Exit mode 0)
            Current function value: 0.34271757499419825
            Iterations: 4
            Function evaluations: 5
            Gradient evaluations: 4
[0.41494475 0.1701105 ]

Tuladha Optimization

Gegayutan karo transisi menyang struktur teknologi kaping lima, ayo goleki optimasi produksi nggunakake conto studio web, sing ngasilake penghasilan cilik nanging stabil. Coba bayangake awake dhewe minangka direktur galley sing ngasilake telung jinis produk:

  • x0 - adol kaca kebangkrutan, saka 10 tr.
  • x1 - situs web perusahaan, saka 20 tr.
  • x2 - toko online, saka 30 tr.

Tim kerja sing ramah kalebu papat junior, loro tengah lan siji senior. Dana wektu kerja saben wulan:

  • Juni: 4 * 150 = 600 чел * час,
  • tengah: 2 * 150 = 300 чел * час,
  • senur: 150 чел * час.

Ayo junior pisanan kasedhiya nglampahi (0, 1, 2) jam ing pembangunan lan panyebaran siji situs saka jinis (x10, x20, x30), tengah - (7, 15, 20), senior - (5, 10, 15 ) jam wektu paling apik ing urip sampeyan.

Kaya direktur normal, kita pengin nggedhekake bathi saben wulan. Langkah pisanan kanggo sukses yaiku nulis fungsi objektif value minangka jumlah penghasilan saka produk sing diprodhuksi saben sasi:

def value(x):
    return - 10*x[0] - 20*x[1] - 30*x[2]

Iki dudu kesalahan; nalika nggoleki maksimal, fungsi objektif diminimalisir kanthi tandha ngelawan.

Langkah sabanjure yaiku nglarang karyawan kita kerja banget lan ngenalake watesan babagan jam kerja:

SciPy, optimasi karo kahanan

Apa sing padha:

SciPy, optimasi karo kahanan

ineq_cons = {'type': 'ineq',
             'fun': lambda x: np.array ([600 - 10 * x [0] - 20 * x [1] - 30 * x[2],
                                         300 - 7  * x [0] - 15 * x [1] - 20 * x[2],
                                         150 - 5  * x [0] - 10 * x [1] - 15 * x[2]])
            }

Watesan resmi yaiku output produk mung kudu positif:

bnds = Bounds ([0, 0, 0], [np.inf, np.inf, np.inf])

Lan pungkasane, asumsi sing paling apik yaiku amarga rega murah lan kualitas dhuwur, antrian pelanggan sing puas terus-terusan. Kita bisa milih volume produksi saben wulan dhéwé, adhedhasar mecahaken masalah Optimization diwatesi karo scipy.optimize:

x0 = np.array([10, 10, 10])
res = minimize(value, x0, method='SLSQP', constraints=ineq_cons, bounds=bnds)
print(res.x)

[7.85714286 5.71428571 3.57142857]

Ayo dibunderake kanthi longgar menyang nomer wutuh lan ngitung beban saben wulan para pendayung kanthi distribusi produk sing optimal x = (8, 6, 3) :

  • Juni: 8 * 10 + 6 * 20 + 3 * 30 = 290 чел * час;
  • tengah: 8 * 7 + 6 * 15 + 3 * 20 = 206 чел * час;
  • senur: 8 * 5 + 6 * 10 + 3 * 15 = 145 чел * час.

Kesimpulan: supaya direktur entuk maksimal sing pantes, paling optimal kanggo nggawe 8 kaca kebangkrutan, 6 situs ukuran medium lan 3 toko saben wulan. Ing kasus iki, senior kudu bajak tanpa katon munggah saka mesin, beban tengah bakal kira-kira 2/3, junior kurang saka setengah.

kesimpulan

Artikel kasebut nerangake teknik dhasar kanggo nggarap paket kasebut scipy.optimize, digunakake kanggo ngatasi masalah minimalake kondisional. Secara pribadi aku nggunakake scipy murni kanggo tujuan akademisi, mula conto sing diwènèhaké iki asipat komik.

Akeh teori lan conto virtual bisa ditemokake, contone, ing buku I.L. Akulich "Program matematika ing conto lan masalah." Aplikasi hardcore liyane scipy.optimize kanggo mbangun struktur 3D saka sakumpulan gambar (artikel ing Habré) bisa dideleng ing scipy-buku masak.

Sumber informasi utama yaiku docs.scipy.orgsing pengin nyumbang kanggo terjemahan iki lan bagean liyane scipy Welcome kanggo GitHub.

Спасибо mephistophees kanggo partisipasi ing preparation saka publikasi.

Source: www.habr.com

Add a comment