Permutation.cpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436
  1. /* Permutation.cpp
  2. *
  3. * Copyright (C) 2005-2018 David Weenink
  4. *
  5. * This code 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 2 of the License, or (at
  8. * your option) any later version.
  9. *
  10. * This code is distributed in the hope that it will be useful, but
  11. * WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  13. * General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU General Public License
  16. * along with this work. If not, see <http://www.gnu.org/licenses/>.
  17. */
  18. /*
  19. djmw 20050706
  20. djmw 20050722 Latest modification.
  21. djmw 20061212 Changed info to Melder_writeLine<x> format.
  22. djmw 20071012 Added: o_CAN_WRITE_AS_ENCODING.h
  23. djmw 20100521 Next and Previous
  24. djmw 20100818 Permutation_permuteTwoItems/Numbers
  25. djmw 20110304 Thing_new
  26. */
  27. #include <time.h>
  28. #include "Permutation.h"
  29. #include "oo_DESTROY.h"
  30. #include "Permutation_def.h"
  31. #include "oo_COPY.h"
  32. #include "Permutation_def.h"
  33. #include "oo_EQUAL.h"
  34. #include "Permutation_def.h"
  35. #include "oo_CAN_WRITE_AS_ENCODING.h"
  36. #include "Permutation_def.h"
  37. #include "oo_WRITE_TEXT.h"
  38. #include "Permutation_def.h"
  39. #include "oo_WRITE_BINARY.h"
  40. #include "Permutation_def.h"
  41. #include "oo_READ_BINARY.h"
  42. #include "Permutation_def.h"
  43. #include "oo_DESCRIPTION.h"
  44. #include "Permutation_def.h"
  45. Thing_implement (Permutation, Daata, 0);
  46. static integer Permutation_checkRange (Permutation me, integer *from, integer *to) {
  47. if (*from == 0)
  48. *from = 1;
  49. if (*to == 0)
  50. *to = my numberOfElements;
  51. Melder_require (*from > 0 && *from <= my numberOfElements && *to > 0 && *to <= my numberOfElements,
  52. U"Range should be in [1, ", my numberOfElements, U"].");
  53. return *to - *from + 1;
  54. }
  55. void Permutation_checkInvariant (Permutation me) {
  56. autoPermutation thee = Data_copy (me);
  57. NUMsort_integer (thy numberOfElements, thy p.at);
  58. for (integer i = 1; i <= my numberOfElements; i ++) {
  59. Melder_require (thy p [i] == i,
  60. me, U": is not a valid permutation.");
  61. }
  62. }
  63. void structPermutation :: v_info () {
  64. structDaata :: v_info ();
  65. MelderInfo_writeLine (U"Number of elements: ", numberOfElements);
  66. }
  67. void structPermutation :: v_readText (MelderReadText text, int /*formatVersion*/) {
  68. numberOfElements = texgeti32 (text);
  69. Melder_require (numberOfElements > 0,
  70. U"Number of elements should be greater than zero.");
  71. p.at = NUMvector_readText_integer32BE (1, numberOfElements, text, "p");
  72. Permutation_checkInvariant (this);
  73. }
  74. void Permutation_init (Permutation me, integer numberOfElements) {
  75. my numberOfElements = numberOfElements;
  76. my p = INTVECraw (numberOfElements);
  77. Permutation_sort (me);
  78. }
  79. void Permutation_tableJump_inline (Permutation me, integer jumpSize, integer first) {
  80. if (jumpSize >= my numberOfElements || first > my numberOfElements)
  81. return;
  82. autoINTVEC p_copy = INTVECcopy (my p.get());
  83. integer index = first, column = 1;
  84. if (first > 1)
  85. column = (first - 1) % jumpSize + 1;
  86. for (integer i = 1; i <= my numberOfElements; i ++) {
  87. my p [i] = p_copy [index];
  88. index += jumpSize;
  89. if (index > my numberOfElements) {
  90. if (++ column > jumpSize)
  91. column = 1;
  92. index = column;
  93. }
  94. }
  95. }
  96. autoPermutation Permutation_create (integer numberOfElements) {
  97. try {
  98. autoPermutation me = Thing_new (Permutation);
  99. Permutation_init (me.get(), numberOfElements);
  100. return me;
  101. } catch (MelderError) {
  102. Melder_throw (U"Permutation not created.");
  103. }
  104. }
  105. void Permutation_sort (Permutation me) {
  106. for (integer i = 1; i <= my numberOfElements; i ++)
  107. my p [i] = i;
  108. }
  109. void Permutation_swapPositions (Permutation me, integer i1, integer i2) {
  110. try {
  111. Melder_require (i1 > 0 && i1 <= my numberOfElements && i2 > 0 && i2 <= my numberOfElements,
  112. U"Positions should be within the range [1, ", my numberOfElements, U"].");
  113. std::swap (my p [i1], my p [i2]);
  114. } catch (MelderError) {
  115. Melder_throw (me, U":positions not swapped.");
  116. }
  117. }
  118. void Permutation_swapNumbers (Permutation me, integer i1, integer i2) {
  119. try {
  120. integer ip = 0;
  121. Melder_require (i1 > 0 && i1 <= my numberOfElements && i2 > 0 && i2 <= my numberOfElements,
  122. U"Positions should be within the range [1, ", my numberOfElements, U"].");
  123. if (i1 == i2)
  124. return;
  125. for (integer i = 1; i <= my numberOfElements; i ++) {
  126. if (my p [i] == i1) {
  127. my p [i] = i2;
  128. ip ++;
  129. } else if (my p [i] == i2) {
  130. my p [i] = i1;
  131. ip ++;
  132. }
  133. if (ip == 2)
  134. break;
  135. }
  136. Melder_assert (ip == 2);
  137. } catch (MelderError) {
  138. Melder_throw (me, U": numbers not swapped.");
  139. }
  140. }
  141. void Permutation_swapBlocks (Permutation me, integer from, integer to, integer blockSize) {
  142. try {
  143. Melder_require (blockSize > 0 && blockSize <= my numberOfElements / 2,
  144. U"The block size should be in the [1, %d] range.", my numberOfElements / 2);
  145. Melder_require (from > 0 && to > 0 && from + blockSize <= my numberOfElements && to + blockSize <= my numberOfElements,
  146. U"Start and finish positions of the two blocks should be in [1,", my numberOfElements, U"] range.");
  147. if (from == to)
  148. return;
  149. for (integer i = 1; i <= blockSize; i ++)
  150. std::swap (my p [from + i - 1], my p [to + i - 1]);
  151. } catch (MelderError) {
  152. Melder_throw (me, U": blocks not swapped.");
  153. }
  154. }
  155. void Permutation_permuteRandomly_inplace (Permutation me, integer from, integer to) {
  156. try {
  157. integer n = Permutation_checkRange (me, & from, & to);
  158. if (n == 1)
  159. return;
  160. for (integer i = from; i < to; i ++) {
  161. integer newpos = NUMrandomInteger (from, to);
  162. std::swap (my p [i], my p [newpos]);
  163. }
  164. } catch (MelderError) {
  165. Melder_throw (me, U": not permuted randomly.");
  166. }
  167. }
  168. autoPermutation Permutation_permuteRandomly (Permutation me, integer from, integer to) {
  169. try {
  170. autoPermutation thee = Data_copy (me);
  171. Permutation_permuteRandomly_inplace (thee.get(), from, to);
  172. return thee;
  173. } catch (MelderError) {
  174. Melder_throw (me, U": not permuted.");
  175. }
  176. }
  177. autoPermutation Permutation_rotate (Permutation me, integer from, integer to, integer step) {
  178. try {
  179. integer n = Permutation_checkRange (me, & from, & to);
  180. step = (step - 1) % n + 1;
  181. autoPermutation thee = Data_copy (me);
  182. for (integer i = from; i <= to; i ++) {
  183. integer ifrom = i + step;
  184. if (ifrom > to)
  185. ifrom -= n;
  186. if (ifrom < from)
  187. ifrom += n;
  188. thy p [ifrom] = my p[i];
  189. }
  190. return thee;
  191. } catch (MelderError) {
  192. Melder_throw (me, U": not rotated.");
  193. }
  194. }
  195. void Permutation_swapOneFromRange (Permutation me, integer from, integer to, integer pos, bool forbidsame) {
  196. try {
  197. integer n = Permutation_checkRange (me, & from, & to);
  198. integer newpos = NUMrandomInteger (from, to);
  199. if (newpos == pos && forbidsame) {
  200. Melder_require (n != 1,
  201. U"Impossible to satisfy \"forbid same\" constraint within the chosen range.");
  202. while ((newpos = NUMrandomInteger (from, to)) == pos) {
  203. ;
  204. }
  205. }
  206. std::swap (my p [pos], my p [newpos]);
  207. } catch (MelderError) {
  208. Melder_throw (me, U": one from range not swapped.");
  209. }
  210. }
  211. autoPermutation Permutation_permuteBlocksRandomly (Permutation me, integer from, integer to, integer blockSize, bool permuteWithinBlocks, bool noDoublets) {
  212. try {
  213. integer n = Permutation_checkRange (me, & from, & to);
  214. if (blockSize == 1 || (blockSize >= n && permuteWithinBlocks)) {
  215. autoPermutation thee = Permutation_permuteRandomly (me, from, to);
  216. return thee;
  217. }
  218. autoPermutation thee = Data_copy (me);
  219. if (blockSize >= n)
  220. return thee;
  221. integer nblocks = n / blockSize, nrest = n % blockSize;
  222. Melder_require (nrest == 0,
  223. U"There should fit an integer number of blocks in the range.\n(The last block is only of size ", nrest, U").");
  224. autoPermutation pblocks = Permutation_create (nblocks);
  225. Permutation_permuteRandomly_inplace (pblocks.get(), 1, nblocks);
  226. integer first = from;
  227. for (integer iblock = 1; iblock <= nblocks; iblock ++, first += blockSize) {
  228. /* (n1,n2,n3,...) means: move block n1 to position 1 etc... */
  229. integer blocktomove = Permutation_getValueAtIndex (pblocks.get(), iblock);
  230. for (integer j = 1; j <= blockSize; j ++)
  231. thy p [first - 1 + j] = my p [from - 1 + (blocktomove - 1) * blockSize + j];
  232. if (permuteWithinBlocks) {
  233. integer last = first + blockSize - 1;
  234. Permutation_permuteRandomly_inplace (thee.get(), first, last);
  235. if (noDoublets && iblock > 0 && thy p [first - 1] % blockSize == thy p [first] % blockSize)
  236. Permutation_swapOneFromRange (thee.get(), first + 1, last, first, 0);
  237. }
  238. }
  239. return thee;
  240. } catch (MelderError) {
  241. Melder_throw (me, U": not permuted block randomly.");
  242. }
  243. }
  244. autoPermutation Permutation_interleave (Permutation me, integer from, integer to, integer blockSize, integer offset) {
  245. try {
  246. Melder_require (offset < blockSize,
  247. U"Offset should be smaller than block size.");
  248. integer n = Permutation_checkRange (me, & from, & to);
  249. integer nblocks = n / blockSize, nrest = n % blockSize;
  250. Melder_require (nrest == 0,
  251. U"There should fit an integer number of blocks in the range.\n"
  252. U"(The last block is only of size ", nrest, U" instead of ", blockSize, U").");
  253. autoPermutation thee = Data_copy (me);
  254. if (nblocks > 1) {
  255. autoNUMvector<integer> occupied (1, blockSize);
  256. integer posinblock = 1 - offset;
  257. for (integer i = 1; i <= n; i ++) {
  258. integer index, rblock = (i - 1) % nblocks + 1;
  259. posinblock += offset;
  260. if (posinblock > blockSize)
  261. posinblock -= blockSize;
  262. if (i % nblocks == 1) {
  263. integer count = blockSize;
  264. while (occupied [posinblock] == 1 && count > 0) {
  265. posinblock ++;
  266. count --;
  267. if (posinblock > blockSize)
  268. posinblock -= blockSize;
  269. }
  270. occupied [posinblock] = 1;
  271. }
  272. index = from - 1 + (rblock - 1) * blockSize + posinblock;
  273. thy p [from - 1 + i] = my p [index];
  274. }
  275. }
  276. return thee;
  277. } catch (MelderError) {
  278. Melder_throw (me, U": not interleaved.");
  279. }
  280. }
  281. integer Permutation_getValueAtIndex (Permutation me, integer i) {
  282. return i > 0 && i <= my numberOfElements ? my p [i] : -1;
  283. }
  284. integer Permutation_getIndexAtValue (Permutation me, integer value) {
  285. for (integer i = 1; i <= my numberOfElements; i ++) {
  286. if (my p [i] == value)
  287. return i;
  288. }
  289. return -1;
  290. }
  291. autoPermutation Permutation_invert (Permutation me) {
  292. try {
  293. autoPermutation thee = Data_copy (me);
  294. for (integer i = 1; i <= my numberOfElements; i ++)
  295. thy p [my p [i]] = i;
  296. return thee;
  297. } catch (MelderError) {
  298. Melder_throw (me, U": not inverted.");
  299. }
  300. }
  301. void Permutation_reverse_inline (Permutation me, integer from, integer to) {
  302. integer n = Permutation_checkRange (me, & from, & to);
  303. for (integer i = 1; i <= n / 2; i ++)
  304. std::swap (my p [from + i - 1], my p [to - i + 1] );
  305. }
  306. autoPermutation Permutation_reverse (Permutation me, integer from, integer to) {
  307. try {
  308. (void) Permutation_checkRange (me, & from, & to);
  309. autoPermutation thee = Data_copy (me);
  310. Permutation_reverse_inline (thee.get(), from, to);
  311. return thee;
  312. } catch (MelderError) {
  313. Melder_throw (me, U": not reversed.");
  314. }
  315. }
  316. /* Replaces p with the next permutation (in the standard lexicographical ordering.
  317. Adapted from the GSL library
  318. */
  319. void Permutation_next_inplace (Permutation me) {
  320. integer size = my numberOfElements;
  321. Melder_require (size > 1,
  322. U"The permutation should have more than one element.");
  323. integer *p = & my p [1];
  324. integer i = size - 2;
  325. while (p [i] > p [i + 1] && i != 0)
  326. i --;
  327. if (i == 0 && p [0] > p [1])
  328. Melder_throw (U"No next element.");
  329. integer k = i + 1;
  330. for (integer j = i + 2; j < size; j ++) {
  331. if (p [j] > p [i] && p [j] < p [k])
  332. k = j;
  333. }
  334. std::swap (p [i], p [k]);
  335. for (integer j = i + 1; j <= (size + i) / 2; j ++)
  336. std::swap (p [j], p [size + i - j]);
  337. }
  338. /* Replaces p with the previous permutation (in the standard lexicographical ordering.
  339. Adapted from the GSL library
  340. */
  341. void Permutation_previous_inplace (Permutation me) {
  342. integer size = my numberOfElements;
  343. Melder_require (size > 1,
  344. U"The permutation should have more than one element.");
  345. integer *p = & my p [1];
  346. integer i = size - 2;
  347. while ((p [i] < p [i + 1]) && (i != 0))
  348. i --;
  349. Melder_require (! (i == 0 && p [0] < p [1]),
  350. U"No previous element.");
  351. integer k = i + 1;
  352. for (integer j = i + 2; j < size; j ++) {
  353. if (p [j] < p [i] && p [j] > p [k])
  354. k = j;
  355. }
  356. std::swap (p [i], p [k]);
  357. for (integer j = i + 1; j <= (size + i) / 2; j ++)
  358. std::swap (p [j], p [size + i - j]);
  359. }
  360. autoPermutation Permutations_multiply2 (Permutation me, Permutation thee) {
  361. try {
  362. Melder_require (my numberOfElements == thy numberOfElements,
  363. U"Number of elements should be equal.");
  364. autoPermutation him = Data_copy (me);
  365. for (integer i = 1; i <= my numberOfElements; i ++)
  366. his p [i] = my p [thy p [i]];
  367. return him;
  368. } catch (MelderError) {
  369. Melder_throw (me, U" & ", thee, U" not multiplied.");
  370. }
  371. }
  372. autoPermutation Permutations_multiply (OrderedOf<structPermutation>* me) {
  373. try {
  374. Melder_require (my size > 1, U"There should be at least two Permutations to multiply.");
  375. autoPermutation thee = Permutations_multiply2 (my at [1], my at [2]);
  376. for (integer i = 3; i <= my size; i ++) {
  377. autoPermutation him = Permutations_multiply2 (thee.get(), my at [i]);
  378. thee = him.move();
  379. }
  380. return thee;
  381. } catch (MelderError) {
  382. Melder_throw (U"Permutations not multiplied.");
  383. }
  384. }
  385. /* End of Permutation.cpp */