slsqp.py 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532
  1. """
  2. This module implements the Sequential Least SQuares Programming optimization
  3. algorithm (SLSQP), originally developed by Dieter Kraft.
  4. See http://www.netlib.org/toms/733
  5. Functions
  6. ---------
  7. .. autosummary::
  8. :toctree: generated/
  9. approx_jacobian
  10. fmin_slsqp
  11. """
  12. from __future__ import division, print_function, absolute_import
  13. __all__ = ['approx_jacobian', 'fmin_slsqp']
  14. import numpy as np
  15. from scipy.optimize._slsqp import slsqp
  16. from numpy import (zeros, array, linalg, append, asfarray, concatenate, finfo,
  17. sqrt, vstack, exp, inf, isfinite, atleast_1d)
  18. from .optimize import wrap_function, OptimizeResult, _check_unknown_options
  19. __docformat__ = "restructuredtext en"
  20. _epsilon = sqrt(finfo(float).eps)
  21. def approx_jacobian(x, func, epsilon, *args):
  22. """
  23. Approximate the Jacobian matrix of a callable function.
  24. Parameters
  25. ----------
  26. x : array_like
  27. The state vector at which to compute the Jacobian matrix.
  28. func : callable f(x,*args)
  29. The vector-valued function.
  30. epsilon : float
  31. The perturbation used to determine the partial derivatives.
  32. args : sequence
  33. Additional arguments passed to func.
  34. Returns
  35. -------
  36. An array of dimensions ``(lenf, lenx)`` where ``lenf`` is the length
  37. of the outputs of `func`, and ``lenx`` is the number of elements in
  38. `x`.
  39. Notes
  40. -----
  41. The approximation is done using forward differences.
  42. """
  43. x0 = asfarray(x)
  44. f0 = atleast_1d(func(*((x0,)+args)))
  45. jac = zeros([len(x0), len(f0)])
  46. dx = zeros(len(x0))
  47. for i in range(len(x0)):
  48. dx[i] = epsilon
  49. jac[i] = (func(*((x0+dx,)+args)) - f0)/epsilon
  50. dx[i] = 0.0
  51. return jac.transpose()
  52. def fmin_slsqp(func, x0, eqcons=(), f_eqcons=None, ieqcons=(), f_ieqcons=None,
  53. bounds=(), fprime=None, fprime_eqcons=None,
  54. fprime_ieqcons=None, args=(), iter=100, acc=1.0E-6,
  55. iprint=1, disp=None, full_output=0, epsilon=_epsilon,
  56. callback=None):
  57. """
  58. Minimize a function using Sequential Least SQuares Programming
  59. Python interface function for the SLSQP Optimization subroutine
  60. originally implemented by Dieter Kraft.
  61. Parameters
  62. ----------
  63. func : callable f(x,*args)
  64. Objective function. Must return a scalar.
  65. x0 : 1-D ndarray of float
  66. Initial guess for the independent variable(s).
  67. eqcons : list, optional
  68. A list of functions of length n such that
  69. eqcons[j](x,*args) == 0.0 in a successfully optimized
  70. problem.
  71. f_eqcons : callable f(x,*args), optional
  72. Returns a 1-D array in which each element must equal 0.0 in a
  73. successfully optimized problem. If f_eqcons is specified,
  74. eqcons is ignored.
  75. ieqcons : list, optional
  76. A list of functions of length n such that
  77. ieqcons[j](x,*args) >= 0.0 in a successfully optimized
  78. problem.
  79. f_ieqcons : callable f(x,*args), optional
  80. Returns a 1-D ndarray in which each element must be greater or
  81. equal to 0.0 in a successfully optimized problem. If
  82. f_ieqcons is specified, ieqcons is ignored.
  83. bounds : list, optional
  84. A list of tuples specifying the lower and upper bound
  85. for each independent variable [(xl0, xu0),(xl1, xu1),...]
  86. Infinite values will be interpreted as large floating values.
  87. fprime : callable `f(x,*args)`, optional
  88. A function that evaluates the partial derivatives of func.
  89. fprime_eqcons : callable `f(x,*args)`, optional
  90. A function of the form `f(x, *args)` that returns the m by n
  91. array of equality constraint normals. If not provided,
  92. the normals will be approximated. The array returned by
  93. fprime_eqcons should be sized as ( len(eqcons), len(x0) ).
  94. fprime_ieqcons : callable `f(x,*args)`, optional
  95. A function of the form `f(x, *args)` that returns the m by n
  96. array of inequality constraint normals. If not provided,
  97. the normals will be approximated. The array returned by
  98. fprime_ieqcons should be sized as ( len(ieqcons), len(x0) ).
  99. args : sequence, optional
  100. Additional arguments passed to func and fprime.
  101. iter : int, optional
  102. The maximum number of iterations.
  103. acc : float, optional
  104. Requested accuracy.
  105. iprint : int, optional
  106. The verbosity of fmin_slsqp :
  107. * iprint <= 0 : Silent operation
  108. * iprint == 1 : Print summary upon completion (default)
  109. * iprint >= 2 : Print status of each iterate and summary
  110. disp : int, optional
  111. Over-rides the iprint interface (preferred).
  112. full_output : bool, optional
  113. If False, return only the minimizer of func (default).
  114. Otherwise, output final objective function and summary
  115. information.
  116. epsilon : float, optional
  117. The step size for finite-difference derivative estimates.
  118. callback : callable, optional
  119. Called after each iteration, as ``callback(x)``, where ``x`` is the
  120. current parameter vector.
  121. Returns
  122. -------
  123. out : ndarray of float
  124. The final minimizer of func.
  125. fx : ndarray of float, if full_output is true
  126. The final value of the objective function.
  127. its : int, if full_output is true
  128. The number of iterations.
  129. imode : int, if full_output is true
  130. The exit mode from the optimizer (see below).
  131. smode : string, if full_output is true
  132. Message describing the exit mode from the optimizer.
  133. See also
  134. --------
  135. minimize: Interface to minimization algorithms for multivariate
  136. functions. See the 'SLSQP' `method` in particular.
  137. Notes
  138. -----
  139. Exit modes are defined as follows ::
  140. -1 : Gradient evaluation required (g & a)
  141. 0 : Optimization terminated successfully.
  142. 1 : Function evaluation required (f & c)
  143. 2 : More equality constraints than independent variables
  144. 3 : More than 3*n iterations in LSQ subproblem
  145. 4 : Inequality constraints incompatible
  146. 5 : Singular matrix E in LSQ subproblem
  147. 6 : Singular matrix C in LSQ subproblem
  148. 7 : Rank-deficient equality constraint subproblem HFTI
  149. 8 : Positive directional derivative for linesearch
  150. 9 : Iteration limit exceeded
  151. Examples
  152. --------
  153. Examples are given :ref:`in the tutorial <tutorial-sqlsp>`.
  154. """
  155. if disp is not None:
  156. iprint = disp
  157. opts = {'maxiter': iter,
  158. 'ftol': acc,
  159. 'iprint': iprint,
  160. 'disp': iprint != 0,
  161. 'eps': epsilon,
  162. 'callback': callback}
  163. # Build the constraints as a tuple of dictionaries
  164. cons = ()
  165. # 1. constraints of the 1st kind (eqcons, ieqcons); no Jacobian; take
  166. # the same extra arguments as the objective function.
  167. cons += tuple({'type': 'eq', 'fun': c, 'args': args} for c in eqcons)
  168. cons += tuple({'type': 'ineq', 'fun': c, 'args': args} for c in ieqcons)
  169. # 2. constraints of the 2nd kind (f_eqcons, f_ieqcons) and their Jacobian
  170. # (fprime_eqcons, fprime_ieqcons); also take the same extra arguments
  171. # as the objective function.
  172. if f_eqcons:
  173. cons += ({'type': 'eq', 'fun': f_eqcons, 'jac': fprime_eqcons,
  174. 'args': args}, )
  175. if f_ieqcons:
  176. cons += ({'type': 'ineq', 'fun': f_ieqcons, 'jac': fprime_ieqcons,
  177. 'args': args}, )
  178. res = _minimize_slsqp(func, x0, args, jac=fprime, bounds=bounds,
  179. constraints=cons, **opts)
  180. if full_output:
  181. return res['x'], res['fun'], res['nit'], res['status'], res['message']
  182. else:
  183. return res['x']
  184. def _minimize_slsqp(func, x0, args=(), jac=None, bounds=None,
  185. constraints=(),
  186. maxiter=100, ftol=1.0E-6, iprint=1, disp=False,
  187. eps=_epsilon, callback=None,
  188. **unknown_options):
  189. """
  190. Minimize a scalar function of one or more variables using Sequential
  191. Least SQuares Programming (SLSQP).
  192. Options
  193. -------
  194. ftol : float
  195. Precision goal for the value of f in the stopping criterion.
  196. eps : float
  197. Step size used for numerical approximation of the Jacobian.
  198. disp : bool
  199. Set to True to print convergence messages. If False,
  200. `verbosity` is ignored and set to 0.
  201. maxiter : int
  202. Maximum number of iterations.
  203. """
  204. _check_unknown_options(unknown_options)
  205. fprime = jac
  206. iter = maxiter
  207. acc = ftol
  208. epsilon = eps
  209. if not disp:
  210. iprint = 0
  211. # Constraints are triaged per type into a dictionary of tuples
  212. if isinstance(constraints, dict):
  213. constraints = (constraints, )
  214. cons = {'eq': (), 'ineq': ()}
  215. for ic, con in enumerate(constraints):
  216. # check type
  217. try:
  218. ctype = con['type'].lower()
  219. except KeyError:
  220. raise KeyError('Constraint %d has no type defined.' % ic)
  221. except TypeError:
  222. raise TypeError('Constraints must be defined using a '
  223. 'dictionary.')
  224. except AttributeError:
  225. raise TypeError("Constraint's type must be a string.")
  226. else:
  227. if ctype not in ['eq', 'ineq']:
  228. raise ValueError("Unknown constraint type '%s'." % con['type'])
  229. # check function
  230. if 'fun' not in con:
  231. raise ValueError('Constraint %d has no function defined.' % ic)
  232. # check Jacobian
  233. cjac = con.get('jac')
  234. if cjac is None:
  235. # approximate Jacobian function. The factory function is needed
  236. # to keep a reference to `fun`, see gh-4240.
  237. def cjac_factory(fun):
  238. def cjac(x, *args):
  239. return approx_jacobian(x, fun, epsilon, *args)
  240. return cjac
  241. cjac = cjac_factory(con['fun'])
  242. # update constraints' dictionary
  243. cons[ctype] += ({'fun': con['fun'],
  244. 'jac': cjac,
  245. 'args': con.get('args', ())}, )
  246. exit_modes = {-1: "Gradient evaluation required (g & a)",
  247. 0: "Optimization terminated successfully.",
  248. 1: "Function evaluation required (f & c)",
  249. 2: "More equality constraints than independent variables",
  250. 3: "More than 3*n iterations in LSQ subproblem",
  251. 4: "Inequality constraints incompatible",
  252. 5: "Singular matrix E in LSQ subproblem",
  253. 6: "Singular matrix C in LSQ subproblem",
  254. 7: "Rank-deficient equality constraint subproblem HFTI",
  255. 8: "Positive directional derivative for linesearch",
  256. 9: "Iteration limit exceeded"}
  257. # Wrap func
  258. feval, func = wrap_function(func, args)
  259. # Wrap fprime, if provided, or approx_jacobian if not
  260. if fprime:
  261. geval, fprime = wrap_function(fprime, args)
  262. else:
  263. geval, fprime = wrap_function(approx_jacobian, (func, epsilon))
  264. # Transform x0 into an array.
  265. x = asfarray(x0).flatten()
  266. # Set the parameters that SLSQP will need
  267. # meq, mieq: number of equality and inequality constraints
  268. meq = sum(map(len, [atleast_1d(c['fun'](x, *c['args']))
  269. for c in cons['eq']]))
  270. mieq = sum(map(len, [atleast_1d(c['fun'](x, *c['args']))
  271. for c in cons['ineq']]))
  272. # m = The total number of constraints
  273. m = meq + mieq
  274. # la = The number of constraints, or 1 if there are no constraints
  275. la = array([1, m]).max()
  276. # n = The number of independent variables
  277. n = len(x)
  278. # Define the workspaces for SLSQP
  279. n1 = n + 1
  280. mineq = m - meq + n1 + n1
  281. len_w = (3*n1+m)*(n1+1)+(n1-meq+1)*(mineq+2) + 2*mineq+(n1+mineq)*(n1-meq) \
  282. + 2*meq + n1 + ((n+1)*n)//2 + 2*m + 3*n + 3*n1 + 1
  283. len_jw = mineq
  284. w = zeros(len_w)
  285. jw = zeros(len_jw)
  286. # Decompose bounds into xl and xu
  287. if bounds is None or len(bounds) == 0:
  288. xl = np.empty(n, dtype=float)
  289. xu = np.empty(n, dtype=float)
  290. xl.fill(np.nan)
  291. xu.fill(np.nan)
  292. else:
  293. bnds = array(bounds, float)
  294. if bnds.shape[0] != n:
  295. raise IndexError('SLSQP Error: the length of bounds is not '
  296. 'compatible with that of x0.')
  297. with np.errstate(invalid='ignore'):
  298. bnderr = bnds[:, 0] > bnds[:, 1]
  299. if bnderr.any():
  300. raise ValueError('SLSQP Error: lb > ub in bounds %s.' %
  301. ', '.join(str(b) for b in bnderr))
  302. xl, xu = bnds[:, 0], bnds[:, 1]
  303. # Mark infinite bounds with nans; the Fortran code understands this
  304. infbnd = ~isfinite(bnds)
  305. xl[infbnd[:, 0]] = np.nan
  306. xu[infbnd[:, 1]] = np.nan
  307. # Clip initial guess to bounds (SLSQP may fail with bounds-infeasible
  308. # initial point)
  309. have_bound = np.isfinite(xl)
  310. x[have_bound] = np.clip(x[have_bound], xl[have_bound], np.inf)
  311. have_bound = np.isfinite(xu)
  312. x[have_bound] = np.clip(x[have_bound], -np.inf, xu[have_bound])
  313. # Initialize the iteration counter and the mode value
  314. mode = array(0, int)
  315. acc = array(acc, float)
  316. majiter = array(iter, int)
  317. majiter_prev = 0
  318. # Initialize internal SLSQP state variables
  319. alpha = array(0, float)
  320. f0 = array(0, float)
  321. gs = array(0, float)
  322. h1 = array(0, float)
  323. h2 = array(0, float)
  324. h3 = array(0, float)
  325. h4 = array(0, float)
  326. t = array(0, float)
  327. t0 = array(0, float)
  328. tol = array(0, float)
  329. iexact = array(0, int)
  330. incons = array(0, int)
  331. ireset = array(0, int)
  332. itermx = array(0, int)
  333. line = array(0, int)
  334. n1 = array(0, int)
  335. n2 = array(0, int)
  336. n3 = array(0, int)
  337. # Print the header if iprint >= 2
  338. if iprint >= 2:
  339. print("%5s %5s %16s %16s" % ("NIT", "FC", "OBJFUN", "GNORM"))
  340. while 1:
  341. if mode == 0 or mode == 1: # objective and constraint evaluation required
  342. # Compute objective function
  343. fx = func(x)
  344. try:
  345. fx = float(np.asarray(fx))
  346. except (TypeError, ValueError):
  347. raise ValueError("Objective function must return a scalar")
  348. # Compute the constraints
  349. if cons['eq']:
  350. c_eq = concatenate([atleast_1d(con['fun'](x, *con['args']))
  351. for con in cons['eq']])
  352. else:
  353. c_eq = zeros(0)
  354. if cons['ineq']:
  355. c_ieq = concatenate([atleast_1d(con['fun'](x, *con['args']))
  356. for con in cons['ineq']])
  357. else:
  358. c_ieq = zeros(0)
  359. # Now combine c_eq and c_ieq into a single matrix
  360. c = concatenate((c_eq, c_ieq))
  361. if mode == 0 or mode == -1: # gradient evaluation required
  362. # Compute the derivatives of the objective function
  363. # For some reason SLSQP wants g dimensioned to n+1
  364. g = append(fprime(x), 0.0)
  365. # Compute the normals of the constraints
  366. if cons['eq']:
  367. a_eq = vstack([con['jac'](x, *con['args'])
  368. for con in cons['eq']])
  369. else: # no equality constraint
  370. a_eq = zeros((meq, n))
  371. if cons['ineq']:
  372. a_ieq = vstack([con['jac'](x, *con['args'])
  373. for con in cons['ineq']])
  374. else: # no inequality constraint
  375. a_ieq = zeros((mieq, n))
  376. # Now combine a_eq and a_ieq into a single a matrix
  377. if m == 0: # no constraints
  378. a = zeros((la, n))
  379. else:
  380. a = vstack((a_eq, a_ieq))
  381. a = concatenate((a, zeros([la, 1])), 1)
  382. # Call SLSQP
  383. slsqp(m, meq, x, xl, xu, fx, c, g, a, acc, majiter, mode, w, jw,
  384. alpha, f0, gs, h1, h2, h3, h4, t, t0, tol,
  385. iexact, incons, ireset, itermx, line,
  386. n1, n2, n3)
  387. # call callback if major iteration has incremented
  388. if callback is not None and majiter > majiter_prev:
  389. callback(np.copy(x))
  390. # Print the status of the current iterate if iprint > 2 and the
  391. # major iteration has incremented
  392. if iprint >= 2 and majiter > majiter_prev:
  393. print("%5i %5i % 16.6E % 16.6E" % (majiter, feval[0],
  394. fx, linalg.norm(g)))
  395. # If exit mode is not -1 or 1, slsqp has completed
  396. if abs(mode) != 1:
  397. break
  398. majiter_prev = int(majiter)
  399. # Optimization loop complete. Print status if requested
  400. if iprint >= 1:
  401. print(exit_modes[int(mode)] + " (Exit mode " + str(mode) + ')')
  402. print(" Current function value:", fx)
  403. print(" Iterations:", majiter)
  404. print(" Function evaluations:", feval[0])
  405. print(" Gradient evaluations:", geval[0])
  406. return OptimizeResult(x=x, fun=fx, jac=g[:-1], nit=int(majiter),
  407. nfev=feval[0], njev=geval[0], status=int(mode),
  408. message=exit_modes[int(mode)], success=(mode == 0))
  409. if __name__ == '__main__':
  410. # objective function
  411. def fun(x, r=[4, 2, 4, 2, 1]):
  412. """ Objective function """
  413. return exp(x[0]) * (r[0] * x[0]**2 + r[1] * x[1]**2 +
  414. r[2] * x[0] * x[1] + r[3] * x[1] +
  415. r[4])
  416. # bounds
  417. bnds = array([[-inf]*2, [inf]*2]).T
  418. bnds[:, 0] = [0.1, 0.2]
  419. # constraints
  420. def feqcon(x, b=1):
  421. """ Equality constraint """
  422. return array([x[0]**2 + x[1] - b])
  423. def jeqcon(x, b=1):
  424. """ Jacobian of equality constraint """
  425. return array([[2*x[0], 1]])
  426. def fieqcon(x, c=10):
  427. """ Inequality constraint """
  428. return array([x[0] * x[1] + c])
  429. def jieqcon(x, c=10):
  430. """ Jacobian of Inequality constraint """
  431. return array([[1, 1]])
  432. # constraints dictionaries
  433. cons = ({'type': 'eq', 'fun': feqcon, 'jac': jeqcon, 'args': (1, )},
  434. {'type': 'ineq', 'fun': fieqcon, 'jac': jieqcon, 'args': (10,)})
  435. # Bounds constraint problem
  436. print(' Bounds constraints '.center(72, '-'))
  437. print(' * fmin_slsqp')
  438. x, f = fmin_slsqp(fun, array([-1, 1]), bounds=bnds, disp=1,
  439. full_output=True)[:2]
  440. print(' * _minimize_slsqp')
  441. res = _minimize_slsqp(fun, array([-1, 1]), bounds=bnds,
  442. **{'disp': True})
  443. # Equality and inequality constraints problem
  444. print(' Equality and inequality constraints '.center(72, '-'))
  445. print(' * fmin_slsqp')
  446. x, f = fmin_slsqp(fun, array([-1, 1]),
  447. f_eqcons=feqcon, fprime_eqcons=jeqcon,
  448. f_ieqcons=fieqcon, fprime_ieqcons=jieqcon,
  449. disp=1, full_output=True)[:2]
  450. print(' * _minimize_slsqp')
  451. res = _minimize_slsqp(fun, array([-1, 1]), constraints=cons,
  452. **{'disp': True})