WPILibC++ 2025.1.1
Loading...
Searching...
No Matches
VariableMatrix.hpp
Go to the documentation of this file.
1// Copyright (c) Sleipnir contributors
2
3#pragma once
4
5#include <algorithm>
6#include <concepts>
7#include <initializer_list>
8#include <iterator>
9#include <span>
10#include <utility>
11#include <vector>
12
13#include <Eigen/Core>
14#include <wpi/SmallVector.h>
15
22
23namespace sleipnir {
24
25/**
26 * A matrix of autodiff variables.
27 */
29 public:
30 /**
31 * Constructs an empty VariableMatrix.
32 */
33 VariableMatrix() = default;
34
35 /**
36 * Constructs a VariableMatrix column vector with the given rows.
37 *
38 * @param rows The number of matrix rows.
39 */
40 explicit VariableMatrix(int rows) : m_rows{rows}, m_cols{1} {
41 for (int row = 0; row < rows; ++row) {
42 m_storage.emplace_back();
43 }
44 }
45
46 /**
47 * Constructs a VariableMatrix with the given dimensions.
48 *
49 * @param rows The number of matrix rows.
50 * @param cols The number of matrix columns.
51 */
52 VariableMatrix(int rows, int cols) : m_rows{rows}, m_cols{cols} {
53 for (int row = 0; row < rows; ++row) {
54 for (int col = 0; col < cols; ++col) {
55 m_storage.emplace_back();
56 }
57 }
58 }
59
60 /**
61 * Constructs a scalar VariableMatrix from a nested list of Variables.
62 *
63 * @param list The nested list of Variables.
64 */
65 VariableMatrix( // NOLINT
66 std::initializer_list<std::initializer_list<Variable>> list) {
67 // Get row and column counts for destination matrix
68 m_rows = list.size();
69 m_cols = 0;
70 if (list.size() > 0) {
71 m_cols = list.begin()->size();
72 }
73
74 // Assert the first and latest column counts are the same
75 for ([[maybe_unused]]
76 const auto& row : list) {
77 Assert(list.begin()->size() == row.size());
78 }
79
80 m_storage.reserve(Rows() * Cols());
81 for (const auto& row : list) {
82 std::copy(row.begin(), row.end(), std::back_inserter(m_storage));
83 }
84 }
85
86 /**
87 * Constructs a scalar VariableMatrix from a nested list of doubles.
88 *
89 * This overload is for Python bindings only.
90 *
91 * @param list The nested list of Variables.
92 */
93 VariableMatrix(const std::vector<std::vector<double>>& list) { // NOLINT
94 // Get row and column counts for destination matrix
95 m_rows = list.size();
96 m_cols = 0;
97 if (list.size() > 0) {
98 m_cols = list.begin()->size();
99 }
100
101 // Assert the first and latest column counts are the same
102 for ([[maybe_unused]]
103 const auto& row : list) {
104 Assert(list.begin()->size() == row.size());
105 }
106
107 m_storage.reserve(Rows() * Cols());
108 for (const auto& row : list) {
109 std::copy(row.begin(), row.end(), std::back_inserter(m_storage));
110 }
111 }
112
113 /**
114 * Constructs a scalar VariableMatrix from a nested list of Variables.
115 *
116 * This overload is for Python bindings only.
117 *
118 * @param list The nested list of Variables.
119 */
120 VariableMatrix(const std::vector<std::vector<Variable>>& list) { // NOLINT
121 // Get row and column counts for destination matrix
122 m_rows = list.size();
123 m_cols = 0;
124 if (list.size() > 0) {
125 m_cols = list.begin()->size();
126 }
127
128 // Assert the first and latest column counts are the same
129 for ([[maybe_unused]]
130 const auto& row : list) {
131 Assert(list.begin()->size() == row.size());
132 }
133
134 m_storage.reserve(Rows() * Cols());
135 for (const auto& row : list) {
136 std::copy(row.begin(), row.end(), std::back_inserter(m_storage));
137 }
138 }
139
140 /**
141 * Constructs a VariableMatrix from an Eigen matrix.
142 *
143 * @param values Eigen matrix of values.
144 */
145 template <typename Derived>
146 VariableMatrix(const Eigen::MatrixBase<Derived>& values) // NOLINT
147 : m_rows{static_cast<int>(values.rows())},
148 m_cols{static_cast<int>(values.cols())} {
149 m_storage.reserve(values.rows() * values.cols());
150 for (int row = 0; row < values.rows(); ++row) {
151 for (int col = 0; col < values.cols(); ++col) {
152 m_storage.emplace_back(values(row, col));
153 }
154 }
155 }
156
157 /**
158 * Constructs a VariableMatrix from an Eigen diagonal matrix.
159 *
160 * @param values Diagonal matrix of values.
161 */
162 template <typename Derived>
163 VariableMatrix(const Eigen::DiagonalBase<Derived>& values) // NOLINT
164 : m_rows{static_cast<int>(values.rows())},
165 m_cols{static_cast<int>(values.cols())} {
166 m_storage.reserve(values.rows() * values.cols());
167 for (int row = 0; row < values.rows(); ++row) {
168 for (int col = 0; col < values.cols(); ++col) {
169 if (row == col) {
170 m_storage.emplace_back(values.diagonal()(row));
171 } else {
172 m_storage.emplace_back(0.0);
173 }
174 }
175 }
176 }
177
178 /**
179 * Assigns an Eigen matrix to a VariableMatrix.
180 *
181 * @param values Eigen matrix of values.
182 */
183 template <typename Derived>
184 VariableMatrix& operator=(const Eigen::MatrixBase<Derived>& values) {
185 Assert(Rows() == values.rows());
186 Assert(Cols() == values.cols());
187
188 for (int row = 0; row < values.rows(); ++row) {
189 for (int col = 0; col < values.cols(); ++col) {
190 (*this)(row, col) = values(row, col);
191 }
192 }
193
194 return *this;
195 }
196
197 /**
198 * Sets the VariableMatrix's internal values.
199 *
200 * @param values Eigen matrix of values.
201 */
202 template <typename Derived>
203 requires std::same_as<typename Derived::Scalar, double>
204 void SetValue(const Eigen::MatrixBase<Derived>& values) {
205 Assert(Rows() == values.rows());
206 Assert(Cols() == values.cols());
207
208 for (int row = 0; row < values.rows(); ++row) {
209 for (int col = 0; col < values.cols(); ++col) {
210 (*this)(row, col).SetValue(values(row, col));
211 }
212 }
213 }
214
215 /**
216 * Constructs a scalar VariableMatrix from a Variable.
217 *
218 * @param variable Variable.
219 */
220 VariableMatrix(const Variable& variable) // NOLINT
221 : m_rows{1}, m_cols{1} {
222 m_storage.emplace_back(variable);
223 }
224
225 /**
226 * Constructs a scalar VariableMatrix from a Variable.
227 *
228 * @param variable Variable.
229 */
230 VariableMatrix(Variable&& variable) : m_rows{1}, m_cols{1} { // NOLINT
231 m_storage.emplace_back(std::move(variable));
232 }
233
234 /**
235 * Constructs a VariableMatrix from a VariableBlock.
236 *
237 * @param values VariableBlock of values.
238 */
240 : m_rows{values.Rows()}, m_cols{values.Cols()} {
241 for (int row = 0; row < Rows(); ++row) {
242 for (int col = 0; col < Cols(); ++col) {
243 m_storage.emplace_back(values(row, col));
244 }
245 }
246 }
247
248 /**
249 * Constructs a VariableMatrix from a VariableBlock.
250 *
251 * @param values VariableBlock of values.
252 */
254 : m_rows{values.Rows()}, m_cols{values.Cols()} {
255 for (int row = 0; row < Rows(); ++row) {
256 for (int col = 0; col < Cols(); ++col) {
257 m_storage.emplace_back(values(row, col));
258 }
259 }
260 }
261
262 /**
263 * Constructs a column vector wrapper around a Variable array.
264 *
265 * @param values Variable array to wrap.
266 */
267 explicit VariableMatrix(std::span<const Variable> values)
268 : m_rows{static_cast<int>(values.size())}, m_cols{1} {
269 for (int row = 0; row < Rows(); ++row) {
270 for (int col = 0; col < Cols(); ++col) {
271 m_storage.emplace_back(values[row * Cols() + col]);
272 }
273 }
274 }
275
276 /**
277 * Constructs a matrix wrapper around a Variable array.
278 *
279 * @param values Variable array to wrap.
280 * @param rows The number of matrix rows.
281 * @param cols The number of matrix columns.
282 */
283 VariableMatrix(std::span<const Variable> values, int rows, int cols)
284 : m_rows{rows}, m_cols{cols} {
285 Assert(static_cast<int>(values.size()) == Rows() * Cols());
286 for (int row = 0; row < Rows(); ++row) {
287 for (int col = 0; col < Cols(); ++col) {
288 m_storage.emplace_back(values[row * Cols() + col]);
289 }
290 }
291 }
292
293 /**
294 * Returns a block pointing to the given row and column.
295 *
296 * @param row The block row.
297 * @param col The block column.
298 */
299 Variable& operator()(int row, int col) {
300 Assert(row >= 0 && row < Rows());
301 Assert(col >= 0 && col < Cols());
302 return m_storage[row * Cols() + col];
303 }
304
305 /**
306 * Returns a block pointing to the given row and column.
307 *
308 * @param row The block row.
309 * @param col The block column.
310 */
311 const Variable& operator()(int row, int col) const {
312 Assert(row >= 0 && row < Rows());
313 Assert(col >= 0 && col < Cols());
314 return m_storage[row * Cols() + col];
315 }
316
317 /**
318 * Returns a block pointing to the given row.
319 *
320 * @param row The block row.
321 */
323 Assert(row >= 0 && row < Rows() * Cols());
324 return m_storage[row];
325 }
326
327 /**
328 * Returns a block pointing to the given row.
329 *
330 * @param row The block row.
331 */
332 const Variable& operator()(int row) const {
333 Assert(row >= 0 && row < Rows() * Cols());
334 return m_storage[row];
335 }
336
337 /**
338 * Returns a block of the variable matrix.
339 *
340 * @param rowOffset The row offset of the block selection.
341 * @param colOffset The column offset of the block selection.
342 * @param blockRows The number of rows in the block selection.
343 * @param blockCols The number of columns in the block selection.
344 */
345 VariableBlock<VariableMatrix> Block(int rowOffset, int colOffset,
346 int blockRows, int blockCols) {
347 Assert(rowOffset >= 0 && rowOffset <= Rows());
348 Assert(colOffset >= 0 && colOffset <= Cols());
349 Assert(blockRows >= 0 && blockRows <= Rows() - rowOffset);
350 Assert(blockCols >= 0 && blockCols <= Cols() - colOffset);
351 return VariableBlock{*this, rowOffset, colOffset, blockRows, blockCols};
352 }
353
354 /**
355 * Returns a block of the variable matrix.
356 *
357 * @param rowOffset The row offset of the block selection.
358 * @param colOffset The column offset of the block selection.
359 * @param blockRows The number of rows in the block selection.
360 * @param blockCols The number of columns in the block selection.
361 */
362 const VariableBlock<const VariableMatrix> Block(int rowOffset, int colOffset,
363 int blockRows,
364 int blockCols) const {
365 Assert(rowOffset >= 0 && rowOffset <= Rows());
366 Assert(colOffset >= 0 && colOffset <= Cols());
367 Assert(blockRows >= 0 && blockRows <= Rows() - rowOffset);
368 Assert(blockCols >= 0 && blockCols <= Cols() - colOffset);
369 return VariableBlock{*this, rowOffset, colOffset, blockRows, blockCols};
370 }
371
372 /**
373 * Returns a slice of the variable matrix.
374 *
375 * @param rowSlice The row slice.
376 * @param colSlice The column slice.
377 */
379 int rowSliceLength = rowSlice.Adjust(Rows());
380 int colSliceLength = colSlice.Adjust(Cols());
381 return VariableBlock{*this, std::move(rowSlice), rowSliceLength,
382 std::move(colSlice), colSliceLength};
383 }
384
385 /**
386 * Returns a slice of the variable matrix.
387 *
388 * @param rowSlice The row slice.
389 * @param colSlice The column slice.
390 */
392 Slice colSlice) const {
393 int rowSliceLength = rowSlice.Adjust(Rows());
394 int colSliceLength = colSlice.Adjust(Cols());
395 return VariableBlock{*this, std::move(rowSlice), rowSliceLength,
396 std::move(colSlice), colSliceLength};
397 }
398
399 /**
400 * Returns a slice of the variable matrix.
401 *
402 * The given slices aren't adjusted. This overload is for Python bindings
403 * only.
404 *
405 * @param rowSlice The row slice.
406 * @param rowSliceLength The row slice length.
407 * @param colSlice The column slice.
408 * @param colSliceLength The column slice length.
409 *
410 */
411 VariableBlock<VariableMatrix> operator()(Slice rowSlice, int rowSliceLength,
412 Slice colSlice, int colSliceLength) {
413 return VariableBlock{*this, std::move(rowSlice), rowSliceLength,
414 std::move(colSlice), colSliceLength};
415 }
416
417 /**
418 * Returns a slice of the variable matrix.
419 *
420 * The given slices aren't adjusted. This overload is for Python bindings
421 * only.
422 *
423 * @param rowSlice The row slice.
424 * @param rowSliceLength The row slice length.
425 * @param colSlice The column slice.
426 * @param colSliceLength The column slice length.
427 */
429 Slice rowSlice, int rowSliceLength, Slice colSlice,
430 int colSliceLength) const {
431 return VariableBlock{*this, std::move(rowSlice), rowSliceLength,
432 std::move(colSlice), colSliceLength};
433 }
434
435 /**
436 * Returns a segment of the variable vector.
437 *
438 * @param offset The offset of the segment.
439 * @param length The length of the segment.
440 */
441 VariableBlock<VariableMatrix> Segment(int offset, int length) {
442 Assert(offset >= 0 && offset < Rows() * Cols());
443 Assert(length >= 0 && length <= Rows() * Cols() - offset);
444 return Block(offset, 0, length, 1);
445 }
446
447 /**
448 * Returns a segment of the variable vector.
449 *
450 * @param offset The offset of the segment.
451 * @param length The length of the segment.
452 */
454 int length) const {
455 Assert(offset >= 0 && offset < Rows() * Cols());
456 Assert(length >= 0 && length <= Rows() * Cols() - offset);
457 return Block(offset, 0, length, 1);
458 }
459
460 /**
461 * Returns a row slice of the variable matrix.
462 *
463 * @param row The row to slice.
464 */
466 Assert(row >= 0 && row < Rows());
467 return Block(row, 0, 1, Cols());
468 }
469
470 /**
471 * Returns a row slice of the variable matrix.
472 *
473 * @param row The row to slice.
474 */
476 Assert(row >= 0 && row < Rows());
477 return Block(row, 0, 1, Cols());
478 }
479
480 /**
481 * Returns a column slice of the variable matrix.
482 *
483 * @param col The column to slice.
484 */
486 Assert(col >= 0 && col < Cols());
487 return Block(0, col, Rows(), 1);
488 }
489
490 /**
491 * Returns a column slice of the variable matrix.
492 *
493 * @param col The column to slice.
494 */
496 Assert(col >= 0 && col < Cols());
497 return Block(0, col, Rows(), 1);
498 }
499
500 /**
501 * Matrix multiplication operator.
502 *
503 * @param lhs Operator left-hand side.
504 * @param rhs Operator right-hand side.
505 */
507 operator*(const VariableMatrix& lhs, const VariableMatrix& rhs) {
508 Assert(lhs.Cols() == rhs.Rows());
509
510 VariableMatrix result{lhs.Rows(), rhs.Cols()};
511
512 for (int i = 0; i < lhs.Rows(); ++i) {
513 for (int j = 0; j < rhs.Cols(); ++j) {
514 Variable sum;
515 for (int k = 0; k < lhs.Cols(); ++k) {
516 sum += lhs(i, k) * rhs(k, j);
517 }
518 result(i, j) = sum;
519 }
520 }
521
522 return result;
523 }
524
525 /**
526 * Matrix-scalar multiplication operator.
527 *
528 * @param lhs Operator left-hand side.
529 * @param rhs Operator right-hand side.
530 */
532 const Variable& rhs) {
533 VariableMatrix result{lhs.Rows(), lhs.Cols()};
534
535 for (int row = 0; row < result.Rows(); ++row) {
536 for (int col = 0; col < result.Cols(); ++col) {
537 result(row, col) = lhs(row, col) * rhs;
538 }
539 }
540
541 return result;
542 }
543
544 /**
545 * Matrix-scalar multiplication operator.
546 *
547 * @param lhs Operator left-hand side.
548 * @param rhs Operator right-hand side.
549 */
551 double rhs) {
552 return lhs * Variable{rhs};
553 }
554
555 /**
556 * Scalar-matrix multiplication operator.
557 *
558 * @param lhs Operator left-hand side.
559 * @param rhs Operator right-hand side.
560 */
562 operator*(const Variable& lhs, const VariableMatrix& rhs) {
563 VariableMatrix result{rhs.Rows(), rhs.Cols()};
564
565 for (int row = 0; row < result.Rows(); ++row) {
566 for (int col = 0; col < result.Cols(); ++col) {
567 result(row, col) = rhs(row, col) * lhs;
568 }
569 }
570
571 return result;
572 }
573
574 /**
575 * Scalar-matrix multiplication operator.
576 *
577 * @param lhs Operator left-hand side.
578 * @param rhs Operator right-hand side.
579 */
581 operator*(double lhs, const VariableMatrix& rhs) {
582 return Variable{lhs} * rhs;
583 }
584
585 /**
586 * Compound matrix multiplication-assignment operator.
587 *
588 * @param rhs Variable to multiply.
589 */
591 Assert(Cols() == rhs.Rows() && Cols() == rhs.Cols());
592
593 for (int i = 0; i < Rows(); ++i) {
594 for (int j = 0; j < rhs.Cols(); ++j) {
595 Variable sum;
596 for (int k = 0; k < Cols(); ++k) {
597 sum += (*this)(i, k) * rhs(k, j);
598 }
599 (*this)(i, j) = sum;
600 }
601 }
602
603 return *this;
604 }
605
606 /**
607 * Binary division operator (only enabled when rhs is a scalar).
608 *
609 * @param lhs Operator left-hand side.
610 * @param rhs Operator right-hand side.
611 */
613 const Variable& rhs) {
614 VariableMatrix result{lhs.Rows(), lhs.Cols()};
615
616 for (int row = 0; row < result.Rows(); ++row) {
617 for (int col = 0; col < result.Cols(); ++col) {
618 result(row, col) = lhs(row, col) / rhs;
619 }
620 }
621
622 return result;
623 }
624
625 /**
626 * Compound matrix division-assignment operator (only enabled when rhs
627 * is a scalar).
628 *
629 * @param rhs Variable to divide.
630 */
632 for (int row = 0; row < Rows(); ++row) {
633 for (int col = 0; col < Cols(); ++col) {
634 (*this)(row, col) /= rhs;
635 }
636 }
637
638 return *this;
639 }
640
641 /**
642 * Binary addition operator.
643 *
644 * @param lhs Operator left-hand side.
645 * @param rhs Operator right-hand side.
646 */
648 operator+(const VariableMatrix& lhs, const VariableMatrix& rhs) {
649 VariableMatrix result{lhs.Rows(), lhs.Cols()};
650
651 for (int row = 0; row < result.Rows(); ++row) {
652 for (int col = 0; col < result.Cols(); ++col) {
653 result(row, col) = lhs(row, col) + rhs(row, col);
654 }
655 }
656
657 return result;
658 }
659
660 /**
661 * Compound addition-assignment operator.
662 *
663 * @param rhs Variable to add.
664 */
666 for (int row = 0; row < Rows(); ++row) {
667 for (int col = 0; col < Cols(); ++col) {
668 (*this)(row, col) += rhs(row, col);
669 }
670 }
671
672 return *this;
673 }
674
675 /**
676 * Binary subtraction operator.
677 *
678 * @param lhs Operator left-hand side.
679 * @param rhs Operator right-hand side.
680 */
682 operator-(const VariableMatrix& lhs, const VariableMatrix& rhs) {
683 VariableMatrix result{lhs.Rows(), lhs.Cols()};
684
685 for (int row = 0; row < result.Rows(); ++row) {
686 for (int col = 0; col < result.Cols(); ++col) {
687 result(row, col) = lhs(row, col) - rhs(row, col);
688 }
689 }
690
691 return result;
692 }
693
694 /**
695 * Compound subtraction-assignment operator.
696 *
697 * @param rhs Variable to subtract.
698 */
700 for (int row = 0; row < Rows(); ++row) {
701 for (int col = 0; col < Cols(); ++col) {
702 (*this)(row, col) -= rhs(row, col);
703 }
704 }
705
706 return *this;
707 }
708
709 /**
710 * Unary minus operator.
711 *
712 * @param lhs Operand for unary minus.
713 */
716 VariableMatrix result{lhs.Rows(), lhs.Cols()};
717
718 for (int row = 0; row < result.Rows(); ++row) {
719 for (int col = 0; col < result.Cols(); ++col) {
720 result(row, col) = -lhs(row, col);
721 }
722 }
723
724 return result;
725 }
726
727 /**
728 * Implicit conversion operator from 1x1 VariableMatrix to Variable.
729 */
730 operator Variable() const { // NOLINT
731 Assert(Rows() == 1 && Cols() == 1);
732 return (*this)(0, 0);
733 }
734
735 /**
736 * Returns the transpose of the variable matrix.
737 */
739 VariableMatrix result{Cols(), Rows()};
740
741 for (int row = 0; row < Rows(); ++row) {
742 for (int col = 0; col < Cols(); ++col) {
743 result(col, row) = (*this)(row, col);
744 }
745 }
746
747 return result;
748 }
749
750 /**
751 * Returns number of rows in the matrix.
752 */
753 int Rows() const { return m_rows; }
754
755 /**
756 * Returns number of columns in the matrix.
757 */
758 int Cols() const { return m_cols; }
759
760 /**
761 * Returns an element of the variable matrix.
762 *
763 * @param row The row of the element to return.
764 * @param col The column of the element to return.
765 */
766 double Value(int row, int col) {
767 Assert(row >= 0 && row < Rows());
768 Assert(col >= 0 && col < Cols());
769 return m_storage[row * Cols() + col].Value();
770 }
771
772 /**
773 * Returns a row of the variable column vector.
774 *
775 * @param index The index of the element to return.
776 */
777 double Value(int index) {
778 Assert(index >= 0 && index < Rows() * Cols());
779 return m_storage[index].Value();
780 }
781
782 /**
783 * Returns the contents of the variable matrix.
784 */
785 Eigen::MatrixXd Value() {
786 Eigen::MatrixXd result{Rows(), Cols()};
787
788 for (int row = 0; row < Rows(); ++row) {
789 for (int col = 0; col < Cols(); ++col) {
790 result(row, col) = Value(row, col);
791 }
792 }
793
794 return result;
795 }
796
797 /**
798 * Transforms the matrix coefficient-wise with an unary operator.
799 *
800 * @param unaryOp The unary operator to use for the transform operation.
801 */
803 function_ref<Variable(const Variable& x)> unaryOp) const {
804 VariableMatrix result{Rows(), Cols()};
805
806 for (int row = 0; row < Rows(); ++row) {
807 for (int col = 0; col < Cols(); ++col) {
808 result(row, col) = unaryOp((*this)(row, col));
809 }
810 }
811
812 return result;
813 }
814
815 class iterator {
816 public:
817 using iterator_category = std::forward_iterator_tag;
819 using difference_type = std::ptrdiff_t;
822
823 iterator(VariableMatrix* mat, int row, int col)
824 : m_mat{mat}, m_row{row}, m_col{col} {}
825
827 ++m_col;
828 if (m_col == m_mat->Cols()) {
829 m_col = 0;
830 ++m_row;
831 }
832 return *this;
833 }
835 iterator retval = *this;
836 ++(*this);
837 return retval;
838 }
839 bool operator==(const iterator&) const = default;
840 reference operator*() { return (*m_mat)(m_row, m_col); }
841
842 private:
843 VariableMatrix* m_mat;
844 int m_row;
845 int m_col;
846 };
847
849 public:
850 using iterator_category = std::forward_iterator_tag;
852 using difference_type = std::ptrdiff_t;
854 using const_reference = const Variable&;
855
856 const_iterator(const VariableMatrix* mat, int row, int col)
857 : m_mat{mat}, m_row{row}, m_col{col} {}
858
860 ++m_col;
861 if (m_col == m_mat->Cols()) {
862 m_col = 0;
863 ++m_row;
864 }
865 return *this;
866 }
868 const_iterator retval = *this;
869 ++(*this);
870 return retval;
871 }
872 bool operator==(const const_iterator&) const = default;
873 const_reference operator*() const { return (*m_mat)(m_row, m_col); }
874
875 private:
876 const VariableMatrix* m_mat;
877 int m_row;
878 int m_col;
879 };
880
881 /**
882 * Returns begin iterator.
883 */
884 iterator begin() { return iterator(this, 0, 0); }
885
886 /**
887 * Returns end iterator.
888 */
889 iterator end() { return iterator(this, Rows(), 0); }
890
891 /**
892 * Returns begin iterator.
893 */
894 const_iterator begin() const { return const_iterator(this, 0, 0); }
895
896 /**
897 * Returns end iterator.
898 */
899 const_iterator end() const { return const_iterator(this, Rows(), 0); }
900
901 /**
902 * Returns begin iterator.
903 */
904 const_iterator cbegin() const { return const_iterator(this, 0, 0); }
905
906 /**
907 * Returns end iterator.
908 */
909 const_iterator cend() const { return const_iterator(this, Rows(), 0); }
910
911 /**
912 * Returns number of elements in matrix.
913 */
914 size_t size() const { return m_rows * m_cols; }
915
916 /**
917 * Returns a variable matrix filled with zeroes.
918 *
919 * @param rows The number of matrix rows.
920 * @param cols The number of matrix columns.
921 */
922 static VariableMatrix Zero(int rows, int cols) {
923 VariableMatrix result{rows, cols};
924
925 for (auto& elem : result) {
926 elem = 0.0;
927 }
928
929 return result;
930 }
931
932 /**
933 * Returns a variable matrix filled with ones.
934 *
935 * @param rows The number of matrix rows.
936 * @param cols The number of matrix columns.
937 */
938 static VariableMatrix Ones(int rows, int cols) {
939 VariableMatrix result{rows, cols};
940
941 for (auto& elem : result) {
942 elem = 1.0;
943 }
944
945 return result;
946 }
947
948 private:
950 int m_rows = 0;
951 int m_cols = 0;
952};
953
954/**
955 * Applies a coefficient-wise reduce operation to two matrices.
956 *
957 * @param lhs The left-hand side of the binary operator.
958 * @param rhs The right-hand side of the binary operator.
959 * @param binaryOp The binary operator to use for the reduce operation.
960 */
962 const VariableMatrix& lhs, const VariableMatrix& rhs,
963 function_ref<Variable(const Variable& x, const Variable& y)> binaryOp) {
964 Assert(lhs.Rows() == rhs.Rows());
965 Assert(lhs.Rows() == rhs.Rows());
966
967 VariableMatrix result{lhs.Rows(), lhs.Cols()};
968
969 for (int row = 0; row < lhs.Rows(); ++row) {
970 for (int col = 0; col < lhs.Cols(); ++col) {
971 result(row, col) = binaryOp(lhs(row, col), rhs(row, col));
972 }
973 }
974
975 return result;
976}
977
978/**
979 * Assemble a VariableMatrix from a nested list of blocks.
980 *
981 * Each row's blocks must have the same height, and the assembled block rows
982 * must have the same width. For example, for the block matrix [[A, B], [C]] to
983 * be constructible, the number of rows in A and B must match, and the number of
984 * columns in [A, B] and [C] must match.
985 *
986 * @param list The nested list of blocks.
987 */
989 std::initializer_list<std::initializer_list<VariableMatrix>> list) {
990 // Get row and column counts for destination matrix
991 int rows = 0;
992 int cols = -1;
993 for (const auto& row : list) {
994 if (row.size() > 0) {
995 rows += row.begin()->Rows();
996 }
997
998 // Get number of columns in this row
999 int latestCols = 0;
1000 for (const auto& elem : row) {
1001 // Assert the first and latest row have the same height
1002 Assert(row.begin()->Rows() == elem.Rows());
1003
1004 latestCols += elem.Cols();
1005 }
1006
1007 // If this is the first row, record the column count. Otherwise, assert the
1008 // first and latest column counts are the same.
1009 if (cols == -1) {
1010 cols = latestCols;
1011 } else {
1012 Assert(cols == latestCols);
1013 }
1014 }
1015
1016 VariableMatrix result{rows, cols};
1017
1018 int rowOffset = 0;
1019 for (const auto& row : list) {
1020 int colOffset = 0;
1021 for (const auto& elem : row) {
1022 result.Block(rowOffset, colOffset, elem.Rows(), elem.Cols()) = elem;
1023 colOffset += elem.Cols();
1024 }
1025 rowOffset += row.begin()->Rows();
1026 }
1027
1028 return result;
1029}
1030
1031/**
1032 * Assemble a VariableMatrix from a nested list of blocks.
1033 *
1034 * Each row's blocks must have the same height, and the assembled block rows
1035 * must have the same width. For example, for the block matrix [[A, B], [C]] to
1036 * be constructible, the number of rows in A and B must match, and the number of
1037 * columns in [A, B] and [C] must match.
1038 *
1039 * This overload is for Python bindings only.
1040 *
1041 * @param list The nested list of blocks.
1042 */
1044 const std::vector<std::vector<VariableMatrix>>& list) {
1045 // Get row and column counts for destination matrix
1046 int rows = 0;
1047 int cols = -1;
1048 for (const auto& row : list) {
1049 if (row.size() > 0) {
1050 rows += row.begin()->Rows();
1051 }
1052
1053 // Get number of columns in this row
1054 int latestCols = 0;
1055 for (const auto& elem : row) {
1056 // Assert the first and latest row have the same height
1057 Assert(row.begin()->Rows() == elem.Rows());
1058
1059 latestCols += elem.Cols();
1060 }
1061
1062 // If this is the first row, record the column count. Otherwise, assert the
1063 // first and latest column counts are the same.
1064 if (cols == -1) {
1065 cols = latestCols;
1066 } else {
1067 Assert(cols == latestCols);
1068 }
1069 }
1070
1071 VariableMatrix result{rows, cols};
1072
1073 int rowOffset = 0;
1074 for (const auto& row : list) {
1075 int colOffset = 0;
1076 for (const auto& elem : row) {
1077 result.Block(rowOffset, colOffset, elem.Rows(), elem.Cols()) = elem;
1078 colOffset += elem.Cols();
1079 }
1080 rowOffset += row.begin()->Rows();
1081 }
1082
1083 return result;
1084}
1085
1086/**
1087 * Solves the VariableMatrix equation AX = B for X.
1088 *
1089 * @param A The left-hand side.
1090 * @param B The right-hand side.
1091 * @return The solution X.
1092 */
1094 const VariableMatrix& B);
1095
1096} // namespace sleipnir
This file defines the SmallVector class.
#define SLEIPNIR_DLLEXPORT
Definition SymbolExports.hpp:34
Definition Slice.hpp:21
constexpr int Adjust(int length)
Adjusts start and end slice indices assuming a sequence of the specified length.
Definition Slice.hpp:118
A submatrix of autodiff variables with reference semantics.
Definition VariableBlock.hpp:24
An autodiff variable pointing to an expression node.
Definition Variable.hpp:31
Definition VariableMatrix.hpp:848
std::forward_iterator_tag iterator_category
Definition VariableMatrix.hpp:850
const_iterator(const VariableMatrix *mat, int row, int col)
Definition VariableMatrix.hpp:856
std::ptrdiff_t difference_type
Definition VariableMatrix.hpp:852
bool operator==(const const_iterator &) const =default
const_iterator & operator++()
Definition VariableMatrix.hpp:859
const_reference operator*() const
Definition VariableMatrix.hpp:873
const_iterator operator++(int)
Definition VariableMatrix.hpp:867
Definition VariableMatrix.hpp:815
reference operator*()
Definition VariableMatrix.hpp:840
std::ptrdiff_t difference_type
Definition VariableMatrix.hpp:819
bool operator==(const iterator &) const =default
iterator & operator++()
Definition VariableMatrix.hpp:826
std::forward_iterator_tag iterator_category
Definition VariableMatrix.hpp:817
iterator operator++(int)
Definition VariableMatrix.hpp:834
iterator(VariableMatrix *mat, int row, int col)
Definition VariableMatrix.hpp:823
A matrix of autodiff variables.
Definition VariableMatrix.hpp:28
int Cols() const
Returns number of columns in the matrix.
Definition VariableMatrix.hpp:758
friend SLEIPNIR_DLLEXPORT VariableMatrix operator*(double lhs, const VariableMatrix &rhs)
Scalar-matrix multiplication operator.
Definition VariableMatrix.hpp:581
double Value(int row, int col)
Returns an element of the variable matrix.
Definition VariableMatrix.hpp:766
friend SLEIPNIR_DLLEXPORT VariableMatrix operator/(const VariableMatrix &lhs, const Variable &rhs)
Binary division operator (only enabled when rhs is a scalar).
Definition VariableMatrix.hpp:612
VariableBlock< VariableMatrix > Col(int col)
Returns a column slice of the variable matrix.
Definition VariableMatrix.hpp:485
VariableMatrix(const std::vector< std::vector< Variable > > &list)
Constructs a scalar VariableMatrix from a nested list of Variables.
Definition VariableMatrix.hpp:120
const Variable & operator()(int row) const
Returns a block pointing to the given row.
Definition VariableMatrix.hpp:332
VariableMatrix & operator*=(const VariableMatrix &rhs)
Compound matrix multiplication-assignment operator.
Definition VariableMatrix.hpp:590
VariableMatrix(const Variable &variable)
Constructs a scalar VariableMatrix from a Variable.
Definition VariableMatrix.hpp:220
VariableMatrix(std::span< const Variable > values)
Constructs a column vector wrapper around a Variable array.
Definition VariableMatrix.hpp:267
VariableBlock< VariableMatrix > operator()(Slice rowSlice, Slice colSlice)
Returns a slice of the variable matrix.
Definition VariableMatrix.hpp:378
friend SLEIPNIR_DLLEXPORT VariableMatrix operator*(const VariableMatrix &lhs, const VariableMatrix &rhs)
Matrix multiplication operator.
Definition VariableMatrix.hpp:507
const VariableBlock< const VariableMatrix > Segment(int offset, int length) const
Returns a segment of the variable vector.
Definition VariableMatrix.hpp:453
static VariableMatrix Zero(int rows, int cols)
Returns a variable matrix filled with zeroes.
Definition VariableMatrix.hpp:922
friend SLEIPNIR_DLLEXPORT VariableMatrix operator*(const VariableMatrix &lhs, double rhs)
Matrix-scalar multiplication operator.
Definition VariableMatrix.hpp:550
static VariableMatrix Ones(int rows, int cols)
Returns a variable matrix filled with ones.
Definition VariableMatrix.hpp:938
iterator begin()
Returns begin iterator.
Definition VariableMatrix.hpp:884
Variable & operator()(int row, int col)
Returns a block pointing to the given row and column.
Definition VariableMatrix.hpp:299
const VariableBlock< const VariableMatrix > operator()(Slice rowSlice, Slice colSlice) const
Returns a slice of the variable matrix.
Definition VariableMatrix.hpp:391
VariableMatrix(int rows, int cols)
Constructs a VariableMatrix with the given dimensions.
Definition VariableMatrix.hpp:52
friend SLEIPNIR_DLLEXPORT VariableMatrix operator*(const Variable &lhs, const VariableMatrix &rhs)
Scalar-matrix multiplication operator.
Definition VariableMatrix.hpp:562
VariableMatrix()=default
Constructs an empty VariableMatrix.
VariableMatrix(const VariableBlock< const VariableMatrix > &values)
Constructs a VariableMatrix from a VariableBlock.
Definition VariableMatrix.hpp:253
VariableMatrix & operator=(const Eigen::MatrixBase< Derived > &values)
Assigns an Eigen matrix to a VariableMatrix.
Definition VariableMatrix.hpp:184
VariableMatrix(Variable &&variable)
Constructs a scalar VariableMatrix from a Variable.
Definition VariableMatrix.hpp:230
Eigen::MatrixXd Value()
Returns the contents of the variable matrix.
Definition VariableMatrix.hpp:785
const VariableBlock< const VariableMatrix > Block(int rowOffset, int colOffset, int blockRows, int blockCols) const
Returns a block of the variable matrix.
Definition VariableMatrix.hpp:362
VariableMatrix(const Eigen::DiagonalBase< Derived > &values)
Constructs a VariableMatrix from an Eigen diagonal matrix.
Definition VariableMatrix.hpp:163
VariableMatrix(std::initializer_list< std::initializer_list< Variable > > list)
Constructs a scalar VariableMatrix from a nested list of Variables.
Definition VariableMatrix.hpp:65
const_iterator begin() const
Returns begin iterator.
Definition VariableMatrix.hpp:894
VariableMatrix T() const
Returns the transpose of the variable matrix.
Definition VariableMatrix.hpp:738
VariableBlock< VariableMatrix > Block(int rowOffset, int colOffset, int blockRows, int blockCols)
Returns a block of the variable matrix.
Definition VariableMatrix.hpp:345
int Rows() const
Returns number of rows in the matrix.
Definition VariableMatrix.hpp:753
friend SLEIPNIR_DLLEXPORT VariableMatrix operator+(const VariableMatrix &lhs, const VariableMatrix &rhs)
Binary addition operator.
Definition VariableMatrix.hpp:648
VariableBlock< VariableMatrix > operator()(Slice rowSlice, int rowSliceLength, Slice colSlice, int colSliceLength)
Returns a slice of the variable matrix.
Definition VariableMatrix.hpp:411
VariableMatrix(std::span< const Variable > values, int rows, int cols)
Constructs a matrix wrapper around a Variable array.
Definition VariableMatrix.hpp:283
size_t size() const
Returns number of elements in matrix.
Definition VariableMatrix.hpp:914
const Variable & operator()(int row, int col) const
Returns a block pointing to the given row and column.
Definition VariableMatrix.hpp:311
VariableMatrix(int rows)
Constructs a VariableMatrix column vector with the given rows.
Definition VariableMatrix.hpp:40
void SetValue(const Eigen::MatrixBase< Derived > &values)
Sets the VariableMatrix's internal values.
Definition VariableMatrix.hpp:204
const VariableBlock< const VariableMatrix > Col(int col) const
Returns a column slice of the variable matrix.
Definition VariableMatrix.hpp:495
VariableMatrix & operator/=(const Variable &rhs)
Compound matrix division-assignment operator (only enabled when rhs is a scalar).
Definition VariableMatrix.hpp:631
const_iterator cbegin() const
Returns begin iterator.
Definition VariableMatrix.hpp:904
VariableMatrix CwiseTransform(function_ref< Variable(const Variable &x)> unaryOp) const
Transforms the matrix coefficient-wise with an unary operator.
Definition VariableMatrix.hpp:802
VariableBlock< VariableMatrix > Segment(int offset, int length)
Returns a segment of the variable vector.
Definition VariableMatrix.hpp:441
VariableMatrix(const VariableBlock< VariableMatrix > &values)
Constructs a VariableMatrix from a VariableBlock.
Definition VariableMatrix.hpp:239
const VariableBlock< const VariableMatrix > Row(int row) const
Returns a row slice of the variable matrix.
Definition VariableMatrix.hpp:475
VariableMatrix & operator+=(const VariableMatrix &rhs)
Compound addition-assignment operator.
Definition VariableMatrix.hpp:665
const VariableBlock< const VariableMatrix > operator()(Slice rowSlice, int rowSliceLength, Slice colSlice, int colSliceLength) const
Returns a slice of the variable matrix.
Definition VariableMatrix.hpp:428
VariableMatrix & operator-=(const VariableMatrix &rhs)
Compound subtraction-assignment operator.
Definition VariableMatrix.hpp:699
VariableMatrix(const Eigen::MatrixBase< Derived > &values)
Constructs a VariableMatrix from an Eigen matrix.
Definition VariableMatrix.hpp:146
friend SLEIPNIR_DLLEXPORT VariableMatrix operator-(const VariableMatrix &lhs, const VariableMatrix &rhs)
Binary subtraction operator.
Definition VariableMatrix.hpp:682
iterator end()
Returns end iterator.
Definition VariableMatrix.hpp:889
double Value(int index)
Returns a row of the variable column vector.
Definition VariableMatrix.hpp:777
const_iterator end() const
Returns end iterator.
Definition VariableMatrix.hpp:899
friend SLEIPNIR_DLLEXPORT VariableMatrix operator*(const VariableMatrix &lhs, const Variable &rhs)
Matrix-scalar multiplication operator.
Definition VariableMatrix.hpp:531
VariableMatrix(const std::vector< std::vector< double > > &list)
Constructs a scalar VariableMatrix from a nested list of doubles.
Definition VariableMatrix.hpp:93
VariableBlock< VariableMatrix > Row(int row)
Returns a row slice of the variable matrix.
Definition VariableMatrix.hpp:465
Variable & operator()(int row)
Returns a block pointing to the given row.
Definition VariableMatrix.hpp:322
friend SLEIPNIR_DLLEXPORT VariableMatrix operator-(const VariableMatrix &lhs)
Unary minus operator.
Definition VariableMatrix.hpp:715
const_iterator cend() const
Returns end iterator.
Definition VariableMatrix.hpp:909
An implementation of std::function_ref, a lightweight non-owning reference to a callable.
Definition FunctionRef.hpp:17
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition SmallVector.h:1212
Definition Hessian.hpp:18
SLEIPNIR_DLLEXPORT VariableMatrix Solve(const VariableMatrix &A, const VariableMatrix &B)
Solves the VariableMatrix equation AX = B for X.
SLEIPNIR_DLLEXPORT VariableMatrix CwiseReduce(const VariableMatrix &lhs, const VariableMatrix &rhs, function_ref< Variable(const Variable &x, const Variable &y)> binaryOp)
Applies a coefficient-wise reduce operation to two matrices.
Definition VariableMatrix.hpp:961
SLEIPNIR_DLLEXPORT VariableMatrix Block(std::initializer_list< std::initializer_list< VariableMatrix > > list)
Assemble a VariableMatrix from a nested list of blocks.
Definition VariableMatrix.hpp:988
#define Assert(condition)
Abort in C++.
Definition Assert.hpp:24