# HG changeset patch # User Marshall Hampton # Date 1294873282 21600 # Node ID f711e2a0e1d559f83ba72655b703f8b7cc9d0548 # Parent c58f82863c75b2e53662e08cd550bb398653174c Trac #9623: rebasing and minor restructuring. diff -r c58f82863c75 -r f711e2a0e1d5 module_list.py --- a/module_list.py Tue Jan 11 00:49:28 2011 +0100 +++ b/module_list.py Wed Jan 12 17:01:22 2011 -0600 @@ -482,6 +482,16 @@ ################################ ## + ## sage.interacts + ## + ################################ + + Extension('sage.interacts.library_cython', + sources = ['sage/interacts/library_cython.pyx'], + libraries = []), + + ################################ + ## ## sage.libs ## ################################ diff -r c58f82863c75 -r f711e2a0e1d5 sage/all.py --- a/sage/all.py Tue Jan 11 00:49:28 2011 +0100 +++ b/sage/all.py Wed Jan 12 17:01:22 2011 -0600 @@ -131,7 +131,7 @@ import sage.finance.all as finance -import sage.interacts as interacts +import sage.interacts.all as interacts from sage.parallel.all import * diff -r c58f82863c75 -r f711e2a0e1d5 sage/interacts/__init__.py --- a/sage/interacts/__init__.py Tue Jan 11 00:49:28 2011 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,5 +0,0 @@ -""" -Interacts included with sage -""" -import calculus -import library diff -r c58f82863c75 -r f711e2a0e1d5 sage/interacts/algebra.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sage/interacts/algebra.py Wed Jan 12 17:01:22 2011 -0600 @@ -0,0 +1,14 @@ +""" +Interacts for Algebra and Number Theory + +""" + + +#***************************************************************************** +# Copyright (C) 2010 Harald Schilly +# +# Distributed under the terms of the GNU General Public License (GPL) +# http://www.gnu.org/licenses/ +#***************************************************************************** + +from library import polar_prime_spiral diff -r c58f82863c75 -r f711e2a0e1d5 sage/interacts/all.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sage/interacts/all.py Wed Jan 12 17:01:22 2011 -0600 @@ -0,0 +1,9 @@ +""" +Interacts included with sage +""" +import calculus +import geometry +import statistics +import fractals +import algebra +from library import demo diff -r c58f82863c75 -r f711e2a0e1d5 sage/interacts/calculus.py --- a/sage/interacts/calculus.py Tue Jan 11 00:49:28 2011 +0100 +++ b/sage/interacts/calculus.py Wed Jan 12 17:01:22 2011 -0600 @@ -1,1 +1,20 @@ +""" +Interacts for Calculus + +""" + + +#***************************************************************************** +# Copyright (C) 2010 Harald Schilly +# +# Distributed under the terms of the GNU General Public License (GPL) +# http://www.gnu.org/licenses/ +#***************************************************************************** + from library import taylor_polynomial +from library import definite_integral +from library import function_derivative, difference_quotient, quadratic_equation +from library import trigonometric_properties_triangle +from library import secant_method, newton_method, trapezoid_integration, simpson_integration, bisection_method +from library import riemann_sum +from library import function_tool diff -r c58f82863c75 -r f711e2a0e1d5 sage/interacts/fractals.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sage/interacts/fractals.py Wed Jan 12 17:01:22 2011 -0600 @@ -0,0 +1,14 @@ +""" +Interacts for Fractals + +""" + + +#***************************************************************************** +# Copyright (C) 2010 Harald Schilly +# +# Distributed under the terms of the GNU General Public License (GPL) +# http://www.gnu.org/licenses/ +#***************************************************************************** + +from library import mandelbrot, julia, cellular_automaton diff -r c58f82863c75 -r f711e2a0e1d5 sage/interacts/geometry.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sage/interacts/geometry.py Wed Jan 12 17:01:22 2011 -0600 @@ -0,0 +1,15 @@ +""" +Interacts for Geometry + +""" + + +#***************************************************************************** +# Copyright (C) 2010 Harald Schilly +# +# Distributed under the terms of the GNU General Public License (GPL) +# http://www.gnu.org/licenses/ +#***************************************************************************** + +from library import unit_circle, cube_hemisphere +from library import trigonometric_properties_triangle, special_points diff -r c58f82863c75 -r f711e2a0e1d5 sage/interacts/library.py --- a/sage/interacts/library.py Tue Jan 11 00:49:28 2011 +0100 +++ b/sage/interacts/library.py Wed Jan 12 17:01:22 2011 -0600 @@ -1,11 +1,33 @@ """ -A library of interacts +Sage Interacts + +Sage interacts are applications of the `@interact decorator <../../sagenb/notebook/interact.html>`_. +They are conveniently accessible in the Sage Notebook via ``interacts.[TAB].[TAB]()``. +The first ``[TAB]`` lists categories and the second ``[TAB]`` reveals the interact examples. + +EXAMPLE:: + + sage: interacts.calculus.taylor_polynomial() + ... + """ -from sagenb.notebook.interact import interact, slider, range_slider, input_box -from sage.all import sin, plot, point, html, show, latex, SR,exp -x=SR.var('x') +#***************************************************************************** +# Copyright (C) 2009 William Stein +# Copyright (C) 2010 Harald Schilly +# +# Distributed under the terms of the GNU General Public License (GPL) +# http://www.gnu.org/licenses/ +#***************************************************************************** + +from sagenb.notebook.interact import interact, slider, range_slider, input_box, selector, checkbox, input_grid, text_control +from sage.all import sin, cos, asin, acos, tan, sqrt, SR, exp, symbolic_expression, N, derivative, pi +from sage.all import factor, srange, Integer, points +from sage.all import point, line2d, text, Graphics, plot, point, html, show, latex, circle, line, parametric_plot, polygon2d +from sage.all import implicit_plot3d, plot3d, cube, integral_numerical, CDF, complex_plot, matrix_plot, disk + +from sage.ext.fast_callable import fast_callable from sage.misc.decorators import sage_wraps from sage.misc.html import html @@ -15,7 +37,8 @@ EXAMPLES:: - sage: @interacts.library.library_interact + sage: import sage.interacts.library as library + sage: @library.library_interact ... def f(n=5): print n ... sage: f() # an interact appears @@ -37,26 +60,27 @@ INPUT: - - `n` -- integer slider - - `m` -- integer slider + - ``n`` -- integer slider + - ``m`` -- integer slider EXAMPLES:: - sage: interacts.library.demo() + sage: interacts.demo() ... """ print n+m - - +x=SR.var('x') @library_interact -def taylor_polynomial(f=input_box(sin(x)*exp(-x)), order=slider(range(1,13))): +def taylor_polynomial( + title = text_control('

Taylor polynomial

'), + f=input_box(sin(x)*exp(-x),label="$f(x)=$"), order=slider(range(1,13))): """ An interact which illustrates the Taylor polynomial approximation of various orders around `x=0`. - - `f` -- function expression - - ``order`` -- integer slider + - ``f`` -- function expression + - ```order``` -- integer slider EXAMPLES:: @@ -71,3 +95,1401 @@ html('$f(x)\;=\;%s$'%latex(f)) html('$\hat{f}(x;%s)\;=\;%s+\mathcal{O}(x^{%s})$'%(x0,latex(ft),order+1)) show(dot + p + pt, ymin = -.5, ymax = 1) + +@library_interact +def definite_integral( + title = text_control('

Definite integral

'), + f = input_box(default = "3*x", label = '$f(x)=$'), + g = input_box(default = "x^2", label = '$g(x)=$'), + interval = range_slider(-10,10,default=(0,3), label="Interval"), + x_range = range_slider(-10,10,default=(0,3), label = "plot range (x)"), + selection = selector(["f", "g", "f and g", "f - g"], default="f and g", label="Select")): + """ + This is a demo interact for plotting the definite intergral of a function + based on work by Lauri Ruotsalainen, 2010. + + INPUT: + + - ``function`` -- input box, function in x + - ``interval`` -- interval for the definite integral + - ``x_range`` -- range slider for plotting range + - ``selection`` -- selector on how to visualize the integrals + + EXAMPLES:: + + sage: interacts.calculus.definite_integral() + ... + """ + x = SR.var('x') + f = symbolic_expression(f).function(x) + g = symbolic_expression(g).function(x) + f_plot = Graphics(); g_plot = Graphics(); h_plot = Graphics(); + text = "" + + # Plot function f. + if selection != "g": + f_plot = plot(f(x), x, x_range, color="blue", thickness=1.5) + + # Color and calculate the area between f and the horizontal axis. + if selection == "f" or selection == "f and g": + f_plot += plot(f(x), x, interval, color="blue", fill=True, fillcolor="blue", fillalpha=0.15) + text += r"$\int_{%.2f}^{%.2f}(\color{Blue}{f(x)})\,\mathrm{d}x=\int_{%.2f}^{%.2f}(%s)\,\mathrm{d}x=%.2f$" % ( + interval[0], interval[1], + interval[0], interval[1], + latex(f(x)), + f(x).nintegrate(x, interval[0], interval[1])[0] + ) + + if selection == "f and g": + text += r"
" + + # Plot function g. Also color and calculate the area between g and the horizontal axis. + if selection == "g" or selection == "f and g": + g_plot = plot(g(x), x, x_range, color="green", thickness=1.5) + g_plot += plot(g(x), x, interval, color="green", fill=True, fillcolor="yellow", fillalpha=0.5) + text += r"$\int_{%.2f}^{%.2f}(\color{Green}{g(x)})\,\mathrm{d}x=\int_{%.2f}^{%.2f}(%s)\,\mathrm{d}x=%.2f$" % ( + interval[0], interval[1], + interval[0], interval[1], + latex(g(x)), + g(x).nintegrate(x, interval[0], interval[1])[0] + ) + + # Plot function f-g. Also color and calculate the area between f-g and the horizontal axis. + if selection == "f - g": + g_plot = plot(g(x), x, x_range, color="green", thickness=1.5) + g_plot += plot(g(x), x, interval, color="green", fill=f(x), fillcolor="red", fillalpha=0.15) + h_plot = plot(f(x)-g(x), x, interval, color="red", thickness=1.5, fill=True, fillcolor="red", fillalpha=0.15) + text = r"$\int_{%.2f}^{%.2f}(\color{Red}{f(x)-g(x)})\,\mathrm{d}x=\int_{%.2f}^{%.2f}(%s)\,\mathrm{d}x=%.2f$" % ( + interval[0], interval[1], + interval[0], interval[1], + latex(f(x)-g(x)), + (f(x)-g(x)).nintegrate(x, interval[0], interval[1])[0] + ) + + show(f_plot + g_plot + h_plot, gridlines=True) + html(text) + +@library_interact +def function_derivative( + title = text_control('

Derivative grapher

'), + function = input_box(default="x^5-3*x^3+1", label="Function:"), + x_range = range_slider(-15,15,0.1, default=(-2,2), label="Range (x)"), + y_range = range_slider(-15,15,0.1, default=(-8,6), label="Range (y)")): + """ + This is a demo interact for plotting derivatives of a function based on work by + Lauri Ruotsalainen, 2010. + + INPUT: + + - ``function`` -- input box, function in x + - ``x_range`` -- range slider for plotting range + - ``y_range`` -- range slider for plotting range + + EXAMPLES:: + + sage: interacts.calculus.function_derivative() + ... + """ + x = SR.var('x') + f = symbolic_expression(function).function(x) + df = derivative(f, x) + ddf = derivative(df, x) + plots = plot(f(x), x_range, thickness=1.5) + plot(df(x), x_range, color="green") + plot(ddf(x), x_range, color="red") + if y_range == (0,0): + show(plots, xmin=x_range[0], xmax=x_range[1]) + else: + show(plots, xmin=x_range[0], xmax=x_range[1], ymin=y_range[0], ymax=y_range[1]) + + html("
$\color{Blue}{f(x) = %s}$
"%latex(f(x))) + html("
$\color{Green}{f'(x) = %s}$
"%latex(df(x))) + html("
$\color{Red}{f''(x) = %s}$
"%latex(ddf(x))) + +@library_interact +def difference_quotient( + title = text_control('

Difference quotient

'), + f = input_box(default="sin(x)", label='f(x)'), + interval= range_slider(0, 10, 0.1, default=(0.0,10.0), label="Range"), + a = slider(0, 10, None, 5.5, label = 'a'), + x0 = slider(0, 10, None, 2.5), label = 'start point'): + """ + This is a demo interact for difference quotient based on work by + Lauri Ruotsalainen, 2010. + + INPUT: + + - ``f`` -- input box, function in x + - ``interval`` -- range slider for plotting + - ``a`` -- slider for a + - ``x0`` -- slider for x0 + + EXAMPLES:: + + sage: interacts.calculus.difference_quotient() + ... + """ + html('

Difference Quotient

') + html('' + ) + + x = SR.var('x') + f = symbolic_expression(f).function(x) + fmax = f.find_maximum_on_interval(interval[0], interval[1])[0] + fmin = f.find_minimum_on_interval(interval[0], interval[1])[0] + f_height = fmax - fmin + measure_y = fmin - 0.1*f_height + + measure_0 = line2d([(x0, measure_y), (a, measure_y)], rgbcolor="black") + measure_1 = line2d([(x0, measure_y + 0.02*f_height), (x0, measure_y-0.02*f_height)], rgbcolor="black") + measure_2 = line2d([(a, measure_y + 0.02*f_height), (a, measure_y-0.02*f_height)], rgbcolor="black") + text_x0 = text("x0", (x0, measure_y - 0.05*f_height), rgbcolor="black") + text_a = text("a", (a, measure_y - 0.05*f_height), rgbcolor="black") + measure = measure_0 + measure_1 + measure_2 + text_x0 + text_a + + tanf = symbolic_expression((f(x0)-f(a))*(x-a)/(x0-a)+f(a)).function(x) + + fplot = plot(f(x), x, interval[0], interval[1]) + tanplot = plot(tanf(x), x, interval[0], interval[1], rgbcolor="#FF0000") + points = point([(x0, f(x0)), (a, f(a))], pointsize=20, rgbcolor="#005500") + dashline = line2d([(x0, f(x0)), (x0, f(a)), (a, f(a))], rgbcolor="#005500", linestyle="--") + html('

Difference Quotient

') + show(fplot + tanplot + points + dashline + measure, xmin=interval[0], xmax=interval[1], ymin=fmin-0.2*f_height, ymax=fmax) + html(r"
$\text{Line's equation:}$") + html(r"$y = %s$
"%tanf(x)) + html(r"$\text{Slope:}$") + html(r"$k = \frac{f(x0)-f(a)}{x0-a} = %s$
" % (N(derivative(tanf(x), x), digits=5))) + +@library_interact +def quadratic_equation(A = slider(-7, 7, 1, 1), B = slider(-7, 7, 1, 1), C = slider(-7, 7, 1, -2)): + """ + This is a demo interact for solving quadratic equations based on work by + Lauri Ruotsalainen, 2010. + + INPUT: + + - ``A`` -- integer slider + - ``B`` -- integer slider + - ``C`` -- integer slider + + EXAMPLES:: + + sage: interacts.calculus.quadratic_equation() + ... + """ + x = SR.var('x') + f = symbolic_expression(A*x**2 + B*x + C).function(x) + html('

The Solutions of the Quadratic Equation

') + html("$%s = 0$" % f(x)) + + show(plot(f(x), x, (-10, 10), ymin=-10, ymax=10), aspect_ratio=1, figsize=4) + + d = B**2 - 4*A*C + + if d < 0: + color = "Red" + sol = r"\text{solution} \in \mathbb{C}" + elif d == 0: + color = "Blue" + sol = -B/(2*A) + else: + color = "Green" + a = (-B+sqrt(B**2-4*A*C))/(2*A) + b = (-B-sqrt(B**2-4*A*C))/(2*A) + sol = r"\begin{cases}%s\\%s\end{cases}" % (latex(a), latex(b)) + + if B < 0: + dis1 = "(%s)^2-4*%s*%s" % (B, A, C) + else: + dis1 = "%s^2-4*%s*%s" % (B, A, C) + dis2 = r"\color{%s}{%s}" % (color, d) + + html("$Ax^2 + Bx + C = 0$") + calc = r"$x = \frac{-B\pm\sqrt{B^2-4AC}}{2A} = " + \ + r"\frac{-%s\pm\sqrt{%s}}{2*%s} = " + \ + r"\frac{-%s\pm\sqrt{%s}}{%s} = %s$" + html(calc % (B, dis1, A, B, dis2, (2*A), sol)) + +@library_interact +def trigonometric_properties_triangle( + a0 = slider(0, 360, 1, 30, label="A"), + a1 = slider(0, 360, 1, 180, label="B"), + a2 = slider(0, 360, 1, 300, label="C")): + """ + This is an interact for demonstrating trigonometric properties + in a triangle based on work by Lauri Ruotsalainen, 2010. + + INPUT: + + - ``a0`` -- angle + - ``a1`` -- angle + - ``a2`` -- angle + + EXAMPLES:: + + sage: interacts.geometry.trigonometric_properties_triangle() + ... + """ + import math + + # Returns the distance between points (x1,y1) and (x2,y2) + def distance((x1, y1), (x2, y2)): + return sqrt((x2-x1)**2 + (y2-y1)**2) + + # Returns an angle (in radians) when sides a and b + # are adjacent and the side c is opposite to the angle + def angle(a, b, c): + a,b,c = map(float,[a,b,c]) + return acos((b**2 + c**2 - a**2)/(2.0*b*c)) + + # Returns the area of a triangle when an angle alpha + # and adjacent sides a and b are known + def area(alpha, a, b): + return 1.0/2.0*a*b*sin(alpha) + + xy = [0]*3 + html('

Trigonometric Properties of a Triangle

') + # Coordinates of the angles + a = map(lambda x : math.radians(float(x)), [a0, a1, a2]) + for i in range(3): + xy[i] = (cos(a[i]), sin(a[i])) + + # Side lengths (bc, ca, ab) corresponding to triangle vertices (a, b, c) + al = [distance(xy[1], xy[2]), distance(xy[2], xy[0]), distance(xy[0], xy[1])] + + # The angles (a, b, c) in radians + ak = [angle(al[0], al[1], al[2]), angle(al[1], al[2], al[0]), angle(al[2], al[0], al[1])] + + # The area of the triangle + A = area(ak[0], al[1], al[2]) + + unit_circle = circle((0, 0), 1, aspect_ratio=1) + + # Triangle + triangle = line([xy[0], xy[1], xy[2], xy[0]], rgbcolor="black") + triangle_points = point(xy, pointsize=30) + + # Labels of the angles drawn in a distance from points + a_label = text("A", (xy[0][0]*1.07, xy[0][1]*1.07)) + b_label = text("B", (xy[1][0]*1.07, xy[1][1]*1.07)) + c_label = text("C", (xy[2][0]*1.07, xy[2][1]*1.07)) + labels = a_label + b_label + c_label + + show(unit_circle + triangle + triangle_points + labels, figsize=[5, 5], xmin=-1, xmax=1, ymin=-1, ymax=1) + angl_txt = r"$\angle A = {%s}^{\circ},$ $\angle B = {%s}^{\circ},$ $\angle C = {%s}^{\circ}$" % ( + math.degrees(ak[0]), + math.degrees(ak[1]), + math.degrees(ak[2]) + ) + html(angl_txt) + html(r"$AB = %s,$ $BC = %s,$ $CA = %s$"%(al[2], al[0], al[1])) + html(r"$\text{Area A} = %s$"%A) + +@library_interact +def unit_circle( + function = selector([(0, sin(x)), (1, cos(x)), (2, tan(x))]), + x = slider(0,2*pi, 0.005*pi, 0)): + """ + This is an interact for Sin, Cos and Tan in the Unit Circle + based on work by Lauri Ruotsalainen, 2010. + + INPUT: + + - ``function`` -- select Sin, Cos or Tan + - ``x`` -- slider to select angle in unit circle + + EXAMPLES:: + + sage: interacts.geometry.unit_circle() + ... + """ + xy = (cos(x), sin(x)) + t = SR.var('t') + html('
Lines of the same color have\ + the same length
') + + # Unit Circle + C = circle((0, 0), 1, figsize=[5, 5], aspect_ratio=1) + C_line = line([(0, 0), (xy[0], xy[1])], rgbcolor="black") + C_point = point((xy[0], xy[1]), pointsize=40, rgbcolor="green") + C_inner = parametric_plot((cos(t), sin(t)), (t, 0, x + 0.001), color="green", thickness=3) + C_outer = parametric_plot((0.1 * cos(t), 0.1 * sin(t)), (t, 0, x + 0.001), color="black") + C_graph = C + C_line + C_point + C_inner + C_outer + + # Graphics related to the graph of the function + G_line = line([(0, 0), (x, 0)], rgbcolor="green", thickness=3) + G_point = point((x, 0), pointsize=30, rgbcolor="green") + G_graph = G_line + G_point + + # Sine + if function == 0: + Gf = plot(sin(t), t, 0, 2*pi, axes_labels=("x", "sin(x)")) + Gf_point = point((x, sin(x)), pointsize=30, rgbcolor="red") + Gf_line = line([(x, 0),(x, sin(x))], rgbcolor="red") + Cf_point = point((0, xy[1]), pointsize=40, rgbcolor="red") + Cf_line1 = line([(0, 0), (0, xy[1])], rgbcolor="red", thickness=3) + Cf_line2 = line([(0, xy[1]), (xy[0], xy[1])], rgbcolor="purple", linestyle="--") + # Cosine + elif function == 1: + Gf = plot(cos(t), t, 0, 2*pi, axes_labels=("x", "cos(x)")) + Gf_point = point((x, cos(x)), pointsize=30, rgbcolor="red") + Gf_line = line([(x, 0), (x, cos(x))], rgbcolor="red") + Cf_point = point((xy[0], 0), pointsize=40, rgbcolor="red") + Cf_line1 = line([(0, 0), (xy[0], 0)], rgbcolor="red", thickness=3) + Cf_line2 = line([(xy[0], 0), (xy[0], xy[1])], rgbcolor="purple", linestyle="--") + # Tangent + else: + Gf = plot(tan(t), t, 0, 2*pi, ymin=-8, ymax=8, axes_labels=("x", "tan(x)")) + Gf_point = point((x, tan(x)), pointsize=30, rgbcolor="red") + Gf_line = line([(x, 0), (x, tan(x))], rgbcolor="red") + Cf_point = point((1, tan(x)), pointsize=40, rgbcolor="red") + Cf_line1 = line([(1, 0), (1, tan(x))], rgbcolor="red", thickness=3) + Cf_line2 = line([(xy[0], xy[1]), (1, tan(x))], rgbcolor="purple", linestyle="--") + + C_graph += Cf_point + Cf_line1 + Cf_line2 + G_graph += Gf + Gf_point + Gf_line + + html.table([[r"$\text{Unit Circle}$",r"$\text{Function}$"], [C_graph, G_graph]], header=True) + +@library_interact +def cube_hemisphere(size = slider(0.5, 1, label="The Edge Length x:")): + """ + This interact demo shows a cube within a hemisphere + based on work by Lauri Ruotsalainen, 2010. + + INPUT: + + - ``size`` -- slider to select the edge length x + + EXAMPLES:: + + sage: interacts.geometry.cube_hemisphere() + ... + """ + html('

Cube within a Hemisphere

') + html('
A cube is placed within a hemisphere so that the corners ' +\ + 'of the cube touch the surface of the hemisphere; Observe numerically ' + \ + 'the ratio of the volume of the cube and the volume of the hemisphere.
') + x, y, z = SR.var("x,y,z") + hemisphere_graph = implicit_plot3d(x**2+y**2+z**2==1, (x, -1, 1), (y, -1, 1), (z, 0, 1), color="green", opacity=0.4) + cube_graph = cube(size=size, opacity=0.9, color="red", frame_thickness=1).translate((0, 0, size/2.0)) + surface_graph = plot3d(0, (x, -1.2, 1.2),(y, -1.2, 1.2), color="lightblue", opacity=0.6) + show(hemisphere_graph + cube_graph + surface_graph, aspect_ratio=1) + + V_c = size**3 + V_hs = 4*pi*1**3/6.0 + html(r"$\text{Volume of the Cube: }V_{cube} = x^3 = {%.5f}^3 = %s" % (N(size, digits=5), N(V_c, digits=5))) + html(r"$\text{Volume of the Hemisphere: }V_{hemisphere} = \frac{4\pi r^3}{3}:2 = \frac{4\pi 1^3}{3}:2 = %.5f$" % N(V_hs, digits=5)) + html(r"$\text{Ratio: }V_{cube}/V_{hemisphere} = %.5f/%.5f = %.5f$" % (N(V_c, digits=5), N(V_hs, digits=5), N(V_c/V_hs, digits=5))) + + +@library_interact +def special_points( + title = text_control('

Special points in triangle

'), + a0 = slider(0, 360, 1, 30, label="A"), + a1 = slider(0, 360, 1, 180, label="B"), + a2 = slider(0, 360, 1, 300, label="C"), + show_median = checkbox(False, label="Medians"), + show_pb = checkbox(False, label="Perpendicular Bisectors"), + show_alt = checkbox(False, label="Altitudes"), + show_ab = checkbox(False, label="Angle Bisectors"), + show_incircle = checkbox(False, label="Incircle"), + show_euler = checkbox(False, label="Euler's Line")): + """ + This interact demo shows special points in a triangle + based on work by Lauri Ruotsalainen, 2010. + + INPUT: + + - ``a0`` -- angle + - ``a1`` -- angle + - ``a2`` -- angle + - ``show_median`` -- checkbox + - ``show_pb`` -- checkbox to show perpendicular bisectors + - ``show_alt`` -- checkbox to show altitudes + - ``show_ab`` -- checkbox to show angle bisectors + - ``show_incircle`` -- checkbox to show incircle + - ``show_euler`` -- checkbox to show euler's line + + EXAMPLES:: + + sage: interacts.geometry.special_points() + ... + """ + import math + # Return the intersection point of the bisector of the angle <(A[a],A[c],A[b]) and the unit circle. Angles given in radians. + def half(A, a, b, c): + 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])): + p = A[a] + (A[b] - A[a]) / 2.0 + else: + p = A[b] + (2*pi - (A[b]-A[a])) / 2.0 + return (math.cos(p), math.sin(p)) + + # Returns the distance between points (x1,y1) and (x2,y2) + def distance((x1, y1), (x2, y2)): + return math.sqrt((x2-x1)**2 + (y2-y1)**2) + + # Returns the line (graph) going through points (x1,y1) and (x2,y2) + def line_to_points((x1, y1), (x2, y2), **plot_kwargs): + return plot((y2-y1) / (x2-x1) * (x-x1) + y1, (x,-3,3), **plot_kwargs) + + # Coordinates of the angles + a = map(lambda x : math.radians(float(x)), [a0, a1, a2]) + xy = [(math.cos(a[i]), math.sin(a[i])) for i in range(3)] + + # Labels of the angles drawn in a distance from points + a_label = text("A", (xy[0][0]*1.07, xy[0][1]*1.07)) + b_label = text("B", (xy[1][0]*1.07, xy[1][1]*1.07)) + c_label = text("C", (xy[2][0]*1.07, xy[2][1]*1.07)) + labels = a_label + b_label + c_label + + C = circle((0, 0), 1, aspect_ratio=1) + + # Triangle + triangle = line([xy[0], xy[1], xy[2], xy[0]], rgbcolor="black") + triangle_points = point(xy, pointsize=30) + + # Side lengths (bc, ca, ab) corresponding to triangle vertices (a, b, c) + ad = [distance(xy[1], xy[2]), distance(xy[2], xy[0]), distance(xy[0], xy[1])] + + # Midpoints of edges (bc, ca, ab) + a_middle = [ + ((xy[1][0] + xy[2][0])/2.0, (xy[1][1] + xy[2][1])/2.0), + ((xy[2][0] + xy[0][0])/2.0, (xy[2][1] + xy[0][1])/2.0), + ((xy[0][0] + xy[1][0])/2.0, (xy[0][1] + xy[1][1])/2.0) + ] + + # Incircle + perimeter = float(ad[0] + ad[1] + ad[2]) + incircle_center = ( + (ad[0]*xy[0][0] + ad[1]*xy[1][0] + ad[2]*xy[2][0]) / perimeter, + (ad[0]*xy[0][1] + ad[1]*xy[1][1] + ad[2]*xy[2][1]) / perimeter + ) + + if show_incircle: + s = perimeter/2.0 + incircle_r = math.sqrt((s - ad[0]) * (s - ad[1]) * (s - ad[2]) / s) + incircle_graph = circle(incircle_center, incircle_r) + point(incircle_center) + else: + incircle_graph = Graphics() + + # Angle Bisectors + if show_ab: + a_ab = line([xy[0], half(a, 1, 2, 0)], rgbcolor="blue", alpha=0.6) + b_ab = line([xy[1], half(a, 2, 0, 1)], rgbcolor="blue", alpha=0.6) + c_ab = line([xy[2], half(a, 0, 1, 2)], rgbcolor="blue", alpha=0.6) + ab_point = point(incircle_center, rgbcolor="blue", pointsize=28) + ab_graph = a_ab + b_ab + c_ab + ab_point + else: + ab_graph = Graphics() + + # Medians + if show_median: + a_median = line([xy[0], a_middle[0]], rgbcolor="green", alpha=0.6) + b_median = line([xy[1], a_middle[1]], rgbcolor="green", alpha=0.6) + c_median = line([xy[2], a_middle[2]], rgbcolor="green", alpha=0.6) + median_point = point( + ( + (xy[0][0]+xy[1][0]+xy[2][0])/3.0, + (xy[0][1]+xy[1][1]+xy[2][1])/3.0 + ), rgbcolor="green", pointsize=28) + median_graph = a_median + b_median + c_median + median_point + else: + median_graph = Graphics() + + # Perpendicular Bisectors + if show_pb: + a_pb = line_to_points(a_middle[0], half(a, 1, 2, 0), rgbcolor="red", alpha=0.6) + b_pb = line_to_points(a_middle[1], half(a, 2, 0, 1), rgbcolor="red", alpha=0.6) + c_pb = line_to_points(a_middle[2], half(a, 0, 1, 2), rgbcolor="red", alpha=0.6) + pb_point = point((0, 0), rgbcolor="red", pointsize=28) + pb_graph = a_pb + b_pb + c_pb + pb_point + else: + pb_graph = Graphics() + + # Altitudes + if show_alt: + xA, xB, xC = xy[0][0], xy[1][0], xy[2][0] + yA, yB, yC = xy[0][1], xy[1][1], xy[2][1] + a_alt = plot(((xC-xB)*x+(xB-xC)*xA)/(yB-yC)+yA, (x,-3,3), rgbcolor="brown", alpha=0.6) + b_alt = plot(((xA-xC)*x+(xC-xA)*xB)/(yC-yA)+yB, (x,-3,3), rgbcolor="brown", alpha=0.6) + c_alt = plot(((xB-xA)*x+(xA-xB)*xC)/(yA-yB)+yC, (x,-3,3), rgbcolor="brown", alpha=0.6) + 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) + 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) + alt_intersection = point((alt_lx, alt_ly), rgbcolor="brown", pointsize=28) + alt_graph = a_alt + b_alt + c_alt + alt_intersection + else: + alt_graph = Graphics() + + # Euler's Line + if show_euler: + euler_graph = line_to_points( + (0, 0), + ( + (xy[0][0]+xy[1][0]+xy[2][0])/3.0, + (xy[0][1]+xy[1][1]+xy[2][1])/3.0 + ), + rgbcolor="purple", + thickness=2, + alpha=0.7 + ) + else: + euler_graph = Graphics() + + show( + C + triangle + triangle_points + labels + ab_graph + median_graph + + pb_graph + alt_graph + incircle_graph + euler_graph, + figsize=[5,5], xmin=-1, xmax=1, ymin=-1, ymax=1 + ) + + +@library_interact +def coin(n = slider(1,10000, 100, default=1000, label="Number of Tosses"), interval = range_slider(0, 1, default=(0.45, 0.55), label="Plotting range (y)")): + """ + This interact demo simulates repeated tosses of a coin, + based on work by Lauri Ruotsalainen, 2010. + + INPUT: + + - ``n`` -- number of tosses + - ``interval`` -- plot range (y) + + EXAMPLES:: + + sage: interacts.statistics.coin() + ... + """ + from random import random + c = [] + k = 0.0 + for i in range(1, n + 1): + k += random() + c.append((i, k/i)) + show(point(c[1:], gridlines=[None, [0.5]], pointsize=1), ymin=interval[0], ymax=interval[1]) + + +@library_interact +def bisection_method( + title = text_control('

Bisection method

'), + f = input_box("x^2-2", label='f(x)'), + interval = range_slider(-5,5,default=(0, 4), label="range"), + d = slider(1, 8, 1, 3, label="10^-d precision"), + maxn = slider(0,50,1,10, label="max iterations")): + """ + Interact explaining the bisection method, based on similar interact + explaining secant method and Wiliam Stein's example from wiki. + + INPUT: + + - ``f`` -- function + - ``interval`` -- range slider for the search interval + - ``d`` -- slider for the precision (10^-d) + - ``maxn`` -- max number of iterations + + EXAMPLES:: + + sage: interacts.calculus.secant_method() + ... + """ + def _bisection_method(f, a, b, maxn, eps): + intervals = [(a,b)] + round = 1 + two = float(2) + while True: + c = (b+a)/two + if abs(f(c)) < h or round >= maxn: + break + fa = f(a); fb = f(b); fc = f(c) + if abs(fc) < eps: + return c, intervals + if fa*fc < 0: + a, b = a, c + elif fc*fb < 0: + a, b = c, b + else: + raise ValueError, "f must have a sign change in the interval (%s,%s)"%(a,b) + intervals.append((a,b)) + round += 1 + return c, intervals + + x = SR.var('x') + f = symbolic_expression(f).function(x) + a, b = interval + h = 10**(-d) + try: + c, intervals = _bisection_method(f, float(a), float(b), maxn, h) + except ValueError: + print "f must have opposite sign at the endpoints of the interval" + show(plot(f, a, b, color='red'), xmin=a, xmax=b) + else: + html(r"$\text{Precision }h = 10^{-d}=10^{-%s}=%.5f$"%(d, float(h))) + html(r"${c = }%s$"%latex(c)) + html(r"${f(c) = }%s"%latex(f(c))) + html(r"$%s \text{ iterations}"%len(intervals)) + P = plot(f, a, b, color='red') + k = (P.ymax() - P.ymin())/ (1.5*len(intervals)) + L = sum(line([(c,k*i), (d,k*i)]) for i, (c,d) in enumerate(intervals) ) + L += sum(line([(c,k*i-k/4), (c,k*i+k/4)]) for i, (c,d) in enumerate(intervals) ) + L += sum(line([(d,k*i-k/4), (d,k*i+k/4)]) for i, (c,d) in enumerate(intervals) ) + show(P + L, xmin=a, xmax=b) + +@library_interact +def secant_method( + title = text_control('

Secant method

'), + f = input_box("x^2-2", label='f(x)'), + interval = range_slider(-5,5,default=(0, 4), label="range"), + d = slider(1, 16, 1, 3, label="10^-d precision"), + maxn = slider(0,15,1,10, label="max iterations")): + """ + Interact explaining the secant method, based on work by + Lauri Ruotsalainen, 2010. + Originally this is based on work by William Stein. + + INPUT: + + - ``f`` -- function + - ``interval`` -- range slider for the search interval + - ``d`` -- slider for the precision (10^-d) + - ``maxn`` -- max number of iterations + + EXAMPLES:: + + sage: interacts.calculus.secant_method() + ... + """ + def _secant_method(f, a, b, maxn, h): + intervals = [(a,b)] + round = 1 + while True: + c = b-(b-a)*f(b)/(f(b)-f(a)) + if abs(f(c)) < h or round >= maxn: + break + a, b = b, c + intervals.append((a,b)) + round += 1 + return c, intervals + + x = SR.var('x') + f = symbolic_expression(f).function(x) + a, b = interval + h = 10**(-d) + if float(f(a)*f(b)) > 0: + print "f must have opposite sign at the endpoints of the interval" + show(plot(f, a, b, color='red'), xmin=a, xmax=b) + else: + c, intervals = _secant_method(f, float(a), float(b), maxn, h) + html(r"$\text{Precision }h = 10^{-d}=10^{-%s}=%.5f$"%(d, float(h))) + html(r"${c = }%s$"%latex(c)) + html(r"${f(c) = }%s"%latex(f(c))) + html(r"$%s \text{ iterations}"%len(intervals)) + P = plot(f, a, b, color='red') + k = (P.ymax() - P.ymin())/ (1.5*len(intervals)) + L = sum(line([(c,k*i), (d,k*i)]) for i, (c,d) in enumerate(intervals) ) + L += sum(line([(c,k*i-k/4), (c,k*i+k/4)]) for i, (c,d) in enumerate(intervals) ) + L += sum(line([(d,k*i-k/4), (d,k*i+k/4)]) for i, (c,d) in enumerate(intervals) ) + 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) + show(P + L + S, xmin=a, xmax=b) + +@library_interact +def newton_method( + title = text_control('

Newton method

'), + f = input_box("x^2 - 2"), + c = slider(-10,10, default=6, label='Start (x)'), + d = slider(1, 16, 1, 3, label="10^-d precision"), + maxn = slider(0, 15, 1, 10, label="max iterations"), + interval = range_slider(-10,10, default = (0,6), label="Interval"), + list_steps = checkbox(default=False, label="List steps")): + """ + Interact explaining the newton method, based on work by + Lauri Ruotsalainen, 2010. + Originally this is based on work by William Stein. + + INPUT: + + - ``f`` -- function + - ``c`` -- starting position (x) + - ``d`` -- slider for the precision (10^-d) + - ``maxn`` -- max number of iterations + - ``interval`` -- range slider for the search interval + - ``list_steps`` -- checkbox, if true shows the steps numerically + + EXAMPLES:: + + sage: interacts.calculus.newton_method() + ... + """ + def _newton_method(f, c, maxn, h): + midpoints = [c] + round = 1 + while True: + c = c-f(c)/f.derivative(x)(x=c) + midpoints.append(c) + if f(c-h)*f(c+h) < 0 or round == maxn: + break + round += 1 + return c, midpoints + + x = SR.var('x') + f = symbolic_expression(f).function(x) + a, b = interval + h = 10**(-d) + c, midpoints = _newton_method(f, float(c), maxn, h/2.0) + html(r"$\text{Precision } 2h = %s$"%latex(float(h))) + html(r"${c = }%s$"%c) + html(r"${f(c) = }%s"%latex(f(c))) + html(r"$%s \text{ iterations}"%len(midpoints)) + if list_steps: + s = [["$n$","$x_n$","$f(x_n)$", "$f(x_n-h)\,f(x_n+h)$"]] + for i, c in enumerate(midpoints): + s.append([i+1, c, f(c), (c-h)*f(c+h)]) + html.table(s,header=True) + else: + P = plot(f, x, interval, color="blue") + L = sum(line([(c, 0), (c, f(c))], color="green") for c in midpoints[:-1]) + for i in range(len(midpoints) - 1): + L += line([(midpoints[i], f(midpoints[i])), (midpoints[i+1], 0)], color="red") + show(P + L, xmin=interval[0], xmax=interval[1], ymin=P.ymin(), ymax=P.ymax()) + +@library_interact +def trapezoid_integration( + title = text_control('

Trapeziod integration

'), + f = input_box(default = "x^2-5*x + 10", label='$f(x)=$'), + n = slider(1,100,1,5, label='# divisions'), + interval_input = selector(['from slider','from keyboard'], label='Integration interval', buttons=True), + interval_s = range_slider(-10,10,default=(0,8), label="slider: "), + interval_g = input_grid(1,2,default=[[0,8]], label="keyboard: "), + output_form = selector(['traditional','table','none'], label='Computations form', buttons=True) + ): + """ + Interact explaining the trapezoid method for definite integrals, based on work by + Lauri Ruotsalainen, 2010 (based on the application "Numerical integrals with various rules" + by Marshall Hampton and Nick Alexander) + + INPUT: + + - ``f`` -- function of variable x to integrate + - ``n`` -- number of divisions + - ``interval_input`` -- swithes the input for interval between slider and keyboard + - ``interval_s`` -- slider for interval to integrate + - ``interval_g`` -- input grid for interval to integrate + - ``output_form`` -- the computation is formatted in a traditional form, in a table or missing + + EXAMPLES:: + + sage: interacts.calculus.trapezoid_integration() + ... + """ + xs = [] + ys = [] + if interval_input == 'from slider': + interval = interval_s + else: + interval = interval_g[0] + h = float(interval[1]-interval[0])/n + x = SR.var('x') + f = symbolic_expression(f).function(x) + + trapezoids = Graphics() + + for i in range(n): + xi = interval[0] + i*h + yi = f(xi) + trapezoids += line([[xi, 0], [xi, yi], [xi + h, f(xi + h)],[xi + h, 0],[xi, 0]], rgbcolor = (1,0,0)) + xs.append(xi) + ys.append(yi) + xs.append(xi + h) + ys.append(f(xi + h)) + + html(r'Function $f(x)=%s$'%latex(f(x))) + show(plot(f, interval[0], interval[1]) + trapezoids, xmin = interval[0], xmax = interval[1]) + + numeric_value = integral_numerical(f, interval[0], interval[1])[0] + approx = h *(ys[0]/2 + sum([ys[i] for i in range(1,n)]) + ys[n]/2) + + html(r'$\displaystyle\int_{%.2f}^{%.2f} {f(x) \, \mathrm{d}x} = %.6f$'%( + interval[0], interval[1], N(numeric_value, digits=7)) + ) + + if output_form == 'traditional': + sum_formula_html = r"\frac {d}{2} \cdot \left[f(x_0) + %s + f(x_{%s})\right]" % ( + ' + '.join([ "2 f(x_{%s})"%i for i in range(1,n)]), + n + ) + sum_placement_html = r"\frac{%.2f}{2} \cdot \left[f(%.2f) + %s + f(%.2f)\right]" % ( + h, + N(xs[0], digits=5), + ' + '.join([ "2 f(%.2f)" %N(i, digits=5) for i in xs[1:-1]]), + N(xs[n], digits=5) + ) + sum_values_html = r"\frac{%.2f}{2} \cdot \left[%.2f + %s + %.2f\right]" % ( + h, + N(ys[0], digits=5), + ' + '.join([ "2\cdot %.2f" % N(i, digits=5) for i in ys[1:-1]]), + N(ys[n], digits=5) + ) + + html(r''' +
+ \begin{align*} + \int_{%.2f}^{%.2f} {f(x) \, \mathrm{d}x} + & \approx %s \\ + & = %s \\ + & = %s \\ + & = %s + \end{align*} +
+ ''' % ( + interval[0], interval[1], + sum_formula_html, sum_placement_html, sum_values_html, + N(approx, digits=7) + )) + elif output_form == 'table': + s = [['$i$','$x_i$','$f(x_i)$','$m$','$m\cdot f(x_i)$']] + for i in range(0,n+1): + if i==0 or i==n: + j = 1 + else: + j = 2 + s.append([i, xs[i], ys[i],j,N(j*ys[i])]) + html.table(s,header=True) + +@library_interact +def simpson_integration( + title = text_control('

Simpson integration

'), + f = input_box(default = 'x*sin(x)+x+1', label='$f(x)=$'), + n = slider(2,100,2,6, label='# divisions'), + interval_input = selector(['from slider','from keyboard'], label='Integration interval', buttons=True), + interval_s = range_slider(-10,10,default=(0,10), label="slider: "), + interval_g = input_grid(1,2,default=[[0,10]], label="keyboard: "), + output_form = selector(['traditional','table','none'], label='Computations form', buttons=True)): + """ + Interact explaining the simpson method for definite integrals, based on work by + Lauri Ruotsalainen, 2010 (based on the application "Numerical integrals with various rules" + by Marshall Hampton and Nick Alexander) + + INPUT: + + - ``f`` -- function of variable x to integrate + - ``n`` -- number of divisions (mult. of 2) + - ``interval_input`` -- swithes the input for interval between slider and keyboard + - ``interval_s`` -- slider for interval to integrate + - ``interval_g`` -- input grid for interval to integrate + - ``output_form`` -- the computation is formatted in a traditional form, in a table or missing + + EXAMPLES:: + + sage: interacts.calculus.simpson_integration() + ... + """ + x = SR.var('x') + f = symbolic_expression(f).function(x) + if interval_input == 'from slider': + interval = interval_s + else: + interval = interval_g[0] + def parabola(a, b, c): + from sage.all import solve + A, B, C = SR.var("A, B, C") + 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] + f = K[A]*x**2+K[B]*x+K[C] + return f + xs = []; ys = [] + dx = float(interval[1]-interval[0])/n + + for i in range(n+1): + xs.append(interval[0] + i*dx) + ys.append(f(x=xs[-1])) + + parabolas = Graphics() + lines = Graphics() + + for i in range(0, n-1, 2): + p = parabola((xs[i],ys[i]),(xs[i+1],ys[i+1]),(xs[i+2],ys[i+2])) + parabolas += plot(p(x=x), (x, xs[i], xs[i+2]), color="red") + lines += line([(xs[i],ys[i]), (xs[i],0), (xs[i+2],0)],color="red") + lines += line([(xs[i+1],ys[i+1]), (xs[i+1],0)], linestyle="-.", color="red") + + lines += line([(xs[-1],ys[-1]), (xs[-1],0)], color="red") + + html(r'Function $f(x)=%s$'%latex(f(x))) + + show(plot(f(x),x,interval[0],interval[1]) + parabolas + lines, xmin = interval[0], xmax = interval[1]) + + numeric_value = integral_numerical(f,interval[0],interval[1])[0] + 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]) + + html(r'$\displaystyle\int_{%.2f}^{%.2f} {f(x) \, \mathrm{d}x} = %.6f$'% + (interval[0],interval[1], + N(numeric_value,digits=7))) + + if output_form == 'traditional': + sum_formula_html = r"\frac{d}{3} \cdot \left[ f(x_0) + %s + f(x_{%s})\right]" % ( + ' + '.join([ r"%s \cdot f(x_{%s})" %(i%2*(-2)+4, i+1) for i in range(0,n-1)]), + n + ) + + sum_placement_html = r"\frac{%.2f}{3} \cdot \left[ f(%.2f) + %s + f(%.2f)\right]" % ( + dx, + N(xs[0],digits=5), + ' + '.join([ r"%s \cdot f(%.2f)" %(i%2*(-2)+4, N(xk, digits=5)) for i, xk in enumerate(xs[1:-1])]), + N(xs[n],digits=5) + ) + + sum_values_html = r"\frac{%.2f}{3} \cdot \left[ %s %s %s\right]" %( + dx, + "%.2f + "%N(ys[0],digits=5), + ' + '.join([ r"%s \cdot %.2f" %(i%2*(-2)+4, N(yk, digits=5)) for i, yk in enumerate(ys[1:-1])]), + " + %.2f"%N(ys[n],digits=5) + ) + + html(r''' +
+ \begin{align*} + \int_{%.2f}^{%.2f} {f(x) \, \mathrm{d}x} + & \approx %s \\ + & = %s \\ + & = %s \\ + & = %.6f + \end{align*} +
+ ''' % ( + interval[0], interval[1], + sum_formula_html, sum_placement_html, sum_values_html, + N(approx,digits=7) + )) + elif output_form == 'table': + s = [['$i$','$x_i$','$f(x_i)$','$m$','$m\cdot f(x_i)$']] + for i in range(0,n+1): + if i==0 or i==n: + j = 1 + else: + j = (i+1)%2*(-2)+4 + s.append([i, xs[i], ys[i],j,N(j*ys[i])]) + s.append(['','','','$\sum$','$%s$'%latex(3/dx*approx)]) + html.table(s,header=True) + html(r'$\int_{%.2f}^{%.2f} {f(x) \, \mathrm{d}x}\approx\frac {%.2f}{3}\cdot %s=%s$'% + (interval[0], interval[1],dx,latex(3/dx*approx),latex(approx))) + +@library_interact +def riemann_sum( + title = text_control('

Riemann integral

'), + f = input_box("x^2+1", label = "$f(x)=$", width=40), + n = slider(1,30,1,5, label='# divisions'), + hr1 = text_control('
'), + interval_input = selector(['from slider','from keyboard'], label='Integration interval', buttons=True), + interval_s = range_slider(-5,10,default=(0,2), label="slider: "), + interval_g = input_grid(1,2,default=[[0,2]], label="keyboard: "), + hr2 = text_control('
'), + list_table = checkbox(default=False, label="List table"), + auto_update = False): + """ + Interact explaining the definition of Riemann integral + + INPUT: + + - ``f`` -- function of variable x to integrate + - ``n`` -- number of divisions + - ``interval_input`` -- swithes the input for interval between slider and keyboard + - ``interval_s`` -- slider for interval to integrate + - ``interval_g`` -- input grid for interval to integrate + - ``list_table`` -- print table with values of the function + + EXAMPLES:: + + sage: interacts.calculus.riemann_sum() + ... + + AUTHORS: + + - Robert Marik (08-2010) + """ + x = SR.var('x') + from random import random + if interval_input == 'from slider': + a = interval_s[0] + b = interval_s[1] + else: + a = interval_g[0][0] + b = interval_g[0][1] + func = symbolic_expression(f).function(x) + division = [a]+[a+random()*(b-a) for i in range(n-1)]+[b] + division = [i for i in division] + division.sort() + xs = [division[i]+random()*(division[i+1]-division[i]) for i in range(n)] + ys = [func(x_val) for x_val in xs] + rects = Graphics() + for i in range(n): + body=[[division[i],0],[division[i],ys[i]],[division[i+1],ys[i]],[division[i+1],0]] + if ys[i].n()>0: + color_rect='green' + else: + color_rect='red' + rects = rects +polygon2d(body, rgbcolor = color_rect,alpha=0.1)\ + + point((xs[i],ys[i]), rgbcolor = (1,0,0))\ + + line(body,rgbcolor='black',zorder=-1) + html('Adjust your data and click Update button. Click repeatedly for another random values.') + + show(plot(func(x),(x,a,b),zorder=5) + rects) + delka_intervalu=[division[i+1]-division[i] for i in range(n)] + if list_table: + html.table([["$i$","$[x_{i-1},x_i]$","$\eta_i$","$f(\eta_i)$","$x_{i}-x_{i-1}$"]]\ + +[[i+1,[division[i],division[i+1]],xs[i],ys[i],delka_intervalu[i]] for i in range(n)],\ + header=True) + + html('Riemann sum: $\displaystyle\sum_{i=1}^{%s} f(\eta_i)(x_i-x_{i-1})=%s$ '% + (latex(n),latex(sum([ys[i]*delka_intervalu[i] for i in range(n)])))) + html('Exact value of the integral $\displaystyle\int_{%s}^{%s}%s\,\mathrm{d}x=%s$'% + (latex(a),latex(b),latex(func(x)),latex(integral_numerical(func(x),a,b)[0]))) + + +x = SR.var('x') +@library_interact +def function_tool(f=sin(x), g=cos(x), xrange=range_slider(-3,3,default=(0,1),label='x-range'), + yrange='auto', + a=1, + action=selector(['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)'], + width=15, nrows=5, label="h = "), + do_plot = ("Draw Plots", True)): + """ + `Function Plotting Tool `_ + (by William Stein (?)) + + INPUT: + + - ``f`` -- function f(x) + - ``g`` -- function g(x) + - ``xrange`` -- range for plotting (x) + - ``yrange`` -- range for plotting ('auto' is default, otherwise a tuple) + - ``a`` -- factor ``a`` + - ``action`` -- select given operation on or combination of functions + - ``do_plot`` -- if true, a plot is drawn + + EXAMPLE:: + + sage: interacts.calculus.function_tool() + ... + """ + x = SR.var('x') + try: + f = SR(f); g = SR(g); a = SR(a) + except TypeError, msg: + print msg[-200:] + print "Unable to make sense of f,g, or a as symbolic expressions in single variable x." + return + if not (isinstance(xrange, tuple) and len(xrange) == 2): + xrange = (0,1) + h = 0; lbl = '' + if action == 'f': + h = f + lbl = 'f' + elif action == 'df/dx': + h = f.derivative(x) + lbl = r'\frac{\mathrm{d}f}{\mathrm{d}x}' + elif action == 'int f': + h = f.integrate(x) + lbl = r'\int f \,\mathrm{d}x' + elif action == 'num f': + h = f.numerator() + lbl = r'\text{numer(f)}' + elif action == 'den f': + h = f.denominator() + lbl = r'\text{denom(f)}' + elif action == '1/f': + h = 1/f + lbl = r'\frac{1}{f}' + elif action == 'finv': + h = solve(f == var('y'), x)[0].rhs() + lbl = 'f^{-1}(y)' + elif action == 'f+a': + h = f+a + lbl = 'f + a' + elif action == 'f-a': + h = f-a + lbl = 'f - a' + elif action == 'f*a': + h = f*a + lbl = r'f \times a' + elif action == 'f/a': + h = f/a + lbl = r'\frac{f}{a}' + elif action == 'f^a': + h = f**a + lbl = 'f^a' + elif action == 'f^a': + h = f**a + lbl = 'f^a' + elif action == 'f(x+a)': + h = f(x+a) + lbl = 'f(x+a)' + elif action == 'f(x*a)': + h = f(x*a) + lbl = 'f(xa)' + elif action == 'f+g': + h = f+g + lbl = 'f + g' + elif action == 'f-g': + h = f-g + lbl = 'f - g' + elif action == 'f*g': + h = f*g + lbl = r'f \times g' + elif action == 'f/g': + h = f/g + lbl = r'\frac{f}{g}' + elif action == 'f(g)': + h = f(g) + lbl = 'f(g)' + html('
$f = %s$
'%latex(f)) + html('
$g = %s$
'%latex(g)) + html('
$h = %s = %s$
'%(lbl, latex(h))) + if do_plot: + P = plot(f, xrange, color='red', thickness=2) + \ + plot(g, xrange, color='green', thickness=2) + \ + plot(h, xrange, color='blue', thickness=2) + if yrange == 'auto': + show(P, xmin=xrange[0], xmax=xrange[1]) + else: + yrange = sage_eval(yrange) + show(P, xmin=xrange[0], xmax=xrange[1], ymin=yrange[0], ymax=yrange[1]) + +@library_interact +def julia(expo = slider(-10,10,0.1,2), + c_real = slider(-2,2,0.01,0.5, label='real part const.'), + c_imag = slider(-2,2,0.01,0.5, label='imag part const.'), + iterations=slider(1,100,1,20, label='# iterations'), + zoom_x = range_slider(-2,2,0.01,(-1.5,1.5), label='Zoom X'), + zoom_y = range_slider(-2,2,0.01,(-1.5,1.5), label='Zoom Y'), + plot_points = slider(20,400,20, default=150, label='plot points'), + dpi = slider(20, 200, 10, default=80, label='dpi')): + """ + Julia Fractal, based on + `Julia by Harald Schilly `_. + + INPUT: + + - ``exponent`` -- exponent ``e`` in $z^e+c$ + - ``c_real`` -- real part of the constant ``c`` + - ``c_imag`` -- imaginary part of the constant ``c`` + - ``iterations`` -- number of iterations + - ``zoom_x`` -- range slider for zoom in x direction + - ``zoom_y`` -- range slider for zoom in y direction + - ``plot_points`` -- number of points to plot + - ``dpi`` -- dots-per-inch parameter for the plot + + EXAMPLE:: + + sage: interacts.fractals.julia() + ... + """ + z = SR.var('z') + I = CDF.gen() + f = symbolic_expression(z**expo + c_real + c_imag*I).function(z) + ff_j = fast_callable(f, vars=[z], domain=CDF) + + from sage.interacts.library_cython import julia + + html('

Julia Fractal

') + html(r'Recursive Formula: $z \leftarrow z^{%.2f} + (%.2f+%.2f*\mathbb{I})$' % (expo, c_real, c_imag)) + 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) + +@library_interact +def mandelbrot(expo = slider(-10,10,0.1,2), + iterations=slider(1,100,1,20, label='# iterations'), + zoom_x = range_slider(-2,2,0.01,(-2,1), label='Zoom X'), + zoom_y = range_slider(-2,2,0.01,(-1.5,1.5), label='Zoom Y'), + plot_points = slider(20,400,20, default=150, label='plot points'), + dpi = slider(20, 200, 10, default=80, label='dpi')): + """ + Mandelbrot Fractal, based on + `Mandelbrot by Harald Schilly `_. + + INPUT: + + - ``exponent`` -- exponent ``e`` in `z^e+c` + - ``iterations`` -- number of iterations + - ``zoom_x`` -- range slider for zoom in x direction + - ``zoom_y`` -- range slider for zoom in y direction + - ``plot_points`` -- number of points to plot + - ``dpi`` -- dots-per-inch parameter for the plot + + EXAMPLE:: + + sage: interacts.fractals.mandelbrot() + ... + """ + x, z, c = SR.var('x, z, c') + f = symbolic_expression(z**expo + c).function(z, c) + ff_m = fast_callable(f, vars=[z,c], domain=CDF) + + from sage.interacts.library_cython import mandel + + html('

Mandelbrot Fractal

') + html(r'Recursive Formula: $z \leftarrow z^{%.2f} + c$ for $c \in \mathbb{C}$' % expo) + 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) + + +@library_interact +def cellular_automaton( + N=slider(1,500,1,label='Number of iterations',default=100), + rule_number=slider(0, 255, 1, default=110, label='Rule number'), + size = slider(1, 11, step_size=1, default=6, label='size')): + """ + Yields a matrix showing the evolution of a + `Wolfram's cellular automaton `_. + + `Based on work by Pablo Angulo `_. + + INPUT: + + - ``N`` -- iterations + - ``rule_number`` -- rule number (0 to 255) + - ``size`` -- size of the shown picture + + EXAMPLE:: + + sage: interacts.fractals.cellular_automaton() + ... + """ + from sage.all import Integer + if not 0 <= rule_number <= 255: + raise Exception('Invalid rule number') + binary_digits = Integer(rule_number).digits(base=2) + rule = binary_digits + [0]*(8-len(binary_digits)) + + html('

Cellular Automaton

'+ + '
"A cellular automaton is a collection of "colored" cells \ + on a grid of specified shape that evolves through a number of \ + discrete time steps according to a set of rules based on the \ + states of neighboring cells." — \ + Mathworld,\ + Cellular Automaton
\ +
Rule %s expands to %s
' % (rule_number, ''.join(map(str,rule))) + ) + + from sage.interacts.library_cython import cellular + M = cellular(rule, N) + plot_M = matrix_plot(M) + plot_M.show(figsize=[size,size]) + + +@library_interact +def polar_prime_spiral( + interval = range_slider(1, 4000, 10, default=(1, 1000), label="range"), + show_factors = True, + highlight_primes = True, + show_curves = True, + n = slider(1,200, 1, default=89, label="number n"), + dpi = slider(10,300, 10, default=100, label="dpi")): + """ + Polar Prime Spiral interact, based on work by David Runde. + + For more information about the factors in the spiral, + `visit John Williams website `_. + + INPUT: + + - ``interval`` -- range slider to specify start and end + - ``show_factors`` -- if true, show factors + - ``highlight_primes`` -- if true, prime numbers are highlighted + - ``show_curves`` -- if true, curves are plotted + - ``n`` -- number n + - ``dpi`` -- dots per inch resolution for plotting + + EXAMPLE:: + + sage: sage.interacts.algebra.polar_prime_spiral() + ... + + """ + + html('

Polar Prime Spiral

\ +
\ + For more information about the factors in the spiral, visit \ + \ + Number Spirals by John Williamson.
' + ) + + start, end = interval + from sage.ext.fast_eval import fast_float + from math import floor, ceil + from sage.plot.colors import hue + + if start < 1 or end <= start: + print "invalid start or end value" + return + if n > end: + print "WARNING: n is greater than end value" + return + if n < start: + print "n < start value" + return + nn = SR.var('nn') + f1 = fast_float(sqrt(nn)*cos(2*pi*sqrt(nn)), 'nn') + f2 = fast_float(sqrt(nn)*sin(2*pi*sqrt(nn)), 'nn') + f = lambda x: (f1(x), f2(x)) + + list =[] + list2=[] + if show_factors == False: + for i in srange(start, end, include_endpoint = True): + if Integer(i).is_pseudoprime(): list.append(f(i-start+1)) #Primes list + else: list2.append(f(i-start+1)) #Composites list + P = points(list) + R = points(list2, alpha = .1) #Faded Composites + else: + for i in srange(start, end, include_endpoint = True): + 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 + if Integer(i).is_pseudoprime() and highlight_primes: list2.append(f(i-start+1)) + P = plot(list) + p_size = 5 #the orange dot size of the prime markers + if not highlight_primes: list2 = [(f(n-start+1))] + R = points(list2, hue = .1, pointsize = p_size) + + if n > 0: + html('n = %s' % factor(n)) + + p = 1 + #The X which marks the given n + W1 = disk((f(n-start+1)), p, (pi/6, 2*pi/6)) + W2 = disk((f(n-start+1)), p, (4*pi/6, 5*pi/6)) + W3 = disk((f(n-start+1)), p, (7*pi/6, 8*pi/6)) + W4 = disk((f(n-start+1)), p, (10*pi/6, 11*pi/6)) + Q = plot(W1 + W2 + W3 + W4, alpha = .1) + + n = n - start +1 #offsets the n for different start values to ensure accurate plotting + if show_curves: + begin_curve = 0 + t = SR.var('t') + a=1.0 + b=0.0 + if n > (floor(sqrt(n)))**2 and n <= (floor(sqrt(n)))**2 + floor(sqrt(n)): + c = -((floor(sqrt(n)))**2 - n) + c2= -((floor(sqrt(n)))**2 + floor(sqrt(n)) - n) + else: + c = -((ceil(sqrt(n)))**2 - n) + c2= -((floor(sqrt(n)))**2 + floor(sqrt(n)) - n) + html('Pink Curve: $n^2 + %s$' % c) + html('Green Curve: $n^2 + n + %s$' % c2) + m = SR.var('m') + g = symbolic_expression(a*m**2+b*m+c).function(m) + r = symbolic_expression(sqrt(g(m))).function(m) + theta = symbolic_expression(r(m)- m*sqrt(a)).function(m) + S1 = parametric_plot(((r(t))*cos(2*pi*(theta(t))),(r(t))*sin(2*pi*(theta(t)))), + (begin_curve, ceil(sqrt(end-start))), color=hue(0.8), thickness = .3) #Pink Line + + b = 1 + c = c2; + g = symbolic_expression(a*m**2+b*m+c).function(m) + r = symbolic_expression(sqrt(g(m))).function(m) + theta = symbolic_expression(r(m)- m*sqrt(a)).function(m) + S2 = parametric_plot(((r(t))*cos(2*pi*(theta(t))),(r(t))*sin(2*pi*(theta(t)))), + (begin_curve, ceil(sqrt(end-start))), color=hue(0.6), thickness = .3) #Green Line + + show(R+P+S1+S2+Q, aspect_ratio = 1, axes = False, dpi = dpi) + else: show(R+P+Q, aspect_ratio = 1, axes = False, dpi = dpi) + else: show(R+P, aspect_ratio = 1, axes = False, dpi = dpi) + + + diff -r c58f82863c75 -r f711e2a0e1d5 sage/interacts/library_cython.pyx --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sage/interacts/library_cython.pyx Wed Jan 12 17:01:22 2011 -0600 @@ -0,0 +1,99 @@ +r""" +Library of cythonized methods +""" + +#***************************************************************************** +# Copyright (C) 2010 Harald Schilly +# +# Distributed under the terms of the GNU General Public License (GPL) +# http://www.gnu.org/licenses/ +#***************************************************************************** + +from sage.misc.misc import prod + +include '../ext/interrupt.pxi' +include '../ext/cdefs.pxi' +include "../ext/stdsage.pxi" + +cpdef julia(ff_j, z, int iterations): + """ + Helper function for the Julia Fractal interact example. + + INPUT: + + - `ff_j` -- fast callable for the inner iteration + - `z` -- complex number + - `iterations` -- number of loops + + TESTS:: + + sage: from sage.interacts.library_cython import julia + sage: z = var('z') + sage: c_real, c_imag = 1, 1 + sage: f = symbolic_expression(z**2 + c_real + c_imag * CDF.gen()).function(z) + sage: ff_m = fast_callable(f, vars=[z], domain=CDF) + sage: julia(ff_m, CDF(1,1), 3) + 1.0 + 3.0*I + """ + for i in range(iterations): + z = ff_j(z) + if z.abs() > 2: break + return z + +cpdef mandel(ff_m, z, int iterations): + """ + Helper function for the Mandelbrot Fractal interact example. + + INPUT: + + - `ff_m` -- fast callable for the inner iteration + - `z` -- complex number + - `iterations` -- number of loops + + TESTS:: + + sage: from sage.interacts.library_cython import mandel + sage: z, c = var('z, c') + sage: f = symbolic_expression(z**2 + c).function(z,c) + sage: ff_m = fast_callable(f, vars=[z,c], domain=CDF) + sage: mandel(ff_m, CDF(1,1), 3) + 1.0 + 3.0*I + + """ + c = z + for i in range(iterations): + z = ff_m(z, c) + if z.abs() > 2: break + return z + + +cpdef cellular(rule, int N): + ''' + Cythonized helper function for the callular_automata fractal. + Yields a matrix showing the evolution of a Wolfram's cellular automaton. + Based on work by Pablo Angulo. + http://wiki.sagemath.org/interact/misc#CellularAutomata + + INPUT: + + - `rule` -- determines how a cell's value is updated, depending on its neighbors + - `N` -- number of iterations + + TESTS:: + + sage: from sage.interacts.library_cython import cellular + sage: rule = [1, 0, 1, 0, 0, 1, 1, 0] + sage: N = 3 + sage: print cellular(rule, 3) + + ''' + from numpy import zeros + cdef int j, k, l + M=zeros((N, 2*N+1), dtype=int) + M[0,N]=1 + + for j in range(1, N): + for k in range(N-j, N+j+1): + l = 4 * M[j-1, k-1] + 2 * M[j-1, k] + M[j-1, k+1] + M[j,k] = rule[l] + return M diff -r c58f82863c75 -r f711e2a0e1d5 sage/interacts/statistics.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sage/interacts/statistics.py Wed Jan 12 17:01:22 2011 -0600 @@ -0,0 +1,14 @@ +""" +Interacts for Statistics + +""" + + +#***************************************************************************** +# Copyright (C) 2010 Harald Schilly +# +# Distributed under the terms of the GNU General Public License (GPL) +# http://www.gnu.org/licenses/ +#***************************************************************************** + +from library import coin