libsemigroups
elements.h
1 //
2 // libsemigroups - C++ library for semigroups and monoids
3 // Copyright (C) 2016 James D. Mitchell
4 //
5 // This program is free software: you can redistribute it and/or modify
6 // it under the terms of the GNU General Public License as published by
7 // the Free Software Foundation, either version 3 of the License, or
8 // (at your option) any later version.
9 //
10 // This program is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 // GNU General Public License for more details.
14 //
15 // You should have received a copy of the GNU General Public License
16 // along with this program. If not, see <http://www.gnu.org/licenses/>.
17 //
18 
19 // This file contains the declaration of the element class and its subclasses.
20 
21 #ifndef LIBSEMIGROUPS_SRC_ELEMENTS_H_
22 #define LIBSEMIGROUPS_SRC_ELEMENTS_H_
23 
24 #include <math.h>
25 
26 #include <algorithm>
27 #include <functional>
28 #include <iostream>
29 #include <unordered_set>
30 #include <vector>
31 
32 #include "blocks.h"
33 #include "libsemigroups-debug.h"
34 #include "recvec.h"
35 #include "semiring.h"
36 
37 // It appears that GCC 4.8.1 (at least) has a bug that causes an internal
38 // compiler error when trying to compile templated static thread_local storage,
39 // see https://gcc.gnu.org/bugzilla/show_bug.cgi?id=58624
40 #ifdef __GNUC_PREREQ
41 #if !(__GNUC_PREREQ(4, 9))
42 #define DO_NOT_USE_THREAD_LOCAL
43 #endif
44 #elif defined(__clang__)
45 #if !(__has_feature(cxx_thread_local))
46 #define DO_NOT_USE_THREAD_LOCAL
47 #endif
48 #endif
49 
50 namespace libsemigroups {
51 
57  class Element {
58  public:
65  enum elm_t {
67  RWSE = 0,
70  };
71 
76  explicit Element(elm_t type = Element::elm_t::NOT_RWSE)
77  : _hash_value(UNDEFINED), _type(type) {}
78 
83  virtual ~Element() {}
84 
86  elm_t get_type() const {
87  return _type;
88  }
89 
94  virtual bool operator==(const Element& that) const = 0;
95 
102  virtual bool operator<(const Element& that) const = 0;
103 
117  virtual size_t complexity() const = 0;
118 
129  virtual size_t degree() const = 0;
130 
136  inline size_t hash_value() const {
137  if (_hash_value == UNDEFINED) {
138  this->cache_hash_value();
139  }
140  return this->_hash_value;
141  }
142 
148  virtual Element* identity() const = 0;
149 
164  virtual Element* really_copy(size_t increase_deg_by = 0) const = 0;
165 
169  virtual void copy(Element const* x) = 0;
170 
174  virtual void swap(Element* x) = 0;
175 
186  virtual void really_delete() = 0;
187 
198  virtual void redefine(Element const* x, Element const* y) {
199  redefine(x, y, 0);
200  }
201 
221  virtual void
222  redefine(Element const* x, Element const* y, size_t const& thread_id) {
223  (void) thread_id;
224  redefine(x, y);
225  }
226 
232  struct Equal {
234  size_t operator()(Element const* x, Element const* y) const {
235  return *x == *y;
236  }
237  };
238 
245  struct Hash {
248  size_t operator()(Element const* x) const {
249  return x->hash_value();
250  }
251  };
252 
253  protected:
257  virtual void cache_hash_value() const = 0;
258 
265  void reset_hash_value() const {
267  }
268 
274  static size_t const UNDEFINED;
275 
281  mutable size_t _hash_value;
282 
283  private:
284  elm_t _type;
285  };
286 
301  template <typename TValueType, class TSubclass>
303  public:
308  : Element(), _vector(new std::vector<TValueType>()) {}
309 
317  explicit ElementWithVectorData(std::vector<TValueType>* vector)
318  : Element(), _vector(vector) {}
319 
326  explicit ElementWithVectorData(std::vector<TValueType> const& vector)
327  : ElementWithVectorData(new std::vector<TValueType>(vector)) {}
328 
334  inline TValueType operator[](size_t pos) const {
335  return (*_vector)[pos];
336  }
337 
342  inline TValueType at(size_t pos) const {
343  return _vector->at(pos);
344  }
345 
350  bool operator==(Element const& that) const override {
351  return *(static_cast<TSubclass const&>(that)._vector) == *(this->_vector);
352  }
353 
359  bool operator<(Element const& that) const override {
360  TSubclass const& ewvd = static_cast<TSubclass const&>(that);
361  if (this->_vector->size() != ewvd._vector->size()) {
362  return this->_vector->size() < ewvd._vector->size();
363  }
364  for (size_t i = 0; i < this->_vector->size(); i++) {
365  if ((*this)[i] != ewvd[i]) {
366  return (*this)[i] < ewvd[i];
367  }
368  }
369  return false;
370  }
371 
379  Element* really_copy(size_t increase_deg_by = 0) const override {
380  LIBSEMIGROUPS_ASSERT(increase_deg_by == 0);
381  (void) increase_deg_by;
382  std::vector<TValueType>* vector(new std::vector<TValueType>(*_vector));
383  TSubclass* copy = new TSubclass(vector);
384  copy->_hash_value = this->_hash_value;
385  return copy;
386  }
387 
395  void copy(Element const* x) override {
396  LIBSEMIGROUPS_ASSERT(x->degree() == this->degree());
397  ElementWithVectorData const* xx
398  = static_cast<ElementWithVectorData const*>(x);
399  _vector->assign(xx->_vector->cbegin(), xx->_vector->cend());
400  this->_hash_value = xx->_hash_value;
401  }
402 
410  void swap(Element* x) override {
411  LIBSEMIGROUPS_ASSERT(x->degree() == this->degree());
412  ElementWithVectorData* xx = static_cast<ElementWithVectorData*>(x);
413  _vector->swap(*(xx->_vector));
414  std::swap(this->_hash_value, xx->_hash_value);
415  }
416 
418  void really_delete() override {
419  delete _vector;
420  }
421 
426  inline typename std::vector<TValueType>::iterator begin() const {
427  return _vector->begin();
428  }
429 
434  inline typename std::vector<TValueType>::iterator end() const {
435  return _vector->end();
436  }
437 
442  inline typename std::vector<TValueType>::iterator cbegin() const {
443  return _vector->cbegin();
444  }
445 
450  inline typename std::vector<TValueType>::iterator cend() const {
451  return _vector->cend();
452  }
453 
454  protected:
455  // Cannot declare cache_hash_value here, since PBR's are vectors of
456  // vectors, and there is not std::hash<vector<whatever>>.
459  template <typename T>
460  static inline size_t vector_hash(std::vector<T> const* vec) {
461  size_t seed = 0;
462  for (auto const& x : *vec) {
463  seed ^= std::hash<T>{}(x) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
464  }
465  return seed;
466  }
467 
471  std::vector<TValueType>* _vector;
472  };
473 
480  template <typename TValueType, class TSubclass>
482  : public ElementWithVectorData<TValueType, TSubclass> {
484 
485  protected:
492  void cache_hash_value() const override {
493  this->_hash_value = this->vector_hash(this->_vector);
494  }
495  };
496 
527  template <typename TValueType, typename TSubclass>
529  : public ElementWithVectorDataDefaultHash<TValueType, TSubclass> {
530  public:
532  ElementWithVectorDataDefaultHash;
533 
539  size_t complexity() const override {
540  return this->_vector->size();
541  }
542 
548  size_t degree() const override {
549  return this->_vector->size();
550  }
551 
557  size_t crank() const {
558  _lookup.clear();
559  _lookup.resize(degree(), false);
560  size_t r = 0;
561  for (auto const& x : *(this->_vector)) {
562  if (x != UNDEFINED && !_lookup[x]) {
563  _lookup[x] = true;
564  r++;
565  }
566  }
567  return r;
568  }
569 
575  Element* identity() const override {
576  std::vector<TValueType>* vector(new std::vector<TValueType>());
577  vector->reserve(this->degree());
578  for (size_t i = 0; i < this->degree(); i++) {
579  vector->push_back(i);
580  }
581  return new TSubclass(vector);
582  }
583 
588  static TValueType const UNDEFINED;
589 
590  private:
591 // Used for determining rank
592 #ifdef DO_NOT_USE_THREAD_LOCAL
593  static std::vector<bool> _lookup;
594 #else
595  static thread_local std::vector<bool> _lookup;
596 #endif
597  };
598 
599  template <typename TValueType, typename TSubclass>
600 #ifndef DO_NOT_USE_THREAD_LOCAL
601  thread_local
602 #endif
603  std::vector<bool>
605  = std::vector<bool>();
606 
607  template <typename TValueType, typename TSubclass>
609  = std::numeric_limits<TValueType>::max();
610 
622  template <typename T>
623  class Transformation : public PartialTransformation<T, Transformation<T>> {
624  public:
626 
633  Element* really_copy(size_t increase_deg_by = 0) const override {
635  = new Transformation<T>(new std::vector<T>(*this->_vector));
636  if (increase_deg_by == 0) {
637  copy->_hash_value = this->_hash_value;
638  } else {
639  size_t n = copy->_vector->size();
640  copy->_vector->reserve(n + increase_deg_by);
641  for (size_t i = n; i < n + increase_deg_by; i++) {
642  copy->_vector->push_back(i);
643  }
644  }
645  return copy;
646  }
647 
654  void redefine(Element const* x, Element const* y) override {
655  LIBSEMIGROUPS_ASSERT(x->degree() == y->degree());
656  LIBSEMIGROUPS_ASSERT(x->degree() == this->degree());
657  LIBSEMIGROUPS_ASSERT(x != this && y != this);
658  Transformation<T> const* xx(static_cast<Transformation<T> const*>(x));
659  Transformation<T> const* yy(static_cast<Transformation<T> const*>(y));
660  size_t const n = this->_vector->size();
661  for (T i = 0; i < n; i++) {
662  (*this->_vector)[i] = (*yy)[(*xx)[i]];
663  }
664  this->reset_hash_value();
665  }
666 
667  protected:
670  void cache_hash_value() const override {
671  size_t seed = 0;
672  size_t deg = this->_vector->size();
673  for (auto const& val : *(this->_vector)) {
674  seed *= deg;
675  seed += val;
676  }
677  this->_hash_value = seed;
678  }
679  };
680 
694  template <typename T>
695  class PartialPerm : public PartialTransformation<T, PartialPerm<T>> {
696  public:
699 
707  explicit PartialPerm(std::vector<T> const& dom,
708  std::vector<T> const& ran,
709  size_t deg)
711  LIBSEMIGROUPS_ASSERT(dom.size() == ran.size());
712  LIBSEMIGROUPS_ASSERT(dom.empty()
713  || deg >= *std::max_element(dom.begin(), dom.end()));
714 
715  this->_vector->resize(deg + 1, UNDEFINED);
716  for (size_t i = 0; i < dom.size(); i++) {
717  (*this->_vector)[dom[i]] = ran[i];
718  }
719  }
720 
728  bool operator<(const Element& that) const override {
729  auto pp_this = static_cast<const PartialPerm<T>*>(this);
730  auto pp_that = static_cast<const PartialPerm<T>&>(that);
731 
732  size_t deg_this = pp_this->degree();
733  for (auto it = pp_this->_vector->end() - 1;
734  it >= pp_this->_vector->begin();
735  it--) {
736  if (*it == UNDEFINED) {
737  deg_this--;
738  } else {
739  break;
740  }
741  }
742  size_t deg_that = pp_that.degree();
743  for (auto it = pp_that._vector->end() - 1;
744  it >= pp_that._vector->begin() && deg_that >= deg_this;
745  it--) {
746  if (*it == UNDEFINED) {
747  deg_that--;
748  } else {
749  break;
750  }
751  }
752 
753  if (deg_this != deg_that) {
754  return deg_this < deg_that;
755  }
756 
757  for (size_t i = 0; i < deg_this; i++) {
758  if ((*pp_this)[i] != pp_that[i]) {
759  return (*pp_this)[i] == UNDEFINED
760  || (pp_that[i] != UNDEFINED && (*pp_this)[i] < pp_that[i]);
761  }
762  }
763  return false;
764  }
765 
772  Element* really_copy(size_t increase_deg_by = 0) const override {
774  = new PartialPerm<T>(new std::vector<T>(*this->_vector));
775  if (increase_deg_by == 0) {
776  copy->_hash_value = this->_hash_value;
777  } else {
778  size_t n = copy->_vector->size();
779  copy->_vector->reserve(n + increase_deg_by);
780  for (size_t i = n; i < n + increase_deg_by; i++) {
781  copy->_vector->push_back(UNDEFINED);
782  }
783  }
784  return copy;
785  }
786 
793  void redefine(Element const* x, Element const* y) override {
794  LIBSEMIGROUPS_ASSERT(x->degree() == y->degree());
795  LIBSEMIGROUPS_ASSERT(x->degree() == this->degree());
796  LIBSEMIGROUPS_ASSERT(x != this && y != this);
797  PartialPerm<T> const* xx(static_cast<PartialPerm<T> const*>(x));
798  PartialPerm<T> const* yy(static_cast<PartialPerm<T> const*>(y));
799  size_t const n = this->degree();
800  for (T i = 0; i < n; i++) {
801  (*this->_vector)[i]
802  = ((*xx)[i] == UNDEFINED ? UNDEFINED : (*yy)[(*xx)[i]]);
803  }
804  this->reset_hash_value();
805  }
806 
815  size_t crank() const {
816  return this->_vector->size() - std::count(this->_vector->cbegin(),
817  this->_vector->cend(),
818  UNDEFINED);
819  }
820  };
821 
829 
834 
836  : public ElementWithVectorDataDefaultHash<u_int32_t, Bipartition> {
837  // TODO add more explanation to the doc here
838  public:
842  explicit Bipartition(size_t degree)
844  _nr_blocks(Bipartition::UNDEFINED),
845  _nr_left_blocks(Bipartition::UNDEFINED),
846  _trans_blocks_lookup(),
847  _rank(Bipartition::UNDEFINED) {
848  this->_vector->resize(2 * degree);
849  }
850 
860  explicit Bipartition(std::vector<u_int32_t>* blocks)
861  : ElementWithVectorDataDefaultHash<u_int32_t, Bipartition>(blocks),
862  _nr_blocks(Bipartition::UNDEFINED),
863  _nr_left_blocks(Bipartition::UNDEFINED),
864  _trans_blocks_lookup(),
865  _rank(Bipartition::UNDEFINED) {}
866 
876  explicit Bipartition(std::vector<u_int32_t> const& blocks)
877  : Bipartition(new std::vector<u_int32_t>(blocks)) {}
878 
879  // TODO another constructor that accepts an actual partition
880 
885  size_t complexity() const override;
886 
891  size_t degree() const override;
892 
898  Element* identity() const override;
899 
911  void redefine(Element const* x,
912  Element const* y,
913  size_t const& thread_id) override;
914 
920  size_t rank();
921 
926  u_int32_t const_nr_blocks() const;
927 
931  u_int32_t nr_blocks();
932 
938  u_int32_t nr_left_blocks();
939 
945  u_int32_t nr_right_blocks();
946 
954  bool is_transverse_block(size_t index);
955 
961  Blocks* left_blocks();
962 
968  Blocks* right_blocks();
969 
975  inline void set_nr_blocks(size_t nr_blocks) {
976  LIBSEMIGROUPS_ASSERT(_nr_blocks == Bipartition::UNDEFINED
977  || _nr_blocks == nr_blocks);
978  _nr_blocks = nr_blocks;
979  }
980 
987  inline void set_nr_left_blocks(size_t nr_left_blocks) {
988  LIBSEMIGROUPS_ASSERT(_nr_left_blocks == Bipartition::UNDEFINED
989  || _nr_left_blocks == nr_left_blocks);
990  _nr_left_blocks = nr_left_blocks;
991  }
992 
998  inline void set_rank(size_t rank) {
999  LIBSEMIGROUPS_ASSERT(_rank == Bipartition::UNDEFINED || _rank == rank);
1000  _rank = rank;
1001  }
1002 
1003  private:
1004  u_int32_t fuseit(std::vector<u_int32_t>& fuse, u_int32_t pos);
1005  void init_trans_blocks_lookup();
1006 
1007  static std::vector<std::vector<u_int32_t>> _fuse;
1008  static std::vector<std::vector<u_int32_t>> _lookup;
1009 
1010  size_t _nr_blocks;
1011  size_t _nr_left_blocks;
1012  std::vector<bool> _trans_blocks_lookup;
1013  size_t _rank;
1014 
1015  static u_int32_t const UNDEFINED;
1016  };
1017 
1033  template <typename TValueType, class TSubclass>
1035  : public ElementWithVectorDataDefaultHash<TValueType, TSubclass> {
1036  public:
1052  MatrixOverSemiringBase(std::vector<TValueType>* matrix,
1053  Semiring<TValueType> const* semiring)
1054  : ElementWithVectorDataDefaultHash<TValueType, TSubclass>(matrix),
1055  _degree(sqrt(matrix->size())),
1056  _semiring(semiring) {
1057  LIBSEMIGROUPS_ASSERT(semiring != nullptr);
1058  LIBSEMIGROUPS_ASSERT(!matrix->empty());
1059  LIBSEMIGROUPS_ASSERT(matrix->size() == _degree * _degree);
1060  }
1061 
1083  MatrixOverSemiringBase(std::vector<std::vector<TValueType>> const& matrix,
1084  Semiring<TValueType> const* semiring)
1085  : ElementWithVectorDataDefaultHash<TValueType, TSubclass>(),
1086  _degree(matrix[0].size()),
1087  _semiring(semiring) {
1088  LIBSEMIGROUPS_ASSERT(semiring != nullptr);
1089  LIBSEMIGROUPS_ASSERT(!matrix.empty());
1090  LIBSEMIGROUPS_ASSERT(all_of(
1091  matrix.begin(), matrix.end(), [matrix](std::vector<TValueType> row) {
1092  return row.size() == matrix.size();
1093  }));
1094 
1095  this->_vector->reserve(matrix.size() * matrix.size());
1096  for (auto const& row : matrix) {
1097  this->_vector->insert(this->_vector->end(), row.begin(), row.end());
1098  }
1099  }
1100 
1103  return _semiring;
1104  }
1105 
1110  size_t complexity() const override {
1111  return pow(this->degree(), 3);
1112  }
1113 
1118  size_t degree() const override {
1119  return _degree;
1120  }
1121 
1127  Element* identity() const override {
1128  std::vector<TValueType>* vec(new std::vector<TValueType>());
1129  vec->resize(this->_vector->size(), _semiring->zero());
1130  size_t n = this->degree();
1131  for (auto it = vec->begin(); it < vec->end(); it += n + 1) {
1132  (*it) = _semiring->one();
1133  }
1134  return new TSubclass(vec, _semiring);
1135  }
1136 
1141  Element* really_copy(size_t increase_deg_by = 0) const override {
1142  LIBSEMIGROUPS_ASSERT(increase_deg_by == 0);
1143  (void) increase_deg_by;
1146  TSubclass>::really_copy());
1147  LIBSEMIGROUPS_ASSERT(copy->_semiring == nullptr
1148  || copy->_semiring == this->_semiring);
1149  copy->_semiring = _semiring;
1150  return copy;
1151  }
1152 
1159  void redefine(Element const* x, Element const* y) override {
1160  auto xx = static_cast<MatrixOverSemiringBase const*>(x);
1161  auto yy = static_cast<MatrixOverSemiringBase const*>(y);
1162  LIBSEMIGROUPS_ASSERT(xx->degree() == yy->degree());
1163  LIBSEMIGROUPS_ASSERT(xx->degree() == this->degree());
1164  LIBSEMIGROUPS_ASSERT(xx != this && yy != this);
1165  // It can be that the elements are defined over semirings that are
1166  // distinct in memory but equal (for example, when one element comes
1167  // from a semigroup and another from an ideal of that semigroup).
1168  // LIBSEMIGROUPS_ASSERT(xx->semiring() == yy->semiring() &&
1169  // xx->semiring() == this->semiring());
1170  // TODO verify that x, y, and this are defined over the same semiring.
1171  size_t deg = this->degree();
1172 
1173  for (size_t i = 0; i < deg; i++) {
1174  for (size_t j = 0; j < deg; j++) {
1175  int64_t v = _semiring->zero();
1176  for (size_t k = 0; k < deg; k++) {
1177  v = _semiring->plus(
1178  v, _semiring->prod((*xx)[i * deg + k], (*yy)[k * deg + j]));
1179  }
1180  (*this->_vector)[i * deg + j] = v;
1181  }
1182  }
1183  after(); // post process this
1184  this->reset_hash_value();
1185  }
1186 
1187  protected:
1188  friend class ElementWithVectorData<TValueType, TSubclass>;
1192  explicit MatrixOverSemiringBase(std::vector<TValueType>* matrix)
1193  : ElementWithVectorDataDefaultHash<TValueType, TSubclass>(matrix),
1194  _degree(sqrt(matrix->size())),
1195  _semiring(nullptr) {}
1196 
1197  private:
1198  // A function applied after redefinition
1199  virtual inline void after() {}
1200  size_t _degree;
1201  Semiring<TValueType> const* _semiring;
1202  };
1203 
1210  template <typename TValueType>
1212  : public MatrixOverSemiringBase<TValueType,
1213  MatrixOverSemiring<TValueType>> {
1214  friend class ElementWithVectorData<TValueType,
1215  MatrixOverSemiring<TValueType>>;
1217  MatrixOverSemiringBase;
1218  };
1219 
1230  : public MatrixOverSemiringBase<int64_t, ProjectiveMaxPlusMatrix> {
1231  public:
1239  ProjectiveMaxPlusMatrix(std::vector<int64_t>* matrix,
1240  Semiring<int64_t> const* semiring)
1241  : MatrixOverSemiringBase(matrix, semiring) {
1242  after(); // this is to put the matrix in normal form
1243  }
1244 
1252  ProjectiveMaxPlusMatrix(std::vector<std::vector<int64_t>> const& matrix,
1253  Semiring<int64_t> const* semiring)
1254  : MatrixOverSemiringBase(matrix, semiring) {
1255  after(); // this is to put the matrix in normal form
1256  }
1257 
1258  private:
1259  friend class ElementWithVectorData<int64_t, ProjectiveMaxPlusMatrix>;
1260  explicit ProjectiveMaxPlusMatrix(std::vector<int64_t>* matrix)
1261  : MatrixOverSemiringBase(matrix) {}
1262 
1263  // A function applied after redefinition
1264  inline void after() final {
1265  int64_t norm = *std::max_element(_vector->begin(), _vector->end());
1266  for (auto& x : *_vector) {
1267  if (x != LONG_MIN) {
1268  x -= norm;
1269  }
1270  }
1271  }
1272  };
1273 
1281  class BooleanMat : public MatrixOverSemiringBase<bool, BooleanMat> {
1282  public:
1293  explicit BooleanMat(std::vector<bool>* matrix)
1294  : MatrixOverSemiringBase<bool, BooleanMat>(matrix, _semiring) {}
1295 
1301  explicit BooleanMat(std::vector<std::vector<bool>> const& matrix)
1302  : MatrixOverSemiringBase<bool, BooleanMat>(matrix,
1303  BooleanMat::_semiring) {}
1304 
1309  void redefine(Element const* x, Element const* y) final;
1310 
1311  // There is a specialization of std::hash for std::vector<bool> but for
1312  // some reason it causes a dramatic slow down in some of the benchmarks if
1313  // it is used by cache_hash_value below. So, we leave this commented out as
1314  // a reminder not to use it.
1315 
1316  // protected:
1317  // void cache_hash_value() const override {
1318  // this->_hash_value = std::hash<std::vector<bool>>{}(*this->_vector);
1319  // }
1320 
1321  private:
1322  // The next constructor only exists to allow the identity method for
1323  // MatrixOverSemiringBase to work.
1324  friend class MatrixOverSemiringBase<bool, BooleanMat>;
1325  explicit BooleanMat(std::vector<bool>* matrix,
1326  Semiring<bool> const* semiring)
1327  : MatrixOverSemiringBase<bool, BooleanMat>(matrix, semiring) {}
1328 
1329  static BooleanSemiring const* const _semiring;
1330  };
1331 
1337  class PBR : public ElementWithVectorData<std::vector<u_int32_t>, PBR> {
1338  public:
1349 
1354  size_t complexity() const override;
1355 
1361  size_t degree() const override;
1362 
1369  Element* identity() const override;
1370 
1382  void redefine(Element const* x,
1383  Element const* y,
1384  size_t const& thread_id) override;
1385 
1386  protected:
1387  void cache_hash_value() const override;
1388 
1389  private:
1390  void unite_rows(RecVec<bool>& out,
1391  RecVec<bool>& tmp,
1392  size_t const& vertex1,
1393  size_t const& vertex2);
1394 
1395  void x_dfs(std::vector<bool>& x_seen,
1396  std::vector<bool>& y_seen,
1397  RecVec<bool>& tmp,
1398  u_int32_t const& n,
1399  u_int32_t const& i,
1400  PBR const* const x,
1401  PBR const* const y,
1402  size_t const& adj);
1403 
1404  void y_dfs(std::vector<bool>& x_seen,
1405  std::vector<bool>& y_seen,
1406  RecVec<bool>& tmp,
1407  u_int32_t const& n,
1408  u_int32_t const& i,
1409  PBR const* const x,
1410  PBR const* const y,
1411  size_t const& adj);
1412 
1413  static std::vector<std::vector<bool>> _x_seen;
1414  static std::vector<std::vector<bool>> _y_seen;
1415  static std::vector<RecVec<bool>> _out;
1416  static std::vector<RecVec<bool>> _tmp;
1417  };
1418 
1419  template <typename T> static inline void really_delete_cont(T cont) {
1420  for (Element const* x : cont) {
1421  const_cast<Element*>(x)->really_delete();
1422  delete x;
1423  }
1424  }
1425 
1426  template <typename T> static inline void really_delete_cont(T* cont) {
1427  for (Element const* x : *cont) {
1428  const_cast<Element*>(x)->really_delete();
1429  delete x;
1430  }
1431  delete cont;
1432  }
1433 } // namespace libsemigroups
1434 #endif // LIBSEMIGROUPS_SRC_ELEMENTS_H_
Class for bipartitions.
Definition: elements.h:835
Element(elm_t type=Element::elm_t::NOT_RWSE)
A constructor.
Definition: elements.h:76
size_t operator()(Element const *x) const
Returns the value of Element::hash_value applied to the Element pointed to by x.
Definition: elements.h:248
BooleanMat(std::vector< bool > *matrix)
A constructor.
Definition: elements.h:1293
Class for partitioned binary relations (PBR).
Definition: elements.h:1337
ElementWithVectorData()
A constructor.
Definition: elements.h:307
ProjectiveMaxPlusMatrix(std::vector< int64_t > *matrix, Semiring< int64_t > const *semiring)
A constructor.
Definition: elements.h:1239
virtual void redefine(Element const *x, Element const *y, size_t const &thread_id)
Multiplies x and y and stores the result in this.
Definition: elements.h:222
The usual Boolean semiring.
Definition: semiring.h:85
Matrices over a semiring.
Definition: elements.h:1211
virtual void swap(Element *x)=0
Swap another Element with this.
static TValueType const UNDEFINED
Undefined image value.
Definition: elements.h:588
virtual size_t degree() const =0
Returns the degree of an Element.
MatrixOverSemiringBase(std::vector< TValueType > *matrix, Semiring< TValueType > const *semiring)
A constructor.
Definition: elements.h:1052
Matrices over the boolean semiring.
Definition: elements.h:1281
Class for signed partitions of the set .
Definition: blocks.h:45
std::vector< TValueType >::iterator cend() const
Returns a const iterator.
Definition: elements.h:450
bool operator<(Element const &that) const override
Returns true if this is less than that.
Definition: elements.h:359
size_t complexity() const override
Returns the approximate time complexity of multiplying two partial transformations.
Definition: elements.h:539
MatrixOverSemiringBase(std::vector< TValueType > *matrix)
Constructs a MatrixOverSemiringBase with whose underlying semiring is not defined. The underlying semiring must be set by any class deriving from this one.
Definition: elements.h:1192
Bipartition(std::vector< u_int32_t > const &blocks)
A constructor.
Definition: elements.h:876
virtual void cache_hash_value() const =0
Calculate and cache a hash value.
MatrixOverSemiringBase(std::vector< std::vector< TValueType >> const &matrix, Semiring< TValueType > const *semiring)
A constructor.
Definition: elements.h:1083
std::vector< TValueType >::iterator cbegin() const
Returns a const iterator.
Definition: elements.h:442
size_t _hash_value
This data member holds a cached version of the hash value of an Element. It is stored here if it is e...
Definition: elements.h:281
Abstract base class for elements using a vector to store their defining data.
Definition: elements.h:302
Provides a call operator for comparing Elements via pointers.
Definition: elements.h:232
virtual void copy(Element const *x)=0
Copy another Element into this.
PartialPerm(std::vector< T > const &dom, std::vector< T > const &ran, size_t deg)
A constructor.
Definition: elements.h:707
Abstract base class for semigroup elements.
Definition: elements.h:57
void redefine(Element const *x, Element const *y) override
Multiply x and y and stores the result in this.
Definition: elements.h:793
void set_nr_blocks(size_t nr_blocks)
Set the cached number of blocks.
Definition: elements.h:975
Element * identity() const override
Returns the identity transformation with degrees of this.
Definition: elements.h:575
size_t complexity() const override
Returns the approximate time complexity of multiplying two matrices.
Definition: elements.h:1110
Template class for partial permutations.
Definition: elements.h:695
Matrices over a semiring.
Definition: elements.h:1034
ElementWithVectorData(std::vector< TValueType > const &vector)
A constructor.
Definition: elements.h:326
ElementWithVectorData(std::vector< TValueType > *vector)
A constructor.
Definition: elements.h:317
Element * really_copy(size_t increase_deg_by=0) const override
Returns a pointer to a copy of this.
Definition: elements.h:1141
size_t operator()(Element const *x, Element const *y) const
Returns true if x and y point to equal Element&#39;s.
Definition: elements.h:234
void redefine(Element const *x, Element const *y) override
Multiply x and y and stores the result in this.
Definition: elements.h:654
void reset_hash_value() const
Reset the cached value used by Element::hash_value.
Definition: elements.h:265
Type for Element objects not arising from a rewriting system RWS.
Definition: elements.h:69
Bipartition(std::vector< u_int32_t > *blocks)
A constructor.
Definition: elements.h:860
void cache_hash_value() const override
This method is included because it seems to give superior performance in some benchmarks.
Definition: elements.h:670
TValueType operator[](size_t pos) const
Returns the pos entry in the vector containing the defining data.
Definition: elements.h:334
void swap(Element *x) override
Swap another Element with this.
Definition: elements.h:410
ProjectiveMaxPlusMatrix(std::vector< std::vector< int64_t >> const &matrix, Semiring< int64_t > const *semiring)
A constructor.
Definition: elements.h:1252
void cache_hash_value() const override
This method implements the default hash function for an ElementWithVectorData, which uses ElementWith...
Definition: elements.h:492
elm_t get_type() const
Returns the type libsemigroups::Element::elm_t of an Element object.
Definition: elements.h:86
Template class for transformations.
Definition: elements.h:623
Element * really_copy(size_t increase_deg_by=0) const override
Returns a pointer to a copy of this.
Definition: elements.h:772
Namespace for everything in the libsemigroups library.
Definition: blocks.cc:32
size_t hash_value() const
Return the hash value of an Element.
Definition: elements.h:136
bool operator<(const Element &that) const override
Returns true if this is less than that.
Definition: elements.h:728
void set_rank(size_t rank)
Set the cached rank.
Definition: elements.h:998
void copy(Element const *x) override
Copy another Element into this.
Definition: elements.h:395
elm_t
This enum contains some different types of Element.
Definition: elements.h:65
static size_t vector_hash(std::vector< T > const *vec)
Returns a hash value for a vector provided there is a specialization of std::hash for the template ty...
Definition: elements.h:460
Abstract base class for elements using a vector to store their defining data and the default hash fun...
Definition: elements.h:481
virtual bool operator==(const Element &that) const =0
Returns true if this equals that.
size_t degree() const override
Returns the degree of a partial transformation.
Definition: elements.h:548
virtual void really_delete()=0
Deletes the defining data of an Element.
void set_nr_left_blocks(size_t nr_left_blocks)
Set the cached number of left blocks.
Definition: elements.h:987
Element * really_copy(size_t increase_deg_by=0) const override
Returns a pointer to a copy of this.
Definition: elements.h:633
static size_t const UNDEFINED
UNDEFINED value.
Definition: elements.h:274
size_t crank() const
Returns the rank of a partial transformation.
Definition: elements.h:557
std::vector< TValueType >::iterator begin() const
Returns an iterator.
Definition: elements.h:426
std::vector< TValueType > * _vector
The vector containing the defining data of this.
Definition: elements.h:471
virtual ~Element()
A default destructor.
Definition: elements.h:83
virtual void redefine(Element const *x, Element const *y)
Multiplies x and y and stores the result in this.
Definition: elements.h:198
Element * identity() const override
Returns the identity matrix with dimension of this.
Definition: elements.h:1127
virtual Element * really_copy(size_t increase_deg_by=0) const =0
Returns a new element completely independent of this.
virtual bool operator<(const Element &that) const =0
Returns true if this is less than that.
Subclass of Element that wraps an libsemigroups::rws_word_t.
Definition: rwse.h:37
size_t crank() const
Returns the rank of a partial permutation.
Definition: elements.h:815
BooleanMat(std::vector< std::vector< bool >> const &matrix)
A constructor.
Definition: elements.h:1301
std::vector< TValueType >::iterator end() const
Returns an iterator.
Definition: elements.h:434
Element * really_copy(size_t increase_deg_by=0) const override
Returns a pointer to a copy of this.
Definition: elements.h:379
Abstract class for partial transformations.
Definition: elements.h:528
Semiring< TValueType > const * semiring() const
Returns a pointer to the Semiring over which the matrix is defined.
Definition: elements.h:1102
Provides a call operator returning a hash value for an Element via a pointer.
Definition: elements.h:245
size_t degree() const override
Returns the dimension of the matrix.
Definition: elements.h:1118
virtual Element * identity() const =0
Returns a new copy of the identity element.
Class for projective max-plus matrices.
Definition: elements.h:1229
virtual size_t complexity() const =0
Returns the approximate time complexity of multiplying two Element objects in a given subclass...
TValueType at(size_t pos) const
Returns the pos entry in the vector containing the defining data.
Definition: elements.h:342
Bipartition(size_t degree)
A constructor.
Definition: elements.h:842
void really_delete() override
Deletes the defining data of an ElementWithVectorData.
Definition: elements.h:418
bool operator==(Element const &that) const override
Returns true if this equals that.
Definition: elements.h:350
void redefine(Element const *x, Element const *y) override
Multiply x and y and stores the result in this.
Definition: elements.h:1159