monoid.hpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588
  1. /**
  2. * This file is part of Gomu.
  3. *
  4. * Copyright 2016 by Jean Fromentin <jean.fromentin@math.cnrs.fr>
  5. *
  6. * Gomu is free software: you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation, either version 3 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * Gomu is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with Gomu. If not, see <http://www.gnu.org/licenses/>.
  18. */
  19. #ifndef MONOID_HPP
  20. #define MONOID_HPP
  21. #include <cstdint>
  22. #include "../../array.hpp"
  23. #include "stacked_list.hpp"
  24. #define MAX_COMPLEMENT_SIZE 64
  25. //************
  26. //* Typedefs *
  27. //************
  28. //! Monoid generator
  29. typedef int16_t Generator;
  30. //! Complement function of a monoid
  31. typedef int(*SetComplement)(const Generator& x,const Generator& y,Generator* comp);
  32. //! Display function for monoid generator
  33. typedef string(*DisplayGenerator)(const Generator& x);
  34. //! Return the number of generators of the monoid of rank n among a monoid familly
  35. typedef size_t(*GeneratorsNumber)(size_t n);
  36. //***************************
  37. //* Early class definitions *
  38. //***************************
  39. class Reversing;
  40. class LeftReversing;
  41. class RightReversing;
  42. class PresentedMonoid;
  43. class Word;
  44. //*********************
  45. //* Class definitions *
  46. //*********************
  47. //-----------
  48. // Reversing
  49. //-----------
  50. //! Common data and function between left and right reversing algorithms
  51. class Reversing{
  52. public:
  53. //! Internal word
  54. StackedList word;
  55. //! Next detected position to reverse
  56. deque<NInd> to_reverse;
  57. //! Destination structure for complement
  58. Generator comp[MAX_COMPLEMENT_SIZE];
  59. //! Complement function
  60. SetComplement set_comp;
  61. //! Clear internal word
  62. void clear();
  63. //! Display internal word
  64. void disp_word() const;
  65. //! Return internal word
  66. Word get_word() const;
  67. //! Init internal word to be of size s
  68. void init_word(size_t s);
  69. //! Number of detected position to reverse. O implies the word is reversed
  70. size_t remaining_size() const;
  71. //! Set internal word
  72. void set_word(const Word& w);
  73. };
  74. //----------------
  75. // Left reversing
  76. //----------------
  77. //! A class for left reversing algorithm
  78. class LeftReversing:public Reversing{
  79. public:
  80. //! Unique constructor
  81. LeftReversing(SetComplement sc);
  82. //! Test if full reversing gives a positive word when internal word is u.v^(-1)
  83. bool check_positivity();
  84. //! Return numerator of the word
  85. Word denominator();
  86. //! Reverse untill the is no more reversing step
  87. void full_reverse();
  88. //! Return numerator of the word
  89. Word numerator();
  90. //! Perform one reversing step
  91. void reverse();
  92. //! Set internal word to be w
  93. void set_word(const Word& w);
  94. //! Set internal word to be num.den^(-1)
  95. void set_word(const Word& num,const Word& den);
  96. };
  97. //-----------------
  98. // Right reversing
  99. //-----------------
  100. //! A class for right reversing
  101. class RightReversing:public Reversing{
  102. public:
  103. //! Unique constructor
  104. RightReversing(SetComplement sc);
  105. //! Test if full reversing gives a positive word when internal word is u^(-1).v
  106. bool check_positivity();
  107. //! Return numerator of the word
  108. Word denominator();
  109. //! Reverse untill the is no more reversing ste
  110. void full_reverse();
  111. //! Return numerator of the word
  112. Word numerator();
  113. //! Perform one reversing
  114. void reverse();
  115. //! Set internal word
  116. void set_word(const Word& w);
  117. //! Set internal word to be den^(-1).num
  118. void set_word(const Word& den,const Word& num);
  119. };
  120. //-------------
  121. // MonoidTrait
  122. //-------------
  123. //! Class for procedure attached to monoid
  124. class MonoidTrait{
  125. public:
  126. //! Pointer to a LeftReversing
  127. LeftReversing* left_reversing;
  128. //! Pointer to a RightReversing
  129. RightReversing* right_reversing;
  130. //! Extra data
  131. void* data;
  132. //! Empty constructor
  133. MonoidTrait();
  134. //! Destructor
  135. ~MonoidTrait();
  136. //! Test if the family is left complemented
  137. bool is_left_complemented() const;
  138. //! Test if a is left divisible by b, i.e.,if it exists c such that a=b.c */
  139. bool is_left_divisible(const Word& a,const Word& b);
  140. //! Return a Couple (f,c) such that f equals true if a is left divisible by b,
  141. //! i.e.,if it exists c such that a=b.c
  142. pair <bool,Word> is_left_divisible_x(const Word& a,const Word& b);
  143. //! Test if the family is right complemented
  144. bool is_right_complemented() const;
  145. //! Test if a is right divisible by b, i.e.,if it exists c such that a=c.b
  146. bool is_right_divisible(const Word& a,const Word& b);
  147. //! Return a Couple (f,c) such that f equals true if a is right divisible by b,
  148. //! i.e.,if it exists c such that a=c.b
  149. pair<bool,Word> is_right_divisible_x(const Word& a,const Word& b);
  150. //! Return left complement of x and y
  151. Word left_complement(const Generator& x,const Generator& y);
  152. //! Return the left denominator
  153. Word left_denominator();
  154. //! Return the left gcd of a and b, i.e., a maximal element c
  155. //! such that there exist x with a=c.x and y with b=c.y
  156. Word left_gcd(const Word& a,const Word& b);
  157. //! Return a Couple (c,d) where c is the left gcd of a and d is such that a=c.d
  158. pair<Word,Word> left_gcd_x(const Word& a,const Word& b);
  159. //! Return the left lcm of a and b, i.e., a minimal element c
  160. //! such that there exist x with c=x.a and y with c=y.a
  161. Word left_lcm(const Word& a,const Word& b);
  162. //! Return the left lcm complement of a and b, i.e.,
  163. //! an element d such that d.a is equal to the left lcm of a and b
  164. Word left_lcm_complement(const Word& a,const Word& b);
  165. //! Return the left numerator
  166. Word left_numerator();
  167. //! Left reverse the word w
  168. Word left_reverse(const Word& w);
  169. //! Left reverse the u.v^(-1)
  170. Word left_reverse(const Word& u,const Word& v);
  171. //! Return right complement of x and y
  172. Word right_complement(const Generator& x,const Generator& y);
  173. //! Return the right denominator
  174. Word right_denominator();
  175. //! Return the left gcd of a and b, i.e., a maximal element c
  176. //! such that there exist x with a=c.x and y with b=c.y
  177. Word right_gcd(const Word& a,const Word& b);
  178. //! Return a Couple (c,d) where c is the right gcd of a and d is such that a=d.c
  179. pair<Word,Word> right_gcd_x(const Word& a,const Word& b);
  180. //! Return the right lcm of a and b, i.e., a minimal element c
  181. //! such that there exist x with c=a.x and y with c=a.y
  182. Word right_lcm(const Word& a,const Word& b);
  183. //! Return the right lcm complement of a and b, i.e.,
  184. //! an element d such that a.d is equal to the right lcm of a and b
  185. Word right_lcm_complement(const Word& a,const Word& b);
  186. //! Return right numerator
  187. Word right_numerator();
  188. //! Right reverse the word w
  189. Word right_reverse(const Word& w);
  190. //! Right reverse the u^(-1).v
  191. Word right_reverse(const Word& u,const Word& v);
  192. //! Set left complement
  193. void set_left_complement(SetComplement sc);
  194. //! Set right complement
  195. void set_right_complement(SetComplement sc);
  196. };
  197. //--------------
  198. // MonoidFamily
  199. //--------------
  200. //! A class for familly of monoid
  201. class MonoidFamily:public MonoidTrait{
  202. public:
  203. //! Function to display generators
  204. DisplayGenerator gdisp;
  205. //! Function returning the number of generators for a given rank
  206. GeneratorsNumber gnum;
  207. //! Label of the monoid family
  208. string label;
  209. //! Unique constructor
  210. MonoidFamily(string l,DisplayGenerator d,GeneratorsNumber n);
  211. //! Destructor
  212. ~MonoidFamily();
  213. //! Display
  214. string display() const;
  215. //! Return number of generators for rank n
  216. size_t generators_number(size_t n);
  217. };
  218. //------
  219. // Word
  220. //------
  221. //! Class for word
  222. class Word:public Array<Generator>{
  223. public:
  224. //! Empty constructor
  225. Word();
  226. //! Construct a word from a list of Generator
  227. Word(const initializer_list<Generator>& l);
  228. //! Recopy constructor
  229. Word(const Word&);
  230. //! Move constructor
  231. Word(Word&&);
  232. //! Construct a word from an array
  233. Word(const Array<Generator>&);
  234. Word(Array<Generator>&&);
  235. //! Concatenate a word to this one
  236. Word concatenate(const Word& w) const;
  237. //! Return the word inverse of this one
  238. Word inverse() const;
  239. //! Display a word
  240. string display(DisplayGenerator d) const;
  241. };
  242. //***********************
  243. //* Auxiliary functions *
  244. //***********************
  245. //! Comparison function for Generator
  246. //! \param x a generator
  247. //! \param y a generator
  248. //! \return -1 if x<y, 0 if x==y and 1 if x>y
  249. int cmp(const Generator& x,const Generator& y);
  250. //! Display a generator with letter
  251. string disp_alpha(const Generator& x);
  252. //! Multiply word
  253. //! \param u a word
  254. //! \param w a word
  255. //! \return the word uv
  256. Word operator*(const Word& u,const Word& v);
  257. //***********************
  258. //* Inline declarations *
  259. //***********************
  260. //-----------
  261. // Reversing
  262. //-----------
  263. inline void
  264. Reversing::clear(){
  265. to_reverse.clear();
  266. }
  267. inline void
  268. Reversing::disp_word() const{
  269. cout<<word<<endl;
  270. }
  271. inline void
  272. Reversing::init_word(size_t s){
  273. word.init(s);
  274. }
  275. inline size_t
  276. Reversing::remaining_size() const{
  277. return to_reverse.size();
  278. }
  279. inline void
  280. Reversing::set_word(const Word& w){
  281. word.init((NData*)w.array,w.size());
  282. }
  283. //----------------
  284. // Left reversing
  285. //----------------
  286. inline
  287. LeftReversing::LeftReversing(SetComplement sc){
  288. set_comp=sc;
  289. }
  290. inline void
  291. LeftReversing::full_reverse(){
  292. while(not to_reverse.empty())
  293. reverse();
  294. }
  295. //-----------------
  296. // Right reversing
  297. //-----------------
  298. inline
  299. RightReversing::RightReversing(SetComplement sc){
  300. set_comp=sc;
  301. }
  302. inline void
  303. RightReversing::full_reverse(){
  304. while(not to_reverse.empty()) reverse();
  305. }
  306. //--------------
  307. // MonoidFamily
  308. //--------------
  309. inline
  310. MonoidFamily::MonoidFamily(string l,DisplayGenerator d,GeneratorsNumber n):label(l),gdisp(d),gnum(n){
  311. left_reversing=nullptr;
  312. right_reversing=nullptr;
  313. }
  314. inline string
  315. MonoidFamily::display() const{
  316. return label+" monoid family";
  317. }
  318. inline size_t
  319. MonoidFamily::generators_number(size_t n){
  320. return gnum(n);
  321. }
  322. //-------------
  323. // MonoidTrait
  324. //-------------
  325. inline
  326. MonoidTrait::MonoidTrait(){
  327. left_reversing=nullptr;
  328. right_reversing=nullptr;
  329. }
  330. inline bool
  331. MonoidTrait::is_left_complemented() const{
  332. return left_reversing!=nullptr;
  333. }
  334. inline bool
  335. MonoidTrait::is_left_divisible(const Word& a,const Word& b){
  336. right_reversing->set_word(b,a);
  337. return right_reversing->check_positivity();
  338. }
  339. inline bool
  340. MonoidTrait::is_right_divisible(const Word& a,const Word& b){
  341. left_reversing->set_word(a,b);
  342. return left_reversing->check_positivity();
  343. }
  344. inline bool
  345. MonoidTrait::is_right_complemented() const{
  346. return right_reversing!=nullptr;
  347. }
  348. inline Word
  349. MonoidTrait::left_denominator(){
  350. return left_reversing->denominator();
  351. }
  352. inline Word
  353. MonoidTrait::left_lcm_complement(const Word& a,const Word& b){
  354. left_reverse(b,a);
  355. return left_numerator();
  356. }
  357. inline Word
  358. MonoidTrait::left_lcm(const Word& a,const Word& b){
  359. return left_lcm_complement(a,b)*a;
  360. }
  361. inline Word
  362. MonoidTrait::left_numerator(){
  363. return left_reversing->numerator();
  364. }
  365. inline Word
  366. MonoidTrait::left_reverse(const Word& w){
  367. left_reversing->set_word(w);
  368. left_reversing->full_reverse();
  369. return left_reversing->get_word();
  370. }
  371. inline Word
  372. MonoidTrait::left_reverse(const Word& u,const Word& v){
  373. left_reversing->set_word(u,v);
  374. left_reversing->full_reverse();
  375. return left_reversing->get_word();
  376. }
  377. inline Word
  378. MonoidTrait::right_denominator(){
  379. return right_reversing->denominator();
  380. }
  381. inline Word
  382. MonoidTrait::right_lcm(const Word& a,const Word& b){
  383. return a*right_lcm_complement(a,b);
  384. }
  385. inline Word
  386. MonoidTrait::right_lcm_complement(const Word& a,const Word& b){
  387. right_reverse(a,b);
  388. return right_numerator();
  389. }
  390. inline Word
  391. MonoidTrait::right_numerator(){
  392. return right_reversing->numerator();
  393. }
  394. inline Word
  395. MonoidTrait::right_reverse(const Word& w){
  396. right_reversing->set_word(w);
  397. right_reversing->full_reverse();
  398. return right_reversing->get_word();
  399. }
  400. inline Word
  401. MonoidTrait::right_reverse(const Word& u,const Word& v){
  402. right_reversing->set_word(u,v);
  403. right_reversing->full_reverse();
  404. return right_reversing->get_word();
  405. }
  406. inline void
  407. MonoidTrait::set_left_complement(SetComplement sc){
  408. left_reversing=new LeftReversing(sc);
  409. }
  410. inline void
  411. MonoidTrait::set_right_complement(SetComplement sc){
  412. right_reversing=new RightReversing(sc);
  413. }
  414. //------
  415. // Word
  416. //------
  417. inline
  418. Word::Word(){}
  419. inline
  420. Word::Word(const Word& w):Array(w){}
  421. inline
  422. Word::Word(Word&& w):Array(w){}
  423. inline
  424. Word::Word(const Array<Generator>& a):Array(a){}
  425. inline
  426. Word::Word(Array<Generator>&& a):Array(a){}
  427. inline Word
  428. Word::concatenate(const Word& w) const{
  429. return Word(append(w));
  430. }
  431. //***********************
  432. //* Auxiliary functions *
  433. //***********************
  434. inline int
  435. cmp(const Generator& x,const Generator& y){
  436. if(x<y) return -1;
  437. if(x==y) return 0;
  438. return 1;
  439. }
  440. inline string
  441. disp_alpha(const Generator& x){
  442. if(x==0) return "e";
  443. string res="";
  444. if(x>0) return res+char(x-1+'a');
  445. return res+char(-x-1+'A');
  446. }
  447. inline Word
  448. operator*(const Word& u,const Word& v){
  449. return u.append(v);
  450. }
  451. #endif