Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sagemath
GitHub Repository: sagemath/sagelib
Path: blob/master/sage/libs/fplll/fplll.pyx
4057 views
1
"""
2
Wrapper for the fpLLL library by Damien Stehle and David Cade found at
3
4
http://perso.ens-lyon.fr/damien.stehle/english.html
5
6
This wrapper provides access to all fpLLL LLL implementations except
7
for integer matrices over C ints as opposed to integer matrices over
8
multi-precision integers. If that feature is required, please let the
9
authors of this know.
10
11
AUTHORS:
12
-- 2007-10 Martin Albrecht <[email protected]>
13
initial release
14
"""
15
16
#*****************************************************************************
17
#
18
# Sage: System for Algebra and Geometry Experimentation
19
#
20
# Copyright (C) 2007 Martin Albrecht <[email protected]>
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
include "../../ext/interrupt.pxi"
35
36
from sage.matrix.matrix_integer_dense cimport Matrix_integer_dense
37
from sage.rings.integer_ring import ZZ
38
from sage.matrix.constructor import matrix
39
40
cdef class FP_LLL:
41
"""
42
A basic wrapper class to support conversion to/from Sage integer
43
matrices and executing the LLL computation.
44
45
.. note:
46
47
Usually you don't want to create this object yourself but use
48
the LLL method of the integer matrices.
49
"""
50
def __cinit__(self, Matrix_integer_dense A):
51
"""
52
Construct a new fpLLL wrapper for the matrix A.
53
54
INPUT:
55
A -- a matrix over the integers
56
57
EXAMPLE::
58
59
sage: from sage.libs.fplll.fplll import FP_LLL
60
sage: A = random_matrix(ZZ,10,10)
61
sage: FP_LLL(A)
62
fpLLL wrapper acting on a 10 x 10 matrix
63
64
sage: A = matrix(ZZ, 2, 0)
65
sage: FP_LLL(A).fast()
66
sage: A = matrix(ZZ, 0, 2)
67
sage: FP_LLL(A)
68
Traceback (most recent call last):
69
...
70
ValueError: fpLLL cannot handle matrices with zero rows.
71
"""
72
cdef int i,j
73
if A._nrows==0:
74
raise ValueError('fpLLL cannot handle matrices with zero rows.')
75
self._lattice = ZZ_mat_new(A._nrows,A._ncols)
76
77
cdef Z_NR *t
78
79
for i from 0 <= i < A._nrows:
80
for j from 0 <= j < A._ncols:
81
t = Z_NR_new()
82
t.set_mpz_t(A._matrix[i][j])
83
self._lattice.Set(i,j,t[0])
84
Z_NR_delete(t)
85
86
def __dealloc__(self):
87
"""
88
Destroy internal data.
89
"""
90
ZZ_mat_delete(self._lattice)
91
92
def __repr__(self):
93
"""
94
EXAMPLE::
95
96
sage: from sage.libs.fplll.fplll import FP_LLL
97
sage: A = random_matrix(ZZ,10,10)
98
sage: FP_LLL(A) # indirect doctest
99
fpLLL wrapper acting on a 10 x 10 matrix
100
"""
101
return "fpLLL wrapper acting on a %d x %d matrix"%(self._lattice.GetNumRows(),self._lattice.GetNumCols())
102
103
def _sage_(self):
104
"""
105
Return a Sage representation of self's matrix.
106
107
EXAMPLE::
108
109
sage: from sage.libs.fplll.fplll import FP_LLL
110
sage: A = random_matrix(ZZ,10,10)
111
sage: fpLLL = FP_LLL(A)
112
sage: fpLLL._sage_() == A
113
True
114
"""
115
return to_sage(self._lattice)
116
117
cdef int _check_precision(self, int precision):
118
"""
119
Check whether the provided precision is within valid
120
bounds. If not raise a TypeError.
121
122
INPUT:
123
precision -- an integer
124
"""
125
if precision < 0:
126
raise TypeError, "precision must be >= 0"
127
128
cdef int _check_eta(self, float eta):
129
"""
130
Check whether the provided parameter $\eta$ is within valid
131
bounds. If not raise a TypeError.
132
133
INPUT:
134
eta -- a floating point number
135
"""
136
if eta < 0.5:
137
raise TypeError, "eta must be >= 0.5"
138
139
cdef int _check_delta(self, float delta):
140
"""
141
Check whether the provided parameter $\delta$ is within valid
142
bounds. If not raise a TypeError.
143
144
INPUT:
145
delta -- a floating point number
146
"""
147
if delta <= 0.25:
148
raise TypeError, "delta must be > 0.25"
149
if delta > 1.0:
150
raise TypeError, "delta must be <= 1.0"
151
152
def wrapper(self, int precision=0, float eta=0.51, float delta=0.99):
153
"""
154
Perform LLL reduction using fpLLL's \code{wrapper}
155
implementation. This implementation invokes a sequence of
156
floating point LLL computations such that
157
* the computation is reasonably fast (based on an heuristic model)
158
* the result is proven to be LLL reduced.
159
160
INPUT:
161
precision -- internal precision (default: auto)
162
eta -- LLL parameter eta with 1/2 <= eta < sqrt(delta) (default: 0.51)
163
delta -- LLL parameter delta with 1/4 < delta <= 1 (default: 0.99)
164
165
OUTPUT:
166
nothing is returned but the internal state modified.
167
168
EXAMPLE::
169
170
sage: from sage.libs.fplll.fplll import FP_LLL
171
sage: A = random_matrix(ZZ,10,10); A
172
[ -8 2 0 0 1 -1 2 1 -95 -1]
173
[ -2 -12 0 0 1 -1 1 -1 -2 -1]
174
[ 4 -4 -6 5 0 0 -2 0 1 -4]
175
[ -6 1 -1 1 1 -1 1 -1 -3 1]
176
[ 1 0 0 -3 2 -2 0 -2 1 0]
177
[ -1 1 0 0 1 -1 4 -1 1 -1]
178
[ 14 1 -5 4 -1 0 2 4 1 1]
179
[ -2 -1 0 4 -3 1 -5 0 -2 -1]
180
[ -9 -1 -1 3 2 1 -1 1 -2 1]
181
[ -1 2 -7 1 0 2 3 -1955 -22 -1]
182
183
sage: F = FP_LLL(A)
184
sage: F.wrapper()
185
sage: L = F._sage_(); L
186
[ 1 0 0 -3 2 -2 0 -2 1 0]
187
[ -1 1 0 0 1 -1 4 -1 1 -1]
188
[ -2 0 0 1 0 -2 -1 -3 0 -2]
189
[ -2 -2 0 -1 3 0 -2 0 2 0]
190
[ 1 1 1 2 3 -2 -2 0 3 1]
191
[ -4 1 -1 0 1 1 2 2 -3 3]
192
[ 1 -3 -7 2 3 -1 0 0 -1 -1]
193
[ 1 -9 1 3 1 -3 1 -1 -1 0]
194
[ 8 5 19 3 27 6 -3 8 -25 -22]
195
[ 172 -25 57 248 261 793 76 -839 -41 376]
196
sage: L.is_LLL_reduced()
197
True
198
sage: L.echelon_form() == A.echelon_form()
199
True
200
"""
201
self._check_precision(precision)
202
self._check_eta(eta)
203
self._check_delta(delta)
204
cdef int ret = 0
205
206
cdef wrapper *w = wrapper_new(self._lattice, 0, eta, delta)
207
sig_on()
208
ret = w.LLL()
209
sig_off()
210
wrapper_delete(w)
211
if ret != 0:
212
raise RuntimeError, "fpLLL returned %d != 0"%ret
213
214
215
def proved(self, int precision=0, float eta=0.51, float delta=0.99, implementation=None):
216
"""
217
Perform LLL reduction using fpLLL's \code{proved}
218
implementation. This implementation is the only provable
219
correct floating point implementation in the free software
220
world. Provability is only guaranteed if the 'mpfr'
221
implementation is chosen.
222
223
INPUT:
224
precision -- internal precision (default: auto)
225
eta -- LLL parameter eta with 1/2 <= eta < sqrt(delta) (default: 0.51)
226
delta -- LLL parameter delta with 1/4 < delta <= 1 (default: 0.99)
227
implementation -- floating point implementation in ('double', 'dpe', 'mpfr')
228
(default: 'mpfr')
229
230
OUTPUT:
231
nothing is returned but the internal state modified.
232
233
EXAMPLE::
234
235
sage: from sage.libs.fplll.fplll import FP_LLL
236
sage: A = random_matrix(ZZ,10,10); A
237
[ -8 2 0 0 1 -1 2 1 -95 -1]
238
[ -2 -12 0 0 1 -1 1 -1 -2 -1]
239
[ 4 -4 -6 5 0 0 -2 0 1 -4]
240
[ -6 1 -1 1 1 -1 1 -1 -3 1]
241
[ 1 0 0 -3 2 -2 0 -2 1 0]
242
[ -1 1 0 0 1 -1 4 -1 1 -1]
243
[ 14 1 -5 4 -1 0 2 4 1 1]
244
[ -2 -1 0 4 -3 1 -5 0 -2 -1]
245
[ -9 -1 -1 3 2 1 -1 1 -2 1]
246
[ -1 2 -7 1 0 2 3 -1955 -22 -1]
247
248
sage: F = FP_LLL(A)
249
sage: F.proved()
250
sage: L = F._sage_(); L
251
[ 1 0 0 -3 2 -2 0 -2 1 0]
252
[ -1 1 0 0 1 -1 4 -1 1 -1]
253
[ -2 0 0 1 0 -2 -1 -3 0 -2]
254
[ -2 -2 0 -1 3 0 -2 0 2 0]
255
[ 1 1 1 2 3 -2 -2 0 3 1]
256
[ -4 1 -1 0 1 1 2 2 -3 3]
257
[ 1 -3 -7 2 3 -1 0 0 -1 -1]
258
[ 1 -9 1 3 1 -3 1 -1 -1 0]
259
[ 8 5 19 3 27 6 -3 8 -25 -22]
260
[ 172 -25 57 248 261 793 76 -839 -41 376]
261
262
sage: L.is_LLL_reduced()
263
True
264
sage: L.echelon_form() == A.echelon_form()
265
True
266
"""
267
self._check_precision(precision)
268
self._check_eta(eta)
269
self._check_delta(delta)
270
271
cdef proved_double *pdouble
272
cdef proved_mpfr *pmpfr
273
cdef proved_dpe *pdpe
274
cdef int ret = 0
275
276
if implementation is None:
277
implementation = "mpfr"
278
279
if implementation == "double":
280
pdouble = proved_double_new(self._lattice, precision, eta, delta)
281
sig_on()
282
ret = pdouble.LLL()
283
sig_off()
284
proved_double_delete(pdouble)
285
elif implementation == "dpe":
286
pdpe = proved_dpe_new(self._lattice, precision, <double>eta, <double>delta)
287
sig_on()
288
ret = pdpe.LLL()
289
sig_off()
290
proved_dpe_delete(pdpe)
291
elif implementation == "mpfr":
292
pmpfr = proved_mpfr_new(self._lattice, precision, eta, delta)
293
sig_on()
294
ret = pmpfr.LLL()
295
sig_off()
296
proved_mpfr_delete(pmpfr)
297
298
if ret != 0:
299
raise RuntimeError, "fpLLL returned %d != 0"%ret
300
301
def fast(self, int precision=0, float eta=0.51, float delta=0.99, implementation=None):
302
"""
303
Perform LLL reduction using fpLLL's \code{fast}
304
implementation. This implementation is the fastest floating
305
point implementation available in the free software world.
306
307
INPUT:
308
precision -- internal precision (default: auto)
309
eta -- LLL parameter eta with 1/2 <= eta < sqrt(delta) (default: 0.51)
310
delta -- LLL parameter delta with 1/4 < delta <= 1 (default: 0.99)
311
implementation -- ignored
312
313
OUTPUT:
314
nothing is returned but the internal state modified.
315
316
EXAMPLE::
317
318
sage: from sage.libs.fplll.fplll import FP_LLL
319
sage: A = random_matrix(ZZ,10,10,x=-(10^5),y=10^5)
320
sage: f = FP_LLL(A)
321
sage: f.fast()
322
sage: L = f._sage_()
323
sage: L.is_LLL_reduced(eta=0.51,delta=0.99)
324
True
325
sage: L.echelon_form() == A.echelon_form()
326
True
327
"""
328
self._check_precision(precision)
329
self._check_eta(eta)
330
self._check_delta(delta)
331
332
cdef fast_double *pdouble
333
cdef int ret = 0
334
335
pdouble = fast_double_new(self._lattice, precision, eta, delta)
336
sig_on()
337
ret = pdouble.LLL()
338
sig_off()
339
fast_double_delete(pdouble)
340
341
def fast_early_red(self, int precision=0, float eta=0.51, float delta=0.99, implementation=None):
342
"""
343
Perform LLL reduction using fpLLL's \code{fast}
344
implementation with early reduction.
345
346
This implementation inserts some early reduction steps inside
347
the execution of the 'fast' LLL algorithm. This sometimes makes the
348
entries of the basis smaller very quickly. It occurs in
349
particular for lattice bases built from minimal polynomial or
350
integer relation detection problems.
351
352
INPUT:
353
precision -- internal precision (default: auto)
354
eta -- LLL parameter eta with 1/2 <= eta < sqrt(delta) (default: 0.51)
355
delta -- LLL parameter delta with 1/4 < delta <= 1 (default: 0.99)
356
implementation -- ignored
357
358
OUTPUT:
359
nothing is returned but the internal state modified.
360
361
EXAMPLE::
362
363
sage: from sage.libs.fplll.fplll import FP_LLL
364
sage: A = random_matrix(ZZ,10,10); A
365
[ -8 2 0 0 1 -1 2 1 -95 -1]
366
[ -2 -12 0 0 1 -1 1 -1 -2 -1]
367
[ 4 -4 -6 5 0 0 -2 0 1 -4]
368
[ -6 1 -1 1 1 -1 1 -1 -3 1]
369
[ 1 0 0 -3 2 -2 0 -2 1 0]
370
[ -1 1 0 0 1 -1 4 -1 1 -1]
371
[ 14 1 -5 4 -1 0 2 4 1 1]
372
[ -2 -1 0 4 -3 1 -5 0 -2 -1]
373
[ -9 -1 -1 3 2 1 -1 1 -2 1]
374
[ -1 2 -7 1 0 2 3 -1955 -22 -1]
375
376
sage: F = FP_LLL(A)
377
sage: F.fast_early_red()
378
sage: L = F._sage_(); L
379
[ 1 0 0 -3 2 -2 0 -2 1 0]
380
[ -1 1 0 0 1 -1 4 -1 1 -1]
381
[ -2 0 0 1 0 -2 -1 -3 0 -2]
382
[ -2 -2 0 -1 3 0 -2 0 2 0]
383
[ 1 1 1 2 3 -2 -2 0 3 1]
384
[ -4 1 -1 0 1 1 2 2 -3 3]
385
[ 1 -3 -7 2 3 -1 0 0 -1 -1]
386
[ 1 -9 1 3 1 -3 1 -1 -1 0]
387
[ 8 5 19 3 27 6 -3 8 -25 -22]
388
[ 172 -25 57 248 261 793 76 -839 -41 376]
389
390
sage: L.is_LLL_reduced(eta=0.51,delta=0.99)
391
True
392
sage: L.echelon_form() == A.echelon_form()
393
True
394
"""
395
self._check_precision(precision)
396
self._check_eta(eta)
397
self._check_delta(delta)
398
cdef int ret = 0
399
400
cdef fast_early_red_double *pdouble
401
402
pdouble = fast_early_red_double_new(self._lattice, precision, eta, delta)
403
sig_on()
404
ret = pdouble.LLL()
405
sig_off()
406
fast_early_red_double_delete(pdouble)
407
408
def heuristic(self, int precision=0, float eta=0.51, float delta=0.99, implementation=None):
409
"""
410
Perform LLL reduction using fpLLL's \code{heuristic}
411
implementation.
412
413
INPUT:
414
precision -- internal precision (default: auto)
415
eta -- LLL parameter eta with 1/2 <= eta < sqrt(delta) (default: 0.51)
416
delta -- LLL parameter delta with 1/4 < delta <= 1 (default: 0.99)
417
implementation -- floating point implementation in ('double', 'dpe', 'mpfr')
418
(default: 'mpfr')
419
420
OUTPUT:
421
nothing is returned but the internal state modified.
422
423
EXAMPLE::
424
425
sage: from sage.libs.fplll.fplll import FP_LLL
426
sage: A = random_matrix(ZZ,10,10); A
427
[ -8 2 0 0 1 -1 2 1 -95 -1]
428
[ -2 -12 0 0 1 -1 1 -1 -2 -1]
429
[ 4 -4 -6 5 0 0 -2 0 1 -4]
430
[ -6 1 -1 1 1 -1 1 -1 -3 1]
431
[ 1 0 0 -3 2 -2 0 -2 1 0]
432
[ -1 1 0 0 1 -1 4 -1 1 -1]
433
[ 14 1 -5 4 -1 0 2 4 1 1]
434
[ -2 -1 0 4 -3 1 -5 0 -2 -1]
435
[ -9 -1 -1 3 2 1 -1 1 -2 1]
436
[ -1 2 -7 1 0 2 3 -1955 -22 -1]
437
438
sage: F = FP_LLL(A)
439
sage: F.heuristic()
440
sage: L = F._sage_(); L
441
[ 1 0 0 -3 2 -2 0 -2 1 0]
442
[ -1 1 0 0 1 -1 4 -1 1 -1]
443
[ -2 0 0 1 0 -2 -1 -3 0 -2]
444
[ -2 -2 0 -1 3 0 -2 0 2 0]
445
[ 1 1 1 2 3 -2 -2 0 3 1]
446
[ -4 1 -1 0 1 1 2 2 -3 3]
447
[ 1 -3 -7 2 3 -1 0 0 -1 -1]
448
[ 1 -9 1 3 1 -3 1 -1 -1 0]
449
[ 8 5 19 3 27 6 -3 8 -25 -22]
450
[ 172 -25 57 248 261 793 76 -839 -41 376]
451
452
sage: L.is_LLL_reduced(eta=0.51,delta=0.99)
453
True
454
sage: L.echelon_form() == A.echelon_form()
455
True
456
"""
457
self._check_precision(precision)
458
self._check_eta(eta)
459
self._check_delta(delta)
460
461
cdef heuristic_double *pdouble
462
cdef heuristic_mpfr *pmpfr
463
cdef heuristic_dpe *pdpe
464
cdef int ret = 0
465
466
if implementation is None:
467
implementation = "mpfr"
468
469
if implementation == "double":
470
pdouble = heuristic_double_new(self._lattice, precision, eta, delta)
471
sig_on()
472
ret = pdouble.LLL()
473
sig_off()
474
heuristic_double_delete(pdouble)
475
elif implementation == "dpe":
476
pdpe = heuristic_dpe_new(self._lattice, precision, <double>eta, <double>delta)
477
sig_on()
478
ret = pdpe.LLL()
479
sig_off()
480
heuristic_dpe_delete(pdpe)
481
elif implementation == "mpfr":
482
pmpfr = heuristic_mpfr_new(self._lattice, precision, eta, delta)
483
sig_on()
484
ret = pmpfr.LLL()
485
sig_off()
486
heuristic_mpfr_delete(pmpfr)
487
488
def heuristic_early_red(self, int precision=0, float eta=0.51, float delta=0.99, implementation=None):
489
"""
490
Perform LLL reduction using fpLLL's \code{heuristic}
491
implementation with early reduction.
492
493
This implementation inserts some early reduction steps inside
494
the execution of the 'fast' LLL algorithm. This sometimes
495
makes the entries of the basis smaller very quickly. It occurs
496
in particular for lattice bases built from minimal polynomial
497
or integer relation detection problems.
498
499
INPUT:
500
precision -- internal precision (default: auto)
501
eta -- LLL parameter eta with 1/2 <= eta < sqrt(delta) (default: 0.51)
502
delta -- LLL parameter delta with 1/4 < delta <= 1 (default: 0.99)
503
implementation -- floating point implementation in ('double', 'dpe', 'mpfr')
504
(default: 'mpfr')
505
506
OUTPUT:
507
nothing is returned but the internal state modified.
508
509
EXAMPLE::
510
511
sage: from sage.libs.fplll.fplll import FP_LLL
512
sage: A = random_matrix(ZZ,10,10); A
513
[ -8 2 0 0 1 -1 2 1 -95 -1]
514
[ -2 -12 0 0 1 -1 1 -1 -2 -1]
515
[ 4 -4 -6 5 0 0 -2 0 1 -4]
516
[ -6 1 -1 1 1 -1 1 -1 -3 1]
517
[ 1 0 0 -3 2 -2 0 -2 1 0]
518
[ -1 1 0 0 1 -1 4 -1 1 -1]
519
[ 14 1 -5 4 -1 0 2 4 1 1]
520
[ -2 -1 0 4 -3 1 -5 0 -2 -1]
521
[ -9 -1 -1 3 2 1 -1 1 -2 1]
522
[ -1 2 -7 1 0 2 3 -1955 -22 -1]
523
524
sage: F = FP_LLL(A)
525
sage: F.heuristic_early_red()
526
sage: L = F._sage_(); L
527
[ 1 0 0 -3 2 -2 0 -2 1 0]
528
[ -1 1 0 0 1 -1 4 -1 1 -1]
529
[ -2 0 0 1 0 -2 -1 -3 0 -2]
530
[ -2 -2 0 -1 3 0 -2 0 2 0]
531
[ 1 1 1 2 3 -2 -2 0 3 1]
532
[ -4 1 -1 0 1 1 2 2 -3 3]
533
[ 1 -3 -7 2 3 -1 0 0 -1 -1]
534
[ 1 -9 1 3 1 -3 1 -1 -1 0]
535
[ 8 5 19 3 27 6 -3 8 -25 -22]
536
[ 172 -25 57 248 261 793 76 -839 -41 376]
537
538
sage: L.is_LLL_reduced(eta=0.51,delta=0.99)
539
True
540
sage: L.echelon_form() == A.echelon_form()
541
True
542
"""
543
self._check_precision(precision)
544
self._check_eta(eta)
545
self._check_delta(delta)
546
547
cdef heuristic_early_red_double *pdouble
548
cdef heuristic_early_red_mpfr *pmpfr
549
cdef heuristic_early_red_dpe *pdpe
550
cdef int ret = 0
551
552
if implementation is None:
553
implementation = "mpfr"
554
555
if implementation == "double":
556
pdouble = heuristic_early_red_double_new(self._lattice, precision, eta, delta)
557
sig_on()
558
ret = pdouble.LLL()
559
sig_off()
560
heuristic_early_red_double_delete(pdouble)
561
elif implementation == "dpe":
562
pdpe = heuristic_early_red_dpe_new(self._lattice, precision, <double>eta, <double>delta)
563
sig_on()
564
ret = pdpe.LLL()
565
sig_off()
566
heuristic_early_red_dpe_delete(pdpe)
567
elif implementation == "mpfr":
568
pmpfr = heuristic_early_red_mpfr_new(self._lattice, precision, eta, delta)
569
sig_on()
570
ret = pmpfr.LLL()
571
sig_off()
572
heuristic_early_red_mpfr_delete(pmpfr)
573
574
def gen_intrel(int d, int b):
575
r"""
576
Return a $(d+1 x d)$-dimensional knapsack-type random lattice,
577
where the $x_i$s are random $b$ bits integers.
578
579
INPUT:
580
d -- dimension
581
b -- bitsize of entries
582
583
EXAMPLE::
584
585
sage: from sage.libs.fplll.fplll import gen_intrel
586
sage: A = gen_intrel(10,10); A
587
[116 1 0 0 0 0 0 0 0 0 0]
588
[331 0 1 0 0 0 0 0 0 0 0]
589
[303 0 0 1 0 0 0 0 0 0 0]
590
[963 0 0 0 1 0 0 0 0 0 0]
591
[456 0 0 0 0 1 0 0 0 0 0]
592
[225 0 0 0 0 0 1 0 0 0 0]
593
[827 0 0 0 0 0 0 1 0 0 0]
594
[381 0 0 0 0 0 0 0 1 0 0]
595
[ 99 0 0 0 0 0 0 0 0 1 0]
596
[649 0 0 0 0 0 0 0 0 0 1]
597
598
sage: L = A.LLL(); L
599
[ 1 1 1 0 0 0 0 -1 1 0 0]
600
[ 1 0 1 0 0 -1 1 0 0 -1 0]
601
[ 0 0 1 1 0 -1 0 -1 0 0 1]
602
[ 0 -1 0 -1 -1 1 0 1 0 1 0]
603
[-1 -1 0 -1 0 -1 1 0 0 0 1]
604
[ 0 1 -1 0 0 -1 1 1 -1 0 0]
605
[ 0 0 0 0 -1 1 1 0 1 -1 0]
606
[ 1 -1 -1 0 0 -1 -1 0 1 1 1]
607
[-1 0 0 -1 -1 0 -1 1 2 -1 0]
608
[-1 -1 0 0 1 0 2 0 0 0 -2]
609
sage: L.is_LLL_reduced()
610
True
611
sage: L.echelon_form() == A.echelon_form()
612
True
613
"""
614
cdef ZZ_mat *A = ZZ_mat_new(d,d+1)
615
A.gen_intrel(b)
616
617
B = to_sage(A)
618
ZZ_mat_delete(A)
619
return B
620
621
def gen_simdioph(int d, int b, int b2):
622
r"""
623
Return a $d$-dimensional simultaneous diophantine approximation
624
random lattice, where the $d$ $x_i$s are random $b$ bits integers.
625
626
INPUT:
627
d -- dimension
628
b -- bitsize of entries
629
b2 -- bitsize of entries
630
631
EXAMPLE::
632
633
sage: from sage.libs.fplll.fplll import gen_simdioph
634
sage: A = gen_simdioph(10,10,3); A
635
[ 8 395 975 566 213 694 254 629 303 597]
636
[ 0 1024 0 0 0 0 0 0 0 0]
637
[ 0 0 1024 0 0 0 0 0 0 0]
638
[ 0 0 0 1024 0 0 0 0 0 0]
639
[ 0 0 0 0 1024 0 0 0 0 0]
640
[ 0 0 0 0 0 1024 0 0 0 0]
641
[ 0 0 0 0 0 0 1024 0 0 0]
642
[ 0 0 0 0 0 0 0 1024 0 0]
643
[ 0 0 0 0 0 0 0 0 1024 0]
644
[ 0 0 0 0 0 0 0 0 0 1024]
645
646
sage: L = A.LLL(); L
647
[ 192 264 -152 272 -8 272 -48 -264 104 -8]
648
[-128 -176 -240 160 -336 160 32 176 272 -336]
649
[ -24 -161 147 350 385 -34 262 161 115 257]
650
[ 520 75 -113 -74 -491 54 126 -75 239 -107]
651
[-376 -133 255 22 229 150 350 133 95 -411]
652
[-168 -103 5 402 -377 -238 -214 103 -219 -249]
653
[-352 28 108 -328 -156 184 88 -28 -20 356]
654
[ 120 -219 289 298 123 170 -286 219 449 -261]
655
[ 160 -292 44 56 164 568 -40 292 -84 -348]
656
[ 192 264 -152 272 -8 272 -48 760 104 -8]
657
sage: L.is_LLL_reduced()
658
True
659
sage: L.echelon_form() == A.echelon_form()
660
True
661
"""
662
cdef ZZ_mat *A = ZZ_mat_new(d,d)
663
A.gen_simdioph(b, b2)
664
665
B = to_sage(A)
666
ZZ_mat_delete(A)
667
return B
668
669
def gen_uniform(int nr, int nc, int b):
670
r"""
671
Return a (nr x nc) matrix where the entries are random $b$ bits
672
integers.
673
674
INPUT:
675
nr -- row dimension
676
nc -- column dimension
677
b-- bitsize of entries
678
679
EXAMPLE::
680
681
sage: from sage.libs.fplll.fplll import gen_uniform
682
sage: A = gen_uniform(10,10,12); A
683
[ 980 3534 533 3303 2491 2960 1475 3998 105 162]
684
[1766 3683 2782 668 2356 2149 1887 2327 976 1151]
685
[1573 438 1480 887 1490 634 3820 3379 4074 2669]
686
[ 215 2054 2388 3214 2459 250 2921 1395 3626 434]
687
[ 638 4011 3626 1864 633 1072 3651 2339 2926 1004]
688
[3731 439 1087 1088 2627 3446 2669 1419 563 2079]
689
[1868 3196 3712 4016 1451 2589 3327 712 647 1057]
690
[2068 2761 3479 2552 197 1258 1544 1116 3090 3667]
691
[1394 529 1683 1781 1779 3032 80 2712 639 3047]
692
[3695 3888 3139 851 2111 3375 208 3766 3925 1465]
693
694
sage: L = A.LLL(); L
695
[ 200 -1144 -365 755 1404 -218 -937 321 -718 790]
696
[ 623 813 873 -595 -422 604 -207 1265 -1418 1360]
697
[ -928 -816 479 1951 -319 -1295 827 333 1232 643]
698
[-1802 -1904 -952 425 -141 697 300 1608 -501 -767]
699
[ -572 -2010 -734 358 -1981 1101 -870 64 381 1106]
700
[ 853 -223 767 1382 -529 -780 -500 1507 -2455 -1190]
701
[-1016 -1755 1297 -2210 -276 -114 712 -63 370 222]
702
[ -430 1471 339 -513 1361 2715 2076 -646 -1406 -60]
703
[-3390 748 62 775 935 1697 -306 -618 88 -452]
704
[ 713 -1115 1887 -563 733 2443 816 972 876 -2074]
705
sage: L.is_LLL_reduced()
706
True
707
sage: L.echelon_form() == A.echelon_form()
708
True
709
"""
710
cdef ZZ_mat *A = ZZ_mat_new(nr,nc)
711
A.gen_uniform(b)
712
713
B = to_sage(A)
714
ZZ_mat_delete(A)
715
return B
716
717
def gen_ntrulike(int d, int b, int q):
718
"""
719
Generate a ntru-like lattice of dimension (2*d x 2*d), with the
720
coefficients $h_i$ chosen as random b bits integers and parameter
721
q:
722
723
\begin{verbatim}
724
[[ 1 0 ... 0 h0 h1 ... h_{d-1} ]
725
[ 0 1 ... 0 h1 h2 ... h0 ]
726
[ ................................ ]
727
[ 0 0 ... 1 h_{d-1} h0 ... h_{d-1} ]
728
[ 0 0 ... 0 q 0 ... 0 ]
729
[ 0 0 ... 0 0 q ... 0 ]
730
[ ................................ ]
731
[ 0 0 ... 0 0 0 ... q ]]
732
\end{verbatim}
733
734
INPUT:
735
d -- dimension
736
b -- bitsize of entries
737
q -- see above
738
739
EXAMPLE::
740
741
sage: from sage.libs.fplll.fplll import gen_ntrulike
742
sage: A = gen_ntrulike(5,10,12); A
743
[ 1 0 0 0 0 320 351 920 714 66]
744
[ 0 1 0 0 0 351 920 714 66 320]
745
[ 0 0 1 0 0 920 714 66 320 351]
746
[ 0 0 0 1 0 714 66 320 351 920]
747
[ 0 0 0 0 1 66 320 351 920 714]
748
[ 0 0 0 0 0 12 0 0 0 0]
749
[ 0 0 0 0 0 0 12 0 0 0]
750
[ 0 0 0 0 0 0 0 12 0 0]
751
[ 0 0 0 0 0 0 0 0 12 0]
752
[ 0 0 0 0 0 0 0 0 0 12]
753
754
sage: L = A.LLL(); L
755
[-1 -1 0 0 0 1 1 -2 0 -2]
756
[-1 0 0 0 -1 -2 1 1 -2 0]
757
[ 0 -1 -1 0 0 1 -2 0 -2 1]
758
[ 0 0 1 1 0 2 0 2 -1 -1]
759
[ 0 0 0 1 1 0 2 -1 -1 2]
760
[-2 -1 -2 1 1 1 0 1 1 0]
761
[-1 -2 1 1 -2 0 1 0 1 1]
762
[ 2 -1 -1 2 1 -1 0 -1 0 -1]
763
[-1 -1 2 1 2 -1 -1 0 -1 0]
764
[ 1 -2 -1 -2 1 0 1 1 0 1]
765
sage: L.is_LLL_reduced()
766
True
767
sage: L.echelon_form() == A.echelon_form()
768
True
769
"""
770
cdef ZZ_mat *A = ZZ_mat_new(2*d,2*d)
771
A.gen_ntrulike(b, q)
772
773
B = to_sage(A)
774
ZZ_mat_delete(A)
775
return B
776
777
def gen_ntrulike2(int d, int b, int q):
778
r"""
779
Like \code{gen_ntrulike} but with the $q$ vectors coming first.
780
781
INPUT:
782
d -- dimension
783
b -- bitsize of entries
784
q -- see gen_ntrulike
785
786
EXAMPLE::
787
788
sage: from sage.libs.fplll.fplll import gen_ntrulike2
789
sage: A = gen_ntrulike2(5,10,12); A
790
[ 12 0 0 0 0 0 0 0 0 0]
791
[ 0 12 0 0 0 0 0 0 0 0]
792
[ 0 0 12 0 0 0 0 0 0 0]
793
[ 0 0 0 12 0 0 0 0 0 0]
794
[ 0 0 0 0 12 0 0 0 0 0]
795
[902 947 306 40 908 1 0 0 0 0]
796
[947 306 40 908 902 0 1 0 0 0]
797
[306 40 908 902 947 0 0 1 0 0]
798
[ 40 908 902 947 306 0 0 0 1 0]
799
[908 902 947 306 40 0 0 0 0 1]
800
801
sage: L = A.LLL(); L
802
[ 1 0 0 2 -3 -2 1 1 0 0]
803
[-1 0 -2 1 2 2 1 -2 -1 0]
804
[ 0 2 -1 -2 1 0 -2 -1 2 1]
805
[ 0 3 0 1 3 1 0 -1 1 0]
806
[ 2 -1 0 -2 1 1 -2 -1 0 2]
807
[ 0 -1 0 -1 -1 1 4 -1 -1 0]
808
[ 2 1 1 1 -1 -3 -2 -1 -1 -1]
809
[-1 0 -1 0 -1 4 -1 -1 0 1]
810
[ 0 1 -2 1 1 -1 0 1 -3 -2]
811
[-2 1 1 0 1 -3 -2 -1 0 1]
812
sage: L.is_LLL_reduced()
813
True
814
sage: L.echelon_form() == A.echelon_form()
815
True
816
"""
817
cdef ZZ_mat *A = ZZ_mat_new(2*d,2*d)
818
A.gen_ntrulike2(b,q)
819
820
B = to_sage(A)
821
ZZ_mat_delete(A)
822
return B
823
824
def gen_ajtai(int d, float alpha):
825
r"""
826
Return Ajtai-like $(d x d)$-matrix of floating point parameter
827
$\alpha$. The matrix is lower-triangular, $B_{imi}$ is
828
$~2^{(d-i+1)^\alpha}$ and $B_{i,j}$ is $~B_{j,j}/2$ for $j<i$q.
829
830
INPUT:
831
d -- dimension
832
alpha -- see above
833
834
EXAMPLE::
835
836
sage: from sage.libs.fplll.fplll import gen_ajtai
837
sage: A = gen_ajtai(10, 0.7); A # random output
838
[117 0 0 0 0 0 0 0 0 0]
839
[ 11 55 0 0 0 0 0 0 0 0]
840
[-47 21 104 0 0 0 0 0 0 0]
841
[ -3 -22 -16 95 0 0 0 0 0 0]
842
[ -8 -21 -3 -28 55 0 0 0 0 0]
843
[-33 -15 -30 37 8 52 0 0 0 0]
844
[-35 21 41 -31 -23 10 21 0 0 0]
845
[ -9 20 -34 -23 -18 -13 -9 63 0 0]
846
[-11 14 -38 -16 -26 -23 -3 11 9 0]
847
[ 15 21 35 37 12 6 -2 10 1 17]
848
849
sage: L = A.LLL(); L # random output
850
[ 4 7 -3 21 -14 -17 -1 -1 -8 17]
851
[-20 0 -6 6 -11 -4 -19 10 1 17]
852
[-22 -1 8 -21 18 -29 3 11 9 0]
853
[ 31 8 20 2 -12 -4 -27 -22 -18 0]
854
[ -2 6 -4 7 -8 -10 6 52 -9 0]
855
[ 3 -7 35 -12 -29 23 3 11 9 0]
856
[-16 -6 -16 37 2 11 -1 -9 7 -34]
857
[ 11 55 0 0 0 0 0 0 0 0]
858
[ 11 14 38 16 26 23 3 11 9 0]
859
[ 13 -28 -1 7 -11 11 -12 3 54 0]
860
sage: L.is_LLL_reduced()
861
True
862
sage: L.echelon_form() == A.echelon_form()
863
True
864
"""
865
cdef ZZ_mat *A = ZZ_mat_new(d,d)
866
A.gen_ajtai(alpha)
867
868
B = to_sage(A)
869
ZZ_mat_delete(A)
870
return B
871
872
873
cdef to_sage(ZZ_mat *A):
874
"""
875
Return a Sage integer matrix for A. A is not destroyed.
876
877
INPUT:
878
A -- ZZ_mat
879
"""
880
cdef int i,j
881
cdef mpz_t *t
882
883
cdef Matrix_integer_dense B = <Matrix_integer_dense>matrix(ZZ,
884
A.GetNumRows(),
885
A.GetNumCols())
886
887
for i from 0 <= i < A.GetNumRows():
888
for j from 0 <= j < A.GetNumCols():
889
t = &B._matrix[i][j]
890
mpz_set(t[0], A.Get(i,j).GetData())
891
return B
892
893