-
Notifications
You must be signed in to change notification settings - Fork 5
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Serializable LDLT Decomposition. #21
Conversation
the lower triangular portion of a cholesky.
and LDLT decomposition.
d4c7dee
to
fe33d34
Compare
57e18e0
to
e3aa94f
Compare
e3aa94f
to
ec0471b
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks great!
/* | ||
* The subsequent save/load methods catch the serialization methods | ||
* for arbitrary Eigen::Matrix* types. The general idea is that each | ||
* row is saved as a Eigen::Vector. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How was it done before?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It was the same idea, but with explict use of VectorXd
. Now it's via template specialization with _Cols=1
.
albatross/cereal/eigen.h
Outdated
size_type rows; | ||
archive(cereal::make_size_tag(rows)); | ||
/* | ||
* In order to determine the size of a matrix, we have to first determine |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would it be easier to serialize the dimensions instead of needing to scan through?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah we could. There's a bit of a trick going on with cereal here. By adding a SizeTag
(via make_size_tag
) cereal
will just serialize a list and upon loading it'll determine the size tag from the length of the data. Without this it'll serialize as a map ({'value0': 0, 'value1': 1, ...}
) which is clearly not an efficient storage technique. What I could do is store redundant information. Ie, store a SizeTag and a shape. Think that's better?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
good point, I'm fine with whichever you think is easiest.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
alright, I changed it around so the rows and cols are stored explicitly. Shouldn't add much overhead in storage and makes the code easier to read (I think).
albatross/eigen/serializable_ldlt.h
Outdated
storage_size -= 2; | ||
// We assume the matrix is square and compute the number of rows from the | ||
// storage size. | ||
double drows = (std::sqrt(static_cast<double>(storage_size * 8 + 1)) - 1) / 2; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we name these numbers so it's clearer what's going on?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
|
||
SerializableLDLT(const LDLT<MatrixXd, Lower> &ldlt) | ||
// Can we get around copying here? | ||
: LDLT<MatrixXd, Lower>(ldlt){}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If this stores a unique pointer we could move
it in which would save the copy?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If I understand correct, the problem with that is that it would require changing the way Eigen::LDLT
works. As it stands all the storage is done in the base class. We might be able to do something like instantiate an empty Eigen::LDLT
then point the internal members to pointers that are passed in ... but that feels wrong.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah probably not worth it.
albatross/eigen/serializable_ldlt.h
Outdated
for (Eigen::Index i = 0; i < n; i++) { | ||
const Eigen::VectorXd col_i = | ||
inverse_cholesky.col(i).cwiseProduct(sqrt_diag); | ||
; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: extra semicolon
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nice catch
albatross/eigen/serializable_ldlt.h
Outdated
this->matrixL().solveInPlace(inverse_cholesky); | ||
|
||
Eigen::VectorXd sqrt_diag = this->vectorD(); | ||
for (Eigen::Index i = 0; i < n; i++) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: You could maybe use the Eigen::Array
functions here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah yeah interesting. Despite the appearance it seems like x.array().sqrt().matrix()
doesn't add any runtime overhead ?!?
* Store rows/cols explicitly for Matrix serialization. * Clarifications.
54853f6
to
b93b5c6
Compare
Adds an extention of Eigen's LDLT which is serializable and only serializes the lower triangular portion.
Changes include:
Matrix3d
andMatrixXd
are now handled in a single case which also allows for different internal types.SerializableLDLT
class which wrapsLDLT<MatrixXd>
.SerilizableLDLT
inGaussianProcessFit
.test_serilalize
to test more than just the models.