SAGBI homotopy testing notebook
To upload the package one has to run the following commands.
[1]:
using Pkg
Pkg.add("SagbiHomotopy")
Updating registry at `~/.julia/registries/General.toml`
Resolving package versions...
No Changes to `~/.julia/environments/v1.11/Project.toml`
No Changes to `~/.julia/environments/v1.11/Manifest.toml`
Now it is ready to use. We also use HomotopyContinuation.jl and Oscar.jl to define polynomials and rings for our examples.
[6]:
using Oscar
using HomotopyContinuation
using SagbiHomotopy
___ ____ ____ _ ____
/ _ \ / ___| / ___| / \ | _ \ | Combining ANTIC, GAP, Polymake, Singular
| | | |\___ \| | / _ \ | |_) | | Type "?Oscar" for more information
| |_| | ___) | |___ / ___ \| _ < | Manual: https://docs.oscar-system.org
\___/ |____/ \____/_/ \_\_| \_\ | Version 1.2.2
We start with small utils functions that we have. wDeg: computes dot product of two exponent vectors.
[7]:
wDeg([1,2,3],[-4,5,6])
[7]:
24
get_coeffs_exponents: computes coefficients and exponents of a polynomial \(f \in S\).
[8]:
S, (x, y) = Oscar.polynomial_ring(Oscar.QQ, [:x, :y])
f = x^3*y + 3x*y^2 + 1
f_terms = get_coeffs_exponents(f)
[8]:
3×2 Matrix{Any}:
1 [3, 1]
3 [1, 2]
1 [0, 0]
initial_form: Computes initial form of \(f \in S\) w.r.t. \(\omega\).
[9]:
w = [1,2]
initial_form(f, S, w)
[9]:
x^3*y + 3*x*y^2
SagbiCriterion: Checks SAGBI property for \(G \subset R\) for a given weight \(\omega\).
[11]:
R, (l, x, y, z) = Oscar.polynomial_ring(Oscar.QQ, ["l","x","y","z"]);
G = [z, z*x, z*y, z*x*(x^2+y^2),z*y*(x^2+y^2), l*z, l*z*x, l*z*y, l*z*x*(x^2+y^2), l*z*y*(x^2+y^2)];
SagbiCriterion(G, R, [2,1,3,4])
[11]:
true
weightVectorsRealizingSAGBI: Compute a weight vector for which \(G\) is SAGBI basis, if there exists one, and verify it with Sagbi criterion.
[12]:
w = weightVectorsRealizingSAGBI(G, R)
SagbiCriterion(G, R, w)
[12]:
true
[14]:
R, (s, u, v) = Oscar.polynomial_ring(Oscar.QQ, ["s","u","v"])
G = [s, s*u,s*v, s*u*(u^2 +v^2), s*v*(u^2 +v^2)]
weightVectorsRealizingSAGBI(G, R)
[14]:
3-element Vector{Int64}:
-1
-2
-1
get_weight: Detects a weight for which we have SAGBI basis as a parameterization of a multiprojective variety.
[15]:
@var x, y, z
sagbi = [[x,y,(x^2 + y^2), 1], [y, z, (x^2 + y^2), (x^3 + z^3)]]
w = get_weight(sagbi)
[15]:
3-element Vector{Int64}:
-2
-1
-3
degree_map: Degree of the map defined by a set \(G\).
[16]:
@var x,y
G = [x*(x^2 + y^2 - 2*x), x*(5-4*y), y*(x^2 + y^2 - 2*x), y*(5-4*y)]
degree_map(G)
[16]:
2
get_base_locus: Compute base locus of the map defined by a set \(G\).
[17]:
get_base_locus(G)
Tracking 9 paths... 100%|███████████████████████████████| Time: 0:00:04
# paths tracked: 9
# non-singular solutions (real): 2 (0)
# singular endpoints (real): 0 (0)
# total solutions (real): 2 (0)
[17]:
2-element Vector{Vector{ComplexF64}}:
[1.0000000000000002 + 0.7499999999999993im, 1.2499999999999998 + 5.726196391229601e-17im]
[1.0000000000000002 - 0.7500000000000001im, 1.25 + 2.7723089573884378e-17im]
weight_deformation_for_poly: construct Gröbner degeneration of a polynomial w.r.t. a weight.
[18]:
@var u, v
weight_deformation_for_poly(u^3 + u*v^2, [u, v], [1, 2])
[18]:
We continue with examples of the functionality of our main function: sagbi_homotopy. The first one is Example 4.1 from the paper.
[19]:
@var x,y,z
sagbi = [x^2+1, y^2+1, x*y + z^2, 1]
w = get_weight(sagbi) #(-2,-2,-3)
[19]:
3-element Vector{Int64}:
-2
-2
-3
[20]:
degree_map(sagbi) #8
degree_monomial_map(sagbi, w) #8
[20]:
8
[ ]:
@var p[1:4]
lin_sys = [ randn(ComplexF64,3,4)*p ]
sagbi_homotopy(lin_sys, sagbi; weight = w, degreeCheck = true) #8 solutions
Tracking 8 paths... 100%|███████████████████████████████| Time: 0:00:00
# paths tracked: 8
# non-singular solutions (real): 8 (0)
# singular endpoints (real): 0 (0)
# total solutions (real): 8 (0)
SAGBI homotopy successfully completed with 8 solutions.
(Result with 8 solutions
=======================
• 8 paths tracked
• 8 non-singular solutions (0 real)
• random_seed: 0xda8b24f5
, Vector{ComplexF64}[[-2.824700736042358 - 9.956533639002785e-33im, 1.9471048797625395e-32 - 3.2941938169367444im, 2.2694939292157943 - 2.050041108191621im], [-2.824700736042358 - 3.8795139355513765e-31im, 3.7036623309969963e-31 - 3.2941938169367444im, -2.2694939292157943 + 2.050041108191621im], [-2.824700736042359 - 1.2511397791280264e-31im, -1.209120357173385e-31 + 3.2941938169367453im, 2.2694939292157947 + 2.050041108191622im], [-2.824700736042359 + 5.795766252856706e-31im, 5.493153167092888e-31 + 3.294193816936745im, -2.2694939292157947 - 2.050041108191622im], [2.8247007360423577 + 5.173483843289766e-31im, 4.911436869136407e-31 - 3.294193816936744im, 2.269493929215794 + 2.050041108191621im], [2.82470073604236 + 8.620068237625805e-31im, 8.156282636834246e-31 - 3.2941938169367457im, -2.269493929215795 - 2.050041108191622im], [2.8247007360423577 + 6.531669290484572e-31im, -6.185599664041674e-31 + 3.294193816936744im, 2.2694939292157943 - 2.050041108191621im], [2.82470073604236 - 3.223529734978748e-30im, 3.0558081640576806e-30 + 3.294193816936746im, -2.269493929215795 + 2.0500411081916226im]])
We pass to Example 4.2. Here we consider the system which is a linear section of biprojective variety.
[23]:
@var x, y, z
sagbi = [[x, y, (x^2 + y^2), 1], [y, z, (x^2 + y^2), (x^3 + z^3)]]
w = get_weight(sagbi) #(-1,-2,-3)
degree_map(sagbi) #1
degree_monomial_map(sagbi, w) #1
[23]:
1
[ ]:
@var p[1:4]
@var q[1:4]
lin_sys = [ randn(ComplexF64,2,4)*p , randn(ComplexF64,1,4)*q]
sagbi_homotopy(lin_sys, sagbi; weight = w) #6 solutions
Tracking 6 paths... 100%|███████████████████████████████| Time: 0:00:00
# paths tracked: 6
# non-singular solutions (real): 6 (0)
# singular endpoints (real): 0 (0)
# total solutions (real): 6 (0)
SAGBI homotopy successfully completed with 6 solutions.
(Result with 6 solutions
=======================
• 6 paths tracked
• 6 non-singular solutions (0 real)
• random_seed: 0xd91786f4
, Vector{ComplexF64}[[-0.6215252282226934 - 1.7413498948359345im, 1.4285131350562092 - 0.5108738165905927im, 1.0992216280431268 - 1.695842713459241im], [-0.6215252282226933 + 1.7413498948359345im, 1.428513135056209 + 0.5108738165905926im, 1.0992216280431268 + 1.6958427134592409im], [-0.6215252282226933 - 1.7413498948359345im, 1.428513135056209 - 0.5108738165905926im, 0.7755803168644473 + 1.9029240719685625im], [-0.6215252282226934 + 1.7413498948359343im, 1.428513135056209 + 0.5108738165905927im, -1.8748019449075741 + 0.20708135850932152im], [-0.6215252282226933 - 1.7413498948359345im, 1.4285131350562092 - 0.5108738165905926im, -1.8748019449075741 - 0.20708135850932163im], [-0.6215252282226933 + 1.7413498948359343im, 1.4285131350562088 + 0.5108738165905926im, 0.7755803168644472 - 1.9029240719685623im]])
Now we present Example 4.3. The function sagbi_homotopy computes only part of the solutions and returns an error message saying that there are missing solutions. In this case we obtain only two of the four expected solutions outside the base locus.
[26]:
@var x,y
sagbi = [[x*(x^2 + y^2 - 2*x), x*(5-4*y), y*(x^2 + y^2 - 2*x), y*(5-4*y)]]
w = get_weight(sagbi) # [-2,-1]
degree_map(sagbi) # 2
degree_monomial_map(sagbi,w) #1
@var p[1:4]
lin_sys = [ rand(ComplexF64,2,4) *p ]
@time res, sols = sagbi_homotopy(lin_sys, sagbi; weight = w)
Error: degree of monomial parameterisation drops from 2 to 1. SAGBI homotopy will not find all the solutions.
SAGBI homotopy successfully completed with 2 solutions.
1.058920 seconds (4.02 M allocations: 197.203 MiB, 98.87% compilation time)
[26]:
(Result with 2 solutions
=======================
• 2 paths tracked
• 2 non-singular solutions (0 real)
• random_seed: 0xdded9f49
, Vector{ComplexF64}[[-0.36126850088434753 + 0.34726254536260237im, 2.3401115363609044 + 0.9678715328624288im], [7.251781859407573 - 3.473638398789833im, 0.9277462498669447 + 11.041188590796573im]])
To compute the remaining solutions from the base locus we set the optional input getBaseLocus to true in the main function.
[30]:
res, sols = sagbi_homotopy(lin_sys, sagbi; weight = w, getBaseLocus = true)
Error: degree of monomial parameterisation drops from 2 to 1. SAGBI homotopy will not find all the solutions.
SAGBI homotopy successfully completed with 4 solutions.
[30]:
(Result with 2 solutions
=======================
• 2 paths tracked
• 2 non-singular solutions (0 real)
• random_seed: 0xce523470
, Any[ComplexF64[7.251781859407573 - 3.47363839878983im, 0.9277462498669398 + 11.041188590796573im], ComplexF64[-0.36126850088434753 + 0.34726254536260204im, 2.3401115363609035 + 0.9678715328624286im], ComplexF64[1.0000000000000002 - 0.75im, 1.25 + 3.6178252795306946e-17im], ComplexF64[0.9999999999999999 + 0.7499999999999997im, 1.25 + 9.248798790699409e-17im]])
[31]:
sols
[31]:
4-element Vector{Any}:
ComplexF64[7.251781859407573 - 3.47363839878983im, 0.9277462498669398 + 11.041188590796573im]
ComplexF64[-0.36126850088434753 + 0.34726254536260204im, 2.3401115363609035 + 0.9678715328624286im]
ComplexF64[1.0000000000000002 - 0.75im, 1.25 + 3.6178252795306946e-17im]
ComplexF64[0.9999999999999999 + 0.7499999999999997im, 1.25 + 9.248798790699409e-17im]