191SCENARIO(
"AffineBasis< Point4i > unit tests",
"[affine_basis][4i]" )
194 typedef Space::Point
Point;
196 GIVEN(
"Given X a set of randomly generated points by adding linear combinations of 1 lattice vectors" ) {
197 std::vector< Point > V = {
Point{ 3, 1, 0, 2 } };
199 Basis
B( X, Basis::Type::ECHELON_REDUCED );
200 THEN(
"When reduced, it has dimension 1" ) {
204 THEN(
"When reduced, it is the vector V[0] or -V[0]" ) {
206 Point b0 =
B.basis()[ 0 ];
208 REQUIRE( ((b0 == V[0]) || (b0 == -V[0])) );
211 GIVEN(
"Given X a set of randomly generated points by adding linear combinations of 2 lattice vectors" ) {
212 std::vector< Point > V = {
Point{ 3, 1, 0, 2 },
Point{ -2, -1, 2, 7 } };
214 Basis
B( X, Basis::Type::SHORTEST_ECHELON_REDUCED );
215 THEN(
"When reduced, basis has dimension 2" ) {
219 THEN(
"When reduced, basis spans vectors V[i] or -V[i]" ) {
221 Point b0 =
B.basis()[ 0 ];
222 Point b1 =
B.basis()[ 1 ];
228 THEN(
"every point of X has rational coordinates with no remainder" ) {
229 unsigned int nb_ok = 0;
232 const auto [d, lambda, rem ] =
B.decompose( p );
233 nb_ok += ( rem == Point::zero ) ? : 1;
234 if ( rem != Point::zero )
235 std::cout <<
"p=" << p <<
" d=" << d
236 <<
" lambda=" << lambda <<
" rem=" << rem <<
"\n";
240 THEN(
"every lattice point can be written as a linear combination" ) {
241 auto Y = makeRandomVectors<Point>( 20, 10 );
242 unsigned int nb_ok = 0;
245 const auto p = y +
B.first;
246 const auto [d, lambda, rem ] =
B.decompose( p );
247 auto q =
B.recompose( d, lambda, rem );
248 nb_ok += ( p == q ) ? : 1;
250 std::cout <<
"p=" << p <<
" d=" << d
251 <<
" lambda=" << lambda <<
" rem=" << rem
252 <<
" q=" << q <<
"\n";
259SCENARIO(
"AffineBasis< Point4i > projection tests",
"[affine_basis][4i][4d]" )
262 typedef Space::Point
Point;
264 typedef Space2::Point PPoint;
267 typedef Space2::RealPoint PRealPoint;
270 GIVEN(
"Given X a set of randomly generated points by adding linear combinations of 2 lattice vectors, and Y the same set but with real coordinates" ) {
271 std::vector< Point > V = {
Point{ 3, 4, 0, 2 },
Point{ -2, -1, 5, -7 } };
273 Basis
B( X, Basis::Type::ECHELON_REDUCED );
274 std::vector< RealPoint > Y( X.size() );
275 for (
auto i = 0; i < Y.size(); i++ )
276 Basis::transform( Y[ i ], X[ i ] );
277 RealBasis RB( Y, RealBasis::Type::ECHELON_REDUCED );
278 std::vector< PPoint > pX;
279 std::vector< PRealPoint > pY;
280 auto lcm =
B .projectPoints( pX, X );
281 auto rlcm = RB.projectPoints( pY, Y );
283 double factor = ( rbox.second - rbox.first ).squaredNorm();
284 THEN(
"When reduced, their affine bases has same dimension 2" ) {
288 REQUIRE( RB.dimension() == 2 );
290 THEN(
"Their projections have the same geometry (i.e. orientations within points)" ) {
295 REQUIRE( pX.size() == pY.size() );
297 const std::size_t nb = 2000;
298 std::size_t nb_ok = 0;
299 const double eps = 1e-12 * factor;
300 for (
auto i = 0; i < nb; i++ )
302 const std::size_t j = rand() % pX.size();
303 const std::size_t k = rand() % pX.size();
304 const std::size_t l = rand() % pX.size();
305 const auto u = pX[ k ] - pX[ j ];
306 const auto v = pX[ l ] - pX[ j ];
307 const auto ru = pY[ k ] - pY[ j ];
308 const auto rv = pY[ l ] - pY[ j ];
309 const auto det = u [ 0 ] * v [ 1 ] - u [ 1 ] * v [ 0 ];
310 const auto rdet = ru[ 0 ] * rv[ 1 ] - ru[ 1 ] * rv[ 0 ];
311 if ( rdet > eps ) nb_ok += ( det > 0 ) ? 1 : 0;
312 else if ( rdet < -eps ) nb_ok += ( det < 0 ) ? 1 : 0;
313 else nb_ok += ( det == 0 ) ? 1 : 0;
316 std::cout <<
"eps=" << eps <<
" factor=" << factor <<
"\n";
317 std::cout <<
"u =" << u <<
" v =" << v <<
" det =" << det <<
"\n";
318 std::cout <<
"ru=" << ru <<
" rv=" << rv <<
" rdet=" << rdet <<
"\n";
332SCENARIO(
"AffineBasis< Point5i > unit tests",
"[affine_basis][5i]" )
335 typedef Space::Point
Point;
340 unsigned int nb_s_parallel_l = 0;
341 unsigned int nb_equal_big = 0;
342 unsigned int nb_equal_N = 0;
343 unsigned int nb_equal_Nr = 0;
344 for (
auto n = 0; n < 10; n++ )
346 std::vector< Point > X = makeRandomVectors<Point>( 5, 100 );
347 std::vector< Point > Y;
348 for (
auto i = 1; i < X.size(); i++ ) Y.push_back( X[ i ] - X[ 0 ] );
349 Basis
B ( X[ 0 ], Y, Basis::Type::LLL_REDUCED );
350 Basis Br( X[ 0 ], Y, Basis::Type::ECHELON_REDUCED );
354 auto N_big = Affine::template orthogonalVector<BigInteger>(
B.basis() );
355 auto Nr_big = Affine::template orthogonalVector<BigInteger>( Br.basis() );
357 auto Nr_cast = Nr_big;
358 for (
auto i = 0; i < 5; i++ ) N_cast[ i ] = N[ i ];
359 for (
auto i = 0; i < 5; i++ ) Nr_cast[ i ] = Nr[ i ];
364 bool s_parallel_l = Br.isParallel(
B );
365 nb_s_parallel_l += s_parallel_l ? 1 : 0;
366 if ( ! s_parallel_l )
368 std::cout <<
"dim(B)=" <<
B.dimension() <<
" dim(Br)=" << Br.dimension() <<
"\n";
369 std::cout <<
"* Br is not // to B:\n" << Br <<
"\n";
370 for (
auto v :
B.basis() )
372 bool parallel = Br.isParallel( v );
373 std::cout <<
" v=" << v <<
" //=" << ( parallel ?
"True" :
"False" ) <<
"\n";
376 const auto [d, lambda, r] =
B.decomposeVector( v );
377 std::cout <<
"d=" << d <<
" L=" << lambda <<
" r=" << r <<
"\n";
385 THEN(
"Normals with big integers are the same" ) {
388 THEN(
"There is less overflow in orthogonal vector computation using non reduced basis" ) {
389 REQUIRE( nb_equal_N >= nb_equal_Nr );
391 THEN(
"The LLL-reduced basis and the echelon-reduced basis are parallel" ) {
392 REQUIRE( nb_s_parallel_l == nb );
401SCENARIO(
"AffineBasis< Z10 > LLL tests",
"[affine_basis][10d][LLL]" )
404 typedef Space::Point
Point;
408 WHEN(
"Using basis is unimodular" ) {
410 std::vector< Point >
B = {
411 Point{ -3, 10, 47, 61, -53, -126, 713, 601,-1476, 1569},
412 Point{ 2, -7, -33, -43, 37, 89, -502, -425, 1047,-1103},
413 Point{ -3, 11, 53, 69, -59, -142, 800, 677,-1663, 1764},
414 Point{ 1, -9, -48, -63, 52, 130, -727, -623, 1543,-1604},
415 Point{ -2, 9, 48, 63, -49, -124, 680, 583,-1409, 1533},
416 Point{ 5, -25, -118, -163, 113, 334,-1761,-1595, 4030,-3838},
417 Point{ -3, 17, 85, 118, -84, -245, 1297, 1173,-2974, 2824},
418 Point{ 5, -24, -119, -156, 126, 321,-1782,-1534, 3799,-3921},
419 Point{ 2, -10, -44, -65, 42, 137, -699, -659, 1713,-1489},
420 Point{ 1, -5, -23, -27, 33, 64, -405, -315, 784, -868}
422 Point o = Point::zero;
423 Basis S( o,
B, Basis::Type::SHORTEST_ECHELON_REDUCED );
424 Basis
L( o,
B, Basis::Type::LLL_REDUCED );
425 THEN(
"The LLL-reduced basis is canonic" ) {
426 const auto& V =
L.basis();
428 unsigned int nbok = 0;
429 for (
auto i = 0; i < V.size(); i++ )
431 nbok += V[ i ].norm1() == 1 ? : 0;
437 THEN(
"The echelon-reduced basis is triangular" ) {
438 const auto& V = S.basis();
440 unsigned int nbok = 0;
441 for (
auto i = 0; i < V.size(); i++ )
442 for (
auto j = 0; j < i; j++ )
444 nbok += ( V[ i ][ j ] == 0 ) ? 1 : 0;
450 THEN(
"The LLL-reduced basis is parallel to the echelon-reduced basis" ) {
457SCENARIO(
"AffineBasis< Point5i > projection tests",
"[affine_basis][5i][5d]" )
460 typedef Space::Point
Point;
465 GIVEN(
"Given X a set of randomly generated points by adding linear combinations of 2 lattice vectors, and Y the same set but with real coordinates" ) {
467 typedef Space2::Point PPoint;
468 typedef Space2::RealPoint PRealPoint;
469 std::vector< Point > V = {
Point{ 3, 4, 0, 2, -5 },
Point{ -2, -1, 5, -7, 1 } };
471 Basis
B( X, Basis::Type::ECHELON_REDUCED );
472 std::vector< RealPoint > Y( X.size() );
473 for (
auto i = 0; i < Y.size(); i++ )
474 Basis::transform( Y[ i ], X[ i ] );
475 RealBasis RB( Y, RealBasis::Type::ECHELON_REDUCED, 0.99, 1e-10 );
476 std::vector< PPoint > pX;
477 std::vector< PRealPoint > pY;
478 auto lcm =
B .projectPoints( pX, X );
479 auto rlcm = RB.projectPoints( pY, Y );
481 double factor = ( rbox.second - rbox.first ).squaredNorm();
482 THEN(
"When reduced, their affine bases has same dimension 2" ) {
486 REQUIRE( RB.dimension() == 2 );
488 THEN(
"Their projections have the same geometry (i.e. orientations within points)" ) {
493 REQUIRE( pX.size() == pY.size() );
495 const std::size_t nb = 200;
496 std::size_t nb_ok = 0;
497 const double eps = 1e-12 * factor;
498 for (
auto i = 0; i < nb; i++ )
500 const std::size_t j = rand() % pX.size();
501 const std::size_t k = rand() % pX.size();
502 const std::size_t l = rand() % pX.size();
503 const auto u = pX[ k ] - pX[ j ];
504 const auto v = pX[ l ] - pX[ j ];
505 const auto ru = pY[ k ] - pY[ j ];
506 const auto rv = pY[ l ] - pY[ j ];
509 if ( rdet > eps ) nb_ok += ( det > 0 ) ? 1 : 0;
510 else if ( rdet < -eps ) nb_ok += ( det < 0 ) ? 1 : 0;
511 else nb_ok += ( det == 0 ) ? 1 : 0;
514 std::cout <<
"eps=" << eps <<
" factor=" << factor <<
"\n";
515 std::cout <<
"u =" << u <<
" v =" << v <<
" det =" << det <<
"\n";
516 std::cout <<
"ru=" << ru <<
" rv=" << rv <<
" rdet=" << rdet <<
"\n";
524 GIVEN(
"Given X a set of randomly generated points by adding linear combinations of 3 lattice vectors, and Y the same set but with real coordinates" ) {
526 typedef Space3::Point PPoint;
527 typedef Space3::RealPoint PRealPoint;
528 std::vector< Point > V = {
Point{ 3, 4, 0, 2, 5 },
529 Point{ -2, -1, 5, -7, 1 },
530 Point{ -5, 2, 11, 1, 4 } };
532 Basis
B( X, Basis::Type::ECHELON_REDUCED );
533 std::vector< RealPoint > Y( X.size() );
534 for (
auto i = 0; i < Y.size(); i++ )
535 Basis::transform( Y[ i ], X[ i ] );
536 RealBasis RB( Y, RealBasis::Type::ECHELON_REDUCED );
537 std::vector< PPoint > pX;
538 std::vector< PRealPoint > pY;
539 auto lcm =
B .projectPoints( pX, X );
540 auto rlcm = RB.projectPoints( pY, Y );
542 double factor = ( rbox.second - rbox.first ).squaredNorm();
543 THEN(
"When reduced, their affine bases has same dimension 2" ) {
547 REQUIRE( RB.dimension() == 3 );
549 THEN(
"Their projections have null remainder" ) {
551 unsigned int nb_null_rem = 0;
552 for (
auto i = 0; i < X.size(); i++ )
554 const auto [ d,
L, r ] =
B.decomposeVector( X[i] -
B.origin() );
555 nb_null_rem += ( r == Point::zero ) ? 1 : 0;
556 if ( r != Point::zero )
557 std::cout << (X[i] -
B.origin()) <<
" => " << d <<
"/" <<
L <<
"/" << r <<
"\n";
559 REQUIRE( nb_null_rem == X.size() );
561 THEN(
"Their projections have the same geometry (i.e. orientations within points)" ) {
568 REQUIRE( pX.size() == pY.size() );
570 const std::size_t nb = 200;
571 std::size_t nb_ok = 0;
572 const double eps = 1e-12 * factor;
573 for (
auto i = 0; i < nb; i++ )
575 const std::size_t j = rand() % pX.size();
576 const std::size_t k = rand() % pX.size();
577 const std::size_t l = rand() % pX.size();
578 const std::size_t m = rand() % pX.size();
579 const auto u = pX[ k ] - pX[ j ];
580 const auto v = pX[ l ] - pX[ j ];
581 const auto w = pX[ m ] - pX[ j ];
582 const auto ru = pY[ k ] - pY[ j ];
583 const auto rv = pY[ l ] - pY[ j ];
584 const auto rw = pY[ m ] - pY[ j ];
587 if ( rdet > eps ) nb_ok += ( det > 0 ) ? 1 : 0;
588 else if ( rdet < -eps ) nb_ok += ( det < 0 ) ? 1 : 0;
589 else nb_ok += ( det == 0 ) ? 1 : 0;
592 std::cout <<
"eps=" << eps <<
" factor=" << factor <<
"\n";
593 std::cout <<
"u =" << u <<
" v =" << v <<
" w =" << w
594 <<
" det =" << det <<
"\n";
595 std::cout <<
"ru=" << ru <<
" rv=" << rv <<
" rw=" << rw
596 <<
" rdet=" << rdet <<
"\n";