SciPy, оптимизатсия бо шароит

SciPy, оптимизатсия бо шароит

SciPy (талаффузи sai pie) як бастаи риёзӣ дар асоси numpy мебошад, ки китобхонаҳои C ва Fortran-ро низ дар бар мегирад. SciPy сессияи интерактивии Python-и шуморо ба муҳити мукаммали илми маълумот ба монанди MATLAB, IDL, Octave, R ё SciLab табдил медиҳад.

Дар ин мақола мо усулҳои асосии барномасозии математикиро дида мебароем - ҳалли масъалаҳои шартии оптимизатсия барои функсияи скалярии якчанд тағирёбандаҳо бо истифода аз бастаи scipy.optimize. Алгоритмҳои оптимизатсияи бемаҳдуд аллакай дар мақола муҳокима карда шудаанд мақолаи охирин. Кӯмаки муфассал ва навтаринро оид ба функсияҳои scipy ҳамеша метавон бо ёрии фармони help(), Shift+Tab ё дар ҳуҷҷатҳои расмӣ.

Муқаддима

Интерфейси умумӣ барои ҳалли мушкилоти оптимизатсияи шартӣ ва бемаҳдуд дар бастаи scipy.optimize аз ҷониби функсия таъмин карда мешавад. minimize(). Аммо маълум аст, ки барои њалли њамаи масъалањо усули универсалї вуљуд надорад, бинобар ин интихоби усули адекватї мисли њамеша ба дўши муњаќќиќ меафтад.
Алгоритми мувофиқи оптимизатсия бо истифода аз аргументи функсия муайян карда мешавад minimize(..., method="").
Барои оптимизатсияи шартии функсияи якчанд тағирёбанда, татбиқи усулҳои зерин дастрасанд:

  • trust-constr — ҷустуҷӯи ҳадди ақали маҳаллӣ дар минтақаи эътимод. Мақолаи Wiki, мақола дар бораи Habre;
  • SLSQP — барномасозии пайдарпайи квадратӣ бо маҳдудиятҳо, усули Нютонӣ барои ҳалли системаи Лагранҷ. Мақолаи Wiki.
  • TNC - Нютон буридашуда Маҳдуд, шумораи маҳдуди такрорҳо, барои функсияҳои ғайрихаттӣ бо шумораи зиёди тағирёбандаҳои мустақил хуб аст. Мақолаи Wiki.
  • L-BFGS-B — усуле аз дастаи Бройден-Флетчер-Голдфарб-Шанно, ки бо истеъмоли ками хотира аз ҳисоби қисман боркунии векторҳо аз матритсаи Ҳессиан амалӣ карда шудааст. Мақолаи Wiki, мақола дар бораи Habre.
  • COBYLA — Оптимизатсияи маҳдуди MARE бо наздикшавии хатӣ, оптимизатсияи маҳдудшуда бо наздикшавии хатӣ (бе ҳисобкунии градиент). Мақолаи Wiki.

Вобаста аз усули интихобшуда, шартҳо ва маҳдудиятҳо барои ҳалли мушкилот гуногунанд:

  • объекти синф Bounds барои усулҳои L-BFGS-B, TNC, SLSQP, trust-constr;
  • рӯйхат (min, max) барои ҳамон усулҳо L-BFGS-B, TNC, SLSQP, trust-constr;
  • объект ё рӯйхати объектҳо LinearConstraint, NonlinearConstraint барои COBYLA, SLSQP, усулҳои эътимод-constr;
  • луғат ё рӯйхати луғатҳо {'type':str, 'fun':callable, 'jac':callable,opt, 'args':sequence,opt} барои усулҳои COBYLA, SLSQP.

Шарҳи мақола:
1) Истифодаи алгоритми оптимизатсияи шартӣ дар минтақаи боварӣ (метод = "trust-constr") бо маҳдудиятҳое, ки ҳамчун объект нишон дода шудаанд, баррасӣ кунед Bounds, LinearConstraint, NonlinearConstraint ;
2) Барномасозии пайдарпайро бо истифода аз усули хурдтарин квадратҳо (метод = "SLSQP") бо маҳдудиятҳое, ки дар шакли луғат муқаррар шудаанд, баррасӣ кунед {'type', 'fun', 'jac', 'args'};
3) Намунаи оптимизатсияи маҳсулоти истеҳсолшударо бо истифода аз мисоли студияи веб таҳлил кунед.

Усули оптимизатсияи шартӣ = "trust-constr"

Татбиқи усул trust-constr бар асоси EQSQP барои мушкилот бо маҳдудиятҳои шакли баробарӣ ва ғайра сафар барои мушкилоти дорои маҳдудиятҳо дар шакли нобаробарӣ. Ҳарду усул аз ҷониби алгоритмҳо барои дарёфти ҳадди ақали маҳаллӣ дар минтақаи эътимод амалӣ карда мешаванд ва барои мушкилоти миқёси калон мувофиқанд.

Тартиби математикии масъалаи дарёфти минимум дар шакли умумӣ:

SciPy, оптимизатсия бо шароит

SciPy, оптимизатсия бо шароит

SciPy, оптимизатсия бо шароит

Барои маҳдудиятҳои қатъии баробарӣ, сарҳади поёнӣ ба сарҳади боло баробар аст SciPy, оптимизатсия бо шароит.
Барои маҳдудияти яктарафа, маҳдудияти болоӣ ё поёнӣ муқаррар карда мешавад np.inf бо аломати дахлдор.
Бигзор ҳадди ақали функсияи маълуми Розенброкро аз ду тағирёбанда пайдо кардан лозим бошад:

SciPy, оптимизатсия бо шароит

Дар ин ҳолат, маҳдудиятҳои зерин дар соҳаи таърифи он муқаррар карда мешаванд:

SciPy, оптимизатсия бо шароит

SciPy, оптимизатсия бо шароит

SciPy, оптимизатсия бо шароит

SciPy, оптимизатсия бо шароит

SciPy, оптимизатсия бо шароит

SciPy, оптимизатсия бо шароит

Дар ҳолати мо, дар нуқтаи ҳалли ягона вуҷуд дорад SciPy, оптимизатсия бо шароит, ки барои онхо танхо махдудиятхои якум ва чорум эътибор доранд.
Биёед маҳдудиятҳоро аз поён то боло гузарем ва бубинем, ки чӣ тавр мо онҳоро дар scipy нависем.
Маҳдудиятҳо SciPy, оптимизатсия бо шароит и SciPy, оптимизатсия бо шароит биёед онро бо истифода аз объекти Bounds муайян кунем.

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

Маҳдудиятҳо SciPy, оптимизатсия бо шароит и SciPy, оптимизатсия бо шароит Биёед онро дар шакли хаттӣ нависед:

SciPy, оптимизатсия бо шароит

Биёед ин маҳдудиятҳоро ҳамчун объекти LinearConstraint муайян кунем:

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

Ва ниҳоят маҳдудияти ғайрихаттӣ дар шакли матритса:

SciPy, оптимизатсия бо шароит

Мо барои ин маҳдудият матритсаи Якобӣ ва омезиши хаттии матритсаи Гессиро бо вектори ихтиёрӣ муайян мекунем. SciPy, оптимизатсия бо шароит:

SciPy, оптимизатсия бо шароит

SciPy, оптимизатсия бо шароит

Акнун мо метавонем маҳдудияти ғайрихаттиро ҳамчун объект муайян кунем 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)

Агар андоза калон бошад, матритсаҳоро низ дар шакли кам нишон додан мумкин аст:

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)

ё ҳамчун объект 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)

Ҳангоми ҳисоб кардани матритсаи Ҳессиан SciPy, оптимизатсия бо шароит чидду чахди зиёдеро талаб мекунад, шумо метавонед як синфро истифода баред HessianUpdateStrategy. Стратегияҳои зерин дастрасанд: BFGS и SR1.

from scipy.optimize import BFGS

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

Ҳессианро инчунин бо истифода аз фарқиятҳои ниҳоӣ ҳисоб кардан мумкин аст:

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

Матритсаи Якобӣ барои маҳдудиятҳо инчунин метавонад бо истифода аз фарқиятҳои ниҳоӣ ҳисоб карда шавад. Аммо, дар ин ҳолат матритсаи Гессиро бо истифода аз фарқиятҳои ниҳоӣ ҳисоб кардан мумкин нест. Hessian бояд ҳамчун функсия ё бо истифода аз синфи HessianUpdateStrategy муайян карда шавад.

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

Ҳалли масъалаи оптимизатсия чунин ба назар мерасад:

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]

Агар лозим бошад, функсияи ҳисобкунии Hessian метавонад бо истифода аз синфи 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)

ё ҳосили гессӣ ва вектори ихтиёрӣ тавассути параметр 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)

Интихобан, ҳосилаҳои якум ва дуюми функсияи оптимизатсияшавандаро тахмин кардан мумкин аст. Масалан, бо истифода аз функсия гессиро тахмин кардан мумкин аст SR1 (тақрибии квази-нютонӣ). Градиентро бо фарқиятҳои ниҳоӣ тахмин кардан мумкин аст.

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)

Усули оптимизатсияи шартӣ = "SLSQP"

Усули SLSQP барои ҳалли масъалаҳои кам кардани функсия дар шакли:

SciPy, оптимизатсия бо шароит

SciPy, оптимизатсия бо шароит

SciPy, оптимизатсия бо шароит

SciPy, оптимизатсия бо шароит

Дар куҷо SciPy, оптимизатсия бо шароит и SciPy, оптимизатсия бо шароит — маҷмӯи нишондиҳандаҳои ифодаҳое, ки маҳдудиятҳоро дар шакли баробарӣ ё нобаробарӣ тавсиф мекунанд. SciPy, оптимизатсия бо шароит — маҷмӯи ҳудуди поёнӣ ва болоӣ барои соҳаи муайянкунии функсия.

Маҳдудиятҳои хатӣ ва ғайрихаттӣ дар шакли луғатҳо бо калидҳо тасвир шудаанд 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])
          }

Ҷустуҷӯи ҳадди ақал ба таври зерин анҷом дода мешавад:

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 ]

Намунаи оптимизатсия

Дар робита ба гузаштан ба сохтори технологии панҷум, биёед бо истифода аз мисоли веб-студия, ки ба мо даромади хурд, вале устувор меорад, оптимизатсияи истеҳсолотро дида мебароем. Биёед худамонро директори галлеа тасаввур кунем, ки се хел махсулот мебарорад:

  • x0 - фурӯши саҳифаҳои фуруд, аз 10 тр.
  • x1 - вебсайтҳои корпоративӣ, аз 20 tr.
  • x2 - мағозаҳои онлайн, аз 30 тр.

Коллективи мехнатии мо чор нафар хурдсол, ду миёна ва як нафар калонсолро дарбар мегирад. Фонди ҳармоҳаи вақти кории онҳо:

  • Июнҳо: 4 * 150 = 600 чел * час,
  • миёнаҳо: 2 * 150 = 300 чел * час,
  • сенор: 150 чел * час.

Бигзор наврасони аввалини дастрас (0, 1, 2) соат барои таҳия ва ҷойгиркунии як сайти навъи (x10, x20, x30), миёна - (7, 15, 20), калонсол - (5, 10, 15) сарф кунанд. ) соатҳои беҳтарини ҳаёти шумо.

Мисли ҳар як директори оддӣ, мо мехоҳем фоидаи ҳармоҳаро ба ҳадди аксар расонанд. Қадами аввалини муваффақият ин навиштани функсияи ҳадаф мебошад value ҳамчун маблағи даромад аз маҳсулоти дар як моҳ истеҳсолшуда:

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

Ин хато нест, ҳангоми ҷустуҷӯи максимум функсияи ҳадаф бо аломати муқобил кам карда мешавад.

Қадами навбатӣ ин манъ кардани коргарони мо аз зиёд кор кардан ва ҷорӣ кардани маҳдудият дар вақти корӣ мебошад:

SciPy, оптимизатсия бо шароит

Чӣ баробар аст:

SciPy, оптимизатсия бо шароит

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]])
            }

Маҳдудияти расмӣ ин аст, ки истеҳсоли маҳсулот бояд танҳо мусбат бошад:

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

Ва дар ниҳоят, фарзияи ҷолибтарин ин аст, ки аз сабаби нархи паст ва сифати баланд, навбати муштариёни қаноатманд ҳамеша барои мо мепайвандад. Мо метавонем ҳаҷми истеҳсоли моҳонаро худамон дар асоси ҳалли мушкилоти маҳдудшудаи оптимизатсия интихоб кунем 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]

Биёед ба ададҳои пурра давр занем ва сарбории моҳонаи қаиқронҳоро бо тақсимоти оптималии маҳсулот ҳисоб кунем x = (8, 6, 3) :

  • Июнҳо: 8 * 10 + 6 * 20 + 3 * 30 = 290 чел * час;
  • миёнаҳо: 8 * 7 + 6 * 15 + 3 * 20 = 206 чел * час;
  • сенор: 8 * 5 + 6 * 10 + 3 * 15 = 145 чел * час.

Хулоса: барои он ки директор ҳадди аксар сазовори худро гирад, дар як моҳ сохтани 8 саҳифаи кушода, 6 сайти миёна ва 3 мағоза беҳтарин аст. Дар ин сурат пирон бояд аз дастгох боло на-истода шудгор кунанд, бори мобайнхо такрибан 2/3, юниорхо аз нисф кам мешавад.

хулоса

Дар мақола усулҳои асосии кор бо бастаҳо оварда шудаанд scipy.optimize, барои ҳалли масъалаҳои кам кардани шартӣ истифода мешавад. Шахсан ман истифода мекунам scipy сирф барои мақсадҳои таълимӣ, бинобар ин мисоли овардашуда чунин хусусияти ҳаҷвӣ дорад.

Масалан, дар китоби И.Л.Акулич «Программасозии математикӣ дар мисолҳо ва масъалаҳо» бисёр назария ва мисолҳои виртуалиро ёфтан мумкин аст. Барномаи бештар хардкор scipy.optimize барои сохтани сохтори 3D аз маҷмӯи тасвирҳо (мақола дар бораи Habre) дидан мумкин аст китобчаи ошпазӣ.

Манбаи асосии иттилоот аст docs.scipy.orgки мехоханд дар тарчимаи ин ва дигар бахшхо сахм гузоранд scipy Хуш омадед ба GitHub.

Спасибо мефистофҳо барои иштирок дар тайёр кардани нашрия.

Манбаъ: will.com

Илова Эзоҳ