• Lattice Reduction (LLL) 算法C代码实现


    废话不多说,大名鼎鼎的Lenstra-Lenstra-Lovasz(LLL) 算法。实现参考论文:Factoring Polynomials with Rational Coefficients, 作者 A.K. Lenstra, H.W. Lenstra, Jr. and L. Lovasz.

    /*    File        : LLL Lattice Reduction Matlab mex interface
    *    Description    : do Lattice Reduction in the Real Field, Complex Lattice Redution is not currently supported
    *                        reference paper 'Factoring Ploynominals with Rational Coefficients ' A.K Lenstra, H. W. Lenstra, and L.Lovasz
    *    Author        : fangying
    *    Date        : 2014-01-12
    *    Modified    :
    */
    
    #include "stdio.h"
    #include "math.h"
    #include "stdlib.h"
    
    /*
    *    Description    : this function is used to give the round interger of the input double variable
    *    Input        : a double variable
    *    Output        : a round interger of the given variable
    */
    int roundinteger(double var)
    {
        return (var > 0) ? (int)(var + 0.5) : (int)(var - 0.5);
    }
    
    /*
    *    Description    : this function is used to perform inner product of two given vector or array
    *    Input        : pointer of vector 'b1' and 'b2' with their length 'm'
    *    Output        : pointer of the output result
    */
    
    double innerproduct(double *b1, double *b2, int m)
    {
        double sum = 0;
    
        while (m--)
        {
            sum += b1[m] * b2[m];
        }
        return sum;
    }
    
    /*
    *    Description    : this function performs Gram-Schmidt on input Matrix
    *    Input        : pointer of the input Matrix(in array format) 'bin',pointer of the output Matrix 'bout',
    *                        the projection between inner-vectors,and dimension 'N*M'('N' for cloumn,'M' for row)
    *    Output        : the GSO(Gram-Schmidt Othogonal) Matrix pointer
    */
    
    void GramSchmidt(double *bin, double *bout, double *u, double *B, int M, int N)
    {
        int i, j, k;
        double uTemp, projection;
    
        /* copy bin to bout */
        for (j = 0; j < M*N; j++)
        {
            bout[j] = bin[j];
        }
    
        /* Euclid Square of the first column */
        B[0] = innerproduct(bout, bout, M);
    
        for (i = 0; i < N; i++)
        {
            for (k = 0; k < i; k++)
            {
                projection = innerproduct(bout + k*M, bin + i*M, M);
                uTemp = projection / B[k];
                u[(i - 1)*(N - 1) + k] = uTemp;
    
                for (j = 0; j < M; j++)
                {
                    bout[i*M + j] -= bout[k*M + j] * uTemp;
                }
            }
            /* calculate the next B[i]*/
            B[i] = innerproduct(bout + i*M, bout + i*M, M);
        }
    }
    
    /*
    *    Description    : this function is used the do the reduction procedure
    *    Input        : the column vector 'b',
    *    Output        : update the ...
    */
    void reduction(double *b, double *u, int k, int l, int M, int N)
    {
        int j, i, r;
        double uTemp, uAbs;
    
        uTemp = u[(k - 1)*(N - 1) + l];
        uAbs = fabs(*u);
        //uAbs = (uTemp >= 0) ? uTemp : (-uTemp);
        //uAbs = (uTemp > 0) ? uTemp : (-uTemp);
    
        if (uAbs > 0.5)
        {
            r = roundinteger(uTemp);
    
            /* update u(k,k-1) <= u(k,k-1) - r */
            u[(k - 1)*(N - 1) + l] -= r;
    
            /* update b(k) <= b(k) -r*b(k-1) */
            for (i = 0; i < M; i++)
            {
                b[k*M + i] -= r*b[l*M + i];
            }
    
            /* for u(k,j) with j<k-1, update u(k,j) <= u(k,j) - r*u(k-1,j) */
            for (j = 0; j <= l - 1; j++)
            {
                u[(k - 1)*(N - 1) + j] -= r*u[(l - 1)*(N - 1) + j];
            }
        }
    }
    
    
    /*
    *    Description    : this function is used the do the check procedure
    *    Input        : 'B' the input column Euclid Squre, 'b' the input Matrix element
    'u' the projection , 'k' the current subscript  and dimension 'M*N'
    *    Output        : update the ...
    */
    void check(double *B, double *b, double *u, int k, int l, int M, int N)
    {
        int i, j;
        double uTemp, Btemp;
        double tmp;
    
        uTemp = u[(k - 1)*(N - 1) + k - 1];        /* this is u(k,k-1) */
    
        /* c(k-1) <= b(k)
        * c(k)   <= b(k-1)
        * c(i)   <= b(i) for i != k,k-1
        */
        Btemp = B[k] + uTemp * uTemp * B[k - 1];    // Btemp = c*(k-1)
    
        /* update u(k,k-1) <= u(k,k-1)B[k-1]/C[k-1] , this is v(k,k-1) */
        u[(k - 1)*(N - 1) + k - 1] = uTemp*B[k - 1] / Btemp;
    
        /* update B[k] <= C[k] */
        B[k] = B[k - 1] * B[k] / Btemp;
        /* update B[k-1] <= C[k-1] */
        B[k - 1] = Btemp;
    
        /* exchange b[k] <=> b[k] */
        for (j = 0; j < M; j++)
        {
            tmp = b[k*M + j];
            b[k*M + j] = b[(k - 1)*M + j];
            b[(k - 1)*M + j] = tmp;
        }
    
        /* for j<k-1 ,i.e  j = [1 to k-2]
        * u(k-1,j) <= u(k,j)
        * u(k,j)   <= u(k-1,j)
        */
        for (j = 0; j < k - 1; j++)
        {
            tmp = u[(k - 2)*(N - 1) + j];                            // u(k-1,j)
            u[(k - 2)*(N - 1) + j] = u[(k - 1)*(N - 1) + j];
            u[(k - 1)*(N - 1) + j] = tmp;                            // u(k,j)
        }
    
        /* for j>k
        *
        * u(i,k)    <= u(i,k-1) - u(i,k)*u(k,k-1)
        * u(i,k-1) <= u(k,k-1) -uTemp*u(i,k)
        */
    
        for (i = k + 1; i < N; i++)
        {
            tmp = u[(i - 1)*(N - 1) + k];                        // u(i,k)
            /* v(i,k) <= u(i,k-1) - u(i,k)*u(k,k-1) */
            u[(i - 1)*(N - 1) + k] = u[(i - 1)*(N - 1) + (k - 1)] - u[(i - 1)*(N - 1) + k] * uTemp;
            /* v(i,k-1)  <= u(i,k-1)*v() */                        //更新v(i,k-1),看文献Page521页
            u[(i - 1)*(N - 1) + k - 1] = u[(k - 1)*(N - 1) + (k - 1)] * u[(i - 1)*(N - 1) + (k - 1)] + tmp*(1 - uTemp*u[(k - 1)*(N - 1) + (k - 1)]);
        }
    
    }
    
    
    /*
    *    Description    : LLL (Lattice Reduction Alogorithm
    *    Input        : the input Matrix in array 'bin',the dimension of the Matrix 'N*M',the output 'HLR'
    */
    void RLLL(double *bin, int M, int N, double *HLR)
    {
        int i, k, l;
    
        double *u;
        double *B;
        double *H;
        
        u = (double *)calloc(N*M, sizeof(double));
        B = (double *)calloc(N, sizeof(double));
        H = (double *)calloc(N*M, sizeof(double));
    
        for (i = 0; i < M*N; i++)
        {
            H[i] = bin[i];
        }
    
    
        GramSchmidt(H, HLR, u, B, M, N);
    
        k = 1;
    
        while (1)
        {
            l = k - 1;
            reduction(H, u, k, l, M, N);
    
            /* iteration procedure */
            if (B[k]<(0.75 - u[(k - 1)*(N - 1) + k - 1] * u[(k - 1)*(N - 1) + k - 1])*B[k - 1])
            {
                check(B, H, u, k, l, M, N);
                if (k>1)
                {
                    k--;
                }
            }
            else
            {
                for (l = k - 2; l >= 0; l--)
                {
                    reduction(H, u, k, l, M, N);
                }
    
                if (k == N - 1)    break;
                k++;
            }
        }
    
    
        for (i = 0; i < M*N; i++)
        {
            HLR[i] = H[i];
        }
    
        free(u);
        free(H);
        free(B);
    
    }
    
    int main()
    {
        int col = 3;
        int row = 3;
        int index = 0;
    
        double magic[] = { 8, 3, 4, 1, 5, 9, 6, 7, 2 };
        double hlr[3 * 3] = { 0 };
    
        LLL(magic, col, row, hlr);
    
        return 0;
    }
  • 相关阅读:
    5 November
    31 October
    K-th Path
    P1525 关押罪犯
    dp-棋盘形dp
    P1462 通往奥格瑞玛的道路
    noip2017部分题目
    洛谷orz--尺取法
    树形dp
    最短路练习
  • 原文地址:https://www.cnblogs.com/fangying7/p/4997013.html
Copyright © 2020-2023  润新知