Skip to content

Commit

Permalink
[LinearAlgebra] CompressedRowSparseMatrixConstraint: make consistent …
Browse files Browse the repository at this point in the history
…the serialization/deserialization process (sofa-framework#5087)

* fix serialization (in/out)

* add test

* restore the previous print into a function

* add qt widget specialization for CRSC
  • Loading branch information
fredroy authored Dec 4, 2024
1 parent 71076be commit e513c48
Show file tree
Hide file tree
Showing 4 changed files with 167 additions and 22 deletions.
9 changes: 9 additions & 0 deletions Sofa/GUI/Qt/src/sofa/gui/qt/SimpleDataWidget.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,15 @@ Creator<DataWidgetFactory, SimpleDataWidget< Mat<6,6,double> > > DWClass_Mat66d(
Creator<DataWidgetFactory, SimpleDataWidget< sofa::core::objectmodel::TagSet > > DWClass_TagSet("default",true);


Creator<DataWidgetFactory, SimpleDataWidget< sofa::linearalgebra::CompressedRowSparseMatrixConstraint<Vec<1,float>> > > DWClass_CRSCVec1f("default",true);
Creator<DataWidgetFactory, SimpleDataWidget< sofa::linearalgebra::CompressedRowSparseMatrixConstraint<Vec<2,float>> > > DWClass_CRSCVec2f("default",true);
Creator<DataWidgetFactory, SimpleDataWidget< sofa::linearalgebra::CompressedRowSparseMatrixConstraint<Vec<3,float>> > > DWClass_CRSCVec3f("default",true);
Creator<DataWidgetFactory, SimpleDataWidget< sofa::linearalgebra::CompressedRowSparseMatrixConstraint<Vec<6,float>> > > DWClass_CRSCVec6f("default",true);
Creator<DataWidgetFactory, SimpleDataWidget< sofa::linearalgebra::CompressedRowSparseMatrixConstraint<Vec<1,double>> > > DWClass_CRSCVec1d("default",true);
Creator<DataWidgetFactory, SimpleDataWidget< sofa::linearalgebra::CompressedRowSparseMatrixConstraint<Vec<2,double>> > > DWClass_CRSCVec2d("default",true);
Creator<DataWidgetFactory, SimpleDataWidget< sofa::linearalgebra::CompressedRowSparseMatrixConstraint<Vec<3,double>> > > DWClass_CRSCVec3d("default",true);
Creator<DataWidgetFactory, SimpleDataWidget< sofa::linearalgebra::CompressedRowSparseMatrixConstraint<Vec<6,double>> > > DWClass_CRSCVec6d("default",true);

////////////////////////////////////////////////////////////////
/// OptionsGroup support
////////////////////////////////////////////////////////////////
Expand Down
40 changes: 40 additions & 0 deletions Sofa/GUI/Qt/src/sofa/gui/qt/SimpleDataWidget.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
//#include <sofa/defaulttype/RigidTypes.h>
#include <sofa/type/fixed_array.h>
#include <sofa/core/topology/Topology.h>
#include <sofa/linearalgebra/CompressedRowSparseMatrixConstraint.h>
#include "WDoubleLineEdit.h"
#include <climits>

Expand Down Expand Up @@ -932,6 +933,45 @@ template<sofa::Size L, sofa::Size C, class T>
class data_widget_container < sofa::type::Mat<L, C, T> > : public fixed_grid_data_widget_container < sofa::type::Mat<L, C, T> >
{};

////////////////////////////////////////////////////////////////
/// sofa::linearalgebra::CompressedRowSparseMatrixConstraint support
////////////////////////////////////////////////////////////////

template<typename TBlock>
class data_widget_trait <sofa::linearalgebra::CompressedRowSparseMatrixConstraint<TBlock>>
{
public:
typedef sofa::linearalgebra::CompressedRowSparseMatrixConstraint<TBlock> data_type;
typedef QLineEdit Widget;
static Widget* create(QWidget* parent, const data_type& /*d*/)
{
Widget* w = new Widget(parent);
w->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Minimum);
return w;
}
static void readFromData(Widget* w, const data_type& d)
{
std::ostringstream oss;
d.prettyPrint(oss);
w->setText(QString(oss.str().c_str()));
}
static void writeToData(Widget* /* w */, const data_type& /* d */)
{
// not supported by this type
// TODO: CompressedRowSparseMatrixConstraint needs a parser for its pretty output
}
static void setReadOnly(Widget* w, bool readOnly)
{
w->setEnabled(!readOnly);
w->setReadOnly(readOnly);
}
static void connectChanged(Widget* w, DataWidget* datawidget)
{
datawidget->connect(w, SIGNAL( textChanged(const QString&) ), datawidget, SLOT(setWidgetDirty()) );
}

};

////////////////////////////////////////////////////////////////
/// OptionsGroup support
////////////////////////////////////////////////////////////////
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -620,31 +620,25 @@ class CompressedRowSparseMatrixConstraint : public sofa::linearalgebra::Compress
/// write to an output stream
inline friend std::ostream& operator << ( std::ostream& out, const CompressedRowSparseMatrixConstraint<TBlock, Policy>& sc)
{
for (RowConstIterator rowIt = sc.begin(); rowIt != sc.end(); ++rowIt)
std::ostringstream ossrow;
std::size_t nbLines = 0;
for (RowConstIterator rowIt = sc.begin(); rowIt != sc.end(); ++rowIt)
{
out << "Constraint ID : ";
out << rowIt.index();
const auto colToString = [](const ColConstIterator& colIt)
{
std::stringstream ss;
ss << "dof ID : " << colIt.index() << " value : " << colIt.val();
return ss.str();
};
ossrow << rowIt.index() << " ";

ColConstIterator colIt = rowIt.begin();
const ColConstIterator colItEnd = rowIt.end();
if (colIt != colItEnd)
std::ostringstream ossline;
std::size_t n = 0;
for (ColConstIterator colIt = rowIt.begin(); colIt != rowIt.end(); ++colIt)
{
out << " " << colToString(colIt++);
while(colIt != colItEnd)
{
out << " " << colToString(colIt++);
}
ossline << colIt.index() << " " << colIt.val() << " ";
n++;
}

out << "\n";
ossrow << n << " " << ossline.str();
nbLines++ ;
}

out << nbLines << " " << ossrow.str();

return out;
}

Expand All @@ -653,16 +647,25 @@ class CompressedRowSparseMatrixConstraint : public sofa::linearalgebra::Compress
{
sc.clear();

unsigned int nbLines;
unsigned int c_id;
unsigned int c_number;
unsigned int c_dofIndex;
TBlock c_value;

while (!(in.rdstate() & std::istream::eofbit))
if (in.rdstate() & std::istream::eofbit)
{
return in;
}

in >> nbLines;

unsigned int currentNbLines = 0;
while (currentNbLines < nbLines && !(in.rdstate() & std::istream::eofbit))
{
in >> c_id;
in >> c_number;

auto c_it = sc.writeLine(c_id);

for (unsigned int i = 0; i < c_number; i++)
Expand All @@ -671,11 +674,44 @@ class CompressedRowSparseMatrixConstraint : public sofa::linearalgebra::Compress
in >> c_value;
c_it.addCol(c_dofIndex, c_value);
}
currentNbLines++;
}

assert(nbLines == currentNbLines);

sc.compress();

return in;
}

/// write into output stream (default is standard output)
void prettyPrint(std::ostream& out = std::cout) const
{
for (RowConstIterator rowIt = this->begin(); rowIt != this->end(); ++rowIt)
{
out << "Constraint ID : ";
out << rowIt.index();
const auto colToString = [](const ColConstIterator& colIt)
{
std::stringstream ss;
ss << "dof ID : " << colIt.index() << " value : " << colIt.val();
return ss.str();
};

ColConstIterator colIt = rowIt.begin();
const ColConstIterator colItEnd = rowIt.end();
if (colIt != colItEnd)
{
out << " " << colToString(colIt++);
while(colIt != colItEnd)
{
out << " " << colToString(colIt++);
}
}

out << "\n";
}
}

static const char* Name()
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -281,6 +281,51 @@ TYPED_TEST(SparseMatrixTest, CheckThatTheSizeOfASparseMatrixIsOneAfterTryingToWr
EXPECT_EQ(1u, matrix.size());
}


//////////////////////////////////////////////////
TYPED_TEST(SparseMatrixTest, CheckOutInSerialization)
{
typedef TypeParam Matrix;
Matrix outMatrix;
auto lineIndices = TestHelpers::Populate(outMatrix, 3u, 3u);
EXPECT_EQ(3u, outMatrix.size());

std::ostringstream oss;
oss << outMatrix;

Matrix inMatrix;
std::istringstream iss(oss.str());
iss >> inMatrix;

EXPECT_TRUE(!lineIndices.empty());

for (const auto& lineIndex : lineIndices)
{
auto inRowIt = inMatrix.readLine(lineIndex);
auto outRowIt = outMatrix.readLine(lineIndex);

EXPECT_TRUE(inRowIt == outRowIt);

if (inRowIt != inMatrix.end() && outRowIt != outMatrix.end())
{
auto inColItEnd = inRowIt.end();
auto outColItEnd = outRowIt.end();

auto inColIt = inRowIt.begin();
auto outColIt = outRowIt.begin();

for (;
inColIt != inColItEnd && outColIt != outColItEnd;
++inColIt, ++outColIt)
{
EXPECT_TRUE(inColIt.index() == outColIt.index());
EXPECT_TRUE(inColIt.val() == outColIt.val());
}
}
}

}

//////////////////////////////////////////////////
TYPED_TEST(SparseMatrixTest, CheckThatAMatrixIsConsideredEmptyAfterIsHasBeenCleared)
{
Expand Down Expand Up @@ -2121,14 +2166,29 @@ TEST(CompressedRowSparseMatrixConstraint, ostream)
std::stringstream ss;
ss << A;

static const std::string expectedOutput =
R"(4 0 2 1 0 0.360985 0 12 0.926981 0 0 2 1 9 0.451858 0 0 3 1 6 0.777417 0 0 4 3 5 0 0 0.474108 7 0 0.983937 0 9 0.238781 0 0 )";

EXPECT_EQ(ss.str(), expectedOutput);
}

TEST(CompressedRowSparseMatrixConstraint, prettyPrint)
{
sofa::linearalgebra::CompressedRowSparseMatrixConstraint<sofa::type::Vec3> A;

generateMatrix(A, 5, 15, 0.1, 7);

static const std::string expectedOutput =
R"(Constraint ID : 0 dof ID : 1 value : 0 0.360985 0 dof ID : 12 value : 0.926981 0 0
Constraint ID : 2 dof ID : 9 value : 0.451858 0 0
Constraint ID : 3 dof ID : 6 value : 0.777417 0 0
Constraint ID : 4 dof ID : 5 value : 0 0 0.474108 dof ID : 7 value : 0 0.983937 0 dof ID : 9 value : 0.238781 0 0
)";

std::ostringstream oss;
A.prettyPrint(oss);

EXPECT_EQ(ss.str(), expectedOutput);
EXPECT_EQ(oss.str(), expectedOutput);
}

} // namespace sofa

0 comments on commit e513c48

Please sign in to comment.