WPILibC++ 2027.0.0-alpha-2
Loading...
Searching...
No Matches
variable_matrix.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 <gch/small_vector.hpp>
15
23
24namespace slp {
25
26/**
27 * A matrix of autodiff variables.
28 */
30 public:
31 /**
32 * Type tag used to designate an uninitialized VariableMatrix.
33 */
34 struct empty_t {};
35
36 /**
37 * Designates an uninitialized VariableMatrix.
38 */
39 static constexpr empty_t empty{};
40
41 /**
42 * Constructs an empty VariableMatrix.
43 */
44 VariableMatrix() = default;
45
46 /**
47 * Constructs a VariableMatrix column vector with the given rows.
48 *
49 * @param rows The number of matrix rows.
50 */
51 explicit VariableMatrix(int rows) : m_rows{rows}, m_cols{1} {
52 m_storage.reserve(rows);
53 for (int row = 0; row < rows; ++row) {
54 m_storage.emplace_back();
55 }
56 }
57
58 /**
59 * Constructs a zero-initialized VariableMatrix with the given dimensions.
60 *
61 * @param rows The number of matrix rows.
62 * @param cols The number of matrix columns.
63 */
64 VariableMatrix(int rows, int cols) : m_rows{rows}, m_cols{cols} {
65 m_storage.reserve(rows * cols);
66 for (int index = 0; index < rows * cols; ++index) {
67 m_storage.emplace_back();
68 }
69 }
70
71 /**
72 * Constructs an empty VariableMatrix with the given dimensions.
73 *
74 * @param rows The number of matrix rows.
75 * @param cols The number of matrix columns.
76 */
77 VariableMatrix(empty_t, int rows, int cols) : m_rows{rows}, m_cols{cols} {
78 m_storage.reserve(rows * cols);
79 for (int index = 0; index < rows * cols; ++index) {
80 m_storage.emplace_back(nullptr);
81 }
82 }
83
84 /**
85 * Constructs a scalar VariableMatrix from a nested list of Variables.
86 *
87 * @param list The nested list of Variables.
88 */
89 VariableMatrix( // NOLINT
90 std::initializer_list<std::initializer_list<Variable>> list) {
91 // Get row and column counts for destination matrix
92 m_rows = list.size();
93 m_cols = 0;
94 if (list.size() > 0) {
95 m_cols = list.begin()->size();
96 }
97
98 // Assert the first and latest column counts are the same
99 for ([[maybe_unused]]
100 const auto& row : list) {
101 slp_assert(list.begin()->size() == row.size());
102 }
103
104 m_storage.reserve(rows() * cols());
105 for (const auto& row : list) {
106 std::ranges::copy(row, std::back_inserter(m_storage));
107 }
108 }
109
110 /**
111 * Constructs a scalar VariableMatrix from a nested list of doubles.
112 *
113 * This overload is for Python bindings only.
114 *
115 * @param list The nested list of Variables.
116 */
117 VariableMatrix(const std::vector<std::vector<double>>& list) { // NOLINT
118 // Get row and column counts for destination matrix
119 m_rows = list.size();
120 m_cols = 0;
121 if (list.size() > 0) {
122 m_cols = list.begin()->size();
123 }
124
125 // Assert the first and latest column counts are the same
126 for ([[maybe_unused]]
127 const auto& row : list) {
128 slp_assert(list.begin()->size() == row.size());
129 }
130
131 m_storage.reserve(rows() * cols());
132 for (const auto& row : list) {
133 std::ranges::copy(row, std::back_inserter(m_storage));
134 }
135 }
136
137 /**
138 * Constructs a scalar VariableMatrix from a nested list of Variables.
139 *
140 * This overload is for Python bindings only.
141 *
142 * @param list The nested list of Variables.
143 */
144 VariableMatrix(const std::vector<std::vector<Variable>>& list) { // NOLINT
145 // Get row and column counts for destination matrix
146 m_rows = list.size();
147 m_cols = 0;
148 if (list.size() > 0) {
149 m_cols = list.begin()->size();
150 }
151
152 // Assert the first and latest column counts are the same
153 for ([[maybe_unused]]
154 const auto& row : list) {
155 slp_assert(list.begin()->size() == row.size());
156 }
157
158 m_storage.reserve(rows() * cols());
159 for (const auto& row : list) {
160 std::ranges::copy(row, std::back_inserter(m_storage));
161 }
162 }
163
164 /**
165 * Constructs a VariableMatrix from an Eigen matrix.
166 *
167 * @param values Eigen matrix of values.
168 */
169 template <typename Derived>
170 VariableMatrix(const Eigen::MatrixBase<Derived>& values) // NOLINT
171 : m_rows{static_cast<int>(values.rows())},
172 m_cols{static_cast<int>(values.cols())} {
173 m_storage.reserve(values.rows() * values.cols());
174 for (int row = 0; row < values.rows(); ++row) {
175 for (int col = 0; col < values.cols(); ++col) {
176 m_storage.emplace_back(values(row, col));
177 }
178 }
179 }
180
181 /**
182 * Constructs a VariableMatrix from an Eigen diagonal matrix.
183 *
184 * @param values Diagonal matrix of values.
185 */
186 template <typename Derived>
187 VariableMatrix(const Eigen::DiagonalBase<Derived>& values) // NOLINT
188 : m_rows{static_cast<int>(values.rows())},
189 m_cols{static_cast<int>(values.cols())} {
190 m_storage.reserve(values.rows() * values.cols());
191 for (int row = 0; row < values.rows(); ++row) {
192 for (int col = 0; col < values.cols(); ++col) {
193 if (row == col) {
194 m_storage.emplace_back(values.diagonal()[row]);
195 } else {
196 m_storage.emplace_back(0.0);
197 }
198 }
199 }
200 }
201
202 /**
203 * Assigns an Eigen matrix to a VariableMatrix.
204 *
205 * @param values Eigen matrix of values.
206 * @return This VariableMatrix.
207 */
208 template <typename Derived>
209 VariableMatrix& operator=(const Eigen::MatrixBase<Derived>& values) {
210 slp_assert(rows() == values.rows() && cols() == values.cols());
211
212 for (int row = 0; row < values.rows(); ++row) {
213 for (int col = 0; col < values.cols(); ++col) {
214 (*this)(row, col) = values(row, col);
215 }
216 }
217
218 return *this;
219 }
220
221 /**
222 * Assigns a double to the matrix.
223 *
224 * This only works for matrices with one row and one column.
225 *
226 * @param value Value to assign.
227 * @return This VariableMatrix.
228 */
230 slp_assert(rows() == 1 && cols() == 1);
231
232 (*this)(0, 0) = value;
233
234 return *this;
235 }
236
237 /**
238 * Sets the VariableMatrix's internal values.
239 *
240 * @param values Eigen matrix of values.
241 */
242 template <typename Derived>
243 requires std::same_as<typename Derived::Scalar, double>
244 void set_value(const Eigen::MatrixBase<Derived>& values) {
245 slp_assert(rows() == values.rows() && cols() == values.cols());
246
247 for (int row = 0; row < values.rows(); ++row) {
248 for (int col = 0; col < values.cols(); ++col) {
249 (*this)(row, col).set_value(values(row, col));
250 }
251 }
252 }
253
254 /**
255 * Constructs a scalar VariableMatrix from a Variable.
256 *
257 * @param variable Variable.
258 */
259 VariableMatrix(const Variable& variable) // NOLINT
260 : m_rows{1}, m_cols{1} {
261 m_storage.emplace_back(variable);
262 }
263
264 /**
265 * Constructs a scalar VariableMatrix from a Variable.
266 *
267 * @param variable Variable.
268 */
269 VariableMatrix(Variable&& variable) : m_rows{1}, m_cols{1} { // NOLINT
270 m_storage.emplace_back(std::move(variable));
271 }
272
273 /**
274 * Constructs a VariableMatrix from a VariableBlock.
275 *
276 * @param values VariableBlock of values.
277 */
279 : m_rows{values.rows()}, m_cols{values.cols()} {
280 m_storage.reserve(rows() * cols());
281 for (int row = 0; row < rows(); ++row) {
282 for (int col = 0; col < cols(); ++col) {
283 m_storage.emplace_back(values(row, col));
284 }
285 }
286 }
287
288 /**
289 * Constructs a VariableMatrix from a VariableBlock.
290 *
291 * @param values VariableBlock of values.
292 */
294 : m_rows{values.rows()}, m_cols{values.cols()} {
295 m_storage.reserve(rows() * cols());
296 for (int row = 0; row < rows(); ++row) {
297 for (int col = 0; col < cols(); ++col) {
298 m_storage.emplace_back(values(row, col));
299 }
300 }
301 }
302
303 /**
304 * Constructs a column vector wrapper around a Variable array.
305 *
306 * @param values Variable array to wrap.
307 */
308 explicit VariableMatrix(std::span<const Variable> values)
309 : m_rows{static_cast<int>(values.size())}, m_cols{1} {
310 m_storage.reserve(rows() * cols());
311 for (int row = 0; row < rows(); ++row) {
312 for (int col = 0; col < cols(); ++col) {
313 m_storage.emplace_back(values[row * cols() + col]);
314 }
315 }
316 }
317
318 /**
319 * Constructs a matrix wrapper around a Variable array.
320 *
321 * @param values Variable array to wrap.
322 * @param rows The number of matrix rows.
323 * @param cols The number of matrix columns.
324 */
325 VariableMatrix(std::span<const Variable> values, int rows, int cols)
326 : m_rows{rows}, m_cols{cols} {
327 slp_assert(static_cast<int>(values.size()) == rows * cols);
328 m_storage.reserve(rows * cols);
329 for (int row = 0; row < rows; ++row) {
330 for (int col = 0; col < cols; ++col) {
331 m_storage.emplace_back(values[row * cols + col]);
332 }
333 }
334 }
335
336 /**
337 * Returns a block pointing to the given row and column.
338 *
339 * @param row The block row.
340 * @param col The block column.
341 * @return A block pointing to the given row and column.
342 */
343 Variable& operator()(int row, int col) {
344 slp_assert(row >= 0 && row < rows());
345 slp_assert(col >= 0 && col < cols());
346 return m_storage[row * cols() + col];
347 }
348
349 /**
350 * Returns a block pointing to the given row and column.
351 *
352 * @param row The block row.
353 * @param col The block column.
354 * @return A block pointing to the given row and column.
355 */
356 const Variable& operator()(int row, int col) const {
357 slp_assert(row >= 0 && row < rows());
358 slp_assert(col >= 0 && col < cols());
359 return m_storage[row * cols() + col];
360 }
361
362 /**
363 * Returns a block pointing to the given row.
364 *
365 * @param row The block row.
366 * @return A block pointing to the given row.
367 */
369 slp_assert(row >= 0 && row < rows() * cols());
370 return m_storage[row];
371 }
372
373 /**
374 * Returns a block pointing to the given row.
375 *
376 * @param row The block row.
377 * @return A block pointing to the given row.
378 */
379 const Variable& operator[](int row) const {
380 slp_assert(row >= 0 && row < rows() * cols());
381 return m_storage[row];
382 }
383
384 /**
385 * Returns a block of the variable matrix.
386 *
387 * @param row_offset The row offset of the block selection.
388 * @param col_offset The column offset of the block selection.
389 * @param block_rows The number of rows in the block selection.
390 * @param block_cols The number of columns in the block selection.
391 * @return A block of the variable matrix.
392 */
393 VariableBlock<VariableMatrix> block(int row_offset, int col_offset,
394 int block_rows, int block_cols) {
395 slp_assert(row_offset >= 0 && row_offset <= rows());
396 slp_assert(col_offset >= 0 && col_offset <= cols());
397 slp_assert(block_rows >= 0 && block_rows <= rows() - row_offset);
398 slp_assert(block_cols >= 0 && block_cols <= cols() - col_offset);
399 return VariableBlock{*this, row_offset, col_offset, block_rows, block_cols};
400 }
401
402 /**
403 * Returns a block of the variable matrix.
404 *
405 * @param row_offset The row offset of the block selection.
406 * @param col_offset The column offset of the block selection.
407 * @param block_rows The number of rows in the block selection.
408 * @param block_cols The number of columns in the block selection.
409 * @return A block of the variable matrix.
410 */
412 int col_offset,
413 int block_rows,
414 int block_cols) const {
415 slp_assert(row_offset >= 0 && row_offset <= rows());
416 slp_assert(col_offset >= 0 && col_offset <= cols());
417 slp_assert(block_rows >= 0 && block_rows <= rows() - row_offset);
418 slp_assert(block_cols >= 0 && block_cols <= cols() - col_offset);
419 return VariableBlock{*this, row_offset, col_offset, block_rows, block_cols};
420 }
421
422 /**
423 * Returns a slice of the variable matrix.
424 *
425 * @param row_slice The row slice.
426 * @param col_slice The column slice.
427 * @return A slice of the variable matrix.
428 */
430 int row_slice_length = row_slice.adjust(rows());
431 int col_slice_length = col_slice.adjust(cols());
432 return VariableBlock{*this, std::move(row_slice), row_slice_length,
433 std::move(col_slice), col_slice_length};
434 }
435
436 /**
437 * Returns a slice of the variable matrix.
438 *
439 * @param row_slice The row slice.
440 * @param col_slice The column slice.
441 * @return A slice of the variable matrix.
442 */
444 Slice col_slice) const {
445 int row_slice_length = row_slice.adjust(rows());
446 int col_slice_length = col_slice.adjust(cols());
447 return VariableBlock{*this, std::move(row_slice), row_slice_length,
448 std::move(col_slice), col_slice_length};
449 }
450
451 /**
452 * Returns a slice of the variable matrix.
453 *
454 * The given slices aren't adjusted. This overload is for Python bindings
455 * only.
456 *
457 * @param row_slice The row slice.
458 * @param row_slice_length The row slice length.
459 * @param col_slice The column slice.
460 * @param col_slice_length The column slice length.
461 * @return A slice of the variable matrix.
462 *
463 */
465 int row_slice_length,
466 Slice col_slice,
467 int col_slice_length) {
468 return VariableBlock{*this, std::move(row_slice), row_slice_length,
469 std::move(col_slice), col_slice_length};
470 }
471
472 /**
473 * Returns a slice of the variable matrix.
474 *
475 * The given slices aren't adjusted. This overload is for Python bindings
476 * only.
477 *
478 * @param row_slice The row slice.
479 * @param row_slice_length The row slice length.
480 * @param col_slice The column slice.
481 * @param col_slice_length The column slice length.
482 * @return A slice of the variable matrix.
483 */
485 Slice row_slice, int row_slice_length, Slice col_slice,
486 int col_slice_length) const {
487 return VariableBlock{*this, std::move(row_slice), row_slice_length,
488 std::move(col_slice), col_slice_length};
489 }
490
491 /**
492 * Returns a segment of the variable vector.
493 *
494 * @param offset The offset of the segment.
495 * @param length The length of the segment.
496 * @return A segment of the variable vector.
497 */
498 VariableBlock<VariableMatrix> segment(int offset, int length) {
499 slp_assert(offset >= 0 && offset < rows() * cols());
500 slp_assert(length >= 0 && length <= rows() * cols() - offset);
501 return block(offset, 0, length, 1);
502 }
503
504 /**
505 * Returns a segment of the variable vector.
506 *
507 * @param offset The offset of the segment.
508 * @param length The length of the segment.
509 * @return A segment of the variable vector.
510 */
512 int length) const {
513 slp_assert(offset >= 0 && offset < rows() * cols());
514 slp_assert(length >= 0 && length <= rows() * cols() - offset);
515 return block(offset, 0, length, 1);
516 }
517
518 /**
519 * Returns a row slice of the variable matrix.
520 *
521 * @param row The row to slice.
522 * @return A row slice of the variable matrix.
523 */
525 slp_assert(row >= 0 && row < rows());
526 return block(row, 0, 1, cols());
527 }
528
529 /**
530 * Returns a row slice of the variable matrix.
531 *
532 * @param row The row to slice.
533 * @return A row slice of the variable matrix.
534 */
536 slp_assert(row >= 0 && row < rows());
537 return block(row, 0, 1, cols());
538 }
539
540 /**
541 * Returns a column slice of the variable matrix.
542 *
543 * @param col The column to slice.
544 * @return A column slice of the variable matrix.
545 */
547 slp_assert(col >= 0 && col < cols());
548 return block(0, col, rows(), 1);
549 }
550
551 /**
552 * Returns a column slice of the variable matrix.
553 *
554 * @param col The column to slice.
555 * @return A column slice of the variable matrix.
556 */
558 slp_assert(col >= 0 && col < cols());
559 return block(0, col, rows(), 1);
560 }
561
562 /**
563 * Matrix multiplication operator.
564 *
565 * @param lhs Operator left-hand side.
566 * @param rhs Operator right-hand side.
567 */
568 template <MatrixLike LHS, MatrixLike RHS>
571 const RHS& rhs) {
572 slp_assert(lhs.cols() == rhs.rows());
573
574 VariableMatrix result(VariableMatrix::empty, lhs.rows(), rhs.cols());
575
576#if __GNUC__ >= 12
577#pragma GCC diagnostic push
578#pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
579#endif
580 for (int i = 0; i < lhs.rows(); ++i) {
581 for (int j = 0; j < rhs.cols(); ++j) {
582 Variable sum;
583 for (int k = 0; k < lhs.cols(); ++k) {
584 sum += lhs(i, k) * rhs(k, j);
585 }
586 result(i, j) = sum;
587 }
588 }
589#if __GNUC__ >= 12
590#pragma GCC diagnostic pop
591#endif
592
593 return result;
594 }
595
596 /**
597 * Matrix-scalar multiplication operator.
598 *
599 * @param lhs Operator left-hand side.
600 * @param rhs Operator right-hand side.
601 */
603 operator*(const SleipnirMatrixLike auto& lhs, const ScalarLike auto& rhs) {
604 VariableMatrix result{VariableMatrix::empty, lhs.rows(), lhs.cols()};
605
606 for (int row = 0; row < result.rows(); ++row) {
607 for (int col = 0; col < result.cols(); ++col) {
608 result(row, col) = lhs(row, col) * rhs;
609 }
610 }
611
612 return result;
613 }
614
615 /**
616 * Matrix-scalar multiplication operator.
617 *
618 * @param lhs Operator left-hand side.
619 * @param rhs Operator right-hand side.
620 */
622 const Variable& rhs) {
623 VariableMatrix result(VariableMatrix::empty, lhs.rows(), lhs.cols());
624
625 for (int row = 0; row < result.rows(); ++row) {
626 for (int col = 0; col < result.cols(); ++col) {
627 result(row, col) = lhs(row, col) * rhs;
628 }
629 }
630
631 return result;
632 }
633
634 /**
635 * Scalar-matrix multiplication operator.
636 *
637 * @param lhs Operator left-hand side.
638 * @param rhs Operator right-hand side.
639 */
641 operator*(const ScalarLike auto& lhs, const SleipnirMatrixLike auto& rhs) {
642 VariableMatrix result{VariableMatrix::empty, rhs.rows(), rhs.cols()};
643
644 for (int row = 0; row < result.rows(); ++row) {
645 for (int col = 0; col < result.cols(); ++col) {
646 result(row, col) = rhs(row, col) * lhs;
647 }
648 }
649
650 return result;
651 }
652
653 /**
654 * Scalar-matrix multiplication operator.
655 *
656 * @param lhs Operator left-hand side.
657 * @param rhs Operator right-hand side.
658 */
660 operator*(const Variable& lhs, const MatrixLike auto& rhs) {
661 VariableMatrix result(VariableMatrix::empty, rhs.rows(), rhs.cols());
662
663 for (int row = 0; row < result.rows(); ++row) {
664 for (int col = 0; col < result.cols(); ++col) {
665 result(row, col) = rhs(row, col) * lhs;
666 }
667 }
668
669 return result;
670 }
671
672 /**
673 * Compound matrix multiplication-assignment operator.
674 *
675 * @param rhs Variable to multiply.
676 * @return Result of multiplication.
677 */
679 slp_assert(cols() == rhs.rows() && cols() == rhs.cols());
680
681 for (int i = 0; i < rows(); ++i) {
682 for (int j = 0; j < rhs.cols(); ++j) {
683 Variable sum;
684 for (int k = 0; k < cols(); ++k) {
685 sum += (*this)(i, k) * rhs(k, j);
686 }
687 (*this)(i, j) = sum;
688 }
689 }
690
691 return *this;
692 }
693
694 /**
695 * Compound matrix-scalar multiplication-assignment operator.
696 *
697 * @param rhs Variable to multiply.
698 * @return Result of multiplication.
699 */
701 for (int row = 0; row < rows(); ++row) {
702 for (int col = 0; col < rhs.cols(); ++col) {
703 (*this)(row, col) *= rhs;
704 }
705 }
706
707 return *this;
708 }
709
710 /**
711 * Binary division operator.
712 *
713 * @param lhs Operator left-hand side.
714 * @param rhs Operator right-hand side.
715 * @return Result of division.
716 */
718 operator/(const MatrixLike auto& lhs, const ScalarLike auto& rhs) {
719 VariableMatrix result(VariableMatrix::empty, lhs.rows(), lhs.cols());
720
721 for (int row = 0; row < result.rows(); ++row) {
722 for (int col = 0; col < result.cols(); ++col) {
723 result(row, col) = lhs(row, col) / rhs;
724 }
725 }
726
727 return result;
728 }
729
730 /**
731 * Compound matrix division-assignment operator.
732 *
733 * @param rhs Variable to divide.
734 * @return Result of division.
735 */
737 for (int row = 0; row < rows(); ++row) {
738 for (int col = 0; col < cols(); ++col) {
739 (*this)(row, col) /= rhs;
740 }
741 }
742
743 return *this;
744 }
745
746 /**
747 * Binary addition operator.
748 *
749 * @param lhs Operator left-hand side.
750 * @param rhs Operator right-hand side.
751 * @return Result of addition.
752 */
753 template <MatrixLike LHS, MatrixLike RHS>
756 const RHS& rhs) {
757 slp_assert(lhs.rows() == rhs.rows() && lhs.cols() == rhs.cols());
758
759 VariableMatrix result(VariableMatrix::empty, lhs.rows(), lhs.cols());
760
761 for (int row = 0; row < result.rows(); ++row) {
762 for (int col = 0; col < result.cols(); ++col) {
763 result(row, col) = lhs(row, col) + rhs(row, col);
764 }
765 }
766
767 return result;
768 }
769
770 /**
771 * Compound addition-assignment operator.
772 *
773 * @param rhs Variable to add.
774 * @return Result of addition.
775 */
777 slp_assert(rows() == rhs.rows() && cols() == rhs.cols());
778
779 for (int row = 0; row < rows(); ++row) {
780 for (int col = 0; col < cols(); ++col) {
781 (*this)(row, col) += rhs(row, col);
782 }
783 }
784
785 return *this;
786 }
787
788 /**
789 * Compound addition-assignment operator.
790 *
791 * @param rhs Variable to add.
792 * @return Result of addition.
793 */
795 slp_assert(rows() == 1 && cols() == 1);
796
797 for (int row = 0; row < rows(); ++row) {
798 for (int col = 0; col < cols(); ++col) {
799 (*this)(row, col) += rhs;
800 }
801 }
802
803 return *this;
804 }
805
806 /**
807 * Binary subtraction operator.
808 *
809 * @param lhs Operator left-hand side.
810 * @param rhs Operator right-hand side.
811 * @return Result of subtraction.
812 */
813 template <MatrixLike LHS, MatrixLike RHS>
816 const RHS& rhs) {
817 slp_assert(lhs.rows() == rhs.rows() && lhs.cols() == rhs.cols());
818
819 VariableMatrix result(VariableMatrix::empty, lhs.rows(), lhs.cols());
820
821 for (int row = 0; row < result.rows(); ++row) {
822 for (int col = 0; col < result.cols(); ++col) {
823 result(row, col) = lhs(row, col) - rhs(row, col);
824 }
825 }
826
827 return result;
828 }
829
830 /**
831 * Compound subtraction-assignment operator.
832 *
833 * @param rhs Variable to subtract.
834 * @return Result of subtraction.
835 */
837 slp_assert(rows() == rhs.rows() && cols() == rhs.cols());
838
839 for (int row = 0; row < rows(); ++row) {
840 for (int col = 0; col < cols(); ++col) {
841 (*this)(row, col) -= rhs(row, col);
842 }
843 }
844
845 return *this;
846 }
847
848 /**
849 * Compound subtraction-assignment operator.
850 *
851 * @param rhs Variable to subtract.
852 * @return Result of subtraction.
853 */
855 slp_assert(rows() == 1 && cols() == 1);
856
857 for (int row = 0; row < rows(); ++row) {
858 for (int col = 0; col < cols(); ++col) {
859 (*this)(row, col) -= rhs;
860 }
861 }
862
863 return *this;
864 }
865
866 /**
867 * Unary minus operator.
868 *
869 * @param lhs Operand for unary minus.
870 */
872 operator-(const SleipnirMatrixLike auto& lhs) {
873 VariableMatrix result{VariableMatrix::empty, lhs.rows(), lhs.cols()};
874
875 for (int row = 0; row < result.rows(); ++row) {
876 for (int col = 0; col < result.cols(); ++col) {
877 result(row, col) = -lhs(row, col);
878 }
879 }
880
881 return result;
882 }
883
884 /**
885 * Implicit conversion operator from 1x1 VariableMatrix to Variable.
886 */
887 operator Variable() const { // NOLINT
888 slp_assert(rows() == 1 && cols() == 1);
889 return (*this)(0, 0);
890 }
891
892 /**
893 * Returns the transpose of the variable matrix.
894 *
895 * @return The transpose of the variable matrix.
896 */
898 VariableMatrix result{VariableMatrix::empty, cols(), rows()};
899
900 for (int row = 0; row < rows(); ++row) {
901 for (int col = 0; col < cols(); ++col) {
902 result(col, row) = (*this)(row, col);
903 }
904 }
905
906 return result;
907 }
908
909 /**
910 * Returns the number of rows in the matrix.
911 *
912 * @return The number of rows in the matrix.
913 */
914 int rows() const { return m_rows; }
915
916 /**
917 * Returns the number of columns in the matrix.
918 *
919 * @return The number of columns in the matrix.
920 */
921 int cols() const { return m_cols; }
922
923 /**
924 * Returns an element of the variable matrix.
925 *
926 * @param row The row of the element to return.
927 * @param col The column of the element to return.
928 * @return An element of the variable matrix.
929 */
930 double value(int row, int col) {
931 slp_assert(row >= 0 && row < rows());
932 slp_assert(col >= 0 && col < cols());
933 return m_storage[row * cols() + col].value();
934 }
935
936 /**
937 * Returns a row of the variable column vector.
938 *
939 * @param index The index of the element to return.
940 * @return A row of the variable column vector.
941 */
942 double value(int index) {
943 slp_assert(index >= 0 && index < rows() * cols());
944 return m_storage[index].value();
945 }
946
947 /**
948 * Returns the contents of the variable matrix.
949 *
950 * @return The contents of the variable matrix.
951 */
952 Eigen::MatrixXd value() {
953 Eigen::MatrixXd result{rows(), cols()};
954
955 for (int row = 0; row < rows(); ++row) {
956 for (int col = 0; col < cols(); ++col) {
957 result(row, col) = value(row, col);
958 }
959 }
960
961 return result;
962 }
963
964 /**
965 * Transforms the matrix coefficient-wise with an unary operator.
966 *
967 * @param unary_op The unary operator to use for the transform operation.
968 * @return Result of the unary operator.
969 */
971 function_ref<Variable(const Variable& x)> unary_op) const {
972 VariableMatrix result{VariableMatrix::empty, rows(), cols()};
973
974 for (int row = 0; row < rows(); ++row) {
975 for (int col = 0; col < cols(); ++col) {
976 result(row, col) = unary_op((*this)(row, col));
977 }
978 }
979
980 return result;
981 }
982
983#ifndef DOXYGEN_SHOULD_SKIP_THIS
984
985 class iterator {
986 public:
987 using iterator_category = std::forward_iterator_tag;
989 using difference_type = std::ptrdiff_t;
992
993 constexpr iterator() noexcept = default;
994
995 explicit constexpr iterator(
996 gch::small_vector<Variable>::iterator it) noexcept
997 : m_it{it} {}
998
999 constexpr iterator& operator++() noexcept {
1000 ++m_it;
1001 return *this;
1002 }
1003
1004 constexpr iterator operator++(int) noexcept {
1005 iterator retval = *this;
1006 ++(*this);
1007 return retval;
1008 }
1009
1010 constexpr bool operator==(const iterator&) const noexcept = default;
1011
1012 constexpr reference operator*() const noexcept { return *m_it; }
1013
1014 private:
1016 };
1017
1019 public:
1020 using iterator_category = std::forward_iterator_tag;
1022 using difference_type = std::ptrdiff_t;
1025
1026 constexpr const_iterator() noexcept = default;
1027
1028 explicit constexpr const_iterator(
1029 gch::small_vector<Variable>::const_iterator it) noexcept
1030 : m_it{it} {}
1031
1032 constexpr const_iterator& operator++() noexcept {
1033 ++m_it;
1034 return *this;
1035 }
1036
1037 constexpr const_iterator operator++(int) noexcept {
1038 const_iterator retval = *this;
1039 ++(*this);
1040 return retval;
1041 }
1042
1043 constexpr bool operator==(const const_iterator&) const noexcept = default;
1044
1045 constexpr const_reference operator*() const noexcept { return *m_it; }
1046
1047 private:
1049 };
1050
1051#endif // DOXYGEN_SHOULD_SKIP_THIS
1052
1053 /**
1054 * Returns begin iterator.
1055 *
1056 * @return Begin iterator.
1057 */
1058 iterator begin() { return iterator{m_storage.begin()}; }
1059
1060 /**
1061 * Returns end iterator.
1062 *
1063 * @return End iterator.
1064 */
1065 iterator end() { return iterator{m_storage.end()}; }
1066
1067 /**
1068 * Returns begin iterator.
1069 *
1070 * @return Begin iterator.
1071 */
1072 const_iterator begin() const { return const_iterator{m_storage.begin()}; }
1073
1074 /**
1075 * Returns end iterator.
1076 *
1077 * @return End iterator.
1078 */
1079 const_iterator end() const { return const_iterator{m_storage.end()}; }
1080
1081 /**
1082 * Returns begin iterator.
1083 *
1084 * @return Begin iterator.
1085 */
1086 const_iterator cbegin() const { return const_iterator{m_storage.begin()}; }
1087
1088 /**
1089 * Returns end iterator.
1090 *
1091 * @return End iterator.
1092 */
1093 const_iterator cend() const { return const_iterator{m_storage.end()}; }
1094
1095 /**
1096 * Returns number of elements in matrix.
1097 *
1098 * @return Number of elements in matrix.
1099 */
1100 size_t size() const { return m_storage.size(); }
1101
1102 /**
1103 * Returns a variable matrix filled with zeroes.
1104 *
1105 * @param rows The number of matrix rows.
1106 * @param cols The number of matrix columns.
1107 * @return A variable matrix filled with zeroes.
1108 */
1109 static VariableMatrix zero(int rows, int cols) {
1110 VariableMatrix result{VariableMatrix::empty, rows, cols};
1111
1112 for (auto& elem : result) {
1113 elem = 0.0;
1114 }
1115
1116 return result;
1117 }
1118
1119 /**
1120 * Returns a variable matrix filled with ones.
1121 *
1122 * @param rows The number of matrix rows.
1123 * @param cols The number of matrix columns.
1124 * @return A variable matrix filled with ones.
1125 */
1126 static VariableMatrix ones(int rows, int cols) {
1127 VariableMatrix result{VariableMatrix::empty, rows, cols};
1128
1129 for (auto& elem : result) {
1130 elem = 1.0;
1131 }
1132
1133 return result;
1134 }
1135
1136 private:
1138 int m_rows = 0;
1139 int m_cols = 0;
1140};
1141
1142/**
1143 * Applies a coefficient-wise reduce operation to two matrices.
1144 *
1145 * @param lhs The left-hand side of the binary operator.
1146 * @param rhs The right-hand side of the binary operator.
1147 * @param binary_op The binary operator to use for the reduce operation.
1148 */
1150 const VariableMatrix& lhs, const VariableMatrix& rhs,
1151 function_ref<Variable(const Variable& x, const Variable& y)> binary_op) {
1152 slp_assert(lhs.rows() == rhs.rows() && lhs.rows() == rhs.rows());
1153
1154 VariableMatrix result{VariableMatrix::empty, lhs.rows(), lhs.cols()};
1155
1156 for (int row = 0; row < lhs.rows(); ++row) {
1157 for (int col = 0; col < lhs.cols(); ++col) {
1158 result(row, col) = binary_op(lhs(row, col), rhs(row, col));
1159 }
1160 }
1161
1162 return result;
1163}
1164
1165/**
1166 * Assemble a VariableMatrix from a nested list of blocks.
1167 *
1168 * Each row's blocks must have the same height, and the assembled block rows
1169 * must have the same width. For example, for the block matrix [[A, B], [C]] to
1170 * be constructible, the number of rows in A and B must match, and the number of
1171 * columns in [A, B] and [C] must match.
1172 *
1173 * @param list The nested list of blocks.
1174 */
1176 std::initializer_list<std::initializer_list<VariableMatrix>> list) {
1177 // Get row and column counts for destination matrix
1178 int rows = 0;
1179 int cols = -1;
1180 for (const auto& row : list) {
1181 if (row.size() > 0) {
1182 rows += row.begin()->rows();
1183 }
1184
1185 // Get number of columns in this row
1186 int latest_cols = 0;
1187 for (const auto& elem : row) {
1188 // Assert the first and latest row have the same height
1189 slp_assert(row.begin()->rows() == elem.rows());
1190
1191 latest_cols += elem.cols();
1192 }
1193
1194 // If this is the first row, record the column count. Otherwise, assert the
1195 // first and latest column counts are the same.
1196 if (cols == -1) {
1197 cols = latest_cols;
1198 } else {
1199 slp_assert(cols == latest_cols);
1200 }
1201 }
1202
1203 VariableMatrix result{VariableMatrix::empty, rows, cols};
1204
1205 int row_offset = 0;
1206 for (const auto& row : list) {
1207 int col_offset = 0;
1208 for (const auto& elem : row) {
1209 result.block(row_offset, col_offset, elem.rows(), elem.cols()) = elem;
1210 col_offset += elem.cols();
1211 }
1212 row_offset += row.begin()->rows();
1213 }
1214
1215 return result;
1216}
1217
1218/**
1219 * Assemble a VariableMatrix from a nested list of blocks.
1220 *
1221 * Each row's blocks must have the same height, and the assembled block rows
1222 * must have the same width. For example, for the block matrix [[A, B], [C]] to
1223 * be constructible, the number of rows in A and B must match, and the number of
1224 * columns in [A, B] and [C] must match.
1225 *
1226 * This overload is for Python bindings only.
1227 *
1228 * @param list The nested list of blocks.
1229 */
1231 const std::vector<std::vector<VariableMatrix>>& list) {
1232 // Get row and column counts for destination matrix
1233 int rows = 0;
1234 int cols = -1;
1235 for (const auto& row : list) {
1236 if (row.size() > 0) {
1237 rows += row.begin()->rows();
1238 }
1239
1240 // Get number of columns in this row
1241 int latest_cols = 0;
1242 for (const auto& elem : row) {
1243 // Assert the first and latest row have the same height
1244 slp_assert(row.begin()->rows() == elem.rows());
1245
1246 latest_cols += elem.cols();
1247 }
1248
1249 // If this is the first row, record the column count. Otherwise, assert the
1250 // first and latest column counts are the same.
1251 if (cols == -1) {
1252 cols = latest_cols;
1253 } else {
1254 slp_assert(cols == latest_cols);
1255 }
1256 }
1257
1258 VariableMatrix result{VariableMatrix::empty, rows, cols};
1259
1260 int row_offset = 0;
1261 for (const auto& row : list) {
1262 int col_offset = 0;
1263 for (const auto& elem : row) {
1264 result.block(row_offset, col_offset, elem.rows(), elem.cols()) = elem;
1265 col_offset += elem.cols();
1266 }
1267 row_offset += row.begin()->rows();
1268 }
1269
1270 return result;
1271}
1272
1273/**
1274 * Solves the VariableMatrix equation AX = B for X.
1275 *
1276 * @param A The left-hand side.
1277 * @param B The right-hand side.
1278 * @return The solution X.
1279 */
1281 const VariableMatrix& B);
1282
1283} // namespace slp
#define slp_assert(condition)
Abort in C++.
Definition assert.hpp:26
Represents a sequence of elements in an iterable object.
Definition slice.hpp:31
constexpr int adjust(int length)
Adjusts start and end slice indices assuming a sequence of the specified length.
Definition slice.hpp:134
A submatrix of autodiff variables with reference semantics.
Definition variable_block.hpp:24
An autodiff variable pointing to an expression node.
Definition variable.hpp:40
Definition variable_matrix.hpp:1018
constexpr const_iterator & operator++() noexcept
Definition variable_matrix.hpp:1032
std::ptrdiff_t difference_type
Definition variable_matrix.hpp:1022
constexpr const_iterator() noexcept=default
constexpr const_iterator operator++(int) noexcept
Definition variable_matrix.hpp:1037
constexpr bool operator==(const const_iterator &) const noexcept=default
constexpr const_reference operator*() const noexcept
Definition variable_matrix.hpp:1045
std::forward_iterator_tag iterator_category
Definition variable_matrix.hpp:1020
Definition variable_matrix.hpp:985
constexpr iterator & operator++() noexcept
Definition variable_matrix.hpp:999
constexpr iterator() noexcept=default
constexpr iterator operator++(int) noexcept
Definition variable_matrix.hpp:1004
std::ptrdiff_t difference_type
Definition variable_matrix.hpp:989
constexpr reference operator*() const noexcept
Definition variable_matrix.hpp:1012
constexpr bool operator==(const iterator &) const noexcept=default
std::forward_iterator_tag iterator_category
Definition variable_matrix.hpp:987
A matrix of autodiff variables.
Definition variable_matrix.hpp:29
VariableMatrix & operator=(ScalarLike auto value)
Assigns a double to the matrix.
Definition variable_matrix.hpp:229
Eigen::MatrixXd value()
Returns the contents of the variable matrix.
Definition variable_matrix.hpp:952
const VariableBlock< const VariableMatrix > row(int row) const
Returns a row slice of the variable matrix.
Definition variable_matrix.hpp:535
VariableBlock< VariableMatrix > segment(int offset, int length)
Returns a segment of the variable vector.
Definition variable_matrix.hpp:498
VariableMatrix(const Eigen::DiagonalBase< Derived > &values)
Constructs a VariableMatrix from an Eigen diagonal matrix.
Definition variable_matrix.hpp:187
const_iterator end() const
Returns end iterator.
Definition variable_matrix.hpp:1079
const_iterator cend() const
Returns end iterator.
Definition variable_matrix.hpp:1093
VariableMatrix(const Variable &variable)
Constructs a scalar VariableMatrix from a Variable.
Definition variable_matrix.hpp:259
VariableBlock< VariableMatrix > block(int row_offset, int col_offset, int block_rows, int block_cols)
Returns a block of the variable matrix.
Definition variable_matrix.hpp:393
friend SLEIPNIR_DLLEXPORT VariableMatrix operator*(const ScalarLike auto &lhs, const SleipnirMatrixLike auto &rhs)
Scalar-matrix multiplication operator.
Definition variable_matrix.hpp:641
VariableMatrix & operator*=(const MatrixLike auto &rhs)
Compound matrix multiplication-assignment operator.
Definition variable_matrix.hpp:678
size_t size() const
Returns number of elements in matrix.
Definition variable_matrix.hpp:1100
VariableMatrix & operator+=(const ScalarLike auto &rhs)
Compound addition-assignment operator.
Definition variable_matrix.hpp:794
friend SLEIPNIR_DLLEXPORT VariableMatrix operator-(const LHS &lhs, const RHS &rhs)
Binary subtraction operator.
Definition variable_matrix.hpp:815
const Variable & operator()(int row, int col) const
Returns a block pointing to the given row and column.
Definition variable_matrix.hpp:356
VariableMatrix & operator/=(const ScalarLike auto &rhs)
Compound matrix division-assignment operator.
Definition variable_matrix.hpp:736
VariableMatrix()=default
Constructs an empty VariableMatrix.
const VariableBlock< const VariableMatrix > block(int row_offset, int col_offset, int block_rows, int block_cols) const
Returns a block of the variable matrix.
Definition variable_matrix.hpp:411
Variable & operator()(int row, int col)
Returns a block pointing to the given row and column.
Definition variable_matrix.hpp:343
const Variable & operator[](int row) const
Returns a block pointing to the given row.
Definition variable_matrix.hpp:379
VariableMatrix(const Eigen::MatrixBase< Derived > &values)
Constructs a VariableMatrix from an Eigen matrix.
Definition variable_matrix.hpp:170
friend SLEIPNIR_DLLEXPORT VariableMatrix operator*(const Variable &lhs, const MatrixLike auto &rhs)
Scalar-matrix multiplication operator.
Definition variable_matrix.hpp:660
VariableMatrix & operator+=(const MatrixLike auto &rhs)
Compound addition-assignment operator.
Definition variable_matrix.hpp:776
VariableMatrix T() const
Returns the transpose of the variable matrix.
Definition variable_matrix.hpp:897
VariableMatrix & operator*=(const ScalarLike auto &rhs)
Compound matrix-scalar multiplication-assignment operator.
Definition variable_matrix.hpp:700
VariableMatrix cwise_transform(function_ref< Variable(const Variable &x)> unary_op) const
Transforms the matrix coefficient-wise with an unary operator.
Definition variable_matrix.hpp:970
const VariableBlock< const VariableMatrix > operator()(Slice row_slice, Slice col_slice) const
Returns a slice of the variable matrix.
Definition variable_matrix.hpp:443
static VariableMatrix ones(int rows, int cols)
Returns a variable matrix filled with ones.
Definition variable_matrix.hpp:1126
double value(int index)
Returns a row of the variable column vector.
Definition variable_matrix.hpp:942
VariableMatrix & operator-=(const MatrixLike auto &rhs)
Compound subtraction-assignment operator.
Definition variable_matrix.hpp:836
VariableMatrix(int rows, int cols)
Constructs a zero-initialized VariableMatrix with the given dimensions.
Definition variable_matrix.hpp:64
VariableBlock< VariableMatrix > operator()(Slice row_slice, Slice col_slice)
Returns a slice of the variable matrix.
Definition variable_matrix.hpp:429
friend SLEIPNIR_DLLEXPORT VariableMatrix operator*(const MatrixLike auto &lhs, const Variable &rhs)
Matrix-scalar multiplication operator.
Definition variable_matrix.hpp:621
VariableMatrix(int rows)
Constructs a VariableMatrix column vector with the given rows.
Definition variable_matrix.hpp:51
const VariableBlock< const VariableMatrix > operator()(Slice row_slice, int row_slice_length, Slice col_slice, int col_slice_length) const
Returns a slice of the variable matrix.
Definition variable_matrix.hpp:484
VariableMatrix(const VariableBlock< const VariableMatrix > &values)
Constructs a VariableMatrix from a VariableBlock.
Definition variable_matrix.hpp:293
friend SLEIPNIR_DLLEXPORT VariableMatrix operator/(const MatrixLike auto &lhs, const ScalarLike auto &rhs)
Binary division operator.
Definition variable_matrix.hpp:718
iterator end()
Returns end iterator.
Definition variable_matrix.hpp:1065
VariableBlock< VariableMatrix > row(int row)
Returns a row slice of the variable matrix.
Definition variable_matrix.hpp:524
VariableMatrix & operator-=(const ScalarLike auto &rhs)
Compound subtraction-assignment operator.
Definition variable_matrix.hpp:854
const_iterator cbegin() const
Returns begin iterator.
Definition variable_matrix.hpp:1086
VariableMatrix(empty_t, int rows, int cols)
Constructs an empty VariableMatrix with the given dimensions.
Definition variable_matrix.hpp:77
Variable & operator[](int row)
Returns a block pointing to the given row.
Definition variable_matrix.hpp:368
VariableMatrix(std::span< const Variable > values)
Constructs a column vector wrapper around a Variable array.
Definition variable_matrix.hpp:308
VariableMatrix(std::span< const Variable > values, int rows, int cols)
Constructs a matrix wrapper around a Variable array.
Definition variable_matrix.hpp:325
const_iterator begin() const
Returns begin iterator.
Definition variable_matrix.hpp:1072
double value(int row, int col)
Returns an element of the variable matrix.
Definition variable_matrix.hpp:930
iterator begin()
Returns begin iterator.
Definition variable_matrix.hpp:1058
static VariableMatrix zero(int rows, int cols)
Returns a variable matrix filled with zeroes.
Definition variable_matrix.hpp:1109
VariableMatrix & operator=(const Eigen::MatrixBase< Derived > &values)
Assigns an Eigen matrix to a VariableMatrix.
Definition variable_matrix.hpp:209
friend SLEIPNIR_DLLEXPORT VariableMatrix operator-(const SleipnirMatrixLike auto &lhs)
Unary minus operator.
Definition variable_matrix.hpp:872
const VariableBlock< const VariableMatrix > col(int col) const
Returns a column slice of the variable matrix.
Definition variable_matrix.hpp:557
int rows() const
Returns the number of rows in the matrix.
Definition variable_matrix.hpp:914
int cols() const
Returns the number of columns in the matrix.
Definition variable_matrix.hpp:921
VariableMatrix(Variable &&variable)
Constructs a scalar VariableMatrix from a Variable.
Definition variable_matrix.hpp:269
const VariableBlock< const VariableMatrix > segment(int offset, int length) const
Returns a segment of the variable vector.
Definition variable_matrix.hpp:511
friend SLEIPNIR_DLLEXPORT VariableMatrix operator*(const SleipnirMatrixLike auto &lhs, const ScalarLike auto &rhs)
Matrix-scalar multiplication operator.
Definition variable_matrix.hpp:603
VariableMatrix(std::initializer_list< std::initializer_list< Variable > > list)
Constructs a scalar VariableMatrix from a nested list of Variables.
Definition variable_matrix.hpp:89
void set_value(const Eigen::MatrixBase< Derived > &values)
Sets the VariableMatrix's internal values.
Definition variable_matrix.hpp:244
VariableMatrix(const std::vector< std::vector< double > > &list)
Constructs a scalar VariableMatrix from a nested list of doubles.
Definition variable_matrix.hpp:117
VariableMatrix(const std::vector< std::vector< Variable > > &list)
Constructs a scalar VariableMatrix from a nested list of Variables.
Definition variable_matrix.hpp:144
VariableBlock< VariableMatrix > col(int col)
Returns a column slice of the variable matrix.
Definition variable_matrix.hpp:546
static constexpr empty_t empty
Designates an uninitialized VariableMatrix.
Definition variable_matrix.hpp:39
friend SLEIPNIR_DLLEXPORT VariableMatrix operator*(const LHS &lhs, const RHS &rhs)
Matrix multiplication operator.
Definition variable_matrix.hpp:570
VariableBlock< VariableMatrix > operator()(Slice row_slice, int row_slice_length, Slice col_slice, int col_slice_length)
Returns a slice of the variable matrix.
Definition variable_matrix.hpp:464
friend SLEIPNIR_DLLEXPORT VariableMatrix operator+(const LHS &lhs, const RHS &rhs)
Binary addition operator.
Definition variable_matrix.hpp:755
VariableMatrix(const VariableBlock< VariableMatrix > &values)
Constructs a VariableMatrix from a VariableBlock.
Definition variable_matrix.hpp:278
Definition function_ref.hpp:13
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition SmallVector.h:1198
T * iterator
Definition SmallVector.h:253
const T * const_iterator
Definition SmallVector.h:254
Definition concepts.hpp:40
Definition concepts.hpp:13
Definition concepts.hpp:30
Definition small_vector.hpp:7
Definition expression_graph.hpp:11
SLEIPNIR_DLLEXPORT VariableMatrix cwise_reduce(const VariableMatrix &lhs, const VariableMatrix &rhs, function_ref< Variable(const Variable &x, const Variable &y)> binary_op)
Applies a coefficient-wise reduce operation to two matrices.
Definition variable_matrix.hpp:1149
SLEIPNIR_DLLEXPORT VariableMatrix block(std::initializer_list< std::initializer_list< VariableMatrix > > list)
Assemble a VariableMatrix from a nested list of blocks.
Definition variable_matrix.hpp:1175
SLEIPNIR_DLLEXPORT VariableMatrix solve(const VariableMatrix &A, const VariableMatrix &B)
Solves the VariableMatrix equation AX = B for X.
Type tag used to designate an uninitialized VariableMatrix.
Definition variable_matrix.hpp:34
#define SLEIPNIR_DLLEXPORT
Definition symbol_exports.hpp:34