Git Product home page Git Product logo

Comments (31)

jml1795 avatar jml1795 commented on June 2, 2024 2

Things sound promising for the numerics proposals. I have followed 1385 from the sidelines for a while and will read the traits section a bit closer.

Regarding the question about storing different types in one vector/matrix, I am not aware of any LA library that does this

Me neither. Not sure it makes sense to explore deeply or if there is a better place for the question (is this a units question, a LA question, a numerics question?), but the problem is frequently encountered in many fields, particularly in tracking and perception systems.

A simple example could be a state vector from a Kalman filter with position and velocity state elements, possibly units::si::length<units::si::metre> and units::si::velocity<units::si::metre_per_second>. What would the syntax for declaring such a thing be, if possible? I've thought about it in the past as something like a (hopefully contiguous) tuple with the common LA operations defined on it.

from mp-units.

dwith-ts avatar dwith-ts commented on June 2, 2024 1

FYI: I am going to present most of my submitted CppCon talk at MUC++ next week https://www.meetup.com/de-DE/MUCplusplus/events/279334186/ , you can join after signing up. Hope to see a few of you there!

from mp-units.

mpusz avatar mpusz commented on June 2, 2024

Hi, I do not have much experience with Eigen but I can imagine 2 approaches here:

  1. quantity behaves like a numeric type so it can be easily used in other libraries as a vector of quantities.
  2. quantity takes Rep as a template parameter and maybe it could be some vector representation there.

I asked @hatcat if he could take a look at it. Maybe we should cooperate while working on units and LA libraries...

from mp-units.

hatcat avatar hatcat commented on June 2, 2024

Sorry about the delay. I have an insane three weeks coming up (C++ Russia in St Petersburg, WG21 in Belfast, Meeting C++ in Berlin).

Looking through the quantity class I see a lot of LA-like stuff going on (although I am confused by operator/). I think both approaches are appropriate: would you like to schedule a telecon to refine the discussion about which would be more appropriate under which conditions?

from mp-units.

mpusz avatar mpusz commented on June 2, 2024

As it is only 2 weeks to Belfast now, maybe we should meet there and discuss possible approaches here?

from mp-units.

mpusz avatar mpusz commented on June 2, 2024

I met with linear algebra folks in Belfast and the outcome is that the current LA proposal will work great with units library :-)

The only thing missing in LA is matrix_cast<To>(From) and an extension point for casting which will be called by it and will allow calling units::quantity_cast<To>(from) for each element of the matrix.

We agreed that we will provide examples of how both libraries can cooperate with each other.

from mp-units.

rconde01 avatar rconde01 commented on June 2, 2024

Great to hear. I'm very interested in seeing some examples. Some thoughts I have at the moment:

  • IIRC the LA proposal is about the base operation implementation. It would be good to know it also works for Expression-Template layers (e.g. Eigen, Blaze) which presumably could layer over that to avoid temporaries. I have no particular reason to think it wouldn't work in this context, but I appreciate the possibility that there might be a blocker there.
  • did your discussions include mixed units or only uniform units?
  • maybe it's straightforward, but i wonder about unit erasing operations like diagonailization
  • I suppose something like a rotation would be a unitless transformation?

Thanks for your work!

from mp-units.

dwith-ts avatar dwith-ts commented on June 2, 2024

@rconde01 : A rotation is a linear transformation between vector spaces and as such is very similar to a jacobian matrix (actually the jacobian of an isometry transformation is the rotation matrix).
=> rotations have unit-less entries

from mp-units.

dwith-ts avatar dwith-ts commented on June 2, 2024

Regarding the idea to put physical units inside a LA library:
This is a godd idea, but I presume that this can break pretty easily because all matrix operations would need to be supported.

This might be easy (if the linalg library is designed very specifically for this) for something like the dot product of 2 vectors where the return type is just decltype(vecA(0) * vecB(0)).

If you have matrices, there are very few matrices where you can get along by just specifying one element unit. A covariance matrix with unit [m^2] for example is something completely different than a Jacobian matrix with unit [m^2] and the allowed operations are also different for a covariance vs. a jacobian.

@rconde01 's question with a rotation is again another level where you would ideally also need support for specifying coordinate systems, not only for si-units.

Furthermore, the distinction between points and displacement vector is important: for example, a position vector can only be transformed with an isometry (rotation + translation) whereas a displacement vector can only be transformed with a rotation (no translation occurs).

To summarize, IMHO it is very valuable to represent units in linalg vectors and matrices, but this needs a unified treatment to also support non-uniform units in vectors and matrices and is best done by an additional layer on top of a LA library that has a user-interface which uses units but internally uses plain scalar vectors and matrices from any linalg library.

This also makes the LA core code easier on the compilers, a library like e.g. Eigen already contains lots of templates.

from mp-units.

kwikius avatar kwikius commented on June 2, 2024

Here FWIW is an example of a matrix multiply with physical quantities in my library

https://github.com/kwikius/quan-trunk/blob/master/quan_matters/examples/fusion/kalman1.cpp
(The matrix is essentially a tuple and, being a tuple, the compiler must precompute the type of the resulting matrix :
https://github.com/kwikius/quan-trunk/blob/master/quan/fun/make_matrix_mux_result.hpp#L140

I have done multiplication on 4,4 x 4,4 matrices and have tried larger matrices but compile time got very long and large amounts of memory where used by the compiler as the matrices got bigger

I also experimented with a "static value" which was designed as a matrix element to optimise out operations on constants by turning them into different types
https://github.com/kwikius/quan-trunk/tree/master/quan/fusion/static_value

An example optimisation is static_value<T1,0> * runtime_x -> static_value<decltype(T1{}*runtime_x),0> which is a nop at runtime and will be computed in the matrix_mux_result metafunction above.

Also compiletime /constexpr operations on such entities e.g inner_product
https://github.com/kwikius/quan-trunk/blob/master/quan_matters/test/fusion/inner_product.cpp

I found that compilation was too slow for most real uses ( may be good for rotation matrices etc), but it was fun getting it working

from mp-units.

kwikius avatar kwikius commented on June 2, 2024

Added a somewhat more complicated example with vectors
https://github.com/kwikius/units/blob/andy_master/example/trilateration.cpp

This is just a translation of my Trilateration example to mpusz/units
and uses some glue to get mpusz/units working with quan types

requires to include my quan library ( headers only required) to run
Anyway shows a use for unit aware 3d points vectors etc

example output
A = sphere(centre = [0 km, 0 km, 0 km], radius = 8 km)
B = sphere(centre = [10 km, 0 km, 0 km], radius = 5 km)
C = sphere(centre = [7 km, 7 km, 0 km], radius = 7 km)
intersection point = [6.95 km, 1.12143 km, 3.79999 km]

from mp-units.

jml1795 avatar jml1795 commented on June 2, 2024

Was taking a look through both the proposal and some of the discussion. I really like the idea of standard support for a units library and have tried some of the other referenced libraries in both toy and production code in the past.

Regarding LA support for units, one issue could be matrices and vectors that are inherently of mixed dimension. Something like a covariance matrix where you have a position x position block, velocity x velocity block, and pos x vel blocks likely end up causing issues. Not sure there is a work around, but worth giving it a thought.

from mp-units.

hatcat avatar hatcat commented on June 2, 2024

The linear algebra proposal, https://wg21.link/P1385, allows for customisation of all operators so you can provide your own algorithms. When you declare your particular vector or matrix type, the operator traits object is part of the spelling.

from mp-units.

mpusz avatar mpusz commented on June 2, 2024

Last week in Prague we made Untis library to work with P1385 :-) There are some changes still needed to be done but soon I will push the LA integration and some examples.

Regarding the question about storing different types in one vector/matrix, I am not aware of any LA library that does this (but it does not mean it is a bad idea).

from mp-units.

dwith-ts avatar dwith-ts commented on June 2, 2024

Not sure if that was clear from my earlier comment: I have written a comprehensive library that can handle vectors and matrices with mixed units. The library is used in production (unfortunately not open source at the moment).

It is also able to completely handle the Kalman filter for tracking and perception systems example @jml1795 mentioned (that was actually the use-case I developed it for). A state can e.g. contain x- and y position, velocity, acceleration and orientation, the same holds for a covariance matrix.

Design-wise I decided to make both the underlying units library as well as the underlying linalg library exchangeable.
It is possible to get the simple case of a vector / matrix with uniform units to work by customizing the value type of a linalg library (as @mpusz @hatcat and showed). If the general heterogeneous units case should be solved, I found it better to seperate the concerns of

  1. providing a units library for scalars
  2. providing an efficient linalg library
  3. providing a library that annotates vector and matrix rows and columns with units (this is sufficient as all unit-correct matrices are an outer product of a list of row units and column units, see the pretty old book http://www.georgehart.com/research/multanal.html and the short paper www.georgehart.com/research/tdm.ps); this library then uses the libraries from 1. and 2. for its implementation

which also makes each of the parts exchangeable.

From that implementation, I have a few wishes / requests for the underlying units / linear algebra library:

  • The units library should be able to handle all scalar types, floating point as well as integral types

  • Plane angle (Radian, degree) support would be great (although implementing this correctly is quite challenging and not as straigthforward as one would think)

  • The linalg library should have traits that specify whether a type (matrix expression or proper matrix with storage) should be stored by value or by reference in an expression.

  • it should clearly state when it returns temporary vectors / matrices instead of matrix expressions (or not do that at all if feasible)

from mp-units.

kwikius avatar kwikius commented on June 2, 2024

Here I implemented a matrix using physical quantities, in this case to transform 3d points in length units, but could be of any quantity type
https://github.com/kwikius/Trilateration/blob/master/trilateration_transform_matrix.cpp

Note that the type of result of a matrix multiplication needs to be deduced. Deducing the types of the elements of rthe resulting matrix takes time,ok for 4x4 matrices but tends to take a long time and memory in the compiler as the size of the matrix is increased
https://github.com/kwikius/Trilateration/blob/master/trilateration_transform_matrix.cpp#L433

The basic_matrix class basically just wraps a tuple, that holds the data. The matrix algorithms work on matrix concept rather than type,
https://github.com/kwikius/quan-trunk/blob/master/quan/concepts/fusion/matrix.hpp
so for example a multiplication returns a multiplies view, storing refs to the inputs( which may also be views of course
https://github.com/kwikius/quan-trunk/blob/master/quan/fusion/make_multiplies_view.hpp

https://github.com/kwikius/Trilateration/blob/master/trilateration_transform_matrix.cpp#L117

The positions coordinates is first converted from a 3d vector of length into into a homogeneous 4 row x 1column matrix. The extra point is required for compatibility with 4 x 4 transform matrices, to do perspective transformation etc
https://github.com/kwikius/quan-trunk/blob/master/quan/fusion/make_column_matrix.hpp#L25

functions returning matrices for the common functions are shown ( the Q type is either a physical quantity or a numeric type)
// translation matrix
https://github.com/kwikius/Trilateration/blob/master/trilateration_transform_matrix.cpp#L131

// rotation around x
https://github.com/kwikius/Trilateration/blob/master/trilateration_transform_matrix.cpp#L160
//rotation around y
https://github.com/kwikius/Trilateration/blob/master/trilateration_transform_matrix.cpp#L189
//rotation around z
https://github.com/kwikius/Trilateration/blob/master/trilateration_transform_matrix.cpp#L218

from mp-units.

dwith-ts avatar dwith-ts commented on June 2, 2024

Note that the type of result of a matrix multiplication needs to be deduced. Deducing the types of the elements of rthe resulting matrix takes time...
This deduction using all matrix entry types can be simplified by only using each matrices row + column types, see also the documents I linked.

When calculating A*b, the inner units (A’s column units and b’s row units) have to cancel which e.g. happens if A is a Jacobian (a transformation is the Jacobian of the linear transform between 2 vector spaces and the units in a Jacobian are given by the row unit divided by the column unit) and b is a vector.

These rules are similar to the classical matrix multiplication rules where the inner dimensions have to match. In the cases of Unit-tagged matrixes, the inner units have to be the inverse of one another in order to cancel

from mp-units.

dwith-ts avatar dwith-ts commented on June 2, 2024

The actual calculations can all be done by an underlying matrix library, the responsibility of such unit-safe matrix classes is mainly to promote the types during calculations, sprinkling the syntactic sugar on top.

from mp-units.

kwikius avatar kwikius commented on June 2, 2024

@dwith-ts The links on dimensioned matrices are great. I have never seen any literature about using physical quantities in matrices before. If compile time can be reduced dramatically for larger matrices, then that makes the use of such matrices much more practical. Thanks for the information!

from mp-units.

mpusz avatar mpusz commented on June 2, 2024

Done: https://mpusz.github.io/units/use_cases/linear_algebra.html :-)

from mp-units.

mpusz avatar mpusz commented on June 2, 2024

Please note the issues for LA: BobSteagall/wg21#36, BobSteagall/wg21#37, BobSteagall/wg21#38, BobSteagall/wg21#39.

from mp-units.

dwith-ts avatar dwith-ts commented on June 2, 2024

For your information: I just submitted a presentation about “Physical Units for Matrices” to CppCon2021. If this will be accepted for the conference, I am going to explain in detail how I did the implementation.
As I already explained, the big advantage is that it also works for the case of non-uniform units (i. e. each element can have a different unit)

from mp-units.

JohelEGP avatar JohelEGP commented on June 2, 2024

Looking forward to it. I believe std::bit_cast might be able to do away with concerns about a matrix of quantities/quantity of matrices and their usability with existing linear algebra libraries that may require something like int[3] to take advantage of built-in CPU instructions.

from mp-units.

dwith-ts avatar dwith-ts commented on June 2, 2024

Std::bit_cast could also be of help there I guess, but it seems that this returns by value, i.e. it makes a copy? This would produce additional run-time overhead then. Or do you know a way how the copy can be avoided?

from mp-units.

JohelEGP avatar JohelEGP commented on June 2, 2024

std::bit_cast alone can't help that. Specially when it come to bigger matrices, like 3x3 or int[9].

With platform-specific knowledge, you could turn the call to std::bit_cast into a reinterpret_cast when not std::is_constant_evaluated(). That's a minefield that requires proper exploration, though.

from mp-units.

kwikius avatar kwikius commented on June 2, 2024

@dwith-ts. This sounds great. I did implement matrices with arbitrary types which work with quantities . For example
https://github.com/kwikius/quan-trunk/blob/master/quan_matters/examples/fusion/kalman1.cpp#L69
However my implementation was quite "dumb".

The main problem I found was that compile times grew very fast with larger matrices. What are the largest matrices you have used? If you have got an efficient implementation for larger matrices I would love to try it out!

(The matrix '''x''' above actually uses 3D vectors as elements so the result of m1 * x is really a 3 x 3 matrix) I found that anything over a (say) 5 x 5 matrix was impractical in my implementation

FWIW A general ( un unit related) advantage of using a matrix with individually typed elements is that it is possible to optimise out calculations where the result is known at compile time. The above matrix '''m1''' elements are actually so called static values.
These have the property that by design no runtime calculation is performed where the result is known at compile time. For example a multiplication of a runtime value by a static_value representing 0 will return a ( suitably typed) static_value representing 0. Further they only use the minimal one byte for storage ( The type information for arbitrary types includng physical quantities is carried along in the type. The value is held as a compile time rational. In any calculation where the result is not known at compile time or can't be held exactly, the static value is evaluated to its normal runtime counterpart. The type of these elements in the result matrix is of course calculated at compile time as part of the signature of the matrix multiply function.

from mp-units.

dwith-ts avatar dwith-ts commented on June 2, 2024

The biggest matrices I tried so far are 9x9. However, it should work with matrices of any size as there is no need to actually model the unit of each entry and thus having M*N template arguments to a matrix.
All useful multipliable matrices of size MxN have a dimensional freedom of M+N because their dimensions can be described as an outer product of a vector of row units row_units and a vector of column units column_units:
[Mat_i,j] = [row_units_i] * [col_units_j]
(This can even be reduced to M+N-1 as the first entry of row_units can be restricted to be dimensionless while still being able to represent all possible matrix units)
Furthermore, my solution does not try to actually put units inside the matrix, this will IMHO break down pretty quickly as the compiler dies of template overload ;-) Instead, the user-interface of my matrix class (and its type promotions) take care of annotating / returning everything as an appropriate physical quantity.
@kwikius your idea of optimizing out certain operations in such matrices (like multiplication with 0 or 1) is really nice, this is also something that I already tried out and it worked.

from mp-units.

kwikius avatar kwikius commented on June 2, 2024

OK. So (something like) the units of elements of an m * n matrix M can be worked out from a row matrix rM and a column matrix cM, because all dimensioned matrices have a specific form as cited in the refs above.

  • in pseudoC++ The unit of an element of M[r,c] can be found from decltype(rM[r] * cM[c]) and most importantly this form reduces the compiletime from O(m*n) to O(n+n) or even slightly better.
  • The numerical values are held privately in the matrix as dimensionless types and coerced to the correct type when required?
  • The dimensioned matrix framework can be layered on top of existing matrix frameworks

I don't know how far I have it right but no matter. This sounds great and I hope that it gets on the agenda at the conference.

As George Hart hints in his papers, there do seem to be many useful ( and under-explored) properties of dimensioned matrices for example in the areas of type checking and correctnesss verifying and there also seem to be some opportunities for optimisation too.

Are you planning to release any source code? I find it hard to follow abstract maths and I would certainly try and get time to work through or just create some examples.

from mp-units.

dwith-ts avatar dwith-ts commented on June 2, 2024

@kwikius your bullet point list is correct. However, if you really want to implement something it IMHO makes sense to wait for my presentation, there are a few other tricks I don't want to spoil just yet (apologies for the secretiveness).

Quoting from my submission overview:
...Furthermore, the approach provides an even richer (and more type-safe) annotation for linear algebra types and their elements than only physical units: it enables annotations that resemble quantity kinds. This means that it can also distinguish between X- and Y-position in the same coordinate frame and between X-position in coordinate frame A and X-position in coordinate frame B. In addition to the element annotations, we also get stronger matrix types which encode the content, e.g. a jacobian matrix, covariance matrix, position and displacement vector types. I will show how these annotations propagate through linear algebra operations, how they determine the subset of valid operations on each type and of course and most importantly, how this can be implemented efficiently in C++. This will enable a whole new level of type-safety in C++ linear algebra applications that allows to catch the majority of mathematically inappropriate operations on vectors and matrices, whereas normal linear algebra libraries like e.g. Eigen, blaze or P1385 can only catch problems related to incompatible vector and matrix sizes. ...

@kwikius : I am trying to get permission to release source code, but I do not want to promise anything here.

from mp-units.

mpusz avatar mpusz commented on June 2, 2024

This sounds great! I always hoped that someone will pick up this subject and provide a standalone library on top of mp-units and linear algebra proposals that will merge them together in an efficient way.

I hope to see you at CppCon. We definitely have to meet over lunch there and talk about it 🍽️ 🍻

from mp-units.

dwith-ts avatar dwith-ts commented on June 2, 2024

I hope to see you at CppCon. We definitely have to meet over lunch there and talk about it 🍽️ 🍻

Perfect, let’s do that! Looking forward to discussing this with you! 🍻

from mp-units.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.