Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sagemath
GitHub Repository: sagemath/sagesmc
Path: blob/master/src/sage/interfaces/four_ti_2.py
8814 views
1
r"""
2
Interface to 4ti2 (http://www.4ti2.de)
3
4
You must have the 4ti2 Sage package installed on your computer
5
for this interface to work.
6
7
AUTHORS:
8
9
- Mike Hansen (2009): Initial version.
10
11
- Bjarke Hammersholt Roune (2009-06-26): Added Groebner, made code
12
usable as part of the Sage library and added documentation and some
13
doctests.
14
15
- Marshall Hampton (2011): Minor fixes to documentation.
16
"""
17
18
#*****************************************************************************
19
# Copyright (C) 2009 Mike Hansen <[email protected]>
20
# Copyright (C) 2009 Bjarke Hammersholt Roune <www.broune.com>
21
#
22
# Distributed under the terms of the GNU General Public License (GPL)
23
#
24
# This code is distributed in the hope that it will be useful,
25
# but WITHOUT ANY WARRANTY; without even the implied warranty of
26
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
27
# General Public License for more details.
28
#
29
# The full text of the GPL is available at:
30
#
31
# http://www.gnu.org/licenses/
32
#*****************************************************************************
33
34
from sage.rings.integer_ring import ZZ
35
import os
36
37
class FourTi2(object):
38
r"""
39
This object defines an interface to the program 4ti2. Each command
40
4ti2 has is exposed as one method.
41
"""
42
43
def __init__(self, directory=None):
44
r"""
45
Initialize this object.
46
47
INPUT:
48
49
- ``directory`` - 4ti2 only deals with files, and this is the
50
directory that Sage will write input files to and run 4ti2
51
in. Use an appropriate temporary directory if the value is
52
``None``.
53
54
EXAMPLES::
55
56
sage: from sage.interfaces.four_ti_2 import FourTi2
57
sage: f = FourTi2("/tmp/")
58
sage: f.directory()
59
'/tmp/'
60
"""
61
self._directory = directory
62
63
##################
64
# Input / output #
65
##################
66
67
def directory(self):
68
r"""
69
Return the directory where the input files for 4ti2 are
70
written by Sage and where 4ti2 is run.
71
72
EXAMPLES::
73
74
sage: from sage.interfaces.four_ti_2 import FourTi2
75
sage: f = FourTi2("/tmp/")
76
sage: f.directory()
77
'/tmp/'
78
"""
79
from sage.misc.temporary_file import tmp_dir
80
if self._directory is None:
81
# we have to put this here rather than in the __init__
82
# method since apparently importing sage.misc.misc does not
83
# work until Sage is done starting up.
84
self._directory = tmp_dir()
85
return self._directory
86
87
def temp_project(self):
88
r"""
89
Return an input project file name that has not been used yet.
90
91
EXAMPLES::
92
93
sage: from sage.interfaces.four_ti_2 import four_ti_2
94
sage: four_ti_2.temp_project()
95
'project_...'
96
"""
97
n = 0
98
while True:
99
project = "project_%s"%n
100
touch_file = os.path.join(self.directory(),project) + '.touch'
101
if not os.path.exists(touch_file):
102
break
103
n += 1
104
f = open(touch_file, 'w')
105
f.write(' ')
106
f.close()
107
return project
108
109
def write_matrix(self, mat, filename):
110
r"""
111
Write the matrix ``mat`` to the file ``filename`` in 4ti2 format.
112
113
INPUT:
114
115
- ``mat`` - A matrix of integers or something that can be
116
converted to that.
117
- ``filename`` - A file name not including a path.
118
119
EXAMPLES::
120
121
sage: from sage.interfaces.four_ti_2 import four_ti_2
122
sage: four_ti_2.write_matrix([[1,2],[3,4]], "test_file")
123
"""
124
from sage.matrix.constructor import matrix
125
from sage.matrix.matrix import is_Matrix
126
if not is_Matrix(mat):
127
mat = matrix(ZZ, mat)
128
if mat.base_ring() != ZZ:
129
mat = mat.change_ring(ZZ)
130
131
self.write_array(mat, mat.nrows(), mat.ncols(), filename)
132
133
def write_single_row(self, row, filename):
134
r"""
135
Write the list ``row`` to the file ``filename`` in 4ti2 format
136
as a matrix with one row.
137
138
INPUT:
139
140
- ``row`` - A list of integers.
141
- ``filename`` - A file name not including a path.
142
143
EXAMPLES::
144
145
sage: from sage.interfaces.four_ti_2 import four_ti_2
146
sage: four_ti_2.write_single_row([1,2,3,4], "test_file")
147
"""
148
self.write_array([row], 1, len(row), filename)
149
150
def write_array(self, array, nrows, ncols, filename):
151
r"""
152
Write the matrix ``array`` of integers (can be represented as
153
a list of lists) to the file ``filename`` in directory
154
``directory()`` in 4ti2 format. The matrix must have ``nrows``
155
rows and ``ncols`` columns.
156
157
INPUT:
158
159
- ``array`` - A matrix of integers. Can be represented as a list
160
of lists.
161
- ``nrows`` - The number of rows in ``array``.
162
- ``ncols`` - The number of columns in ``array``.
163
- ``file`` - A file name not including a path.
164
165
EXAMPLES::
166
167
sage: from sage.interfaces.four_ti_2 import four_ti_2
168
sage: four_ti_2.write_array([[1,2,3],[3,4,5]], 2, 3, "test_file")
169
"""
170
f = open(os.path.join(self.directory(), filename), 'w')
171
f.write("%s %s\n"%(nrows, ncols))
172
for row in array:
173
f.write(" ".join(map(str, row)))
174
f.write("\n")
175
f.close()
176
177
def read_matrix(self, filename):
178
r"""
179
Read a matrix in 4ti2 format from the file ``filename`` in
180
directory ``directory()``.
181
182
INPUT:
183
184
- ``filename`` - The name of the file to read from.
185
186
OUTPUT:
187
The data from the file as a matrix over `\ZZ`.
188
189
EXAMPLES::
190
191
sage: from sage.interfaces.four_ti_2 import four_ti_2
192
sage: four_ti_2.write_matrix([[1,2,3],[3,4,6]], "test_file")
193
sage: four_ti_2.read_matrix("test_file")
194
[1 2 3]
195
[3 4 6]
196
"""
197
from sage.matrix.constructor import matrix
198
try:
199
f = open(os.path.join(self.directory(), filename))
200
lines = f.readlines()
201
f.close()
202
except IOError:
203
return matrix(ZZ, 0, 0)
204
205
nrows, ncols = map(ZZ, lines.pop(0).strip().split())
206
return matrix(ZZ, nrows, ncols,
207
[map(ZZ, line.strip().split()) for line in lines
208
if line.strip() != ""])
209
210
def _process_input(self, kwds):
211
r"""
212
kwds is a dict, and the values are written to files with
213
extension given by the keys, except for the keys ``self``
214
and ``project``.
215
216
This interesting method is intended to be called as the first
217
thing going on in a method implementing some action of 4ti2,
218
where the value of ``locals()`` is passed as the dict, thus
219
achieving to write out many project files to the right places
220
just by giving the parameters of the method names that are the
221
extension of the corresponding files.
222
223
Nothing is written if the value is None. Otherwise the value
224
is written as a matrix to the file given by the value of the
225
key ``'project'`` with extension given by the key.
226
227
INPUT:
228
229
- kwds - A dict controlling what data is written to what files.
230
231
OUTPUT:
232
The value of the key ``project``.
233
234
EXAMPLES::
235
236
sage: from sage.interfaces.four_ti_2 import four_ti_2
237
sage: pr = four_ti_2._process_input( \
238
... {'project': "test_file", \
239
... 'self': None, \
240
... 'tst': [[1,2,3],[3,4,5]]})
241
sage: four_ti_2.read_matrix("test_file.tst")
242
[1 2 3]
243
[3 4 5]
244
"""
245
kwds.pop('self', None)
246
247
# Get the project
248
project = kwds.pop('project', None)
249
if project is None:
250
project = self.temp_project()
251
252
for ext, value in kwds.iteritems():
253
if value is None:
254
continue
255
256
if (isinstance(value, list) and
257
not (len(value) > 0 and isinstance(value[0], list))):
258
self.write_single_row(value, project + "." + ext)
259
else:
260
self.write_matrix(value, project + "." + ext)
261
262
return project
263
264
############
265
# Commands #
266
############
267
268
def call(self, command, project, verbose=True):
269
r"""
270
Run the 4ti2 program ``command`` on the project named
271
``project`` in the directory ``directory()``.
272
273
INPUT:
274
275
- command - The 4ti2 program to run.
276
- project - The file name of the project to run on.
277
- verbose - Display the output of 4ti2 if ``True``.
278
279
EXAMPLES::
280
281
sage: from sage.interfaces.four_ti_2 import four_ti_2
282
sage: four_ti_2.write_matrix([[6,10,15]], "test_file")
283
sage: four_ti_2.call("groebner", "test_file", False) # optional - 4ti2
284
sage: four_ti_2.read_matrix("test_file.gro") # optional - 4ti2
285
[-5 0 2]
286
[-5 3 0]
287
"""
288
import subprocess
289
290
cmd = '%s %s'%(command, project)
291
if verbose is False:
292
cmd += " > /dev/null 2> /dev/null"
293
subprocess.call(cmd, shell=True, cwd=self.directory())
294
295
def zsolve(self, mat=None, rel=None, rhs=None, sign=None, project=None):
296
r"""
297
Runs the 4ti2 program ``zsolve`` on the parameters. See
298
``http://www.4ti2.de/`` for details.
299
300
EXAMPLES::
301
302
sage: from sage.interfaces.four_ti_2 import four_ti_2
303
sage: A = [[1,1,1],[1,2,3]]
304
sage: rel = ['<', '<']
305
sage: rhs = [2, 3]
306
sage: sign = [1,0,1]
307
sage: four_ti_2.zsolve(A, rel, rhs, sign) # optional - 4ti2
308
[
309
[ 1 -1 0]
310
[ 0 -1 0]
311
[0 0 1] [ 0 -3 2]
312
[1 1 0] [ 1 -2 1]
313
[0 1 0], [ 0 -2 1], []
314
]
315
"""
316
project = self._process_input(locals())
317
self.call('zsolve -q', project)
318
return [self.read_matrix(project+'.'+ext) for ext in
319
['zinhom', 'zhom', 'zfree']]
320
321
def qsolve(self, mat=None, rel=None, sign=None, project=None):
322
r"""
323
Runs the 4ti2 program ``qsolve`` on the parameters. See
324
``http://www.4ti2.de/`` for details.
325
326
EXAMPLES::
327
328
sage: from sage.interfaces.four_ti_2 import four_ti_2
329
sage: A = [[1,1,1],[1,2,3]]
330
sage: four_ti_2.qsolve(A) # optional - 4ti2
331
[[], [ 1 -2 1]]
332
"""
333
project = self._process_input(locals())
334
self.call('qsolve -q -parbitrary', project)
335
return [self.read_matrix(project+'.'+ext) for ext in
336
['qhom', 'qfree']]
337
338
def rays(self, mat=None, project=None):
339
r"""
340
Runs the 4ti2 program ``rays`` on the parameters. See
341
``http://www.4ti2.de/`` for details.
342
343
EXAMPLES::
344
345
sage: from sage.interfaces.four_ti_2 import four_ti_2
346
sage: four_ti_2.rays(four_ti_2._magic3x3()) # optional - 4ti2
347
[0 2 1 2 1 0 1 0 2]
348
[1 0 2 2 1 0 0 2 1]
349
[1 2 0 0 1 2 2 0 1]
350
[2 0 1 0 1 2 1 2 0]
351
"""
352
project = self._process_input(locals())
353
self.call('rays -q -parbitrary', project)
354
return self.read_matrix(project+'.ray')
355
356
def hilbert(self, mat=None, project=None):
357
r"""
358
Runs the 4ti2 program ``hilbert`` on the parameters. See
359
``http://www.4ti2.de/`` for details.
360
361
EXAMPLES::
362
363
sage: from sage.interfaces.four_ti_2 import four_ti_2
364
sage: four_ti_2.hilbert(four_ti_2._magic3x3()) # optional - 4ti2
365
[2 0 1 0 1 2 1 2 0]
366
[1 0 2 2 1 0 0 2 1]
367
[0 2 1 2 1 0 1 0 2]
368
[1 2 0 0 1 2 2 0 1]
369
[1 1 1 1 1 1 1 1 1]
370
"""
371
project = self._process_input(locals())
372
self.call('hilbert -q', project)
373
return self.read_matrix(project+'.hil')
374
375
def graver(self, mat=None, project=None):
376
r"""
377
Runs the 4ti2 program ``graver`` on the parameters. See
378
``http://www.4ti2.de/`` for details.
379
380
EXAMPLES::
381
382
sage: from sage.interfaces.four_ti_2 import four_ti_2
383
sage: four_ti_2.graver([1,2,3]) # optional - 4ti2
384
[ 2 -1 0]
385
[ 3 0 -1]
386
[ 1 1 -1]
387
[ 1 -2 1]
388
[ 0 3 -2]
389
390
"""
391
project = self._process_input(locals())
392
self.call('graver -q', project)
393
return self.read_matrix(project+'.gra')
394
395
def ppi(self, n):
396
r"""
397
Runs the 4ti2 program ``ppi`` on the parameters. See
398
``http://www.4ti2.de/`` for details.
399
400
EXAMPLES::
401
402
sage: from sage.interfaces.four_ti_2 import four_ti_2
403
sage: four_ti_2.ppi(3) # optional - 4ti2
404
[-2 1 0]
405
[ 0 -3 2]
406
[-1 -1 1]
407
[-3 0 1]
408
[ 1 -2 1]
409
410
"""
411
self.call('ppi 2> /dev/null', n)
412
return self.read_matrix('ppi%s.gra'%n)
413
414
def circuits(self, mat=None, project=None):
415
r"""
416
Runs the 4ti2 program ``circuits`` on the parameters. See
417
``http://www.4ti2.de/`` for details.
418
419
EXAMPLES::
420
421
sage: from sage.interfaces.four_ti_2 import four_ti_2
422
sage: four_ti_2.circuits([1,2,3]) # optional - 4ti2
423
[ 0 3 -2]
424
[ 2 -1 0]
425
[ 3 0 -1]
426
"""
427
project = self._process_input(locals())
428
self.call('circuits -q -parbitrary', project)
429
return self.read_matrix(project+'.cir')
430
431
def minimize(self, mat=None):
432
r"""
433
Runs the 4ti2 program ``minimize`` on the parameters. See
434
``http://www.4ti2.de/`` for details.
435
436
EXAMPLES::
437
438
sage: from sage.interfaces.four_ti_2 import four_ti_2
439
sage: four_ti_2.minimize() # optional - 4ti2
440
Traceback (most recent call last):
441
...
442
NotImplementedError: 4ti2 command 'minimize' not implemented in Sage.
443
"""
444
raise NotImplementedError("4ti2 command 'minimize' not implemented "
445
"in Sage.")
446
447
def groebner(self, mat=None, project=None):
448
r"""
449
Runs the 4ti2 program ``groebner`` on the parameters. This
450
computes a Toric Groebner basis of a matrix. See
451
``http://www.4ti2.de/`` for details.
452
453
EXAMPLES::
454
455
sage: from sage.interfaces.four_ti_2 import four_ti_2
456
sage: A = [6,10,15]
457
sage: four_ti_2.groebner(A) # optional - 4ti2
458
[-5 0 2]
459
[-5 3 0]
460
"""
461
project = self._process_input(locals())
462
self.call('groebner -q -parbitrary', project)
463
return self.read_matrix(project+'.gro')
464
465
def _magic3x3(self):
466
r"""
467
Return a matrix used for testing this class.
468
469
EXAMPLES::
470
471
sage: from sage.interfaces.four_ti_2 import four_ti_2
472
sage: four_ti_2._magic3x3() # optional - 4ti2
473
[ 1 1 1 -1 -1 -1 0 0 0]
474
[ 1 1 1 0 0 0 -1 -1 -1]
475
[ 0 1 1 -1 0 0 -1 0 0]
476
[ 1 0 1 0 -1 0 0 -1 0]
477
[ 1 1 0 0 0 -1 0 0 -1]
478
[ 0 1 1 0 -1 0 0 0 -1]
479
[ 1 1 0 0 -1 0 -1 0 0]
480
481
"""
482
from sage.matrix.constructor import matrix
483
return matrix \
484
(ZZ, 7, 9,
485
[[1, 1, 1, -1, -1, -1, 0, 0, 0],
486
[1, 1, 1, 0, 0, 0, -1, -1, -1],
487
[0, 1, 1, -1, 0, 0, -1, 0, 0],
488
[1, 0, 1, 0, -1, 0, 0, -1, 0],
489
[1, 1, 0, 0, 0, -1, 0, 0, -1],
490
[0, 1, 1, 0, -1, 0, 0, 0, -1],
491
[1, 1, 0, 0, -1, 0, -1, 0, 0]])
492
493
# The instance that should be used outside this file.
494
four_ti_2 = FourTi2()
495
496