Algebraic Geometry in Sage¶
File for the general methods concerning Algebraic Geometry
In this file we include several useful methods that can be written in a generic way involving reasoning over Algebraic Geometry. Our main concern will be Projective curves, although sometimes the methods will work with Affine varieties.
This package is based on Sage implementation of Algebraic geometry such as subschemes, coordinate rings and morphism. For further information, look to the documentation of each particular method.
- AUTHORS:
- Antonio Jimenez-Pastor (2020-04-11): initial version
- TODO:
- do the examples of the package
This package is under the terms of GNU General Public License version 3.
-
comb_walks.alggeo.
apply_map
(*args, **kwds)¶ Method to apply a map between projective varieties.
This method applies a morphism given by
map
to a pointpoint
. Since the morphism is between projective varieties, it is described by a list of polynomials. Ifpoint
is not a common zero for all those polynomials, the image is just the evaluation of each polynomial on the point.However, there are times where the point is a common zero for all the components and we still have an evaluation. In this method we focus on the particular case when the domain of
map
is a projective plane curve.See method
eval_at_zero_on_variety()
to know exactly how this evaluation is performed in each of the projective components of the image.- INPUT:
map
: the morphism between projective varieties.point
: a point on the domain ofmap
. This point can be given as an actual point on the domain or it can also be a list of coordinates.
- OUTPUT:
- A point \(P\) in the codomain such that
map(point) == P
or aNotImplementedError
in case the domain is not an algebraic curve, the curve is not smooth on the required point or the direct application does not work.
EXAMPLES:
sage: from comb_walks.alggeo import * sage: P2 = ProjectiveSpace(2, QQ, 'xyz'); x,y,z = P2.gens(); O = P2([0,0,1]) sage: C = P2.subscheme(x^2 - y*z); O in C True sage: h = Hom(C,C)([z*y, z*x, x*y]); # (x, x^2) --> (1/x, 1/x^2) sage: h(O) Traceback (most recent call last): ... ValueError: [0, 0, 0] does not define a valid point since all entries are 0 sage: apply_map(h, O) (0 : 1 : 0) sage: apply_map(h,O) in h.codomain() True
This method allows also points on algebraic extensions of the ground field:
sage: F = NumberField(QQ['a']("a^2-2"), 'a'); a = F.gens()[0] sage: apply_map(h, (a, 2, 1)) (1/2*a : 1/2 : 1) sage: G = NumberField(QQ['i']("i^2+1"), 'i'); i = G.gens()[0] sage: apply_map(h, (i, 1, 1)) # point not on the curve Traceback (most recent call last): ... TypeError: Coordinates [i, 1, 1] do not define a point on ... sage: apply_map(h, (i,-1,1)) (-i : -1 : 1)
Also, this method can compute the image in each of the components of the product of Projective spaces:
sage: C = P2.subscheme((-4)*z^3 + y^2*z + (-13/4)*x*z^2 + (-7/8)*z^3) sage: P1P1 = ProjectiveSpace(1, QQ, 'x').cartesian_product(ProjectiveSpace(1,QQ,'y')); x0,x1,y0,y1 = P1P1.gens() sage: D = P1P1.subscheme(-x0*x1*y0^2 + x0*x1*y0*y1 - x0^2*y1^2 - x0*x1*y1^2 - x1^2*y1^2) sage: h = Hom(C,D)([(-24)*z, 24*x + (6)*z, 12*x + 12*y + (3)*z, 24*x + (6)*z]); apply_map(h, (0,1,0)) (0 : 1 , 1 : 0)
-
comb_walks.alggeo.
asymptotics
(*args, **kwds)¶ Method to compute a asymptotic approximation of a rational function.
This methods allows the user to compute asymptotic information around one point on a variety. This variety must be a plane curve or the code woult not work properly.
This method will check that the given point (which can be defined in an algebraic extension field) is on the curve and then compute the local expansion of the rational function given by
func
around that point.This method is equivalent to
order_at_variety()
when the point is the origin. This is an enhanced method that allows more flexibility on the point and take care of the changes of coordinates required to compute this asymptotic data.- INPUT:
variety
: a hypersurface that defines a plane affine curve after its dehomogenization.func
: a rational function on the variety. This method will check out that it is a valid rational function. This means either it is an affine rational function in the usual sense, or both numerator and denominator need to be homogeneous of the same degree.point
: a point on the variety. It can have coordinates in extensions of the base ring of the variety.
- OUTPUT:
A triplet containing:
- The order of the function
func
atpoint
on the variety. - The first non-zero coefficient of the expansion of
func
aroundpoint
. - The local parameter on
variety
used to compute the expansion offunc
aroundpoint
.
- The order of the function
EXAMPLES:
sage: from comb_walks.alggeo import * sage: P2 = ProjectiveSpace(2, QQ, 'xyz'); x,y,z = P2.gens() sage: C = P2.subscheme(x^2 - y*z); # the usual parabola sage: O = origin(C); P = C([0,1,0]); # origin and the point at infinity sage: asymptotics(C, x, O) (1, 1, x/z) sage: asymptotics(C, y, O) (2, 1, x/z) sage: asymptotics(C, x/z, O) == asymptotics(C, x, O) True sage: asymptotics(C, x/z, P) (-1, 1, x/y) sage: asymptotics(C, y/z, P) (-2, 1, x/y) sage: asymptotics(C, y/z - (y/x)^2, P) (+Infinity, 0, x/y) sage: asymptotics(C, (x^2 - 3*y^2)/(7*x^3), P) (-1, -3/7, x/y) sage: asymptotics(C, (x^2 - 3*y^2)/(7*x^3) + (3/7)*(y/x), P) (1, 1/7, x/y)
This method also allows to study the asymptotics around algebraic points:
sage: F = QQ.extension(QQ[x](x^2 + 1), 'i'); i = F.gens()[0] sage: Q = point_extension([i, -1, 1], C) sage: asymptotics(C, x^2+1, Q) (1, (2*i), (x + (-i)*z)/z) sage: asymptotics(C, (y^2-1)/(x^2+1), Q) (0, -2, (x + (-i)*z)/z)
-
comb_walks.alggeo.
decompose_at_zero
(*args, **kwds)¶ Method that decomposes an affine curve at \((0,0)\) in a convinient way.
This method takes a plane curve that is smooth at \((0,0)\) and then computes a decomposition of the form
\[f(x,y) = y(b+h(x,y)) + x^dg(x),\]where the following properties hold:
- \(f(x,y)\) is the curve,
- \(x\) is a local parameter at \((0,0)\),
- \(y\) is the other coordinate for the curve,
- \(b\) is a constant,
- \(h(x,y)\) is a polynomial with \(h(0,0) = 0\),
- \(g(x)\) is a polynomial with \(g(0)=0\).
This indicates that \(x\) has a zero of order 1 at \((0,0)\) and \(y\) has a zero of order \(d\). This can easily help to compute the order of rational functions over the curve at \((0,0)\).
This method cache the result, although different calls with different
main_var
arguments will lead to repeat computations sice we may have that the other variable is NOT a local parameter.- INPUT:
curve
: a projective hypersurface or the defining polynomial in two variables of the curve.main_var
: optional argument to indicate which of the variables is better for considering as a local parameter on the curve.
- OUTPUT:
- The output of this method is the tuple \((d,g,b,h,X,Y)\) where \(d\), \(g\), \(b\), \(h\) are the described elements before, \(X\) is the local parameter chosen and \(Y\) the remaining variable.
EXAMPLES:
sage: from comb_walks.alggeo import * sage: R.<x,y> = QQ[] sage: f = x^4 + 2*y^2*x^2 - y; decompose_at_zero(f) (4, 1, -1, 2*x^2*y, x, y) sage: R.<x,y,z> = QQ[] sage: f = x^3 - 3*x^2*y + 3*x*y^2 - y^3 + x; decompose_at_zero(f) (3, -1, 1, x^2 - 3*x*y + 3*y^2, y, x) sage: R.<x,y,z> = QQ.extension(QQ['i']("i^2+1"), 'i')[]; i = R.base().gens()[0] sage: f = i*z^3 - 2*(i-1)*x^2*z + x - z; decompose_at_zero(f) (1, 1, -1, (-2*i + 2)*x^2 + (i)*z^2, x, z) sage: f = z + x + y; decompose_at_zero(f) Traceback (most recent call last): ... TypeError: The curve ''x + y + z'' is defined with an innapropriate number of variables (Expected 2, got 3) sage: f = x^3 - x^2 - 3*y^2; decompose_at_zero(f) Traceback (most recent call last): ... ValueError: The curve ''x^3 - x^2 - 3*y^2'' is singular at the point (0,0) sage: f = x^2 - 2*y + 1; decompose_at_zero(f) Traceback (most recent call last): ... ValueError: The curve ''x^2 - 2*y + 1'' does not go through the point (0,0) sage: f = 3*y^3 + 2*x*y^2 + y; decompose_at_zero(f) (+Infinity, 0, 1, 2*x*y + 3*y^2, x, y)
We can use the argument
main_var
to try to use that variable as a local parameter. Only if both variables are local parameters the result will be different:sage: f = x^3 - y; decompose_at_zero(f, x) (3, 1, -1, 0, x, y) sage: decompose_at_zero(f, y) (3, 1, -1, 0, x, y) sage: f = x^3 - x - y; decompose_at_zero(f, x) (1, x^2 - 1, -1, 0, x, y) sage: decompose_at_zero(f, y) (1, -1, -1, x^2, y, x)
This method can also be applied to projective varieties that defines plane curves:
sage: P1P1 = ProjectiveSpace(QQ, 1, 'x').cartesian_product(ProjectiveSpace(QQ, 1, 'y')) sage: x0,x1,y0,y1 = P1P1.gens() sage: C = P1P1.subscheme(x0^2*y1 - x1^2*y0); # the usual parabola sage: decompose_at_zero(C, x0) (2, 1, -1, 0, x0, y0) sage: P2 = ProjectiveSpace(QQ, 2, 'xyz'); x, y, z = P2.gens() sage: C = P2.subscheme(x^3 - 2*y^2*z + x*z^2) sage: decompose_at_zero(C) (2, -2, 1, x^2, y, x)
-
comb_walks.alggeo.
dehomogenize_at_zero
(variety)¶ Method to dehomogenize a variety defining polynomials at the origin.
This method dehomogenize the defining polynomials of an algebraic variety taking into account the different types of homogenization. Since in Projective Spaces there are (usually) several ways to dehomogenize, we take the affine chart define at the origin of the ambient space.
- INPUT:
variety
: an algebraic variety. It can be either an ambient space or a subscheme.
EXAMPLES:
sage: from comb_walks.alggeo import * sage: P2 = ProjectiveSpace(2, QQ, 'xyz'); x, y, z = P2.gens() sage: C = P2.subscheme(x^2 - y*z); dehomogenize_at_zero(C) [x^2 - y] sage: C = P2.subscheme(x^3 - 3*z*x^2 + x*y*z - y^2*z + z^3); dehomogenize_at_zero(C) [x^3 - 3*x^2 + x*y - y^2 + 1] sage: P1P1 = ProjectiveSpace(1, QQ, 'x').cartesian_product(ProjectiveSpace(1, QQ, 'y')) sage: x0, x1, y0, y1 = P1P1.gens() sage: C = P1P1.subscheme(x0^2*y1 - x1^2*y0); dehomogenize_at_zero(C) [x0^2 - y0] sage: C = P1P1.subscheme(x0^3*y1*y0 - y0^2*x1*x0^2 + y1^2*x1^2*x0 + y1^2*x1^3); dehomogenize_at_zero(C) [x0^3*y0 - x0^2*y0^2 + x0 + 1]
-
comb_walks.alggeo.
eval_at_zero_on_variety
(*args, **kwds)¶ Method to evaluate a list of polynomials at the origin over a curve
This method computes the projective image of a list a polynomial functions at the point the origin using the information that those polynomials are defined over a hypersurface
variety
. This “projective” image means that not all of the values can be zero at the same time.First, we use the equation of the curve to reduce the polynomials and, if there is a non-zero polynomial, we compute the value of the list. For doing this we require that
variety
is a hypersurface (i.e., it is defined with only one polynomial) and smooth at the origin.This method is closely related to the method
apply_map()
. This method is allowed to receive as input both a unique polynomial defining a curve or a hypersurface (see methodorder_at_variety()
). Essentially, any input where we can decompose the algebraic object using the methoddecompose_at_zero()
.- INPUT:
polys
: list of polynmoials we want to evaluate at \((0,0)\).variety
: either a hypersurface or a polynomial defining a hypersurface.
- OUTPUT:
- A list of values resulting after removing the zeros of the polynomials.
EXAMPLES:
sage: from comb_walks.alggeo import * sage: P2 = ProjectiveSpace(2, QQ, 'xyz'); x,y,z = P2.gens() sage: C = P2.subscheme(x^2 - y*z); # usual parabola sage: eval_at_zero_on_variety([x^2, y], C) [1, 1] sage: eval_at_zero_on_variety([x^2, y], x^2 - y) [1, 1] sage: C = P2.subscheme(x^3 - x^2*z - y^2*z) sage: eval_at_zero_on_variety([x^2-1, y^3+2-x^2], C) Traceback (most recent call last): ... ValueError: The curve ''x^3 - x^2 - y^2'' is singular at the point (0,0) sage: C = P2.subscheme(x^2 - y*z + z^2) sage: eval_at_zero_on_variety([x^2-1, y^3+2-x^2], C) Traceback (most recent call last): ... ValueError: The curve ''x^2 - y + 1'' does not go through the point (0,0)
-
comb_walks.alggeo.
expand_at_point
(variety, func, point, bound)¶ Method to expand a rational function on a variety using a local parameter.
Given a projective variety \(A\) and a point \(P \in A\) where the variety is smooth, we can have a local parameter \(t \in C(A)\), i.e., a function that vanishes at \(P\) with order 1. This local parameter generates the ideal of all rational functions over \(A\) that vanish at \(P\).
In fact, given a rational function \(f \in C(A)\), we can compute a local expansion of \(f\) around \(P\) using this local parameter such that:
\[f = \sum_{k\geq d} f_d t^d,\]where \(d\) is defined as the order of \(f\) at \(P\).
This method computes a local parameter \(t\) for the variety given by
variety
and the corresponding sequence of elements \(f_k\) for \(d \leq k < bound\).- INPUT:
variety
: the variety \(A\) to perform the computations,func
: the rational function over \(A\). It can be given a an affine rational function (and we homogenize it) or as a projective rational function (i.e., a rational function defined as a quotient of two homogeneous polynomials of same degree).point
: a point \(P\) on the variety \(A\).bound
: and integer number.
- OUTPUT:
- A tuple
(d,t)
such thatd[n]
returns the coefficient \(f_n\) in the expansion with respect tot
offunc
aroundpoint
invariety
.
EXAMPLES:
sage: from comb_walks.alggeo import * sage: P2 = ProjectiveSpace(2, QQ, 'xyz'); x,y,z = P2.gens() sage: C = P2.subscheme(x^3 - 3*y^2*z + x^2*z + y*z^2); O = origin(C) sage: expand_at_point(C,1/x^3, O, 10) ({-3: 1, -2: 0, -1: 0, 0: 0, 1: 0, 2: 0, 3: 0, 4: 0, 5: 0, 6: 0, 7: 0, 8: 0, 9: 0}, x/z) sage: expand_at_point(C,x/y, O, 5) ({-1: -1, 0: 1, 1: -4, 2: 1, 3: 8, 4: 10}, x/z) sage: all(expand_at_point(C,1/x^3 - x/y, O,10)[0].get(i,0) == expand_at_point(C,1/x^3, O,10)[0].get(i,0) - expand_at_point(C,x/y, O,10)[0].get(i,0) for i in range(-3,9)) True
- TODO:
- Add examples and tests
-
comb_walks.alggeo.
homogenize_function_on_variety
(func, variety)¶ Method to homogenize a rational function using the coordinates of a variety.
This method takes a rational function or a polynomial and computes its rational homogenize equivalent, i.e., a rational function where the numerator and the denominator are homogeneous of the same degree.
Since there are several ways to homogenize, we use the homogenization on each projective component of the variety provided. If the homogeneous variable appeared on the function, and it is not a valid rational function, we raise an error. Otherwise we add the necessary variables.
- INPUT:
func
: the rational fucntion to homogenizevariety
: an algebraic variety used to the homogenization.
EXAMPLES:
sage: from comb_walks.alggeo import * sage: P2 = ProjectiveSpace(2, QQ, 'xyz'); x,y,z = P2.gens() sage: C = P2.subscheme(x^3 - 3*y*z^2 + x^2*z -z^3) sage: homogenize_function_on_variety(x, C) x/z sage: homogenize_function_on_variety(y, P2) y/z sage: homogenize_function_on_variety(x^2 - y, C) (x^2 - y*z)/z^2 sage: homogenize_function_on_variety((x^2 - y^2)/(x*y), C) (x^2 - y^2)/(x*y) sage: homogenize_function_on_variety(x*z - y^3, P2) Traceback (most recent call last): ... ValueError: The homogenization variable (z) appears and the function is not a rational function
This method also wors for producs of Projective spaces:
sage: P1P2 = ProjectiveSpace(1, QQ, 'x').cartesian_product(ProjectiveSpace(2, QQ, 'y')) sage: x0, x1, y0, y1, y2 = P1P2.gens() sage: D = P1P2.subscheme(x0^2*y2^2 - x0*x1*y0*y1 + x1^2*y0^2) sage: homogenize_function_on_variety(x0 - y1, D) (-x1*y1 + x0*y2)/(x1*y2) sage: homogenize_function_on_variety(y0, P1P2) y0/y2 sage: homogenize_function_on_variety(y2, D) Traceback (most recent call last): ... ValueError: The homogenization variable (y2) appears and the function is not a rational function sage: homogenize_function_on_variety(x1*y1/y2, P1P2) Traceback (most recent call last): ... ValueError: The homogenization variable (x1) appears and the function is not a rational function sage: homogenize_function_on_variety((x0 - x1)*(y0 - y1 - y2)/(x0 * y1), P1P2) (x0*y0 - x1*y0 - x0*y1 + x1*y1 - x0*y2 + x1*y2)/(x0*y1) sage: homogenize_function_on_variety(x1*y0/x0, D) x1*y0/(x0*y2)
-
comb_walks.alggeo.
is_hypersurface
(variety)¶ Method to decide wether a variety is a hypersurface or not.
A hypersurface in affine geometry is an affine variety defined with one unique equation. This then can be extended to any type of projectivized space (multiple projectivations or standar projectivation).
EXAMPLES:
sage: from comb_walks.alggeo import * sage: P1P1 = ProjectiveSpace(1, QQ, 'x').cartesian_product(ProjectiveSpace(1, QQ, 'y')) sage: x0, x1, y0, y1 = P1P1.gens() sage: is_hypersurface(P1P1) False sage: is_hypersurface(P1P1.subscheme(x0*y1-y0*x1)) True sage: is_hypersurface(P1P1.subscheme(x0^3*y1^3 + 3*x0^2*x1*y1*y0^2 + 3*x0*x1^2*y1^2*y0 + x1^3*y0^3)) True sage: is_hypersurface(P1P1.subscheme([x0, y0])) False sage: P3 = ProjectiveSpace(3, QQ, 'abcd'); a,b,c,d = P3.gens() sage: is_hypersurface(P3) False sage: is_hypersurface(P3.subscheme(a^2*d - b^3 + c*d^2)) True sage: is_hypersurface(P3.subscheme([a, a^2])) False
-
comb_walks.alggeo.
is_identity
(*args, **kwds)¶ Method to check if a morphism is the identity morphism or not.
This method takes a morphism \(\varphi : A \rightarrow A\) and tries to deduce if it is the identity morphism. For doing so, first we rely on Sage code to check the equality and, in case it returns False, we try to go further:
- For each projective component, we divide each coordinate with the corresponding variables. Then we check if that is the same through all the coordinates.
EXAMPLES:
sage: from comb_walks.alggeo import * sage: P2 = ProjectiveSpace(2, QQ, 'xyz'); x,y,z = P2.gens() sage: is_identity(P2.identity_morphism()) True sage: is_identity(Hom(P2,P2)([x,y,z])) True sage: is_identity(Hom(P2,P2)([y,z,x])) False sage: C = P2.subscheme(x^2 - y*z); # the usual parabola sage: h = Hom(C,C)([x*y*z, x^2*y, x^2*z]); is_identity(h) True sage: h = Hom(C,C)([-x,-y,-z]); is_identity(h) True
-
comb_walks.alggeo.
is_prod_point
(point)¶ Boolean method to check if an object is a point on a product of projective spaces
This method checks that an element is precisely a point on an ambient space that is the product of several Projective Spaces.
- INPUT:
point
: the object to be checked.
EXAMPLES:
sage: from comb_walks.alggeo import * sage: P2 = ProjectiveSpace(2, QQ, 'xyz'); O = origin(P2) sage: is_prod_point(O) False sage: is_prod_point([0,1,1]) False sage: P1P1 = ProjectiveSpace(1, QQ, 'x').cartesian_product(ProjectiveSpace(1, QQ, 'y')) sage: is_prod_point(origin(P1P1)) True
-
comb_walks.alggeo.
is_smooth_at
(variety, point)¶ Method that considers a hypersurface and check if it is smooth at a point.
In algebraic geometry, a variety is smooth at a point if it is well approximated by an affine space near that point. For hypersurfaces, this property can be easily checked using derivatives and evaluation of the defining equation.
Since this computation using derivatives only works for affine varieties and projective spaces, we will always dehomogenize around the require point (if it is on the curve), see method
lin_change_to_zero()
.For convention, we say that if
point
is not in the variety, the variety is not smooth at that point.EXAMPLES:
sage: from comb_walks.alggeo import * sage: P2 = ProjectiveSpace(2, QQ, 'xyz'); x, y, z = P2.gens() sage: C = P2.subscheme(x^2-y*z); # normal parabola sage: O = origin(P2); P = P2([0,1,0]); Q = P2([1,0,1]) sage: is_smooth_at(C, O) True sage: is_smooth_at(C, P) True sage: is_smooth_at(C, Q) False sage: C = P2.subscheme(x^3 - x^2*z - y^2*z) sage: is_smooth_at(C, O) False sage: is_smooth_at(C, P) True sage: is_smooth_at(C, Q) True sage: P1P1 = ProjectiveSpace(1, QQ, 'x').cartesian_product(ProjectiveSpace(1, QQ, 'y')) sage: x0,x1,y0,y1 = P1P1.gens() sage: C = P1P1.subscheme(x0^2*y0*y1 + y0^2*x0*x1 + x0*x1*y1^2 + y0*y1*x1^2 - x0*y0*y1*x1) sage: O = origin(C) sage: is_smooth_at(C, O) True
-
comb_walks.alggeo.
lin_change_from_zero
(*args, **kwds)¶ Method to get a dictionary of linear change of coordinates from the origin.
This method takes a point on an algebraic scheme and computes a linear change of coordinates in its ambient space that maps the origin to
point
. The output is a dictionary that can be plugged into rational functions to get the pullback of this change of coordinates.Remark: if
point
is the origin, this map will lead to a simple homoginization.- OUTPUT:
- A dictionary such that
pullback(change)(f) = f(**dict).numerator()
.
- A dictionary such that
EXAMPLES:
sage: from comb_walks.alggeo import * sage: # Test for P2 and a plane curve sage: D = ProjectiveSpace(2, QQ, 'xyz'); x,y,z = D.gens(); O = D([0,0,1]) sage: C = D.subscheme(x^2 - y*z); # the normal parabloa sage: O in C True sage: P = D([1,1,1]) sage: lin_change_from_zero(P) {'x': (x - z)/z, 'y': (y - z)/z, 'z': 1} sage: C.defining_polynomials()[0](**lin_change_from_zero(P)).numerator() x^2 - 2*x*z - y*z + 2*z^2 sage: P in D.subscheme([el(**lin_change_from_zero(P)).numerator() for el in C.defining_polynomials()]) True sage: # Testing a change with an infinity point sage: P = D([1,0,0]) sage: lin_change_from_zero(P) {'x': z/x, 'y': y/x, 'z': 1} sage: P in D.subscheme([el(**lin_change_from_zero(P)).numerator() for el in C.defining_polynomials()]) True sage: P = D([1,1,0]) sage: lin_change_from_zero(P) {'x': (x - y)/y, 'y': z/y, 'z': 1} sage: P in D.subscheme([el(**lin_change_from_zero(P)).numerator() for el in C.defining_polynomials()]) True sage: # Testing with a bigger space and more complex variety sage: P4 = ProjectiveSpace(4, QQ, 'abcde'); a,b,c,d,e = P4.gens(); O = P4([0,0,0,0,1]) sage: C = P4.subscheme([a^2+b^2+c^2+d^2, a^4-b^2*c^2+d*e^3]) sage: O in C True sage: P = P4([1,-1,0,1,1]) sage: lin_change_from_zero(P) {'a': (a - e)/e, 'b': (b + e)/e, 'c': c/e, 'd': (d - e)/e, 'e': 1} sage: P in P4.subscheme([el(**lin_change_from_zero(P)).numerator() for el in C.defining_polynomials()]) True
This method can also work with product of projective spaces:
sage: # Testing product of two projective spaces and plane curves sage: P1P1 = ProjectiveSpace(1, QQ, 'x').cartesian_product(ProjectiveSpace(1, QQ, 'y')) sage: x0,x1,y0,y1 = P1P1.gens(); O = P1P1([0,1,0,1]) sage: C = P1P1.subscheme(x0^2*y1 - y0*x1^2); # the usual parabola sage: O in C True sage: P = P1P1([1,1,0,1]); # P = (1,0) sage: lin_change_from_zero(P) {'x0': (x0 - x1)/x1, 'x1': 1, 'y0': y0/y1, 'y1': 1} sage: P in P1P1.subscheme([el(**lin_change_from_zero(P)).numerator() for el in C.defining_polynomials()]) True sage: # Testing with plance curves and points at infinity sage: P = P1P1([3,1,1,0]); # P = (3,inf) sage: lin_change_from_zero(P) {'x0': (x0 - 3*x1)/x1, 'x1': 1, 'y0': y1/y0, 'y1': 1} sage: P in P1P1.subscheme([el(**lin_change_from_zero(P)).numerator() for el in C.defining_polynomials()]) True sage: P = P1P1([1,0,-2,1]); # P = (inf,-2) sage: lin_change_from_zero(P) {'x0': x1/x0, 'x1': 1, 'y0': (y0 + 2*y1)/y1, 'y1': 1} sage: P in P1P1.subscheme([el(**lin_change_from_zero(P)).numerator() for el in C.defining_polynomials()]) True sage: P = P1P1([1,0,1,0]); # P = (inf,inf) sage: lin_change_from_zero(P) {'x0': x1/x0, 'x1': 1, 'y0': y1/y0, 'y1': 1} sage: P in P1P1.subscheme([el(**lin_change_from_zero(P)).numerator() for el in C.defining_polynomials()]) True
-
comb_walks.alggeo.
lin_change_to_zero
(*args, **kwds)¶ Method to get a dictionary of linear change of coordinates to the origin.
This method takes a point in an algebraic scheme and computes a linear change of coordinates in its ambient space that maps
point
to the origin. The output is a dictionary that can be plugged into rational functions to get the pullback of this change of coordinates.Remark: if
point
is the origin, this map will lead to a simple dehomoginization.- OUTPUT:
- A dictionary such that
pullback(change)(f) = f(**dict)
. - A list of variables equals to
f(**dict).variables()
.
- A dictionary such that
EXAMPLES:
sage: from comb_walks.alggeo import * sage: # Test for P2 and a plane curve sage: D = ProjectiveSpace(2, QQ, 'xyz'); x,y,z = D.gens(); O = D([0,0,1]) sage: C = D.subscheme(x^3*z - 3*x^2*y^2 + 3*x*z^3 - z^4); O in C False sage: P = D([1,1,1]); P in C True sage: lin_change_to_zero(P) ({'x': x + 1, 'y': y + 1, 'z': 1}, [x, y]) sage: O in D.subscheme([el(**lin_change_to_zero(P)[0]).homogenize(z) for el in C.defining_polynomials()]) True sage: # Testing a change with an infinity point sage: P = D([1,0,0]) sage: lin_change_to_zero(P) ({'x': 1, 'y': y, 'z': x}, [x, y]) sage: O in D.subscheme([el(**lin_change_to_zero(P)[0]).homogenize(z) for el in C.defining_polynomials()]) True sage: C = D.subscheme(x^3 - y^3 + z^3); O in C False sage: P = D([1,1,0]); P in C True sage: lin_change_to_zero(P) ({'x': x + 1, 'y': 1, 'z': y}, [x, y]) sage: O in D.subscheme([el(**lin_change_to_zero(P)[0]).homogenize(z) for el in C.defining_polynomials()]) True sage: # Testing with a bigger space and more complex variety sage: P4 = ProjectiveSpace(4, QQ, 'abcde'); a,b,c,d,e = P4.gens(); O = P4([0,0,0,0,1]) sage: C = P4.subscheme([a^2+b^2+c^2-d^2-e^2, a^4-b^2*c^2+d*e^3]); O in C False sage: P = P4([-1,1,0,-1,1]); P in C True sage: lin_change_to_zero(P) ({'a': a - 1, 'b': b + 1, 'c': c, 'd': d - 1, 'e': 1}, [a, b, c, d]) sage: O in P4.subscheme([el(**lin_change_to_zero(P)[0]).homogenize(e) for el in C.defining_polynomials()]) True
This method can also work with product of projective spaces:
sage: # Testing product of two projective spaces and plane curves sage: P1P1 = ProjectiveSpace(1, QQ, 'x').cartesian_product(ProjectiveSpace(1, QQ, 'y')) sage: x0,x1,y0,y1 = P1P1.gens(); O = P1P1([0,1,0,1]) sage: C = P1P1.subscheme(x0^2*y1^2 - x0*y0*x1*y1 + x1^2*y0^2 - x1^2*y1^2); O in C False sage: P = P1P1([1,1,1,1]); P in C True sage: lin_change_to_zero(P) ({'x0': x0 + 1, 'x1': 1, 'y0': y0 + 1, 'y1': 1}, [x0, y0]) sage: O in P1P1.subscheme([el(**lin_change_to_zero(P)[0])(x0=x0/x1,y0=y0/y1).numerator() for el in C.defining_polynomials()]) True sage: P = P1P1([0,1,-1,1]); P in C True sage: lin_change_to_zero(P) ({'x0': x0, 'x1': 1, 'y0': y0 - 1, 'y1': 1}, [x0, y0]) sage: O in P1P1.subscheme([el(**lin_change_to_zero(P)[0])(x0=x0/x1,y0=y0/y1).numerator() for el in C.defining_polynomials()]) True sage: P = P1P1([1,1,0,1]); P in C True sage: lin_change_to_zero(P) ({'x0': x0 + 1, 'x1': 1, 'y0': y0, 'y1': 1}, [x0, y0]) sage: O in P1P1.subscheme([el(**lin_change_to_zero(P)[0])(x0=x0/x1,y0=y0/y1).numerator() for el in C.defining_polynomials()]) True sage: # Testing with plance curves and points at infinity sage: P = P1P1([1,0,1,0]); # P = (inf,inf) sage: lin_change_to_zero(P) ({'x0': 1, 'x1': x0, 'y0': 1, 'y1': y0}, [x0, y0]) sage: O in P1P1.subscheme([el(**lin_change_to_zero(P)[0])(x0=x0/x1,y0=y0/y1).numerator() for el in C.defining_polynomials()]) True sage: C = P1P1.subscheme(x0^2*y0*y1 - 3*x0^2*y1^2 + x1^2*y0^2 - x1^2*y1^2); O in C False sage: P = P1P1([1,0,3,1]); P in C True sage: lin_change_to_zero(P) ({'x0': 1, 'x1': x0, 'y0': y0 + 3, 'y1': 1}, [x0, y0]) sage: O in P1P1.subscheme([el(**lin_change_to_zero(P)[0])(x0=x0/x1,y0=y0/y1).numerator() for el in C.defining_polynomials()]) True sage: C = P1P1.subscheme(y1^4*x1^2 - y1^2*y0^2*x0^2 + y0^4*x1*(x0 + 2*x1)); O in C False sage: P = P1P1([-2,1,1,0]); P in C True sage: lin_change_to_zero(P) ({'x0': x0 - 2, 'x1': 1, 'y0': 1, 'y1': y0}, [x0, y0]) sage: O in P1P1.subscheme([el(**lin_change_to_zero(P)[0])(x0=x0/x1,y0=y0/y1).numerator() for el in C.defining_polynomials()]) True
-
comb_walks.alggeo.
order_at_variety
(*args, **kwds)¶ Method to compute the order and the residue of a rational function at \((0,0)\) over an affine curve.
This method computes the order of a polynomial function over a curve at \((0,0)\). If
curve
defines an affine curve that is regular at \((0,0)\), then there is a local parameter \(t\). Then, any rational function can be written like\[F(t) = \sum_{k \geq m} f_k t^k,\]where \(f_m \neq 0\). We say that \(m\) is the order of \(F\) and \(f_m\) is its residue.
We define that the order of the zero function is \(\infty\) with residue \(0\).
- INPUT:
rational
: the polynomial functionvariety
: a hypersurface smooth at the origin or a polynomial defining an affine curve smooth at (0,0).main_var
: variable that will be considered local parameter if possible.
- OUTPUT:
A triplet containing:
- An integer with the order of
rational
at the origin overvariety
, - An element representing the residue (the first non-zero coefficient) of
poly
, - The affine local parameter used for computing the residue.
- An integer with the order of
EXAMPLES:
sage: from comb_walks.alggeo import * sage: P2 = ProjectiveSpace(QQ, 2, 'xyz'); x,y,z = P2.gens() sage: C = P2.subscheme(x^3 - 3*x*y*z + 7*y^2*z - y*z^2) sage: order_at_variety(x, C) (1, 1, x) sage: order_at_variety(y, C) (3, 1, x) sage: order_at_variety(7*y^2*x+ 9*y^3, C) (7, 7, x) sage: order_at_variety((3*x^7+2*y^2)/(3*x^6 + y^4), C) (0, 2/3, x) sage: order_at_variety(0, C) (+Infinity, 0, x)
This method can also work with a defining polynomial in two variables instead of the projective variety:
sage: P1P1 = ProjectiveSpace(QQ, 1, 'x').cartesian_product(ProjectiveSpace(QQ, 1, 'y')) sage: x0, x1, y0, y1 = P1P1.gens() sage: C = P1P1.subscheme(x0^3*y1^2 - 3*x0*x1^2*y0*y1 + 7*y0^2*x1^3 - y0*y1*x1^3) sage: order_at_variety(x0, C) == order_at_variety(x0, dehomogenize_at_zero(C)[0]) True sage: order_at_variety(y0, C) == order_at_variety(y0, dehomogenize_at_zero(C)[0]) True sage: order_at_variety((3*x0+y0^2)/x0^6, C) == order_at_variety((3*x0+y0^2)/x0^6, dehomogenize_at_zero(C)[0]) True
-
comb_walks.alggeo.
order_morphism
(*args, **kwds)¶ Method for computing the order of a morphism up to a bound.
Given a projective morphism \(\varphi\) with same domain and codomain, we can define its order as the minimal value of \(n\) such that \(\varphi^n = id\). If such \(n\) does not exist, then we say \(\varphi\) has infinite order.
This method checks blindly if a method has a finite order up to some power given by the argument
bound
. This method also cache the answer in such a way that if the bound has been reached we return(Infinity, d, m)
whered
is the current bound that have been checked.m
is the current valuemorphism^d
.
Hence if the user ask for the order again with smaller bound, the answer is inmediate and if the user ask for the order for a higher bound only new computations are done.
EXAMPLES:
sage: from comb_walks.alggeo import * sage: P2 = ProjectiveSpace(2, QQ, 'xyz'); x,y,z = P2.gens() sage: C = P2.subscheme(x^2-y*z) sage: h = Hom(C,C)([-x,y,z]); order_morphism(h) 2 sage: h = Hom(C,C)([y*z, x*z, x*y]); order_morphism(h) 2 sage: C2 = P2.subscheme(x^3-3*x^2*y+3*x*y^2-y^3) sage: h = Hom(C,C2)([x,x,z]); order_morphism(h) +Infinity
In the package
comb_walks.walkmodel
, we can find several examples of morphisms that have finite order, and also some that have infinite order:sage: from comb_walks.walkmodel import * sage: for m in AllModels: # long time (> 15 seconds) ....: if(order_morphism(m.iota(1,'p')) != 2): ....: print("Error in the order of x-involution on the model %s" %m.name()) ....: if(order_morphism(m.iota(2,'p')) != 2): ....: print("Error in the order of y-involution on the model %s" %m.name())
-
comb_walks.alggeo.
origin
(variety)¶ Method to retrieve the origin of an algebraic variety.
This method returns the origin point of the ambient space where a variety is. It also check if the origin belongs to that particular variety, otherwise it returns a
TypeError
.The variety must be a subscheme of some projective space or a product of projective spaces. Using that information we dompute the origin for each of the components of the space and return it if it is on the variety.
- INPUT:
variety
: an algebraic subscheme to look for the origin
- OUTPUT:
- Either the origin point of the ambient space if it is on the variety or
a
TypeError
.
EXAMPLES:
sage: from comb_walks.alggeo import * sage: P1P1 = ProjectiveSpace(1, QQ, 'x').cartesian_product(ProjectiveSpace(1, QQ, 'y')) sage: x0, x1, y0, y1 = P1P1.gens() sage: origin(P1P1) (0 : 1 , 0 : 1) sage: C = P1P1.subscheme(x0^2*y1 - y0*x1^2); # usual parabola sage: origin(C) (0 : 1 , 0 : 1)
It is important to remark that this method returns the origin on the curve. This means that the object is different although they can be checked as equals:
sage: origin(C) is origin(P1P1) False sage: origin(C) == origin(P1P1) True
This method also works with only one projective component:
sage: P2 = ProjectiveSpace(2, QQ, 'xyz'); x,y,z = P2.gens() sage: origin(P2) (0 : 0 : 1) sage: C2 = P2.subscheme([x,y]); origin(C2) (0 : 0 : 1) sage: C2 = P2.subscheme(x^2 - 2*x*z + z^2 - y*z) # translated parabola sage: origin(C2) Traceback (most recent call last): ... TypeError: The origin (0 : 0 : 1) is not on ...
And we can have even more complexes schemes:
sage: A = ProjectiveSpace(2, QQ, 'xyz').cartesian_product(ProjectiveSpace(1, QQ, 'y')).cartesian_product(ProjectiveSpace(3, QQ, 'abcd')) sage: origin(A) ((0 : 0 : 1 , 0 : 1), (0 : 0 : 0 : 1))
-
comb_walks.alggeo.
point_extension
(*args, **kwds)¶ Method to create a point structure for a variety even with extensions on the field
On Sage, algebraic subschemes are based on ground fields that are, usually, not algebraically closed. This means that it is very common to have points on a variety but Sage is unable to detect that membership property since the coordinates of the point are algebraic over the field over where the curve is defined.
This method allows the user to check that membership easier doing the corresponding pushouts and extensions of the curve to bigger fields automatically.
- INPUT:
point
: a point. This point can be a point structure in some projective space or a list of coordinates. It has to be any structure such that, when we iterate through its elements (in the wayfor coordinate in point:...
) we obtain its coordinates.variety
: algebraic scheme where we want to check the membership ofpoint
.
- OUTPUT:
- The method will return the point structure for
point
in the corresponding exteded variety or an Exception if the point is not in any extension of the variety.
EXAMPLES:
sage: from comb_walks.alggeo import * sage: P1P1 = ProjectiveSpace(1, QQ, 'x').cartesian_product(ProjectiveSpace(1, QQ, 'y')) sage: x0,x1,y0,y1 = P1P1.gens(); O = P1P1([0,1,0,1]) sage: C = P1P1.subscheme(x0^2*y1^2 - x0*y0*x1*y1 + x1^2*y0^2); O in C True sage: point_extension(O, C) (0 : 1 , 0 : 1) sage: F = QQ.extension(QQ[x](x^2-x+1), 'a'); a = F.gens()[0]; # created an algebraic element sage: point_extension([a,1,0,1], P1P1) (a : 1 , 0 : 1) sage: point_extension([a,1,1,1], C) (a : 1 , 1 : 1)
It is interesting to remark that after applying this method, the Sage membership command still returns
False
, but now we can recover the extended variety from the point:sage: point_extension([a,1,1,1], C) in C False sage: point_extension([a,1,0,1], P1P1).scheme() Product of projective spaces P^1 x P^1 over Number Field in a with defining polynomial x^2 - x + 1 sage: point_extension([a,1,1,1], C).scheme() Closed subscheme of Product of projective spaces P^1 x P^1 over Number Field in a with defining polynomial x^2 - x + 1 defined by: x1^2*y0^2 - x0*x1*y0*y1 + x0^2*y1^2
The method returns error if the point is not valid for the variety:
sage: point_extension([1,0,a], P1P1) Traceback (most recent call last): ... TypeError: the list v=[1, 0, a] must have 4 components sage: point_extension([a,1,0,1], C) Traceback (most recent call last): ... TypeError: Coordinates [a, 1, 0, 1] do not define a point on ...
-
comb_walks.alggeo.
polar_part
(*args, **kwds)¶ Method that gets the polar part at one point of a rational function.
Given a projective variety \(A\) and a point \(P \in A\) where the variety is smooth, we can have a local parameter \(t \in C(A)\), i.e., a function that vanishes at \(P\) with order 1. This local parameter generates the ideal of all rational functions over \(A\) that vanish at \(P\).
In fact, given a rational function \(f \in C(A)\), we can compute a local expansion of \(f\) around \(P\) using this local parameter such that:
\[f = \sum_{k\geq d} f_d t^d,\]where \(d\) is defined as the order of \(f\) at \(P\). If \(d < 0\) we say that \(f\) has a pole at \(P\). And we say that the part of the expansions with negative exponents of \(t\) is the polar part of `f` at `P` w.r.t. `t`.
Since any two local parameters differs by a constant, then the polar part of \(f\) is almost uniquely defined. If we consider the polar part as the list of coefficients \([0,f_{-1}, f_{-2},\ldots]\), then this list is uniquely determined up to a multiplication termwise by the geometric sequence \([1,c, c^2, \ldots]\).
- INPUT:
variety
: variety over we are considering the function.func
: rational function overvariety
.point
: a point on the variety. It can be a point defined over an algebraic extenstion of the ground field ofvariety
.sequence
: boolean value to determine if we return the whole polar part function or the sequence of the Laurent expansion with respect to the local parameter. In the last case, the output will be a list of valuesl
wherel[i]
represents the value \(f_{-i}\).
- OUTPUT:
- A tuple containing the polar part and the local parameter we used to compute it.
EXAMPLES:
sage: from comb_walks.alggeo import * sage: P2 = ProjectiveSpace(2, QQ, 'xyz'); x,y,z = P2.gens() sage: C = P2.subscheme(x^3 - 3*y^2*z + x^2*z + y*z^2); O = origin(C) sage: polar_part(C, 1/x^3 - x/y, O) ((x^2*z + z^3)/x^3, x/z) sage: polar_part(C, 1/x^3 - x/y, O, True) ([0, 1, 0, 1], x/z) sage: C = P2.subscheme(x^3 - y^2*z + 7*x*z^2 + 3*z^3); P = C([0,1,0]);# elliptic curve sage: polar_part(C, y, P, True) ([0, 0, 0, 1], x/y) sage: polar_part(C, y, P) (y^3/x^3, x/y) sage: polar_part(C, x^3 - y^2 + 3*x*y, P) ((-42*x^4*y - 7*x^3*y^2 + 3*y^5)/x^5, x/y) sage: polar_part(C, x^3 - y^2 + 3*x*y, P, True) ([0, -42, -7, 0, 0, 3], x/y)
-
comb_walks.alggeo.
pullback
(morphism, lift=True)¶ Method that takes a rational map between Projective varieties and returns its pullback.
Given a rational map between two projectives varieties \(\varphi: A \rightarrow B\), the pullback is defined as a map on the ring of rational functions over the varieties \(C(A)\) and \(C(B)\) defined as
\[\varphi^* : C(B) \rightarrow C(A),\]such that for any point \(P \in A\), \(\varphi^*(f)(P) = f(\varphi(P))\), i.e., \(\varphi(f) = f \circ \varphi\).
The argument
lift
determines if the map is considered in the total ambient space or in the coordinate rings.EXAMPLES:
sage: from comb_walks.alggeo import * sage: # Testing a pullback between the ambient spaces sage: D = ProjectiveSpace(2, QQ, 'xyz'); CD = ProjectiveSpace(2,QQ, 'uvw') sage: x,y,z = D.gens(); u,v,w = CD.gens() sage: h = Hom(D, CD)([x^2, y*z-x*z, y^2]) sage: p = pullback(h); p Ring morphism: From: Fraction Field of Multivariate Polynomial Ring in u, v, w over Rational Field To: Fraction Field of Multivariate Polynomial Ring in x, y, z over Rational Field Defn: u |--> x^2 v |--> -x*z + y*z w |--> y^2 sage: p(u) x^2 sage: p(v) -x*z + y*z sage: p(w) y^2 sage: # Testing a pullback between two curves sage: C1 = D.subscheme(x^2-z*y); # usual parabola sage: C2 = CD.subscheme(v); # the u axis sage: h = Hom(C2, C1)([u*w,u^2,w^2]); h # the vertical lifting Scheme morphism: From: Closed subscheme of Projective Space of dimension 2 over Rational Field defined by: v To: Closed subscheme of Projective Space of dimension 2 over Rational Field defined by: x^2 - y*z Defn: Defined on coordinates by sending (u : v : w) to (u*w : u^2 : w^2) sage: p = pullback(h); p Ring morphism: From: Fraction Field of Multivariate Polynomial Ring in x, y, z over Rational Field To: Fraction Field of Multivariate Polynomial Ring in u, v, w over Rational Field Defn: x |--> u*w y |--> u^2 z |--> w^2 sage: p(x^2-y*z) == 0 # the pullback of the equation for C2 has to go to the zero element True
-
comb_walks.alggeo.
simpl_morphism
(*args, **kwds)¶ Static method that simplifies a morphism between projectives varieties.
This method reduces the gcd from the defining polynomials of the morphism provided. Since the map is between projective varieties, the map is defined up to a common factor between its coordinates. In fact, the bigger the number of common factors, the bigger the locus of indeterminacy of the map.
Here we divide all the defining polynomials by the \(gcd\) and also try to recude the size of the content of those polynomials.
EXAMPLES:
sage: from comb_walks.alggeo import * sage: D = ProjectiveSpace(2, QQ, 'xyz'); CD = ProjectiveSpace(2,QQ, 'uvw') sage: x,y,z = D.gens(); u,v,w = CD.gens() sage: C1 = D.subscheme(x^2-z*y); # usual parabola sage: C2 = CD.subscheme(v); # the u axis sage: h = Hom(C1, C2)([el*3*(27*x-y+z) for el in [x, 0, z]]) sage: h Scheme morphism: From: Closed subscheme of Projective Space of dimension 2 over Rational Field defined by: x^2 - y*z To: Closed subscheme of Projective Space of dimension 2 over Rational Field defined by: v Defn: Defined on coordinates by sending (x : y : z) to (81*x^2 - 3*x*y + 3*x*z : 0 : 81*x*z - 3*y*z + 3*z^2) sage: simpl_morphism(h) Scheme morphism: From: Closed subscheme of Projective Space of dimension 2 over Rational Field defined by: x^2 - y*z To: Closed subscheme of Projective Space of dimension 2 over Rational Field defined by: v Defn: Defined on coordinates by sending (x : y : z) to (x : 0 : z)
The simplification can be done also when the image is a product of projective spaces:
sage: P2 = ProjectiveSpace(1, QQ, 'x').cartesian_product(ProjectiveSpace(1, QQ, 'y')) sage: x0, x1, y0, y1 = P2.gens() sage: C3 = P2.subscheme(x0^2*y1 + x1^2*y0); # same as C1 but symmetric in the X axis sage: h = Hom(C3,C3)([(18*x0*y0+11*x0*y1)*el for el in [x1,x0,y1,y0]]) sage: simpl_morphism(h) Scheme endomorphism of Closed subscheme of Product of projective spaces P^1 x P^1 over Rational Field defined by: x1^2*y0 + x0^2*y1 Defn: Defined by sending (x0 : x1 , y0 : y1) to (x1 : x0 , y1 : y0).
However, if the original space is not the product of some spaces, the simplification can not be performed. Then we do the usual simplification:
sage: h = Hom(C1,C3)([(23*x-17*y+5*z)*el for el in [x^2*z^2, z^4, y^4, z^4]]); h Scheme morphism: From: Closed subscheme of Projective Space of dimension 2 over Rational Field defined by: x^2 - y*z To: Closed subscheme of Product of projective spaces P^1 x P^1 over Rational Field defined by: x1^2*y0 + x0^2*y1 Defn: Defined on coordinates by sending (x : y : z) to (23*x^3*z^2 - 17*x^2*y*z^2 + 5*x^2*z^3 : 23*x*z^4 - 17*y*z^4 + 5*z^5 , 23*x*y^4 - 17*y^5 + 5*y^4*z : 23*x*z^4 - 17*y*z^4 + 5*z^5) sage: simpl_morphism(h) Scheme morphism: From: Closed subscheme of Projective Space of dimension 2 over Rational Field defined by: x^2 - y*z To: Closed subscheme of Product of projective spaces P^1 x P^1 over Rational Field defined by: x1^2*y0 + x0^2*y1 Defn: Defined on coordinates by sending (x : y : z) to (x^2 : z^2 , y^4 : z^4)
-
comb_walks.alggeo.
simplify_on_affine_curve
(*args, **kwargs)¶ Method that simplifies a rational function over a curve.
This method reduces a rational function defined over a curve reducing the trailing_var to reduce the degree. It computes a canonical form where the rational function has no appearances of
trailing_var
of degree highter thancurve_equation.degree(trailing_var)
and it does not show up on the denominator.Deprecated since version 0.1: This will be removed in 0.2. Use ‘simplify_rational_variety’ instead
-
comb_walks.alggeo.
simplify_rational_variety
(*args, **kwds)¶ Method that simplifies rational functions using the equation of a variety.
This method takes a rational function as an input and build an equivalent rational function using the standard reduction performed by Sage after going to the coordinate ring of a variety.
This simplification usually leads to a cannonical form inside the variety of a rational function and can be use to check some equalities of those rational functions that, sintactically seem different.
EXAMPLES:
sage: from comb_walks.alggeo import * sage: P2 = ProjectiveSpace(2, QQ, 'xyz'); x,y,z = P2.gens() sage: simplify_rational_variety(x^2-3*y/z, P2) == x^2 - 3*y/z True sage: C = P2.subscheme(x^2-y*z) sage: simplify_rational_variety(x^2-y*z, C) 0 sage: simplify_rational_variety(x^2/(y*z), C) 1 sage: simplify_rational_variety((x^3-y*x^2+3*x*z^2)/(z^3), C) (x*y - y^2 + 3*x*z)/z^2
-
comb_walks.alggeo.
zeros_bihom
(*args, **kwds)¶ Method to compute the zeros of a bivariate homogeneous form in the given variables.
Let \(f(x,y) \in F[x,y]\) be homogeneous of degree \(d\). Then:
- \(f(0,0) = 0\) if and only if \(d > 0\).
- \(f(ax,ay) = a^d f(x,y)\).
Hence, if \(f(x,y)\) is not a constant polynomials, the zeros of a bivariate homogeneous polynomial are infinitely many. Here we are going to fix the zeros that we may get by saying that \(y = 1\) or \(y=0\) (i.e., looking solutions in the projective line).
If \(f(x,0) = 0\), then \(y\) divides \(f(x,y)\). So, without lost of generality, we may assume that \(f(x,0) \neq 0\) and all zeros of \(f(x,y)\) are of the form \((\alpha, 1)\) and all the multiples we want.
If we evaluate \(y=1\) and factorized \(g(x) = f(x,1)\), then we obtain several factors \(h_1(x),\ldots,h_t(x)\) where \(t \leq d\) (with equality when \(F\) is algebraically closed). Then the numerators of \(h_i(x/y)\) make a factorization of \(f(x,y)\) and we can describe all the zeros for \(f(x,y)\) using those minimal polynomials \(h_1,\ldots,h_t\).
If \(\deg(h_j) = 1\), then we have \(h_j(x,y) = ax + b\), so the point \((-b,a)\) is a zero of the original \(f(x,y)\). If the degree is higer, we may need some algebraic extension on the ground field in orther to express the zeros.
For these algebraic points, we need to extend the field F using the corresponding polynomial \(h_j(x)\). We do so using the method
extenstion
that can be found in any field when \(\deg(h_j) = 2\). Otherwise we use the (possibly slower) methodsplitting_field
.- INPUT:
poly
: a homogeneous polynomial in two variables. This is checked by the function.vars
: the list of two variables we are going to require on the polynomial. This is also checked by the function.alg_name
: name for the algebraic elements that this method generates.diff_names
: if set to True, the algebraic elements will be named differently using a number after the preffix given byalg_name
. Since we can not guarantee that this method only generates one algebraic extension, it is left for the user to decide if they have to be distinguish or not. It is set toTrue
by default.algebraic
: method with interface(R, poly, name)
such that takes a ring \(R\) and computes an algebraic extension usingpoly
andname
and return the final extension, the list of roots forpoly
and the number of algebraic extenstions required. By default, this method calls the methodextension
of the Ring Sage class.
- OUTPUT:
- A list of tuples \((x_0,y_0)\) such that
poly(x=x0,y=y0)
returns 0.
EXAMPLES:
sage: from comb_walks.alggeo import * sage: F.<x,y> = QQ[] sage: zeros_bihom(F.one(), [x, y]) [] sage: zeros_bihom(x-1, [x,y]) Traceback (most recent call last): ... ValueError: Polynomial x - 1 is not homogenous or not in variables [x, y] sage: G.<a,b> = QQ[] sage: zeros_bihom(a-b, [x,y]) Traceback (most recent call last): ... CoercionException: ... sage: F.<x,y,z> = QQ[] sage: zeros_bihom(x-z, [x,y]) Traceback (most recent call last): ... ValueError: Polynomial x - z is not homogenous or not in variables [x, y] sage: zeros_bihom(x-z, [x,y,z]) Traceback (most recent call last): ... TypeError: The requested variables ([x, y, z]) are not two --> no bivariate polynomial sage: zeros_bihom(y*x - y^2, [x,y]) [(1, 0), (1, 1)] sage: zeros_bihom(y*x - y^2, [y,x]) # here the first coordinate is for `y` [(1, 1), (0, 1)] sage: out = zeros_bihom(x^2 + y^2, [x,y]); out [(a_0, 1), (-a_0, 1)] sage: out[0][0]^2 == -1 # checking the algebraic property for `a_0` True sage: out = zeros_bihom((x^2+y^2)*(x^2+x*y+y^2), [x,y]); out [(a_0, 1), (-a_0, 1), (a_1, 1), (-a_1 - 1, 1)] sage: (out[0][0]^2 == -1) and (out[2][0]^2 + out[2][0] + 1 == 0) True