time_indexed_solver.py
Go to the documentation of this file.
1 # -*- coding: utf-8 -*-
2 from __future__ import print_function, division
3 
4 from scipy.optimize import (
5  minimize,
6  Bounds,
7  # LinearConstraint,
8  NonlinearConstraint,
9  SR1,
10  # BFGS
11 )
12 import numpy as np
13 from time import time
14 
15 
16 class SciPyTimeIndexedSolver(object):
17  """
18  Uses SciPy to solve a constrained TimeIndexedProblem. Options for SciPy minimize
19  can be found here:
20  https://docs.scipy.org/doc/scipy/reference/generated/scipy.optimize.minimize.html
21  """
22 
23  def __init__(self, problem=None, method=None, debug=False):
24  print("Initialising SciPy Solver")
25  self.problem = problem
26  self.debug = debug
27  self.method = method
29  if self.method != "SLSQP":
30  self.hessian_update_strategy = SR1()
31  self.max_iterations = 500
32 
33  def specifyProblem(self, problem):
34  self.problem = problem
35 
36  def eq_constraint_fun(self, x):
37  self.problem.update(x)
38  # print("EQ", self.problem.get_equality().shape)
39  return self.problem.get_equality()
40 
41  def eq_constraint_jac(self, x):
42  self.problem.update(x)
43  # print("EQ-Jac", self.problem.get_equality_jacobian().shape)
44  if self.method == "SLSQP": # SLSQP does not support sparse Jacobians/Hessians
45  return self.problem.get_equality_jacobian().todense()
46  else:
47  return self.problem.get_equality_jacobian()
48 
49  def neq_constraint_fun(self, x):
50  self.problem.update(x)
51  # print("NEQ", self.problem.get_inequality().shape)
52  return -1.0 * self.problem.get_inequality()
53 
54  def neq_constraint_jac(self, x):
55  self.problem.update(x)
56  # print("NEQ-Jac", self.problem.get_inequality_jacobian().shape)
57  if self.method == "SLSQP": # SLSQP does not support sparse Jacobians/Hessians
58  return -1.0 * self.problem.get_inequality_jacobian().todense()
59  else:
60  return -1.0 * self.problem.get_inequality_jacobian()
61 
62  def cost_fun(self, x):
63  self.problem.update(x)
64  return self.problem.get_cost(), self.problem.get_cost_jacobian()
65 
66  def solve(self):
67  # Extract start state
68  x0 = np.asarray(self.problem.initial_trajectory)[1:, :].flatten()
69  x0 += np.random.normal(
70  0.0, 1.0e-3, x0.shape[0]
71  ) # for SLSQP we do require some initial noise to avoid singular matrices
72 
73  # Add constraints
74  cons = []
75  if self.method != "trust-constr":
76  if self.problem.inequality.length_Phi > 0:
77  cons.append(
78  {
79  "type": "ineq",
80  "fun": self.neq_constraint_fun,
81  "jac": self.neq_constraint_jac,
82  }
83  )
84 
85  if self.problem.equality.length_Phi:
86  cons.append(
87  {
88  "type": "eq",
89  "fun": self.eq_constraint_fun,
90  "jac": self.eq_constraint_jac,
91  }
92  )
93  else:
94  if self.problem.inequality.length_Phi > 0:
95  cons.append(
96  NonlinearConstraint(
97  self.neq_constraint_fun,
98  0.0,
99  np.inf,
100  jac=self.neq_constraint_jac,
101  hess=self.hessian_update_strategy,
102  )
103  )
104 
105  if self.problem.equality.length_Phi:
106  cons.append(
107  NonlinearConstraint(
108  self.eq_constraint_fun,
109  0.0,
110  0.0,
111  jac=self.eq_constraint_jac,
112  hess=self.hessian_update_strategy,
113  )
114  )
115 
116  # Bounds
117  bounds = None
118  if self.problem.use_bounds:
119  bounds = Bounds(
120  self.problem.get_bounds()[:, 0].repeat(self.problem.T - 1),
121  self.problem.get_bounds()[:, 1].repeat(self.problem.T - 1),
122  )
123 
124  s = time()
125  res = minimize(
126  self.cost_fun,
127  x0,
128  method=self.method,
129  bounds=bounds,
130  jac=True,
131  hess=self.hessian_update_strategy,
132  constraints=cons,
133  options={
134  "disp": self.debug,
135  "initial_tr_radius": 1000.0,
136  "verbose": 2,
137  "maxiter": self.max_iterations,
138  },
139  )
140  e = time()
141  if self.debug:
142  print(e - s)
143 
144  traj = np.zeros((self.problem.T, self.problem.N))
145  traj[0, :] = self.problem.start_state
146  for t in range(0, self.problem.T - 1):
147  traj[t + 1, :] = res.x[t * self.problem.N : (t + 1) * self.problem.N]
148  return traj
def __init__(self, problem=None, method=None, debug=False)


exotica_scipy_solver
Author(s): Wolfgang Merkt
autogenerated on Sat Apr 10 2021 02:36:55