monoid.hpp 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636
  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. //* Early class definitions *
  27. //***************************
  28. class Reversing;
  29. class LeftReversing;
  30. class RightReversing;
  31. class PresentedMonoid;
  32. class Word;
  33. //************
  34. //* Typedefs *
  35. //************
  36. //! Monoid generator
  37. typedef int16_t Generator;
  38. //! Complement function of a monoid
  39. typedef int(*SetComplement)(const Generator& x,const Generator& y,Generator* comp);
  40. //! Display function for monoid generator
  41. typedef string(*DisplayGenerator)(const Generator& x);
  42. //! Return the number of generators of the monoid of rank n among a monoid familly
  43. typedef size_t(*GeneratorsNumber)(size_t n);
  44. //! Ranked Generator bijection
  45. typedef Generator(*RankedGeneratorBijection)(size_t r,const Generator& x,int p);
  46. //! Return a ranked word
  47. typedef Word(*RankedWordFactory)(size_t r);
  48. //*********************
  49. //* Class definitions *
  50. //*********************
  51. //-----------
  52. // Reversing
  53. //-----------
  54. //! Common data and function between left and right reversing algorithms
  55. class Reversing{
  56. public:
  57. //! Internal word
  58. StackedList word;
  59. //! Next detected position to reverse
  60. deque<NInd> to_reverse;
  61. //! Destination structure for complement
  62. Generator comp[MAX_COMPLEMENT_SIZE];
  63. //! Complement function
  64. SetComplement set_comp;
  65. //! Clear internal word
  66. void clear();
  67. //! Display internal word
  68. void disp_word() const;
  69. //! Return internal word
  70. Word get_word() const;
  71. //! Init internal word to be of size s
  72. void init_word(size_t s);
  73. //! Number of detected position to reverse. O implies the word is reversed
  74. size_t remaining_size() const;
  75. //! Set internal word
  76. void set_word(const Word& w);
  77. };
  78. //----------------
  79. // Left reversing
  80. //----------------
  81. //! A class for left reversing algorithm
  82. class LeftReversing:public Reversing{
  83. public:
  84. //! Unique constructor
  85. LeftReversing(SetComplement sc);
  86. //! Test if full reversing gives a positive word when internal word is u.v^(-1)
  87. bool check_positivity();
  88. //! Return numerator of the word
  89. Word denominator();
  90. //! Reverse untill the is no more reversing step
  91. void full_reverse();
  92. //! Return numerator of the word
  93. Word numerator();
  94. //! Perform one reversing step
  95. void reverse();
  96. //! Set internal word to be w
  97. void set_word(const Word& w);
  98. //! Set internal word to be num.den^(-1)
  99. void set_word(const Word& num,const Word& den);
  100. };
  101. //-----------------
  102. // Right reversing
  103. //-----------------
  104. //! A class for right reversing
  105. class RightReversing:public Reversing{
  106. public:
  107. //! Unique constructor
  108. RightReversing(SetComplement sc);
  109. //! Test if full reversing gives a positive word when internal word is u^(-1).v
  110. bool check_positivity();
  111. //! Return numerator of the word
  112. Word denominator();
  113. //! Reverse untill the is no more reversing ste
  114. void full_reverse();
  115. //! Return numerator of the word
  116. Word numerator();
  117. //! Perform one reversing
  118. void reverse();
  119. //! Set internal word
  120. void set_word(const Word& w);
  121. //! Set internal word to be den^(-1).num
  122. void set_word(const Word& den,const Word& num);
  123. };
  124. //-------------
  125. // MonoidTrait
  126. //-------------
  127. //! Class for procedure attached to monoid
  128. class MonoidTrait{
  129. public:
  130. //! Pointer to a LeftReversing
  131. LeftReversing* left_reversing;
  132. //! Pointer to a RightReversing
  133. RightReversing* right_reversing;
  134. //! Ranked Garside automorphism germ
  135. RankedGeneratorBijection ranked_phi_germ;
  136. //! Ranked Garside element factory
  137. RankedWordFactory ranked_garside_word_factory;
  138. //! Extra data
  139. void* data;
  140. //! Empty constructor
  141. MonoidTrait();
  142. //! Destructor
  143. ~MonoidTrait();
  144. //! Apply phi_r^p to the word
  145. void apply_phi(size_t r,Word& w,int p=1);
  146. //! Return garside_element of rank r
  147. Word garside_element(size_t r);
  148. //! Test if the family has a left complement
  149. bool has_left_complement() const;
  150. //! Test if the family has a right complement
  151. bool has_right_complement() const;
  152. //! Test if the family has a Garside automorphism
  153. bool has_garside_automorphism() const;
  154. //! Test if the family has a Garside element
  155. bool has_garside_element() const;
  156. //! Test if a is left divisible by b, i.e.,if it exists c such that a=b.c */
  157. bool is_left_divisible(const Word& a,const Word& b);
  158. //! Return a Couple (f,c) such that f equals true if a is left divisible by b,
  159. //! i.e.,if it exists c such that a=b.c
  160. pair <bool,Word> is_left_divisible_x(const Word& a,const Word& b);
  161. //! Test if a is right divisible by b, i.e.,if it exists c such that a=c.b
  162. bool is_right_divisible(const Word& a,const Word& b);
  163. //! Return a Couple (f,c) such that f equals true if a is right divisible by b,
  164. //! i.e.,if it exists c such that a=c.b
  165. pair<bool,Word> is_right_divisible_x(const Word& a,const Word& b);
  166. //! Return left complement of x and y
  167. Word left_complement(const Generator& x,const Generator& y);
  168. //! Return the left denominator
  169. Word left_denominator();
  170. //! Return the left gcd of a and b, i.e., a maximal element c
  171. //! such that there exist x with a=c.x and y with b=c.y
  172. Word left_gcd(const Word& a,const Word& b);
  173. //! Return a Couple (c,d) where c is the left gcd of a and d is such that a=c.d
  174. pair<Word,Word> left_gcd_x(const Word& a,const Word& b);
  175. //! Return the left lcm of a and b, i.e., a minimal element c
  176. //! such that there exist x with c=x.a and y with c=y.a
  177. Word left_lcm(const Word& a,const Word& b);
  178. //! Return the left lcm complement of a and b, i.e.,
  179. //! an element d such that d.a is equal to the left lcm of a and b
  180. Word left_lcm_complement(const Word& a,const Word& b);
  181. //! Return the left numerator
  182. Word left_numerator();
  183. //! Left reverse the word w
  184. Word left_reverse(const Word& w);
  185. //! Left reverse the u.v^(-1)
  186. Word left_reverse(const Word& u,const Word& v);
  187. //! Return the word obtained under phi_r^p
  188. Word phi(size_t r,const Word& w,int p=1);
  189. //! Return right complement of x and y
  190. Word right_complement(const Generator& x,const Generator& y);
  191. //! Return the right denominator
  192. Word right_denominator();
  193. //! Return the left gcd of a and b, i.e., a maximal element c
  194. //! such that there exist x with a=c.x and y with b=c.y
  195. Word right_gcd(const Word& a,const Word& b);
  196. //! Return a Couple (c,d) where c is the right gcd of a and d is such that a=d.c
  197. pair<Word,Word> right_gcd_x(const Word& a,const Word& b);
  198. //! Return the right lcm of a and b, i.e., a minimal element c
  199. //! such that there exist x with c=a.x and y with c=a.y
  200. Word right_lcm(const Word& a,const Word& b);
  201. //! Return the right lcm complement of a and b, i.e.,
  202. //! an element d such that a.d is equal to the right lcm of a and b
  203. Word right_lcm_complement(const Word& a,const Word& b);
  204. //! Return right numerator
  205. Word right_numerator();
  206. //! Right reverse the word w
  207. Word right_reverse(const Word& w);
  208. //! Right reverse the u^(-1).v
  209. Word right_reverse(const Word& u,const Word& v);
  210. //! Set left complement
  211. void set_left_complement(SetComplement sc);
  212. //! Set right complement
  213. void set_right_complement(SetComplement sc);
  214. //! Set ranked phi germ
  215. void set_ranked_phi_germ(RankedGeneratorBijection rpg);
  216. //! Set ranked garside word factory
  217. void set_ranked_garside_word_factory(RankedWordFactory rgwf);
  218. };
  219. //--------------
  220. // MonoidFamily
  221. //--------------
  222. //! A class for familly of monoid
  223. class MonoidFamily:public MonoidTrait{
  224. public:
  225. //! Function to display generators
  226. DisplayGenerator gdisp;
  227. //! Function returning the number of generators for a given rank
  228. GeneratorsNumber gnum;
  229. //! Label of the monoid family
  230. string label;
  231. //! Unique constructor
  232. MonoidFamily(string l,DisplayGenerator d,GeneratorsNumber n);
  233. //! Destructor
  234. ~MonoidFamily();
  235. //! Display
  236. string display() const;
  237. //! Return number of generators for rank n
  238. size_t generators_number(size_t n);
  239. };
  240. //------
  241. // Word
  242. //------
  243. //! Class for word
  244. class Word:public Array<Generator>{
  245. public:
  246. //! Empty constructor
  247. Word();
  248. //! Construct a word from a list of Generator
  249. Word(const initializer_list<Generator>& l);
  250. //! Recopy constructor
  251. Word(const Word&);
  252. //! Move constructor
  253. Word(Word&&);
  254. //! Construct a word from an array
  255. Word(const Array<Generator>&);
  256. Word(Array<Generator>&&);
  257. //! Concatenate a word to this one
  258. Word concatenate(const Word& w) const;
  259. //! Return the word inverse of this one
  260. Word inverse() const;
  261. //! Display a word
  262. string display(DisplayGenerator d) const;
  263. };
  264. //***********************
  265. //* Auxiliary functions *
  266. //***********************
  267. //! Comparison function for Generator
  268. //! \param x a generator
  269. //! \param y a generator
  270. //! \return -1 if x<y, 0 if x==y and 1 if x>y
  271. int cmp(const Generator& x,const Generator& y);
  272. //! Display a generator with letter
  273. string disp_alpha(const Generator& x);
  274. //! Multiply word
  275. //! \param u a word
  276. //! \param w a word
  277. //! \return the word uv
  278. Word operator*(const Word& u,const Word& v);
  279. //***********************
  280. //* Inline declarations *
  281. //***********************
  282. //-----------
  283. // Reversing
  284. //-----------
  285. inline void
  286. Reversing::clear(){
  287. to_reverse.clear();
  288. }
  289. inline void
  290. Reversing::disp_word() const{
  291. cout<<word<<endl;
  292. }
  293. inline void
  294. Reversing::init_word(size_t s){
  295. word.init(s);
  296. }
  297. inline size_t
  298. Reversing::remaining_size() const{
  299. return to_reverse.size();
  300. }
  301. inline void
  302. Reversing::set_word(const Word& w){
  303. word.init((NData*)w.array,w.size());
  304. }
  305. //----------------
  306. // Left reversing
  307. //----------------
  308. inline
  309. LeftReversing::LeftReversing(SetComplement sc){
  310. set_comp=sc;
  311. }
  312. inline void
  313. LeftReversing::full_reverse(){
  314. while(not to_reverse.empty())
  315. reverse();
  316. }
  317. //-----------------
  318. // Right reversing
  319. //-----------------
  320. inline
  321. RightReversing::RightReversing(SetComplement sc){
  322. set_comp=sc;
  323. }
  324. inline void
  325. RightReversing::full_reverse(){
  326. while(not to_reverse.empty()) reverse();
  327. }
  328. //--------------
  329. // MonoidFamily
  330. //--------------
  331. inline
  332. MonoidFamily::MonoidFamily(string l,DisplayGenerator d,GeneratorsNumber n):label(l),gdisp(d),gnum(n){
  333. left_reversing=nullptr;
  334. right_reversing=nullptr;
  335. }
  336. inline string
  337. MonoidFamily::display() const{
  338. return label+" monoid family";
  339. }
  340. inline size_t
  341. MonoidFamily::generators_number(size_t n){
  342. return gnum(n);
  343. }
  344. //-------------
  345. // MonoidTrait
  346. //-------------
  347. inline Word
  348. MonoidTrait::garside_element(size_t r){
  349. return ranked_garside_word_factory(r);
  350. }
  351. inline bool
  352. MonoidTrait::has_garside_element() const{
  353. return ranked_garside_word_factory!=nullptr;
  354. }
  355. inline bool
  356. MonoidTrait::has_garside_automorphism() const{
  357. return ranked_phi_germ!=nullptr;
  358. }
  359. inline bool
  360. MonoidTrait::has_left_complement() const{
  361. return left_reversing!=nullptr;
  362. }
  363. inline bool
  364. MonoidTrait::has_right_complement() const{
  365. return right_reversing!=nullptr;
  366. }
  367. inline bool
  368. MonoidTrait::is_left_divisible(const Word& a,const Word& b){
  369. right_reversing->set_word(b,a);
  370. return right_reversing->check_positivity();
  371. }
  372. inline bool
  373. MonoidTrait::is_right_divisible(const Word& a,const Word& b){
  374. left_reversing->set_word(a,b);
  375. return left_reversing->check_positivity();
  376. }
  377. inline Word
  378. MonoidTrait::left_denominator(){
  379. return left_reversing->denominator();
  380. }
  381. inline Word
  382. MonoidTrait::left_lcm_complement(const Word& a,const Word& b){
  383. left_reverse(b,a);
  384. return left_numerator();
  385. }
  386. inline Word
  387. MonoidTrait::left_lcm(const Word& a,const Word& b){
  388. return left_lcm_complement(a,b)*a;
  389. }
  390. inline Word
  391. MonoidTrait::left_numerator(){
  392. return left_reversing->numerator();
  393. }
  394. inline Word
  395. MonoidTrait::left_reverse(const Word& w){
  396. left_reversing->set_word(w);
  397. left_reversing->full_reverse();
  398. return left_reversing->get_word();
  399. }
  400. inline Word
  401. MonoidTrait::left_reverse(const Word& u,const Word& v){
  402. left_reversing->set_word(u,v);
  403. left_reversing->full_reverse();
  404. return left_reversing->get_word();
  405. }
  406. inline Word
  407. MonoidTrait::right_denominator(){
  408. return right_reversing->denominator();
  409. }
  410. inline Word
  411. MonoidTrait::right_lcm(const Word& a,const Word& b){
  412. return a*right_lcm_complement(a,b);
  413. }
  414. inline Word
  415. MonoidTrait::right_lcm_complement(const Word& a,const Word& b){
  416. right_reverse(a,b);
  417. return right_numerator();
  418. }
  419. inline Word
  420. MonoidTrait::right_numerator(){
  421. return right_reversing->numerator();
  422. }
  423. inline Word
  424. MonoidTrait::right_reverse(const Word& w){
  425. right_reversing->set_word(w);
  426. right_reversing->full_reverse();
  427. return right_reversing->get_word();
  428. }
  429. inline Word
  430. MonoidTrait::right_reverse(const Word& u,const Word& v){
  431. right_reversing->set_word(u,v);
  432. right_reversing->full_reverse();
  433. return right_reversing->get_word();
  434. }
  435. inline void
  436. MonoidTrait::set_left_complement(SetComplement sc){
  437. left_reversing=new LeftReversing(sc);
  438. }
  439. inline void
  440. MonoidTrait::set_right_complement(SetComplement sc){
  441. right_reversing=new RightReversing(sc);
  442. }
  443. inline void
  444. MonoidTrait::set_ranked_phi_germ(RankedGeneratorBijection rpg){
  445. ranked_phi_germ=rpg;
  446. }
  447. inline void
  448. MonoidTrait::set_ranked_garside_word_factory(RankedWordFactory rgwf){
  449. ranked_garside_word_factory=rgwf;
  450. }
  451. //------
  452. // Word
  453. //------
  454. inline
  455. Word::Word(){}
  456. inline
  457. Word::Word(const Word& w):Array(w){}
  458. inline
  459. Word::Word(Word&& w):Array(w){}
  460. inline
  461. Word::Word(const Array<Generator>& a):Array(a){}
  462. inline
  463. Word::Word(Array<Generator>&& a):Array(a){}
  464. inline Word
  465. Word::concatenate(const Word& w) const{
  466. return Word(append(w));
  467. }
  468. //***********************
  469. //* Auxiliary functions *
  470. //***********************
  471. inline int
  472. cmp(const Generator& x,const Generator& y){
  473. if(x<y) return -1;
  474. if(x==y) return 0;
  475. return 1;
  476. }
  477. inline string
  478. disp_alpha(const Generator& x){
  479. if(x==0) return "e";
  480. string res="";
  481. if(x>0) return res+char(x-1+'a');
  482. return res+char(-x-1+'A');
  483. }
  484. inline Word
  485. operator*(const Word& u,const Word& v){
  486. return u.append(v);
  487. }
  488. #endif