In this guide we want to take a deep dive into the modeling language (ModelKit
) provided
by HomotopyContinuation.jl and also provide some tips along the way on how to best
formulate your specific problem.
This guide is complementary to the package function documentation
where all available functions are described.
Variables
We start with the basic building block of every problem: variables.
You can construct a variable using the Variable
constructor.
Let's start by creating variables x
and y
.
julia> using HomotopyContinuation
julia> x, y = Variable(:x), Variable(:y)
(x, y)
Since this is somewhat repetitive we provide the macro @var
to automatically do this for us
julia> @var x y
(x, y)
Often it is convenient to work with a vector or matrix of variables (or even at tensor).
For this the @var
macro interprets Julia's indexing syntax as a hint to create an array of variables
## Create variables a₁,a₂,a₃ and b₁₋₁, b₁₋₂, b₂₋₁ and b₂₋₂
julia> @var a[1:3] b[1:2, 1:2];
## a is vector
julia> a
3-element Array{Variable,1}:
a₁
a₂
a₃
## b is a matrix
julia> b
2×2 Array{Variable,2}:
b₁₋₁ b₁₋₂
b₂₋₁ b₂₋₂
## We can index them as expected
julia> b[2,2]
b₂₋₂
Variables are identified by their name, so two variables are identical if they have the same name
julia> x == y
false
julia> x == Variable(:x)
true
The default variable ordering is lexicographic, independently from when variables got created.
julia> @var y x
(y, x)
julia> x < y
true
Expressions
After constructing variables we can construct some expressions using the basic
arithmetic functions *
, -
, +
, /
.
julia> f = (x + 2y)^3
(x + 2y)^3
As you notice the expression exactly stays as we formulated it.
In case you really want to see the expanded expression you can use expand
julia> expand(f)
12*x*y^2 + 6*x^2*y + x^3 + 8*y^3
You can do also basic manipulations. Let's compute the gradient of f
julia> differentiate(f, [x, y])
2-element Array{Expression,1}:
3*(x + 2*y)^2
6*(x + 2*y)^2
Systems
A System
is the basic input to the solve
and monodromy_solve
functions of HomotopyContinuation.jl, as well as to many other functions.
The role of a System
is to specify the variable ordering and to (possibly) declare some of the variables as parameters.
Let's consider an example from our introduction guide.
# define f
@var x y
f = (x^4 + y^4 - 1) * (x^2 + y^2 - 2) + x^5 * y
# define new variables u₁, u₂ and λ
@var u[1:2] λ
# Compute the gradient of f
∇f = differentiate(f, [x,y])
C = System([[x,y] - u - ∇f .* λ; f]; variables = [x,y,λ], parameters = u)
System of length 3
3 variables: x, y, λ
2 parameters: u₁, u₂
-u₁ + x - λ*(5*x^4*y + 4*(-2 + x^2 + y^2)*x^3 + 2*(-1 + x^4 + y^4)*x)
-u₂ + y - λ*(4*(-2 + x^2 + y^2)*y^3 + 2*(-1 + x^4 + y^4)*y + x^5)
x^5*y + (-2 + x^2 + y^2)*(-1 + x^4 + y^4)
Here you can see that C
is a system consisting of 3 polynomials in 3 variables with 2 parameters u
.