monoid.hpp 14 KB

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