def __init__(self, begin, end, step=Integer(1), middle_point=Integer(1)): r""" TESTS:: sage: from sage.sets.integer_range import IntegerRangeFromMiddle sage: I = IntegerRangeFromMiddle(-100,100,10,0) sage: I.category() Category of facade finite enumerated sets sage: TestSuite(I).run() sage: I = IntegerRangeFromMiddle(Infinity,-Infinity,-37,0) sage: I.category() Category of facade infinite enumerated sets sage: TestSuite(I).run() sage: IntegerRange(0, 5, 1, -3) Traceback (most recent call last): ... ValueError: middle_point is not in the interval """ self._begin = begin self._end = end self._step = step self._middle_point = middle_point if not middle_point in self: raise ValueError("middle_point is not in the interval") if (begin != Infinity and begin != -Infinity) and \ (end != Infinity and end != -Infinity): Parent.__init__(self, facade=IntegerRing(), category=FiniteEnumeratedSets()) else: Parent.__init__(self, facade=IntegerRing(), category=InfiniteEnumeratedSets())
def __dimension_Sp6Z(wt): """ Return the dimensions of subspaces of Siegel modular forms on $Sp(4,Z)$. OUTPUT ("Total", "Miyawaki-Type-1", "Miyawaki-Type-2 (conjectured)", "Interesting") Remember, Miywaki type 2 is ONLY CONJECTURED!! """ if not is_even(wt): return (0, 0, 0, 0) R = PowerSeriesRing(IntegerRing(), default_prec=wt + 1, names=('x', )) (x, ) = R._first_ngens(1) R = PowerSeriesRing(IntegerRing(), default_prec=2 * wt - 1, names=('y', )) (y, ) = R._first_ngens(1) H_all = 1 / ( (1 - x**4) * (1 - x**12)**2 * (1 - x**14) * (1 - x**18) * (1 - x**20) * (1 - x**30)) * (1 + x**6 + x**10 + x**12 + 3 * x**16 + 2 * x**18 + 2 * x**20 + 5 * x**22 + 4 * x**24 + 5 * x**26 + 7 * x**28 + 6 * x**30 + 9 * x**32 + 10 * x**34 + 10 * x**36 + 12 * x**38 + 14 * x**40 + 15 * x**42 + 16 * x**44 + 18 * x**46 + 18 * x**48 + 19 * x**50 + 21 * x**52 + 19 * x**54 + 21 * x**56 + 21 * x**58 + 19 * x**60 + 21 * x**62 + 19 * x**64 + 18 * x**66 + 18 * x**68 + 16 * x**70 + 15 * x**72 + 14 * x**74 + 12 * x**76 + 10 * x**78 + 10 * x**80 + 9 * x**82 + 6 * x**84 + 7 * x**86 + 5 * x**88 + 4 * x**90 + 5 * x**92 + 2 * x**94 + 2 * x**96 + 3 * x**98 + x**102 + x**104 + x**108 + x**114) H_noncusp = 1 / (1 - x**4) / (1 - x**6) / (1 - x**10) / (1 - x**12) H_E = y**12 / (1 - y**4) / (1 - y**6) H_Miyawaki1 = H_E[wt] * H_E[2 * wt - 4] H_Miyawaki2 = H_E[wt - 2] * H_E[2 * wt - 2] a, b, c, d = H_all[wt], H_noncusp[wt], H_Miyawaki1, H_Miyawaki2 return (a, c, d, a - b - c - d)
def __getitem__(self, level): """ Return the modular polynomial of given level, or an error if there is no such polynomial in the database. EXAMPLES: sage: DBMP = ClassicalModularPolynomialDatabase() # optional - database_kohel sage: f = DBMP[29] # optional - database_kohel sage: f.degree() # optional - database_kohel 58 sage: f.coefficient([28,28]) # optional - database_kohel 400152899204646997840260839128 sage: DBMP[50] # optional - database_kohel Traceback (most recent call last): ... RuntimeError: No database entry for modular polynomial of level 50 """ if self.model in ("Atk", "Eta"): level = Integer(level) if not level.is_prime(): raise TypeError("Argument level (= %s) must be prime." % level) elif self.model in ("AtkCrr", "EtaCrr"): N = Integer(level[0]) if not N in (2, 3, 5, 7, 13): raise TypeError("Argument level (= %s) must be prime." % N) modpol = self._dbpath(level) try: coeff_list = _dbz_to_integer_list(modpol) except RuntimeError as msg: print(msg) raise RuntimeError( "No database entry for modular polynomial of level %s" % level) if self.model == "Cls": P = PolynomialRing(IntegerRing(), 2, "j") else: P = PolynomialRing(IntegerRing(), 2, "x,j") poly = {} if self.model == "Cls": if level == 1: return P({(1, 0): 1, (0, 1): -1}) for cff in coeff_list: i = cff[0] j = cff[1] poly[(i, j)] = Integer(cff[2]) if i != j: poly[(j, i)] = Integer(cff[2]) else: for cff in coeff_list: poly[(cff[0], cff[1])] = Integer(cff[2]) return P(poly)
def __getitem__(self, level): """ Return the modular polynomial of given level, or an error if there is no such polynomial in the database. EXAMPLES:: sage: DBMP = ClassicalModularPolynomialDatabase() sage: f = DBMP[29] # optional - database_kohel sage: f.degree() # optional - database_kohel 58 sage: f.coefficient([28,28]) # optional - database_kohel 400152899204646997840260839128 sage: DBMP[50] # optional - database_kohel Traceback (most recent call last): ... LookupError: filename .../kohel/PolMod/Cls/pol.050.dbz does not exist """ from sage.rings.integer import Integer from sage.rings.integer_ring import IntegerRing from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing if self.model in ("Atk", "Eta"): level = Integer(level) if not level.is_prime(): raise TypeError("Argument level (= %s) must be prime." % level) elif self.model in ("AtkCrr", "EtaCrr"): N = Integer(level[0]) if not N in (2, 3, 5, 7, 13): raise TypeError("Argument level (= %s) must be prime." % N) modpol = self._dbpath(level) coeff_list = _dbz_to_integer_list(modpol) if self.model == "Cls": P = PolynomialRing(IntegerRing(), 2, "j") else: P = PolynomialRing(IntegerRing(), 2, "x,j") poly = {} if self.model == "Cls": if level == 1: return P({(1, 0): 1, (0, 1): -1}) for cff in coeff_list: i = cff[0] j = cff[1] poly[(i, j)] = Integer(cff[2]) if i != j: poly[(j, i)] = Integer(cff[2]) else: for cff in coeff_list: poly[(cff[0], cff[1])] = Integer(cff[2]) return P(poly)
def global_genus_symbol(self): """ Returns the genus of a two times a quadratic form over ZZ. These are defined by a collection of local genus symbols (a la Chapter 15 of Conway-Sloane), and a signature. EXAMPLES:: sage: Q = DiagonalQuadraticForm(ZZ, [1,2,3,4]) sage: Q.global_genus_symbol() Genus of [2 0 0 0] [0 4 0 0] [0 0 6 0] [0 0 0 8] :: sage: Q = QuadraticForm(ZZ, 4, range(10)) sage: Q.global_genus_symbol() Genus of [ 0 1 2 3] [ 1 8 5 6] [ 2 5 14 8] [ 3 6 8 18] """ ## Check that the form is defined over ZZ if not self.base_ring() == IntegerRing(): raise TypeError, "Oops! The quadratic form is not defined over the integers." ## Return the result try: return Genus(self.Hessian_matrix()) except Exception: raise TypeError, "Oops! There is a problem computing the genus symbols for this form."
def __init__(self): r""" TESTS:: sage: TestSuite(SetsWithGrading().example()).run() """ Parent.__init__(self, category=SetsWithGrading(), facade=IntegerRing())
class ClassPolynomialDatabase: def _dbpath(self, disc, level=1): """ TESTS: sage: db = HilbertClassPolynomialDatabase() sage: db.__getitem__(-23,level=2) Traceback (most recent call last): ... NotImplementedError: Level (= 2) > 1 not yet implemented. """ if level != 1: raise NotImplementedError, "Level (= %s) > 1 not yet implemented." % level n1 = 5000 * ((abs(disc) - 1) // 5000) s1 = _pad_int_str(n1 + 1, disc_length) s2 = _pad_int_str(n1 + 5000, disc_length) subdir = "%s-%s" % (s1, s2) discstr = _pad_int_str(abs(disc), disc_length) return "PolHeeg/%s/%s/pol.%s.dbz" % (self.model, subdir, discstr) def __getitem__(self, disc, level=1, var='x'): classpol = self._dbpath(disc, level) try: coeff_list = _dbz_to_integers(classpol) except RuntimeError, msg: print msg raise RuntimeError, \ "No database entry for class polynomial of discriminant %s"%disc P = PolynomialRing(IntegerRing(), names=var) return P(list(coeff_list))
def __init__(self): """ TESTS:: sage: P = Sets().example("inherits") """ Parent.__init__(self, facade=IntegerRing(), category=Sets())
def _dimension_Sp4Z(wt_range): """ Return the dimensions of subspaces of Siegel modular forms on $Sp(4,Z)$. OUTPUT ("Total", "Eisenstein", "Klingen", "Maass", "Interesting") """ headers = ['Total', 'Eisenstein', 'Klingen', 'Maass', 'Interesting'] R = PowerSeriesRing(IntegerRing(), default_prec=wt_range[-1] + 1, names=('x', )) (x, ) = R._first_ngens(1) H_all = 1 / (1 - x**4) / (1 - x**6) / (1 - x**10) / (1 - x**12) H_Kl = x**12 / (1 - x**4) / (1 - x**6) H_MS = (x**10 + x**12) / (1 - x**4) / (1 - x**6) dct = dict( (k, { 'Total': H_all[k], 'Eisenstein': 1 if k >= 4 else 0, 'Klingen': H_Kl[k], 'Maass': H_MS[k], 'Interesting': H_all[k] - (1 if k >= 4 else 0) - H_Kl[k] - H_MS[k] } if is_even(k) else { 'Total': H_all[k - 35], 'Eisenstein': 0, 'Klingen': 0, 'Maass': 0, 'Interesting': H_all[k - 35] }) for k in wt_range) return headers, dct
def __getitem__(self,disc,level=1,var='x'): classpol = self._dbpath(disc,level) try: coeff_list = _dbz_to_integers(classpol) except RuntimeError as msg: print(msg) raise RuntimeError("No database entry for class polynomial of discriminant %s"%disc) P = PolynomialRing(IntegerRing(),names=var) return P(list(coeff_list))
def __init__(self): """ TESTS:: sage: P = Sets().example("inherits") sage: type(P(13)+P(17)) <type 'sage.rings.integer.Integer'> sage: type(P(2)+P(3)) <type 'sage.rings.integer.Integer'> """ super(PrimeNumbers_Inherits, self).__init__() self._populate_coercion_lists_(embedding=IntegerRing())
def __init__(self): """ TESTS:: sage: from sage.categories.examples.sets_cat import PrimeNumbers sage: P = PrimeNumbers() sage: P.category() Category of facade sets sage: P is Sets().example() True """ Parent.__init__(self, facade=IntegerRing(), category=Sets())
def burau_matrix(self, var='t'): """ Return the Burau matrix of the braid. INPUT: - ``var`` -- string (default: ``'t'``). The name of the variable in the entries of the matrix. OUTPUT: The Burau matrix of the braid. It is a matrix whose entries are Laurent polynomials in the variable ``var``. EXAMPLES:: sage: B = BraidGroup(4) sage: B.inject_variables() Defining s0, s1, s2 sage: b=s0*s1/s2/s1 sage: b.burau_matrix() [ -t + 1 0 -t^2 + t t^2] [ 1 0 0 0] [ 0 0 1 0] [ 0 t^-2 t^-1 - t^-2 1 - t^-1] sage: s2.burau_matrix('x') [ 1 0 0 0] [ 0 1 0 0] [ 0 0 -x + 1 x] [ 0 0 1 0] REFERENCES: http://en.wikipedia.org/wiki/Burau_representation """ R = LaurentPolynomialRing(IntegerRing(), var) t = R.gen() M = identity_matrix(R, self.strands()) for i in self.Tietze(): A = identity_matrix(R, self.strands()) if i>0: A[i-1, i-1] = 1-t A[i, i] = 0 A[i, i-1] = 1 A[i-1, i] = t if i<0: A[-1-i, -1-i] = 0 A[-i, -i] = 1-t**(-1) A[-1-i, -i] = 1 A[-i, -1-i] = t**(-1) M=M*A return M
def __init__(self, begin, step=Integer(1)): r""" TESTS:: sage: I = IntegerRange(-57,Infinity,8) sage: I.category() Category of facade infinite enumerated sets sage: TestSuite(I).run() """ assert isinstance(begin, Integer) self._begin = begin self._step = step Parent.__init__(self, facade = IntegerRing(), category = InfiniteEnumeratedSets())
def __init__(self, begin, end, step=Integer(1)): r""" TESTS:: sage: I = IntegerRange(123,12,-4) sage: I.category() Category of facade finite enumerated sets sage: TestSuite(I).run() """ self._begin = begin self._end = end self._step = step Parent.__init__(self, facade = IntegerRing(), category = FiniteEnumeratedSets())
def __init__(self): """ TESTS:: sage: C = FiniteEnumeratedSets().example() sage: C An example of a finite enumerated set: {1,2,3} sage: C.category() Category of facade finite enumerated sets sage: TestSuite(C).run() """ self._set = map(Integer, [1,2,3]) Parent.__init__(self, facade = IntegerRing(), category = FiniteEnumeratedSets())
def __init__(self, ambient = Example()): """ TESTS:: sage: C = FiniteEnumeratedSets().IsomorphicObjects().example() sage: C The image by some isomorphism of An example of a finite enumerated set: {1,2,3} sage: C.category() Category of facade isomorphic objects of finite enumerated sets sage: TestSuite(C).run() """ self._ambient = ambient Parent.__init__(self, facade = IntegerRing(), category = FiniteEnumeratedSets().IsomorphicObjects())
def _dimension_Gamma0_4(wt): """ Return the dimensions of subspaces of Siegel modular forms on $Gamma0(4)$. OUTPUT ( "Total",) REMARK Not completely implemented """ R = PowerSeriesRing(IntegerRing(), default_prec=wt + 1, names=('x', )) (x, ) = R._first_ngens(1) H_all = (1 + x**4)(1 + x**11) / (1 - x**2)**3 / (1 - x**6) return (H_all[wt], )
def __init__(self, begin, step=Integer(1)): r""" TESTS:: sage: I = IntegerRange(-57,Infinity,8) sage: I.category() Category of facade infinite enumerated sets sage: TestSuite(I).run() """ if not isinstance(begin, Integer): raise TypeError("begin should be Integer, not %r" % type(begin)) self._begin = begin self._step = step Parent.__init__(self, facade = IntegerRing(), category = InfiniteEnumeratedSets())
def tropical_coordinates(self): r""" Return the tropical coordinates of ``self`` in the braid group `B_n`. OUTPUT: - a list of `2n` tropical integers EXAMPLES:: sage: B = BraidGroup(3) sage: b = B([1]) sage: tc = b.tropical_coordinates(); tc [1, 0, 0, 2, 0, 1] sage: tc[0].parent() Tropical semiring over Integer Ring sage: b = B([-2, -2, -1, -1, 2, 2, 1, 1]) sage: b.tropical_coordinates() [1, -19, -12, 9, 0, 13] REFERENCES: .. [Dynnikov07] I. Dynnikov and B. Wiest, On the complexity of braids, J. Europ. Math. Soc. 9 (2007) .. [Dehornoy] P. Dehornoy, Le probleme d'isotopie des tresses, in lecons de mathematiques d'aujourd'hui vol. 4 """ coord = [0, 1] * self.strands() for s in self.Tietze(): k = 2 * (abs(s) - 1) x1, y1, x2, y2 = coord[k:k + 4] if s > 0: sign = 1 z = x1 - min(y1, 0) - x2 + max(y2, 0) coord[k + 1] = y2 - max(z, 0) coord[k + 3] = y1 + max(z, 0) else: sign = -1 z = x1 + min(y1, 0) - x2 - max(y2, 0) coord[k + 1] = y2 + min(z, 0) coord[k + 3] = y1 - min(z, 0) coord[k] = x1 + sign * (max(y1, 0) + max(max(y2, 0) - sign * z, 0)) coord[k + 2] = x2 + sign * (min(y2, 0) + min(min(y1, 0) + sign * z, 0)) from sage.rings.semirings.tropical_semiring import TropicalSemiring T = TropicalSemiring(IntegerRing()) return map(T, coord)
def _dimension_Gamma0_3(wt): """ Return the dimensions of subspaces of Siegel modular forms on $Gamma0(3)$. OUTPUT ( "Total") REMARK Only total dimension implemented. """ R = PowerSeriesRing(IntegerRing(), default_prec=wt + 1, names=('x', )) (x, ) = R._first_ngens(1) H_all = (1 + 2 * x**4 + x**6 + x**15 * (1 + 2 * x**2 + x**6)) / (1 - x**2) / (1 - x**4) / (1 - x**6)**2 return (H_all[wt], )
def __init__(self, field): """ Initialize. TESTS:: sage: K.<x> = FunctionField(GF(5)); _.<Y> = K[] sage: F.<y> = K.extension(Y^2 - x^3 - 1) sage: G = F.divisor_group() sage: TestSuite(G).run() """ Parent.__init__(self, base=IntegerRing(), category=CommutativeAdditiveGroups()) self._field = field # function field
def generating_series(self, var='z'): r""" Return `1 / (1-z)`. EXAMPLES:: sage: N = SetsWithGrading().example(); N Non negative integers sage: f = N.generating_series(); f 1/(-z + 1) sage: LaurentSeriesRing(ZZ,'z')(f) 1 + z + z^2 + z^3 + z^4 + z^5 + z^6 + z^7 + z^8 + z^9 + z^10 + z^11 + z^12 + z^13 + z^14 + z^15 + z^16 + z^17 + z^18 + z^19 + O(z^20) """ from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing from sage.rings.integer import Integer R = PolynomialRing(IntegerRing(), var) z = R.gen() return Integer(1) / (Integer(1) - z)
def __init__( self, doc): self.__collection = doc.get( 'collection') self.__name = doc.get( 'name') weight = doc.get( 'weight') self.__weight = sage_eval( weight) if weight else weight field = doc.get( 'field') R = PolynomialRing( IntegerRing(), name = 'x') self.__field = sage_eval( field, locals = R.gens_dict()) if field else field self.__explicit_formula = doc.get( 'explicit_formula') self.__type = doc.get( 'type') self.__is_eigenform = doc.get( 'is_eigenform') self.__is_integral = doc.get( 'is_integral') self.__representation = doc.get( 'representation') self.__id = doc.get( '_id')
def __init__(self, ainvs, verbose=False): r""" Create the mwrank elliptic curve with invariants ``ainvs``, which is a list of 5 or less *integers* `a_1`, `a_2`, `a_3`, `a_4`, and `a_5`. See the docstring of this class for full documentation. EXAMPLES: We create the elliptic curve `y^2 + y = x^3 + x^2 - 2x`:: sage: e = mwrank_EllipticCurve([0, 1, 1, -2, 0]) sage: e.ainvs() [0, 1, 1, -2, 0] """ # import here to save time during startup (mwrank takes a while to init) from sage.libs.mwrank.mwrank import _Curvedata # if not isinstance(ainvs, list) and len(ainvs) <= 5: if not isinstance(ainvs, (list,tuple)) or not len(ainvs) <= 5: raise TypeError, "ainvs must be a list or tuple of length at most 5." # Pad ainvs on the beginning by 0's, so e.g. # [a4,a5] works. ainvs = [0]*(5-len(ainvs)) + ainvs # Convert each entry to an int try: a_int = [IntegerRing()(x) for x in ainvs] except (TypeError, ValueError): raise TypeError, "ainvs must be a list or tuple of integers." self.__ainvs = a_int self.__curve = _Curvedata(a_int[0], a_int[1], a_int[2], a_int[3], a_int[4]) if verbose: self.__verbose = True else: self.__verbose = False # place holders self.__saturate = -2 # not yet saturated
def fox_derivative(self, gen): """ Return the Fox derivative of self with respect to a given generator. INPUT: - ``gen`` : the generator with respect to which the derivative will be computed. OUTPUT: An element of the group algebra with integer coefficients. EXAMPLES:: sage: G = FreeGroup(5) sage: G.inject_variables() Defining x0, x1, x2, x3, x4 sage: (~x0*x1*x0*x2*~x0).fox_derivative(x0) -B[x0^-1] + B[x0^-1*x1] - B[x0^-1*x1*x0*x2*x0^-1] sage: (~x0*x1*x0*x2*~x0).fox_derivative(x1) B[x0^-1] sage: (~x0*x1*x0*x2*~x0).fox_derivative(x2) B[x0^-1*x1*x0] sage: (~x0*x1*x0*x2*~x0).fox_derivative(x3) 0 """ if not gen in self.parent().generators(): raise ValueError( "Fox derivative can only be computed with respect to generators of the group" ) l = list(self.Tietze()) R = self.parent().algebra(IntegerRing()) i = gen.Tietze()[0] a = R.zero() while len(l) > 0: b = l.pop(-1) if b == i: p = R(self.parent()(l)) a += p elif b == -i: p = R(self.parent()(l + [b])) a -= p return a
def __init__(self): """ TESTS:: sage: P = Sets().example("wrapper") sage: P.category() Category of sets sage: P(13) == 13 True sage: ZZ(P(13)) == 13 True sage: P(13) + 1 == 14 True """ Parent.__init__(self, category=Sets()) from sage.rings.integer_ring import IntegerRing from sage.categories.homset import Hom self.mor = Hom(self, IntegerRing())(lambda z: z.value) self._populate_coercion_lists_(embedding=self.mor)
def __init__(self, field): """ Initialize. INPUT: - ``field`` -- function field EXAMPLES:: sage: K.<x> = FunctionField(GF(5)); _.<t> = PolynomialRing(K) sage: F.<y> = K.extension(t^2-x^3-1) sage: F.divisor_group() Divisor group of Function field in y defined by y^2 + 4*x^3 + 4 """ Parent.__init__(self, base=IntegerRing(), category=CommutativeAdditiveGroups()) self._field = field # function field
def _dimension_Gamma0_3_psi_3(wt): """ Return the dimensions of the space of Siegel modular forms on $Gamma_0(3)$ with character $\psi_3$. OUTPUT ( "Total") REMARK Not completely implemented """ R = PowerSeriesRing(IntegerRing(), default_prec=wt + 1, names=('x', )) (x, ) = R._first_ngens(1) B = 1 / (1 - x**1) / (1 - x**3) / (1 - x**4) / (1 - x**3) H_all_odd = B H_all_even = B * x**14 if is_even(wt): return (H_all_even[wt], ) else: return (H_all_odd[wt], )
def __init__(self, ainvs, verbose=False): r""" Create the mwrank elliptic curve with invariants ``ainvs``, which is a list of 5 or less *integers* `a_1`, `a_2`, `a_3`, `a_4`, and `a_5`. See the docstring of this class for full documentation. EXAMPLES: We create the elliptic curve `y^2 + y = x^3 + x^2 - 2x`:: sage: e = mwrank_EllipticCurve([0, 1, 1, -2, 0]) sage: e.ainvs() [0, 1, 1, -2, 0] """ ainvs = list(ainvs) if len(ainvs) > 5: raise TypeError("ainvs must have length at most 5") # Pad ainvs on the beginning by 0's, so e.g. [a4, a6] works ainvs = [0] * (5 - len(ainvs)) + ainvs # Convert each entry to an int try: a_int = [IntegerRing()(x) for x in ainvs] except (TypeError, ValueError): raise TypeError("ainvs must be a list or tuple of integers.") self.__ainvs = a_int self.__curve = _Curvedata(a_int[0], a_int[1], a_int[2], a_int[3], a_int[4]) if verbose: self.__verbose = True else: self.__verbose = False # place holders self.__saturate = -2 # not yet saturated self.__descent = None
def gen_lattice(type='modular', n=4, m=8, q=11, seed=None, \ quotient=None, dual=False, ntl=False): """ This function generates different types of integral lattice bases of row vectors relevant in cryptography. Randomness can be set either with ``seed``, or by using :func:`sage.misc.randstate.set_random_seed`. INPUT: * ``type`` - one of the following strings * ``'modular'`` (default). A class of lattices for which asymptotic worst-case to average-case connections hold. For more refer to [A96]_. * ``'random'`` - Special case of modular (n=1). A dense class of lattice used for testing basis reduction algorithms proposed by Goldstein and Mayer [GM02]_. * ``'ideal'`` - Special case of modular. Allows for a more compact representation proposed by [LM06]_. * ``'cyclotomic'`` - Special case of ideal. Allows for efficient processing proposed by [LM06]_. * ``n`` - Determinant size, primal:`det(L) = q^n`, dual:`det(L) = q^{m-n}`. For ideal lattices this is also the degree of the quotient polynomial. * ``m`` - Lattice dimension, `L \subseteq Z^m`. * ``q`` - Coefficent size, `q*Z^m \subseteq L`. * ``seed`` - Randomness seed. * ``quotient`` - For the type ideal, this determines the quotient polynomial. Ignored for all other types. * ``dual`` - Set this flag if you want a basis for `q*dual(L)`, for example for Regev's LWE bases [R05]_. * ``ntl`` - Set this flag if you want the lattice basis in NTL readable format. OUTPUT: ``B`` a unique size-reduced triangular (primal: lower_left, dual: lower_right) basis of row vectors for the lattice in question. EXAMPLES: * Modular basis :: sage: sage.crypto.gen_lattice(m=10, seed=42) [11 0 0 0 0 0 0 0 0 0] [ 0 11 0 0 0 0 0 0 0 0] [ 0 0 11 0 0 0 0 0 0 0] [ 0 0 0 11 0 0 0 0 0 0] [ 2 4 3 5 1 0 0 0 0 0] [ 1 -5 -4 2 0 1 0 0 0 0] [-4 3 -1 1 0 0 1 0 0 0] [-2 -3 -4 -1 0 0 0 1 0 0] [-5 -5 3 3 0 0 0 0 1 0] [-4 -3 2 -5 0 0 0 0 0 1] * Random basis :: sage: sage.crypto.gen_lattice(type='random', n=1, m=10, q=11^4, seed=42) [14641 0 0 0 0 0 0 0 0 0] [ 431 1 0 0 0 0 0 0 0 0] [-4792 0 1 0 0 0 0 0 0 0] [ 1015 0 0 1 0 0 0 0 0 0] [-3086 0 0 0 1 0 0 0 0 0] [-5378 0 0 0 0 1 0 0 0 0] [ 4769 0 0 0 0 0 1 0 0 0] [-1159 0 0 0 0 0 0 1 0 0] [ 3082 0 0 0 0 0 0 0 1 0] [-4580 0 0 0 0 0 0 0 0 1] * Ideal bases with quotient x^n-1, m=2*n are NTRU bases :: sage: sage.crypto.gen_lattice(type='ideal', seed=42, quotient=x^4-1) [11 0 0 0 0 0 0 0] [ 0 11 0 0 0 0 0 0] [ 0 0 11 0 0 0 0 0] [ 0 0 0 11 0 0 0 0] [ 4 -2 -3 -3 1 0 0 0] [-3 4 -2 -3 0 1 0 0] [-3 -3 4 -2 0 0 1 0] [-2 -3 -3 4 0 0 0 1] * Cyclotomic bases with n=2^k are SWIFFT bases :: sage: sage.crypto.gen_lattice(type='cyclotomic', seed=42) [11 0 0 0 0 0 0 0] [ 0 11 0 0 0 0 0 0] [ 0 0 11 0 0 0 0 0] [ 0 0 0 11 0 0 0 0] [ 4 -2 -3 -3 1 0 0 0] [ 3 4 -2 -3 0 1 0 0] [ 3 3 4 -2 0 0 1 0] [ 2 3 3 4 0 0 0 1] * Dual modular bases are related to Regev's famous public-key encryption [R05]_ :: sage: sage.crypto.gen_lattice(type='modular', m=10, seed=42, dual=True) [ 0 0 0 0 0 0 0 0 0 11] [ 0 0 0 0 0 0 0 0 11 0] [ 0 0 0 0 0 0 0 11 0 0] [ 0 0 0 0 0 0 11 0 0 0] [ 0 0 0 0 0 11 0 0 0 0] [ 0 0 0 0 11 0 0 0 0 0] [ 0 0 0 1 -5 -2 -1 1 -3 5] [ 0 0 1 0 -3 4 1 4 -3 -2] [ 0 1 0 0 -4 5 -3 3 5 3] [ 1 0 0 0 -2 -1 4 2 5 4] * Relation of primal and dual bases :: sage: B_primal=sage.crypto.gen_lattice(m=10, q=11, seed=42) sage: B_dual=sage.crypto.gen_lattice(m=10, q=11, seed=42, dual=True) sage: B_dual_alt=transpose(11*B_primal.inverse()).change_ring(ZZ) sage: B_dual_alt.hermite_form() == B_dual.hermite_form() True REFERENCES: .. [A96] Miklos Ajtai. Generating hard instances of lattice problems (extended abstract). STOC, pp. 99--108, ACM, 1996. .. [GM02] Daniel Goldstein and Andrew Mayer. On the equidistribution of Hecke points. Forum Mathematicum, 15:2, pp. 165--189, De Gruyter, 2003. .. [LM06] Vadim Lyubashevsky and Daniele Micciancio. Generalized compact knapsacks are collision resistant. ICALP, pp. 144--155, Springer, 2006. .. [R05] Oded Regev. On lattices, learning with errors, random linear codes, and cryptography. STOC, pp. 84--93, ACM, 2005. """ from sage.rings.finite_rings.integer_mod_ring \ import IntegerModRing from sage.matrix.constructor import matrix, \ identity_matrix, block_matrix from sage.matrix.matrix_space import MatrixSpace from sage.rings.integer_ring import IntegerRing if seed != None: from sage.misc.randstate import set_random_seed set_random_seed(seed) if type == 'random': if n != 1: raise ValueError('random bases require n = 1') ZZ = IntegerRing() ZZ_q = IntegerModRing(q) A = identity_matrix(ZZ_q, n) if type == 'random' or type == 'modular': R = MatrixSpace(ZZ_q, m-n, n) A = A.stack(R.random_element()) elif type == 'ideal': if quotient == None: raise \ ValueError('ideal bases require a quotient polynomial') x = quotient.default_variable() if n != quotient.degree(x): raise \ ValueError('ideal bases require n = quotient.degree()') R = ZZ_q[x].quotient(quotient, x) for i in range(m//n): A = A.stack(R.random_element().matrix()) elif type == 'cyclotomic': from sage.rings.arith import euler_phi from sage.misc.functional import cyclotomic_polynomial # we assume that n+1 <= min( euler_phi^{-1}(n) ) <= 2*n found = False for k in range(2*n,n,-1): if euler_phi(k) == n: found = True break if not found: raise \ ValueError('cyclotomic bases require that n is an image of' + \ 'Euler\'s totient function') R = ZZ_q['x'].quotient(cyclotomic_polynomial(k, 'x'), 'x') for i in range(m//n): A = A.stack(R.random_element().matrix()) # switch from representatives 0,...,(q-1) to (1-q)/2,....,(q-1)/2 def minrep(a): if abs(a-q) < abs(a): return a-q else: return a A_prime = A[n:m].lift().apply_map(minrep) if not dual: B = block_matrix([[ZZ(q), ZZ.zero()], [A_prime, ZZ.one()] ], \ subdivide=False) else: B = block_matrix([[ZZ.one(), -A_prime.transpose()], [ZZ.zero(), \ ZZ(q)]], subdivide=False) for i in range(m//2): B.swap_rows(i,m-i-1) if not ntl: return B else: return B._ntl_()
def gen_lattice(type='modular', n=4, m=8, q=11, seed=None, quotient=None, dual=False, ntl=False, lattice=False): """ This function generates different types of integral lattice bases of row vectors relevant in cryptography. Randomness can be set either with ``seed``, or by using :func:`sage.misc.randstate.set_random_seed`. INPUT: - ``type`` -- one of the following strings - ``'modular'`` (default) -- A class of lattices for which asymptotic worst-case to average-case connections hold. For more refer to [A96]_. - ``'random'`` -- Special case of modular (n=1). A dense class of lattice used for testing basis reduction algorithms proposed by Goldstein and Mayer [GM02]_. - ``'ideal'`` -- Special case of modular. Allows for a more compact representation proposed by [LM06]_. - ``'cyclotomic'`` -- Special case of ideal. Allows for efficient processing proposed by [LM06]_. - ``n`` -- Determinant size, primal:`det(L) = q^n`, dual:`det(L) = q^{m-n}`. For ideal lattices this is also the degree of the quotient polynomial. - ``m`` -- Lattice dimension, `L \subseteq Z^m`. - ``q`` -- Coefficient size, `q-Z^m \subseteq L`. - ``seed`` -- Randomness seed. - ``quotient`` -- For the type ideal, this determines the quotient polynomial. Ignored for all other types. - ``dual`` -- Set this flag if you want a basis for `q-dual(L)`, for example for Regev's LWE bases [R05]_. - ``ntl`` -- Set this flag if you want the lattice basis in NTL readable format. - ``lattice`` -- Set this flag if you want a :class:`FreeModule_submodule_with_basis_integer` object instead of an integer matrix representing the basis. OUTPUT: ``B`` a unique size-reduced triangular (primal: lower_left, dual: lower_right) basis of row vectors for the lattice in question. EXAMPLES: Modular basis:: sage: sage.crypto.gen_lattice(m=10, seed=42) [11 0 0 0 0 0 0 0 0 0] [ 0 11 0 0 0 0 0 0 0 0] [ 0 0 11 0 0 0 0 0 0 0] [ 0 0 0 11 0 0 0 0 0 0] [ 2 4 3 5 1 0 0 0 0 0] [ 1 -5 -4 2 0 1 0 0 0 0] [-4 3 -1 1 0 0 1 0 0 0] [-2 -3 -4 -1 0 0 0 1 0 0] [-5 -5 3 3 0 0 0 0 1 0] [-4 -3 2 -5 0 0 0 0 0 1] Random basis:: sage: sage.crypto.gen_lattice(type='random', n=1, m=10, q=11^4, seed=42) [14641 0 0 0 0 0 0 0 0 0] [ 431 1 0 0 0 0 0 0 0 0] [-4792 0 1 0 0 0 0 0 0 0] [ 1015 0 0 1 0 0 0 0 0 0] [-3086 0 0 0 1 0 0 0 0 0] [-5378 0 0 0 0 1 0 0 0 0] [ 4769 0 0 0 0 0 1 0 0 0] [-1159 0 0 0 0 0 0 1 0 0] [ 3082 0 0 0 0 0 0 0 1 0] [-4580 0 0 0 0 0 0 0 0 1] Ideal bases with quotient x^n-1, m=2*n are NTRU bases:: sage: sage.crypto.gen_lattice(type='ideal', seed=42, quotient=x^4-1) [11 0 0 0 0 0 0 0] [ 0 11 0 0 0 0 0 0] [ 0 0 11 0 0 0 0 0] [ 0 0 0 11 0 0 0 0] [ 4 -2 -3 -3 1 0 0 0] [-3 4 -2 -3 0 1 0 0] [-3 -3 4 -2 0 0 1 0] [-2 -3 -3 4 0 0 0 1] Ideal bases also work with polynomials:: sage: R.<t> = PolynomialRing(ZZ) sage: sage.crypto.gen_lattice(type='ideal', seed=1234, quotient=t^4-1) [11 0 0 0 0 0 0 0] [ 0 11 0 0 0 0 0 0] [ 0 0 11 0 0 0 0 0] [ 0 0 0 11 0 0 0 0] [ 4 1 4 -3 1 0 0 0] [-3 4 1 4 0 1 0 0] [ 4 -3 4 1 0 0 1 0] [ 1 4 -3 4 0 0 0 1] Cyclotomic bases with n=2^k are SWIFFT bases:: sage: sage.crypto.gen_lattice(type='cyclotomic', seed=42) [11 0 0 0 0 0 0 0] [ 0 11 0 0 0 0 0 0] [ 0 0 11 0 0 0 0 0] [ 0 0 0 11 0 0 0 0] [ 4 -2 -3 -3 1 0 0 0] [ 3 4 -2 -3 0 1 0 0] [ 3 3 4 -2 0 0 1 0] [ 2 3 3 4 0 0 0 1] Dual modular bases are related to Regev's famous public-key encryption [R05]_:: sage: sage.crypto.gen_lattice(type='modular', m=10, seed=42, dual=True) [ 0 0 0 0 0 0 0 0 0 11] [ 0 0 0 0 0 0 0 0 11 0] [ 0 0 0 0 0 0 0 11 0 0] [ 0 0 0 0 0 0 11 0 0 0] [ 0 0 0 0 0 11 0 0 0 0] [ 0 0 0 0 11 0 0 0 0 0] [ 0 0 0 1 -5 -2 -1 1 -3 5] [ 0 0 1 0 -3 4 1 4 -3 -2] [ 0 1 0 0 -4 5 -3 3 5 3] [ 1 0 0 0 -2 -1 4 2 5 4] Relation of primal and dual bases:: sage: B_primal=sage.crypto.gen_lattice(m=10, q=11, seed=42) sage: B_dual=sage.crypto.gen_lattice(m=10, q=11, seed=42, dual=True) sage: B_dual_alt=transpose(11*B_primal.inverse()).change_ring(ZZ) sage: B_dual_alt.hermite_form() == B_dual.hermite_form() True TESTS: Test some bad quotient polynomials:: sage: sage.crypto.gen_lattice(type='ideal', seed=1234, quotient=cos(x)) Traceback (most recent call last): ... TypeError: unable to convert cos(x) to an integer sage: sage.crypto.gen_lattice(type='ideal', seed=1234, quotient=x^23-1) Traceback (most recent call last): ... ValueError: ideal basis requires n = quotient.degree() sage: R.<u,v> = ZZ[] sage: sage.crypto.gen_lattice(type='ideal', seed=1234, quotient=u+v) Traceback (most recent call last): ... TypeError: quotient should be a univariate polynomial We are testing output format choices:: sage: sage.crypto.gen_lattice(m=10, q=11, seed=42) [11 0 0 0 0 0 0 0 0 0] [ 0 11 0 0 0 0 0 0 0 0] [ 0 0 11 0 0 0 0 0 0 0] [ 0 0 0 11 0 0 0 0 0 0] [ 2 4 3 5 1 0 0 0 0 0] [ 1 -5 -4 2 0 1 0 0 0 0] [-4 3 -1 1 0 0 1 0 0 0] [-2 -3 -4 -1 0 0 0 1 0 0] [-5 -5 3 3 0 0 0 0 1 0] [-4 -3 2 -5 0 0 0 0 0 1] sage: sage.crypto.gen_lattice(m=10, q=11, seed=42, ntl=True) [ [11 0 0 0 0 0 0 0 0 0] [0 11 0 0 0 0 0 0 0 0] [0 0 11 0 0 0 0 0 0 0] [0 0 0 11 0 0 0 0 0 0] [2 4 3 5 1 0 0 0 0 0] [1 -5 -4 2 0 1 0 0 0 0] [-4 3 -1 1 0 0 1 0 0 0] [-2 -3 -4 -1 0 0 0 1 0 0] [-5 -5 3 3 0 0 0 0 1 0] [-4 -3 2 -5 0 0 0 0 0 1] ] sage: sage.crypto.gen_lattice(m=10, q=11, seed=42, lattice=True) Free module of degree 10 and rank 10 over Integer Ring User basis matrix: [ 0 0 1 1 0 -1 -1 -1 1 0] [-1 1 0 1 0 1 1 0 1 1] [-1 0 0 0 -1 1 1 -2 0 0] [-1 -1 0 1 1 0 0 1 1 -1] [ 1 0 -1 0 0 0 -2 -2 0 0] [ 2 -1 0 0 1 0 1 0 0 -1] [-1 1 -1 0 1 -1 1 0 -1 -2] [ 0 0 -1 3 0 0 0 -1 -1 -1] [ 0 -1 0 -1 2 0 -1 0 0 2] [ 0 1 1 0 1 1 -2 1 -1 -2] REFERENCES: .. [A96] Miklos Ajtai. Generating hard instances of lattice problems (extended abstract). STOC, pp. 99--108, ACM, 1996. .. [GM02] Daniel Goldstein and Andrew Mayer. On the equidistribution of Hecke points. Forum Mathematicum, 15:2, pp. 165--189, De Gruyter, 2003. .. [LM06] Vadim Lyubashevsky and Daniele Micciancio. Generalized compact knapsacks are collision resistant. ICALP, pp. 144--155, Springer, 2006. .. [R05] Oded Regev. On lattices, learning with errors, random linear codes, and cryptography. STOC, pp. 84--93, ACM, 2005. """ from sage.rings.finite_rings.integer_mod_ring import IntegerModRing from sage.matrix.constructor import identity_matrix, block_matrix from sage.matrix.matrix_space import MatrixSpace from sage.rings.integer_ring import IntegerRing if seed is not None: from sage.misc.randstate import set_random_seed set_random_seed(seed) if type == 'random': if n != 1: raise ValueError('random bases require n = 1') ZZ = IntegerRing() ZZ_q = IntegerModRing(q) A = identity_matrix(ZZ_q, n) if type == 'random' or type == 'modular': R = MatrixSpace(ZZ_q, m-n, n) A = A.stack(R.random_element()) elif type == 'ideal': if quotient is None: raise ValueError('ideal bases require a quotient polynomial') try: quotient = quotient.change_ring(ZZ_q) except (AttributeError, TypeError): quotient = quotient.polynomial(base_ring=ZZ_q) P = quotient.parent() # P should be a univariate polynomial ring over ZZ_q if not is_PolynomialRing(P): raise TypeError("quotient should be a univariate polynomial") assert P.base_ring() is ZZ_q if quotient.degree() != n: raise ValueError('ideal basis requires n = quotient.degree()') R = P.quotient(quotient) for i in range(m//n): A = A.stack(R.random_element().matrix()) elif type == 'cyclotomic': from sage.arith.all import euler_phi from sage.misc.functional import cyclotomic_polynomial # we assume that n+1 <= min( euler_phi^{-1}(n) ) <= 2*n found = False for k in range(2*n,n,-1): if euler_phi(k) == n: found = True break if not found: raise ValueError("cyclotomic bases require that n " "is an image of Euler's totient function") R = ZZ_q['x'].quotient(cyclotomic_polynomial(k, 'x'), 'x') for i in range(m//n): A = A.stack(R.random_element().matrix()) # switch from representatives 0,...,(q-1) to (1-q)/2,....,(q-1)/2 def minrep(a): if abs(a-q) < abs(a): return a-q else: return a A_prime = A[n:m].lift().apply_map(minrep) if not dual: B = block_matrix([[ZZ(q), ZZ.zero()], [A_prime, ZZ.one()] ], subdivide=False) else: B = block_matrix([[ZZ.one(), -A_prime.transpose()], [ZZ.zero(), ZZ(q)]], subdivide=False) for i in range(m//2): B.swap_rows(i,m-i-1) if ntl and lattice: raise ValueError("Cannot specify ntl=True and lattice=True " "at the same time") if ntl: return B._ntl_() elif lattice: from sage.modules.free_module_integer import IntegerLattice return IntegerLattice(B) else: return B