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.
- passagemath_standard_no_symbolics-10.6.31rc3.data/scripts/sage-grep +5 -0
- passagemath_standard_no_symbolics-10.6.31rc3.data/scripts/sage-grepdoc +5 -0
- passagemath_standard_no_symbolics-10.6.31rc3.data/scripts/sage-list-packages +103 -0
- passagemath_standard_no_symbolics-10.6.31rc3.dist-info/METADATA +151 -0
- passagemath_standard_no_symbolics-10.6.31rc3.dist-info/RECORD +82 -0
- passagemath_standard_no_symbolics-10.6.31rc3.dist-info/WHEEL +6 -0
- passagemath_standard_no_symbolics-10.6.31rc3.dist-info/top_level.txt +1 -0
- sage/all.py +207 -0
- sage/all_cmdline.py +36 -0
- sage/cli/__init__.py +61 -0
- sage/cli/__main__.py +5 -0
- sage/cli/eval_cmd.py +45 -0
- sage/cli/eval_cmd_test.py +25 -0
- sage/cli/interactive_shell_cmd.py +28 -0
- sage/cli/notebook_cmd.py +51 -0
- sage/cli/notebook_cmd_test.py +39 -0
- sage/cli/options.py +26 -0
- sage/cli/run_file_cmd.py +50 -0
- sage/cli/version_cmd.py +26 -0
- sage/databases/all.py +83 -0
- sage/databases/cubic_hecke_db.py +1527 -0
- sage/dynamics/all.py +31 -0
- sage/dynamics/surface_dynamics_deprecation.py +32 -0
- sage/ext_data/kenzo/CP2.txt +45 -0
- sage/ext_data/kenzo/CP3.txt +349 -0
- sage/ext_data/kenzo/CP4.txt +4774 -0
- sage/ext_data/kenzo/README.txt +49 -0
- sage/ext_data/kenzo/S4.txt +20 -0
- sage/ext_data/mwrank/PRIMES +1 -0
- sage/ext_data/nbconvert/postprocess.py +48 -0
- sage/ext_data/nbconvert/rst_sage.tpl +99 -0
- sage/ext_data/nodoctest +0 -0
- sage/ext_data/notebook-ipython/kernel.json.in +11 -0
- sage/ext_data/notebook-ipython/logo-64x64.png +0 -0
- sage/ext_data/notebook-ipython/logo.svg +352 -0
- sage/ext_data/valgrind/pyalloc.supp +58 -0
- sage/ext_data/valgrind/sage-additional.supp +417 -0
- sage/ext_data/valgrind/sage.supp +43 -0
- sage/ext_data/valgrind/valgrind-python.supp +480 -0
- sage/geometry/all.py +12 -0
- sage/groups/matrix_gps/pickling_overrides.py +110 -0
- sage/homology/tests.py +66 -0
- sage/interacts/algebra.py +20 -0
- sage/interacts/all.py +25 -0
- sage/interacts/calculus.py +24 -0
- sage/interacts/fractals.py +18 -0
- sage/interacts/geometry.py +19 -0
- sage/interacts/library.py +1950 -0
- sage/interacts/library_cython.cpython-314-darwin.so +0 -0
- sage/interacts/statistics.py +19 -0
- sage/interfaces/axiom.py +1002 -0
- sage/interfaces/kash.py +834 -0
- sage/interfaces/lie.py +950 -0
- sage/interfaces/matlab.py +413 -0
- sage/interfaces/mupad.py +686 -0
- sage/interfaces/octave.py +858 -0
- sage/interfaces/phc.py +943 -0
- sage/interfaces/psage.py +189 -0
- sage/interfaces/qsieve.py +4 -0
- sage/interfaces/r.py +2096 -0
- sage/interfaces/read_data.py +46 -0
- sage/interfaces/scilab.py +576 -0
- sage/interfaces/tests.py +81 -0
- sage/libs/all.py +11 -0
- sage/libs/cremona/__init__.py +0 -0
- sage/libs/mwrank/__init__.py +0 -0
- sage/logic/all.py +3 -0
- sage/logic/booleval.py +160 -0
- sage/logic/boolformula.py +1490 -0
- sage/logic/logic.py +856 -0
- sage/logic/logicparser.py +696 -0
- sage/logic/logictable.py +272 -0
- sage/logic/propcalc.py +311 -0
- sage/misc/all.py +28 -0
- sage/misc/lazy_attribute.pyi +11 -0
- sage/rings/all.py +48 -0
- sage/rings/commutative_algebra.py +38 -0
- sage/rings/finite_rings/all.py +21 -0
- sage/rings/numbers_abc.py +58 -0
- sage/rings/polynomial/all.py +22 -0
- sage/rings/polynomial/convolution.py +421 -0
- 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." — \
|
|
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)
|