passagemath-standard-no-symbolics 10.6.31rc3__cp314-cp314-macosx_13_0_arm64.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of passagemath-standard-no-symbolics might be problematic. Click here for more details.

Files changed (82) hide show
  1. passagemath_standard_no_symbolics-10.6.31rc3.data/scripts/sage-grep +5 -0
  2. passagemath_standard_no_symbolics-10.6.31rc3.data/scripts/sage-grepdoc +5 -0
  3. passagemath_standard_no_symbolics-10.6.31rc3.data/scripts/sage-list-packages +103 -0
  4. passagemath_standard_no_symbolics-10.6.31rc3.dist-info/METADATA +151 -0
  5. passagemath_standard_no_symbolics-10.6.31rc3.dist-info/RECORD +82 -0
  6. passagemath_standard_no_symbolics-10.6.31rc3.dist-info/WHEEL +6 -0
  7. passagemath_standard_no_symbolics-10.6.31rc3.dist-info/top_level.txt +1 -0
  8. sage/all.py +207 -0
  9. sage/all_cmdline.py +36 -0
  10. sage/cli/__init__.py +61 -0
  11. sage/cli/__main__.py +5 -0
  12. sage/cli/eval_cmd.py +45 -0
  13. sage/cli/eval_cmd_test.py +25 -0
  14. sage/cli/interactive_shell_cmd.py +28 -0
  15. sage/cli/notebook_cmd.py +51 -0
  16. sage/cli/notebook_cmd_test.py +39 -0
  17. sage/cli/options.py +26 -0
  18. sage/cli/run_file_cmd.py +50 -0
  19. sage/cli/version_cmd.py +26 -0
  20. sage/databases/all.py +83 -0
  21. sage/databases/cubic_hecke_db.py +1527 -0
  22. sage/dynamics/all.py +31 -0
  23. sage/dynamics/surface_dynamics_deprecation.py +32 -0
  24. sage/ext_data/kenzo/CP2.txt +45 -0
  25. sage/ext_data/kenzo/CP3.txt +349 -0
  26. sage/ext_data/kenzo/CP4.txt +4774 -0
  27. sage/ext_data/kenzo/README.txt +49 -0
  28. sage/ext_data/kenzo/S4.txt +20 -0
  29. sage/ext_data/mwrank/PRIMES +1 -0
  30. sage/ext_data/nbconvert/postprocess.py +48 -0
  31. sage/ext_data/nbconvert/rst_sage.tpl +99 -0
  32. sage/ext_data/nodoctest +0 -0
  33. sage/ext_data/notebook-ipython/kernel.json.in +11 -0
  34. sage/ext_data/notebook-ipython/logo-64x64.png +0 -0
  35. sage/ext_data/notebook-ipython/logo.svg +352 -0
  36. sage/ext_data/valgrind/pyalloc.supp +58 -0
  37. sage/ext_data/valgrind/sage-additional.supp +417 -0
  38. sage/ext_data/valgrind/sage.supp +43 -0
  39. sage/ext_data/valgrind/valgrind-python.supp +480 -0
  40. sage/geometry/all.py +12 -0
  41. sage/groups/matrix_gps/pickling_overrides.py +110 -0
  42. sage/homology/tests.py +66 -0
  43. sage/interacts/algebra.py +20 -0
  44. sage/interacts/all.py +25 -0
  45. sage/interacts/calculus.py +24 -0
  46. sage/interacts/fractals.py +18 -0
  47. sage/interacts/geometry.py +19 -0
  48. sage/interacts/library.py +1950 -0
  49. sage/interacts/library_cython.cpython-314-darwin.so +0 -0
  50. sage/interacts/statistics.py +19 -0
  51. sage/interfaces/axiom.py +1002 -0
  52. sage/interfaces/kash.py +834 -0
  53. sage/interfaces/lie.py +950 -0
  54. sage/interfaces/matlab.py +413 -0
  55. sage/interfaces/mupad.py +686 -0
  56. sage/interfaces/octave.py +858 -0
  57. sage/interfaces/phc.py +943 -0
  58. sage/interfaces/psage.py +189 -0
  59. sage/interfaces/qsieve.py +4 -0
  60. sage/interfaces/r.py +2096 -0
  61. sage/interfaces/read_data.py +46 -0
  62. sage/interfaces/scilab.py +576 -0
  63. sage/interfaces/tests.py +81 -0
  64. sage/libs/all.py +11 -0
  65. sage/libs/cremona/__init__.py +0 -0
  66. sage/libs/mwrank/__init__.py +0 -0
  67. sage/logic/all.py +3 -0
  68. sage/logic/booleval.py +160 -0
  69. sage/logic/boolformula.py +1490 -0
  70. sage/logic/logic.py +856 -0
  71. sage/logic/logicparser.py +696 -0
  72. sage/logic/logictable.py +272 -0
  73. sage/logic/propcalc.py +311 -0
  74. sage/misc/all.py +28 -0
  75. sage/misc/lazy_attribute.pyi +11 -0
  76. sage/rings/all.py +48 -0
  77. sage/rings/commutative_algebra.py +38 -0
  78. sage/rings/finite_rings/all.py +21 -0
  79. sage/rings/numbers_abc.py +58 -0
  80. sage/rings/polynomial/all.py +22 -0
  81. sage/rings/polynomial/convolution.py +421 -0
  82. sage/symbolic/all__sagemath_standard_no_symbolics.py +0 -0
@@ -0,0 +1,1950 @@
1
+ # sage.doctest: needs sage.symbolic
2
+ r"""
3
+ Sage Interacts
4
+
5
+ Sage interacts are applications of the `@interact decorator <../../sagenb/notebook/interact.html>`_.
6
+ They are conveniently accessible in the Sage notebook via ``interacts.[TAB].[TAB]()``.
7
+ The first ``[TAB]`` lists categories and the second ``[TAB]`` reveals the interact examples.
8
+
9
+ EXAMPLES:
10
+
11
+ Invoked in the notebook, the following command will produce the fully formatted
12
+ interactive mathlet. In the command line, it will simply return the underlying
13
+ HTML and Sage code which creates the mathlet::
14
+
15
+ sage: interacts.calculus.taylor_polynomial() # needs sage.symbolic
16
+ ...Interactive function <function taylor_polynomial at ...> with 3 widgets
17
+ title: HTMLText(value='<h2>Taylor polynomial</h2>')
18
+ f: EvalText(value='e^(-x)*sin(x)', description='$f(x)=$', layout=Layout(max_width='81em'))
19
+ order: SelectionSlider(description='order', options=(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12), value=1)
20
+
21
+ AUTHORS:
22
+
23
+ - William Stein
24
+ - Harald Schilly, Robert Marik (2011-01-16): added many examples (#9623)
25
+ partially based on work by Lauri Ruotsalainen
26
+ """
27
+
28
+ # *****************************************************************************
29
+ # Copyright (C) 2009 William Stein <wstein@gmail.com>
30
+ # Copyright (C) 2011 Harald Schilly <harald.schilly@gmail.com>
31
+ #
32
+ # Distributed under the terms of the GNU General Public License (GPL)
33
+ # as published by the Free Software Foundation; either version 2 of
34
+ # the License, or (at your option) any later version.
35
+ #
36
+ # https://www.gnu.org/licenses/
37
+ # *****************************************************************************
38
+
39
+ from typing import Any, Callable
40
+
41
+ from sage.arith.misc import factor
42
+ from sage.arith.srange import srange
43
+ from sage.calculus.all import symbolic_expression
44
+ from sage.calculus.functional import derivative
45
+ from sage.calculus.integration import numerical_integral as integral_numerical
46
+ from sage.ext.fast_callable import fast_callable
47
+ from sage.functions.log import exp
48
+ from sage.misc.functional import sqrt
49
+ from sage.functions.trig import (acos, cos, sin, tan)
50
+ from sage.misc.decorators import sage_wraps
51
+ from sage.misc.functional import N
52
+ from sage.misc.latex import latex
53
+ from sage.misc.sage_eval import sage_eval
54
+ from sage.misc.table import table
55
+ from sage.misc.lazy_import import lazy_import
56
+ lazy_import("sage.plot.circle", "circle")
57
+ lazy_import("sage.plot.complex_plot", "complex_plot")
58
+ lazy_import("sage.plot.disk", "disk")
59
+ lazy_import("sage.plot.graphics", "Graphics")
60
+ lazy_import("sage.plot.line", ["line", "line2d"])
61
+ lazy_import("sage.plot.matrix_plot", "matrix_plot")
62
+ lazy_import("sage.plot.plot", ["graphics_array", "parametric_plot", "plot"])
63
+ lazy_import("sage.plot.point", ["point", "points"])
64
+ lazy_import("sage.plot.polygon", "polygon2d")
65
+ lazy_import("sage.plot.text", "text")
66
+ from sage.repl.rich_output.pretty_print import (pretty_print, show)
67
+ from sage.rings.complex_double import CDF
68
+ from sage.rings.integer import Integer
69
+ from sage.symbolic.constants import pi
70
+ from sage.symbolic.relation import solve
71
+ from sage.symbolic.ring import SR
72
+
73
+ x = SR.var('x')
74
+
75
+ # It is important that this file is lazily imported for this to work
76
+ from sage.repl.user_globals import get_global
77
+
78
+ assert get_global # to suppress pyflakes warning
79
+
80
+ from sage.repl.ipython_kernel.all_jupyter import (interact, checkbox,
81
+ input_box, input_grid, range_slider, selector, slider, text_control)
82
+
83
+
84
+ def library_interact(
85
+ decorator_target: Callable[..., Any] = None, **widgets: Callable[..., Any]
86
+ ):
87
+ r"""
88
+ This is a decorator for using interacts in the Sage library.
89
+
90
+ This is essentially a wrapper around the ``interact`` function.
91
+
92
+ INPUT:
93
+
94
+ - ``**widgets`` -- keyword arguments that are passed to the
95
+ ``interact`` function to create the widgets. Each value must
96
+ be a callable that returns a widget.
97
+
98
+ EXAMPLES::
99
+
100
+ sage: from sage.interacts.library import library_interact
101
+ sage: @library_interact(n=lambda: slider(-5, 15, None, 5))
102
+ ....: def f(n):
103
+ ....: print(n)
104
+ sage: f() # an interact appears if using the notebook, else code
105
+ ...Interactive function <function f at ...> with 1 widget
106
+ n: TransformIntSlider(value=5, description='n', max=15, min=-5)
107
+
108
+ TESTS:
109
+
110
+ Backwards compatibility::
111
+
112
+ sage: from sage.interacts.library import library_interact
113
+ sage: @library_interact
114
+ ....: def f(n=slider(-5, 15, None, 5)):
115
+ ....: print(n)
116
+ doctest:warning
117
+ ...
118
+ DeprecationWarning: Use decorator factory @library_interact(widgets) instead of @library_interact without any arguments.
119
+ See https://github.com/sagemath/sage/issues/33382 for details.
120
+ sage: f() # an interact appears if using the notebook, else code
121
+ ...Interactive function <function f at ...> with 1 widget
122
+ n: TransformIntSlider(value=5, description='n', max=15, min=-5)
123
+
124
+ .. NOTE::
125
+
126
+ We use a callable to construct the widget so that the widget is only
127
+ initialized when the function is called and not upon loading the module.
128
+ """
129
+
130
+ def decorator(f: Callable[..., Any]):
131
+ @sage_wraps(f)
132
+ def library_wrapper():
133
+ widgets_constructed = {
134
+ key: constructor() for key, constructor in widgets.items()
135
+ }
136
+ # This will display the interact, no need to return anything
137
+ interact(f, **widgets_constructed)
138
+
139
+ # Store the widget constructors for later use in tests
140
+ library_wrapper._widgets = widgets
141
+ return library_wrapper
142
+
143
+ if decorator_target is None:
144
+ return decorator
145
+ else:
146
+ from sage.misc.superseded import deprecation
147
+
148
+ deprecation(
149
+ 33382,
150
+ "Use decorator factory @library_interact(widgets) instead of @library_interact without any arguments.",
151
+ )
152
+ return decorator(decorator_target)
153
+
154
+
155
+ def html(obj):
156
+ r"""
157
+ Shorthand to pretty print HTML.
158
+
159
+ EXAMPLES::
160
+
161
+ sage: from sage.interacts.library import html
162
+ sage: html("<h1>Hello world</h1>")
163
+ <h1>Hello world</h1>
164
+ """
165
+ from sage.misc.html import html
166
+ pretty_print(html(obj))
167
+
168
+
169
+ @library_interact(n=lambda: slider(range(10)), m=lambda: slider(range(10)))
170
+ def demo(n: int, m: int):
171
+ r"""
172
+ This is a demo interact that sums two numbers.
173
+
174
+ INPUT:
175
+
176
+ - ``n`` -- integer
177
+ - ``m`` -- integer
178
+
179
+ EXAMPLES:
180
+
181
+ Invoked in the notebook, the following command will produce
182
+ the fully formatted interactive mathlet. In the command line,
183
+ it will simply return the underlying HTML and Sage code which
184
+ creates the mathlet::
185
+
186
+ sage: interacts.demo()
187
+ ...Interactive function <function demo at ...> with 2 widgets
188
+ n: SelectionSlider(description='n', options=(0, 1, 2, 3, 4, 5, 6, 7, 8, 9), value=0)
189
+ m: SelectionSlider(description='m', options=(0, 1, 2, 3, 4, 5, 6, 7, 8, 9), value=0)
190
+ """
191
+ print(n + m)
192
+
193
+
194
+ @library_interact(
195
+ title=lambda: text_control("<h2>Taylor polynomial</h2>"),
196
+ f=lambda: input_box(sin(x) * exp(-x), label="$f(x)=$"),
197
+ order=lambda: slider(range(1, 13)),
198
+ )
199
+ def taylor_polynomial(title, f, order: int):
200
+ r"""
201
+ Illustrate the Taylor polynomial approximation
202
+ of various orders around `x=0`.
203
+
204
+ INPUT:
205
+
206
+ - ``f`` -- function expression
207
+ - ``order`` -- integer
208
+
209
+ EXAMPLES:
210
+
211
+ Invoked in the notebook, the following command will produce
212
+ the fully formatted interactive mathlet. In the command line,
213
+ it will simply return the underlying HTML and Sage code which
214
+ creates the mathlet::
215
+
216
+ sage: interacts.calculus.taylor_polynomial()
217
+ ...Interactive function <function taylor_polynomial at ...> with 3 widgets
218
+ title: HTMLText(value='<h2>Taylor polynomial</h2>')
219
+ f: EvalText(value='e^(-x)*sin(x)', description='$f(x)=$', layout=Layout(max_width='81em'))
220
+ order: SelectionSlider(description='order', options=(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12), value=1)
221
+ """
222
+ x0 = 0
223
+ p = plot(f, (x, -1, 5), thickness=2)
224
+ dot = point((x0, f(x=x0)), pointsize=80, rgbcolor=(1, 0, 0))
225
+ ft = f.taylor(x, x0, order)
226
+ pt = plot(ft, (-1, 5), color='green', thickness=2)
227
+ html(r'$f(x)\;=\;%s$' % latex(f))
228
+ html(r'$\hat{f}(x;%s)\;=\;%s+\mathcal{O}(x^{%s})$' % (x0, latex(ft),
229
+ order + 1))
230
+ show(dot + p + pt, ymin=-.5, ymax=1)
231
+
232
+
233
+ @library_interact(
234
+ title=lambda: text_control("<h2>Definite integral</h2>"),
235
+ f=lambda: input_box(default='3*x', label="$f(x)=$"),
236
+ g=lambda: input_box(default='x^2', label="$g(x)=$"),
237
+ interval=lambda: range_slider(-10, 10, default=(0, 3), label='Interval'),
238
+ x_range=lambda: range_slider(-10, 10, default=(0, 3), label="plot range (x)"),
239
+ selection=lambda: selector(
240
+ ["f", "g", "f and g", "f - g"], default="f and g", label="Select"
241
+ ),
242
+ )
243
+ def definite_integral(title, f, g, interval, x_range, selection):
244
+ r"""
245
+ This is a demo interact for plotting the definite integral of a function
246
+ based on work by Lauri Ruotsalainen, 2010.
247
+
248
+ INPUT:
249
+
250
+ - ``function`` -- input box, function in x
251
+ - ``interval`` -- interval for the definite integral
252
+ - ``x_range`` -- range slider for plotting range
253
+ - ``selection`` -- selector on how to visualize the integrals
254
+
255
+ EXAMPLES:
256
+
257
+ Invoked in the notebook, the following command will produce
258
+ the fully formatted interactive mathlet. In the command line,
259
+ it will simply return the underlying HTML and Sage code which
260
+ creates the mathlet::
261
+
262
+ sage: interacts.calculus.definite_integral()
263
+ ...Interactive function <function definite_integral at ...> with 6 widgets
264
+ title: HTMLText(value='<h2>Definite integral</h2>')
265
+ f: EvalText(value='3*x', description='$f(x)=$', layout=Layout(max_width='81em'))
266
+ g: EvalText(value='x^2', description='$g(x)=$', layout=Layout(max_width='81em'))
267
+ interval: IntRangeSlider(value=(0, 3), description='Interval', max=10, min=-10)
268
+ x_range: IntRangeSlider(value=(0, 3), description='plot range (x)', max=10, min=-10)
269
+ selection: Dropdown(description='Select', index=2,
270
+ options=('f', 'g', 'f and g', 'f - g'), value='f and g')
271
+ """
272
+ x = SR.var('x')
273
+ f = symbolic_expression(f).function(x)
274
+ g = symbolic_expression(g).function(x)
275
+ f_plot = Graphics()
276
+ g_plot = Graphics()
277
+ h_plot = Graphics()
278
+ text = ""
279
+
280
+ # Plot function f.
281
+ if selection != "g":
282
+ f_plot = plot(f(x), x, x_range, color='blue', thickness=1.5)
283
+
284
+ # Color and calculate the area between f and the horizontal axis.
285
+ if selection == "f" or selection == "f and g":
286
+ f_plot += plot(f(x), x, interval, color='blue', fill=True, fillcolor='blue', fillalpha=0.15)
287
+ text += r"$\int_{%.2f}^{%.2f}(\color{Blue}{f(x)})\,\mathrm{d}x=\int_{%.2f}^{%.2f}(%s)\,\mathrm{d}x=%.2f$" % (
288
+ interval[0], interval[1],
289
+ interval[0], interval[1],
290
+ latex(f(x)),
291
+ f(x).nintegrate(x, interval[0], interval[1])[0]
292
+ )
293
+
294
+ if selection == "f and g":
295
+ text += r"<br/>"
296
+
297
+ # Plot function g. Also color and calculate the area between g and the horizontal axis.
298
+ if selection == "g" or selection == "f and g":
299
+ g_plot = plot(g(x), x, x_range, color='green', thickness=1.5)
300
+ g_plot += plot(g(x), x, interval, color='green', fill=True, fillcolor='yellow', fillalpha=0.5)
301
+ text += r"$\int_{%.2f}^{%.2f}(\color{Green}{g(x)})\,\mathrm{d}x=\int_{%.2f}^{%.2f}(%s)\,\mathrm{d}x=%.2f$" % (
302
+ interval[0], interval[1],
303
+ interval[0], interval[1],
304
+ latex(g(x)),
305
+ g(x).nintegrate(x, interval[0], interval[1])[0]
306
+ )
307
+
308
+ # Plot function f-g. Also color and calculate the area between f-g and the horizontal axis.
309
+ if selection == "f - g":
310
+ g_plot = plot(g(x), x, x_range, color='green', thickness=1.5)
311
+ g_plot += plot(g(x), x, interval, color='green', fill=f(x), fillcolor='red', fillalpha=0.15)
312
+ h_plot = plot(f(x)-g(x), x, interval, color='red', thickness=1.5, fill=True, fillcolor='red', fillalpha=0.15)
313
+ text = r"$\int_{%.2f}^{%.2f}(\color{Red}{f(x)-g(x)})\,\mathrm{d}x=\int_{%.2f}^{%.2f}(%s)\,\mathrm{d}x=%.2f$" % (
314
+ interval[0], interval[1],
315
+ interval[0], interval[1],
316
+ latex(f(x)-g(x)),
317
+ (f(x)-g(x)).nintegrate(x, interval[0], interval[1])[0]
318
+ )
319
+
320
+ show(f_plot + g_plot + h_plot, gridlines=True)
321
+ html(text)
322
+
323
+
324
+ @library_interact(
325
+ title=lambda: text_control("<h2>Derivative grapher</h2>"),
326
+ function=lambda: input_box(default='x^5-3*x^3+1', label='Function:'),
327
+ x_range=lambda: range_slider(-15, 15, 0.1, default=(-2, 2), label="Range (x)"),
328
+ y_range=lambda: range_slider(-15, 15, 0.1, default=(-8, 6), label="Range (y)"),
329
+ )
330
+ def function_derivative(title, function, x_range, y_range):
331
+ r"""
332
+ This is a demo interact for plotting derivatives of a function based on work by
333
+ Lauri Ruotsalainen, 2010.
334
+
335
+ INPUT:
336
+
337
+ - ``function`` -- input box, function in x
338
+ - ``x_range`` -- range slider for plotting range
339
+ - ``y_range`` -- range slider for plotting range
340
+
341
+ EXAMPLES:
342
+
343
+ Invoked in the notebook, the following command will produce
344
+ the fully formatted interactive mathlet. In the command line,
345
+ it will simply return the underlying HTML and Sage code which
346
+ creates the mathlet::
347
+
348
+ sage: interacts.calculus.function_derivative()
349
+ ...Interactive function <function function_derivative at ...> with 4 widgets
350
+ title: HTMLText(value='<h2>Derivative grapher</h2>')
351
+ function: EvalText(value='x^5-3*x^3+1', description='Function:', layout=Layout(max_width='81em'))
352
+ x_range: FloatRangeSlider(value=(-2.0, 2.0), description='Range (x)', max=15.0, min=-15.0)
353
+ y_range: FloatRangeSlider(value=(-8.0, 6.0), description='Range (y)', max=15.0, min=-15.0)
354
+ """
355
+ x = SR.var('x')
356
+ f = symbolic_expression(function).function(x)
357
+ df = derivative(f, x)
358
+ ddf = derivative(df, x)
359
+ plots = plot(f(x), x_range, thickness=1.5) + plot(df(x), x_range, color='green') + plot(ddf(x), x_range, color='red')
360
+ if y_range == (0,0):
361
+ show(plots, xmin=x_range[0], xmax=x_range[1])
362
+ else:
363
+ show(plots, xmin=x_range[0], xmax=x_range[1], ymin=y_range[0], ymax=y_range[1])
364
+
365
+ html(r"<center>$\color{Blue}{f(x) = %s}$</center>" % latex(f(x)))
366
+ html(r"<center>$\color{Green}{f'(x) = %s}$</center>" % latex(df(x)))
367
+ html(r"<center>$\color{Red}{f''(x) = %s}$</center>" % latex(ddf(x)))
368
+
369
+
370
+ @library_interact(
371
+ title=lambda: text_control("<h2>Difference quotient</h2>"),
372
+ f=lambda: input_box(default='sin(x)', label="f(x)"),
373
+ interval=lambda: range_slider(0, 10, 0.1, default=(0.0, 10.0), label='Range'),
374
+ a=lambda: slider(0, 10, None, 5.5, label='$a$'),
375
+ x0=lambda: slider(0, 10, None, 2.5, label="$x_0$ (start point)"),
376
+ )
377
+ def difference_quotient(title, f, interval, a, x0):
378
+ r"""
379
+ This is a demo interact for difference quotient based on work by
380
+ Lauri Ruotsalainen, 2010.
381
+
382
+ INPUT:
383
+
384
+ - ``f`` -- input box, function in `x`
385
+ - ``interval`` -- range slider for plotting
386
+ - ``a`` -- slider for `a`
387
+ - ``x0`` -- slider for starting point `x_0`
388
+
389
+ EXAMPLES:
390
+
391
+ Invoked in the notebook, the following command will produce
392
+ the fully formatted interactive mathlet. In the command line,
393
+ it will simply return the underlying HTML and Sage code which
394
+ creates the mathlet::
395
+
396
+ sage: interacts.calculus.difference_quotient()
397
+ ...Interactive function <function difference_quotient at ...> with 5 widgets
398
+ title: HTMLText(value='<h2>Difference quotient</h2>')
399
+ f: EvalText(value='sin(x)', description='f(x)', layout=Layout(max_width='81em'))
400
+ interval: FloatRangeSlider(value=(0.0, 10.0), description='Range', max=10.0)
401
+ a: IntSlider(value=5, description='$a$', max=10)
402
+ x0: IntSlider(value=2, description='$x_0$ (start point)', max=10)
403
+ """
404
+ html('<h2>Difference Quotient</h2>')
405
+ html('<div style="white-space: normal;">\
406
+ <a href="https://en.wikipedia.org/wiki/Difference_quotient" target="_blank">\
407
+ Wikipedia article about difference quotient</a></div>'
408
+ )
409
+
410
+ x = SR.var('x')
411
+ f = symbolic_expression(f).function(x)
412
+ fmax = f.find_local_maximum(interval[0], interval[1])[0]
413
+ fmin = f.find_local_minimum(interval[0], interval[1])[0]
414
+ f_height = fmax - fmin
415
+ measure_y = fmin - 0.1*f_height
416
+
417
+ measure_0 = line2d([(x0, measure_y), (a, measure_y)], rgbcolor='black')
418
+ measure_1 = line2d([(x0, measure_y + 0.02*f_height), (x0, measure_y-0.02*f_height)], rgbcolor='black')
419
+ measure_2 = line2d([(a, measure_y + 0.02*f_height), (a, measure_y-0.02*f_height)], rgbcolor='black')
420
+ text_x0 = text("x0", (x0, measure_y - 0.05*f_height), rgbcolor='black')
421
+ text_a = text("a", (a, measure_y - 0.05*f_height), rgbcolor='black')
422
+ measure = measure_0 + measure_1 + measure_2 + text_x0 + text_a
423
+
424
+ tanf = symbolic_expression((f(x0)-f(a))*(x-a)/(x0-a)+f(a)).function(x)
425
+
426
+ fplot = plot(f(x), x, interval[0], interval[1])
427
+ tanplot = plot(tanf(x), x, interval[0], interval[1], rgbcolor='#FF0000')
428
+ points = point([(x0, f(x0)), (a, f(a))], pointsize=20, rgbcolor='#005500')
429
+ dashline = line2d([(x0, f(x0)), (x0, f(a)), (a, f(a))], rgbcolor='#005500', linestyle='--')
430
+ html('<h2>Difference Quotient</h2>')
431
+ show(fplot + tanplot + points + dashline + measure, xmin=interval[0], xmax=interval[1], ymin=fmin-0.2*f_height, ymax=fmax)
432
+ html(r"<br>$\text{Line's equation:}$")
433
+ html(r"$y = %s$<br>" % tanf(x))
434
+ html(r"$\text{Slope:}$")
435
+ html(r"$k = \frac{f(x_0)-f(a)}{x_0-a} = %s$<br>" % (N(derivative(tanf(x), x), digits=5)))
436
+
437
+
438
+ @library_interact(
439
+ A=lambda: slider(-7, 7, 1, 1),
440
+ B=lambda: slider(-7, 7, 1, 1),
441
+ C=lambda: slider(-7, 7, 1, -2),
442
+ )
443
+ def quadratic_equation(A, B, C):
444
+ r"""
445
+ This is a demo interact for solving quadratic equations based on work by
446
+ Lauri Ruotsalainen, 2010.
447
+
448
+ INPUT:
449
+
450
+ - ``A`` -- integer slider
451
+ - ``B`` -- integer slider
452
+ - ``C`` -- integer slider
453
+
454
+ EXAMPLES:
455
+
456
+ Invoked in the notebook, the following command will produce
457
+ the fully formatted interactive mathlet. In the command line,
458
+ it will simply return the underlying HTML and Sage code which
459
+ creates the mathlet::
460
+
461
+ sage: interacts.calculus.quadratic_equation()
462
+ ...Interactive function <function quadratic_equation at ...> with 3 widgets
463
+ A: IntSlider(value=1, description='A', max=7, min=-7)
464
+ B: IntSlider(value=1, description='B', max=7, min=-7)
465
+ C: IntSlider(value=-2, description='C', max=7, min=-7)
466
+ """
467
+ x = SR.var('x')
468
+ f = symbolic_expression(A*x**2 + B*x + C).function(x)
469
+ html('<h2>The Solutions of the Quadratic Equation</h2>')
470
+ html("$%s = 0$" % f(x))
471
+
472
+ show(plot(f(x), x, (-10, 10), ymin=-10, ymax=10), aspect_ratio=1, figsize=4)
473
+
474
+ d = B**2 - 4*A*C
475
+
476
+ if d < 0:
477
+ color = "Red"
478
+ sol = r"\text{solution} \in \mathbb{C}"
479
+ elif d == 0:
480
+ color = "Blue"
481
+ sol = -B/(2*A)
482
+ else:
483
+ color = "Green"
484
+ a = (-B+sqrt(B**2-4*A*C))/(2*A)
485
+ b = (-B-sqrt(B**2-4*A*C))/(2*A)
486
+ sol = r"\begin{cases}%s\\%s\end{cases}" % (latex(a), latex(b))
487
+
488
+ if B < 0:
489
+ dis1 = "(%s)^2-4*%s*%s" % (B, A, C)
490
+ else:
491
+ dis1 = "%s^2-4*%s*%s" % (B, A, C)
492
+ dis2 = r"\color{%s}{%s}" % (color, d)
493
+
494
+ html("$Ax^2 + Bx + C = 0$")
495
+ calc = r"$x = \frac{-B\pm\sqrt{B^2-4AC}}{2A} = " + \
496
+ r"\frac{-%s\pm\sqrt{%s}}{2*%s} = " + \
497
+ r"\frac{-%s\pm\sqrt{%s}}{%s} = %s$"
498
+ html(calc % (B, dis1, A, B, dis2, (2*A), sol))
499
+
500
+
501
+ @library_interact(
502
+ a0=lambda: slider(0, 360, 1, 30, label='A'),
503
+ a1=lambda: slider(0, 360, 1, 180, label='B'),
504
+ a2=lambda: slider(0, 360, 1, 300, label='C'),
505
+ )
506
+ def trigonometric_properties_triangle(a0, a1, a2):
507
+ r"""
508
+ This is an interact for demonstrating trigonometric properties
509
+ in a triangle based on work by Lauri Ruotsalainen, 2010.
510
+
511
+ INPUT:
512
+
513
+ - ``a0`` -- angle
514
+ - ``a1`` -- angle
515
+ - ``a2`` -- angle
516
+
517
+ EXAMPLES:
518
+
519
+ Invoked in the notebook, the following command will produce
520
+ the fully formatted interactive mathlet. In the command line,
521
+ it will simply return the underlying HTML and Sage code which
522
+ creates the mathlet::
523
+
524
+ sage: interacts.geometry.trigonometric_properties_triangle()
525
+ ...Interactive function <function trigonometric_properties_triangle at ...> with 3 widgets
526
+ a0: IntSlider(value=30, description='A', max=360)
527
+ a1: IntSlider(value=180, description='B', max=360)
528
+ a2: IntSlider(value=300, description='C', max=360)
529
+ """
530
+ import math
531
+
532
+ # Returns the distance between points (x1,y1) and (x2,y2)
533
+ def distance(x1_y1, x2_y2):
534
+ (x1, y1) = x1_y1
535
+ (x2, y2) = x2_y2
536
+ return sqrt((x2-x1)**2 + (y2-y1)**2)
537
+
538
+ # Returns an angle (in radians) when sides a and b
539
+ # are adjacent and the side c is opposite to the angle
540
+ def angle(a, b, c):
541
+ a,b,c = map(float,[a,b,c])
542
+ return acos(0.5 * (b**2 + c**2 - a**2) / (b * c))
543
+
544
+ # Returns the area of a triangle when an angle alpha
545
+ # and adjacent sides a and b are known
546
+ def area(alpha, a, b):
547
+ return 0.5 * a * b * sin(alpha)
548
+
549
+ xy = [0]*3
550
+ html('<h2>Trigonometric Properties of a Triangle</h2>')
551
+ # Coordinates of the angles
552
+ a = [math.radians(float(x)) for x in [a0, a1, a2]]
553
+ for i in range(3):
554
+ xy[i] = (cos(a[i]), sin(a[i]))
555
+
556
+ # Side lengths (bc, ca, ab) corresponding to triangle vertices (a, b, c)
557
+ al = [distance(xy[1], xy[2]), distance(xy[2], xy[0]), distance(xy[0], xy[1])]
558
+
559
+ # The angles (a, b, c) in radians
560
+ ak = [angle(al[0], al[1], al[2]), angle(al[1], al[2], al[0]), angle(al[2], al[0], al[1])]
561
+
562
+ # The area of the triangle
563
+ A = area(ak[0], al[1], al[2])
564
+
565
+ unit_circle = circle((0, 0), 1, aspect_ratio=1)
566
+
567
+ # Triangle
568
+ triangle = line([xy[0], xy[1], xy[2], xy[0]], rgbcolor='black')
569
+ triangle_points = point(xy, pointsize=30)
570
+
571
+ # Labels of the angles drawn in a distance from points
572
+ a_label = text("A", (xy[0][0]*1.07, xy[0][1]*1.07))
573
+ b_label = text("B", (xy[1][0]*1.07, xy[1][1]*1.07))
574
+ c_label = text("C", (xy[2][0]*1.07, xy[2][1]*1.07))
575
+ labels = a_label + b_label + c_label
576
+
577
+ show(unit_circle + triangle + triangle_points + labels, figsize=[5, 5], xmin=-1, xmax=1, ymin=-1, ymax=1)
578
+ html(r"$\angle A = {%.3f}^{\circ},$ $\angle B = {%.3f}^{\circ},$ $\angle C = {%.3f}^{\circ}$"
579
+ % (math.degrees(ak[0]), math.degrees(ak[1]), math.degrees(ak[2])))
580
+ html(r"$AB = %.6f$, $BC = %.6f$, $CA = %.6f$" % (al[2], al[0], al[1]))
581
+ html(r"Area of triangle $ABC = %.6f$" % A)
582
+
583
+
584
+ @library_interact(
585
+ function=lambda: selector([(0, sin(x)), (1, cos(x)), (2, tan(x))]),
586
+ x=lambda: slider(0, 2 * pi, 0.005 * pi, 0),
587
+ )
588
+ def unit_circle(function, x):
589
+ r"""
590
+ This is an interact for Sin, Cos and Tan in the Unit Circle
591
+ based on work by Lauri Ruotsalainen, 2010.
592
+
593
+ INPUT:
594
+
595
+ - ``function`` -- select Sin, Cos or Tan
596
+ - ``x`` -- slider to select angle in unit circle
597
+
598
+ EXAMPLES:
599
+
600
+ Invoked in the notebook, the following command will produce
601
+ the fully formatted interactive mathlet. In the command line,
602
+ it will simply return the underlying HTML and Sage code which
603
+ creates the mathlet::
604
+
605
+ sage: interacts.geometry.unit_circle()
606
+ ...Interactive function <function unit_circle at ...> with 2 widgets
607
+ function: Dropdown(description='function', options=(('sin(x)', 0), ('cos(x)', 1), ('tan(x)', 2)), value=0)
608
+ x: TransformFloatSlider(value=0.0, description='x', max=6.283185307179586, step=0.015707963267948967)
609
+ """
610
+ xy = (cos(x), sin(x))
611
+ t = SR.var('t')
612
+ html('<div style="white-space: normal;">Lines of the same color have\
613
+ the same length</div>')
614
+
615
+ # Unit Circle
616
+ C = circle((0, 0), 1, figsize=[5, 5], aspect_ratio=1)
617
+ C_line = line([(0, 0), (xy[0], xy[1])], rgbcolor='black')
618
+ C_point = point((xy[0], xy[1]), pointsize=40, rgbcolor='green')
619
+ C_inner = parametric_plot((cos(t), sin(t)), (t, 0, x + 0.001), color='green', thickness=3)
620
+ C_outer = parametric_plot((0.1 * cos(t), 0.1 * sin(t)), (t, 0, x + 0.001), color='black')
621
+ C_graph = C + C_line + C_point + C_inner + C_outer
622
+
623
+ # Graphics related to the graph of the function
624
+ G_line = line([(0, 0), (x, 0)], rgbcolor='green', thickness=3)
625
+ G_point = point((x, 0), pointsize=30, rgbcolor='green')
626
+ G_graph = G_line + G_point
627
+
628
+ # Sine
629
+ if function == 0:
630
+ Gf = plot(sin(t), t, 0, 2*pi, axes_labels=("x", "sin(x)"))
631
+ Gf_point = point((x, sin(x)), pointsize=30, rgbcolor='red')
632
+ Gf_line = line([(x, 0),(x, sin(x))], rgbcolor='red')
633
+ Cf_point = point((0, xy[1]), pointsize=40, rgbcolor='red')
634
+ Cf_line1 = line([(0, 0), (0, xy[1])], rgbcolor='red', thickness=3)
635
+ Cf_line2 = line([(0, xy[1]), (xy[0], xy[1])], rgbcolor='purple', linestyle='--')
636
+ # Cosine
637
+ elif function == 1:
638
+ Gf = plot(cos(t), t, 0, 2*pi, axes_labels=("x", "cos(x)"))
639
+ Gf_point = point((x, cos(x)), pointsize=30, rgbcolor='red')
640
+ Gf_line = line([(x, 0), (x, cos(x))], rgbcolor='red')
641
+ Cf_point = point((xy[0], 0), pointsize=40, rgbcolor='red')
642
+ Cf_line1 = line([(0, 0), (xy[0], 0)], rgbcolor='red', thickness=3)
643
+ Cf_line2 = line([(xy[0], 0), (xy[0], xy[1])], rgbcolor='purple', linestyle='--')
644
+ # Tangent
645
+ else:
646
+ Gf = plot(tan(t), t, 0, 2*pi, ymin=-8, ymax=8, axes_labels=("x", "tan(x)"))
647
+ Gf_point = point((x, tan(x)), pointsize=30, rgbcolor='red')
648
+ Gf_line = line([(x, 0), (x, tan(x))], rgbcolor='red')
649
+ Cf_point = point((1, tan(x)), pointsize=40, rgbcolor='red')
650
+ Cf_line1 = line([(1, 0), (1, tan(x))], rgbcolor='red', thickness=3)
651
+ Cf_line2 = line([(xy[0], xy[1]), (1, tan(x))], rgbcolor='purple', linestyle='--')
652
+
653
+ C_graph += Cf_point + Cf_line1 + Cf_line2
654
+ G_graph += Gf + Gf_point + Gf_line
655
+
656
+ show(graphics_array([C_graph, G_graph]))
657
+
658
+
659
+ @library_interact(
660
+ title=lambda: text_control("<h2>Special points in triangle</h2>"),
661
+ a0=lambda: slider(0, 360, 1, 30, label='A'),
662
+ a1=lambda: slider(0, 360, 1, 180, label='B'),
663
+ a2=lambda: slider(0, 360, 1, 300, label='C'),
664
+ show_median=lambda: checkbox(False, label='Medians'),
665
+ show_pb=lambda: checkbox(False, label="Perpendicular Bisectors"),
666
+ show_alt=lambda: checkbox(False, label='Altitudes'),
667
+ show_ab=lambda: checkbox(False, label="Angle Bisectors"),
668
+ show_incircle=lambda: checkbox(False, label='Incircle'),
669
+ show_euler=lambda: checkbox(False, label="Euler's Line"),
670
+ )
671
+ def special_points(
672
+ title,
673
+ a0,
674
+ a1,
675
+ a2,
676
+ show_median,
677
+ show_pb,
678
+ show_alt,
679
+ show_ab,
680
+ show_incircle,
681
+ show_euler,
682
+ ):
683
+ r"""
684
+ This interact demo shows special points in a triangle
685
+ based on work by Lauri Ruotsalainen, 2010.
686
+
687
+ INPUT:
688
+
689
+ - ``a0`` -- angle
690
+ - ``a1`` -- angle
691
+ - ``a2`` -- angle
692
+ - ``show_median`` -- checkbox
693
+ - ``show_pb`` -- checkbox to show perpendicular bisectors
694
+ - ``show_alt`` -- checkbox to show altitudes
695
+ - ``show_ab`` -- checkbox to show angle bisectors
696
+ - ``show_incircle`` -- checkbox to show incircle
697
+ - ``show_euler`` -- checkbox to show euler's line
698
+
699
+ EXAMPLES:
700
+
701
+ Invoked in the notebook, the following command will produce
702
+ the fully formatted interactive mathlet. In the command line,
703
+ it will simply return the underlying HTML and Sage code which
704
+ creates the mathlet::
705
+
706
+ sage: interacts.geometry.special_points()
707
+ ...Interactive function <function special_points at ...> with 10 widgets
708
+ title: HTMLText(value='<h2>Special points in triangle</h2>')
709
+ a0: IntSlider(value=30, description='A', max=360)
710
+ a1: IntSlider(value=180, description='B', max=360)
711
+ a2: IntSlider(value=300, description='C', max=360)
712
+ show_median: Checkbox(value=False, description='Medians')
713
+ show_pb: Checkbox(value=False, description='Perpendicular Bisectors')
714
+ show_alt: Checkbox(value=False, description='Altitudes')
715
+ show_ab: Checkbox(value=False, description='Angle Bisectors')
716
+ show_incircle: Checkbox(value=False, description='Incircle')
717
+ show_euler: Checkbox(value=False, description="Euler's Line")
718
+ """
719
+ import math
720
+ # Return the intersection point of the bisector of the angle <(A[a],A[c],A[b]) and the unit circle. Angles given in radians.
721
+
722
+ def half(A, a, b, c):
723
+ if (A[a] < A[b] and (A[c] < A[a] or A[c] > A[b])) or (A[a] > A[b] and (A[c] > A[a] or A[c] < A[b])):
724
+ p = A[a] + 0.5 * (A[b] - A[a])
725
+ else:
726
+ p = A[b] + 0.5 * (2*pi - (A[b]-A[a]))
727
+ return (math.cos(p), math.sin(p))
728
+
729
+ # Returns the distance between points (x1,y1) and (x2,y2)
730
+ def distance(x1_y1, x2_y2):
731
+ (x1, y1) = x1_y1
732
+ (x2, y2) = x2_y2
733
+ return math.sqrt((x2-x1)**2 + (y2-y1)**2)
734
+
735
+ # Returns the line (graph) going through points (x1,y1) and (x2,y2)
736
+ def line_to_points(x1_y1, x2_y2, **plot_kwargs):
737
+ (x1, y1) = x1_y1
738
+ (x2, y2) = x2_y2
739
+ return plot((y2-y1) / (x2-x1) * (x-x1) + y1, (x,-3,3), **plot_kwargs)
740
+
741
+ # Coordinates of the angles
742
+ a = [math.radians(float(x)) for x in [a0, a1, a2]]
743
+ xy = [(math.cos(a[i]), math.sin(a[i])) for i in range(3)]
744
+
745
+ # Labels of the angles drawn in a distance from points
746
+ a_label = text("A", (xy[0][0]*1.07, xy[0][1]*1.07))
747
+ b_label = text("B", (xy[1][0]*1.07, xy[1][1]*1.07))
748
+ c_label = text("C", (xy[2][0]*1.07, xy[2][1]*1.07))
749
+ labels = a_label + b_label + c_label
750
+
751
+ C = circle((0, 0), 1, aspect_ratio=1)
752
+
753
+ # Triangle
754
+ triangle = line([xy[0], xy[1], xy[2], xy[0]], rgbcolor='black')
755
+ triangle_points = point(xy, pointsize=30)
756
+
757
+ # Side lengths (bc, ca, ab) corresponding to triangle vertices (a, b, c)
758
+ ad = [distance(xy[1], xy[2]), distance(xy[2], xy[0]), distance(xy[0], xy[1])]
759
+
760
+ # Midpoints of edges (bc, ca, ab)
761
+ a_middle = [
762
+ (0.5 * (xy[1][0] + xy[2][0]), 0.5 * (xy[1][1] + xy[2][1])),
763
+ (0.5 * (xy[2][0] + xy[0][0]), 0.5 * (xy[2][1] + xy[0][1])),
764
+ (0.5 * (xy[0][0] + xy[1][0]), 0.5 * (xy[0][1] + xy[1][1]))
765
+ ]
766
+
767
+ # Incircle
768
+ perimeter = float(ad[0] + ad[1] + ad[2])
769
+ incircle_center = (
770
+ (ad[0]*xy[0][0] + ad[1]*xy[1][0] + ad[2]*xy[2][0]) / perimeter,
771
+ (ad[0]*xy[0][1] + ad[1]*xy[1][1] + ad[2]*xy[2][1]) / perimeter
772
+ )
773
+
774
+ if show_incircle:
775
+ s = 0.5 * perimeter
776
+ incircle_r = math.sqrt((s - ad[0]) * (s - ad[1]) * (s - ad[2]) / s)
777
+ incircle_graph = circle(incircle_center, incircle_r) + point(incircle_center)
778
+ else:
779
+ incircle_graph = Graphics()
780
+
781
+ # Angle Bisectors
782
+ if show_ab:
783
+ a_ab = line([xy[0], half(a, 1, 2, 0)], rgbcolor='blue', alpha=0.6)
784
+ b_ab = line([xy[1], half(a, 2, 0, 1)], rgbcolor='blue', alpha=0.6)
785
+ c_ab = line([xy[2], half(a, 0, 1, 2)], rgbcolor='blue', alpha=0.6)
786
+ ab_point = point(incircle_center, rgbcolor='blue', pointsize=28)
787
+ ab_graph = a_ab + b_ab + c_ab + ab_point
788
+ else:
789
+ ab_graph = Graphics()
790
+
791
+ # Medians
792
+ if show_median:
793
+ a_median = line([xy[0], a_middle[0]], rgbcolor='green', alpha=0.6)
794
+ b_median = line([xy[1], a_middle[1]], rgbcolor='green', alpha=0.6)
795
+ c_median = line([xy[2], a_middle[2]], rgbcolor='green', alpha=0.6)
796
+ median_point = point(
797
+ (
798
+ (xy[0][0]+xy[1][0]+xy[2][0])/3.0,
799
+ (xy[0][1]+xy[1][1]+xy[2][1])/3.0
800
+ ), rgbcolor='green', pointsize=28)
801
+ median_graph = a_median + b_median + c_median + median_point
802
+ else:
803
+ median_graph = Graphics()
804
+
805
+ # Perpendicular Bisectors
806
+ if show_pb:
807
+ a_pb = line_to_points(a_middle[0], half(a, 1, 2, 0), rgbcolor='red', alpha=0.6)
808
+ b_pb = line_to_points(a_middle[1], half(a, 2, 0, 1), rgbcolor='red', alpha=0.6)
809
+ c_pb = line_to_points(a_middle[2], half(a, 0, 1, 2), rgbcolor='red', alpha=0.6)
810
+ pb_point = point((0, 0), rgbcolor='red', pointsize=28)
811
+ pb_graph = a_pb + b_pb + c_pb + pb_point
812
+ else:
813
+ pb_graph = Graphics()
814
+
815
+ # Altitudes
816
+ if show_alt:
817
+ xA, xB, xC = xy[0][0], xy[1][0], xy[2][0]
818
+ yA, yB, yC = xy[0][1], xy[1][1], xy[2][1]
819
+ a_alt = plot(((xC-xB)*x+(xB-xC)*xA)/(yB-yC)+yA, (x,-3,3), rgbcolor='brown', alpha=0.6)
820
+ b_alt = plot(((xA-xC)*x+(xC-xA)*xB)/(yC-yA)+yB, (x,-3,3), rgbcolor='brown', alpha=0.6)
821
+ c_alt = plot(((xB-xA)*x+(xA-xB)*xC)/(yA-yB)+yC, (x,-3,3), rgbcolor='brown', alpha=0.6)
822
+ alt_lx = (xA*xB*(yA-yB)+xB*xC*(yB-yC)+xC*xA*(yC-yA)-(yA-yB)*(yB-yC)*(yC-yA))/(xC*yB-xB*yC+xA*yC-xC*yA+xB*yA-xA*yB)
823
+ alt_ly = (yA*yB*(xA-xB)+yB*yC*(xB-xC)+yC*yA*(xC-xA)-(xA-xB)*(xB-xC)*(xC-xA))/(yC*xB-yB*xC+yA*xC-yC*xA+yB*xA-yA*xB)
824
+ alt_intersection = point((alt_lx, alt_ly), rgbcolor='brown', pointsize=28)
825
+ alt_graph = a_alt + b_alt + c_alt + alt_intersection
826
+ else:
827
+ alt_graph = Graphics()
828
+
829
+ # Euler's Line
830
+ if show_euler:
831
+ euler_graph = line_to_points(
832
+ (0, 0),
833
+ (
834
+ (xy[0][0]+xy[1][0]+xy[2][0])/3.0,
835
+ (xy[0][1]+xy[1][1]+xy[2][1])/3.0
836
+ ),
837
+ rgbcolor='purple',
838
+ thickness=2,
839
+ alpha=0.7
840
+ )
841
+ else:
842
+ euler_graph = Graphics()
843
+
844
+ show(
845
+ C + triangle + triangle_points + labels + ab_graph + median_graph +
846
+ pb_graph + alt_graph + incircle_graph + euler_graph,
847
+ figsize=[5,5], xmin=-1, xmax=1, ymin=-1, ymax=1
848
+ )
849
+
850
+
851
+ @library_interact(
852
+ n=lambda: slider(2, 10000, 100, default=1000, label="Number of Tosses"),
853
+ interval=lambda: range_slider(
854
+ 0.0, 1.0, default=(0.45, 0.55), label="Plotting range (y)"
855
+ ),
856
+ )
857
+ def coin(n, interval):
858
+ r"""
859
+ This interact demo simulates repeated tosses of a coin,
860
+ based on work by Lauri Ruotsalainen, 2010.
861
+
862
+ The points give the cumulative percentage of tosses which
863
+ are heads in a given run of the simulation, so that the
864
+ point `(x,y)` gives the percentage of the first `x` tosses
865
+ that were heads; this proportion should approach .5, of
866
+ course, if we are simulating a fair coin.
867
+
868
+ INPUT:
869
+
870
+ - ``n`` -- number of tosses
871
+ - ``interval`` -- plot range along vertical axis
872
+
873
+ EXAMPLES:
874
+
875
+ Invoked in the notebook, the following command will produce
876
+ the fully formatted interactive mathlet. In the command line,
877
+ it will simply return the underlying HTML and Sage code which
878
+ creates the mathlet::
879
+
880
+ sage: interacts.statistics.coin()
881
+ ...Interactive function <function coin at ...> with 2 widgets
882
+ n: IntSlider(value=1000, description='Number of Tosses', max=10000, min=2, step=100)
883
+ interval: FloatRangeSlider(value=(0.45, 0.55), description='Plotting range (y)', max=1.0)
884
+ """
885
+ from random import random
886
+ c = []
887
+ k = 0.0
888
+ for i in range(1, n + 1):
889
+ k += random()
890
+ c.append((i, k/i))
891
+ show(point(c[1:], gridlines=[None, [0.5]], pointsize=1), ymin=interval[0], ymax=interval[1])
892
+
893
+
894
+ @library_interact(
895
+ title=lambda: text_control("<h2>Bisection method</h2>"),
896
+ f=lambda: input_box("x^2-2", label="f(x)"),
897
+ interval=lambda: range_slider(-5, 5, default=(0, 4), label='range'),
898
+ d=lambda: slider(1, 8, 1, 3, label="$10^{-d}$ precision"),
899
+ maxn=lambda: slider(0, 50, 1, 10, label="max iterations"),
900
+ )
901
+ def bisection_method(title, f, interval, d, maxn):
902
+ r"""
903
+ Interact explaining the bisection method, based on similar interact
904
+ explaining secant method and Wiliam Stein's example from wiki.
905
+
906
+ INPUT:
907
+
908
+ - ``f`` -- function
909
+ - ``interval`` -- range slider for the search interval
910
+ - ``d`` -- slider for the precision (`10^{-d}`)
911
+ - ``maxn`` -- max number of iterations
912
+
913
+ EXAMPLES:
914
+
915
+ Invoked in the notebook, the following command will produce
916
+ the fully formatted interactive mathlet. In the command line,
917
+ it will simply return the underlying HTML and Sage code which
918
+ creates the mathlet::
919
+
920
+ sage: interacts.calculus.secant_method()
921
+ ...Interactive function <function secant_method at ...> with 5 widgets
922
+ title: HTMLText(value='<h2>Secant method for numerical root finding</h2>')
923
+ f: EvalText(value='x^2-2', description='f(x)', layout=Layout(max_width='81em'))
924
+ interval: IntRangeSlider(value=(0, 4), description='range', max=5, min=-5)
925
+ d: IntSlider(value=3, description='10^-d precision', max=16, min=1)
926
+ maxn: IntSlider(value=10, description='max iterations', max=15)
927
+ """
928
+ def _bisection_method(f, a, b, maxn, eps):
929
+ intervals = [(a, b)]
930
+ round = 1
931
+ two = float(2)
932
+ while True:
933
+ c = (b+a)/two
934
+ if abs(f(c)) < h or round >= maxn:
935
+ break
936
+ fa = f(a)
937
+ fb = f(b)
938
+ fc = f(c)
939
+ if abs(fc) < eps:
940
+ return c, intervals
941
+ if fa*fc < 0:
942
+ b = c
943
+ elif fc*fb < 0:
944
+ a = c
945
+ else:
946
+ raise ValueError("f must have a sign change in the interval (%s,%s)" % (a,b))
947
+ intervals.append((a, b))
948
+ round += 1
949
+ return c, intervals
950
+
951
+ x = SR.var('x')
952
+ f = symbolic_expression(f).function(x)
953
+ a, b = interval
954
+ h = 10**(-d)
955
+ try:
956
+ c, intervals = _bisection_method(f, float(a), float(b), maxn, h)
957
+ except ValueError:
958
+ print("f must have opposite sign at the endpoints of the interval")
959
+ show(plot(f, a, b, color='red'), xmin=a, xmax=b)
960
+ else:
961
+ html(r"$\text{Precision }h = 10^{-d}=10^{-%s}=%.5f$" % (d, float(h)))
962
+ html(r"${c = }%s$" % latex(c))
963
+ html(r"${f(c) = }%s" % latex(f(c)))
964
+ html(r"$%s \text{ iterations}" % len(intervals))
965
+ P = plot(f, a, b, color='red')
966
+ k = (P.ymax() - P.ymin()) / (1.5*len(intervals))
967
+ L = sum(line([(c,k*i), (d,k*i)]) for i, (c,d) in enumerate(intervals) )
968
+ L += sum(line([(c,k*i-k/4), (c,k*i+k/4)]) for i, (c,d) in enumerate(intervals) )
969
+ L += sum(line([(d,k*i-k/4), (d,k*i+k/4)]) for i, (c,d) in enumerate(intervals) )
970
+ show(P + L, xmin=a, xmax=b)
971
+
972
+
973
+ @library_interact(
974
+ title=lambda: text_control("<h2>Secant method for numerical root finding</h2>"),
975
+ f=lambda: input_box("x^2-2", label="f(x)"),
976
+ interval=lambda: range_slider(-5, 5, default=(0, 4), label='range'),
977
+ d=lambda: slider(1, 16, 1, 3, label="10^-d precision"),
978
+ maxn=lambda: slider(0, 15, 1, 10, label="max iterations"),
979
+ )
980
+ def secant_method(title, f, interval, d, maxn):
981
+ r"""
982
+ Interact explaining the secant method, based on work by
983
+ Lauri Ruotsalainen, 2010.
984
+ Originally this is based on work by William Stein.
985
+
986
+ INPUT:
987
+
988
+ - ``f`` -- function
989
+ - ``interval`` -- range slider for the search interval
990
+ - ``d`` -- slider for the precision (10^-d)
991
+ - ``maxn`` -- max number of iterations
992
+
993
+ EXAMPLES:
994
+
995
+ Invoked in the notebook, the following command will produce
996
+ the fully formatted interactive mathlet. In the command line,
997
+ it will simply return the underlying HTML and Sage code which
998
+ creates the mathlet::
999
+
1000
+ sage: interacts.calculus.secant_method()
1001
+ ...Interactive function <function secant_method at ...> with 5 widgets
1002
+ title: HTMLText(value='<h2>Secant method for numerical root finding</h2>')
1003
+ f: EvalText(value='x^2-2', description='f(x)', layout=Layout(max_width='81em'))
1004
+ interval: IntRangeSlider(value=(0, 4), description='range', max=5, min=-5)
1005
+ d: IntSlider(value=3, description='10^-d precision', max=16, min=1)
1006
+ maxn: IntSlider(value=10, description='max iterations', max=15)
1007
+ """
1008
+ def _secant_method(f, a, b, maxn, h):
1009
+ intervals = [(a,b)]
1010
+ round = 1
1011
+ while True:
1012
+ c = b-(b-a)*f(b)/(f(b)-f(a))
1013
+ if abs(f(c)) < h or round >= maxn:
1014
+ break
1015
+ a, b = b, c
1016
+ intervals.append((a,b))
1017
+ round += 1
1018
+ return c, intervals
1019
+
1020
+ x = SR.var('x')
1021
+ f = symbolic_expression(f).function(x)
1022
+ a, b = interval
1023
+ h = 10**(-d)
1024
+ if float(f(a)*f(b)) > 0:
1025
+ print("f must have opposite sign at the endpoints of the interval")
1026
+ show(plot(f, a, b, color='red'), xmin=a, xmax=b)
1027
+ else:
1028
+ c, intervals = _secant_method(f, float(a), float(b), maxn, h)
1029
+ html(r"$\text{Precision }h = 10^{-d}=10^{-%s}=%.5f$" % (d, float(h)))
1030
+ html(r"${c = }%s$" % latex(c))
1031
+ html(r"${f(c) = }%s" % latex(f(c)))
1032
+ html(r"$%s \text{ iterations}" % len(intervals))
1033
+ P = plot(f, a, b, color='red')
1034
+ k = (P.ymax() - P.ymin()) / (1.5*len(intervals))
1035
+ L = sum(line([(c,k*i), (d,k*i)]) for i, (c,d) in enumerate(intervals) )
1036
+ L += sum(line([(c,k*i-k/4), (c,k*i+k/4)]) for i, (c,d) in enumerate(intervals) )
1037
+ L += sum(line([(d,k*i-k/4), (d,k*i+k/4)]) for i, (c,d) in enumerate(intervals) )
1038
+ S = sum(line([(c,f(c)), (d,f(d)), (d-(d-c)*f(d)/(f(d)-f(c)), 0)], color='green') for (c, d) in intervals)
1039
+ show(P + L + S, xmin=a, xmax=b)
1040
+
1041
+
1042
+ @library_interact(
1043
+ title=lambda: text_control("<h2>Newton method</h2>"),
1044
+ f=lambda: input_box("x^2 - 2"),
1045
+ c=lambda: slider(-10, 10, default=6, label="Start ($x$)"),
1046
+ d=lambda: slider(1, 16, 1, 3, label="$10^{-d}$ precision"),
1047
+ maxn=lambda: slider(0, 15, 1, 10, label="max iterations"),
1048
+ interval=lambda: range_slider(-10, 10, default=(0, 6), label='Interval'),
1049
+ list_steps=lambda: checkbox(default=False, label="List steps"),
1050
+ )
1051
+ def newton_method(title, f, c, d, maxn, interval, list_steps):
1052
+ r"""
1053
+ Interact explaining the Newton method, based on work by
1054
+ Lauri Ruotsalainen, 2010.
1055
+ Originally this is based on work by William Stein.
1056
+
1057
+ INPUT:
1058
+
1059
+ - ``f`` -- function
1060
+ - ``c`` -- starting position (`x`)
1061
+ - ``d`` -- slider for the precision (`10^{-d}`)
1062
+ - ``maxn`` -- max number of iterations
1063
+ - ``interval`` -- range slider for the search interval
1064
+ - ``list_steps`` -- checkbox, if ``True`` shows the steps numerically
1065
+
1066
+ EXAMPLES:
1067
+
1068
+ Invoked in the notebook, the following command will produce
1069
+ the fully formatted interactive mathlet. In the command line,
1070
+ it will simply return the underlying HTML and Sage code which
1071
+ creates the mathlet::
1072
+
1073
+ sage: interacts.calculus.newton_method()
1074
+ ...Interactive function <function newton_method at ...> with 7 widgets
1075
+ title: HTMLText(value='<h2>Newton method</h2>')
1076
+ f: EvalText(value='x^2 - 2', description='f', layout=Layout(max_width='81em'))
1077
+ c: IntSlider(value=6, description='Start ($x$)', max=10, min=-10)
1078
+ d: IntSlider(value=3, description='$10^{-d}$ precision', max=16, min=1)
1079
+ maxn: IntSlider(value=10, description='max iterations', max=15)
1080
+ interval: IntRangeSlider(value=(0, 6), description='Interval', max=10, min=-10)
1081
+ list_steps: Checkbox(value=False, description='List steps')
1082
+ """
1083
+ def _newton_method(f, c, maxn, h):
1084
+ midpoints = [c]
1085
+ round = 1
1086
+ while True:
1087
+ c = c-f(c)/f.derivative(x)(x=c)
1088
+ midpoints.append(c)
1089
+ if f(c-h)*f(c+h) < 0 or round == maxn:
1090
+ break
1091
+ round += 1
1092
+ return c, midpoints
1093
+
1094
+ x = SR.var('x')
1095
+ f = symbolic_expression(f).function(x)
1096
+ a, b = interval
1097
+ h = 10**(-d)
1098
+ c, midpoints = _newton_method(f, float(c), maxn, 0.5 * h)
1099
+ html(r"$\text{Precision } 2h = %s$" % latex(float(h)))
1100
+ html(r"${c = }%s$" % c)
1101
+ html(r"${f(c) = }%s" % latex(f(c)))
1102
+ html(r"$%s \text{ iterations}" % len(midpoints))
1103
+ if list_steps:
1104
+ s = [["$n$", "$x_n$", "$f(x_n)$", r"$f(x_n-h)\,f(x_n+h)$"]]
1105
+ for i, c in enumerate(midpoints):
1106
+ s.append([i+1, c, f(c), (c-h)*f(c+h)])
1107
+ pretty_print(table(s, header_row=True))
1108
+ else:
1109
+ P = plot(f, x, interval, color='blue')
1110
+ L = sum(line([(c, 0), (c, f(c))], color='green') for c in midpoints[:-1])
1111
+ for i in range(len(midpoints) - 1):
1112
+ L += line([(midpoints[i], f(midpoints[i])), (midpoints[i+1], 0)], color='red')
1113
+ show(P + L, xmin=interval[0], xmax=interval[1], ymin=P.ymin(), ymax=P.ymax())
1114
+
1115
+
1116
+ @library_interact(
1117
+ title=lambda: text_control("<h2>Trapezoid integration</h2>"),
1118
+ f=lambda: input_box(default="x^2-5*x + 10", label="$f(x)=$"),
1119
+ n=lambda: slider(1, 100, 1, 5, label="# divisions"),
1120
+ interval_input=lambda: selector(
1121
+ ["from slider", "from keyboard"],
1122
+ label="Integration interval",
1123
+ buttons=True,
1124
+ ),
1125
+ interval_s=lambda: range_slider(-10, 10, default=(0, 8), label="slider: "),
1126
+ interval_g=lambda: input_grid(1, 2, default=[[0, 8]], label="keyboard: "),
1127
+ output_form=lambda: selector(
1128
+ ["traditional", "table", "none"], label="Computations form", buttons=True
1129
+ ),
1130
+ )
1131
+ def trapezoid_integration(
1132
+ title, f, n, interval_input, interval_s, interval_g, output_form
1133
+ ):
1134
+ r"""
1135
+ Interact explaining the trapezoid method for definite integrals.
1136
+
1137
+ Based on work by
1138
+ Lauri Ruotsalainen, 2010 (based on the application "Numerical integrals with various rules"
1139
+ by Marshall Hampton and Nick Alexander)
1140
+
1141
+ INPUT:
1142
+
1143
+ - ``f`` -- function of variable x to integrate
1144
+ - ``n`` -- number of divisions
1145
+ - ``interval_input`` -- switches the input for interval between slider and keyboard
1146
+ - ``interval_s`` -- slider for interval to integrate
1147
+ - ``interval_g`` -- input grid for interval to integrate
1148
+ - ``output_form`` -- the computation is formatted in a traditional form, in a table or missing
1149
+
1150
+ EXAMPLES:
1151
+
1152
+ Invoked in the notebook, the following command will produce
1153
+ the fully formatted interactive mathlet. In the command line,
1154
+ it will simply return the underlying HTML and Sage code which
1155
+ creates the mathlet::
1156
+
1157
+ sage: interacts.calculus.trapezoid_integration()
1158
+ ...Interactive function <function trapezoid_integration at ...> with 7 widgets
1159
+ title: HTMLText(value='<h2>Trapezoid integration</h2>')
1160
+ f: EvalText(value='x^2-5*x + 10', description='$f(x)=$', layout=Layout(max_width='81em'))
1161
+ n: IntSlider(value=5, description='# divisions', min=1)
1162
+ interval_input: ToggleButtons(description='Integration interval', options=('from slider', 'from keyboard'), value='from slider')
1163
+ interval_s: IntRangeSlider(value=(0, 8), description='slider: ', max=10, min=-10)
1164
+ interval_g: Grid(value=[[0, 8]], children=(Label(value='keyboard: '), VBox(children=(EvalText(value='0', layout=Layout(max_width='5em')),)), VBox(children=(EvalText(value='8', layout=Layout(max_width='5em')),))))
1165
+ output_form: ToggleButtons(description='Computations form', options=('traditional', 'table', 'none'), value='traditional')
1166
+ """
1167
+ xs = []
1168
+ ys = []
1169
+ if interval_input == 'from slider':
1170
+ interval = interval_s
1171
+ else:
1172
+ interval = interval_g[0]
1173
+ h = float(interval[1]-interval[0])/n
1174
+ x = SR.var('x')
1175
+ f = symbolic_expression(f).function(x)
1176
+
1177
+ trapezoids = Graphics()
1178
+
1179
+ for i in range(n):
1180
+ xi = interval[0] + i*h
1181
+ yi = f(xi)
1182
+ trapezoids += line([[xi, 0], [xi, yi], [xi + h, f(xi + h)],[xi + h, 0],[xi, 0]], rgbcolor=(1, 0, 0))
1183
+ xs.append(xi)
1184
+ ys.append(yi)
1185
+ xs.append(xi + h)
1186
+ ys.append(f(xi + h))
1187
+
1188
+ html(r'Function $f(x)=%s$' % latex(f(x)))
1189
+ show(plot(f, interval[0], interval[1]) + trapezoids,
1190
+ xmin=interval[0], xmax=interval[1])
1191
+
1192
+ numeric_value = integral_numerical(f, interval[0], interval[1])[0]
1193
+ approx = h * (ys[0]/2 + sum([ys[i] for i in range(1,n)]) + ys[n]/2)
1194
+
1195
+ html(r'Integral value to seven decimal places is: $\displaystyle\int_{%.2f}^{%.2f} {f(x) \, \mathrm{d}x} = %.6f$' % (
1196
+ interval[0], interval[1], N(numeric_value, digits=7))
1197
+ )
1198
+
1199
+ if output_form == 'traditional':
1200
+ sum_formula_html = r"\frac {d}{2} \cdot \left[f(x_0) + %s + f(x_{%s})\right]" % (
1201
+ ' + '.join([ "2 f(x_{%s})" % i for i in range(1,n)]),
1202
+ n
1203
+ )
1204
+ sum_placement_html = r"\frac{%.2f}{2} \cdot \left[f(%.2f) + %s + f(%.2f)\right]" % (
1205
+ h,
1206
+ N(xs[0], digits=5),
1207
+ ' + '.join([ "2 f(%.2f)" % N(i, digits=5) for i in xs[1:-1]]),
1208
+ N(xs[n], digits=5)
1209
+ )
1210
+ sum_values_html = r"\frac{%.2f}{2} \cdot \left[%.2f + %s + %.2f\right]" % (
1211
+ h,
1212
+ N(ys[0], digits=5),
1213
+ ' + '.join([ r"2\cdot %.2f" % N(i, digits=5) for i in ys[1:-1]]),
1214
+ N(ys[n], digits=5)
1215
+ )
1216
+
1217
+ html(r'''
1218
+ <div class="math">
1219
+ \begin{align*}
1220
+ \int_{%.2f}^{%.2f} {f(x) \, \mathrm{d}x}
1221
+ & \approx %s \\
1222
+ & = %s \\
1223
+ & = %s \\
1224
+ & = %s
1225
+ \end{align*}
1226
+ </div>
1227
+ ''' % (
1228
+ interval[0], interval[1],
1229
+ sum_formula_html, sum_placement_html, sum_values_html,
1230
+ N(approx, digits=7)
1231
+ ))
1232
+ elif output_form == 'table':
1233
+ s = [['$i$', '$x_i$', '$f(x_i)$', '$m$', r'$m\cdot f(x_i)$']]
1234
+ for i in range(0,n+1):
1235
+ if i == 0 or i == n:
1236
+ j = 1
1237
+ else:
1238
+ j = 2
1239
+ s.append([i, xs[i], ys[i],j,N(j*ys[i])])
1240
+ pretty_print(table(s, header_row=True))
1241
+
1242
+
1243
+ @library_interact(
1244
+ title=lambda: text_control("<h2>Simpson integration</h2>"),
1245
+ f=lambda: input_box(default='x*sin(x)+x+1', label="$f(x)=$"),
1246
+ n=lambda: slider(2, 100, 2, 6, label="# divisions"),
1247
+ interval_input=lambda: selector(
1248
+ ["from slider", "from keyboard"],
1249
+ label="Integration interval",
1250
+ buttons=True,
1251
+ ),
1252
+ interval_s=lambda: range_slider(-10, 10, default=(0, 10), label="slider: "),
1253
+ interval_g=lambda: input_grid(1, 2, default=[[0, 10]], label="keyboard: "),
1254
+ output_form=lambda: selector(
1255
+ ["traditional", "table", "none"], label="Computations form", buttons=True
1256
+ ),
1257
+ )
1258
+ def simpson_integration(
1259
+ title,
1260
+ f,
1261
+ n,
1262
+ interval_input,
1263
+ interval_s,
1264
+ interval_g,
1265
+ output_form,
1266
+ ):
1267
+ r"""
1268
+ Interact explaining the simpson method for definite integrals.
1269
+
1270
+ Based on work by
1271
+ Lauri Ruotsalainen, 2010 (based on the application "Numerical integrals with various rules"
1272
+ by Marshall Hampton and Nick Alexander)
1273
+
1274
+ INPUT:
1275
+
1276
+ - ``f`` -- function of variable x to integrate
1277
+ - ``n`` -- number of divisions (mult. of 2)
1278
+ - ``interval_input`` -- switches the input for interval between slider and keyboard
1279
+ - ``interval_s`` -- slider for interval to integrate
1280
+ - ``interval_g`` -- input grid for interval to integrate
1281
+ - ``output_form`` -- the computation is formatted in a traditional form, in a table or missing
1282
+
1283
+ EXAMPLES:
1284
+
1285
+ Invoked in the notebook, the following command will produce
1286
+ the fully formatted interactive mathlet. In the command line,
1287
+ it will simply return the underlying HTML and Sage code which
1288
+ creates the mathlet::
1289
+
1290
+ sage: interacts.calculus.simpson_integration()
1291
+ ...Interactive function <function simpson_integration at ...> with 7 widgets
1292
+ title: HTMLText(value='<h2>Simpson integration</h2>')
1293
+ f: EvalText(value='x*sin(x)+x+1', description='$f(x)=$', layout=Layout(max_width='81em'))
1294
+ n: IntSlider(value=6, description='# divisions', min=2, step=2)
1295
+ interval_input: ToggleButtons(description='Integration interval', options=('from slider', 'from keyboard'), value='from slider')
1296
+ interval_s: IntRangeSlider(value=(0, 10), description='slider: ', max=10, min=-10)
1297
+ interval_g: Grid(value=[[0, 10]], children=(Label(value='keyboard: '), VBox(children=(EvalText(value='0', layout=Layout(max_width='5em')),)), VBox(children=(EvalText(value='10', layout=Layout(max_width='5em')),))))
1298
+ output_form: ToggleButtons(description='Computations form', options=('traditional', 'table', 'none'), value='traditional')
1299
+ """
1300
+ x = SR.var("x")
1301
+ f = symbolic_expression(f).function(x)
1302
+ if interval_input == 'from slider':
1303
+ interval = interval_s
1304
+ else:
1305
+ interval = interval_g[0]
1306
+
1307
+ def parabola(a, b, c):
1308
+ from sage.symbolic.relation import solve
1309
+ A, B, C = SR.var("A, B, C")
1310
+ K = solve([A*a[0]**2+B*a[0]+C == a[1], A*b[0]**2+B*b[0]+C == b[1], A*c[0]**2+B*c[0]+C == c[1]], [A, B, C], solution_dict=True)[0]
1311
+ f = K[A]*x**2+K[B]*x+K[C]
1312
+ return f
1313
+ xs = []
1314
+ ys = []
1315
+ dx = float(interval[1]-interval[0])/n
1316
+
1317
+ for i in range(n+1):
1318
+ xs.append(interval[0] + i*dx)
1319
+ ys.append(f(x=xs[-1]))
1320
+
1321
+ parabolas = Graphics()
1322
+ lines = Graphics()
1323
+
1324
+ for i in range(0, n-1, 2):
1325
+ p = parabola((xs[i],ys[i]),(xs[i+1],ys[i+1]),(xs[i+2],ys[i+2]))
1326
+ parabolas += plot(p(x=x), (x, xs[i], xs[i+2]), color='red')
1327
+ lines += line([(xs[i],ys[i]), (xs[i],0), (xs[i+2],0)],color='red')
1328
+ lines += line([(xs[i+1],ys[i+1]), (xs[i+1],0)], linestyle='-.', color='red')
1329
+
1330
+ lines += line([(xs[-1],ys[-1]), (xs[-1],0)], color='red')
1331
+
1332
+ html(r'Function $f(x)=%s$' % latex(f(x)))
1333
+
1334
+ show(plot(f(x), x, interval[0], interval[1]) + parabolas + lines,
1335
+ xmin=interval[0], xmax=interval[1])
1336
+
1337
+ numeric_value = integral_numerical(f,interval[0],interval[1])[0]
1338
+ approx = dx/3 * (ys[0] + sum([4*ys[i] for i in range(1,n,2)]) + sum([2*ys[i] for i in range(2,n,2)]) + ys[n])
1339
+
1340
+ html(r'Integral value to seven decimal places is: $\displaystyle\int_{%.2f}^{%.2f} {f(x) \, \mathrm{d}x} = %.6f$' %
1341
+ (interval[0],interval[1],
1342
+ N(numeric_value,digits=7)))
1343
+
1344
+ if output_form == 'traditional':
1345
+ sum_formula_html = r"\frac{d}{3} \cdot \left[ f(x_0) + %s + f(x_{%s})\right]" % (
1346
+ ' + '.join(r"%s \cdot f(x_{%s})" % (i % 2 * (-2) + 4, i + 1)
1347
+ for i in range(0,n-1)),
1348
+ n
1349
+ )
1350
+
1351
+ sum_placement_html = r"\frac{%.2f}{3} \cdot \left[ f(%.2f) + %s + f(%.2f)\right]" % (
1352
+ dx,
1353
+ N(xs[0],digits=5),
1354
+ ' + '.join(r"%s \cdot f(%.2f)" % (i % 2 * (-2) + 4, N(xk, digits=5))
1355
+ for i, xk in enumerate(xs[1:-1])),
1356
+ N(xs[n],digits=5)
1357
+ )
1358
+
1359
+ sum_values_html = r"\frac{%.2f}{3} \cdot \left[ %s %s %s\right]" % (
1360
+ dx,
1361
+ "%.2f + " % N(ys[0],digits=5),
1362
+ ' + '.join(r"%s \cdot %.2f" % (i % 2 * (-2) + 4, N(yk, digits=5))
1363
+ for i, yk in enumerate(ys[1:-1])),
1364
+ " + %.2f" % N(ys[n],digits=5)
1365
+ )
1366
+
1367
+ html(r'''
1368
+ <div class="math">
1369
+ \begin{align*}
1370
+ \int_{%.2f}^{%.2f} {f(x) \, \mathrm{d}x}
1371
+ & \approx %s \\
1372
+ & = %s \\
1373
+ & = %s \\
1374
+ & = %.6f
1375
+ \end{align*}
1376
+ </div>
1377
+ ''' % (
1378
+ interval[0], interval[1],
1379
+ sum_formula_html, sum_placement_html, sum_values_html,
1380
+ N(approx,digits=7)
1381
+ ))
1382
+ elif output_form == 'table':
1383
+ s = [['$i$', '$x_i$', '$f(x_i)$', '$m$', r'$m\cdot f(x_i)$']]
1384
+ for i in range(n + 1):
1385
+ if i == 0 or i == n:
1386
+ j = 1
1387
+ else:
1388
+ j = (i + 1) % 2 * (-2) + 4
1389
+ s.append([i, xs[i], ys[i], j, N(j*ys[i])])
1390
+ s.append(['', '', '', r'$\sum$', '$%s$' % latex(3/dx*approx)])
1391
+ pretty_print(table(s, header_row=True))
1392
+ html(r'$\int_{%.2f}^{%.2f} {f(x) \, \mathrm{d}x}\approx\frac {%.2f}{3}\cdot %s=%s$' %
1393
+ (interval[0], interval[1],dx,latex(3/dx*approx),latex(approx)))
1394
+
1395
+
1396
+ @library_interact(
1397
+ title=lambda: text_control("<h2>Riemann integral with random sampling</h2>"),
1398
+ f=lambda: input_box("x^2+1", label='$f(x)=$', width=40),
1399
+ n=lambda: slider(1, 30, 1, 5, label="# divisions"),
1400
+ hr1=lambda: text_control("<hr>"),
1401
+ interval_input=lambda: selector(
1402
+ ["from slider", "from keyboard"],
1403
+ label="Integration interval",
1404
+ buttons=True,
1405
+ ),
1406
+ interval_s=lambda: range_slider(-5, 10, default=(0, 2), label="slider: "),
1407
+ interval_g=lambda: input_grid(1, 2, default=[[0, 2]], label="keyboard: "),
1408
+ hr2=lambda: text_control("<hr>"),
1409
+ list_table=lambda: checkbox(default=False, label="List table"),
1410
+ auto_update=lambda: False,
1411
+ )
1412
+ def riemann_sum(
1413
+ title,
1414
+ f,
1415
+ n,
1416
+ hr1,
1417
+ interval_input,
1418
+ interval_s,
1419
+ interval_g,
1420
+ hr2,
1421
+ list_table,
1422
+ auto_update=False,
1423
+ ):
1424
+ r"""
1425
+ Interact explaining the definition of Riemann integral.
1426
+
1427
+ INPUT:
1428
+
1429
+ - ``f`` -- function of variable x to integrate
1430
+ - ``n`` -- number of divisions
1431
+ - ``interval_input`` -- switches the input for interval between slider and keyboard
1432
+ - ``interval_s`` -- slider for interval to integrate
1433
+ - ``interval_g`` -- input grid for interval to integrate
1434
+ - ``list_table`` -- print table with values of the function
1435
+
1436
+ EXAMPLES:
1437
+
1438
+ Invoked in the notebook, the following command will produce
1439
+ the fully formatted interactive mathlet. In the command line,
1440
+ it will simply return the underlying HTML and Sage code which
1441
+ creates the mathlet::
1442
+
1443
+ sage: interacts.calculus.riemann_sum()
1444
+ Manual interactive function <function riemann_sum at ...> with 9 widgets
1445
+ title: HTMLText(value='<h2>Riemann integral with random sampling</h2>')
1446
+ f: EvalText(value='x^2+1',... description='$f(x)=$', layout=Layout(max_width='41em'))
1447
+ n: IntSlider(value=5, description='# divisions', max=30, min=1)
1448
+ hr1: HTMLText(value='<hr>')
1449
+ interval_input: ToggleButtons(description='Integration interval', options=('from slider', 'from keyboard'), value='from slider')
1450
+ interval_s: IntRangeSlider(value=(0, 2), description='slider: ', max=10, min=-5)
1451
+ interval_g: Grid(value=[[0, 2]], children=(Label(value='keyboard: '), VBox(children=(EvalText(value='0', layout=Layout(max_width='5em')),)), VBox(children=(EvalText(value='2', layout=Layout(max_width='5em')),))))
1452
+ hr2: HTMLText(value='<hr>')
1453
+ list_table: Checkbox(value=False, description='List table')
1454
+
1455
+ AUTHORS:
1456
+
1457
+ - Robert Marik (2010-08)
1458
+ """
1459
+ x = SR.var('x')
1460
+ from random import random
1461
+ if interval_input == 'from slider':
1462
+ a = interval_s[0]
1463
+ b = interval_s[1]
1464
+ else:
1465
+ a = interval_g[0][0]
1466
+ b = interval_g[0][1]
1467
+ func = symbolic_expression(f).function(x)
1468
+ division = [a]+[a+random()*(b-a) for i in range(n-1)]+[b]
1469
+ division = sorted(division)
1470
+ xs = [division[i]+random()*(division[i+1]-division[i]) for i in range(n)]
1471
+ ys = [func(x_val) for x_val in xs]
1472
+ rects = Graphics()
1473
+ for i in range(n):
1474
+ body = [[division[i], 0], [division[i], ys[i]],
1475
+ [division[i+1], ys[i]], [division[i+1], 0]]
1476
+ if ys[i].n() > 0:
1477
+ color_rect = 'green'
1478
+ else:
1479
+ color_rect = 'red'
1480
+ rects = rects + polygon2d(body, rgbcolor=color_rect, alpha=0.1)\
1481
+ + point((xs[i], ys[i]), rgbcolor=(1, 0, 0))\
1482
+ + line(body, rgbcolor='black', zorder=-1)
1483
+ html('<small>Adjust your data and click Update button. Click repeatedly for another random values.</small>')
1484
+
1485
+ show(plot(func(x),(x,a,b),zorder=5) + rects)
1486
+ delka_intervalu = [division[i+1]-division[i] for i in range(n)]
1487
+ if list_table:
1488
+ pretty_print(table([
1489
+ ["$i$", "$[x_{i-1},x_i]$", r"$\eta_i$", r"$f(\eta_i)$", "$x_{i}-x_{i-1}$"]
1490
+ ] + [
1491
+ [i+1,[division[i],division[i+1]],xs[i],ys[i],delka_intervalu[i]] for i in range(n)
1492
+ ], header_row=True))
1493
+
1494
+ html(r'Riemann sum: $\displaystyle\sum_{i=1}^{%s} f(\eta_i)(x_i-x_{i-1})=%s$ ' %
1495
+ (latex(n),latex(sum([ys[i]*delka_intervalu[i] for i in range(n)]))))
1496
+ html(r'Exact value of the integral $\displaystyle\int_{%s}^{%s}%s\,\mathrm{d}x=%s$' %
1497
+ (latex(a),latex(b),latex(func(x)),latex(integral_numerical(func(x),a,b)[0])))
1498
+
1499
+
1500
+ x = SR.var("x")
1501
+
1502
+
1503
+ @library_interact(
1504
+ f=lambda: sin(x),
1505
+ g=lambda: cos(x),
1506
+ xrange=lambda: range_slider(-3, 3, default=(0, 1), label='x-range'),
1507
+ yrange=lambda: "auto",
1508
+ a=lambda: 1,
1509
+ action=lambda: selector(
1510
+ [
1511
+ "f",
1512
+ "df/dx",
1513
+ "int f",
1514
+ "num f",
1515
+ "den f",
1516
+ "1/f",
1517
+ "finv",
1518
+ "f+a",
1519
+ "f-a",
1520
+ "f*a",
1521
+ "f/a",
1522
+ "f^a",
1523
+ "f(x+a)",
1524
+ "f(x*a)",
1525
+ "f+g",
1526
+ "f-g",
1527
+ "f*g",
1528
+ "f/g",
1529
+ "f(g)",
1530
+ ],
1531
+ width=15,
1532
+ nrows=5,
1533
+ label="h = ",
1534
+ ),
1535
+ do_plot=lambda: ("Draw Plots", True),
1536
+ )
1537
+ def function_tool(f, g, xrange, yrange, a, action, do_plot):
1538
+ r"""
1539
+ `Function Plotting Tool <http://wiki.sagemath.org/interact/calculus#Functiontool>`_
1540
+ (by William Stein (?))
1541
+
1542
+ INPUT:
1543
+
1544
+ - ``f`` -- function f(x)
1545
+ - ``g`` -- function g(x)
1546
+ - ``xrange`` -- range for plotting (x)
1547
+ - ``yrange`` -- range for plotting ('auto' is default, otherwise a tuple)
1548
+ - ``a`` -- factor ``a``
1549
+ - ``action`` -- select given operation on or combination of functions
1550
+ - ``do_plot`` -- if ``True``, a plot is drawn
1551
+
1552
+ EXAMPLES:
1553
+
1554
+ Invoked in the notebook, the following command will produce
1555
+ the fully formatted interactive mathlet. In the command line,
1556
+ it will simply return the underlying HTML and Sage code which
1557
+ creates the mathlet::
1558
+
1559
+ sage: interacts.calculus.function_tool() # long time
1560
+ ...Interactive function <function function_tool at ...> with 7 widgets
1561
+ f: EvalText(value='sin(x)', description='f')
1562
+ g: EvalText(value='cos(x)', description='g')
1563
+ xrange: IntRangeSlider(value=(0, 1), description='x-range', max=3, min=-3)
1564
+ yrange: Text(value='auto', description='yrange')
1565
+ a: IntSlider(value=1, description='a', max=3, min=-1)
1566
+ action: ToggleButtons(description='h = ', options=('f', 'df/dx', 'int f', 'num f', 'den f', '1/f', 'finv', 'f+a', 'f-a', 'f*a', 'f/a', 'f^a', 'f(x+a)', 'f(x*a)', 'f+g', 'f-g', 'f*g', 'f/g', 'f(g)'), value='f')
1567
+ do_plot: Checkbox(value=True, description='Draw Plots')
1568
+ """
1569
+ x = SR.var('x')
1570
+ try:
1571
+ f = SR(f)
1572
+ g = SR(g)
1573
+ a = SR(a)
1574
+ except TypeError as msg:
1575
+ print(msg[-200:])
1576
+ print("Unable to make sense of f,g, or a as symbolic expressions in single variable x.")
1577
+ return
1578
+ if not (isinstance(xrange, tuple) and len(xrange) == 2):
1579
+ xrange = (0, 1)
1580
+ h = 0
1581
+ lbl = ''
1582
+ if action == 'f':
1583
+ h = f
1584
+ lbl = 'f'
1585
+ elif action == 'df/dx':
1586
+ h = f.derivative(x)
1587
+ lbl = r'\frac{\mathrm{d}f}{\mathrm{d}x}'
1588
+ elif action == 'int f':
1589
+ h = f.integrate(x)
1590
+ lbl = r'\int f \,\mathrm{d}x'
1591
+ elif action == 'num f':
1592
+ h = f.numerator()
1593
+ lbl = r'\text{numer(f)}'
1594
+ elif action == 'den f':
1595
+ h = f.denominator()
1596
+ lbl = r'\text{denom(f)}'
1597
+ elif action == '1/f':
1598
+ h = 1/f
1599
+ lbl = r'\frac{1}{f}'
1600
+ elif action == 'finv':
1601
+ h = solve(f == SR.var('y'), x)[0].rhs()
1602
+ lbl = 'f^{-1}(y)'
1603
+ elif action == 'f+a':
1604
+ h = f+a
1605
+ lbl = 'f + a'
1606
+ elif action == 'f-a':
1607
+ h = f-a
1608
+ lbl = 'f - a'
1609
+ elif action == 'f*a':
1610
+ h = f*a
1611
+ lbl = r'f \times a'
1612
+ elif action == 'f/a':
1613
+ h = f/a
1614
+ lbl = r'\frac{f}{a}'
1615
+ elif action == 'f^a':
1616
+ h = f**a
1617
+ lbl = 'f^a'
1618
+ elif action == 'f^a':
1619
+ h = f**a
1620
+ lbl = 'f^a'
1621
+ elif action == 'f(x+a)':
1622
+ h = f.subs(x=x+a)
1623
+ lbl = 'f(x+a)'
1624
+ elif action == 'f(x*a)':
1625
+ h = f.subs(x=x*a)
1626
+ lbl = 'f(xa)'
1627
+ elif action == 'f+g':
1628
+ h = f+g
1629
+ lbl = 'f + g'
1630
+ elif action == 'f-g':
1631
+ h = f-g
1632
+ lbl = 'f - g'
1633
+ elif action == 'f*g':
1634
+ h = f*g
1635
+ lbl = r'f \times g'
1636
+ elif action == 'f/g':
1637
+ h = f/g
1638
+ lbl = r'\frac{f}{g}'
1639
+ elif action == 'f(g)':
1640
+ h = f(g)
1641
+ lbl = 'f(g)'
1642
+ html('<center><font color="red">$f = %s$</font></center>' % latex(f))
1643
+ html('<center><font color="green">$g = %s$</font></center>' % latex(g))
1644
+ html('<center><font color="blue"><b>$h = %s = %s$</b></font></center>' % (lbl, latex(h)))
1645
+ if do_plot:
1646
+ P = plot(f, xrange, color='red', thickness=2) + \
1647
+ plot(g, xrange, color='green', thickness=2) + \
1648
+ plot(h, xrange, color='blue', thickness=2)
1649
+ if yrange == 'auto':
1650
+ show(P, xmin=xrange[0], xmax=xrange[1])
1651
+ else:
1652
+ yrange = sage_eval(yrange)
1653
+ show(P, xmin=xrange[0], xmax=xrange[1], ymin=yrange[0], ymax=yrange[1])
1654
+
1655
+
1656
+ @library_interact(
1657
+ expo=lambda: slider(-10, 10, 0.1, 2),
1658
+ c_real=lambda: slider(-2, 2, 0.01, 0.5, label="real part const."),
1659
+ c_imag=lambda: slider(-2, 2, 0.01, 0.5, label="imag part const."),
1660
+ iterations=lambda: slider(1, 100, 1, 20, label="# iterations"),
1661
+ zoom_x=lambda: range_slider(-2, 2, 0.01, (-1.5, 1.5), label="Zoom X"),
1662
+ zoom_y=lambda: range_slider(-2, 2, 0.01, (-1.5, 1.5), label="Zoom Y"),
1663
+ plot_points=lambda: slider(20, 400, 20, default=150, label="plot points"),
1664
+ dpi=lambda: slider(20, 200, 10, default=80, label='dpi'),
1665
+ )
1666
+ def julia(expo, c_real, c_imag, iterations, zoom_x, zoom_y, plot_points, dpi):
1667
+ r"""
1668
+ Julia Fractal, based on
1669
+ `Julia by Harald Schilly <http://wiki.sagemath.org/interact/fractal#Julia>`_.
1670
+
1671
+ INPUT:
1672
+
1673
+ - ``exponent`` -- exponent ``e`` in `z^e+c`
1674
+ - ``c_real`` -- real part of the constant ``c``
1675
+ - ``c_imag`` -- imaginary part of the constant ``c``
1676
+ - ``iterations`` -- number of iterations
1677
+ - ``zoom_x`` -- range slider for zoom in x direction
1678
+ - ``zoom_y`` -- range slider for zoom in y direction
1679
+ - ``plot_points`` -- number of points to plot
1680
+ - ``dpi`` -- dots-per-inch parameter for the plot
1681
+
1682
+ EXAMPLES:
1683
+
1684
+ Invoked in the notebook, the following command will produce
1685
+ the fully formatted interactive mathlet. In the command line,
1686
+ it will simply return the underlying HTML and Sage code which
1687
+ creates the mathlet::
1688
+
1689
+ sage: interacts.fractals.julia() # long time
1690
+ ...Interactive function <function julia at ...> with 8 widgets
1691
+ expo: FloatSlider(value=2.0, description='expo', max=10.0, min=-10.0)
1692
+ c_real: FloatSlider(value=0.5, description='real part const.', max=2.0, min=-2.0, step=0.01)
1693
+ c_imag: FloatSlider(value=0.5, description='imag part const.', max=2.0, min=-2.0, step=0.01)
1694
+ iterations: IntSlider(value=20, description='# iterations', min=1)
1695
+ zoom_x: FloatRangeSlider(value=(-1.5, 1.5), description='Zoom X', max=2.0, min=-2.0, step=0.01)
1696
+ zoom_y: FloatRangeSlider(value=(-1.5, 1.5), description='Zoom Y', max=2.0, min=-2.0, step=0.01)
1697
+ plot_points: IntSlider(value=150, description='plot points', max=400, min=20, step=20)
1698
+ dpi: IntSlider(value=80, description='dpi', max=200, min=20, step=10)
1699
+ """
1700
+ z = SR.var('z')
1701
+ I = CDF.gen()
1702
+ f = symbolic_expression(z**expo + c_real + c_imag*I).function(z)
1703
+ ff_j = fast_callable(f, vars=[z], domain=CDF)
1704
+
1705
+ from sage.interacts.library_cython import julia
1706
+
1707
+ html('<h2>Julia Fractal</h2>')
1708
+ html(r'Recursive Formula: $z \leftarrow z^{%.2f} + (%.2f+%.2f*\mathbb{I})$' % (expo, c_real, c_imag))
1709
+ complex_plot(lambda z: julia(ff_j, z, iterations), zoom_x, zoom_y, plot_points=plot_points, dpi=dpi).show(frame=True, aspect_ratio=1)
1710
+
1711
+
1712
+ @library_interact(
1713
+ expo=lambda: slider(-10, 10, 0.1, 2),
1714
+ iterations=lambda: slider(1, 100, 1, 20, label="# iterations"),
1715
+ zoom_x=lambda: range_slider(-2, 2, 0.01, (-2, 1), label="Zoom X"),
1716
+ zoom_y=lambda: range_slider(-2, 2, 0.01, (-1.5, 1.5), label="Zoom Y"),
1717
+ plot_points=lambda: slider(20, 400, 20, default=150, label="plot points"),
1718
+ dpi=lambda: slider(20, 200, 10, default=80, label='dpi'),
1719
+ )
1720
+ def mandelbrot(expo, iterations, zoom_x, zoom_y, plot_points, dpi):
1721
+ r"""
1722
+ Mandelbrot Fractal, based on
1723
+ `Mandelbrot by Harald Schilly <http://wiki.sagemath.org/interact/fractal#Mandelbrot>`_.
1724
+
1725
+ INPUT:
1726
+
1727
+ - ``exponent`` -- exponent ``e`` in `z^e+c`
1728
+ - ``iterations`` -- number of iterations
1729
+ - ``zoom_x`` -- range slider for zoom in x direction
1730
+ - ``zoom_y`` -- range slider for zoom in y direction
1731
+ - ``plot_points`` -- number of points to plot
1732
+ - ``dpi`` -- dots-per-inch parameter for the plot
1733
+
1734
+ EXAMPLES:
1735
+
1736
+ Invoked in the notebook, the following command will produce
1737
+ the fully formatted interactive mathlet. In the command line,
1738
+ it will simply return the underlying HTML and Sage code which
1739
+ creates the mathlet::
1740
+
1741
+ sage: interacts.fractals.mandelbrot() # long time
1742
+ ...Interactive function <function mandelbrot at ...> with 6 widgets
1743
+ expo: FloatSlider(value=2.0, description='expo', max=10.0, min=-10.0)
1744
+ iterations: IntSlider(value=20, description='# iterations', min=1)
1745
+ zoom_x: FloatRangeSlider(value=(-2.0, 1.0), description='Zoom X', max=2.0, min=-2.0, step=0.01)
1746
+ zoom_y: FloatRangeSlider(value=(-1.5, 1.5), description='Zoom Y', max=2.0, min=-2.0, step=0.01)
1747
+ plot_points: IntSlider(value=150, description='plot points', max=400, min=20, step=20)
1748
+ dpi: IntSlider(value=80, description='dpi', max=200, min=20, step=10)
1749
+ """
1750
+ x, z, c = SR.var('x, z, c')
1751
+ f = symbolic_expression(z**expo + c).function(z, c)
1752
+ ff_m = fast_callable(f, vars=[z,c], domain=CDF)
1753
+
1754
+ from sage.interacts.library_cython import mandel
1755
+
1756
+ html('<h2>Mandelbrot Fractal</h2>')
1757
+ html(r'Recursive Formula: $z \leftarrow z^{%.2f} + c$ for $c \in \mathbb{C}$' % expo)
1758
+ complex_plot(lambda z: mandel(ff_m, z, iterations), zoom_x, zoom_y, plot_points=plot_points, dpi=dpi).show(frame=True, aspect_ratio=1)
1759
+
1760
+
1761
+ @library_interact(
1762
+ N=lambda: slider(1, 500, 1, label="Number of iterations", default=100),
1763
+ rule_number=lambda: slider(0, 255, 1, default=110, label="Rule number"),
1764
+ size=lambda: slider(1, 11, step_size=1, default=6, label="size of graphic"),
1765
+ )
1766
+ def cellular_automaton(N, rule_number, size):
1767
+ r"""
1768
+ Yields a matrix showing the evolution of a
1769
+ `Wolfram's cellular automaton <http://mathworld.wolfram.com/CellularAutomaton.html>`_.
1770
+
1771
+ `Based on work by Pablo Angulo <http://wiki.sagemath.org/interact/misc#CellularAutomata>`_.
1772
+
1773
+ INPUT:
1774
+
1775
+ - ``N`` -- iterations
1776
+ - ``rule_number`` -- rule number (0 to 255)
1777
+ - ``size`` -- size of the shown picture
1778
+
1779
+ EXAMPLES:
1780
+
1781
+ Invoked in the notebook, the following command will produce
1782
+ the fully formatted interactive mathlet. In the command line,
1783
+ it will simply return the underlying HTML and Sage code which
1784
+ creates the mathlet::
1785
+
1786
+ sage: interacts.fractals.cellular_automaton() # long time
1787
+ ...Interactive function <function cellular_automaton at ...> with 3 widgets
1788
+ N: IntSlider(value=100, description='Number of iterations', max=500, min=1)
1789
+ rule_number: IntSlider(value=110, description='Rule number', max=255)
1790
+ size: IntSlider(value=6, description='size of graphic', max=11, min=1)
1791
+ """
1792
+ from sage.rings.integer import Integer
1793
+ if not 0 <= rule_number <= 255:
1794
+ raise ValueError('Invalid rule number')
1795
+ binary_digits = Integer(rule_number).digits(base=2)
1796
+ rule = binary_digits + [0]*(8-len(binary_digits))
1797
+
1798
+ html('<h2>Cellular Automaton</h2>' +
1799
+ '<div style="white-space: normal;">"A cellular automaton is a collection of "colored" cells \
1800
+ on a grid of specified shape that evolves through a number of \
1801
+ discrete time steps according to a set of rules based on the \
1802
+ states of neighboring cells." &mdash; \
1803
+ <a target="_blank" href="http://mathworld.wolfram.com/CellularAutomaton.html">Mathworld,\
1804
+ Cellular Automaton</a></div>\
1805
+ <div>Rule %s expands to %s</div>' % (rule_number, ''.join(map(str,rule)))
1806
+ )
1807
+
1808
+ from sage.interacts.library_cython import cellular
1809
+ M = cellular(rule, N)
1810
+ plot_M = matrix_plot(M, cmap='binary')
1811
+ plot_M.show(figsize=[size,size])
1812
+
1813
+
1814
+ @library_interact(
1815
+ interval=lambda: range_slider(1, 4000, 10, default=(1, 1000), label='range'),
1816
+ show_factors=lambda: True,
1817
+ highlight_primes=lambda: True,
1818
+ show_curves=lambda: True,
1819
+ n=lambda: slider(1, 200, 1, default=89, label="number $n$"),
1820
+ dpi=lambda: slider(10, 300, 10, default=100, label='dpi'),
1821
+ )
1822
+ def polar_prime_spiral(interval, show_factors, highlight_primes, show_curves, n, dpi):
1823
+ r"""
1824
+ Polar Prime Spiral interact, based on work by David Runde.
1825
+
1826
+ For more information about the factors in the spiral,
1827
+ `visit John Williamson's website <http://www.dcs.gla.ac.uk/~jhw/spirals/index.html>`_.
1828
+
1829
+ INPUT:
1830
+
1831
+ - ``interval`` -- range slider to specify start and end
1832
+ - ``show_factors`` -- if ``True``, show factors
1833
+ - ``highlight_primes`` -- if ``True``, prime numbers are highlighted
1834
+ - ``show_curves`` -- if ``True``, curves are plotted
1835
+ - ``n`` -- number `n`
1836
+ - ``dpi`` -- dots per inch resolution for plotting
1837
+
1838
+ EXAMPLES:
1839
+
1840
+ Invoked in the notebook, the following command will produce
1841
+ the fully formatted interactive mathlet. In the command line,
1842
+ it will simply return the underlying HTML and Sage code which
1843
+ creates the mathlet::
1844
+
1845
+ sage: sage.interacts.algebra.polar_prime_spiral() # long time
1846
+ ...Interactive function <function polar_prime_spiral at ...> with 6 widgets
1847
+ interval: IntRangeSlider(value=(1, 1000), description='range', max=4000, min=1, step=10)
1848
+ show_factors: Checkbox(value=True, description='show_factors')
1849
+ highlight_primes: Checkbox(value=True, description='highlight_primes')
1850
+ show_curves: Checkbox(value=True, description='show_curves')
1851
+ n: IntSlider(value=89, description='number $n$', max=200, min=1)
1852
+ dpi: IntSlider(value=100, description='dpi', max=300, min=10, step=10)
1853
+ """
1854
+ html('<h2>Polar Prime Spiral</h2> \
1855
+ <div style="white-space: normal;">\
1856
+ For more information about the factors in the spiral, visit \
1857
+ <a href="http://www.dcs.gla.ac.uk/~jhw/spirals/index.html" target="_blank">\
1858
+ Number Spirals by John Williamson</a>.</div>'
1859
+ )
1860
+
1861
+ start, end = interval
1862
+ from sage.ext.fast_eval import fast_float
1863
+ from math import ceil
1864
+ from sage.plot.colors import hue
1865
+
1866
+ if start < 1 or end <= start:
1867
+ print("invalid start or end value")
1868
+ return
1869
+ if n > end:
1870
+ print("WARNING: n is greater than end value")
1871
+ return
1872
+ if n < start:
1873
+ print("n < start value")
1874
+ return
1875
+ nn = SR.var('nn')
1876
+ f1 = fast_float(sqrt(nn)*cos(2*pi*sqrt(nn)), 'nn')
1877
+ f2 = fast_float(sqrt(nn)*sin(2*pi*sqrt(nn)), 'nn')
1878
+ f = lambda x: (f1(x), f2(x))
1879
+
1880
+ list = []
1881
+ list2 = []
1882
+ if not show_factors:
1883
+ for i in srange(start, end, include_endpoint=True):
1884
+ if Integer(i).is_pseudoprime():
1885
+ list.append(f(i-start+1)) # primes list
1886
+ else:
1887
+ list2.append(f(i-start+1)) # composites list
1888
+ P = points(list)
1889
+ R = points(list2, alpha=.1) # faded composites
1890
+ else:
1891
+ for i in srange(start, end, include_endpoint=True):
1892
+ # Resize each of the dots depending of the number of factors of each number
1893
+ list.append(disk((f(i-start+1)),0.05*pow(2,len(factor(i))-1), (0,2*pi)))
1894
+ if Integer(i).is_pseudoprime() and highlight_primes:
1895
+ list2.append(f(i-start+1))
1896
+ P = Graphics()
1897
+ for g in list:
1898
+ P += g
1899
+ p_size = 5 # the orange dot size of the prime markers
1900
+ if not highlight_primes:
1901
+ list2 = [(f(n-start+1))]
1902
+ R = points(list2, hue=.1, pointsize=p_size)
1903
+
1904
+ if n > 0:
1905
+ html('$n = %s$' % factor(n))
1906
+
1907
+ p = 1
1908
+ # The X which marks the given n
1909
+ W1 = disk((f(n-start+1)), p, (pi/6, 2*pi/6), alpha=.1)
1910
+ W2 = disk((f(n-start+1)), p, (4*pi/6, 5*pi/6), alpha=.1)
1911
+ W3 = disk((f(n-start+1)), p, (7*pi/6, 8*pi/6), alpha=.1)
1912
+ W4 = disk((f(n-start+1)), p, (10*pi/6, 11*pi/6), alpha=.1)
1913
+ Q = W1 + W2 + W3 + W4
1914
+
1915
+ n -= start - 1 # offset n for different start values to ensure accurate plotting
1916
+ if show_curves:
1917
+ begin_curve = 0
1918
+ t = SR.var('t')
1919
+ a = 1.0
1920
+ b = 0.0
1921
+ S = int(sqrt(n))
1922
+ if n <= S * (S + 1):
1923
+ c = n - S**2
1924
+ else:
1925
+ c = n - (S + 1)**2
1926
+ c2 = n - S * (S + 1)
1927
+ html('Pink Curve: $n^2 + %s$' % c)
1928
+ html('Green Curve: $n^2 + n + %s$' % c2)
1929
+ m = SR.var('m')
1930
+ g = symbolic_expression(a*m**2+b*m+c).function(m)
1931
+ r = symbolic_expression(sqrt(g(m))).function(m)
1932
+ theta = symbolic_expression(r(m) - m*sqrt(a)).function(m)
1933
+ S1 = parametric_plot(((r(t))*cos(2*pi*(theta(t))),(r(t))*sin(2*pi*(theta(t)))),
1934
+ (begin_curve, ceil(sqrt(end-start))),
1935
+ color=hue(0.8), thickness=.3) # pink line
1936
+
1937
+ b = 1
1938
+ c = c2
1939
+ g = symbolic_expression(a*m**2+b*m+c).function(m)
1940
+ r = symbolic_expression(sqrt(g(m))).function(m)
1941
+ theta = symbolic_expression(r(m) - m*sqrt(a)).function(m)
1942
+ S2 = parametric_plot(((r(t))*cos(2*pi*(theta(t))),(r(t))*sin(2*pi*(theta(t)))),
1943
+ (begin_curve, ceil(sqrt(end-start))),
1944
+ color=hue(0.6), thickness=.3) # green line
1945
+
1946
+ show(R+P+S1+S2+Q, aspect_ratio=1, axes=False, dpi=dpi)
1947
+ else:
1948
+ show(R+P+Q, aspect_ratio=1, axes=False, dpi=dpi)
1949
+ else:
1950
+ show(R+P, aspect_ratio=1, axes=False, dpi=dpi)