SciPy, optimasi jeung kaayaan

SciPy, optimasi jeung kaayaan

SciPy (dibaca sai pie) mangrupikeun pakét matematika dumasar-numpy anu ogé kalebet perpustakaan C sareng Fortran. SciPy ngarobih sési Python interaktif anjeun janten lingkungan élmu data lengkep sapertos MATLAB, IDL, Octave, R, atanapi SciLab.

Dina artikel ieu kami baris kasampak di téknik dasar programming matematik - ngarengsekeun masalah optimasi kondisional pikeun fungsi skalar sababaraha variabel ngagunakeun pakét scipy.optimize. Algoritma optimasi unconstrained geus dibahas dina tulisan panungtung. Pitulung anu langkung lengkep sareng up-to-date dina fungsi scipy tiasa didapet nganggo paréntah pitulung (), Shift + Tab atanapi di dokuméntasi resmi.

perkenalan

Antarbeungeut umum pikeun ngarengsekeun masalah optimasi kondisional sareng henteu terbatas dina pakét scipy.optimize disayogikeun ku fungsi. minimize(). Nanging, dipikanyaho yén teu aya metode universal pikeun ngarengsekeun sadaya masalah, janten pilihan metode anu nyukupan, sapertos biasa, tumiba dina taktak panalungtik.
Algoritma optimasi anu luyu ditunjukkeun nganggo argumen fungsi minimize(..., method="").
Pikeun optimasi kondisional hiji fungsi sababaraha variabel, palaksanaan sahiji metodeu di handap ieu sadia:

  • trust-constr - milarian minimum lokal di daérah kapercayaan. Artikel Wiki, artikel ngeunaan Habré;
  • SLSQP - programming kuadrat sequential kalawan konstrain, métode Newtonian pikeun ngarengsekeun sistem Lagrange. Artikel Wiki.
  • TNC - Dipotong Newton Konstrain, jumlah kawates iterations, alus pikeun fungsi nonlinier kalawan jumlah badag variabel bebas. Artikel Wiki.
  • L-BFGS-B - métode ti tim Broyden-Fletcher-Goldfarb-Shanno, dilaksanakeun kalawan ngurangan konsumsi memori alatan loading parsial vektor ti matrix Hessian. Artikel Wiki, artikel ngeunaan Habré.
  • COBYLA - MARE Konstrain Optimasi Ku Linear Approximation, konstrain optimasi kalawan pendekatan linier (tanpa itungan gradién). Artikel Wiki.

Gumantung kana metode anu dipilih, kaayaan sareng larangan pikeun ngarengsekeun masalah diatur béda:

  • objék kelas Bounds pikeun métode L-BFGS-B, TNC, SLSQP, trust-constr;
  • daptar (min, max) pikeun métode sarua L-BFGS-B, TNC, SLSQP, trust-constr;
  • hiji obyék atawa daptar objék LinearConstraint, NonlinearConstraint pikeun COBYLA, SLSQP, métode trust-constr;
  • kamus atawa daptar kamus {'type':str, 'fun':callable, 'jac':callable,opt, 'args':sequence,opt} pikeun COBYLA, métode SLSQP.

Outline artikel:
1) Pertimbangkeun pamakean algoritma optimasi kondisional di daérah amanah (metode = "trust-constr") kalayan konstrain anu ditetepkeun salaku objék Bounds, LinearConstraint, NonlinearConstraint ;
2) Pertimbangkeun program sequential nganggo metode kuadrat pangleutikna (metode = "SLSQP") kalayan larangan anu ditetepkeun dina bentuk kamus {'type', 'fun', 'jac', 'args'};
3) Nganalisis conto optimasi produk anu diproduksi nganggo conto studio wéb.

Conditional optimization method="trust-constr"

Palaksanaan métode trust-constr dumasarkeun kana EQSQP pikeun masalah jeung konstrain tina bentuk sarua jeung saterusna perjalanan pikeun masalah sareng konstrain dina bentuk kateusaruaan. Kadua metodeu dilaksanakeun ku algoritma pikeun milarian minimum lokal di daérah kapercayaan sareng cocog pikeun masalah skala ageung.

Rumusan matematik tina masalah milarian minimum dina bentuk umum:

SciPy, optimasi jeung kaayaan

SciPy, optimasi jeung kaayaan

SciPy, optimasi jeung kaayaan

Pikeun konstrain sarua ketat, wates handap diatur sarua jeung wates luhur SciPy, optimasi jeung kaayaan.
Pikeun konstrain hiji arah, wates luhur atawa handap disetel np.inf kalawan tanda pakait.
Anggap perlu pikeun manggihan minimum hiji fungsi Rosenbrock dipikawanoh dua variabel:

SciPy, optimasi jeung kaayaan

Dina hal ieu, larangan di handap ieu diatur dina domain definisi na:

SciPy, optimasi jeung kaayaan

SciPy, optimasi jeung kaayaan

SciPy, optimasi jeung kaayaan

SciPy, optimasi jeung kaayaan

SciPy, optimasi jeung kaayaan

SciPy, optimasi jeung kaayaan

Dina kasus urang, aya solusi unik dina titik SciPy, optimasi jeung kaayaan, anu ngan ukur larangan kahiji sareng kaopat anu valid.
Hayu urang ngaliwat larangan ti handap ka luhur sareng tingali kumaha urang tiasa nyeratna dina scipy.
larangan SciPy, optimasi jeung kaayaan и SciPy, optimasi jeung kaayaan hayu urang ngartikeun eta ngagunakeun obyék Bounds.

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

larangan SciPy, optimasi jeung kaayaan и SciPy, optimasi jeung kaayaan Hayu urang nulis dina wangun linier:

SciPy, optimasi jeung kaayaan

Hayu urang ngartikeun konstrain ieu salaku obyék LinearConstraint:

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

Sareng tungtungna konstrain nonlinier dina bentuk matriks:

SciPy, optimasi jeung kaayaan

Urang nangtukeun matriks Jacobian pikeun konstrain ieu sareng kombinasi linier tina matriks Hessian sareng véktor arbitrér. SciPy, optimasi jeung kaayaan:

SciPy, optimasi jeung kaayaan

SciPy, optimasi jeung kaayaan

Ayeuna urang bisa nangtukeun konstrain nonlinier salaku hiji obyék 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)

Lamun ukuranana badag, matriks ogé bisa dieusian dina formulir sparse:

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)

atawa salaku objék 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 jeung kaayaan merlukeun loba usaha , Anjeun tiasa make kelas hiji HessianUpdateStrategy. Strategi di handap ieu sayogi: BFGS и SR1.

from scipy.optimize import BFGS

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

The Hessian ogé bisa diitung ngagunakeun béda terhingga:

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

Matriks Jacobian pikeun konstrain ogé tiasa diitung nganggo bédana terbatas. Sanajan kitu, dina hal ieu matriks Hessian teu bisa diitung ngagunakeun béda terhingga. Hessian kedah dihartikeun salaku fungsi atanapi nganggo kelas HessianUpdateStrategy.

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

Solusi pikeun masalah optimasi sapertos kieu:

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]

Upami diperlukeun, fungsi keur ngitung Hessian bisa dihartikeun ngagunakeun 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)

atawa produk tina Hessian jeung véktor wenang ngaliwatan 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)

Alternatipna, turunan kahiji jeung kadua tina fungsi nu keur dioptimalkeun bisa diitung kira. Salaku conto, Hessian tiasa dideukeutan nganggo fungsina SR1 (perkiraan kuasi-Newtonian). Gradién tiasa dikira-kira ku bédana anu terbatas.

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)

Métode optimasi kondisional = "SLSQP"

Metodeu SLSQP dirancang pikeun ngajawab masalah ngaminimalkeun fungsi dina bentuk:

SciPy, optimasi jeung kaayaan

SciPy, optimasi jeung kaayaan

SciPy, optimasi jeung kaayaan

SciPy, optimasi jeung kaayaan

di mana SciPy, optimasi jeung kaayaan и SciPy, optimasi jeung kaayaan - susunan indéks ekspresi ngajéntrékeun larangan dina bentuk sarua atawa kateusaruaan. SciPy, optimasi jeung kaayaan - susunan wates handap jeung luhur pikeun domain tina harti fungsi.

Konstrain linier jeung nonlinier digambarkeun dina wangun kamus kalawan konci 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])
          }

Pilarian pikeun minimum dilaksanakeun sapertos kieu:

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 ]

Conto Optimasi

Dina sambungan jeung transisi ka struktur téhnologis kalima, hayu urang nempo optimasi produksi ngagunakeun conto hiji studio web, nu brings kami panghasilan leutik tapi stabil. Hayu urang ngabayangkeun diri urang salaku diréktur galley nu ngahasilkeun tilu jenis produk:

  • x0 - ngajual kaca badarat, ti 10 tr.
  • x1 - situs web perusahaan, ti 20 tr.
  • x2 - toko online, ti 30 tr.

Tim kerja ramah kami ngawengku opat juniors, dua middles sarta hiji senior. Dana waktos kerja bulanan maranéhna:

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

Hayu kahiji sadia junior méakkeun (0, 1, 2) jam dina ngembangkeun sarta deployment sahiji situs tina tipe (x10, x20, x30), tengah - (7, 15, 20), senior - (5, 10, 15). ) jam tina waktos pangalusna dina hirup anjeun.

Sapertos diréktur biasa, urang hoyong maksimalkeun kauntungan bulanan. Léngkah munggaran pikeun suksés nyaéta nuliskeun fungsi tujuan value sakumaha jumlah panghasilan tina produk dihasilkeun per bulan:

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

Ieu sanés kasalahan; nalika milarian maksimal, fungsi tujuan diminimalkeun ku tanda sabalikna.

Léngkah satuluyna nyaéta nyaram pagawé urang tina overworking sareng ngenalkeun larangan dina jam gawé:

SciPy, optimasi jeung kaayaan

Naon anu sarua:

SciPy, optimasi jeung kaayaan

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 nyaéta yén kaluaran produk ngan ukur positip:

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

Sarta pamustunganana, asumsi paling rosy éta alatan harga low jeung kualitas luhur, antrian konsumén wareg terus baris pikeun urang. Urang bisa milih volume produksi bulanan sorangan, dumasar kana ngarengsekeun masalah optimasi konstrain jeung 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]

Hayu urang buleud sacara bébas kana sakabeh angka jeung ngitung beban bulanan rowers kalawan distribusi optimal produk x = (8, 6, 3) :

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

Kacindekan: supados sutradara nampi maksimal anu pantes, optimal pikeun nyiptakeun 8 halaman badarat, 6 situs ukuran sedeng sareng 3 toko per bulan. Dina hal ieu, senior kudu bajak tanpa pilari ka luhur tina mesin, beban tina middles bakal kurang leuwih 2/3, juniors kirang ti satengah.

kacindekan

Tulisan éta ngajelaskeun téknik dasar pikeun damel sareng bungkusan scipy.optimize, dipaké pikeun ngajawab masalah minimization kondisional. Pribadi kuring nganggo scipy murni pikeun tujuan akademik, naha éta conto anu dipasihkeun sipatna humoris.

Seueur téori sareng conto maya tiasa dipendakan, contona, dina buku I.L. Akulich "Programming Matematika dina conto sareng masalah." Langkung aplikasi hardcore scipy.optimize ngawangun struktur 3D tina sakumpulan gambar (artikel ngeunaan Habré) tiasa ditingali dina scipy-buku masak.

Sumber utama inpormasi nyaéta docs.scipy.organu hoyong nyumbang kana tarjamahan ieu sareng bagian anu sanés scipy Wilujeng sumping di GitHub.

Спасибо méphistophées pikeun partisipasi dina persiapan publikasi.

sumber: www.habr.com

Tambahkeun komentar