Metadata-Version: 2.1
Name: DQbee
Version: 0.1.5
Summary: DQode is a Python Library to compute the optimal inner-quadratic quadratization and dissipative quadratization of a given polynomial ODE system.
Home-page: 
Author: 
Author-email: 
Maintainer: 
Maintainer-email: 
License: MIT
Project-URL: Code, 
Project-URL: Issue tracker, 
Keywords: quadratization,differential equation,symbolic computing
Classifier: Operating System :: OS Independent
Classifier: Topic :: Text Processing :: Indexing
Classifier: Topic :: Utilities
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Classifier: License :: OSI Approved :: BSD License
Classifier: Programming Language :: Python
Classifier: Programming Language :: Python :: 3.8
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Requires-Python: >=3.8
Description-Content-Type: text/markdown
License-File: LICENSE

# Dissipative Quadratiation package

`DQbee` is a python package for computing the dissipative quadratization of polynomial ODE system. 

### Installation
```bash
pip install DQbee
```

Or you can download the package from local file:
```bash
cd filename_path #(example: cd /Users/yourname/Desktop/DQbee)
pip install .
```
We also provide `python` package in `tar.gz`` format:
```bash
cd filename_path/dist
pip install DQbee-0.1.5.tar.gz
```

## 1. Artifact Evaluation
We provide the artifact evaluation for the paper. Please check the `README.md` file in the `Example` folder [[here]](Examples/README.md)

## 2. Package Description
This python package is mainly used to compute the inner-quadratic quadratization and dissipative quadratization of multivariate high-dimensional polynomial ODE system. This algorithm also has tools to perform reachability analysis of the system. Here are some of the specific features of this package:

- Compute the inner-quadratic quadratization of polynomial ODE system.
- Compute the dissipative quadratization of polynomial ODE system at origin.
- Compute the dissipative quadratization of polynomial ODE system at an equilibrium point (input by the user), or at multiple equilibrium points (input by the user) with method `numpy`, `sympy`, or `Routh-Huritwz criterion`.
- Compute the weakly nonlinearity bound $\left| \mathcal{X_{0}} \right|$ of dissipative system.

## 3. Package Usage
We will demonstrate usage of Package on the example below.  **We recommend to run the package in IPython environment or Jupyter notebook in order to see the result display with $\LaTeX$**.

### 3.1. Importing the Package
```python
import sympy as sp
from DQbee.EquationSystem import *
from DQbee.DQuadratization import *
```

### 3.2. Polynomial ODE System Setting
We take the following duffing equation as an example:

$$
x'' = kx + ax^{3} + bx'
$$

which described damped oscillator with non-linear restoring force. The equation can be written as a first-order system by introducing $x_1 := x, x_2 := x'$ as follows

$$
\begin{cases}
    x_1' = x_2,\\
    x_2' = kx_1 + a x_1^3 + b x_2.
\end{cases}
$$

We can define the system as follows:
```python
x1, x2 = sp.symbols('x1 x2')
k, a, b = sp.symbols('k a b')

system = [
    sp.Eq(x1, x2),
    sp.Eq(x2, k*x1 + a*x1**3 + b*x2)
]

eq_system = EquationSystem(system) # This step transform the system into `EquationSystem` object
display_or_print(eq_system.show_system_latex()) # Display the system in latex format, inner method of `EquationSystem` object
```

### 3.3. Quadratization
In our package, we provide several quadratization functions to the `EquationSystem` object:
- `optimal_inner_quadratization`: compute the inner-quadratic quadratization of a given polynomial ODE system. *(Implementation of Algorithm 1 in the paper)*
- `optimal_dissipative_quadratization`: transform an inner-quadratic system into dissipative quadratization at origin, where the user can choose the value of the coefficients of the linear terms in order to make the system dissipative.
- `dquadratization_one_equilibrium`: compute the dissipative quadratization of a given polynomial ODE system at a given equilibrium point.
- `dquadratization_multi_equilibrium`: compute the dissipative quadratization of a given polynomial ODE system at multiple equilibrium points. *(Implementation of Algorithm 2 in the paper)*

```py
inner_result = optimal_inner_quadratization(eq_system,
                                            display=False) # Set `display` to True if you want to display the result
# Output:
oiq_system = inner_result[0]
sub_oiq_system = inner_result[1]
monomial_to_quadratic_form = inner_result[2] # This is only used for optimal_dissipative_quadratization` function
map_variables = inner_result[3]
```
Here, we will explain with these outputs. We show transformation from `oiq_system` to `sub_oiq_system` by substitution of variables:

$$
\begin{cases}
\left(x_1\right)^{\prime}=x_2 \\
\left(x_2\right)^{\prime}=a x_1^3+b x_2+k x_1 \\
\left(x_1^2\right)^{\prime}=2 x_1 x_2
\end{cases}
\xRightarrow{x_1^2 = w_1} 
\begin{cases}
\left(x_1\right)^{\prime} & =x_2 \\ 
\left(x_2\right)^{\prime} & =a w_1 x_1+b x_2+k x_1 \\ 
\left(w_1\right)^{\prime} & =2 x_1 x_2
\end{cases}
$$

where `map_variables` is the map from the original variables to the new variables. In this case, we have $w_{1}=x_{1}^{2}$. With all the information above, we can compute the dissipative quadratization of the system at origin as follows:
```py
dissipative_result = optimal_dissipative_quadratization(eq_system,
                                                        sub_oiq_system,
                                                        monomial_to_quadratic_form,
                                                        map_variables,
                                                        Input_diagonal=None, # the coefficients of the linear terms
                                                        display=False) 
```
The function will transfer all the linear terms in the ODE of introduced variables into quadratic terms, and keep negative linear terms in order to have a dissipative system *(by keep all diagonal terms of the matrix associated to linear part negative )*. If the `input_diagonal` is None, then the function will choose the largest eigenvalue of orginal system as the diagonal value. In our case, the output is as follows:

$$
\begin{cases}
\left(x_1\right)^{\prime} & =x_2 \\ 
\left(x_2\right)^{\prime} & =a w_1 x_1+b x_2+k x_1 \\ 
\left(w_1\right)^{\prime} & =w_1\left(\frac{b}{2}-\frac{\sqrt{b^2+4 k}}{2}\right)-x_1^2\left(\frac{b}{2}-\frac{\sqrt{b^2+4 k}}{2}\right)+2 x_1 x_2
\end{cases}
\xRightarrow{\text{matrix associated to linear part}} 
\left[\begin{array}{ccc}
0 & 1 & 0 \\
k & b & 0 \\
0 & 0 & \frac{b}{2}-\frac{\sqrt{b^2+4 k}}{2}
\end{array}\right]
$$

We take another example to show how to compute the dissipative quadratization with multiple given equilibrium point. We take the following system as an example:

$$
x' = -x (x - 1) (x - 2)
$$

where $a$ is positive. The system has three equilibrium points: $x_1 = 0, x_2 = 1, x_3 = 2$ but only dissipative at $x_1 = 0, 2$. We can define the system as follows:
```py
multistable_eq_system = EquationSystem([sp.Eq(x, - x * (x - 1) * (x - 2))])
```
Then we can compute the dissipative quadratization of the system at multiple equilibrium points as follows:
```py
result = dquadratization_multi_equilibrium(multistable_eq_system, 
                                           equilibrium = [[0],[2]],
                                           display=True,
                                           method='numpy' # or 'sympy' or 'Routh-Hurwitz'
                                        )
```
which will return the $\lambda$ and the dissipative quadratization of the system which make all the equilibrium points dissipative. In this case, the output is as follows:

$$
\left\{\begin{array}{l}
(x)^{\prime}=-g_1 x+3 x^2-2 x \\
\left(g_1\right)^{\prime}=-2 g_1^2+6 g_1 x-8 g_1+4 x^2
\end{array}\right.
$$

In this function, we provide three methods to compute the dissipative quadratization of the system at multiple equilibrium points:
- `numpy`: use `numpy.linalg.eigvals` to compute the eigenvalues of the Jacobian matrix of the system at equilibrium points, which is the fastest method.
- `sympy`: use `sympy.Matrix.eigenvals` to compute the eigenvalues of the Jacobian matrix of the system at equilibrium points.
- `Routh-Hurwitz`: use Routh-Hurwitz criterion to justify the stability of the system at equilibrium points.
