# Table of Contents

1  Unicycle Model

2  Kinematic bicycle Model

3  Dynamic bicycle Model

4  Compare Model

5  linealize Dynamic Bicycle Model memo

# Unicycle Model

非常にシンプルなモデル。
シンプルだが、速度ベクトルが車両の進行方向と同じなので少し無理がある

\begin{align}
x_{k+1} &= x_{k} + v_k cos(\phi_k)dt\\
y_{k+1} &= y_{k} + v_k sin(\phi_k)dt\\
\phi_{k+1} &= \phi_{k} + \frac{v_{k}}{L}tan(\delta_t)dt\\
v_{k+1} &= v_{k} + a_k dt \\
\end{align}

# Kinematic bicycle Model
Unicycle Modelと比べて、車両のすべり角は考慮しているが、車輪のすべり角は考慮していない。
速度が15km/h以下の時には有効らしい (Parking などでは有効らしい)

\begin{align}
x_{k+1} &= x_{k} + v_k cos(\phi_k+\beta_k)dt \\
y_{k+1} &= y_{k} + v_k sin(\phi_k+\beta_k)dt\\
\phi_{k+1} &= \phi_{k} + \frac{v_{k}}{L_r}sin(\beta_k)dt\\
v_{k+1} &= v_{k} + a_k dt\\
\beta_{k} &= tan^{-1}(\frac{L_r}{L_f+L_r}tan(\delta_{f,k}))
\end{align}

# Dynamic bicycle Model
高速で走行するモデルには基本的にこれをつかう
分母にv_xがあるため、速度が0の時に計算できなくなる。

\begin{align}
x_{k+1} &= x_{k} + v_{x,k} cos(\phi_k)dt - v_{y,k} sin(\phi_k)dt \\
y_{k+1} &= y_{k} + v_{x,k} sin(\phi_k)dt + v_{y,k} cos(\phi_k)dt\\
\phi_{k+1} &= \phi_{k} + \omega_k dt\\
F_{fy,k} &= -C_f( \frac{v_{y,k}+L_f\omega_k}{v_{x,k}}-\delta_t) \\
F_{ry,k} &= -C_r( \frac{v_{y,k}-L_r\omega_k}{v_{x,k}}) \\
v_{x,k+1} &= v_{x,k} + (a_k-\frac{F_{fy,k}sin(\delta_{k})}{m}+v_{y,k}\omega_k)dt\\
v_{y,k+1} &= v_{y,k} + (\frac{F_{ry,t}}{m}+\frac{F_{fy,k}cos(\delta_{k})}{m}-v_{x,k}\omega_k)dt\\
\omega_{k+1} &= \omega_{k} + \frac{dt}{I_z}(F_{fy,t}L_fcos(\delta_{t})-F_{ry,t}L_r)
\end{align}

# Compare Model

```python
#%matplotlib inline

import matplotlib.pyplot as plt
import numpy as np
import unicycle_model
import kinematic_bicycle_model
import dynamic_bicyccle_model
import math

T = 100
a = [1.0] * T
delta = [math.radians(1.0)] * T

ustate = unicycle_model.State()
kstate = kinematic_bicycle_model.State()
dstate = dynamic_bicyccle_model.State()

ux,uy,uyaw,uv, = [],[],[],[]
dx,dy,dyaw,dv, = [],[],[],[]
kx,ky,kyaw,kv, kbeta= [],[],[],[],[]
time = []
t = 0.0

for (ai, di) in zip(a, delta):
    t = t + unicycle_model.dt
    time.append(t)

    ustate = unicycle_model.update(ustate, ai, di)
    ux.append(ustate.x+kinematic_bicycle_model.Lr*math.cos(ustate.yaw))
    uy.append(ustate.y+kinematic_bicycle_model.Lr*math.sin(ustate.yaw))
    uyaw.append(ustate.yaw)
    uv.append(ustate.v)

    kstate = kinematic_bicycle_model.update(kstate, ai, di)
    kx.append(kstate.x)
    ky.append(kstate.y)
    kyaw.append(kstate.yaw)
    kv.append(kstate.v)
    kbeta.append(kstate.beta)

    dstate = dynamic_bicyccle_model.update(dstate, ai, di)
    dx.append(dstate.x)
    dy.append(dstate.y)
    dyaw.append(dstate.yaw)

```

    0.0
    6.0189879062819264e-05
    0.00018056963718845778
    0.0003611392743769156
    0.0006018987906281927
    0.0009028481859422891
    0.0012639874603192047
    0.0016853166137589396
    0.0021668356462614937
    0.002708544557826867
    0.0033104433484550597
    0.003972532018146071
    0.004694810566899903
    0.005477278994716553
    0.006319937301596024
    0.0072227854875383125
    0.00818582355254342
    0.009209051496611349
    0.010292469319742096
    0.011436077021935663
    0.012639874603192047
    0.013903862063511251
    0.015228039402893275
    0.01661240662133812
    0.018056963718845784
    0.019561710695416266
    0.021126647551049565
    0.022751774285745686
    0.024437090899504625
    0.026182597392326385
    0.027988293764210963
    0.02985418001515836
    0.03178025614516858
    0.03376652215424161
    0.03581297804237747
    0.03791962380957615
    0.04008645945583764
    0.042313484981161956
    0.044600700385549086
    0.04694810566899904
    0.04935570083151181
    0.0518234858730874
    0.05435146079372581
    0.05693962559342704
    0.05958798027219109
    0.062296524830017956
    0.06506525926690765
    0.06789418358286016
    0.07078329777787548
    0.07373260185195363
    0.07674209580509458
    0.07981177963729837
    0.08294165334856497
    0.08613171693889439
    0.08938197040828663
    0.09269241375674168
    0.09606304698425956
    0.09949387009084026
    0.10298488307648378
    0.10653608594119011
    0.11014747868495926
    0.11381906130779124
    0.11755083380968603
    0.12134279619064364
    0.12519494845066406
    0.12910729058974732
    0.1330798226078934
    0.13711254450510227
    0.141205456281374
    0.14535855793670852
    0.14957184947110586
    0.153845330884566
    0.158179002177089
    0.1625728633486748
    0.1670269143993234
    0.17154115532903486
    0.17611558613780912
    0.1807502068256462
    0.1854450173925461
    0.19020001783850882
    0.19501520816353435
    0.1998905883676227
    0.20482615845077387
    0.20982191841298786
    0.21487786825426466
    0.2199940079746043
    0.22517033757400676
    0.23040685705247202
    0.2357035664100001
    0.241060465646591
    0.24647755476224473
    0.25195483375696126
    0.25749230263074063
    0.2630899613835828
    0.2687478100154878
    0.2744658485264556
    0.28024407691648623
    0.2860824951855797
    0.291981103333736
    0.2979399013609551

```python
%timeit dynamic_bicyccle_model.update(dstate,ai,di)
```

    100000 loops, best of 3: 4.47 µs per loop

```python
dynamic_bicyccle_model?
```

```python
plt.plot(ux,uy,label="unicycle_model")
plt.plot(kx,ky,label="kinematic_bicycle_model")
plt.plot(dx,dy,label="dynamic_bicyccle_model")
plt.axis("equal")
plt.xlabel("X[m]")
plt.ylabel("Y[m]")
plt.legend()
plt.grid(True)
plt.show()
```

```python
plt.plot(ux,uy,label="unicycle_model")
plt.plot(kx,ky,label="kinematic_bicycle_model")
plt.axis("equal")
plt.xlabel("X[m]")
plt.ylabel("Y[m]")
plt.legend()
plt.grid(True)
plt.show()
```

```python
plt.plot(time, uyaw,label="unicycle_model")
plt.plot(time, kyaw,label="kinematic_bicycle_model")
plt.xlabel("Time[s]")
plt.ylabel("Yaw[rad]")
plt.legend()
plt.grid(True)
plt.show()
```

# linealize Dynamic Bicycle Model memo

```python
%matplotlib inline
```

```python
import sympy
from sympy import init_printing
init_printing()

x,y,vx, vy, phi, a, d, cf, cr, m, Lf, Lr, w,Iz = sympy.symbols('x y vx vy phi a d cf cr m Lf Lr, w, Iz')
f = vx*sympy.cos(phi) - vy*sympy.sin(phi)
f
```

```python
sympy.diff(f,x)
```

```python
sympy.diff(f,y)
```

```python
sympy.diff(f,phi)
```

```python
sympy.diff(f,vy)
```

```python
sympy.diff(f,vx)
```

```python
f2 = vx*sympy.sin(phi) - vy*sympy.cos(phi)
print(f2)
```

    vx*sin(phi) - vy*cos(phi)

```python
sympy.diff(f2,phi)
```

```python
fvx = a + sympy.sin(d) * cf / m * ((vy+Lf*w)/vx - d) + vy*w
fvx
```

```python
sympy.diff(fvx,vx)
```

```python
sympy.diff(fvx,vy)
```

```python
sympy.diff(fvx,w)
```

```python
sympy.diff(fvx,x)
```

```python
sympy.diff(fvx,d)
```

```python
fvy = - cr / m * (vy-Lr*w)/vx + sympy.cos(d)/m*((vy+Lf*w)/vx - d) -vx*w
fvy
```

```python
sympy.diff(fvy, vx)
```

```python
sympy.diff(fvy, vy)
```

```python
sympy.diff(fvy, w)
```

```python
sympy.diff(fvy,d)
```

```python
fw = -cf/Iz*((vy+Lf*w)/vx-d)*Lf*sympy.cos(d)+cr/Iz*(vy-Lr*w)/vx*Lr
fw
```

```python
sympy.diff(fw,vx)
```

```python
sympy.diff(fw,vy)
```

```python
sympy.diff(fw,w)
```

```python
sympy.diff(fw,d)
```


# Symbolic Partial Derivative Routine

## Authors: Zach Etienne & Tyler Knowles

## This module contains a routine for computing an analytic partial derivative of a mathematical expression that is written as seveal subexpressions.

**Notebook Status:**  In progress

**Validation Notes:** This tutorial notebook has been confirmed to be self-consistent with its corresponding NRPy+ module, as documented [below](#code_validation). Additionally, this notebook has been validated by checking that results are consistent with finite-difference derivative values in [LALSuite](https://git.ligo.org/lscsoft/lalsuite).

### NRPy+ Source Code for this module: [SEOBNR_Derivative_Routine.py](../../edit/in_progress/SEOBNR/SEOBNR_Derivative_Routine.py)

## Introduction
$$\label{intro}$$

This notebook documents the symbolic partial derivative routine used to generate analytic derivatives of the [SEOBNRv3](https://git.ligo.org/lscsoft/lalsuite) Hamiltonian (documented [here](../Tutorial-SEOBNR_Documentation.ipynb)) and described in [this article](https://arxiv.org/abs/1803.06346).

# Table of Contents
$$\label{toc}$$

This notebook is organized as follows

1. [Step 1](#initializenrpy): Initialize core Python/NRPy+ modules
1. [Step 2:](#step2) Read in expressions
1. [Step 3:](#step3) Read in constants
1. [Step 4:](#step4) List free symbols
1. [Step 5:](#step5) Convert expressions to function notation
1. [Step 6:](#step6) Differentiate with respect to xx
1. [Step 7:](#step7) Simplify derivative expressions
1. [Step 9:](#step9) Differentiate with respect to a specific free variable
1. [Step 10:](#step10) Compute derivatives with respect to each free variable
1. [Step 11:](#step11) Output result
1. [Step 12:](#code_validation): Code Validation against `SEOBNR_Derivative_Routine` NRPy+ module
1. [Step 13:](#latex_pdf_output) Output this notebook to $\LaTeX$-formatted PDF file

# Step 1: Initialize core Python/NRPy+ modules \[Back to [top](#toc)\]
$$\label{initializenrpy}$$

Let's start by importing all the needed modules from Python/NRPy+:

```python
# Step 1.a: import all needed modules from Python/NRPy+:
import sympy as sp                # SymPy: The Python computer algebra package upon which NRPy+ depends
import os, sys                    # Standard Python modules for multiplatform OS-level functions

# Step 1.?: check system path so can use outputC; #TylerK: remove and put outputC back with other imports
nrpy_dir_path = os.path.join("..")
if nrpy_dir_path not in sys.path:
    sys.path.append(nrpy_dir_path)

from outputC import *             # TylerK: check what is imported and remove *; also find appropriate description
```

# Step 2: Read in expressions \[Back to [top](#toc)\]
$$\label{step2}$$

We read in the expressions of which we will compute partial derivatives in a single large string before splitting the string by line (carriage return) and by "=".  Doing so allows us to manipulate the right- and left-hand sides of the expressions appropriately.  We store the left- and right-hand sides in the array $\texttt{lr}$, which consists of $\texttt{lhrh}$ arrays with left-hand sides $\texttt{lhs}$ and right-hand sides $\texttt{rhs}$.  Note that $\texttt{Lambda}$ is a protected keyword in Python, so the variable $\Lambda$ in the Hamiltonian is renamed $\texttt{Lamb}$.

```python
# Step 2.a: Read in expressions as a (single) string
with open('SEOBNR/Hamstring_lite.txt', 'r') as file:
    all_expressions = file.read()

# Step 2.b: Split the expression string by carriage returns
string_lines = all_expressions.splitlines()

#TylerK: for debuggin
print(string_lines)

# Step 2.c: Create and populate the "lr" array, which separates each line into left- and right-hand sides
#   Each entry is a string of the form lhrh(lhs='',rhs='')
lr = []

for i in range(len(string_lines)):
    # Ignore lines with 2 or fewer characters and those starting with #
    if len(string_lines[i]) > 2 and string_lines[i][0] != "#":
        # Split each line by its equals sign
        split_line = string_lines[i].split("=")
        # Append the line to "lr", removing spaces, "sp." prefixes, and replacing Lambda->Lamb
        #   (Lambda is a protected keyword):
        lr.append(lhrh(lhs=split_line[0].replace(" ","").replace("Lambda","Lamb"),
                       rhs=split_line[1].replace(" ","").replace("sp.","").replace("Lambda","Lamb")))

# Step 2.d: Separate and simplify right- and left-hand sides into separate arrays
lhss = []
rhss = []
for i in range(len(lr)):
    lhss.append(sp.sympify(lr[i].lhs))
    rhss.append(sp.sympify(lr[i].rhs))

# Step 2.e: Read in variables with which to take derivatives
with open('SEOBNR/Hamstring_variables.txt', 'r') as file:
    variables = file.read()
# Step 2.f: Split the variable string by carriage returns
dynamic_variables = variables.splitlines()
#TylerK: for debuggin
print(lhss)
print(rhss)
print(dynamic_variables)
```

    ['sigmaKerr0 = s1x + s2x', 'r2 = x*x + y*y + z*z', 'r = sp.sqrt(r2)', 'u = 1/r', 'tmppx = px - r*eta', 'quagsire = eta*eta']
    [sigmaKerr0, r2, r, u, tmppx, quagsire]
    [s1x + s2x, x**2 + y**2 + z**2, sqrt(r2), 1/r, -eta*r + px, eta**2]
    ['x', 'y', 'z', 'px', 'py', 'pz', 's1x', 's1y', 's1z', 's2x', 's2y', 's2z']

# Step 3: Read in constants \[Back to [top](#toc)\]
$$\label{step3}$$

We declare the constant values; derivatives with respect to these variables will be set to zero.

```python
# Step 3.a: Read in constants as a (single) string
with open('SEOBNR/constants.txt', 'r') as file:
    constants = file.read()

# Step 3.b: Split the input string by carriage returns
constants_as_strings = constants.splitlines()

# Step 3.c: Create "input_constants" array and populate with SymPy constants
input_constants = []
for constant in constants_as_strings:
    constant = sp.symbols(constant,real=True)
    input_constants.append(constant)

#TylerK: for debuggin
print(input_constants)
```

    [m1, m2, eta, tortoise, dSO, dSS]

# Step 4: List free symbols \[Back to [top](#toc)\]
$$\label{step4}$$

By ''free symbols'' we mean the variables in the right-hand sides.  We first create a list of all such terms (using SymPy's built-in free_symbol attribute), including duplicates, and then strip the duplicates.  We then remove input constants from the symbol list.

```python
# Step 4.a: Prepare array of "free symbols" in the right-hand side expressions
full_symbol_list_with_dups = []
for i in range(len(lr)):
    for variable in rhss[i].free_symbols:
        full_symbol_list_with_dups.append(variable)

# TylerK: print for debuggin
print(full_symbol_list_with_dups)

# Step 4.b: Remove duplicate free symbols
full_symbol_list = superfast_uniq(full_symbol_list_with_dups)

# Step 4.c: Remove input constants from symbol list
for inputconst in input_constants:
    for symbol in full_symbol_list:
        if str(symbol) == str(inputconst):
            full_symbol_list.remove(symbol)

# TylerK: print for debuggin
print(full_symbol_list)
```

    [s1x, s2x, z, x, y, r2, r, r, eta, px, eta]
    [s1x, s2x, z, x, y, r2, r, px]

# Step 5: Convert expressions to function notation \[Back to [top](#toc)\]
$$\label{step5}$$

In order to compute the partial derivative of each right-hand side, we mark each variable (left-hand side) and each free symbol (in right-hand sides) as a function with argument $\texttt{xx}$.

```python
# Step 5.a: Convert each left-hand side to function notation
#   while separating and simplifying left- and right-hand sides
xx = sp.Symbol('xx')
func = []
for i in range(len(lr)):
    func.append(sp.sympify(sp.Function(lr[i].lhs)(xx)))

# Step 5.b: Mark each free variable as a function with argument xx
full_function_list = []
for symb in full_symbol_list:
    func = sp.sympify(sp.Function(str(symb))(xx))
    full_function_list.append(func)
    for i in range(len(rhss)):
        for var in rhss[i].free_symbols:
            if str(var) == str(symb):
                rhss[i] = rhss[i].subs(var,func)
```

# Step 6: Differentiate with respect to xx \[Back to [top](#toc)\]
$$\label{step6}$$

Now we differentiate the right-hand expressions with respect to $\textrm{xx}$.  We use the SymPy $\texttt{diff}$ command, differentiating with respect to $\texttt{xx}$.  After so doing, we remove $\texttt{(xx)}$ and "Derivative" (which is output by $\texttt{diff}$, and use "prm" suffix to denote the derivative with respect to $\texttt{xx}$.

```python
# Step 6.a: Use SymPy's diff function to differentiate right-hand sides with respect to xx
#   and append "prm" notation to left-hand sides
lhss_deriv = []
rhss_deriv = []
for i in range(len(rhss)):
    lhss_deriv.append(sp.sympify(str(lhss[i])+"prm"))
    newrhs = sp.sympify(str(sp.diff(rhss[i],xx)).replace("(xx)","").replace(", xx","prm").replace("Derivative",""))
    rhss_deriv.append(newrhs)
#TylerK: for debuggin
print(lhss_deriv)
print(rhss_deriv)
```

    [sigmaKerr0prm, r2prm, rprm, uprm, tmppxprm, quagsireprm]
    [s1xprm + s2xprm, 2*x*xprm + 2*y*yprm + 2*z*zprm, r2prm/(2*sqrt(r2)), -rprm/r**2, -eta*rprm + pxprm, 0]

# Step 7: Simplify derivative expressions \[Back to [top](#toc)\]
$$\label{step7}$$

We declare a function to simply the derivative expressions.  In particular, we want to remove terms equal to zero.

```python
# Derivative simplification function
def simplify_deriv(lhss_deriv,rhss_deriv):
    # Copy expressions into another array
    lhss_deriv_simp = []
    rhss_deriv_simp = []
    for i in range(len(rhss_deriv)):
        lhss_deriv_simp.append(lhss_deriv[i])
        rhss_deriv_simp.append(rhss_deriv[i])
    # If a right-hand side is 0, substitute value 0 for the corresponding left-hand side in later terms
    for i in range(len(rhss_deriv_simp)):
        if rhss_deriv_simp[i] == 0:
            for j in range(i+1,len(rhss_deriv_simp)):
                for var in rhss_deriv_simp[j].free_symbols:
                    if str(var) == str(lhss_deriv_simp[i]):
                        rhss_deriv_simp[j] = rhss_deriv_simp[j].subs(var,0)
    zero_elements_to_remove = []
    # Create array of indices for expressions that are zero
    for i in range(len(rhss_deriv_simp)):
        if rhss_deriv_simp[i] == sp.sympify(0):
            zero_elements_to_remove.append(i)

    # When removing terms that are zero, we need to take into account their new index (after each removal)
    count = 0
    for i in range(len(zero_elements_to_remove)):
        del lhss_deriv_simp[zero_elements_to_remove[i]+count]
        del rhss_deriv_simp[zero_elements_to_remove[i]+count]
        count -= 1
    return lhss_deriv_simp,rhss_deriv_simp

# Step 7: Call the simplication function and then copy results
lhss_deriv_simp,rhss_deriv_simp = simplify_deriv(lhss_deriv,rhss_deriv)
lhss_deriv = lhss_deriv_simp
rhss_deriv = rhss_deriv_simp
#TylerK: for debuggin
print(lhss_deriv)
print(rhss_deriv)
```

    [sigmaKerr0prm, r2prm, rprm, uprm, tmppxprm]
    [s1xprm + s2xprm, 2*x*xprm + 2*y*yprm + 2*z*zprm, r2prm/(2*sqrt(r2)), -rprm/r**2, -eta*rprm + pxprm]

# Step 8: Differentiate with respect to a specific free variable \[Back to [top](#toc)\]
$$\label{step8}$$

In [Step 6](#step6) we took a generic derivative of each term, assuming it is a function of the varible $\textrm{xx}$.  We now define a function that will select a specific free variable for differentiation.

```python
def deriv_onevar(lhss_deriv,rhss_deriv,xprm=0,yprm=0,zprm=0,pxprm=0,pyprm=0,pzprm=0,
                 s1xprm=0,s1yprm=0,s1zprm=0,s2xprm=0,s2yprm=0,s2zprm=0):

    # Copy expressions into another array
    lhss_deriv_new = []
    rhss_deriv_new = []
    for i in range(len(rhss_deriv)):
        lhss_deriv_new.append(lhss_deriv[i])
        rhss_deriv_new.append(rhss_deriv[i])
    # For each free symbol, replace it with the desired derivative
    for i in range(len(rhss_deriv_new)):
        for var in rhss_deriv_new[i].free_symbols:
            if str(var)=="xprm":
                rhss_deriv_new[i] = rhss_deriv_new[i].subs(var,xprm)
            elif str(var)=="yprm":
                rhss_deriv_new[i] = rhss_deriv_new[i].subs(var,yprm)
            elif str(var)=="zprm":
                rhss_deriv_new[i] = rhss_deriv_new[i].subs(var,zprm)
            elif str(var)=="pxprm":
                rhss_deriv_new[i] = rhss_deriv_new[i].subs(var,pxprm)
            elif str(var)=="pyprm":
                rhss_deriv_new[i] = rhss_deriv_new[i].subs(var,pyprm)
            elif str(var)=="pzprm":
                rhss_deriv_new[i] = rhss_deriv_new[i].subs(var,pzprm)
            elif str(var)=="s1xprm":
                rhss_deriv_new[i] = rhss_deriv_new[i].subs(var,s1xprm)
            elif str(var)=="s1yprm":
                rhss_deriv_new[i] = rhss_deriv_new[i].subs(var,s1yprm)
            elif str(var)=="s1zprm":
                rhss_deriv_new[i] = rhss_deriv_new[i].subs(var,s1zprm)
            elif str(var)=="s2xprm":
                rhss_deriv_new[i] = rhss_deriv_new[i].subs(var,s2xprm)
            elif str(var)=="s2yprm":
                rhss_deriv_new[i] = rhss_deriv_new[i].subs(var,s2yprm)
            elif str(var)=="s2zprm":
                rhss_deriv_new[i] = rhss_deriv_new[i].subs(var,s2zprm)
    # Simplify derivative expressions again
    lhss_deriv_simp,rhss_deriv_simp = simplify_deriv(lhss_deriv_new,rhss_deriv_new)
    return lhss_deriv_simp,rhss_deriv_simp

#def deriv_onevar_test(lhss_deriv,rhss_deriv,variable_list,variable):
def deriv_onevar_test(lhss_deriv,rhss_deriv,variable_list,variable):
    variableprm_list = []
    for variable in variable_list:
        variableprm_list.append(str(variable)+"prm")

    # Copy expressions into another array
    lhss_deriv_new = []
    rhss_deriv_new = []
    for i in range(len(rhss_deriv)):
        lhss_deriv_new.append(lhss_deriv[i])
        rhss_deriv_new.append(rhss_deriv[i])
    # For each free symbol, replace it with the desired derivative
    for i in range(len(rhss_deriv_new)):
        #for var in rhss_deriv_new[i].free_symbols:
        for var in variableprm_list:
#            if variableprm_list.index(str(var))==index:
            if str(var)==str(variable+"prm"):
                #TylerK: print for debuggin
                print("I'm in the == loop")
                rhss_deriv_new[i] = rhss_deriv_new[i].subs(var,1)
            else:
                #TylerK: print for debuggin
                print("I'm in the else loop with var ", var, " and variable ", variable)
                rhss_deriv_new[i] = rhss_deriv_new[i].subs(var,0)
    # Simplify derivative expressions again
    lhss_deriv_simp,rhss_deriv_simp = simplify_deriv(lhss_deriv_new,rhss_deriv_new)
    #TylerK: print for debuggin
    print(lhss_deriv_simp)
    print(rhss_deriv_simp)
    return lhss_deriv_simp,rhss_deriv_simp
```

# Step 9: Compute derivatives with respect to each free variable \[Back to [top](#toc)\]
$$\label{step9}$$

This needs to be made into a loop!

```python
print("New routine")
lhss_derivative = dict()
rhss_derivative = dict()
#for index in range(len(dynamic_variables)):
for var in dynamic_variables:
    #TylerK: print for debuggin
    print("computing deriv with respect to ",var)
    lhss_derivative[var],rhss_derivative[var] = deriv_onevar_test(lhss_deriv,rhss_deriv,dynamic_variables,var)
    #lhss_derivative[dynamic_variables[index]],rhss_derivative[dynamic_variables[index]] = deriv_onevar_test(lhss_deriv,rhss_deriv,dynamic_variables,index)
    #lhss_deriv_partial,rhss_deriv_partial = deriv_onevar_test(lhss_deriv,rhss_deriv,dynamic_variables,index)
    #lhss_derivative.append(lhss_deriv_partial)
    #rhss_derivative.append(rhss_deriv_partial)
#TylerK: for debuggin
print("left-hand side is", lhss_derivative)
print("right-hand side is", rhss_derivative)
print("left-hand side is", lhss_derivative['x'])
print("right-hand side is", rhss_derivative['x'])

print("Old routine")
lhss_deriv_x,rhss_deriv_x = deriv_onevar(lhss_deriv,rhss_deriv, xprm=1,yprm=0,zprm=0,pxprm=0,pyprm=0,pzprm=0,
                                         s1xprm=0,s1yprm=0,s1zprm=0,s2xprm=0,s2yprm=0,s2zprm=0)
lhss_deriv_y,rhss_deriv_y = deriv_onevar(lhss_deriv,rhss_deriv,xprm=0,yprm=1,zprm=0,pxprm=0,pyprm=0,pzprm=0,
                                         s1xprm=0,s1yprm=0,s1zprm=0,s2xprm=0,s2yprm=0,s2zprm=0)
lhss_deriv_z,rhss_deriv_z = deriv_onevar(lhss_deriv,rhss_deriv,xprm=0,yprm=0,zprm=1,pxprm=0,pyprm=0,pzprm=0,
                                         s1xprm=0,s1yprm=0,s1zprm=0,s2xprm=0,s2yprm=0,s2zprm=0)
lhss_deriv_px,rhss_deriv_px = deriv_onevar(lhss_deriv,rhss_deriv,xprm=0,yprm=0,zprm=0,pxprm=1,pyprm=0,pzprm=0,
                                           s1xprm=0,s1yprm=0,s1zprm=0,s2xprm=0,s2yprm=0,s2zprm=0)
lhss_deriv_py,rhss_deriv_py = deriv_onevar(lhss_deriv,rhss_deriv,xprm=0,yprm=0,zprm=0,pxprm=0,pyprm=1,pzprm=0,
                                           s1xprm=0,s1yprm=0,s1zprm=0,s2xprm=0,s2yprm=0,s2zprm=0)
lhss_deriv_pz,rhss_deriv_pz = deriv_onevar(lhss_deriv,rhss_deriv,xprm=0,yprm=0,zprm=0,pxprm=0,pyprm=1,pzprm=1,
                                           s1xprm=0,s1yprm=0,s1zprm=0,s2xprm=0,s2yprm=0,s2zprm=0)
lhss_deriv_s1x,rhss_deriv_s1x = deriv_onevar(lhss_deriv,rhss_deriv, xprm=0,yprm=0,zprm=0,pxprm=0,pyprm=0,pzprm=0,
                                             s1xprm=1,s1yprm=0,s1zprm=0,s2xprm=0,s2yprm=0,s2zprm=0)
lhss_deriv_s1y,rhss_deriv_s1y = deriv_onevar(lhss_deriv,rhss_deriv,xprm=0,yprm=0,zprm=0,pxprm=0,pyprm=0,pzprm=0,
                                             s1xprm=0,s1yprm=1,s1zprm=0,s2xprm=0,s2yprm=0,s2zprm=0)
lhss_deriv_s1z,rhss_deriv_s1z = deriv_onevar(lhss_deriv,rhss_deriv,xprm=0,yprm=0,zprm=0,pxprm=0,pyprm=0,pzprm=0,
                                             s1xprm=0,s1yprm=0,s1zprm=1,s2xprm=0,s2yprm=0,s2zprm=0)
lhss_deriv_s2x,rhss_deriv_s2x = deriv_onevar(lhss_deriv,rhss_deriv,xprm=0,yprm=0,zprm=0,pxprm=0,pyprm=0,pzprm=0,
                                             s1xprm=0,s1yprm=0,s1zprm=0,s2xprm=1,s2yprm=0,s2zprm=0)
lhss_deriv_s2y,rhss_deriv_s2y = deriv_onevar(lhss_deriv,rhss_deriv,xprm=0,yprm=0,zprm=0,pxprm=0,pyprm=0,pzprm=0,
                                             s1xprm=0,s1yprm=0,s1zprm=0,s2xprm=0,s2yprm=1,s2zprm=0)
lhss_deriv_s2z,rhss_deriv_s2z = deriv_onevar(lhss_deriv,rhss_deriv,xprm=0,yprm=0,zprm=0,pxprm=0,pyprm=0,pzprm=0,
                                             s1xprm=0,s1yprm=0,s1zprm=0,s2xprm=0,s2yprm=0,s2zprm=1)
#TylerK: for debuggin
print("left-hand side is", lhss_deriv_px)
print("right-hand side is", rhss_deriv_px)
```

    New routine
    computing deriv with respect to  x
    I'm in the else loop with var  xprm  and variable  s2z
    I'm in the else loop with var  yprm  and variable  s2z
    I'm in the else loop with var  zprm  and variable  s2z
    I'm in the else loop with var  pxprm  and variable  s2z
    I'm in the else loop with var  pyprm  and variable  s2z
    I'm in the else loop with var  pzprm  and variable  s2z
    I'm in the else loop with var  s1xprm  and variable  s2z
    I'm in the else loop with var  s1yprm  and variable  s2z
    I'm in the else loop with var  s1zprm  and variable  s2z
    I'm in the else loop with var  s2xprm  and variable  s2z
    I'm in the else loop with var  s2yprm  and variable  s2z
    I'm in the == loop
    I'm in the else loop with var  xprm  and variable  s2z
    I'm in the else loop with var  yprm  and variable  s2z
    I'm in the else loop with var  zprm  and variable  s2z
    I'm in the else loop with var  pxprm  and variable  s2z
    I'm in the else loop with var  pyprm  and variable  s2z
    I'm in the else loop with var  pzprm  and variable  s2z
    I'm in the else loop with var  s1xprm  and variable  s2z
    I'm in the else loop with var  s1yprm  and variable  s2z
    I'm in the else loop with var  s1zprm  and variable  s2z
    I'm in the else loop with var  s2xprm  and variable  s2z
    I'm in the else loop with var  s2yprm  and variable  s2z
    I'm in the == loop
    I'm in the else loop with var  xprm  and variable  s2z
    I'm in the else loop with var  yprm  and variable  s2z
    I'm in the else loop with var  zprm  and variable  s2z
    I'm in the else loop with var  pxprm  and variable  s2z
    I'm in the else loop with var  pyprm  and variable  s2z
    I'm in the else loop with var  pzprm  and variable  s2z
    I'm in the else loop with var  s1xprm  and variable  s2z
    I'm in the else loop with var  s1yprm  and variable  s2z
    I'm in the else loop with var  s1zprm  and variable  s2z
    I'm in the else loop with var  s2xprm  and variable  s2z
    I'm in the else loop with var  s2yprm  and variable  s2z
    I'm in the == loop
    I'm in the else loop with var  xprm  and variable  s2z
    I'm in the else loop with var  yprm  and variable  s2z
    I'm in the else loop with var  zprm  and variable  s2z
    I'm in the else loop with var  pxprm  and variable  s2z
    I'm in the else loop with var  pyprm  and variable  s2z
    I'm in the else loop with var  pzprm  and variable  s2z
    I'm in the else loop with var  s1xprm  and variable  s2z
    I'm in the else loop with var  s1yprm  and variable  s2z
    I'm in the else loop with var  s1zprm  and variable  s2z
    I'm in the else loop with var  s2xprm  and variable  s2z
    I'm in the else loop with var  s2yprm  and variable  s2z
    I'm in the == loop
    I'm in the else loop with var  xprm  and variable  s2z
    I'm in the else loop with var  yprm  and variable  s2z
    I'm in the else loop with var  zprm  and variable  s2z
    I'm in the else loop with var  pxprm  and variable  s2z
    I'm in the else loop with var  pyprm  and variable  s2z
    I'm in the else loop with var  pzprm  and variable  s2z
    I'm in the else loop with var  s1xprm  and variable  s2z
    I'm in the else loop with var  s1yprm  and variable  s2z
    I'm in the else loop with var  s1zprm  and variable  s2z
    I'm in the else loop with var  s2xprm  and variable  s2z
    I'm in the else loop with var  s2yprm  and variable  s2z
    I'm in the == loop
    []
    []
    computing deriv with respect to  y
    I'm in the else loop with var  xprm  and variable  s2z
    I'm in the else loop with var  yprm  and variable  s2z
    I'm in the else loop with var  zprm  and variable  s2z
    I'm in the else loop with var  pxprm  and variable  s2z
    I'm in the else loop with var  pyprm  and variable  s2z
    I'm in the else loop with var  pzprm  and variable  s2z
    I'm in the else loop with var  s1xprm  and variable  s2z
    I'm in the else loop with var  s1yprm  and variable  s2z
    I'm in the else loop with var  s1zprm  and variable  s2z
    I'm in the else loop with var  s2xprm  and variable  s2z
    I'm in the else loop with var  s2yprm  and variable  s2z
    I'm in the == loop
    I'm in the else loop with var  xprm  and variable  s2z
    I'm in the else loop with var  yprm  and variable  s2z
    I'm in the else loop with var  zprm  and variable  s2z
    I'm in the else loop with var  pxprm  and variable  s2z
    I'm in the else loop with var  pyprm  and variable  s2z
    I'm in the else loop with var  pzprm  and variable  s2z
    I'm in the else loop with var  s1xprm  and variable  s2z
    I'm in the else loop with var  s1yprm  and variable  s2z
    I'm in the else loop with var  s1zprm  and variable  s2z
    I'm in the else loop with var  s2xprm  and variable  s2z
    I'm in the else loop with var  s2yprm  and variable  s2z
    I'm in the == loop
    I'm in the else loop with var  xprm  and variable  s2z
    I'm in the else loop with var  yprm  and variable  s2z
    I'm in the else loop with var  zprm  and variable  s2z
    I'm in the else loop with var  pxprm  and variable  s2z
    I'm in the else loop with var  pyprm  and variable  s2z
    I'm in the else loop with var  pzprm  and variable  s2z
    I'm in the else loop with var  s1xprm  and variable  s2z
    I'm in the else loop with var  s1yprm  and variable  s2z
    I'm in the else loop with var  s1zprm  and variable  s2z
    I'm in the else loop with var  s2xprm  and variable  s2z
    I'm in the else loop with var  s2yprm  and variable  s2z
    I'm in the == loop
    I'm in the else loop with var  xprm  and variable  s2z
    I'm in the else loop with var  yprm  and variable  s2z
    I'm in the else loop with var  zprm  and variable  s2z
    I'm in the else loop with var  pxprm  and variable  s2z
    I'm in the else loop with var  pyprm  and variable  s2z
    I'm in the else loop with var  pzprm  and variable  s2z
    I'm in the else loop with var  s1xprm  and variable  s2z
    I'm in the else loop with var  s1yprm  and variable  s2z
    I'm in the else loop with var  s1zprm  and variable  s2z
    I'm in the else loop with var  s2xprm  and variable  s2z
    I'm in the else loop with var  s2yprm  and variable  s2z
    I'm in the == loop
    I'm in the else loop with var  xprm  and variable  s2z
    I'm in the else loop with var  yprm  and variable  s2z
    I'm in the else loop with var  zprm  and variable  s2z
    I'm in the else loop with var  pxprm  and variable  s2z
    I'm in the else loop with var  pyprm  and variable  s2z
    I'm in the else loop with var  pzprm  and variable  s2z
    I'm in the else loop with var  s1xprm  and variable  s2z
    I'm in the else loop with var  s1yprm  and variable  s2z
    I'm in the else loop with var  s1zprm  and variable  s2z
    I'm in the else loop with var  s2xprm  and variable  s2z
    I'm in the else loop with var  s2yprm  and variable  s2z
    I'm in the == loop
    []
    []
    computing deriv with respect to  z
    I'm in the else loop with var  xprm  and variable  s2z
    I'm in the else loop with var  yprm  and variable  s2z
    I'm in the else loop with var  zprm  and variable  s2z
    I'm in the else loop with var  pxprm  and variable  s2z
    I'm in the else loop with var  pyprm  and variable  s2z
    I'm in the else loop with var  pzprm  and variable  s2z
    I'm in the else loop with var  s1xprm  and variable  s2z
    I'm in the else loop with var  s1yprm  and variable  s2z
    I'm in the else loop with var  s1zprm  and variable  s2z
    I'm in the else loop with var  s2xprm  and variable  s2z
    I'm in the else loop with var  s2yprm  and variable  s2z
    I'm in the == loop
    I'm in the else loop with var  xprm  and variable  s2z
    I'm in the else loop with var  yprm  and variable  s2z
    I'm in the else loop with var  zprm  and variable  s2z
    I'm in the else loop with var  pxprm  and variable  s2z
    I'm in the else loop with var  pyprm  and variable  s2z
    I'm in the else loop with var  pzprm  and variable  s2z
    I'm in the else loop with var  s1xprm  and variable  s2z
    I'm in the else loop with var  s1yprm  and variable  s2z
    I'm in the else loop with var  s1zprm  and variable  s2z
    I'm in the else loop with var  s2xprm  and variable  s2z
    I'm in the else loop with var  s2yprm  and variable  s2z
    I'm in the == loop
    I'm in the else loop with var  xprm  and variable  s2z
    I'm in the else loop with var  yprm  and variable  s2z
    I'm in the else loop with var  zprm  and variable  s2z
    I'm in the else loop with var  pxprm  and variable  s2z
    I'm in the else loop with var  pyprm  and variable  s2z
    I'm in the else loop with var  pzprm  and variable  s2z
    I'm in the else loop with var  s1xprm  and variable  s2z
    I'm in the else loop with var  s1yprm  and variable  s2z
    I'm in the else loop with var  s1zprm  and variable  s2z
    I'm in the else loop with var  s2xprm  and variable  s2z
    I'm in the else loop with var  s2yprm  and variable  s2z
    I'm in the == loop
    I'm in the else loop with var  xprm  and variable  s2z
    I'm in the else loop with var  yprm  and variable  s2z
    I'm in the else loop with var  zprm  and variable  s2z
    I'm in the else loop with var  pxprm  and variable  s2z
    I'm in the else loop with var  pyprm  and variable  s2z
    I'm in the else loop with var  pzprm  and variable  s2z
    I'm in the else loop with var  s1xprm  and variable  s2z
    I'm in the else loop with var  s1yprm  and variable  s2z
    I'm in the else loop with var  s1zprm  and variable  s2z
    I'm in the else loop with var  s2xprm  and variable  s2z
    I'm in the else loop with var  s2yprm  and variable  s2z
    I'm in the == loop
    I'm in the else loop with var  xprm  and variable  s2z
    I'm in the else loop with var  yprm  and variable  s2z
    I'm in the else loop with var  zprm  and variable  s2z
    I'm in the else loop with var  pxprm  and variable  s2z
    I'm in the else loop with var  pyprm  and variable  s2z
    I'm in the else loop with var  pzprm  and variable  s2z
    I'm in the else loop with var  s1xprm  and variable  s2z
    I'm in the else loop with var  s1yprm  and variable  s2z
    I'm in the else loop with var  s1zprm  and variable  s2z
    I'm in the else loop with var  s2xprm  and variable  s2z
    I'm in the else loop with var  s2yprm  and variable  s2z
    I'm in the == loop
    []
    []
    computing deriv with respect to  px
    I'm in the else loop with var  xprm  and variable  s2z
    I'm in the else loop with var  yprm  and variable  s2z
    I'm in the else loop with var  zprm  and variable  s2z
    I'm in the else loop with var  pxprm  and variable  s2z
    I'm in the else loop with var  pyprm  and variable  s2z
    I'm in the else loop with var  pzprm  and variable  s2z
    I'm in the else loop with var  s1xprm  and variable  s2z
    I'm in the else loop with var  s1yprm  and variable  s2z
    I'm in the else loop with var  s1zprm  and variable  s2z
    I'm in the else loop with var  s2xprm  and variable  s2z
    I'm in the else loop with var  s2yprm  and variable  s2z
    I'm in the == loop
    I'm in the else loop with var  xprm  and variable  s2z
    I'm in the else loop with var  yprm  and variable  s2z
    I'm in the else loop with var  zprm  and variable  s2z
    I'm in the else loop with var  pxprm  and variable  s2z
    I'm in the else loop with var  pyprm  and variable  s2z
    I'm in the else loop with var  pzprm  and variable  s2z
    I'm in the else loop with var  s1xprm  and variable  s2z
    I'm in the else loop with var  s1yprm  and variable  s2z
    I'm in the else loop with var  s1zprm  and variable  s2z
    I'm in the else loop with var  s2xprm  and variable  s2z
    I'm in the else loop with var  s2yprm  and variable  s2z
    I'm in the == loop
    I'm in the else loop with var  xprm  and variable  s2z
    I'm in the else loop with var  yprm  and variable  s2z
    I'm in the else loop with var  zprm  and variable  s2z
    I'm in the else loop with var  pxprm  and variable  s2z
    I'm in the else loop with var  pyprm  and variable  s2z
    I'm in the else loop with var  pzprm  and variable  s2z
    I'm in the else loop with var  s1xprm  and variable  s2z
    I'm in the else loop with var  s1yprm  and variable  s2z
    I'm in the else loop with var  s1zprm  and variable  s2z
    I'm in the else loop with var  s2xprm  and variable  s2z
    I'm in the else loop with var  s2yprm  and variable  s2z
    I'm in the == loop
    I'm in the else loop with var  xprm  and variable  s2z
    I'm in the else loop with var  yprm  and variable  s2z
    I'm in the else loop with var  zprm  and variable  s2z
    I'm in the else loop with var  pxprm  and variable  s2z
    I'm in the else loop with var  pyprm  and variable  s2z
    I'm in the else loop with var  pzprm  and variable  s2z
    I'm in the else loop with var  s1xprm  and variable  s2z
    I'm in the else loop with var  s1yprm  and variable  s2z
    I'm in the else loop with var  s1zprm  and variable  s2z
    I'm in the else loop with var  s2xprm  and variable  s2z
    I'm in the else loop with var  s2yprm  and variable  s2z
    I'm in the == loop
    I'm in the else loop with var  xprm  and variable  s2z
    I'm in the else loop with var  yprm  and variable  s2z
    I'm in the else loop with var  zprm  and variable  s2z
    I'm in the else loop with var  pxprm  and variable  s2z
    I'm in the else loop with var  pyprm  and variable  s2z
    I'm in the else loop with var  pzprm  and variable  s2z
    I'm in the else loop with var  s1xprm  and variable  s2z
    I'm in the else loop with var  s1yprm  and variable  s2z
    I'm in the else loop with var  s1zprm  and variable  s2z
    I'm in the else loop with var  s2xprm  and variable  s2z
    I'm in the else loop with var  s2yprm  and variable  s2z
    I'm in the == loop
    []
    []
    computing deriv with respect to  py
    I'm in the else loop with var  xprm  and variable  s2z
    I'm in the else loop with var  yprm  and variable  s2z
    I'm in the else loop with var  zprm  and variable  s2z
    I'm in the else loop with var  pxprm  and variable  s2z
    I'm in the else loop with var  pyprm  and variable  s2z
    I'm in the else loop with var  pzprm  and variable  s2z
    I'm in the else loop with var  s1xprm  and variable  s2z
    I'm in the else loop with var  s1yprm  and variable  s2z
    I'm in the else loop with var  s1zprm  and variable  s2z
    I'm in the else loop with var  s2xprm  and variable  s2z
    I'm in the else loop with var  s2yprm  and variable  s2z
    I'm in the == loop
    I'm in the else loop with var  xprm  and variable  s2z
    I'm in the else loop with var  yprm  and variable  s2z
    I'm in the else loop with var  zprm  and variable  s2z
    I'm in the else loop with var  pxprm  and variable  s2z
    I'm in the else loop with var  pyprm  and variable  s2z
    I'm in the else loop with var  pzprm  and variable  s2z
    I'm in the else loop with var  s1xprm  and variable  s2z
    I'm in the else loop with var  s1yprm  and variable  s2z
    I'm in the else loop with var  s1zprm  and variable  s2z
    I'm in the else loop with var  s2xprm  and variable  s2z
    I'm in the else loop with var  s2yprm  and variable  s2z
    I'm in the == loop
    I'm in the else loop with var  xprm  and variable  s2z
    I'm in the else loop with var  yprm  and variable  s2z
    I'm in the else loop with var  zprm  and variable  s2z
    I'm in the else loop with var  pxprm  and variable  s2z
    I'm in the else loop with var  pyprm  and variable  s2z
    I'm in the else loop with var  pzprm  and variable  s2z
    I'm in the else loop with var  s1xprm  and variable  s2z
    I'm in the else loop with var  s1yprm  and variable  s2z
    I'm in the else loop with var  s1zprm  and variable  s2z
    I'm in the else loop with var  s2xprm  and variable  s2z
    I'm in the else loop with var  s2yprm  and variable  s2z
    I'm in the == loop
    I'm in the else loop with var  xprm  and variable  s2z
    I'm in the else loop with var  yprm  and variable  s2z
    I'm in the else loop with var  zprm  and variable  s2z
    I'm in the else loop with var  pxprm  and variable  s2z
    I'm in the else loop with var  pyprm  and variable  s2z
    I'm in the else loop with var  pzprm  and variable  s2z
    I'm in the else loop with var  s1xprm  and variable  s2z
    I'm in the else loop with var  s1yprm  and variable  s2z
    I'm in the else loop with var  s1zprm  and variable  s2z
    I'm in the else loop with var  s2xprm  and variable  s2z
    I'm in the else loop with var  s2yprm  and variable  s2z
    I'm in the == loop
    I'm in the else loop with var  xprm  and variable  s2z
    I'm in the else loop with var  yprm  and variable  s2z
    I'm in the else loop with var  zprm  and variable  s2z
    I'm in the else loop with var  pxprm  and variable  s2z
    I'm in the else loop with var  pyprm  and variable  s2z
    I'm in the else loop with var  pzprm  and variable  s2z
    I'm in the else loop with var  s1xprm  and variable  s2z
    I'm in the else loop with var  s1yprm  and variable  s2z
    I'm in the else loop with var  s1zprm  and variable  s2z
    I'm in the else loop with var  s2xprm  and variable  s2z
    I'm in the else loop with var  s2yprm  and variable  s2z
    I'm in the == loop
    []
    []
    computing deriv with respect to  pz
    I'm in the else loop with var  xprm  and variable  s2z
    I'm in the else loop with var  yprm  and variable  s2z
    I'm in the else loop with var  zprm  and variable  s2z
    I'm in the else loop with var  pxprm  and variable  s2z
    I'm in the else loop with var  pyprm  and variable  s2z
    I'm in the else loop with var  pzprm  and variable  s2z
    I'm in the else loop with var  s1xprm  and variable  s2z
    I'm in the else loop with var  s1yprm  and variable  s2z
    I'm in the else loop with var  s1zprm  and variable  s2z
    I'm in the else loop with var  s2xprm  and variable  s2z
    I'm in the else loop with var  s2yprm  and variable  s2z
    I'm in the == loop
    I'm in the else loop with var  xprm  and variable  s2z
    I'm in the else loop with var  yprm  and variable  s2z
    I'm in the else loop with var  zprm  and variable  s2z
    I'm in the else loop with var  pxprm  and variable  s2z
    I'm in the else loop with var  pyprm  and variable  s2z
    I'm in the else loop with var  pzprm  and variable  s2z
    I'm in the else loop with var  s1xprm  and variable  s2z
    I'm in the else loop with var  s1yprm  and variable  s2z
    I'm in the else loop with var  s1zprm  and variable  s2z
    I'm in the else loop with var  s2xprm  and variable  s2z
    I'm in the else loop with var  s2yprm  and variable  s2z
    I'm in the == loop
    I'm in the else loop with var  xprm  and variable  s2z
    I'm in the else loop with var  yprm  and variable  s2z
    I'm in the else loop with var  zprm  and variable  s2z
    I'm in the else loop with var  pxprm  and variable  s2z
    I'm in the else loop with var  pyprm  and variable  s2z
    I'm in the else loop with var  pzprm  and variable  s2z
    I'm in the else loop with var  s1xprm  and variable  s2z
    I'm in the else loop with var  s1yprm  and variable  s2z
    I'm in the else loop with var  s1zprm  and variable  s2z
    I'm in the else loop with var  s2xprm  and variable  s2z
    I'm in the else loop with var  s2yprm  and variable  s2z
    I'm in the == loop
    I'm in the else loop with var  xprm  and variable  s2z
    I'm in the else loop with var  yprm  and variable  s2z
    I'm in the else loop with var  zprm  and variable  s2z
    I'm in the else loop with var  pxprm  and variable  s2z
    I'm in the else loop with var  pyprm  and variable  s2z
    I'm in the else loop with var  pzprm  and variable  s2z
    I'm in the else loop with var  s1xprm  and variable  s2z
    I'm in the else loop with var  s1yprm  and variable  s2z
    I'm in the else loop with var  s1zprm  and variable  s2z
    I'm in the else loop with var  s2xprm  and variable  s2z
    I'm in the else loop with var  s2yprm  and variable  s2z
    I'm in the == loop
    I'm in the else loop with var  xprm  and variable  s2z
    I'm in the else loop with var  yprm  and variable  s2z
    I'm in the else loop with var  zprm  and variable  s2z
    I'm in the else loop with var  pxprm  and variable  s2z
    I'm in the else loop with var  pyprm  and variable  s2z
    I'm in the else loop with var  pzprm  and variable  s2z
    I'm in the else loop with var  s1xprm  and variable  s2z
    I'm in the else loop with var  s1yprm  and variable  s2z
    I'm in the else loop with var  s1zprm  and variable  s2z
    I'm in the else loop with var  s2xprm  and variable  s2z
    I'm in the else loop with var  s2yprm  and variable  s2z
    I'm in the == loop
    []
    []
    computing deriv with respect to  s1x
    I'm in the else loop with var  xprm  and variable  s2z
    I'm in the else loop with var  yprm  and variable  s2z
    I'm in the else loop with var  zprm  and variable  s2z
    I'm in the else loop with var  pxprm  and variable  s2z
    I'm in the else loop with var  pyprm  and variable  s2z
    I'm in the else loop with var  pzprm  and variable  s2z
    I'm in the else loop with var  s1xprm  and variable  s2z
    I'm in the else loop with var  s1yprm  and variable  s2z
    I'm in the else loop with var  s1zprm  and variable  s2z
    I'm in the else loop with var  s2xprm  and variable  s2z
    I'm in the else loop with var  s2yprm  and variable  s2z
    I'm in the == loop
    I'm in the else loop with var  xprm  and variable  s2z
    I'm in the else loop with var  yprm  and variable  s2z
    I'm in the else loop with var  zprm  and variable  s2z
    I'm in the else loop with var  pxprm  and variable  s2z
    I'm in the else loop with var  pyprm  and variable  s2z
    I'm in the else loop with var  pzprm  and variable  s2z
    I'm in the else loop with var  s1xprm  and variable  s2z
    I'm in the else loop with var  s1yprm  and variable  s2z
    I'm in the else loop with var  s1zprm  and variable  s2z
    I'm in the else loop with var  s2xprm  and variable  s2z
    I'm in the else loop with var  s2yprm  and variable  s2z
    I'm in the == loop
    I'm in the else loop with var  xprm  and variable  s2z
    I'm in the else loop with var  yprm  and variable  s2z
    I'm in the else loop with var  zprm  and variable  s2z
    I'm in the else loop with var  pxprm  and variable  s2z
    I'm in the else loop with var  pyprm  and variable  s2z
    I'm in the else loop with var  pzprm  and variable  s2z
    I'm in the else loop with var  s1xprm  and variable  s2z
    I'm in the else loop with var  s1yprm  and variable  s2z
    I'm in the else loop with var  s1zprm  and variable  s2z
    I'm in the else loop with var  s2xprm  and variable  s2z
    I'm in the else loop with var  s2yprm  and variable  s2z
    I'm in the == loop
    I'm in the else loop with var  xprm  and variable  s2z
    I'm in the else loop with var  yprm  and variable  s2z
    I'm in the else loop with var  zprm  and variable  s2z
    I'm in the else loop with var  pxprm  and variable  s2z
    I'm in the else loop with var  pyprm  and variable  s2z
    I'm in the else loop with var  pzprm  and variable  s2z
    I'm in the else loop with var  s1xprm  and variable  s2z
    I'm in the else loop with var  s1yprm  and variable  s2z
    I'm in the else loop with var  s1zprm  and variable  s2z
    I'm in the else loop with var  s2xprm  and variable  s2z
    I'm in the else loop with var  s2yprm  and variable  s2z
    I'm in the == loop
    I'm in the else loop with var  xprm  and variable  s2z
    I'm in the else loop with var  yprm  and variable  s2z
    I'm in the else loop with var  zprm  and variable  s2z
    I'm in the else loop with var  pxprm  and variable  s2z
    I'm in the else loop with var  pyprm  and variable  s2z
    I'm in the else loop with var  pzprm  and variable  s2z
    I'm in the else loop with var  s1xprm  and variable  s2z
    I'm in the else loop with var  s1yprm  and variable  s2z
    I'm in the else loop with var  s1zprm  and variable  s2z
    I'm in the else loop with var  s2xprm  and variable  s2z
    I'm in the else loop with var  s2yprm  and variable  s2z
    I'm in the == loop
    []
    []
    computing deriv with respect to  s1y
    I'm in the else loop with var  xprm  and variable  s2z
    I'm in the else loop with var  yprm  and variable  s2z
    I'm in the else loop with var  zprm  and variable  s2z
    I'm in the else loop with var  pxprm  and variable  s2z
    I'm in the else loop with var  pyprm  and variable  s2z
    I'm in the else loop with var  pzprm  and variable  s2z
    I'm in the else loop with var  s1xprm  and variable  s2z
    I'm in the else loop with var  s1yprm  and variable  s2z
    I'm in the else loop with var  s1zprm  and variable  s2z
    I'm in the else loop with var  s2xprm  and variable  s2z
    I'm in the else loop with var  s2yprm  and variable  s2z
    I'm in the == loop
    I'm in the else loop with var  xprm  and variable  s2z
    I'm in the else loop with var  yprm  and variable  s2z
    I'm in the else loop with var  zprm  and variable  s2z
    I'm in the else loop with var  pxprm  and variable  s2z
    I'm in the else loop with var  pyprm  and variable  s2z
    I'm in the else loop with var  pzprm  and variable  s2z
    I'm in the else loop with var  s1xprm  and variable  s2z
    I'm in the else loop with var  s1yprm  and variable  s2z
    I'm in the else loop with var  s1zprm  and variable  s2z
    I'm in the else loop with var  s2xprm  and variable  s2z
    I'm in the else loop with var  s2yprm  and variable  s2z
    I'm in the == loop
    I'm in the else loop with var  xprm  and variable  s2z
    I'm in the else loop with var  yprm  and variable  s2z
    I'm in the else loop with var  zprm  and variable  s2z
    I'm in the else loop with var  pxprm  and variable  s2z
    I'm in the else loop with var  pyprm  and variable  s2z
    I'm in the else loop with var  pzprm  and variable  s2z
    I'm in the else loop with var  s1xprm  and variable  s2z
    I'm in the else loop with var  s1yprm  and variable  s2z
    I'm in the else loop with var  s1zprm  and variable  s2z
    I'm in the else loop with var  s2xprm  and variable  s2z
    I'm in the else loop with var  s2yprm  and variable  s2z
    I'm in the == loop
    I'm in the else loop with var  xprm  and variable  s2z
    I'm in the else loop with var  yprm  and variable  s2z
    I'm in the else loop with var  zprm  and variable  s2z
    I'm in the else loop with var  pxprm  and variable  s2z
    I'm in the else loop with var  pyprm  and variable  s2z
    I'm in the else loop with var  pzprm  and variable  s2z
    I'm in the else loop with var  s1xprm  and variable  s2z
    I'm in the else loop with var  s1yprm  and variable  s2z
    I'm in the else loop with var  s1zprm  and variable  s2z
    I'm in the else loop with var  s2xprm  and variable  s2z
    I'm in the else loop with var  s2yprm  and variable  s2z
    I'm in the == loop
    I'm in the else loop with var  xprm  and variable  s2z
    I'm in the else loop with var  yprm  and variable  s2z
    I'm in the else loop with var  zprm  and variable  s2z
    I'm in the else loop with var  pxprm  and variable  s2z
    I'm in the else loop with var  pyprm  and variable  s2z
    I'm in the else loop with var  pzprm  and variable  s2z
    I'm in the else loop with var  s1xprm  and variable  s2z
    I'm in the else loop with var  s1yprm  and variable  s2z
    I'm in the else loop with var  s1zprm  and variable  s2z
    I'm in the else loop with var  s2xprm  and variable  s2z
    I'm in the else loop with var  s2yprm  and variable  s2z
    I'm in the == loop
    []
    []
    computing deriv with respect to  s1z
    I'm in the else loop with var  xprm  and variable  s2z
    I'm in the else loop with var  yprm  and variable  s2z
    I'm in the else loop with var  zprm  and variable  s2z
    I'm in the else loop with var  pxprm  and variable  s2z
    I'm in the else loop with var  pyprm  and variable  s2z
    I'm in the else loop with var  pzprm  and variable  s2z
    I'm in the else loop with var  s1xprm  and variable  s2z
    I'm in the else loop with var  s1yprm  and variable  s2z
    I'm in the else loop with var  s1zprm  and variable  s2z
    I'm in the else loop with var  s2xprm  and variable  s2z
    I'm in the else loop with var  s2yprm  and variable  s2z
    I'm in the == loop
    I'm in the else loop with var  xprm  and variable  s2z
    I'm in the else loop with var  yprm  and variable  s2z
    I'm in the else loop with var  zprm  and variable  s2z
    I'm in the else loop with var  pxprm  and variable  s2z
    I'm in the else loop with var  pyprm  and variable  s2z
    I'm in the else loop with var  pzprm  and variable  s2z
    I'm in the else loop with var  s1xprm  and variable  s2z
    I'm in the else loop with var  s1yprm  and variable  s2z
    I'm in the else loop with var  s1zprm  and variable  s2z
    I'm in the else loop with var  s2xprm  and variable  s2z
    I'm in the else loop with var  s2yprm  and variable  s2z
    I'm in the == loop
    I'm in the else loop with var  xprm  and variable  s2z
    I'm in the else loop with var  yprm  and variable  s2z
    I'm in the else loop with var  zprm  and variable  s2z
    I'm in the else loop with var  pxprm  and variable  s2z
    I'm in the else loop with var  pyprm  and variable  s2z
    I'm in the else loop with var  pzprm  and variable  s2z
    I'm in the else loop with var  s1xprm  and variable  s2z
    I'm in the else loop with var  s1yprm  and variable  s2z
    I'm in the else loop with var  s1zprm  and variable  s2z
    I'm in the else loop with var  s2xprm  and variable  s2z
    I'm in the else loop with var  s2yprm  and variable  s2z
    I'm in the == loop
    I'm in the else loop with var  xprm  and variable  s2z
    I'm in the else loop with var  yprm  and variable  s2z
    I'm in the else loop with var  zprm  and variable  s2z
    I'm in the else loop with var  pxprm  and variable  s2z
    I'm in the else loop with var  pyprm  and variable  s2z
    I'm in the else loop with var  pzprm  and variable  s2z
    I'm in the else loop with var  s1xprm  and variable  s2z
    I'm in the else loop with var  s1yprm  and variable  s2z
    I'm in the else loop with var  s1zprm  and variable  s2z
    I'm in the else loop with var  s2xprm  and variable  s2z
    I'm in the else loop with var  s2yprm  and variable  s2z
    I'm in the == loop
    I'm in the else loop with var  xprm  and variable  s2z
    I'm in the else loop with var  yprm  and variable  s2z
    I'm in the else loop with var  zprm  and variable  s2z
    I'm in the else loop with var  pxprm  and variable  s2z
    I'm in the else loop with var  pyprm  and variable  s2z
    I'm in the else loop with var  pzprm  and variable  s2z
    I'm in the else loop with var  s1xprm  and variable  s2z
    I'm in the else loop with var  s1yprm  and variable  s2z
    I'm in the else loop with var  s1zprm  and variable  s2z
    I'm in the else loop with var  s2xprm  and variable  s2z
    I'm in the else loop with var  s2yprm  and variable  s2z
    I'm in the == loop
    []
    []
    computing deriv with respect to  s2x
    I'm in the else loop with var  xprm  and variable  s2z
    I'm in the else loop with var  yprm  and variable  s2z
    I'm in the else loop with var  zprm  and variable  s2z
    I'm in the else loop with var  pxprm  and variable  s2z
    I'm in the else loop with var  pyprm  and variable  s2z
    I'm in the else loop with var  pzprm  and variable  s2z
    I'm in the else loop with var  s1xprm  and variable  s2z
    I'm in the else loop with var  s1yprm  and variable  s2z
    I'm in the else loop with var  s1zprm  and variable  s2z
    I'm in the else loop with var  s2xprm  and variable  s2z
    I'm in the else loop with var  s2yprm  and variable  s2z
    I'm in the == loop
    I'm in the else loop with var  xprm  and variable  s2z
    I'm in the else loop with var  yprm  and variable  s2z
    I'm in the else loop with var  zprm  and variable  s2z
    I'm in the else loop with var  pxprm  and variable  s2z
    I'm in the else loop with var  pyprm  and variable  s2z
    I'm in the else loop with var  pzprm  and variable  s2z
    I'm in the else loop with var  s1xprm  and variable  s2z
    I'm in the else loop with var  s1yprm  and variable  s2z
    I'm in the else loop with var  s1zprm  and variable  s2z
    I'm in the else loop with var  s2xprm  and variable  s2z
    I'm in the else loop with var  s2yprm  and variable  s2z
    I'm in the == loop
    I'm in the else loop with var  xprm  and variable  s2z
    I'm in the else loop with var  yprm  and variable  s2z
    I'm in the else loop with var  zprm  and variable  s2z
    I'm in the else loop with var  pxprm  and variable  s2z
    I'm in the else loop with var  pyprm  and variable  s2z
    I'm in the else loop with var  pzprm  and variable  s2z
    I'm in the else loop with var  s1xprm  and variable  s2z
    I'm in the else loop with var  s1yprm  and variable  s2z
    I'm in the else loop with var  s1zprm  and variable  s2z
    I'm in the else loop with var  s2xprm  and variable  s2z
    I'm in the else loop with var  s2yprm  and variable  s2z
    I'm in the == loop
    I'm in the else loop with var  xprm  and variable  s2z
    I'm in the else loop with var  yprm  and variable  s2z
    I'm in the else loop with var  zprm  and variable  s2z
    I'm in the else loop with var  pxprm  and variable  s2z
    I'm in the else loop with var  pyprm  and variable  s2z
    I'm in the else loop with var  pzprm  and variable  s2z
    I'm in the else loop with var  s1xprm  and variable  s2z
    I'm in the else loop with var  s1yprm  and variable  s2z
    I'm in the else loop with var  s1zprm  and variable  s2z
    I'm in the else loop with var  s2xprm  and variable  s2z
    I'm in the else loop with var  s2yprm  and variable  s2z
    I'm in the == loop
    I'm in the else loop with var  xprm  and variable  s2z
    I'm in the else loop with var  yprm  and variable  s2z
    I'm in the else loop with var  zprm  and variable  s2z
    I'm in the else loop with var  pxprm  and variable  s2z
    I'm in the else loop with var  pyprm  and variable  s2z
    I'm in the else loop with var  pzprm  and variable  s2z
    I'm in the else loop with var  s1xprm  and variable  s2z
    I'm in the else loop with var  s1yprm  and variable  s2z
    I'm in the else loop with var  s1zprm  and variable  s2z
    I'm in the else loop with var  s2xprm  and variable  s2z
    I'm in the else loop with var  s2yprm  and variable  s2z
    I'm in the == loop
    []
    []
    computing deriv with respect to  s2y
    I'm in the else loop with var  xprm  and variable  s2z
    I'm in the else loop with var  yprm  and variable  s2z
    I'm in the else loop with var  zprm  and variable  s2z
    I'm in the else loop with var  pxprm  and variable  s2z
    I'm in the else loop with var  pyprm  and variable  s2z
    I'm in the else loop with var  pzprm  and variable  s2z
    I'm in the else loop with var  s1xprm  and variable  s2z
    I'm in the else loop with var  s1yprm  and variable  s2z
    I'm in the else loop with var  s1zprm  and variable  s2z
    I'm in the else loop with var  s2xprm  and variable  s2z
    I'm in the else loop with var  s2yprm  and variable  s2z
    I'm in the == loop
    I'm in the else loop with var  xprm  and variable  s2z
    I'm in the else loop with var  yprm  and variable  s2z
    I'm in the else loop with var  zprm  and variable  s2z
    I'm in the else loop with var  pxprm  and variable  s2z
    I'm in the else loop with var  pyprm  and variable  s2z
    I'm in the else loop with var  pzprm  and variable  s2z
    I'm in the else loop with var  s1xprm  and variable  s2z
    I'm in the else loop with var  s1yprm  and variable  s2z
    I'm in the else loop with var  s1zprm  and variable  s2z
    I'm in the else loop with var  s2xprm  and variable  s2z
    I'm in the else loop with var  s2yprm  and variable  s2z
    I'm in the == loop
    I'm in the else loop with var  xprm  and variable  s2z
    I'm in the else loop with var  yprm  and variable  s2z
    I'm in the else loop with var  zprm  and variable  s2z
    I'm in the else loop with var  pxprm  and variable  s2z
    I'm in the else loop with var  pyprm  and variable  s2z
    I'm in the else loop with var  pzprm  and variable  s2z
    I'm in the else loop with var  s1xprm  and variable  s2z
    I'm in the else loop with var  s1yprm  and variable  s2z
    I'm in the else loop with var  s1zprm  and variable  s2z
    I'm in the else loop with var  s2xprm  and variable  s2z
    I'm in the else loop with var  s2yprm  and variable  s2z
    I'm in the == loop
    I'm in the else loop with var  xprm  and variable  s2z
    I'm in the else loop with var  yprm  and variable  s2z
    I'm in the else loop with var  zprm  and variable  s2z
    I'm in the else loop with var  pxprm  and variable  s2z
    I'm in the else loop with var  pyprm  and variable  s2z
    I'm in the else loop with var  pzprm  and variable  s2z
    I'm in the else loop with var  s1xprm  and variable  s2z
    I'm in the else loop with var  s1yprm  and variable  s2z
    I'm in the else loop with var  s1zprm  and variable  s2z
    I'm in the else loop with var  s2xprm  and variable  s2z
    I'm in the else loop with var  s2yprm  and variable  s2z
    I'm in the == loop
    I'm in the else loop with var  xprm  and variable  s2z
    I'm in the else loop with var  yprm  and variable  s2z
    I'm in the else loop with var  zprm  and variable  s2z
    I'm in the else loop with var  pxprm  and variable  s2z
    I'm in the else loop with var  pyprm  and variable  s2z
    I'm in the else loop with var  pzprm  and variable  s2z
    I'm in the else loop with var  s1xprm  and variable  s2z
    I'm in the else loop with var  s1yprm  and variable  s2z
    I'm in the else loop with var  s1zprm  and variable  s2z
    I'm in the else loop with var  s2xprm  and variable  s2z
    I'm in the else loop with var  s2yprm  and variable  s2z
    I'm in the == loop
    []
    []
    computing deriv with respect to  s2z
    I'm in the else loop with var  xprm  and variable  s2z
    I'm in the else loop with var  yprm  and variable  s2z
    I'm in the else loop with var  zprm  and variable  s2z
    I'm in the else loop with var  pxprm  and variable  s2z
    I'm in the else loop with var  pyprm  and variable  s2z
    I'm in the else loop with var  pzprm  and variable  s2z
    I'm in the else loop with var  s1xprm  and variable  s2z
    I'm in the else loop with var  s1yprm  and variable  s2z
    I'm in the else loop with var  s1zprm  and variable  s2z
    I'm in the else loop with var  s2xprm  and variable  s2z
    I'm in the else loop with var  s2yprm  and variable  s2z
    I'm in the == loop
    I'm in the else loop with var  xprm  and variable  s2z
    I'm in the else loop with var  yprm  and variable  s2z
    I'm in the else loop with var  zprm  and variable  s2z
    I'm in the else loop with var  pxprm  and variable  s2z
    I'm in the else loop with var  pyprm  and variable  s2z
    I'm in the else loop with var  pzprm  and variable  s2z
    I'm in the else loop with var  s1xprm  and variable  s2z
    I'm in the else loop with var  s1yprm  and variable  s2z
    I'm in the else loop with var  s1zprm  and variable  s2z
    I'm in the else loop with var  s2xprm  and variable  s2z
    I'm in the else loop with var  s2yprm  and variable  s2z
    I'm in the == loop
    I'm in the else loop with var  xprm  and variable  s2z
    I'm in the else loop with var  yprm  and variable  s2z
    I'm in the else loop with var  zprm  and variable  s2z
    I'm in the else loop with var  pxprm  and variable  s2z
    I'm in the else loop with var  pyprm  and variable  s2z
    I'm in the else loop with var  pzprm  and variable  s2z
    I'm in the else loop with var  s1xprm  and variable  s2z
    I'm in the else loop with var  s1yprm  and variable  s2z
    I'm in the else loop with var  s1zprm  and variable  s2z
    I'm in the else loop with var  s2xprm  and variable  s2z
    I'm in the else loop with var  s2yprm  and variable  s2z
    I'm in the == loop
    I'm in the else loop with var  xprm  and variable  s2z
    I'm in the else loop with var  yprm  and variable  s2z
    I'm in the else loop with var  zprm  and variable  s2z
    I'm in the else loop with var  pxprm  and variable  s2z
    I'm in the else loop with var  pyprm  and variable  s2z
    I'm in the else loop with var  pzprm  and variable  s2z
    I'm in the else loop with var  s1xprm  and variable  s2z
    I'm in the else loop with var  s1yprm  and variable  s2z
    I'm in the else loop with var  s1zprm  and variable  s2z
    I'm in the else loop with var  s2xprm  and variable  s2z
    I'm in the else loop with var  s2yprm  and variable  s2z
    I'm in the == loop
    I'm in the else loop with var  xprm  and variable  s2z
    I'm in the else loop with var  yprm  and variable  s2z
    I'm in the else loop with var  zprm  and variable  s2z
    I'm in the else loop with var  pxprm  and variable  s2z
    I'm in the else loop with var  pyprm  and variable  s2z
    I'm in the else loop with var  pzprm  and variable  s2z
    I'm in the else loop with var  s1xprm  and variable  s2z
    I'm in the else loop with var  s1yprm  and variable  s2z
    I'm in the else loop with var  s1zprm  and variable  s2z
    I'm in the else loop with var  s2xprm  and variable  s2z
    I'm in the else loop with var  s2yprm  and variable  s2z
    I'm in the == loop
    []
    []
    left-hand side is {'y': [], 's1z': [], 's2x': [], 'x': [], 's1y': [], 's2z': [], 'pz': [], 'z': [], 'px': [], 's2y': [], 's1x': [], 'py': []}
    right-hand side is {'y': [], 's1z': [], 's2x': [], 'x': [], 's1y': [], 's2z': [], 'pz': [], 'z': [], 'px': [], 's2y': [], 's1x': [], 'py': []}
    left-hand side is []
    right-hand side is []
    Old routine
    left-hand side is [tmppxprm]
    right-hand side is [1]

# Step 10: Output result \[Back to [top](#toc)\]
$$\label{step10}$$

We write the resulting derivatives in C code.

```python
for var in dynamic_variables:
    with open("dHreal_d"+str(var)+".txt", "w") as output:
        outstring = "/* SEOBNR Hamiltonian expression: */\n"
        outstringsp = ""
        outsplhs = []
        outsprhs = []
        for i in range(len(lr)):
            outstring += outputC(sp.sympify(lr[i].rhs),lr[i].lhs,"returnstring","outCverbose=False,includebraces=False,CSE_enable=False")
            outstringsp += lr[i].lhs+" = "+lr[i].rhs+"\n"
            outsplhs.append(sp.sympify(lr[i].lhs))
            outsprhs.append(sp.sympify(lr[i].rhs))
        outstring += "\n\n\n/* SEOBNR \partial_"+str(var)+" H expression: */\n"
#        for i in range(len(lhss_deriv_x)):
#            outstring += outputC(rhss_deriv_x[i],str(lhss_deriv_x[i]),"returnstring","outCverbose=False,includebraces=False,CSE_enable=False")
#            outstringsp += str(lhss_deriv_x[i])+" = "+str(rhss_deriv_x[i])+"\n"
#            outsplhs.append(lhss_deriv_x[i])
#            outsprhs.append(rhss_deriv_x[i])
        for i in range(len(lhss_derivative)):
            outstring += outputC(rhss_derivative[var][i],str(lhss_deriv_x[i]),"returnstring","outCverbose=False,includebraces=False,CSE_enable=False")
            outstringsp += str(lhss_deriv_x[i])+" = "+str(rhss_deriv_x[i])+"\n"
            outsplhs.append(lhss_deriv_x[i])
            outsprhs.append(rhss_deriv_x[i])
        output.write("%s" % outstring)
```

# Step 11: Code Validation against `SEOBNR_Derivative_Routine` NRPy+ module \[Back to [top](#toc)\]
$$\label{code_validation}$$

# Step 11: Output this notebook to $\LaTeX$-formatted PDF file \[Back to [top](#toc)\]
$$\label{latex_pdf_output}$$

The following code cell converts this Jupyter notebook into a proper, clickable $\LaTeX$-formatted PDF file. After the cell is successfully run, the generated PDF may be found in the root NRPy+ tutorial directory, with filename
[Tutorial-SEOBNR_Derivative_Routine.pdf](Tutorial-SEOBNR_Derivative_Routine.pdf) (Note that clicking on this link may not work; you may need to open the PDF file through another means.)

```python
import os,sys                    # Standard Python modules for multiplatform OS-level functions
nrpy_dir_path = os.path.join("..")
if nrpy_dir_path not in sys.path:
    sys.path.append(nrpy_dir_path)
import cmdline_helper as cmd    # NRPy+: Multi-platform Python command-line interface
cmd.output_Jupyter_notebook_to_LaTeXed_PDF("NRPyPN_shortcuts",location_of_template_file=os.path.join(".."))
```


# 变分量子本征求解器

<em> Copyright (c) 2021 Institute for Quantum Computing, Baidu Inc. All Rights Reserved. </em>

## 概览

目前普遍认为，量子计算在近期很有前景的一个应用是处理量子化学问题 [1-2]。**变分量子本征求解器** （VQE）作为这个研究方向的核心应用之一，为研究者们提供了可以在目前含噪的中等规模量子设备（NISQ device）上研究量子化学的可能 [1-4]。其核心任务是求解一个量子尺度上封闭物理系统的哈密顿量 $\hat{H}$ 的基态能量及其对应的量子态。主要的实现方法是通过在量子设备上准备一个参数化的试探波函数 $|\Psi(\boldsymbol\theta)\rangle$ 然后结合经典机器学习中的优化算法（例如梯度下降法）去不断地调整、优化参数 $\boldsymbol\theta$ 使得期望值  $\langle \Psi(\boldsymbol\theta)|\hat{H}|\Psi(\boldsymbol\theta)\rangle$ 最小化。这套方案的基本原理是基于 **Rayleigh-Ritz 变分原理**。

$$
E_0 = \min_{\boldsymbol\theta} \langle \Psi(\boldsymbol\theta)|\hat{H}|\Psi(\boldsymbol\theta)\rangle.
\tag{1}
$$

其中 $E_0$ 表示该系统的基态能量。从数值分析的角度来看，该问题可以被理解为求解一个**离散化**哈密顿量 $H$（厄米矩阵）的最小本征值 $\lambda_{\min}$ 和其对应的本征向量 $|\Psi_0\rangle$。具体的离散化过程是如何通过建立模型实现的，这属于量子化学的专业领域范畴。精确地解释该过程需要很长的篇幅，这超过了本教程所能处理的范围。我们会在下一节背景知识模块粗略的介绍一下相关知识，感兴趣的读者可以参考 `量子化学: 基本原理和从头计算法`系列丛书 [5]。通常来说，为了能在量子设备上处理量子化学问题，哈密顿量 $H$ 会被表示成为泡利算符 $\{X,Y,Z\}$ 的加权求和形式。

$$
H = \sum_k c_k ~ \bigg( \bigotimes_{j=0}^{M-1} \sigma_j^{(k)} \bigg),
\tag{2}
$$

其中 $c_k$ 表示权重系数, $\sigma_j^{(k)} \in \{I,X,Y,Z\}$ 并且 $M$ 表示所需的量子比特个数。这样一种哈密顿量的表示形式被称为 **泡利字符串**。以下为一个2量子比特的具体例子，

$$
H= 0.12~Y_0 \otimes I_1-0.04~X_0\otimes Z_1.
\tag{3}
$$

在下一节，我们会补充一些关于电子结构问题的背景知识。本质上讨论的就是上述哈密顿量 $H$ 究竟是从哪里来的。对于熟悉相关背景的读者，或者主要关心如何在量桨上实现 VQE 的读者，请直接跳转至第三节分析氢分子（$H_2$）基态的具体例子。

## 背景： 电子结构问题

这本小节，我们集中讨论下量子化学中的一个基本问题 -- **电子结构问题**。更准确的说，我们关心的是给定分子（molecule）的低位能量本征态。这些信息可以帮助我们预测化学反应的速率和分子的稳定结构等等 [6]。假设一个分子由 $N_n$ 个原子核和 $N_e$ 个电子组成，描述该分子系统总能量的哈密顿量算符 $\hat{H}_{mol}$ 在一次量子化表示下可以写为，

$$
\begin{align}
\hat{H}_{\text{mol}} & = -\sum_{i}\frac{\nabla_{R_i}^2}{2M_i} - \sum_{i} \frac{\nabla_{r_i}^2}{2} -\sum_{i,j}\frac{Z_i}{\lvert R_i - r_j\lvert} + \sum_{i,j>i}\frac{Z_iZ_j}{\lvert R_i - R_j\lvert} + \sum_{i, j>i}\frac{1}{\lvert r_i - r_j\lvert},
\tag{4}
\end{align}
$$

其中 $R_i、M_i$ 和 $Z_i$ 分别表示第 $i$ 个原子核的位置、质量和原子序数（原子核内质子数），第 $i$ 个电子的位置则表示为 $r_i$。以上公式右边前两项分别代表原子核和电子的总动能。第三项表示带正电的质子和带负电的电子之间的库伦相互吸引作用。最后两项则表示原子核-原子核之间，电子-电子之间的相互排斥作用。这里，分子哈密顿量 $\hat{H}_\text{mol}$ 使用的是原子单位制能量 **哈特里能量**（Hartree），记为 Ha。1哈特里能量的大小为 $[\hbar^2/(m_ee^2a_0^2)] = 27.2$ 电子伏或 630 千卡/摩尔，其中 $m_e、e$ 和 $a_0$ 分别表示电子质量、基本电荷和玻尔半径。

**注释1：** 在这个图景下，我们不考虑自旋-轨道耦合以及超精细结构。如果出于计算需要，可以作为微扰加入。

### 玻恩-奥本海默近似

由于一般原子核的质量要远大于电子，因而在同样的相互作用下电子的运动速度会比原子核快很多。所以，将原子核所处的位置看成固定 $R_i =$常数 是一种合理的近似。这种通过在时间尺度上将电子行为和原子核行为去耦合的近似处理思想被称为玻恩-奥本海默近似。作为近似的直接结果，公式（4）中原子核的动能项会被消去并且表示原子核-原子核相互排斥作用的项可以被认为是一个能量移位（这个项是与电子位置 $r_i$ 无关的）从而也可以作为常数项被忽略。经过这些步骤后，我们可以把哈密顿量近似为：

$$
\begin{align}
\hat{H}_{\text{electron}} & =  - \sum_{i} \frac{\nabla_{r_i}^2}{2} -\sum_{i,j}\frac{Z_i}{\lvert R_i - r_j\lvert} + \sum_{i, j>i}\frac{1}{\lvert r_i - r_j\lvert}
\tag{5},
\end{align}
$$

在经过以上近似后，分子中多电子结构的能级在理论上可以通过求解以下不含时薛定谔方程获得：

$$
\hat{H}_{\text{electron}} |\Psi_n \rangle = E_n |\Psi_n \rangle,
\tag{6}
$$

其中 $n$ 指代能级。值得注意的是，电子哈密顿量中电子-电子相互排斥作用的求和项数会随着电子数 $N_e$ 的增多至 $N_e(N_e-1)/2$ 项。这意味着对于一个含有16个电子的氧分子（$O_2$）我们需要计算多达120项的相互排斥作用项。 一般来说，这样的问题是无法从理论上精确求解的。正如狄拉克在 [Quantum mechanics of many-electron systems](https://royalsocietypublishing.org/doi/10.1098/rspa.1929.0094) [7] 所指出的那样，

> *The underlying physical laws necessary for the mathematical theory of a large part of physics and the whole of chemistry are thus completely known, and the difficulty is only that the exact application of these laws leads to equations much too complicated to be soluble.*
>
> -- Paul Dirac (1929)

既然解析的做法因为太复杂了不太可行，那么我们可以采用数值方法来处理。一个最简单的数值方法（离散化方法）就是把上述作用中无限维度希尔伯特空间离散化为等间距排开的立方体晶格点。在这样一个离散化的空间里，主要运算规则为复数域的线性代数。假设空间的每个轴都离散为等间距排开的 $k$ 个点，则 $N$-电子（为了方便去掉下标 $e$）的多体波函数可以写为 [2]：

$$
|\Psi \rangle = \sum_{\mathbf{x_1}, \ldots, \mathbf{x_N}} \psi(\mathbf{x_1}, \ldots, \mathbf{x_N}) \mathcal{A}(|\mathbf{x_1}, \ldots, \mathbf{x_N}\rangle).
\tag{7}
$$

其中坐标 $|\mathbf{x_j}\rangle = |r_j\rangle |\sigma_j\rangle$ 记录第 $j$ 个电子的空间位置信息和自旋，$|r_j\rangle  = |x_j,y_j,z_j\rangle$ 且 $j\in \{1,2,\cdots,N\}$, $x_j,y_j,z_j \in \{0,1,\cdots,k-1\}$ 同时 $\sigma_j \in \{\downarrow,\uparrow\}$ 表示自旋向下和向上。这样一种离散化方式共计需要 $k^{3N}\times 2^{N}$ 个数据来表示波函数。在这里，$\mathcal{A}$ 表示反对称化操作（出于泡利不相容原理）并且 $\psi(\mathbf{x_1}, \mathbf{x_2}, \ldots, \mathbf{x_N})=\langle\mathbf{x_1}, \mathbf{x_2}, \ldots, \mathbf{x_N}|\Psi\rangle$。 可以看出，经典计算机存储这样一个波函数需要的内存是随着电子个数呈指数增长的。这使得基于这种离散化的经典数值方法，无法模拟超过几十个电子的系统。那么，我们是不是能够通过量子设备来存储和准备这样一个波函数然后求解基态能量 $E_0$ 呢？在下一节中，我们将以最简单的分子系统 -- 氢分子（$H_2$）为例，讲解 VQE 算法。

**注释2：** 关于量子化学和现有数值计算方法的综述也超过了本教程的处理范围，我们推荐感兴趣的读者去查阅以下经典教材 Helgaker 等人撰写的 *'Molecular Electronic-Structure Theory'* [6] 以及 Szabo & Ostlund 撰写的 *'Modern Quantum Chemistry: Introduction to Advanced Electronic Structure Theory'* [8]。 如果需要弥补量子计算和量子化学之间知识空缺，请参考以下综述文章 [Quantum chemistry in the age of quantum computing](https://pubs.acs.org/doi/10.1021/acs.chemrev.8b00803) [1] 和  [Quantum computational chemistry](https://journals.aps.org/rmp/abstract/10.1103/RevModPhys.92.015003) [2] 。

**注释3：** 对于量子化学中的能量计算，我们期望能够达到 **化学精度**（chemical accuracy）$1.6\times10^{-3}$ Ha 或者 1 千卡/摩尔。

## 氢分子 $H_2$ 基态能量

### 构造电子哈密顿量

首先，让我们通过下面几行代码引入必要的 library 和 package。

```python
import os
import platform
import matplotlib.pyplot as plt
from IPython.display import clear_output

import numpy
from numpy import concatenate
from numpy import pi as PI
from numpy import savez, zeros

import paddle
from paddle_quantum.circuit import UAnsatz
from paddle_quantum.utils import pauli_str_to_matrix
from paddle_quantum.VQE.chemistrysub import H2_generator
```

对于具体需要分析的分子，我们需要其**几何构型** (geometry)、**基组**（basis set，例如 STO-3G 基于高斯函数）、**多重度**（multiplicity）以及**分子的净电荷数** (charge) 等多项信息来建模获取描述系统的哈密顿量。具体的，通过我们内置的量子化学工具包可以利用 fermion-to-qubit 映射的技术来输出目标分子的量子比特哈密顿量表示（泡利字符串）。

```python
Hamiltonian, N = H2_generator()
```

面向更高级的用户，我们这里提供一个简单的生成氢分子 (H2)哈密顿量的教程。先安装以下两个package (**仅Mac/Linux用户可使用，Windows用户暂时不支持**):

```python
!pip install openfermion
clear_output()
```

```python
!pip install openfermionpyscf
clear_output()
```

```python
# 操作系统信息
sysStr = platform.system()

# 判断操作系统
if sysStr in ('Linux', 'Darwin'):

    import openfermion
    import openfermionpyscf

    # 请检查是否正确下载了 h2 的几何构型文件
    geometry = 'h2.xyz'
    # geometry = [('H', (0.0, 0.0, 0.0)), ('H', (0.0, 0.0, 0.74))]
    basis = 'sto-3g'
    charge = 0
    multiplicity = 1

    # 生成哈密顿量
    molecular_hamiltonian = openfermionpyscf.generate_molecular_hamiltonian(geometry, basis, multiplicity, charge)
    qubit_op = openfermion.transforms.jordan_wigner(molecular_hamiltonian)

    # 打印结果
    print("The generated h2 Hamiltonian is \n", qubit_op)
```

    The generated h2 Hamiltonian is
     -0.042078976477822494 [] +
    -0.04475014401535163 [X0 X1 Y2 Y3] +
    0.04475014401535163 [X0 Y1 Y2 X3] +
    0.04475014401535163 [Y0 X1 X2 Y3] +
    -0.04475014401535163 [Y0 Y1 X2 X3] +
    0.17771287465139946 [Z0] +
    0.17059738328801055 [Z0 Z1] +
    0.12293305056183797 [Z0 Z2] +
    0.1676831945771896 [Z0 Z3] +
    0.17771287465139946 [Z1] +
    0.1676831945771896 [Z1 Z2] +
    0.12293305056183797 [Z1 Z3] +
    -0.24274280513140462 [Z2] +
    0.1762764080431959 [Z2 Z3] +
    -0.24274280513140462 [Z3]

**注释4：** 生成这个哈密顿量的几何构型中，两个氢原子间的原子间隔（interatomic distance）为 $d = 74$ pm。

除了氢分子 (H2) 之外, 我们也提供了氟化氢 (HF) 分子的几何构型文件 `hf.xyz`。如果你需要测试更多分子的几何构型，请移步至这个[数据库](http://smart.sns.it/molecules/index.html)。此外，我们还需要把这些本质上由泡利算符表示的哈密顿量转化成量桨支持的数据格式，这里我们提供这个接口。

```python
def Hamiltonian_str_convert(qubit_op):
    '''
    将上述提供的哈密顿量信息转为量桨支持的泡利字符串
    H = [[1.0, "z0,x1"], [-1.0, "y0,z1"], ...]
    '''
    info_dic = qubit_op.terms

    def process_tuple(tup):
        if len(tup) == 0:
            return 'i0'
        else:
            res = ''
            for ele in tup:
                res += ele[1].lower()
                res += str(ele[0])
                res += ','
            return res[:-1]
    H_info = []

    for key, value in qubit_op.terms.items():
        H_info.append([value.real, process_tuple(key)])

    return H_info

if sysStr in ('Linux', 'Darwin'):
    Hamiltonian = Hamiltonian_str_convert(qubit_op)
```

### 搭建量子神经网络（QNN）和试探波函数

在实现VQE的过程中，我们首先需要设计量子神经网络QNN（也可以理解为参数化量子电路）来准备试探波函数 $|\Psi(\boldsymbol\theta)\rangle$。这里，我们提供一个预设好的的深度为 $D$ 层的 4-量子比特的量子电路模板，图中的虚线框内为一层：

- 我们预设一些该参数化电路的参数，比如宽度为 $N = 4$ 量子位。

- 初始化其中的变量参数，${\bf{\theta }}$ 代表我们量子神经网络中的参数组成的向量。

接下来我们根据上图中的电路设计，通过 Paddle Quantum 的 `UAnsatz` 函数和内置的 `real_entangled_layer(theta, D)` 电路模板来高效搭建量子神经网络。

```python
def U_theta(theta, Hamiltonian, N, D):
    """
    Quantum Neural Network
    """

    # 按照量子比特数量/网络宽度初始化量子神经网络
    cir = UAnsatz(N)

    # 内置的 {R_y + CNOT} 电路模板
    cir.real_entangled_layer(theta[:D], D)

    # 铺上最后一列 R_y 旋转门
    for i in range(N):
        cir.ry(theta=theta[D][i][0], which_qubit=i)

    # 量子神经网络作用在默认的初始态 |0000>上
    cir.run_state_vector()

    # 计算给定哈密顿量的期望值
    expectation_val = cir.expecval(Hamiltonian)

    return expectation_val, cir
```

### 配置训练模型 - 损失函数

现在我们已经有了数据和量子神经网络的架构，我们将进一步定义训练参数、模型和损失函数。通过作用量子神经网络 $U(\theta)$ 在初始态 $|0..0\rangle$ 上，我们将得到输出态 $\left| {\psi \left( {\bf{\theta }} \right)} \right\rangle $。进一步，在VQE模型中的损失函数一般由量子态 $\left| {\psi \left( {\bf{\theta }} \right)} \right\rangle$ 关于哈密顿量 $H$ 的期望值 (能量期望值 expectation value) 给出，

$$
\min_{\boldsymbol\theta}  \mathcal{L}(\boldsymbol \theta) = \min_{\boldsymbol\theta} \langle \Psi(\boldsymbol\theta)|H |\Psi(\boldsymbol\theta)\rangle
= \min_{\boldsymbol\theta} \sum_k c_k~\langle \Psi(\boldsymbol\theta)| \bigotimes_j \sigma_j^{(k)}|\Psi(\boldsymbol\theta)\rangle.
\tag{8}
$$

```python
class StateNet(paddle.nn.Layer):
    """
    Construct the model net
    """

    def __init__(self, shape, dtype="float64"):
        super(StateNet, self).__init__()

        # 初始化 theta 参数列表，并用 [0, 2*pi] 的均匀分布来填充初始值
        self.theta = self.create_parameter(shape=shape,
                                           default_initializer=paddle.nn.initializer.Uniform(low=0.0, high=2*PI),
                                           dtype=dtype, is_bias=False)

    # 定义损失函数和前向传播机制
    def forward(self, N, D):

        # 计算损失函数/期望值
        loss, cir = U_theta(self.theta, Hamiltonian, N, D)

        return loss, cir
```

### 配置训练模型 - 模型参数

在进行量子神经网络的训练之前，我们还需要进行一些训练的超参数设置，主要是学习速率（LR, learning rate）、迭代次数（ITR, iteration）和量子神经网络计算模块的深度（D, Depth）。这里我们设定学习速率为 0.5, 迭代次数为 50 次。读者不妨自行调整来直观感受下超参数调整对训练效果的影响。

```python
ITR = 80  # 设置训练的总迭代次数
LR = 0.4   # 设置学习速率
D = 2      # 设置量子神经网络中重复计算模块的深度 Depth
```

### 进行训练

当训练模型的各项参数都设置完成后，我们将数据转化为 Paddle 中的张量，进而进行量子神经网络的训练。过程中我们用的是Adam Optimizer，也可以调用Paddle中提供的其他优化器。我们将训练过程中的结果存储在summary_data文件中。

```python
# 确定网络的参数维度
net = StateNet(shape=[D + 1, N, 1])

# 一般来说，我们利用Adam优化器来获得相对好的收敛，
# 当然你可以改成SGD或者是RMS prop.
opt = paddle.optimizer.Adam(learning_rate=LR, parameters=net.parameters())

# 记录优化结果
summary_iter, summary_loss = [], []

# 优化循环
for itr in range(1, ITR + 1):

    # 前向传播计算损失函数
    loss, cir = net(N, D)

    # 在动态图机制下，反向传播极小化损失函数
    loss.backward()
    opt.minimize(loss)
    opt.clear_grad()

    # 更新优化结果
    summary_loss.append(loss.numpy())
    summary_iter.append(itr)

    # 打印结果
    if itr % 20 == 0:
        print("iter:", itr, "loss:", "%.4f" % loss.numpy())
        print("iter:", itr, "Ground state energy:", "%.4f Ha"
                                            % loss.numpy())
    if itr == ITR:
        print("\n训练后的电路：")
        print(cir)

# 储存训练结果到 output 文件夹
os.makedirs("output", exist_ok=True)
savez("./output/summary_data", iter = summary_iter,
                               energy=summary_loss)
```

    iter: 20 loss: -0.9930
    iter: 20 Ground state energy: -0.9930 Ha
    iter: 40 loss: -1.1221
    iter: 40 Ground state energy: -1.1221 Ha
    iter: 60 loss: -1.1333
    iter: 60 Ground state energy: -1.1333 Ha
    iter: 80 loss: -1.1359
    iter: 80 Ground state energy: -1.1359 Ha

    训练后的电路：
    --Ry(4.717)----*--------------X----Ry(4.718)----*--------------X----Ry(-0.02)--
                   |              |                 |              |
    --Ry(4.733)----X----*---------|----Ry(4.486)----X----*---------|----Ry(4.828)--
                        |         |                      |         |
    --Ry(-3.25)---------X----*----|----Ry(4.729)---------X----*----|----Ry(-0.01)--
                             |    |                           |    |
    --Ry(-1.55)--------------X----*----Ry(4.704)--------------X----*----Ry(3.094)--

### 测试效果
我们现在已经完成了量子神经网络的训练，通过 VQE 得到的基态能量的估计值大致为 $E_0 \approx -1.136$ Ha，这与通过全价构型相互作用（FCI）$E_0 = -1.13618$ Ha 计算得出的值是在化学精度 $\varepsilon = 1.6 \times 10^{-3}$ Ha 内相符合的。

```python
result = numpy.load('./output/summary_data.npz')

eig_val, eig_state = numpy.linalg.eig(
                     pauli_str_to_matrix(Hamiltonian, N))
min_eig_H = numpy.min(eig_val.real)
min_loss = numpy.ones([len(result['iter'])]) * min_eig_H

plt.figure(1)
func1, = plt.plot(result['iter'], result['energy'],
                  alpha=0.7, marker='', linestyle="-", color='r')
func_min, = plt.plot(result['iter'], min_loss,
                  alpha=0.7, marker='', linestyle=":", color='b')
plt.xlabel('Number of iteration')
plt.ylabel('Energy (Ha)')

plt.legend(handles=[
    func1,
    func_min
],
    labels=[
        r'$\left\langle {\psi \left( {\theta } \right)} '
        r'\right|H\left| {\psi \left( {\theta } \right)} \right\rangle $',
        'Ground-state energy',
    ], loc='best')

#plt.savefig("vqe.png", bbox_inches='tight', dpi=300)
plt.show()
```

## 通过 VQE 确定原子间隔

还记得在前面的注释中提到我们默认使用的两个氢原子间原子间隔为 $74$ pm 吗？VQE 的另一个用法便是通过在不同的原子间隔下多次运行然后观察运行结果的最小值是在什么原子间隔发生的，这个间隔即为估计得真实原子间隔。

从上述过程中可以看出，最小值确实发生在 $d = 74$ pm (1 pm = $1\times 10^{-12}$m) 附近，这是与[实验测得数据](https://cccbdb.nist.gov/exp2x.asp?casno=1333740&charge=0)相符合的 $d_{exp} (H_2) = 74.14$ pm.

_______

## 参考文献

[1] Cao, Yudong, et al. Quantum Chemistry in the Age of Quantum Computing. [Chemical reviews 119.19 (2019): 10856-10915.](https://pubs.acs.org/doi/10.1021/acs.chemrev.8b00803)

[2] McArdle, Sam, et al. Quantum computational chemistry. [Reviews of Modern Physics 92.1 (2020): 015003.](https://journals.aps.org/rmp/abstract/10.1103/RevModPhys.92.015003)

[3] Peruzzo, A. et al. A variational eigenvalue solver on a photonic quantum processor. [Nat. Commun. 5, 4213 (2014).](https://www.nature.com/articles/ncomms5213)

[4] Moll, Nikolaj, et al. Quantum optimization using variational algorithms on near-term quantum devices. [Quantum Science and Technology 3.3 (2018): 030503.](https://iopscience.iop.org/article/10.1088/2058-9565/aab822)

[5] 徐光宪, 黎乐民, 王德民. 量子化学: 基本原理和从头计算法(上)[M], 第二版. 北京: 科学出版社, 2012;

[6] Helgaker, Trygve, Poul Jorgensen, and Jeppe Olsen. Molecular electronic-structure theory. John Wiley & Sons, 2014.

[7] Dirac, Paul Adrien Maurice. Quantum mechanics of many-electron systems. [Proceedings of the Royal Society of London. Series A, Containing Papers of a Mathematical and Physical Character 123.792 (1929): 714-733.](https://royalsocietypublishing.org/doi/10.1098/rspa.1929.0094)

[8] Szabo, Attila, and Neil S. Ostlund. Modern quantum chemistry: introduction to advanced electronic structure theory. Courier Corporation, 2012.