File: example-linear-diophantine-equations.rst

package info (click to toggle)
fpylll 0.6.3-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 1,068 kB
  • sloc: python: 2,193; makefile: 172; sh: 89; ansic: 79; cpp: 48
file content (71 lines) | stat: -rw-r--r-- 2,494 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
.. _example-linear-diophantine-equations:

.. role:: math(raw)
   :format: html latex
..

.. role:: raw-latex(raw)
   :format: latex
..

:orphan:


Small solutions to a linear diophantine equation
================================================

Say we want find a small solution to a linear diophantine equation `\sum_{i=1}^{n}a_ix_i=a_0`. In general Euclidean algorithm will provide a solution in polynomial time. This method does not provide small solution in general. We can use the lattice from [1]_ to attack this problem. Let A be the basis:

.. math::

   A = \begin{bmatrix}
   1 & 0 & 0 & \cdots & 0 & 0 & N_2a_1 \\
   0 & 1 & 0 & \cdots & 0 & 0 & N_2a_2 \\
   \vdots & \vdots & \vdots & \ddots & \vdots & \vdots \\
   0 & 0 & 0 & \cdots & 1& 0 &N_2a_n \\
   0 & 0 & 0 & \cdots & 0 & N_1 &-N_2a_0
   \end{bmatrix}

where `N_1`, `N_2` are some positive integers. Say `(x_1,x_2,...,x_n,x_{n+1},x_{n+2})` is a row of the LLL-reduced matrix of A. If `x_{n+1}=N_1, x_{n+2}=0,` then `(x_1,...,x_n)` is a solution of the linear equation. Say `{\bf a} = (1124, 1799, 1151, 1979, 1799, 1625, 1077, 1666, 1438, 1739)`, `a_0=22833`, `N_1=100`, `N_2=1000`.::

::

    >>> from fpylll import IntegerMatrix, LLL
    >>> N1 = 100
    >>> N2 = 10000
    >>> a = [1124, 1799, 1151, 1979, 1799, 1625, 1077, 1666, 1438, 1739]
    >>> a0 = 22833
    >>> n = len(a)
    >>> M = IntegerMatrix(n+1, n+2)
    >>> for i in range(len(a)):
    ...     M[i, -1] = a[i]*N2
    ...     M[i,  i] = 1
    ...
  
    >>> M[-1, -2] = N1
    >>> M[-1, -1] = -a0 * N2
 

We can now apply LLL::

  >>> L = LLL.reduction(M); print(L)
  [  0 -1  0  0  1  0  0  0  0 0   0      0 ]
  [  0  1  0  0  0  0  1  0 -2 0   0      0 ]
  [ -1  0 -1 -1  0  0  1  0  1 1   0      0 ]
  [ -1 -1  0  1 -1  0  1  1  0 0   0      0 ]
  [  1 -1  0  0 -1  1  1 -1  1 0   0      0 ]
  [  0  0  0  0  0  1 -2  1 -2 1   0      0 ]
  [  0  0  0  0  0 -2  0 -1  1 2   0      0 ]
  [ -1 -1  2  0  0  1 -1 -1  0 1   0      0 ]
  [ -2  1 -2  3  0  2  0 -3 -1 0   0      0 ]
  [  1  2  0  1  2  3  1  1  1 2 100      0 ]
  [  1  0  0  1  0  0  0 -1 -1 0   0 -10000 ]

So a small solution is `{\bf v} = ( 1,  2,  0,  1,  2,  3,  1,  1,  1, 2 ),` with norm

::

  >>> L.submatrix(0, 0, n, n)[-1].norm()  # doctest: +ELLIPSIS
  5.099019513...

.. [1] K. Aardal, C. Hurkens, A. Lenstra, Solving a linear Diophantine equation with lower and upper bounds on the variables. Integer programming and combinatorial optimization LNCS 1412, p.229–242, 1998.