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