Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sagemath
GitHub Repository: sagemath/sagelib
Path: blob/master/sage/schemes/toric/ideal.py
4108 views
1
r"""
2
Toric ideals
3
4
A toric ideal (associated to an integer matrix `A`) is an ideal of the
5
form
6
7
.. MATH::
8
9
I_A = \left<
10
x^u - x^v
11
: u,v \in \ZZ_\geq^n
12
, u-v \in \ker(A)
13
\right>
14
15
In other words, it is an ideal generated by irreducible "binomials",
16
that is, differences of monomials without a common factor. Since the
17
Buchberger algorithm preserves this property, any Groebner basis is
18
then also generated by binomials.
19
20
EXAMPLES::
21
22
sage: A = matrix([[1,1,1],[0,1,2]])
23
sage: IA = ToricIdeal(A)
24
sage: IA.ker()
25
Free module of degree 3 and rank 1 over Integer Ring
26
User basis matrix:
27
[ 1 -2 1]
28
sage: IA
29
Ideal (-z1^2 + z0*z2) of Multivariate Polynomial
30
Ring in z0, z1, z2 over Rational Field
31
32
Here, the "naive" ideal generated by `z_0 z_2 - z_1^2` does already
33
equal the toric ideal. But that is not true in general! For example,
34
this toric ideal ([ProcSympPureMath62], Example 1.2) is the twisted
35
cubic and cannot be generated by `2=\dim \ker(A)` polynomials::
36
37
sage: A = matrix([[3,2,1,0],[0,1,2,3]])
38
sage: IA = ToricIdeal(A)
39
sage: IA.ker()
40
Free module of degree 4 and rank 2 over Integer Ring
41
User basis matrix:
42
[ 1 -1 -1 1]
43
[ 1 -2 1 0]
44
sage: IA
45
Ideal (-z1*z2 + z0*z3, -z1^2 + z0*z2, z2^2 - z1*z3) of
46
Multivariate Polynomial Ring in z0, z1, z2, z3 over Rational Field
47
48
The following family of toric ideals is from Example 4.4 of
49
[ProcSympPureMath62]_. One can show that `I_d` is generated by one
50
quadric and `d` binomials of degree `d`::
51
52
sage: I = lambda d: ToricIdeal(matrix([[1,1,1,1,1],[0,1,1,0,0],[0,0,1,1,d]]))
53
sage: I(2)
54
Ideal (-z3^2 + z0*z4,
55
z0*z2 - z1*z3,
56
z2*z3 - z1*z4) of
57
Multivariate Polynomial Ring in z0, z1, z2, z3, z4 over Rational Field
58
sage: I(3)
59
Ideal (-z3^3 + z0^2*z4,
60
z0*z2 - z1*z3,
61
z2*z3^2 - z0*z1*z4,
62
z2^2*z3 - z1^2*z4) of
63
Multivariate Polynomial Ring in z0, z1, z2, z3, z4 over Rational Field
64
sage: I(4)
65
Ideal (-z3^4 + z0^3*z4,
66
z0*z2 - z1*z3,
67
z2*z3^3 - z0^2*z1*z4,
68
z2^2*z3^2 - z0*z1^2*z4,
69
z2^3*z3 - z1^3*z4) of
70
Multivariate Polynomial Ring in z0, z1, z2, z3, z4 over Rational Field
71
72
Finally, the example in [GRIN]_ ::
73
74
sage: A = matrix(ZZ, [ [15, 4, 14, 19, 2, 1, 10, 17],
75
... [18, 11, 13, 5, 16, 16, 8, 19],
76
... [11, 7, 8, 19, 15, 18, 14, 6],
77
... [17, 10, 13, 17, 16, 14, 15, 18] ])
78
sage: IA = ToricIdeal(A) # long time
79
sage: IA.ngens() # long time
80
213
81
82
TESTS::
83
84
sage: A = matrix(ZZ, [[1, 1, 0, 0, -1, 0, 0, -1],
85
... [0, 0, 1, 1, 0, -1, -1, 0],
86
... [1, 0, 0, 1, 1, 1, 0, 0],
87
... [1, 0, 0, 1, 0, 0, -1, -1]])
88
sage: IA = ToricIdeal(A)
89
sage: R = IA.ring()
90
sage: R.inject_variables()
91
Defining z0, z1, z2, z3, z4, z5, z6, z7
92
sage: IA == R.ideal([z4*z6-z5*z7, z2*z5-z3*z6, -z3*z7+z2*z4,
93
... -z2*z6+z1*z7, z1*z4-z3*z6, z0*z7-z3*z6, -z1*z5+z0*z6, -z3*z5+z0*z4,
94
... z0*z2-z1*z3]) # Computed with Maple 12
95
True
96
97
The next example first appeared in Example 12.7 in [GBCP]_. It is also
98
used by the Maple 12 help system as example::
99
100
sage: A = matrix(ZZ, [[1, 2, 3, 4, 0, 1, 4, 5],
101
... [2, 3, 4, 1, 1, 4, 5, 0],
102
... [3, 4, 1, 2, 4, 5, 0, 1],
103
... [4, 1, 2, 3, 5, 0, 1, 4]])
104
sage: IA = ToricIdeal(A, 'z1, z2, z3, z4, z5, z6, z7, z8')
105
sage: R = IA.ring()
106
sage: R.inject_variables()
107
Defining z1, z2, z3, z4, z5, z6, z7, z8
108
sage: IA == R.ideal([z4^4-z6*z8^3, z3^4-z5*z7^3, -z4^3+z2*z8^2,
109
... z2*z4-z6*z8, -z4^2*z6+z2^2*z8, -z4*z6^2+z2^3, -z3^3+z1*z7^2,
110
... z1*z3-z5*z7, -z3^2*z5+z1^2*z7, z1^3-z3*z5^2])
111
True
112
113
114
REFERENCES:
115
116
.. [GRIN]
117
Bernd Sturmfels, Serkan Hosten:
118
GRIN: An implementation of Grobner bases for integer programming,
119
in "Integer Programming and Combinatorial Optimization",
120
[E. Balas and J. Clausen, eds.],
121
Proceedings of the IV. IPCO Conference (Copenhagen, May 1995),
122
Springer Lecture Notes in Computer Science 920 (1995) 267-276.
123
124
.. [ProcSympPureMath62]
125
Bernd Sturmfels:
126
Equations defining toric varieties,
127
Algebraic Geometry - Santa Cruz 1995,
128
Proc. Sympos. Pure Math., 62, Part 2,
129
Amer. Math. Soc., Providence, RI, 1997,
130
pp. 437-449.
131
132
.. [GBCP]
133
Bernd Sturmfels:
134
Grobner Bases and Convex Polytopes
135
AMS University Lecture Series Vol. 8 (01 December 1995)
136
137
AUTHORS:
138
139
- Volker Braun (2011-01-03): Initial version
140
"""
141
142
#*****************************************************************************
143
# Copyright (C) 2010 Volker Braun <[email protected]>
144
#
145
# Distributed under the terms of the GNU General Public License (GPL)
146
# as published by the Free Software Foundation; either version 2 of
147
# the License, or (at your option) any later version.
148
# http://www.gnu.org/licenses/
149
#*****************************************************************************
150
151
# TODO:
152
# * Implement the Di Biase & Urbanke algorithm
153
# * Implement the Conti & Traverso algorithm (for educational purposes)
154
# * Cythonize the Buchberger algorithm for toric ideals
155
# * Use the (multiple) weighted homegeneity during Groebner basis computations
156
157
158
159
from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing
160
from sage.misc.misc_c import prod
161
from sage.matrix.constructor import matrix
162
from sage.rings.all import ZZ, QQ
163
from sage.rings.polynomial.multi_polynomial_ideal import MPolynomialIdeal
164
165
166
class ToricIdeal(MPolynomialIdeal):
167
r"""
168
This class represents a toric ideal defined by an integral matrix.
169
170
INPUT:
171
172
- ``A`` -- integer matrix. The defining matrix of the toric ideal.
173
174
- ``names`` -- string (optional). Names for the variables. By
175
default, this is ``'z'`` and the variables will be named ``z0``,
176
``z1``, ...
177
178
- ``base_ring`` -- a ring (optional). Default: `\QQ`. The base
179
ring of the ideal. A toric ideal uses only coefficents `\pm 1`.
180
181
- ``polynomial_ring`` -- a polynomial ring (optional). The
182
polynomial ring to construct the ideal in.
183
184
You may specify the ambient polynomial ring via the
185
``polynomial_ring`` parameter or via the ``names`` and
186
``base_ring`` parameter. A ``ValueError`` is raised if you
187
specify both.
188
189
- ``algorithm`` -- string (optional). The algorithm to use. For
190
now, must be ``'HostenSturmfels'`` which is the algorithm
191
proposed by Hosten and Sturmfels in [GRIN].
192
193
EXAMPLES::
194
195
sage: A = matrix([[1,1,1],[0,1,2]])
196
sage: ToricIdeal(A)
197
Ideal (-z1^2 + z0*z2) of Multivariate Polynomial Ring
198
in z0, z1, z2 over Rational Field
199
200
First way of specifying the polynomial ring::
201
202
sage: ToricIdeal(A, names='x,y,z', base_ring=ZZ)
203
Ideal (-y^2 + x*z) of Multivariate Polynomial Ring
204
in x, y, z over Integer Ring
205
206
Second way of specifying the polynomial ring::
207
208
sage: R.<x,y,z> = ZZ[]
209
sage: ToricIdeal(A, polynomial_ring=R)
210
Ideal (-y^2 + x*z) of Multivariate Polynomial Ring
211
in x, y, z over Integer Ring
212
213
It is an error to specify both::
214
215
sage: ToricIdeal(A, names='x,y,z', polynomial_ring=R)
216
Traceback (most recent call last):
217
...
218
ValueError: You must not specify both variable names and a polynomial ring.
219
"""
220
221
def __init__(self, A,
222
names='z', base_ring=QQ,
223
polynomial_ring=None,
224
algorithm='HostenSturmfels'):
225
r"""
226
Create an ideal and a multivariate polynomial ring containing it.
227
228
See the :mod:`module documentation
229
<sage.schemes.toric.ideal>` for an introduction to
230
toric ideals.
231
232
INPUT:
233
234
See the :class:`class-level documentation <ToricIdeal>` for
235
input values.
236
237
EXAMPLES::
238
239
sage: A = matrix([[1,1,1],[0,1,2]])
240
sage: ToricIdeal(A)
241
Ideal (-z1^2 + z0*z2) of Multivariate Polynomial Ring
242
in z0, z1, z2 over Rational Field
243
sage: ToricIdeal(A, names='x', base_ring=GF(101))
244
Ideal (-x1^2 + x0*x2) of Multivariate Polynomial Ring
245
in x0, x1, x2 over Finite Field of size 101
246
sage: ToricIdeal(A, names='x', base_ring=FractionField(QQ['t']))
247
Ideal (-x1^2 + x0*x2) of Multivariate Polynomial Ring
248
in x0, x1, x2 over Fraction Field of Univariate Polynomial Ring in t over Rational Field
249
"""
250
self._A = matrix(ZZ, A)
251
if polynomial_ring:
252
if (names!='z') or (base_ring is not QQ):
253
raise ValueError('You must not specify both variable names and a polynomial ring.')
254
self._names = map(str, polynomial_ring.gens())
255
self._base_ring = polynomial_ring.base_ring()
256
ring = polynomial_ring
257
else:
258
self._names = names
259
self._base_ring = base_ring
260
ring = self._init_ring('degrevlex')
261
262
if algorithm=='HostenSturmfels':
263
ideal = self._ideal_HostenSturmfels()
264
else:
265
raise ValueError, 'Algorithm = '+str(algorithm)+' is not known!'
266
267
gens = [ ring(x) for x in ideal.gens() ]
268
MPolynomialIdeal.__init__(self, ring, gens, coerce=False)
269
270
def A(self):
271
"""
272
Return the defining matrix.
273
274
OUTPUT:
275
276
An integer matrix.
277
278
EXAMPLES::
279
280
sage: A = matrix([[1,1,1],[0,1,2]])
281
sage: IA = ToricIdeal(A)
282
sage: IA.A()
283
[1 1 1]
284
[0 1 2]
285
"""
286
return self._A
287
288
def ker(self):
289
"""
290
Return the kernel of the defining matrix.
291
292
OUTPUT:
293
294
The kernel of ``self.A()``.
295
296
EXAMPLES::
297
298
sage: A = matrix([[1,1,1],[0,1,2]])
299
sage: IA = ToricIdeal(A)
300
sage: IA.ker()
301
Free module of degree 3 and rank 1 over Integer Ring
302
User basis matrix:
303
[ 1 -2 1]
304
"""
305
306
if '_ker' in self.__dict__:
307
return self._ker
308
self._ker = self.A().right_kernel(basis='LLL')
309
return self._ker
310
311
def nvariables(self):
312
r"""
313
Return the number of variables of the ambient polynomial ring.
314
315
OUTPUT:
316
317
Integer. The number of columns of the defining matrix
318
:meth:`A`.
319
320
EXAMPLES::
321
322
sage: A = matrix([[1,1,1],[0,1,2]])
323
sage: IA = ToricIdeal(A)
324
sage: IA.nvariables()
325
3
326
"""
327
return self.A().ncols()
328
329
def _init_ring(self, term_order):
330
r"""
331
Construct the ambient polynomial ring.
332
333
INPUT:
334
335
- ``term_order`` -- string. The order of the variables, for
336
example ``'neglex'`` and ``'degrevlex'``.
337
338
OUTPUT:
339
340
A polynomial ring with the given term order.
341
342
.. NOTE::
343
344
Reverse lexicographic ordering is equivalent to negative
345
lexicographic order with the reversed list of
346
variables. We are using the latter in the implementation
347
of the Hosten/Sturmfels algorithm.
348
349
EXAMPLES::
350
351
sage: A = matrix([[1,1,1],[0,1,2]])
352
sage: IA = ToricIdeal(A)
353
sage: R = IA._init_ring('neglex'); R
354
Multivariate Polynomial Ring in z0, z1, z2 over Rational Field
355
sage: R.term_order()
356
Negative lexicographic term order
357
sage: R.inject_variables()
358
Defining z0, z1, z2
359
sage: z0 < z1 and z1 < z2
360
True
361
"""
362
return PolynomialRing(self._base_ring, self._names,
363
self.nvariables(), order=term_order)
364
365
def _naive_ideal(self, ring):
366
r"""
367
Return the "naive" subideal.
368
369
INPUT:
370
371
- ``ring`` -- the ambient ring of the ideal.
372
373
OUTPUT:
374
375
A subideal of the toric ideal in the polynomial ring ``ring``.
376
377
EXAMPLES::
378
379
sage: A = matrix([[1,1,1],[0,1,2]])
380
sage: IA = ToricIdeal(A)
381
sage: IA.ker()
382
Free module of degree 3 and rank 1 over Integer Ring
383
User basis matrix:
384
[ 1 -2 1]
385
sage: IA._naive_ideal(IA.ring())
386
Ideal (-z1^2 + z0*z2) of Multivariate Polynomial Ring in z0, z1, z2 over Rational Field
387
"""
388
x = ring.gens()
389
binomials = []
390
for row in self.ker().matrix().rows():
391
xpos = prod(x[i]**max( row[i],0) for i in range(0,len(x)))
392
xneg = prod(x[i]**max(-row[i],0) for i in range(0,len(x)))
393
binomials.append(xpos - xneg)
394
return ring.ideal(binomials)
395
396
def _ideal_quotient_by_variable(self, ring, ideal, n):
397
r"""
398
Return the ideal quotient `(J:x_n^\infty)`.
399
400
INPUT:
401
402
- ``ring`` -- the ambient polynomial ring in neglex order.
403
404
- ``ideal`` -- the ideal `J`.
405
406
- ``n`` -- Integer. The index of the next variable to divide by.
407
408
OUTPUT:
409
410
The ideal quotient `(J:x_n^\infty)`.
411
412
ALGORITHM:
413
414
Proposition 4 of [GRIN].
415
416
EXAMPLES::
417
418
sage: A = lambda d: matrix([[1,1,1,1,1],[0,1,1,0,0],[0,0,1,1,d]])
419
sage: IA = ToricIdeal(A(3))
420
sage: R = PolynomialRing(QQ, 5, 'z', order='neglex')
421
sage: J0 = IA._naive_ideal(R)
422
sage: IA._ideal_quotient_by_variable(R, J0, 0)
423
Ideal (z2*z3^2 - z0*z1*z4, z1*z3 - z0*z2,
424
z2^2*z3 - z1^2*z4, z1^3*z4 - z0*z2^3)
425
of Multivariate Polynomial Ring in z0, z1, z2, z3, z4 over Rational Field
426
"""
427
N = self.nvariables()
428
y = list(ring.gens())
429
x = [ y[i-n] for i in range(0,N) ]
430
y_to_x = dict(zip(x,y))
431
x_to_y = dict(zip(y,x))
432
# swap variables such that the n-th variable becomes the last one
433
J = ideal.subs(y_to_x)
434
435
# TODO: Can we use the weighted homogeneity with respect to
436
# the rows of self.A() when computing the Groebner basis, see
437
# [GRIN]?
438
basis = J.groebner_basis()
439
440
x_n = y[0] # the cheapest variable in the revlex order
441
def subtract(e,power):
442
l = list(e)
443
return tuple([l[0]-power] + l[1:])
444
def divide_by_x_n(p):
445
d_old = p.dict()
446
power = min([ e[0] for e in d_old.keys() ])
447
d_new = dict( (subtract(exponent,power), coefficient)
448
for exponent, coefficient in d_old.iteritems() )
449
return p.parent()(d_new)
450
basis = map(divide_by_x_n, basis)
451
quotient = ring.ideal(basis)
452
return quotient.subs(x_to_y)
453
454
def _ideal_HostenSturmfels(self):
455
r"""
456
Compute the toric ideal by Hosten and Sturmfels' algorithm.
457
458
OUTPUT:
459
460
The toric ideal as an ideal in the polynomial ring
461
``self.ring()``.
462
463
EXAMPLES::
464
465
sage: A = matrix([[3,2,1,0],[0,1,2,3]])
466
sage: IA = ToricIdeal(A); IA
467
Ideal (-z1*z2 + z0*z3, -z1^2 + z0*z2, z2^2 - z1*z3)
468
of Multivariate Polynomial Ring in z0, z1, z2, z3 over Rational Field
469
sage: R = IA.ring()
470
sage: IA == IA._ideal_HostenSturmfels()
471
True
472
473
TESTS::
474
475
sage: I_2x2 = identity_matrix(ZZ,2)
476
sage: ToricIdeal(I_2x2)
477
Ideal (0) of Multivariate Polynomial Ring in z0, z1 over Rational Field
478
"""
479
ring = self._init_ring('neglex')
480
J = self._naive_ideal(ring)
481
if J.is_zero():
482
return J
483
for i in range(0,self.nvariables()):
484
J = self._ideal_quotient_by_variable(ring, J, i)
485
return J
486
487
488
489