A Python (2 and 3) wrapper for fplll.
>>> from fpylll import *
>>> A = IntegerMatrix(50, 50)
>>> A.randomize("ntrulike", bits=50, q=127)
>>> A[0].norm()
3564748886669202.5
>>> M = GSO.Mat(A)
>>> M.update_gso()
>>> M.get_mu(1,0)
0.815748944429783
>>> L = LLL.Reduction(M)
>>> L()
>>> M.get_mu(1,0)
0.41812865497076024
>>> A[0].norm()
24.06241883103193
The basic BKZ algorithm can be implemented in about 60 pretty readable lines of Python code (cf. simple_bkz.py).
fpylll relies on the following C/C++ libraries:
- GMP or MPIR for arbitrary precision integer arithmetic.
- MPFR for arbitrary precision floating point arithmetic.
- QD for double double and quad double arithmetic (optional).
- fplll for pretty much everything.
fpylll also relies on
- Cython for linking Python and C/C++.
- cysignals for signal handling such as interrupting C++ code.
- py.test for testing Python.
- flake8 for linting.
We also suggest
- IPython for interacting with Python
- Numpy for numerical computations (e.g. with Gram-Schmidt values)
We recommend virtualenv for isolating Python build environments and virtualenvwrapper to manage virtual environments.
Create a new virtualenv and activate it:
$ virtualenv env $ source ./env/bin/activate
We indicate active virtualenvs by the prefix
(fpylll)
.Install the required libraries – GMP or MPIR and MPFR – if not available already. You may also want to install QD.
Install fplll:
$ (fpylll) ./install-dependencies.sh $VIRTUAL_ENV
Then, execute:
$ (fpylll) pip install Cython $ (fpylll) pip install -r requirements.txt
to install the required Python packages (see above).
If you are so inclined, run:
$ (fpylll) pip install -r suggestions.txt
to install suggested Python packages as well (optional).
Build the Python extension:
$ (fpylll) export PKG_CONFIG_PATH="$VIRTUAL_ENV/lib/pkgconfig:$PKG_CONFIG_PATH" $ (fpylll) python setup.py build_ext $ (fpylll) python setup.py install
To run fpylll, you will need to:
$ (fpylll) export LD_LIBRARY_PATH="$VIRTUAL_ENV/lib"
so that Python can find fplll and friends.
Start Python:
$ (fpylll) ipython
To reactivate the virtual environment later, simply run:
$ source ./env/bin/activate
Note that you can also patch activate
to set LD_LIBRRY_PATH
. For this, add:
### LD_LIBRARY_HACK
_OLD_LD_LIBRARY_PATH="$LD_LIBRARY_PATH"
LD_LIBRARY_PATH="$VIRTUAL_ENV/lib:$LD_LIBRARY_PATH"
export LD_LIBRARY_PATH
### END_LD_LIBRARY_HACK
### PKG_CONFIG_HACK
_OLD_PKG_CONFIG_PATH="$PKG_CONFIG_PATH"
PKG_CONFIG_PATH="$VIRTUAL_ENV/lib/pkgconfig:$PKG_CONFIG_PATH"
export PKG_CONFIG_PATH
### END_PKG_CONFIG_HACK
towards the end and:
### LD_LIBRARY_HACK
if ! [ -z ${_OLD_LD_LIBRARY_PATH+x} ] ; then
LD_LIBRARY_PATH="$_OLD_LD_LIBRARY_PATH"
export LD_LIBRARY_PATH
unset _OLD_LD_LIBRARY_PATH
fi
### END_LD_LIBRARY_HACK
### PKG_CONFIG_HACK
if ! [ -z ${_OLD_PKG_CONFIG_PATH+x} ] ; then
PKG_CONFIG_PATH="$_OLD_PKG_CONFIG_PATH"
export PKG_CONFIG_PATH
unset _OLD_PKG_CONFIG_PATH
fi
### END_PKG_CONFIG_HACK
in the deactivate
function in the activate
script.
fpylll supports parallelisation on multiple cores. For all C++ support to drop the GIL is enabled, allowing the use of threads to parallelise. Note, however, that because fplll’s enumeration is not thread safe, we using locks to enforce only one thread calls it at any one point. Also, fpylll does not actually drop the GIL in all calls to C++ functions yet. In many scenarios using multiprocessing, which sidesteps the GIL and thread safety issues by using processes instead of threads, will be the better choice.
The example below calls LLL.reduction
on 128 matrices of dimension 30 on four worker processes.
from fpylll import IntegerMatrix, LLL
from multiprocessing import Pool
d, workers, tasks = 30, 4, 128
def run_it(p, f, A, prefix=""):
"""Print status during parallel execution."""
import sys
r = []
for i, retval in enumerate(p.imap_unordered(f, A, 1)):
r.append(retval)
sys.stderr.write('\r{0} done: {1:.2%}'.format(prefix, float(i)/len(A)))
sys.stderr.flush()
sys.stderr.write('\r{0} done {1:.2%}\n'.format(prefix, float(i+1)/len(A)))
return r
A = [IntegerMatrix.random(d, "uniform", bits=30) for _ in range(tasks)]
A = run_it(Pool(workers), LLL.reduction)
To test threading simply replace the line from multiprocessing import Pool
with from multiprocessing.pool import ThreadPool as Pool
. For calling BKZ.reduction
this way, which expects a second parameter with options, using functools.partial is a good choice.
fpylll welcomes contributions, cf. the list of open issues. To contribute, clone this repository, commit your code on a separate branch and send a pull request. Please write tests for your code. You can run them by calling:
$ (fpylll) py.test
from the top-level directory which runs all tests in tests/test_*.py
. We run flake8 on every commit automatically, In particular, we run:
$ (fpylll) flake8 --max-line-length=120 --max-complexity=16 --ignore=E22,E241 src
Note that fpylll supports Python 2 and 3. In particular, tests are run using Python 2.7 and 3.5. See .travis.yml for details on automated testing.
fpylll is maintained by Martin Albrecht.
The following people have contributed to fpylll
- Martin Albrecht
- Guillaume Bonnoron
- Leo Ducas
- Omer Katz
We copied a decent bit of code over from Sage, mostly from it’s fpLLL interface.
fpylll is licensed under the GPLv2+.