Skip Symbolic Differentiation¶
Although symbolic differentiation is convenient for most problems, you may want to skip it for the following reasons:
- The problem cannot be simply described as symbolic expressions
- There are other more suitable automatic differentiation methods
- Functions need to call pre-compiled external libraries
- You want to call compiled functions directly for better performance
Setup Method¶
If you need to skip symbolic differentiation for certain functions, the method is similar to using the cache feature (see Compilation Is Very Slow). Simply place the manually edited function files in a specified folder, then set the cache parameter to that folder path in the set_* functions. Pockit will directly load these functions, thereby skipping symbolic differentiation.
For example, to replace the first state dynamics, prepare cache/dynamic_0.py and pass cache="cache" to set_dynamics. Pockit loads that file instead of generating it from the supplied symbolic expression. The filenames are:
| Function | Filename |
|---|---|
Phase.set_dynamics |
dynamic_{i}.py |
Phase.set_integral |
integral_{i}.py |
Phase.set_phase_constraint |
phase_constraint_{i}.py |
Phase.set_boundary_condition |
boundary_condition_0_{i}.py,boundary_condition_f_{i}.py,boundary_condition_t_0.py,boundary_condition_t_f.py |
System.set_objective |
objective.py |
System.set_system_constraint |
system_constraint_{i}.py |
File Format¶
The provided Python files should contain vector functions F, G, H and variables G_index, H_index_row, H_index_col. These functions and variables are defined as follows (also see the API documentation):
- Functions
F,G, andHtake a one-dimensional NumPy arrayxand an integerl. For a scalar function \(f(z_0,\ldots,z_{m-1})\),xstoreslevaluation points in parameter-major order:
$$ x=[z_0^{(0)},\ldots,z_0^{(l-1)},z_1^{(0)},\ldots,z_{m-1}^{(l-1)}]. $$
The value function therefore satisfies
$$ F(x,l)j=f!\left(z_0^{(j)},\ldots,z\right), \qquad j=0,\ldots,l-1. $$}^{(j)
Freturns a one-dimensional array of lengthl.Greturns an array with shape(len(G_index), l), one row for each stored gradient entry.Hreturns an array with shape(len(H_index_row), l), one row for each stored Hessian entry.G_index,H_index_row, andH_index_colare integer NumPy arrays that identify the nonzero derivative entries returned byGandH.H_index_rowandH_index_colhave equal length and contain only lower-triangular indices because the Hessian is symmetric.G_indexmust be strictly increasing.H_index_rowmust be nondecreasing, andH_index_colmust be strictly increasing among entries that share the same row.
Example files can be found in the generated cache files.
Given a system with \(n_x\) state variables, \(n_u\) control variables, \(n_i\) integrals, and \(n_s\) static parameters, the input parameters and dimensions for different functions are shown in the following table:
| Function | Input Parameters | Input Dimension \(m\) |
|---|---|---|
Phase.set_dynamics |
\(x\), \(u\), \(t\), \(s\) | \(n_x + n_u + 1 + n_s\) |
Phase.set_integral |
\(x\), \(u\), \(t\), \(s\) | \(n_x + n_u + 1 + n_s\) |
Phase.set_phase_constraint |
\(x\), \(u\), \(t\), \(s\) | \(n_x + n_u + 1 + n_s\) |
Phase.set_boundary_condition |
\(s\) | \(n_s\) |
System.set_objective |
\(I\), \(s\) | \(n_i + n_s\) |
System.set_system_constraint |
\(I\), \(s\) | \(n_i + n_s\) |