Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sagemath
GitHub Repository: sagemath/sagelib
Path: blob/master/sage/interacts/library.py
4045 views
1
"""
2
Sage Interacts
3
4
Sage interacts are applications of the `@interact decorator <../../sagenb/notebook/interact.html>`_.
5
They are conveniently accessible in the Sage Notebook via ``interacts.[TAB].[TAB]()``.
6
The first ``[TAB]`` lists categories and the second ``[TAB]`` reveals the interact examples.
7
8
EXAMPLE:
9
10
Invoked in the notebook, the following command will produce the fully formatted
11
interactive mathlet. In the command line, it will simply return the underlying
12
HTML and Sage code which creates the mathlet::
13
14
sage: interacts.calculus.taylor_polynomial()
15
<html>...</html>
16
17
AUTHORS:
18
19
- William Stein
20
21
- Harald Schilly, Robert Marik (2011-01-16): added many examples (#9623) partially based on work by Lauri Ruotsalainen
22
23
"""
24
25
#*****************************************************************************
26
# Copyright (C) 2009 William Stein <[email protected]>
27
# Copyright (C) 2011 Harald Schilly <[email protected]>
28
#
29
# Distributed under the terms of the GNU General Public License (GPL)
30
# as published by the Free Software Foundation; either version 2 of
31
# the License, or (at your option) any later version.
32
# http://www.gnu.org/licenses/
33
#*****************************************************************************
34
35
36
from sage.all import *
37
# this is not imported in sage.all, so we have to import it
38
from sage.ext.fast_callable import fast_callable
39
x=SR.var('x')
40
41
def library_interact(f):
42
"""
43
This is a decorator for using interacts in the Sage library.
44
45
EXAMPLES::
46
47
sage: import sage.interacts.library as library
48
sage: @library.library_interact
49
... def f(n=5): print n
50
...
51
sage: f() # an interact appears, if using the notebook, else code
52
<html>...</html>
53
"""
54
@sage_wraps(f)
55
def library_wrapper():
56
# Maybe program around bug (?) in the notebook:
57
html("</pre>")
58
# This prints out the relevant html code to make
59
# the interact appear:
60
interact(f)
61
return library_wrapper
62
63
@library_interact
64
def demo(n=tuple(range(10)), m=tuple(range(10))):
65
"""
66
This is a demo interact that sums two numbers.
67
68
INPUT:
69
70
- ``n`` -- integer slider
71
- ``m`` -- integer slider
72
73
EXAMPLES:
74
75
Invoked in the notebook, the following command will produce
76
the fully formatted interactive mathlet. In the command line,
77
it will simply return the underlying HTML and Sage code which
78
creates the mathlet::
79
80
sage: interacts.demo()
81
<html>...</html>
82
"""
83
print n+m
84
85
@library_interact
86
def taylor_polynomial(
87
title = text_control('<h2>Taylor polynomial</h2>'),
88
f=input_box(sin(x)*exp(-x),label="$f(x)=$"), order=slider(range(1,13))):
89
"""
90
An interact which illustrates the Taylor polynomial approximation
91
of various orders around `x=0`.
92
93
- ``f`` -- function expression
94
- ```order``` -- integer slider
95
96
EXAMPLES:
97
98
Invoked in the notebook, the following command will produce
99
the fully formatted interactive mathlet. In the command line,
100
it will simply return the underlying HTML and Sage code which
101
creates the mathlet::
102
103
sage: interacts.calculus.taylor_polynomial()
104
<html>...</html>
105
"""
106
x0 = 0
107
p = plot(f,(x,-1,5), thickness=2)
108
dot = point((x0,f(x=x0)),pointsize=80,rgbcolor=(1,0,0))
109
ft = f.taylor(x,x0,order)
110
pt = plot(ft,(-1, 5), color='green', thickness=2)
111
html('$f(x)\;=\;%s$'%latex(f))
112
html('$\hat{f}(x;%s)\;=\;%s+\mathcal{O}(x^{%s})$'%(x0,latex(ft),order+1))
113
show(dot + p + pt, ymin = -.5, ymax = 1)
114
115
@library_interact
116
def definite_integral(
117
title = text_control('<h2>Definite integral</h2>'),
118
f = input_box(default = "3*x", label = '$f(x)=$'),
119
g = input_box(default = "x^2", label = '$g(x)=$'),
120
interval = range_slider(-10,10,default=(0,3), label="Interval"),
121
x_range = range_slider(-10,10,default=(0,3), label = "plot range (x)"),
122
selection = selector(["f", "g", "f and g", "f - g"], default="f and g", label="Select")):
123
"""
124
This is a demo interact for plotting the definite integral of a function
125
based on work by Lauri Ruotsalainen, 2010.
126
127
INPUT:
128
129
- ``function`` -- input box, function in x
130
- ``interval`` -- interval for the definite integral
131
- ``x_range`` -- range slider for plotting range
132
- ``selection`` -- selector on how to visualize the integrals
133
134
EXAMPLES:
135
136
Invoked in the notebook, the following command will produce
137
the fully formatted interactive mathlet. In the command line,
138
it will simply return the underlying HTML and Sage code which
139
creates the mathlet::
140
141
sage: interacts.calculus.definite_integral()
142
<html>...</html>
143
"""
144
x = SR.var('x')
145
f = symbolic_expression(f).function(x)
146
g = symbolic_expression(g).function(x)
147
f_plot = Graphics(); g_plot = Graphics(); h_plot = Graphics();
148
text = ""
149
150
# Plot function f.
151
if selection != "g":
152
f_plot = plot(f(x), x, x_range, color="blue", thickness=1.5)
153
154
# Color and calculate the area between f and the horizontal axis.
155
if selection == "f" or selection == "f and g":
156
f_plot += plot(f(x), x, interval, color="blue", fill=True, fillcolor="blue", fillalpha=0.15)
157
text += r"$\int_{%.2f}^{%.2f}(\color{Blue}{f(x)})\,\mathrm{d}x=\int_{%.2f}^{%.2f}(%s)\,\mathrm{d}x=%.2f$" % (
158
interval[0], interval[1],
159
interval[0], interval[1],
160
latex(f(x)),
161
f(x).nintegrate(x, interval[0], interval[1])[0]
162
)
163
164
if selection == "f and g":
165
text += r"<br/>"
166
167
# Plot function g. Also color and calculate the area between g and the horizontal axis.
168
if selection == "g" or selection == "f and g":
169
g_plot = plot(g(x), x, x_range, color="green", thickness=1.5)
170
g_plot += plot(g(x), x, interval, color="green", fill=True, fillcolor="yellow", fillalpha=0.5)
171
text += r"$\int_{%.2f}^{%.2f}(\color{Green}{g(x)})\,\mathrm{d}x=\int_{%.2f}^{%.2f}(%s)\,\mathrm{d}x=%.2f$" % (
172
interval[0], interval[1],
173
interval[0], interval[1],
174
latex(g(x)),
175
g(x).nintegrate(x, interval[0], interval[1])[0]
176
)
177
178
# Plot function f-g. Also color and calculate the area between f-g and the horizontal axis.
179
if selection == "f - g":
180
g_plot = plot(g(x), x, x_range, color="green", thickness=1.5)
181
g_plot += plot(g(x), x, interval, color="green", fill=f(x), fillcolor="red", fillalpha=0.15)
182
h_plot = plot(f(x)-g(x), x, interval, color="red", thickness=1.5, fill=True, fillcolor="red", fillalpha=0.15)
183
text = r"$\int_{%.2f}^{%.2f}(\color{Red}{f(x)-g(x)})\,\mathrm{d}x=\int_{%.2f}^{%.2f}(%s)\,\mathrm{d}x=%.2f$" % (
184
interval[0], interval[1],
185
interval[0], interval[1],
186
latex(f(x)-g(x)),
187
(f(x)-g(x)).nintegrate(x, interval[0], interval[1])[0]
188
)
189
190
show(f_plot + g_plot + h_plot, gridlines=True)
191
html(text)
192
193
@library_interact
194
def function_derivative(
195
title = text_control('<h2>Derivative grapher</h2>'),
196
function = input_box(default="x^5-3*x^3+1", label="Function:"),
197
x_range = range_slider(-15,15,0.1, default=(-2,2), label="Range (x)"),
198
y_range = range_slider(-15,15,0.1, default=(-8,6), label="Range (y)")):
199
"""
200
This is a demo interact for plotting derivatives of a function based on work by
201
Lauri Ruotsalainen, 2010.
202
203
INPUT:
204
205
- ``function`` -- input box, function in x
206
- ``x_range`` -- range slider for plotting range
207
- ``y_range`` -- range slider for plotting range
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.function_derivative()
217
<html>...</html>
218
"""
219
x = SR.var('x')
220
f = symbolic_expression(function).function(x)
221
df = derivative(f, x)
222
ddf = derivative(df, x)
223
plots = plot(f(x), x_range, thickness=1.5) + plot(df(x), x_range, color="green") + plot(ddf(x), x_range, color="red")
224
if y_range == (0,0):
225
show(plots, xmin=x_range[0], xmax=x_range[1])
226
else:
227
show(plots, xmin=x_range[0], xmax=x_range[1], ymin=y_range[0], ymax=y_range[1])
228
229
html("<center>$\color{Blue}{f(x) = %s}$</center>"%latex(f(x)))
230
html("<center>$\color{Green}{f'(x) = %s}$</center>"%latex(df(x)))
231
html("<center>$\color{Red}{f''(x) = %s}$</center>"%latex(ddf(x)))
232
233
@library_interact
234
def difference_quotient(
235
title = text_control('<h2>Difference quotient</h2>'),
236
f = input_box(default="sin(x)", label='f(x)'),
237
interval= range_slider(0, 10, 0.1, default=(0.0,10.0), label="Range"),
238
a = slider(0, 10, None, 5.5, label = '$a$'),
239
x0 = slider(0, 10, None, 2.5, label = '$x_0$ (start point)')):
240
"""
241
This is a demo interact for difference quotient based on work by
242
Lauri Ruotsalainen, 2010.
243
244
INPUT:
245
246
- ``f`` -- input box, function in `x`
247
- ``interval`` -- range slider for plotting
248
- ``a`` -- slider for `a`
249
- ``x0`` -- slider for starting point `x_0`
250
251
EXAMPLES:
252
253
Invoked in the notebook, the following command will produce
254
the fully formatted interactive mathlet. In the command line,
255
it will simply return the underlying HTML and Sage code which
256
creates the mathlet::
257
258
sage: interacts.calculus.difference_quotient()
259
<html>...</html>
260
"""
261
html('<h2>Difference Quotient</h2>')
262
html('<div style="white-space: normal;">\
263
<a href="http://en.wikipedia.org/wiki/Difference_quotient" target="_blank">\
264
Wikipedia article about difference quotient</a></div>'
265
)
266
267
x = SR.var('x')
268
f = symbolic_expression(f).function(x)
269
fmax = f.find_maximum_on_interval(interval[0], interval[1])[0]
270
fmin = f.find_minimum_on_interval(interval[0], interval[1])[0]
271
f_height = fmax - fmin
272
measure_y = fmin - 0.1*f_height
273
274
measure_0 = line2d([(x0, measure_y), (a, measure_y)], rgbcolor="black")
275
measure_1 = line2d([(x0, measure_y + 0.02*f_height), (x0, measure_y-0.02*f_height)], rgbcolor="black")
276
measure_2 = line2d([(a, measure_y + 0.02*f_height), (a, measure_y-0.02*f_height)], rgbcolor="black")
277
text_x0 = text("x0", (x0, measure_y - 0.05*f_height), rgbcolor="black")
278
text_a = text("a", (a, measure_y - 0.05*f_height), rgbcolor="black")
279
measure = measure_0 + measure_1 + measure_2 + text_x0 + text_a
280
281
tanf = symbolic_expression((f(x0)-f(a))*(x-a)/(x0-a)+f(a)).function(x)
282
283
fplot = plot(f(x), x, interval[0], interval[1])
284
tanplot = plot(tanf(x), x, interval[0], interval[1], rgbcolor="#FF0000")
285
points = point([(x0, f(x0)), (a, f(a))], pointsize=20, rgbcolor="#005500")
286
dashline = line2d([(x0, f(x0)), (x0, f(a)), (a, f(a))], rgbcolor="#005500", linestyle="--")
287
html('<h2>Difference Quotient</h2>')
288
show(fplot + tanplot + points + dashline + measure, xmin=interval[0], xmax=interval[1], ymin=fmin-0.2*f_height, ymax=fmax)
289
html(r"<br>$\text{Line's equation:}$")
290
html(r"$y = %s$<br>"%tanf(x))
291
html(r"$\text{Slope:}$")
292
html(r"$k = \frac{f(x_0)-f(a)}{x_0-a} = %s$<br>" % (N(derivative(tanf(x), x), digits=5)))
293
294
@library_interact
295
def quadratic_equation(A = slider(-7, 7, 1, 1), B = slider(-7, 7, 1, 1), C = slider(-7, 7, 1, -2)):
296
"""
297
This is a demo interact for solving quadratic equations based on work by
298
Lauri Ruotsalainen, 2010.
299
300
INPUT:
301
302
- ``A`` -- integer slider
303
- ``B`` -- integer slider
304
- ``C`` -- integer slider
305
306
EXAMPLES:
307
308
Invoked in the notebook, the following command will produce
309
the fully formatted interactive mathlet. In the command line,
310
it will simply return the underlying HTML and Sage code which
311
creates the mathlet::
312
313
sage: interacts.calculus.quadratic_equation()
314
<html>...</html>
315
"""
316
x = SR.var('x')
317
f = symbolic_expression(A*x**2 + B*x + C).function(x)
318
html('<h2>The Solutions of the Quadratic Equation</h2>')
319
html("$%s = 0$" % f(x))
320
321
show(plot(f(x), x, (-10, 10), ymin=-10, ymax=10), aspect_ratio=1, figsize=4)
322
323
d = B**2 - 4*A*C
324
325
if d < 0:
326
color = "Red"
327
sol = r"\text{solution} \in \mathbb{C}"
328
elif d == 0:
329
color = "Blue"
330
sol = -B/(2*A)
331
else:
332
color = "Green"
333
a = (-B+sqrt(B**2-4*A*C))/(2*A)
334
b = (-B-sqrt(B**2-4*A*C))/(2*A)
335
sol = r"\begin{cases}%s\\%s\end{cases}" % (latex(a), latex(b))
336
337
if B < 0:
338
dis1 = "(%s)^2-4*%s*%s" % (B, A, C)
339
else:
340
dis1 = "%s^2-4*%s*%s" % (B, A, C)
341
dis2 = r"\color{%s}{%s}" % (color, d)
342
343
html("$Ax^2 + Bx + C = 0$")
344
calc = r"$x = \frac{-B\pm\sqrt{B^2-4AC}}{2A} = " + \
345
r"\frac{-%s\pm\sqrt{%s}}{2*%s} = " + \
346
r"\frac{-%s\pm\sqrt{%s}}{%s} = %s$"
347
html(calc % (B, dis1, A, B, dis2, (2*A), sol))
348
349
@library_interact
350
def trigonometric_properties_triangle(
351
a0 = slider(0, 360, 1, 30, label="A"),
352
a1 = slider(0, 360, 1, 180, label="B"),
353
a2 = slider(0, 360, 1, 300, label="C")):
354
"""
355
This is an interact for demonstrating trigonometric properties
356
in a triangle based on work by Lauri Ruotsalainen, 2010.
357
358
INPUT:
359
360
- ``a0`` -- angle
361
- ``a1`` -- angle
362
- ``a2`` -- angle
363
364
EXAMPLES:
365
366
Invoked in the notebook, the following command will produce
367
the fully formatted interactive mathlet. In the command line,
368
it will simply return the underlying HTML and Sage code which
369
creates the mathlet::
370
371
sage: interacts.geometry.trigonometric_properties_triangle()
372
<html>...</html>
373
"""
374
import math
375
376
# Returns the distance between points (x1,y1) and (x2,y2)
377
def distance((x1, y1), (x2, y2)):
378
return sqrt((x2-x1)**2 + (y2-y1)**2)
379
380
# Returns an angle (in radians) when sides a and b
381
# are adjacent and the side c is opposite to the angle
382
def angle(a, b, c):
383
a,b,c = map(float,[a,b,c])
384
return acos((b**2 + c**2 - a**2)/(2.0*b*c))
385
386
# Returns the area of a triangle when an angle alpha
387
# and adjacent sides a and b are known
388
def area(alpha, a, b):
389
return 1.0/2.0*a*b*sin(alpha)
390
391
xy = [0]*3
392
html('<h2>Trigonometric Properties of a Triangle</h2>')
393
# Coordinates of the angles
394
a = map(lambda x : math.radians(float(x)), [a0, a1, a2])
395
for i in range(3):
396
xy[i] = (cos(a[i]), sin(a[i]))
397
398
# Side lengths (bc, ca, ab) corresponding to triangle vertices (a, b, c)
399
al = [distance(xy[1], xy[2]), distance(xy[2], xy[0]), distance(xy[0], xy[1])]
400
401
# The angles (a, b, c) in radians
402
ak = [angle(al[0], al[1], al[2]), angle(al[1], al[2], al[0]), angle(al[2], al[0], al[1])]
403
404
# The area of the triangle
405
A = area(ak[0], al[1], al[2])
406
407
unit_circle = circle((0, 0), 1, aspect_ratio=1)
408
409
# Triangle
410
triangle = line([xy[0], xy[1], xy[2], xy[0]], rgbcolor="black")
411
triangle_points = point(xy, pointsize=30)
412
413
# Labels of the angles drawn in a distance from points
414
a_label = text("A", (xy[0][0]*1.07, xy[0][1]*1.07))
415
b_label = text("B", (xy[1][0]*1.07, xy[1][1]*1.07))
416
c_label = text("C", (xy[2][0]*1.07, xy[2][1]*1.07))
417
labels = a_label + b_label + c_label
418
419
show(unit_circle + triangle + triangle_points + labels, figsize=[5, 5], xmin=-1, xmax=1, ymin=-1, ymax=1)
420
angl_txt = r"$\angle A = {%s}^{\circ},$ $\angle B = {%s}^{\circ},$ $\angle C = {%s}^{\circ}$" % (
421
math.degrees(ak[0]),
422
math.degrees(ak[1]),
423
math.degrees(ak[2])
424
)
425
html(angl_txt)
426
html(r"$AB = %s,$ $BC = %s,$ $CA = %s$"%(al[2], al[0], al[1]))
427
html(r"Area of triangle $ABC = %s$"%A)
428
429
@library_interact
430
def unit_circle(
431
function = selector([(0, sin(x)), (1, cos(x)), (2, tan(x))]),
432
x = slider(0,2*pi, 0.005*pi, 0)):
433
"""
434
This is an interact for Sin, Cos and Tan in the Unit Circle
435
based on work by Lauri Ruotsalainen, 2010.
436
437
INPUT:
438
439
- ``function`` -- select Sin, Cos or Tan
440
- ``x`` -- slider to select angle in unit circle
441
442
EXAMPLES:
443
444
Invoked in the notebook, the following command will produce
445
the fully formatted interactive mathlet. In the command line,
446
it will simply return the underlying HTML and Sage code which
447
creates the mathlet::
448
449
sage: interacts.geometry.unit_circle()
450
<html>...</html>
451
"""
452
xy = (cos(x), sin(x))
453
t = SR.var('t')
454
html('<div style="white-space: normal;">Lines of the same color have\
455
the same length</div>')
456
457
# Unit Circle
458
C = circle((0, 0), 1, figsize=[5, 5], aspect_ratio=1)
459
C_line = line([(0, 0), (xy[0], xy[1])], rgbcolor="black")
460
C_point = point((xy[0], xy[1]), pointsize=40, rgbcolor="green")
461
C_inner = parametric_plot((cos(t), sin(t)), (t, 0, x + 0.001), color="green", thickness=3)
462
C_outer = parametric_plot((0.1 * cos(t), 0.1 * sin(t)), (t, 0, x + 0.001), color="black")
463
C_graph = C + C_line + C_point + C_inner + C_outer
464
465
# Graphics related to the graph of the function
466
G_line = line([(0, 0), (x, 0)], rgbcolor="green", thickness=3)
467
G_point = point((x, 0), pointsize=30, rgbcolor="green")
468
G_graph = G_line + G_point
469
470
# Sine
471
if function == 0:
472
Gf = plot(sin(t), t, 0, 2*pi, axes_labels=("x", "sin(x)"))
473
Gf_point = point((x, sin(x)), pointsize=30, rgbcolor="red")
474
Gf_line = line([(x, 0),(x, sin(x))], rgbcolor="red")
475
Cf_point = point((0, xy[1]), pointsize=40, rgbcolor="red")
476
Cf_line1 = line([(0, 0), (0, xy[1])], rgbcolor="red", thickness=3)
477
Cf_line2 = line([(0, xy[1]), (xy[0], xy[1])], rgbcolor="purple", linestyle="--")
478
# Cosine
479
elif function == 1:
480
Gf = plot(cos(t), t, 0, 2*pi, axes_labels=("x", "cos(x)"))
481
Gf_point = point((x, cos(x)), pointsize=30, rgbcolor="red")
482
Gf_line = line([(x, 0), (x, cos(x))], rgbcolor="red")
483
Cf_point = point((xy[0], 0), pointsize=40, rgbcolor="red")
484
Cf_line1 = line([(0, 0), (xy[0], 0)], rgbcolor="red", thickness=3)
485
Cf_line2 = line([(xy[0], 0), (xy[0], xy[1])], rgbcolor="purple", linestyle="--")
486
# Tangent
487
else:
488
Gf = plot(tan(t), t, 0, 2*pi, ymin=-8, ymax=8, axes_labels=("x", "tan(x)"))
489
Gf_point = point((x, tan(x)), pointsize=30, rgbcolor="red")
490
Gf_line = line([(x, 0), (x, tan(x))], rgbcolor="red")
491
Cf_point = point((1, tan(x)), pointsize=40, rgbcolor="red")
492
Cf_line1 = line([(1, 0), (1, tan(x))], rgbcolor="red", thickness=3)
493
Cf_line2 = line([(xy[0], xy[1]), (1, tan(x))], rgbcolor="purple", linestyle="--")
494
495
C_graph += Cf_point + Cf_line1 + Cf_line2
496
G_graph += Gf + Gf_point + Gf_line
497
498
html.table([[r"$\text{Unit Circle}$",r"$\text{Function}$"], [C_graph, G_graph]], header=True)
499
500
@library_interact
501
def special_points(
502
title = text_control('<h2>Special points in triangle</h2>'),
503
a0 = slider(0, 360, 1, 30, label="A"),
504
a1 = slider(0, 360, 1, 180, label="B"),
505
a2 = slider(0, 360, 1, 300, label="C"),
506
show_median = checkbox(False, label="Medians"),
507
show_pb = checkbox(False, label="Perpendicular Bisectors"),
508
show_alt = checkbox(False, label="Altitudes"),
509
show_ab = checkbox(False, label="Angle Bisectors"),
510
show_incircle = checkbox(False, label="Incircle"),
511
show_euler = checkbox(False, label="Euler's Line")):
512
"""
513
This interact demo shows special points in a triangle
514
based on work by Lauri Ruotsalainen, 2010.
515
516
INPUT:
517
518
- ``a0`` -- angle
519
- ``a1`` -- angle
520
- ``a2`` -- angle
521
- ``show_median`` -- checkbox
522
- ``show_pb`` -- checkbox to show perpendicular bisectors
523
- ``show_alt`` -- checkbox to show altitudes
524
- ``show_ab`` -- checkbox to show angle bisectors
525
- ``show_incircle`` -- checkbox to show incircle
526
- ``show_euler`` -- checkbox to show euler's line
527
528
EXAMPLES:
529
530
Invoked in the notebook, the following command will produce
531
the fully formatted interactive mathlet. In the command line,
532
it will simply return the underlying HTML and Sage code which
533
creates the mathlet::
534
535
sage: interacts.geometry.special_points()
536
<html>...</html>
537
"""
538
import math
539
# Return the intersection point of the bisector of the angle <(A[a],A[c],A[b]) and the unit circle. Angles given in radians.
540
def half(A, a, b, c):
541
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])):
542
p = A[a] + (A[b] - A[a]) / 2.0
543
else:
544
p = A[b] + (2*pi - (A[b]-A[a])) / 2.0
545
return (math.cos(p), math.sin(p))
546
547
# Returns the distance between points (x1,y1) and (x2,y2)
548
def distance((x1, y1), (x2, y2)):
549
return math.sqrt((x2-x1)**2 + (y2-y1)**2)
550
551
# Returns the line (graph) going through points (x1,y1) and (x2,y2)
552
def line_to_points((x1, y1), (x2, y2), **plot_kwargs):
553
return plot((y2-y1) / (x2-x1) * (x-x1) + y1, (x,-3,3), **plot_kwargs)
554
555
# Coordinates of the angles
556
a = map(lambda x : math.radians(float(x)), [a0, a1, a2])
557
xy = [(math.cos(a[i]), math.sin(a[i])) for i in range(3)]
558
559
# Labels of the angles drawn in a distance from points
560
a_label = text("A", (xy[0][0]*1.07, xy[0][1]*1.07))
561
b_label = text("B", (xy[1][0]*1.07, xy[1][1]*1.07))
562
c_label = text("C", (xy[2][0]*1.07, xy[2][1]*1.07))
563
labels = a_label + b_label + c_label
564
565
C = 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
# Side lengths (bc, ca, ab) corresponding to triangle vertices (a, b, c)
572
ad = [distance(xy[1], xy[2]), distance(xy[2], xy[0]), distance(xy[0], xy[1])]
573
574
# Midpoints of edges (bc, ca, ab)
575
a_middle = [
576
((xy[1][0] + xy[2][0])/2.0, (xy[1][1] + xy[2][1])/2.0),
577
((xy[2][0] + xy[0][0])/2.0, (xy[2][1] + xy[0][1])/2.0),
578
((xy[0][0] + xy[1][0])/2.0, (xy[0][1] + xy[1][1])/2.0)
579
]
580
581
# Incircle
582
perimeter = float(ad[0] + ad[1] + ad[2])
583
incircle_center = (
584
(ad[0]*xy[0][0] + ad[1]*xy[1][0] + ad[2]*xy[2][0]) / perimeter,
585
(ad[0]*xy[0][1] + ad[1]*xy[1][1] + ad[2]*xy[2][1]) / perimeter
586
)
587
588
if show_incircle:
589
s = perimeter/2.0
590
incircle_r = math.sqrt((s - ad[0]) * (s - ad[1]) * (s - ad[2]) / s)
591
incircle_graph = circle(incircle_center, incircle_r) + point(incircle_center)
592
else:
593
incircle_graph = Graphics()
594
595
# Angle Bisectors
596
if show_ab:
597
a_ab = line([xy[0], half(a, 1, 2, 0)], rgbcolor="blue", alpha=0.6)
598
b_ab = line([xy[1], half(a, 2, 0, 1)], rgbcolor="blue", alpha=0.6)
599
c_ab = line([xy[2], half(a, 0, 1, 2)], rgbcolor="blue", alpha=0.6)
600
ab_point = point(incircle_center, rgbcolor="blue", pointsize=28)
601
ab_graph = a_ab + b_ab + c_ab + ab_point
602
else:
603
ab_graph = Graphics()
604
605
# Medians
606
if show_median:
607
a_median = line([xy[0], a_middle[0]], rgbcolor="green", alpha=0.6)
608
b_median = line([xy[1], a_middle[1]], rgbcolor="green", alpha=0.6)
609
c_median = line([xy[2], a_middle[2]], rgbcolor="green", alpha=0.6)
610
median_point = point(
611
(
612
(xy[0][0]+xy[1][0]+xy[2][0])/3.0,
613
(xy[0][1]+xy[1][1]+xy[2][1])/3.0
614
), rgbcolor="green", pointsize=28)
615
median_graph = a_median + b_median + c_median + median_point
616
else:
617
median_graph = Graphics()
618
619
# Perpendicular Bisectors
620
if show_pb:
621
a_pb = line_to_points(a_middle[0], half(a, 1, 2, 0), rgbcolor="red", alpha=0.6)
622
b_pb = line_to_points(a_middle[1], half(a, 2, 0, 1), rgbcolor="red", alpha=0.6)
623
c_pb = line_to_points(a_middle[2], half(a, 0, 1, 2), rgbcolor="red", alpha=0.6)
624
pb_point = point((0, 0), rgbcolor="red", pointsize=28)
625
pb_graph = a_pb + b_pb + c_pb + pb_point
626
else:
627
pb_graph = Graphics()
628
629
# Altitudes
630
if show_alt:
631
xA, xB, xC = xy[0][0], xy[1][0], xy[2][0]
632
yA, yB, yC = xy[0][1], xy[1][1], xy[2][1]
633
a_alt = plot(((xC-xB)*x+(xB-xC)*xA)/(yB-yC)+yA, (x,-3,3), rgbcolor="brown", alpha=0.6)
634
b_alt = plot(((xA-xC)*x+(xC-xA)*xB)/(yC-yA)+yB, (x,-3,3), rgbcolor="brown", alpha=0.6)
635
c_alt = plot(((xB-xA)*x+(xA-xB)*xC)/(yA-yB)+yC, (x,-3,3), rgbcolor="brown", alpha=0.6)
636
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)
637
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)
638
alt_intersection = point((alt_lx, alt_ly), rgbcolor="brown", pointsize=28)
639
alt_graph = a_alt + b_alt + c_alt + alt_intersection
640
else:
641
alt_graph = Graphics()
642
643
# Euler's Line
644
if show_euler:
645
euler_graph = line_to_points(
646
(0, 0),
647
(
648
(xy[0][0]+xy[1][0]+xy[2][0])/3.0,
649
(xy[0][1]+xy[1][1]+xy[2][1])/3.0
650
),
651
rgbcolor="purple",
652
thickness=2,
653
alpha=0.7
654
)
655
else:
656
euler_graph = Graphics()
657
658
show(
659
C + triangle + triangle_points + labels + ab_graph + median_graph +
660
pb_graph + alt_graph + incircle_graph + euler_graph,
661
figsize=[5,5], xmin=-1, xmax=1, ymin=-1, ymax=1
662
)
663
664
665
@library_interact
666
def coin(n = slider(2,10000, 100, default=1000, label="Number of Tosses"), interval = range_slider(0, 1, default=(0.45, 0.55), label="Plotting range (y)")):
667
"""
668
This interact demo simulates repeated tosses of a coin,
669
based on work by Lauri Ruotsalainen, 2010.
670
671
The points give the cumulative percentage of tosses which
672
are heads in a given run of the simulation, so that the
673
point `(x,y)` gives the percentage of the first `x` tosses
674
that were heads; this proportion should approach .5, of
675
course, if we are simulating a fair coin.
676
677
INPUT:
678
679
- ``n`` -- number of tosses
680
- ``interval`` -- plot range along
681
vertical axis
682
683
EXAMPLES:
684
685
Invoked in the notebook, the following command will produce
686
the fully formatted interactive mathlet. In the command line,
687
it will simply return the underlying HTML and Sage code which
688
creates the mathlet::
689
690
sage: interacts.statistics.coin()
691
<html>...</html>
692
"""
693
from random import random
694
c = []
695
k = 0.0
696
for i in range(1, n + 1):
697
k += random()
698
c.append((i, k/i))
699
show(point(c[1:], gridlines=[None, [0.5]], pointsize=1), ymin=interval[0], ymax=interval[1])
700
701
702
@library_interact
703
def bisection_method(
704
title = text_control('<h2>Bisection method</h2>'),
705
f = input_box("x^2-2", label='f(x)'),
706
interval = range_slider(-5,5,default=(0, 4), label="range"),
707
d = slider(1, 8, 1, 3, label="$10^{-d}$ precision"),
708
maxn = slider(0,50,1,10, label="max iterations")):
709
"""
710
Interact explaining the bisection method, based on similar interact
711
explaining secant method and Wiliam Stein's example from wiki.
712
713
INPUT:
714
715
- ``f`` -- function
716
- ``interval`` -- range slider for the search interval
717
- ``d`` -- slider for the precision (`10^{-d}`)
718
- ``maxn`` -- max number of iterations
719
720
EXAMPLES:
721
722
Invoked in the notebook, the following command will produce
723
the fully formatted interactive mathlet. In the command line,
724
it will simply return the underlying HTML and Sage code which
725
creates the mathlet::
726
727
sage: interacts.calculus.secant_method()
728
<html>...</html>
729
"""
730
def _bisection_method(f, a, b, maxn, eps):
731
intervals = [(a,b)]
732
round = 1
733
two = float(2)
734
while True:
735
c = (b+a)/two
736
if abs(f(c)) < h or round >= maxn:
737
break
738
fa = f(a); fb = f(b); fc = f(c)
739
if abs(fc) < eps:
740
return c, intervals
741
if fa*fc < 0:
742
a, b = a, c
743
elif fc*fb < 0:
744
a, b = c, b
745
else:
746
raise ValueError, "f must have a sign change in the interval (%s,%s)"%(a,b)
747
intervals.append((a,b))
748
round += 1
749
return c, intervals
750
751
x = SR.var('x')
752
f = symbolic_expression(f).function(x)
753
a, b = interval
754
h = 10**(-d)
755
try:
756
c, intervals = _bisection_method(f, float(a), float(b), maxn, h)
757
except ValueError:
758
print "f must have opposite sign at the endpoints of the interval"
759
show(plot(f, a, b, color='red'), xmin=a, xmax=b)
760
else:
761
html(r"$\text{Precision }h = 10^{-d}=10^{-%s}=%.5f$"%(d, float(h)))
762
html(r"${c = }%s$"%latex(c))
763
html(r"${f(c) = }%s"%latex(f(c)))
764
html(r"$%s \text{ iterations}"%len(intervals))
765
P = plot(f, a, b, color='red')
766
k = (P.ymax() - P.ymin())/ (1.5*len(intervals))
767
L = sum(line([(c,k*i), (d,k*i)]) for i, (c,d) in enumerate(intervals) )
768
L += sum(line([(c,k*i-k/4), (c,k*i+k/4)]) for i, (c,d) in enumerate(intervals) )
769
L += sum(line([(d,k*i-k/4), (d,k*i+k/4)]) for i, (c,d) in enumerate(intervals) )
770
show(P + L, xmin=a, xmax=b)
771
772
@library_interact
773
def secant_method(
774
title = text_control('<h2>Secant method for numerical root finding</h2>'),
775
f = input_box("x^2-2", label='f(x)'),
776
interval = range_slider(-5,5,default=(0, 4), label="range"),
777
d = slider(1, 16, 1, 3, label="10^-d precision"),
778
maxn = slider(0,15,1,10, label="max iterations")):
779
"""
780
Interact explaining the secant method, based on work by
781
Lauri Ruotsalainen, 2010.
782
Originally this is based on work by William Stein.
783
784
INPUT:
785
786
- ``f`` -- function
787
- ``interval`` -- range slider for the search interval
788
- ``d`` -- slider for the precision (10^-d)
789
- ``maxn`` -- max number of iterations
790
791
EXAMPLES:
792
793
Invoked in the notebook, the following command will produce
794
the fully formatted interactive mathlet. In the command line,
795
it will simply return the underlying HTML and Sage code which
796
creates the mathlet::
797
798
sage: interacts.calculus.secant_method()
799
<html>...</html>
800
"""
801
def _secant_method(f, a, b, maxn, h):
802
intervals = [(a,b)]
803
round = 1
804
while True:
805
c = b-(b-a)*f(b)/(f(b)-f(a))
806
if abs(f(c)) < h or round >= maxn:
807
break
808
a, b = b, c
809
intervals.append((a,b))
810
round += 1
811
return c, intervals
812
813
x = SR.var('x')
814
f = symbolic_expression(f).function(x)
815
a, b = interval
816
h = 10**(-d)
817
if float(f(a)*f(b)) > 0:
818
print "f must have opposite sign at the endpoints of the interval"
819
show(plot(f, a, b, color='red'), xmin=a, xmax=b)
820
else:
821
c, intervals = _secant_method(f, float(a), float(b), maxn, h)
822
html(r"$\text{Precision }h = 10^{-d}=10^{-%s}=%.5f$"%(d, float(h)))
823
html(r"${c = }%s$"%latex(c))
824
html(r"${f(c) = }%s"%latex(f(c)))
825
html(r"$%s \text{ iterations}"%len(intervals))
826
P = plot(f, a, b, color='red')
827
k = (P.ymax() - P.ymin())/ (1.5*len(intervals))
828
L = sum(line([(c,k*i), (d,k*i)]) for i, (c,d) in enumerate(intervals) )
829
L += sum(line([(c,k*i-k/4), (c,k*i+k/4)]) for i, (c,d) in enumerate(intervals) )
830
L += sum(line([(d,k*i-k/4), (d,k*i+k/4)]) for i, (c,d) in enumerate(intervals) )
831
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)
832
show(P + L + S, xmin=a, xmax=b)
833
834
@library_interact
835
def newton_method(
836
title = text_control('<h2>Newton method</h2>'),
837
f = input_box("x^2 - 2"),
838
c = slider(-10,10, default=6, label='Start ($x$)'),
839
d = slider(1, 16, 1, 3, label="$10^{-d}$ precision"),
840
maxn = slider(0, 15, 1, 10, label="max iterations"),
841
interval = range_slider(-10,10, default = (0,6), label="Interval"),
842
list_steps = checkbox(default=False, label="List steps")):
843
"""
844
Interact explaining the newton method, based on work by
845
Lauri Ruotsalainen, 2010.
846
Originally this is based on work by William Stein.
847
848
INPUT:
849
850
- ``f`` -- function
851
- ``c`` -- starting position (`x`)
852
- ``d`` -- slider for the precision (`10^{-d}`)
853
- ``maxn`` -- max number of iterations
854
- ``interval`` -- range slider for the search interval
855
- ``list_steps`` -- checkbox, if true shows the steps numerically
856
857
EXAMPLES:
858
859
Invoked in the notebook, the following command will produce
860
the fully formatted interactive mathlet. In the command line,
861
it will simply return the underlying HTML and Sage code which
862
creates the mathlet::
863
864
sage: interacts.calculus.newton_method()
865
<html>...</html>
866
"""
867
def _newton_method(f, c, maxn, h):
868
midpoints = [c]
869
round = 1
870
while True:
871
c = c-f(c)/f.derivative(x)(x=c)
872
midpoints.append(c)
873
if f(c-h)*f(c+h) < 0 or round == maxn:
874
break
875
round += 1
876
return c, midpoints
877
878
x = SR.var('x')
879
f = symbolic_expression(f).function(x)
880
a, b = interval
881
h = 10**(-d)
882
c, midpoints = _newton_method(f, float(c), maxn, h/2.0)
883
html(r"$\text{Precision } 2h = %s$"%latex(float(h)))
884
html(r"${c = }%s$"%c)
885
html(r"${f(c) = }%s"%latex(f(c)))
886
html(r"$%s \text{ iterations}"%len(midpoints))
887
if list_steps:
888
s = [["$n$","$x_n$","$f(x_n)$", "$f(x_n-h)\,f(x_n+h)$"]]
889
for i, c in enumerate(midpoints):
890
s.append([i+1, c, f(c), (c-h)*f(c+h)])
891
html.table(s,header=True)
892
else:
893
P = plot(f, x, interval, color="blue")
894
L = sum(line([(c, 0), (c, f(c))], color="green") for c in midpoints[:-1])
895
for i in range(len(midpoints) - 1):
896
L += line([(midpoints[i], f(midpoints[i])), (midpoints[i+1], 0)], color="red")
897
show(P + L, xmin=interval[0], xmax=interval[1], ymin=P.ymin(), ymax=P.ymax())
898
899
@library_interact
900
def trapezoid_integration(
901
title = text_control('<h2>Trapezoid integration</h2>'),
902
f = input_box(default = "x^2-5*x + 10", label='$f(x)=$'),
903
n = slider(1,100,1,5, label='# divisions'),
904
interval_input = selector(['from slider','from keyboard'], label='Integration interval', buttons=True),
905
interval_s = range_slider(-10,10,default=(0,8), label="slider: "),
906
interval_g = input_grid(1,2,default=[[0,8]], label="keyboard: "),
907
output_form = selector(['traditional','table','none'], label='Computations form', buttons=True)
908
):
909
"""
910
Interact explaining the trapezoid method for definite integrals, based on work by
911
Lauri Ruotsalainen, 2010 (based on the application "Numerical integrals with various rules"
912
by Marshall Hampton and Nick Alexander)
913
914
INPUT:
915
916
- ``f`` -- function of variable x to integrate
917
- ``n`` -- number of divisions
918
- ``interval_input`` -- swithes the input for interval between slider and keyboard
919
- ``interval_s`` -- slider for interval to integrate
920
- ``interval_g`` -- input grid for interval to integrate
921
- ``output_form`` -- the computation is formatted in a traditional form, in a table or missing
922
923
EXAMPLES:
924
925
Invoked in the notebook, the following command will produce
926
the fully formatted interactive mathlet. In the command line,
927
it will simply return the underlying HTML and Sage code which
928
creates the mathlet::
929
930
sage: interacts.calculus.trapezoid_integration()
931
<html>...</html>
932
"""
933
xs = []
934
ys = []
935
if interval_input == 'from slider':
936
interval = interval_s
937
else:
938
interval = interval_g[0]
939
h = float(interval[1]-interval[0])/n
940
x = SR.var('x')
941
f = symbolic_expression(f).function(x)
942
943
trapezoids = Graphics()
944
945
for i in range(n):
946
xi = interval[0] + i*h
947
yi = f(xi)
948
trapezoids += line([[xi, 0], [xi, yi], [xi + h, f(xi + h)],[xi + h, 0],[xi, 0]], rgbcolor = (1,0,0))
949
xs.append(xi)
950
ys.append(yi)
951
xs.append(xi + h)
952
ys.append(f(xi + h))
953
954
html(r'Function $f(x)=%s$'%latex(f(x)))
955
show(plot(f, interval[0], interval[1]) + trapezoids, xmin = interval[0], xmax = interval[1])
956
957
numeric_value = integral_numerical(f, interval[0], interval[1])[0]
958
approx = h *(ys[0]/2 + sum([ys[i] for i in range(1,n)]) + ys[n]/2)
959
960
html(r'Integral value to seven decimal places is: $\displaystyle\int_{%.2f}^{%.2f} {f(x) \, \mathrm{d}x} = %.6f$'%(
961
interval[0], interval[1], N(numeric_value, digits=7))
962
)
963
964
if output_form == 'traditional':
965
sum_formula_html = r"\frac {d}{2} \cdot \left[f(x_0) + %s + f(x_{%s})\right]" % (
966
' + '.join([ "2 f(x_{%s})"%i for i in range(1,n)]),
967
n
968
)
969
sum_placement_html = r"\frac{%.2f}{2} \cdot \left[f(%.2f) + %s + f(%.2f)\right]" % (
970
h,
971
N(xs[0], digits=5),
972
' + '.join([ "2 f(%.2f)" %N(i, digits=5) for i in xs[1:-1]]),
973
N(xs[n], digits=5)
974
)
975
sum_values_html = r"\frac{%.2f}{2} \cdot \left[%.2f + %s + %.2f\right]" % (
976
h,
977
N(ys[0], digits=5),
978
' + '.join([ "2\cdot %.2f" % N(i, digits=5) for i in ys[1:-1]]),
979
N(ys[n], digits=5)
980
)
981
982
html(r'''
983
<div class="math">
984
\begin{align*}
985
\int_{%.2f}^{%.2f} {f(x) \, \mathrm{d}x}
986
& \approx %s \\
987
& = %s \\
988
& = %s \\
989
& = %s
990
\end{align*}
991
</div>
992
''' % (
993
interval[0], interval[1],
994
sum_formula_html, sum_placement_html, sum_values_html,
995
N(approx, digits=7)
996
))
997
elif output_form == 'table':
998
s = [['$i$','$x_i$','$f(x_i)$','$m$','$m\cdot f(x_i)$']]
999
for i in range(0,n+1):
1000
if i==0 or i==n:
1001
j = 1
1002
else:
1003
j = 2
1004
s.append([i, xs[i], ys[i],j,N(j*ys[i])])
1005
html.table(s,header=True)
1006
1007
@library_interact
1008
def simpson_integration(
1009
title = text_control('<h2>Simpson integration</h2>'),
1010
f = input_box(default = 'x*sin(x)+x+1', label='$f(x)=$'),
1011
n = slider(2,100,2,6, label='# divisions'),
1012
interval_input = selector(['from slider','from keyboard'], label='Integration interval', buttons=True),
1013
interval_s = range_slider(-10,10,default=(0,10), label="slider: "),
1014
interval_g = input_grid(1,2,default=[[0,10]], label="keyboard: "),
1015
output_form = selector(['traditional','table','none'], label='Computations form', buttons=True)):
1016
"""
1017
Interact explaining the simpson method for definite integrals, based on work by
1018
Lauri Ruotsalainen, 2010 (based on the application "Numerical integrals with various rules"
1019
by Marshall Hampton and Nick Alexander)
1020
1021
INPUT:
1022
1023
- ``f`` -- function of variable x to integrate
1024
- ``n`` -- number of divisions (mult. of 2)
1025
- ``interval_input`` -- swithes the input for interval between slider and keyboard
1026
- ``interval_s`` -- slider for interval to integrate
1027
- ``interval_g`` -- input grid for interval to integrate
1028
- ``output_form`` -- the computation is formatted in a traditional form, in a table or missing
1029
1030
EXAMPLES:
1031
1032
Invoked in the notebook, the following command will produce
1033
the fully formatted interactive mathlet. In the command line,
1034
it will simply return the underlying HTML and Sage code which
1035
creates the mathlet::
1036
1037
sage: interacts.calculus.simpson_integration()
1038
<html>...</html>
1039
"""
1040
x = SR.var('x')
1041
f = symbolic_expression(f).function(x)
1042
if interval_input == 'from slider':
1043
interval = interval_s
1044
else:
1045
interval = interval_g[0]
1046
def parabola(a, b, c):
1047
from sage.all import solve
1048
A, B, C = SR.var("A, B, C")
1049
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]
1050
f = K[A]*x**2+K[B]*x+K[C]
1051
return f
1052
xs = []; ys = []
1053
dx = float(interval[1]-interval[0])/n
1054
1055
for i in range(n+1):
1056
xs.append(interval[0] + i*dx)
1057
ys.append(f(x=xs[-1]))
1058
1059
parabolas = Graphics()
1060
lines = Graphics()
1061
1062
for i in range(0, n-1, 2):
1063
p = parabola((xs[i],ys[i]),(xs[i+1],ys[i+1]),(xs[i+2],ys[i+2]))
1064
parabolas += plot(p(x=x), (x, xs[i], xs[i+2]), color="red")
1065
lines += line([(xs[i],ys[i]), (xs[i],0), (xs[i+2],0)],color="red")
1066
lines += line([(xs[i+1],ys[i+1]), (xs[i+1],0)], linestyle="-.", color="red")
1067
1068
lines += line([(xs[-1],ys[-1]), (xs[-1],0)], color="red")
1069
1070
html(r'Function $f(x)=%s$'%latex(f(x)))
1071
1072
show(plot(f(x),x,interval[0],interval[1]) + parabolas + lines, xmin = interval[0], xmax = interval[1])
1073
1074
numeric_value = integral_numerical(f,interval[0],interval[1])[0]
1075
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])
1076
1077
html(r'Integral value to seven decimal places is: $\displaystyle\int_{%.2f}^{%.2f} {f(x) \, \mathrm{d}x} = %.6f$'%
1078
(interval[0],interval[1],
1079
N(numeric_value,digits=7)))
1080
1081
if output_form == 'traditional':
1082
sum_formula_html = r"\frac{d}{3} \cdot \left[ f(x_0) + %s + f(x_{%s})\right]" % (
1083
' + '.join([ r"%s \cdot f(x_{%s})" %(i%2*(-2)+4, i+1) for i in range(0,n-1)]),
1084
n
1085
)
1086
1087
sum_placement_html = r"\frac{%.2f}{3} \cdot \left[ f(%.2f) + %s + f(%.2f)\right]" % (
1088
dx,
1089
N(xs[0],digits=5),
1090
' + '.join([ r"%s \cdot f(%.2f)" %(i%2*(-2)+4, N(xk, digits=5)) for i, xk in enumerate(xs[1:-1])]),
1091
N(xs[n],digits=5)
1092
)
1093
1094
sum_values_html = r"\frac{%.2f}{3} \cdot \left[ %s %s %s\right]" %(
1095
dx,
1096
"%.2f + "%N(ys[0],digits=5),
1097
' + '.join([ r"%s \cdot %.2f" %(i%2*(-2)+4, N(yk, digits=5)) for i, yk in enumerate(ys[1:-1])]),
1098
" + %.2f"%N(ys[n],digits=5)
1099
)
1100
1101
html(r'''
1102
<div class="math">
1103
\begin{align*}
1104
\int_{%.2f}^{%.2f} {f(x) \, \mathrm{d}x}
1105
& \approx %s \\
1106
& = %s \\
1107
& = %s \\
1108
& = %.6f
1109
\end{align*}
1110
</div>
1111
''' % (
1112
interval[0], interval[1],
1113
sum_formula_html, sum_placement_html, sum_values_html,
1114
N(approx,digits=7)
1115
))
1116
elif output_form == 'table':
1117
s = [['$i$','$x_i$','$f(x_i)$','$m$','$m\cdot f(x_i)$']]
1118
for i in range(0,n+1):
1119
if i==0 or i==n:
1120
j = 1
1121
else:
1122
j = (i+1)%2*(-2)+4
1123
s.append([i, xs[i], ys[i],j,N(j*ys[i])])
1124
s.append(['','','','$\sum$','$%s$'%latex(3/dx*approx)])
1125
html.table(s,header=True)
1126
html(r'$\int_{%.2f}^{%.2f} {f(x) \, \mathrm{d}x}\approx\frac {%.2f}{3}\cdot %s=%s$'%
1127
(interval[0], interval[1],dx,latex(3/dx*approx),latex(approx)))
1128
1129
@library_interact
1130
def riemann_sum(
1131
title = text_control('<h2>Riemann integral with random sampling</h2>'),
1132
f = input_box("x^2+1", label = "$f(x)=$", width=40),
1133
n = slider(1,30,1,5, label='# divisions'),
1134
hr1 = text_control('<hr>'),
1135
interval_input = selector(['from slider','from keyboard'], label='Integration interval', buttons=True),
1136
interval_s = range_slider(-5,10,default=(0,2), label="slider: "),
1137
interval_g = input_grid(1,2,default=[[0,2]], label="keyboard: "),
1138
hr2 = text_control('<hr>'),
1139
list_table = checkbox(default=False, label="List table"),
1140
auto_update = False):
1141
"""
1142
Interact explaining the definition of Riemann integral
1143
1144
INPUT:
1145
1146
- ``f`` -- function of variable x to integrate
1147
- ``n`` -- number of divisions
1148
- ``interval_input`` -- swithes the input for interval between slider and keyboard
1149
- ``interval_s`` -- slider for interval to integrate
1150
- ``interval_g`` -- input grid for interval to integrate
1151
- ``list_table`` -- print table with values of the function
1152
1153
EXAMPLES:
1154
1155
Invoked in the notebook, the following command will produce
1156
the fully formatted interactive mathlet. In the command line,
1157
it will simply return the underlying HTML and Sage code which
1158
creates the mathlet::
1159
1160
sage: interacts.calculus.riemann_sum()
1161
<html>...</html>
1162
1163
AUTHORS:
1164
1165
- Robert Marik (08-2010)
1166
"""
1167
x = SR.var('x')
1168
from random import random
1169
if interval_input == 'from slider':
1170
a = interval_s[0]
1171
b = interval_s[1]
1172
else:
1173
a = interval_g[0][0]
1174
b = interval_g[0][1]
1175
func = symbolic_expression(f).function(x)
1176
division = [a]+[a+random()*(b-a) for i in range(n-1)]+[b]
1177
division = [i for i in division]
1178
division.sort()
1179
xs = [division[i]+random()*(division[i+1]-division[i]) for i in range(n)]
1180
ys = [func(x_val) for x_val in xs]
1181
rects = Graphics()
1182
for i in range(n):
1183
body=[[division[i],0],[division[i],ys[i]],[division[i+1],ys[i]],[division[i+1],0]]
1184
if ys[i].n()>0:
1185
color_rect='green'
1186
else:
1187
color_rect='red'
1188
rects = rects +polygon2d(body, rgbcolor = color_rect,alpha=0.1)\
1189
+ point((xs[i],ys[i]), rgbcolor = (1,0,0))\
1190
+ line(body,rgbcolor='black',zorder=-1)
1191
html('<small>Adjust your data and click Update button. Click repeatedly for another random values.</small>')
1192
1193
show(plot(func(x),(x,a,b),zorder=5) + rects)
1194
delka_intervalu=[division[i+1]-division[i] for i in range(n)]
1195
if list_table:
1196
html.table([["$i$","$[x_{i-1},x_i]$","$\eta_i$","$f(\eta_i)$","$x_{i}-x_{i-1}$"]]\
1197
+[[i+1,[division[i],division[i+1]],xs[i],ys[i],delka_intervalu[i]] for i in range(n)],\
1198
header=True)
1199
1200
html('Riemann sum: $\displaystyle\sum_{i=1}^{%s} f(\eta_i)(x_i-x_{i-1})=%s$ '%
1201
(latex(n),latex(sum([ys[i]*delka_intervalu[i] for i in range(n)]))))
1202
html('Exact value of the integral $\displaystyle\int_{%s}^{%s}%s\,\mathrm{d}x=%s$'%
1203
(latex(a),latex(b),latex(func(x)),latex(integral_numerical(func(x),a,b)[0])))
1204
1205
1206
x = SR.var('x')
1207
@library_interact
1208
def function_tool(f=sin(x), g=cos(x), xrange=range_slider(-3,3,default=(0,1),label='x-range'),
1209
yrange='auto',
1210
a=1,
1211
action=selector(['f', 'df/dx', 'int f', 'num f', 'den f', '1/f', 'finv',
1212
'f+a', 'f-a', 'f*a', 'f/a', 'f^a', 'f(x+a)', 'f(x*a)',
1213
'f+g', 'f-g', 'f*g', 'f/g', 'f(g)'],
1214
width=15, nrows=5, label="h = "),
1215
do_plot = ("Draw Plots", True)):
1216
"""
1217
`Function Plotting Tool <http://wiki.sagemath.org/interact/calculus#Functiontool>`_
1218
(by William Stein (?))
1219
1220
INPUT:
1221
1222
- ``f`` -- function f(x)
1223
- ``g`` -- function g(x)
1224
- ``xrange`` -- range for plotting (x)
1225
- ``yrange`` -- range for plotting ('auto' is default, otherwise a tuple)
1226
- ``a`` -- factor ``a``
1227
- ``action`` -- select given operation on or combination of functions
1228
- ``do_plot`` -- if true, a plot is drawn
1229
1230
EXAMPLE:
1231
1232
Invoked in the notebook, the following command will produce
1233
the fully formatted interactive mathlet. In the command line,
1234
it will simply return the underlying HTML and Sage code which
1235
creates the mathlet::
1236
1237
sage: interacts.calculus.function_tool()
1238
<html>...</html>
1239
"""
1240
x = SR.var('x')
1241
try:
1242
f = SR(f); g = SR(g); a = SR(a)
1243
except TypeError, msg:
1244
print msg[-200:]
1245
print "Unable to make sense of f,g, or a as symbolic expressions in single variable x."
1246
return
1247
if not (isinstance(xrange, tuple) and len(xrange) == 2):
1248
xrange = (0,1)
1249
h = 0; lbl = ''
1250
if action == 'f':
1251
h = f
1252
lbl = 'f'
1253
elif action == 'df/dx':
1254
h = f.derivative(x)
1255
lbl = r'\frac{\mathrm{d}f}{\mathrm{d}x}'
1256
elif action == 'int f':
1257
h = f.integrate(x)
1258
lbl = r'\int f \,\mathrm{d}x'
1259
elif action == 'num f':
1260
h = f.numerator()
1261
lbl = r'\text{numer(f)}'
1262
elif action == 'den f':
1263
h = f.denominator()
1264
lbl = r'\text{denom(f)}'
1265
elif action == '1/f':
1266
h = 1/f
1267
lbl = r'\frac{1}{f}'
1268
elif action == 'finv':
1269
h = solve(f == var('y'), x)[0].rhs()
1270
lbl = 'f^{-1}(y)'
1271
elif action == 'f+a':
1272
h = f+a
1273
lbl = 'f + a'
1274
elif action == 'f-a':
1275
h = f-a
1276
lbl = 'f - a'
1277
elif action == 'f*a':
1278
h = f*a
1279
lbl = r'f \times a'
1280
elif action == 'f/a':
1281
h = f/a
1282
lbl = r'\frac{f}{a}'
1283
elif action == 'f^a':
1284
h = f**a
1285
lbl = 'f^a'
1286
elif action == 'f^a':
1287
h = f**a
1288
lbl = 'f^a'
1289
elif action == 'f(x+a)':
1290
h = f.subs(x=x+a)
1291
lbl = 'f(x+a)'
1292
elif action == 'f(x*a)':
1293
h = f.subs(x=x*a)
1294
lbl = 'f(xa)'
1295
elif action == 'f+g':
1296
h = f+g
1297
lbl = 'f + g'
1298
elif action == 'f-g':
1299
h = f-g
1300
lbl = 'f - g'
1301
elif action == 'f*g':
1302
h = f*g
1303
lbl = r'f \times g'
1304
elif action == 'f/g':
1305
h = f/g
1306
lbl = r'\frac{f}{g}'
1307
elif action == 'f(g)':
1308
h = f(g)
1309
lbl = 'f(g)'
1310
html('<center><font color="red">$f = %s$</font></center>'%latex(f))
1311
html('<center><font color="green">$g = %s$</font></center>'%latex(g))
1312
html('<center><font color="blue"><b>$h = %s = %s$</b></font></center>'%(lbl, latex(h)))
1313
if do_plot:
1314
P = plot(f, xrange, color='red', thickness=2) + \
1315
plot(g, xrange, color='green', thickness=2) + \
1316
plot(h, xrange, color='blue', thickness=2)
1317
if yrange == 'auto':
1318
show(P, xmin=xrange[0], xmax=xrange[1])
1319
else:
1320
yrange = sage_eval(yrange)
1321
show(P, xmin=xrange[0], xmax=xrange[1], ymin=yrange[0], ymax=yrange[1])
1322
1323
@library_interact
1324
def julia(expo = slider(-10,10,0.1,2),
1325
c_real = slider(-2,2,0.01,0.5, label='real part const.'),
1326
c_imag = slider(-2,2,0.01,0.5, label='imag part const.'),
1327
iterations=slider(1,100,1,20, label='# iterations'),
1328
zoom_x = range_slider(-2,2,0.01,(-1.5,1.5), label='Zoom X'),
1329
zoom_y = range_slider(-2,2,0.01,(-1.5,1.5), label='Zoom Y'),
1330
plot_points = slider(20,400,20, default=150, label='plot points'),
1331
dpi = slider(20, 200, 10, default=80, label='dpi')):
1332
"""
1333
Julia Fractal, based on
1334
`Julia by Harald Schilly <http://wiki.sagemath.org/interact/fractal#Julia>`_.
1335
1336
INPUT:
1337
1338
- ``exponent`` -- exponent ``e`` in `z^e+c`
1339
- ``c_real`` -- real part of the constant ``c``
1340
- ``c_imag`` -- imaginary part of the constant ``c``
1341
- ``iterations`` -- number of iterations
1342
- ``zoom_x`` -- range slider for zoom in x direction
1343
- ``zoom_y`` -- range slider for zoom in y direction
1344
- ``plot_points`` -- number of points to plot
1345
- ``dpi`` -- dots-per-inch parameter for the plot
1346
1347
EXAMPLE:
1348
1349
Invoked in the notebook, the following command will produce
1350
the fully formatted interactive mathlet. In the command line,
1351
it will simply return the underlying HTML and Sage code which
1352
creates the mathlet::
1353
1354
sage: interacts.fractals.julia()
1355
<html>...</html>
1356
"""
1357
z = SR.var('z')
1358
I = CDF.gen()
1359
f = symbolic_expression(z**expo + c_real + c_imag*I).function(z)
1360
ff_j = fast_callable(f, vars=[z], domain=CDF)
1361
1362
from sage.interacts.library_cython import julia
1363
1364
html('<h2>Julia Fractal</h2>')
1365
html(r'Recursive Formula: $z \leftarrow z^{%.2f} + (%.2f+%.2f*\mathbb{I})$' % (expo, c_real, c_imag))
1366
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)
1367
1368
@library_interact
1369
def mandelbrot(expo = slider(-10,10,0.1,2),
1370
iterations=slider(1,100,1,20, label='# iterations'),
1371
zoom_x = range_slider(-2,2,0.01,(-2,1), label='Zoom X'),
1372
zoom_y = range_slider(-2,2,0.01,(-1.5,1.5), label='Zoom Y'),
1373
plot_points = slider(20,400,20, default=150, label='plot points'),
1374
dpi = slider(20, 200, 10, default=80, label='dpi')):
1375
"""
1376
Mandelbrot Fractal, based on
1377
`Mandelbrot by Harald Schilly <http://wiki.sagemath.org/interact/fractal#Mandelbrot>`_.
1378
1379
INPUT:
1380
1381
- ``exponent`` -- exponent ``e`` in `z^e+c`
1382
- ``iterations`` -- number of iterations
1383
- ``zoom_x`` -- range slider for zoom in x direction
1384
- ``zoom_y`` -- range slider for zoom in y direction
1385
- ``plot_points`` -- number of points to plot
1386
- ``dpi`` -- dots-per-inch parameter for the plot
1387
1388
EXAMPLE:
1389
1390
Invoked in the notebook, the following command will produce
1391
the fully formatted interactive mathlet. In the command line,
1392
it will simply return the underlying HTML and Sage code which
1393
creates the mathlet::
1394
1395
sage: interacts.fractals.mandelbrot()
1396
<html>...</html>
1397
"""
1398
x, z, c = SR.var('x, z, c')
1399
f = symbolic_expression(z**expo + c).function(z, c)
1400
ff_m = fast_callable(f, vars=[z,c], domain=CDF)
1401
1402
from sage.interacts.library_cython import mandel
1403
1404
html('<h2>Mandelbrot Fractal</h2>')
1405
html(r'Recursive Formula: $z \leftarrow z^{%.2f} + c$ for $c \in \mathbb{C}$' % expo)
1406
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)
1407
1408
1409
@library_interact
1410
def cellular_automaton(
1411
N=slider(1,500,1,label='Number of iterations',default=100),
1412
rule_number=slider(0, 255, 1, default=110, label='Rule number'),
1413
size = slider(1, 11, step_size=1, default=6, label='size of graphic')):
1414
"""
1415
Yields a matrix showing the evolution of a
1416
`Wolfram's cellular automaton <http://mathworld.wolfram.com/CellularAutomaton.html>`_.
1417
1418
`Based on work by Pablo Angulo <http://wiki.sagemath.org/interact/misc#CellularAutomata>`_.
1419
1420
INPUT:
1421
1422
- ``N`` -- iterations
1423
- ``rule_number`` -- rule number (0 to 255)
1424
- ``size`` -- size of the shown picture
1425
1426
EXAMPLE:
1427
1428
Invoked in the notebook, the following command will produce
1429
the fully formatted interactive mathlet. In the command line,
1430
it will simply return the underlying HTML and Sage code which
1431
creates the mathlet::
1432
1433
sage: interacts.fractals.cellular_automaton()
1434
<html>...</html>
1435
"""
1436
from sage.all import Integer
1437
if not 0 <= rule_number <= 255:
1438
raise Exception('Invalid rule number')
1439
binary_digits = Integer(rule_number).digits(base=2)
1440
rule = binary_digits + [0]*(8-len(binary_digits))
1441
1442
html('<h2>Cellular Automaton</h2>'+
1443
'<div style="white-space: normal;">"A cellular automaton is a collection of "colored" cells \
1444
on a grid of specified shape that evolves through a number of \
1445
discrete time steps according to a set of rules based on the \
1446
states of neighboring cells." &mdash; \
1447
<a target="_blank" href="http://mathworld.wolfram.com/CellularAutomaton.html">Mathworld,\
1448
Cellular Automaton</a></div>\
1449
<div>Rule %s expands to %s</div>' % (rule_number, ''.join(map(str,rule)))
1450
)
1451
1452
from sage.interacts.library_cython import cellular
1453
M = cellular(rule, N)
1454
plot_M = matrix_plot(M, cmap='binary')
1455
plot_M.show(figsize=[size,size])
1456
1457
1458
@library_interact
1459
def polar_prime_spiral(
1460
interval = range_slider(1, 4000, 10, default=(1, 1000), label="range"),
1461
show_factors = True,
1462
highlight_primes = True,
1463
show_curves = True,
1464
n = slider(1,200, 1, default=89, label="number $n$"),
1465
dpi = slider(10,300, 10, default=100, label="dpi")):
1466
"""
1467
Polar Prime Spiral interact, based on work by David Runde.
1468
1469
For more information about the factors in the spiral,
1470
`visit John Williamson's website <http://www.dcs.gla.ac.uk/~jhw/spirals/index.html>`_.
1471
1472
INPUT:
1473
1474
- ``interval`` -- range slider to specify start and end
1475
- ``show_factors`` -- if true, show factors
1476
- ``highlight_primes`` -- if true, prime numbers are highlighted
1477
- ``show_curves`` -- if true, curves are plotted
1478
- ``n`` -- number `n`
1479
- ``dpi`` -- dots per inch resolution for plotting
1480
1481
EXAMPLE:
1482
1483
Invoked in the notebook, the following command will produce
1484
the fully formatted interactive mathlet. In the command line,
1485
it will simply return the underlying HTML and Sage code which
1486
creates the mathlet::
1487
1488
sage: sage.interacts.algebra.polar_prime_spiral()
1489
<html>...</html>
1490
1491
"""
1492
1493
html('<h2>Polar Prime Spiral</h2> \
1494
<div style="white-space: normal;">\
1495
For more information about the factors in the spiral, visit \
1496
<a href="http://www.dcs.gla.ac.uk/~jhw/spirals/index.html" target="_blank">\
1497
Number Spirals by John Williamson</a>.</div>'
1498
)
1499
1500
start, end = interval
1501
from sage.ext.fast_eval import fast_float
1502
from math import floor, ceil
1503
from sage.plot.colors import hue
1504
1505
if start < 1 or end <= start:
1506
print "invalid start or end value"
1507
return
1508
if n > end:
1509
print "WARNING: n is greater than end value"
1510
return
1511
if n < start:
1512
print "n < start value"
1513
return
1514
nn = SR.var('nn')
1515
f1 = fast_float(sqrt(nn)*cos(2*pi*sqrt(nn)), 'nn')
1516
f2 = fast_float(sqrt(nn)*sin(2*pi*sqrt(nn)), 'nn')
1517
f = lambda x: (f1(x), f2(x))
1518
1519
list =[]
1520
list2=[]
1521
if show_factors == False:
1522
for i in srange(start, end, include_endpoint = True):
1523
if Integer(i).is_pseudoprime(): list.append(f(i-start+1)) #Primes list
1524
else: list2.append(f(i-start+1)) #Composites list
1525
P = points(list)
1526
R = points(list2, alpha = .1) #Faded Composites
1527
else:
1528
for i in srange(start, end, include_endpoint = True):
1529
list.append(disk((f(i-start+1)),0.05*pow(2,len(factor(i))-1), (0,2*pi))) #resizes each of the dots depending of the number of factors of each number
1530
if Integer(i).is_pseudoprime() and highlight_primes: list2.append(f(i-start+1))
1531
P = plot(list)
1532
p_size = 5 #the orange dot size of the prime markers
1533
if not highlight_primes: list2 = [(f(n-start+1))]
1534
R = points(list2, hue = .1, pointsize = p_size)
1535
1536
if n > 0:
1537
html('$n = %s$' % factor(n))
1538
1539
p = 1
1540
#The X which marks the given n
1541
W1 = disk((f(n-start+1)), p, (pi/6, 2*pi/6))
1542
W2 = disk((f(n-start+1)), p, (4*pi/6, 5*pi/6))
1543
W3 = disk((f(n-start+1)), p, (7*pi/6, 8*pi/6))
1544
W4 = disk((f(n-start+1)), p, (10*pi/6, 11*pi/6))
1545
Q = plot(W1 + W2 + W3 + W4, alpha = .1)
1546
1547
n = n - start +1 #offsets the n for different start values to ensure accurate plotting
1548
if show_curves:
1549
begin_curve = 0
1550
t = SR.var('t')
1551
a=1.0
1552
b=0.0
1553
if n > (floor(sqrt(n)))**2 and n <= (floor(sqrt(n)))**2 + floor(sqrt(n)):
1554
c = -((floor(sqrt(n)))**2 - n)
1555
c2= -((floor(sqrt(n)))**2 + floor(sqrt(n)) - n)
1556
else:
1557
c = -((ceil(sqrt(n)))**2 - n)
1558
c2= -((floor(sqrt(n)))**2 + floor(sqrt(n)) - n)
1559
html('Pink Curve: $n^2 + %s$' % c)
1560
html('Green Curve: $n^2 + n + %s$' % c2)
1561
m = SR.var('m')
1562
g = symbolic_expression(a*m**2+b*m+c).function(m)
1563
r = symbolic_expression(sqrt(g(m))).function(m)
1564
theta = symbolic_expression(r(m)- m*sqrt(a)).function(m)
1565
S1 = parametric_plot(((r(t))*cos(2*pi*(theta(t))),(r(t))*sin(2*pi*(theta(t)))),
1566
(begin_curve, ceil(sqrt(end-start))), color=hue(0.8), thickness = .3) #Pink Line
1567
1568
b = 1
1569
c = c2;
1570
g = symbolic_expression(a*m**2+b*m+c).function(m)
1571
r = symbolic_expression(sqrt(g(m))).function(m)
1572
theta = symbolic_expression(r(m)- m*sqrt(a)).function(m)
1573
S2 = parametric_plot(((r(t))*cos(2*pi*(theta(t))),(r(t))*sin(2*pi*(theta(t)))),
1574
(begin_curve, ceil(sqrt(end-start))), color=hue(0.6), thickness = .3) #Green Line
1575
1576
show(R+P+S1+S2+Q, aspect_ratio = 1, axes = False, dpi = dpi)
1577
else: show(R+P+Q, aspect_ratio = 1, axes = False, dpi = dpi)
1578
else: show(R+P, aspect_ratio = 1, axes = False, dpi = dpi)
1579
1580
1581
1582
1583