Get the reflexification or double dual (in the case of a normal ring, S2-ification) of an ideal $I$ or module $M$. Recall the double dual is defined to be $Hom(Hom(M, R), R)$.
i1 : R = QQ[x,y,z]/ideal(x^2-y*z); |
i2 : m = ideal(x,y,z); o2 : Ideal of R |
i3 : reflexify(m) o3 = ideal 1 o3 : Ideal of R |
i4 : I = ideal(x,y); o4 : Ideal of R |
i5 : reflexify(I) o5 = ideal (y, x) o5 : Ideal of R |
i6 : reflexify(I^2) o6 = ideal y o6 : Ideal of R |
i7 : reflexify(I^3) 2 o7 = ideal (y , x*y) o7 : Ideal of R |
We also have an example of reflexifying a module.
i8 : R = QQ[x,y,z]/ideal(x^2-y*z); |
i9 : m = ideal(x,y,z); o9 : Ideal of R |
i10 : prune reflexify(m*R^2) 2 o10 = R o10 : R-module, free |
i11 : I = ideal(x,y); o11 : Ideal of R |
i12 : prune reflexify(I*R^1) o12 = cokernel {1} | x -y | {1} | -z x | 2 o12 : R-module, quotient of R |
i13 : prune reflexify(I^2*R^1) 1 o13 = R o13 : R-module, free, degrees {1} |
There is a canonical map from a module $M$ to its reflexification, $Hom(Hom(M, R), R)$. If reflexify is passed the option ReturnMap => true, then instead of returning a module, reflexify returns that map. This is not necessary for ideals since an ideal is canonically a subsetset of its reflexification.
i14 : R = QQ[x,y]; |
i15 : m = ideal(x,y); o15 : Ideal of R |
i16 : M = m*R^1; |
i17 : f = reflexify( M, ReturnMap => true ) o17 = | x y | o17 : Matrix |
i18 : source f o18 = image | x y | 1 o18 : R-module, submodule of R |
i19 : target f 1 o19 = R o19 : R-module, free |
Generally speaking, it is faster to reflexify ideals as opposed to modules. Consider the following example of a point on an elliptic curve.
i20 : R = QQ[x,y,z]/ideal(-y^2*z +x^3 + x^2*z + x*z^2+z^3); |
i21 : I = ideal(x-z,y-2*z); o21 : Ideal of R |
i22 : J = I^21; o22 : Ideal of R |
i23 : time reflexify(J); -- used 0.626022 seconds o23 : Ideal of R |
i24 : time reflexify(J*R^1); -- used 0.803348 seconds |
Because of this, there are two strategies for computing a reflexification (at least if the module embeds as an ideal).
IdealStrategy. In the case that $R$ is a domain, and our module is isomorphic to an ideal $I$, then one can compute the reflexification by computing colons.
ModuleStrategy. This computes the reflexification simply by computing $Hom$ twice.
ModuleStrategy is the default strategy for modules, IdealStrategy is the default strategy for ideals. In our experience, IdealStrategy is faster on average. Note that calling ModuleStrategy for ideals or IdealStrategy for modules creates overhead which can slow things down substantially (since we must embed various modules as ideals).
i25 : R = ZZ/13[x,y,z]/ideal(x^3 + y^3-z^11*x*y); |
i26 : I = ideal(x-4*y, z); o26 : Ideal of R |
i27 : J = I^20; o27 : Ideal of R |
i28 : M = J*R^1; |
i29 : J1 = time reflexify( J, Strategy=>IdealStrategy ) -- used 0.207849 seconds 2 2 9 9 11 o29 = ideal (x + 5x*y + 3y , x*z - 4y*z , z + x - 4y) o29 : Ideal of R |
i30 : J2 = time reflexify( J, Strategy=>ModuleStrategy ) -- used 12.1996 seconds 2 2 9 9 11 o30 = ideal (x + 5x*y + 3y , x*z - 4y*z , z + x - 4y) o30 : Ideal of R |
i31 : J1 == J2 o31 = true |
i32 : time reflexify( M, Strategy=>IdealStrategy ); -- used 11.2431 seconds |
i33 : time reflexify( M, Strategy=>ModuleStrategy ); -- used 0.608905 seconds |
However, sometimes ModuleStrategy is faster, especially for Monomial ideals.
i34 : R = QQ[x,y,u,v]/ideal(x*y-u*v); |
i35 : I = ideal(x,u); o35 : Ideal of R |
i36 : J = I^20; o36 : Ideal of R |
i37 : M = I^20*R^1; |
i38 : time reflexify( J, Strategy=>IdealStrategy ) -- used 0.334843 seconds 20 19 2 18 3 17 4 16 5 15 6 14 7 13 8 12 o38 = ideal (u , x*u , x u , x u , x u , x u , x u , x u , x u , ----------------------------------------------------------------------- 9 11 10 10 11 9 12 8 13 7 14 6 15 5 16 4 17 3 18 2 x u , x u , x u , x u , x u , x u , x u , x u , x u , x u , ----------------------------------------------------------------------- 19 20 x u, x ) o38 : Ideal of R |
i39 : time reflexify( J, Strategy=>ModuleStrategy ) -- used 0.0152154 seconds 20 19 2 18 3 17 4 16 5 15 6 14 7 13 8 12 o39 = ideal (u , x*u , x u , x u , x u , x u , x u , x u , x u , ----------------------------------------------------------------------- 9 11 10 10 11 9 12 8 13 7 14 6 15 5 16 4 17 3 18 2 x u , x u , x u , x u , x u , x u , x u , x u , x u , x u , ----------------------------------------------------------------------- 19 20 x u, x ) o39 : Ideal of R |
i40 : time reflexify( M, Strategy=>IdealStrategy ); -- used 0.0501187 seconds |
i41 : time reflexify( M, Strategy=>ModuleStrategy ); -- used 0.0170442 seconds |
For ideals, if KnownDomain is false (default value is true), then the function will check whether it is a domain. If it is a domain (or assumed to be a domain), it will reflexify using a strategy which can speed up computation, if not it will compute using a sometimes slower method which is essentially reflexifying it as a module.
Consider the following example showing the importance of making the correct assumption about the ring being a domain.
i42 : R = QQ[x,y]/ideal(x*y); |
i43 : I = ideal(x,y); o43 : Ideal of R |
i44 : reflexify(I, KnownDomain=>false) o44 = ideal (y, x) o44 : Ideal of R |
i45 : reflexify(I, KnownDomain=>true) o45 = ideal 1 o45 : Ideal of R |
i46 : J = ideal(x-y, x+y); o46 : Ideal of R |
i47 : reflexify(J, KnownDomain=>false) o47 = ideal (y, x) o47 : Ideal of R |
i48 : reflexify(I, KnownDomain=>true) o48 = ideal 1 o48 : Ideal of R |
In the above, when KnownDomain=>true (an incorrect assumption), this function returns the incorrect answer for $I$.
The object reflexify is a method function with options.