_optimize.py 136 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951
  1. #__docformat__ = "restructuredtext en"
  2. # ******NOTICE***************
  3. # optimize.py module by Travis E. Oliphant
  4. #
  5. # You may copy and use this module as you see fit with no
  6. # guarantee implied provided you keep this notice in all copies.
  7. # *****END NOTICE************
  8. # A collection of optimization algorithms. Version 0.5
  9. # CHANGES
  10. # Added fminbound (July 2001)
  11. # Added brute (Aug. 2002)
  12. # Finished line search satisfying strong Wolfe conditions (Mar. 2004)
  13. # Updated strong Wolfe conditions line search to use
  14. # cubic-interpolation (Mar. 2004)
  15. # Minimization routines
  16. __all__ = ['fmin', 'fmin_powell', 'fmin_bfgs', 'fmin_ncg', 'fmin_cg',
  17. 'fminbound', 'brent', 'golden', 'bracket', 'rosen', 'rosen_der',
  18. 'rosen_hess', 'rosen_hess_prod', 'brute', 'approx_fprime',
  19. 'line_search', 'check_grad', 'OptimizeResult', 'show_options',
  20. 'OptimizeWarning']
  21. __docformat__ = "restructuredtext en"
  22. import warnings
  23. import sys
  24. from numpy import (atleast_1d, eye, argmin, zeros, shape, squeeze,
  25. asarray, sqrt, Inf, asfarray)
  26. import numpy as np
  27. from scipy.sparse.linalg import LinearOperator
  28. from ._linesearch import (line_search_wolfe1, line_search_wolfe2,
  29. line_search_wolfe2 as line_search,
  30. LineSearchWarning)
  31. from ._numdiff import approx_derivative
  32. from ._hessian_update_strategy import HessianUpdateStrategy
  33. from scipy._lib._util import getfullargspec_no_self as _getfullargspec
  34. from scipy._lib._util import MapWrapper, check_random_state
  35. from scipy.optimize._differentiable_functions import ScalarFunction, FD_METHODS
  36. # standard status messages of optimizers
  37. _status_message = {'success': 'Optimization terminated successfully.',
  38. 'maxfev': 'Maximum number of function evaluations has '
  39. 'been exceeded.',
  40. 'maxiter': 'Maximum number of iterations has been '
  41. 'exceeded.',
  42. 'pr_loss': 'Desired error not necessarily achieved due '
  43. 'to precision loss.',
  44. 'nan': 'NaN result encountered.',
  45. 'out_of_bounds': 'The result is outside of the provided '
  46. 'bounds.'}
  47. class MemoizeJac:
  48. """ Decorator that caches the return values of a function returning `(fun, grad)`
  49. each time it is called. """
  50. def __init__(self, fun):
  51. self.fun = fun
  52. self.jac = None
  53. self._value = None
  54. self.x = None
  55. def _compute_if_needed(self, x, *args):
  56. if not np.all(x == self.x) or self._value is None or self.jac is None:
  57. self.x = np.asarray(x).copy()
  58. fg = self.fun(x, *args)
  59. self.jac = fg[1]
  60. self._value = fg[0]
  61. def __call__(self, x, *args):
  62. """ returns the function value """
  63. self._compute_if_needed(x, *args)
  64. return self._value
  65. def derivative(self, x, *args):
  66. self._compute_if_needed(x, *args)
  67. return self.jac
  68. def _indenter(s, n=0):
  69. """
  70. Ensures that lines after the first are indented by the specified amount
  71. """
  72. split = s.split("\n")
  73. indent = " "*n
  74. return ("\n" + indent).join(split)
  75. def _float_formatter_10(x):
  76. """
  77. Returns a string representation of a float with exactly ten characters
  78. """
  79. if np.isposinf(x):
  80. return " inf"
  81. elif np.isneginf(x):
  82. return " -inf"
  83. elif np.isnan(x):
  84. return " nan"
  85. return np.format_float_scientific(x, precision=3, pad_left=2, unique=False)
  86. def _dict_formatter(d, n=0, mplus=1, sorter=None):
  87. """
  88. Pretty printer for dictionaries
  89. `n` keeps track of the starting indentation;
  90. lines are indented by this much after a line break.
  91. `mplus` is additional left padding applied to keys
  92. """
  93. if isinstance(d, dict):
  94. m = max(map(len, list(d.keys()))) + mplus # width to print keys
  95. s = '\n'.join([k.rjust(m) + ': ' + # right justified, width m
  96. _indenter(_dict_formatter(v, m+n+2, 0, sorter), m+2)
  97. for k, v in sorter(d)]) # +2 for ': '
  98. else:
  99. # By default, NumPy arrays print with linewidth=76. `n` is
  100. # the indent at which a line begins printing, so it is subtracted
  101. # from the default to avoid exceeding 76 characters total.
  102. # `edgeitems` is the number of elements to include before and after
  103. # ellipses when arrays are not shown in full.
  104. # `threshold` is the maximum number of elements for which an
  105. # array is shown in full.
  106. # These values tend to work well for use with OptimizeResult.
  107. with np.printoptions(linewidth=76-n, edgeitems=2, threshold=12,
  108. formatter={'float_kind': _float_formatter_10}):
  109. s = str(d)
  110. return s
  111. class OptimizeResult(dict):
  112. """ Represents the optimization result.
  113. Attributes
  114. ----------
  115. x : ndarray
  116. The solution of the optimization.
  117. success : bool
  118. Whether or not the optimizer exited successfully.
  119. status : int
  120. Termination status of the optimizer. Its value depends on the
  121. underlying solver. Refer to `message` for details.
  122. message : str
  123. Description of the cause of the termination.
  124. fun, jac, hess: ndarray
  125. Values of objective function, its Jacobian and its Hessian (if
  126. available). The Hessians may be approximations, see the documentation
  127. of the function in question.
  128. hess_inv : object
  129. Inverse of the objective function's Hessian; may be an approximation.
  130. Not available for all solvers. The type of this attribute may be
  131. either np.ndarray or scipy.sparse.linalg.LinearOperator.
  132. nfev, njev, nhev : int
  133. Number of evaluations of the objective functions and of its
  134. Jacobian and Hessian.
  135. nit : int
  136. Number of iterations performed by the optimizer.
  137. maxcv : float
  138. The maximum constraint violation.
  139. Notes
  140. -----
  141. `OptimizeResult` may have additional attributes not listed here depending
  142. on the specific solver being used. Since this class is essentially a
  143. subclass of dict with attribute accessors, one can see which
  144. attributes are available using the `OptimizeResult.keys` method.
  145. """
  146. def __getattr__(self, name):
  147. try:
  148. return self[name]
  149. except KeyError as e:
  150. raise AttributeError(name) from e
  151. __setattr__ = dict.__setitem__
  152. __delattr__ = dict.__delitem__
  153. def __repr__(self):
  154. order_keys = ['message', 'success', 'status', 'fun', 'funl', 'x', 'xl',
  155. 'col_ind', 'nit', 'lower', 'upper', 'eqlin', 'ineqlin']
  156. # 'slack', 'con' are redundant with residuals
  157. # 'crossover_nit' is probably not interesting to most users
  158. omit_keys = {'slack', 'con', 'crossover_nit'}
  159. def key(item):
  160. try:
  161. return order_keys.index(item[0].lower())
  162. except ValueError: # item not in list
  163. return np.inf
  164. def omit_redundant(items):
  165. for item in items:
  166. if item[0] in omit_keys:
  167. continue
  168. yield item
  169. def item_sorter(d):
  170. return sorted(omit_redundant(d.items()), key=key)
  171. if self.keys():
  172. return _dict_formatter(self, sorter=item_sorter)
  173. else:
  174. return self.__class__.__name__ + "()"
  175. def __dir__(self):
  176. return list(self.keys())
  177. class OptimizeWarning(UserWarning):
  178. pass
  179. def _check_unknown_options(unknown_options):
  180. if unknown_options:
  181. msg = ", ".join(map(str, unknown_options.keys()))
  182. # Stack level 4: this is called from _minimize_*, which is
  183. # called from another function in SciPy. Level 4 is the first
  184. # level in user code.
  185. warnings.warn("Unknown solver options: %s" % msg, OptimizeWarning, 4)
  186. def is_finite_scalar(x):
  187. """Test whether `x` is either a finite scalar or a finite array scalar.
  188. """
  189. return np.size(x) == 1 and np.isfinite(x)
  190. _epsilon = sqrt(np.finfo(float).eps)
  191. def vecnorm(x, ord=2):
  192. if ord == Inf:
  193. return np.amax(np.abs(x))
  194. elif ord == -Inf:
  195. return np.amin(np.abs(x))
  196. else:
  197. return np.sum(np.abs(x)**ord, axis=0)**(1.0 / ord)
  198. def _prepare_scalar_function(fun, x0, jac=None, args=(), bounds=None,
  199. epsilon=None, finite_diff_rel_step=None,
  200. hess=None):
  201. """
  202. Creates a ScalarFunction object for use with scalar minimizers
  203. (BFGS/LBFGSB/SLSQP/TNC/CG/etc).
  204. Parameters
  205. ----------
  206. fun : callable
  207. The objective function to be minimized.
  208. ``fun(x, *args) -> float``
  209. where ``x`` is an 1-D array with shape (n,) and ``args``
  210. is a tuple of the fixed parameters needed to completely
  211. specify the function.
  212. x0 : ndarray, shape (n,)
  213. Initial guess. Array of real elements of size (n,),
  214. where 'n' is the number of independent variables.
  215. jac : {callable, '2-point', '3-point', 'cs', None}, optional
  216. Method for computing the gradient vector. If it is a callable, it
  217. should be a function that returns the gradient vector:
  218. ``jac(x, *args) -> array_like, shape (n,)``
  219. If one of `{'2-point', '3-point', 'cs'}` is selected then the gradient
  220. is calculated with a relative step for finite differences. If `None`,
  221. then two-point finite differences with an absolute step is used.
  222. args : tuple, optional
  223. Extra arguments passed to the objective function and its
  224. derivatives (`fun`, `jac` functions).
  225. bounds : sequence, optional
  226. Bounds on variables. 'new-style' bounds are required.
  227. eps : float or ndarray
  228. If `jac is None` the absolute step size used for numerical
  229. approximation of the jacobian via forward differences.
  230. finite_diff_rel_step : None or array_like, optional
  231. If `jac in ['2-point', '3-point', 'cs']` the relative step size to
  232. use for numerical approximation of the jacobian. The absolute step
  233. size is computed as ``h = rel_step * sign(x0) * max(1, abs(x0))``,
  234. possibly adjusted to fit into the bounds. For ``method='3-point'``
  235. the sign of `h` is ignored. If None (default) then step is selected
  236. automatically.
  237. hess : {callable, '2-point', '3-point', 'cs', None}
  238. Computes the Hessian matrix. If it is callable, it should return the
  239. Hessian matrix:
  240. ``hess(x, *args) -> {LinearOperator, spmatrix, array}, (n, n)``
  241. Alternatively, the keywords {'2-point', '3-point', 'cs'} select a
  242. finite difference scheme for numerical estimation.
  243. Whenever the gradient is estimated via finite-differences, the Hessian
  244. cannot be estimated with options {'2-point', '3-point', 'cs'} and needs
  245. to be estimated using one of the quasi-Newton strategies.
  246. Returns
  247. -------
  248. sf : ScalarFunction
  249. """
  250. if callable(jac):
  251. grad = jac
  252. elif jac in FD_METHODS:
  253. # epsilon is set to None so that ScalarFunction is made to use
  254. # rel_step
  255. epsilon = None
  256. grad = jac
  257. else:
  258. # default (jac is None) is to do 2-point finite differences with
  259. # absolute step size. ScalarFunction has to be provided an
  260. # epsilon value that is not None to use absolute steps. This is
  261. # normally the case from most _minimize* methods.
  262. grad = '2-point'
  263. epsilon = epsilon
  264. if hess is None:
  265. # ScalarFunction requires something for hess, so we give a dummy
  266. # implementation here if nothing is provided, return a value of None
  267. # so that downstream minimisers halt. The results of `fun.hess`
  268. # should not be used.
  269. def hess(x, *args):
  270. return None
  271. if bounds is None:
  272. bounds = (-np.inf, np.inf)
  273. # ScalarFunction caches. Reuse of fun(x) during grad
  274. # calculation reduces overall function evaluations.
  275. sf = ScalarFunction(fun, x0, args, grad, hess,
  276. finite_diff_rel_step, bounds, epsilon=epsilon)
  277. return sf
  278. def _clip_x_for_func(func, bounds):
  279. # ensures that x values sent to func are clipped to bounds
  280. # this is used as a mitigation for gh11403, slsqp/tnc sometimes
  281. # suggest a move that is outside the limits by 1 or 2 ULP. This
  282. # unclean fix makes sure x is strictly within bounds.
  283. def eval(x):
  284. x = _check_clip_x(x, bounds)
  285. return func(x)
  286. return eval
  287. def _check_clip_x(x, bounds):
  288. if (x < bounds[0]).any() or (x > bounds[1]).any():
  289. warnings.warn("Values in x were outside bounds during a "
  290. "minimize step, clipping to bounds", RuntimeWarning)
  291. x = np.clip(x, bounds[0], bounds[1])
  292. return x
  293. return x
  294. def rosen(x):
  295. """
  296. The Rosenbrock function.
  297. The function computed is::
  298. sum(100.0*(x[1:] - x[:-1]**2.0)**2.0 + (1 - x[:-1])**2.0)
  299. Parameters
  300. ----------
  301. x : array_like
  302. 1-D array of points at which the Rosenbrock function is to be computed.
  303. Returns
  304. -------
  305. f : float
  306. The value of the Rosenbrock function.
  307. See Also
  308. --------
  309. rosen_der, rosen_hess, rosen_hess_prod
  310. Examples
  311. --------
  312. >>> import numpy as np
  313. >>> from scipy.optimize import rosen
  314. >>> X = 0.1 * np.arange(10)
  315. >>> rosen(X)
  316. 76.56
  317. For higher-dimensional input ``rosen`` broadcasts.
  318. In the following example, we use this to plot a 2D landscape.
  319. Note that ``rosen_hess`` does not broadcast in this manner.
  320. >>> import matplotlib.pyplot as plt
  321. >>> from mpl_toolkits.mplot3d import Axes3D
  322. >>> x = np.linspace(-1, 1, 50)
  323. >>> X, Y = np.meshgrid(x, x)
  324. >>> ax = plt.subplot(111, projection='3d')
  325. >>> ax.plot_surface(X, Y, rosen([X, Y]))
  326. >>> plt.show()
  327. """
  328. x = asarray(x)
  329. r = np.sum(100.0 * (x[1:] - x[:-1]**2.0)**2.0 + (1 - x[:-1])**2.0,
  330. axis=0)
  331. return r
  332. def rosen_der(x):
  333. """
  334. The derivative (i.e. gradient) of the Rosenbrock function.
  335. Parameters
  336. ----------
  337. x : array_like
  338. 1-D array of points at which the derivative is to be computed.
  339. Returns
  340. -------
  341. rosen_der : (N,) ndarray
  342. The gradient of the Rosenbrock function at `x`.
  343. See Also
  344. --------
  345. rosen, rosen_hess, rosen_hess_prod
  346. Examples
  347. --------
  348. >>> import numpy as np
  349. >>> from scipy.optimize import rosen_der
  350. >>> X = 0.1 * np.arange(9)
  351. >>> rosen_der(X)
  352. array([ -2. , 10.6, 15.6, 13.4, 6.4, -3. , -12.4, -19.4, 62. ])
  353. """
  354. x = asarray(x)
  355. xm = x[1:-1]
  356. xm_m1 = x[:-2]
  357. xm_p1 = x[2:]
  358. der = np.zeros_like(x)
  359. der[1:-1] = (200 * (xm - xm_m1**2) -
  360. 400 * (xm_p1 - xm**2) * xm - 2 * (1 - xm))
  361. der[0] = -400 * x[0] * (x[1] - x[0]**2) - 2 * (1 - x[0])
  362. der[-1] = 200 * (x[-1] - x[-2]**2)
  363. return der
  364. def rosen_hess(x):
  365. """
  366. The Hessian matrix of the Rosenbrock function.
  367. Parameters
  368. ----------
  369. x : array_like
  370. 1-D array of points at which the Hessian matrix is to be computed.
  371. Returns
  372. -------
  373. rosen_hess : ndarray
  374. The Hessian matrix of the Rosenbrock function at `x`.
  375. See Also
  376. --------
  377. rosen, rosen_der, rosen_hess_prod
  378. Examples
  379. --------
  380. >>> import numpy as np
  381. >>> from scipy.optimize import rosen_hess
  382. >>> X = 0.1 * np.arange(4)
  383. >>> rosen_hess(X)
  384. array([[-38., 0., 0., 0.],
  385. [ 0., 134., -40., 0.],
  386. [ 0., -40., 130., -80.],
  387. [ 0., 0., -80., 200.]])
  388. """
  389. x = atleast_1d(x)
  390. H = np.diag(-400 * x[:-1], 1) - np.diag(400 * x[:-1], -1)
  391. diagonal = np.zeros(len(x), dtype=x.dtype)
  392. diagonal[0] = 1200 * x[0]**2 - 400 * x[1] + 2
  393. diagonal[-1] = 200
  394. diagonal[1:-1] = 202 + 1200 * x[1:-1]**2 - 400 * x[2:]
  395. H = H + np.diag(diagonal)
  396. return H
  397. def rosen_hess_prod(x, p):
  398. """
  399. Product of the Hessian matrix of the Rosenbrock function with a vector.
  400. Parameters
  401. ----------
  402. x : array_like
  403. 1-D array of points at which the Hessian matrix is to be computed.
  404. p : array_like
  405. 1-D array, the vector to be multiplied by the Hessian matrix.
  406. Returns
  407. -------
  408. rosen_hess_prod : ndarray
  409. The Hessian matrix of the Rosenbrock function at `x` multiplied
  410. by the vector `p`.
  411. See Also
  412. --------
  413. rosen, rosen_der, rosen_hess
  414. Examples
  415. --------
  416. >>> import numpy as np
  417. >>> from scipy.optimize import rosen_hess_prod
  418. >>> X = 0.1 * np.arange(9)
  419. >>> p = 0.5 * np.arange(9)
  420. >>> rosen_hess_prod(X, p)
  421. array([ -0., 27., -10., -95., -192., -265., -278., -195., -180.])
  422. """
  423. x = atleast_1d(x)
  424. Hp = np.zeros(len(x), dtype=x.dtype)
  425. Hp[0] = (1200 * x[0]**2 - 400 * x[1] + 2) * p[0] - 400 * x[0] * p[1]
  426. Hp[1:-1] = (-400 * x[:-2] * p[:-2] +
  427. (202 + 1200 * x[1:-1]**2 - 400 * x[2:]) * p[1:-1] -
  428. 400 * x[1:-1] * p[2:])
  429. Hp[-1] = -400 * x[-2] * p[-2] + 200*p[-1]
  430. return Hp
  431. def _wrap_scalar_function(function, args):
  432. # wraps a minimizer function to count number of evaluations
  433. # and to easily provide an args kwd.
  434. ncalls = [0]
  435. if function is None:
  436. return ncalls, None
  437. def function_wrapper(x, *wrapper_args):
  438. ncalls[0] += 1
  439. # A copy of x is sent to the user function (gh13740)
  440. fx = function(np.copy(x), *(wrapper_args + args))
  441. # Ideally, we'd like to a have a true scalar returned from f(x). For
  442. # backwards-compatibility, also allow np.array([1.3]), np.array([[1.3]]) etc.
  443. if not np.isscalar(fx):
  444. try:
  445. fx = np.asarray(fx).item()
  446. except (TypeError, ValueError) as e:
  447. raise ValueError("The user-provided objective function "
  448. "must return a scalar value.") from e
  449. return fx
  450. return ncalls, function_wrapper
  451. class _MaxFuncCallError(RuntimeError):
  452. pass
  453. def _wrap_scalar_function_maxfun_validation(function, args, maxfun):
  454. # wraps a minimizer function to count number of evaluations
  455. # and to easily provide an args kwd.
  456. ncalls = [0]
  457. if function is None:
  458. return ncalls, None
  459. def function_wrapper(x, *wrapper_args):
  460. if ncalls[0] >= maxfun:
  461. raise _MaxFuncCallError("Too many function calls")
  462. ncalls[0] += 1
  463. # A copy of x is sent to the user function (gh13740)
  464. fx = function(np.copy(x), *(wrapper_args + args))
  465. # Ideally, we'd like to a have a true scalar returned from f(x). For
  466. # backwards-compatibility, also allow np.array([1.3]),
  467. # np.array([[1.3]]) etc.
  468. if not np.isscalar(fx):
  469. try:
  470. fx = np.asarray(fx).item()
  471. except (TypeError, ValueError) as e:
  472. raise ValueError("The user-provided objective function "
  473. "must return a scalar value.") from e
  474. return fx
  475. return ncalls, function_wrapper
  476. def fmin(func, x0, args=(), xtol=1e-4, ftol=1e-4, maxiter=None, maxfun=None,
  477. full_output=0, disp=1, retall=0, callback=None, initial_simplex=None):
  478. """
  479. Minimize a function using the downhill simplex algorithm.
  480. This algorithm only uses function values, not derivatives or second
  481. derivatives.
  482. Parameters
  483. ----------
  484. func : callable func(x,*args)
  485. The objective function to be minimized.
  486. x0 : ndarray
  487. Initial guess.
  488. args : tuple, optional
  489. Extra arguments passed to func, i.e., ``f(x,*args)``.
  490. xtol : float, optional
  491. Absolute error in xopt between iterations that is acceptable for
  492. convergence.
  493. ftol : number, optional
  494. Absolute error in func(xopt) between iterations that is acceptable for
  495. convergence.
  496. maxiter : int, optional
  497. Maximum number of iterations to perform.
  498. maxfun : number, optional
  499. Maximum number of function evaluations to make.
  500. full_output : bool, optional
  501. Set to True if fopt and warnflag outputs are desired.
  502. disp : bool, optional
  503. Set to True to print convergence messages.
  504. retall : bool, optional
  505. Set to True to return list of solutions at each iteration.
  506. callback : callable, optional
  507. Called after each iteration, as callback(xk), where xk is the
  508. current parameter vector.
  509. initial_simplex : array_like of shape (N + 1, N), optional
  510. Initial simplex. If given, overrides `x0`.
  511. ``initial_simplex[j,:]`` should contain the coordinates of
  512. the jth vertex of the ``N+1`` vertices in the simplex, where
  513. ``N`` is the dimension.
  514. Returns
  515. -------
  516. xopt : ndarray
  517. Parameter that minimizes function.
  518. fopt : float
  519. Value of function at minimum: ``fopt = func(xopt)``.
  520. iter : int
  521. Number of iterations performed.
  522. funcalls : int
  523. Number of function calls made.
  524. warnflag : int
  525. 1 : Maximum number of function evaluations made.
  526. 2 : Maximum number of iterations reached.
  527. allvecs : list
  528. Solution at each iteration.
  529. See also
  530. --------
  531. minimize: Interface to minimization algorithms for multivariate
  532. functions. See the 'Nelder-Mead' `method` in particular.
  533. Notes
  534. -----
  535. Uses a Nelder-Mead simplex algorithm to find the minimum of function of
  536. one or more variables.
  537. This algorithm has a long history of successful use in applications.
  538. But it will usually be slower than an algorithm that uses first or
  539. second derivative information. In practice, it can have poor
  540. performance in high-dimensional problems and is not robust to
  541. minimizing complicated functions. Additionally, there currently is no
  542. complete theory describing when the algorithm will successfully
  543. converge to the minimum, or how fast it will if it does. Both the ftol and
  544. xtol criteria must be met for convergence.
  545. Examples
  546. --------
  547. >>> def f(x):
  548. ... return x**2
  549. >>> from scipy import optimize
  550. >>> minimum = optimize.fmin(f, 1)
  551. Optimization terminated successfully.
  552. Current function value: 0.000000
  553. Iterations: 17
  554. Function evaluations: 34
  555. >>> minimum[0]
  556. -8.8817841970012523e-16
  557. References
  558. ----------
  559. .. [1] Nelder, J.A. and Mead, R. (1965), "A simplex method for function
  560. minimization", The Computer Journal, 7, pp. 308-313
  561. .. [2] Wright, M.H. (1996), "Direct Search Methods: Once Scorned, Now
  562. Respectable", in Numerical Analysis 1995, Proceedings of the
  563. 1995 Dundee Biennial Conference in Numerical Analysis, D.F.
  564. Griffiths and G.A. Watson (Eds.), Addison Wesley Longman,
  565. Harlow, UK, pp. 191-208.
  566. """
  567. opts = {'xatol': xtol,
  568. 'fatol': ftol,
  569. 'maxiter': maxiter,
  570. 'maxfev': maxfun,
  571. 'disp': disp,
  572. 'return_all': retall,
  573. 'initial_simplex': initial_simplex}
  574. res = _minimize_neldermead(func, x0, args, callback=callback, **opts)
  575. if full_output:
  576. retlist = res['x'], res['fun'], res['nit'], res['nfev'], res['status']
  577. if retall:
  578. retlist += (res['allvecs'], )
  579. return retlist
  580. else:
  581. if retall:
  582. return res['x'], res['allvecs']
  583. else:
  584. return res['x']
  585. def _minimize_neldermead(func, x0, args=(), callback=None,
  586. maxiter=None, maxfev=None, disp=False,
  587. return_all=False, initial_simplex=None,
  588. xatol=1e-4, fatol=1e-4, adaptive=False, bounds=None,
  589. **unknown_options):
  590. """
  591. Minimization of scalar function of one or more variables using the
  592. Nelder-Mead algorithm.
  593. Options
  594. -------
  595. disp : bool
  596. Set to True to print convergence messages.
  597. maxiter, maxfev : int
  598. Maximum allowed number of iterations and function evaluations.
  599. Will default to ``N*200``, where ``N`` is the number of
  600. variables, if neither `maxiter` or `maxfev` is set. If both
  601. `maxiter` and `maxfev` are set, minimization will stop at the
  602. first reached.
  603. return_all : bool, optional
  604. Set to True to return a list of the best solution at each of the
  605. iterations.
  606. initial_simplex : array_like of shape (N + 1, N)
  607. Initial simplex. If given, overrides `x0`.
  608. ``initial_simplex[j,:]`` should contain the coordinates of
  609. the jth vertex of the ``N+1`` vertices in the simplex, where
  610. ``N`` is the dimension.
  611. xatol : float, optional
  612. Absolute error in xopt between iterations that is acceptable for
  613. convergence.
  614. fatol : number, optional
  615. Absolute error in func(xopt) between iterations that is acceptable for
  616. convergence.
  617. adaptive : bool, optional
  618. Adapt algorithm parameters to dimensionality of problem. Useful for
  619. high-dimensional minimization [1]_.
  620. bounds : sequence or `Bounds`, optional
  621. Bounds on variables. There are two ways to specify the bounds:
  622. 1. Instance of `Bounds` class.
  623. 2. Sequence of ``(min, max)`` pairs for each element in `x`. None
  624. is used to specify no bound.
  625. Note that this just clips all vertices in simplex based on
  626. the bounds.
  627. References
  628. ----------
  629. .. [1] Gao, F. and Han, L.
  630. Implementing the Nelder-Mead simplex algorithm with adaptive
  631. parameters. 2012. Computational Optimization and Applications.
  632. 51:1, pp. 259-277
  633. """
  634. _check_unknown_options(unknown_options)
  635. maxfun = maxfev
  636. retall = return_all
  637. x0 = asfarray(x0).flatten()
  638. if adaptive:
  639. dim = float(len(x0))
  640. rho = 1
  641. chi = 1 + 2/dim
  642. psi = 0.75 - 1/(2*dim)
  643. sigma = 1 - 1/dim
  644. else:
  645. rho = 1
  646. chi = 2
  647. psi = 0.5
  648. sigma = 0.5
  649. nonzdelt = 0.05
  650. zdelt = 0.00025
  651. if bounds is not None:
  652. lower_bound, upper_bound = bounds.lb, bounds.ub
  653. # check bounds
  654. if (lower_bound > upper_bound).any():
  655. raise ValueError("Nelder Mead - one of the lower bounds is greater than an upper bound.")
  656. if np.any(lower_bound > x0) or np.any(x0 > upper_bound):
  657. warnings.warn("Initial guess is not within the specified bounds",
  658. OptimizeWarning, 3)
  659. if bounds is not None:
  660. x0 = np.clip(x0, lower_bound, upper_bound)
  661. if initial_simplex is None:
  662. N = len(x0)
  663. sim = np.empty((N + 1, N), dtype=x0.dtype)
  664. sim[0] = x0
  665. for k in range(N):
  666. y = np.array(x0, copy=True)
  667. if y[k] != 0:
  668. y[k] = (1 + nonzdelt)*y[k]
  669. else:
  670. y[k] = zdelt
  671. sim[k + 1] = y
  672. else:
  673. sim = np.asfarray(initial_simplex).copy()
  674. if sim.ndim != 2 or sim.shape[0] != sim.shape[1] + 1:
  675. raise ValueError("`initial_simplex` should be an array of shape (N+1,N)")
  676. if len(x0) != sim.shape[1]:
  677. raise ValueError("Size of `initial_simplex` is not consistent with `x0`")
  678. N = sim.shape[1]
  679. if retall:
  680. allvecs = [sim[0]]
  681. # If neither are set, then set both to default
  682. if maxiter is None and maxfun is None:
  683. maxiter = N * 200
  684. maxfun = N * 200
  685. elif maxiter is None:
  686. # Convert remaining Nones, to np.inf, unless the other is np.inf, in
  687. # which case use the default to avoid unbounded iteration
  688. if maxfun == np.inf:
  689. maxiter = N * 200
  690. else:
  691. maxiter = np.inf
  692. elif maxfun is None:
  693. if maxiter == np.inf:
  694. maxfun = N * 200
  695. else:
  696. maxfun = np.inf
  697. if bounds is not None:
  698. sim = np.clip(sim, lower_bound, upper_bound)
  699. one2np1 = list(range(1, N + 1))
  700. fsim = np.full((N + 1,), np.inf, dtype=float)
  701. fcalls, func = _wrap_scalar_function_maxfun_validation(func, args, maxfun)
  702. try:
  703. for k in range(N + 1):
  704. fsim[k] = func(sim[k])
  705. except _MaxFuncCallError:
  706. pass
  707. finally:
  708. ind = np.argsort(fsim)
  709. sim = np.take(sim, ind, 0)
  710. fsim = np.take(fsim, ind, 0)
  711. ind = np.argsort(fsim)
  712. fsim = np.take(fsim, ind, 0)
  713. # sort so sim[0,:] has the lowest function value
  714. sim = np.take(sim, ind, 0)
  715. iterations = 1
  716. while (fcalls[0] < maxfun and iterations < maxiter):
  717. try:
  718. if (np.max(np.ravel(np.abs(sim[1:] - sim[0]))) <= xatol and
  719. np.max(np.abs(fsim[0] - fsim[1:])) <= fatol):
  720. break
  721. xbar = np.add.reduce(sim[:-1], 0) / N
  722. xr = (1 + rho) * xbar - rho * sim[-1]
  723. if bounds is not None:
  724. xr = np.clip(xr, lower_bound, upper_bound)
  725. fxr = func(xr)
  726. doshrink = 0
  727. if fxr < fsim[0]:
  728. xe = (1 + rho * chi) * xbar - rho * chi * sim[-1]
  729. if bounds is not None:
  730. xe = np.clip(xe, lower_bound, upper_bound)
  731. fxe = func(xe)
  732. if fxe < fxr:
  733. sim[-1] = xe
  734. fsim[-1] = fxe
  735. else:
  736. sim[-1] = xr
  737. fsim[-1] = fxr
  738. else: # fsim[0] <= fxr
  739. if fxr < fsim[-2]:
  740. sim[-1] = xr
  741. fsim[-1] = fxr
  742. else: # fxr >= fsim[-2]
  743. # Perform contraction
  744. if fxr < fsim[-1]:
  745. xc = (1 + psi * rho) * xbar - psi * rho * sim[-1]
  746. if bounds is not None:
  747. xc = np.clip(xc, lower_bound, upper_bound)
  748. fxc = func(xc)
  749. if fxc <= fxr:
  750. sim[-1] = xc
  751. fsim[-1] = fxc
  752. else:
  753. doshrink = 1
  754. else:
  755. # Perform an inside contraction
  756. xcc = (1 - psi) * xbar + psi * sim[-1]
  757. if bounds is not None:
  758. xcc = np.clip(xcc, lower_bound, upper_bound)
  759. fxcc = func(xcc)
  760. if fxcc < fsim[-1]:
  761. sim[-1] = xcc
  762. fsim[-1] = fxcc
  763. else:
  764. doshrink = 1
  765. if doshrink:
  766. for j in one2np1:
  767. sim[j] = sim[0] + sigma * (sim[j] - sim[0])
  768. if bounds is not None:
  769. sim[j] = np.clip(
  770. sim[j], lower_bound, upper_bound)
  771. fsim[j] = func(sim[j])
  772. iterations += 1
  773. except _MaxFuncCallError:
  774. pass
  775. finally:
  776. ind = np.argsort(fsim)
  777. sim = np.take(sim, ind, 0)
  778. fsim = np.take(fsim, ind, 0)
  779. if callback is not None:
  780. callback(sim[0])
  781. if retall:
  782. allvecs.append(sim[0])
  783. x = sim[0]
  784. fval = np.min(fsim)
  785. warnflag = 0
  786. if fcalls[0] >= maxfun:
  787. warnflag = 1
  788. msg = _status_message['maxfev']
  789. if disp:
  790. warnings.warn(msg, RuntimeWarning, 3)
  791. elif iterations >= maxiter:
  792. warnflag = 2
  793. msg = _status_message['maxiter']
  794. if disp:
  795. warnings.warn(msg, RuntimeWarning, 3)
  796. else:
  797. msg = _status_message['success']
  798. if disp:
  799. print(msg)
  800. print(" Current function value: %f" % fval)
  801. print(" Iterations: %d" % iterations)
  802. print(" Function evaluations: %d" % fcalls[0])
  803. result = OptimizeResult(fun=fval, nit=iterations, nfev=fcalls[0],
  804. status=warnflag, success=(warnflag == 0),
  805. message=msg, x=x, final_simplex=(sim, fsim))
  806. if retall:
  807. result['allvecs'] = allvecs
  808. return result
  809. def approx_fprime(xk, f, epsilon=_epsilon, *args):
  810. """Finite difference approximation of the derivatives of a
  811. scalar or vector-valued function.
  812. If a function maps from :math:`R^n` to :math:`R^m`, its derivatives form
  813. an m-by-n matrix
  814. called the Jacobian, where an element :math:`(i, j)` is a partial
  815. derivative of f[i] with respect to ``xk[j]``.
  816. Parameters
  817. ----------
  818. xk : array_like
  819. The coordinate vector at which to determine the gradient of `f`.
  820. f : callable
  821. Function of which to estimate the derivatives of. Has the signature
  822. ``f(xk, *args)`` where `xk` is the argument in the form of a 1-D array
  823. and `args` is a tuple of any additional fixed parameters needed to
  824. completely specify the function. The argument `xk` passed to this
  825. function is an ndarray of shape (n,) (never a scalar even if n=1).
  826. It must return a 1-D array_like of shape (m,) or a scalar.
  827. .. versionchanged:: 1.9.0
  828. `f` is now able to return a 1-D array-like, with the :math:`(m, n)`
  829. Jacobian being estimated.
  830. epsilon : {float, array_like}, optional
  831. Increment to `xk` to use for determining the function gradient.
  832. If a scalar, uses the same finite difference delta for all partial
  833. derivatives. If an array, should contain one value per element of
  834. `xk`. Defaults to ``sqrt(np.finfo(float).eps)``, which is approximately
  835. 1.49e-08.
  836. \\*args : args, optional
  837. Any other arguments that are to be passed to `f`.
  838. Returns
  839. -------
  840. jac : ndarray
  841. The partial derivatives of `f` to `xk`.
  842. See Also
  843. --------
  844. check_grad : Check correctness of gradient function against approx_fprime.
  845. Notes
  846. -----
  847. The function gradient is determined by the forward finite difference
  848. formula::
  849. f(xk[i] + epsilon[i]) - f(xk[i])
  850. f'[i] = ---------------------------------
  851. epsilon[i]
  852. Examples
  853. --------
  854. >>> import numpy as np
  855. >>> from scipy import optimize
  856. >>> def func(x, c0, c1):
  857. ... "Coordinate vector `x` should be an array of size two."
  858. ... return c0 * x[0]**2 + c1*x[1]**2
  859. >>> x = np.ones(2)
  860. >>> c0, c1 = (1, 200)
  861. >>> eps = np.sqrt(np.finfo(float).eps)
  862. >>> optimize.approx_fprime(x, func, [eps, np.sqrt(200) * eps], c0, c1)
  863. array([ 2. , 400.00004198])
  864. """
  865. xk = np.asarray(xk, float)
  866. f0 = f(xk, *args)
  867. return approx_derivative(f, xk, method='2-point', abs_step=epsilon,
  868. args=args, f0=f0)
  869. def check_grad(func, grad, x0, *args, epsilon=_epsilon,
  870. direction='all', seed=None):
  871. """Check the correctness of a gradient function by comparing it against a
  872. (forward) finite-difference approximation of the gradient.
  873. Parameters
  874. ----------
  875. func : callable ``func(x0, *args)``
  876. Function whose derivative is to be checked.
  877. grad : callable ``grad(x0, *args)``
  878. Jacobian of `func`.
  879. x0 : ndarray
  880. Points to check `grad` against forward difference approximation of grad
  881. using `func`.
  882. args : \\*args, optional
  883. Extra arguments passed to `func` and `grad`.
  884. epsilon : float, optional
  885. Step size used for the finite difference approximation. It defaults to
  886. ``sqrt(np.finfo(float).eps)``, which is approximately 1.49e-08.
  887. direction : str, optional
  888. If set to ``'random'``, then gradients along a random vector
  889. are used to check `grad` against forward difference approximation
  890. using `func`. By default it is ``'all'``, in which case, all
  891. the one hot direction vectors are considered to check `grad`.
  892. If `func` is a vector valued function then only ``'all'`` can be used.
  893. seed : {None, int, `numpy.random.Generator`, `numpy.random.RandomState`}, optional
  894. If `seed` is None (or `np.random`), the `numpy.random.RandomState`
  895. singleton is used.
  896. If `seed` is an int, a new ``RandomState`` instance is used,
  897. seeded with `seed`.
  898. If `seed` is already a ``Generator`` or ``RandomState`` instance then
  899. that instance is used.
  900. Specify `seed` for reproducing the return value from this function.
  901. The random numbers generated with this seed affect the random vector
  902. along which gradients are computed to check ``grad``. Note that `seed`
  903. is only used when `direction` argument is set to `'random'`.
  904. Returns
  905. -------
  906. err : float
  907. The square root of the sum of squares (i.e., the 2-norm) of the
  908. difference between ``grad(x0, *args)`` and the finite difference
  909. approximation of `grad` using func at the points `x0`.
  910. See Also
  911. --------
  912. approx_fprime
  913. Examples
  914. --------
  915. >>> import numpy as np
  916. >>> def func(x):
  917. ... return x[0]**2 - 0.5 * x[1]**3
  918. >>> def grad(x):
  919. ... return [2 * x[0], -1.5 * x[1]**2]
  920. >>> from scipy.optimize import check_grad
  921. >>> check_grad(func, grad, [1.5, -1.5])
  922. 2.9802322387695312e-08 # may vary
  923. >>> rng = np.random.default_rng()
  924. >>> check_grad(func, grad, [1.5, -1.5],
  925. ... direction='random', seed=rng)
  926. 2.9802322387695312e-08
  927. """
  928. step = epsilon
  929. x0 = np.asarray(x0)
  930. def g(w, func, x0, v, *args):
  931. return func(x0 + w*v, *args)
  932. if direction == 'random':
  933. _grad = np.asanyarray(grad(x0, *args))
  934. if _grad.ndim > 1:
  935. raise ValueError("'random' can only be used with scalar valued"
  936. " func")
  937. random_state = check_random_state(seed)
  938. v = random_state.normal(0, 1, size=(x0.shape))
  939. _args = (func, x0, v) + args
  940. _func = g
  941. vars = np.zeros((1,))
  942. analytical_grad = np.dot(_grad, v)
  943. elif direction == 'all':
  944. _args = args
  945. _func = func
  946. vars = x0
  947. analytical_grad = grad(x0, *args)
  948. else:
  949. raise ValueError("{} is not a valid string for "
  950. "``direction`` argument".format(direction))
  951. return np.sqrt(np.sum(np.abs(
  952. (analytical_grad - approx_fprime(vars, _func, step, *_args))**2
  953. )))
  954. def approx_fhess_p(x0, p, fprime, epsilon, *args):
  955. # calculate fprime(x0) first, as this may be cached by ScalarFunction
  956. f1 = fprime(*((x0,) + args))
  957. f2 = fprime(*((x0 + epsilon*p,) + args))
  958. return (f2 - f1) / epsilon
  959. class _LineSearchError(RuntimeError):
  960. pass
  961. def _line_search_wolfe12(f, fprime, xk, pk, gfk, old_fval, old_old_fval,
  962. **kwargs):
  963. """
  964. Same as line_search_wolfe1, but fall back to line_search_wolfe2 if
  965. suitable step length is not found, and raise an exception if a
  966. suitable step length is not found.
  967. Raises
  968. ------
  969. _LineSearchError
  970. If no suitable step size is found
  971. """
  972. extra_condition = kwargs.pop('extra_condition', None)
  973. ret = line_search_wolfe1(f, fprime, xk, pk, gfk,
  974. old_fval, old_old_fval,
  975. **kwargs)
  976. if ret[0] is not None and extra_condition is not None:
  977. xp1 = xk + ret[0] * pk
  978. if not extra_condition(ret[0], xp1, ret[3], ret[5]):
  979. # Reject step if extra_condition fails
  980. ret = (None,)
  981. if ret[0] is None:
  982. # line search failed: try different one.
  983. with warnings.catch_warnings():
  984. warnings.simplefilter('ignore', LineSearchWarning)
  985. kwargs2 = {}
  986. for key in ('c1', 'c2', 'amax'):
  987. if key in kwargs:
  988. kwargs2[key] = kwargs[key]
  989. ret = line_search_wolfe2(f, fprime, xk, pk, gfk,
  990. old_fval, old_old_fval,
  991. extra_condition=extra_condition,
  992. **kwargs2)
  993. if ret[0] is None:
  994. raise _LineSearchError()
  995. return ret
  996. def fmin_bfgs(f, x0, fprime=None, args=(), gtol=1e-5, norm=Inf,
  997. epsilon=_epsilon, maxiter=None, full_output=0, disp=1,
  998. retall=0, callback=None, xrtol=0):
  999. """
  1000. Minimize a function using the BFGS algorithm.
  1001. Parameters
  1002. ----------
  1003. f : callable ``f(x,*args)``
  1004. Objective function to be minimized.
  1005. x0 : ndarray
  1006. Initial guess.
  1007. fprime : callable ``f'(x,*args)``, optional
  1008. Gradient of f.
  1009. args : tuple, optional
  1010. Extra arguments passed to f and fprime.
  1011. gtol : float, optional
  1012. Terminate successfully if gradient norm is less than `gtol`
  1013. norm : float, optional
  1014. Order of norm (Inf is max, -Inf is min)
  1015. epsilon : int or ndarray, optional
  1016. If `fprime` is approximated, use this value for the step size.
  1017. callback : callable, optional
  1018. An optional user-supplied function to call after each
  1019. iteration. Called as ``callback(xk)``, where ``xk`` is the
  1020. current parameter vector.
  1021. maxiter : int, optional
  1022. Maximum number of iterations to perform.
  1023. full_output : bool, optional
  1024. If True, return ``fopt``, ``func_calls``, ``grad_calls``, and
  1025. ``warnflag`` in addition to ``xopt``.
  1026. disp : bool, optional
  1027. Print convergence message if True.
  1028. retall : bool, optional
  1029. Return a list of results at each iteration if True.
  1030. xrtol : float, default: 0
  1031. Relative tolerance for `x`. Terminate successfully if step
  1032. size is less than ``xk * xrtol`` where ``xk`` is the current
  1033. parameter vector.
  1034. Returns
  1035. -------
  1036. xopt : ndarray
  1037. Parameters which minimize f, i.e., ``f(xopt) == fopt``.
  1038. fopt : float
  1039. Minimum value.
  1040. gopt : ndarray
  1041. Value of gradient at minimum, f'(xopt), which should be near 0.
  1042. Bopt : ndarray
  1043. Value of 1/f''(xopt), i.e., the inverse Hessian matrix.
  1044. func_calls : int
  1045. Number of function_calls made.
  1046. grad_calls : int
  1047. Number of gradient calls made.
  1048. warnflag : integer
  1049. 1 : Maximum number of iterations exceeded.
  1050. 2 : Gradient and/or function calls not changing.
  1051. 3 : NaN result encountered.
  1052. allvecs : list
  1053. The value of `xopt` at each iteration. Only returned if `retall` is
  1054. True.
  1055. Notes
  1056. -----
  1057. Optimize the function, `f`, whose gradient is given by `fprime`
  1058. using the quasi-Newton method of Broyden, Fletcher, Goldfarb,
  1059. and Shanno (BFGS).
  1060. See Also
  1061. --------
  1062. minimize: Interface to minimization algorithms for multivariate
  1063. functions. See ``method='BFGS'`` in particular.
  1064. References
  1065. ----------
  1066. Wright, and Nocedal 'Numerical Optimization', 1999, p. 198.
  1067. Examples
  1068. --------
  1069. >>> import numpy as np
  1070. >>> from scipy.optimize import fmin_bfgs
  1071. >>> def quadratic_cost(x, Q):
  1072. ... return x @ Q @ x
  1073. ...
  1074. >>> x0 = np.array([-3, -4])
  1075. >>> cost_weight = np.diag([1., 10.])
  1076. >>> # Note that a trailing comma is necessary for a tuple with single element
  1077. >>> fmin_bfgs(quadratic_cost, x0, args=(cost_weight,))
  1078. Optimization terminated successfully.
  1079. Current function value: 0.000000
  1080. Iterations: 7 # may vary
  1081. Function evaluations: 24 # may vary
  1082. Gradient evaluations: 8 # may vary
  1083. array([ 2.85169950e-06, -4.61820139e-07])
  1084. >>> def quadratic_cost_grad(x, Q):
  1085. ... return 2 * Q @ x
  1086. ...
  1087. >>> fmin_bfgs(quadratic_cost, x0, quadratic_cost_grad, args=(cost_weight,))
  1088. Optimization terminated successfully.
  1089. Current function value: 0.000000
  1090. Iterations: 7
  1091. Function evaluations: 8
  1092. Gradient evaluations: 8
  1093. array([ 2.85916637e-06, -4.54371951e-07])
  1094. """
  1095. opts = {'gtol': gtol,
  1096. 'norm': norm,
  1097. 'eps': epsilon,
  1098. 'disp': disp,
  1099. 'maxiter': maxiter,
  1100. 'return_all': retall}
  1101. res = _minimize_bfgs(f, x0, args, fprime, callback=callback, **opts)
  1102. if full_output:
  1103. retlist = (res['x'], res['fun'], res['jac'], res['hess_inv'],
  1104. res['nfev'], res['njev'], res['status'])
  1105. if retall:
  1106. retlist += (res['allvecs'], )
  1107. return retlist
  1108. else:
  1109. if retall:
  1110. return res['x'], res['allvecs']
  1111. else:
  1112. return res['x']
  1113. def _minimize_bfgs(fun, x0, args=(), jac=None, callback=None,
  1114. gtol=1e-5, norm=Inf, eps=_epsilon, maxiter=None,
  1115. disp=False, return_all=False, finite_diff_rel_step=None,
  1116. xrtol=0, **unknown_options):
  1117. """
  1118. Minimization of scalar function of one or more variables using the
  1119. BFGS algorithm.
  1120. Options
  1121. -------
  1122. disp : bool
  1123. Set to True to print convergence messages.
  1124. maxiter : int
  1125. Maximum number of iterations to perform.
  1126. gtol : float
  1127. Terminate successfully if gradient norm is less than `gtol`.
  1128. norm : float
  1129. Order of norm (Inf is max, -Inf is min).
  1130. eps : float or ndarray
  1131. If `jac is None` the absolute step size used for numerical
  1132. approximation of the jacobian via forward differences.
  1133. return_all : bool, optional
  1134. Set to True to return a list of the best solution at each of the
  1135. iterations.
  1136. finite_diff_rel_step : None or array_like, optional
  1137. If `jac in ['2-point', '3-point', 'cs']` the relative step size to
  1138. use for numerical approximation of the jacobian. The absolute step
  1139. size is computed as ``h = rel_step * sign(x) * max(1, abs(x))``,
  1140. possibly adjusted to fit into the bounds. For ``method='3-point'``
  1141. the sign of `h` is ignored. If None (default) then step is selected
  1142. automatically.
  1143. xrtol : float, default: 0
  1144. Relative tolerance for `x`. Terminate successfully if step size is
  1145. less than ``xk * xrtol`` where ``xk`` is the current parameter vector.
  1146. """
  1147. _check_unknown_options(unknown_options)
  1148. retall = return_all
  1149. x0 = asarray(x0).flatten()
  1150. if x0.ndim == 0:
  1151. x0.shape = (1,)
  1152. if maxiter is None:
  1153. maxiter = len(x0) * 200
  1154. sf = _prepare_scalar_function(fun, x0, jac, args=args, epsilon=eps,
  1155. finite_diff_rel_step=finite_diff_rel_step)
  1156. f = sf.fun
  1157. myfprime = sf.grad
  1158. old_fval = f(x0)
  1159. gfk = myfprime(x0)
  1160. k = 0
  1161. N = len(x0)
  1162. I = np.eye(N, dtype=int)
  1163. Hk = I
  1164. # Sets the initial step guess to dx ~ 1
  1165. old_old_fval = old_fval + np.linalg.norm(gfk) / 2
  1166. xk = x0
  1167. if retall:
  1168. allvecs = [x0]
  1169. warnflag = 0
  1170. gnorm = vecnorm(gfk, ord=norm)
  1171. while (gnorm > gtol) and (k < maxiter):
  1172. pk = -np.dot(Hk, gfk)
  1173. try:
  1174. alpha_k, fc, gc, old_fval, old_old_fval, gfkp1 = \
  1175. _line_search_wolfe12(f, myfprime, xk, pk, gfk,
  1176. old_fval, old_old_fval, amin=1e-100, amax=1e100)
  1177. except _LineSearchError:
  1178. # Line search failed to find a better solution.
  1179. warnflag = 2
  1180. break
  1181. sk = alpha_k * pk
  1182. xkp1 = xk + sk
  1183. if retall:
  1184. allvecs.append(xkp1)
  1185. xk = xkp1
  1186. if gfkp1 is None:
  1187. gfkp1 = myfprime(xkp1)
  1188. yk = gfkp1 - gfk
  1189. gfk = gfkp1
  1190. if callback is not None:
  1191. callback(xk)
  1192. k += 1
  1193. gnorm = vecnorm(gfk, ord=norm)
  1194. if (gnorm <= gtol):
  1195. break
  1196. # See Chapter 5 in P.E. Frandsen, K. Jonasson, H.B. Nielsen,
  1197. # O. Tingleff: "Unconstrained Optimization", IMM, DTU. 1999.
  1198. # These notes are available here:
  1199. # http://www2.imm.dtu.dk/documents/ftp/publlec.html
  1200. if (alpha_k*vecnorm(pk) <= xrtol*(xrtol + vecnorm(xk))):
  1201. break
  1202. if not np.isfinite(old_fval):
  1203. # We correctly found +-Inf as optimal value, or something went
  1204. # wrong.
  1205. warnflag = 2
  1206. break
  1207. rhok_inv = np.dot(yk, sk)
  1208. # this was handled in numeric, let it remaines for more safety
  1209. # Cryptic comment above is preserved for posterity. Future reader:
  1210. # consider change to condition below proposed in gh-1261/gh-17345.
  1211. if rhok_inv == 0.:
  1212. rhok = 1000.0
  1213. if disp:
  1214. print("Divide-by-zero encountered: rhok assumed large")
  1215. else:
  1216. rhok = 1. / rhok_inv
  1217. A1 = I - sk[:, np.newaxis] * yk[np.newaxis, :] * rhok
  1218. A2 = I - yk[:, np.newaxis] * sk[np.newaxis, :] * rhok
  1219. Hk = np.dot(A1, np.dot(Hk, A2)) + (rhok * sk[:, np.newaxis] *
  1220. sk[np.newaxis, :])
  1221. fval = old_fval
  1222. if warnflag == 2:
  1223. msg = _status_message['pr_loss']
  1224. elif k >= maxiter:
  1225. warnflag = 1
  1226. msg = _status_message['maxiter']
  1227. elif np.isnan(gnorm) or np.isnan(fval) or np.isnan(xk).any():
  1228. warnflag = 3
  1229. msg = _status_message['nan']
  1230. else:
  1231. msg = _status_message['success']
  1232. if disp:
  1233. print("%s%s" % ("Warning: " if warnflag != 0 else "", msg))
  1234. print(" Current function value: %f" % fval)
  1235. print(" Iterations: %d" % k)
  1236. print(" Function evaluations: %d" % sf.nfev)
  1237. print(" Gradient evaluations: %d" % sf.ngev)
  1238. result = OptimizeResult(fun=fval, jac=gfk, hess_inv=Hk, nfev=sf.nfev,
  1239. njev=sf.ngev, status=warnflag,
  1240. success=(warnflag == 0), message=msg, x=xk,
  1241. nit=k)
  1242. if retall:
  1243. result['allvecs'] = allvecs
  1244. return result
  1245. def fmin_cg(f, x0, fprime=None, args=(), gtol=1e-5, norm=Inf, epsilon=_epsilon,
  1246. maxiter=None, full_output=0, disp=1, retall=0, callback=None):
  1247. """
  1248. Minimize a function using a nonlinear conjugate gradient algorithm.
  1249. Parameters
  1250. ----------
  1251. f : callable, ``f(x, *args)``
  1252. Objective function to be minimized. Here `x` must be a 1-D array of
  1253. the variables that are to be changed in the search for a minimum, and
  1254. `args` are the other (fixed) parameters of `f`.
  1255. x0 : ndarray
  1256. A user-supplied initial estimate of `xopt`, the optimal value of `x`.
  1257. It must be a 1-D array of values.
  1258. fprime : callable, ``fprime(x, *args)``, optional
  1259. A function that returns the gradient of `f` at `x`. Here `x` and `args`
  1260. are as described above for `f`. The returned value must be a 1-D array.
  1261. Defaults to None, in which case the gradient is approximated
  1262. numerically (see `epsilon`, below).
  1263. args : tuple, optional
  1264. Parameter values passed to `f` and `fprime`. Must be supplied whenever
  1265. additional fixed parameters are needed to completely specify the
  1266. functions `f` and `fprime`.
  1267. gtol : float, optional
  1268. Stop when the norm of the gradient is less than `gtol`.
  1269. norm : float, optional
  1270. Order to use for the norm of the gradient
  1271. (``-np.Inf`` is min, ``np.Inf`` is max).
  1272. epsilon : float or ndarray, optional
  1273. Step size(s) to use when `fprime` is approximated numerically. Can be a
  1274. scalar or a 1-D array. Defaults to ``sqrt(eps)``, with eps the
  1275. floating point machine precision. Usually ``sqrt(eps)`` is about
  1276. 1.5e-8.
  1277. maxiter : int, optional
  1278. Maximum number of iterations to perform. Default is ``200 * len(x0)``.
  1279. full_output : bool, optional
  1280. If True, return `fopt`, `func_calls`, `grad_calls`, and `warnflag` in
  1281. addition to `xopt`. See the Returns section below for additional
  1282. information on optional return values.
  1283. disp : bool, optional
  1284. If True, return a convergence message, followed by `xopt`.
  1285. retall : bool, optional
  1286. If True, add to the returned values the results of each iteration.
  1287. callback : callable, optional
  1288. An optional user-supplied function, called after each iteration.
  1289. Called as ``callback(xk)``, where ``xk`` is the current value of `x0`.
  1290. Returns
  1291. -------
  1292. xopt : ndarray
  1293. Parameters which minimize f, i.e., ``f(xopt) == fopt``.
  1294. fopt : float, optional
  1295. Minimum value found, f(xopt). Only returned if `full_output` is True.
  1296. func_calls : int, optional
  1297. The number of function_calls made. Only returned if `full_output`
  1298. is True.
  1299. grad_calls : int, optional
  1300. The number of gradient calls made. Only returned if `full_output` is
  1301. True.
  1302. warnflag : int, optional
  1303. Integer value with warning status, only returned if `full_output` is
  1304. True.
  1305. 0 : Success.
  1306. 1 : The maximum number of iterations was exceeded.
  1307. 2 : Gradient and/or function calls were not changing. May indicate
  1308. that precision was lost, i.e., the routine did not converge.
  1309. 3 : NaN result encountered.
  1310. allvecs : list of ndarray, optional
  1311. List of arrays, containing the results at each iteration.
  1312. Only returned if `retall` is True.
  1313. See Also
  1314. --------
  1315. minimize : common interface to all `scipy.optimize` algorithms for
  1316. unconstrained and constrained minimization of multivariate
  1317. functions. It provides an alternative way to call
  1318. ``fmin_cg``, by specifying ``method='CG'``.
  1319. Notes
  1320. -----
  1321. This conjugate gradient algorithm is based on that of Polak and Ribiere
  1322. [1]_.
  1323. Conjugate gradient methods tend to work better when:
  1324. 1. `f` has a unique global minimizing point, and no local minima or
  1325. other stationary points,
  1326. 2. `f` is, at least locally, reasonably well approximated by a
  1327. quadratic function of the variables,
  1328. 3. `f` is continuous and has a continuous gradient,
  1329. 4. `fprime` is not too large, e.g., has a norm less than 1000,
  1330. 5. The initial guess, `x0`, is reasonably close to `f` 's global
  1331. minimizing point, `xopt`.
  1332. References
  1333. ----------
  1334. .. [1] Wright & Nocedal, "Numerical Optimization", 1999, pp. 120-122.
  1335. Examples
  1336. --------
  1337. Example 1: seek the minimum value of the expression
  1338. ``a*u**2 + b*u*v + c*v**2 + d*u + e*v + f`` for given values
  1339. of the parameters and an initial guess ``(u, v) = (0, 0)``.
  1340. >>> import numpy as np
  1341. >>> args = (2, 3, 7, 8, 9, 10) # parameter values
  1342. >>> def f(x, *args):
  1343. ... u, v = x
  1344. ... a, b, c, d, e, f = args
  1345. ... return a*u**2 + b*u*v + c*v**2 + d*u + e*v + f
  1346. >>> def gradf(x, *args):
  1347. ... u, v = x
  1348. ... a, b, c, d, e, f = args
  1349. ... gu = 2*a*u + b*v + d # u-component of the gradient
  1350. ... gv = b*u + 2*c*v + e # v-component of the gradient
  1351. ... return np.asarray((gu, gv))
  1352. >>> x0 = np.asarray((0, 0)) # Initial guess.
  1353. >>> from scipy import optimize
  1354. >>> res1 = optimize.fmin_cg(f, x0, fprime=gradf, args=args)
  1355. Optimization terminated successfully.
  1356. Current function value: 1.617021
  1357. Iterations: 4
  1358. Function evaluations: 8
  1359. Gradient evaluations: 8
  1360. >>> res1
  1361. array([-1.80851064, -0.25531915])
  1362. Example 2: solve the same problem using the `minimize` function.
  1363. (This `myopts` dictionary shows all of the available options,
  1364. although in practice only non-default values would be needed.
  1365. The returned value will be a dictionary.)
  1366. >>> opts = {'maxiter' : None, # default value.
  1367. ... 'disp' : True, # non-default value.
  1368. ... 'gtol' : 1e-5, # default value.
  1369. ... 'norm' : np.inf, # default value.
  1370. ... 'eps' : 1.4901161193847656e-08} # default value.
  1371. >>> res2 = optimize.minimize(f, x0, jac=gradf, args=args,
  1372. ... method='CG', options=opts)
  1373. Optimization terminated successfully.
  1374. Current function value: 1.617021
  1375. Iterations: 4
  1376. Function evaluations: 8
  1377. Gradient evaluations: 8
  1378. >>> res2.x # minimum found
  1379. array([-1.80851064, -0.25531915])
  1380. """
  1381. opts = {'gtol': gtol,
  1382. 'norm': norm,
  1383. 'eps': epsilon,
  1384. 'disp': disp,
  1385. 'maxiter': maxiter,
  1386. 'return_all': retall}
  1387. res = _minimize_cg(f, x0, args, fprime, callback=callback, **opts)
  1388. if full_output:
  1389. retlist = res['x'], res['fun'], res['nfev'], res['njev'], res['status']
  1390. if retall:
  1391. retlist += (res['allvecs'], )
  1392. return retlist
  1393. else:
  1394. if retall:
  1395. return res['x'], res['allvecs']
  1396. else:
  1397. return res['x']
  1398. def _minimize_cg(fun, x0, args=(), jac=None, callback=None,
  1399. gtol=1e-5, norm=Inf, eps=_epsilon, maxiter=None,
  1400. disp=False, return_all=False, finite_diff_rel_step=None,
  1401. **unknown_options):
  1402. """
  1403. Minimization of scalar function of one or more variables using the
  1404. conjugate gradient algorithm.
  1405. Options
  1406. -------
  1407. disp : bool
  1408. Set to True to print convergence messages.
  1409. maxiter : int
  1410. Maximum number of iterations to perform.
  1411. gtol : float
  1412. Gradient norm must be less than `gtol` before successful
  1413. termination.
  1414. norm : float
  1415. Order of norm (Inf is max, -Inf is min).
  1416. eps : float or ndarray
  1417. If `jac is None` the absolute step size used for numerical
  1418. approximation of the jacobian via forward differences.
  1419. return_all : bool, optional
  1420. Set to True to return a list of the best solution at each of the
  1421. iterations.
  1422. finite_diff_rel_step : None or array_like, optional
  1423. If `jac in ['2-point', '3-point', 'cs']` the relative step size to
  1424. use for numerical approximation of the jacobian. The absolute step
  1425. size is computed as ``h = rel_step * sign(x) * max(1, abs(x))``,
  1426. possibly adjusted to fit into the bounds. For ``method='3-point'``
  1427. the sign of `h` is ignored. If None (default) then step is selected
  1428. automatically.
  1429. """
  1430. _check_unknown_options(unknown_options)
  1431. retall = return_all
  1432. x0 = asarray(x0).flatten()
  1433. if maxiter is None:
  1434. maxiter = len(x0) * 200
  1435. sf = _prepare_scalar_function(fun, x0, jac=jac, args=args, epsilon=eps,
  1436. finite_diff_rel_step=finite_diff_rel_step)
  1437. f = sf.fun
  1438. myfprime = sf.grad
  1439. old_fval = f(x0)
  1440. gfk = myfprime(x0)
  1441. k = 0
  1442. xk = x0
  1443. # Sets the initial step guess to dx ~ 1
  1444. old_old_fval = old_fval + np.linalg.norm(gfk) / 2
  1445. if retall:
  1446. allvecs = [xk]
  1447. warnflag = 0
  1448. pk = -gfk
  1449. gnorm = vecnorm(gfk, ord=norm)
  1450. sigma_3 = 0.01
  1451. while (gnorm > gtol) and (k < maxiter):
  1452. deltak = np.dot(gfk, gfk)
  1453. cached_step = [None]
  1454. def polak_ribiere_powell_step(alpha, gfkp1=None):
  1455. xkp1 = xk + alpha * pk
  1456. if gfkp1 is None:
  1457. gfkp1 = myfprime(xkp1)
  1458. yk = gfkp1 - gfk
  1459. beta_k = max(0, np.dot(yk, gfkp1) / deltak)
  1460. pkp1 = -gfkp1 + beta_k * pk
  1461. gnorm = vecnorm(gfkp1, ord=norm)
  1462. return (alpha, xkp1, pkp1, gfkp1, gnorm)
  1463. def descent_condition(alpha, xkp1, fp1, gfkp1):
  1464. # Polak-Ribiere+ needs an explicit check of a sufficient
  1465. # descent condition, which is not guaranteed by strong Wolfe.
  1466. #
  1467. # See Gilbert & Nocedal, "Global convergence properties of
  1468. # conjugate gradient methods for optimization",
  1469. # SIAM J. Optimization 2, 21 (1992).
  1470. cached_step[:] = polak_ribiere_powell_step(alpha, gfkp1)
  1471. alpha, xk, pk, gfk, gnorm = cached_step
  1472. # Accept step if it leads to convergence.
  1473. if gnorm <= gtol:
  1474. return True
  1475. # Accept step if sufficient descent condition applies.
  1476. return np.dot(pk, gfk) <= -sigma_3 * np.dot(gfk, gfk)
  1477. try:
  1478. alpha_k, fc, gc, old_fval, old_old_fval, gfkp1 = \
  1479. _line_search_wolfe12(f, myfprime, xk, pk, gfk, old_fval,
  1480. old_old_fval, c2=0.4, amin=1e-100, amax=1e100,
  1481. extra_condition=descent_condition)
  1482. except _LineSearchError:
  1483. # Line search failed to find a better solution.
  1484. warnflag = 2
  1485. break
  1486. # Reuse already computed results if possible
  1487. if alpha_k == cached_step[0]:
  1488. alpha_k, xk, pk, gfk, gnorm = cached_step
  1489. else:
  1490. alpha_k, xk, pk, gfk, gnorm = polak_ribiere_powell_step(alpha_k, gfkp1)
  1491. if retall:
  1492. allvecs.append(xk)
  1493. if callback is not None:
  1494. callback(xk)
  1495. k += 1
  1496. fval = old_fval
  1497. if warnflag == 2:
  1498. msg = _status_message['pr_loss']
  1499. elif k >= maxiter:
  1500. warnflag = 1
  1501. msg = _status_message['maxiter']
  1502. elif np.isnan(gnorm) or np.isnan(fval) or np.isnan(xk).any():
  1503. warnflag = 3
  1504. msg = _status_message['nan']
  1505. else:
  1506. msg = _status_message['success']
  1507. if disp:
  1508. print("%s%s" % ("Warning: " if warnflag != 0 else "", msg))
  1509. print(" Current function value: %f" % fval)
  1510. print(" Iterations: %d" % k)
  1511. print(" Function evaluations: %d" % sf.nfev)
  1512. print(" Gradient evaluations: %d" % sf.ngev)
  1513. result = OptimizeResult(fun=fval, jac=gfk, nfev=sf.nfev,
  1514. njev=sf.ngev, status=warnflag,
  1515. success=(warnflag == 0), message=msg, x=xk,
  1516. nit=k)
  1517. if retall:
  1518. result['allvecs'] = allvecs
  1519. return result
  1520. def fmin_ncg(f, x0, fprime, fhess_p=None, fhess=None, args=(), avextol=1e-5,
  1521. epsilon=_epsilon, maxiter=None, full_output=0, disp=1, retall=0,
  1522. callback=None):
  1523. """
  1524. Unconstrained minimization of a function using the Newton-CG method.
  1525. Parameters
  1526. ----------
  1527. f : callable ``f(x, *args)``
  1528. Objective function to be minimized.
  1529. x0 : ndarray
  1530. Initial guess.
  1531. fprime : callable ``f'(x, *args)``
  1532. Gradient of f.
  1533. fhess_p : callable ``fhess_p(x, p, *args)``, optional
  1534. Function which computes the Hessian of f times an
  1535. arbitrary vector, p.
  1536. fhess : callable ``fhess(x, *args)``, optional
  1537. Function to compute the Hessian matrix of f.
  1538. args : tuple, optional
  1539. Extra arguments passed to f, fprime, fhess_p, and fhess
  1540. (the same set of extra arguments is supplied to all of
  1541. these functions).
  1542. epsilon : float or ndarray, optional
  1543. If fhess is approximated, use this value for the step size.
  1544. callback : callable, optional
  1545. An optional user-supplied function which is called after
  1546. each iteration. Called as callback(xk), where xk is the
  1547. current parameter vector.
  1548. avextol : float, optional
  1549. Convergence is assumed when the average relative error in
  1550. the minimizer falls below this amount.
  1551. maxiter : int, optional
  1552. Maximum number of iterations to perform.
  1553. full_output : bool, optional
  1554. If True, return the optional outputs.
  1555. disp : bool, optional
  1556. If True, print convergence message.
  1557. retall : bool, optional
  1558. If True, return a list of results at each iteration.
  1559. Returns
  1560. -------
  1561. xopt : ndarray
  1562. Parameters which minimize f, i.e., ``f(xopt) == fopt``.
  1563. fopt : float
  1564. Value of the function at xopt, i.e., ``fopt = f(xopt)``.
  1565. fcalls : int
  1566. Number of function calls made.
  1567. gcalls : int
  1568. Number of gradient calls made.
  1569. hcalls : int
  1570. Number of Hessian calls made.
  1571. warnflag : int
  1572. Warnings generated by the algorithm.
  1573. 1 : Maximum number of iterations exceeded.
  1574. 2 : Line search failure (precision loss).
  1575. 3 : NaN result encountered.
  1576. allvecs : list
  1577. The result at each iteration, if retall is True (see below).
  1578. See also
  1579. --------
  1580. minimize: Interface to minimization algorithms for multivariate
  1581. functions. See the 'Newton-CG' `method` in particular.
  1582. Notes
  1583. -----
  1584. Only one of `fhess_p` or `fhess` need to be given. If `fhess`
  1585. is provided, then `fhess_p` will be ignored. If neither `fhess`
  1586. nor `fhess_p` is provided, then the hessian product will be
  1587. approximated using finite differences on `fprime`. `fhess_p`
  1588. must compute the hessian times an arbitrary vector. If it is not
  1589. given, finite-differences on `fprime` are used to compute
  1590. it.
  1591. Newton-CG methods are also called truncated Newton methods. This
  1592. function differs from scipy.optimize.fmin_tnc because
  1593. 1. scipy.optimize.fmin_ncg is written purely in Python using NumPy
  1594. and scipy while scipy.optimize.fmin_tnc calls a C function.
  1595. 2. scipy.optimize.fmin_ncg is only for unconstrained minimization
  1596. while scipy.optimize.fmin_tnc is for unconstrained minimization
  1597. or box constrained minimization. (Box constraints give
  1598. lower and upper bounds for each variable separately.)
  1599. References
  1600. ----------
  1601. Wright & Nocedal, 'Numerical Optimization', 1999, p. 140.
  1602. """
  1603. opts = {'xtol': avextol,
  1604. 'eps': epsilon,
  1605. 'maxiter': maxiter,
  1606. 'disp': disp,
  1607. 'return_all': retall}
  1608. res = _minimize_newtoncg(f, x0, args, fprime, fhess, fhess_p,
  1609. callback=callback, **opts)
  1610. if full_output:
  1611. retlist = (res['x'], res['fun'], res['nfev'], res['njev'],
  1612. res['nhev'], res['status'])
  1613. if retall:
  1614. retlist += (res['allvecs'], )
  1615. return retlist
  1616. else:
  1617. if retall:
  1618. return res['x'], res['allvecs']
  1619. else:
  1620. return res['x']
  1621. def _minimize_newtoncg(fun, x0, args=(), jac=None, hess=None, hessp=None,
  1622. callback=None, xtol=1e-5, eps=_epsilon, maxiter=None,
  1623. disp=False, return_all=False,
  1624. **unknown_options):
  1625. """
  1626. Minimization of scalar function of one or more variables using the
  1627. Newton-CG algorithm.
  1628. Note that the `jac` parameter (Jacobian) is required.
  1629. Options
  1630. -------
  1631. disp : bool
  1632. Set to True to print convergence messages.
  1633. xtol : float
  1634. Average relative error in solution `xopt` acceptable for
  1635. convergence.
  1636. maxiter : int
  1637. Maximum number of iterations to perform.
  1638. eps : float or ndarray
  1639. If `hessp` is approximated, use this value for the step size.
  1640. return_all : bool, optional
  1641. Set to True to return a list of the best solution at each of the
  1642. iterations.
  1643. """
  1644. _check_unknown_options(unknown_options)
  1645. if jac is None:
  1646. raise ValueError('Jacobian is required for Newton-CG method')
  1647. fhess_p = hessp
  1648. fhess = hess
  1649. avextol = xtol
  1650. epsilon = eps
  1651. retall = return_all
  1652. x0 = asarray(x0).flatten()
  1653. # TODO: add hessp (callable or FD) to ScalarFunction?
  1654. sf = _prepare_scalar_function(
  1655. fun, x0, jac, args=args, epsilon=eps, hess=hess
  1656. )
  1657. f = sf.fun
  1658. fprime = sf.grad
  1659. _h = sf.hess(x0)
  1660. # Logic for hess/hessp
  1661. # - If a callable(hess) is provided, then use that
  1662. # - If hess is a FD_METHOD, or the output fom hess(x) is a LinearOperator
  1663. # then create a hessp function using those.
  1664. # - If hess is None but you have callable(hessp) then use the hessp.
  1665. # - If hess and hessp are None then approximate hessp using the grad/jac.
  1666. if (hess in FD_METHODS or isinstance(_h, LinearOperator)):
  1667. fhess = None
  1668. def _hessp(x, p, *args):
  1669. return sf.hess(x).dot(p)
  1670. fhess_p = _hessp
  1671. def terminate(warnflag, msg):
  1672. if disp:
  1673. print(msg)
  1674. print(" Current function value: %f" % old_fval)
  1675. print(" Iterations: %d" % k)
  1676. print(" Function evaluations: %d" % sf.nfev)
  1677. print(" Gradient evaluations: %d" % sf.ngev)
  1678. print(" Hessian evaluations: %d" % hcalls)
  1679. fval = old_fval
  1680. result = OptimizeResult(fun=fval, jac=gfk, nfev=sf.nfev,
  1681. njev=sf.ngev, nhev=hcalls, status=warnflag,
  1682. success=(warnflag == 0), message=msg, x=xk,
  1683. nit=k)
  1684. if retall:
  1685. result['allvecs'] = allvecs
  1686. return result
  1687. hcalls = 0
  1688. if maxiter is None:
  1689. maxiter = len(x0)*200
  1690. cg_maxiter = 20*len(x0)
  1691. xtol = len(x0) * avextol
  1692. update = [2 * xtol]
  1693. xk = x0
  1694. if retall:
  1695. allvecs = [xk]
  1696. k = 0
  1697. gfk = None
  1698. old_fval = f(x0)
  1699. old_old_fval = None
  1700. float64eps = np.finfo(np.float64).eps
  1701. while np.add.reduce(np.abs(update)) > xtol:
  1702. if k >= maxiter:
  1703. msg = "Warning: " + _status_message['maxiter']
  1704. return terminate(1, msg)
  1705. # Compute a search direction pk by applying the CG method to
  1706. # del2 f(xk) p = - grad f(xk) starting from 0.
  1707. b = -fprime(xk)
  1708. maggrad = np.add.reduce(np.abs(b))
  1709. eta = np.min([0.5, np.sqrt(maggrad)])
  1710. termcond = eta * maggrad
  1711. xsupi = zeros(len(x0), dtype=x0.dtype)
  1712. ri = -b
  1713. psupi = -ri
  1714. i = 0
  1715. dri0 = np.dot(ri, ri)
  1716. if fhess is not None: # you want to compute hessian once.
  1717. A = sf.hess(xk)
  1718. hcalls = hcalls + 1
  1719. for k2 in range(cg_maxiter):
  1720. if np.add.reduce(np.abs(ri)) <= termcond:
  1721. break
  1722. if fhess is None:
  1723. if fhess_p is None:
  1724. Ap = approx_fhess_p(xk, psupi, fprime, epsilon)
  1725. else:
  1726. Ap = fhess_p(xk, psupi, *args)
  1727. hcalls = hcalls + 1
  1728. else:
  1729. if isinstance(A, HessianUpdateStrategy):
  1730. # if hess was supplied as a HessianUpdateStrategy
  1731. Ap = A.dot(psupi)
  1732. else:
  1733. Ap = np.dot(A, psupi)
  1734. # check curvature
  1735. Ap = asarray(Ap).squeeze() # get rid of matrices...
  1736. curv = np.dot(psupi, Ap)
  1737. if 0 <= curv <= 3 * float64eps:
  1738. break
  1739. elif curv < 0:
  1740. if (i > 0):
  1741. break
  1742. else:
  1743. # fall back to steepest descent direction
  1744. xsupi = dri0 / (-curv) * b
  1745. break
  1746. alphai = dri0 / curv
  1747. xsupi = xsupi + alphai * psupi
  1748. ri = ri + alphai * Ap
  1749. dri1 = np.dot(ri, ri)
  1750. betai = dri1 / dri0
  1751. psupi = -ri + betai * psupi
  1752. i = i + 1
  1753. dri0 = dri1 # update np.dot(ri,ri) for next time.
  1754. else:
  1755. # curvature keeps increasing, bail out
  1756. msg = ("Warning: CG iterations didn't converge. The Hessian is not "
  1757. "positive definite.")
  1758. return terminate(3, msg)
  1759. pk = xsupi # search direction is solution to system.
  1760. gfk = -b # gradient at xk
  1761. try:
  1762. alphak, fc, gc, old_fval, old_old_fval, gfkp1 = \
  1763. _line_search_wolfe12(f, fprime, xk, pk, gfk,
  1764. old_fval, old_old_fval)
  1765. except _LineSearchError:
  1766. # Line search failed to find a better solution.
  1767. msg = "Warning: " + _status_message['pr_loss']
  1768. return terminate(2, msg)
  1769. update = alphak * pk
  1770. xk = xk + update # upcast if necessary
  1771. if callback is not None:
  1772. callback(xk)
  1773. if retall:
  1774. allvecs.append(xk)
  1775. k += 1
  1776. else:
  1777. if np.isnan(old_fval) or np.isnan(update).any():
  1778. return terminate(3, _status_message['nan'])
  1779. msg = _status_message['success']
  1780. return terminate(0, msg)
  1781. def fminbound(func, x1, x2, args=(), xtol=1e-5, maxfun=500,
  1782. full_output=0, disp=1):
  1783. """Bounded minimization for scalar functions.
  1784. Parameters
  1785. ----------
  1786. func : callable f(x,*args)
  1787. Objective function to be minimized (must accept and return scalars).
  1788. x1, x2 : float or array scalar
  1789. Finite optimization bounds.
  1790. args : tuple, optional
  1791. Extra arguments passed to function.
  1792. xtol : float, optional
  1793. The convergence tolerance.
  1794. maxfun : int, optional
  1795. Maximum number of function evaluations allowed.
  1796. full_output : bool, optional
  1797. If True, return optional outputs.
  1798. disp : int, optional
  1799. If non-zero, print messages.
  1800. 0 : no message printing.
  1801. 1 : non-convergence notification messages only.
  1802. 2 : print a message on convergence too.
  1803. 3 : print iteration results.
  1804. Returns
  1805. -------
  1806. xopt : ndarray
  1807. Parameters (over given interval) which minimize the
  1808. objective function.
  1809. fval : number
  1810. The function value evaluated at the minimizer.
  1811. ierr : int
  1812. An error flag (0 if converged, 1 if maximum number of
  1813. function calls reached).
  1814. numfunc : int
  1815. The number of function calls made.
  1816. See also
  1817. --------
  1818. minimize_scalar: Interface to minimization algorithms for scalar
  1819. univariate functions. See the 'Bounded' `method` in particular.
  1820. Notes
  1821. -----
  1822. Finds a local minimizer of the scalar function `func` in the
  1823. interval x1 < xopt < x2 using Brent's method. (See `brent`
  1824. for auto-bracketing.)
  1825. References
  1826. ----------
  1827. .. [1] Forsythe, G.E., M. A. Malcolm, and C. B. Moler. "Computer Methods
  1828. for Mathematical Computations." Prentice-Hall Series in Automatic
  1829. Computation 259 (1977).
  1830. .. [2] Brent, Richard P. Algorithms for Minimization Without Derivatives.
  1831. Courier Corporation, 2013.
  1832. Examples
  1833. --------
  1834. `fminbound` finds the minimizer of the function in the given range.
  1835. The following examples illustrate this.
  1836. >>> from scipy import optimize
  1837. >>> def f(x):
  1838. ... return (x-1)**2
  1839. >>> minimizer = optimize.fminbound(f, -4, 4)
  1840. >>> minimizer
  1841. 1.0
  1842. >>> minimum = f(minimizer)
  1843. >>> minimum
  1844. 0.0
  1845. >>> minimizer = optimize.fminbound(f, 3, 4)
  1846. >>> minimizer
  1847. 3.000005960860986
  1848. >>> minimum = f(minimizer)
  1849. >>> minimum
  1850. 4.000023843479476
  1851. """
  1852. options = {'xatol': xtol,
  1853. 'maxiter': maxfun,
  1854. 'disp': disp}
  1855. res = _minimize_scalar_bounded(func, (x1, x2), args, **options)
  1856. if full_output:
  1857. return res['x'], res['fun'], res['status'], res['nfev']
  1858. else:
  1859. return res['x']
  1860. def _minimize_scalar_bounded(func, bounds, args=(),
  1861. xatol=1e-5, maxiter=500, disp=0,
  1862. **unknown_options):
  1863. """
  1864. Options
  1865. -------
  1866. maxiter : int
  1867. Maximum number of iterations to perform.
  1868. disp: int, optional
  1869. If non-zero, print messages.
  1870. 0 : no message printing.
  1871. 1 : non-convergence notification messages only.
  1872. 2 : print a message on convergence too.
  1873. 3 : print iteration results.
  1874. xatol : float
  1875. Absolute error in solution `xopt` acceptable for convergence.
  1876. """
  1877. _check_unknown_options(unknown_options)
  1878. maxfun = maxiter
  1879. # Test bounds are of correct form
  1880. if len(bounds) != 2:
  1881. raise ValueError('bounds must have two elements.')
  1882. x1, x2 = bounds
  1883. if not (is_finite_scalar(x1) and is_finite_scalar(x2)):
  1884. raise ValueError("Optimization bounds must be finite scalars.")
  1885. if x1 > x2:
  1886. raise ValueError("The lower bound exceeds the upper bound.")
  1887. flag = 0
  1888. header = ' Func-count x f(x) Procedure'
  1889. step = ' initial'
  1890. sqrt_eps = sqrt(2.2e-16)
  1891. golden_mean = 0.5 * (3.0 - sqrt(5.0))
  1892. a, b = x1, x2
  1893. fulc = a + golden_mean * (b - a)
  1894. nfc, xf = fulc, fulc
  1895. rat = e = 0.0
  1896. x = xf
  1897. fx = func(x, *args)
  1898. num = 1
  1899. fmin_data = (1, xf, fx)
  1900. fu = np.inf
  1901. ffulc = fnfc = fx
  1902. xm = 0.5 * (a + b)
  1903. tol1 = sqrt_eps * np.abs(xf) + xatol / 3.0
  1904. tol2 = 2.0 * tol1
  1905. if disp > 2:
  1906. print(" ")
  1907. print(header)
  1908. print("%5.0f %12.6g %12.6g %s" % (fmin_data + (step,)))
  1909. while (np.abs(xf - xm) > (tol2 - 0.5 * (b - a))):
  1910. golden = 1
  1911. # Check for parabolic fit
  1912. if np.abs(e) > tol1:
  1913. golden = 0
  1914. r = (xf - nfc) * (fx - ffulc)
  1915. q = (xf - fulc) * (fx - fnfc)
  1916. p = (xf - fulc) * q - (xf - nfc) * r
  1917. q = 2.0 * (q - r)
  1918. if q > 0.0:
  1919. p = -p
  1920. q = np.abs(q)
  1921. r = e
  1922. e = rat
  1923. # Check for acceptability of parabola
  1924. if ((np.abs(p) < np.abs(0.5*q*r)) and (p > q*(a - xf)) and
  1925. (p < q * (b - xf))):
  1926. rat = (p + 0.0) / q
  1927. x = xf + rat
  1928. step = ' parabolic'
  1929. if ((x - a) < tol2) or ((b - x) < tol2):
  1930. si = np.sign(xm - xf) + ((xm - xf) == 0)
  1931. rat = tol1 * si
  1932. else: # do a golden-section step
  1933. golden = 1
  1934. if golden: # do a golden-section step
  1935. if xf >= xm:
  1936. e = a - xf
  1937. else:
  1938. e = b - xf
  1939. rat = golden_mean*e
  1940. step = ' golden'
  1941. si = np.sign(rat) + (rat == 0)
  1942. x = xf + si * np.maximum(np.abs(rat), tol1)
  1943. fu = func(x, *args)
  1944. num += 1
  1945. fmin_data = (num, x, fu)
  1946. if disp > 2:
  1947. print("%5.0f %12.6g %12.6g %s" % (fmin_data + (step,)))
  1948. if fu <= fx:
  1949. if x >= xf:
  1950. a = xf
  1951. else:
  1952. b = xf
  1953. fulc, ffulc = nfc, fnfc
  1954. nfc, fnfc = xf, fx
  1955. xf, fx = x, fu
  1956. else:
  1957. if x < xf:
  1958. a = x
  1959. else:
  1960. b = x
  1961. if (fu <= fnfc) or (nfc == xf):
  1962. fulc, ffulc = nfc, fnfc
  1963. nfc, fnfc = x, fu
  1964. elif (fu <= ffulc) or (fulc == xf) or (fulc == nfc):
  1965. fulc, ffulc = x, fu
  1966. xm = 0.5 * (a + b)
  1967. tol1 = sqrt_eps * np.abs(xf) + xatol / 3.0
  1968. tol2 = 2.0 * tol1
  1969. if num >= maxfun:
  1970. flag = 1
  1971. break
  1972. if np.isnan(xf) or np.isnan(fx) or np.isnan(fu):
  1973. flag = 2
  1974. fval = fx
  1975. if disp > 0:
  1976. _endprint(x, flag, fval, maxfun, xatol, disp)
  1977. result = OptimizeResult(fun=fval, status=flag, success=(flag == 0),
  1978. message={0: 'Solution found.',
  1979. 1: 'Maximum number of function calls '
  1980. 'reached.',
  1981. 2: _status_message['nan']}.get(flag, ''),
  1982. x=xf, nfev=num, nit=num)
  1983. return result
  1984. class Brent:
  1985. #need to rethink design of __init__
  1986. def __init__(self, func, args=(), tol=1.48e-8, maxiter=500,
  1987. full_output=0, disp=0):
  1988. self.func = func
  1989. self.args = args
  1990. self.tol = tol
  1991. self.maxiter = maxiter
  1992. self._mintol = 1.0e-11
  1993. self._cg = 0.3819660
  1994. self.xmin = None
  1995. self.fval = None
  1996. self.iter = 0
  1997. self.funcalls = 0
  1998. self.disp = disp
  1999. # need to rethink design of set_bracket (new options, etc.)
  2000. def set_bracket(self, brack=None):
  2001. self.brack = brack
  2002. def get_bracket_info(self):
  2003. #set up
  2004. func = self.func
  2005. args = self.args
  2006. brack = self.brack
  2007. ### BEGIN core bracket_info code ###
  2008. ### carefully DOCUMENT any CHANGES in core ##
  2009. if brack is None:
  2010. xa, xb, xc, fa, fb, fc, funcalls = bracket(func, args=args)
  2011. elif len(brack) == 2:
  2012. xa, xb, xc, fa, fb, fc, funcalls = bracket(func, xa=brack[0],
  2013. xb=brack[1], args=args)
  2014. elif len(brack) == 3:
  2015. xa, xb, xc = brack
  2016. if (xa > xc): # swap so xa < xc can be assumed
  2017. xc, xa = xa, xc
  2018. if not ((xa < xb) and (xb < xc)):
  2019. raise ValueError(
  2020. "Bracketing values (xa, xb, xc) do not"
  2021. " fulfill this requirement: (xa < xb) and (xb < xc)"
  2022. )
  2023. fa = func(*((xa,) + args))
  2024. fb = func(*((xb,) + args))
  2025. fc = func(*((xc,) + args))
  2026. if not ((fb < fa) and (fb < fc)):
  2027. raise ValueError(
  2028. "Bracketing values (xa, xb, xc) do not fulfill"
  2029. " this requirement: (f(xb) < f(xa)) and (f(xb) < f(xc))"
  2030. )
  2031. funcalls = 3
  2032. else:
  2033. raise ValueError("Bracketing interval must be "
  2034. "length 2 or 3 sequence.")
  2035. ### END core bracket_info code ###
  2036. return xa, xb, xc, fa, fb, fc, funcalls
  2037. def optimize(self):
  2038. # set up for optimization
  2039. func = self.func
  2040. xa, xb, xc, fa, fb, fc, funcalls = self.get_bracket_info()
  2041. _mintol = self._mintol
  2042. _cg = self._cg
  2043. #################################
  2044. #BEGIN CORE ALGORITHM
  2045. #################################
  2046. x = w = v = xb
  2047. fw = fv = fx = fb
  2048. if (xa < xc):
  2049. a = xa
  2050. b = xc
  2051. else:
  2052. a = xc
  2053. b = xa
  2054. deltax = 0.0
  2055. iter = 0
  2056. if self.disp > 2:
  2057. print(" ")
  2058. print(f"{'Func-count':^12} {'x':^12} {'f(x)': ^12}")
  2059. print(f"{funcalls:^12g} {x:^12.6g} {fx:^12.6g}")
  2060. while (iter < self.maxiter):
  2061. tol1 = self.tol * np.abs(x) + _mintol
  2062. tol2 = 2.0 * tol1
  2063. xmid = 0.5 * (a + b)
  2064. # check for convergence
  2065. if np.abs(x - xmid) < (tol2 - 0.5 * (b - a)):
  2066. break
  2067. # XXX In the first iteration, rat is only bound in the true case
  2068. # of this conditional. This used to cause an UnboundLocalError
  2069. # (gh-4140). It should be set before the if (but to what?).
  2070. if (np.abs(deltax) <= tol1):
  2071. if (x >= xmid):
  2072. deltax = a - x # do a golden section step
  2073. else:
  2074. deltax = b - x
  2075. rat = _cg * deltax
  2076. else: # do a parabolic step
  2077. tmp1 = (x - w) * (fx - fv)
  2078. tmp2 = (x - v) * (fx - fw)
  2079. p = (x - v) * tmp2 - (x - w) * tmp1
  2080. tmp2 = 2.0 * (tmp2 - tmp1)
  2081. if (tmp2 > 0.0):
  2082. p = -p
  2083. tmp2 = np.abs(tmp2)
  2084. dx_temp = deltax
  2085. deltax = rat
  2086. # check parabolic fit
  2087. if ((p > tmp2 * (a - x)) and (p < tmp2 * (b - x)) and
  2088. (np.abs(p) < np.abs(0.5 * tmp2 * dx_temp))):
  2089. rat = p * 1.0 / tmp2 # if parabolic step is useful.
  2090. u = x + rat
  2091. if ((u - a) < tol2 or (b - u) < tol2):
  2092. if xmid - x >= 0:
  2093. rat = tol1
  2094. else:
  2095. rat = -tol1
  2096. else:
  2097. if (x >= xmid):
  2098. deltax = a - x # if it's not do a golden section step
  2099. else:
  2100. deltax = b - x
  2101. rat = _cg * deltax
  2102. if (np.abs(rat) < tol1): # update by at least tol1
  2103. if rat >= 0:
  2104. u = x + tol1
  2105. else:
  2106. u = x - tol1
  2107. else:
  2108. u = x + rat
  2109. fu = func(*((u,) + self.args)) # calculate new output value
  2110. funcalls += 1
  2111. if (fu > fx): # if it's bigger than current
  2112. if (u < x):
  2113. a = u
  2114. else:
  2115. b = u
  2116. if (fu <= fw) or (w == x):
  2117. v = w
  2118. w = u
  2119. fv = fw
  2120. fw = fu
  2121. elif (fu <= fv) or (v == x) or (v == w):
  2122. v = u
  2123. fv = fu
  2124. else:
  2125. if (u >= x):
  2126. a = x
  2127. else:
  2128. b = x
  2129. v = w
  2130. w = x
  2131. x = u
  2132. fv = fw
  2133. fw = fx
  2134. fx = fu
  2135. if self.disp > 2:
  2136. print(f"{funcalls:^12g} {x:^12.6g} {fx:^12.6g}")
  2137. iter += 1
  2138. #################################
  2139. #END CORE ALGORITHM
  2140. #################################
  2141. self.xmin = x
  2142. self.fval = fx
  2143. self.iter = iter
  2144. self.funcalls = funcalls
  2145. def get_result(self, full_output=False):
  2146. if full_output:
  2147. return self.xmin, self.fval, self.iter, self.funcalls
  2148. else:
  2149. return self.xmin
  2150. def brent(func, args=(), brack=None, tol=1.48e-8, full_output=0, maxiter=500):
  2151. """
  2152. Given a function of one variable and a possible bracket, return
  2153. the local minimum of the function isolated to a fractional precision
  2154. of tol.
  2155. Parameters
  2156. ----------
  2157. func : callable f(x,*args)
  2158. Objective function.
  2159. args : tuple, optional
  2160. Additional arguments (if present).
  2161. brack : tuple, optional
  2162. Either a triple (xa,xb,xc) where xa<xb<xc and func(xb) <
  2163. func(xa), func(xc) or a pair (xa,xb) which are used as a
  2164. starting interval for a downhill bracket search (see
  2165. `bracket`). Providing the pair (xa,xb) does not always mean
  2166. the obtained solution will satisfy xa<=x<=xb.
  2167. tol : float, optional
  2168. Relative error in solution `xopt` acceptable for convergence.
  2169. full_output : bool, optional
  2170. If True, return all output args (xmin, fval, iter,
  2171. funcalls).
  2172. maxiter : int, optional
  2173. Maximum number of iterations in solution.
  2174. Returns
  2175. -------
  2176. xmin : ndarray
  2177. Optimum point.
  2178. fval : float
  2179. Optimum value.
  2180. iter : int
  2181. Number of iterations.
  2182. funcalls : int
  2183. Number of objective function evaluations made.
  2184. See also
  2185. --------
  2186. minimize_scalar: Interface to minimization algorithms for scalar
  2187. univariate functions. See the 'Brent' `method` in particular.
  2188. Notes
  2189. -----
  2190. Uses inverse parabolic interpolation when possible to speed up
  2191. convergence of golden section method.
  2192. Does not ensure that the minimum lies in the range specified by
  2193. `brack`. See `fminbound`.
  2194. Examples
  2195. --------
  2196. We illustrate the behaviour of the function when `brack` is of
  2197. size 2 and 3 respectively. In the case where `brack` is of the
  2198. form (xa,xb), we can see for the given values, the output need
  2199. not necessarily lie in the range (xa,xb).
  2200. >>> def f(x):
  2201. ... return x**2
  2202. >>> from scipy import optimize
  2203. >>> minimum = optimize.brent(f,brack=(1,2))
  2204. >>> minimum
  2205. 0.0
  2206. >>> minimum = optimize.brent(f,brack=(-1,0.5,2))
  2207. >>> minimum
  2208. -2.7755575615628914e-17
  2209. """
  2210. options = {'xtol': tol,
  2211. 'maxiter': maxiter}
  2212. res = _minimize_scalar_brent(func, brack, args, **options)
  2213. if full_output:
  2214. return res['x'], res['fun'], res['nit'], res['nfev']
  2215. else:
  2216. return res['x']
  2217. def _minimize_scalar_brent(func, brack=None, args=(), xtol=1.48e-8,
  2218. maxiter=500, disp=0,
  2219. **unknown_options):
  2220. """
  2221. Options
  2222. -------
  2223. maxiter : int
  2224. Maximum number of iterations to perform.
  2225. xtol : float
  2226. Relative error in solution `xopt` acceptable for convergence.
  2227. disp: int, optional
  2228. If non-zero, print messages.
  2229. 0 : no message printing.
  2230. 1 : non-convergence notification messages only.
  2231. 2 : print a message on convergence too.
  2232. 3 : print iteration results.
  2233. Notes
  2234. -----
  2235. Uses inverse parabolic interpolation when possible to speed up
  2236. convergence of golden section method.
  2237. """
  2238. _check_unknown_options(unknown_options)
  2239. tol = xtol
  2240. if tol < 0:
  2241. raise ValueError('tolerance should be >= 0, got %r' % tol)
  2242. brent = Brent(func=func, args=args, tol=tol,
  2243. full_output=True, maxiter=maxiter, disp=disp)
  2244. brent.set_bracket(brack)
  2245. brent.optimize()
  2246. x, fval, nit, nfev = brent.get_result(full_output=True)
  2247. success = nit < maxiter and not (np.isnan(x) or np.isnan(fval))
  2248. if success:
  2249. message = ("\nOptimization terminated successfully;\n"
  2250. "The returned value satisfies the termination criteria\n"
  2251. f"(using xtol = {xtol} )")
  2252. else:
  2253. if nit >= maxiter:
  2254. message = "\nMaximum number of iterations exceeded"
  2255. if np.isnan(x) or np.isnan(fval):
  2256. message = f"{_status_message['nan']}"
  2257. if disp:
  2258. print(message)
  2259. return OptimizeResult(fun=fval, x=x, nit=nit, nfev=nfev,
  2260. success=success, message=message)
  2261. def golden(func, args=(), brack=None, tol=_epsilon,
  2262. full_output=0, maxiter=5000):
  2263. """
  2264. Return the minimum of a function of one variable using golden section
  2265. method.
  2266. Given a function of one variable and a possible bracketing interval,
  2267. return the minimum of the function isolated to a fractional precision of
  2268. tol.
  2269. Parameters
  2270. ----------
  2271. func : callable func(x,*args)
  2272. Objective function to minimize.
  2273. args : tuple, optional
  2274. Additional arguments (if present), passed to func.
  2275. brack : tuple, optional
  2276. Triple (a,b,c), where (a<b<c) and func(b) <
  2277. func(a),func(c). If bracket consists of two numbers (a,
  2278. c), then they are assumed to be a starting interval for a
  2279. downhill bracket search (see `bracket`); it doesn't always
  2280. mean that obtained solution will satisfy a<=x<=c.
  2281. tol : float, optional
  2282. x tolerance stop criterion
  2283. full_output : bool, optional
  2284. If True, return optional outputs.
  2285. maxiter : int
  2286. Maximum number of iterations to perform.
  2287. See also
  2288. --------
  2289. minimize_scalar: Interface to minimization algorithms for scalar
  2290. univariate functions. See the 'Golden' `method` in particular.
  2291. Notes
  2292. -----
  2293. Uses analog of bisection method to decrease the bracketed
  2294. interval.
  2295. Examples
  2296. --------
  2297. We illustrate the behaviour of the function when `brack` is of
  2298. size 2 and 3, respectively. In the case where `brack` is of the
  2299. form (xa,xb), we can see for the given values, the output need
  2300. not necessarily lie in the range ``(xa, xb)``.
  2301. >>> def f(x):
  2302. ... return x**2
  2303. >>> from scipy import optimize
  2304. >>> minimum = optimize.golden(f, brack=(1, 2))
  2305. >>> minimum
  2306. 1.5717277788484873e-162
  2307. >>> minimum = optimize.golden(f, brack=(-1, 0.5, 2))
  2308. >>> minimum
  2309. -1.5717277788484873e-162
  2310. """
  2311. options = {'xtol': tol, 'maxiter': maxiter}
  2312. res = _minimize_scalar_golden(func, brack, args, **options)
  2313. if full_output:
  2314. return res['x'], res['fun'], res['nfev']
  2315. else:
  2316. return res['x']
  2317. def _minimize_scalar_golden(func, brack=None, args=(),
  2318. xtol=_epsilon, maxiter=5000, disp=0,
  2319. **unknown_options):
  2320. """
  2321. Options
  2322. -------
  2323. xtol : float
  2324. Relative error in solution `xopt` acceptable for convergence.
  2325. maxiter : int
  2326. Maximum number of iterations to perform.
  2327. disp: int, optional
  2328. If non-zero, print messages.
  2329. 0 : no message printing.
  2330. 1 : non-convergence notification messages only.
  2331. 2 : print a message on convergence too.
  2332. 3 : print iteration results.
  2333. """
  2334. _check_unknown_options(unknown_options)
  2335. tol = xtol
  2336. if brack is None:
  2337. xa, xb, xc, fa, fb, fc, funcalls = bracket(func, args=args)
  2338. elif len(brack) == 2:
  2339. xa, xb, xc, fa, fb, fc, funcalls = bracket(func, xa=brack[0],
  2340. xb=brack[1], args=args)
  2341. elif len(brack) == 3:
  2342. xa, xb, xc = brack
  2343. if (xa > xc): # swap so xa < xc can be assumed
  2344. xc, xa = xa, xc
  2345. if not ((xa < xb) and (xb < xc)):
  2346. raise ValueError(
  2347. "Bracketing values (xa, xb, xc) do not"
  2348. " fulfill this requirement: (xa < xb) and (xb < xc)"
  2349. )
  2350. fa = func(*((xa,) + args))
  2351. fb = func(*((xb,) + args))
  2352. fc = func(*((xc,) + args))
  2353. if not ((fb < fa) and (fb < fc)):
  2354. raise ValueError(
  2355. "Bracketing values (xa, xb, xc) do not fulfill"
  2356. " this requirement: (f(xb) < f(xa)) and (f(xb) < f(xc))"
  2357. )
  2358. funcalls = 3
  2359. else:
  2360. raise ValueError("Bracketing interval must be length 2 or 3 sequence.")
  2361. _gR = 0.61803399 # golden ratio conjugate: 2.0/(1.0+sqrt(5.0))
  2362. _gC = 1.0 - _gR
  2363. x3 = xc
  2364. x0 = xa
  2365. if (np.abs(xc - xb) > np.abs(xb - xa)):
  2366. x1 = xb
  2367. x2 = xb + _gC * (xc - xb)
  2368. else:
  2369. x2 = xb
  2370. x1 = xb - _gC * (xb - xa)
  2371. f1 = func(*((x1,) + args))
  2372. f2 = func(*((x2,) + args))
  2373. funcalls += 2
  2374. nit = 0
  2375. if disp > 2:
  2376. print(" ")
  2377. print(f"{'Func-count':^12} {'x':^12} {'f(x)': ^12}")
  2378. for i in range(maxiter):
  2379. if np.abs(x3 - x0) <= tol * (np.abs(x1) + np.abs(x2)):
  2380. break
  2381. if (f2 < f1):
  2382. x0 = x1
  2383. x1 = x2
  2384. x2 = _gR * x1 + _gC * x3
  2385. f1 = f2
  2386. f2 = func(*((x2,) + args))
  2387. else:
  2388. x3 = x2
  2389. x2 = x1
  2390. x1 = _gR * x2 + _gC * x0
  2391. f2 = f1
  2392. f1 = func(*((x1,) + args))
  2393. funcalls += 1
  2394. if disp > 2:
  2395. if (f1 < f2):
  2396. xmin, fval = x1, f1
  2397. else:
  2398. xmin, fval = x2, f2
  2399. print(f"{funcalls:^12g} {xmin:^12.6g} {fval:^12.6g}")
  2400. nit += 1
  2401. # end of iteration loop
  2402. if (f1 < f2):
  2403. xmin = x1
  2404. fval = f1
  2405. else:
  2406. xmin = x2
  2407. fval = f2
  2408. success = nit < maxiter and not (np.isnan(fval) or np.isnan(xmin))
  2409. if success:
  2410. message = ("\nOptimization terminated successfully;\n"
  2411. "The returned value satisfies the termination criteria\n"
  2412. f"(using xtol = {xtol} )")
  2413. else:
  2414. if nit >= maxiter:
  2415. message = "\nMaximum number of iterations exceeded"
  2416. if np.isnan(xmin) or np.isnan(fval):
  2417. message = f"{_status_message['nan']}"
  2418. if disp:
  2419. print(message)
  2420. return OptimizeResult(fun=fval, nfev=funcalls, x=xmin, nit=nit,
  2421. success=success, message=message)
  2422. def bracket(func, xa=0.0, xb=1.0, args=(), grow_limit=110.0, maxiter=1000):
  2423. """
  2424. Bracket the minimum of the function.
  2425. Given a function and distinct initial points, search in the
  2426. downhill direction (as defined by the initial points) and return
  2427. new points xa, xb, xc that bracket the minimum of the function
  2428. f(xa) > f(xb) < f(xc). It doesn't always mean that obtained
  2429. solution will satisfy xa<=x<=xb.
  2430. Parameters
  2431. ----------
  2432. func : callable f(x,*args)
  2433. Objective function to minimize.
  2434. xa, xb : float, optional
  2435. Bracketing interval. Defaults `xa` to 0.0, and `xb` to 1.0.
  2436. args : tuple, optional
  2437. Additional arguments (if present), passed to `func`.
  2438. grow_limit : float, optional
  2439. Maximum grow limit. Defaults to 110.0
  2440. maxiter : int, optional
  2441. Maximum number of iterations to perform. Defaults to 1000.
  2442. Returns
  2443. -------
  2444. xa, xb, xc : float
  2445. Bracket.
  2446. fa, fb, fc : float
  2447. Objective function values in bracket.
  2448. funcalls : int
  2449. Number of function evaluations made.
  2450. Examples
  2451. --------
  2452. This function can find a downward convex region of a function:
  2453. >>> import numpy as np
  2454. >>> import matplotlib.pyplot as plt
  2455. >>> from scipy.optimize import bracket
  2456. >>> def f(x):
  2457. ... return 10*x**2 + 3*x + 5
  2458. >>> x = np.linspace(-2, 2)
  2459. >>> y = f(x)
  2460. >>> init_xa, init_xb = 0, 1
  2461. >>> xa, xb, xc, fa, fb, fc, funcalls = bracket(f, xa=init_xa, xb=init_xb)
  2462. >>> plt.axvline(x=init_xa, color="k", linestyle="--")
  2463. >>> plt.axvline(x=init_xb, color="k", linestyle="--")
  2464. >>> plt.plot(x, y, "-k")
  2465. >>> plt.plot(xa, fa, "bx")
  2466. >>> plt.plot(xb, fb, "rx")
  2467. >>> plt.plot(xc, fc, "bx")
  2468. >>> plt.show()
  2469. """
  2470. _gold = 1.618034 # golden ratio: (1.0+sqrt(5.0))/2.0
  2471. _verysmall_num = 1e-21
  2472. fa = func(*(xa,) + args)
  2473. fb = func(*(xb,) + args)
  2474. if (fa < fb): # Switch so fa > fb
  2475. xa, xb = xb, xa
  2476. fa, fb = fb, fa
  2477. xc = xb + _gold * (xb - xa)
  2478. fc = func(*((xc,) + args))
  2479. funcalls = 3
  2480. iter = 0
  2481. while (fc < fb):
  2482. tmp1 = (xb - xa) * (fb - fc)
  2483. tmp2 = (xb - xc) * (fb - fa)
  2484. val = tmp2 - tmp1
  2485. if np.abs(val) < _verysmall_num:
  2486. denom = 2.0 * _verysmall_num
  2487. else:
  2488. denom = 2.0 * val
  2489. w = xb - ((xb - xc) * tmp2 - (xb - xa) * tmp1) / denom
  2490. wlim = xb + grow_limit * (xc - xb)
  2491. if iter > maxiter:
  2492. raise RuntimeError("Too many iterations.")
  2493. iter += 1
  2494. if (w - xc) * (xb - w) > 0.0:
  2495. fw = func(*((w,) + args))
  2496. funcalls += 1
  2497. if (fw < fc):
  2498. xa = xb
  2499. xb = w
  2500. fa = fb
  2501. fb = fw
  2502. return xa, xb, xc, fa, fb, fc, funcalls
  2503. elif (fw > fb):
  2504. xc = w
  2505. fc = fw
  2506. return xa, xb, xc, fa, fb, fc, funcalls
  2507. w = xc + _gold * (xc - xb)
  2508. fw = func(*((w,) + args))
  2509. funcalls += 1
  2510. elif (w - wlim)*(wlim - xc) >= 0.0:
  2511. w = wlim
  2512. fw = func(*((w,) + args))
  2513. funcalls += 1
  2514. elif (w - wlim)*(xc - w) > 0.0:
  2515. fw = func(*((w,) + args))
  2516. funcalls += 1
  2517. if (fw < fc):
  2518. xb = xc
  2519. xc = w
  2520. w = xc + _gold * (xc - xb)
  2521. fb = fc
  2522. fc = fw
  2523. fw = func(*((w,) + args))
  2524. funcalls += 1
  2525. else:
  2526. w = xc + _gold * (xc - xb)
  2527. fw = func(*((w,) + args))
  2528. funcalls += 1
  2529. xa = xb
  2530. xb = xc
  2531. xc = w
  2532. fa = fb
  2533. fb = fc
  2534. fc = fw
  2535. return xa, xb, xc, fa, fb, fc, funcalls
  2536. def _line_for_search(x0, alpha, lower_bound, upper_bound):
  2537. """
  2538. Given a parameter vector ``x0`` with length ``n`` and a direction
  2539. vector ``alpha`` with length ``n``, and lower and upper bounds on
  2540. each of the ``n`` parameters, what are the bounds on a scalar
  2541. ``l`` such that ``lower_bound <= x0 + alpha * l <= upper_bound``.
  2542. Parameters
  2543. ----------
  2544. x0 : np.array.
  2545. The vector representing the current location.
  2546. Note ``np.shape(x0) == (n,)``.
  2547. alpha : np.array.
  2548. The vector representing the direction.
  2549. Note ``np.shape(alpha) == (n,)``.
  2550. lower_bound : np.array.
  2551. The lower bounds for each parameter in ``x0``. If the ``i``th
  2552. parameter in ``x0`` is unbounded below, then ``lower_bound[i]``
  2553. should be ``-np.inf``.
  2554. Note ``np.shape(lower_bound) == (n,)``.
  2555. upper_bound : np.array.
  2556. The upper bounds for each parameter in ``x0``. If the ``i``th
  2557. parameter in ``x0`` is unbounded above, then ``upper_bound[i]``
  2558. should be ``np.inf``.
  2559. Note ``np.shape(upper_bound) == (n,)``.
  2560. Returns
  2561. -------
  2562. res : tuple ``(lmin, lmax)``
  2563. The bounds for ``l`` such that
  2564. ``lower_bound[i] <= x0[i] + alpha[i] * l <= upper_bound[i]``
  2565. for all ``i``.
  2566. """
  2567. # get nonzero indices of alpha so we don't get any zero division errors.
  2568. # alpha will not be all zero, since it is called from _linesearch_powell
  2569. # where we have a check for this.
  2570. nonzero, = alpha.nonzero()
  2571. lower_bound, upper_bound = lower_bound[nonzero], upper_bound[nonzero]
  2572. x0, alpha = x0[nonzero], alpha[nonzero]
  2573. low = (lower_bound - x0) / alpha
  2574. high = (upper_bound - x0) / alpha
  2575. # positive and negative indices
  2576. pos = alpha > 0
  2577. lmin_pos = np.where(pos, low, 0)
  2578. lmin_neg = np.where(pos, 0, high)
  2579. lmax_pos = np.where(pos, high, 0)
  2580. lmax_neg = np.where(pos, 0, low)
  2581. lmin = np.max(lmin_pos + lmin_neg)
  2582. lmax = np.min(lmax_pos + lmax_neg)
  2583. # if x0 is outside the bounds, then it is possible that there is
  2584. # no way to get back in the bounds for the parameters being updated
  2585. # with the current direction alpha.
  2586. # when this happens, lmax < lmin.
  2587. # If this is the case, then we can just return (0, 0)
  2588. return (lmin, lmax) if lmax >= lmin else (0, 0)
  2589. def _linesearch_powell(func, p, xi, tol=1e-3,
  2590. lower_bound=None, upper_bound=None, fval=None):
  2591. """Line-search algorithm using fminbound.
  2592. Find the minimium of the function ``func(x0 + alpha*direc)``.
  2593. lower_bound : np.array.
  2594. The lower bounds for each parameter in ``x0``. If the ``i``th
  2595. parameter in ``x0`` is unbounded below, then ``lower_bound[i]``
  2596. should be ``-np.inf``.
  2597. Note ``np.shape(lower_bound) == (n,)``.
  2598. upper_bound : np.array.
  2599. The upper bounds for each parameter in ``x0``. If the ``i``th
  2600. parameter in ``x0`` is unbounded above, then ``upper_bound[i]``
  2601. should be ``np.inf``.
  2602. Note ``np.shape(upper_bound) == (n,)``.
  2603. fval : number.
  2604. ``fval`` is equal to ``func(p)``, the idea is just to avoid
  2605. recomputing it so we can limit the ``fevals``.
  2606. """
  2607. def myfunc(alpha):
  2608. return func(p + alpha*xi)
  2609. # if xi is zero, then don't optimize
  2610. if not np.any(xi):
  2611. return ((fval, p, xi) if fval is not None else (func(p), p, xi))
  2612. elif lower_bound is None and upper_bound is None:
  2613. # non-bounded minimization
  2614. alpha_min, fret, _, _ = brent(myfunc, full_output=1, tol=tol)
  2615. xi = alpha_min * xi
  2616. return squeeze(fret), p + xi, xi
  2617. else:
  2618. bound = _line_for_search(p, xi, lower_bound, upper_bound)
  2619. if np.isneginf(bound[0]) and np.isposinf(bound[1]):
  2620. # equivalent to unbounded
  2621. return _linesearch_powell(func, p, xi, fval=fval, tol=tol)
  2622. elif not np.isneginf(bound[0]) and not np.isposinf(bound[1]):
  2623. # we can use a bounded scalar minimization
  2624. res = _minimize_scalar_bounded(myfunc, bound, xatol=tol / 100)
  2625. xi = res.x * xi
  2626. return squeeze(res.fun), p + xi, xi
  2627. else:
  2628. # only bounded on one side. use the tangent function to convert
  2629. # the infinity bound to a finite bound. The new bounded region
  2630. # is a subregion of the region bounded by -np.pi/2 and np.pi/2.
  2631. bound = np.arctan(bound[0]), np.arctan(bound[1])
  2632. res = _minimize_scalar_bounded(
  2633. lambda x: myfunc(np.tan(x)),
  2634. bound,
  2635. xatol=tol / 100)
  2636. xi = np.tan(res.x) * xi
  2637. return squeeze(res.fun), p + xi, xi
  2638. def fmin_powell(func, x0, args=(), xtol=1e-4, ftol=1e-4, maxiter=None,
  2639. maxfun=None, full_output=0, disp=1, retall=0, callback=None,
  2640. direc=None):
  2641. """
  2642. Minimize a function using modified Powell's method.
  2643. This method only uses function values, not derivatives.
  2644. Parameters
  2645. ----------
  2646. func : callable f(x,*args)
  2647. Objective function to be minimized.
  2648. x0 : ndarray
  2649. Initial guess.
  2650. args : tuple, optional
  2651. Extra arguments passed to func.
  2652. xtol : float, optional
  2653. Line-search error tolerance.
  2654. ftol : float, optional
  2655. Relative error in ``func(xopt)`` acceptable for convergence.
  2656. maxiter : int, optional
  2657. Maximum number of iterations to perform.
  2658. maxfun : int, optional
  2659. Maximum number of function evaluations to make.
  2660. full_output : bool, optional
  2661. If True, ``fopt``, ``xi``, ``direc``, ``iter``, ``funcalls``, and
  2662. ``warnflag`` are returned.
  2663. disp : bool, optional
  2664. If True, print convergence messages.
  2665. retall : bool, optional
  2666. If True, return a list of the solution at each iteration.
  2667. callback : callable, optional
  2668. An optional user-supplied function, called after each
  2669. iteration. Called as ``callback(xk)``, where ``xk`` is the
  2670. current parameter vector.
  2671. direc : ndarray, optional
  2672. Initial fitting step and parameter order set as an (N, N) array, where N
  2673. is the number of fitting parameters in `x0`. Defaults to step size 1.0
  2674. fitting all parameters simultaneously (``np.eye((N, N))``). To
  2675. prevent initial consideration of values in a step or to change initial
  2676. step size, set to 0 or desired step size in the Jth position in the Mth
  2677. block, where J is the position in `x0` and M is the desired evaluation
  2678. step, with steps being evaluated in index order. Step size and ordering
  2679. will change freely as minimization proceeds.
  2680. Returns
  2681. -------
  2682. xopt : ndarray
  2683. Parameter which minimizes `func`.
  2684. fopt : number
  2685. Value of function at minimum: ``fopt = func(xopt)``.
  2686. direc : ndarray
  2687. Current direction set.
  2688. iter : int
  2689. Number of iterations.
  2690. funcalls : int
  2691. Number of function calls made.
  2692. warnflag : int
  2693. Integer warning flag:
  2694. 1 : Maximum number of function evaluations.
  2695. 2 : Maximum number of iterations.
  2696. 3 : NaN result encountered.
  2697. 4 : The result is out of the provided bounds.
  2698. allvecs : list
  2699. List of solutions at each iteration.
  2700. See also
  2701. --------
  2702. minimize: Interface to unconstrained minimization algorithms for
  2703. multivariate functions. See the 'Powell' method in particular.
  2704. Notes
  2705. -----
  2706. Uses a modification of Powell's method to find the minimum of
  2707. a function of N variables. Powell's method is a conjugate
  2708. direction method.
  2709. The algorithm has two loops. The outer loop merely iterates over the inner
  2710. loop. The inner loop minimizes over each current direction in the direction
  2711. set. At the end of the inner loop, if certain conditions are met, the
  2712. direction that gave the largest decrease is dropped and replaced with the
  2713. difference between the current estimated x and the estimated x from the
  2714. beginning of the inner-loop.
  2715. The technical conditions for replacing the direction of greatest
  2716. increase amount to checking that
  2717. 1. No further gain can be made along the direction of greatest increase
  2718. from that iteration.
  2719. 2. The direction of greatest increase accounted for a large sufficient
  2720. fraction of the decrease in the function value from that iteration of
  2721. the inner loop.
  2722. References
  2723. ----------
  2724. Powell M.J.D. (1964) An efficient method for finding the minimum of a
  2725. function of several variables without calculating derivatives,
  2726. Computer Journal, 7 (2):155-162.
  2727. Press W., Teukolsky S.A., Vetterling W.T., and Flannery B.P.:
  2728. Numerical Recipes (any edition), Cambridge University Press
  2729. Examples
  2730. --------
  2731. >>> def f(x):
  2732. ... return x**2
  2733. >>> from scipy import optimize
  2734. >>> minimum = optimize.fmin_powell(f, -1)
  2735. Optimization terminated successfully.
  2736. Current function value: 0.000000
  2737. Iterations: 2
  2738. Function evaluations: 16
  2739. >>> minimum
  2740. array(0.0)
  2741. """
  2742. opts = {'xtol': xtol,
  2743. 'ftol': ftol,
  2744. 'maxiter': maxiter,
  2745. 'maxfev': maxfun,
  2746. 'disp': disp,
  2747. 'direc': direc,
  2748. 'return_all': retall}
  2749. res = _minimize_powell(func, x0, args, callback=callback, **opts)
  2750. if full_output:
  2751. retlist = (res['x'], res['fun'], res['direc'], res['nit'],
  2752. res['nfev'], res['status'])
  2753. if retall:
  2754. retlist += (res['allvecs'], )
  2755. return retlist
  2756. else:
  2757. if retall:
  2758. return res['x'], res['allvecs']
  2759. else:
  2760. return res['x']
  2761. def _minimize_powell(func, x0, args=(), callback=None, bounds=None,
  2762. xtol=1e-4, ftol=1e-4, maxiter=None, maxfev=None,
  2763. disp=False, direc=None, return_all=False,
  2764. **unknown_options):
  2765. """
  2766. Minimization of scalar function of one or more variables using the
  2767. modified Powell algorithm.
  2768. Parameters
  2769. ----------
  2770. fun : callable
  2771. The objective function to be minimized.
  2772. ``fun(x, *args) -> float``
  2773. where ``x`` is a 1-D array with shape (n,) and ``args``
  2774. is a tuple of the fixed parameters needed to completely
  2775. specify the function.
  2776. x0 : ndarray, shape (n,)
  2777. Initial guess. Array of real elements of size (n,),
  2778. where ``n`` is the number of independent variables.
  2779. args : tuple, optional
  2780. Extra arguments passed to the objective function and its
  2781. derivatives (`fun`, `jac` and `hess` functions).
  2782. method : str or callable, optional
  2783. The present documentation is specific to ``method='powell'``, but other
  2784. options are available. See documentation for `scipy.optimize.minimize`.
  2785. bounds : sequence or `Bounds`, optional
  2786. Bounds on decision variables. There are two ways to specify the bounds:
  2787. 1. Instance of `Bounds` class.
  2788. 2. Sequence of ``(min, max)`` pairs for each element in `x`. None
  2789. is used to specify no bound.
  2790. If bounds are not provided, then an unbounded line search will be used.
  2791. If bounds are provided and the initial guess is within the bounds, then
  2792. every function evaluation throughout the minimization procedure will be
  2793. within the bounds. If bounds are provided, the initial guess is outside
  2794. the bounds, and `direc` is full rank (or left to default), then some
  2795. function evaluations during the first iteration may be outside the
  2796. bounds, but every function evaluation after the first iteration will be
  2797. within the bounds. If `direc` is not full rank, then some parameters
  2798. may not be optimized and the solution is not guaranteed to be within
  2799. the bounds.
  2800. options : dict, optional
  2801. A dictionary of solver options. All methods accept the following
  2802. generic options:
  2803. maxiter : int
  2804. Maximum number of iterations to perform. Depending on the
  2805. method each iteration may use several function evaluations.
  2806. disp : bool
  2807. Set to True to print convergence messages.
  2808. See method-specific options for ``method='powell'`` below.
  2809. callback : callable, optional
  2810. Called after each iteration. The signature is:
  2811. ``callback(xk)``
  2812. where ``xk`` is the current parameter vector.
  2813. Returns
  2814. -------
  2815. res : OptimizeResult
  2816. The optimization result represented as a ``OptimizeResult`` object.
  2817. Important attributes are: ``x`` the solution array, ``success`` a
  2818. Boolean flag indicating if the optimizer exited successfully and
  2819. ``message`` which describes the cause of the termination. See
  2820. `OptimizeResult` for a description of other attributes.
  2821. Options
  2822. -------
  2823. disp : bool
  2824. Set to True to print convergence messages.
  2825. xtol : float
  2826. Relative error in solution `xopt` acceptable for convergence.
  2827. ftol : float
  2828. Relative error in ``fun(xopt)`` acceptable for convergence.
  2829. maxiter, maxfev : int
  2830. Maximum allowed number of iterations and function evaluations.
  2831. Will default to ``N*1000``, where ``N`` is the number of
  2832. variables, if neither `maxiter` or `maxfev` is set. If both
  2833. `maxiter` and `maxfev` are set, minimization will stop at the
  2834. first reached.
  2835. direc : ndarray
  2836. Initial set of direction vectors for the Powell method.
  2837. return_all : bool, optional
  2838. Set to True to return a list of the best solution at each of the
  2839. iterations.
  2840. """
  2841. _check_unknown_options(unknown_options)
  2842. maxfun = maxfev
  2843. retall = return_all
  2844. x = asarray(x0).flatten()
  2845. if retall:
  2846. allvecs = [x]
  2847. N = len(x)
  2848. # If neither are set, then set both to default
  2849. if maxiter is None and maxfun is None:
  2850. maxiter = N * 1000
  2851. maxfun = N * 1000
  2852. elif maxiter is None:
  2853. # Convert remaining Nones, to np.inf, unless the other is np.inf, in
  2854. # which case use the default to avoid unbounded iteration
  2855. if maxfun == np.inf:
  2856. maxiter = N * 1000
  2857. else:
  2858. maxiter = np.inf
  2859. elif maxfun is None:
  2860. if maxiter == np.inf:
  2861. maxfun = N * 1000
  2862. else:
  2863. maxfun = np.inf
  2864. # we need to use a mutable object here that we can update in the
  2865. # wrapper function
  2866. fcalls, func = _wrap_scalar_function_maxfun_validation(func, args, maxfun)
  2867. if direc is None:
  2868. direc = eye(N, dtype=float)
  2869. else:
  2870. direc = asarray(direc, dtype=float)
  2871. if np.linalg.matrix_rank(direc) != direc.shape[0]:
  2872. warnings.warn("direc input is not full rank, some parameters may "
  2873. "not be optimized",
  2874. OptimizeWarning, 3)
  2875. if bounds is None:
  2876. # don't make these arrays of all +/- inf. because
  2877. # _linesearch_powell will do an unnecessary check of all the elements.
  2878. # just keep them None, _linesearch_powell will not have to check
  2879. # all the elements.
  2880. lower_bound, upper_bound = None, None
  2881. else:
  2882. # bounds is standardized in _minimize.py.
  2883. lower_bound, upper_bound = bounds.lb, bounds.ub
  2884. if np.any(lower_bound > x0) or np.any(x0 > upper_bound):
  2885. warnings.warn("Initial guess is not within the specified bounds",
  2886. OptimizeWarning, 3)
  2887. fval = squeeze(func(x))
  2888. x1 = x.copy()
  2889. iter = 0
  2890. while True:
  2891. try:
  2892. fx = fval
  2893. bigind = 0
  2894. delta = 0.0
  2895. for i in range(N):
  2896. direc1 = direc[i]
  2897. fx2 = fval
  2898. fval, x, direc1 = _linesearch_powell(func, x, direc1,
  2899. tol=xtol * 100,
  2900. lower_bound=lower_bound,
  2901. upper_bound=upper_bound,
  2902. fval=fval)
  2903. if (fx2 - fval) > delta:
  2904. delta = fx2 - fval
  2905. bigind = i
  2906. iter += 1
  2907. if callback is not None:
  2908. callback(x)
  2909. if retall:
  2910. allvecs.append(x)
  2911. bnd = ftol * (np.abs(fx) + np.abs(fval)) + 1e-20
  2912. if 2.0 * (fx - fval) <= bnd:
  2913. break
  2914. if fcalls[0] >= maxfun:
  2915. break
  2916. if iter >= maxiter:
  2917. break
  2918. if np.isnan(fx) and np.isnan(fval):
  2919. # Ended up in a nan-region: bail out
  2920. break
  2921. # Construct the extrapolated point
  2922. direc1 = x - x1
  2923. x1 = x.copy()
  2924. # make sure that we don't go outside the bounds when extrapolating
  2925. if lower_bound is None and upper_bound is None:
  2926. lmax = 1
  2927. else:
  2928. _, lmax = _line_for_search(x, direc1, lower_bound, upper_bound)
  2929. x2 = x + min(lmax, 1) * direc1
  2930. fx2 = squeeze(func(x2))
  2931. if (fx > fx2):
  2932. t = 2.0*(fx + fx2 - 2.0*fval)
  2933. temp = (fx - fval - delta)
  2934. t *= temp*temp
  2935. temp = fx - fx2
  2936. t -= delta*temp*temp
  2937. if t < 0.0:
  2938. fval, x, direc1 = _linesearch_powell(
  2939. func, x, direc1,
  2940. tol=xtol * 100,
  2941. lower_bound=lower_bound,
  2942. upper_bound=upper_bound,
  2943. fval=fval
  2944. )
  2945. if np.any(direc1):
  2946. direc[bigind] = direc[-1]
  2947. direc[-1] = direc1
  2948. except _MaxFuncCallError:
  2949. break
  2950. warnflag = 0
  2951. # out of bounds is more urgent than exceeding function evals or iters,
  2952. # but I don't want to cause inconsistencies by changing the
  2953. # established warning flags for maxfev and maxiter, so the out of bounds
  2954. # warning flag becomes 3, but is checked for first.
  2955. if bounds and (np.any(lower_bound > x) or np.any(x > upper_bound)):
  2956. warnflag = 4
  2957. msg = _status_message['out_of_bounds']
  2958. elif fcalls[0] >= maxfun:
  2959. warnflag = 1
  2960. msg = _status_message['maxfev']
  2961. if disp:
  2962. warnings.warn(msg, RuntimeWarning, 3)
  2963. elif iter >= maxiter:
  2964. warnflag = 2
  2965. msg = _status_message['maxiter']
  2966. if disp:
  2967. warnings.warn(msg, RuntimeWarning, 3)
  2968. elif np.isnan(fval) or np.isnan(x).any():
  2969. warnflag = 3
  2970. msg = _status_message['nan']
  2971. if disp:
  2972. warnings.warn(msg, RuntimeWarning, 3)
  2973. else:
  2974. msg = _status_message['success']
  2975. if disp:
  2976. print(msg)
  2977. print(" Current function value: %f" % fval)
  2978. print(" Iterations: %d" % iter)
  2979. print(" Function evaluations: %d" % fcalls[0])
  2980. result = OptimizeResult(fun=fval, direc=direc, nit=iter, nfev=fcalls[0],
  2981. status=warnflag, success=(warnflag == 0),
  2982. message=msg, x=x)
  2983. if retall:
  2984. result['allvecs'] = allvecs
  2985. return result
  2986. def _endprint(x, flag, fval, maxfun, xtol, disp):
  2987. if flag == 0:
  2988. if disp > 1:
  2989. print("\nOptimization terminated successfully;\n"
  2990. "The returned value satisfies the termination criteria\n"
  2991. "(using xtol = ", xtol, ")")
  2992. if flag == 1:
  2993. if disp:
  2994. print("\nMaximum number of function evaluations exceeded --- "
  2995. "increase maxfun argument.\n")
  2996. if flag == 2:
  2997. if disp:
  2998. print("\n{}".format(_status_message['nan']))
  2999. return
  3000. def brute(func, ranges, args=(), Ns=20, full_output=0, finish=fmin,
  3001. disp=False, workers=1):
  3002. """Minimize a function over a given range by brute force.
  3003. Uses the "brute force" method, i.e., computes the function's value
  3004. at each point of a multidimensional grid of points, to find the global
  3005. minimum of the function.
  3006. The function is evaluated everywhere in the range with the datatype of the
  3007. first call to the function, as enforced by the ``vectorize`` NumPy
  3008. function. The value and type of the function evaluation returned when
  3009. ``full_output=True`` are affected in addition by the ``finish`` argument
  3010. (see Notes).
  3011. The brute force approach is inefficient because the number of grid points
  3012. increases exponentially - the number of grid points to evaluate is
  3013. ``Ns ** len(x)``. Consequently, even with coarse grid spacing, even
  3014. moderately sized problems can take a long time to run, and/or run into
  3015. memory limitations.
  3016. Parameters
  3017. ----------
  3018. func : callable
  3019. The objective function to be minimized. Must be in the
  3020. form ``f(x, *args)``, where ``x`` is the argument in
  3021. the form of a 1-D array and ``args`` is a tuple of any
  3022. additional fixed parameters needed to completely specify
  3023. the function.
  3024. ranges : tuple
  3025. Each component of the `ranges` tuple must be either a
  3026. "slice object" or a range tuple of the form ``(low, high)``.
  3027. The program uses these to create the grid of points on which
  3028. the objective function will be computed. See `Note 2` for
  3029. more detail.
  3030. args : tuple, optional
  3031. Any additional fixed parameters needed to completely specify
  3032. the function.
  3033. Ns : int, optional
  3034. Number of grid points along the axes, if not otherwise
  3035. specified. See `Note2`.
  3036. full_output : bool, optional
  3037. If True, return the evaluation grid and the objective function's
  3038. values on it.
  3039. finish : callable, optional
  3040. An optimization function that is called with the result of brute force
  3041. minimization as initial guess. `finish` should take `func` and
  3042. the initial guess as positional arguments, and take `args` as
  3043. keyword arguments. It may additionally take `full_output`
  3044. and/or `disp` as keyword arguments. Use None if no "polishing"
  3045. function is to be used. See Notes for more details.
  3046. disp : bool, optional
  3047. Set to True to print convergence messages from the `finish` callable.
  3048. workers : int or map-like callable, optional
  3049. If `workers` is an int the grid is subdivided into `workers`
  3050. sections and evaluated in parallel (uses
  3051. `multiprocessing.Pool <multiprocessing>`).
  3052. Supply `-1` to use all cores available to the Process.
  3053. Alternatively supply a map-like callable, such as
  3054. `multiprocessing.Pool.map` for evaluating the grid in parallel.
  3055. This evaluation is carried out as ``workers(func, iterable)``.
  3056. Requires that `func` be pickleable.
  3057. .. versionadded:: 1.3.0
  3058. Returns
  3059. -------
  3060. x0 : ndarray
  3061. A 1-D array containing the coordinates of a point at which the
  3062. objective function had its minimum value. (See `Note 1` for
  3063. which point is returned.)
  3064. fval : float
  3065. Function value at the point `x0`. (Returned when `full_output` is
  3066. True.)
  3067. grid : tuple
  3068. Representation of the evaluation grid. It has the same
  3069. length as `x0`. (Returned when `full_output` is True.)
  3070. Jout : ndarray
  3071. Function values at each point of the evaluation
  3072. grid, i.e., ``Jout = func(*grid)``. (Returned
  3073. when `full_output` is True.)
  3074. See Also
  3075. --------
  3076. basinhopping, differential_evolution
  3077. Notes
  3078. -----
  3079. *Note 1*: The program finds the gridpoint at which the lowest value
  3080. of the objective function occurs. If `finish` is None, that is the
  3081. point returned. When the global minimum occurs within (or not very far
  3082. outside) the grid's boundaries, and the grid is fine enough, that
  3083. point will be in the neighborhood of the global minimum.
  3084. However, users often employ some other optimization program to
  3085. "polish" the gridpoint values, i.e., to seek a more precise
  3086. (local) minimum near `brute's` best gridpoint.
  3087. The `brute` function's `finish` option provides a convenient way to do
  3088. that. Any polishing program used must take `brute's` output as its
  3089. initial guess as a positional argument, and take `brute's` input values
  3090. for `args` as keyword arguments, otherwise an error will be raised.
  3091. It may additionally take `full_output` and/or `disp` as keyword arguments.
  3092. `brute` assumes that the `finish` function returns either an
  3093. `OptimizeResult` object or a tuple in the form:
  3094. ``(xmin, Jmin, ... , statuscode)``, where ``xmin`` is the minimizing
  3095. value of the argument, ``Jmin`` is the minimum value of the objective
  3096. function, "..." may be some other returned values (which are not used
  3097. by `brute`), and ``statuscode`` is the status code of the `finish` program.
  3098. Note that when `finish` is not None, the values returned are those
  3099. of the `finish` program, *not* the gridpoint ones. Consequently,
  3100. while `brute` confines its search to the input grid points,
  3101. the `finish` program's results usually will not coincide with any
  3102. gridpoint, and may fall outside the grid's boundary. Thus, if a
  3103. minimum only needs to be found over the provided grid points, make
  3104. sure to pass in `finish=None`.
  3105. *Note 2*: The grid of points is a `numpy.mgrid` object.
  3106. For `brute` the `ranges` and `Ns` inputs have the following effect.
  3107. Each component of the `ranges` tuple can be either a slice object or a
  3108. two-tuple giving a range of values, such as (0, 5). If the component is a
  3109. slice object, `brute` uses it directly. If the component is a two-tuple
  3110. range, `brute` internally converts it to a slice object that interpolates
  3111. `Ns` points from its low-value to its high-value, inclusive.
  3112. Examples
  3113. --------
  3114. We illustrate the use of `brute` to seek the global minimum of a function
  3115. of two variables that is given as the sum of a positive-definite
  3116. quadratic and two deep "Gaussian-shaped" craters. Specifically, define
  3117. the objective function `f` as the sum of three other functions,
  3118. ``f = f1 + f2 + f3``. We suppose each of these has a signature
  3119. ``(z, *params)``, where ``z = (x, y)``, and ``params`` and the functions
  3120. are as defined below.
  3121. >>> import numpy as np
  3122. >>> params = (2, 3, 7, 8, 9, 10, 44, -1, 2, 26, 1, -2, 0.5)
  3123. >>> def f1(z, *params):
  3124. ... x, y = z
  3125. ... a, b, c, d, e, f, g, h, i, j, k, l, scale = params
  3126. ... return (a * x**2 + b * x * y + c * y**2 + d*x + e*y + f)
  3127. >>> def f2(z, *params):
  3128. ... x, y = z
  3129. ... a, b, c, d, e, f, g, h, i, j, k, l, scale = params
  3130. ... return (-g*np.exp(-((x-h)**2 + (y-i)**2) / scale))
  3131. >>> def f3(z, *params):
  3132. ... x, y = z
  3133. ... a, b, c, d, e, f, g, h, i, j, k, l, scale = params
  3134. ... return (-j*np.exp(-((x-k)**2 + (y-l)**2) / scale))
  3135. >>> def f(z, *params):
  3136. ... return f1(z, *params) + f2(z, *params) + f3(z, *params)
  3137. Thus, the objective function may have local minima near the minimum
  3138. of each of the three functions of which it is composed. To
  3139. use `fmin` to polish its gridpoint result, we may then continue as
  3140. follows:
  3141. >>> rranges = (slice(-4, 4, 0.25), slice(-4, 4, 0.25))
  3142. >>> from scipy import optimize
  3143. >>> resbrute = optimize.brute(f, rranges, args=params, full_output=True,
  3144. ... finish=optimize.fmin)
  3145. >>> resbrute[0] # global minimum
  3146. array([-1.05665192, 1.80834843])
  3147. >>> resbrute[1] # function value at global minimum
  3148. -3.4085818767
  3149. Note that if `finish` had been set to None, we would have gotten the
  3150. gridpoint [-1.0 1.75] where the rounded function value is -2.892.
  3151. """
  3152. N = len(ranges)
  3153. if N > 40:
  3154. raise ValueError("Brute Force not possible with more "
  3155. "than 40 variables.")
  3156. lrange = list(ranges)
  3157. for k in range(N):
  3158. if type(lrange[k]) is not type(slice(None)):
  3159. if len(lrange[k]) < 3:
  3160. lrange[k] = tuple(lrange[k]) + (complex(Ns),)
  3161. lrange[k] = slice(*lrange[k])
  3162. if (N == 1):
  3163. lrange = lrange[0]
  3164. grid = np.mgrid[lrange]
  3165. # obtain an array of parameters that is iterable by a map-like callable
  3166. inpt_shape = grid.shape
  3167. if (N > 1):
  3168. grid = np.reshape(grid, (inpt_shape[0], np.prod(inpt_shape[1:]))).T
  3169. if not np.iterable(args):
  3170. args = (args,)
  3171. wrapped_func = _Brute_Wrapper(func, args)
  3172. # iterate over input arrays, possibly in parallel
  3173. with MapWrapper(pool=workers) as mapper:
  3174. Jout = np.array(list(mapper(wrapped_func, grid)))
  3175. if (N == 1):
  3176. grid = (grid,)
  3177. Jout = np.squeeze(Jout)
  3178. elif (N > 1):
  3179. Jout = np.reshape(Jout, inpt_shape[1:])
  3180. grid = np.reshape(grid.T, inpt_shape)
  3181. Nshape = shape(Jout)
  3182. indx = argmin(Jout.ravel(), axis=-1)
  3183. Nindx = np.empty(N, int)
  3184. xmin = np.empty(N, float)
  3185. for k in range(N - 1, -1, -1):
  3186. thisN = Nshape[k]
  3187. Nindx[k] = indx % Nshape[k]
  3188. indx = indx // thisN
  3189. for k in range(N):
  3190. xmin[k] = grid[k][tuple(Nindx)]
  3191. Jmin = Jout[tuple(Nindx)]
  3192. if (N == 1):
  3193. grid = grid[0]
  3194. xmin = xmin[0]
  3195. if callable(finish):
  3196. # set up kwargs for `finish` function
  3197. finish_args = _getfullargspec(finish).args
  3198. finish_kwargs = dict()
  3199. if 'full_output' in finish_args:
  3200. finish_kwargs['full_output'] = 1
  3201. if 'disp' in finish_args:
  3202. finish_kwargs['disp'] = disp
  3203. elif 'options' in finish_args:
  3204. # pass 'disp' as `options`
  3205. # (e.g., if `finish` is `minimize`)
  3206. finish_kwargs['options'] = {'disp': disp}
  3207. # run minimizer
  3208. res = finish(func, xmin, args=args, **finish_kwargs)
  3209. if isinstance(res, OptimizeResult):
  3210. xmin = res.x
  3211. Jmin = res.fun
  3212. success = res.success
  3213. else:
  3214. xmin = res[0]
  3215. Jmin = res[1]
  3216. success = res[-1] == 0
  3217. if not success:
  3218. if disp:
  3219. warnings.warn(
  3220. "Either final optimization did not succeed "
  3221. "or `finish` does not return `statuscode` as its last "
  3222. "argument.", RuntimeWarning, 2)
  3223. if full_output:
  3224. return xmin, Jmin, grid, Jout
  3225. else:
  3226. return xmin
  3227. class _Brute_Wrapper:
  3228. """
  3229. Object to wrap user cost function for optimize.brute, allowing picklability
  3230. """
  3231. def __init__(self, f, args):
  3232. self.f = f
  3233. self.args = [] if args is None else args
  3234. def __call__(self, x):
  3235. # flatten needed for one dimensional case.
  3236. return self.f(np.asarray(x).flatten(), *self.args)
  3237. def show_options(solver=None, method=None, disp=True):
  3238. """
  3239. Show documentation for additional options of optimization solvers.
  3240. These are method-specific options that can be supplied through the
  3241. ``options`` dict.
  3242. Parameters
  3243. ----------
  3244. solver : str
  3245. Type of optimization solver. One of 'minimize', 'minimize_scalar',
  3246. 'root', 'root_scalar', 'linprog', or 'quadratic_assignment'.
  3247. method : str, optional
  3248. If not given, shows all methods of the specified solver. Otherwise,
  3249. show only the options for the specified method. Valid values
  3250. corresponds to methods' names of respective solver (e.g., 'BFGS' for
  3251. 'minimize').
  3252. disp : bool, optional
  3253. Whether to print the result rather than returning it.
  3254. Returns
  3255. -------
  3256. text
  3257. Either None (for disp=True) or the text string (disp=False)
  3258. Notes
  3259. -----
  3260. The solver-specific methods are:
  3261. `scipy.optimize.minimize`
  3262. - :ref:`Nelder-Mead <optimize.minimize-neldermead>`
  3263. - :ref:`Powell <optimize.minimize-powell>`
  3264. - :ref:`CG <optimize.minimize-cg>`
  3265. - :ref:`BFGS <optimize.minimize-bfgs>`
  3266. - :ref:`Newton-CG <optimize.minimize-newtoncg>`
  3267. - :ref:`L-BFGS-B <optimize.minimize-lbfgsb>`
  3268. - :ref:`TNC <optimize.minimize-tnc>`
  3269. - :ref:`COBYLA <optimize.minimize-cobyla>`
  3270. - :ref:`SLSQP <optimize.minimize-slsqp>`
  3271. - :ref:`dogleg <optimize.minimize-dogleg>`
  3272. - :ref:`trust-ncg <optimize.minimize-trustncg>`
  3273. `scipy.optimize.root`
  3274. - :ref:`hybr <optimize.root-hybr>`
  3275. - :ref:`lm <optimize.root-lm>`
  3276. - :ref:`broyden1 <optimize.root-broyden1>`
  3277. - :ref:`broyden2 <optimize.root-broyden2>`
  3278. - :ref:`anderson <optimize.root-anderson>`
  3279. - :ref:`linearmixing <optimize.root-linearmixing>`
  3280. - :ref:`diagbroyden <optimize.root-diagbroyden>`
  3281. - :ref:`excitingmixing <optimize.root-excitingmixing>`
  3282. - :ref:`krylov <optimize.root-krylov>`
  3283. - :ref:`df-sane <optimize.root-dfsane>`
  3284. `scipy.optimize.minimize_scalar`
  3285. - :ref:`brent <optimize.minimize_scalar-brent>`
  3286. - :ref:`golden <optimize.minimize_scalar-golden>`
  3287. - :ref:`bounded <optimize.minimize_scalar-bounded>`
  3288. `scipy.optimize.root_scalar`
  3289. - :ref:`bisect <optimize.root_scalar-bisect>`
  3290. - :ref:`brentq <optimize.root_scalar-brentq>`
  3291. - :ref:`brenth <optimize.root_scalar-brenth>`
  3292. - :ref:`ridder <optimize.root_scalar-ridder>`
  3293. - :ref:`toms748 <optimize.root_scalar-toms748>`
  3294. - :ref:`newton <optimize.root_scalar-newton>`
  3295. - :ref:`secant <optimize.root_scalar-secant>`
  3296. - :ref:`halley <optimize.root_scalar-halley>`
  3297. `scipy.optimize.linprog`
  3298. - :ref:`simplex <optimize.linprog-simplex>`
  3299. - :ref:`interior-point <optimize.linprog-interior-point>`
  3300. - :ref:`revised simplex <optimize.linprog-revised_simplex>`
  3301. - :ref:`highs <optimize.linprog-highs>`
  3302. - :ref:`highs-ds <optimize.linprog-highs-ds>`
  3303. - :ref:`highs-ipm <optimize.linprog-highs-ipm>`
  3304. `scipy.optimize.quadratic_assignment`
  3305. - :ref:`faq <optimize.qap-faq>`
  3306. - :ref:`2opt <optimize.qap-2opt>`
  3307. Examples
  3308. --------
  3309. We can print documentations of a solver in stdout:
  3310. >>> from scipy.optimize import show_options
  3311. >>> show_options(solver="minimize")
  3312. ...
  3313. Specifying a method is possible:
  3314. >>> show_options(solver="minimize", method="Nelder-Mead")
  3315. ...
  3316. We can also get the documentations as a string:
  3317. >>> show_options(solver="minimize", method="Nelder-Mead", disp=False)
  3318. Minimization of scalar function of one or more variables using the ...
  3319. """
  3320. import textwrap
  3321. doc_routines = {
  3322. 'minimize': (
  3323. ('bfgs', 'scipy.optimize._optimize._minimize_bfgs'),
  3324. ('cg', 'scipy.optimize._optimize._minimize_cg'),
  3325. ('cobyla', 'scipy.optimize._cobyla_py._minimize_cobyla'),
  3326. ('dogleg', 'scipy.optimize._trustregion_dogleg._minimize_dogleg'),
  3327. ('l-bfgs-b', 'scipy.optimize._lbfgsb_py._minimize_lbfgsb'),
  3328. ('nelder-mead', 'scipy.optimize._optimize._minimize_neldermead'),
  3329. ('newton-cg', 'scipy.optimize._optimize._minimize_newtoncg'),
  3330. ('powell', 'scipy.optimize._optimize._minimize_powell'),
  3331. ('slsqp', 'scipy.optimize._slsqp_py._minimize_slsqp'),
  3332. ('tnc', 'scipy.optimize._tnc._minimize_tnc'),
  3333. ('trust-ncg',
  3334. 'scipy.optimize._trustregion_ncg._minimize_trust_ncg'),
  3335. ('trust-constr',
  3336. 'scipy.optimize._trustregion_constr.'
  3337. '_minimize_trustregion_constr'),
  3338. ('trust-exact',
  3339. 'scipy.optimize._trustregion_exact._minimize_trustregion_exact'),
  3340. ('trust-krylov',
  3341. 'scipy.optimize._trustregion_krylov._minimize_trust_krylov'),
  3342. ),
  3343. 'root': (
  3344. ('hybr', 'scipy.optimize._minpack_py._root_hybr'),
  3345. ('lm', 'scipy.optimize._root._root_leastsq'),
  3346. ('broyden1', 'scipy.optimize._root._root_broyden1_doc'),
  3347. ('broyden2', 'scipy.optimize._root._root_broyden2_doc'),
  3348. ('anderson', 'scipy.optimize._root._root_anderson_doc'),
  3349. ('diagbroyden', 'scipy.optimize._root._root_diagbroyden_doc'),
  3350. ('excitingmixing', 'scipy.optimize._root._root_excitingmixing_doc'),
  3351. ('linearmixing', 'scipy.optimize._root._root_linearmixing_doc'),
  3352. ('krylov', 'scipy.optimize._root._root_krylov_doc'),
  3353. ('df-sane', 'scipy.optimize._spectral._root_df_sane'),
  3354. ),
  3355. 'root_scalar': (
  3356. ('bisect', 'scipy.optimize._root_scalar._root_scalar_bisect_doc'),
  3357. ('brentq', 'scipy.optimize._root_scalar._root_scalar_brentq_doc'),
  3358. ('brenth', 'scipy.optimize._root_scalar._root_scalar_brenth_doc'),
  3359. ('ridder', 'scipy.optimize._root_scalar._root_scalar_ridder_doc'),
  3360. ('toms748', 'scipy.optimize._root_scalar._root_scalar_toms748_doc'),
  3361. ('secant', 'scipy.optimize._root_scalar._root_scalar_secant_doc'),
  3362. ('newton', 'scipy.optimize._root_scalar._root_scalar_newton_doc'),
  3363. ('halley', 'scipy.optimize._root_scalar._root_scalar_halley_doc'),
  3364. ),
  3365. 'linprog': (
  3366. ('simplex', 'scipy.optimize._linprog._linprog_simplex_doc'),
  3367. ('interior-point', 'scipy.optimize._linprog._linprog_ip_doc'),
  3368. ('revised simplex', 'scipy.optimize._linprog._linprog_rs_doc'),
  3369. ('highs-ipm', 'scipy.optimize._linprog._linprog_highs_ipm_doc'),
  3370. ('highs-ds', 'scipy.optimize._linprog._linprog_highs_ds_doc'),
  3371. ('highs', 'scipy.optimize._linprog._linprog_highs_doc'),
  3372. ),
  3373. 'quadratic_assignment': (
  3374. ('faq', 'scipy.optimize._qap._quadratic_assignment_faq'),
  3375. ('2opt', 'scipy.optimize._qap._quadratic_assignment_2opt'),
  3376. ),
  3377. 'minimize_scalar': (
  3378. ('brent', 'scipy.optimize._optimize._minimize_scalar_brent'),
  3379. ('bounded', 'scipy.optimize._optimize._minimize_scalar_bounded'),
  3380. ('golden', 'scipy.optimize._optimize._minimize_scalar_golden'),
  3381. ),
  3382. }
  3383. if solver is None:
  3384. text = ["\n\n\n========\n", "minimize\n", "========\n"]
  3385. text.append(show_options('minimize', disp=False))
  3386. text.extend(["\n\n===============\n", "minimize_scalar\n",
  3387. "===============\n"])
  3388. text.append(show_options('minimize_scalar', disp=False))
  3389. text.extend(["\n\n\n====\n", "root\n",
  3390. "====\n"])
  3391. text.append(show_options('root', disp=False))
  3392. text.extend(['\n\n\n=======\n', 'linprog\n',
  3393. '=======\n'])
  3394. text.append(show_options('linprog', disp=False))
  3395. text = "".join(text)
  3396. else:
  3397. solver = solver.lower()
  3398. if solver not in doc_routines:
  3399. raise ValueError('Unknown solver %r' % (solver,))
  3400. if method is None:
  3401. text = []
  3402. for name, _ in doc_routines[solver]:
  3403. text.extend(["\n\n" + name, "\n" + "="*len(name) + "\n\n"])
  3404. text.append(show_options(solver, name, disp=False))
  3405. text = "".join(text)
  3406. else:
  3407. method = method.lower()
  3408. methods = dict(doc_routines[solver])
  3409. if method not in methods:
  3410. raise ValueError("Unknown method %r" % (method,))
  3411. name = methods[method]
  3412. # Import function object
  3413. parts = name.split('.')
  3414. mod_name = ".".join(parts[:-1])
  3415. __import__(mod_name)
  3416. obj = getattr(sys.modules[mod_name], parts[-1])
  3417. # Get doc
  3418. doc = obj.__doc__
  3419. if doc is not None:
  3420. text = textwrap.dedent(doc).strip()
  3421. else:
  3422. text = ""
  3423. if disp:
  3424. print(text)
  3425. return
  3426. else:
  3427. return text