numeric_monoid.pyx 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716
  1. r"""
  2. Recompile with::
  3. sage -python setup.py build_ext --inplace
  4. Due to compilation outside Sage, the option `--force_lib` has ot be given for
  5. doctests to prevent Sage for recompiling this file. The doctest command is::
  6. sage -t --force-lib numeric_monoid.pyx`
  7. And the each doctest series should start with::
  8. sage: import os; os.sys.path.insert(0,os.path.abspath('.')); from numeric_monoid import *
  9. The following bound are fixed at compile time::
  10. sage: SIZE
  11. 256
  12. sage: MAX_GENUS
  13. 86
  14. .. warning::
  15. Due to modular arithmetic the 255-th decomposition number of the full
  16. monoid is considered as 0 instead of 256.
  17. """
  18. import cython
  19. from sage.rings.integer cimport Integer
  20. from sage.rings.integer import GCD_list
  21. from sage.structure.sage_object cimport SageObject
  22. include 'cysignals/signals.pxi'
  23. from monoid cimport *
  24. from treewalk cimport *
  25. SIZE = cSIZE
  26. MAX_GENUS = cMAX_GENUS
  27. print_gen = True
  28. cdef class NumericMonoid(object):
  29. r"""
  30. sage: import os; os.sys.path.insert(0,os.path.abspath('.')); from numeric_monoid import *
  31. sage: Full
  32. < 1 >
  33. """
  34. def __init__(self):
  35. r"""
  36. sage: import os; os.sys.path.insert(0,os.path.abspath('.')); from numeric_monoid import *
  37. sage: NumericMonoid()
  38. < 1 >
  39. """
  40. init_full_N(self._m)
  41. cpdef int genus(self):
  42. r"""
  43. sage: import os; os.sys.path.insert(0,os.path.abspath('.')); from numeric_monoid import *
  44. sage: Full.genus()
  45. 0
  46. sage: NumericMonoid.from_generators([3,5]).genus()
  47. 4
  48. """
  49. return self._m.genus
  50. cpdef int min(self):
  51. r"""
  52. sage: import os; os.sys.path.insert(0,os.path.abspath('.')); from numeric_monoid import *
  53. sage: Full.min()
  54. 1
  55. sage: NumericMonoid.from_generators([3,5]).min()
  56. 3
  57. """
  58. return self._m.min
  59. cpdef int conductor(self):
  60. r"""
  61. sage: import os; os.sys.path.insert(0,os.path.abspath('.')); from numeric_monoid import *
  62. sage: Full.conductor()
  63. 1
  64. sage: NumericMonoid.from_generators([3,5]).conductor()
  65. 8
  66. """
  67. return self._m.conductor
  68. cpdef _print(self):
  69. r"""
  70. sage: import os; os.sys.path.insert(0,os.path.abspath('.')); from numeric_monoid import *
  71. sage: Full._print()
  72. min = 1, cond = 1, genus = 0, decs = 1 1 2 2 3 3 4 4 ... 128 128
  73. sage: NumericMonoid.from_generators([3,5])._print()
  74. min = 3, cond = 8, genus = 4, decs = 1 0 0 1 0 1 2 0 2 2 2 3 3 3 4 4 5 5 ... 124 124
  75. """
  76. print_monoid(self._m)
  77. def __contains__(self, unsigned int i):
  78. r"""
  79. sage: import os; os.sys.path.insert(0,os.path.abspath('.')); from numeric_monoid import *
  80. sage: m = NumericMonoid.from_generators([3,5])
  81. sage: [i in m for i in range(10)]
  82. [True, False, False, True, False, True, True, False, True, True]
  83. sage: 1000 in m
  84. True
  85. """
  86. if i > self._m.conductor:
  87. return True
  88. return self._m.decs[i] != 0
  89. cpdef list elements(self):
  90. r"""
  91. sage: import os; os.sys.path.insert(0,os.path.abspath('.')); from numeric_monoid import *
  92. sage: Full.elements()
  93. [0, 1]
  94. sage: NumericMonoid.from_generators([3,5]).elements()
  95. [0, 3, 5, 6, 8]
  96. """
  97. cdef list res = []
  98. cdef ind_t i
  99. for i in range(self._m.conductor+1):
  100. if self._m.decs[i] > 0:
  101. res.append(int(i))
  102. return res
  103. cpdef list gaps(self):
  104. r"""
  105. sage: import os; os.sys.path.insert(0,os.path.abspath('.')); from numeric_monoid import *
  106. sage: Full.gaps()
  107. []
  108. sage: NumericMonoid.from_generators([3,5]).gaps()
  109. [1, 2, 4, 7]
  110. sage: all(len(m.gaps())==m.genus() for i in range(6) for m in Full.nth_generation(i))
  111. True
  112. """
  113. cdef list res = []
  114. cdef ind_t i
  115. for i in range(self._m.conductor):
  116. if self._m.decs[i] == 0:
  117. res.append(int(i))
  118. return res
  119. def __repr__(self):
  120. r"""
  121. sage: import os; os.sys.path.insert(0,os.path.abspath('.')); from numeric_monoid import *
  122. sage: Full # indirect doctest
  123. < 1 >
  124. sage: NumericMonoid.from_generators([3,5]) # indirect doctest
  125. < 3 5 >
  126. """
  127. cdef str res
  128. cdef ind_t i
  129. if print_gen:
  130. return "< "+" ".join(str(i) for i in self.generators())+" >"
  131. else:
  132. res = "Mon("
  133. for i in range(self._m.conductor+2):
  134. if self._m.decs[i] > 0:
  135. res += "%i "%i
  136. return res+"...)"
  137. def _latex_(self):
  138. r"""
  139. sage: import os; os.sys.path.insert(0,os.path.abspath('.')); from numeric_monoid import *
  140. sage: Full._latex_()
  141. '\\langle\\,1\\,\\rangle'
  142. sage: NumericMonoid.from_generators([3,5])._latex_()
  143. '\\langle\\,3\\,5\\,\\rangle'
  144. """
  145. cdef int i
  146. if print_gen:
  147. return "\\langle\\,"+"\\,".join(str(i) for i in self.generators())+"\\,\\rangle"
  148. def __reduce__(self):
  149. r"""
  150. sage: import os; os.sys.path.insert(0,os.path.abspath('.')); from numeric_monoid import *
  151. sage: Full.__reduce__()
  152. (<built-in function _from_pickle>, (<type 'numeric_monoid.NumericMonoid'>, 256, 1L, 1L, 0L, (1, 1, 2, 2, 3, 3, 4, 4, ..., 128)))
  153. sage: NumericMonoid.from_generators([3,5]).__reduce__()
  154. (<built-in function _from_pickle>, (<type 'numeric_monoid.NumericMonoid'>, 256, 8L, 3L, 4L, (1, 0, 0, 1, 0, 1, 2, 0, 2, 2, ..., 124, 124)))
  155. """
  156. return (_from_pickle,
  157. (NumericMonoid, cSIZE,
  158. self._m.conductor, self._m.min, self._m.genus,
  159. tuple(self._decomposition_numbers())))
  160. # < 0 <= 1 == 2 != 3 > 4 >= 5
  161. def __richcmp__(NumericMonoid self, NumericMonoid other, int op):
  162. """
  163. Inclusion Order
  164. EXAMPLE::
  165. sage: import os; os.sys.path.insert(0,os.path.abspath('.')); from numeric_monoid import *
  166. sage: m1 = NumericMonoid.from_generators([3,5,7])
  167. sage: Full == Full, Full != Full, Full == m1, Full != m1
  168. (True, False, False, True)
  169. sage: m1 == m1, m1 != m1, m1 < m1, m1 <= m1, m1 > m1, m1 >= m1
  170. (True, False, False, True, False, True)
  171. sage: Full < m1, m1 > Full, Full > m1, m1 < Full
  172. (False, False, True, True)
  173. """
  174. cdef bint eq, incl
  175. eq = (self._m.conductor == other._m.conductor and
  176. self._m.min == other._m.min and
  177. self.genus == other.genus and
  178. all(self._m.decs[i] == other._m.decs[i] for i in range(cSIZE)))
  179. if op == 2: return eq
  180. elif op == 3: return not eq
  181. elif op < 2:
  182. incl = all(i in other for i in self.generators())
  183. if op == 0: return incl and not eq
  184. elif op == 1: return incl
  185. else:
  186. incl = all(i in self for i in other.generators())
  187. if op == 4: return incl and not eq
  188. elif op == 5: return incl
  189. def __hash__(self):
  190. r"""
  191. sage: import os; os.sys.path.insert(0,os.path.abspath('.')); from numeric_monoid import *
  192. sage: Full.__hash__()
  193. 7122582034698508706
  194. sage: hash(NumericMonoid.from_generators([3,5,7]))
  195. 7609276871119479011
  196. sage: len(set(Full.nth_generation(4)))
  197. 7
  198. """
  199. return hash((self.conductor(), self.min(), self.genus(),
  200. tuple(self._decomposition_numbers())))
  201. cpdef NumericMonoid remove_generator(self, unsigned int gen):
  202. r"""
  203. sage: import os; os.sys.path.insert(0,os.path.abspath('.')); from numeric_monoid import *
  204. sage: Full.remove_generator(1)
  205. < 2 3 >
  206. sage: NumericMonoid.from_generators([3,5,7]).remove_generator(7)
  207. < 3 5 >
  208. sage: NumericMonoid.from_generators([3,5,7]).remove_generator(8)
  209. Traceback (most recent call last):
  210. ...
  211. ValueError: 8 is not a generator for < 3 5 7 >
  212. """
  213. cdef NumericMonoid res
  214. res = NumericMonoid.__new__(NumericMonoid)
  215. if gen > cSIZE or self._m.decs[gen] != 1:
  216. raise ValueError, "%i is not a generator for %s"%(gen, self)
  217. remove_generator(res._m, self._m, gen)
  218. return res
  219. cpdef list generators(self):
  220. r"""
  221. sage: import os; os.sys.path.insert(0,os.path.abspath('.')); from numeric_monoid import *
  222. sage: Full.generators()
  223. [1]
  224. sage: NumericMonoid.from_generators([3,5,7]).generators()
  225. [3, 5, 7]
  226. """
  227. cdef list res = []
  228. cdef int gen
  229. cdef generator_iter[ALL] *iter = new generator_iter[ALL](self._m)
  230. while iter.move_next():
  231. res.append(int(iter.get_gen()))
  232. del iter
  233. return res
  234. cpdef int count_children(self):
  235. r"""
  236. sage: import os; os.sys.path.insert(0,os.path.abspath('.')); from numeric_monoid import *
  237. sage: Full.count_children()
  238. 1
  239. sage: NumericMonoid.from_generators([3,5,7]).count_children()
  240. 2
  241. """
  242. cdef int res
  243. cdef generator_iter[CHILDREN] *iter = new generator_iter[CHILDREN](self._m)
  244. res = iter.count()
  245. del iter
  246. return res
  247. cpdef list children(self):
  248. r"""
  249. sage: import os; os.sys.path.insert(0,os.path.abspath('.')); from numeric_monoid import *
  250. sage: Full.children()
  251. [< 2 3 >]
  252. sage: NumericMonoid.from_generators([3,5,7]).children()
  253. [< 3 7 8 >, < 3 5 >]
  254. """
  255. cdef list res = []
  256. cdef generator_iter[CHILDREN] *iter = new generator_iter[CHILDREN](self._m)
  257. while iter.move_next():
  258. res.append(self.remove_generator(iter.get_gen()))
  259. del iter
  260. return res
  261. cpdef list children_generators(self):
  262. r"""
  263. sage: import os; os.sys.path.insert(0,os.path.abspath('.')); from numeric_monoid import *
  264. sage: Full.children_generators()
  265. [1]
  266. sage: NumericMonoid.from_generators([3,5,7]).children_generators()
  267. [5, 7]
  268. """
  269. cdef list res = []
  270. cdef int gen
  271. cdef generator_iter[CHILDREN] *iter = new generator_iter[CHILDREN](self._m)
  272. while iter.move_next():
  273. res.append(int(iter.get_gen()))
  274. del iter
  275. return res
  276. cpdef list successors(self):
  277. r"""
  278. sage: import os; os.sys.path.insert(0,os.path.abspath('.')); from numeric_monoid import *
  279. sage: Full.successors()
  280. [< 2 3 >]
  281. sage: NumericMonoid.from_generators([3,5,7]).successors()
  282. [< 5 6 7 8 9 >, < 3 7 8 >, < 3 5 >]
  283. """
  284. cdef list res = []
  285. cdef generator_iter[ALL] *iter = new generator_iter[ALL](self._m)
  286. while iter.move_next():
  287. # Straigten a monoid obtained by removing an non children generators
  288. try:
  289. newmon = self.from_generators(self.remove_generator(iter.get_gen()).generators())
  290. except ValueError:
  291. pass # Ignore the result if GCD is not 1 anymore.
  292. else:
  293. res.append(newmon)
  294. del iter
  295. return res
  296. cpdef list successor_generators(self):
  297. r"""
  298. sage: import os; os.sys.path.insert(0,os.path.abspath('.')); from numeric_monoid import *
  299. sage: Full.successor_generators()
  300. [1]
  301. sage: NumericMonoid.from_generators([3,5,7]).successor_generators()
  302. [3, 5, 7]
  303. """
  304. cdef list res = []
  305. cdef int gen
  306. cdef generator_iter[ALL] *iter = new generator_iter[ALL](self._m)
  307. while iter.move_next():
  308. res.append(int(iter.get_gen()))
  309. del iter
  310. return res
  311. cpdef list nth_generation(self, unsigned int genus):
  312. r"""
  313. sage: import os; os.sys.path.insert(0,os.path.abspath('.')); from numeric_monoid import *
  314. sage: Full.nth_generation(3)
  315. [< 4 5 6 7 >, < 3 5 7 >, < 3 4 >, < 2 7 >]
  316. sage: NumericMonoid.from_generators([3,5,7]).nth_generation(8)
  317. [< 3 13 14 >, < 3 11 16 >, < 3 10 17 >]
  318. """
  319. cdef ind_t i
  320. cdef list lst = [self]
  321. for i in range(self._m.genus, genus):
  322. lst = [x for m in lst for x in m.children()]
  323. return lst
  324. cpdef MonoidList nth_generation_cilk(self, unsigned int genus):
  325. r"""
  326. sage: import os; os.sys.path.insert(0,os.path.abspath('.')); from numeric_monoid import *
  327. sage: list(Full.nth_generation_cilk(0))
  328. [< 1 >]
  329. sage: list(Full.nth_generation_cilk(1))
  330. [< 2 3 >]
  331. sage: list(Full.nth_generation_cilk(2))
  332. [< 3 4 5 >, < 2 5 >]
  333. sage: list(Full.nth_generation_cilk(4))
  334. [< 5 6 7 8 9 >, < 4 6 7 9 >, < 4 5 7 >, < 4 5 6 >, < 3 7 8 >, < 3 5 >, < 2 9 >]
  335. """
  336. cdef MonoidList res = MonoidList.__new__(MonoidList)
  337. cilk_list_results.get_reference().clear()
  338. sig_on()
  339. with nogil:
  340. list_children(self._m, genus)
  341. sig_off()
  342. res._l = cilk_list_results.get_value()
  343. cilk_list_results.get_reference().clear()
  344. return res
  345. # don't know how to make it readonly !
  346. cpdef unsigned char[:] _decomposition_numbers(self):
  347. r"""
  348. sage: import os; os.sys.path.insert(0,os.path.abspath('.')); from numeric_monoid import *
  349. sage: Full._decomposition_numbers()
  350. <MemoryView of 'array' at 0x...>
  351. sage: len(list(Full._decomposition_numbers())) == 256
  352. True
  353. sage: len(list(NumericMonoid.from_generators([3,5,7])._decomposition_numbers())) == 256
  354. True
  355. """
  356. cdef unsigned char[:] slice = (<unsigned char[:cSIZE]>
  357. <unsigned char *> self._m.decs)
  358. return slice
  359. cpdef list multiplicities(self):
  360. r"""
  361. sage: import os; os.sys.path.insert(0,os.path.abspath('.')); from numeric_monoid import *
  362. sage: Full.multiplicities() == range(1, 257)
  363. True
  364. sage: NumericMonoid.from_generators([3,5,7]).multiplicities()
  365. [1, 0, 0, 2, 0, 2, 3, 2, 4, 4, 5, 6, 7, 8, 9, 10, 11, ..., 249, 250]
  366. """
  367. cdef unsigned char[:] decs = self._decomposition_numbers()
  368. cdef int i
  369. cdef int mults[cSIZE]
  370. cdef int[:] mults_view = mults
  371. mults[0] = 1
  372. for i in range(1, cSIZE):
  373. mults[i] = decs[i] << 1
  374. if i % 2 == 0 and mults[i/2] != 0:
  375. mults[i] -= 1
  376. return list(mults_view)
  377. @classmethod
  378. def from_generators(cls, list l):
  379. r"""
  380. sage: import os; os.sys.path.insert(0,os.path.abspath('.')); from numeric_monoid import *
  381. sage: NumericMonoid.from_generators([1])
  382. < 1 >
  383. sage: NumericMonoid.from_generators([3,5,7])
  384. < 3 5 7 >
  385. sage: NumericMonoid.from_generators([3,5,8])
  386. < 3 5 >
  387. sage: NumericMonoid.from_generators([3,6])
  388. Traceback (most recent call last):
  389. ...
  390. ValueError: gcd of generators must be 1
  391. """
  392. cdef int i
  393. cdef set gens = {int(i) for i in l}
  394. cdef NumericMonoid res = cls()
  395. cdef generator_iter[CHILDREN] *iter = new generator_iter[CHILDREN](res._m)
  396. if GCD_list(l) != 1:
  397. raise ValueError, "gcd of generators must be 1"
  398. while iter.move_next():
  399. gen = iter.get_gen()
  400. if gen not in gens:
  401. res = res.remove_generator(gen)
  402. del iter
  403. iter = new generator_iter[CHILDREN](res._m)
  404. del iter
  405. return res
  406. def gcd_small_generator(self):
  407. r"""
  408. sage: import os; os.sys.path.insert(0,os.path.abspath('.')); from numeric_monoid import *
  409. sage: Full.gcd_small_generator()
  410. 0
  411. sage: NumericMonoid.from_generators([3,5,7]).gcd_small_generator()
  412. 3
  413. """
  414. if self._m.min == 1: # self == Full
  415. return Integer(0)
  416. return GCD_list([i for i in self.generators() if i < self.conductor()])
  417. def has_finite_descendance(self):
  418. r"""
  419. sage: import os; os.sys.path.insert(0,os.path.abspath('.')); from numeric_monoid import *
  420. sage: Full.has_finite_descendance()
  421. False
  422. sage: NumericMonoid.from_generators([3,5,7]).has_finite_descendance()
  423. False
  424. sage: NumericMonoid.from_generators([3,7]).has_finite_descendance()
  425. True
  426. """
  427. return self.gcd_small_generator() == 1
  428. def support_generating_series(self):
  429. r"""
  430. sage: import os; os.sys.path.insert(0,os.path.abspath('.')); from numeric_monoid import *
  431. sage: Full.support_generating_series()
  432. -1/(x - 1)
  433. sage: NumericMonoid.from_generators([3,5,7]).support_generating_series()
  434. -(x^5 - x^4 + x^3 - x + 1)/(x - 1)
  435. sage: NumericMonoid.from_generators([3,7]).support_generating_series()
  436. -(x^12 - x^11 + x^9 - x^8 + x^6 - x^4 + x^3 - x + 1)/(x - 1)
  437. """
  438. from sage.calculus.var import var
  439. x = var('x')
  440. cdef int c = self.conductor()
  441. return (sum(x**i for i in range(c) if i in self) +
  442. x**c/(1-x)).normalize()
  443. def multiplicities_generating_series(self):
  444. r"""
  445. sage: import os; os.sys.path.insert(0,os.path.abspath('.')); from numeric_monoid import *
  446. sage: Full.multiplicities_generating_series()
  447. (x - 1)^(-2)
  448. sage: NumericMonoid.from_generators([3,5,7]).multiplicities_generating_series()
  449. (x^5 - x^4 + x^3 - x + 1)^2/(x - 1)^2
  450. sage: NumericMonoid.from_generators([3,7]).multiplicities_generating_series()
  451. (x^12 - x^11 + x^9 - x^8 + x^6 - x^4 + x^3 - x + 1)^2/(x - 1)^2
  452. sage: bound = 20
  453. sage: all( [(m.support_generating_series()^2).taylor(x, 0, bound-1).coefficient(x, i)
  454. ... for i in range(bound)] ==
  455. ... list(m.multiplicities())[:bound]
  456. ... for k in range(7) for m in Full.nth_generation(k))
  457. True
  458. """
  459. return (self.support_generating_series()**2).normalize()
  460. def generating_series(self):
  461. r"""
  462. sage: import os; os.sys.path.insert(0,os.path.abspath('.')); from numeric_monoid import *
  463. sage: Full.generating_series()
  464. (x - 1)/(x*y + x - 1)
  465. sage: NumericMonoid.from_generators([3,5,7]).generating_series()
  466. (x - 1)/(x^5*y - x^4*y + x^3*y + x - 1)
  467. sage: NumericMonoid.from_generators([3,7]).generating_series()
  468. (x - 1)/(x^12*y - x^11*y + x^9*y - x^8*y + x^6*y - x^4*y + x^3*y + x - 1)
  469. """
  470. from sage.calculus.var import var
  471. return 1/(1-var('y')*(self.support_generating_series()-1)).normalize()
  472. def _test_monoid(self, **options):
  473. r"""
  474. sage: import os; os.sys.path.insert(0,os.path.abspath('.')); from numeric_monoid import *
  475. sage: m = NumericMonoid.from_generators([3,5,7])
  476. sage: m._test_monoid()
  477. sage: m._decomposition_numbers()[2] = 1 # don't do this at home, kids
  478. sage: m._test_monoid()
  479. Traceback (most recent call last):
  480. ...
  481. AssertionError: wrong min
  482. sage: m = NumericMonoid.from_generators([3,5,7])
  483. sage: m._decomposition_numbers()[20] = 0 # don't do this at home, kids
  484. sage: m._test_monoid()
  485. Traceback (most recent call last):
  486. ...
  487. AssertionError: wrong genus
  488. """
  489. cdef ind_t i, genus = 0, size = cSIZE
  490. tester = self._tester(**options)
  491. if self._m.conductor == 1:
  492. tester.assertEqual(self._m.min, 1, "wrong min")
  493. tester.assertTrue(all(self._m.decs[i] == 0 for i in range(1, self._m.min)),
  494. "wrong min")
  495. for i in range(size):
  496. if self._m.decs[i] == 0:
  497. genus += 1
  498. tester.assertEqual(self._m.genus, genus, "wrong genus")
  499. tester.assertEqual(self._m.decs[0], 1, "wrong decs[0]")
  500. if self._m.conductor != 1:
  501. tester.assertEqual(self._m.decs[self._m.conductor-1], 0,
  502. "conductor in not minimal")
  503. tester.assertTrue(all(self._m.decs[i] != 0
  504. for i in range(self._m.conductor, <unsigned int>cSIZE)),
  505. "wrong conductor")
  506. def _test_generators(self, **options):
  507. r"""
  508. sage: import os; os.sys.path.insert(0,os.path.abspath('.')); from numeric_monoid import *
  509. sage: Full._test_generators()
  510. sage: m = NumericMonoid.from_generators([3,5,7])
  511. sage: m._test_generators()
  512. sage: m._decomposition_numbers()[2] = 2 # don't do this at home, kids
  513. sage: m._test_generators()
  514. Traceback (most recent call last):
  515. ...
  516. AssertionError: wrong generators
  517. """
  518. tester = self._tester(**options)
  519. tester.assertEqual(self, NumericMonoid.from_generators(self.generators()),
  520. "wrong generators")
  521. cpdef list walk_children_stack(NumericMonoid self, int bound):
  522. r"""
  523. sage: import os; os.sys.path.insert(0,os.path.abspath('.')); from numeric_monoid import *
  524. sage: Full.walk_children_stack(5)
  525. [1, 2, 4, 7, 12]
  526. """
  527. cdef results_type res
  528. cdef int i
  529. for i in range(bound):
  530. res[i] = 0
  531. sig_on()
  532. with nogil:
  533. walk_children_stack(self._m, bound, res)
  534. sig_off()
  535. return [int(res[i]) for i in range(bound)]
  536. cpdef list walk_children(NumericMonoid self, int bound):
  537. r"""
  538. sage: import os; os.sys.path.insert(0,os.path.abspath('.')); from numeric_monoid import *
  539. sage: Full.walk_children(15)
  540. [1, 2, 4, 7, 12, 23, 39, 67, 118, 204, 343, 592, 1001, 1693, 2857]
  541. """
  542. cilk_results.reset()
  543. sig_on()
  544. with nogil:
  545. walk_children(self._m, bound)
  546. sig_off()
  547. return [int(cilk_results[i]) for i in range(bound)]
  548. cpdef NumericMonoid _from_pickle(type typ, int sz, int cond, int mn, int genus, tuple decs):
  549. r"""
  550. sage: import os; os.sys.path.insert(0,os.path.abspath('.')); from numeric_monoid import *
  551. sage: TestSuite(Full).run(verbose=True) # indirect doctest
  552. running ._test_category() . . . pass
  553. running ._test_generators() . . . pass
  554. running ._test_monoid() . . . pass
  555. running ._test_new() . . . pass
  556. running ._test_not_implemented_methods() . . . pass
  557. running ._test_pickling() . . . pass
  558. sage: TestSuite(Full.remove_generator(1)).run() # indirect doctest
  559. sage: TestSuite(NumericMonoid.from_generators([3,5,7])).run() # indirect doctest
  560. """
  561. cdef NumericMonoid res
  562. cdef int i
  563. if sz != cSIZE:
  564. raise ValueError, "mon is compiled with different size (pickle size=%i)"%sz
  565. res = NumericMonoid.__new__(typ)
  566. res._m.conductor = cond
  567. res._m.min = mn
  568. res._m.genus = genus
  569. for i in range(cSIZE):
  570. res._m.decs[i] = decs[i]
  571. return res
  572. Full = NumericMonoid()
  573. cdef class MonoidList(object):
  574. r"""
  575. A wrapper for C++ STL lists of monoids.
  576. """
  577. def __init__(self):
  578. r"""
  579. sage: import os; os.sys.path.insert(0,os.path.abspath('.')); from numeric_monoid import *
  580. sage: MonoidList()
  581. Traceback (most recent call last):
  582. ...
  583. RuntimeError: You are not supposed to call init
  584. """
  585. raise RuntimeError, "You are not supposed to call init"
  586. def __len__(self):
  587. r"""
  588. sage: import os; os.sys.path.insert(0,os.path.abspath('.')); from numeric_monoid import *
  589. sage: len(Full.nth_generation_cilk(4))
  590. 7
  591. """
  592. return self._l.size()
  593. def __iter__(self):
  594. r"""
  595. sage: import os; os.sys.path.insert(0,os.path.abspath('.')); from numeric_monoid import *
  596. sage: iter(Full.nth_generation_cilk(4))
  597. <numeric_monoid.MonoidListIterator object at 0x...>
  598. """
  599. return MonoidListIterator(self)
  600. cdef class MonoidListIterator(object):
  601. r"""
  602. A wrapper for C++ STL iterator for list of monoids.
  603. """
  604. def __cinit__(self, MonoidList l):
  605. r"""
  606. sage: import os; os.sys.path.insert(0,os.path.abspath('.')); from numeric_monoid import *
  607. sage: MonoidListIterator(Full.nth_generation_cilk(0))
  608. <numeric_monoid.MonoidListIterator object at 0x...>
  609. """
  610. self._ml = l # keep a reference on _ml to prevent _ml._l from being deallocated
  611. self._it = self._ml._l.begin()
  612. self._end = self._ml._l.end()
  613. def __next__(self):
  614. r"""
  615. sage: import os; os.sys.path.insert(0,os.path.abspath('.')); from numeric_monoid import *
  616. sage: it = iter(Full.nth_generation_cilk(2))
  617. sage: it.__next__()
  618. < 3 4 5 >
  619. sage: it.__next__()
  620. < 2 5 >
  621. sage: it.__next__()
  622. Traceback (most recent call last):
  623. ...
  624. StopIteration
  625. sage: it = iter(Full.nth_generation_cilk(10))
  626. sage: it.__next__()
  627. < 11 12 13 14 15 16 17 18 19 20 21 >
  628. sage: it.__next__()
  629. < 10 12 13 14 15 16 17 18 19 21 >
  630. """
  631. cdef NumericMonoid res = NumericMonoid.__new__(NumericMonoid)
  632. if self._it != self._end:
  633. res._m = cython.operator.dereference(self._it)
  634. cython.operator.preincrement(self._it)
  635. return res
  636. else:
  637. raise StopIteration
  638. def __iter__(self):
  639. r"""
  640. sage: import os; os.sys.path.insert(0,os.path.abspath('.')); from numeric_monoid import *
  641. sage: it = iter(Full.nth_generation_cilk(0))
  642. sage: iter(it) is it
  643. True
  644. """
  645. return self