Monodromy

We're solving a system by monodromy

The monodromy method

An alternative to using the solve function is solving a polynomial system $F=(f_1,\ldots,f_n)$ by monodromy. This approach is more efficient, but requires the user to provide at least one solution of $F=0$. Here is the basic idea:

Suppose $x$ is a solution $F(x)=0$ and that $F=F_{u_0}$ is a point in a family of polynomial systems $\mathcal{F}=\{F_u : u\in \mathbb{C}^k\}$ which is defined with $k\geq 1$ parameters. The monodromy method consists in moving around $u$ in a loop starting and ending at $u_0$ while tracking $x$ along that loop. After one iteration usually one has found a new solution $y\in \mathbb{C}^n$. This process then is repeated until some stopping criterion is fulfilled.

The general syntax for this is monodromy_solve(F, x₀, u₀) where we call $(x_0, u_0)$ a start pair.

Here is a simple example. Take

$$F_u(x,y) = \begin{bmatrix} x^4 + y - 2u_1\\ x^4 + x^2 - 2u_2y^2 \end{bmatrix}.$$

For $u=1$ we have the solution $(x,y) = (1,1)$. For finding all solutions of $F_2$ we use

using HomotopyContinuation
@var x y u[1:2]
F = System([x^4 + y - 2u[1], x^4 + x^2 - 2*u[2]*y^2]; parameters = u)
monodromy_solve(F, [1, 1], [1, 1])
MonodromyResult
===============
• return_code → :heuristic_stop
• 8 solutions
• 88 tracked loops
• random_seed → 0x170fb647

Instead of providing explicitly a start pair, you can also let the program perform a random search for a start pair using the find_start_pair routine. This is automatically done, if you don't provide a start pair:

res = monodromy_solve(F, [1, 1], [1, 1])
MonodromyResult
===============
• return_code → :heuristic_stop
• 8 solutions
• 56 tracked loops
• random_seed → 0x437da29f

You can then obtain the generated parameters $u_0$

parameters(res)
2-element Array{Complex{Float64},1}:
 0.0038611666763959164 + 0.13680689997048212im
  -0.14196466931492574 + 0.6958312604959469im

Group Actions

If the set of solutions of F is invariant under some group actions you can exploit this in your computation.

monodromy_solve(F, x, u₀, group_actions = G)

computes only with equivalence classes modulo G.

monodromy_solve(F, x, u₀, group_action = G, equivalence_classes = false)

computes only with all solutions but exploits G to find solutions more quickly.

In the above example, the group that interchanges x and y acts on the solution set of F. We can use the group that multiplies x by $\pm 1$.

monodromy_solve(F, [1, 1], [1, 1], group_action = a -> [[-a[1], a[2]]])
MonodromyResult
===============
• return_code → :heuristic_stop
• 4 classes of solutions (modulo group action)
• 40 tracked loops
• random_seed → 0x156b9866

Now, we found only 4 solutions: one from each orbit. If we suppress computing with equivalence classes, then

monodromy_solve(F, [1, 1], [1, 1], group_action = a -> [[-a[1], a[2]]], equivalence_classes = false)
MonodromyResult
===============
• return_code → :heuristic_stop
• 8 solutions
• 80 tracked loops
• random_seed → 0x0ef98350