oILAB
Loading...
Searching...
No Matches
RLLL.cpp
Go to the documentation of this file.
1/* This file is part of gbLAB.
2 *
3 * gbLAB is distributed without any warranty under the MIT License.
4 */
5
6
7#ifndef gbLAB_RLLL_cpp_
8#define gbLAB_RLLL_cpp_
9
10#include "RLLL.h"
11#include <vector>
12
13namespace gbLAB
14{
15
16
17 /**********************************************************************/
19 MatrixType &M,
20 const int &k)
21 {
22 const int n = B.cols();
23
24 // B1=B;
25 // B1(:,k-1)=B(:,k);
26 // B1(:,k)=B(:,k-1);
27 B.col(k).swap(B.col(k - 1));
28
29 MatrixType H1 = H;
30 MatrixType M1 = M;
31 H1(k - 1) = H(k) + std::pow(M(k, k - 1), 2) * H(k - 1);
32 // M1(k,k-1)=M(k,k-1)*H(k-1)/H1(k-1);
33 M1(k, k - 1) *= H(k - 1) / H1(k - 1);
34 H1(k) = H(k - 1) - std::pow(M1(k, k - 1), 2) * H1(k - 1);
35 // for i=k+1:n
36 for (int i = k + 1; i < n; ++i)
37 {
38 M1(i, k - 1) = M(i, k - 1) * M1(k, k - 1) + M(i, k) * H(k) / H1(k - 1);
39 M1(i, k) = M(i, k - 1) - M(i, k) * M(k, k - 1);
40 }
41 // for j=1:k-2
42 for (int j = 0; j <= k - 2; ++j)
43 {
44 M1(k - 1, j) = M(k, j);
45 M1(k, j) = M(k - 1, j);
46 }
47 H = H1;
48 M = M1;
49 }
50
51 /**********************************************************************/
53 const int &k,
54 const int &j)
55 {
56
57 const long long int c = std::round(M(k, j));
58 B.col(k) -= c * B.col(j);
59 U.col(k) -= c * U.col(j);
60 for (int l = 0; l <= j; ++l) // j is already 0-based, so use <=
61 {
62 M(k, l) -= c * M(j, l);
63 }
64 }
65
66 /**********************************************************************/
68 const double &delta) : /* init */ B(B0),
69 /* init */ U(Eigen::Matrix<long long int, Eigen::Dynamic, Eigen::Dynamic>::Identity(B0.cols(), B0.cols()))
70 {
71 assert(delta >= 0.5 && delta <= 1.0 && "delta must be in [0.5 1]");
72
73 const int n = B0.cols();
74 const int dim = B0.rows();
75 double err;
76 double absDetU;
77 //double scale= B.norm();
78 double scale= 1;
79
80 assert(dim <= B0.rows() && "B.rows() must be >= B.cols()");
81
82 if (n < dim)
83 {
84 MatrixType orthonormalBasis(dim,n);
85 orthonormalBasis= B0.householderQr().householderQ();
86 orthonormalBasis= orthonormalBasis.block(0,0,dim,n).eval();
87
88 MatrixType B0InNewCoords(n,n);
89 B0InNewCoords= orthonormalBasis.transpose()*B0;
90
91 Eigen::MatrixXd reducedB0InNewCoords= RLLL(B0InNewCoords,delta).reducedBasis();
92 U = RLLL(B0InNewCoords,delta).unimodularMatrix();
93 B = orthonormalBasis*reducedB0InNewCoords;
94 }
95 else
96 {
97 std::vector<int> indices(n);
98 Eigen::Matrix<long long int, Eigen::Dynamic, Eigen::Dynamic> preU(n,n);
99 for(int i=0; i<n; ++i)
100 indices[i]= i;
101 for (int i=0;i<2;++i) {
102 if (i == 0)
103 scale = 1.0;
104 else
105 scale = B.norm();
106
107 do {
108 B = B0 / scale;
109 U = Eigen::Matrix<long long int, Eigen::Dynamic, Eigen::Dynamic>::Identity(n, n);
110 for (int i = 0; i < n; ++i) {
111 B.col(i) = B0.col(indices[i]) / scale;
112 preU.col(i) = U.col(indices[i]);
113 }
114
115 // //std::cout<<"here 0"<<std::endl;
116 VectorType H(VectorType::Zero(n));
117 for (int j = 0; j < n; ++j) {
118 H(j) = B.col(j).squaredNorm();
119 }
120
121 //std::cout<<H.transpose()<<std::endl;
122
123 //std::cout<<"here 1"<<std::endl;
124 MatrixType M(MatrixType::Identity(n, n));
125 for (int j = 0; j < n; ++j) {
126 for (int i = j + 1; i < n; ++i) {
127 double temp = 0.0;
128 //std::cout<<i<<" "<<j<<std::endl;
129
130 for (int k = 0; k <= j - 1; ++k) // j is already 0-based, so use <=
131 {
132 //std::cout<<i<<" "<<j<<" "<<k<<std::endl;
133
134 temp += M(j, k) * M(i, k) * H(k);
135 }
136 M(i, j) = (B.col(i).dot(B.col(j)) - temp) / H(j);
137 H(i) -= std::pow(M(i, j), 2) * H(j);
138 }
139 }
140
141
142 //std::cout<<std::setprecision(15)<<std::scientific<<M<<std::endl;
143 //std::cout<<std::setprecision(15)<<std::scientific<<H<<std::endl;
144
145 // MatrixType M(MatrixType::Identity(n,n));
146 int k = 1;
147 while (k < n) {
148 if (fabs(M(k, k - 1)) > 0.5) {
149 size_reduce(M, k, k - 1);
150 }
151
152 if (H(k) < (delta - std::pow(M(k, k - 1), 2)) * H(k - 1)) {
153 update(H, M, k);
154 U.col(k).swap(U.col(k - 1));
155 k = std::max(1, k - 1);
156 } else {
157 // for j=k-2:-1:1
158 for (int j = k - 2; j >= 0; --j) {
159 if (fabs(M(k, j)) > 0.5) {
160 size_reduce(M, k, j);
161 }
162 }
163 k = k + 1;
164 }
165 }
166 U = preU * U;
167
168 err = (B0.lu().solve(scale * B) - U.cast<double>()).norm() / U.cast<double>().norm();
169 absDetU = fabs(U.cast<double>().determinant());
170 if (err < FLT_EPSILON && fabs(absDetU - 1.0) < FLT_EPSILON) {
171 B = B * scale;
172 return;
173 }
174 } while (std::next_permutation(indices.begin(), indices.end()));
175 }
176
177 if (err > FLT_EPSILON) {
178 std::cout << "RLLL relative error= " << std::setprecision(15) << std::scientific << err << " > "
179 << FLT_EPSILON << std::endl;
180 throw std::runtime_error("Relative error too large. RLLL failed.\n");
181 }
182
183 if (fabs(absDetU - 1.0) > FLT_EPSILON) {
184 std::cout << "|det(U)|= " << std::setprecision(15) << std::scientific << absDetU << std::endl;
185 throw std::runtime_error("U is not unimodular. RLLL failed.\n");
186 }
187
188 }
189 }
190
191 /**********************************************************************/
192 const typename RLLL::MatrixType& RLLL::reducedBasis() const
193 {
194 return B;
195 }
196
197 /**********************************************************************/
198 const Eigen::Matrix<long long int, Eigen::Dynamic, Eigen::Dynamic>& RLLL::unimodularMatrix() const
199 {
200 return U;
201 }
202
203} // end namespace
204#endif
Eigen::MatrixXd MatrixType
Definition RLLL.h:24
Eigen::VectorXd VectorType
Definition RLLL.h:25
Eigen::Matrix< long long int, Eigen::Dynamic, Eigen::Dynamic > U
Definition RLLL.h:29
void update(VectorType &H, MatrixType &M, const int &k)
Definition RLLL.cpp:18
const MatrixType & reducedBasis() const
Definition RLLL.cpp:192
const Eigen::Matrix< long long int, Eigen::Dynamic, Eigen::Dynamic > & unimodularMatrix() const
Definition RLLL.cpp:198
RLLL(const MatrixType &B0, const double &delta)
Definition RLLL.cpp:67
MatrixType B
Definition RLLL.h:28
void size_reduce(MatrixType &M, const int &k, const int &j)
Definition RLLL.cpp:52