# Ticket #715: cachefunc_94107.py

File cachefunc_94107.py, 97.0 KB (added by , 7 years ago) |
---|

Line | |
---|---|

1 | # -*- coding: utf-8 -*- |

2 | |

3 | # This file was generated by 'sage-doctest' from |

4 | # '/scratch/sking/sage-5.4.beta0/devel/sage-main/sage/misc/cachefunc.pyx'. |

5 | |

6 | from sage.all_cmdline import *; |

7 | import sage.plot.plot; sage.plot.plot.DOCTEST_MODE=True |

8 | |

9 | def warning_function(f): |

10 | import warnings |

11 | |

12 | def doctest_showwarning(message, category, filename, lineno, file=f, line=None): |

13 | try: |

14 | file.write(warnings.formatwarning(message, category, 'doctest', lineno, line)) |

15 | except IOError: |

16 | pass # the file (probably stdout) is invalid |

17 | return doctest_showwarning |

18 | |

19 | def change_warning_output(file): |

20 | import warnings |

21 | warnings.showwarning = warning_function(file) |

22 | |

23 | import re |

24 | float_pattern = re.compile('[+-]?((\d*\.?\d+)|(\d+\.?))([eE][+-]?\d+)?') |

25 | |

26 | def check_with_tolerance(expected, actual, epsilon, rel_or_abs=None): |

27 | if actual is Exception: |

28 | return # error computing actual |

29 | else: |

30 | actual = str(actual) |

31 | expected = re.sub('\n +', '\n', expected) |

32 | actual = re.sub('\n +', '\n', actual) |

33 | assert float_pattern.sub('#', expected.strip()) == float_pattern.sub('#', actual.strip()), \ |

34 | "Expected '" + expected + "' got '" + actual + "'" |

35 | for expected_value, actual_value in zip(float_pattern.finditer(expected), float_pattern.finditer(actual)): |

36 | expected_value = float(expected_value.group()) |

37 | actual_value = float(actual_value.group()) |

38 | if rel_or_abs == 'abs' or expected_value == 0: |

39 | assert abs(expected_value - actual_value) < epsilon, "Out of tolerance %s vs %s" % (expected_value, actual_value) |

40 | else: |

41 | assert abs((expected_value - actual_value) / expected_value) < epsilon, "Out of tolerance %s vs %s" % (expected_value, actual_value) |

42 | def example_0(): r""">>> set_random_seed(0L) |

43 | |

44 | >>> change_warning_output(sys.stdout) |

45 | |

46 | |

47 | Cached Functions and Methods |

48 | |

49 | AUTHORS: |

50 | |

51 | - William Stein (inspired by conversation with Justin Walker). |

52 | - Mike Hansen (added doctests and made it work with class methods). |

53 | - Willem Jan Palenstijn (add CachedMethodCaller for binding cached |

54 | methods to instances). |

55 | - Tom Boothby (added DiskCachedFunction). |

56 | - Simon King (improved performance, more doctests, cython version, |

57 | added CachedMethodCallerNoArgs). |

58 | |

59 | EXAMPLES: |

60 | |

61 | By trac ticket #11115, cached functions and methods are now also |

62 | available in Cython code. The following examples cover various ways |

63 | of usage. |

64 | |

65 | Python functions:: |

66 | |

67 | >>> @cached_function###line 22:_sage_ >>> @cached_function |

68 | ... def test_pfunc(x): |

69 | ... ''' |

70 | ... Some documentation |

71 | ... ''' |

72 | ... return -x |

73 | ... |

74 | >>> test_pfunc(Integer(5)) is test_pfunc(Integer(5))###line 29:_sage_ >>> test_pfunc(5) is test_pfunc(5) |

75 | True |

76 | |

77 | Unfortunately, cython functions do not allow arbitrary |

78 | decorators. However, one can wrap a Cython function and |

79 | turn it into a cached function, by trac ticket #11115. |

80 | We need to provide the name that the wrapped method or |

81 | function should have, since otherwise the name of the |

82 | original function would be used:: |

83 | |

84 | >>> cython('''cpdef test_funct(x): return -x''')###line 39:_sage_ >>> cython('''cpdef test_funct(x): return -x''') |

85 | >>> wrapped_funct = cached_function(test_funct, name='wrapped_funct')###line 40:_sage_ >>> wrapped_funct = cached_function(test_funct, name='wrapped_funct') |

86 | >>> wrapped_funct###line 41:_sage_ >>> wrapped_funct |

87 | Cached version of <built-in function test_funct> |

88 | >>> wrapped_funct.__name__###line 43:_sage_ >>> wrapped_funct.__name__ |

89 | 'wrapped_funct' |

90 | >>> wrapped_funct(Integer(5))###line 45:_sage_ >>> wrapped_funct(5) |

91 | -5 |

92 | >>> wrapped_funct(Integer(5)) is wrapped_funct(Integer(5))###line 47:_sage_ >>> wrapped_funct(5) is wrapped_funct(5) |

93 | True |

94 | |

95 | We can proceed similarly for cached methods of Cython classes, |

96 | provided that they allow attribute assignment or have a public |

97 | attribute ``__cached_methods`` of type ``<dict>``. Since trac ticket |

98 | #11115, this is the case for all classes inheriting from |

99 | :class:`~sage.structure.parent.Parent`:: |

100 | |

101 | >>> cython_code = ['cpdef test_meth(self,x):',###line 56:_sage_ >>> cython_code = ['cpdef test_meth(self,x):', |

102 | ... ' "some doc for a wrapped cython method"', |

103 | ... ' return -x', |

104 | ... 'from sage.all import cached_method', |

105 | ... 'from sage.structure.parent cimport Parent', |

106 | ... 'cdef class MyClass(Parent):', |

107 | ... ' wrapped_method = cached_method(test_meth,name="wrapped_method")'] |

108 | >>> cython('\n'.join(cython_code))###line 63:_sage_ >>> cython('\n'.join(cython_code)) |

109 | >>> O = MyClass()###line 64:_sage_ >>> O = MyClass() |

110 | >>> O.wrapped_method###line 65:_sage_ >>> O.wrapped_method |

111 | Cached version of <built-in function test_meth> |

112 | >>> O.wrapped_method.__name__###line 67:_sage_ >>> O.wrapped_method.__name__ |

113 | 'wrapped_method' |

114 | >>> O.wrapped_method(Integer(5))###line 69:_sage_ >>> O.wrapped_method(5) |

115 | -5 |

116 | >>> O.wrapped_method(Integer(5)) is O.wrapped_method(Integer(5))###line 71:_sage_ >>> O.wrapped_method(5) is O.wrapped_method(5) |

117 | True |

118 | |

119 | By trac ticket #11115, even if a parent does not allow attribute |

120 | assignment, it can inherit a cached method from the parent class of a |

121 | category (previously, the cache would have been broken):: |

122 | |

123 | >>> cython_code = ["from sage.all import cached_method, cached_in_parent_method, Category, Objects",###line 78:_sage_ >>> cython_code = ["from sage.all import cached_method, cached_in_parent_method, Category, Objects", |

124 | ... "class MyCategory(Category):", |

125 | ... " @cached_method", |

126 | ... " def super_categories(self):", |

127 | ... " return [Objects()]", |

128 | ... " class ElementMethods:", |

129 | ... " @cached_method", |

130 | ... " def element_cache_test(self):", |

131 | ... " return -self", |

132 | ... " @cached_in_parent_method", |

133 | ... " def element_via_parent_test(self):", |

134 | ... " return -self", |

135 | ... " class ParentMethods:", |

136 | ... " @cached_method", |

137 | ... " def one(self):", |

138 | ... " return self.element_class(self,1)", |

139 | ... " @cached_method", |

140 | ... " def invert(self, x):", |

141 | ... " return -x"] |

142 | >>> cython('\n'.join(cython_code))###line 97:_sage_ >>> cython('\n'.join(cython_code)) |

143 | >>> C = MyCategory()###line 98:_sage_ >>> C = MyCategory() |

144 | |

145 | In order to keep the memory footprint of elements small, it was |

146 | decided to not support the same freedom of using cached methods |

147 | for elements: If an instance of a class derived from |

148 | :class:`~sage.structure.element.Element` does not allow attribute |

149 | assignment, then a cached method inherited from the category of |

150 | its parent will break, as in the class ``MyBrokenElement`` below. |

151 | |

152 | However, there is a class :class:`~sage.structure.element.ElementWithCachedMethod` |

153 | that has generally a slower attribute access, but fully supports |

154 | cached methods. We remark, however, that cached methods are |

155 | *much* faster if attribute access works. So, we expect that |

156 | :class:`~sage.structure.element.ElementWithCachedMethod` will |

157 | hardly by used. |

158 | :: |

159 | |

160 | >>> cython_code = ["from sage.structure.element cimport Element, ElementWithCachedMethod",###line 115:_sage_ >>> cython_code = ["from sage.structure.element cimport Element, ElementWithCachedMethod", |

161 | ... "cdef class MyBrokenElement(Element):", |

162 | ... " cdef public object x", |

163 | ... " def __init__(self,P,x):", |

164 | ... " self.x=x", |

165 | ... " Element.__init__(self,P)", |

166 | ... " def __neg__(self):", |

167 | ... " return MyBrokenElement(self.parent(),-self.x)", |

168 | ... " def _repr_(self):", |

169 | ... " return '<%s>'%self.x", |

170 | ... " def __hash__(self):", |

171 | ... " return hash(self.x)", |

172 | ... " def __cmp__(left, right):", |

173 | ... " return (<Element>left)._cmp(right)", |

174 | ... " def __richcmp__(left, right, op):", |

175 | ... " return (<Element>left)._richcmp(right,op)", |

176 | ... " cdef int _cmp_c_impl(left, Element right) except -2:", |

177 | ... " return cmp(left.x,right.x)", |

178 | ... " def raw_test(self):", |

179 | ... " return -self", |

180 | ... "cdef class MyElement(ElementWithCachedMethod):", |

181 | ... " cdef public object x", |

182 | ... " def __init__(self,P,x):", |

183 | ... " self.x=x", |

184 | ... " ElementWithCachedMethod.__init__(self,P)", |

185 | ... " def __neg__(self):", |

186 | ... " return MyElement(self.parent(),-self.x)", |

187 | ... " def _repr_(self):", |

188 | ... " return '<%s>'%self.x", |

189 | ... " def __hash__(self):", |

190 | ... " return hash(self.x)", |

191 | ... " def __cmp__(left, right):", |

192 | ... " return (<Element>left)._cmp(right)", |

193 | ... " def __richcmp__(left, right, op):", |

194 | ... " return (<Element>left)._richcmp(right,op)", |

195 | ... " cdef int _cmp_c_impl(left, Element right) except -2:", |

196 | ... " return cmp(left.x,right.x)", |

197 | ... " def raw_test(self):", |

198 | ... " return -self", |

199 | ... "from sage.structure.parent cimport Parent", |

200 | ... "cdef class MyParent(Parent):", |

201 | ... " Element = MyElement"] |

202 | >>> cython('\n'.join(cython_code))###line 157:_sage_ >>> cython('\n'.join(cython_code)) |

203 | >>> P = MyParent(category=C)###line 158:_sage_ >>> P = MyParent(category=C) |

204 | >>> ebroken = MyBrokenElement(P,Integer(5))###line 159:_sage_ >>> ebroken = MyBrokenElement(P,5) |

205 | >>> e = MyElement(P,Integer(5))###line 160:_sage_ >>> e = MyElement(P,5) |

206 | |

207 | The cached methods inherited by the parent works:: |

208 | |

209 | >>> P.one()###line 164:_sage_ >>> P.one() |

210 | <1> |

211 | >>> P.one() is P.one()###line 166:_sage_ >>> P.one() is P.one() |

212 | True |

213 | >>> P.invert(e)###line 168:_sage_ >>> P.invert(e) |

214 | <-5> |

215 | >>> P.invert(e) is P.invert(e)###line 170:_sage_ >>> P.invert(e) is P.invert(e) |

216 | True |

217 | |

218 | The cached methods inherited by ``MyElement`` works:: |

219 | |

220 | >>> e.element_cache_test()###line 175:_sage_ >>> e.element_cache_test() |

221 | <-5> |

222 | >>> e.element_cache_test() is e.element_cache_test()###line 177:_sage_ >>> e.element_cache_test() is e.element_cache_test() |

223 | True |

224 | >>> e.element_via_parent_test()###line 179:_sage_ >>> e.element_via_parent_test() |

225 | <-5> |

226 | >>> e.element_via_parent_test() is e.element_via_parent_test()###line 181:_sage_ >>> e.element_via_parent_test() is e.element_via_parent_test() |

227 | True |

228 | |

229 | The other element class can only inherit a ``cached_in_parent_method``, since |

230 | the cache is stored in the parent. In fact, equal elements share the cache, |

231 | even if they are of different types:: |

232 | |

233 | >>> e == ebroken###line 188:_sage_ >>> e == ebroken |

234 | True |

235 | >>> type(e) == type(ebroken)###line 190:_sage_ >>> type(e) == type(ebroken) |

236 | False |

237 | >>> ebroken.element_via_parent_test() is e.element_via_parent_test()###line 192:_sage_ >>> ebroken.element_via_parent_test() is e.element_via_parent_test() |

238 | True |

239 | |

240 | However, the cache of the other inherited method breaks, although the method |

241 | as such works:: |

242 | |

243 | >>> ebroken.element_cache_test()###line 198:_sage_ >>> ebroken.element_cache_test() |

244 | <-5> |

245 | >>> ebroken.element_cache_test() is ebroken.element_cache_test()###line 200:_sage_ >>> ebroken.element_cache_test() is ebroken.element_cache_test() |

246 | False |

247 | |

248 | The cache can be emptied:: |

249 | |

250 | >>> a = test_pfunc(Integer(5))###line 205:_sage_ >>> a = test_pfunc(5) |

251 | >>> test_pfunc.clear_cache()###line 206:_sage_ >>> test_pfunc.clear_cache() |

252 | >>> a is test_pfunc(Integer(5))###line 207:_sage_ >>> a is test_pfunc(5) |

253 | False |

254 | >>> a = P.one()###line 209:_sage_ >>> a = P.one() |

255 | >>> P.one.clear_cache()###line 210:_sage_ >>> P.one.clear_cache() |

256 | >>> a is P.one()###line 211:_sage_ >>> a is P.one() |

257 | False |

258 | |

259 | Since ``e`` and ``ebroken`` share the cache, when we empty it for one element |

260 | it is empty for the other as well:: |

261 | |

262 | >>> b = ebroken.element_via_parent_test()###line 217:_sage_ >>> b = ebroken.element_via_parent_test() |

263 | >>> e.element_via_parent_test.clear_cache()###line 218:_sage_ >>> e.element_via_parent_test.clear_cache() |

264 | >>> b is ebroken.element_via_parent_test()###line 219:_sage_ >>> b is ebroken.element_via_parent_test() |

265 | False |

266 | |

267 | Introspection works:: |

268 | |

269 | >>> from sage.misc.edit_module import file_and_line###line 224:_sage_ >>> from sage.misc.edit_module import file_and_line |

270 | >>> from sage.misc.sageinspect import sage_getdoc, sage_getfile, sage_getsource###line 225:_sage_ >>> from sage.misc.sageinspect import sage_getdoc, sage_getfile, sage_getsource |

271 | >>> print sage_getdoc(test_pfunc)###line 226:_sage_ >>> print sage_getdoc(test_pfunc) |

272 | Some documentation |

273 | >>> print sage_getdoc(O.wrapped_method)###line 228:_sage_ >>> print sage_getdoc(O.wrapped_method) |

274 | some doc for a wrapped cython method |

275 | <BLANKLINE> |

276 | >>> print sage_getsource(O.wrapped_method)###line 231:_sage_ >>> print sage_getsource(O.wrapped_method) |

277 | cpdef test_meth(self,x): |

278 | "some doc for a wrapped cython method" |

279 | return -x |

280 | |

281 | It is a very common special case to cache a method that has no |

282 | arguments. In that special case, the time needed to access the cache |

283 | can be drastically reduced by using a special implementation. The |

284 | cached method decorator automatically determines which implementation |

285 | ought to be chosen. A typical example is |

286 | :meth:`sage.rings.polynomial.multi_polynomial_ideal.MPolynomialIdeal.gens` |

287 | (no arguments) versus |

288 | :meth:`sage.rings.polynomial.multi_polynomial_ideal.MPolynomialIdeal.groebner_basis` |

289 | (several arguments):: |

290 | |

291 | >>> P = QQ['a, b, c, d']; (a, b, c, d,) = P._first_ngens(4)###line 246:_sage_ >>> P.<a,b,c,d> = QQ[] |

292 | >>> I = P*[a,b]###line 247:_sage_ >>> I = P*[a,b] |

293 | >>> I.gens()###line 248:_sage_ >>> I.gens() |

294 | [a, b] |

295 | >>> I.gens() is I.gens()###line 250:_sage_ >>> I.gens() is I.gens() |

296 | True |

297 | >>> I.groebner_basis()###line 252:_sage_ >>> I.groebner_basis() |

298 | [a, b] |

299 | >>> I.groebner_basis() is I.groebner_basis()###line 254:_sage_ >>> I.groebner_basis() is I.groebner_basis() |

300 | True |

301 | >>> type(I.gens)###line 256:_sage_ >>> type(I.gens) |

302 | <type 'sage.misc.cachefunc.CachedMethodCallerNoArgs'> |

303 | >>> type(I.groebner_basis)###line 258:_sage_ >>> type(I.groebner_basis) |

304 | <type 'sage.misc.cachefunc.CachedMethodCaller'> |

305 | |

306 | |

307 | >>> sig_on_count() |

308 | 0 |

309 | """ |

310 | |

311 | def example_1(): r""">>> set_random_seed(0L) |

312 | |

313 | >>> change_warning_output(sys.stdout) |

314 | |

315 | |

316 | Unpickling of cached functions. |

317 | |

318 | NOTE: |

319 | |

320 | Pickling and unpickling of cached functions is by importing |

321 | from the module in which the function is defined. |

322 | |

323 | INPUT: |

324 | |

325 | - ``module``: A string, describing the module to import the |

326 | function from. |

327 | - ``name``: A string, name of the to-be-imported cached function. |

328 | |

329 | EXAMPLE:: |

330 | |

331 | >>> type(cunningham_prime_factors)###line 292:_sage_ >>> type(cunningham_prime_factors) |

332 | <type 'sage.misc.cachefunc.CachedFunction'> |

333 | >>> loads(dumps(cunningham_prime_factors)) is cunningham_prime_factors #indirect doctest###line 294:_sage_ >>> loads(dumps(cunningham_prime_factors)) is cunningham_prime_factors #indirect doctest |

334 | True |

335 | |

336 | |

337 | >>> sig_on_count() |

338 | 0 |

339 | """ |

340 | |

341 | def example_2(): r""">>> set_random_seed(0L) |

342 | |

343 | >>> change_warning_output(sys.stdout) |

344 | |

345 | |

346 | Create a cached version of a function, which only recomputes |

347 | values it hasn't already computed. Synonyme: ``cached_function`` |

348 | |

349 | INPUT: |

350 | |

351 | - ``f`` -- a function |

352 | - ``name`` (optional string) -- name that the cached version |

353 | of ``f`` should be provided with. |

354 | |

355 | If ``f`` is a function, do either ``g = CachedFunction(f)`` |

356 | or ``g = cached_function(f)`` to make a cached version of ``f``, |

357 | or put ``@cached_function`` right before the definition of ``f`` |

358 | (i.e., use Python decorators):: |

359 | |

360 | @cached_function |

361 | def f(...): |

362 | .... |

363 | |

364 | The inputs to the function must be hashable. |

365 | |

366 | EXAMPLES:: |

367 | |

368 | >>> @cached_function###line 324:_sage_ >>> @cached_function |

369 | ... def mul(x, y=Integer(2)): |

370 | ... return x*y |

371 | ... |

372 | >>> mul(Integer(3))###line 328:_sage_ >>> mul(3) |

373 | 6 |

374 | |

375 | We demonstrate that the result is cached, and that, moreover, |

376 | the cache takes into account the various ways of providing |

377 | default arguments:: |

378 | |

379 | >>> mul(Integer(3)) is mul(Integer(3),Integer(2))###line 335:_sage_ >>> mul(3) is mul(3,2) |

380 | True |

381 | >>> mul(Integer(3),y=Integer(2)) is mul(Integer(3),Integer(2))###line 337:_sage_ >>> mul(3,y=2) is mul(3,2) |

382 | True |

383 | |

384 | The user can clear the cache:: |

385 | |

386 | >>> a = mul(Integer(4))###line 342:_sage_ >>> a = mul(4) |

387 | >>> mul.clear_cache()###line 343:_sage_ >>> mul.clear_cache() |

388 | >>> a is mul(Integer(4))###line 344:_sage_ >>> a is mul(4) |

389 | False |

390 | |

391 | It is also possible to explicitly override the cache with |

392 | a different value:: |

393 | |

394 | >>> mul.set_cache('foo',Integer(5))###line 350:_sage_ >>> mul.set_cache('foo',5) |

395 | >>> mul(Integer(5),Integer(2))###line 351:_sage_ >>> mul(5,2) |

396 | 'foo' |

397 | |

398 | |

399 | >>> sig_on_count() |

400 | 0 |

401 | """ |

402 | |

403 | def example_3(): r""">>> set_random_seed(0L) |

404 | |

405 | >>> change_warning_output(sys.stdout) |

406 | |

407 | |

408 | Create a cached version of a function, which only recomputes |

409 | values it hasn't already computed. A custom name can be |

410 | provided by an optional argument "name". |

411 | |

412 | If f is a function, do either g = CachedFunction(f) to make |

413 | a cached version of f, or put @CachedFunction right before |

414 | the definition of f (i.e., use Python decorators, but then |

415 | the optional argument ``name`` can not be used):: |

416 | |

417 | @CachedFunction |

418 | def f(...): |

419 | .... |

420 | |

421 | The inputs to the function must be hashable. |

422 | |

423 | TESTS:: |

424 | |

425 | >>> g = CachedFunction(number_of_partitions)###line 374:_sage_ >>> g = CachedFunction(number_of_partitions) |

426 | >>> g.__name__###line 375:_sage_ >>> g.__name__ |

427 | 'number_of_partitions' |

428 | >>> 'partitions' in sage.misc.sageinspect.sage_getdoc(g)###line 377:_sage_ >>> 'partitions' in sage.misc.sageinspect.sage_getdoc(g) |

429 | True |

430 | >>> g(Integer(5))###line 379:_sage_ >>> g(5) |

431 | 7 |

432 | >>> g.cache###line 381:_sage_ >>> g.cache |

433 | {((5, None, 'default'), ()): 7} |

434 | >>> def f(t=Integer(1)): print(t)###line 383:_sage_ >>> def f(t=1): print(t) |

435 | >>> h = CachedFunction(f)###line 384:_sage_ >>> h = CachedFunction(f) |

436 | >>> w = walltime()###line 385:_sage_ >>> w = walltime() |

437 | >>> h(); h(Integer(1)); h(t=Integer(1))###line 386:_sage_ >>> h(); h(1); h(t=1) |

438 | 1 |

439 | >>> walltime(w) < Integer(2)###line 388:_sage_ >>> walltime(w) < 2 |

440 | True |

441 | |

442 | |

443 | >>> sig_on_count() |

444 | 0 |

445 | """ |

446 | |

447 | def example_4(): r""">>> set_random_seed(0L) |

448 | |

449 | >>> change_warning_output(sys.stdout) |

450 | |

451 | |

452 | Perform initialization common to CachedFunction and CachedMethodCaller. |

453 | |

454 | TESTS:: |

455 | |

456 | >>> @cached_function###line 401:_sage_ >>> @cached_function |

457 | ... def test_cache(x): |

458 | ... return -x |

459 | >>> test_cache._fix_to_pos is not None # indirect doctest###line 404:_sage_ >>> test_cache._fix_to_pos is not None # indirect doctest |

460 | True |

461 | |

462 | |

463 | >>> sig_on_count() |

464 | 0 |

465 | """ |

466 | |

467 | def example_5(): r""">>> set_random_seed(0L) |

468 | |

469 | >>> change_warning_output(sys.stdout) |

470 | |

471 | |

472 | Pickling of cached functions. |

473 | |

474 | TEST:: |

475 | |

476 | >>> type(cunningham_prime_factors)###line 426:_sage_ >>> type(cunningham_prime_factors) |

477 | <type 'sage.misc.cachefunc.CachedFunction'> |

478 | >>> loads(dumps(cunningham_prime_factors)) is cunningham_prime_factors #indirect doctest###line 428:_sage_ >>> loads(dumps(cunningham_prime_factors)) is cunningham_prime_factors #indirect doctest |

479 | True |

480 | |

481 | |

482 | >>> sig_on_count() |

483 | 0 |

484 | """ |

485 | |

486 | def example_6(): r""">>> set_random_seed(0L) |

487 | |

488 | >>> change_warning_output(sys.stdout) |

489 | |

490 | |

491 | Provide documentation for the cached function. |

492 | |

493 | A cached function shall inherit the documentation |

494 | from the function that is wrapped, not from the |

495 | documentation of the wrapper. |

496 | |

497 | TEST:: |

498 | |

499 | >>> P = QQ['x, y']; (x, y,) = P._first_ngens(2)###line 450:_sage_ >>> P.<x,y> = QQ[] |

500 | >>> I = P*[x,y]###line 451:_sage_ >>> I = P*[x,y] |

501 | >>> from sage.misc.sageinspect import sage_getdoc###line 452:_sage_ >>> from sage.misc.sageinspect import sage_getdoc |

502 | >>> print sage_getdoc(I.groebner_basis) # indirect doctest###line 453:_sage_ >>> print sage_getdoc(I.groebner_basis) # indirect doctest |

503 | Return the reduced Groebner basis of this ideal. |

504 | ... |

505 | ALGORITHM: Uses Singular, Magma (if available), Macaulay2 (if |

506 | available), or a toy implementation. |

507 | |

508 | |

509 | >>> sig_on_count() |

510 | 0 |

511 | """ |

512 | |

513 | def example_7(): r""">>> set_random_seed(0L) |

514 | |

515 | >>> change_warning_output(sys.stdout) |

516 | |

517 | |

518 | Returns the source code for the wrapped function. |

519 | |

520 | TESTS:: |

521 | |

522 | >>> from sage.misc.sageinspect import sage_getsource###line 491:_sage_ >>> from sage.misc.sageinspect import sage_getsource |

523 | >>> g = CachedFunction(number_of_partitions)###line 492:_sage_ >>> g = CachedFunction(number_of_partitions) |

524 | >>> 'bober' in sage_getsource(g) # indirect doctest###line 493:_sage_ >>> 'bober' in sage_getsource(g) # indirect doctest |

525 | True |

526 | |

527 | |

528 | >>> sig_on_count() |

529 | 0 |

530 | """ |

531 | |

532 | def example_8(): r""">>> set_random_seed(0L) |

533 | |

534 | >>> change_warning_output(sys.stdout) |

535 | |

536 | |

537 | Returns the list of source lines and the first line number |

538 | of the wrapped function. |

539 | |

540 | TEST:: |

541 | |

542 | >>> P = QQ['x, y']; (x, y,) = P._first_ngens(2)###line 507:_sage_ >>> P.<x,y> = QQ[] |

543 | >>> I = P*[x,y]###line 508:_sage_ >>> I = P*[x,y] |

544 | >>> from sage.misc.sageinspect import sage_getsourcelines###line 509:_sage_ >>> from sage.misc.sageinspect import sage_getsourcelines |

545 | >>> l = " elif algorithm == 'macaulay2:gb':\n"###line 510:_sage_ >>> l = " elif algorithm == 'macaulay2:gb':\n" |

546 | >>> l in sage_getsourcelines(I.groebner_basis)[Integer(0)] # indirect doctest###line 511:_sage_ >>> l in sage_getsourcelines(I.groebner_basis)[0] # indirect doctest |

547 | True |

548 | |

549 | |

550 | >>> sig_on_count() |

551 | 0 |

552 | """ |

553 | |

554 | def example_9(): r""">>> set_random_seed(0L) |

555 | |

556 | >>> change_warning_output(sys.stdout) |

557 | |

558 | |

559 | Return the argspec of the wrapped function or method. |

560 | |

561 | This was implemented in trac ticket #11115. |

562 | |

563 | EXAMPLE:: |

564 | |

565 | >>> P = QQ['x, y']; (x, y,) = P._first_ngens(2)###line 526:_sage_ >>> P.<x,y> = QQ[] |

566 | >>> I = P*[x,y]###line 527:_sage_ >>> I = P*[x,y] |

567 | >>> from sage.misc.sageinspect import sage_getargspec###line 528:_sage_ >>> from sage.misc.sageinspect import sage_getargspec |

568 | >>> sage_getargspec(I.groebner_basis) # indirect doctest###line 529:_sage_ >>> sage_getargspec(I.groebner_basis) # indirect doctest |

569 | ArgSpec(args=['self', 'algorithm', 'deg_bound', 'mult_bound', 'prot'], |

570 | varargs='args', keywords='kwds', defaults=('', None, None, |

571 | False)) |

572 | |

573 | |

574 | >>> sig_on_count() |

575 | 0 |

576 | """ |

577 | |

578 | def example_10(): r""">>> set_random_seed(0L) |

579 | |

580 | >>> change_warning_output(sys.stdout) |

581 | |

582 | |

583 | Return value from cache or call the wrapped function, |

584 | caching the output. |

585 | |

586 | TESTS:: |

587 | |

588 | >>> g = CachedFunction(number_of_partitions)###line 545:_sage_ >>> g = CachedFunction(number_of_partitions) |

589 | >>> a = g(Integer(5))###line 546:_sage_ >>> a = g(5) |

590 | >>> g.get_cache()###line 547:_sage_ >>> g.get_cache() |

591 | {((5, None, 'default'), ()): 7} |

592 | >>> a = g(Integer(10)**Integer(5)) # indirect doctest###line 549:_sage_ >>> a = g(10^5) # indirect doctest |

593 | >>> a == number_of_partitions(Integer(10)**Integer(5))###line 550:_sage_ >>> a == number_of_partitions(10^5) |

594 | True |

595 | >>> a is g(Integer(10)**Integer(5))###line 552:_sage_ >>> a is g(10^5) |

596 | True |

597 | >>> a is number_of_partitions(Integer(10)**Integer(5))###line 554:_sage_ >>> a is number_of_partitions(10^5) |

598 | False |

599 | |

600 | |

601 | >>> sig_on_count() |

602 | 0 |

603 | """ |

604 | |

605 | def example_11(): r""">>> set_random_seed(0L) |

606 | |

607 | >>> change_warning_output(sys.stdout) |

608 | |

609 | |

610 | Returns the cache dictionary. |

611 | |

612 | EXAMPLES:: |

613 | |

614 | >>> g = CachedFunction(number_of_partitions)###line 580:_sage_ >>> g = CachedFunction(number_of_partitions) |

615 | >>> a = g(Integer(5))###line 581:_sage_ >>> a = g(5) |

616 | >>> g.get_cache()###line 582:_sage_ >>> g.get_cache() |

617 | {((5, None, 'default'), ()): 7} |

618 | |

619 | |

620 | >>> sig_on_count() |

621 | 0 |

622 | """ |

623 | |

624 | def example_12(): r""">>> set_random_seed(0L) |

625 | |

626 | >>> change_warning_output(sys.stdout) |

627 | |

628 | |

629 | Checks if the argument list is in the cache. |

630 | |

631 | EXAMPLES:: |

632 | |

633 | >>> class Foo:###line 594:_sage_ >>> class Foo: |

634 | ... def __init__(self, x): |

635 | ... self._x = x |

636 | ... @cached_method |

637 | ... def f(self, z, y=Integer(0)): |

638 | ... return self._x*z+y |

639 | ... |

640 | >>> a = Foo(Integer(2))###line 601:_sage_ >>> a = Foo(2) |

641 | >>> a.f.is_in_cache(Integer(3))###line 602:_sage_ >>> a.f.is_in_cache(3) |

642 | False |

643 | >>> a.f(Integer(3))###line 604:_sage_ >>> a.f(3) |

644 | 6 |

645 | >>> a.f.is_in_cache(Integer(3),y=Integer(0))###line 606:_sage_ >>> a.f.is_in_cache(3,y=0) |

646 | True |

647 | |

648 | >>> sig_on_count() |

649 | 0 |

650 | """ |

651 | |

652 | def example_13(): r""">>> set_random_seed(0L) |

653 | |

654 | >>> change_warning_output(sys.stdout) |

655 | |

656 | |

657 | Set the value for those args and keyword args |

658 | Mind the unintuitive syntax (value first). |

659 | Any idea on how to improve that welcome! |

660 | |

661 | EXAMPLES:: |

662 | |

663 | >>> g = CachedFunction(number_of_partitions)###line 619:_sage_ >>> g = CachedFunction(number_of_partitions) |

664 | >>> a = g(Integer(5))###line 620:_sage_ >>> a = g(5) |

665 | >>> g.get_cache()###line 621:_sage_ >>> g.get_cache() |

666 | {((5, None, 'default'), ()): 7} |

667 | >>> g.set_cache(Integer(17), Integer(5))###line 623:_sage_ >>> g.set_cache(17, 5) |

668 | >>> g.get_cache()###line 624:_sage_ >>> g.get_cache() |

669 | {((5, None, 'default'), ()): 17} |

670 | >>> g(Integer(5))###line 626:_sage_ >>> g(5) |

671 | 17 |

672 | |

673 | DEVELOPER NOTE: |

674 | |

675 | Is there a way to use the following intuitive syntax? |

676 | |

677 | :: |

678 | |

679 | |

680 | |

681 | |

682 | |

683 | 19 |

684 | |

685 | >>> sig_on_count() |

686 | 0 |

687 | """ |

688 | |

689 | def example_14(): r""">>> set_random_seed(0L) |

690 | |

691 | >>> change_warning_output(sys.stdout) |

692 | |

693 | |

694 | Returns the key in the cache to be used when args |

695 | and kwds are passed in as parameters. |

696 | |

697 | EXAMPLES:: |

698 | |

699 | >>> @cached_function###line 648:_sage_ >>> @cached_function |

700 | ... def foo(x): |

701 | ... return x**Integer(2) |

702 | ... |

703 | >>> foo(Integer(2))###line 652:_sage_ >>> foo(2) |

704 | 4 |

705 | >>> foo.get_key(Integer(2))###line 654:_sage_ >>> foo.get_key(2) |

706 | ((2,), ()) |

707 | >>> foo.get_key(x=Integer(3))###line 656:_sage_ >>> foo.get_key(x=3) |

708 | ((3,), ()) |

709 | |

710 | >>> sig_on_count() |

711 | 0 |

712 | """ |

713 | |

714 | def example_15(): r""">>> set_random_seed(0L) |

715 | |

716 | >>> change_warning_output(sys.stdout) |

717 | |

718 | |

719 | EXAMPLES:: |

720 | |

721 | >>> g = CachedFunction(number_of_partitions)###line 665:_sage_ >>> g = CachedFunction(number_of_partitions) |

722 | >>> g # indirect doctest###line 666:_sage_ >>> g # indirect doctest |

723 | Cached version of <function number_of_partitions at 0x...> |

724 | |

725 | >>> sig_on_count() |

726 | 0 |

727 | """ |

728 | |

729 | def example_16(): r""">>> set_random_seed(0L) |

730 | |

731 | >>> change_warning_output(sys.stdout) |

732 | |

733 | |

734 | Clear the cache dictionary. |

735 | |

736 | EXAMPLES:: |

737 | |

738 | >>> g = CachedFunction(number_of_partitions)###line 680:_sage_ >>> g = CachedFunction(number_of_partitions) |

739 | >>> a = g(Integer(5))###line 681:_sage_ >>> a = g(5) |

740 | >>> g.get_cache()###line 682:_sage_ >>> g.get_cache() |

741 | {((5, None, 'default'), ()): 7} |

742 | >>> g.clear_cache()###line 684:_sage_ >>> g.clear_cache() |

743 | >>> g.get_cache()###line 685:_sage_ >>> g.get_cache() |

744 | {} |

745 | |

746 | >>> sig_on_count() |

747 | 0 |

748 | """ |

749 | |

750 | def example_17(): r""">>> set_random_seed(0L) |

751 | |

752 | >>> change_warning_output(sys.stdout) |

753 | |

754 | |

755 | Cache values for a number of inputs. Do the computation |

756 | in parallel, and only bother to compute values that we |

757 | haven't already cached. |

758 | |

759 | EXAMPLES:: |

760 | |

761 | >>> @cached_function###line 700:_sage_ >>> @cached_function |

762 | ... def oddprime_factors(n): |

763 | ... l = [p for p,e in factor(n) if p != Integer(2)] |

764 | ... return len(l) |

765 | >>> oddprime_factors.precompute(range(Integer(1),Integer(100)), Integer(4))###line 704:_sage_ >>> oddprime_factors.precompute(range(1,100), 4) |

766 | >>> oddprime_factors.cache[(Integer(25),),()]###line 705:_sage_ >>> oddprime_factors.cache[(25,),()] |

767 | 1 |

768 | |

769 | >>> sig_on_count() |

770 | 0 |

771 | """ |

772 | |

773 | def example_18(): r""">>> set_random_seed(0L) |

774 | |

775 | >>> change_warning_output(sys.stdout) |

776 | |

777 | |

778 | This class helps to unpickle cached methods. |

779 | |

780 | NOTE: |

781 | |

782 | Since trac ticket #8611, a cached method is an attribute |

783 | of the instance (provided that it has a ``__dict__``). |

784 | Hence, when pickling the instance, it would be attempted |

785 | to pickle that attribute as well, but this is a problem, |

786 | since functions can not be pickled, currently. Therefore, |

787 | we replace the actual cached method by a place holder, |

788 | that kills itself as soon as any attribute is requested. |

789 | Then, the original cached attribute is reinstated. But the |

790 | cached values are in fact saved. |

791 | |

792 | EXAMPLE:: |

793 | |

794 | >>> R = PolynomialRing(QQ, Integer(3), names=('x', 'y', 'z',)); (x, y, z,) = R._first_ngens(3)###line 738:_sage_ >>> R.<x, y, z> = PolynomialRing(QQ, 3) |

795 | >>> I = R*(x**Integer(3) + y**Integer(3) + z**Integer(3),x**Integer(4)-y**Integer(4))###line 739:_sage_ >>> I = R*(x^3 + y^3 + z^3,x^4-y^4) |

796 | >>> I.groebner_basis()###line 740:_sage_ >>> I.groebner_basis() |

797 | [y^5*z^3 - 1/4*x^2*z^6 + 1/2*x*y*z^6 + 1/4*y^2*z^6, |

798 | x^2*y*z^3 - x*y^2*z^3 + 2*y^3*z^3 + z^6, |

799 | x*y^3 + y^4 + x*z^3, x^3 + y^3 + z^3] |

800 | >>> I.groebner_basis###line 744:_sage_ >>> I.groebner_basis |

801 | Cached version of <function groebner_basis at 0x...> |

802 | |

803 | We now pickle and unpickle the ideal. The cached method |

804 | ``groebner_basis`` is replaced by a placeholder:: |

805 | |

806 | >>> J = loads(dumps(I))###line 750:_sage_ >>> J = loads(dumps(I)) |

807 | >>> J.groebner_basis###line 751:_sage_ >>> J.groebner_basis |

808 | Pickle of the cached method "groebner_basis" |

809 | |

810 | But as soon as any other attribute is requested from the |

811 | placeholder, it replaces itself by the cached method, and |

812 | the entries of the cache are actually preserved:: |

813 | |

814 | >>> J.groebner_basis.is_in_cache()###line 758:_sage_ >>> J.groebner_basis.is_in_cache() |

815 | True |

816 | >>> J.groebner_basis###line 760:_sage_ >>> J.groebner_basis |

817 | Cached version of <function groebner_basis at 0x...> |

818 | >>> J.groebner_basis() == I.groebner_basis()###line 762:_sage_ >>> J.groebner_basis() == I.groebner_basis() |

819 | True |

820 | |

821 | TESTS: |

822 | |

823 | Since Trac Ticket #11115, there is a special implementation for |

824 | cached methods that don't take arguments:: |

825 | |

826 | >>> P = QQ['a, b, c, d']; (a, b, c, d,) = P._first_ngens(4)###line 770:_sage_ >>> P.<a,b,c,d> = QQ[] |

827 | >>> I = P*[a,b]###line 771:_sage_ >>> I = P*[a,b] |

828 | >>> type(I.gens)###line 772:_sage_ >>> type(I.gens) |

829 | <type 'sage.misc.cachefunc.CachedMethodCallerNoArgs'> |

830 | >>> type(I.groebner_basis)###line 774:_sage_ >>> type(I.groebner_basis) |

831 | <type 'sage.misc.cachefunc.CachedMethodCaller'> |

832 | |

833 | We demonstrate that both implementations can be pickled and |

834 | preserve the cache. For that purpose, we assign nonsense to the |

835 | cache. Of course, it is a very bad idea to override the cache in |

836 | that way. So, please don't try this at home:: |

837 | |

838 | >>> I.groebner_basis.set_cache('foo',algorithm='singular')###line 782:_sage_ >>> I.groebner_basis.set_cache('foo',algorithm='singular') |

839 | >>> I.groebner_basis(algorithm='singular')###line 783:_sage_ >>> I.groebner_basis(algorithm='singular') |

840 | 'foo' |

841 | >>> I.gens.set_cache('bar')###line 785:_sage_ >>> I.gens.set_cache('bar') |

842 | >>> I.gens()###line 786:_sage_ >>> I.gens() |

843 | 'bar' |

844 | >>> J = loads(dumps(I))###line 788:_sage_ >>> J = loads(dumps(I)) |

845 | >>> J.gens()###line 789:_sage_ >>> J.gens() |

846 | 'bar' |

847 | >>> J.groebner_basis(algorithm='singular')###line 791:_sage_ >>> J.groebner_basis(algorithm='singular') |

848 | 'foo' |

849 | |

850 | Anyway, the cache will be automatically reconstructed after |

851 | clearing it:: |

852 | |

853 | >>> J.gens.clear_cache()###line 797:_sage_ >>> J.gens.clear_cache() |

854 | >>> J.gens()###line 798:_sage_ >>> J.gens() |

855 | [a, b] |

856 | >>> J.groebner_basis.clear_cache()###line 800:_sage_ >>> J.groebner_basis.clear_cache() |

857 | >>> J.groebner_basis(algorithm='singular')###line 801:_sage_ >>> J.groebner_basis(algorithm='singular') |

858 | [a, b] |

859 | |

860 | AUTHOR: |

861 | |

862 | - Simon King (2011-01) |

863 | |

864 | >>> sig_on_count() |

865 | 0 |

866 | """ |

867 | |

868 | def example_19(): r""">>> set_random_seed(0L) |

869 | |

870 | >>> change_warning_output(sys.stdout) |

871 | |

872 | |

873 | INPUT: |

874 | |

875 | - ``inst`` - some instance. |

876 | - ``name`` (string) - usually the name of an attribute |

877 | of ``inst`` to which ``self`` is assigned. |

878 | |

879 | TEST:: |

880 | |

881 | >>> from sage.misc.cachefunc import CachedMethodPickle###line 818:_sage_ >>> from sage.misc.cachefunc import CachedMethodPickle |

882 | >>> P = CachedMethodPickle(Integer(1), 'foo')###line 819:_sage_ >>> P = CachedMethodPickle(1, 'foo') |

883 | >>> P###line 820:_sage_ >>> P |

884 | Pickle of the cached method "foo" |

885 | |

886 | |

887 | >>> sig_on_count() |

888 | 0 |

889 | """ |

890 | |

891 | def example_20(): r""">>> set_random_seed(0L) |

892 | |

893 | >>> change_warning_output(sys.stdout) |

894 | |

895 | |

896 | TEST:: |

897 | |

898 | >>> R = PolynomialRing(QQ, Integer(3), names=('x', 'y', 'z',)); (x, y, z,) = R._first_ngens(3)###line 831:_sage_ >>> R.<x, y, z> = PolynomialRing(QQ, 3) |

899 | >>> I = R*(x**Integer(3) + y**Integer(3) + z**Integer(3),x**Integer(4)-y**Integer(4))###line 832:_sage_ >>> I = R*(x^3 + y^3 + z^3,x^4-y^4) |

900 | >>> G = I.groebner_basis()###line 833:_sage_ >>> G = I.groebner_basis() |

901 | >>> J = loads(dumps(I))###line 834:_sage_ >>> J = loads(dumps(I)) |

902 | >>> J.groebner_basis #indirect doctest###line 835:_sage_ >>> J.groebner_basis #indirect doctest |

903 | Pickle of the cached method "groebner_basis" |

904 | |

905 | >>> sig_on_count() |

906 | 0 |

907 | """ |

908 | |

909 | def example_21(): r""">>> set_random_seed(0L) |

910 | |

911 | >>> change_warning_output(sys.stdout) |

912 | |

913 | |

914 | This class is a pickle. However, sometimes, pickles |

915 | need to be pickled another time. |

916 | |

917 | TEST:: |

918 | |

919 | >>> PF = WeylGroup(['A',Integer(3)]).pieri_factors()###line 846:_sage_ >>> PF = WeylGroup(['A',3]).pieri_factors() |

920 | >>> a = PF.an_element()###line 847:_sage_ >>> a = PF.an_element() |

921 | >>> a.bruhat_lower_covers()###line 848:_sage_ >>> a.bruhat_lower_covers() |

922 | [[0 1 0 0] |

923 | [0 0 1 0] |

924 | [1 0 0 0] |

925 | [0 0 0 1], [0 1 0 0] |

926 | [1 0 0 0] |

927 | [0 0 0 1] |

928 | [0 0 1 0], [1 0 0 0] |

929 | [0 0 1 0] |

930 | [0 0 0 1] |

931 | [0 1 0 0]] |

932 | >>> b = loads(dumps(a))###line 859:_sage_ >>> b = loads(dumps(a)) |

933 | >>> b.bruhat_lower_covers###line 860:_sage_ >>> b.bruhat_lower_covers |

934 | Pickle of the cached method "bruhat_lower_covers" |

935 | |

936 | When we now pickle ``b``, the pickle of the cached method |

937 | needs to be taken care of:: |

938 | |

939 | >>> c = loads(dumps(b)) # indirect doctest###line 866:_sage_ >>> c = loads(dumps(b)) # indirect doctest |

940 | >>> c.bruhat_lower_covers###line 867:_sage_ >>> c.bruhat_lower_covers |

941 | Pickle of the cached method "bruhat_lower_covers" |

942 | >>> c.bruhat_lower_covers()###line 869:_sage_ >>> c.bruhat_lower_covers() |

943 | [[0 1 0 0] |

944 | [0 0 1 0] |

945 | [1 0 0 0] |

946 | [0 0 0 1], [0 1 0 0] |

947 | [1 0 0 0] |

948 | [0 0 0 1] |

949 | [0 0 1 0], [1 0 0 0] |

950 | [0 0 1 0] |

951 | [0 0 0 1] |

952 | [0 1 0 0]] |

953 | |

954 | |

955 | >>> sig_on_count() |

956 | 0 |

957 | """ |

958 | |

959 | def example_22(): r""">>> set_random_seed(0L) |

960 | |

961 | >>> change_warning_output(sys.stdout) |

962 | |

963 | |

964 | The purpose of this call method is to kill ``self`` and to |

965 | replace it by an actual :class:`CachedMethodCaller`. The last |

966 | thing that ``self`` does before disappearing is to call the |

967 | :class:`CachedMethodCaller` and return the result. |

968 | |

969 | EXAMPLE:: |

970 | |

971 | >>> P = QQ['a, b, c, d']; (a, b, c, d,) = P._first_ngens(4)###line 892:_sage_ >>> P.<a,b,c,d> = QQ[] |

972 | >>> I = P*[a,b]###line 893:_sage_ >>> I = P*[a,b] |

973 | >>> I.gens###line 894:_sage_ >>> I.gens |

974 | Cached version of <function gens at 0x...> |

975 | >>> J = loads(dumps(I))###line 896:_sage_ >>> J = loads(dumps(I)) |

976 | >>> J.gens###line 897:_sage_ >>> J.gens |

977 | Pickle of the cached method "gens" |

978 | >>> J.gens() # indirect doctest###line 899:_sage_ >>> J.gens() # indirect doctest |

979 | [a, b] |

980 | >>> J.gens###line 901:_sage_ >>> J.gens |

981 | Cached version of <function gens at 0x...> |

982 | |

983 | |

984 | >>> sig_on_count() |

985 | 0 |

986 | """ |

987 | |

988 | def example_23(): r""">>> set_random_seed(0L) |

989 | |

990 | >>> change_warning_output(sys.stdout) |

991 | |

992 | |

993 | TEST:: |

994 | |

995 | >>> R = PolynomialRing(QQ, Integer(3), names=('x', 'y', 'z',)); (x, y, z,) = R._first_ngens(3)###line 919:_sage_ >>> R.<x, y, z> = PolynomialRing(QQ, 3) |

996 | >>> I = R*(x**Integer(3) + y**Integer(3) + z**Integer(3),x**Integer(4)-y**Integer(4))###line 920:_sage_ >>> I = R*(x^3 + y^3 + z^3,x^4-y^4) |

997 | >>> G = I.groebner_basis()###line 921:_sage_ >>> G = I.groebner_basis() |

998 | >>> J = loads(dumps(I))###line 922:_sage_ >>> J = loads(dumps(I)) |

999 | >>> J.groebner_basis###line 923:_sage_ >>> J.groebner_basis |

1000 | Pickle of the cached method "groebner_basis" |

1001 | |

1002 | If an attribute of name ``s`` is requested (say, |

1003 | ``is_in_cache``), the attribute ``self._name`` of |

1004 | ``self._instance`` is deleted. Then, the attribute |

1005 | of name ``s`` of the attribute ``self._name`` of |

1006 | ``self._instance`` is requested. Since ``self._name`` |

1007 | is a cached method defined for the class of |

1008 | ``self._instance``, retrieving the just-deleted |

1009 | attribute ``self._name`` succeeds. |

1010 | |

1011 | In that way, the unpickling of the cached method is |

1012 | finally accomplished:: |

1013 | |

1014 | >>> J.groebner_basis.is_in_cache() #indirect doctest###line 938:_sage_ >>> J.groebner_basis.is_in_cache() #indirect doctest |

1015 | True |

1016 | >>> J.groebner_basis###line 940:_sage_ >>> J.groebner_basis |

1017 | Cached version of <function groebner_basis at 0x...> |

1018 | |

1019 | |

1020 | >>> sig_on_count() |

1021 | 0 |

1022 | """ |

1023 | |

1024 | def example_24(): r""">>> set_random_seed(0L) |

1025 | |

1026 | >>> change_warning_output(sys.stdout) |

1027 | |

1028 | |

1029 | Utility class that is used by :class:`CachedMethod` to bind a |

1030 | cached method to an instance. |

1031 | |

1032 | NOTE: |

1033 | |

1034 | Since Trac Ticket #11115, there is a special implementation |

1035 | :class:`CachedMethodCallerNoArgs` for methods that do not take |

1036 | arguments. |

1037 | |

1038 | EXAMPLE:: |

1039 | |

1040 | >>> class A:###line 967:_sage_ >>> class A: |

1041 | ... @cached_method |

1042 | ... def bar(self,x): |

1043 | ... return x**Integer(2) |

1044 | >>> a = A()###line 971:_sage_ >>> a = A() |

1045 | >>> a.bar###line 972:_sage_ >>> a.bar |

1046 | Cached version of <function bar at 0x...> |

1047 | >>> type(a.bar)###line 974:_sage_ >>> type(a.bar) |

1048 | <type 'sage.misc.cachefunc.CachedMethodCaller'> |

1049 | >>> a.bar(Integer(2)) is a.bar(x=Integer(2))###line 976:_sage_ >>> a.bar(2) is a.bar(x=2) |

1050 | True |

1051 | |

1052 | |

1053 | >>> sig_on_count() |

1054 | 0 |

1055 | """ |

1056 | |

1057 | def example_25(): r""">>> set_random_seed(0L) |

1058 | |

1059 | >>> change_warning_output(sys.stdout) |

1060 | |

1061 | |

1062 | EXAMPLES:: |

1063 | |

1064 | >>> class Foo:###line 984:_sage_ >>> class Foo: |

1065 | ... def __init__(self, x): |

1066 | ... self._x = x |

1067 | ... @cached_method |

1068 | ... def f(self,*args): |

1069 | ... return self._x**Integer(2) |

1070 | ... |

1071 | >>> a = Foo(Integer(2))###line 991:_sage_ >>> a = Foo(2) |

1072 | >>> a.f.get_cache()###line 992:_sage_ >>> a.f.get_cache() |

1073 | {} |

1074 | >>> a.f()###line 994:_sage_ >>> a.f() |

1075 | 4 |

1076 | >>> a.f.get_cache()###line 996:_sage_ >>> a.f.get_cache() |

1077 | {((), ()): 4} |

1078 | |

1079 | >>> sig_on_count() |

1080 | 0 |

1081 | """ |

1082 | |

1083 | def example_26(): r""">>> set_random_seed(0L) |

1084 | |

1085 | >>> change_warning_output(sys.stdout) |

1086 | |

1087 | |

1088 | The pickle of a :class:`CachedMethodCaller` unpickles |

1089 | to a :class:`CachedMethodPickle`, that is able to replace |

1090 | itself by a copy of the original :class:`CachedMethodCaller`. |

1091 | |

1092 | TEST:: |

1093 | |

1094 | >>> R = PolynomialRing(QQ, Integer(3), names=('x', 'y', 'z',)); (x, y, z,) = R._first_ngens(3)###line 1014:_sage_ >>> R.<x, y, z> = PolynomialRing(QQ, 3) |

1095 | >>> I = R*(x**Integer(3) + y**Integer(3) + z**Integer(3),x**Integer(4)-y**Integer(4))###line 1015:_sage_ >>> I = R*(x^3 + y^3 + z^3,x^4-y^4) |

1096 | >>> G = I.groebner_basis()###line 1016:_sage_ >>> G = I.groebner_basis() |

1097 | >>> J = loads(dumps(I)) #indirect doctest###line 1017:_sage_ >>> J = loads(dumps(I)) #indirect doctest |

1098 | >>> J.groebner_basis###line 1018:_sage_ >>> J.groebner_basis |

1099 | Pickle of the cached method "groebner_basis" |

1100 | >>> J.groebner_basis.is_in_cache()###line 1020:_sage_ >>> J.groebner_basis.is_in_cache() |

1101 | True |

1102 | >>> J.groebner_basis###line 1022:_sage_ >>> J.groebner_basis |

1103 | Cached version of <function groebner_basis at 0x...> |

1104 | |

1105 | |

1106 | >>> sig_on_count() |

1107 | 0 |

1108 | """ |

1109 | |

1110 | def example_27(): r""">>> set_random_seed(0L) |

1111 | |

1112 | >>> change_warning_output(sys.stdout) |

1113 | |

1114 | |

1115 | Call the cached method without using the cache. |

1116 | |

1117 | EXAMPLE:: |

1118 | |

1119 | >>> P = QQ['a, b, c, d']; (a, b, c, d,) = P._first_ngens(4)###line 1038:_sage_ >>> P.<a,b,c,d> = QQ[] |

1120 | >>> I = P*[a,b]###line 1039:_sage_ >>> I = P*[a,b] |

1121 | >>> I.groebner_basis()###line 1040:_sage_ >>> I.groebner_basis() |

1122 | [a, b] |

1123 | >>> I.groebner_basis._instance_call() is I.groebner_basis()###line 1042:_sage_ >>> I.groebner_basis._instance_call() is I.groebner_basis() |

1124 | False |

1125 | >>> I.groebner_basis._instance_call() == I.groebner_basis()###line 1044:_sage_ >>> I.groebner_basis._instance_call() == I.groebner_basis() |

1126 | True |

1127 | |

1128 | |

1129 | >>> sig_on_count() |

1130 | 0 |

1131 | """ |

1132 | |

1133 | def example_28(): r""">>> set_random_seed(0L) |

1134 | |

1135 | >>> change_warning_output(sys.stdout) |

1136 | |

1137 | |

1138 | Call the cached method. |

1139 | |

1140 | TESTS:: |

1141 | |

1142 | >>> class Foo:###line 1056:_sage_ >>> class Foo: |

1143 | ... @cached_method |

1144 | ... def f(self, x,y=Integer(1)): |

1145 | ... return x+y |

1146 | ... |

1147 | >>> a = Foo()###line 1061:_sage_ >>> a = Foo() |

1148 | >>> a.f(Integer(1)) #indirect doctest###line 1062:_sage_ >>> a.f(1) #indirect doctest |

1149 | 2 |

1150 | |

1151 | The result is cached, taking into account |

1152 | the three ways of providing (named) arguments:: |

1153 | |

1154 | >>> a.f(Integer(5)) is a.f(Integer(5),Integer(1))###line 1068:_sage_ >>> a.f(5) is a.f(5,1) |

1155 | True |

1156 | >>> a.f(Integer(5)) is a.f(Integer(5),y=Integer(1))###line 1070:_sage_ >>> a.f(5) is a.f(5,y=1) |

1157 | True |

1158 | >>> a.f(Integer(5)) is a.f(y=Integer(1),x=Integer(5))###line 1072:_sage_ >>> a.f(5) is a.f(y=1,x=5) |

1159 | True |

1160 | |

1161 | We test that #5843 is fixed:: |

1162 | |

1163 | >>> class Foo:###line 1077:_sage_ >>> class Foo: |

1164 | ... def __init__(self, x): |

1165 | ... self._x = x |

1166 | ... @cached_method |

1167 | ... def f(self, y): |

1168 | ... return self._x |

1169 | ... |

1170 | >>> a = Foo(Integer(2))###line 1084:_sage_ >>> a = Foo(2) |

1171 | >>> b = Foo(Integer(3))###line 1085:_sage_ >>> b = Foo(3) |

1172 | >>> a.f(b.f)###line 1086:_sage_ >>> a.f(b.f) |

1173 | 2 |

1174 | |

1175 | >>> sig_on_count() |

1176 | 0 |

1177 | """ |

1178 | |

1179 | def example_29(): r""">>> set_random_seed(0L) |

1180 | |

1181 | >>> change_warning_output(sys.stdout) |

1182 | |

1183 | |

1184 | Convert arguments to the key for this instance's cache. |

1185 | |

1186 | EXAMPLES:: |

1187 | |

1188 | >>> class Foo:###line 1135:_sage_ >>> class Foo: |

1189 | ... def __init__(self, x): |

1190 | ... self._x = x |

1191 | ... @cached_method |

1192 | ... def f(self, y, z=Integer(0)): |

1193 | ... return self._x * y + z |

1194 | ... |

1195 | >>> a = Foo(Integer(2))###line 1142:_sage_ >>> a = Foo(2) |

1196 | >>> z = a.f(Integer(37))###line 1143:_sage_ >>> z = a.f(37) |

1197 | >>> k = a.f.get_key(Integer(37)); k###line 1144:_sage_ >>> k = a.f.get_key(37); k |

1198 | ((37, 0), ()) |

1199 | >>> a.f.get_cache()[k] is z###line 1146:_sage_ >>> a.f.get_cache()[k] is z |

1200 | True |

1201 | |

1202 | Note that the method does not test whether there are |

1203 | too many arguments, or wrong argument names:: |

1204 | |

1205 | >>> a.f.get_key(Integer(1),Integer(2),Integer(3),x=Integer(4),y=Integer(5),z=Integer(6))###line 1152:_sage_ >>> a.f.get_key(1,2,3,x=4,y=5,z=6) |

1206 | ((1, 2, 3), (('x', 4), ('y', 5), ('z', 6))) |

1207 | |

1208 | It does, however, take into account the different |

1209 | ways of providing named arguments, possibly with a |

1210 | default value:: |

1211 | |

1212 | >>> a.f.get_key(Integer(5))###line 1159:_sage_ >>> a.f.get_key(5) |

1213 | ((5, 0), ()) |

1214 | >>> a.f.get_key(y=Integer(5))###line 1161:_sage_ >>> a.f.get_key(y=5) |

1215 | ((5, 0), ()) |

1216 | >>> a.f.get_key(Integer(5),Integer(0))###line 1163:_sage_ >>> a.f.get_key(5,0) |

1217 | ((5, 0), ()) |

1218 | >>> a.f.get_key(Integer(5),z=Integer(0))###line 1165:_sage_ >>> a.f.get_key(5,z=0) |

1219 | ((5, 0), ()) |

1220 | >>> a.f.get_key(y=Integer(5),z=Integer(0))###line 1167:_sage_ >>> a.f.get_key(y=5,z=0) |

1221 | ((5, 0), ()) |

1222 | |

1223 | |

1224 | >>> sig_on_count() |

1225 | 0 |

1226 | """ |

1227 | |

1228 | def example_30(): r""">>> set_random_seed(0L) |

1229 | |

1230 | >>> change_warning_output(sys.stdout) |

1231 | |

1232 | |

1233 | Get a :class:`CachedMethodCaller` bound to a specific |

1234 | instance of the class of the cached method. |

1235 | |

1236 | NOTE: |

1237 | |

1238 | :class:`CachedMethodCaller` has a separate ``__get__`` |

1239 | since the categories framework creates and caches the |

1240 | return value of ``CachedMethod.__get__`` with |

1241 | ``inst==None``. |

1242 | |

1243 | This getter attempts to assign a bound method as an |

1244 | attribute to the given instance. If this is not |

1245 | possible (for example, for some extension classes), |

1246 | it is attempted to find an attribute ``__cached_methods``, |

1247 | and store/retrieve the bound method there. In that |

1248 | way, cached methods can be implemented for extension |

1249 | classes deriving from :class:`~sage.structure.parent.Parent` |

1250 | and :class:`~sage.structure.element.Element`. |

1251 | |

1252 | TESTS: |

1253 | |

1254 | Due to the separate ``__get__`` method, it is possible |

1255 | to define a cached method in one class and use it as |

1256 | an attribute of another class. |

1257 | |

1258 | >>> class Foo:###line 1202:_sage_ >>> class Foo: |

1259 | ... @cached_method |

1260 | ... def f(self, y): |

1261 | ... return y - Integer(1) |

1262 | >>> class Bar:###line 1206:_sage_ >>> class Bar: |

1263 | ... f = Foo.f |

1264 | >>> b1 = Bar()###line 1208:_sage_ >>> b1 = Bar() |

1265 | >>> b2 = Bar()###line 1209:_sage_ >>> b2 = Bar() |

1266 | |

1267 | The :class:`CachedMethod` is replaced by an instance |

1268 | of :class:`CachedMethodCaller` that (by trac ticket |

1269 | #8611) is set as an attribute. Hence, we have:: |

1270 | |

1271 | >>> b1.f is b1.f###line 1215:_sage_ >>> b1.f is b1.f |

1272 | True |

1273 | |

1274 | Any instance of ``Bar`` gets its own instance of |

1275 | :class:`CachedMethodCaller``:: |

1276 | |

1277 | >>> b1.f is b2.f###line 1221:_sage_ >>> b1.f is b2.f |

1278 | False |

1279 | |

1280 | The method caller knows the instance that it belongs |

1281 | to:: |

1282 | |

1283 | >>> Foo.f._instance is None###line 1227:_sage_ >>> Foo.f._instance is None |

1284 | True |

1285 | >>> b1.f._instance is b1###line 1229:_sage_ >>> b1.f._instance is b1 |

1286 | True |

1287 | >>> b2.f._instance is b2###line 1231:_sage_ >>> b2.f._instance is b2 |

1288 | True |

1289 | |

1290 | An extension class can inherit a cached method from the |

1291 | parent or element class of a category (trac ticket #11115). |

1292 | See :class:`CachedMethodCaller` for examples. |

1293 | |

1294 | |

1295 | >>> sig_on_count() |

1296 | 0 |

1297 | """ |

1298 | |

1299 | def example_31(): r""">>> set_random_seed(0L) |

1300 | |

1301 | >>> change_warning_output(sys.stdout) |

1302 | |

1303 | |

1304 | Utility class that is used by :class:`CachedMethod` to bind a |

1305 | cached method to an instance, in the case of a method that does |

1306 | not accept any arguments except ``self``. |

1307 | |

1308 | NOTE: |

1309 | |

1310 | The return value ``None`` would not be cached. So, if you have |

1311 | a method that does not accept arguments and may return ``None`` |

1312 | after a lengthy computation, then ``@cached_method`` should not |

1313 | be used. |

1314 | |

1315 | EXAMPLE:: |

1316 | |

1317 | >>> P = QQ['a, b, c, d']; (a, b, c, d,) = P._first_ngens(4)###line 1274:_sage_ >>> P.<a,b,c,d> = QQ[] |

1318 | >>> I = P*[a,b]###line 1275:_sage_ >>> I = P*[a,b] |

1319 | >>> I.gens###line 1276:_sage_ >>> I.gens |

1320 | Cached version of <function gens at 0x...> |

1321 | >>> type(I.gens)###line 1278:_sage_ >>> type(I.gens) |

1322 | <type 'sage.misc.cachefunc.CachedMethodCallerNoArgs'> |

1323 | >>> I.gens is I.gens###line 1280:_sage_ >>> I.gens is I.gens |

1324 | True |

1325 | >>> I.gens() is I.gens()###line 1282:_sage_ >>> I.gens() is I.gens() |

1326 | True |

1327 | |

1328 | AUTHOR: |

1329 | |

1330 | - Simon King (2011-04) |

1331 | |

1332 | >>> sig_on_count() |

1333 | 0 |

1334 | """ |

1335 | |

1336 | def example_32(): r""">>> set_random_seed(0L) |

1337 | |

1338 | >>> change_warning_output(sys.stdout) |

1339 | |

1340 | |

1341 | EXAMPLES:: |

1342 | |

1343 | >>> class Foo:###line 1293:_sage_ >>> class Foo: |

1344 | ... def __init__(self, x): |

1345 | ... self._x = x |

1346 | ... @cached_method |

1347 | ... def f(self): |

1348 | ... return self._x**Integer(2) |

1349 | ... |

1350 | >>> a = Foo(Integer(2))###line 1300:_sage_ >>> a = Foo(2) |

1351 | >>> print a.f.get_cache()###line 1301:_sage_ >>> print a.f.get_cache() |

1352 | None |

1353 | >>> a.f()###line 1303:_sage_ >>> a.f() |

1354 | 4 |

1355 | >>> a.f.get_cache()###line 1305:_sage_ >>> a.f.get_cache() |

1356 | 4 |

1357 | |

1358 | |

1359 | >>> sig_on_count() |

1360 | 0 |

1361 | """ |

1362 | |

1363 | def example_33(): r""">>> set_random_seed(0L) |

1364 | |

1365 | >>> change_warning_output(sys.stdout) |

1366 | |

1367 | |

1368 | Since functions can not be pickled, the cached method caller |

1369 | is pickled by a :class:`CachedMethodPickle`, that replaces |

1370 | itself by an actual :class:`CachedMethodCallerNoArgs` as soon |

1371 | as it is asked to do anything. |

1372 | |

1373 | TEST:: |

1374 | |

1375 | >>> P = QQ['a, b, c, d']; (a, b, c, d,) = P._first_ngens(4)###line 1346:_sage_ >>> P.<a,b,c,d> = QQ[] |

1376 | >>> I = P*[a,b]###line 1347:_sage_ >>> I = P*[a,b] |

1377 | >>> I.gens()###line 1348:_sage_ >>> I.gens() |

1378 | [a, b] |

1379 | >>> I.gens###line 1350:_sage_ >>> I.gens |

1380 | Cached version of <function gens at 0x...> |

1381 | >>> J = loads(dumps(I))###line 1352:_sage_ >>> J = loads(dumps(I)) |

1382 | >>> J.gens###line 1353:_sage_ >>> J.gens |

1383 | Pickle of the cached method "gens" |

1384 | >>> J.gens.cache###line 1355:_sage_ >>> J.gens.cache |

1385 | [a, b] |

1386 | >>> J.gens###line 1357:_sage_ >>> J.gens |

1387 | Cached version of <function gens at 0x...> |

1388 | |

1389 | |

1390 | >>> sig_on_count() |

1391 | 0 |

1392 | """ |

1393 | |

1394 | def example_34(): r""">>> set_random_seed(0L) |

1395 | |

1396 | >>> change_warning_output(sys.stdout) |

1397 | |

1398 | |

1399 | Call the cached method without using the cache. |

1400 | |

1401 | EXAMPLE:: |

1402 | |

1403 | >>> P = QQ['a, b, c, d']; (a, b, c, d,) = P._first_ngens(4)###line 1369:_sage_ >>> P.<a,b,c,d> = QQ[] |

1404 | >>> I = P*[a,b]###line 1370:_sage_ >>> I = P*[a,b] |

1405 | >>> I.gens()###line 1371:_sage_ >>> I.gens() |

1406 | [a, b] |

1407 | >>> I.gens._instance_call() is I.gens()###line 1373:_sage_ >>> I.gens._instance_call() is I.gens() |

1408 | False |

1409 | >>> I.gens._instance_call() == I.gens()###line 1375:_sage_ >>> I.gens._instance_call() == I.gens() |

1410 | True |

1411 | |

1412 | |

1413 | >>> sig_on_count() |

1414 | 0 |

1415 | """ |

1416 | |

1417 | def example_35(): r""">>> set_random_seed(0L) |

1418 | |

1419 | >>> change_warning_output(sys.stdout) |

1420 | |

1421 | |

1422 | Call the cached method. |

1423 | |

1424 | EXAMPLE:: |

1425 | |

1426 | >>> P = QQ['a, b, c, d']; (a, b, c, d,) = P._first_ngens(4)###line 1387:_sage_ >>> P.<a,b,c,d> = QQ[] |

1427 | >>> I = P*[a,b]###line 1388:_sage_ >>> I = P*[a,b] |

1428 | >>> I.gens() # indirect doctest###line 1389:_sage_ >>> I.gens() # indirect doctest |

1429 | [a, b] |

1430 | >>> I.gens() is I.gens()###line 1391:_sage_ >>> I.gens() is I.gens() |

1431 | True |

1432 | |

1433 | |

1434 | >>> sig_on_count() |

1435 | 0 |

1436 | """ |

1437 | |

1438 | def example_36(): r""">>> set_random_seed(0L) |

1439 | |

1440 | >>> change_warning_output(sys.stdout) |

1441 | |

1442 | |

1443 | Override the cache with a specific value. |

1444 | |

1445 | NOTE: |

1446 | |

1447 | ``None`` is not suitable for a cached value. It would be |

1448 | interpreted as an empty cache, forcing a new computation. |

1449 | |

1450 | EXAMPLES:: |

1451 | |

1452 | >>> P = QQ['a, b, c, d']; (a, b, c, d,) = P._first_ngens(4)###line 1411:_sage_ >>> P.<a,b,c,d> = QQ[] |

1453 | >>> I = P*[a,b]###line 1412:_sage_ >>> I = P*[a,b] |

1454 | >>> I.gens()###line 1413:_sage_ >>> I.gens() |

1455 | [a, b] |

1456 | >>> I.gens.set_cache('bar')###line 1415:_sage_ >>> I.gens.set_cache('bar') |

1457 | >>> I.gens()###line 1416:_sage_ >>> I.gens() |

1458 | 'bar' |

1459 | |

1460 | The cache can be emptied and thus the original value will |

1461 | be reconstructed:: |

1462 | |

1463 | >>> I.gens.clear_cache()###line 1422:_sage_ >>> I.gens.clear_cache() |

1464 | >>> I.gens()###line 1423:_sage_ >>> I.gens() |

1465 | [a, b] |

1466 | |

1467 | The attempt to assign ``None`` to the cache fails:: |

1468 | |

1469 | >>> I.gens.set_cache(None)###line 1428:_sage_ >>> I.gens.set_cache(None) |

1470 | >>> I.gens()###line 1429:_sage_ >>> I.gens() |

1471 | [a, b] |

1472 | |

1473 | |

1474 | >>> sig_on_count() |

1475 | 0 |

1476 | """ |

1477 | |

1478 | def example_37(): r""">>> set_random_seed(0L) |

1479 | |

1480 | >>> change_warning_output(sys.stdout) |

1481 | |

1482 | |

1483 | Clear the cache dictionary. |

1484 | |

1485 | EXAMPLES:: |

1486 | |

1487 | >>> P = QQ['a, b, c, d']; (a, b, c, d,) = P._first_ngens(4)###line 1441:_sage_ >>> P.<a,b,c,d> = QQ[] |

1488 | >>> I = P*[a,b]###line 1442:_sage_ >>> I = P*[a,b] |

1489 | >>> I.gens()###line 1443:_sage_ >>> I.gens() |

1490 | [a, b] |

1491 | >>> I.gens.set_cache('bar')###line 1445:_sage_ >>> I.gens.set_cache('bar') |

1492 | >>> I.gens()###line 1446:_sage_ >>> I.gens() |

1493 | 'bar' |

1494 | |

1495 | The cache can be emptied and thus the original value will |

1496 | be reconstructed:: |

1497 | |

1498 | >>> I.gens.clear_cache()###line 1452:_sage_ >>> I.gens.clear_cache() |

1499 | >>> I.gens()###line 1453:_sage_ >>> I.gens() |

1500 | [a, b] |

1501 | |

1502 | |

1503 | >>> sig_on_count() |

1504 | 0 |

1505 | """ |

1506 | |

1507 | def example_38(): r""">>> set_random_seed(0L) |

1508 | |

1509 | >>> change_warning_output(sys.stdout) |

1510 | |

1511 | |

1512 | Answers whether the return value is already in the cache. |

1513 | |

1514 | NOTE: |

1515 | |

1516 | Recall that a cached method without arguments can not cache |

1517 | the return value ``None``. |

1518 | |

1519 | EXAMPLE:: |

1520 | |

1521 | >>> P = QQ['x, y']; (x, y,) = P._first_ngens(2)###line 1470:_sage_ >>> P.<x,y> = QQ[] |

1522 | >>> I = P*[x,y]###line 1471:_sage_ >>> I = P*[x,y] |

1523 | >>> I.gens.is_in_cache()###line 1472:_sage_ >>> I.gens.is_in_cache() |

1524 | False |

1525 | >>> I.gens()###line 1474:_sage_ >>> I.gens() |

1526 | [x, y] |

1527 | >>> I.gens.is_in_cache()###line 1476:_sage_ >>> I.gens.is_in_cache() |

1528 | True |

1529 | |

1530 | |

1531 | >>> sig_on_count() |

1532 | 0 |

1533 | """ |

1534 | |

1535 | def example_39(): r""">>> set_random_seed(0L) |

1536 | |

1537 | >>> change_warning_output(sys.stdout) |

1538 | |

1539 | |

1540 | Get a :class:`CachedMethodCallerNoArgs` bound to a specific |

1541 | instance of the class of the cached method. |

1542 | |

1543 | NOTE: |

1544 | |

1545 | :class:`CachedMethodCallerNoArgs` has a separate ``__get__`` |

1546 | since the categories framework creates and caches the |

1547 | return value of ``CachedMethod.__get__`` with |

1548 | ``inst==None``. |

1549 | |

1550 | This getter attempts to assign a bound method as an |

1551 | attribute to the given instance. If this is not |

1552 | possible (for example, for some extension classes), |

1553 | it is attempted to find an attribute ``__cached_methods``, |

1554 | and store/retrieve the bound method there. In that |

1555 | way, cached methods can be implemented for extension |

1556 | classes deriving from :class:`~sage.structure.parent.Parent` |

1557 | and :class:`~sage.structure.element.Element`. |

1558 | |

1559 | TESTS: |

1560 | |

1561 | Due to the separate ``__get__`` method, it is possible |

1562 | to define a cached method in one class and use it as |

1563 | an attribute of another class. |

1564 | |

1565 | >>> class Foo:###line 1509:_sage_ >>> class Foo: |

1566 | ... def __init__(self, n): |

1567 | ... self.__n = n |

1568 | ... @cached_method |

1569 | ... def f(self): |

1570 | ... return self.__n**Integer(2) |

1571 | ... |

1572 | >>> class Bar:###line 1516:_sage_ >>> class Bar: |

1573 | ... f = Foo.f |

1574 | ... |

1575 | >>> b1 = Bar()###line 1519:_sage_ >>> b1 = Bar() |

1576 | >>> b2 = Bar()###line 1520:_sage_ >>> b2 = Bar() |

1577 | |

1578 | The :class:`CachedMethod` is replaced by an instance of |

1579 | :class:`CachedMethodCallerNoArgs` that is set as an |

1580 | attribute. Hence, we have:: |

1581 | |

1582 | >>> b1.f is b1.f###line 1526:_sage_ >>> b1.f is b1.f |

1583 | True |

1584 | >>> type(b1.f)###line 1528:_sage_ >>> type(b1.f) |

1585 | <type 'sage.misc.cachefunc.CachedMethodCallerNoArgs'> |

1586 | |

1587 | Any instance of ``Bar`` gets its own instance of |

1588 | :class:`CachedMethodCaller``:: |

1589 | |

1590 | >>> b1.f is b2.f###line 1534:_sage_ >>> b1.f is b2.f |

1591 | False |

1592 | |

1593 | The method caller knows the instance that it belongs |

1594 | to:: |

1595 | |

1596 | >>> Foo.f._instance is None###line 1540:_sage_ >>> Foo.f._instance is None |

1597 | True |

1598 | >>> b1.f._instance is b1###line 1542:_sage_ >>> b1.f._instance is b1 |

1599 | True |

1600 | >>> b2.f._instance is b2###line 1544:_sage_ >>> b2.f._instance is b2 |

1601 | True |

1602 | |

1603 | |

1604 | >>> sig_on_count() |

1605 | 0 |

1606 | """ |

1607 | |

1608 | def example_40(): r""">>> set_random_seed(0L) |

1609 | |

1610 | >>> change_warning_output(sys.stdout) |

1611 | |

1612 | |

1613 | A decorator that creates a cached version of an instance |

1614 | method of a class. |

1615 | |

1616 | NOTE: |

1617 | |

1618 | For proper behavior, the method must be a pure function |

1619 | (no side effects). Arguments to the method must be hashable. |

1620 | |

1621 | EXAMPLES:: |

1622 | |

1623 | >>> class Foo(object):###line 1580:_sage_ >>> class Foo(object): |

1624 | ... @cached_method |

1625 | ... def f(self, t, x=Integer(2)): |

1626 | ... print 'computing' |

1627 | ... return t**x |

1628 | >>> a = Foo()###line 1585:_sage_ >>> a = Foo() |

1629 | |

1630 | The example shows that the actual computation |

1631 | takes place only once, and that the result is |

1632 | identical for equivalent input:: |

1633 | |

1634 | >>> res = a.f(Integer(3), Integer(2)); res###line 1591:_sage_ >>> res = a.f(3, 2); res |

1635 | computing |

1636 | 9 |

1637 | >>> a.f(t = Integer(3), x = Integer(2)) is res###line 1594:_sage_ >>> a.f(t = 3, x = 2) is res |

1638 | True |

1639 | >>> a.f(Integer(3)) is res###line 1596:_sage_ >>> a.f(3) is res |

1640 | True |

1641 | |

1642 | Note, however, that the :class:`CachedMethod` is replaced by a |

1643 | :class:`CachedMethodCaller` or :class:`CachedMethodCallerNoArgs` |

1644 | as soon as it is bound to an instance or class:: |

1645 | |

1646 | >>> P = QQ['a, b, c, d']; (a, b, c, d,) = P._first_ngens(4)###line 1603:_sage_ >>> P.<a,b,c,d> = QQ[] |

1647 | >>> I = P*[a,b]###line 1604:_sage_ >>> I = P*[a,b] |

1648 | >>> type(I.__class__.gens)###line 1605:_sage_ >>> type(I.__class__.gens) |

1649 | <type 'sage.misc.cachefunc.CachedMethodCallerNoArgs'> |

1650 | |

1651 | So, you would hardly ever see an instance of this class alive. |

1652 | |

1653 | >>> sig_on_count() |

1654 | 0 |

1655 | """ |

1656 | |

1657 | def example_41(): r""">>> set_random_seed(0L) |

1658 | |

1659 | >>> change_warning_output(sys.stdout) |

1660 | |

1661 | |

1662 | EXAMPLES:: |

1663 | |

1664 | >>> class Foo:###line 1614:_sage_ >>> class Foo: |

1665 | ... def __init__(self, x): |

1666 | ... self._x = x |

1667 | ... @cached_method |

1668 | ... def f(self,n): |

1669 | ... return self._x**n |

1670 | ... @cached_method |

1671 | ... def f0(self): |

1672 | ... return self._x**Integer(2) |

1673 | ... |

1674 | >>> a = Foo(Integer(2))###line 1624:_sage_ >>> a = Foo(2) |

1675 | >>> a.f(Integer(2))###line 1625:_sage_ >>> a.f(2) |

1676 | 4 |

1677 | >>> a.f0()###line 1627:_sage_ >>> a.f0() |

1678 | 4 |

1679 | |

1680 | The computations in method ``f`` are tried to store in a |

1681 | dictionary assigned to the instance ``a``:: |

1682 | |

1683 | >>> hasattr(a, '_cache__f')###line 1633:_sage_ >>> hasattr(a, '_cache__f') |

1684 | True |

1685 | >>> a._cache__f###line 1635:_sage_ >>> a._cache__f |

1686 | {((2,), ()): 4} |

1687 | |

1688 | As a shortcut, useful to speed up internal computations, |

1689 | the same dictionary is also available as an attribute |

1690 | of the ``CachedMethodCaller``:: |

1691 | |

1692 | >>> type(a.f)###line 1642:_sage_ >>> type(a.f) |

1693 | <type 'sage.misc.cachefunc.CachedMethodCaller'> |

1694 | >>> a.f.cache is a._cache__f###line 1644:_sage_ >>> a.f.cache is a._cache__f |

1695 | True |

1696 | |

1697 | Note that if the instance ``a`` would not accept attribute |

1698 | assignment, the computations would still be cached in |

1699 | ``a.f.cache``, and they would in fact be preserved when |

1700 | pickling. |

1701 | |

1702 | The cached method ``f0`` accepts no arguments, which allows |

1703 | for an improved way of caching: By an attribute of the cached |

1704 | method itsel. This cache is *only* available in that way, i.e., |

1705 | it is not additionally stored as an attribute of ``a``:: |

1706 | |

1707 | >>> type(a.f0)###line 1657:_sage_ >>> type(a.f0) |

1708 | <type 'sage.misc.cachefunc.CachedMethodCallerNoArgs'> |

1709 | >>> a.f0.cache###line 1659:_sage_ >>> a.f0.cache |

1710 | 4 |

1711 | >>> sorted(dir(a))###line 1661:_sage_ >>> sorted(dir(a)) |

1712 | ['__doc__', '__init__', '__module__', '_cache__f', '_x', 'f', 'f0'] |

1713 | |

1714 | |

1715 | >>> sig_on_count() |

1716 | 0 |

1717 | """ |

1718 | |

1719 | def example_42(): r""">>> set_random_seed(0L) |

1720 | |

1721 | >>> change_warning_output(sys.stdout) |

1722 | |

1723 | |

1724 | Call the cached method *without* using the cache. |

1725 | |

1726 | INPUT: |

1727 | |

1728 | - ``inst`` - an instance at which the method is to be called |

1729 | - Further positional or named arguments. |

1730 | |

1731 | EXAMPLES:: |

1732 | |

1733 | >>> class Foo(object):###line 1679:_sage_ >>> class Foo(object): |

1734 | ... def __init__(self, x): |

1735 | ... self._x = x |

1736 | ... @cached_method |

1737 | ... def f(self,n=Integer(2)): |

1738 | ... return self._x**n |

1739 | ... |

1740 | >>> a = Foo(Integer(2))###line 1686:_sage_ >>> a = Foo(2) |

1741 | >>> a.f()###line 1687:_sage_ >>> a.f() |

1742 | 4 |

1743 | |

1744 | Usually, a cached method is indeed cached:: |

1745 | |

1746 | >>> a.f() is a.f()###line 1692:_sage_ >>> a.f() is a.f() |

1747 | True |

1748 | |

1749 | However, when it becomes necessary, one can call it without |

1750 | using the cache. Note that ``a.f`` is an instance of |

1751 | :class:`CachedMethodCaller`. But its |

1752 | :meth:`CachedMethodCaller._instance_call` relies on this |

1753 | method, so, we have an indirect doctest:: |

1754 | |

1755 | >>> a.f._instance_call() is a.f() # indirect doctest###line 1701:_sage_ >>> a.f._instance_call() is a.f() # indirect doctest |

1756 | False |

1757 | >>> a.f._instance_call() == a.f()###line 1703:_sage_ >>> a.f._instance_call() == a.f() |

1758 | True |

1759 | |

1760 | |

1761 | >>> sig_on_count() |

1762 | 0 |

1763 | """ |

1764 | |

1765 | def example_43(): r""">>> set_random_seed(0L) |

1766 | |

1767 | >>> change_warning_output(sys.stdout) |

1768 | |

1769 | |

1770 | Returns the cache dictionary. |

1771 | |

1772 | TESTS:: |

1773 | |

1774 | >>> class Foo:###line 1715:_sage_ >>> class Foo: |

1775 | ... def __init__(self, x): |

1776 | ... self._x = x |

1777 | ... @cached_method |

1778 | ... def f(self,n=Integer(2)): |

1779 | ... return self._x**n |

1780 | ... |

1781 | >>> a = Foo(Integer(2))###line 1722:_sage_ >>> a = Foo(2) |

1782 | >>> a.f()###line 1723:_sage_ >>> a.f() |

1783 | 4 |

1784 | |

1785 | Note that we can not provide a direct test, since ``a.f`` is |

1786 | an instance of :class:`CachedMethodCaller`. But during its |

1787 | initialisation, this method was called in order to provide the |

1788 | cached method caller with its cache, and, if possible, assign |

1789 | it to an attribute of ``a``. So, the following is an indirect |

1790 | doctest:: |

1791 | |

1792 | >>> a.f.get_cache() # indirect doctest###line 1733:_sage_ >>> a.f.get_cache() # indirect doctest |

1793 | {((2,), ()): 4} |

1794 | >>> a._cache__f###line 1735:_sage_ >>> a._cache__f |

1795 | {((2,), ()): 4} |

1796 | |

1797 | |

1798 | >>> sig_on_count() |

1799 | 0 |

1800 | """ |

1801 | |

1802 | def example_44(): r""">>> set_random_seed(0L) |

1803 | |

1804 | >>> change_warning_output(sys.stdout) |

1805 | |

1806 | |

1807 | Get a CachedMethodCaller bound to this specific instance of |

1808 | the class of the cached method. |

1809 | |

1810 | TESTS:: |

1811 | |

1812 | >>> class Foo:###line 1751:_sage_ >>> class Foo: |

1813 | ... @cached_method |

1814 | ... def f(self): |

1815 | ... return Integer(1) |

1816 | ... @cached_method |

1817 | ... def g(self, x,n=Integer(3)): |

1818 | ... return x**n |

1819 | ... |

1820 | >>> a = Foo()###line 1759:_sage_ >>> a = Foo() |

1821 | >>> type(a.f)###line 1760:_sage_ >>> type(a.f) |

1822 | <type 'sage.misc.cachefunc.CachedMethodCallerNoArgs'> |

1823 | >>> type(a.g)###line 1762:_sage_ >>> type(a.g) |

1824 | <type 'sage.misc.cachefunc.CachedMethodCaller'> |

1825 | |

1826 | By trac ticket #8611, it is attempted to set the |

1827 | CachedMethodCaller as an attribute of the instance ``a``, |

1828 | replacing the original cached attribute. Therefore, the |

1829 | ``__get__`` method will be used only once, which saves much |

1830 | time. Hence, we have:: |

1831 | |

1832 | >>> a.f is a.f###line 1771:_sage_ >>> a.f is a.f |

1833 | True |

1834 | >>> a.g is a.g###line 1773:_sage_ >>> a.g is a.g |

1835 | True |

1836 | |

1837 | |

1838 | >>> sig_on_count() |

1839 | 0 |

1840 | """ |

1841 | |

1842 | def example_45(): r""">>> set_random_seed(0L) |

1843 | |

1844 | >>> change_warning_output(sys.stdout) |

1845 | |

1846 | |

1847 | A decorator that creates a cached version of an instance |

1848 | method of a class. |

1849 | |

1850 | In contrast to :class:`CachedMethod`, |

1851 | the cache dictionary is an attribute of the parent of |

1852 | the instance to which the method belongs. |

1853 | |

1854 | ASSUMPTION: |

1855 | |

1856 | This way of caching works only if |

1857 | |

1858 | - the instances *have* a parent, and |

1859 | - the instances are hashable (they are part of the cache key). |

1860 | |

1861 | NOTE: |

1862 | |

1863 | For proper behavior, the method must be a pure function (no side |

1864 | effects). If this decorator is used on a method, it will have |

1865 | identical output on equal elements. This is since the element is |

1866 | part of the hash key. Arguments to the method and the instance |

1867 | it is assigned to must be hashable. |

1868 | |

1869 | Examples can be found at :mod:`~sage.misc.cachefunc`. |

1870 | |

1871 | |

1872 | >>> sig_on_count() |

1873 | 0 |

1874 | """ |

1875 | |

1876 | def example_46(): r""">>> set_random_seed(0L) |

1877 | |

1878 | >>> change_warning_output(sys.stdout) |

1879 | |

1880 | |

1881 | Constructs a new method with cache stored in the parent of the instance. |

1882 | |

1883 | See also ``cached_method`` and ``cached_function``. |

1884 | |

1885 | EXAMPLES:: |

1886 | |

1887 | >>> class MyParent(Parent):###line 1857:_sage_ >>> class MyParent(Parent): |

1888 | ... pass |

1889 | >>> class Foo:###line 1859:_sage_ >>> class Foo: |

1890 | ... def __init__(self, x): |

1891 | ... self._x = x |

1892 | ... _parent = MyParent() |

1893 | ... def parent(self): |

1894 | ... return self._parent |

1895 | ... @cached_in_parent_method #indirect doctest |

1896 | ... def f(self): |

1897 | ... return self._x**Integer(2) |

1898 | ... |

1899 | >>> a = Foo(Integer(2))###line 1869:_sage_ >>> a = Foo(2) |

1900 | >>> a.f()###line 1870:_sage_ >>> a.f() |

1901 | 4 |

1902 | >>> hasattr(a.parent(), '_cache__element_f')###line 1872:_sage_ >>> hasattr(a.parent(), '_cache__element_f') |

1903 | True |

1904 | |

1905 | For speeding up internal computations, this dictionary |

1906 | is also accessible as an attribute of the CachedMethodCaller |

1907 | (by trac ticket #8611):: |

1908 | |

1909 | >>> a.parent()._cache__element_f is a.f.cache###line 1879:_sage_ >>> a.parent()._cache__element_f is a.f.cache |

1910 | True |

1911 | |

1912 | >>> sig_on_count() |

1913 | 0 |

1914 | """ |

1915 | |

1916 | def example_47(): r""">>> set_random_seed(0L) |

1917 | |

1918 | >>> change_warning_output(sys.stdout) |

1919 | |

1920 | |

1921 | Returns the cache dictionary, which is stored in the parent. |

1922 | |

1923 | EXAMPLES:: |

1924 | |

1925 | >>> class MyParent(Parent):###line 1891:_sage_ >>> class MyParent(Parent): |

1926 | ... pass |

1927 | ... |

1928 | >>> class Foo:###line 1894:_sage_ >>> class Foo: |

1929 | ... def __init__(self, x): |

1930 | ... self._x = x |

1931 | ... _parent = MyParent() |

1932 | ... def parent(self): |

1933 | ... return self._parent |

1934 | ... def __eq__(self, other): |

1935 | ... return self._x**Integer(2) == other._x**Integer(2) |

1936 | ... def __hash__(self): |

1937 | ... return hash(self._x**Integer(2)) |

1938 | ... def __repr__(self): |

1939 | ... return 'My %s'%self._x |

1940 | ... @cached_in_parent_method |

1941 | ... def f(self): |

1942 | ... return self._x**Integer(3) |

1943 | ... |

1944 | >>> a = Foo(Integer(2))###line 1910:_sage_ >>> a = Foo(2) |

1945 | >>> a.f()###line 1911:_sage_ >>> a.f() |

1946 | 8 |

1947 | >>> a.f.get_cache() #indirect doctest###line 1913:_sage_ >>> a.f.get_cache() #indirect doctest |

1948 | {(My 2, ((), ())): 8} |

1949 | |

1950 | Since the key for the cache depends on equality of |

1951 | the instances, we obtain *identical* result for |

1952 | *equal* instance - even though in this particular |

1953 | example the result is wrong:: |

1954 | |

1955 | >>> b = Foo(-Integer(2))###line 1921:_sage_ >>> b = Foo(-2) |

1956 | >>> a is not b###line 1922:_sage_ >>> a is not b |

1957 | True |

1958 | >>> a == b###line 1924:_sage_ >>> a == b |

1959 | True |

1960 | >>> b.f() is a.f()###line 1926:_sage_ >>> b.f() is a.f() |

1961 | True |

1962 | |

1963 | Non-equal instances do not share the result of |

1964 | the cached method, but they do share the cache:: |

1965 | |

1966 | >>> c = Foo(Integer(3))###line 1932:_sage_ >>> c = Foo(3) |

1967 | >>> c.f()###line 1933:_sage_ >>> c.f() |

1968 | 27 |

1969 | >>> c.f.get_cache() is a.f.get_cache() #indirect doctest###line 1935:_sage_ >>> c.f.get_cache() is a.f.get_cache() #indirect doctest |

1970 | True |

1971 | |

1972 | Note that the cache is also available as an |

1973 | attribute of the cached method, which speeds |

1974 | up internal computations:: |

1975 | |

1976 | >>> a.f.cache is b.f.get_cache() is c.f._cachedmethod._get_instance_cache(c)###line 1942:_sage_ >>> a.f.cache is b.f.get_cache() is c.f._cachedmethod._get_instance_cache(c) |

1977 | True |

1978 | |

1979 | |

1980 | >>> sig_on_count() |

1981 | 0 |

1982 | """ |

1983 | |

1984 | def example_48(): r""">>> set_random_seed(0L) |

1985 | |

1986 | >>> change_warning_output(sys.stdout) |

1987 | |

1988 | |

1989 | Get a CachedMethodCaller bound to this specific instance of |

1990 | the class of the cached-in-parent method. |

1991 | |

1992 | >>> sig_on_count() |

1993 | 0 |

1994 | """ |

1995 | |

1996 | def example_49(): r""">>> set_random_seed(0L) |

1997 | |

1998 | >>> change_warning_output(sys.stdout) |

1999 | |

2000 | |

2001 | FileCache is a dictionary-like class which stores keys and |

2002 | values on disk. The keys take the form of a tuple (A,K) |

2003 | |

2004 | - A is a tuple of objects t where each t is an exact |

2005 | object which is uniquely identified by a short string. |

2006 | |

2007 | - K is a tuple of tuples (s,v) where s is a valid |

2008 | variable name and v is an exact object which is uniquely |

2009 | identified by a short string with letters [a-zA-Z0-9-._] |

2010 | |

2011 | The primary use case is the DiskCachedFunction. If |

2012 | ``memory_cache == True``, we maintain a cache of objects seen |

2013 | during this session in memory -- but we don't load them from |

2014 | disk until necessary. The keys and values are stored in a |

2015 | pair of files: |

2016 | |

2017 | - ``prefix-argstring.key.sobj`` contains the ``key`` only, |

2018 | - ``prefix-argstring.sobj`` contains the tuple ``(key,val)`` |

2019 | |

2020 | where ``self[key] == val``. |

2021 | |

2022 | NOTE: |

2023 | |

2024 | We assume that each FileCache lives in its own directory. |

2025 | Use **extreme** caution if you wish to break that assumption. |

2026 | |

2027 | >>> sig_on_count() |

2028 | 0 |

2029 | """ |

2030 | |

2031 | def example_50(): r""">>> set_random_seed(0L) |

2032 | |

2033 | >>> change_warning_output(sys.stdout) |

2034 | |

2035 | |

2036 | EXAMPLES:: |

2037 | |

2038 | >>> from sage.misc.cachefunc import FileCache###line 2005:_sage_ >>> from sage.misc.cachefunc import FileCache |

2039 | >>> dir = tmp_dir()###line 2006:_sage_ >>> dir = tmp_dir() |

2040 | >>> FC = FileCache(dir, memory_cache = True)###line 2007:_sage_ >>> FC = FileCache(dir, memory_cache = True) |

2041 | >>> FC[((),())] = Integer(1)###line 2008:_sage_ >>> FC[((),())] = 1 |

2042 | >>> FC[((Integer(1),Integer(2)),())] = Integer(2)###line 2009:_sage_ >>> FC[((1,2),())] = 2 |

2043 | >>> FC[((),())]###line 2010:_sage_ >>> FC[((),())] |

2044 | 1 |

2045 | |

2046 | >>> sig_on_count() |

2047 | 0 |

2048 | """ |

2049 | |

2050 | def example_51(): r""">>> set_random_seed(0L) |

2051 | |

2052 | >>> change_warning_output(sys.stdout) |

2053 | |

2054 | |

2055 | Returns the list of files corresponding to self. |

2056 | |

2057 | EXAMPLES:: |

2058 | |

2059 | >>> from sage.misc.cachefunc import FileCache###line 2032:_sage_ >>> from sage.misc.cachefunc import FileCache |

2060 | >>> dir = tmp_dir()###line 2033:_sage_ >>> dir = tmp_dir() |

2061 | >>> FC = FileCache(dir, memory_cache = True, prefix='t')###line 2034:_sage_ >>> FC = FileCache(dir, memory_cache = True, prefix='t') |

2062 | >>> FC[((),())] = Integer(1)###line 2035:_sage_ >>> FC[((),())] = 1 |

2063 | >>> FC[((Integer(1),Integer(2)),())] = Integer(2)###line 2036:_sage_ >>> FC[((1,2),())] = 2 |

2064 | >>> FC[((Integer(1),),(('a',Integer(1)),))] = Integer(3)###line 2037:_sage_ >>> FC[((1,),(('a',1),))] = 3 |

2065 | >>> for f in sorted(FC.file_list()): print f[len(dir):]###line 2038:_sage_ >>> for f in sorted(FC.file_list()): print f[len(dir):] |

2066 | /t-.key.sobj |

2067 | /t-.sobj |

2068 | /t-1_2.key.sobj |

2069 | /t-1_2.sobj |

2070 | /t-a-1.1.key.sobj |

2071 | /t-a-1.1.sobj |

2072 | |

2073 | >>> sig_on_count() |

2074 | 0 |

2075 | """ |

2076 | |

2077 | def example_52(): r""">>> set_random_seed(0L) |

2078 | |

2079 | >>> change_warning_output(sys.stdout) |

2080 | |

2081 | |

2082 | Returns a list of tuples ``(k,v)`` where ``self[k] = v``. |

2083 | |

2084 | EXAMPLES:: |

2085 | |

2086 | >>> from sage.misc.cachefunc import FileCache###line 2061:_sage_ >>> from sage.misc.cachefunc import FileCache |

2087 | >>> dir = tmp_dir()###line 2062:_sage_ >>> dir = tmp_dir() |

2088 | >>> FC = FileCache(dir, memory_cache = False)###line 2063:_sage_ >>> FC = FileCache(dir, memory_cache = False) |

2089 | >>> FC[((),())] = Integer(1)###line 2064:_sage_ >>> FC[((),())] = 1 |

2090 | >>> FC[((Integer(1),Integer(2)),())] = Integer(2)###line 2065:_sage_ >>> FC[((1,2),())] = 2 |

2091 | >>> FC[((Integer(1),),(('a',Integer(1)),))] = Integer(3)###line 2066:_sage_ >>> FC[((1,),(('a',1),))] = 3 |

2092 | >>> I = FC.items()###line 2067:_sage_ >>> I = FC.items() |

2093 | >>> I.sort(); print I###line 2068:_sage_ >>> I.sort(); print I |

2094 | [(((), ()), 1), (((1,), (('a', 1),)), 3), (((1, 2), ()), 2)] |

2095 | |

2096 | >>> sig_on_count() |

2097 | 0 |

2098 | """ |

2099 | |

2100 | def example_53(): r""">>> set_random_seed(0L) |

2101 | |

2102 | >>> change_warning_output(sys.stdout) |

2103 | |

2104 | |

2105 | Returns a list of values that are stored in ``self``. |

2106 | |

2107 | EXAMPLES:: |

2108 | |

2109 | >>> from sage.misc.cachefunc import FileCache###line 2079:_sage_ >>> from sage.misc.cachefunc import FileCache |

2110 | >>> dir = tmp_dir()###line 2080:_sage_ >>> dir = tmp_dir() |

2111 | >>> FC = FileCache(dir, memory_cache = False)###line 2081:_sage_ >>> FC = FileCache(dir, memory_cache = False) |

2112 | >>> FC[((),())] = Integer(1)###line 2082:_sage_ >>> FC[((),())] = 1 |

2113 | >>> FC[((Integer(1),Integer(2)),())] = Integer(2)###line 2083:_sage_ >>> FC[((1,2),())] = 2 |

2114 | >>> FC[((Integer(1),),(('a',Integer(1)),))] = Integer(3)###line 2084:_sage_ >>> FC[((1,),(('a',1),))] = 3 |

2115 | >>> FC[((),(('a',Integer(1)),))] = Integer(4)###line 2085:_sage_ >>> FC[((),(('a',1),))] = 4 |

2116 | >>> v = FC.values()###line 2086:_sage_ >>> v = FC.values() |

2117 | >>> v.sort(); print v###line 2087:_sage_ >>> v.sort(); print v |

2118 | [1, 2, 3, 4] |

2119 | |

2120 | >>> sig_on_count() |

2121 | 0 |

2122 | """ |

2123 | |

2124 | def example_54(): r""">>> set_random_seed(0L) |

2125 | |

2126 | >>> change_warning_output(sys.stdout) |

2127 | |

2128 | |

2129 | Returns a list of keys of ``self``. |

2130 | |

2131 | EXAMPLES:: |

2132 | |

2133 | >>> from sage.misc.cachefunc import FileCache###line 2098:_sage_ >>> from sage.misc.cachefunc import FileCache |

2134 | >>> dir = tmp_dir()###line 2099:_sage_ >>> dir = tmp_dir() |

2135 | >>> FC = FileCache(dir, memory_cache = False)###line 2100:_sage_ >>> FC = FileCache(dir, memory_cache = False) |

2136 | >>> FC[((),())] = Integer(1)###line 2101:_sage_ >>> FC[((),())] = 1 |

2137 | >>> FC[((Integer(1),Integer(2)),())] = Integer(2)###line 2102:_sage_ >>> FC[((1,2),())] = 2 |

2138 | >>> FC[((Integer(1),),(('a',Integer(1)),))] = Integer(3)###line 2103:_sage_ >>> FC[((1,),(('a',1),))] = 3 |

2139 | >>> for k in sorted(FC): print k###line 2104:_sage_ >>> for k in sorted(FC): print k |

2140 | ((), ()) |

2141 | ((1,), (('a', 1),)) |

2142 | ((1, 2), ()) |

2143 | |

2144 | >>> sig_on_count() |

2145 | 0 |

2146 | """ |

2147 | |

2148 | def example_55(): r""">>> set_random_seed(0L) |

2149 | |

2150 | >>> change_warning_output(sys.stdout) |

2151 | |

2152 | |

2153 | Returns a list of keys ``k`` where ``self[k]`` is defined. |

2154 | |

2155 | EXAMPLES:: |

2156 | |

2157 | >>> from sage.misc.cachefunc import FileCache###line 2117:_sage_ >>> from sage.misc.cachefunc import FileCache |

2158 | >>> dir = tmp_dir()###line 2118:_sage_ >>> dir = tmp_dir() |

2159 | >>> FC = FileCache(dir, memory_cache = False)###line 2119:_sage_ >>> FC = FileCache(dir, memory_cache = False) |

2160 | >>> FC[((),())] = Integer(1)###line 2120:_sage_ >>> FC[((),())] = 1 |

2161 | >>> FC[((Integer(1),Integer(2)),())] = Integer(2)###line 2121:_sage_ >>> FC[((1,2),())] = 2 |

2162 | >>> FC[((Integer(1),),(('a',Integer(1)),))] = Integer(3)###line 2122:_sage_ >>> FC[((1,),(('a',1),))] = 3 |

2163 | >>> K = FC.keys()###line 2123:_sage_ >>> K = FC.keys() |

2164 | >>> K.sort(); print K###line 2124:_sage_ >>> K.sort(); print K |

2165 | [((), ()), ((1,), (('a', 1),)), ((1, 2), ())] |

2166 | |

2167 | >>> sig_on_count() |

2168 | 0 |

2169 | """ |

2170 | |

2171 | def example_56(): r""">>> set_random_seed(0L) |

2172 | |

2173 | >>> change_warning_output(sys.stdout) |

2174 | |

2175 | |

2176 | Computes the filename associated with a certain key. |

2177 | |

2178 | EXAMPLES:: |

2179 | |

2180 | >>> from sage.misc.cachefunc import FileCache###line 2140:_sage_ >>> from sage.misc.cachefunc import FileCache |

2181 | >>> dir = tmp_dir() + '/'###line 2141:_sage_ >>> dir = tmp_dir() + '/' |

2182 | >>> FC = FileCache(dir, memory_cache = False, prefix='foo')###line 2142:_sage_ >>> FC = FileCache(dir, memory_cache = False, prefix='foo') |

2183 | >>> N = FC._filename(((Integer(1),Integer(2)), (('a',Integer(1)),('b',Integer(2)))))###line 2143:_sage_ >>> N = FC._filename(((1,2), (('a',1),('b',2)))) |

2184 | >>> print N[len(dir):]###line 2144:_sage_ >>> print N[len(dir):] |

2185 | foo-a-1_b-2.1_2 |

2186 | >>> N = FC._filename(((), (('a',Integer(1)),('b',Integer(2)))))###line 2146:_sage_ >>> N = FC._filename(((), (('a',1),('b',2)))) |

2187 | >>> print N[len(dir):]###line 2147:_sage_ >>> print N[len(dir):] |

2188 | foo-a-1_b-2 |

2189 | >>> N = FC._filename(((Integer(1),Integer(2)), ()))###line 2149:_sage_ >>> N = FC._filename(((1,2), ())) |

2190 | >>> print N[len(dir):]###line 2150:_sage_ >>> print N[len(dir):] |

2191 | foo-1_2 |

2192 | |

2193 | >>> sig_on_count() |

2194 | 0 |

2195 | """ |

2196 | |

2197 | def example_57(): r""">>> set_random_seed(0L) |

2198 | |

2199 | >>> change_warning_output(sys.stdout) |

2200 | |

2201 | |

2202 | Returns ``True`` if ``self[key]`` is defined and False otherwise. |

2203 | |

2204 | EXAMPLES:: |

2205 | |

2206 | >>> from sage.misc.cachefunc import FileCache###line 2168:_sage_ >>> from sage.misc.cachefunc import FileCache |

2207 | >>> dir = tmp_dir() + '/'###line 2169:_sage_ >>> dir = tmp_dir() + '/' |

2208 | >>> FC = FileCache(dir, memory_cache = False, prefix='foo')###line 2170:_sage_ >>> FC = FileCache(dir, memory_cache = False, prefix='foo') |

2209 | >>> k = ((),(('a',Integer(1)),))###line 2171:_sage_ >>> k = ((),(('a',1),)) |

2210 | >>> FC[k] = True###line 2172:_sage_ >>> FC[k] = True |

2211 | >>> FC.has_key(k)###line 2173:_sage_ >>> FC.has_key(k) |

2212 | True |

2213 | >>> FC.has_key(((),()))###line 2175:_sage_ >>> FC.has_key(((),())) |

2214 | False |

2215 | |

2216 | >>> sig_on_count() |

2217 | 0 |

2218 | """ |

2219 | |

2220 | def example_58(): r""">>> set_random_seed(0L) |

2221 | |

2222 | >>> change_warning_output(sys.stdout) |

2223 | |

2224 | |

2225 | Returns the value set by ``self[key] = val``, in this session |

2226 | or a previous one. |

2227 | |

2228 | EXAMPLES:: |

2229 | |

2230 | >>> from sage.misc.cachefunc import FileCache###line 2187:_sage_ >>> from sage.misc.cachefunc import FileCache |

2231 | >>> dir = tmp_dir() + '/'###line 2188:_sage_ >>> dir = tmp_dir() + '/' |

2232 | >>> FC1 = FileCache(dir, memory_cache = False, prefix='foo')###line 2189:_sage_ >>> FC1 = FileCache(dir, memory_cache = False, prefix='foo') |

2233 | >>> FC2 = FileCache(dir, memory_cache = False, prefix='foo')###line 2190:_sage_ >>> FC2 = FileCache(dir, memory_cache = False, prefix='foo') |

2234 | >>> k = ((),(('a',Integer(1)),))###line 2191:_sage_ >>> k = ((),(('a',1),)) |

2235 | >>> t = randint(Integer(0), Integer(1000))###line 2192:_sage_ >>> t = randint(0, 1000) |

2236 | >>> FC1[k] = t###line 2193:_sage_ >>> FC1[k] = t |

2237 | >>> FC2[k] == FC1[k] == t###line 2194:_sage_ >>> FC2[k] == FC1[k] == t |

2238 | True |

2239 | >>> FC1[(Integer(1),Integer(2)),(('a',Integer(4)),('b',Integer(2)))]###line 2196:_sage_ >>> FC1[(1,2),(('a',4),('b',2))] |

2240 | Traceback (most recent call last): |

2241 | ... |

2242 | KeyError: ((1, 2), (('a', 4), ('b', 2))) |

2243 | |

2244 | |

2245 | >>> sig_on_count() |

2246 | 0 |

2247 | """ |

2248 | |

2249 | def example_59(): r""">>> set_random_seed(0L) |

2250 | |

2251 | >>> change_warning_output(sys.stdout) |

2252 | |

2253 | |

2254 | Sets ``self[key] = value`` and stores both key and value on |

2255 | disk. |

2256 | |

2257 | EXAMPLES:: |

2258 | |

2259 | >>> from sage.misc.cachefunc import FileCache###line 2228:_sage_ >>> from sage.misc.cachefunc import FileCache |

2260 | >>> dir = tmp_dir() + '/'###line 2229:_sage_ >>> dir = tmp_dir() + '/' |

2261 | >>> FC1 = FileCache(dir, memory_cache = False, prefix='foo')###line 2230:_sage_ >>> FC1 = FileCache(dir, memory_cache = False, prefix='foo') |

2262 | >>> FC2 = FileCache(dir, memory_cache = False, prefix='foo')###line 2231:_sage_ >>> FC2 = FileCache(dir, memory_cache = False, prefix='foo') |

2263 | >>> k = ((),(('a',Integer(1)),))###line 2232:_sage_ >>> k = ((),(('a',1),)) |

2264 | >>> t = randint(Integer(0), Integer(1000))###line 2233:_sage_ >>> t = randint(0, 1000) |

2265 | >>> FC1[k] = t###line 2234:_sage_ >>> FC1[k] = t |

2266 | >>> FC2[k] == t###line 2235:_sage_ >>> FC2[k] == t |

2267 | True |

2268 | >>> FC1[k] = Integer(2000)###line 2237:_sage_ >>> FC1[k] = 2000 |

2269 | >>> FC2[k]!= t###line 2238:_sage_ >>> FC2[k]!= t |

2270 | True |

2271 | |

2272 | >>> sig_on_count() |

2273 | 0 |

2274 | """ |

2275 | |

2276 | def example_60(): r""">>> set_random_seed(0L) |

2277 | |

2278 | >>> change_warning_output(sys.stdout) |

2279 | |

2280 | |

2281 | Delete the key,value pair from self and unlink the associated |

2282 | files from the file cache. |

2283 | |

2284 | EXAMPLES:: |

2285 | |

2286 | >>> from sage.misc.cachefunc import FileCache###line 2257:_sage_ >>> from sage.misc.cachefunc import FileCache |

2287 | >>> dir = tmp_dir() + '/'###line 2258:_sage_ >>> dir = tmp_dir() + '/' |

2288 | >>> FC1 = FileCache(dir, memory_cache = False, prefix='foo')###line 2259:_sage_ >>> FC1 = FileCache(dir, memory_cache = False, prefix='foo') |

2289 | >>> FC2 = FileCache(dir, memory_cache = False, prefix='foo')###line 2260:_sage_ >>> FC2 = FileCache(dir, memory_cache = False, prefix='foo') |

2290 | >>> k = ((),(('a',Integer(1)),))###line 2261:_sage_ >>> k = ((),(('a',1),)) |

2291 | >>> t = randint(Integer(0), Integer(1000))###line 2262:_sage_ >>> t = randint(0, 1000) |

2292 | >>> FC1[k] = t###line 2263:_sage_ >>> FC1[k] = t |

2293 | >>> del FC2[k]###line 2264:_sage_ >>> del FC2[k] |

2294 | >>> FC1.has_key(k)###line 2265:_sage_ >>> FC1.has_key(k) |

2295 | False |

2296 | |

2297 | >>> sig_on_count() |

2298 | 0 |

2299 | """ |

2300 | |

2301 | def example_61(): r""">>> set_random_seed(0L) |

2302 | |

2303 | >>> change_warning_output(sys.stdout) |

2304 | |

2305 | |

2306 | Works similar to CachedFunction, but instead, we keep the |

2307 | cache on disk (optionally, we keep it in memory too). |

2308 | |

2309 | EXAMPLES:: |

2310 | |

2311 | >>> from sage.misc.cachefunc import DiskCachedFunction###line 2285:_sage_ >>> from sage.misc.cachefunc import DiskCachedFunction |

2312 | >>> dir = tmp_dir()###line 2286:_sage_ >>> dir = tmp_dir() |

2313 | >>> factor = DiskCachedFunction(factor, dir, memory_cache=True)###line 2287:_sage_ >>> factor = DiskCachedFunction(factor, dir, memory_cache=True) |

2314 | >>> f = factor(Integer(2775)); f###line 2288:_sage_ >>> f = factor(2775); f |

2315 | 3 * 5^2 * 37 |

2316 | >>> f is factor(Integer(2775))###line 2290:_sage_ >>> f is factor(2775) |

2317 | True |

2318 | |

2319 | >>> sig_on_count() |

2320 | 0 |

2321 | """ |

2322 | |

2323 | def example_62(): r""">>> set_random_seed(0L) |

2324 | |

2325 | >>> change_warning_output(sys.stdout) |

2326 | |

2327 | |

2328 | EXAMPLES:: |

2329 | |

2330 | >>> from sage.misc.cachefunc import DiskCachedFunction###line 2297:_sage_ >>> from sage.misc.cachefunc import DiskCachedFunction |

2331 | >>> def foo(x): sleep(x)###line 2298:_sage_ >>> def foo(x): sleep(x) |

2332 | >>> dir = tmp_dir()###line 2299:_sage_ >>> dir = tmp_dir() |

2333 | >>> bar = DiskCachedFunction(foo, dir, memory_cache = False)###line 2300:_sage_ >>> bar = DiskCachedFunction(foo, dir, memory_cache = False) |

2334 | >>> w = walltime()###line 2301:_sage_ >>> w = walltime() |

2335 | >>> for i in range(Integer(10)): bar(Integer(1))###line 2302:_sage_ >>> for i in range(10): bar(1) |

2336 | >>> walltime(w) < Integer(2)###line 2303:_sage_ >>> walltime(w) < 2 |

2337 | True |

2338 | |

2339 | >>> sig_on_count() |

2340 | 0 |

2341 | """ |

2342 | |

2343 | def example_63(): r""">>> set_random_seed(0L) |

2344 | |

2345 | >>> change_warning_output(sys.stdout) |

2346 | |

2347 | |

2348 | Decorator for :class:`DiskCachedFunction`. |

2349 | |

2350 | EXAMPLES:: |

2351 | |

2352 | >>> dir = tmp_dir()###line 2317:_sage_ >>> dir = tmp_dir() |

2353 | >>> @disk_cached_function(dir)###line 2318:_sage_ >>> @disk_cached_function(dir) |

2354 | ... def foo(x): return next_prime(Integer(2)**x)%x |

2355 | >>> x = foo(Integer(200));x###line 2320:_sage_ >>> x = foo(200);x |

2356 | 11 |

2357 | >>> @disk_cached_function(dir)###line 2322:_sage_ >>> @disk_cached_function(dir) |

2358 | ... def foo(x): return Integer(1)/x |

2359 | >>> foo(Integer(200))###line 2324:_sage_ >>> foo(200) |

2360 | 11 |

2361 | >>> foo.clear_cache()###line 2326:_sage_ >>> foo.clear_cache() |

2362 | >>> foo(Integer(200))###line 2327:_sage_ >>> foo(200) |

2363 | 1/200 |

2364 | |

2365 | >>> sig_on_count() |

2366 | 0 |

2367 | """ |

2368 | |

2369 | def example_64(): r""">>> set_random_seed(0L) |

2370 | |

2371 | >>> change_warning_output(sys.stdout) |

2372 | |

2373 | |

2374 | EXAMPLES:: |

2375 | |

2376 | >>> dir = tmp_dir()###line 2334:_sage_ >>> dir = tmp_dir() |

2377 | >>> @disk_cached_function(dir, memory_cache=True)###line 2335:_sage_ >>> @disk_cached_function(dir, memory_cache=True) |

2378 | ... def foo(x): return next_prime(Integer(2)**x) |

2379 | >>> x = foo(Integer(200))###line 2337:_sage_ >>> x = foo(200) |

2380 | >>> x is foo(Integer(200))###line 2338:_sage_ >>> x is foo(200) |

2381 | True |

2382 | >>> @disk_cached_function(dir, memory_cache=False)###line 2340:_sage_ >>> @disk_cached_function(dir, memory_cache=False) |

2383 | ... def foo(x): return next_prime(Integer(2)**x) |

2384 | >>> x is foo(Integer(200))###line 2342:_sage_ >>> x is foo(200) |

2385 | False |

2386 | |

2387 | >>> sig_on_count() |

2388 | 0 |

2389 | """ |

2390 | |

2391 | def example_65(): r""">>> set_random_seed(0L) |

2392 | |

2393 | >>> change_warning_output(sys.stdout) |

2394 | |

2395 | |

2396 | EXAMPLES:: |

2397 | |

2398 | >>> dir = tmp_dir()###line 2352:_sage_ >>> dir = tmp_dir() |

2399 | >>> @disk_cached_function(dir)###line 2353:_sage_ >>> @disk_cached_function(dir) |

2400 | ... def foo(x): return ModularSymbols(x) |

2401 | >>> foo(Integer(389))###line 2355:_sage_ >>> foo(389) |

2402 | Modular Symbols space of dimension 65 for Gamma_0(389) of weight 2 with sign 0 over Rational Field |

2403 | |

2404 | >>> sig_on_count() |

2405 | 0 |

2406 | """ |

2407 | |

2408 | def example_66(): r""">>> set_random_seed(0L) |

2409 | |

2410 | >>> change_warning_output(sys.stdout) |

2411 | |

2412 | |

2413 | This class implements an appropriate ``__getstate__`` method that |

2414 | clears the cache of the methods (see @cached_method) before |

2415 | passing them on to the caller, typically the pickle and copy modules. |

2416 | |

2417 | The implemented ``__getstate__`` method calls the ``__getstate__`` |

2418 | methods of classes later in the method resolution |

2419 | order. Therefore, classes which want this behaviour should inherit |

2420 | first from this one. |

2421 | |

2422 | EXAMPLE: |

2423 | |

2424 | In the following example, we create a Python class that inherits |

2425 | from multivariate polynomial ideals, but does not pickle cached |

2426 | values. We provide the definition in Cython, however, since |

2427 | interactive Cython definitions provide introspection by trac |

2428 | ticket #9976, whereas Python definitions don't. |

2429 | :: |

2430 | |

2431 | >>> P = QQ['a, b, c, d']; (a, b, c, d,) = P._first_ngens(4)###line 2380:_sage_ >>> P.<a,b,c,d> = QQ[] |

2432 | >>> I = P*[a,b]###line 2381:_sage_ >>> I = P*[a,b] |

2433 | >>> classdef = ['from sage.misc.cachefunc import ClearCacheOnPickle',###line 2382:_sage_ >>> classdef = ['from sage.misc.cachefunc import ClearCacheOnPickle', |

2434 | ... 'from sage.all import QQ', |

2435 | ... 'P = QQ["a","b","c","d"]; I = P*[P.gen(0),P.gen(1)]', |

2436 | ... 'class MyClass(ClearCacheOnPickle,I.__class__):', |

2437 | ... ' def __init__(self,ring,gens):', |

2438 | ... ' I.__class__.__init__(self,ring,gens)', |

2439 | ... ' def __getnewargs__(self):', |

2440 | ... ' return (self._Ideal_generic__ring,self._Ideal_generic__gens)'] |

2441 | >>> cython('\n'.join(classdef))###line 2390:_sage_ >>> cython('\n'.join(classdef)) |

2442 | |

2443 | We destroy the cache of two methods of ``I`` on purpose |

2444 | (demonstrating that the two different implementations of cached |

2445 | methods are correctly dealt with). Pickling ``I`` preserves the |

2446 | cache:: |

2447 | |

2448 | >>> I.gens.set_cache('bar')###line 2397:_sage_ >>> I.gens.set_cache('bar') |

2449 | >>> I.groebner_basis.set_cache('foo',algorithm='singular')###line 2398:_sage_ >>> I.groebner_basis.set_cache('foo',algorithm='singular') |

2450 | >>> J = loads(dumps(I))###line 2399:_sage_ >>> J = loads(dumps(I)) |

2451 | >>> J.gens()###line 2400:_sage_ >>> J.gens() |

2452 | 'bar' |

2453 | >>> J.groebner_basis(algorithm='singular')###line 2402:_sage_ >>> J.groebner_basis(algorithm='singular') |

2454 | 'foo' |

2455 | |

2456 | However, if we have an ideal that additionally descends from |

2457 | :class:`ClearCacheOnPickle`, the carefully corrupted cache is not |

2458 | pickled:: |

2459 | |

2460 | >>> A = MyClass(P,[a,b])###line 2409:_sage_ >>> A = MyClass(P,[a,b]) |

2461 | >>> A###line 2410:_sage_ >>> A |

2462 | Ideal (a, b) of Multivariate Polynomial Ring in a, b, c, d over Rational Field |

2463 | >>> A.gens.set_cache('foo')###line 2412:_sage_ >>> A.gens.set_cache('foo') |

2464 | >>> A.groebner_basis.set_cache('bar',algorithm='singular')###line 2413:_sage_ >>> A.groebner_basis.set_cache('bar',algorithm='singular') |

2465 | >>> A.gens()###line 2414:_sage_ >>> A.gens() |

2466 | 'foo' |

2467 | >>> A.groebner_basis(algorithm='singular')###line 2416:_sage_ >>> A.groebner_basis(algorithm='singular') |

2468 | 'bar' |

2469 | >>> B = loads(dumps(A))###line 2418:_sage_ >>> B = loads(dumps(A)) |

2470 | >>> B.gens()###line 2419:_sage_ >>> B.gens() |

2471 | [a, b] |

2472 | >>> B.groebner_basis(algorithm='singular')###line 2421:_sage_ >>> B.groebner_basis(algorithm='singular') |

2473 | [a, b] |

2474 | >>> A.gens()###line 2423:_sage_ >>> A.gens() |

2475 | 'foo' |

2476 | |

2477 | |

2478 | >>> sig_on_count() |

2479 | 0 |

2480 | """ |

2481 | |

2482 | def example_67(): r""">>> set_random_seed(0L) |

2483 | |

2484 | >>> change_warning_output(sys.stdout) |

2485 | |

2486 | |

2487 | The idea is to remove that might provide a cache to some cached method |

2488 | from the return value of the ``__getstate__`` method. |

2489 | |

2490 | EXAMPLE: |

2491 | |

2492 | In the following example, we create a Python class that |

2493 | inherits from multivariate polynomial ideals, but clears the |

2494 | cache as well. |

2495 | |

2496 | >>> P = QQ['a, b, c, d']; (a, b, c, d,) = P._first_ngens(4)###line 2438:_sage_ >>> P.<a,b,c,d> = QQ[] |

2497 | >>> I = P*[a,b]###line 2439:_sage_ >>> I = P*[a,b] |

2498 | |

2499 | We destroy the cache of two methods if ``I`` on purpose |

2500 | (demonstrating that the two different implementations of cached |

2501 | methods are correctly dealt with). Pickling ``I`` preserves the |

2502 | cache:: |

2503 | |

2504 | >>> I.gens.set_cache('bar')###line 2446:_sage_ >>> I.gens.set_cache('bar') |

2505 | >>> I.groebner_basis.set_cache('foo',algorithm='singular')###line 2447:_sage_ >>> I.groebner_basis.set_cache('foo',algorithm='singular') |

2506 | >>> J = loads(dumps(I))###line 2448:_sage_ >>> J = loads(dumps(I)) |

2507 | >>> J.gens()###line 2449:_sage_ >>> J.gens() |

2508 | 'bar' |

2509 | >>> J.groebner_basis(algorithm='singular')###line 2451:_sage_ >>> J.groebner_basis(algorithm='singular') |

2510 | 'foo' |

2511 | |

2512 | However, if we do the same with a class that additionally |

2513 | descends from :class:`ClearCacheOnPickle`, the cache is not |

2514 | pickled. We provide the definition in Cython, however, since |

2515 | interactive Cython definitions provide introspection by trac |

2516 | ticket #9976, whereas Python definitions don't. |

2517 | :: |

2518 | |

2519 | >>> classdef = ['from sage.misc.cachefunc import ClearCacheOnPickle',###line 2461:_sage_ >>> classdef = ['from sage.misc.cachefunc import ClearCacheOnPickle', |

2520 | ... 'from sage.all import QQ', |

2521 | ... 'from sage.rings.polynomial.multi_polynomial_ideal import MPolynomialIdeal', |

2522 | ... 'class MyClass(ClearCacheOnPickle,MPolynomialIdeal):', |

2523 | ... ' def __init__(self,ring,gens):', |

2524 | ... ' MPolynomialIdeal.__init__(self,ring,gens)', |

2525 | ... ' def __getnewargs__(self):', |

2526 | ... ' return (self._Ideal_generic__ring,self._Ideal_generic__gens)'] |

2527 | >>> cython('\n'.join(classdef))###line 2469:_sage_ >>> cython('\n'.join(classdef)) |

2528 | >>> A = MyClass(P,[a,b])###line 2470:_sage_ >>> A = MyClass(P,[a,b]) |

2529 | >>> A###line 2471:_sage_ >>> A |

2530 | Ideal (a, b) of Multivariate Polynomial Ring in a, b, c, d over Rational Field |

2531 | >>> A.gens.set_cache('foo')###line 2473:_sage_ >>> A.gens.set_cache('foo') |

2532 | >>> A.groebner_basis.set_cache('bar',algorithm='singular')###line 2474:_sage_ >>> A.groebner_basis.set_cache('bar',algorithm='singular') |

2533 | >>> A.gens()###line 2475:_sage_ >>> A.gens() |

2534 | 'foo' |

2535 | >>> A.groebner_basis(algorithm='singular')###line 2477:_sage_ >>> A.groebner_basis(algorithm='singular') |

2536 | 'bar' |

2537 | >>> B = loads(dumps(A))###line 2479:_sage_ >>> B = loads(dumps(A)) |

2538 | >>> B.gens()###line 2480:_sage_ >>> B.gens() |

2539 | [a, b] |

2540 | >>> B.groebner_basis(algorithm='singular')###line 2482:_sage_ >>> B.groebner_basis(algorithm='singular') |

2541 | [a, b] |

2542 | >>> A.gens()###line 2484:_sage_ >>> A.gens() |

2543 | 'foo' |

2544 | |

2545 | And here is why the example works:: |

2546 | |

2547 | >>> ST = I.__getstate__(); ST[Integer(0)],sorted(ST[Integer(1)].items())###line 2489:_sage_ >>> ST = I.__getstate__(); ST[0],sorted(ST[1].items()) |

2548 | (Monoid of ideals of Multivariate Polynomial Ring in a, b, c, d over Rational Field, [('_Ideal_generic__gens', (a, b)), ('_Ideal_generic__ring', Multivariate Polynomial Ring in a, b, c, d over Rational Field), ('_cache__groebner_basis', {(('singular', None, None, False), ()): 'foo'}), ('gens', Cached version of <function gens at 0x...>), ('groebner_basis', Cached version of <function groebner_basis at 0x...>)]) |

2549 | >>> ST = A.__getstate__(); ST[Integer(0)],sorted(ST[Integer(1)].items())###line 2491:_sage_ >>> ST = A.__getstate__(); ST[0],sorted(ST[1].items()) |

2550 | (Monoid of ideals of Multivariate Polynomial Ring in a, b, c, d over Rational Field, [('_Ideal_generic__gens', (a, b)), ('_Ideal_generic__ring', Multivariate Polynomial Ring in a, b, c, d over Rational Field)]) |

2551 | |

2552 | |

2553 | >>> sig_on_count() |

2554 | 0 |

2555 | """ |

2556 | |

2557 | |

2558 | if __name__ == '__main__': |

2559 | verbose = False |

2560 | do_timeit = False |

2561 | output_filename = '/scratch/sking/sage-5.4.beta0/devel/sage-main/sage/misc/cachefunc.pyx.timeit.sobj' |

2562 | |

2563 | import sys |

2564 | sys.path = sys.path + ['/scratch/sking/sage-5.4.beta0/local/bin'] |

2565 | import sagedoctest |

2566 | |

2567 | # execfile('/scratch/sking/sage-5.4.beta0/devel/sage-main/sage/misc/cachefunc.pyx') |

2568 | m = sys.modules[__name__] |

2569 | m.__file__ = '/scratch/sking/sage-5.4.beta0/devel/sage-main/sage/misc/cachefunc.pyx' |

2570 | |

2571 | try: |

2572 | |

2573 | # configure special sage doc test runner |

2574 | runner = sagedoctest.SageDocTestRunner(checker=None, verbose=verbose, optionflags=0) |

2575 | runner._collect_timeit_stats = do_timeit |

2576 | runner._reset_random_seed = True |

2577 | |

2578 | runner = sagedoctest.testmod_returning_runner(m, |

2579 | # filename='/scratch/sking/sage-5.4.beta0/devel/sage-main/sage/misc/cachefunc.pyx', |

2580 | verbose=verbose, |

2581 | globs=globals(), |

2582 | runner=runner) |

2583 | runner.save_timeit_stats_to_file_named(output_filename) |

2584 | except: |

2585 | quit_sage(verbose=False) |

2586 | import traceback |

2587 | traceback.print_exc(file=sys.stdout) |

2588 | sys.exit(255) |

2589 | quit_sage(verbose=False) |

2590 | if runner.failures > 254: |

2591 | sys.exit(254) |

2592 | sys.exit(runner.failures) |