# Installation

The following instructions were prepared using

```julia
versioninfo()
```

    Julia Version 1.5.2
    Commit 539f3ce943 (2020-09-23 23:17 UTC)
    Platform Info:
      OS: Linux (x86_64-pc-linux-gnu)
      CPU: Intel(R) Core(TM) i9-9900X CPU @ 3.50GHz
      WORD_SIZE: 64
      LIBM: libopenlibm
      LLVM: libLLVM-9.0.1 (ORCJIT, skylake-avx512)
    Environment:
      JULIA_NUM_THREADS = 4

Before exploring the notebook you need to clone the main repository:
```bash
 git clone https://github.com/kalmarek/1812.03456.git
```
This notebook should be located in `1812.03456/notebooks` directory.

In the main directory (`1812.03456`) you should run the following code in `julia`s `REPL` console to instantiate the environment for computations:
```julia
using Pkg
Pkg.activate(".")
Pkg.instantiate()
```
(this needs to be done once per installation).

Instantiation should install (among others): the [`SCS` solver][1], [`JuMP` package][2] for mathematical programming and `IntervalArithmetic.jl` package from [`ValidatedNumerics.jl`][3].

The environment uses [`Groups.jl`][7], [`GroupRings.jl`][6] (which are built on the framework of  [`AbstractAlgebra.jl`][4]) and [`PropertyT.jl`][8] packages.

[1]: https://github.com/cvxgrp/scs
[2]: https://github.com/JuliaOpt/JuMP.jl
[3]: https://github.com/JuliaIntervals/ValidatedNumerics.jl
[4]: https://github.com/Nemocas/AbstractAlgebra.jl
[5]: https://github.com/Nemocas/Nemo.jl
[6]: https://github.com/kalmarek/GroupRings.jl
[7]: https://github.com/kalmarek/Groups.jl
[8]: https://github.com/kalmarek/PropertyT.jl

A jupyter server may be launched then within the directory `1812.03456` by issuing from julia command-line (`REPL`) the following commands.
```julia
using Pkg
Pkg.activate(".")
using IJulia
notebook(dir=".")

```
During the first run the user may be asked for installation of `Jupyter` program (a server for running this notebook) within `miniconda` environment, which will happen automatically after confirmation. To execute the commands in the notebook, one needs to navigate to `notebooks` subdirectory of `1812.03456` and click either of the notebooks.

> Code "cells" have a label, e.g. `In [1]:` on their left margin. Click somewhere in the proximity of the label to select a cell. The selected cell is _run_ by either clicking the `Run` button in the top toolbar, or by pressing `Shift`+`Enter`.

# The computation

The following notebook uses the precomputed solutions to certify that

$$\operatorname{Adj}_5 + 2\operatorname{Op}_5 - 0.28\Delta_5 \simeq \Sigma_i \xi_i^*\xi_i \in \Sigma^2_2 I\operatorname{SAut}(F_5),$$

and that

$$\operatorname{Adj}_5 + 3\operatorname{Op}_5 - 1.4 \Delta_5 \simeq \Sigma_i \xi_i^*\xi_i \in \Sigma^2_2 I\operatorname{SAut}(F_5),$$

where $\simeq \Sigma_i \xi_i^*\xi_i$ means "admits approximate sum of squares decomposition" in the language of [arXiv:1812.03456](https://arxiv.org/abs/1812.03456).

These are the computations upon the main results of [arXiv:1812.03456](https://arxiv.org/abs/1812.03456) depend.
Additionaly, one may execute the whole program (including the optimization) proving that

$$\operatorname{Adj}_4 + 100 \mathrm{Op}_4 - 0.1\Delta_4 \simeq \Sigma_i \xi_i^*\xi_i \in \Sigma^2_2 I\operatorname{SAut}(F_4).$$

This result shows that almost all groups $\operatorname{SAut}(F_n)$ have property (T). While the constants in the result are by no means optimal, is should be achievable fairly quickly (at most an hour) on a standard laptop computer.

```julia
using Pkg
Pkg.activate("..")
using Dates
now()
```

     Activating environment at `~/1812.03456/Project.toml`

    2020-10-21T13:39:54.894

```julia
using SparseArrays
import LinearAlgebra: norm
using AbstractAlgebra

using Groups
using GroupRings
using PropertyT

using PropertyT.JLD

using PropertyT.IntervalArithmetic
IntervalArithmetic.setrounding(Interval, :tight)
IntervalArithmetic.setformat(:standard, sigfigs=6);
```

So far we only made the needed packages available in the notebook. You need to dowload `SAutF5_r2.tar.xz` file from zenodo.org (`doi:10.5281/zenodo.4118043`) and unpack it in the `1812.03456` directory. In the next cell we define the directory where the precomputed solutions should reside and check that required files are in place.

```julia
const N = 5
const prefix = abspath(joinpath(@__DIR__,  ".." , "SAutF$(N)_r2"))
isdir(prefix) || @error "You need to place the precomputed solutions downloaded from zenodo in \n $prefix"

const DELTA_FILE = joinpath(prefix,"delta.jld");
const SQADJOP_FILE = joinpath(prefix, "SqAdjOp_coeffs.jld");
const BLOCKDEC_FILE = joinpath(prefix, "BlockDecomposition.jld");

if !(isfile(DELTA_FILE) && isfile(SQADJOP_FILE) && isfile(BLOCKDEC_FILE))
    @error "The directory structure must be preserved exactly as in the archive downloaded from zenodo:
    $prefix \n\t $DELTA_FILE \n\t $SQADJOP_FILE \n\t $ORBITDATA_FILE
    must exist!
    "
end
```

Below we define a simple function which takes a group ring element `eoi` and a matrix `Q` and computes the the sum of squares `sos` group ring element which `Q` represents (in the parent group ring of `eoi`) and returns the difference `eoi - sos`. This function will be used to compare target elements with the ones obtained through semi-definite optimization.

```julia
function SOS_residual(eoi::GroupRingElem, Q::AbstractMatrix)
    RG = parent(eoi)
    @time sos = PropertyT.compute_SOS(RG, Q);
    return eoi - sos
end
```

    SOS_residual (generic function with 1 method)

## Loading the precomputed group ring elements
Below we load $\Delta$, the group Laplacian for $\operatorname{SAut}(F_5)$, vectors of coefficients defining elements $\operatorname{Sq}_5$, $\operatorname{Adj}_5$ and $\operatorname{Op}_5$ and turn these into data structures `GroupRingElem` which represent group ring elements.

Note that the vectors of coefficients only have meaning with respect to the particular basis which was used for computations. The basis is not saved and loaded due to space concerns. It can be re-computed using
```julia
let basis, sizes = Groups.generate_balls(gens(G), one(G), radius=4)
    @assert sizes[2] == size(RG.pm, 1) == size(RG.pm, 2)
    RG.basis, RG.basis_dict = basis, GroupRings.reverse_dict(basis)
end
```

```julia
G = SAut(FreeGroup(N))
Δ = PropertyT.loadGRElem(DELTA_FILE, G)
RG = parent(Δ)
block_decomposition = let od = load(BLOCKDEC_FILE, "BlockDecomposition")
    block_decomposition = PropertyT.decimate(od, false) # sparsification of projection matrices
end
Sq, Adj, Op = let (sq_c, adj_c, op_c) = load(SQADJOP_FILE, "Sq", "Adj", "Op")
    sq = GroupRingElem(sq_c, RG)
    adj = GroupRingElem(adj_c, RG)
    op = GroupRingElem(op_c, RG)
    sq, adj, op
end;
```

## Replicating $\operatorname{Adj}_5 + 2\operatorname{Op}_5 - 0.28\Delta_5 \in \Sigma^2_2 ISAut(F_5)$

Let us define: $\lambda = 0.28$ and $k=2$ and check that precomputed solution file is in place:

```julia
const λ = 0.28
const k = 2.0

const fullpath = joinpath(prefix, "$(λ)_K=$k")
const SOLUTION_FILE = joinpath(fullpath, "solution.jld")

if !(isdir(fullpath) && isfile(SOLUTION_FILE))
    @error "Couldn't find the precomputed solution: \n\t$SOLUTION_FILE"
end
```

Let us finally define the element of interest (we don't show it by default by placing `;` at the end of line):

```julia
elt = Adj + k*Op;
```

`Q` loaded below is the matrix whose columns represent the elements $\xi_i \in \mathbb{R}\operatorname{SAut}(F_5)$ such that
$$
\operatorname{Adj}_5 + 2\operatorname{Op}_5 - 0.28 \Delta_5 - \sum_i \xi_i^* \xi_i = b,
$$
where $\|b\|_1$ is sufficiently small with respect to $\lambda$ (i.e. `Q` represents _approximate sum of squares_ in the language of [arXiv:1812.03456](https://arxiv.org/abs/1812.03456).

```julia
Q = load(SOLUTION_FILE, "Q")
```

    4641×4641 Array{Float64,2}:
      2.97397     -0.244942     -0.244942     …   0.0158543     0.0131965
     -0.244942     7.72331      -0.311095         0.000722162  -0.000870519
     -0.244942    -0.311095      7.72331         -0.00516345   -0.000870519
     -0.244942    -0.311095     -0.311095        -0.00615118   -0.00498285
     -0.244942    -0.311095     -0.311095         0.000245145  -0.00112319
     -0.244942    -0.00261826   -0.136534     …   0.000722162  -0.000870519
     -0.244942    -0.136534     -0.161489        -0.00516345   -0.000870519
     -0.244942    -0.136534      0.0399134       -0.00615118   -0.00498285
     -0.244942    -0.136534      0.0399134        0.000245145  -0.00112319
     -0.244942    -0.136534     -0.00261826      -0.00153488   -0.000870519
     -0.244942    -0.161489     -0.136534     …  -0.00153488   -0.000870519
     -0.244942     0.0399134    -0.136534        -0.0101051    -0.00498285
     -0.244942     0.0399134    -0.136534        -0.00738246   -0.00112319
      ⋮                                       ⋱                 ⋮
     -0.00908463   0.000179479   0.000179479     -0.00166578    0.00250892
     -0.012501     0.00848923    0.00848923   …   0.0145313    -0.00325656
     -0.012501    -0.00724905   -0.000773334      0.0145313    -0.00325656
     -0.012501    -0.000773334  -0.00724905      -0.0802158    -0.00325656
     -0.00747264   0.00418861    0.00418861      -0.00592741    0.0013943
     -0.00747264  -0.00159755    0.00234181      -0.00592741    0.0013943
     -0.00747264   0.00234181   -0.00159755   …   0.0254635     0.0013943
     -0.0117098   -2.82897e-5   -2.82897e-5      -0.00196401   -0.0401892
      0.0158545   -0.00153483   -0.00153483      -0.00165852   -0.00797284
      0.0158545   -0.00516343    0.000722191     -0.00165852   -0.00797284
      0.0158545    0.000722191  -0.00516343       0.40492      -0.00797284
      0.0131965   -0.000870492  -0.000870492  …  -0.00797307    0.135697

Below we compute the residual $b$. As we do it in floating-point arithmetic, the result can't be taken too seriously.

```julia
let EOI = elt - λ*Δ
    residual = SOS_residual(EOI, Q)
    @info "In floating point arithmetic the ℓ₁-norm of the residual" norm(residual, 1);
end
```

     28.313046 seconds (245.26 k allocations: 270.780 MiB)

    ┌ Info: In floating point arithmetic the ℓ₁-norm of the residual
    │   norm(residual, 1) = 9.173410298989073e-5
    └ @ Main In[10]:3

Therefore we resort to interval arithmetic to provide certified upper and lower bounds on the norm of the residual:
* We first change entries of `Q` to narrow intervals,
* We project columns of `Q` so that $0$ is in the sum of coefficients of each column (i.e. $\xi_i \in I \operatorname{SAut}(F_5)$),
* We compute the sum of squares and the $\ell_1$-norm of the residual in the interval arithmetic.

The returned `check_columns_augmentation` is a boolean flag to detect if the projection was successful, i.e. if we can guarantee that each column of `Q_aug` can be represented by an element from the augmentation ideal. (If it were not successful, one may project `Q = PropertyT.augIdproj(Q)` in the floating point arithmetic prior to the cell below).

```julia
Q_aug, check_columns_augmentation = PropertyT.augIdproj(Interval, Q);
@assert check_columns_augmentation
Q_aug
```

    4641×4641 Array{Interval{Float64},2}:
      [2.97397, 2.97398]         …   [0.0131964, 0.0131965]
     [-0.244942, -0.244941]         [-0.000870514, -0.000870513]
     [-0.244942, -0.244941]         [-0.000870514, -0.000870513]
     [-0.244942, -0.244941]         [-0.00498285, -0.00498284]
     [-0.244942, -0.244941]         [-0.00112319, -0.00112318]
     [-0.244942, -0.244941]      …  [-0.000870514, -0.000870513]
     [-0.244942, -0.244941]         [-0.000870514, -0.000870513]
     [-0.244942, -0.244941]         [-0.00498285, -0.00498284]
     [-0.244942, -0.244941]         [-0.00112319, -0.00112318]
     [-0.244942, -0.244941]         [-0.000870514, -0.000870513]
     [-0.244942, -0.244941]      …  [-0.000870514, -0.000870513]
     [-0.244942, -0.244941]         [-0.00498285, -0.00498284]
     [-0.244942, -0.244941]         [-0.00112319, -0.00112318]
       ⋮                         ⋱    ⋮
     [-0.00908475, -0.00908474]      [0.00250892, 0.00250893]
     [-0.0125012, -0.0125011]    …  [-0.00325656, -0.00325655]
     [-0.0125012, -0.0125011]       [-0.00325656, -0.00325655]
     [-0.0125012, -0.0125011]       [-0.00325656, -0.00325655]
     [-0.00747276, -0.00747275]      [0.0013943, 0.00139431]
     [-0.00747276, -0.00747275]      [0.0013943, 0.00139431]
     [-0.00747276, -0.00747275]  …   [0.0013943, 0.00139431]
     [-0.0117099, -0.0117098]       [-0.0401893, -0.0401892]
      [0.0158543, 0.0158544]        [-0.00797284, -0.00797283]
      [0.0158543, 0.0158544]        [-0.00797284, -0.00797283]
      [0.0158543, 0.0158544]        [-0.00797284, -0.00797283]
      [0.0131964, 0.0131965]     …   [0.135696, 0.135697]

We now create the element of interest, $\operatorname{Adj}_5 + 2\operatorname{Op}_5 - 0.28 \Delta_5$ with coefficients in real intervals. Note that only $\lambda$ is turned into a non-exact interval, and except the support of $\Delta$ (the first `49` elements) all coefficients are honest integers.

```julia
elt_int = elt - @interval(λ)*Δ;
elt_int.coeffs
```

    11154301-element SparseVector{Interval{Float64},Int64} with 4161 stored entries:
      [1       ]  =  [7657.59, 7657.61]
      [2       ]  =  [-191.721, -191.719]
      [3       ]  =  [-191.721, -191.719]
      [4       ]  =  [-191.721, -191.719]
      [5       ]  =  [-191.721, -191.719]
      [6       ]  =  [-191.721, -191.719]
      [7       ]  =  [-191.721, -191.719]
      [8       ]  =  [-191.721, -191.719]
      [9       ]  =  [-191.721, -191.719]
      [10      ]  =  [-191.721, -191.719]
                  ⋮
      [4628    ]  =  [1, 1]
      [4629    ]  =  [1, 1]
      [4631    ]  =  [1, 1]
      [4632    ]  =  [1, 1]
      [4633    ]  =  [1, 1]
      [4634    ]  =  [1, 1]
      [4635    ]  =  [1, 1]
      [4636    ]  =  [1, 1]
      [4638    ]  =  [1, 1]
      [4639    ]  =  [1, 1]
      [4640    ]  =  [1, 1]

Finally we compute the $\ell_1$ norm of the residual with interval arithmetic. The result is **guaranteed** to be contained in the resulting interval, i.e. if each entry of `Q` were changed into an honest rational number and all the computations were carried out in rational arithmetic, the rational $\ell_1$-norm will be contained in the interval $\ell_1$-norm.

```julia
residual_int = SOS_residual(elt_int, Q_aug)
@show norm(residual_int, 1);
```

    953.889613 seconds (520.88 k allocations: 529.781 MiB, 0.00% gc time)
    norm(residual_int, 1) = [0.000228394, 0.000228496]

Using Lemma 4.10 of [arXiv:1812.03456](https://arxiv.org/abs/1812.03456) and the fact that none of the generating transvections of $\operatorname{SAut}(F_N)$ is involutive we obtain

```julia
λ_cert = @interval(λ) - 2*norm(residual_int,1)
@info "λ is certified to be > " λ_cert.lo
@info "i.e Adj_$N + $k·Op_$N - ($(λ_cert.lo))·Δ_$N ∈ Σ²₂ ISAut(F_$N)"
```

    ┌ Info: λ is certified to be >
    │   λ_cert.lo = 0.2795430082668905
    └ @ Main In[14]:2
    ┌ Info: i.e Adj_5 + 2.0·Op_5 - (0.2795430082668905)·Δ_5 ∈ Σ²₂ ISAut(F_5)
    └ @ Main In[14]:3

## Replicating $\operatorname{Adj}_5 + 3\operatorname{Op}_5 - 1.4\Delta_5 \in \Sigma^2_2 ISAut(F_5)$

```julia
const λ = 1.4
const k = 3.0

const fullpath = joinpath(prefix, "$(λ)_K=$k")
const SOLUTION_FILE = joinpath(fullpath, "solution.jld")

if !(isdir(fullpath) && isfile(SOLUTION_FILE))
    @error "Couldn't find the precomputed solution: \n\t$SOLUTION_FILE"
end
```

```julia
elt = Adj + k*Op;
Q = load(SOLUTION_FILE, "Q");
Q_aug, check_columns_augmentation = PropertyT.augIdproj(Interval, Q);
@assert check_columns_augmentation
```

```julia
elt_int = elt - @interval(λ)*Δ;
residual_int = SOS_residual(elt_int, Q_aug)
@show norm(residual_int, 1);
```

    953.420002 seconds (113.01 k allocations: 512.971 MiB, 0.05% gc time)
    norm(residual_int, 1) = [0.0149432, 0.0149435]

```julia
λ_cert = @interval(λ) - 2*norm(residual_int,1)
@info "λ is certified to be > " λ_cert.lo
@info "i.e Adj_$N + $k·Op_$N - ($(λ_cert.lo))·Δ_$N ∈ Σ²₂ ISAut(F_$N)"
```

    ┌ Info: λ is certified to be >
    │   λ_cert.lo = 1.3701131734136716
    └ @ Main In[18]:2
    ┌ Info: i.e Adj_5 + 3.0·Op_5 - (1.3701131734136716)·Δ_5 ∈ Σ²₂ ISAut(F_5)
    └ @ Main In[18]:3

## Confirming that $\operatorname{Adj}_4 + 100.0\operatorname{Op}_4 - 0.1\Delta_4$ admits approximate sum of squares decomposition

```julia
const λ = 0.1
const k = 100.0
```

1 0 0 . 0

Now we will generate the ball $B_R$ of radius $R=4$ in $\operatorname{SAut}(F_4)$, and use it as a (partial) basis of a group ring. Such a group ring also needs a (partial) multiplication table to square elements supported on radius $2$ (it is called `pm`, which is actually a "division table" due to `twisted=true` argument). The table is created as follows: when $x$,$y$ reside at positions `i` and `j` in $B_R$, then `pm[i,j] = k`, where `k` is the position of $x^{-1}y$ in $B_R$.

Then we create the Laplace operator $\Delta$.

```julia
SAutF₄ = SAut(FreeGroup(4))
Δ₄ = let G = SAutF₄, halfradius = 2

    S = gens(G)
    S = [S; inv.(S)] # generating set must be symmetric

    B_R, sizes = Groups.wlmetric_ball(S, radius=2*halfradius);
    B_rdict = GroupRings.reverse_dict(B_R)
    pm = GroupRings.create_pm(B_R, B_rdict, sizes[halfradius]; twisted=true);
    RG = GroupRing(G, B_R, B_rdict, pm)
    @show sizes;
    Δ = length(S)*one(RG) - sum(RG(s) for s in S)
end
```

    sizes = [49, 1777, 57725, 1777541]

    48(id) - 1ϱ₁₂ - 1ϱ₁₃ - 1ϱ₁₄ - 1ϱ₂₁ - 1ϱ₂₃ - 1ϱ₂₄ - 1ϱ₃₁ - 1ϱ₃₂ - 1ϱ₃₄ - 1ϱ₄₁ - 1ϱ₄₂ - 1ϱ₄₃ - 1λ₁₂ - 1λ₁₃ - 1λ₁₄ - 1λ₂₁ - 1λ₂₃ - 1λ₂₄ - 1λ₃₁ - 1λ₃₂ - 1λ₃₄ - 1λ₄₁ - 1λ₄₂ - 1λ₄₃ - 1ϱ₁₂^-1 - 1ϱ₁₃^-1 - 1ϱ₁₄^-1 - 1ϱ₂₁^-1 - 1ϱ₂₃^-1 - 1ϱ₂₄^-1 - 1ϱ₃₁^-1 - 1ϱ₃₂^-1 - 1ϱ₃₄^-1 - 1ϱ₄₁^-1 - 1ϱ₄₂^-1 - 1ϱ₄₃^-1 - 1λ₁₂^-1 - 1λ₁₃^-1 - 1λ₁₄^-1 - 1λ₂₁^-1 - 1λ₂₃^-1 - 1λ₂₄^-1 - 1λ₃₁^-1 - 1λ₃₂^-1 - 1λ₃₄^-1 - 1λ₄₁^-1 - 1λ₄₂^-1 - 1λ₄₃^-1

In the cell below we compute Wedderburn-Artin decomposition of `pm` with respect to the action of the Weyl group ($S_2 \wr S_4$) and sparsify it numerically.

```julia
block_decomposition = let od = PropertyT.BlockDecomposition(parent(Δ₄), WreathProduct(SymmetricGroup(2), SymmetricGroup(4)))
    PropertyT.decimate(od, false);
end;
```

    ┌ Info: Decomposing basis of RG into orbits of
    │   autS = Wreath Product of Full symmetric group over 2 elements by Full symmetric group over 4 elements
    └ @ PropertyT /home/kalmar/.julia/packages/PropertyT/vcGsE/src/blockdecomposition.jl:15

     48.762163 seconds (1.11 G allocations: 76.049 GiB, 37.93% gc time)

    ┌ Info: The action has 6231 orbits
    └ @ PropertyT /home/kalmar/.julia/packages/PropertyT/vcGsE/src/blockdecomposition.jl:18
    ┌ Info: Finding projections in the Group Ring of
    │   autS = Wreath Product of Full symmetric group over 2 elements by Full symmetric group over 4 elements
    └ @ PropertyT /home/kalmar/.julia/packages/PropertyT/vcGsE/src/blockdecomposition.jl:20

      4.558152 seconds (6.03 M allocations: 308.531 MiB, 15.56% gc time)

    ┌ Info: Finding AutS-action matrix representation
    └ @ PropertyT /home/kalmar/.julia/packages/PropertyT/vcGsE/src/blockdecomposition.jl:23

     11.694259 seconds (291.32 M allocations: 19.976 GiB, 34.16% gc time)
      0.392333 seconds (1.13 M allocations: 120.585 MiB)

    ┌ Info: Computing the projection matrices Uπs
    └ @ PropertyT /home/kalmar/.julia/packages/PropertyT/vcGsE/src/blockdecomposition.jl:27

     31.218765 seconds (1.29 M allocations: 8.241 GiB, 2.36% gc time)

    ┌ Info:
    │ multiplicities  =   6  27  38  23  18  22  56  34  22  23  27  32   9  17   8   1   1   1   2   1
    │     dimensions  =   1   3   3   2   1   4   8   4   6   6   6   6   4   8   4   1   3   3   2   1
    └ @ PropertyT /home/kalmar/.julia/packages/PropertyT/vcGsE/src/blockdecomposition.jl:37

```julia
@time Adj₄ = PropertyT.Adj(parent(Δ₄), 4)
@time Op₄ = PropertyT.Op(parent(Δ₄), 4)

elt₄ = Adj₄ + k*Op₄
```

      7.023643 seconds (1.36 M allocations: 71.502 MiB)
      1.688224 seconds (190.03 k allocations: 10.537 MiB)

    39936(id) - 1664ϱ₁₂ - 1664ϱ₁₃ - 1664ϱ₁₄ - 1664ϱ₂₁ - 1664ϱ₂₃ - 1664ϱ₂₄ - 1664ϱ₃₁ - 1664ϱ₃₂ - 1664ϱ₃₄ - 1664ϱ₄₁ - 1664ϱ₄₂ - 1664ϱ₄₃ - 1664λ₁₂ - 1664λ₁₃ - 1664λ₁₄ - 1664λ₂₁ - 1664λ₂₃ - 1664λ₂₄ - 1664λ₃₁ - 1664λ₃₂ - 1664λ₃₄ - 1664λ₄₁ - 1664λ₄₂ - 1664λ₄₃ - 1664ϱ₁₂^-1 - 1664ϱ₁₃^-1 - 1664ϱ₁₄^-1 - 1664ϱ₂₁^-1 - 1664ϱ₂₃^-1 - 1664ϱ₂₄^-1 - 1664ϱ₃₁^-1 - 1664ϱ₃₂^-1 - 1664ϱ₃₄^-1 - 1664ϱ₄₁^-1 - 1664ϱ₄₂^-1 - 1664ϱ₄₃^-1 - 1664λ₁₂^-1 - 1664λ₁₃^-1 - 1664λ₁₄^-1 - 1664λ₂₁^-1 - 1664λ₂₃^-1 - 1664λ₂₄^-1 - 1664λ₃₁^-1 - 1664λ₃₂^-1 - 1664λ₃₄^-1 - 1664λ₄₁^-1 - 1664λ₄₂^-1 - 1664λ₄₃^-1 + ϱ₁₂*ϱ₁₃ + ϱ₁₂*ϱ₁₄ + ϱ₁₂*ϱ₂₃ + ϱ₁₂*ϱ₂₄ + ϱ₁₂*ϱ₃₁ + 2ϱ₁₂*ϱ₃₂ + 200ϱ₁₂*ϱ₃₄ + ϱ₁₂*ϱ₄₁ + 2ϱ₁₂*ϱ₄₂ + 200ϱ₁₂*ϱ₄₃ + 2ϱ₁₂*λ₁₃ + 2ϱ₁₂*λ₁₄ + ϱ₁₂*λ₂₃ + ϱ₁₂*λ₂₄ + ϱ₁₂*λ₃₁ + 2ϱ₁₂*λ₃₂ + 200ϱ₁₂*λ₃₄ + ϱ₁₂*λ₄₁ + 2ϱ₁₂*λ₄₂ + 200ϱ₁₂*λ₄₃ + ϱ₁₂*ϱ₁₃^-1 + ϱ₁₂*ϱ₁₄^-1 + ϱ₁₂*ϱ₂₃^-1 + ϱ₁₂*ϱ₂₄^-1 + ϱ₁₂*ϱ₃₁^-1 + 2ϱ₁₂*ϱ₃₂^-1 + 200ϱ₁₂*ϱ₃₄^-1 + ϱ₁₂*ϱ₄₁^-1 + 2ϱ₁₂*ϱ₄₂^-1 + 200ϱ₁₂*ϱ₄₃^-1 + 2ϱ₁₂*λ₁₃^-1 + 2ϱ₁₂*λ₁₄^-1 + ϱ₁₂*λ₂₃^-1 + ϱ₁₂*λ₂₄^-1 + ϱ₁₂*λ₃₁^-1 + 2ϱ₁₂*λ₃₂^-1 + 200ϱ₁₂*λ₃₄^-1 + ϱ₁₂*λ₄₁^-1 + 2ϱ₁₂*λ₄₂^-1 + 200ϱ₁₂*λ₄₃^-1 + ϱ₁₃*ϱ₁₂ + ϱ₁₃*ϱ₁₄ + ϱ₁₃*ϱ₂₁ + 2ϱ₁₃*ϱ₂₃ + 200ϱ₁₃*ϱ₂₄ + ϱ₁₃*ϱ₃₂ + ϱ₁₃*ϱ₃₄ + ϱ₁₃*ϱ₄₁ + 200ϱ₁₃*ϱ₄₂ + 2ϱ₁₃*ϱ₄₃ + 2ϱ₁₃*λ₁₂ + 2ϱ₁₃*λ₁₄ + ϱ₁₃*λ₂₁ + 2ϱ₁₃*λ₂₃ + 200ϱ₁₃*λ₂₄ + ϱ₁₃*λ₃₂ + ϱ₁₃*λ₃₄ + ϱ₁₃*λ₄₁ + 200ϱ₁₃*λ₄₂ + 2ϱ₁₃*λ₄₃ + ϱ₁₃*ϱ₁₂^-1 + ϱ₁₃*ϱ₁₄^-1 + ϱ₁₃*ϱ₂₁^-1 + 2ϱ₁₃*ϱ₂₃^-1 + 200ϱ₁₃*ϱ₂₄^-1 + ϱ₁₃*ϱ₃₂^-1 + ϱ₁₃*ϱ₃₄^-1 + ϱ₁₃*ϱ₄₁^-1 + 200ϱ₁₃*ϱ₄₂^-1 + 2ϱ₁₃*ϱ₄₃^-1 + 2ϱ₁₃*λ₁₂^-1 + 2ϱ₁₃*λ₁₄^-1 + ϱ₁₃*λ₂₁^-1 + 2ϱ₁₃*λ₂₃^-1 + 200ϱ₁₃*λ₂₄^-1 + ϱ₁₃*λ₃₂^-1 + ϱ₁₃*λ₃₄^-1 + ϱ₁₃*λ₄₁^-1 + 200ϱ₁₃*λ₄₂^-1 + 2ϱ₁₃*λ₄₃^-1 + ϱ₁₄*ϱ₁₂ + ϱ₁₄*ϱ₁₃ + ϱ₁₄*ϱ₂₁ + 200ϱ₁₄*ϱ₂₃ + 2ϱ₁₄*ϱ₂₄ + ϱ₁₄*ϱ₃₁ + 200ϱ₁₄*ϱ₃₂ + 2ϱ₁₄*ϱ₃₄ + ϱ₁₄*ϱ₄₂ + ϱ₁₄*ϱ₄₃ + 2ϱ₁₄*λ₁₂ + 2ϱ₁₄*λ₁₃ + ϱ₁₄*λ₂₁ + 200ϱ₁₄*λ₂₃ + 2ϱ₁₄*λ₂₄ + ϱ₁₄*λ₃₁ + 200ϱ₁₄*λ₃₂ + 2ϱ₁₄*λ₃₄ + ϱ₁₄*λ₄₂ + ϱ₁₄*λ₄₃ + ϱ₁₄*ϱ₁₂^-1 + ϱ₁₄*ϱ₁₃^-1 + ϱ₁₄*ϱ₂₁^-1 + 200ϱ₁₄*ϱ₂₃^-1 + 2ϱ₁₄*ϱ₂₄^-1 + ϱ₁₄*ϱ₃₁^-1 + 200ϱ₁₄*ϱ₃₂^-1 + 2ϱ₁₄*ϱ₃₄^-1 + ϱ₁₄*ϱ₄₂^-1 + ϱ₁₄*ϱ₄₃^-1 + 2ϱ₁₄*λ₁₂^-1 + 2ϱ₁₄*λ₁₃^-1 + ϱ₁₄*λ₂₁^-1 + 200ϱ₁₄*λ₂₃^-1 + 2ϱ₁₄*λ₂₄^-1 + ϱ₁₄*λ₃₁^-1 + 200ϱ₁₄*λ₃₂^-1 + 2ϱ₁₄*λ₃₄^-1 + ϱ₁₄*λ₄₂^-1 + ϱ₁₄*λ₄₃^-1 + ϱ₂₁*ϱ₁₃ + ϱ₂₁*ϱ₁₄ + ϱ₂₁*ϱ₂₃ + ϱ₂₁*ϱ₂₄ + 2ϱ₂₁*ϱ₃₁ + ϱ₂₁*ϱ₃₂ + 200ϱ₂₁*ϱ₃₄ + 2ϱ₂₁*ϱ₄₁ + ϱ₂₁*ϱ₄₂ + 200ϱ₂₁*ϱ₄₃ + ϱ₂₁*λ₁₃ + ϱ₂₁*λ₁₄ + 2ϱ₂₁*λ₂₃ + 2ϱ₂₁*λ₂₄ + 2ϱ₂₁*λ₃₁ + ϱ₂₁*λ₃₂ + 200ϱ₂₁*λ₃₄ + 2ϱ₂₁*λ₄₁ + ϱ₂₁*λ₄₂ + 200ϱ₂₁*λ₄₃ + ϱ₂₁*ϱ₁₃^-1 + ϱ₂₁*ϱ₁₄^-1 + ϱ₂₁*ϱ₂₃^-1 + ϱ₂₁*ϱ₂₄^-1 + 2ϱ₂₁*ϱ₃₁^-1 + ϱ₂₁*ϱ₃₂^-1 + 200ϱ₂₁*ϱ₃₄^-1 + 2ϱ₂₁*ϱ₄₁^-1 + ϱ₂₁*ϱ₄₂^-1 + 200ϱ₂₁*ϱ₄₃^-1 + ϱ₂₁*λ₁₃^-1 + ϱ₂₁*λ₁₄^-1 + 2ϱ₂₁*λ₂₃^-1 + 2ϱ₂₁*λ₂₄^-1 + 2ϱ₂₁*λ₃₁^-1 + ϱ₂₁*λ₃₂^-1 + 200ϱ₂₁*λ₃₄^-1 + 2ϱ₂₁*λ₄₁^-1 + ϱ₂₁*λ₄₂^-1 + 200ϱ₂₁*λ₄₃^-1 + ϱ₂₃*ϱ₁₂ + ϱ₂₃*ϱ₂₁ + ϱ₂₃*ϱ₂₄ + ϱ₂₃*ϱ₃₁ + ϱ₂₃*ϱ₃₄ + 200ϱ₂₃*ϱ₄₁ + ϱ₂₃*ϱ₄₂ + 2ϱ₂₃*ϱ₄₃ + ϱ₂₃*λ₁₂ + 2ϱ₂₃*λ₁₃ + 200ϱ₂₃*λ₁₄ + 2ϱ₂₃*λ₂₁ + 2ϱ₂₃*λ₂₄ + ϱ₂₃*λ₃₁ + ϱ₂₃*λ₃₄ + 200ϱ₂₃*λ₄₁ + ϱ₂₃*λ₄₂ + 2ϱ₂₃*λ₄₃ + ϱ₂₃*ϱ₁₂^-1 + 2ϱ₂₃*ϱ₁₃^-1 + 200ϱ₂₃*ϱ₁₄^-1 + ϱ₂₃*ϱ₂₁^-1 + ϱ₂₃*ϱ₂₄^-1 + ϱ₂₃*ϱ₃₁^-1 + ϱ₂₃*ϱ₃₄^-1 + 200ϱ₂₃*ϱ₄₁^-1 + ϱ₂₃*ϱ₄₂^-1 + 2ϱ₂₃*ϱ₄₃^-1 + ϱ₂₃*λ₁₂^-1 + 2ϱ₂₃*λ₁₃^-1 + 200ϱ₂₃*λ₁₄^-1 + 2ϱ₂₃*λ₂₁^-1 + 2ϱ₂₃*λ₂₄^-1 + ϱ₂₃*λ₃₁^-1 + ϱ₂₃*λ₃₄^-1 + 200ϱ₂₃*λ₄₁^-1 + ϱ₂₃*λ₄₂^-1 + 2ϱ₂₃*λ₄₃^-1 + ϱ₂₄*ϱ₁₂ + ϱ₂₄*ϱ₂₁ + ϱ₂₄*ϱ₂₃ + 200ϱ₂₄*ϱ₃₁ + ϱ₂₄*ϱ₃₂ + 2ϱ₂₄*ϱ₃₄ + ϱ₂₄*ϱ₄₁ + ϱ₂₄*ϱ₄₃ + ϱ₂₄*λ₁₂ + 200ϱ₂₄*λ₁₃ + 2ϱ₂₄*λ₁₄ + 2ϱ₂₄*λ₂₁ + 2ϱ₂₄*λ₂₃ + 200ϱ₂₄*λ₃₁ + ϱ₂₄*λ₃₂ + 2ϱ₂₄*λ₃₄ + ϱ₂₄*λ₄₁ + ϱ₂₄*λ₄₃ + ϱ₂₄*ϱ₁₂^-1 + 200ϱ₂₄*ϱ₁₃^-1 + 2ϱ₂₄*ϱ₁₄^-1 + ϱ₂₄*ϱ₂₁^-1 + ϱ₂₄*ϱ₂₃^-1 + 200ϱ₂₄*ϱ₃₁^-1 + ϱ₂₄*ϱ₃₂^-1 + 2ϱ₂₄*ϱ₃₄^-1 + ϱ₂₄*ϱ₄₁^-1 + ϱ₂₄*ϱ₄₃^-1 + ϱ₂₄*λ₁₂^-1 + 200ϱ₂₄*λ₁₃^-1 + 2ϱ₂₄*λ₁₄^-1 + 2ϱ₂₄*λ₂₁^-1 + 2ϱ₂₄*λ₂₃^-1 + 200ϱ₂₄*λ₃₁^-1 + ϱ₂₄*λ₃₂^-1 + 2ϱ₂₄*λ₃₄^-1 + ϱ₂₄*λ₄₁^-1 + ϱ₂₄*λ₄₃^-1 + ϱ₃₁*ϱ₁₂ + ϱ₃₁*ϱ₁₄ + ϱ₃₁*ϱ₂₃ + ϱ₃₁*ϱ₃₂ + ϱ₃₁*ϱ₃₄ + 2ϱ₃₁*ϱ₄₁ + 200ϱ₃₁*ϱ₄₂ + ϱ₃₁*ϱ₄₃ + ϱ₃₁*λ₁₂ + ϱ₃₁*λ₁₄ + 2ϱ₃₁*λ₂₁ + ϱ₃₁*λ₂₃ + 200ϱ₃₁*λ₂₄ + 2ϱ₃₁*λ₃₂ + 2ϱ₃₁*λ₃₄ + 2ϱ₃₁*λ₄₁ + 200ϱ₃₁*λ₄₂ + ϱ₃₁*λ₄₃ + ϱ₃₁*ϱ₁₂^-1 + ϱ₃₁*ϱ₁₄^-1 + 2ϱ₃₁*ϱ₂₁^-1 + ϱ₃₁*ϱ₂₃^-1 + 200ϱ₃₁*ϱ₂₄^-1 + ϱ₃₁*ϱ₃₂^-1 + ϱ₃₁*ϱ₃₄^-1 + 2ϱ₃₁*ϱ₄₁^-1 + 200ϱ₃₁*ϱ₄₂^-1 + ϱ₃₁*ϱ₄₃^-1 + ϱ₃₁*λ₁₂^-1 + ϱ₃₁*λ₁₄^-1 + 2ϱ₃₁*λ₂₁^-1 + ϱ₃₁*λ₂₃^-1 + 200ϱ₃₁*λ₂₄^-1 + 2ϱ₃₁*λ₃₂^-1 + 2ϱ₃₁*λ₃₄^-1 + 2ϱ₃₁*λ₄₁^-1 + 200ϱ₃₁*λ₄₂^-1 + ϱ₃₁*λ₄₃^-1 + ϱ₃₂*ϱ₁₃ + ϱ₃₂*ϱ₂₁ + ϱ₃₂*ϱ₂₄ + ϱ₃₂*ϱ₃₁ + ϱ₃₂*ϱ₃₄ + 200ϱ₃₂*ϱ₄₁ + 2ϱ₃₂*ϱ₄₂ + ϱ₃₂*ϱ₄₃ + 2ϱ₃₂*λ₁₂ + ϱ₃₂*λ₁₃ + 200ϱ₃₂*λ₁₄ + ϱ₃₂*λ₂₁ + ϱ₃₂*λ₂₄ + 2ϱ₃₂*λ₃₁ + 2ϱ₃₂*λ₃₄ + 200ϱ₃₂*λ₄₁ + 2ϱ₃₂*λ₄₂ + ϱ₃₂*λ₄₃ + 2ϱ₃₂*ϱ₁₂^-1 + ϱ₃₂*ϱ₁₃^-1 + 200ϱ₃₂*ϱ₁₄^-1 + ϱ₃₂*ϱ₂₁^-1 + ϱ₃₂*ϱ₂₄^-1 + ϱ₃₂*ϱ₃₁^-1 + ϱ₃₂*ϱ₃₄^-1 + 200ϱ₃₂*ϱ₄₁^-1 + 2ϱ₃₂*ϱ₄₂^-1 + ϱ₃₂*ϱ₄₃^-1 + 2ϱ₃₂*λ₁₂^-1 + ϱ₃₂*λ₁₃^-1 + 200ϱ₃₂*λ₁₄^-1 + ϱ₃₂*λ₂₁^-1 + ϱ₃₂*λ₂₄^-1 + 2ϱ₃₂*λ₃₁^-1 + 2ϱ₃₂*λ₃₄^-1 + 200ϱ₃₂*λ₄₁^-1 + 2ϱ₃₂*λ₄₂^-1 + ϱ₃₂*λ₄₃^-1 + ϱ₃₄*ϱ₁₃ + ϱ₃₄*ϱ₂₃ + ϱ₃₄*ϱ₃₁ + ϱ₃₄*ϱ₃₂ + ϱ₃₄*ϱ₄₁ + ϱ₃₄*ϱ₄₂ + 200ϱ₃₄*λ₁₂ + ϱ₃₄*λ₁₃ + 2ϱ₃₄*λ₁₄ + 200ϱ₃₄*λ₂₁ + ϱ₃₄*λ₂₃ + 2ϱ₃₄*λ₂₄ + 2ϱ₃₄*λ₃₁ + 2ϱ₃₄*λ₃₂ + ϱ₃₄*λ₄₁ + ϱ₃₄*λ₄₂ + 200ϱ₃₄*ϱ₁₂^-1 + ϱ₃₄*ϱ₁₃^-1 + 2ϱ₃₄*ϱ₁₄^-1 + 200ϱ₃₄*ϱ₂₁^-1 + ϱ₃₄*ϱ₂₃^-1 + 2ϱ₃₄*ϱ₂₄^-1 + ϱ₃₄*ϱ₃₁^-1 + ϱ₃₄*ϱ₃₂^-1 + ϱ₃₄*ϱ₄₁^-1 + ϱ₃₄*ϱ₄₂^-1 + 200ϱ₃₄*λ₁₂^-1 + ϱ₃₄*λ₁₃^-1 + 2ϱ₃₄*λ₁₄^-1 + 200ϱ₃₄*λ₂₁^-1 + ϱ₃₄*λ₂₃^-1 + 2ϱ₃₄*λ₂₄^-1 + 2ϱ₃₄*λ₃₁^-1 + 2ϱ₃₄*λ₃₂^-1 + ϱ₃₄*λ₄₁^-1 + ϱ₃₄*λ₄₂^-1 + ϱ₄₁*ϱ₁₂ + ϱ₄₁*ϱ₁₃ + ϱ₄₁*ϱ₂₄ + ϱ₄₁*ϱ₃₄ + ϱ₄₁*ϱ₄₂ + ϱ₄₁*ϱ₄₃ + ϱ₄₁*λ₁₂ + ϱ₄₁*λ₁₃ + 2ϱ₄₁*λ₂₁ + 200ϱ₄₁*λ₂₃ + ϱ₄₁*λ₂₄ + 2ϱ₄₁*λ₃₁ + 200ϱ₄₁*λ₃₂ + ϱ₄₁*λ₃₄ + 2ϱ₄₁*λ₄₂ + 2ϱ₄₁*λ₄₃ + ϱ₄₁*ϱ₁₂^-1 + ϱ₄₁*ϱ₁₃^-1 + 2ϱ₄₁*ϱ₂₁^-1 + 200ϱ₄₁*ϱ₂₃^-1 + ϱ₄₁*ϱ₂₄^-1 + 2ϱ₄₁*ϱ₃₁^-1 + 200ϱ₄₁*ϱ₃₂^-1 + ϱ₄₁*ϱ₃₄^-1 + ϱ₄₁*ϱ₄₂^-1 + ϱ₄₁*ϱ₄₃^-1 + ϱ₄₁*λ₁₂^-1 + ϱ₄₁*λ₁₃^-1 + 2ϱ₄₁*λ₂₁^-1 + 200ϱ₄₁*λ₂₃^-1 + ϱ₄₁*λ₂₄^-1 + 2ϱ₄₁*λ₃₁^-1 + 200ϱ₄₁*λ₃₂^-1 + ϱ₄₁*λ₃₄^-1 + 2ϱ₄₁*λ₄₂^-1 + 2ϱ₄₁*λ₄₃^-1 + ϱ₄₂*ϱ₁₄ + ϱ₄₂*ϱ₂₁ + ϱ₄₂*ϱ₂₃ + ϱ₄₂*ϱ₃₄ + ϱ₄₂*ϱ₄₁ + ϱ₄₂*ϱ₄₃ + 2ϱ₄₂*λ₁₂ + 200ϱ₄₂*λ₁₃ + ϱ₄₂*λ₁₄ + ϱ₄₂*λ₂₁ + ϱ₄₂*λ₂₃ + 200ϱ₄₂*λ₃₁ + 2ϱ₄₂*λ₃₂ + ϱ₄₂*λ₃₄ + 2ϱ₄₂*λ₄₁ + 2ϱ₄₂*λ₄₃ + 2ϱ₄₂*ϱ₁₂^-1 + 200ϱ₄₂*ϱ₁₃^-1 + ϱ₄₂*ϱ₁₄^-1 + ϱ₄₂*ϱ₂₁^-1 + ϱ₄₂*ϱ₂₃^-1 + 200ϱ₄₂*ϱ₃₁^-1 + 2ϱ₄₂*ϱ₃₂^-1 + ϱ₄₂*ϱ₃₄^-1 + ϱ₄₂*ϱ₄₁^-1 + ϱ₄₂*ϱ₄₃^-1 + 2ϱ₄₂*λ₁₂^-1 + 200ϱ₄₂*λ₁₃^-1 + ϱ₄₂*λ₁₄^-1 + ϱ₄₂*λ₂₁^-1 + ϱ₄₂*λ₂₃^-1 + 200ϱ₄₂*λ₃₁^-1 + 2ϱ₄₂*λ₃₂^-1 + ϱ₄₂*λ₃₄^-1 + 2ϱ₄₂*λ₄₁^-1 + 2ϱ₄₂*λ₄₃^-1 + ϱ₄₃*ϱ₁₄ + ϱ₄₃*ϱ₂₄ + ϱ₄₃*ϱ₃₁ + ϱ₄₃*ϱ₃₂ + ϱ₄₃*ϱ₄₁ + ϱ₄₃*ϱ₄₂ + 200ϱ₄₃*λ₁₂ + 2ϱ₄₃*λ₁₃ + ϱ₄₃*λ₁₄ + 200ϱ₄₃*λ₂₁ + 2ϱ₄₃*λ₂₃ + ϱ₄₃*λ₂₄ + ϱ₄₃*λ₃₁ + ϱ₄₃*λ₃₂ + 2ϱ₄₃*λ₄₁ + 2ϱ₄₃*λ₄₂ + 200ϱ₄₃*ϱ₁₂^-1 + 2ϱ₄₃*ϱ₁₃^-1 + ϱ₄₃*ϱ₁₄^-1 + 200ϱ₄₃*ϱ₂₁^-1 + 2ϱ₄₃*ϱ₂₃^-1 + ϱ₄₃*ϱ₂₄^-1 + ϱ₄₃*ϱ₃₁^-1 + ϱ₄₃*ϱ₃₂^-1 + ϱ₄₃*ϱ₄₁^-1 + ϱ₄₃*ϱ₄₂^-1 + 200ϱ₄₃*λ₁₂^-1 + 2ϱ₄₃*λ₁₃^-1 + ϱ₄₃*λ₁₄^-1 + 200ϱ₄₃*λ₂₁^-1 + 2ϱ₄₃*λ₂₃^-1 + ϱ₄₃*λ₂₄^-1 + ϱ₄₃*λ₃₁^-1 + ϱ₄₃*λ₃₂^-1 + 2ϱ₄₃*λ₄₁^-1 + 2ϱ₄₃*λ₄₂^-1 + λ₁₂*ϱ₂₃ + λ₁₂*ϱ₂₄ + λ₁₂*ϱ₃₁ + λ₁₂*ϱ₄₁ + λ₁₂*λ₁₃ + λ₁₂*λ₁₄ + λ₁₂*λ₂₃ + λ₁₂*λ₂₄ + λ₁₂*λ₃₁ + 2λ₁₂*λ₃₂ + 200λ₁₂*λ₃₄ + λ₁₂*λ₄₁ + 2λ₁₂*λ₄₂ + 200λ₁₂*λ₄₃ + 2λ₁₂*ϱ₁₃^-1 + 2λ₁₂*ϱ₁₄^-1 + λ₁₂*ϱ₂₃^-1 + λ₁₂*ϱ₂₄^-1 + λ₁₂*ϱ₃₁^-1 + 2λ₁₂*ϱ₃₂^-1 + 200λ₁₂*ϱ₃₄^-1 + λ₁₂*ϱ₄₁^-1 + 2λ₁₂*ϱ₄₂^-1 + 200λ₁₂*ϱ₄₃^-1 + λ₁₂*λ₁₃^-1 + λ₁₂*λ₁₄^-1 + λ₁₂*λ₂₃^-1 + λ₁₂*λ₂₄^-1 + λ₁₂*λ₃₁^-1 + 2λ₁₂*λ₃₂^-1 + 200λ₁₂*λ₃₄^-1 + λ₁₂*λ₄₁^-1 + 2λ₁₂*λ₄₂^-1 + 200λ₁₂*λ₄₃^-1 + λ₁₃*ϱ₂₁ + λ₁₃*ϱ₃₂ + λ₁₃*ϱ₃₄ + λ₁₃*ϱ₄₁ + λ₁₃*λ₁₂ + λ₁₃*λ₁₄ + λ₁₃*λ₂₁ + 2λ₁₃*λ₂₃ + 200λ₁₃*λ₂₄ + λ₁₃*λ₃₂ + λ₁₃*λ₃₄ + λ₁₃*λ₄₁ + 200λ₁₃*λ₄₂ + 2λ₁₃*λ₄₃ + 2λ₁₃*ϱ₁₂^-1 + 2λ₁₃*ϱ₁₄^-1 + λ₁₃*ϱ₂₁^-1 + 2λ₁₃*ϱ₂₃^-1 + 200λ₁₃*ϱ₂₄^-1 + λ₁₃*ϱ₃₂^-1 + λ₁₃*ϱ₃₄^-1 + λ₁₃*ϱ₄₁^-1 + 200λ₁₃*ϱ₄₂^-1 + 2λ₁₃*ϱ₄₃^-1 + λ₁₃*λ₁₂^-1 + λ₁₃*λ₁₄^-1 + λ₁₃*λ₂₁^-1 + 2λ₁₃*λ₂₃^-1 + 200λ₁₃*λ₂₄^-1 + λ₁₃*λ₃₂^-1 + λ₁₃*λ₃₄^-1 + λ₁₃*λ₄₁^-1 + 200λ₁₃*λ₄₂^-1 + 2λ₁₃*λ₄₃^-1 + λ₁₄*ϱ₂₁ + λ₁₄*ϱ₃₁ + λ₁₄*ϱ₄₂ + λ₁₄*ϱ₄₃ + λ₁₄*λ₁₂ + λ₁₄*λ₁₃ + λ₁₄*λ₂₁ + 200λ₁₄*λ₂₃ + 2λ₁₄*λ₂₄ + λ₁₄*λ₃₁ + 200λ₁₄*λ₃₂ + 2λ₁₄*λ₃₄ + λ₁₄*λ₄₂ + λ₁₄*λ₄₃ + 2λ₁₄*ϱ₁₂^-1 + 2λ₁₄*ϱ₁₃^-1 + λ₁₄*ϱ₂₁^-1 + 200λ₁₄*ϱ₂₃^-1 + 2λ₁₄*ϱ₂₄^-1 + λ₁₄*ϱ₃₁^-1 + 200λ₁₄*ϱ₃₂^-1 + 2λ₁₄*ϱ₃₄^-1 + λ₁₄*ϱ₄₂^-1 + λ₁₄*ϱ₄₃^-1 + λ₁₄*λ₁₂^-1 + λ₁₄*λ₁₃^-1 + λ₁₄*λ₂₁^-1 + 200λ₁₄*λ₂₃^-1 + 2λ₁₄*λ₂₄^-1 + λ₁₄*λ₃₁^-1 + 200λ₁₄*λ₃₂^-1 + 2λ₁₄*λ₃₄^-1 + λ₁₄*λ₄₂^-1 + λ₁₄*λ₄₃^-1 + λ₂₁*ϱ₁₃ + λ₂₁*ϱ₁₄ + λ₂₁*ϱ₃₂ + λ₂₁*ϱ₄₂ + λ₂₁*λ₁₃ + λ₂₁*λ₁₄ + λ₂₁*λ₂₃ + λ₂₁*λ₂₄ + 2λ₂₁*λ₃₁ + λ₂₁*λ₃₂ + 200λ₂₁*λ₃₄ + 2λ₂₁*λ₄₁ + λ₂₁*λ₄₂ + 200λ₂₁*λ₄₃ + λ₂₁*ϱ₁₃^-1 + λ₂₁*ϱ₁₄^-1 + 2λ₂₁*ϱ₂₃^-1 + 2λ₂₁*ϱ₂₄^-1 + 2λ₂₁*ϱ₃₁^-1 + λ₂₁*ϱ₃₂^-1 + 200λ₂₁*ϱ₃₄^-1 + 2λ₂₁*ϱ₄₁^-1 + λ₂₁*ϱ₄₂^-1 + 200λ₂₁*ϱ₄₃^-1 + λ₂₁*λ₁₃^-1 + λ₂₁*λ₁₄^-1 + λ₂₁*λ₂₃^-1 + λ₂₁*λ₂₄^-1 + 2λ₂₁*λ₃₁^-1 + λ₂₁*λ₃₂^-1 + 200λ₂₁*λ₃₄^-1 + 2λ₂₁*λ₄₁^-1 + λ₂₁*λ₄₂^-1 + 200λ₂₁*λ₄₃^-1 + λ₂₃*ϱ₁₂ + λ₂₃*ϱ₃₁ + λ₂₃*ϱ₃₄ + λ₂₃*ϱ₄₂ + λ₂₃*λ₁₂ + λ₂₃*λ₂₁ + λ₂₃*λ₂₄ + λ₂₃*λ₃₁ + λ₂₃*λ₃₄ + 200λ₂₃*λ₄₁ + λ₂₃*λ₄₂ + 2λ₂₃*λ₄₃ + λ₂₃*ϱ₁₂^-1 + 2λ₂₃*ϱ₁₃^-1 + 200λ₂₃*ϱ₁₄^-1 + 2λ₂₃*ϱ₂₁^-1 + 2λ₂₃*ϱ₂₄^-1 + λ₂₃*ϱ₃₁^-1 + λ₂₃*ϱ₃₄^-1 + 200λ₂₃*ϱ₄₁^-1 + λ₂₃*ϱ₄₂^-1 + 2λ₂₃*ϱ₄₃^-1 + λ₂₃*λ₁₂^-1 + 2λ₂₃*λ₁₃^-1 + 200λ₂₃*λ₁₄^-1 + λ₂₃*λ₂₁^-1 + λ₂₃*λ₂₄^-1 + λ₂₃*λ₃₁^-1 + λ₂₃*λ₃₄^-1 + 200λ₂₃*λ₄₁^-1 + λ₂₃*λ₄₂^-1 + 2λ₂₃*λ₄₃^-1 + λ₂₄*ϱ₁₂ + λ₂₄*ϱ₃₂ + λ₂₄*ϱ₄₁ + λ₂₄*ϱ₄₃ + λ₂₄*λ₁₂ + λ₂₄*λ₂₁ + λ₂₄*λ₂₃ + 200λ₂₄*λ₃₁ + λ₂₄*λ₃₂ + 2λ₂₄*λ₃₄ + λ₂₄*λ₄₁ + λ₂₄*λ₄₃ + λ₂₄*ϱ₁₂^-1 + 200λ₂₄*ϱ₁₃^-1 + 2λ₂₄*ϱ₁₄^-1 + 2λ₂₄*ϱ₂₁^-1 + 2λ₂₄*ϱ₂₃^-1 + 200λ₂₄*ϱ₃₁^-1 + λ₂₄*ϱ₃₂^-1 + 2λ₂₄*ϱ₃₄^-1 + λ₂₄*ϱ₄₁^-1 + λ₂₄*ϱ₄₃^-1 + λ₂₄*λ₁₂^-1 + 200λ₂₄*λ₁₃^-1 + 2λ₂₄*λ₁₄^-1 + λ₂₄*λ₂₁^-1 + λ₂₄*λ₂₃^-1 + 200λ₂₄*λ₃₁^-1 + λ₂₄*λ₃₂^-1 + 2λ₂₄*λ₃₄^-1 + λ₂₄*λ₄₁^-1 + λ₂₄*λ₄₃^-1 + λ₃₁*ϱ₁₂ + λ₃₁*ϱ₁₄ + λ₃₁*ϱ₂₃ + λ₃₁*ϱ₄₃ + λ₃₁*λ₁₂ + λ₃₁*λ₁₄ + λ₃₁*λ₂₃ + λ₃₁*λ₃₂ + λ₃₁*λ₃₄ + 2λ₃₁*λ₄₁ + 200λ₃₁*λ₄₂ + λ₃₁*λ₄₃ + λ₃₁*ϱ₁₂^-1 + λ₃₁*ϱ₁₄^-1 + 2λ₃₁*ϱ₂₁^-1 + λ₃₁*ϱ₂₃^-1 + 200λ₃₁*ϱ₂₄^-1 + 2λ₃₁*ϱ₃₂^-1 + 2λ₃₁*ϱ₃₄^-1 + 2λ₃₁*ϱ₄₁^-1 + 200λ₃₁*ϱ₄₂^-1 + λ₃₁*ϱ₄₃^-1 + λ₃₁*λ₁₂^-1 + λ₃₁*λ₁₄^-1 + 2λ₃₁*λ₂₁^-1 + λ₃₁*λ₂₃^-1 + 200λ₃₁*λ₂₄^-1 + λ₃₁*λ₃₂^-1 + λ₃₁*λ₃₄^-1 + 2λ₃₁*λ₄₁^-1 + 200λ₃₁*λ₄₂^-1 + λ₃₁*λ₄₃^-1 + λ₃₂*ϱ₁₃ + λ₃₂*ϱ₂₁ + λ₃₂*ϱ₂₄ + λ₃₂*ϱ₄₃ + λ₃₂*λ₁₃ + λ₃₂*λ₂₁ + λ₃₂*λ₂₄ + λ₃₂*λ₃₁ + λ₃₂*λ₃₄ + 200λ₃₂*λ₄₁ + 2λ₃₂*λ₄₂ + λ₃₂*λ₄₃ + 2λ₃₂*ϱ₁₂^-1 + λ₃₂*ϱ₁₃^-1 + 200λ₃₂*ϱ₁₄^-1 + λ₃₂*ϱ₂₁^-1 + λ₃₂*ϱ₂₄^-1 + 2λ₃₂*ϱ₃₁^-1 + 2λ₃₂*ϱ₃₄^-1 + 200λ₃₂*ϱ₄₁^-1 + 2λ₃₂*ϱ₄₂^-1 + λ₃₂*ϱ₄₃^-1 + 2λ₃₂*λ₁₂^-1 + λ₃₂*λ₁₃^-1 + 200λ₃₂*λ₁₄^-1 + λ₃₂*λ₂₁^-1 + λ₃₂*λ₂₄^-1 + λ₃₂*λ₃₁^-1 + λ₃₂*λ₃₄^-1 + 200λ₃₂*λ₄₁^-1 + 2λ₃₂*λ₄₂^-1 + λ₃₂*λ₄₃^-1 + λ₃₄*ϱ₁₃ + λ₃₄*ϱ₂₃ + λ₃₄*ϱ₄₁ + λ₃₄*ϱ₄₂ + λ₃₄*λ₁₃ + λ₃₄*λ₂₃ + λ₃₄*λ₃₁ + λ₃₄*λ₃₂ + λ₃₄*λ₄₁ + λ₃₄*λ₄₂ + 200λ₃₄*ϱ₁₂^-1 + λ₃₄*ϱ₁₃^-1 + 2λ₃₄*ϱ₁₄^-1 + 200λ₃₄*ϱ₂₁^-1 + λ₃₄*ϱ₂₃^-1 + 2λ₃₄*ϱ₂₄^-1 + 2λ₃₄*ϱ₃₁^-1 + 2λ₃₄*ϱ₃₂^-1 + λ₃₄*ϱ₄₁^-1 + λ₃₄*ϱ₄₂^-1 + 200λ₃₄*λ₁₂^-1 + λ₃₄*λ₁₃^-1 + 2λ₃₄*λ₁₄^-1 + 200λ₃₄*λ₂₁^-1 + λ₃₄*λ₂₃^-1 + 2λ₃₄*λ₂₄^-1 + λ₃₄*λ₃₁^-1 + λ₃₄*λ₃₂^-1 + λ₃₄*λ₄₁^-1 + λ₃₄*λ₄₂^-1 + λ₄₁*ϱ₁₂ + λ₄₁*ϱ₁₃ + λ₄₁*ϱ₂₄ + λ₄₁*ϱ₃₄ + λ₄₁*λ₁₂ + λ₄₁*λ₁₃ + λ₄₁*λ₂₄ + λ₄₁*λ₃₄ + λ₄₁*λ₄₂ + λ₄₁*λ₄₃ + λ₄₁*ϱ₁₂^-1 + λ₄₁*ϱ₁₃^-1 + 2λ₄₁*ϱ₂₁^-1 + 200λ₄₁*ϱ₂₃^-1 + λ₄₁*ϱ₂₄^-1 + 2λ₄₁*ϱ₃₁^-1 + 200λ₄₁*ϱ₃₂^-1 + λ₄₁*ϱ₃₄^-1 + 2λ₄₁*ϱ₄₂^-1 + 2λ₄₁*ϱ₄₃^-1 + λ₄₁*λ₁₂^-1 + λ₄₁*λ₁₃^-1 + 2λ₄₁*λ₂₁^-1 + 200λ₄₁*λ₂₃^-1 + λ₄₁*λ₂₄^-1 + 2λ₄₁*λ₃₁^-1 + 200λ₄₁*λ₃₂^-1 + λ₄₁*λ₃₄^-1 + λ₄₁*λ₄₂^-1 + λ₄₁*λ₄₃^-1 + λ₄₂*ϱ₁₄ + λ₄₂*ϱ₂₁ + λ₄₂*ϱ₂₃ + λ₄₂*ϱ₃₄ + λ₄₂*λ₁₄ + λ₄₂*λ₂₁ + λ₄₂*λ₂₃ + λ₄₂*λ₃₄ + λ₄₂*λ₄₁ + λ₄₂*λ₄₃ + 2λ₄₂*ϱ₁₂^-1 + 200λ₄₂*ϱ₁₃^-1 + λ₄₂*ϱ₁₄^-1 + λ₄₂*ϱ₂₁^-1 + λ₄₂*ϱ₂₃^-1 + 200λ₄₂*ϱ₃₁^-1 + 2λ₄₂*ϱ₃₂^-1 + λ₄₂*ϱ₃₄^-1 + 2λ₄₂*ϱ₄₁^-1 + 2λ₄₂*ϱ₄₃^-1 + 2λ₄₂*λ₁₂^-1 + 200λ₄₂*λ₁₃^-1 + λ₄₂*λ₁₄^-1 + λ₄₂*λ₂₁^-1 + λ₄₂*λ₂₃^-1 + 200λ₄₂*λ₃₁^-1 + 2λ₄₂*λ₃₂^-1 + λ₄₂*λ₃₄^-1 + λ₄₂*λ₄₁^-1 + λ₄₂*λ₄₃^-1 + λ₄₃*ϱ₁₄ + λ₄₃*ϱ₂₄ + λ₄₃*ϱ₃₁ + λ₄₃*ϱ₃₂ + λ₄₃*λ₁₄ + λ₄₃*λ₂₄ + λ₄₃*λ₃₁ + λ₄₃*λ₃₂ + λ₄₃*λ₄₁ + λ₄₃*λ₄₂ + 200λ₄₃*ϱ₁₂^-1 + 2λ₄₃*ϱ₁₃^-1 + λ₄₃*ϱ₁₄^-1 + 200λ₄₃*ϱ₂₁^-1 + 2λ₄₃*ϱ₂₃^-1 + λ₄₃*ϱ₂₄^-1 + λ₄₃*ϱ₃₁^-1 + λ₄₃*ϱ₃₂^-1 + 2λ₄₃*ϱ₄₁^-1 + 2λ₄₃*ϱ₄₂^-1 + 200λ₄₃*λ₁₂^-1 + 2λ₄₃*λ₁₃^-1 + λ₄₃*λ₁₄^-1 + 200λ₄₃*λ₂₁^-1 + 2λ₄₃*λ₂₃^-1 + λ₄₃*λ₂₄^-1 + λ₄₃*λ₃₁^-1 + λ₄₃*λ₃₂^-1 + λ₄₃*λ₄₁^-1 + λ₄₃*λ₄₂^-1 + ϱ₁₂^-1*ϱ₁₃ + ϱ₁₂^-1*ϱ₁₄ + ϱ₁₂^-1*ϱ₂₃ + ϱ₁₂^-1*ϱ₂₄ + ϱ₁₂^-1*ϱ₃₁ + ϱ₁₂^-1*ϱ₄₁ + ϱ₁₂^-1*λ₂₃ + ϱ₁₂^-1*λ₂₄ + ϱ₁₂^-1*λ₃₁ + ϱ₁₂^-1*λ₄₁ + ϱ₁₂^-1*ϱ₁₃^-1 + ϱ₁₂^-1*ϱ₁₄^-1 + ϱ₁₂^-1*ϱ₂₃^-1 + ϱ₁₂^-1*ϱ₂₄^-1 + ϱ₁₂^-1*ϱ₃₁^-1 + 2ϱ₁₂^-1*ϱ₃₂^-1 + 200ϱ₁₂^-1*ϱ₃₄^-1 + ϱ₁₂^-1*ϱ₄₁^-1 + 2ϱ₁₂^-1*ϱ₄₂^-1 + 200ϱ₁₂^-1*ϱ₄₃^-1 + 2ϱ₁₂^-1*λ₁₃^-1 + 2ϱ₁₂^-1*λ₁₄^-1 + ϱ₁₂^-1*λ₂₃^-1 + ϱ₁₂^-1*λ₂₄^-1 + ϱ₁₂^-1*λ₃₁^-1 + 2ϱ₁₂^-1*λ₃₂^-1 + 200ϱ₁₂^-1*λ₃₄^-1 + ϱ₁₂^-1*λ₄₁^-1 + 2ϱ₁₂^-1*λ₄₂^-1 + 200ϱ₁₂^-1*λ₄₃^-1 + ϱ₁₃^-1*ϱ₁₂ + ϱ₁₃^-1*ϱ₁₄ + ϱ₁₃^-1*ϱ₂₁ + ϱ₁₃^-1*ϱ₃₂ + ϱ₁₃^-1*ϱ₃₄ + ϱ₁₃^-1*ϱ₄₁ + ϱ₁₃^-1*λ₂₁ + ϱ₁₃^-1*λ₃₂ + ϱ₁₃^-1*λ₃₄ + ϱ₁₃^-1*λ₄₁ + ϱ₁₃^-1*ϱ₁₂^-1 + ϱ₁₃^-1*ϱ₁₄^-1 + ϱ₁₃^-1*ϱ₂₁^-1 + 2ϱ₁₃^-1*ϱ₂₃^-1 + 200ϱ₁₃^-1*ϱ₂₄^-1 + ϱ₁₃^-1*ϱ₃₂^-1 + ϱ₁₃^-1*ϱ₃₄^-1 + ϱ₁₃^-1*ϱ₄₁^-1 + 200ϱ₁₃^-1*ϱ₄₂^-1 + 2ϱ₁₃^-1*ϱ₄₃^-1 + 2ϱ₁₃^-1*λ₁₂^-1 + 2ϱ₁₃^-1*λ₁₄^-1 + ϱ₁₃^-1*λ₂₁^-1 + 2ϱ₁₃^-1*λ₂₃^-1 + 200ϱ₁₃^-1*λ₂₄^-1 + ϱ₁₃^-1*λ₃₂^-1 + ϱ₁₃^-1*λ₃₄^-1 + ϱ₁₃^-1*λ₄₁^-1 + 200ϱ₁₃^-1*λ₄₂^-1 + 2ϱ₁₃^-1*λ₄₃^-1 + ϱ₁₄^-1*ϱ₁₂ + ϱ₁₄^-1*ϱ₁₃ + ϱ₁₄^-1*ϱ₂₁ + ϱ₁₄^-1*ϱ₃₁ + ϱ₁₄^-1*ϱ₄₂ + ϱ₁₄^-1*ϱ₄₃ + ϱ₁₄^-1*λ₂₁ + ϱ₁₄^-1*λ₃₁ + ϱ₁₄^-1*λ₄₂ + ϱ₁₄^-1*λ₄₃ + ϱ₁₄^-1*ϱ₁₂^-1 + ϱ₁₄^-1*ϱ₁₃^-1 + ϱ₁₄^-1*ϱ₂₁^-1 + 200ϱ₁₄^-1*ϱ₂₃^-1 + 2ϱ₁₄^-1*ϱ₂₄^-1 + ϱ₁₄^-1*ϱ₃₁^-1 + 200ϱ₁₄^-1*ϱ₃₂^-1 + 2ϱ₁₄^-1*ϱ₃₄^-1 + ϱ₁₄^-1*ϱ₄₂^-1 + ϱ₁₄^-1*ϱ₄₃^-1 + 2ϱ₁₄^-1*λ₁₂^-1 + 2ϱ₁₄^-1*λ₁₃^-1 + ϱ₁₄^-1*λ₂₁^-1 + 200ϱ₁₄^-1*λ₂₃^-1 + 2ϱ₁₄^-1*λ₂₄^-1 + ϱ₁₄^-1*λ₃₁^-1 + 200ϱ₁₄^-1*λ₃₂^-1 + 2ϱ₁₄^-1*λ₃₄^-1 + ϱ₁₄^-1*λ₄₂^-1 + ϱ₁₄^-1*λ₄₃^-1 + ϱ₂₁^-1*ϱ₁₃ + ϱ₂₁^-1*ϱ₁₄ + ϱ₂₁^-1*ϱ₂₃ + ϱ₂₁^-1*ϱ₂₄ + ϱ₂₁^-1*ϱ₃₂ + ϱ₂₁^-1*ϱ₄₂ + ϱ₂₁^-1*λ₁₃ + ϱ₂₁^-1*λ₁₄ + ϱ₂₁^-1*λ₃₂ + ϱ₂₁^-1*λ₄₂ + ϱ₂₁^-1*ϱ₁₃^-1 + ϱ₂₁^-1*ϱ₁₄^-1 + ϱ₂₁^-1*ϱ₂₃^-1 + ϱ₂₁^-1*ϱ₂₄^-1 + 2ϱ₂₁^-1*ϱ₃₁^-1 + ϱ₂₁^-1*ϱ₃₂^-1 + 200ϱ₂₁^-1*ϱ₃₄^-1 + 2ϱ₂₁^-1*ϱ₄₁^-1 + ϱ₂₁^-1*ϱ₄₂^-1 + 200ϱ₂₁^-1*ϱ₄₃^-1 + ϱ₂₁^-1*λ₁₃^-1 + ϱ₂₁^-1*λ₁₄^-1 + 2ϱ₂₁^-1*λ₂₃^-1 + 2ϱ₂₁^-1*λ₂₄^-1 + 2ϱ₂₁^-1*λ₃₁^-1 + ϱ₂₁^-1*λ₃₂^-1 + 200ϱ₂₁^-1*λ₃₄^-1 + 2ϱ₂₁^-1*λ₄₁^-1 + ϱ₂₁^-1*λ₄₂^-1 + 200ϱ₂₁^-1*λ₄₃^-1 + ϱ₂₃^-1*ϱ₁₂ + ϱ₂₃^-1*ϱ₂₁ + ϱ₂₃^-1*ϱ₂₄ + ϱ₂₃^-1*ϱ₃₁ + ϱ₂₃^-1*ϱ₃₄ + ϱ₂₃^-1*ϱ₄₂ + ϱ₂₃^-1*λ₁₂ + ϱ₂₃^-1*λ₃₁ + ϱ₂₃^-1*λ₃₄ + ϱ₂₃^-1*λ₄₂ + ϱ₂₃^-1*ϱ₁₂^-1 + ϱ₂₃^-1*ϱ₂₁^-1 + ϱ₂₃^-1*ϱ₂₄^-1 + ϱ₂₃^-1*ϱ₃₁^-1 + ϱ₂₃^-1*ϱ₃₄^-1 + 200ϱ₂₃^-1*ϱ₄₁^-1 + ϱ₂₃^-1*ϱ₄₂^-1 + 2ϱ₂₃^-1*ϱ₄₃^-1 + ϱ₂₃^-1*λ₁₂^-1 + 2ϱ₂₃^-1*λ₁₃^-1 + 200ϱ₂₃^-1*λ₁₄^-1 + 2ϱ₂₃^-1*λ₂₁^-1 + 2ϱ₂₃^-1*λ₂₄^-1 + ϱ₂₃^-1*λ₃₁^-1 + ϱ₂₃^-1*λ₃₄^-1 + 200ϱ₂₃^-1*λ₄₁^-1 + ϱ₂₃^-1*λ₄₂^-1 + 2ϱ₂₃^-1*λ₄₃^-1 + ϱ₂₄^-1*ϱ₁₂ + ϱ₂₄^-1*ϱ₂₁ + ϱ₂₄^-1*ϱ₂₃ + ϱ₂₄^-1*ϱ₃₂ + ϱ₂₄^-1*ϱ₄₁ + ϱ₂₄^-1*ϱ₄₃ + ϱ₂₄^-1*λ₁₂ + ϱ₂₄^-1*λ₃₂ + ϱ₂₄^-1*λ₄₁ + ϱ₂₄^-1*λ₄₃ + ϱ₂₄^-1*ϱ₁₂^-1 + ϱ₂₄^-1*ϱ₂₁^-1 + ϱ₂₄^-1*ϱ₂₃^-1 + 200ϱ₂₄^-1*ϱ₃₁^-1 + ϱ₂₄^-1*ϱ₃₂^-1 + 2ϱ₂₄^-1*ϱ₃₄^-1 + ϱ₂₄^-1*ϱ₄₁^-1 + ϱ₂₄^-1*ϱ₄₃^-1 + ϱ₂₄^-1*λ₁₂^-1 + 200ϱ₂₄^-1*λ₁₃^-1 + 2ϱ₂₄^-1*λ₁₄^-1 + 2ϱ₂₄^-1*λ₂₁^-1 + 2ϱ₂₄^-1*λ₂₃^-1 + 200ϱ₂₄^-1*λ₃₁^-1 + ϱ₂₄^-1*λ₃₂^-1 + 2ϱ₂₄^-1*λ₃₄^-1 + ϱ₂₄^-1*λ₄₁^-1 + ϱ₂₄^-1*λ₄₃^-1 + ϱ₃₁^-1*ϱ₁₂ + ϱ₃₁^-1*ϱ₁₄ + ϱ₃₁^-1*ϱ₂₃ + ϱ₃₁^-1*ϱ₃₂ + ϱ₃₁^-1*ϱ₃₄ + ϱ₃₁^-1*ϱ₄₃ + ϱ₃₁^-1*λ₁₂ + ϱ₃₁^-1*λ₁₄ + ϱ₃₁^-1*λ₂₃ + ϱ₃₁^-1*λ₄₃ + ϱ₃₁^-1*ϱ₁₂^-1 + ϱ₃₁^-1*ϱ₁₄^-1 + ϱ₃₁^-1*ϱ₂₃^-1 + ϱ₃₁^-1*ϱ₃₂^-1 + ϱ₃₁^-1*ϱ₃₄^-1 + 2ϱ₃₁^-1*ϱ₄₁^-1 + 200ϱ₃₁^-1*ϱ₄₂^-1 + ϱ₃₁^-1*ϱ₄₃^-1 + ϱ₃₁^-1*λ₁₂^-1 + ϱ₃₁^-1*λ₁₄^-1 + 2ϱ₃₁^-1*λ₂₁^-1 + ϱ₃₁^-1*λ₂₃^-1 + 200ϱ₃₁^-1*λ₂₄^-1 + 2ϱ₃₁^-1*λ₃₂^-1 + 2ϱ₃₁^-1*λ₃₄^-1 + 2ϱ₃₁^-1*λ₄₁^-1 + 200ϱ₃₁^-1*λ₄₂^-1 + ϱ₃₁^-1*λ₄₃^-1 + ϱ₃₂^-1*ϱ₁₃ + ϱ₃₂^-1*ϱ₂₁ + ϱ₃₂^-1*ϱ₂₄ + ϱ₃₂^-1*ϱ₃₁ + ϱ₃₂^-1*ϱ₃₄ + ϱ₃₂^-1*ϱ₄₃ + ϱ₃₂^-1*λ₁₃ + ϱ₃₂^-1*λ₂₁ + ϱ₃₂^-1*λ₂₄ + ϱ₃₂^-1*λ₄₃ + ϱ₃₂^-1*ϱ₁₃^-1 + ϱ₃₂^-1*ϱ₂₁^-1 + ϱ₃₂^-1*ϱ₂₄^-1 + ϱ₃₂^-1*ϱ₃₁^-1 + ϱ₃₂^-1*ϱ₃₄^-1 + 200ϱ₃₂^-1*ϱ₄₁^-1 + 2ϱ₃₂^-1*ϱ₄₂^-1 + ϱ₃₂^-1*ϱ₄₃^-1 + 2ϱ₃₂^-1*λ₁₂^-1 + ϱ₃₂^-1*λ₁₃^-1 + 200ϱ₃₂^-1*λ₁₄^-1 + ϱ₃₂^-1*λ₂₁^-1 + ϱ₃₂^-1*λ₂₄^-1 + 2ϱ₃₂^-1*λ₃₁^-1 + 2ϱ₃₂^-1*λ₃₄^-1 + 200ϱ₃₂^-1*λ₄₁^-1 + 2ϱ₃₂^-1*λ₄₂^-1 + ϱ₃₂^-1*λ₄₃^-1 + ϱ₃₄^-1*ϱ₁₃ + ϱ₃₄^-1*ϱ₂₃ + ϱ₃₄^-1*ϱ₃₁ + ϱ₃₄^-1*ϱ₃₂ + ϱ₃₄^-1*ϱ₄₁ + ϱ₃₄^-1*ϱ₄₂ + ϱ₃₄^-1*λ₁₃ + ϱ₃₄^-1*λ₂₃ + ϱ₃₄^-1*λ₄₁ + ϱ₃₄^-1*λ₄₂ + ϱ₃₄^-1*ϱ₁₃^-1 + ϱ₃₄^-1*ϱ₂₃^-1 + ϱ₃₄^-1*ϱ₃₁^-1 + ϱ₃₄^-1*ϱ₃₂^-1 + ϱ₃₄^-1*ϱ₄₁^-1 + ϱ₃₄^-1*ϱ₄₂^-1 + 200ϱ₃₄^-1*λ₁₂^-1 + ϱ₃₄^-1*λ₁₃^-1 + 2ϱ₃₄^-1*λ₁₄^-1 + 200ϱ₃₄^-1*λ₂₁^-1 + ϱ₃₄^-1*λ₂₃^-1 + 2ϱ₃₄^-1*λ₂₄^-1 + 2ϱ₃₄^-1*λ₃₁^-1 + 2ϱ₃₄^-1*λ₃₂^-1 + ϱ₃₄^-1*λ₄₁^-1 + ϱ₃₄^-1*λ₄₂^-1 + ϱ₄₁^-1*ϱ₁₂ + ϱ₄₁^-1*ϱ₁₃ + ϱ₄₁^-1*ϱ₂₄ + ϱ₄₁^-1*ϱ₃₄ + ϱ₄₁^-1*ϱ₄₂ + ϱ₄₁^-1*ϱ₄₃ + ϱ₄₁^-1*λ₁₂ + ϱ₄₁^-1*λ₁₃ + ϱ₄₁^-1*λ₂₄ + ϱ₄₁^-1*λ₃₄ + ϱ₄₁^-1*ϱ₁₂^-1 + ϱ₄₁^-1*ϱ₁₃^-1 + ϱ₄₁^-1*ϱ₂₄^-1 + ϱ₄₁^-1*ϱ₃₄^-1 + ϱ₄₁^-1*ϱ₄₂^-1 + ϱ₄₁^-1*ϱ₄₃^-1 + ϱ₄₁^-1*λ₁₂^-1 + ϱ₄₁^-1*λ₁₃^-1 + 2ϱ₄₁^-1*λ₂₁^-1 + 200ϱ₄₁^-1*λ₂₃^-1 + ϱ₄₁^-1*λ₂₄^-1 + 2ϱ₄₁^-1*λ₃₁^-1 + 200ϱ₄₁^-1*λ₃₂^-1 + ϱ₄₁^-1*λ₃₄^-1 + 2ϱ₄₁^-1*λ₄₂^-1 + 2ϱ₄₁^-1*λ₄₃^-1 + ϱ₄₂^-1*ϱ₁₄ + ϱ₄₂^-1*ϱ₂₁ + ϱ₄₂^-1*ϱ₂₃ + ϱ₄₂^-1*ϱ₃₄ + ϱ₄₂^-1*ϱ₄₁ + ϱ₄₂^-1*ϱ₄₃ + ϱ₄₂^-1*λ₁₄ + ϱ₄₂^-1*λ₂₁ + ϱ₄₂^-1*λ₂₃ + ϱ₄₂^-1*λ₃₄ + ϱ₄₂^-1*ϱ₁₄^-1 + ϱ₄₂^-1*ϱ₂₁^-1 + ϱ₄₂^-1*ϱ₂₃^-1 + ϱ₄₂^-1*ϱ₃₄^-1 + ϱ₄₂^-1*ϱ₄₁^-1 + ϱ₄₂^-1*ϱ₄₃^-1 + 2ϱ₄₂^-1*λ₁₂^-1 + 200ϱ₄₂^-1*λ₁₃^-1 + ϱ₄₂^-1*λ₁₄^-1 + ϱ₄₂^-1*λ₂₁^-1 + ϱ₄₂^-1*λ₂₃^-1 + 200ϱ₄₂^-1*λ₃₁^-1 + 2ϱ₄₂^-1*λ₃₂^-1 + ϱ₄₂^-1*λ₃₄^-1 + 2ϱ₄₂^-1*λ₄₁^-1 + 2ϱ₄₂^-1*λ₄₃^-1 + ϱ₄₃^-1*ϱ₁₄ + ϱ₄₃^-1*ϱ₂₄ + ϱ₄₃^-1*ϱ₃₁ + ϱ₄₃^-1*ϱ₃₂ + ϱ₄₃^-1*ϱ₄₁ + ϱ₄₃^-1*ϱ₄₂ + ϱ₄₃^-1*λ₁₄ + ϱ₄₃^-1*λ₂₄ + ϱ₄₃^-1*λ₃₁ + ϱ₄₃^-1*λ₃₂ + ϱ₄₃^-1*ϱ₁₄^-1 + ϱ₄₃^-1*ϱ₂₄^-1 + ϱ₄₃^-1*ϱ₃₁^-1 + ϱ₄₃^-1*ϱ₃₂^-1 + ϱ₄₃^-1*ϱ₄₁^-1 + ϱ₄₃^-1*ϱ₄₂^-1 + 200ϱ₄₃^-1*λ₁₂^-1 + 2ϱ₄₃^-1*λ₁₃^-1 + ϱ₄₃^-1*λ₁₄^-1 + 200ϱ₄₃^-1*λ₂₁^-1 + 2ϱ₄₃^-1*λ₂₃^-1 + ϱ₄₃^-1*λ₂₄^-1 + ϱ₄₃^-1*λ₃₁^-1 + ϱ₄₃^-1*λ₃₂^-1 + 2ϱ₄₃^-1*λ₄₁^-1 + 2ϱ₄₃^-1*λ₄₂^-1 + λ₁₂^-1*ϱ₂₃ + λ₁₂^-1*ϱ₂₄ + λ₁₂^-1*ϱ₃₁ + λ₁₂^-1*ϱ₄₁ + λ₁₂^-1*λ₁₃ + λ₁₂^-1*λ₁₄ + λ₁₂^-1*λ₂₃ + λ₁₂^-1*λ₂₄ + λ₁₂^-1*λ₃₁ + λ₁₂^-1*λ₄₁ + λ₁₂^-1*ϱ₂₃^-1 + λ₁₂^-1*ϱ₂₄^-1 + λ₁₂^-1*ϱ₃₁^-1 + λ₁₂^-1*ϱ₄₁^-1 + λ₁₂^-1*λ₁₃^-1 + λ₁₂^-1*λ₁₄^-1 + λ₁₂^-1*λ₂₃^-1 + λ₁₂^-1*λ₂₄^-1 + λ₁₂^-1*λ₃₁^-1 + 2λ₁₂^-1*λ₃₂^-1 + 200λ₁₂^-1*λ₃₄^-1 + λ₁₂^-1*λ₄₁^-1 + 2λ₁₂^-1*λ₄₂^-1 + 200λ₁₂^-1*λ₄₃^-1 + λ₁₃^-1*ϱ₂₁ + λ₁₃^-1*ϱ₃₂ + λ₁₃^-1*ϱ₃₄ + λ₁₃^-1*ϱ₄₁ + λ₁₃^-1*λ₁₂ + λ₁₃^-1*λ₁₄ + λ₁₃^-1*λ₂₁ + λ₁₃^-1*λ₃₂ + λ₁₃^-1*λ₃₄ + λ₁₃^-1*λ₄₁ + λ₁₃^-1*ϱ₂₁^-1 + λ₁₃^-1*ϱ₃₂^-1 + λ₁₃^-1*ϱ₃₄^-1 + λ₁₃^-1*ϱ₄₁^-1 + λ₁₃^-1*λ₁₂^-1 + λ₁₃^-1*λ₁₄^-1 + λ₁₃^-1*λ₂₁^-1 + 2λ₁₃^-1*λ₂₃^-1 + 200λ₁₃^-1*λ₂₄^-1 + λ₁₃^-1*λ₃₂^-1 + λ₁₃^-1*λ₃₄^-1 + λ₁₃^-1*λ₄₁^-1 + 200λ₁₃^-1*λ₄₂^-1 + 2λ₁₃^-1*λ₄₃^-1 + λ₁₄^-1*ϱ₂₁ + λ₁₄^-1*ϱ₃₁ + λ₁₄^-1*ϱ₄₂ + λ₁₄^-1*ϱ₄₃ + λ₁₄^-1*λ₁₂ + λ₁₄^-1*λ₁₃ + λ₁₄^-1*λ₂₁ + λ₁₄^-1*λ₃₁ + λ₁₄^-1*λ₄₂ + λ₁₄^-1*λ₄₃ + λ₁₄^-1*ϱ₂₁^-1 + λ₁₄^-1*ϱ₃₁^-1 + λ₁₄^-1*ϱ₄₂^-1 + λ₁₄^-1*ϱ₄₃^-1 + λ₁₄^-1*λ₁₂^-1 + λ₁₄^-1*λ₁₃^-1 + λ₁₄^-1*λ₂₁^-1 + 200λ₁₄^-1*λ₂₃^-1 + 2λ₁₄^-1*λ₂₄^-1 + λ₁₄^-1*λ₃₁^-1 + 200λ₁₄^-1*λ₃₂^-1 + 2λ₁₄^-1*λ₃₄^-1 + λ₁₄^-1*λ₄₂^-1 + λ₁₄^-1*λ₄₃^-1 + λ₂₁^-1*ϱ₁₃ + λ₂₁^-1*ϱ₁₄ + λ₂₁^-1*ϱ₃₂ + λ₂₁^-1*ϱ₄₂ + λ₂₁^-1*λ₁₃ + λ₂₁^-1*λ₁₄ + λ₂₁^-1*λ₂₃ + λ₂₁^-1*λ₂₄ + λ₂₁^-1*λ₃₂ + λ₂₁^-1*λ₄₂ + λ₂₁^-1*ϱ₁₃^-1 + λ₂₁^-1*ϱ₁₄^-1 + λ₂₁^-1*ϱ₃₂^-1 + λ₂₁^-1*ϱ₄₂^-1 + λ₂₁^-1*λ₁₃^-1 + λ₂₁^-1*λ₁₄^-1 + λ₂₁^-1*λ₂₃^-1 + λ₂₁^-1*λ₂₄^-1 + 2λ₂₁^-1*λ₃₁^-1 + λ₂₁^-1*λ₃₂^-1 + 200λ₂₁^-1*λ₃₄^-1 + 2λ₂₁^-1*λ₄₁^-1 + λ₂₁^-1*λ₄₂^-1 + 200λ₂₁^-1*λ₄₃^-1 + λ₂₃^-1*ϱ₁₂ + λ₂₃^-1*ϱ₃₁ + λ₂₃^-1*ϱ₃₄ + λ₂₃^-1*ϱ₄₂ + λ₂₃^-1*λ₁₂ + λ₂₃^-1*λ₂₁ + λ₂₃^-1*λ₂₄ + λ₂₃^-1*λ₃₁ + λ₂₃^-1*λ₃₄ + λ₂₃^-1*λ₄₂ + λ₂₃^-1*ϱ₁₂^-1 + λ₂₃^-1*ϱ₃₁^-1 + λ₂₃^-1*ϱ₃₄^-1 + λ₂₃^-1*ϱ₄₂^-1 + λ₂₃^-1*λ₁₂^-1 + λ₂₃^-1*λ₂₁^-1 + λ₂₃^-1*λ₂₄^-1 + λ₂₃^-1*λ₃₁^-1 + λ₂₃^-1*λ₃₄^-1 + 200λ₂₃^-1*λ₄₁^-1 + λ₂₃^-1*λ₄₂^-1 + 2λ₂₃^-1*λ₄₃^-1 + λ₂₄^-1*ϱ₁₂ + λ₂₄^-1*ϱ₃₂ + λ₂₄^-1*ϱ₄₁ + λ₂₄^-1*ϱ₄₃ + λ₂₄^-1*λ₁₂ + λ₂₄^-1*λ₂₁ + λ₂₄^-1*λ₂₃ + λ₂₄^-1*λ₃₂ + λ₂₄^-1*λ₄₁ + λ₂₄^-1*λ₄₃ + λ₂₄^-1*ϱ₁₂^-1 + λ₂₄^-1*ϱ₃₂^-1 + λ₂₄^-1*ϱ₄₁^-1 + λ₂₄^-1*ϱ₄₃^-1 + λ₂₄^-1*λ₁₂^-1 + λ₂₄^-1*λ₂₁^-1 + λ₂₄^-1*λ₂₃^-1 + 200λ₂₄^-1*λ₃₁^-1 + λ₂₄^-1*λ₃₂^-1 + 2λ₂₄^-1*λ₃₄^-1 + λ₂₄^-1*λ₄₁^-1 + λ₂₄^-1*λ₄₃^-1 + λ₃₁^-1*ϱ₁₂ + λ₃₁^-1*ϱ₁₄ + λ₃₁^-1*ϱ₂₃ + λ₃₁^-1*ϱ₄₃ + λ₃₁^-1*λ₁₂ + λ₃₁^-1*λ₁₄ + λ₃₁^-1*λ₂₃ + λ₃₁^-1*λ₃₂ + λ₃₁^-1*λ₃₄ + λ₃₁^-1*λ₄₃ + λ₃₁^-1*ϱ₁₂^-1 + λ₃₁^-1*ϱ₁₄^-1 + λ₃₁^-1*ϱ₂₃^-1 + λ₃₁^-1*ϱ₄₃^-1 + λ₃₁^-1*λ₁₂^-1 + λ₃₁^-1*λ₁₄^-1 + λ₃₁^-1*λ₂₃^-1 + λ₃₁^-1*λ₃₂^-1 + λ₃₁^-1*λ₃₄^-1 + 2λ₃₁^-1*λ₄₁^-1 + 200λ₃₁^-1*λ₄₂^-1 + λ₃₁^-1*λ₄₃^-1 + λ₃₂^-1*ϱ₁₃ + λ₃₂^-1*ϱ₂₁ + λ₃₂^-1*ϱ₂₄ + λ₃₂^-1*ϱ₄₃ + λ₃₂^-1*λ₁₃ + λ₃₂^-1*λ₂₁ + λ₃₂^-1*λ₂₄ + λ₃₂^-1*λ₃₁ + λ₃₂^-1*λ₃₄ + λ₃₂^-1*λ₄₃ + λ₃₂^-1*ϱ₁₃^-1 + λ₃₂^-1*ϱ₂₁^-1 + λ₃₂^-1*ϱ₂₄^-1 + λ₃₂^-1*ϱ₄₃^-1 + λ₃₂^-1*λ₁₃^-1 + λ₃₂^-1*λ₂₁^-1 + λ₃₂^-1*λ₂₄^-1 + λ₃₂^-1*λ₃₁^-1 + λ₃₂^-1*λ₃₄^-1 + 200λ₃₂^-1*λ₄₁^-1 + 2λ₃₂^-1*λ₄₂^-1 + λ₃₂^-1*λ₄₃^-1 + λ₃₄^-1*ϱ₁₃ + λ₃₄^-1*ϱ₂₃ + λ₃₄^-1*ϱ₄₁ + λ₃₄^-1*ϱ₄₂ + λ₃₄^-1*λ₁₃ + λ₃₄^-1*λ₂₃ + λ₃₄^-1*λ₃₁ + λ₃₄^-1*λ₃₂ + λ₃₄^-1*λ₄₁ + λ₃₄^-1*λ₄₂ + λ₃₄^-1*ϱ₁₃^-1 + λ₃₄^-1*ϱ₂₃^-1 + λ₃₄^-1*ϱ₄₁^-1 + λ₃₄^-1*ϱ₄₂^-1 + λ₃₄^-1*λ₁₃^-1 + λ₃₄^-1*λ₂₃^-1 + λ₃₄^-1*λ₃₁^-1 + λ₃₄^-1*λ₃₂^-1 + λ₃₄^-1*λ₄₁^-1 + λ₃₄^-1*λ₄₂^-1 + λ₄₁^-1*ϱ₁₂ + λ₄₁^-1*ϱ₁₃ + λ₄₁^-1*ϱ₂₄ + λ₄₁^-1*ϱ₃₄ + λ₄₁^-1*λ₁₂ + λ₄₁^-1*λ₁₃ + λ₄₁^-1*λ₂₄ + λ₄₁^-1*λ₃₄ + λ₄₁^-1*λ₄₂ + λ₄₁^-1*λ₄₃ + λ₄₁^-1*ϱ₁₂^-1 + λ₄₁^-1*ϱ₁₃^-1 + λ₄₁^-1*ϱ₂₄^-1 + λ₄₁^-1*ϱ₃₄^-1 + λ₄₁^-1*λ₁₂^-1 + λ₄₁^-1*λ₁₃^-1 + λ₄₁^-1*λ₂₄^-1 + λ₄₁^-1*λ₃₄^-1 + λ₄₁^-1*λ₄₂^-1 + λ₄₁^-1*λ₄₃^-1 + λ₄₂^-1*ϱ₁₄ + λ₄₂^-1*ϱ₂₁ + λ₄₂^-1*ϱ₂₃ + λ₄₂^-1*ϱ₃₄ + λ₄₂^-1*λ₁₄ + λ₄₂^-1*λ₂₁ + λ₄₂^-1*λ₂₃ + λ₄₂^-1*λ₃₄ + λ₄₂^-1*λ₄₁ + λ₄₂^-1*λ₄₃ + λ₄₂^-1*ϱ₁₄^-1 + λ₄₂^-1*ϱ₂₁^-1 + λ₄₂^-1*ϱ₂₃^-1 + λ₄₂^-1*ϱ₃₄^-1 + λ₄₂^-1*λ₁₄^-1 + λ₄₂^-1*λ₂₁^-1 + λ₄₂^-1*λ₂₃^-1 + λ₄₂^-1*λ₃₄^-1 + λ₄₂^-1*λ₄₁^-1 + λ₄₂^-1*λ₄₃^-1 + λ₄₃^-1*ϱ₁₄ + λ₄₃^-1*ϱ₂₄ + λ₄₃^-1*ϱ₃₁ + λ₄₃^-1*ϱ₃₂ + λ₄₃^-1*λ₁₄ + λ₄₃^-1*λ₂₄ + λ₄₃^-1*λ₃₁ + λ₄₃^-1*λ₃₂ + λ₄₃^-1*λ₄₁ + λ₄₃^-1*λ₄₂ + λ₄₃^-1*ϱ₁₄^-1 + λ₄₃^-1*ϱ₂₄^-1 + λ₄₃^-1*ϱ₃₁^-1 + λ₄₃^-1*ϱ₃₂^-1 + λ₄₃^-1*λ₁₄^-1 + λ₄₃^-1*λ₂₄^-1 + λ₄₃^-1*λ₃₁^-1 + λ₄₃^-1*λ₃₂^-1 + λ₄₃^-1*λ₄₁^-1 + λ₄₃^-1*λ₄₂^-1

We are ready to define the optimisation problem. Function
> `PropertyT.SOS_problem(x, Δ, orbit_data; upper_bound=UB)`

defines the optimisation problem equivalent to the one of the form
\begin{align}
\text{ maximize : } \quad & \lambda\\
\text{under constraints : }\quad & 0 \leqslant \lambda \leqslant \operatorname{UB},\\
     & x - \lambda \Delta = \sum \xi_i^* \xi_i,\\
     & \text{with $\sum \xi_i^* \xi_i$ invariant under the action of $S_2 \wr S_4$}.
\end{align}

```julia
SDP_problem, varP = PropertyT.SOS_problem_primal(elt₄, Δ₄, block_decomposition; upper_bound=0.1);
(SDP_problem,)
```

    ┌ Info: Adding 6231 constraints...
    └ @ PropertyT /home/kalmar/.julia/packages/PropertyT/vcGsE/src/sos_sdps.jl:124

     24.120746 seconds (8.20 M allocations: 33.581 GiB, 7.96% gc time)

    (A JuMP Model
    Maximization problem with:
    Variables: 11047
    Objective function type: JuMP.VariableRef
    `JuMP.GenericAffExpr{Float64,JuMP.VariableRef}`-in-`MathOptInterface.EqualTo{Float64}`: 6231 constraints
    `Array{JuMP.GenericAffExpr{Float64,JuMP.VariableRef},1}`-in-`MathOptInterface.PositiveSemidefiniteConeSquare`: 20 constraints
    `JuMP.VariableRef`-in-`MathOptInterface.LessThan{Float64}`: 1 constraint
    Model mode: AUTOMATIC
    CachingOptimizer state: NO_OPTIMIZER
    Solver name: No optimizer attached.
    Names registered in the model: λ,)

### Solving the problem
Depending on the actual problem one may need to tweak the parameters given to the solver:
 * `eps` sets the requested accuracy,
 * `max_iters` sets the number of iterations to run before solver gives up,
 * `alpha` is a bias parameter ($\alpha \in (0,2)$) which determines the step size (hence the rate of convergence). $\alpha$ close to $2$ shoudl provide fastest initial convergence, but may introduce numerical noise.
 * `acceleration_lookback`: if you experience numerical instability in scs log should be changed to `0`.

The parameters below should be enough to obtain a decent solution for $\operatorname{Adj}_4 + 100.0\operatorname{Op}_4 - 0.1\Delta_4$ in reasonable time (<10 minutes).

```julia
using PropertyT.JuMP
using SCS
warm = nothing
```

```julia
with_SCS = with_optimizer(SCS.Optimizer,
    linear_solver=SCS.DirectSolver,
    eps=1e-10,
    max_iters=10_000,
    alpha=1.5,
    acceleration_lookback=25,
    warm_start=true)

status, warm = PropertyT.solve(SDP_problem, with_SCS, warm);
@show status;
```

    ----------------------------------------------------------------------------
    	SCS v2.1.2 - Splitting Conic Solver
    	(c) Brendan O'Donoghue, Stanford University, 2012
    ----------------------------------------------------------------------------
    Lin-sys: sparse-direct, nnz in A = 8010504
    eps = 1.00e-10, alpha = 1.50, max_iters = 10000, normalize = 1, scale = 1.00
    acceleration_lookback = 25, rho_x = 1.00e-03
    Variables n = 11047, constraints m = 17278
    Cones:	primal zero / dual free vars: 11570
    	linear vars: 1
    	sd vars: 5707, sd blks: 20
    Setup time: 8.97e+01s
    SCS using variable warm-starting
    ----------------------------------------------------------------------------
     Iter | pri res | dua res | rel gap | pri obj | dua obj | kap/tau | time (s)
    ----------------------------------------------------------------------------
         0| 3.46e+20  2.60e+20  1.00e+00 -2.31e+23  1.87e+21  5.59e+22  1.99e-01
       100| 8.05e-04  4.66e-04  5.00e-02  4.02e-02 -1.24e-02  1.95e-15  1.05e+01
       200| 3.06e-04  2.06e-04  2.33e-03  3.49e-02  3.24e-02  8.28e-15  2.08e+01
       300| 2.20e-04  1.50e-04  7.79e-03  9.21e-03  1.34e-03  5.06e-15  3.12e+01
       400| 1.23e-04  9.22e-05  9.82e-04  2.12e-02  2.22e-02  7.79e-16  4.16e+01
       500| 1.08e-04  7.81e-05  1.21e-02  1.22e-02  2.47e-02  1.02e-14  5.19e+01
       600| 8.40e-05  6.04e-05  1.85e-03  4.37e-03  2.51e-03  5.90e-15  6.23e+01
       700| 6.99e-05  5.00e-05  1.01e-03  4.32e-03  5.34e-03  1.13e-15  7.26e+01
       800| 5.73e-05  4.39e-05  2.75e-03  2.33e-03  5.10e-03  1.05e-14  8.29e+01
       900| 4.30e-05  3.50e-05  1.23e-03  2.11e-03  8.76e-04  6.81e-15  9.32e+01
      1000| 3.76e-05  2.80e-05  2.67e-04  2.71e-03  2.97e-03  4.71e-15  1.04e+02
      1100| 2.44e-05  1.79e-05  6.35e-04  2.55e-03  3.19e-03  2.63e-15  1.14e+02
      1200| 2.55e-05  1.96e-05  3.56e-04  1.82e-03  1.46e-03  2.04e-14  1.24e+02
      1300| 1.32e-05  1.16e-05  7.56e-04 -1.02e-03 -1.78e-03  9.40e-15  1.34e+02
      1400| 1.08e-05  8.13e-06  6.76e-04 -1.21e-03 -1.88e-03  8.61e-15  1.45e+02
      1500| 7.78e-06  7.03e-06  1.07e-04  2.65e-04  1.58e-04  2.42e-14  1.55e+02
      1600| 6.93e-06  5.65e-06  2.58e-04  3.38e-04  8.01e-05  2.51e-14  1.65e+02
      1700| 5.30e-06  4.94e-06  1.84e-04 -4.83e-04 -2.98e-04  2.34e-14  1.75e+02
      1800| 6.58e-06  6.49e-06  4.62e-04 -5.02e-04 -9.65e-04  7.54e-15  1.86e+02
      1900| 6.68e-06  6.49e-06  5.31e-04  2.03e-05 -5.11e-04  4.04e-15  1.96e+02
      2000| 5.36e-06  5.03e-06  3.51e-04 -8.41e-05  2.67e-04  1.85e-14  2.06e+02
      2100| 6.41e-06  4.85e-06  2.48e-04  7.09e-05 -1.77e-04  9.05e-15  2.16e+02
      2200| 6.55e-06  6.66e-06  3.96e-04  3.61e-04 -3.59e-05  3.11e-15  2.26e+02
      2300| 6.06e-06  6.42e-06  9.80e-04  3.12e-04  1.29e-03  8.79e-15  2.37e+02
      2400| 5.02e-06  4.55e-06  1.14e-04  4.07e-04  2.93e-04  1.11e-14  2.47e+02
      2500| 1.08e-05  9.33e-06  9.65e-05  1.25e-03  1.35e-03  9.50e-15  2.57e+02
      2600| 2.63e-05  2.06e-05  2.72e-03  4.13e-03  6.88e-03  1.14e-14  2.67e+02
      2700| 5.67e-06  4.68e-06  1.23e-04 -1.17e-04  6.24e-06  2.69e-14  2.78e+02
      2800| 5.19e-06  4.87e-06  3.51e-04  7.82e-05  4.30e-04  1.11e-14  2.88e+02
      2900| 6.07e-06  5.66e-06  5.06e-05 -1.05e-04 -1.55e-04  9.22e-15  2.98e+02
      3000| 4.78e-06  3.70e-06  1.16e-03 -2.16e-04  9.48e-04  2.63e-14  3.08e+02
      3100| 1.80e-06  1.50e-06  3.74e-04  5.71e-05 -3.17e-04  3.64e-15  3.18e+02
      3200| 7.36e-12  6.15e-12  3.89e-10 -3.53e-11 -4.24e-10  3.96e-15  3.29e+02
      3204| 3.61e-13  2.95e-13  9.02e-11  1.22e-11 -7.80e-11  7.20e-16  3.29e+02
    ----------------------------------------------------------------------------
    Status: Solved
    Timing: Solve time: 3.29e+02s
    	Lin-sys: nnz in L factor: 28748612, avg solve time: 9.36e-02s
    	Cones: avg projection time: 3.30e-03s
    	Acceleration: avg step time: 4.10e-03s
    ----------------------------------------------------------------------------
    Error metrics:
    dist(s, K) = 1.1395e-09, dist(y, K*) = 2.0661e-09, s'y/|s||y| = -7.6432e-14
    primal res: |Ax + s - b|_2 / (1 + |b|_2) = 3.6127e-13
    dual res:   |A'y + c|_2 / (1 + |c|_2) = 2.9493e-13
    rel gap:    |c'x + b'y| / (1 + |c'x| + |b'y|) = 9.0154e-11
    ----------------------------------------------------------------------------
    c'x = 0.0000, -b'y = -0.0000
    ============================================================================
    status = MathOptInterface.OPTIMAL

NOTE: if `status = ALMOST_OPTIMAL`, you may need to re-run the cell above.

It seems that solver obtained sum of squares decomposition for $\operatorname{Adj}_4 + 100.0\operatorname{Op}_4 - 0.1\Delta_4$ with $\lambda$:

```julia
λ₄ = value(SDP_problem[:λ])
```

0 . 0 9 9 9 9 9 9 9 9 9 8 7 8 2 1 6 6

To apply the `SOS_residual` function we need to reconstruct matrix `Q` from the semipositive-definite blocks in `SDP_problem`:

```julia
Q₄ = let Ps = [value.(P) for P in varP], bd = block_decomposition
    Qs = real.(sqrt.(Ps));
    PropertyT.reconstruct(Qs, block_decomposition);
end
```

    1777×1777 Array{Float64,2}:
     73.6668      -3.53685      -3.53685      …   0.042403      0.052693
     -3.53685     20.088        -0.672753        -0.00720344   -0.0118432
     -3.53685     -0.672753     20.088           -0.0412075     4.17635e-5
     -3.53685     -0.672753     -0.672753         0.0136568     0.00637814
     -3.53685     -0.909577     -0.399332         0.00507484   -0.0118432
     -3.53685     -0.399332     -0.431527     …  -0.000939495   4.17635e-5
     -3.53685     -0.399332      1.35135          0.000623127   0.00637814
     -3.53685     -0.399332     -0.909577         0.00937818   -0.000377992
     -3.53685     -0.431527     -0.399332         0.00280739   -0.000377992
     -3.53685      1.35135      -0.399332         0.00367772    0.00719231
     -3.53685     -0.399332     -0.399332     …   0.0318183     0.00811301
     -3.53685     -0.431527      1.35135         -0.00728109    0.00811301
     -3.53685      1.35135      -0.431527         0.00512306    0.00785316
      ⋮                                       ⋱   ⋮
     -0.0181961    0.00308358    0.00426268   …  -0.012201     -0.01126
      0.00609812   0.00547639   -0.00683407       0.00421675    0.00893611
      0.00609812  -0.000991355  -0.00105234      -0.0323998     0.00893611
     -0.0179306   -0.00174578   -0.000656216     -0.0022567    -0.012395
     -0.0167704   -0.021978     -0.00857865       0.0290574     0.0019202
     -0.0167704   -0.0122136    -0.00147366   …  -0.0116298     0.0019202
     -0.0599944   -0.0119557    -0.0161813       -0.00655492    0.000431544
     -0.0599944   -0.0123905     0.00256829      -0.0029705     0.000431544
     -0.0195403    0.00735981   -0.000662284     -0.00319418   -0.0453741
      0.042403     0.00507484   -0.000939495      0.000746334   0.0175979
      0.042403    -0.00720344   -0.0412075    …   0.533857      0.0175979
      0.052693    -0.0118432     4.17637e-5       0.0175979     0.16533

```julia
Q₄_aug, check_columns_augmentation = PropertyT.augIdproj(Interval, Q₄);
@assert check_columns_augmentation
```

```julia
elt₄_int = elt₄ - @interval(λ₄)*Δ₄;
residual₄_int = SOS_residual(elt₄_int, Q₄_aug)
@show norm(residual₄_int, 1);
λ₄_cert = @interval(λ₄) - 2*norm(residual₄_int, 1)
@info "λ₄ is certified to be > " λ₄_cert.lo
@info "i.e Adj₄ + $k·Op₄ - ($(λ₄_cert.lo))·Δ₄ ∈ Σ²₂ ISAut(F₄)"
```

     54.242839 seconds (40.43 k allocations: 80.632 MiB)
    norm(residual₄_int, 1) = [1.08665e-05, 1.09478e-05]

    ┌ Info: λ₄ is certified to be >
    │   λ₄_cert.lo = 0.09997810453347668
    └ @ Main In[29]:5
    ┌ Info: i.e Adj₄ + 100.0·Op₄ - (0.09997810453347668)·Δ₄ ∈ Σ²₂ ISAut(F₄)
    └ @ Main In[29]:6

```julia
now()
```

    2020-10-21T14:24:45.043

notebooks/Positivity of Adj_n + kOp_n in ISAut(F_n).ipynb


```python
%matplotlib inline
```

Dynamics of a single particle in free space is the simplest kind of simulation. It allows to check basic functionality of the program, and, besides, it is a good way to become familiar with how the program works.

In absence of external forces, a body moves in straight line with constant velocity

\begin{align}
& \textbf{r}(t) = \textbf{r}_0 + \textbf{v}_0 t
\\
& \textbf{v}(t) = \textbf{v}_0
\end{align}

To get some sense of scales (see below), suppose the particle is an electron that has just passed an 1 keV accelerating potential difference. Its mass `m` and charge `q` are `q = 4.8e-10 [cgs], m = 9.1e-28 [g]`. Since its energy is nonrelativistic, it's possible to calculate its speed simply as $v = \sqrt{ 2 E / m } = 1.808e+09 ~ [cm/s]$. To cover a `10 [cm]` distance with such speed, it will take the electron `t = 5.530e-09 [s] ~ 6 [ns]`.

```python
from math import *

m = 9.8e-28
q = 4.8e-10
print( "q = {:.3e} [cgs]".format( q ) )
print( "m = {:.3e} [g]".format( m ) )

ev_to_cgs = 1.60218e-12
E = 1000 * ev_to_cgs
v = sqrt( 2 * E / m )
z = 10
t = z / v
print( "E = {:.3e} [eV] = {:.3e} [erg]".format( E / ev_to_cgs, E ) )
print( "v = {:.3e} [cm/s]; p = {:.3e} [g * cm/s]".format( v, v * m ) )
print( "z = {:.3e} [cm]".format( z ) )
print( "t = {:.3e} [s]".format( t ) )
```

To perform a simulation, it's necessary to prepare a config file. It is an `ini`-file with sections describing the simulation parameters, e.g.:

```
[TimeGrid]
total_time = 6e-09
time_save_step = 6e-12
time_step_size = 6e-12

[SpatialMesh]
grid_x_size = 5.0
grid_x_step = 0.5
grid_y_size = 5.0
grid_y_step = 0.5
grid_z_size = 15.0
grid_z_step = 1.5

[ParticleSourceBox.emit_single_particle]
box_x_left = 0.11
box_x_right = 0.1
...
```
If Ef is invoked from the command line, this file is passed as an argument:

```
./ef.out conf.ini
```

The list of supported config sections can be found in the wiki: https://github.com/epicf/ef/wiki/Supported-Config-File-Sections .

Config classes can be used to create, visualize and read/write to ini the config file with python or jupyter.

```python
from ef.config.components import *
from ef.config.config import Config
from ef.config.visualizer import Visualizer3d
Visualizer3d()

```

First, it's necessary to set a total time of the simulation and a time step.
Let's use the estimates above as guiding values and set the total time to `6e-9 [s]`.
We use `1000` time steps, so that `time_step_size = 6.0e-12 [s]`.
Besides, it's necessary to decide at which time steps the state of the whole simulation should be saved to the disk.
To save each step, `time_save_step` is set equal to `time_step_size`: `time_save_step = 6.0e-12`.

```python
single_particle_in_free_space_conf = ""

time_grid_sec = """
[TimeGrid]
total_time = 6e-09
time_save_step = 6e-12
time_step_size = 6e-12
"""

single_particle_in_free_space_conf = single_particle_in_free_space_conf + time_grid_sec

print( single_particle_in_free_space_conf )
```

```python
timegrid = TimeGridConf(total=6e-09, save_step=6e-12, step=6e-12)
print(repr(timegrid))
print(timegrid)
```

Next we need to define size of a computational volume.
Domain size is set to 15 [cm] along the z-axis and 5 [cm] along the x- and y-axes.
The parameters for PIC-mesh are also defined in this section.
Since we are going to use noninteracting particle model instead of PIC, they are not used and can be set arbitrary.

```python
spat_mesh_sec = """
[SpatialMesh]
grid_x_size = 5.0
grid_x_step = 0.5
grid_y_size = 5.0
grid_y_step = 0.5
grid_z_size = 15.0
grid_z_step = 1.5
"""

single_particle_in_free_space_conf = single_particle_in_free_space_conf + spat_mesh_sec

print( single_particle_in_free_space_conf )
```

```python
mesh = SpatialMeshConf((5, 5, 15), (.5, .5, 1.5))
print(repr(mesh))
print(mesh)
Visualizer3d().visualize([mesh])

```

Next, a particle source.
We need a single particle at startup ( `initial_number_of_particles = 1` ), approximately 1 [mm] away from
coordinate axis origin at the bottom-left-near corner of the domain (`shape = Box( origin = (0.1, ...` below and `box_x_left = 0.10 ...` in the ini-version).
Charge and mass are set to those of the electron.
Momentum corresponding to 1 keV energy is `1.772e-18 [g * cm / s]`.
Such value is set for momentum along the z-axis.
Momenta along the x- and y-axes could be set to zero; instead they are chosen 3 times smaller than the z-axis momentum
(domain size along the x and y is 3 times smaller than along the z).
To prevent any variation in momentum, the `temperature` is set to 0.
Notice that the source is given a descriptive name: `emit_single_particle` in this case.

```python
emit_single_particle_sec = """
[ParticleSourceBox.emit_single_particle]
box_x_left = 0.11
box_x_right = 0.1
box_y_bottom = 0.1
box_y_top = 0.11
box_z_near = 0.1
box_z_far = 0.11
initial_number_of_particles = 1
particles_to_generate_each_step = 0
mean_momentum_x = 6e-19
mean_momentum_y = 6e-19
mean_momentum_z = 1.77e-18
temperature = 0.0
charge = 4.8e-10
mass = 9.8e-28
"""

single_particle_in_free_space_conf = single_particle_in_free_space_conf + emit_single_particle_sec

print( single_particle_in_free_space_conf )
```

```python
source = ParticleSourceConf("emit_single_particle", Box((.1, .1, .1), (.01, .01, .01)), 1, 0,
                           (6e-19, 6e-19, 1.77e-18), 0., 4.8e-10, 9.8e-28)
print(repr(source))
print(source)
Visualizer3d().visualize([mesh, source]) # small dot near (0, 0, 0) because mesh is so big
```

Next section is boundary conditions.
In a free space, potentials on each boundary should be equal.
It is possible to simply set them to zero.

```python
boundary_sec = """
[BoundaryConditions]
boundary_phi_right = 0.0
boundary_phi_left = 0.0
boundary_phi_bottom = 0.0
boundary_phi_top = 0.0
boundary_phi_near = 0.0
boundary_phi_far = 0.0
"""

single_particle_in_free_space_conf = single_particle_in_free_space_conf + boundary_sec

print( single_particle_in_free_space_conf )
```

```python
boundary_conditions = BoundaryConditionsConf(0)
print(repr(boundary_conditions))
print(boundary_conditions)
```

Particle interaction model allows to choose between noninteracting particles, particle interacting with binary forces and PIC method. Since there is only one particle, there is no need to use PIC, and noninteracting mode is enough. Moreover, PIC will lead to wrong results (because particle creates electric field that acts back on the particle).

```python
particle_interaction_model_sec = """
[ParticleInteractionModel]
particle_interaction_model = noninteracting
"""

single_particle_in_free_space_conf = single_particle_in_free_space_conf + particle_interaction_model_sec

print( single_particle_in_free_space_conf )
```

```python
model = ParticleInteractionModelConf('noninteracting')
print(repr(model))
print(model)
```

The last step is to specify pattern for output file names.
They will be of the form `single_particle_free_space_0001000.h5`, where `0001000` is a time step number.

```python
output_sec = """
[OutputFilename]
output_filename_prefix = single_particle_free_space_
output_filename_suffix = .h5
"""

single_particle_in_free_space_conf = single_particle_in_free_space_conf + output_sec

print( single_particle_in_free_space_conf )
```

To start the simulation, the config should saved into file and provided as an argument to the `ef.out`, e.g.:

```
ef.out ./single_particle_in_free_space_conf.ini
```

EfJupyter module provides a wrapper `EfRunner` to do this.

```python
file_conf = OutputFileConf('single_particle_free_space_', '.h5')
print(repr(file_conf))
print(file_conf)
```

You can check that config objects describe the same simulation:

```python
conf = Config(timegrid, mesh, [source], [], file_conf, boundary_conditions, model)
print(conf)
print(conf.export_to_string())
assert repr(Config.from_string(single_particle_in_free_space_conf)) == repr(conf)
conf.visualize_all(Visualizer3d())
```

To run outside Jupyter just save the config file

-  with any text editor
-  or with `efconf.export_to_file()`

Run `ef config.ini` in the directory where you want simulation to run and save results.

To run in python from Jupyter:

```python
# if you start from .ini
# conf = Config.from_fname('config.ini')
domain = conf.make()
domain.start_pic_simulation()

```

To run outside python (for example, C++ ef):

```python
conf.export_to_fname('config.ini')
```

```python
!ef config.ini
```

After the simulation finishes, a bunch of `*.h5` files emerge in the directory.

```python
!ls
```

To open these files and glance over the results, an [Hdfview](https://support.hdfgroup.org/products/java/hdfview/) is a convenient tool.
In this simulation, two places are of interest: `current time` and particle position
and momentum at this time moment:

<p align="center">

</p>

Each created `h5`-file corresponds to a different time step.
If we were able to extract time, position and momentum of the particle from each file, we could have obtained numerical trajectory, which could be compared to the analytical one.

Data extraction and plotting are accomplished by the accompanying [`plot.py`](https://github.com/epicf/ef/blob/master/examples/single_particle_in_free_space/plot.py) python script (see below). Its constituent parts are described further. The script produces a 3d plot and side views of the numerical and analytical trajectories. Besides, kinetic energies are compared.

```python
import pandas as pd
import os, glob
import h5py
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D

def main():
    num = extract_num_trajectory_from_out_files()
    an = eval_an_trajectory_at_num_time_points( num )
    plot_trajectories( num , an )

def extract_num_trajectory_from_out_files():
    out_files = glob.glob("single_particle_free_space_[0-9]*.h5")

    num_trajectory = []
    for f in out_files:
        num_trajectory.append( extract_time_pos_mom( f ) )

    num_trajectory = sorted([ x for x in num_trajectory if x ], key = lambda x: x[0])
    return pd.DataFrame.from_records(num_trajectory, columns=('t', 'x', 'y', 'z', 'px', 'py', 'pz'))

def extract_time_pos_mom( h5file ):
    with h5py.File(h5file, mode="r") as h5:
        t = h5["/time_grid"].attrs["current_time"]
        particle_array = h5["/particle_sources/0/particle_arrays/0"]
        pos = particle_array["positions"][0]
        momentum = particle_array["momentums"][0]
    return [t] + list(pos) + list(momentum)

def eval_an_trajectory_at_num_time_points( num_trajectory ):
    global particle_mass
    particle_mass, pos0, mom0 =  get_mass_and_initial_pos_and_mom()

    an_trajectory = []
    for t in num_trajectory.t:
        pos = coords( particle_mass, t, pos0, mom0 )
        mom = momenta( t, mom0 )
        an_trajectory.append([t] + list(pos) + list(mom))

    return pd.DataFrame.from_records(an_trajectory, columns=('t', 'x', 'y', 'z', 'px', 'py', 'pz'))

def get_mass_and_initial_pos_and_mom():
    initial_out_file = "single_particle_free_space_0000000.h5"
    with h5py.File( initial_out_file, mode="r") as h5:
        particle_array = h5["/particle_sources/0/particle_arrays/0"]
        m = particle_array.attrs["mass"]
        pos0 = particle_array["positions"][0]
        mom0 = particle_array["momentums"][0]
    return m, pos0, mom0

def momenta( t, mom0 ):
    return mom0

def coords( m, t, pos0, mom0 ):
    pos = pos0 + mom0 / m * t
    return pos

def plot_trajectories( num , an ):
    plot_3d( num, an )
    plot_2d( num, an )
    plot_kin_en( num , an )

def plot_3d( num, an ):
    fig = plt.figure()
    ax = fig.gca( projection='3d' )
    ax.plot( num.x, num.z, num.y, 'b.', markersize = 12, label = "Num" )
    ax.plot( an.x, an.z, an.y,  'g-', linewidth = 3, label = "An" )
    ax.set_xlabel('X [cm]')
    ax.set_ylabel('Z [cm]')
    ax.set_zlabel('Y [cm]')
    plt.legend( loc = 'upper left', title="3d" )
    #print( 'Saving 3d trajectory plot to "3d.png"' )
    #plt.savefig('3d.png')
    plt.show()

def plot_2d( num, an ):
    plt.figure( figsize=( 16, 6 ) )
    plt.subplots_adjust( left = None, bottom = None,
                         right = None, top = None,
                         wspace = 0.4, hspace = None )
    #XY
    ax = plt.subplot(131)
    plt.plot( num.x, num.y,
              linestyle='', marker='o',
              label = "Num" )
    plt.plot( an.x, an.y,
              linestyle='-', marker='', lw = 2,
              label = "An" )
    ax.set_xlabel('X [cm]')
    ax.set_ylabel('Y [cm]')
    plt.legend( loc = 'upper left', title="XY" )
    #ZX
    ax = plt.subplot(132)
    plt.plot( num.z, num.x,
        linestyle='', marker='o',
        label = "Num" )
    plt.plot( an.z, an.x,
              linestyle='-', marker='', lw = 2,
              label = "An" )
    ax.set_xlabel('Z [cm]')
    ax.set_ylabel('X [cm]')
    plt.legend( loc = 'upper left', title="ZX" )
    #ZY
    ax = plt.subplot(133)
    plt.plot( num.z, num.y,
        linestyle='', marker='o',
        label = "Num" )
    plt.plot( an.z, an.y,
              linestyle='-', marker='', lw = 2,
              label = "An" )
    ax.set_xlabel('Z [cm]')
    ax.set_ylabel('Y [cm]')
    plt.legend( loc = 'upper left', title="ZY" )
    #print( 'Saving 2d trajectory projection plots to "2d.png"' )
    #plt.savefig('2d.png')
    plt.show()

def plot_kin_en( num , an ):
    global particle_mass
    E_num = (num.px**2 + num.py**2 + num.pz**2) / ( 2 * particle_mass )
    E_an = (an.px**2 + an.py**2 + an.pz**2) / ( 2 * particle_mass )
    t = num.t
    plt.figure()
    axes = plt.gca()
    axes.set_xlabel( "t [s]" )
    axes.set_ylabel( "E [erg]" )
    # axes.set_ylim( [min( E_an.min(), E_num.min() ),
    #                 max( E_an.max(), E_num.max() ) ] )
    line, = plt.plot( t, E_num, 'o' )
    line.set_label( "Num" )
    line, = plt.plot( t, E_an, ls = 'solid', lw = 3 )
    line.set_label( "An" )
    plt.legend( loc = 'upper right' )
    #print( 'Saving kinetic energy comparison plot to "kin_en.png"' )
    #plt.savefig('kin_en.png')
    plt.show()

main()
```

It can be seen, that numerical trajectory (points) coincides with the analytical (line) and that the energy is conserved during the simulation.

### Plotting script

The `main` function of the script does exactly what is described above: extracts numerical trajectory from the output files, evaluates analytical trajectory at the extracted time points and plots both numerical and analytical trajectories on the same axes.

```
def main():
    num = extract_num_trajectory_from_out_files()
    an = eval_an_trajectory_at_num_time_points( num )
    plot_trajectories( num , an )
```

It uses [h5py](http://www.h5py.org/) library to read from h5 files, [numpy](http://www.numpy.org/) to simplify working with arrays and [matplotlib](https://matplotlib.org/) to perform plotting of the trajectory.

```
import os, glob
import h5py
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
```

Let's examine the function to obtain the numerical trajectory:

```
def extract_num_trajectory_from_out_files():
    out_files = find_necessary_out_files()                           # (*1)

    num_trajectory = []
    for f in out_files:
        num_trajectory.append( extract_time_pos_mom( f ) )           # (*2)

    num_trajectory = remove_empty_and_sort_by_time( num_trajectory ) # (*3)
    num_trajectory = np.array( num_trajectory,                       # (*4)
                               dtype=[('t','float'),
                                      ('x','float'), ('y','float'), ('z','float'),
                                      ('px','float'), ('py','float'),('pz','float')])
    return( num_trajectory )
```

(\*1): To extract data, first we find all `*.h5` files in the current directory.
(\*2): Then the script iterates over them and extracts a relevant data from each one.
(\*3): In the end of this process, `num_trajectory` array contains positions and velocities of particle at different
time steps. In is convenient to sort it over time values.
(\*4): After the previous step the numerical trajectory is in a format of a list of tuples:
`[ (t, x, y, z, px, py, pz), ..... ]` . It is convenient to convert it into one of the `np.array` types to simplify further manipulations with it.

For analytical trajectory we need the initial position and momentum.
They can be extracted from the first h5-file:

```
def get_mass_and_initial_pos_and_mom():
    initial_out_file = "single_particle_free_space_0000000.h5"
    h5 = h5py.File( initial_out_file, mode="r")
    m = h5["/ParticleSources/emit_single_particle"].attrs["mass"][0]
    x0 = h5["/ParticleSources/emit_single_particle/position_x"][0]
    y0 = h5["/ParticleSources/emit_single_particle/position_y"][0]
    z0 = h5["/ParticleSources/emit_single_particle/position_z"][0]
    px0 = h5["/ParticleSources/emit_single_particle/momentum_x"][0]
    py0 = h5["/ParticleSources/emit_single_particle/momentum_y"][0]
    pz0 = h5["/ParticleSources/emit_single_particle/momentum_z"][0]
    h5.close()
    return( m, x0, y0, z0, px0, py0, pz0 )
```

With this function, the analytical trajectory can be computed at the same
time points as the numerical one:

```
def eval_an_trajectory_at_num_time_points( num_trajectory ):
    global particle_mass
    particle_mass, x0, y0, z0, px0, py0, pz0 =  get_mass_and_initial_pos_and_mom()
    #
    an_trajectory = np.empty_like( num_trajectory )
    for i, t in enumerate( num_trajectory['t'] ):
        x, y, z = coords( particle_mass, t, x0, y0, z0, px0, py0, pz0 )
        px, py, pz = momenta( t, px0, py0, pz0 )
        an_trajectory[i] = ( t, x, y ,z, px, py, pz )
    #
    return( an_trajectory )
```

Finally, both numerical and analytical trajectories are plotted in 3d and side views.
Kinetic energies are also compared.

```
def plot_trajectories( num , an ):
    plot_3d( num, an )
    plot_2d( num, an )
    plot_kin_en( num , an )
```

```python

```


```python
# import all relevant libraries dependencies and set up the backend
import qsharp
import numpy as np
import matplotlib
import sys
import time
import progressbar
import matplotlib.pyplot as plt
from qsharp import Result
from Quantum.Hubbard import Evolve, EvolveSingleTimestepDummy
import exact_diagonalisation.ed_hubbard as ED
from cycler import cycler
%matplotlib inline

c1_a = '#003AF0'
c2_a = '#008F24'
c3_a = '#FE7B22'
c4_a = '#FE000C'
c5_a = '#FB30F2'
c6_a = '#82E0AA'
c7_a = '#9966CC'
c8_a = '#7FFFD4'
c9_a = '#66FF00'
c10_a = '#8B008B'
c11_a = '#000000'
colors = [c1_a, c2_a, c3_a, c4_a, c5_a, c6_a, c7_a, c8_a, c9_a, c10_a, c11_a]
```

# Time Evolution

Assumes a chain of lench L, a ladder of size L x 2 or an L x L lattice of sites. Uses the values of J, U and $\mu$ to evolve.

\begin{equation}\label{eq:}
H = -J\sum_{i, j}\sum_{\sigma} (c^{\dagger}_{i, \sigma}c_{j, \sigma} + h.c) + U\sum_{i}n_{i, \uparrow}n_{i, \downarrow} - \mu\sum_{i}\sum_{\sigma}n_{i, \sigma}
\end{equation}

A random initial state with N1 spin downs and N2 spin ups is generated where N1 and N2 are provided by the user

```python
# define system parameters
attempt_ED = True
p = {}
p['L'] = 3 # system length
p['W'] = 3 # system width
p['N1'] = 1 # number of particles in 1
p['N2'] = 1 # number of particles in 2
p['t1'] = p['t2'] = J = 0.5 # hopping
p['U12'] = U = 0.3 # on-site interaction between 1 and 2
p['mu1'] = p['mu2'] = mu = 0 # chemical potential
p['t_initial'] = 0.0 # begin of time evolution
p['dt'] = dt = 0.01 # time-step
p['t_final'] = total_time = 1.0 # end of time evolution
p['N'] = N = p['L'] * p['W'] # system size
ave = 50
if p['W'] == 2:
    structure = 3 # ladder
elif p['W'] == p['L']:
    structure = 4 # lattice
else:
    structure = 1 # chain
if N > 9:
    attempt_ED = False
```

```python
# generate random initial state
initial_state = [0 for _ in range(N)]
N1s = np.random.choice(range(N), p['N1'], replace=False)
N2s = np.random.choice(range(N), p['N2'], replace=False)
for i in N1s:
    initial_state[i] += 1
for i in N2s:
    initial_state[i] += 2
```

```python
# do exact evolution
if attempt_ED:
    state_table = ED.generate_state_table(p)
    tic = time.time()
    sim, state_table = ED.evolve(
        p, state_table, initial_state, kind="list",
        correlation_measurement=False, trotterised=True)
    toc = time.time()
    print("Exact evolution took ", toc-tic, "s")
```

    Exact evolution took  0.6433570384979248 s

```python
# do qsharp evolution
tic = time.time()
times = np.linspace(0, total_time, num=10)
result_up = np.zeros((len(times), len(initial_state)))
result_down = np.zeros((len(times), len(initial_state)))
progress_bar = progressbar.ProgressBar(max_value=ave)
points_taken = 0
for _ in range(ave):
    for i, t in enumerate(times):
        res = Evolve.simulate(
            initialState=initial_state, time=t, dt=dt, mu=mu, U=U, J=J,
            structure=structure)
        result_up[i] += ED.project_state_into_spinsectors(res)[0] / ave
        result_down[i] += ED.project_state_into_spinsectors(res)[1] / ave
    points_taken += 1
    progress_bar.update(points_taken)
toc = time.time()
print("Q# Evolution took {} mins {} s".format(int((toc-tic) // 60), int((toc-tic) % 60)))
```

```python
# plottable_times = np.append(np.array([0]), times)
fig = plt.figure()
for i in range(len(initial_state)):
    fig = plt.figure()
    if attempt_ED:
        plt.plot(sim['Time'], sim['Re(N1 Site {})'.format(i + 1)], color=colors[i])
        plt.plot(sim['Time'], sim['Re(N2 Site {})'.format(i + 1)], color=colors[i + 1])
    plt.plot(times, result_up[:, i],
             color=colors[i], marker='o', linestyle='--', label='N{}up'.format(i + 1))
    plt.plot(times, result_down[:, i],
             color=colors[i + 1], marker='o', linestyle='--', label='N{}down'.format(i + 1))
    plt.xlabel('time')
    plt.legend()
```

# Resource Estimation

Estimate the resources for the full evolution (1st order) and for a single timestep. Currently the depth only measures T gates of which there are none. The number of Cliffords and Rotations will be slightly off because the Y gate is implemented as a Rotation in Q# as it is not in the 'Intrinsic' gate set.

```python
# estimate resources
full_gatecount = Evolve.estimate_resources(initialState=initial_state, time=total_time, dt=dt, mu=mu, U=U, J=J,
                                           structure=structure)
timestep_gatecount = EvolveSingleTimestepDummy.estimate_resources(
                        initialState=initial_state, dt=dt, mu=mu, U=U, J=J, structure=structure)

print('Full Evolution')
print(*['\t{}: {}\n'.format(k, v) for k, v in full_gatecount.items()])
print('Single Timestep')
print(*['\t{}: {}\n'.format(k, v) for k, v in timestep_gatecount.items()])
```

    Full Evolution
    	CNOT: 261200
     	QubitClifford: 208802
     	R: 246000
     	Measure: 210
     	T: 0
     	Depth: 0
     	Width: 210
     	BorrowedWidth: 0

    Single Timestep
    	CNOT: 2612
     	QubitClifford: 2088
     	R: 2460
     	Measure: 0
     	T: 0
     	Depth: 0
     	Width: 210
     	BorrowedWidth: 0

```python

```