# HG changeset patch # User Harald Schilly # Date 1280582452 -7200 # Node ID dd9d78f1125180d10b04844cabf58d7d4aa3cefa # Parent cb1ad1ee5bd452850fde04d47f9618dec4c3e997 #9623 interacts for high school level education by Lauri Ruotsalainen and selected interact examples from wiki.sagemath.org/interacts diff -r cb1ad1ee5bd4 -r dd9d78f11251 doc/en/reference/index.rst --- a/doc/en/reference/index.rst Fri Jul 16 01:54:01 2010 -0700 +++ b/doc/en/reference/index.rst Sat Jul 31 15:20:52 2010 +0200 @@ -45,6 +45,7 @@ calculus plotting plot3d + interacts games graphs constants diff -r cb1ad1ee5bd4 -r dd9d78f11251 module_list.py --- a/module_list.py Fri Jul 16 01:54:01 2010 -0700 +++ b/module_list.py Sat Jul 31 15:20:52 2010 +0200 @@ -451,6 +451,16 @@ ################################ ## + ## sage.interacts + ## + ################################ + + Extension('sage.interacts.library_cython', + sources = ['sage/interacts/library_cython.pyx'], + libraries = []), + + ################################ + ## ## sage.libs ## ################################ diff -r cb1ad1ee5bd4 -r dd9d78f11251 sage/interacts/__init__.py --- a/sage/interacts/__init__.py Fri Jul 16 01:54:01 2010 -0700 +++ b/sage/interacts/__init__.py Sat Jul 31 15:20:52 2010 +0200 @@ -2,4 +2,7 @@ Interacts included with sage """ import calculus -import library +import geometry +import statistics +import fractals +import algebra diff -r cb1ad1ee5bd4 -r dd9d78f11251 sage/interacts/algebra.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sage/interacts/algebra.py Sat Jul 31 15:20:52 2010 +0200 @@ -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 cb1ad1ee5bd4 -r dd9d78f11251 sage/interacts/calculus.py --- a/sage/interacts/calculus.py Fri Jul 16 01:54:01 2010 -0700 +++ b/sage/interacts/calculus.py Sat Jul 31 15:20:52 2010 +0200 @@ -1,1 +1,19 @@ +""" +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 practice_differentiating_polynomials, trigonometric_properties_triangle +from library import secant_method, newton_method, trapezoid_integration, simpson_integration +from library import function_tool diff -r cb1ad1ee5bd4 -r dd9d78f11251 sage/interacts/fractals.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sage/interacts/fractals.py Sat Jul 31 15:20:52 2010 +0200 @@ -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 cb1ad1ee5bd4 -r dd9d78f11251 sage/interacts/geometry.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sage/interacts/geometry.py Sat Jul 31 15:20:52 2010 +0200 @@ -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 cb1ad1ee5bd4 -r dd9d78f11251 sage/interacts/library.py --- a/sage/interacts/library.py Fri Jul 16 01:54:01 2010 -0700 +++ b/sage/interacts/library.py Sat Jul 31 15:20:52 2010 +0200 @@ -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 +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 +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.misc import sage_wraps from sage.misc.html import html @@ -37,8 +59,8 @@ INPUT: - - `n` -- integer slider - - `m` -- integer slider + - ``n`` -- integer slider + - ``m`` -- integer slider EXAMPLES:: @@ -47,16 +69,15 @@ """ print n+m - - +x=SR.var('x') @library_interact def taylor_polynomial(f=input_box(sin(x)*exp(-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 +92,1262 @@ 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( + 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)})\,dx=\int_{%.2f}^{%.2f}(%s)\,dx=%.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)})\,dx=\int_{%.2f}^{%.2f}(%s)\,dx=%.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)})\,dx=\int_{%.2f}^{%.2f}(%s)\,dx=%.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( + 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( + 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)) + +#R. = ZZ[] +new_ex_state = True +prac_function = None + +@library_interact +def practice_differentiating_polynomials( + answer = input_box(label="Answer"), + new_exercise = checkbox(default=False, label="New exercise"), + show_solution = checkbox(default=False, label="Show solution")): + """ + This is an interact for practicing differentiating random polynomials + based on work by Lauri Ruotsalainen, 2010. + + INPUT: + + - ``answer`` -- enter your answer here + - ``new_exercise`` -- generate a new exercise + - ``show_solution`` -- show the solution + + EXAMPLES:: + + sage: interacts.calculus.practice_differentiating_polynomials() + ... + """ + import sage + from sage.interacts.library import prac_function, new_ex_state + from sage.all import ZZ + R = ZZ['x']; (x,) = R._first_ngens(1) + if prac_function is None: + prac_function = R.random_element(3, -10,10) + sage.interacts.library.prac_function = prac_function + + if answer == derivative(prac_function(x)) or new_exercise == new_ex_state: + new_ex_state = not new_exercise + sage.interacts.library.new_ex_state = new_ex_state + prac_function = R.random_element(3, -10,10) + sage.interacts.library.prac_function = prac_function + + if answer == derivative(prac_function(x)): + html(r"$\text{Very good! New exercise:}$") + prac_function = R.random_element(3, -10,10) + sage.interacts.library.prac_function = prac_function + + elif answer and show_solution is False and new_exercise != new_ex_state: + html(r"$\text{You've made an error. Try again!}$") + + html(r"$\text{Calculate the derivative: }\;\;\;\;%s$
"%latex(prac_function(x))) + + if show_solution: + html(r"$\text{Solution: }\;\;\;\;%s$
"%latex(derivative(prac_function(x)))) + + +@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"$< A = {%s}^{\circ},$ $< B = {%s}^{\circ},$ $< 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( + 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 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 + - ``slider`` -- 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) + 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"$\text{c = }%s$"%c) + html(r"$\text{f(c) = }%s"%f(c)) + html(r"$\text{Iterations = }%s"%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( + f = input_box("x^2 - 2"), + c = slider(-10,10, default=6, label='Start (x)'), + hh = slider(-16, -1, 1, -3, label="Precision 2h"), + 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) + - ``interval`` -- range slider for the search interval + - ``slider`` -- slider for the precision (10^-d) + - ``maxn`` -- max number of iterations + - ``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**hh + c, midpoints = _newton_method(f, float(c), maxn, h/2.0) + html(r"$\text{Precision 2h = }%.5f$"%float(h)) + html(r"$\text{c = }%s$"%c) + html(r"$\text{f(c) = }%s"%f(c)) + html(r"$\text{Iterations = }%s"%len(midpoints)) + if list_steps: + s = "

" + s += "" + for i, c in enumerate(midpoints): + s += ""%(i, c, f(c), f(c-h)*f(c+h)) + s += "
$n$$x_n$$f(x_n)$$f(x_n-h)f(x_n+h)$
$%d$$%.4f$$%.4f$$%.4f$
" + html(s) + 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( + f = input_box(default = "x^2-5*x + 10", label='f(x)'), + n = slider(1,100,1,5, label='# divisions'), + interval = range_slider(-10,10,default=(0,8), label="Integral interval") + ): + """ + 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`` -- interval to integrate + + EXAMPLES:: + + sage: interacts.calculus.trapezoid_integration() + ... + """ + xs = [] + ys = [] + h = (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)) + + 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) + + sum_formula_html = r"d \cdot \left[\frac{f(x_0)}{2} + %s + \frac{f(x_{%s})}{2}\right]" % ( + ' + '.join([ "f(x_{%s})"%i for i in range(1,n)]), + n + ) + sum_placement_html = r"%.2f \cdot \left[\frac{f(%.2f)}{2} + %s + \frac{f(%.2f)}{2}\right]" % ( + h, + N(xs[0], digits=5), + ' + '.join([ "f(%.2f)" %N(i, digits=5) for i in xs[1:-1]]), + N(xs[n], digits=5) + ) + sum_values_html = r"%.2f \cdot \left[\frac{%.2f}{2} + %s + \frac{%.2f}{2}\right]" % ( + h, + N(ys[0], digits=5), + ' + '.join([ "%.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) \, dx} & = %.6f \\\ + \\ + \int_{%.2f}^{%.2f} {f(x) \, dx} + & \approx %s \\ + & = %s \\ + & = %s \\ + & = %s + \end{align*} +
+ ''' % ( + interval[0], interval[1], + N(numeric_value, digits=7), + interval[0], interval[1], + sum_formula_html, sum_placement_html, sum_values_html, + N(approx, digits=7) + )) + + +@library_interact +def simpson_integration( + f = input_box(default = 'x*sin(x)+x+1', label='f(x)'), + n=slider(2,100,2,6, label='# divisions'), + interval=range_slider(-10,10,default=(0,10), label="Integration Interval")): + """ + 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`` -- interval to integrate + + EXAMPLES:: + + sage: interacts.calculus.simpson_integration() + ... + """ + x = SR.var('x') + f = symbolic_expression(f).function(x) + + 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 = (interval[1]-interval[0])/n + + for i in range(n+1): + xs.append(interval[0] + i*dx) + ys.append(f(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, xmin=xs[i], xmax=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") + + 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]) + + 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) \, dx} & = %.6f \\ + \\ + \int_{%.2f}^{%.2f} {f(x) \, dx} + & \approx %s \\ + & = %s \\ + & = %s \\ + & = %.6f + \end{align*} +
+ ''' % ( + interval[0],interval[1], + N(numeric_value,digits=7), + interval[0], interval[1], + sum_formula_html, sum_placement_html, sum_values_html, + N(approx,digits=7) + )) + +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{df}{dx}' + elif action == 'int f': + h = f.integrate(x) + lbl = r'\int f dx' + 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 cb1ad1ee5bd4 -r dd9d78f11251 sage/interacts/library_cython.pyx --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sage/interacts/library_cython.pyx Sat Jul 31 15:20:52 2010 +0200 @@ -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 cb1ad1ee5bd4 -r dd9d78f11251 sage/interacts/statistics.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sage/interacts/statistics.py Sat Jul 31 15:20:52 2010 +0200 @@ -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