23#ifndef LIBSEMIGROUPS_MATRIX_HPP_
24#define LIBSEMIGROUPS_MATRIX_HPP_
31#include <initializer_list>
39#include <unordered_map>
40#include <unordered_set>
44#include "adapters.hpp"
47#include "constants.hpp"
49#include "exception.hpp"
51#include "detail/containers.hpp"
52#include "detail/formatters.hpp"
53#include "detail/string.hpp"
135 template <
typename T>
136 struct IsStdBitSetHelper : std::false_type {};
139 struct IsStdBitSetHelper<std::bitset<N>> : std::true_type {};
141 template <
typename T>
142 static constexpr bool IsStdBitSet = IsStdBitSetHelper<T>::value;
144 struct MatrixPolymorphicBase {};
146 template <
typename T>
147 struct IsMatrixHelper {
148 static constexpr bool value
149 = std::is_base_of<detail::MatrixPolymorphicBase, T>::value;
167 template <
typename T>
168 constexpr bool IsMatrix = detail::IsMatrixHelper<T>::value;
183 template <
typename Mat>
185 if (x.number_of_rows() != x.number_of_cols()) {
205 template <
typename Mat>
207 -> std::enable_if_t<IsMatrix<Mat>> {
208 if (x.number_of_rows() != y.number_of_rows()
209 || x.number_of_cols() != y.number_of_cols()) {
211 "expected matrices with the same dimensions, the 1st argument is a "
212 "{}x{} matrix, and the 2nd is a {}x{} matrix",
234 template <
typename Mat>
236 -> std::enable_if_t<IsMatrix<Mat>> {
237 if (r >= x.number_of_rows()) {
239 "values in [0, {}) x [0, {})",
246 if (c >= x.number_of_cols()) {
248 "values in [0, {}) x [0, {})",
262 template <
typename Container,
265 typename Semiring =
void>
266 class MatrixCommon : MatrixPolymorphicBase {
272 using scalar_type =
typename Container::value_type;
273 using scalar_reference =
typename Container::reference;
274 using scalar_const_reference =
typename Container::const_reference;
275 using semiring_type = Semiring;
277 using container_type = Container;
278 using iterator =
typename Container::iterator;
279 using const_iterator =
typename Container::const_iterator;
281 using RowView = TRowView;
283 scalar_type scalar_one() const noexcept {
284 return static_cast<Subclass const*
>(
this)->one_impl();
287 scalar_type scalar_zero() const noexcept {
288 return static_cast<Subclass const*
>(
this)->zero_impl();
291 Semiring
const* semiring() const noexcept {
292 return static_cast<Subclass const*
>(
this)->semiring_impl();
300 scalar_type plus_no_checks(scalar_type x, scalar_type y)
const noexcept {
301 return static_cast<Subclass const*
>(
this)->plus_no_checks_impl(y, x);
304 scalar_type product_no_checks(scalar_type x,
305 scalar_type y)
const noexcept {
306 return static_cast<Subclass const*
>(
this)->product_no_checks_impl(y, x);
315 template <
typename SFINAE = container_type>
316 auto resize(
size_t r,
size_t c) -> std::enable_if_t<
317 std::is_same_v<SFINAE, std::vector<scalar_type>>> {
318 _container.resize(r * c);
321 template <
typename SFINAE = container_type>
322 auto resize(
size_t,
size_t) -> std::enable_if_t<
323 !std::is_same_v<SFINAE, std::vector<scalar_type>>> {}
331 MatrixCommon() =
default;
332 MatrixCommon(MatrixCommon
const&) =
default;
333 MatrixCommon(MatrixCommon&&) =
default;
334 MatrixCommon& operator=(MatrixCommon
const&) =
default;
335 MatrixCommon& operator=(MatrixCommon&&) =
default;
337 explicit MatrixCommon(std::initializer_list<scalar_type>
const& c)
343 explicit MatrixCommon(std::vector<std::vector<scalar_type>>
const& m)
349 std::initializer_list<std::initializer_list<scalar_type>>
const& m)
356 template <
typename T>
357 void init(T
const& m) {
358 size_t const R = m.size();
362 size_t const C = m.begin()->size();
364 for (
size_t r = 0; r < R; ++r) {
365 auto row = m.begin() + r;
366 for (
size_t c = 0; c < C; ++c) {
367 _container[r * C + c] = *(row->begin() + c);
374 init(std::initializer_list<std::initializer_list<scalar_type>>
const& m) {
375 init<std::initializer_list<std::initializer_list<scalar_type>>>(m);
379 explicit MatrixCommon(RowView
const& rv) : MatrixCommon() {
380 resize(1, rv.size());
381 std::copy(rv.cbegin(), rv.cend(), _container.begin());
384 ~MatrixCommon() =
default;
387 Subclass one()
const {
388 size_t const n = number_of_rows();
389 Subclass x(semiring(), n, n);
390 std::fill(x.begin(), x.end(), scalar_zero());
391 for (
size_t r = 0; r < n; ++r) {
392 x(r, r) = scalar_one();
402 bool operator==(MatrixCommon
const& that)
const {
403 return _container == that._container;
407 bool operator==(RowView
const& that)
const {
408 return number_of_rows() == 1
409 &&
static_cast<RowView
>(*
static_cast<Subclass const*
>(
this))
414 bool operator<(MatrixCommon
const& that)
const {
415 return _container < that._container;
419 bool operator<(RowView
const& that)
const {
420 return number_of_rows() == 1
421 &&
static_cast<RowView
>(*
static_cast<Subclass const*
>(
this))
426 template <
typename T>
427 bool operator!=(T
const& that)
const {
428 static_assert(
IsMatrix<T> || std::is_same_v<T, RowView>);
429 return !(*
this == that);
433 template <
typename T>
434 bool operator>(T
const& that)
const {
435 static_assert(
IsMatrix<T> || std::is_same_v<T, RowView>);
440 template <
typename T>
441 bool operator>=(T
const& that)
const {
442 static_assert(
IsMatrix<T> || std::is_same_v<T, RowView>);
443 return that < *
this || that == *
this;
447 template <
typename T>
448 bool operator<=(T
const& that)
const {
449 static_assert(
IsMatrix<T> || std::is_same_v<T, RowView>);
450 return *
this < that || that == *
this;
459 scalar_reference operator()(
size_t r,
size_t c) {
460 return this->_container[r * number_of_cols() + c];
463 scalar_reference at(
size_t r,
size_t c) {
465 return this->operator()(r, c);
470 scalar_const_reference operator()(
size_t r,
size_t c)
const {
471 return this->_container[r * number_of_cols() + c];
474 scalar_const_reference at(
size_t r,
size_t c)
const {
476 return this->operator()(r, c);
480 size_t number_of_rows() const noexcept {
481 return static_cast<Subclass const*
>(
this)->number_of_rows_impl();
485 size_t number_of_cols() const noexcept {
486 return static_cast<Subclass const*
>(
this)->number_of_cols_impl();
490 size_t hash_value()
const {
491 return Hash<Container>()(_container);
499 void product_inplace_no_checks(Subclass
const& A, Subclass
const& B) {
500 LIBSEMIGROUPS_ASSERT(number_of_rows() == number_of_cols());
501 LIBSEMIGROUPS_ASSERT(A.number_of_rows() == number_of_rows());
502 LIBSEMIGROUPS_ASSERT(B.number_of_rows() == number_of_rows());
503 LIBSEMIGROUPS_ASSERT(A.number_of_cols() == number_of_cols());
504 LIBSEMIGROUPS_ASSERT(B.number_of_cols() == number_of_cols());
505 LIBSEMIGROUPS_ASSERT(&A !=
this);
506 LIBSEMIGROUPS_ASSERT(&B !=
this);
514 size_t const N = A.number_of_rows();
515 std::vector<scalar_type> tmp(N, 0);
517 for (
size_t c = 0; c < N; c++) {
518 for (
size_t i = 0; i < N; i++) {
521 for (
size_t r = 0; r < N; r++) {
523 A._container.begin() + r * N,
524 A._container.begin() + (r + 1) * N,
527 [
this](scalar_type x, scalar_type y) {
528 return this->plus_no_checks(x, y);
530 [
this](scalar_type x, scalar_type y) {
531 return this->product_no_checks(x, y);
538 void operator*=(scalar_type a) {
539 for (
auto it = _container.begin(); it < _container.end(); ++it) {
540 *it = product_no_checks(*it, a);
545 void operator+=(Subclass
const& that) {
546 LIBSEMIGROUPS_ASSERT(that.number_of_rows() == number_of_rows());
547 LIBSEMIGROUPS_ASSERT(that.number_of_cols() == number_of_cols());
548 for (
size_t i = 0; i < _container.size(); ++i) {
549 _container[i] = plus_no_checks(_container[i], that._container[i]);
553 void operator+=(RowView
const& that) {
554 LIBSEMIGROUPS_ASSERT(number_of_rows() == 1);
555 RowView(*
static_cast<Subclass const*
>(
this)) += that;
558 void operator+=(scalar_type a) {
559 for (
auto it = _container.begin(); it < _container.end(); ++it) {
560 *it = plus_no_checks(*it, a);
571 Subclass operator+(Subclass
const& y)
const {
572 Subclass result(*
static_cast<Subclass const*
>(
this));
578 Subclass operator*(Subclass
const& y)
const {
579 Subclass result(*
static_cast<Subclass const*
>(
this));
580 result.product_inplace_no_checks(*
static_cast<Subclass const*
>(
this),
585 Subclass operator*(scalar_type a)
const {
586 Subclass result(*
static_cast<Subclass const*
>(
this));
591 Subclass operator+(scalar_type a)
const {
592 Subclass result(*
static_cast<Subclass const*
>(
this));
602 iterator begin() noexcept {
603 return _container.begin();
607 iterator end() noexcept {
608 return _container.end();
612 const_iterator begin() const noexcept {
613 return _container.begin();
617 const_iterator end() const noexcept {
618 return _container.end();
622 const_iterator cbegin() const noexcept {
623 return _container.cbegin();
627 const_iterator cend() const noexcept {
628 return _container.cend();
631 template <
typename U>
632 std::pair<scalar_type, scalar_type> coords(U
const& it)
const {
634 std::is_same_v<U, iterator> || std::is_same_v<U, const_iterator>,
635 "the parameter it must be of type iterator or const_iterator");
637 return std::make_pair(v / number_of_cols(), v % number_of_cols());
645 void swap(MatrixCommon& that)
noexcept {
651 void transpose_no_checks() noexcept {
652 LIBSEMIGROUPS_ASSERT(number_of_rows() == number_of_cols());
653 if (number_of_rows() == 0) {
657 for (
size_t r = 0; r < number_of_rows() - 1; ++r) {
658 for (
size_t c = r + 1; c < number_of_cols(); ++c) {
666 transpose_no_checks();
674 RowView row_no_checks(
size_t i)
const {
675 auto& container =
const_cast<Container&
>(_container);
676 return RowView(
static_cast<Subclass const*
>(
this),
677 container.begin() + i * number_of_cols(),
681 RowView row(
size_t i)
const {
682 if (i >= number_of_rows()) {
684 "index out of range, expected value in [{}, {}), found {}",
689 return row_no_checks(i);
693 template <
typename T>
694 void rows(T& x)
const {
695 auto& container =
const_cast<Container&
>(_container);
696 for (
auto itc = container.begin(); itc != container.end();
697 itc += number_of_cols()) {
699 static_cast<Subclass const*
>(
this), itc, number_of_cols());
701 LIBSEMIGROUPS_ASSERT(x.size() == number_of_rows());
708 friend std::ostream& operator<<(std::ostream& os, MatrixCommon
const& x) {
709 os << detail::to_string(x);
717 container_type _container;
720 template <
typename Scalar>
721 class MatrixDynamicDim {
723 MatrixDynamicDim() : _number_of_cols(0), _number_of_rows(0) {}
724 MatrixDynamicDim(MatrixDynamicDim
const&) =
default;
725 MatrixDynamicDim(MatrixDynamicDim&&) =
default;
726 MatrixDynamicDim& operator=(MatrixDynamicDim
const&) =
default;
727 MatrixDynamicDim& operator=(MatrixDynamicDim&&) =
default;
729 MatrixDynamicDim(
size_t r,
size_t c)
730 : _number_of_cols(c), _number_of_rows(r) {}
732 ~MatrixDynamicDim() =
default;
734 void swap(MatrixDynamicDim& that)
noexcept {
735 std::swap(_number_of_cols, that._number_of_cols);
736 std::swap(_number_of_rows, that._number_of_rows);
740 size_t number_of_rows_impl() const noexcept {
741 return _number_of_rows;
744 size_t number_of_cols_impl() const noexcept {
745 return _number_of_cols;
749 size_t _number_of_cols;
750 size_t _number_of_rows;
753 template <
typename PlusOp,
758 struct MatrixStaticArithmetic {
759 MatrixStaticArithmetic() =
default;
760 MatrixStaticArithmetic(MatrixStaticArithmetic
const&) =
default;
761 MatrixStaticArithmetic(MatrixStaticArithmetic&&) =
default;
762 MatrixStaticArithmetic& operator=(MatrixStaticArithmetic
const&)
764 MatrixStaticArithmetic& operator=(MatrixStaticArithmetic&&) =
default;
768 using scalar_type = Scalar;
770 static constexpr scalar_type plus_no_checks_impl(scalar_type x,
771 scalar_type y)
noexcept {
772 return PlusOp()(x, y);
775 static constexpr scalar_type
776 product_no_checks_impl(scalar_type x, scalar_type y)
noexcept {
777 return ProdOp()(x, y);
780 static constexpr scalar_type one_impl() noexcept {
784 static constexpr scalar_type zero_impl() noexcept {
788 static constexpr void const* semiring_impl() noexcept {
797 template <
typename Mat,
typename Sub
class>
798 class RowViewCommon {
800 "the template parameter Mat must be derived from "
801 "MatrixPolymorphicBase");
804 using const_iterator =
typename Mat::const_iterator;
805 using iterator =
typename Mat::iterator;
807 using scalar_type =
typename Mat::scalar_type;
808 using scalar_reference =
typename Mat::scalar_reference;
809 using scalar_const_reference =
typename Mat::scalar_const_reference;
811 using Row =
typename Mat::Row;
812 using matrix_type = Mat;
814 size_t size() const noexcept {
815 return static_cast<Subclass const*
>(
this)->length_impl();
819 scalar_type plus_no_checks(scalar_type x, scalar_type y)
const noexcept {
820 return static_cast<Subclass const*
>(
this)->plus_no_checks_impl(y, x);
823 scalar_type product_no_checks(scalar_type x,
824 scalar_type y)
const noexcept {
825 return static_cast<Subclass const*
>(
this)->product_no_checks_impl(y, x);
829 RowViewCommon() =
default;
830 RowViewCommon(RowViewCommon
const&) =
default;
831 RowViewCommon(RowViewCommon&&) =
default;
832 RowViewCommon& operator=(RowViewCommon
const&) =
default;
833 RowViewCommon& operator=(RowViewCommon&&) =
default;
835 explicit RowViewCommon(Row
const& r)
836 : RowViewCommon(const_cast<Row&>(r).begin()) {}
839 scalar_const_reference operator[](
size_t i)
const {
844 scalar_reference operator[](
size_t i) {
849 scalar_const_reference operator()(
size_t i)
const {
854 scalar_reference operator()(
size_t i) {
859 const_iterator cbegin() const noexcept {
864 const_iterator cend()
const {
865 return _begin + size();
869 const_iterator begin() const noexcept {
874 const_iterator end()
const {
875 return _begin + size();
879 iterator begin() noexcept {
884 iterator end() noexcept {
885 return _begin + size();
893 void operator+=(RowViewCommon
const& x) {
895 for (
size_t i = 0; i < size(); ++i) {
896 this_[i] = plus_no_checks(this_[i], x[i]);
901 void operator+=(scalar_type a) {
902 for (
auto& x : *
this) {
903 x = plus_no_checks(x, a);
908 void operator*=(scalar_type a) {
909 for (
auto& x : *
this) {
910 x = product_no_checks(x, a);
915 Row operator*(scalar_type a)
const {
916 Row result(*
static_cast<Subclass const*
>(
this));
922 Row operator+(RowViewCommon
const& that)
const {
923 Row result(*
static_cast<Subclass const*
>(
this));
924 result +=
static_cast<Subclass const&
>(that);
928 template <
typename U>
929 bool operator==(U
const& that)
const {
931 return std::equal(begin(), end(), that.begin());
934 template <
typename U>
935 bool operator!=(U
const& that)
const {
936 return !(*
this == that);
939 template <
typename U>
940 bool operator<(U
const& that)
const {
942 cbegin(), cend(), that.cbegin(), that.cend());
945 template <
typename U>
946 bool operator>(U
const& that)
const {
950 void swap(RowViewCommon& that)
noexcept {
954 friend std::ostream& operator<<(std::ostream& os,
955 RowViewCommon
const& x) {
956 os << detail::to_string(x);
961 explicit RowViewCommon(iterator first) : _begin(first) {}
967 template <
typename Container>
968 void throw_if_any_row_wrong_size(Container
const& m) {
972 uint64_t
const C = m.begin()->size();
974 m.begin() + 1, m.end(), [&C](
typename Container::const_reference r) {
975 return r.size() == C;
979 "have length {}, found {} in entry {}",
986 template <
typename Scalar>
987 void throw_if_any_row_wrong_size(
988 std::initializer_list<std::initializer_list<Scalar>> m) {
989 throw_if_any_row_wrong_size<
990 std::initializer_list<std::initializer_list<Scalar>>>(m);
999#ifndef LIBSEMIGROUPS_PARSED_BY_DOXYGEN
1000 template <
typename PlusOp,
1009 template <
typename... Args>
1010 class DynamicMatrix;
1012 template <
typename PlusOp,
1017 class DynamicMatrix<PlusOp, ProdOp, ZeroOp, OneOp, Scalar>;
1019 template <
typename Semiring,
typename Scalar>
1020 class DynamicMatrix<Semiring, Scalar>;
1068 template <
typename PlusOp,
1075 :
public detail::RowViewCommon<
1076 StaticMatrix<PlusOp, ProdOp, ZeroOp, OneOp, 1, C, Scalar>,
1077 StaticRowView<PlusOp, ProdOp, ZeroOp, OneOp, C, Scalar>>,
1079 MatrixStaticArithmetic<PlusOp, ProdOp, ZeroOp, OneOp, Scalar> {
1081 using RowViewCommon = detail::RowViewCommon<
1084 friend RowViewCommon;
1087 using StaticMatrix_ = ::libsemigroups::
1088 StaticMatrix<PlusOp, ProdOp, ZeroOp, OneOp, R, C, Scalar>;
1113 using Row =
typename matrix_type::Row;
1130#ifndef LIBSEMIGROUPS_PARSED_BY_DOXYGEN
1131 using RowViewCommon::RowViewCommon;
1136 typename RowViewCommon::iterator it,
1138 : RowViewCommon(it) {}
1140 using RowViewCommon::size;
1167 static constexpr size_t size() const noexcept;
1291 template <typename U>
1292 bool operator==(U const& that) const;
1314 template <typename U>
1315 bool operator!=(U const& that) const;
1340 template <typename U>
1341 bool operator<(U const& that) const;
1364 template <typename U>
1365 bool operator<(U const& that) const;
1459 static constexpr size_t length_impl() noexcept {
1468#ifndef LIBSEMIGROUPS_PARSED_BY_DOXYGEN
1471 template <
typename... Args>
1472 class DynamicRowView;
1512 template <
typename PlusOp,
1518 :
public detail::RowViewCommon<
1519 DynamicMatrix<PlusOp, ProdOp, ZeroOp, OneOp, Scalar>,
1520 DynamicRowView<PlusOp, ProdOp, ZeroOp, OneOp, Scalar>>,
1522 MatrixStaticArithmetic<PlusOp, ProdOp, ZeroOp, OneOp, Scalar> {
1524 using DynamicMatrix_ = DynamicMatrix<PlusOp, ProdOp, ZeroOp, OneOp, Scalar>;
1525 using RowViewCommon = detail::RowViewCommon<
1528 friend RowViewCommon;
1553 using Row =
typename matrix_type::Row;
1572 : RowViewCommon(r), _length(r.number_of_cols()) {}
1574#ifndef LIBSEMIGROUPS_PARSED_BY_DOXYGEN
1575 using RowViewCommon::RowViewCommon;
1578 DynamicRowView(DynamicMatrix_
const*, iterator
const& it,
size_t N)
1579 : RowViewCommon(it), _length(N) {}
1581 using RowViewCommon::size;
1611 template <typename U>
1612 bool operator==(U const& that) const;
1615 template <typename U>
1616 bool operator!=(U const& that) const;
1619 template <typename U>
1620 bool operator<(U const& that) const;
1623 template <typename U>
1624 bool operator<(U const& that) const;
1643 size_t length_impl() const noexcept {
1673 template <
typename Semiring,
typename Scalar>
1675 :
public detail::RowViewCommon<DynamicMatrix<Semiring, Scalar>,
1676 DynamicRowView<Semiring, Scalar>> {
1678 using DynamicMatrix_ = DynamicMatrix<Semiring, Scalar>;
1679 friend DynamicMatrix_;
1681 = detail::RowViewCommon<DynamicMatrix_,
1683 friend RowViewCommon;
1690 using iterator =
typename RowViewCommon::iterator;
1705 using matrix_type =
typename RowViewCommon::matrix_type;
1708 using Row =
typename matrix_type::Row;
1728#ifndef LIBSEMIGROUPS_PARSED_BY_DOXYGEN
1729 using RowViewCommon::RowViewCommon;
1732 DynamicRowView(DynamicMatrix_
const* mat, iterator
const& it,
size_t)
1733 : RowViewCommon(it), _matrix(mat) {}
1735 using RowViewCommon::size;
1738 size_t size() const noexcept;
1765 template <typename U>
1766 bool operator==(U const& that) const;
1769 template <typename U>
1770 bool operator!=(U const& that) const;
1773 template <typename U>
1774 bool operator<(U const& that) const;
1777 template <typename U>
1778 bool operator<(U const& that) const;
1797 size_t length_impl() const noexcept {
1798 return _matrix->number_of_cols();
1801 scalar_type plus_no_checks_impl(scalar_type x,
1802 scalar_type y)
const noexcept {
1803 return _matrix->plus_no_checks_impl(x, y);
1806 scalar_type product_no_checks_impl(scalar_type x,
1807 scalar_type y)
const noexcept {
1808 return _matrix->product_no_checks_impl(x, y);
1811 DynamicMatrix_
const* _matrix;
1851 template <
typename PlusOp,
1860 MatrixStaticArithmetic<PlusOp, ProdOp, ZeroOp, OneOp, Scalar>,
1861 public detail::MatrixCommon<
1862 std::array<Scalar, R * C>,
1863 StaticMatrix<PlusOp, ProdOp, ZeroOp, OneOp, R, C, Scalar>,
1864 StaticRowView<PlusOp, ProdOp, ZeroOp, OneOp, C, Scalar>> {
1869 using MatrixCommon = ::libsemigroups::detail::MatrixCommon<
1873 friend MatrixCommon;
1916 static constexpr size_t nr_rows = R;
1917 static constexpr size_t nr_cols = C;
1941 static_assert(R == 1,
1942 "cannot construct Matrix from the given initializer list, "
1943 "incompatible dimensions");
1944 LIBSEMIGROUPS_ASSERT(c.
size() == C);
1968 : MatrixCommon(m) {}
1983 : MatrixCommon(m) {}
2005 "cannot construct Matrix with more than one row from RowView!");
2033#ifndef LIBSEMIGROUPS_PARSED_BY_DOXYGEN
2046 LIBSEMIGROUPS_ASSERT(ptr ==
nullptr);
2055 LIBSEMIGROUPS_ASSERT(ptr ==
nullptr);
2062 LIBSEMIGROUPS_ASSERT(ptr ==
nullptr);
2068 LIBSEMIGROUPS_ASSERT(ptr ==
nullptr);
2074#ifndef LIBSEMIGROUPS_PARSED_BY_DOXYGEN
2078 LIBSEMIGROUPS_ASSERT(n == 0 || n == R);
2080#if defined(__APPLE__) && defined(__clang__) \
2081 && (__clang_major__ == 13 || __clang_major__ == 14)
2086 size_t volatile const m = R;
2091 std::fill(x.begin(), x.end(), ZeroOp()());
2092 for (
size_t r = 0; r < m; ++r) {
2093 x(r, r) = OneOp()();
2100 LIBSEMIGROUPS_ASSERT(ptr ==
nullptr);
2101 LIBSEMIGROUPS_ASSERT(n == 0 || n == R);
2109#ifdef LIBSEMIGROUPS_PARSED_BY_DOXYGEN
2509 template <typename T>
2598 template <typename U>
2599 bool operator<=(U const& that) const;
2615 template <typename U>
2616 bool operator>=(U const& that) const;
2685 using MatrixCommon::at;
2686 using MatrixCommon::begin;
2687 using MatrixCommon::cbegin;
2688 using MatrixCommon::cend;
2689 using MatrixCommon::coords;
2690 using MatrixCommon::end;
2691 using MatrixCommon::hash_value;
2692 using MatrixCommon::number_of_cols;
2693 using MatrixCommon::number_of_rows;
2694 using MatrixCommon::one;
2695 using MatrixCommon::operator!=;
2696 using MatrixCommon::operator();
2697 using MatrixCommon::operator*;
2698 using MatrixCommon::operator*=;
2699 using MatrixCommon::operator+;
2700 using MatrixCommon::operator+=;
2701 using MatrixCommon::operator<;
2702 using MatrixCommon::operator<=;
2703 using MatrixCommon::operator==;
2704 using MatrixCommon::operator>;
2705 using MatrixCommon::operator>=;
2706 using MatrixCommon::product_inplace_no_checks;
2707 using MatrixCommon::row;
2708 using MatrixCommon::row_no_checks;
2709 using MatrixCommon::rows;
2710 using MatrixCommon::scalar_one;
2711 using MatrixCommon::scalar_zero;
2712 using MatrixCommon::semiring;
2713 using MatrixCommon::swap;
2714 using MatrixCommon::transpose;
2715 using MatrixCommon::transpose_no_checks;
2723 static constexpr size_t number_of_rows_impl() noexcept {
2726 static constexpr size_t number_of_cols_impl() noexcept {
2768 template <
typename PlusOp,
2774 :
public detail::MatrixDynamicDim<Scalar>,
2775 public detail::MatrixCommon<
2776 std::vector<Scalar>,
2777 DynamicMatrix<PlusOp, ProdOp, ZeroOp, OneOp, Scalar>,
2778 DynamicRowView<PlusOp, ProdOp, ZeroOp, OneOp, Scalar>>,
2780 MatrixStaticArithmetic<PlusOp, ProdOp, ZeroOp, OneOp, Scalar> {
2781 using MatrixDynamicDim = ::libsemigroups::detail::MatrixDynamicDim<Scalar>;
2782 using MatrixCommon = ::libsemigroups::detail::MatrixCommon<
2785 DynamicRowView<PlusOp, ProdOp, ZeroOp, OneOp, Scalar>>;
2786 friend MatrixCommon;
2805 using RowView = DynamicRowView<PlusOp, ProdOp, ZeroOp, OneOp, Scalar>;
2893 : MatrixDynamicDim(1, c.size()), MatrixCommon(c) {}
2917 : MatrixDynamicDim(m.size(),
std::empty(m) ? 0 : m.
begin()->size()),
2935 : MatrixDynamicDim(m.size(),
std::empty(m) ? 0 : m.
begin()->size()),
2950 : MatrixDynamicDim(1, rv.size()), MatrixCommon(rv) {}
2952#ifndef LIBSEMIGROUPS_PARSED_BY_DOXYGEN
2954 DynamicMatrix(
void const* ptr,
size_t r,
size_t c) : DynamicMatrix(r, c) {
2956 LIBSEMIGROUPS_ASSERT(ptr ==
nullptr);
2961 : DynamicMatrix(c) {
2963 LIBSEMIGROUPS_ASSERT(ptr ==
nullptr);
2969 std::initializer_list<std::initializer_list<scalar_type>>
const& m)
2970 : DynamicMatrix(m) {
2972 LIBSEMIGROUPS_ASSERT(ptr ==
nullptr);
2975 static DynamicMatrix
one(
void const* ptr,
size_t n) {
2977 LIBSEMIGROUPS_ASSERT(ptr ==
nullptr);
2982 ~DynamicMatrix() =
default;
2998 std::fill(x.begin(), x.end(), ZeroOp()());
2999 for (
size_t r = 0; r < n; ++r) {
3000 x(r, r) = OneOp()();
3005#ifdef LIBSEMIGROUPS_PARSED_BY_DOXYGEN
3095 template <typename T>
3096 bool operator<=(T const& that) const;
3108 template <typename T>
3109 bool operator>=(T const& that) const;
3122 template <typename T>
3140 using MatrixCommon::at;
3141 using MatrixCommon::begin;
3142 using MatrixCommon::cbegin;
3143 using MatrixCommon::cend;
3144 using MatrixCommon::coords;
3145 using MatrixCommon::end;
3146 using MatrixCommon::hash_value;
3147 using MatrixCommon::number_of_cols;
3148 using MatrixCommon::number_of_rows;
3149 using MatrixCommon::one;
3150 using MatrixCommon::operator!=;
3151 using MatrixCommon::operator();
3152 using MatrixCommon::operator*;
3153 using MatrixCommon::operator*=;
3154 using MatrixCommon::operator+;
3155 using MatrixCommon::operator+=;
3156 using MatrixCommon::operator<;
3157 using MatrixCommon::operator<=;
3158 using MatrixCommon::operator==;
3159 using MatrixCommon::operator>;
3160 using MatrixCommon::operator>=;
3161 using MatrixCommon::product_inplace_no_checks;
3162 using MatrixCommon::row;
3163 using MatrixCommon::row_no_checks;
3164 using MatrixCommon::rows;
3165 using MatrixCommon::scalar_one;
3166 using MatrixCommon::scalar_zero;
3167 using MatrixCommon::semiring;
3169 using MatrixCommon::transpose;
3170 using MatrixCommon::transpose_no_checks;
3175 static_cast<MatrixDynamicDim&
>(*this).swap(
3176 static_cast<MatrixDynamicDim&
>(that));
3177 static_cast<MatrixCommon&
>(*this).swap(
static_cast<MatrixCommon&
>(that));
3181 using MatrixCommon::resize;
3222 template <
typename Semiring,
typename Scalar>
3224 :
public detail::MatrixDynamicDim<Scalar>,
3225 public detail::MatrixCommon<std::vector<Scalar>,
3226 DynamicMatrix<Semiring, Scalar>,
3227 DynamicRowView<Semiring, Scalar>,
3229 using MatrixCommon = detail::MatrixCommon<std::vector<Scalar>,
3231 DynamicRowView<Semiring, Scalar>,
3233 friend MatrixCommon;
3234 using MatrixDynamicDim = ::libsemigroups::detail::MatrixDynamicDim<Scalar>;
3294 : MatrixDynamicDim(r, c), MatrixCommon(), _semiring(sr) {
3316 : MatrixDynamicDim(rws.size(),
3317 std::empty(rws) ? 0 : rws.
begin()->size()),
3338 : MatrixDynamicDim(rws.size(), (rws.empty() ? 0 : rws.
begin()->size())),
3357 : MatrixDynamicDim(1, rw.size()), MatrixCommon(rw), _semiring(sr) {}
3371 : MatrixDynamicDim(1, rv.size()),
3373 _semiring(rv._matrix->
semiring()) {}
3392 std::fill(x.begin(), x.end(), x.scalar_zero());
3393 for (
size_t r = 0; r < n; ++r) {
3394 x(r, r) = x.scalar_one();
3399 ~DynamicMatrix() =
default;
3401#ifdef LIBSEMIGROUPS_PARSED_BY_DOXYGEN
3491 template <typename T>
3492 bool operator<=(T const& that) const;
3504 template <typename T>
3505 bool operator>=(T const& that) const;
3518 template <typename T>
3536 using MatrixCommon::at;
3537 using MatrixCommon::begin;
3538 using MatrixCommon::cbegin;
3539 using MatrixCommon::cend;
3540 using MatrixCommon::coords;
3541 using MatrixCommon::end;
3542 using MatrixCommon::hash_value;
3543 using MatrixCommon::number_of_cols;
3544 using MatrixCommon::number_of_rows;
3545 using MatrixCommon::one;
3546 using MatrixCommon::operator!=;
3547 using MatrixCommon::operator();
3548 using MatrixCommon::operator*;
3549 using MatrixCommon::operator*=;
3550 using MatrixCommon::operator+;
3551 using MatrixCommon::operator+=;
3552 using MatrixCommon::operator<;
3553 using MatrixCommon::operator<=;
3554 using MatrixCommon::operator==;
3555 using MatrixCommon::operator>;
3556 using MatrixCommon::operator>=;
3557 using MatrixCommon::product_inplace_no_checks;
3558 using MatrixCommon::row;
3559 using MatrixCommon::row_no_checks;
3560 using MatrixCommon::rows;
3561 using MatrixCommon::scalar_one;
3562 using MatrixCommon::scalar_zero;
3563 using MatrixCommon::semiring;
3565 using MatrixCommon::transpose;
3566 using MatrixCommon::transpose_no_checks;
3571 static_cast<MatrixDynamicDim&
>(*this).swap(
3572 static_cast<MatrixDynamicDim&
>(that));
3573 static_cast<MatrixCommon&
>(*this).swap(
static_cast<MatrixCommon&
>(that));
3578 using MatrixCommon::resize;
3580 scalar_type plus_no_checks_impl(scalar_type x,
3581 scalar_type y)
const noexcept {
3582 return _semiring->plus_no_checks(x, y);
3585 scalar_type product_no_checks_impl(scalar_type x,
3586 scalar_type y)
const noexcept {
3587 return _semiring->product_no_checks(x, y);
3590 scalar_type one_impl() const noexcept {
3591 return _semiring->scalar_one();
3594 scalar_type zero_impl() const noexcept {
3595 return _semiring->scalar_zero();
3598 Semiring
const* semiring_impl() const noexcept {
3602 Semiring
const* _semiring;
3611 template <
typename T>
3612 struct IsStaticMatrixHelper : std::false_type {};
3614 template <
typename PlusOp,
3621 struct IsStaticMatrixHelper<
3622 StaticMatrix<PlusOp, ProdOp, ZeroOp, OneOp, R, C, Scalar>>
3623 : std::true_type {};
3625 template <
typename T>
3626 struct IsMatWithSemiringHelper : std::false_type {};
3628 template <
typename Semiring,
typename Scalar>
3629 struct IsMatWithSemiringHelper<DynamicMatrix<Semiring, Scalar>>
3630 : std::true_type {};
3632 template <
typename S,
typename T =
void>
3633 struct IsTruncMatHelper : std::false_type {};
3647 template <
typename T>
3660 template <
typename T>
3673 template <
typename T>
3675 = detail::IsMatWithSemiringHelper<T>::value;
3679 template <
typename T>
3680 static constexpr bool IsTruncMat = IsTruncMatHelper<T>::value;
3682 template <
typename Mat>
3683 void throw_if_semiring_nullptr(Mat
const& m) {
3686 "the matrix's pointer to a semiring is nullptr!")
3690 template <
typename Mat,
typename Container>
3691 auto throw_if_bad_dim(Container
const& m)
3692 -> std::enable_if_t<IsStaticMatrix<Mat>> {
3694 uint64_t
const R = m.size();
3695 uint64_t
const C = std::empty(m) ? 0 : m.begin()->size();
3696 if (R != Mat::nr_rows || C != Mat::nr_cols) {
3698 "invalid argument, cannot initialize an {}x{} matrix with compile "
3699 "time dimension, with an {}x{} container",
3707 template <
typename Mat,
typename Container>
3708 auto throw_if_bad_dim(Container
const&)
3709 -> std::enable_if_t<IsDynamicMatrix<Mat>> {}
3712 template <
typename Mat,
typename Container>
3713 auto throw_if_bad_row_dim(Container
const& row)
3714 -> std::enable_if_t<IsStaticMatrix<Mat>> {
3715 uint64_t
const C = row.size();
3716 if (C != Mat::nr_cols) {
3718 "invalid argument, cannot initialize a row of a matrix with "
3719 "compile time number of columns {} with a container of size {}",
3725 template <
typename Mat,
typename Container>
3726 auto throw_if_bad_row_dim(Container
const&)
3727 -> std::enable_if_t<IsDynamicMatrix<Mat>> {}
3753 template <
typename Mat>
3755 -> std::enable_if_t<!detail::IsTruncMat<Mat>,
3756 typename Mat::scalar_type> {
3773 template <
typename Mat>
3774 constexpr auto threshold(Mat
const&)
noexcept
3776 typename Mat::scalar_type> {
3777 return detail::IsTruncMatHelper<Mat>::threshold;
3795 template <
typename Mat>
3798 typename Mat::scalar_type> {
3799 return x.semiring()->threshold();
3957 = DynamicMatrix<BooleanPlus, BooleanProd, BooleanZero, BooleanOne, int>;
3970 template <
size_t R,
size_t C>
3993 template <
size_t R = 0,
size_t C = R>
3995 = std::conditional_t<R == 0 || C == 0, DynamicBMat, StaticBMat<R, C>>;
3998 template <
typename T>
4001 template <
size_t R,
size_t C>
4007 template <
typename T>
4008 struct BitSetCapacity {
4009 static constexpr size_t value = BitSet<1>::max_size();
4012 template <
size_t R,
size_t C>
4014 static_assert(R == C,
"the number of rows and columns must be equal");
4015 static constexpr size_t value = R;
4029 template <
typename T>
4030 static constexpr bool IsBMat = detail::IsBMatHelper<T>::value;
4041 template <
typename Scalar>
4043 if constexpr (std::is_same_v<Scalar, NegativeInfinity>
4044 || std::is_signed_v<Scalar>) {
4052 return fmt::format(
"{}", a);
4074 template <
typename Mat>
4076 using scalar_type =
typename Mat::scalar_type;
4078 m.cbegin(), m.cend(), [](scalar_type x) { return x == 0 || x == 1; });
4079 if (it != m.cend()) {
4080 auto [r, c] = m.coords(it);
4082 "invalid entry, expected 0 or 1 but found {} in entry ({}, {})",
4083 detail::entry_repr(*it),
4106 template <
typename Mat>
4107 std::enable_if_t<IsBMat<Mat>>
4109 if (val != 0 && val != 1) {
4111 detail::entry_repr(val));
4160 template <
typename Scalar>
4174 constexpr Scalar
operator()(Scalar x, Scalar y)
const noexcept {
4191 template <
typename Scalar>
4205 constexpr Scalar
operator()(Scalar x, Scalar y)
const noexcept {
4219 template <
typename Scalar>
4230 constexpr Scalar
operator()() const noexcept {
4244 template <
typename Scalar>
4255 constexpr Scalar
operator()() const noexcept {
4270 template <
typename Scalar>
4293 template <
size_t R,
size_t C,
typename Scalar>
4318 template <
size_t R = 0,
size_t C = R,
typename Scalar =
int>
4319 using IntMat = std::conditional_t<R == 0 || C == 0,
4323 template <
typename T>
4326 template <
size_t R,
size_t C,
typename Scalar>
4329 template <
typename Scalar>
4343 template <
typename T>
4344 static constexpr bool IsIntMat = detail::IsIntMatHelper<T>::value;
4361 template <
typename Mat>
4363 using scalar_type =
typename Mat::scalar_type;
4364 auto it =
std::find_if(x.cbegin(), x.cend(), [](scalar_type val) {
4365 return val == POSITIVE_INFINITY || val == NEGATIVE_INFINITY;
4367 if (it != x.cend()) {
4368 auto [r, c] = x.coords(it);
4370 "invalid entry, expected entries to be integers, "
4371 "but found {} in entry ({}, {})",
4372 detail::entry_repr(*it),
4394 template <
typename Mat>
4395 std::enable_if_t<IsIntMat<Mat>>
4399 "invalid entry, expected entries to be integers, "
4401 detail::entry_repr(val));
4462 template <
typename Scalar>
4465 "MaxPlus requires a signed integer type as parameter!");
4478 Scalar
operator()(Scalar x, Scalar y)
const noexcept {
4509 template <
typename Scalar>
4512 "MaxPlus requires a signed integer type as parameter!");
4525 Scalar
operator()(Scalar x, Scalar y)
const noexcept {
4546 template <
typename Scalar>
4549 "MaxPlus requires a signed integer type as parameter!");
4559 constexpr Scalar
operator()() const noexcept {
4574 template <
typename Scalar>
4593 template <
size_t R,
size_t C,
typename Scalar>
4617 template <
size_t R = 0,
size_t C = R,
typename Scalar =
int>
4618 using MaxPlusMat = std::conditional_t<R == 0 || C == 0,
4623 template <
typename T>
4626 template <
size_t R,
size_t C,
typename Scalar>
4630 template <
typename Scalar>
4644 template <
typename T>
4645 static constexpr bool IsMaxPlusMat = detail::IsMaxPlusMatHelper<T>::value;
4663 template <
typename Mat>
4665 -> std::enable_if_t<IsMaxPlusMat<Mat>> {
4666 using scalar_type =
typename Mat::scalar_type;
4667 auto it =
std::find_if(x.cbegin(), x.cend(), [](scalar_type val) {
4668 return val == POSITIVE_INFINITY;
4670 if (it != x.cend()) {
4671 auto [r, c] = x.coords(it);
4673 "invalid entry, expected entries to be integers or {} (= {}), "
4674 "but found {} (= {}) in entry ({}, {})",
4699 template <
typename Mat>
4700 std::enable_if_t<IsMaxPlusMat<Mat>>
4703 using scalar_type =
typename Mat::scalar_type;
4705 "integers or {} (= {}) but found {} (= {})",
4770 template <
typename Scalar>
4773 "MinPlus requires a signed integer type as parameter!");
4786 Scalar
operator()(Scalar x, Scalar y)
const noexcept {
4817 template <
typename Scalar>
4820 "MinPlus requires a signed integer type as parameter!");
4833 Scalar
operator()(Scalar x, Scalar y)
const noexcept {
4854 template <
typename Scalar>
4857 "MinPlus requires a signed integer type as parameter!");
4867 constexpr Scalar
operator()() const noexcept {
4882 template <
typename Scalar>
4901 template <
size_t R,
size_t C,
typename Scalar>
4925 template <
size_t R = 0,
size_t C = R,
typename Scalar =
int>
4926 using MinPlusMat = std::conditional_t<R == 0 || C == 0,
4931 template <
typename T>
4934 template <
size_t R,
size_t C,
typename Scalar>
4938 template <
typename Scalar>
4952 template <
typename T>
4953 static constexpr bool IsMinPlusMat = detail::IsMinPlusMatHelper<T>::value;
4971 template <
typename Mat>
4973 using scalar_type =
typename Mat::scalar_type;
4974 auto it =
std::find_if(x.cbegin(), x.cend(), [](scalar_type val) {
4975 return val == NEGATIVE_INFINITY;
4977 if (it != x.cend()) {
4978 auto [r, c] = x.coords(it);
4980 "invalid entry, expected entries to be integers or {} (= {}), "
4981 "but found {} (= {}) in entry ({}, {})",
5006 template <
typename Mat>
5007 std::enable_if_t<IsMinPlusMat<Mat>>
5010 using scalar_type =
typename Mat::scalar_type;
5012 "integers or {} (= {}) but found {} (= {})",
5096 template <
size_t T,
typename Scalar>
5099 "MaxPlus requires a signed integer type as parameter!");
5112 Scalar
operator()(Scalar x, Scalar y)
const noexcept {
5113 LIBSEMIGROUPS_ASSERT((x >= 0 && x <=
static_cast<Scalar
>(T))
5115 LIBSEMIGROUPS_ASSERT((y >= 0 && y <=
static_cast<Scalar
>(T))
5120 return std::min(x + y,
static_cast<Scalar
>(T));
5138 template <
typename Scalar =
int>
5141 "MaxPlus requires a signed integer type as parameter!");
5199 static constexpr Scalar
scalar_one() noexcept {
5242 LIBSEMIGROUPS_ASSERT((x >= 0 && x <= _threshold)
5244 LIBSEMIGROUPS_ASSERT((y >= 0 && y <= _threshold)
5249 return std::min(x + y, _threshold);
5277 LIBSEMIGROUPS_ASSERT((x >= 0 && x <= _threshold)
5279 LIBSEMIGROUPS_ASSERT((y >= 0 && y <= _threshold)
5306 Scalar
const _threshold;
5321 template <
size_t T,
typename Scalar>
5341 template <
size_t T,
size_t R,
size_t C,
typename Scalar>
5367 template <
size_t T = 0,
size_t R = 0,
size_t C = R,
typename Scalar =
int>
5370 std::conditional_t<T == 0,
5371 DynamicMatrix<MaxPlusTruncSemiring<Scalar>, Scalar>,
5376 template <
typename T>
5379 template <
size_t T,
size_t R,
size_t C,
typename Scalar>
5382 static constexpr Scalar threshold = T;
5385 template <
size_t T,
typename Scalar>
5388 static constexpr Scalar threshold = T;
5391 template <
typename Scalar>
5392 struct IsMaxPlusTruncMatHelper<
5394 static constexpr Scalar threshold =
UNDEFINED;
5409 template <
typename T>
5411 = detail::IsMaxPlusTruncMatHelper<T>::value;
5414 template <
typename T>
5415 struct IsTruncMatHelper<T,
std::enable_if_t<IsMaxPlusTruncMat<T>>>
5417 static constexpr typename T::scalar_type threshold
5418 = IsMaxPlusTruncMatHelper<T>::threshold;
5441 template <
typename Mat>
5444 detail::throw_if_semiring_nullptr(m);
5446 using scalar_type =
typename Mat::scalar_type;
5449 return x == NEGATIVE_INFINITY || (0 <= x && x <= t);
5451 if (it != m.cend()) {
5452 auto [r, c] = m.coords(it);
5454 "invalid entry, expected values in {{0, 1, ..., {}, {} (= {})}} "
5455 "but found {} in entry ({}, {})",
5459 detail::entry_repr(*it),
5484 template <
typename Mat>
5485 std::enable_if_t<IsMaxPlusTruncMat<Mat>>
5487 detail::throw_if_semiring_nullptr(m);
5488 using scalar_type =
typename Mat::scalar_type;
5492 "invalid entry, expected values in {{0, 1, ..., {}, -{} (= {})}} "
5497 detail::entry_repr(val));
5576 template <
size_t T,
typename Scalar>
5590 Scalar
operator()(Scalar x, Scalar y)
const noexcept {
5591 LIBSEMIGROUPS_ASSERT((x >= 0 && x <=
static_cast<Scalar
>(T))
5593 LIBSEMIGROUPS_ASSERT((y >= 0 && y <=
static_cast<Scalar
>(T))
5598 return std::min(x + y,
static_cast<Scalar
>(T));
5615 template <
typename Scalar =
int>
5618 "MinPlus requires an integral type as parameter!");
5674 static constexpr Scalar
scalar_one() noexcept {
5718 LIBSEMIGROUPS_ASSERT((x >= 0 && x <= _threshold)
5720 LIBSEMIGROUPS_ASSERT((y >= 0 && y <= _threshold)
5725 return std::min(x + y, _threshold);
5753 LIBSEMIGROUPS_ASSERT((x >= 0 && x <= _threshold)
5755 LIBSEMIGROUPS_ASSERT((y >= 0 && y <= _threshold)
5782 Scalar
const _threshold;
5797 template <
size_t T,
typename Scalar>
5817 template <
size_t T,
size_t R,
size_t C,
typename Scalar>
5844 template <
size_t T = 0,
size_t R = 0,
size_t C = R,
typename Scalar =
int>
5847 std::conditional_t<T == 0,
5848 DynamicMatrix<MinPlusTruncSemiring<Scalar>, Scalar>,
5853 template <
typename T>
5856 template <
size_t T,
size_t R,
size_t C,
typename Scalar>
5859 static constexpr Scalar threshold = T;
5862 template <
size_t T,
typename Scalar>
5865 static constexpr Scalar threshold = T;
5868 template <
typename Scalar>
5869 struct IsMinPlusTruncMatHelper<
5871 static constexpr Scalar threshold =
UNDEFINED;
5886 template <
typename T>
5888 = detail::IsMinPlusTruncMatHelper<T>::value;
5891 template <
typename T>
5892 struct IsTruncMatHelper<T,
std::enable_if_t<IsMinPlusTruncMat<T>>>
5894 static constexpr typename T::scalar_type threshold
5895 = IsMinPlusTruncMatHelper<T>::threshold;
5919 template <
typename Mat>
5922 detail::throw_if_semiring_nullptr(m);
5924 using scalar_type =
typename Mat::scalar_type;
5927 return x == POSITIVE_INFINITY || (0 <= x && x <= t);
5929 if (it != m.cend()) {
5934 "invalid entry, expected values in {{0, 1, ..., {}, {} (= {})}} "
5935 "but found {} in entry ({}, {})",
5939 detail::entry_repr(*it),
5964 template <
typename Mat>
5965 std::enable_if_t<IsMinPlusTruncMat<Mat>>
5967 detail::throw_if_semiring_nullptr(m);
5969 using scalar_type =
typename Mat::scalar_type;
5973 "invalid entry, expected values in {{0, 1, ..., {}, {} (= {})}} "
5978 detail::entry_repr(val));
6041 template <
size_t T,
size_t P,
typename Scalar>
6042 constexpr Scalar thresholdperiod(Scalar x)
noexcept {
6044 return T + (x - T) % P;
6049 template <
typename Scalar>
6050 inline Scalar thresholdperiod(Scalar x,
6052 Scalar period)
noexcept {
6053 if (x > threshold) {
6083 template <
size_t T,
size_t P,
typename Scalar>
6096 constexpr Scalar
operator()(Scalar x, Scalar y)
const noexcept {
6097 return detail::thresholdperiod<T, P>(x + y);
6124 template <
size_t T,
size_t P,
typename Scalar>
6139 constexpr Scalar
operator()(Scalar x, Scalar y)
const noexcept {
6140 return detail::thresholdperiod<T, P>(x * y);
6158 template <
typename Scalar =
size_t>
6201 NTPSemiring(Scalar t, Scalar p) : _period(p), _threshold(t) {
6205 "expected non-negative value for 1st argument, found {}", t);
6210 "expected positive value for 2nd argument, found {}", p);
6224 static constexpr Scalar
scalar_one() noexcept {
6269 LIBSEMIGROUPS_ASSERT(x >= 0 && x <= _period + _threshold - 1);
6270 LIBSEMIGROUPS_ASSERT(y >= 0 && y <= _period + _threshold - 1);
6271 return detail::thresholdperiod(x * y, _threshold, _period);
6299 LIBSEMIGROUPS_ASSERT(x >= 0 && x <= _period + _threshold - 1);
6300 LIBSEMIGROUPS_ASSERT(y >= 0 && y <= _period + _threshold - 1);
6301 return detail::thresholdperiod(x + y, _threshold, _period);
6332 Scalar
period() const noexcept {
6351 template <
typename Scalar>
6367 template <
size_t T,
size_t P,
typename Scalar>
6393 template <
size_t T,
size_t P,
size_t R,
size_t C,
typename Scalar>
6424 template <
size_t T = 0,
6428 typename Scalar =
size_t>
6429 using NTPMat = std::conditional_t<
6431 std::conditional_t<T == 0 && P == 0,
6437 template <
typename T>
6440 template <
typename Scalar>
6442 static constexpr Scalar threshold =
UNDEFINED;
6443 static constexpr Scalar period =
UNDEFINED;
6446 template <
size_t T,
size_t P,
typename Scalar>
6449 static constexpr Scalar threshold = T;
6450 static constexpr Scalar period = P;
6453 template <
size_t T,
size_t P,
size_t R,
size_t C,
typename Scalar>
6455 static constexpr Scalar threshold = T;
6456 static constexpr Scalar period = P;
6471 template <
typename U>
6472 static constexpr bool IsNTPMat = detail::IsNTPMatHelper<U>::value;
6475 template <
typename T>
6477 static constexpr typename T::scalar_type threshold
6478 = IsNTPMatHelper<T>::threshold;
6479 static constexpr typename T::scalar_type period
6480 = IsNTPMatHelper<T>::period;
6507 template <
size_t T,
size_t P,
size_t R,
size_t C,
typename Scalar>
6529 template <
size_t T,
size_t P,
typename Scalar>
6550 template <
typename Scalar>
6552 return x.semiring()->period();
6577 template <
typename Mat>
6579 detail::throw_if_semiring_nullptr(m);
6581 using scalar_type =
typename Mat::scalar_type;
6585 return (0 <= x && x < p + t);
6587 if (it != m.cend()) {
6592 "invalid entry, expected values in {{0, 1, ..., {}}}, but "
6593 "found {} in entry ({}, {})",
6595 detail::entry_repr(*it),
6622 template <
typename Mat>
6623 std::enable_if_t<IsNTPMat<Mat>>
6625 detail::throw_if_semiring_nullptr(m);
6626 using scalar_type =
typename Mat::scalar_type;
6629 if (val < 0 || val >= p + t) {
6631 "invalid entry, expected values in {{0, 1, ..., {}}}, but "
6634 detail::entry_repr(val));
6644 template <
typename T>
6647 using scalar_type =
typename T::scalar_type;
6648 using scalar_reference =
typename T::scalar_reference;
6649 using scalar_const_reference =
typename T::scalar_const_reference;
6650 using semiring_type = void;
6652 using container_type =
typename T::container_type;
6653 using iterator =
typename T::iterator;
6654 using const_iterator =
typename T::const_iterator;
6656 using underlying_matrix_type = T;
6658 using RowView =
typename T::RowView;
6664 using Row =
typename T::Row;
6666 scalar_type scalar_one() const noexcept {
6667 return _underlying_mat.scalar_one();
6670 scalar_type scalar_zero() const noexcept {
6671 return _underlying_mat.scalar_zero();
6678 ProjMaxPlusMat() : _is_normalized(false), _underlying_mat() {}
6679 ProjMaxPlusMat(ProjMaxPlusMat
const&) =
default;
6680 ProjMaxPlusMat(ProjMaxPlusMat&&) =
default;
6681 ProjMaxPlusMat& operator=(ProjMaxPlusMat
const&) =
default;
6682 ProjMaxPlusMat& operator=(ProjMaxPlusMat&&) =
default;
6684 ProjMaxPlusMat(
size_t r,
size_t c)
6685 : _is_normalized(false), _underlying_mat(r, c) {}
6689 typename underlying_matrix_type::semiring_type
const* semiring,
6692 : _is_normalized(false), _underlying_mat(semiring, r, c) {}
6694 explicit ProjMaxPlusMat(std::vector<std::vector<scalar_type>>
const& m)
6695 : _is_normalized(false), _underlying_mat(m) {
6700 std::initializer_list<std::initializer_list<scalar_type>>
const& m)
6702 std::vector<std::vector<scalar_type>>(m.begin(), m.
end())) {}
6704 ~ProjMaxPlusMat() =
default;
6706 ProjMaxPlusMat one()
const {
6707 auto result = ProjMaxPlusMat(_underlying_mat.one());
6711 static ProjMaxPlusMat one(
size_t n) {
6712 return ProjMaxPlusMat(T::one(n));
6719 bool operator==(ProjMaxPlusMat
const& that)
const {
6722 return _underlying_mat == that._underlying_mat;
6725 bool operator!=(ProjMaxPlusMat
const& that)
const {
6726 return !(_underlying_mat == that._underlying_mat);
6729 bool operator<(ProjMaxPlusMat
const& that)
const {
6732 return _underlying_mat < that._underlying_mat;
6735 bool operator>(ProjMaxPlusMat
const& that)
const {
6736 return that < *
this;
6739 template <
typename Thing>
6740 bool operator>=(Thing
const& that)
const {
6742 return that < *
this || that == *
this;
6746 template <
typename Thing>
6747 bool operator<=(Thing
const& that)
const {
6749 return *
this < that || that == *
this;
6756 scalar_reference operator()(
size_t r,
size_t c) {
6761 _is_normalized =
false;
6762 return _underlying_mat(r, c);
6765 scalar_reference at(
size_t r,
size_t c) {
6767 return this->operator()(r, c);
6770 scalar_const_reference operator()(
size_t r,
size_t c)
const {
6772 return _underlying_mat(r, c);
6775 scalar_const_reference at(
size_t r,
size_t c)
const {
6777 return this->operator()(r, c);
6780 size_t number_of_rows() const noexcept {
6781 return _underlying_mat.number_of_rows();
6784 size_t number_of_cols() const noexcept {
6785 return _underlying_mat.number_of_cols();
6788 size_t hash_value()
const {
6790 return Hash<T>()(_underlying_mat);
6797 void product_inplace_no_checks(ProjMaxPlusMat
const& A,
6798 ProjMaxPlusMat
const& B) {
6799 _underlying_mat.product_inplace_no_checks(A._underlying_mat,
6804 void operator+=(ProjMaxPlusMat
const& that) {
6805 _underlying_mat += that._underlying_mat;
6809 void operator*=(scalar_type a) {
6810 _underlying_mat *= a;
6814 void operator+=(scalar_type a) {
6815 _underlying_mat += a;
6819 ProjMaxPlusMat operator*(scalar_type a)
const {
6820 ProjMaxPlusMat result(*
this);
6825 ProjMaxPlusMat operator+(scalar_type a)
const {
6826 ProjMaxPlusMat result(*
this);
6835 ProjMaxPlusMat operator+(ProjMaxPlusMat
const& that)
const {
6836 return ProjMaxPlusMat(_underlying_mat + that._underlying_mat);
6839 ProjMaxPlusMat operator*(ProjMaxPlusMat
const& that)
const {
6840 return ProjMaxPlusMat(_underlying_mat * that._underlying_mat);
6851 iterator begin() noexcept {
6856 _is_normalized =
false;
6857 return _underlying_mat.begin();
6860 iterator
end() noexcept {
6865 _is_normalized =
false;
6866 return _underlying_mat.end();
6869 const_iterator begin() const noexcept {
6871 return _underlying_mat.begin();
6874 const_iterator
end() const noexcept {
6876 return _underlying_mat.end();
6879 const_iterator cbegin() const noexcept {
6881 return _underlying_mat.cbegin();
6884 const_iterator cend() const noexcept {
6886 return _underlying_mat.cend();
6893 void swap(ProjMaxPlusMat& that)
noexcept {
6894 std::swap(_underlying_mat, that._underlying_mat);
6898 _underlying_mat.transpose();
6901 void transpose_no_checks() noexcept {
6902 _underlying_mat.transpose_no_checks();
6909 RowView row(
size_t i)
const {
6911 return _underlying_mat.row(i);
6914 template <
typename C>
6915 void rows(C& x)
const {
6917 return _underlying_mat.rows(x);
6924 friend std::ostream& operator<<(std::ostream& os,
6925 ProjMaxPlusMat
const& x) {
6927 os << detail::to_string(x._underlying_mat);
6931 T
const& underlying_matrix() const noexcept {
6933 return _underlying_mat;
6937 explicit ProjMaxPlusMat(T&& mat)
6938 : _is_normalized(false), _underlying_mat(std::
move(mat)) {
6942 void normalize(
bool force =
false)
const {
6943 if ((_is_normalized && !force)
6944 || (_underlying_mat.number_of_rows() == 0)
6945 || (_underlying_mat.number_of_cols() == 0)) {
6946 _is_normalized =
true;
6950 _underlying_mat.cend());
6952 _underlying_mat.end(),
6953 [&n](scalar_type& s) {
6954 if (s != NEGATIVE_INFINITY) {
6958 _is_normalized =
true;
6961 mutable bool _is_normalized;
6962 mutable T _underlying_mat;
7024 template <
size_t R,
size_t C,
typename Scalar>
7026 = detail::ProjMaxPlusMat<StaticMaxPlusMat<R, C, Scalar>>;
7039 template <
typename Scalar>
7041 = detail::ProjMaxPlusMat<DynamicMaxPlusMat<Scalar>>;
7057 template <
size_t R = 0,
size_t C = R,
typename Scalar =
int>
7063 template <
typename T>
7066 template <
size_t R,
size_t C,
typename Scalar>
7070 template <
typename Scalar>
7086 template <
typename T>
7088 = detail::IsProjMaxPlusMatHelper<T>::value;
7108 template <
typename Mat>
7109 constexpr std::enable_if_t<IsProjMaxPlusMat<Mat>>
7131 template <
typename Mat>
7132 constexpr std::enable_if_t<IsProjMaxPlusMat<Mat>>
7177 template <
typename Mat>
7178 Mat
pow(Mat
const& x,
typename Mat::scalar_type e) {
7179 using scalar_type =
typename Mat::scalar_type;
7184 "negative exponent, expected value >= 0, found {}", e);
7190 typename Mat::semiring_type
const* sr =
nullptr;
7204 auto z = (e % 2 == 0 ? x.one() : y);
7206 Mat tmp(sr, x.number_of_rows(), x.number_of_cols());
7208 tmp.product_inplace_no_checks(y, y);
7212 tmp.product_inplace_no_checks(z, y);
7242 template <
typename Mat,
typename = std::enable_if_t<IsDynamicMatrix<Mat>>>
7269 template <
typename Mat,
typename = std::enable_if_t<IsStaticMatrix<Mat>>>
7270 detail::StaticVector1<typename Mat::RowView, Mat::nr_rows>
7271 rows(Mat
const& x) {
7272 detail::StaticVector1<typename Mat::RowView, Mat::nr_rows> container;
7313 template <
typename Mat,
size_t R,
size_t C,
typename Container>
7315 detail::StaticVector1<BitSet<C>, R>& result) {
7316 using RowView =
typename Mat::RowView;
7317 using value_type =
typename std::decay_t<Container>::value_type;
7319 static_assert(
IsBMat<Mat>,
"IsBMat<Mat> must be true!");
7320 static_assert(std::is_same_v<value_type, RowView>
7321 || std::is_same_v<value_type, std::vector<bool>>,
7322 "Container::value_type must equal Mat::RowView or "
7323 "std::vector<bool>!!");
7324 static_assert(R <= BitSet<1>::max_size(),
7325 "R must be at most BitSet<1>::max_size()!");
7326 static_assert(C <= BitSet<1>::max_size(),
7327 "C must be at most BitSet<1>::max_size()!");
7328 LIBSEMIGROUPS_ASSERT(views.size() <= R);
7329 LIBSEMIGROUPS_ASSERT(views.empty() || views[0].size() <= C);
7330 for (
auto const& v : views) {
7331 result.emplace_back(v.cbegin(), v.cend());
7367 template <
typename Mat,
size_t R,
size_t C,
typename Container>
7369 using RowView =
typename Mat::RowView;
7370 using value_type =
typename std::decay_t<Container>::value_type;
7371 static_assert(
IsBMat<Mat>,
"IsBMat<Mat> must be true!");
7372 static_assert(std::is_same_v<value_type, RowView>
7373 || std::is_same_v<value_type, std::vector<bool>>,
7374 "Container::value_type must equal Mat::RowView or "
7375 "std::vector<bool>!!");
7376 static_assert(R <= BitSet<1>::max_size(),
7377 "R must be at most BitSet<1>::max_size()!");
7378 static_assert(C <= BitSet<1>::max_size(),
7379 "C must be at most BitSet<1>::max_size()!");
7380 LIBSEMIGROUPS_ASSERT(views.size() <= R);
7381 LIBSEMIGROUPS_ASSERT(views.empty() || views[0].size() <= C);
7382 detail::StaticVector1<BitSet<C>, R> result;
7416 template <
typename Mat,
size_t R,
size_t C>
7418 detail::StaticVector1<BitSet<C>, R>& result) {
7419 static_assert(
IsBMat<Mat>,
"IsBMat<Mat> must be true!");
7420 static_assert(R <= BitSet<1>::max_size(),
7421 "R must be at most BitSet<1>::max_size()!");
7422 static_assert(C <= BitSet<1>::max_size(),
7423 "C must be at most BitSet<1>::max_size()!");
7424 LIBSEMIGROUPS_ASSERT(x.number_of_cols() <= C);
7425 LIBSEMIGROUPS_ASSERT(x.number_of_rows() <= R);
7448 template <
typename Mat>
7450 static_assert(
IsBMat<Mat>,
"IsBMat<Mat> must be true!");
7451 LIBSEMIGROUPS_ASSERT(x.number_of_rows() <= BitSet<1>::max_size());
7452 LIBSEMIGROUPS_ASSERT(x.number_of_cols() <= BitSet<1>::max_size());
7453 size_t const M = detail::BitSetCapacity<Mat>::value;
7485 template <
typename Mat,
typename Container>
7487 using value_type =
typename std::decay_t<Container>::value_type;
7488 static_assert(
IsBMat<Mat>,
"IsBMat<Mat> must be true!");
7489 static_assert(IsBitSet<value_type> || detail::IsStdBitSet<value_type>,
7490 "Container::value_type must be BitSet or std::bitset");
7491 LIBSEMIGROUPS_ASSERT(
rows.size() <= BitSet<1>::max_size());
7492 LIBSEMIGROUPS_ASSERT(
rows.empty()
7493 ||
rows[0].size() <= BitSet<1>::max_size());
7498 for (
size_t i = 0; i <
rows.size(); ++i) {
7501 for (
size_t j = 0; j < i; ++j) {
7506 for (
size_t j = i + 1; j <
rows.size(); ++j) {
7511 if (cup !=
rows[i]) {
7540 template <
typename Mat,
typename Container>
7542 using value_type =
typename std::decay_t<Container>::value_type;
7543 static_assert(
IsBMat<Mat>,
"IsBMat<Mat> must be true!");
7544 static_assert(IsBitSet<value_type> || detail::IsStdBitSet<value_type>,
7545 "Container::value_type must be BitSet or std::bitset");
7546 LIBSEMIGROUPS_ASSERT(
rows.size() <= BitSet<1>::max_size());
7547 LIBSEMIGROUPS_ASSERT(
rows.empty()
7548 ||
rows[0].size() <= BitSet<1>::max_size());
7549 std::decay_t<Container> result;
7581 template <typename Mat, size_t M = detail::BitSetCapacity<Mat>::value>
7583 static_assert(
IsBMat<Mat>,
"IsBMat<Mat> must be true!");
7584 LIBSEMIGROUPS_ASSERT(x.number_of_rows() <= BitSet<1>::max_size());
7585 LIBSEMIGROUPS_ASSERT(x.number_of_cols() <= BitSet<1>::max_size());
7586 detail::StaticVector1<BitSet<M>, M> result;
7614 template <
typename Mat,
typename Container>
7616 using value_type =
typename Container::value_type;
7617 static_assert(
IsBMat<Mat>,
"IsBMat<Mat> must be true!");
7618 static_assert(IsBitSet<value_type> || detail::IsStdBitSet<value_type>,
7619 "Container::value_type must be BitSet or std::bitset");
7620 LIBSEMIGROUPS_ASSERT(x.number_of_rows() <= BitSet<1>::max_size());
7621 LIBSEMIGROUPS_ASSERT(x.number_of_cols() <= BitSet<1>::max_size());
7656 template <
typename Mat,
typename Container>
7657 std::enable_if_t<IsMaxPlusTruncMat<Mat>>
7658 row_basis(Container&& views, std::decay_t<Container>& result) {
7659 using value_type =
typename std::decay_t<Container>::value_type;
7660 static_assert(std::is_same_v<value_type, typename Mat::RowView>,
7661 "Container::value_type must be Mat::RowView");
7662 using scalar_type =
typename Mat::scalar_type;
7663 using Row =
typename Mat::Row;
7665 if (views.empty()) {
7669 LIBSEMIGROUPS_ASSERT(result.empty());
7674 for (
size_t r1 = 0; r1 < views.size(); ++r1) {
7675 if (r1 == 0 || views[r1] != views[r1 - 1]) {
7676 std::fill(tmp1.begin(), tmp1.end(), tmp1.scalar_zero());
7677 for (
size_t r2 = 0; r2 < r1; ++r2) {
7679 for (
size_t c = 0; c < tmp1.number_of_cols(); ++c) {
7680 if (views[r2][c] == tmp1.scalar_zero()) {
7683 if (views[r1][c] >= views[r2][c]) {
7686 =
std::min(max_scalar, views[r1][c] - views[r2][c]);
7689 max_scalar = tmp1.scalar_zero();
7693 if (max_scalar != tmp1.scalar_zero()) {
7694 tmp1 += views[r2] * max_scalar;
7697 if (tmp1 != views[r1]) {
7698 result.push_back(views[r1]);
7734 template <
typename Mat,
typename Container>
7735 std::enable_if_t<IsBMat<Mat>>
row_basis(Container&& views,
7736 std::decay_t<Container>& result) {
7737 using RowView =
typename Mat::RowView;
7738 using value_type =
typename std::decay_t<Container>::value_type;
7740 static_assert(std::is_same_v<value_type, RowView>
7741 || std::is_same_v<value_type, std::vector<bool>>,
7742 "Container::value_type must equal Mat::RowView or "
7743 "std::vector<bool>!!");
7745 if (views.empty()) {
7750 size_t const M = detail::BitSetCapacity<Mat>::value;
7752 using bitset_type =
typename decltype(br)::value_type;
7756 LIBSEMIGROUPS_ASSERT(br.size() == views.size());
7757 for (
size_t i = 0; i < br.size(); ++i) {
7758 lookup.
insert({br[i], i});
7763 auto it = lookup.
find(bs);
7764 LIBSEMIGROUPS_ASSERT(it != lookup.
end());
7765 result.push_back(views[it->second]);
7795 template <
typename Mat,
7797 typename = std::enable_if_t<IsMatrix<Mat>>>
7798 void row_basis(Mat
const& x, Container& result) {
7822 template <
typename Mat,
typename = std::enable_if_t<IsDynamicMatrix<Mat>>>
7848 template <
typename Mat,
typename = std::enable_if_t<IsStaticMatrix<Mat>>>
7849 detail::StaticVector1<typename Mat::RowView, Mat::nr_rows>
7851 detail::StaticVector1<typename Mat::RowView, Mat::nr_rows> container;
7875 template <
typename Mat,
7877 typename = std::enable_if_t<!IsMatrix<std::decay_t<Container>>>>
7879 using value_type =
typename std::decay_t<Container>::value_type;
7880 static_assert(
IsMatrix<Mat>,
"IsMatrix<Mat> must be true!");
7881 static_assert(std::is_same_v<value_type, typename Mat::RowView>,
7882 "Container::value_type must be Mat::RowView");
7884 std::decay_t<Container> result;
7889 template <
typename T>
7891 void operator()(T& res, T
const& pt, T
const& x)
const {
7897 template <
typename Mat,
7899 typename = std::enable_if_t<IsMatrix<Mat>>>
7900 void row_basis_rows(Mat
const& x, Container& result) {
7901 LIBSEMIGROUPS_ASSERT(result.empty());
7902 for (
auto y : row_basis<Mat>(x)) {
7903 result.push_back(
typename Mat::Row(y));
7907 template <
typename Mat,
7909 typename = std::enable_if_t<IsStaticMatrix<Mat>>>
7910 detail::StaticVector1<typename Mat::Row, Mat::nr_rows>
7911 row_basis_rows(Mat
const& x) {
7912 detail::StaticVector1<typename Mat::Row, Mat::nr_rows> container;
7913 row_basis_rows(x, container);
7917 template <
typename Mat,
7919 typename = std::enable_if_t<IsDynamicMatrix<Mat>>>
7920 std::vector<typename Mat::Row> row_basis_rows(Mat
const& x) {
7921 std::vector<typename Mat::Row> container;
7922 row_basis_rows(x, container);
7927 template <
typename Mat,
7929 typename = std::enable_if_t<IsStaticMatrix<Mat>>>
7930 detail::StaticVector1<typename Mat::Row, Mat::nr_rows>
7931 row_basis_rows(Container&& rows) {
7932 using value_type =
typename std::decay_t<Container>::value_type;
7933 static_assert(IsMatrix<Mat>,
"IsMatrix<Mat> must be true!");
7934 static_assert(std::is_same_v<value_type, typename Mat::Row>,
7935 "Container::value_type must be Mat::Row");
7937 detail::StaticVector1<typename Mat::RowView, Mat::nr_rows> rvs;
7938 std::unordered_map<typename Mat::scalar_type*, size_t> lookup;
7940 for (
size_t i = 0; i <
rows.size(); ++i) {
7941 auto rv =
typename Mat::RowView(rows[i]);
7943 lookup.
insert({&(*rv.begin()), i});
7945 std::decay_t<Container> result;
7946 for (
auto rv : row_basis<Mat>(rvs)) {
7947 auto&& row =
rows[lookup.
at(&(*rv.begin()))];
7987 template <
typename Mat,
typename = std::enable_if_t<IsBMat<Mat>>>
7989 size_t const M = detail::BitSetCapacity<Mat>::value;
7994 st.
insert(bitset_row_basis_.cbegin(), bitset_row_basis_.cend());
7996 bitset_row_basis_.cend());
7997 for (
size_t i = 0; i < orb.
size(); ++i) {
7998 for (
auto& row : bitset_row_basis_) {
8000 for (
size_t j = 0; j < x.number_of_rows(); ++j) {
8001 cup.set(j, cup[j] || row[j]);
8003 if (st.
insert(cup).second) {
8032 template <
typename Mat>
8033 auto operator+(
typename Mat::scalar_type a, Mat
const& x)
8034 -> std::enable_if_t<IsMatrix<Mat>, Mat> {
8057 template <
typename Mat>
8058 auto operator*(
typename Mat::scalar_type a, Mat
const& x)
8059 -> std::enable_if_t<IsMatrix<Mat>, Mat> {
8099 template <
typename Mat,
8103 detail::throw_if_any_row_wrong_size(rows);
8104 detail::throw_if_bad_dim<Mat>(rows);
8135 template <
typename Mat,
8169 template <
typename Mat,
8173 detail::throw_if_bad_row_dim<Mat>(row);
8211 template <
typename Mat,
8213 typename = std::enable_if_t<IsMatrix<Mat>>>
8216 Mat
make(Semiring
const* semiring,
8219 detail::throw_if_any_row_wrong_size(rows);
8220 detail::throw_if_bad_dim<Mat>(rows);
8221 Mat m(semiring, rows);
8257 template <
typename Mat,
8259 typename = std::enable_if_t<IsMatrix<Mat>>>
8260 Mat
make(Semiring
const* semiring,
8262 detail::throw_if_any_row_wrong_size(rows);
8263 detail::throw_if_bad_dim<Mat>(rows);
8264 Mat m(semiring, rows);
8291 template <
typename Mat,
8293 typename = std::enable_if_t<IsMatrix<Mat>>>
8294 Mat
make(Semiring
const* semiring,
8296 detail::throw_if_bad_row_dim<Mat>(row);
8297 Mat m(semiring, row);
8329 template <
size_t R,
size_t C,
typename Scalar>
8352 template <
typename S,
typename T>
8354 detail::RowViewCommon<S, T>
const& x) {
8356 for (
auto it = x.cbegin(); it != x.cend(); ++it) {
8358 if (it != x.cend() - 1) {
8382 template <
typename Mat>
8386 if (x.number_of_rows() != 1) {
8391 if (n != x.number_of_rows() - 1) {
8396 if (x.number_of_rows() != 1) {
8418 template <
typename Mat>
8423 size_t max_width = 72)
8425 if (braces.size() != 2) {
8427 "the 4th argument (braces) must have size 2, found {}",
8431 size_t const R = x.number_of_rows();
8436 for (
size_t r = 0; r < R; ++r) {
8437 for (
size_t c = 0; c < C; ++c) {
8439 = detail::unicode_string_length(detail::entry_repr(x(r, c)));
8440 row_widths[r] += width;
8441 if (width > max_col_widths[c]) {
8442 max_col_widths[c] = width;
8449 auto const total_width = col_width * C + prefix.size() + 1;
8450 if (total_width > max_width) {
8455 "<{}x{} {}>", x.number_of_rows(), x.number_of_cols(), short_name);
8463 auto const lbrace = braces[0], rbrace = braces[1];
8464 if (R != 0 && C != 0) {
8466 for (
size_t r = 0; r < R; ++r) {
8467 result += fmt::format(
"{}{}", rindent, lbrace);
8470 for (
size_t c = 0; c < C; ++c) {
8471 result += fmt::format(
8472 "{}{:>{}}", csep, detail::entry_repr(x(r, c)), col_width);
8475 result += fmt::format(
"{}", rbrace);
8515 template <
typename Mat>
8530 constexpr size_t operator()(Mat
const& x)
const noexcept {
8531 return x.number_of_rows() * x.number_of_rows() * x.number_of_rows();
8545 template <
typename Mat>
8546 struct Degree<Mat,
std::enable_if_t<IsMatrix<Mat>>> {
8559 constexpr size_t operator()(Mat
const& x)
const noexcept {
8560 return x.number_of_rows();
8574 template <
typename Mat>
8575 struct Hash<Mat,
std::enable_if_t<IsMatrix<Mat>>> {
8588 constexpr size_t operator()(Mat
const& x)
const {
8589 return x.hash_value();
8608 template <
typename Mat>
8613 constexpr void operator()(Mat&,
size_t)
const noexcept {
8615 LIBSEMIGROUPS_ASSERT(
false);
8632 template <
typename Mat>
8633 struct One<Mat,
std::enable_if_t<IsMatrix<Mat>>> {
8662 template <
typename Mat>
8663 struct Product<Mat,
std::enable_if_t<IsMatrix<Mat>>> {
8683 operator()(Mat& xy, Mat
const& x, Mat
const& y,
size_t = 0)
const {
8684 xy.product_inplace_no_checks(x, y);
8692 std::enable_if_t<libsemigroups::IsMatrix<Mat>>>
8693 inline void swap(Mat& x, Mat& y)
noexcept {
DynamicMatrix(std::initializer_list< scalar_type > const &c)
Construct a vector from a std::initializer_list.
Definition matrix.hpp:2892
DynamicMatrix(std::initializer_list< std::initializer_list< scalar_type > > const &m)
Construct a matrix from std::initializer_list of std::initializer_list of scalars.
Definition matrix.hpp:2915
DynamicMatrix()=default
Default constructor.
DynamicMatrix & operator=(DynamicMatrix &&)=default
Default move assignment operator.
scalar_reference at(size_t r, size_t c)
Returns a reference to the specified entry of the matrix.
ProdOp Prod
Alias for the template parameter ProdOp.
Definition matrix.hpp:2811
void product_inplace_no_checks(DynamicMatrix const &x, DynamicMatrix const &y)
Multiplies x and y and stores the result in this.
DynamicMatrix & operator=(DynamicMatrix const &)=default
Default copy assignment operator.
DynamicMatrix Row
The type of a row of a DynamicMatrix.
Definition matrix.hpp:2802
PlusOp Plus
Alias for the template parameter PlusOp.
Definition matrix.hpp:2808
void rows(T &x) const
Add row views for every row in the matrix to a container.
scalar_type scalar_one() const noexcept
Returns the multiplicative identity of the underlying semiring.
typename MatrixCommon::scalar_const_reference scalar_const_reference
The type of const references to the entries in the matrix.
Definition matrix.hpp:2798
void swap(DynamicMatrix &that) noexcept
Swaps the contents of *this with the contents of that.
Definition matrix.hpp:3174
const_iterator cend() noexcept
Returns a const iterator pointing one beyond the last entry in the matrix.
static DynamicMatrix one(size_t n)
Construct the identity matrix.
Definition matrix.hpp:2996
DynamicMatrix(size_t r, size_t c)
Construct a matrix with given dimensions.
Definition matrix.hpp:2869
ZeroOp Zero
Alias for the template parameter ZeroOp.
Definition matrix.hpp:2814
scalar_type scalar_zero() const noexcept
Returns the additive identity of the underlying semiring.
void transpose_no_checks()
Transpose a matrix in-place.
semiring_type const * semiring() const noexcept
Returns the underlying semiring.
OneOp One
Alias for the template parameter OneOp.
Definition matrix.hpp:2817
void semiring_type
Alias for the semiring type (void).
Definition matrix.hpp:2824
RowView row(size_t i) const
Returns a view into a row.
DynamicMatrix(RowView const &rv)
Construct a row from a row view.
Definition matrix.hpp:2949
iterator begin() noexcept
Returns an iterator pointing at the first entry.
size_t number_of_rows() const noexcept
Returns the number of rows of the matrix.
DynamicRowView< PlusOp, ProdOp, ZeroOp, OneOp, Scalar > RowView
The type of a row view into a DynamicMatrix.
Definition matrix.hpp:2805
RowView row_no_checks(size_t i) const
Returns a view into a row.
DynamicMatrix(std::vector< std::vector< scalar_type > > const &m)
Construct a matrix from std::vector of std::vector of scalars.
Definition matrix.hpp:2934
typename MatrixCommon::scalar_reference scalar_reference
The type of references to the entries in the matrix.
Definition matrix.hpp:2793
scalar_reference at(size_t r, size_t c) const
Returns a const reference to the specified entry of the matrix.
DynamicMatrix(DynamicMatrix const &)=default
Default copy constructor.
size_t hash_value() const
Return a hash value of a matrix.
const_iterator cbegin() noexcept
Returns a const iterator pointing at the first entry.
DynamicMatrix(DynamicMatrix &&)=default
Default move constructor.
typename MatrixCommon::scalar_type scalar_type
The type of the entries in the matrix.
Definition matrix.hpp:2790
size_t number_of_cols() const noexcept
Returns the number of columns of the matrix.
void transpose()
Transpose a matrix in-place.
std::pair< scalar_type, scalar_type > coords(const_iterator it) const
Get the coordinates of an iterator.
iterator end() noexcept
Returns an iterator pointing one beyond the last entry in the matrix.
DynamicMatrix(Semiring const *sr, std::initializer_list< std::initializer_list< scalar_type > > const &rws)
Construct a matrix over a given semiring (std::initializer_list of std::initializer_list).
Definition matrix.hpp:3313
DynamicMatrix & operator=(DynamicMatrix &&)=default
Default move assignment operator.
static DynamicMatrix one(Semiring const *semiring, size_t n)
Construct the identity matrix.
Definition matrix.hpp:3390
scalar_reference at(size_t r, size_t c)
Returns a reference to the specified entry of the matrix.
DynamicMatrix(Semiring const *sr, std::vector< std::vector< scalar_type > > const &rws)
Construct a matrix over a given semiring (std::vector of std::vector).
Definition matrix.hpp:3336
DynamicMatrix(Semiring const *sr, size_t r, size_t c)
Construct a matrix over a given semiring with given dimensions.
Definition matrix.hpp:3293
void product_inplace_no_checks(DynamicMatrix const &x, DynamicMatrix const &y)
Multiplies x and y and stores the result in this.
DynamicMatrix & operator=(DynamicMatrix const &)=default
Default copy assignment operator.
DynamicMatrix Row
Alias for the type of the rows of a DynamicMatrix.
Definition matrix.hpp:3250
void rows(T &x) const
Add row views for every row in the matrix to a container.
scalar_type scalar_one() const noexcept
Returns the multiplicative identity of the underlying semiring.
typename MatrixCommon::scalar_const_reference scalar_const_reference
Alias for const references to the template parameter Scalar.
Definition matrix.hpp:3246
void swap(DynamicMatrix &that) noexcept
Swaps the contents of *this with the contents of that.
Definition matrix.hpp:3570
const_iterator cend() noexcept
Returns a const iterator pointing one beyond the last entry in the matrix.
scalar_type scalar_zero() const noexcept
Returns the additive identity of the underlying semiring.
void transpose_no_checks()
Transpose a matrix in-place.
DynamicMatrix()=delete
Deleted.
semiring_type const * semiring() const noexcept
Returns the underlying semiring.
RowView row(size_t i) const
Returns a view into a row.
DynamicMatrix(RowView const &rv)
Construct a row over a given semiring (RowView).
Definition matrix.hpp:3370
iterator begin() noexcept
Returns an iterator pointing at the first entry.
size_t number_of_rows() const noexcept
Returns the number of rows of the matrix.
DynamicMatrix(Semiring const *sr, std::initializer_list< scalar_type > const &rw)
Construct a row over a given semiring (std::initializer_list).
Definition matrix.hpp:3355
RowView row_no_checks(size_t i) const
Returns a view into a row.
typename MatrixCommon::scalar_reference scalar_reference
Alias for references to the template parameter Scalar.
Definition matrix.hpp:3241
scalar_reference at(size_t r, size_t c) const
Returns a const reference to the specified entry of the matrix.
DynamicMatrix(DynamicMatrix const &)=default
Default copy constructor.
size_t hash_value() const
Return a hash value of a matrix.
const_iterator cbegin() noexcept
Returns a const iterator pointing at the first entry.
DynamicMatrix(DynamicMatrix &&)=default
Default move constructor.
typename MatrixCommon::scalar_type scalar_type
Alias for the template parameter Scalar.
Definition matrix.hpp:3238
DynamicRowView< Semiring, Scalar > RowView
Alias for the type of row views of a DynamicMatrix.
Definition matrix.hpp:3253
Semiring semiring_type
Alias for the template parameter Semiring.
Definition matrix.hpp:3258
size_t number_of_cols() const noexcept
Returns the number of columns of the matrix.
void transpose()
Transpose a matrix in-place.
std::pair< scalar_type, scalar_type > coords(const_iterator it) const
Get the coordinates of an iterator.
iterator end() noexcept
Returns an iterator pointing one beyond the last entry in the matrix.
DynamicRowView & operator=(DynamicRowView &&)=default
Default move assignment operator.
size_t size() const noexcept
Returns the size of the row.
DynamicRowView & operator=(DynamicRowView const &)=default
Default copy assignment operator.
DynamicRowView(DynamicRowView const &)=default
Default copy constructor.
DynamicRowView(DynamicRowView &&)=default
Default move constructor.
DynamicRowView(Row const &r)
Construct a row view from a Row.
Definition matrix.hpp:1571
typename RowViewCommon::iterator iterator
Alias for const iterators pointing at entries of a matrix.
Definition matrix.hpp:1535
typename RowViewCommon::scalar_const_reference scalar_const_reference
Alias for const references to the template parameter Scalar.
Definition matrix.hpp:1546
typename RowViewCommon::scalar_reference scalar_reference
Alias for references to the template parameter Scalar.
Definition matrix.hpp:1541
iterator begin() noexcept
Returns a iterator pointing at the first entry.
iterator cend()
Returns a const iterator pointing one beyond the last entry of the row.
typename matrix_type::Row Row
Alias for the type of a row in the underlying matrix.
Definition matrix.hpp:1553
typename RowViewCommon::const_iterator const_iterator
Alias for const iterators pointing at entries of a matrix.
Definition matrix.hpp:1532
const_iterator cbegin() const noexcept
Returns a const iterator pointing at the first entry.
iterator end()
Returns a iterator pointing one beyond the last entry of the row.
Scalar scalar_type
Alias for the template parameter Scalar.
Definition matrix.hpp:1538
typename RowViewCommon::matrix_type matrix_type
Alias for the type of the underlying matrix.
Definition matrix.hpp:1550
DynamicRowView()=default
Default constructor.
size_t size() const noexcept
Returns the size of the row.
DynamicRowView & operator=(DynamicRowView const &)=default
Default copy assignment operator.
typename RowViewCommon::iterator iterator
Alias for const iterators pointing at entries of a matrix.
Definition matrix.hpp:1689
typename RowViewCommon::scalar_const_reference scalar_const_reference
Alias for const references to the template parameter Scalar.
Definition matrix.hpp:1700
typename RowViewCommon::scalar_reference scalar_reference
Alias for references to the template parameter Scalar.
Definition matrix.hpp:1695
iterator begin() noexcept
Returns a iterator pointing at the first entry.
iterator cend()
Returns a const iterator pointing one beyond the last entry of the row.
typename matrix_type::Row Row
Alias for the type of a row in the underlying matrix.
Definition matrix.hpp:1707
typename RowViewCommon::const_iterator const_iterator
Alias for const iterators pointing at entries of a matrix.
Definition matrix.hpp:1686
const_iterator cbegin() const noexcept
Returns a const iterator pointing at the first entry.
iterator end()
Returns a iterator pointing one beyond the last entry of the row.
Scalar scalar_type
Alias for the template parameter Scalar.
Definition matrix.hpp:1692
typename RowViewCommon::matrix_type matrix_type
Alias for the type of the underlying matrix.
Definition matrix.hpp:1704
DynamicRowView()=default
Default constructor.
Class representing a truncated max-plus semiring.
Definition matrix.hpp:5137
static constexpr Scalar scalar_zero() noexcept
Get the additive identity.
Definition matrix.hpp:5211
Scalar plus_no_checks(Scalar x, Scalar y) const noexcept
Addition in a truncated max-plus semiring.
Definition matrix.hpp:5274
Scalar product_no_checks(Scalar x, Scalar y) const noexcept
Multiplication in a truncated max-plus semiring.
Definition matrix.hpp:5239
MaxPlusTruncSemiring()=delete
Deleted default constructor.
Scalar threshold() const noexcept
Get the threshold.
Definition matrix.hpp:5299
static constexpr Scalar scalar_one() noexcept
Get the multiplicative identity.
Definition matrix.hpp:5197
Class representing a truncated min-plus semiring.
Definition matrix.hpp:5614
static constexpr Scalar scalar_zero() noexcept
Get the additive identity.
Definition matrix.hpp:5687
Scalar plus_no_checks(Scalar x, Scalar y) const noexcept
Addition in a truncated min-plus semiring.
Definition matrix.hpp:5750
Scalar product_no_checks(Scalar x, Scalar y) const noexcept
Multiplication in a truncated min-plus semiring.
Definition matrix.hpp:5715
Scalar threshold() const noexcept
Get the threshold.
Definition matrix.hpp:5775
static constexpr Scalar scalar_one() noexcept
Get the multiplicative identity.
Definition matrix.hpp:5672
MinPlusTruncSemiring()=delete
Deleted default constructor.
NTPSemiring & operator=(NTPSemiring const &)=default
Default copy assignment operator.
static constexpr Scalar scalar_zero() noexcept
Get the additive identity.
Definition matrix.hpp:6238
Scalar plus_no_checks(Scalar x, Scalar y) const noexcept
Addition in an ntp semiring.
Definition matrix.hpp:6296
NTPSemiring()=delete
Deleted default constructor.
Scalar product_no_checks(Scalar x, Scalar y) const noexcept
Multiplication in an ntp semiring.
Definition matrix.hpp:6266
Scalar period() const noexcept
Get the period.
Definition matrix.hpp:6330
Scalar threshold() const noexcept
Get the threshold.
Definition matrix.hpp:6314
static constexpr Scalar scalar_one() noexcept
Get the multiplicative identity.
Definition matrix.hpp:6222
Static matrix class.
Definition matrix.hpp:1864
typename MatrixCommon::iterator iterator
Definition matrix.hpp:1911
StaticMatrix(std::initializer_list< scalar_type > const &c)
Construct a row (from std::initializer_list).
Definition matrix.hpp:1939
typename MatrixCommon::const_iterator const_iterator
Definition matrix.hpp:1914
scalar_const_reference at(size_t r, size_t c) const
Returns a const reference to the specified entry of the matrix.
scalar_reference at(size_t r, size_t c)
Returns a reference to the specified entry of the matrix.
ProdOp Prod
Definition matrix.hpp:1902
PlusOp Plus
Definition matrix.hpp:1899
scalar_type scalar_one() const noexcept
StaticMatrix(StaticMatrix &&)=default
Default move constructor.
typename MatrixCommon::scalar_const_reference scalar_const_reference
Alias for const references to the template parameter Scalar.
Definition matrix.hpp:1889
scalar_reference operator()(size_t r, size_t c)
Returns a reference to the specified entry of the matrix.
ZeroOp Zero
Definition matrix.hpp:1905
scalar_type scalar_zero() const noexcept
void transpose_no_checks()
semiring_type const * semiring() const noexcept
void product_inplace_no_checks(StaticMatrix const &x, StaticMatrix const &y)
OneOp One
Definition matrix.hpp:1908
StaticMatrix(std::initializer_list< std::initializer_list< scalar_type > > const &m)
Construct a matrix.
Definition matrix.hpp:1966
StaticRowView< PlusOp, ProdOp, ZeroOp, OneOp, C, Scalar > RowView
Definition matrix.hpp:1896
RowView row(size_t i) const
void swap(StaticMatrix &that) noexcept
static StaticMatrix one() const
Returns an identity matrix.
StaticMatrix(StaticMatrix const &)=default
Default copy constructor.
iterator begin() noexcept
Returns an iterator pointing at the first entry.
StaticMatrix(RowView const &rv)
Construct a row from a row view.
Definition matrix.hpp:2002
size_t number_of_rows() const noexcept
Returns the number of rows of the matrix.
StaticMatrix(std::vector< std::vector< scalar_type > > const &m)
Construct a matrix.
Definition matrix.hpp:1982
StaticMatrix< PlusOp, ProdOp, ZeroOp, OneOp, 1, C, Scalar > Row
Alias for the type of the rows of a StaticMatrix.
Definition matrix.hpp:1893
const_iterator cbegin() const noexcept
RowView row_no_checks(size_t i) const
StaticMatrix()=default
Default constructor.
typename MatrixCommon::scalar_reference scalar_reference
Alias for references to the template parameter Scalar.
Definition matrix.hpp:1884
size_t hash_value() const
typename MatrixCommon::scalar_type scalar_type
Alias for the template parameter Scalar.
Definition matrix.hpp:1881
scalar_const_reference operator()(size_t r, size_t c) const
Returns a const reference to the specified entry of the matrix.
StaticMatrix & operator=(StaticMatrix &&)=default
Default move assignment operator.
size_t number_of_cols() const noexcept
Returns the number of columns of the matrix.
StaticMatrix & operator=(StaticMatrix const &)=default
Default copy assignment operator.
std::pair< scalar_type, scalar_type > coords(const_iterator it) const
Class for views into a row of a matrix over a semiring.
Definition matrix.hpp:1079
typename RowViewCommon::iterator iterator
Alias for const iterators pointing at entries of a matrix.
Definition matrix.hpp:1095
typename RowViewCommon::scalar_const_reference scalar_const_reference
Alias for const references to the template parameter Scalar.
Definition matrix.hpp:1106
StaticRowView & operator=(StaticRowView &&)=default
Default move assignment operator.
typename RowViewCommon::scalar_reference scalar_reference
Alias for references to the template parameter Scalar.
Definition matrix.hpp:1101
iterator begin() noexcept
Returns a iterator pointing at the first entry.
iterator cend()
Returns a const iterator pointing one beyond the last entry of the row.
StaticRowView()=default
Default constructor.
typename matrix_type::Row Row
Alias for the type of a row in the underlying matrix.
Definition matrix.hpp:1113
typename RowViewCommon::const_iterator const_iterator
Alias for const iterators pointing at entries of a matrix.
Definition matrix.hpp:1092
const_iterator cbegin() const noexcept
Returns a const iterator pointing at the first entry.
iterator end()
Returns a iterator pointing one beyond the last entry of the row.
Scalar scalar_type
Alias for the template parameter Scalar.
Definition matrix.hpp:1098
StaticRowView(StaticRowView &&)=default
Default move constructor.
typename RowViewCommon::matrix_type matrix_type
Alias for the type of the underlying matrix.
Definition matrix.hpp:1110
StaticRowView(StaticRowView const &)=default
Default copy constructor.
static constexpr size_t size() const noexcept
Returns the size of the row.
StaticRowView & operator=(StaticRowView const &)=default
Default copy assignment operator.
StaticRowView(Row const &r)
Construct a row view from a Row.
std::string to_human_readable_repr(Action< Element, Point, Func, Traits, LeftOrRight > const &action)
Return a human readable representation of an Action object.
Bipartition operator*(Bipartition const &x, Bipartition const &y)
Multiply two bipartitions.
std::ostringstream & operator<<(std::ostringstream &os, BMat8 const &x)
Insertion operator.
StaticMatrix< BooleanPlus, BooleanProd, BooleanZero, BooleanOne, R, C, int > StaticBMat
Alias for static boolean matrices.
Definition matrix.hpp:3970
static constexpr bool IsBMat
Helper to check if a type is BMat.
Definition matrix.hpp:4028
DynamicMatrix< BooleanPlus, BooleanProd, BooleanZero, BooleanOne, int > DynamicBMat
Alias for dynamic boolean matrices.
Definition matrix.hpp:3956
std::enable_if_t< IsBMat< Mat > > throw_if_bad_entry(Mat const &m)
Check the entries in a boolean matrix are valid.
Definition matrix.hpp:4073
std::conditional_t< R==0||C==0, DynamicBMat, StaticBMat< R, C > > BMat
Alias template for boolean matrices.
Definition matrix.hpp:3993
NegativeInfinity const NEGATIVE_INFINITY
Value for negative infinity.
Undefined const UNDEFINED
Value for something undefined.
PositiveInfinity const POSITIVE_INFINITY
Value for positive infinity.
#define LIBSEMIGROUPS_EXCEPTION(...)
Throw a LibsemigroupsException.
Definition exception.hpp:99
std::conditional_t< R==0||C==0, DynamicIntMat< Scalar >, StaticIntMat< R, C, Scalar > > IntMat
Alias template for integer matrices.
Definition matrix.hpp:4317
DynamicMatrix< IntegerPlus< Scalar >, IntegerProd< Scalar >, IntegerZero< Scalar >, IntegerOne< Scalar >, Scalar > DynamicIntMat
Alias for dynamic integer matrices.
Definition matrix.hpp:4269
StaticMatrix< IntegerPlus< Scalar >, IntegerProd< Scalar >, IntegerZero< Scalar >, IntegerOne< Scalar >, R, C, Scalar > StaticIntMat
Alias for static integer matrices.
Definition matrix.hpp:4292
enable_if_is_same< Return, Blocks > make(Container const &cont)
Check the arguments, construct a Blocks object, and check it.
Definition bipart.hpp:856
static constexpr bool IsMaxPlusMat
Helper variable template.
Definition matrix.hpp:4643
constexpr bool IsStaticMatrix
Helper variable template.
Definition matrix.hpp:3648
constexpr bool IsDynamicMatrix
Helper variable template.
Definition matrix.hpp:3661
static constexpr bool IsIntMat
Helper variable template.
Definition matrix.hpp:4342
auto operator+(typename Mat::scalar_type a, Mat const &x) -> std::enable_if_t< IsMatrix< Mat >, Mat >
Add a scalar to a matrix.
Definition matrix.hpp:8029
static constexpr bool IsMatWithSemiring
Helper variable template.
Definition matrix.hpp:3675
static constexpr bool IsMinPlusMat
Helper variable template.
Definition matrix.hpp:4951
constexpr bool IsMatrix
Helper variable template.
Definition matrix.hpp:168
StaticMatrix< MaxPlusPlus< Scalar >, MaxPlusProd< Scalar >, MaxPlusZero< Scalar >, IntegerZero< Scalar >, R, C, Scalar > StaticMaxPlusMat
Alias for static max-plus matrices.
Definition matrix.hpp:4592
DynamicMatrix< MaxPlusPlus< Scalar >, MaxPlusProd< Scalar >, MaxPlusZero< Scalar >, IntegerZero< Scalar >, Scalar > DynamicMaxPlusMat
Alias for dynamic max-plus matrices.
Definition matrix.hpp:4573
std::conditional_t< R==0||C==0, DynamicMaxPlusMat< Scalar >, StaticMaxPlusMat< R, C, Scalar > > MaxPlusMat
Alias template for max-plus matrices.
Definition matrix.hpp:4616
DynamicMatrix< MaxPlusPlus< Scalar >, MaxPlusTruncProd< T, Scalar >, MaxPlusZero< Scalar >, IntegerZero< Scalar >, Scalar > DynamicMaxPlusTruncMat
Alias for dynamic truncated max-plus matrices.
Definition matrix.hpp:5320
std::conditional_t< R==0||C==0, std::conditional_t< T==0, DynamicMatrix< MaxPlusTruncSemiring< Scalar >, Scalar >, DynamicMaxPlusTruncMat< T, Scalar > >, StaticMaxPlusTruncMat< T, R, C, Scalar > > MaxPlusTruncMat
Alias template for truncated max-plus matrices.
Definition matrix.hpp:5366
StaticMatrix< MaxPlusPlus< Scalar >, MaxPlusTruncProd< T, Scalar >, MaxPlusZero< Scalar >, IntegerZero< Scalar >, R, C, Scalar > StaticMaxPlusTruncMat
Alias for static truncated max-plus matrices.
Definition matrix.hpp:5340
static constexpr bool IsMaxPlusTruncMat
Helper to check if a type is MaxPlusTruncMat.
Definition matrix.hpp:5409
DynamicMatrix< MinPlusPlus< Scalar >, MinPlusProd< Scalar >, MinPlusZero< Scalar >, IntegerZero< Scalar >, Scalar > DynamicMinPlusMat
Alias for dynamic min-plus matrices.
Definition matrix.hpp:4881
StaticMatrix< MinPlusPlus< Scalar >, MinPlusProd< Scalar >, MinPlusZero< Scalar >, IntegerZero< Scalar >, R, C, Scalar > StaticMinPlusMat
Alias for static min-plus matrices.
Definition matrix.hpp:4900
std::conditional_t< R==0||C==0, DynamicMinPlusMat< Scalar >, StaticMinPlusMat< R, C, Scalar > > MinPlusMat
Alias template for min-plus matrices.
Definition matrix.hpp:4924
DynamicMatrix< MinPlusPlus< Scalar >, MinPlusTruncProd< T, Scalar >, MinPlusZero< Scalar >, IntegerZero< Scalar >, Scalar > DynamicMinPlusTruncMat
Alias for dynamic truncated min-plus matrices.
Definition matrix.hpp:5796
StaticMatrix< MinPlusPlus< Scalar >, MinPlusTruncProd< T, Scalar >, MinPlusZero< Scalar >, IntegerZero< Scalar >, R, C, Scalar > StaticMinPlusTruncMat
Alias for static truncated min-plus matrices.
Definition matrix.hpp:5816
static constexpr bool IsMinPlusTruncMat
Helper to check if a type is MinPlusTruncMat.
Definition matrix.hpp:5886
std::conditional_t< R==0||C==0, std::conditional_t< T==0, DynamicMatrix< MinPlusTruncSemiring< Scalar >, Scalar >, DynamicMinPlusTruncMat< T, Scalar > >, StaticMinPlusTruncMat< T, R, C, Scalar > > MinPlusTruncMat
Alias template for truncated min-plus matrices.
Definition matrix.hpp:5843
DynamicMatrix< NTPSemiring< Scalar >, Scalar > DynamicNTPMatWithSemiring
Alias for ntp matrices with dynamic threshold and period.
Definition matrix.hpp:6350
DynamicMatrix< NTPPlus< T, P, Scalar >, NTPProd< T, P, Scalar >, IntegerZero< Scalar >, IntegerOne< Scalar >, Scalar > DynamicNTPMatWithoutSemiring
Alias for ntp matrices with static threshold and period.
Definition matrix.hpp:6366
static constexpr bool IsNTPMat
Helper to check if a type is NTPMat.
Definition matrix.hpp:6470
std::conditional_t< R==0||C==0, std::conditional_t< T==0 &&P==0, DynamicNTPMatWithSemiring< Scalar >, DynamicNTPMatWithoutSemiring< T, P, Scalar > >, StaticNTPMat< T, P, R, C, Scalar > > NTPMat
Alias template for ntp matrices.
Definition matrix.hpp:6427
StaticMatrix< NTPPlus< T, P, Scalar >, NTPProd< T, P, Scalar >, IntegerZero< Scalar >, IntegerOne< Scalar >, R, C, Scalar > StaticNTPMat
Alias for ntp matrices with static threshold and period, and dimensions.
Definition matrix.hpp:6392
std::conditional_t< R==0||C==0, DynamicProjMaxPlusMat< Scalar >, StaticProjMaxPlusMat< R, C, Scalar > > ProjMaxPlusMat
Alias template for projective max-plus matrices.
Definition matrix.hpp:7054
detail::ProjMaxPlusMat< DynamicMaxPlusMat< Scalar > > DynamicProjMaxPlusMat
Alias for dynamic projective max-plus matrices with run-time dimensions.
Definition matrix.hpp:7037
static constexpr bool IsProjMaxPlusMat
Helper to check if a type is ProjMaxPlusMat.
Definition matrix.hpp:7084
detail::ProjMaxPlusMat< StaticMaxPlusMat< R, C, Scalar > > StaticProjMaxPlusMat
Alias for static projective max-plus matrices with compile-time arithmetic and dimensions.
Definition matrix.hpp:7023
T inner_product(T... args)
T lexicographical_compare(T... args)
Bipartition one(Bipartition const &f)
Return the identity bipartition with the same degree as the given bipartition.
std::vector< uint8_t > rows(BMat8 const &x)
Returns a vector of the rows of a BMat8.
constexpr BMat8 transpose(BMat8 const &x) noexcept
Returns the transpose of a BMat8.
Definition bmat8.hpp:719
Namespace for helper functions for matrices.
Definition matrix.hpp:170
void bitset_row_basis(Container &&rows, std::decay_t< Container > &result)
Appends a basis for the space spanned by some bitsets to a container.
Definition matrix.hpp:7482
void bitset_rows(Container &&views, detail::StaticVector1< BitSet< C >, R > &result)
Converts a container of row views of a boolean matrix to bit sets, and append them to another contain...
Definition matrix.hpp:7310
constexpr Scalar period(StaticNTPMat< T, P, R, C, Scalar > const &) noexcept
Returns the period of a static ntp matrix.
Definition matrix.hpp:6506
auto throw_if_bad_coords(Mat const &x, size_t r, size_t c) -> std::enable_if_t< IsMatrix< Mat > >
Throws the arguments do not index an entry of a matrix.
Definition matrix.hpp:235
constexpr auto threshold(Mat const &) noexcept -> std::enable_if_t<!detail::IsTruncMat< Mat >, typename Mat::scalar_type >
Returns the threshold of a matrix.
Definition matrix.hpp:3754
size_t row_space_size(Mat const &x)
Returns the size of the row space of a boolean matrix.
Definition matrix.hpp:7984
std::vector< typename Mat::RowView > rows(Mat const &x)
Returns a std::vector of row views into the rows of a dynamic matrix.
Definition matrix.hpp:7239
auto throw_if_bad_dim(Mat const &x, Mat const &y) -> std::enable_if_t< IsMatrix< Mat > >
Throws if two matrices do not have the same dimensions.
Definition matrix.hpp:206
Mat pow(Mat const &x, typename Mat::scalar_type e)
Returns a power of a matrix.
Definition matrix.hpp:7174
auto throw_if_not_square(Mat const &x) -> std::enable_if_t< IsMatrix< Mat > >
Throws if a matrix is not square.
Definition matrix.hpp:184
std::enable_if_t< IsMaxPlusTruncMat< Mat > > row_basis(Container &&views, std::decay_t< Container > &result)
Appends a basis for a space spanned by row views or bit sets to a container.
Definition matrix.hpp:7654
Namespace for everything in the libsemigroups library.
Definition action.hpp:44
Function object for returning the multiplicative identity.
Definition matrix.hpp:3904
constexpr bool operator()() const noexcept
Call operator returning the multiplication identity true of the boolean semiring.
Definition matrix.hpp:3915
Function object for addition in the boolean semiring.
Definition matrix.hpp:3850
constexpr bool operator()(bool x, bool y) const noexcept
Call operator for addition.
Definition matrix.hpp:3863
Function object for multiplication in the boolean semiring.
Definition matrix.hpp:3877
constexpr bool operator()(bool x, bool y) const noexcept
Call operator for multiplication.
Definition matrix.hpp:3890
Function object for returning the additive identity.
Definition matrix.hpp:3929
constexpr bool operator()() const noexcept
Call operator returning the additive identity false of the boolean semiring.
Definition matrix.hpp:3940
constexpr size_t operator()(Mat const &x) const noexcept
Call operator.
Definition matrix.hpp:8526
Adapter for the complexity of multiplication.
Definition adapters.hpp:128
constexpr size_t operator()(Mat const &x) const noexcept
Call operator.
Definition matrix.hpp:8555
Adapter for the degree of an element.
Definition adapters.hpp:166
constexpr size_t operator()(Mat const &x) const
Call operator.
Definition matrix.hpp:8584
Adapter for hashing.
Definition adapters.hpp:451
constexpr void operator()(Mat &, size_t) const noexcept
Call operator.
Definition matrix.hpp:8609
Adapter for increasing the degree of an element.
Definition adapters.hpp:206
Function object for returning the multiplicative identity.
Definition matrix.hpp:4243
constexpr Scalar operator()() const noexcept
Call operator returning the integer 1.
Definition matrix.hpp:4253
Function object for addition in the ring of integers.
Definition matrix.hpp:4159
constexpr Scalar operator()(Scalar x, Scalar y) const noexcept
Call operator for addition.
Definition matrix.hpp:4172
Function object for multiplication in the ring of integers.
Definition matrix.hpp:4190
constexpr Scalar operator()(Scalar x, Scalar y) const noexcept
Call operator for multiplication.
Definition matrix.hpp:4203
Function object for returning the additive identity.
Definition matrix.hpp:4218
constexpr Scalar operator()() const noexcept
Call operator returning the integer 0.
Definition matrix.hpp:4228
Function object for addition in the max-plus semiring.
Definition matrix.hpp:4461
Scalar operator()(Scalar x, Scalar y) const noexcept
Call operator for addition.
Definition matrix.hpp:4476
Function object for multiplication in the max-plus semiring.
Definition matrix.hpp:4508
Scalar operator()(Scalar x, Scalar y) const noexcept
Call operator for multiplication.
Definition matrix.hpp:4523
Function object for multiplication in truncated max-plus semirings.
Definition matrix.hpp:5095
Scalar operator()(Scalar x, Scalar y) const noexcept
Call operator for multiplication.
Definition matrix.hpp:5110
Function object for returning the additive identity of the max-plus semiring.
Definition matrix.hpp:4545
constexpr Scalar operator()() const noexcept
Call operator for additive identity.
Definition matrix.hpp:4557
Function object for addition in the min-plus semiring.
Definition matrix.hpp:4769
Scalar operator()(Scalar x, Scalar y) const noexcept
Call operator for addition.
Definition matrix.hpp:4784
Function object for multiplication in the min-plus semiring.
Definition matrix.hpp:4816
Scalar operator()(Scalar x, Scalar y) const noexcept
Call operator for multiplication.
Definition matrix.hpp:4831
Function object for multiplication in min-plus truncated semirings.
Definition matrix.hpp:5575
Scalar operator()(Scalar x, Scalar y) const noexcept
Call operator for multiplication.
Definition matrix.hpp:5588
Function object for returning the additive identity of the min-plus semiring.
Definition matrix.hpp:4853
constexpr Scalar operator()() const noexcept
Call operator for additive identity.
Definition matrix.hpp:4865
Function object for addition in ntp semirings.
Definition matrix.hpp:6082
constexpr Scalar operator()(Scalar x, Scalar y) const noexcept
Call operator for addition.
Definition matrix.hpp:6094
Function object for multiplication in an ntp semirings.
Definition matrix.hpp:6123
constexpr Scalar operator()(Scalar x, Scalar y) const noexcept
Call operator for multiplication.
Definition matrix.hpp:6137
Mat operator()(Mat const &x) const
Call operator.
Definition matrix.hpp:8643
Adapter for the identity element of the given type.
Definition adapters.hpp:251
void operator()(Mat &xy, Mat const &x, Mat const &y, size_t=0) const
Call operator.
Definition matrix.hpp:8679
Adapter for the product of two elements.
Definition adapters.hpp:289