[mathicgb] 26/393: Added QuadMatrixBuilder for building F4 matrices along with tests of this class.
Doug Torrance
dtorrance-guest at moszumanska.debian.org
Fri Apr 3 15:58:26 UTC 2015
This is an automated email from the git hooks/post-receive script.
dtorrance-guest pushed a commit to branch upstream
in repository mathicgb.
commit a34360b0f6cc2e1386178ccd2fb91783a18a1cfd
Author: Bjarke Hammersholt Roune <bjarkehr.code at gmail.com>
Date: Tue Sep 25 22:23:22 2012 +0200
Added QuadMatrixBuilder for building F4 matrices along with tests of this class.
---
Makefile.am | 5 +-
src/mathicgb/QuadMatrixBuilder.cpp | 117 ++++++++++++++++++
src/mathicgb/QuadMatrixBuilder.hpp | 240 +++++++++++++++++++++++++++++++++++++
src/test/QuadMatrixBuilder.cpp | 122 +++++++++++++++++++
4 files changed, 482 insertions(+), 2 deletions(-)
diff --git a/Makefile.am b/Makefile.am
index 1cd973b..4c42627 100755
--- a/Makefile.am
+++ b/Makefile.am
@@ -54,7 +54,8 @@ libmathicgb_la_SOURCES = src/mathicgb/BjarkeGeobucket2.cpp \
src/mathicgb/stdinc.h src/mathicgb/TournamentReducer.cpp \
src/mathicgb/TournamentReducer.hpp src/mathicgb/SigSPairQueue.hpp \
src/mathicgb/SigSPairQueue.cpp src/mathicgb/SparseMatrix.hpp \
- src/mathicgb/SparseMatrix.cpp
+ src/mathicgb/SparseMatrix.cpp src/mathicgb/QuadMatrixBuilder.hpp \
+ src/mathicgb/QuadMatrixBuilder.cpp
# When making a distribution file, Automake knows to include all files
# that are necessary to build the project. EXTRA_DIST specifies files
@@ -84,4 +85,4 @@ test_LIBS=
unittest_SOURCES=src/test/FreeModuleOrderTest.cpp \
src/test/gtestInclude.cpp src/test/testMain.cpp src/test/gb-test.cpp \
src/test/ideals.cpp src/test/poly-test.cpp src/test/ideals.hpp \
- src/test/SparseMatrix.cpp
+ src/test/SparseMatrix.cpp src/test/QuadMatrixBuilder.cpp
diff --git a/src/mathicgb/QuadMatrixBuilder.cpp b/src/mathicgb/QuadMatrixBuilder.cpp
new file mode 100755
index 0000000..b7dc8d6
--- /dev/null
+++ b/src/mathicgb/QuadMatrixBuilder.cpp
@@ -0,0 +1,117 @@
+#include "stdinc.h"
+#include "QuadMatrixBuilder.hpp"
+
+#include <mathic.h>
+#include <sstream>
+
+namespace {
+ /// Creates a column and updates the associated data structures that
+ /// are passed in. Copies mono - ownership is not taken over. The
+ /// purpose of this function is to avoid code duplication. It is a
+ /// template in order to avoid referring to private types of
+ /// QuadMatrixBuilder.
+ template<class ToMono, class ToCol>
+ QuadMatrixBuilder::ColIndex createCol
+ (const_monomial mono,
+ SparseMatrix& top,
+ SparseMatrix& bottom,
+ ToMono& toMonomial,
+ ToCol& toCol,
+ const PolyRing& ring,
+ const bool left)
+ {
+ MATHICGB_ASSERT(top.colCount() == bottom.colCount());
+ MATHICGB_ASSERT(toMonomial.size() == bottom.colCount());
+ MATHICGB_ASSERT(toCol.find(mono) == toCol.end());
+
+ const QuadMatrixBuilder::ColIndex colCount = top.colCount();
+ if (colCount == std::numeric_limits<QuadMatrixBuilder::ColIndex>::max())
+ throw std::overflow_error("Too many columns in QuadMatrixBuilder");
+
+ toMonomial.reserve(toMonomial.size() + 1);
+ monomial copied = ring.allocMonomial();
+ ring.monomialCopy(mono, copied);
+ try {
+ toCol.insert(std::make_pair
+ (copied,
+ QuadMatrixBuilder::LeftRightColIndex(colCount, left)));
+ } catch (...) {
+ ring.freeMonomial(copied);
+ throw;
+ }
+ toMonomial.push_back(copied); // no throw due to reserve
+
+ top.ensureAtLeastThisManyColumns(colCount + 1);
+ bottom.ensureAtLeastThisManyColumns(colCount + 1);
+ return colCount;
+ }
+}
+
+QuadMatrixBuilder::ColIndex QuadMatrixBuilder::createColumnLeft
+(const_monomial monomialToBeCopied) {
+ return createCol
+ (monomialToBeCopied,
+ mTopLeft,
+ mBottomLeft,
+ mMonomialsLeft,
+ mMonomialToCol,
+ ring(),
+ true);
+ MATHICGB_ASSERT(mMonomialToCol.size() == leftColCount() + rightColCount());
+ MATHICGB_ASSERT
+ (findColumn(monomialToBeCopied).leftIndex() == leftColCount() - 1);
+}
+
+QuadMatrixBuilder::ColIndex QuadMatrixBuilder::createColumnRight
+(const_monomial monomialToBeCopied) {
+ return createCol
+ (monomialToBeCopied,
+ mTopRight,
+ mBottomRight,
+ mMonomialsRight,
+ mMonomialToCol,
+ ring(),
+ false);
+ MATHICGB_ASSERT(mMonomialToCol.size() == leftColCount() + rightColCount());
+ MATHICGB_ASSERT
+ (findColumn(monomialToBeCopied).rightIndex() == rightColCount() - 1);
+}
+
+void QuadMatrixBuilder::print(std::ostream& out) const {
+ mathic::ColumnPrinter printer;
+ printer.addColumn(true, "", "");
+ printer.addColumn(true, " | ", "");
+
+ // column monomials
+ out << "Left columns:";
+ for (ColIndex leftCol = 0; leftCol < leftColCount(); ++leftCol) {
+ out << ' ';
+ ring().monomialDisplay(out, monomialOfLeftCol(leftCol), false, true);
+ }
+
+ out << "\nRight columns:";
+ for (ColIndex rightCol = 0; rightCol < rightColCount(); ++rightCol) {
+ out << ' ';
+ ring().monomialDisplay(out, monomialOfRightCol(rightCol), false, true);
+ }
+ out << '\n';
+
+ // left side
+ topLeft().print(printer[0]);
+ printer[0] << '\n';
+ bottomLeft().print(printer[0]);
+
+ // right side
+ topRight().print(printer[1]);
+ printer[1] << '\n';
+ bottomRight().print(printer[1]);
+
+ out << printer;
+}
+
+// String representation intended for debugging.
+std::string QuadMatrixBuilder::toString() const {
+ std::ostringstream out;
+ print(out);
+ return out.str();
+}
diff --git a/src/mathicgb/QuadMatrixBuilder.hpp b/src/mathicgb/QuadMatrixBuilder.hpp
new file mode 100755
index 0000000..18adbaf
--- /dev/null
+++ b/src/mathicgb/QuadMatrixBuilder.hpp
@@ -0,0 +1,240 @@
+#ifndef MATHICGB_QUAD_MATRIX_BUILDER_GUARD
+#define MATHICGB_QUAD_MATRIX_BUILDER_GUARD
+
+#include "SparseMatrix.hpp"
+#include "PolyRing.hpp"
+#include <vector>
+#include <map>
+#include <string>
+#include <ostream>
+
+/** Builder for a set of 4 sub-matrices that fit together and where
+ columns have an associated monomial.
+
+ The sub-matrices are top left, top right, bottom left and bottom
+ right. The interface ensures that these fit together in terms of
+ number of rows and columns so that they could form one bigger
+ matrix.
+
+ Columns have an associated monomial and it is possible to search for
+ the column with a given monomial.
+
+ This matrix is intended to be used while constructing matrices to
+ reduce polynomials using the F4 algorithm of Faugere. */
+class QuadMatrixBuilder {
+ public:
+ typedef SparseMatrix::RowIndex RowIndex;
+ typedef SparseMatrix::ColIndex ColIndex;
+ typedef SparseMatrix::Scalar Scalar;
+
+ QuadMatrixBuilder(const PolyRing& ring):
+ mMonomialToCol(ArbitraryOrdering(ring)) {}
+
+ /// The index of a column that can be either on the left or the
+ /// right side. The largest representable ColIndex is an invalid
+ /// index. This is the default value. The only allowed method to
+ /// call for an invalid index is valid().
+ class LeftRightColIndex {
+ public:
+ LeftRightColIndex():
+ mRawIndex(std::numeric_limits<ColIndex>::max()), mLeft(false) {}
+ LeftRightColIndex(ColIndex index, bool left):
+ mRawIndex(index), mLeft(left) {
+ }
+
+ ColIndex leftIndex() const {
+ MATHICGB_ASSERT(left());
+ return index();
+ }
+
+ ColIndex rightIndex() const {
+ MATHICGB_ASSERT(right());
+ return index();
+ }
+
+ /// Use leftIndex() or rightIndex() instead if you know what side
+ /// you are expecting, as check the side in assert mode.
+ ColIndex index() const {
+ MATHICGB_ASSERT(valid());
+ return mRawIndex;
+ }
+
+ bool left() const {
+ MATHICGB_ASSERT(valid());
+ return mLeft;
+ }
+
+ bool right() const {
+ MATHICGB_ASSERT(valid());
+ return !left();
+ }
+
+ bool valid() const {
+ return mRawIndex != std::numeric_limits<ColIndex>::max();
+ }
+
+ private:
+ ColIndex mRawIndex;
+ bool mLeft;
+ };
+
+ // **** Appending entries to top matrices.
+ // Same interface as SparseMatrix except with two matrices and here
+ // you have to create columns before you can use them.
+
+ void appendEntryTopLeft(ColIndex col, Scalar scalar) {
+ MATHICGB_ASSERT(col < leftColCount());
+ mTopLeft.appendEntry(col, scalar);
+ }
+
+ void appendEntryTopRight(ColIndex col, Scalar scalar) {
+ MATHICGB_ASSERT(col < rightColCount());
+ mTopRight.appendEntry(col, scalar);
+ }
+
+ void appendEntryTop(LeftRightColIndex col, Scalar scalar) {
+ MATHICGB_ASSERT(col.valid());
+ if (col.left())
+ appendEntryTopLeft(col.leftIndex(), scalar);
+ else
+ appendEntryTopRight(col.rightIndex(), scalar);
+ }
+
+ void rowDoneTopLeftAndRight() {
+ mTopLeft.rowDone();
+ mTopRight.rowDone();
+ }
+
+ // **** Appending entries to bottom matrices
+ // Same interface as SparseMatrix except with two matrices and here
+ // you have to create columns before you can use them.
+
+ void appendEntryBottomLeft(ColIndex col, Scalar scalar) {
+ MATHICGB_ASSERT(col < leftColCount());
+ mBottomLeft.appendEntry(col, scalar);
+ }
+
+ void appendEntryBottomRight(ColIndex col, Scalar scalar) {
+ MATHICGB_ASSERT(col < rightColCount());
+ mBottomRight.appendEntry(col, scalar);
+ }
+
+ void appendEntryBottom(LeftRightColIndex col, Scalar scalar) {
+ MATHICGB_ASSERT(col.valid());
+ if (col.left())
+ appendEntryBottomLeft(col.leftIndex(), scalar);
+ else
+ appendEntryBottomRight(col.rightIndex(), scalar);
+ }
+
+ void rowDoneBottomLeftAndRight() {
+ mBottomLeft.rowDone();
+ mBottomRight.rowDone();
+ }
+
+ // *** Creating columns
+ // Unlike the interface for SparseMatrix, here you have to create
+ // columns before you can append entries in those columns. All
+ // passed in monomials are copied so that ownership of the memory is
+ // not taken over.
+
+ /** Creates a new column associated to the monomial
+ monomialToBeCopied to the left matrices. There must not already
+ exist a column for this monomial on the left or on the right. */
+ ColIndex createColumnLeft(const_monomial monomialToBeCopied);
+
+ /** Creates a new column associated to the monomial monomialToBeCopied
+ to the right matrices. There must not already exist a column for
+ this monomial on the left or on the right. */
+ ColIndex createColumnRight(const_monomial monomialToBeCopied);
+
+
+ // *** Querying columns
+
+ // Returns a column for the findThis monomial. Searches on both the
+ // left and right side. Returns an invalid index if no such column
+ // exists.
+ LeftRightColIndex findColumn(const_monomial findThis) const {
+ MonomialToColType::const_iterator it = mMonomialToCol.find(findThis);
+ if (it != mMonomialToCol.end())
+ return it->second;
+ else
+ return LeftRightColIndex();
+ }
+
+ const_monomial monomialOfLeftCol(ColIndex col) const {
+ MATHICGB_ASSERT(col < mMonomialsLeft.size());
+ return mMonomialsLeft[col];
+ }
+
+ const_monomial monomialOfRightCol(ColIndex col) const {
+ MATHICGB_ASSERT(col < mMonomialsRight.size());
+ return mMonomialsRight[col];
+ }
+
+ const_monomial monomialOfCol(LeftRightColIndex col) const {
+ MATHICGB_ASSERT(col.valid());
+ if (col.left())
+ return monomialOfLeftCol(col.leftIndex());
+ else
+ return monomialOfRightCol(col.rightIndex());
+ }
+
+ const SparseMatrix& topLeft() const {return mTopLeft;}
+ const SparseMatrix& topRight() const {return mTopRight;}
+ const SparseMatrix& bottomLeft() const {return mBottomLeft;}
+ const SparseMatrix& bottomRight() const {return mBottomRight;}
+
+ // String representation intended for debugging.
+ void print(std::ostream& out) const;
+
+ // String representation intended for debugging.
+ std::string toString() const;
+
+ const PolyRing& ring() const {
+ // The key comparer object already has a ring reference - we might
+ // as well use that one instead of adding another reference to
+ // this object.
+ return mMonomialToCol.key_comp().ring();
+ }
+
+ ColIndex leftColCount() const {
+ MATHICGB_ASSERT(topLeft().colCount() == bottomLeft().colCount());
+ return topLeft().colCount();
+ }
+
+ ColIndex rightColCount() const {
+ MATHICGB_ASSERT(topRight().colCount() == bottomRight().colCount());
+ return topRight().colCount();
+ }
+
+private:
+ // Store the monomials for each left and right column respectivewy.
+ typedef std::vector<monomial> MonomialsType;
+ MonomialsType mMonomialsLeft;
+ MonomialsType mMonomialsRight;
+
+ /// We need SOME ordering to make std::map work.
+ class ArbitraryOrdering {
+ public:
+ ArbitraryOrdering(const PolyRing& ring): mRing(ring) {}
+ bool operator()(const_monomial a, const_monomial b) const {
+ return mRing.monomialLT(a, b);
+ }
+ const PolyRing& ring() const {return mRing;}
+
+ private:
+ const PolyRing& mRing;
+ };
+ /// Allows fast determination of which column has a given monomial.
+ typedef std::map<const_monomial, LeftRightColIndex, ArbitraryOrdering>
+ MonomialToColType;
+ MonomialToColType mMonomialToCol;
+
+ SparseMatrix mTopLeft;
+ SparseMatrix mTopRight;
+ SparseMatrix mBottomLeft;
+ SparseMatrix mBottomRight;
+};
+
+#endif
diff --git a/src/test/QuadMatrixBuilder.cpp b/src/test/QuadMatrixBuilder.cpp
new file mode 100755
index 0000000..c2dede2
--- /dev/null
+++ b/src/test/QuadMatrixBuilder.cpp
@@ -0,0 +1,122 @@
+#include "mathicgb/stdinc.h"
+
+#include "mathicgb/Poly.hpp"
+#include "mathicgb/PolyRing.hpp"
+#include "mathicgb/QuadMatrixBuilder.hpp"
+#include "mathicgb/io-util.hpp"
+#include <gtest/gtest.h>
+
+namespace {
+ void createColumns(const char* left, const char* right, QuadMatrixBuilder& b)
+ {
+ const PolyRing& ring = b.ring();
+ {
+ Poly p(&b.ring());
+ std::istringstream in(left);
+ p.parse(in);
+ size_t colCount = 0;
+ for (Poly::iterator it = p.begin(); it != p.end(); ++it) {
+ QuadMatrixBuilder::ColIndex col = b.createColumnLeft(it.getMonomial());
+ ASSERT_EQ(colCount, col);
+ ++colCount;
+ // not equal as pointers
+ ASSERT_TRUE(it.getMonomial().unsafeGetRepresentation() !=
+ b.monomialOfLeftCol(col).unsafeGetRepresentation());
+ ASSERT_TRUE // equal as values
+ (b.ring().monomialEQ(it.getMonomial(), b.monomialOfLeftCol(col)));
+ }
+ ASSERT_EQ(colCount, b.leftColCount());
+ }
+ {
+ Poly p(&b.ring());
+ std::istringstream in(right);
+ p.parse(in);
+ size_t colCount = 0;
+ for (Poly::iterator it = p.begin(); it != p.end(); ++it) {
+ QuadMatrixBuilder::ColIndex col = b.createColumnRight(it.getMonomial());
+ ASSERT_EQ(colCount, col);
+ ++colCount;
+ // not equal as pointers
+ ASSERT_TRUE(it.getMonomial().unsafeGetRepresentation() !=
+ b.monomialOfRightCol(col).unsafeGetRepresentation());
+ ASSERT_TRUE // equal as values
+ (b.ring().monomialEQ(it.getMonomial(), b.monomialOfRightCol(col)));
+ }
+ ASSERT_EQ(colCount, b.rightColCount());
+ }
+ }
+}
+
+TEST(QuadMatrixBuilder, Empty) {
+ PolyRing ring(2, 0, 0);
+ QuadMatrixBuilder b(ring); // test a builder with no rows and no columns
+ const char* matrixStr =
+ "Left columns:\n"
+ "Right columns:\n"
+ "matrix with no rows | matrix with no rows\n"
+ " | \n"
+ "matrix with no rows | matrix with no rows\n";
+ ASSERT_EQ(matrixStr, b.toString());
+}
+
+TEST(QuadMatrixBuilder, Construction) {
+ std::auto_ptr<PolyRing> ring(ringFromString("32003 6 1\n1 1 1 1 1 1"));
+ QuadMatrixBuilder b(*ring);
+ createColumns("a<1>+<0>", "b<0>+c<0>+bc<0>", b);
+
+ // top row: nothing, nothing
+ b.rowDoneTopLeftAndRight();
+
+ // top row: 0#1 1#2, 2#3
+ b.appendEntryTopLeft(0, 1);
+ b.appendEntryTopLeft(1, 2);
+ b.appendEntryTopRight(2, 3);
+ b.rowDoneTopLeftAndRight();
+
+ // bottom row: 1#4, nothing
+ b.appendEntryBottomLeft(1,4);
+ b.rowDoneBottomLeftAndRight();
+
+ // bottom row: nothing, 0#5
+ b.appendEntryBottomRight(0,5);
+ b.rowDoneBottomLeftAndRight();
+
+ // bottom row: nothing, nothing
+ b.rowDoneBottomLeftAndRight();
+
+ const char* matrixStr =
+ "Left columns: a 1\n"
+ "Right columns: b c bc\n"
+ "0: | 0: \n"
+ "1: 0#1 1#2 | 1: 2#3\n"
+ " | \n"
+ "0: 1#4 | 0: \n"
+ "1: | 1: 0#5\n"
+ "2: | 2: \n";
+ ASSERT_EQ(matrixStr, b.toString());
+}
+
+TEST(QuadMatrixBuilder, ColumnQuery) {
+ std::auto_ptr<PolyRing> ring(ringFromString("32003 6 1\n1 1 1 1 1 1"));
+ QuadMatrixBuilder b(*ring);
+ createColumns("a<1>+<0>", "b<0>+c<0>+bc<0>", b);
+
+ Poly p(&b.ring());
+ // coefficient 1X=left, 2X=right, 30=not there, % 10 = column index
+ std::istringstream in
+ ("10a<1>+11<0>+20b<0>+21c<0>+22bc<0>+30ab<0>+30e<0>+10a<1>");
+ p.parse(in);
+ for (Poly::iterator it = p.begin(); it != p.end(); ++it) {
+ QuadMatrixBuilder::LeftRightColIndex col = b.findColumn(it.getMonomial());
+ if (it.getCoefficient() / 10 == 3)
+ ASSERT_FALSE(col.valid());
+ else {
+ ASSERT_TRUE(col.valid());
+ ASSERT_EQ(it.getCoefficient() % 10, col.index());
+ if (it.getCoefficient() / 10 == 2)
+ ASSERT_TRUE(col.right());
+ else
+ ASSERT_TRUE(col.left());
+ }
+ }
+}
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/debian-science/packages/mathicgb.git
More information about the debian-science-commits
mailing list