
SciPy (útsprutsen sai pie) is in numpy-basearre wiskundepakket dat ek C- en Fortran-biblioteken omfettet. SciPy feroaret jo ynteraktive Python-sesje yn in folsleine gegevenswittenskiplike omjouwing lykas MATLAB, IDL, Octave, R, of SciLab.
Yn dit artikel sille wy sjen nei de basis techniken fan wiskundige programmearring - oplossen betingst optimalisearjen problemen foar in scalar funksje fan ferskate fariabelen mei help fan it pakket scipy.optimize. Unbeheinde optimisaasjealgoritmen binne al besprutsen yn . Mear detaillearre en aktualisearre help oer Scipy-funksjes kin altyd wurde krigen mei help () kommando, Shift+Tab of yn .
Ynlieding
In mienskiplike ynterface foar it oplossen fan sawol betingsten as ûnbeheinde optimisaasjeproblemen yn it pakket scipy.optimize wurdt levere troch de funksje minimize(). It is lykwols bekend dat der gjin universele metoade is foar it oplossen fan alle problemen, sadat de kar fan in adekwate metoade, lykas altyd, falt op 'e skouders fan' e ûndersiker.
It passende optimisaasjealgoritme wurdt oanjûn mei it funksjeargumint minimize(..., method="").
Foar betingste optimisaasje fan in funksje fan ferskate fariabelen binne ymplemintaasjes fan 'e folgjende metoaden beskikber:
trust-constr- sykje nei in lokaal minimum yn 'e fertrouwenregio. , ;SLSQP- sekwinsjele kwadratyske programmearring mei beheiningen, Newtoniaanske metoade foar it oplossen fan it Lagrange-systeem. .TNC- Truncated Newton Constrained, beheind oantal iteraasjes, goed foar net-lineêre funksjes mei in grut oantal ûnôfhinklike fariabelen. .L-BFGS-B- in metoade fan it Broyden-Fletcher-Goldfarb-Shanno-team, ymplementearre mei fermindere ûnthâldferbrûk troch in part laden fan fektors út 'e Hessyske matrix. , .COBYLA- MARE beheinde optimalisaasje troch lineêre approximaasje, beheinde optimalisaasje mei lineêre approximaasje (sûnder gradientberekkening). .
Ofhinklik fan 'e keazen metoade binne betingsten en beheiningen foar it oplossen fan it probleem oars ynsteld:
- klasse foarwerp
Boundsfoar metoaden L-BFGS-B, TNC, SLSQP, trust-constr; - de list
(min, max)foar deselde metoaden L-BFGS-B, TNC, SLSQP, trust-constr; - in objekt of in list mei objekten
LinearConstraint,NonlinearConstraintfoar COBYLA, SLSQP, trust-constr metoaden; - wurdboek of list fan wurdboeken
{'type':str, 'fun':callable, 'jac':callable,opt, 'args':sequence,opt}foar COBYLA, SLSQP metoaden.
Artikel oersjoch:
1) Beskôgje it gebrûk fan in betingst optimalisearjen algoritme yn 'e trustregio (metoade = "trust-constr") mei beheiningen oantsjutte as objekten Bounds, LinearConstraint, NonlinearConstraint ;
2) Beskôgje sekwinsjele programmearring mei de metoade fan it minste kwadraten (metoade = "SLSQP") mei beheiningen oantsjutte yn 'e foarm fan in wurdboek {'type', 'fun', 'jac', 'args'};
3) Analysearje in foarbyld fan optimisaasje fan produsearre produkten mei it foarbyld fan in webstudio.
Betingst optimalisearjen metoade = "trust-constr"
Utfiering fan de metoade trust-constr basearre op foar problemen mei beheinings fan de foarm fan gelikensens en op foar problemen mei beheiningen yn 'e foarm fan ûngelikens. Beide metoaden wurde ymplementearre troch algoritmen foar it finen fan in lokale minimum yn 'e fertrouwenregio en binne goed geskikt foar grutskalige problemen.
Wiskundige formulearring fan it probleem fan it finen fan in minimum yn algemiene foarm:



Foar strange gelikensensbeheiningen wurdt de ûndergrins gelyk oan de boppegrins ynsteld
.
Foar in iensidige beheining wurdt de boppeste of legere limyt ynsteld np.inf mei it byhearrende teken.
Lit it nedich wêze om it minimum te finen fan in bekende Rosenbrock-funksje fan twa fariabelen:

Yn dit gefal wurde de folgjende beheiningen ynsteld op har definysjedomein:






Yn ús gefal is d'r in unike oplossing op it punt
, wêrfoar allinich de earste en fjirde beheiningen jildich binne.
Lit ús gean troch de beheinings fan ûnderen nei boppen en sjoch nei hoe't wy kinne skriuwe se yn scipy.
Beskikberens
и
litte wy it definiearje mei it Bounds-objekt.
from scipy.optimize import Bounds
bounds = Bounds ([0, -0.5], [1.0, 2.0])Beskikberens
и
Litte wy it yn lineêre foarm skriuwe:

Litte wy dizze beheiningen definiearje as in LinearConstraint-objekt:
import numpy as np
from scipy.optimize import LinearConstraint
linear_constraint = LinearConstraint ([[1, 2], [2, 1]], [-np.inf, 1], [1, 1])En as lêste de net-lineêre beheining yn matrixfoarm:

Wy definiearje de Jacobiaanske matrix foar dizze beheining en in lineêre kombinaasje fan de Hessian matrix mei in willekeurige fektor
:


No kinne wy in net-lineêre beheining definiearje as in objekt 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)As de grutte grut is, kinne matriksen ek yn sparse foarm oantsjutte wurde:
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)of as in objekt 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)By it berekkenjen fan de Hessyske matrix
fereasket in soad ynspannings, kinne jo gebrûk meitsje fan in klasse . De folgjende strategyen binne beskikber: BFGS и SR1.
from scipy.optimize import BFGS
nonlinear_constraint = NonlinearConstraint(cons_f, -np.inf, 1, jac=cons_J, hess=BFGS())De Hessian kin ek berekkene wurde mei finite ferskillen:
nonlinear_constraint = NonlinearConstraint (cons_f, -np.inf, 1, jac = cons_J, hess = '2-point')De Jacobiaanske matrix foar beheiningen kin ek berekkene wurde mei finite ferskillen. Yn dit gefal kin de Hessyske matrix lykwols net berekkene wurde mei finite ferskillen. De Hessian moat wurde definiearre as in funksje of mei de klasse HessianUpdateStrategy.
nonlinear_constraint = NonlinearConstraint (cons_f, -np.inf, 1, jac = '2-point', hess = BFGS ())De oplossing foar it optimalisaasjeprobleem sjocht der sa út:
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]As it nedich is, kin de funksje foar it berekkenjen fan 'e Hessian definieare wurde mei de klasse 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)of it produkt fan de Hessian en in willekeurige vector troch de 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)As alternatyf kinne de earste en twadde derivatives fan 'e funksje dy't wurdt optimalisearre wurde benadere. Bygelyks, de Hessian kin benadere wurde mei de funksje SR1 (kwasy-Newtonian approximation). De gradient kin benadere wurde troch einige ferskillen.
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)Betingst optimalisearjen metoade = "SLSQP"
De SLSQP-metoade is ûntworpen om problemen op te lossen fan it minimalisearjen fan in funksje yn 'e foarm:




Wêr
и
- sets fan yndeksen fan útdrukkingen dy't beheiningen beskriuwe yn 'e foarm fan gelikensens of ûngelikens.
- sets fan legere en boppegrins foar it domein fan definysje fan 'e funksje.
Lineêre en net-lineêre beheiningen wurde beskreaun yn 'e foarm fan wurdboeken mei kaaien 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])
}It sykjen nei it minimum wurdt as folget útfierd:
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 ]Optimalisaasje foarbyld
Yn ferbân mei de oergong nei de fyfde technologyske struktuer, lit ús beskôgje produksje optimalisaasje mei help fan it foarbyld fan in web studio, dat bringt ús in lyts, mar stabile ynkommen. Litte wy ússels foarstelle as de direkteur fan in galei dy't trije soarten produkten produseart:
- x0 - ferkeapjende lâningssiden, fan 10 tr.
- x1 - corporate websites, fan 20 tr.
- x2 - online winkels, fan 30 tr.
Us freonlike wurkteam bestiet út fjouwer junioaren, twa middens en ien senioaren. Harren moanlikse wurktiidfûns:
- juny:
4 * 150 = 600 чел * час, - middelste:
2 * 150 = 300 чел * час, - senor:
150 чел * час.
Lit de earste beskikbere junior (0, 1, 2) oeren besteegje oan 'e ûntwikkeling en ynset fan ien side fan type (x10, x20, x30), midden - (7, 15, 20), senior - (5, 10, 15) ) oeren fan 'e bêste tiid fan jo libben.
Lykas elke normale direkteur wolle wy moanlikse winsten maksimalisearje. De earste stap nei sukses is om de objektive funksje op te skriuwen value as it bedrach fan ynkommen út produkten produsearre per moanne:
def value(x):
return - 10*x[0] - 20*x[1] - 30*x[2]Dit is gjin flater by it sykjen nei it maksimum, de objektive funksje wurdt minimalisearre mei it tsjinoerstelde teken.
De folgjende stap is om ús meiwurkers te ferbieden fan oerwurking en beheiningen op wurktiden yn te fieren:

Wat is lykweardich:

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]])
}In formele beheining is dat produktútfier allinich posityf moat wêze:
bnds = Bounds ([0, 0, 0], [np.inf, np.inf, np.inf])En as lêste, de meast rôze oanname is dat fanwegen de lege priis en hege kwaliteit, in wachtrige fan tefreden klanten is konstant line up foar ús. Wy kinne de moanlikse produksjevoluminten sels kieze, basearre op it oplossen fan it beheinde optimalisaasjeprobleem mei 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]Litte wy losrûnje op heule getallen en de moanlikse lading fan roeiers berekkenje mei in optimale ferdieling fan produkten x = (8, 6, 3) :
- juny:
8 * 10 + 6 * 20 + 3 * 30 = 290 чел * час; - middelste:
8 * 7 + 6 * 15 + 3 * 20 = 206 чел * час; - senor:
8 * 5 + 6 * 10 + 3 * 15 = 145 чел * час.
Konklúzje: om de direkteur syn goedfertsjinne maksimum te ûntfangen, is it optimaal om 8 lâningssiden, 6 middelgrutte siden en 3 winkels per moanne te meitsjen. Yn dit gefal moat de senioaren ploegje sûnder op 'e masine te sjen, de lading fan 'e middens sil sawat 2/3 wêze, de junioaren minder as de helte.
konklúzje
It artikel beskriuwt de basistechniken foar it wurkjen mei it pakket scipy.optimize, brûkt om problemen mei betingst minimaasje op te lossen. Persoanlik brûk ik scipy puur foar akademyske doelen, dêrom is it jûn foarbyld fan sa'n komyske aard.
In protte teory en firtuele foarbylden kinne wurde fûn, bygelyks, yn it boek fan I.L. Akulich "Wiskundige programmearring yn foarbylden en problemen." Mear hardcore applikaasje scipy.optimize om in 3D-struktuer te bouwen út in set ôfbyldings () kin sjoen wurde yn .
De wichtichste boarne fan ynformaasje is dyjingen dy't bydrage wolle oan de oersetting fan dizze en oare seksjes scipy Wolkom by .
Спасибо foar dielname oan de tarieding fan de publikaasje.
Boarne: www.habr.com
