[Mlir-commits] [mlir] [MLIR][Presburger] Add LLL basis reduction (PR #75565)
llvmlistbot at llvm.org
llvmlistbot at llvm.org
Thu Dec 14 23:08:35 PST 2023
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-mlir-presburger
@llvm/pr-subscribers-mlir
Author: None (Abhinav271828)
<details>
<summary>Changes</summary>
Add a method for LLL basis reduction to the FracMatrix class.
This needs an abs() method for Fractions, which is added to Fraction.h.
---
Full diff: https://github.com/llvm/llvm-project/pull/75565.diff
4 Files Affected:
- (modified) mlir/include/mlir/Analysis/Presburger/Fraction.h (+2)
- (modified) mlir/include/mlir/Analysis/Presburger/Matrix.h (+4)
- (modified) mlir/lib/Analysis/Presburger/Matrix.cpp (+36-1)
- (modified) mlir/unittests/Analysis/Presburger/MatrixTest.cpp (+48-1)
``````````diff
diff --git a/mlir/include/mlir/Analysis/Presburger/Fraction.h b/mlir/include/mlir/Analysis/Presburger/Fraction.h
index afcbed84c66bc3..e95056ae5fc961 100644
--- a/mlir/include/mlir/Analysis/Presburger/Fraction.h
+++ b/mlir/include/mlir/Analysis/Presburger/Fraction.h
@@ -101,6 +101,8 @@ inline bool operator>=(const Fraction &x, const Fraction &y) {
return compare(x, y) >= 0;
}
+inline Fraction abs(const Fraction &f) { return Fraction(abs(f.num), f.den); }
+
inline Fraction reduce(const Fraction &f) {
if (f == Fraction(0))
return Fraction(0, 1);
diff --git a/mlir/include/mlir/Analysis/Presburger/Matrix.h b/mlir/include/mlir/Analysis/Presburger/Matrix.h
index 89fad85c0c3374..fca3164bda6278 100644
--- a/mlir/include/mlir/Analysis/Presburger/Matrix.h
+++ b/mlir/include/mlir/Analysis/Presburger/Matrix.h
@@ -270,6 +270,10 @@ class FracMatrix : public Matrix<Fraction> {
// of the rows of matrix (cubic time).
// The rows of the matrix must be linearly independent.
FracMatrix gramSchmidt() const;
+
+ // Run LLL basis reduction on the matrix, modifying it in-place.
+ // The parameter is delta.
+ void LLL(Fraction delta);
};
} // namespace presburger
diff --git a/mlir/lib/Analysis/Presburger/Matrix.cpp b/mlir/lib/Analysis/Presburger/Matrix.cpp
index 1fcc6d072b44b7..ae04c9f9149a5a 100644
--- a/mlir/lib/Analysis/Presburger/Matrix.cpp
+++ b/mlir/lib/Analysis/Presburger/Matrix.cpp
@@ -576,4 +576,39 @@ FracMatrix FracMatrix::gramSchmidt() const {
}
}
return orth;
-}
\ No newline at end of file
+}
+
+void FracMatrix::LLL(Fraction delta) {
+ MPInt nearest;
+ Fraction mu;
+
+ // `bStar` holds the Gram-Schmidt orthogonalisation
+ // of the matrix at all times. It is recomputed every
+ // time the matrix is modified during the algorithm.
+ FracMatrix bStar = gramSchmidt();
+
+ unsigned k = 1;
+ while (k < getNumRows()) {
+ for (unsigned j = k - 1; j < k; j--) {
+ mu = dotProduct(getRow(k), bStar.getRow(j)) /
+ dotProduct(bStar.getRow(j), bStar.getRow(j));
+ if (abs(mu) > Fraction(1, 2)) {
+ nearest = floor(mu + Fraction(1, 2));
+ addToRow(k, getRow(j), -Fraction(nearest, 1));
+ bStar = gramSchmidt();
+ }
+ }
+ mu = dotProduct(getRow(k), bStar.getRow(k - 1)) /
+ dotProduct(bStar.getRow(k - 1), bStar.getRow(k - 1));
+ if (dotProduct(bStar.getRow(k), bStar.getRow(k)) >
+ (delta - mu * mu) *
+ dotProduct(bStar.getRow(k - 1), bStar.getRow(k - 1)))
+ k += 1;
+ else {
+ swapRows(k, k - 1);
+ bStar = gramSchmidt();
+ k = k > 1 ? k - 1 : 1;
+ }
+ }
+ return;
+}
diff --git a/mlir/unittests/Analysis/Presburger/MatrixTest.cpp b/mlir/unittests/Analysis/Presburger/MatrixTest.cpp
index 508d4fa369c14c..4d7d0531e5ee84 100644
--- a/mlir/unittests/Analysis/Presburger/MatrixTest.cpp
+++ b/mlir/unittests/Analysis/Presburger/MatrixTest.cpp
@@ -377,4 +377,51 @@ TEST(MatrixTest, gramSchmidt) {
gs = mat.gramSchmidt();
EXPECT_EQ_FRAC_MATRIX(gs, FracMatrix::identity(10));
-}
\ No newline at end of file
+}
+
+TEST(MatrixTest, LLL) {
+ FracMatrix mat =
+ makeFracMatrix(3, 3,
+ {{Fraction(1, 1), Fraction(1, 1), Fraction(1, 1)},
+ {Fraction(-1, 1), Fraction(0, 1), Fraction(2, 1)},
+ {Fraction(3, 1), Fraction(5, 1), Fraction(6, 1)}});
+ mat.LLL(Fraction(3, 4));
+
+ FracMatrix LLL =
+ makeFracMatrix(3, 3,
+ {{Fraction(0, 1), Fraction(1, 1), Fraction(0, 1)},
+ {Fraction(1, 1), Fraction(0, 1), Fraction(1, 1)},
+ {Fraction(-1, 1), Fraction(0, 1), Fraction(2, 1)}});
+
+ for (unsigned row = 0; row < 3; row++)
+ for (unsigned col = 0; col < 3; col++)
+ EXPECT_EQ(mat(row, col), LLL(row, col));
+
+ mat = makeFracMatrix(
+ 2, 2,
+ {{Fraction(12, 1), Fraction(2, 1)}, {Fraction(13, 1), Fraction(4, 1)}});
+ LLL = makeFracMatrix(
+ 2, 2,
+ {{Fraction(1, 1), Fraction(2, 1)}, {Fraction(9, 1), Fraction(-4, 1)}});
+
+ mat.LLL(Fraction(3, 4));
+
+ for (unsigned row = 0; row < 2; row++)
+ for (unsigned col = 0; col < 2; col++)
+ EXPECT_EQ(mat(row, col), LLL(row, col));
+
+ mat = makeFracMatrix(3, 3,
+ {{Fraction(1, 1), Fraction(0, 1), Fraction(2, 1)},
+ {Fraction(0, 1), Fraction(1, 3), -Fraction(5, 3)},
+ {Fraction(0, 1), Fraction(0, 1), Fraction(1, 1)}});
+ LLL = makeFracMatrix(3, 3,
+ {{Fraction(0, 1), Fraction(1, 3), Fraction(1, 3)},
+ {Fraction(0, 1), Fraction(1, 3), -Fraction(2, 3)},
+ {Fraction(1, 1), Fraction(0, 1), Fraction(0, 1)}});
+
+ mat.LLL(Fraction(3, 4));
+
+ for (unsigned row = 0; row < 3; row++)
+ for (unsigned col = 0; col < 3; col++)
+ EXPECT_EQ(mat(row, col), LLL(row, col));
+}
``````````
</details>
https://github.com/llvm/llvm-project/pull/75565
More information about the Mlir-commits
mailing list