Ticket #9623: 9623-interacts-high-school.patch

File 9623-interacts-high-school.patch, 38.3 KB (added by schilly, 11 years ago)
  • sage/interacts/__init__.py

    # HG changeset patch
    # User Harald Schilly <harald.schilly@gmail.com>
    # Date 1280358068 -7200
    # Node ID 12c5ece399703e70d63205c71a66ff1d9f735cfb
    # Parent  cb1ad1ee5bd452850fde04d47f9618dec4c3e997
    #9623 interacts for high school level education by Lauri Ruotsalainen adopted for the sage library
    
    diff --git a/sage/interacts/__init__.py b/sage/interacts/__init__.py
    a b  
    22Interacts included with sage
    33"""
    44import calculus
    5 import library
     5import geometry
     6import statistics
  • sage/interacts/calculus.py

    diff --git a/sage/interacts/calculus.py b/sage/interacts/calculus.py
    a b  
    1 from library import taylor_polynomial
     1"""
     2Interacts for Calculus
     3
     4"""
     5
     6
     7#*****************************************************************************
     8#     Copyright (C) 2010 Harald Schilly <harald.schilly@gmail.com>
     9#
     10#  Distributed under the terms of the GNU General Public License (GPL)
     11#                  http://www.gnu.org/licenses/
     12#*****************************************************************************
     13
     14from library import taylor_polynomial, definite_integral
     15from library import function_derivative, difference_quotient, quadratic_equation
     16from library import practice_differentiating_polynomials, trigonometric_properties_triangle
     17from library import secant_method, newton_method, trapezoid_integration, simpson_integration
  • new file sage/interacts/geometry.py

    diff --git a/sage/interacts/geometry.py b/sage/interacts/geometry.py
    new file mode 100644
    - +  
     1"""
     2Interacts for Geometry
     3
     4"""
     5
     6
     7#*****************************************************************************
     8#     Copyright (C) 2010 Harald Schilly <harald.schilly@gmail.com>
     9#
     10#  Distributed under the terms of the GNU General Public License (GPL)
     11#                  http://www.gnu.org/licenses/
     12#*****************************************************************************
     13
     14from library import unit_circle, cube_hemisphere
     15from library import trigonometric_properties_triangle, special_points
  • sage/interacts/library.py

    diff --git a/sage/interacts/library.py b/sage/interacts/library.py
    a b  
    22A library of interacts
    33"""
    44
    5 from sagenb.notebook.interact import interact, slider, range_slider, input_box
    6 from sage.all import sin, plot, point, html, show, latex, SR,exp
    7 x=SR.var('x')
     5
     6#*****************************************************************************
     7#        Copyright (C) 2009 William Stein <wstein@gmail.com>
     8#     Copyright (C) 2010 Harald Schilly <harald.schilly@gmail.com>
     9#
     10#  Distributed under the terms of the GNU General Public License (GPL)
     11#                  http://www.gnu.org/licenses/
     12#*****************************************************************************
     13
     14from sagenb.notebook.interact import interact, slider, range_slider, input_box, selector, checkbox
     15from sage.all import sin, cos, asin, acos, tan, sqrt, SR, exp, symbolic_expression, N, derivative, pi
     16from sage.all import point, line2d, text, Graphics, plot, point, html, show, latex, circle, line, parametric_plot
     17from sage.all import implicit_plot3d, plot3d, cube, integral_numerical
    818
    919from sage.misc.misc import sage_wraps
    1020from sage.misc.html import html
     
    4757    """
    4858    print n+m
    4959
    50 
    51 
     60x=SR.var('x')
    5261@library_interact
    5362def taylor_polynomial(f=input_box(sin(x)*exp(-x)), order=slider(range(1,13))):
    5463    """
     
    7180    html('$f(x)\;=\;%s$'%latex(f))
    7281    html('$\hat{f}(x;%s)\;=\;%s+\mathcal{O}(x^{%s})$'%(x0,latex(ft),order+1))
    7382    show(dot + p + pt, ymin = -.5, ymax = 1)
     83
     84@library_interact
     85def definite_integral(
     86    f = input_box(default = "3*x", label = 'f(x)'),
     87    g = input_box(default = "x^2", label = 'g(x)'),
     88    interval = range_slider(-10,10,default=(0,3), label="Interval"),
     89    x_range = range_slider(-10,10,default=(0,3), label = "plot range (x)"),
     90    selection = selector(["f", "g", "f and g", "f - g"], default="f and g", label="Select")):
     91    """
     92    This is a demo interact for plotting the definite intergral of a function
     93    based on work by Lauri Ruotsalainen, 2010.
     94
     95    INPUT:
     96
     97        - `function` -- input box, function in x
     98        - `interval` -- interval for the definite integral
     99        - `x_range` -- range slider for plotting range
     100        - `selection` -- selector on how to visualize the integrals
     101
     102    EXAMPLES::
     103
     104        sage: interacts.calculus.definite_integral()
     105        <html>...</html>
     106    """
     107    x = SR.var('x')
     108    f = symbolic_expression(f).function(x)
     109    g = symbolic_expression(g).function(x)
     110    f_plot = Graphics(); g_plot = Graphics(); h_plot = Graphics();
     111    text = ""
     112
     113    # Plot function f.
     114    if selection != "g":   
     115        f_plot = plot(f(x), x, x_range, color="blue", thickness=1.5)
     116           
     117    # Color and calculate the area between f and the horizontal axis. 
     118    if selection == "f" or selection == "f and g":
     119        f_plot += plot(f(x), x, interval, color="blue", fill=True, fillcolor="blue", fillalpha=0.15)
     120        text += r"$\int_{%.2f}^{%.2f}(\color{Blue}{f(x)})\,dx=\int_{%.2f}^{%.2f}(%s)\,dx=%.2f$" % (
     121            interval[0], interval[1],
     122            interval[0], interval[1],
     123            latex(f(x)),
     124            f(x).nintegrate(x, interval[0], interval[1])[0]
     125        )
     126
     127    if selection == "f and g":
     128        text += r"<br/>"
     129
     130    # Plot function g. Also color and calculate the area between g and the horizontal axis.   
     131    if selection == "g" or selection == "f and g":
     132        g_plot = plot(g(x), x, x_range, color="green", thickness=1.5)
     133        g_plot += plot(g(x), x, interval, color="green", fill=True, fillcolor="yellow", fillalpha=0.5)
     134        text += r"$\int_{%.2f}^{%.2f}(\color{Green}{g(x)})\,dx=\int_{%.2f}^{%.2f}(%s)\,dx=%.2f$" % (
     135            interval[0], interval[1],
     136            interval[0], interval[1],
     137            latex(g(x)),
     138            g(x).nintegrate(x, interval[0], interval[1])[0]
     139        )     
     140         
     141    # Plot function f-g. Also color and calculate the area between f-g and the horizontal axis.
     142    if selection == "f - g":
     143        g_plot = plot(g(x), x, x_range, color="green", thickness=1.5)
     144        g_plot += plot(g(x), x, interval, color="green", fill=f(x), fillcolor="red", fillalpha=0.15)
     145        h_plot = plot(f(x)-g(x), x, interval, color="red", thickness=1.5, fill=True, fillcolor="red", fillalpha=0.15)
     146        text = r"$\int_{%.2f}^{%.2f}(\color{Red}{f(x)-g(x)})\,dx=\int_{%.2f}^{%.2f}(%s)\,dx=%.2f$" % (
     147            interval[0], interval[1],
     148            interval[0], interval[1],
     149            latex(f(x)-g(x)),
     150            (f(x)-g(x)).nintegrate(x, interval[0], interval[1])[0]
     151        )
     152               
     153    show(f_plot + g_plot + h_plot, gridlines=True)
     154    html(text)
     155
     156@library_interact
     157def function_derivative(
     158    function = input_box(default="x^5-3*x^3+1", label="Function:"),
     159    x_range  = range_slider(-15,15,0.1, default=(-2,2), label="Range (x)"),
     160    y_range  = range_slider(-15,15,0.1, default=(-8,6), label="Range (y)")):
     161    """
     162    This is a demo interact for plotting derivatives of a function based on work by
     163    Lauri Ruotsalainen, 2010.
     164
     165    INPUT:
     166
     167        - `function` -- input box, function in x
     168        - `x_range` -- range slider for plotting range
     169        - `y_range` -- range slider for plotting range
     170
     171    EXAMPLES::
     172
     173        sage: interacts.calculus.function_derivative()
     174        <html>...</html>
     175    """
     176    x = SR.var('x')
     177    f = symbolic_expression(function).function(x)
     178    df = derivative(f, x)
     179    ddf = derivative(df, x)
     180    plots = plot(f(x), x_range, thickness=1.5) + plot(df(x), x_range, color="green") + plot(ddf(x), x_range, color="red")
     181    if y_range == (0,0):
     182        show(plots, xmin=x_range[0], xmax=x_range[1])
     183    else:
     184        show(plots, xmin=x_range[0], xmax=x_range[1], ymin=y_range[0], ymax=y_range[1])
     185
     186    html("<center>$\color{Blue}{f(x) = %s}$</center>"%latex(f(x)))
     187    html("<center>$\color{Green}{f'(x) = %s}$</center>"%latex(df(x)))
     188    html("<center>$\color{Red}{f''(x) = %s}$</center>"%latex(ddf(x)))
     189
     190@library_interact
     191def difference_quotient(
     192    f = input_box(default="sin(x)", label='f(x)'),
     193    interval= range_slider(0, 10, 0.1, default=(0.0,10.0), label="Range"),
     194    a = slider(0, 10, None, 5.5, label = 'a'),
     195    x0 = slider(0, 10, None, 2.5), label = 'start point'):
     196    """
     197    This is a demo interact for difference quotient based on work by
     198    Lauri Ruotsalainen, 2010.
     199
     200    INPUT:
     201
     202        - `f` -- input box, function in x
     203        - `interval` -- range slider for plotting
     204        - `a` -- slider for a
     205        - `x0` -- slider for x0
     206
     207    EXAMPLES::
     208
     209        sage: interacts.calculus.difference_quotient()
     210        <html>...</html>
     211    """
     212    html('<h2>Difference Quotient</h2>')
     213    html('<div style="white-space: normal;">\
     214         <a href="http://en.wikipedia.org/wiki/Difference_quotient" target="_blank">\
     215         Wikipedia article about difference quotient</a></div>'
     216         )
     217
     218    x = SR.var('x')
     219    f = symbolic_expression(f).function(x)
     220    fmax = f.find_maximum_on_interval(interval[0], interval[1])[0]
     221    fmin = f.find_minimum_on_interval(interval[0], interval[1])[0]
     222    f_height = fmax - fmin
     223    measure_y = fmin - 0.1*f_height
     224
     225    measure_0 = line2d([(x0, measure_y), (a, measure_y)], rgbcolor="black")
     226    measure_1 = line2d([(x0, measure_y + 0.02*f_height), (x0, measure_y-0.02*f_height)], rgbcolor="black")
     227    measure_2 = line2d([(a, measure_y + 0.02*f_height), (a, measure_y-0.02*f_height)], rgbcolor="black")
     228    text_x0 = text("x0", (x0, measure_y - 0.05*f_height), rgbcolor="black")
     229    text_a = text("a", (a, measure_y - 0.05*f_height), rgbcolor="black")
     230    measure = measure_0 + measure_1 + measure_2 + text_x0 + text_a
     231
     232    tanf = symbolic_expression((f(x0)-f(a))*(x-a)/(x0-a)+f(a)).function(x)
     233
     234    fplot = plot(f(x), x, interval[0], interval[1])
     235    tanplot = plot(tanf(x), x, interval[0], interval[1], rgbcolor="#FF0000")
     236    points = point([(x0, f(x0)), (a, f(a))], pointsize=20, rgbcolor="#005500")
     237    dashline = line2d([(x0, f(x0)), (x0, f(a)), (a, f(a))], rgbcolor="#005500", linestyle="--")
     238    html('<h2>Difference Quotient</h2>')
     239    show(fplot + tanplot + points + dashline + measure, xmin=interval[0], xmax=interval[1], ymin=fmin-0.2*f_height, ymax=fmax)
     240    html(r"<br>$\text{Line's equation:}$")
     241    html(r"$y = %s$<br>"%tanf(x))
     242    html(r"$\text{Slope:}$")
     243    html(r"$k = \frac{f(x0)-f(a)}{x0-a} = %s$<br>" % (N(derivative(tanf(x), x), digits=5)))
     244
     245@library_interact
     246def quadratic_equation(A = slider(-7, 7, 1, 1), B = slider(-7, 7, 1, 1), C = slider(-7, 7, 1, -2)):
     247    """
     248    This is a demo interact for solving quadratic equations based on work by
     249    Lauri Ruotsalainen, 2010.
     250
     251    INPUT:
     252
     253        - `A` -- integer slider
     254        - `B` -- integer slider
     255        - `C` -- integer slider
     256
     257    EXAMPLES::
     258
     259        sage: interacts.calculus.quadratic_equation()
     260        <html>...</html>
     261    """
     262    x = SR.var('x')
     263    f = symbolic_expression(A*x**2 + B*x + C).function(x)
     264    html('<h2>The Solutions of the Quadratic Equation</h2>')
     265    html("$%s = 0$" % f(x))
     266   
     267    show(plot(f(x), x, (-10, 10), ymin=-10, ymax=10), aspect_ratio=1, figsize=4)
     268
     269    d = B**2 - 4*A*C
     270
     271    if d < 0:
     272        color = "Red"
     273        sol = r"\text{solution} \in \mathbb{C}"
     274    elif d == 0:
     275        color = "Blue"
     276        sol = -B/(2*A)
     277    else:
     278        color = "Green"
     279        a = (-B+sqrt(B**2-4*A*C))/(2*A)
     280        b = (-B-sqrt(B**2-4*A*C))/(2*A)
     281        sol = r"\begin{cases}%s\\%s\end{cases}" % (latex(a), latex(b))
     282
     283    if B < 0:
     284        dis1 = "(%s)^2-4*%s*%s" % (B, A, C)
     285    else:
     286        dis1 = "%s^2-4*%s*%s" % (B, A, C)       
     287    dis2 = r"\color{%s}{%s}" % (color, d)
     288
     289    html("$Ax^2 + Bx + C = 0$")
     290    calc = r"$x = \frac{-B\pm\sqrt{B^2-4AC}}{2A} = " + \
     291           r"\frac{-%s\pm\sqrt{%s}}{2*%s} = " + \
     292           r"\frac{-%s\pm\sqrt{%s}}{%s} = %s$"
     293    html(calc % (B, dis1, A, B, dis2, (2*A), sol))
     294
     295#R.<x> = ZZ[]
     296new_ex_state = True
     297prac_function = None
     298
     299@library_interact
     300def practice_differentiating_polynomials(
     301    answer = input_box(label="Answer"),
     302    new_exercise = checkbox(default=False, label="New exercise"),
     303    show_solution = checkbox(default=False, label="Show solution")):
     304    """
     305    This is an interact for practicing differentiating random polynomials
     306    based on work by Lauri Ruotsalainen, 2010.
     307
     308    INPUT:
     309
     310        - `answer` -- enter your answer here
     311        - `new_exercise` -- generate a new exercise
     312        - `show_solution` -- show the solution
     313
     314    EXAMPLES::
     315
     316        sage: interacts.calculus.practice_differentiating_polynomials()
     317        <html>...</html>
     318    """
     319    import sage
     320    from sage.interacts.library import prac_function, new_ex_state
     321    from sage.all import ZZ
     322    R = ZZ['x']; (x,) = R._first_ngens(1)
     323    if prac_function is None:
     324        prac_function = R.random_element(3, -10,10)
     325        sage.interacts.library.prac_function = prac_function
     326
     327    if answer == derivative(prac_function(x)) or new_exercise == new_ex_state:
     328        new_ex_state = not new_exercise
     329        sage.interacts.library.new_ex_state = new_ex_state
     330        prac_function = R.random_element(3, -10,10)
     331        sage.interacts.library.prac_function = prac_function
     332
     333    if answer == derivative(prac_function(x)):
     334        html(r"$\text{Very good! New exercise:}$")
     335        prac_function = R.random_element(3, -10,10)
     336        sage.interacts.library.prac_function = prac_function
     337
     338    elif answer and show_solution is False and new_exercise != new_ex_state:
     339        html(r"$\text{You've made an error. Try again!}$")
     340
     341    html(r"$\text{Calculate the derivative: }\;\;\;\;%s$<br>"%latex(prac_function(x)))
     342
     343    if show_solution:
     344        html(r"$\text{Solution: }\;\;\;\;%s$<br>"%latex(derivative(prac_function(x))))
     345
     346
     347@library_interact
     348def trigonometric_properties_triangle(
     349    a0 = slider(0, 360, 1, 30, label="A"),
     350    a1 = slider(0, 360, 1, 180, label="B"),
     351    a2 = slider(0, 360, 1, 300, label="C")):
     352    """
     353    This is an interact for demonstrating trigonometric properties
     354    in a triangle based on work by Lauri Ruotsalainen, 2010.
     355
     356    INPUT:
     357
     358        - `a0` -- angle
     359        - `a1` -- angle
     360        - `a2` -- angle
     361
     362    EXAMPLES::
     363
     364        sage: interacts.geometry.trigonometric_properties_triangle()
     365        <html>...</html>
     366    """
     367    import math
     368
     369    # Returns the distance between points (x1,y1) and (x2,y2)
     370    def distance((x1, y1), (x2, y2)):
     371        return sqrt((x2-x1)**2 + (y2-y1)**2)
     372   
     373    # Returns an angle (in radians) when sides a and b
     374    # are adjacent and the side c is opposite to the angle
     375    def angle(a, b, c):
     376        a,b,c = map(float,[a,b,c])
     377        return acos((b**2 + c**2 - a**2)/(2.0*b*c))
     378   
     379    # Returns the area of a triangle when an angle alpha
     380    # and adjacent sides a and b are known
     381    def area(alpha, a, b):
     382        return 1.0/2.0*a*b*sin(alpha)
     383   
     384    xy = [0]*3
     385    html('<h2>Trigonometric Properties of a Triangle</h2>')
     386    # Coordinates of the angles
     387    a = map(lambda x : math.radians(float(x)), [a0, a1, a2])
     388    for i in range(3):
     389        xy[i] = (cos(a[i]), sin(a[i]))
     390
     391    # Side lengths (bc, ca, ab) corresponding to triangle vertices (a, b, c)
     392    al = [distance(xy[1], xy[2]), distance(xy[2], xy[0]), distance(xy[0], xy[1])]
     393
     394    # The angles (a, b, c) in radians
     395    ak = [angle(al[0], al[1], al[2]), angle(al[1], al[2], al[0]), angle(al[2], al[0], al[1])]
     396
     397    # The area of the triangle
     398    A = area(ak[0], al[1], al[2])
     399
     400    unit_circle = circle((0, 0), 1, aspect_ratio=1)
     401
     402    # Triangle
     403    triangle = line([xy[0], xy[1], xy[2], xy[0]], rgbcolor="black")
     404    triangle_points = point(xy, pointsize=30)
     405
     406    # Labels of the angles drawn in a distance from points
     407    a_label = text("A", (xy[0][0]*1.07, xy[0][1]*1.07))
     408    b_label = text("B", (xy[1][0]*1.07, xy[1][1]*1.07))
     409    c_label = text("C", (xy[2][0]*1.07, xy[2][1]*1.07))
     410    labels = a_label + b_label + c_label
     411
     412    show(unit_circle + triangle + triangle_points + labels, figsize=[5, 5], xmin=-1, xmax=1, ymin=-1, ymax=1)
     413    angl_txt = r"$< A = {%s}^{\circ},$ $< B = {%s}^{\circ},$ $< C = {%s}^{\circ}$" % (
     414            math.degrees(ak[0]),
     415            math.degrees(ak[1]),
     416            math.degrees(ak[2])
     417        )
     418    html(angl_txt)
     419    html(r"$AB = %s,$  $BC = %s,$  $CA = %s$"%(al[2], al[0], al[1]))
     420    html(r"$\text{Area A} = %s$"%A)
     421
     422@library_interact
     423def unit_circle(
     424    function = selector([(0, sin(x)), (1, cos(x)), (2, tan(x))]),
     425    x = slider(0,2*pi, 0.005*pi, 0)):
     426    """
     427    This is an interact for Sin, Cos and Tan in the Unit Circle
     428    based on work by Lauri Ruotsalainen, 2010.
     429
     430    INPUT:
     431
     432        - `function` -- select Sin, Cos or Tan
     433        - `x` -- slider to select angle in unit circle
     434
     435    EXAMPLES::
     436
     437        sage: interacts.geometry.unit_circle()
     438        <html>...</html>
     439    """
     440    xy = (cos(x), sin(x))
     441    t = SR.var('t')
     442    html('<div style="white-space: normal;">Lines of the same color have\
     443         the same length</div>')
     444
     445    # Unit Circle
     446    C = circle((0, 0), 1, figsize=[5, 5], aspect_ratio=1)
     447    C_line = line([(0, 0), (xy[0], xy[1])], rgbcolor="black")
     448    C_point = point((xy[0], xy[1]), pointsize=40, rgbcolor="green")
     449    C_inner = parametric_plot((cos(t), sin(t)), (t, 0, x + 0.001), color="green", thickness=3)
     450    C_outer = parametric_plot((0.1 * cos(t), 0.1 * sin(t)), (t, 0, x + 0.001), color="black")
     451    C_graph = C + C_line + C_point + C_inner + C_outer
     452
     453    # Graphics related to the graph of the function
     454    G_line = line([(0, 0), (x, 0)], rgbcolor="green", thickness=3)
     455    G_point = point((x, 0), pointsize=30, rgbcolor="green")
     456    G_graph = G_line + G_point
     457
     458    # Sine
     459    if function == 0:
     460        Gf = plot(sin(t), t, 0, 2*pi, axes_labels=("x", "sin(x)"))
     461        Gf_point = point((x, sin(x)), pointsize=30, rgbcolor="red")
     462        Gf_line = line([(x, 0),(x, sin(x))], rgbcolor="red")
     463        Cf_point = point((0, xy[1]), pointsize=40, rgbcolor="red")
     464        Cf_line1 = line([(0, 0), (0, xy[1])], rgbcolor="red", thickness=3)
     465        Cf_line2 = line([(0, xy[1]), (xy[0], xy[1])], rgbcolor="purple", linestyle="--")
     466    # Cosine
     467    elif function == 1:
     468        Gf = plot(cos(t), t, 0, 2*pi, axes_labels=("x", "cos(x)"))
     469        Gf_point = point((x, cos(x)), pointsize=30, rgbcolor="red")
     470        Gf_line = line([(x, 0), (x, cos(x))], rgbcolor="red")
     471        Cf_point = point((xy[0], 0), pointsize=40, rgbcolor="red")
     472        Cf_line1 = line([(0, 0), (xy[0], 0)], rgbcolor="red", thickness=3)
     473        Cf_line2 = line([(xy[0], 0), (xy[0], xy[1])], rgbcolor="purple", linestyle="--")
     474    # Tangent
     475    else:
     476        Gf = plot(tan(t), t, 0, 2*pi, ymin=-8, ymax=8, axes_labels=("x", "tan(x)"))
     477        Gf_point = point((x, tan(x)), pointsize=30, rgbcolor="red")
     478        Gf_line = line([(x, 0), (x, tan(x))], rgbcolor="red")
     479        Cf_point = point((1, tan(x)), pointsize=40, rgbcolor="red")
     480        Cf_line1 = line([(1, 0), (1, tan(x))], rgbcolor="red", thickness=3)
     481        Cf_line2 = line([(xy[0], xy[1]), (1, tan(x))], rgbcolor="purple", linestyle="--")
     482
     483    C_graph += Cf_point + Cf_line1 + Cf_line2
     484    G_graph += Gf + Gf_point + Gf_line
     485
     486    html.table([[r"$\text{Unit Circle}$",r"$\text{Function}$"], [C_graph, G_graph]], header=True)
     487
     488@library_interact
     489def cube_hemisphere(size = slider(0.5, 1, label="The Edge Length x:")):
     490    """
     491    This interact demo shows a cube within a hemisphere
     492    based on work by Lauri Ruotsalainen, 2010.
     493
     494    INPUT:
     495
     496        - `size` -- slider to select the edge length x
     497
     498    EXAMPLES::
     499
     500        sage: interacts.geometry.cube_hemisphere()
     501        <html>...</html>
     502    """
     503    html('<h2>Cube within a Hemisphere</h2>')
     504    html('<div style="white-space: normal">A cube is placed within a hemisphere so that the corners ' +\
     505        'of the cube touch the surface of the hemisphere; Observe numerically' + \
     506        'the ratio of the volume of the cube and the volume of the hemisphere.</div>')
     507    x, y, z = SR.var("x,y,z")
     508    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)
     509    cube_graph = cube(size=size, opacity=0.9, color="red", frame_thickness=1).translate((0, 0, size/2.0))
     510    surface_graph = plot3d(0, (x, -1.2, 1.2),(y, -1.2, 1.2), color="lightblue", opacity=0.6)
     511    show(hemisphere_graph + cube_graph + surface_graph, aspect_ratio=1)
     512
     513    V_c = size**3
     514    V_hs = 4*pi*1**3/6.0
     515    html(r"$\text{Volume of the Cube: }V_{cube} = x^3 = {%.5f}^3 = %s" % (N(size, digits=5), N(V_c, digits=5)))
     516    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))
     517    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)))
     518
     519
     520@library_interact
     521def special_points(
     522    a0 = slider(0, 360, 1, 30, label="A"),
     523    a1 = slider(0, 360, 1, 180, label="B"),
     524    a2 = slider(0, 360, 1, 300, label="C"),
     525    show_median = checkbox(False, label="Medians"),
     526    show_pb = checkbox(False, label="Perpendicular Bisectors"),
     527    show_alt = checkbox(False, label="Altitudes"),
     528    show_ab = checkbox(False, label="Angle Bisectors"),
     529    show_incircle = checkbox(False, label="Incircle"),
     530    show_euler = checkbox(False, label="Euler's Line")):
     531    """
     532    This interact demo shows special points in a triangle
     533    based on work by Lauri Ruotsalainen, 2010.
     534
     535    INPUT:
     536
     537        - `a0` -- angle
     538        - `a1` -- angle
     539        - `a2` -- angle
     540        - `show_median` -- checkbox
     541        - `show_pb` -- checkbox to show perpendicular bisectors
     542        - `show_alt` -- checkbox to show altitudes
     543        - `show_ab` -- checkbox to show angle bisectors
     544        - `show_incircle` -- checkbox to show incircle
     545        - `show_euler` -- checkbox to show euler's line
     546
     547    EXAMPLES::
     548
     549        sage: interacts.geometry.special_points()
     550        <html>...</html>
     551    """
     552    import math
     553    # Return the intersection point of the bisector of the angle <(A[a],A[c],A[b]) and the unit circle. Angles given in radians.
     554    def half(A, a, b, c):
     555        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])):
     556            p = A[a] + (A[b] - A[a]) / 2.0
     557        else:
     558            p = A[b] + (2*pi - (A[b]-A[a])) / 2.0
     559        return (math.cos(p), math.sin(p))
     560   
     561    # Returns the distance between points (x1,y1) and (x2,y2)
     562    def distance((x1, y1), (x2, y2)):
     563        return math.sqrt((x2-x1)**2 + (y2-y1)**2)
     564   
     565    # Returns the line (graph) going through points (x1,y1) and (x2,y2)
     566    def line_to_points((x1, y1), (x2, y2), **plot_kwargs):
     567        return plot((y2-y1) / (x2-x1) * (x-x1) + y1, (x,-3,3), **plot_kwargs)
     568
     569    # Coordinates of the angles
     570    a = map(lambda x : math.radians(float(x)), [a0, a1, a2])
     571    xy = [(math.cos(a[i]), math.sin(a[i])) for i in range(3)]
     572
     573    # Labels of the angles drawn in a distance from points
     574    a_label = text("A", (xy[0][0]*1.07, xy[0][1]*1.07))
     575    b_label = text("B", (xy[1][0]*1.07, xy[1][1]*1.07))
     576    c_label = text("C", (xy[2][0]*1.07, xy[2][1]*1.07))
     577    labels = a_label + b_label + c_label
     578
     579    C = circle((0, 0), 1, aspect_ratio=1)
     580
     581    # Triangle
     582    triangle = line([xy[0], xy[1], xy[2], xy[0]], rgbcolor="black")
     583    triangle_points = point(xy, pointsize=30)
     584
     585    # Side lengths (bc, ca, ab) corresponding to triangle vertices (a, b, c)
     586    ad = [distance(xy[1], xy[2]), distance(xy[2], xy[0]), distance(xy[0], xy[1])]
     587
     588    # Midpoints of edges (bc, ca, ab)
     589    a_middle = [
     590        ((xy[1][0] + xy[2][0])/2.0, (xy[1][1] + xy[2][1])/2.0),
     591        ((xy[2][0] + xy[0][0])/2.0, (xy[2][1] + xy[0][1])/2.0),
     592        ((xy[0][0] + xy[1][0])/2.0, (xy[0][1] + xy[1][1])/2.0)
     593    ]
     594
     595    # Incircle
     596    perimeter = float(ad[0] + ad[1] + ad[2])
     597    incircle_center = (
     598        (ad[0]*xy[0][0] + ad[1]*xy[1][0] + ad[2]*xy[2][0]) / perimeter,
     599        (ad[0]*xy[0][1] + ad[1]*xy[1][1] + ad[2]*xy[2][1]) / perimeter
     600    )
     601
     602    if show_incircle:
     603        s = perimeter/2.0
     604        incircle_r = math.sqrt((s - ad[0]) * (s - ad[1]) * (s - ad[2]) / s)
     605        incircle_graph = circle(incircle_center, incircle_r) + point(incircle_center)
     606    else:
     607        incircle_graph = Graphics()
     608
     609    # Angle Bisectors
     610    if show_ab:
     611        a_ab = line([xy[0], half(a, 1, 2, 0)], rgbcolor="blue", alpha=0.6)
     612        b_ab = line([xy[1], half(a, 2, 0, 1)], rgbcolor="blue", alpha=0.6)
     613        c_ab = line([xy[2], half(a, 0, 1, 2)], rgbcolor="blue", alpha=0.6)
     614        ab_point = point(incircle_center, rgbcolor="blue", pointsize=28)
     615        ab_graph = a_ab + b_ab + c_ab + ab_point
     616    else:
     617        ab_graph = Graphics()
     618
     619    # Medians
     620    if show_median:
     621        a_median = line([xy[0], a_middle[0]], rgbcolor="green", alpha=0.6)
     622        b_median = line([xy[1], a_middle[1]], rgbcolor="green", alpha=0.6)
     623        c_median = line([xy[2], a_middle[2]], rgbcolor="green", alpha=0.6)
     624        median_point = point(
     625            (
     626                (xy[0][0]+xy[1][0]+xy[2][0])/3.0,
     627                (xy[0][1]+xy[1][1]+xy[2][1])/3.0
     628            ), rgbcolor="green", pointsize=28)
     629        median_graph = a_median + b_median + c_median + median_point
     630    else:
     631        median_graph = Graphics()
     632
     633    # Perpendicular Bisectors
     634    if show_pb:
     635        a_pb = line_to_points(a_middle[0], half(a, 1, 2, 0), rgbcolor="red", alpha=0.6)
     636        b_pb = line_to_points(a_middle[1], half(a, 2, 0, 1), rgbcolor="red", alpha=0.6)
     637        c_pb = line_to_points(a_middle[2], half(a, 0, 1, 2), rgbcolor="red", alpha=0.6)
     638        pb_point = point((0, 0), rgbcolor="red", pointsize=28)
     639        pb_graph = a_pb + b_pb + c_pb + pb_point
     640    else:
     641        pb_graph = Graphics()
     642
     643    # Altitudes
     644    if show_alt:
     645        xA, xB, xC = xy[0][0], xy[1][0], xy[2][0]
     646        yA, yB, yC = xy[0][1], xy[1][1], xy[2][1]
     647        a_alt = plot(((xC-xB)*x+(xB-xC)*xA)/(yB-yC)+yA, (x,-3,3), rgbcolor="brown", alpha=0.6)
     648        b_alt = plot(((xA-xC)*x+(xC-xA)*xB)/(yC-yA)+yB, (x,-3,3), rgbcolor="brown", alpha=0.6)
     649        c_alt = plot(((xB-xA)*x+(xA-xB)*xC)/(yA-yB)+yC, (x,-3,3), rgbcolor="brown", alpha=0.6)
     650        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)
     651        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)
     652        alt_intersection = point((alt_lx, alt_ly), rgbcolor="brown", pointsize=28)
     653        alt_graph = a_alt + b_alt + c_alt + alt_intersection
     654    else:
     655        alt_graph = Graphics()
     656
     657    # Euler's Line
     658    if show_euler:
     659        euler_graph = line_to_points(
     660            (0, 0),
     661            (
     662                (xy[0][0]+xy[1][0]+xy[2][0])/3.0,
     663                (xy[0][1]+xy[1][1]+xy[2][1])/3.0
     664            ),
     665            rgbcolor="purple",
     666            thickness=2,
     667            alpha=0.7
     668        )
     669    else:
     670        euler_graph = Graphics()
     671
     672    show(
     673        C + triangle + triangle_points + labels + ab_graph + median_graph +
     674        pb_graph + alt_graph + incircle_graph + euler_graph,
     675        figsize=[5,5], xmin=-1, xmax=1, ymin=-1, ymax=1
     676    )
     677
     678
     679@library_interact
     680def 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)")):
     681    """
     682    This interact demo simulates repeated tosses of a coin,
     683    based on work by Lauri Ruotsalainen, 2010.
     684
     685    INPUT:
     686
     687      - `n` -- number of tosses
     688      - `interval` -- plot range (y)
     689
     690    EXAMPLES::
     691
     692        sage: interacts.statistics.coin()
     693        <html>...</html>
     694    """
     695    from random import random
     696    c = []
     697    k = 0.0
     698    for i in range(1, n + 1):
     699        k += random()
     700        c.append((i, k/i))
     701    show(point(c[1:], gridlines=[None, [0.5]], pointsize=1), ymin=interval[0], ymax=interval[1])
     702
     703
     704@library_interact
     705def secant_method(
     706    f = input_box("x^2-2", label='f(x)'),
     707    interval = range_slider(-5,5,default=(0, 4), label="range"),
     708    d = slider(1, 16, 1, 3, label="10^-d precision"),
     709    maxn = slider(0,15,1,10, label="max iterations")):
     710    """
     711    Interact explaining the secant method, based on work by
     712    Lauri Ruotsalainen, 2010.
     713    Originally this is based on work by William Stein.
     714
     715    INPUT:
     716
     717      - `f` -- function
     718      - `interval` -- range slider for the search interval
     719      - `slider` -- slider for the precision (10^-d)
     720      - `maxn` -- max number of iterations
     721
     722    EXAMPLES::
     723
     724        sage: interacts.calculus.secant_method()
     725        <html>...</html>
     726    """
     727    def _secant_method(f, a, b, maxn, h):
     728        intervals = [(a,b)]
     729        round = 1
     730        while True:
     731            c = b-(b-a)*f(b)/(f(b)-f(a))
     732            if abs(f(c)) < h or round >= maxn:
     733                break
     734            a, b = b, c
     735            intervals.append((a,b))
     736            round += 1
     737        return c, intervals
     738
     739    x = SR.var('x')
     740    f = symbolic_expression(f).function(x)
     741    a, b = interval
     742    h = 10**(-d)
     743    c, intervals = _secant_method(f, float(a), float(b), maxn, h)
     744    html(r"$\text{Precision h =} 10^{-d}=10^{-%s}=%.5f$"%(d, float(h)))
     745    html(r"$\text{c = }%s$"%c)
     746    html(r"$\text{f(c) = }%s"%f(c))
     747    html(r"$\text{Iterations = }%s"%len(intervals))
     748    P = plot(f, a, b, color='red')
     749    k = (P.ymax() - P.ymin())/ (1.5*len(intervals))
     750    L = sum(line([(c,k*i), (d,k*i)]) for i, (c,d) in enumerate(intervals) )
     751    L += sum(line([(c,k*i-k/4), (c,k*i+k/4)]) for i, (c,d) in enumerate(intervals) )
     752    L += sum(line([(d,k*i-k/4), (d,k*i+k/4)]) for i, (c,d) in enumerate(intervals) )
     753    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)
     754    show(P + L + S, xmin=a, xmax=b)
     755
     756@library_interact
     757def newton_method(
     758    f = input_box("x^2 - 2"),
     759    c = slider(-10,10, default=6, label='Start (x)'),
     760    hh = slider(-16, -1, 1, -3, label="Precision 2h"),
     761    maxn = slider(0, 15, 1, 10, label="max iterations"),
     762    interval = range_slider(-10,10, default = (0,6), label="Interval"),
     763    list_steps = checkbox(default=False, label="List steps")):
     764    """
     765    Interact explaining the newton method, based on work by
     766    Lauri Ruotsalainen, 2010.
     767    Originally this is based on work by William Stein.
     768
     769    INPUT:
     770
     771      - `f` -- function
     772      - `c` -- starting position (x)
     773      - `interval` -- range slider for the search interval
     774      - `slider` -- slider for the precision (10^-d)
     775      - `maxn` -- max number of iterations
     776      - `list_steps` -- checkbox, if true shows the steps numerically
     777
     778    EXAMPLES::
     779
     780        sage: interacts.calculus.newton_method()
     781        <html>...</html>
     782    """
     783    def _newton_method(f, c, maxn, h):
     784        midpoints = [c]
     785        round = 1
     786        while True:
     787            c = c-f(c)/f.derivative(x)(x=c)
     788            midpoints.append(c)
     789            if f(c-h)*f(c+h) < 0 or round == maxn:
     790                break
     791            round += 1
     792        return c, midpoints
     793
     794    x = SR.var('x')
     795    f = symbolic_expression(f).function(x)
     796    a, b = interval
     797    h = 10**hh
     798    c, midpoints = _newton_method(f, float(c), maxn, h/2.0)
     799    html(r"$\text{Precision 2h = }%.5f$"%float(h))
     800    html(r"$\text{c = }%s$"%c)
     801    html(r"$\text{f(c) = }%s"%f(c))
     802    html(r"$\text{Iterations = }%s"%len(midpoints))
     803    if list_steps:
     804        s = "<br><br><table border=1 cellpadding=5>"
     805        s += "<tr><td>$n$</td><td>$x_n$</td><td>$f(x_n)$</td><td>$f(x_n-h)f(x_n+h)$</td></tr>"
     806        for i, c in enumerate(midpoints):
     807            s += "<tr><td>$%d$</td><td>$%.4f$</td><td>$%.4f$</td><td>$%.4f$</td></tr>"%(i, c, f(c), f(c-h)*f(c+h))
     808        s += "</table>"
     809        html(s)
     810    else:
     811        P = plot(f, x, interval, color="blue")
     812        L = sum(line([(c, 0), (c, f(c))], color="green") for c in midpoints[:-1])
     813        for i in range(len(midpoints) - 1):
     814            L += line([(midpoints[i], f(midpoints[i])), (midpoints[i+1], 0)], color="red")
     815        show(P + L, xmin=interval[0], xmax=interval[1], ymin=P.ymin(), ymax=P.ymax())
     816
     817@library_interact
     818def trapezoid_integration(
     819    f = input_box(default = "x^2-5*x + 10", label='f(x)'),
     820    n = slider(1,100,1,5, label='# divisions'),
     821    interval = range_slider(-10,10,default=(0,8), label="Integral interval")
     822    ):
     823    """
     824    Interact explaining the trapezoid method for definite integrals, based on work by
     825    Lauri Ruotsalainen, 2010 (based on the application "Numerical integrals with various rules"
     826    by Marshall Hampton and Nick Alexander)
     827
     828    INPUT:
     829   
     830      - `f` -- function of variable x to integrate
     831      - `n` -- number of divisions
     832      - `interval` -- interval to integrate
     833
     834    EXAMPLES::
     835
     836        sage: interacts.calculus.trapezoid_integration()
     837        <html>...</html>
     838    """
     839    xs = []
     840    ys = []
     841    h = (interval[1]-interval[0])/n
     842    x = SR.var('x')
     843    f = symbolic_expression(f).function(x)
     844
     845    trapezoids = Graphics()
     846   
     847    for i in range(n):
     848        xi = interval[0] + i*h
     849        yi = f(xi)
     850        trapezoids += line([[xi, 0], [xi, yi], [xi + h, f(xi + h)],[xi + h, 0],[xi, 0]], rgbcolor = (1,0,0))
     851        xs.append(xi)
     852        ys.append(yi)
     853    xs.append(xi + h)
     854    ys.append(f(xi + h))
     855
     856    show(plot(f, interval[0], interval[1]) + trapezoids, xmin = interval[0], xmax = interval[1])
     857   
     858    numeric_value = integral_numerical(f, interval[0], interval[1])[0]
     859    approx = h *(ys[0]/2 + sum([ys[i] for i in range(1,n)]) + ys[n]/2)
     860   
     861    sum_formula_html = r"d \cdot \left[\frac{f(x_0)}{2} + %s + \frac{f(x_{%s})}{2}\right]" % (
     862        ' + '.join([ "f(x_{%s})"%i for i in range(1,n)]),
     863        n
     864    )
     865    sum_placement_html = r"%.2f \cdot \left[\frac{f(%.2f)}{2} + %s + \frac{f(%.2f)}{2}\right]" % (
     866        h,
     867        N(xs[0], digits=5),
     868        ' + '.join([ "f(%.2f)" %N(i, digits=5) for i in xs[1:-1]]),
     869        N(xs[n], digits=5)
     870    )
     871    sum_values_html = r"%.2f \cdot \left[\frac{%.2f}{2} + %s + \frac{%.2f}{2}\right]" % (
     872        h,
     873        N(ys[0], digits=5),
     874        ' + '.join([ "%.2f" % N(i, digits=5) for i in ys[1:-1]]),
     875        N(ys[n], digits=5)
     876    )
     877
     878    html(r'''
     879        <div class="math">
     880        \begin{align*}
     881        \int_{%.2f}^{%.2f} {f(x) \, dx} & = %.6f \\\
     882        \\
     883       \int_{%.2f}^{%.2f} {f(x) \, dx}
     884            & \approx %s \\
     885            & = %s \\
     886            & = %s \\
     887            & = %s
     888        \end{align*}
     889        </div>
     890    ''' % (
     891        interval[0], interval[1],
     892        N(numeric_value, digits=7),
     893        interval[0], interval[1],
     894        sum_formula_html, sum_placement_html, sum_values_html,
     895        N(approx, digits=7)
     896    ))
     897
     898
     899@library_interact
     900def simpson_integration(
     901    f = input_box(default = 'x*sin(x)+x+1', label='f(x)'),
     902    n=slider(2,100,2,6, label='# divisions'),
     903    interval=range_slider(-10,10,default=(0,10), label="Integration Interval")):
     904    """
     905    Interact explaining the simpson method for definite integrals, based on work by
     906    Lauri Ruotsalainen, 2010 (based on the application "Numerical integrals with various rules"
     907    by Marshall Hampton and Nick Alexander)
     908
     909    INPUT:
     910   
     911      - `f` -- function of variable x to integrate
     912      - `n` -- number of divisions (mult. of 2)
     913      - `interval` -- interval to integrate
     914
     915    EXAMPLES::
     916
     917        sage: interacts.calculus.simpson_integration()
     918        <html>...</html>
     919    """
     920    x = SR.var('x')
     921    f = symbolic_expression(f).function(x)
     922
     923    def parabola(a, b, c):
     924        from sage.all import solve
     925        A, B, C = SR.var("A, B, C")
     926        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]
     927        f = K[A]*x**2+K[B]*x+K[C]
     928        return f
     929    xs = []; ys = []
     930    dx = (interval[1]-interval[0])/n
     931   
     932    for i in range(n+1):
     933        xs.append(interval[0] + i*dx)
     934        ys.append(f(xs[-1]))
     935
     936    parabolas = Graphics()
     937    lines = Graphics()
     938   
     939    for i in range(0, n-1, 2):
     940        p = parabola((xs[i],ys[i]),(xs[i+1],ys[i+1]),(xs[i+2],ys[i+2]))
     941        parabolas += plot(p(x), x, xmin=xs[i], xmax=xs[i+2], color="red")
     942        lines += line([(xs[i],ys[i]), (xs[i],0), (xs[i+2],0)],color="red")
     943        lines += line([(xs[i+1],ys[i+1]), (xs[i+1],0)], linestyle="-.", color="red")
     944       
     945    lines += line([(xs[-1],ys[-1]), (xs[-1],0)], color="red")
     946   
     947    show(plot(f(x),x,interval[0],interval[1]) + parabolas + lines, xmin = interval[0], xmax = interval[1])
     948   
     949    numeric_value = integral_numerical(f,interval[0],interval[1])[0]
     950    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])
     951   
     952    sum_formula_html = r"\frac{d}{3} \cdot \left[ f(x_0) + %s + f(x_{%s})\right]" % (
     953        ' + '.join([ r"%s \cdot f(x_{%s})" %(i%2*(-2)+4, i+1) for i in range(0,n-1)]),
     954        n
     955    )
     956   
     957    sum_placement_html = r"\frac{%.2f}{3} \cdot \left[ f(%.2f) +  %s + f(%.2f)\right]" % (
     958        dx,
     959        N(xs[0],digits=5),
     960        ' + '.join([ r"%s \cdot f(%.2f)" %(i%2*(-2)+4, N(xk, digits=5)) for i, xk in enumerate(xs[1:-1])]),
     961        N(xs[n],digits=5)
     962    )
     963   
     964    sum_values_html = r"\frac{%.2f}{3} \cdot \left[ %s %s %s\right]" %(
     965        dx,
     966        "%.2f + "%N(ys[0],digits=5),
     967        ' + '.join([ r"%s \cdot %.2f" %(i%2*(-2)+4, N(yk, digits=5)) for i, yk in enumerate(ys[1:-1])]),
     968        " + %.2f"%N(ys[n],digits=5)
     969    )
     970
     971    html(r'''
     972    <div class="math">
     973    \begin{align*}
     974    \int_{%.2f}^{%.2f} {f(x) \, dx} & = %.6f \\
     975    \\
     976    \int_{%.2f}^{%.2f} {f(x) \, dx}
     977        & \approx %s \\
     978        & = %s \\
     979        & = %s \\
     980        & = %.6f
     981    \end{align*}
     982    </div>
     983    ''' % (
     984        interval[0],interval[1],
     985        N(numeric_value,digits=7),
     986        interval[0], interval[1],
     987        sum_formula_html, sum_placement_html, sum_values_html,
     988        N(approx,digits=7)
     989    ))
  • new file sage/interacts/statistics.py

    diff --git a/sage/interacts/statistics.py b/sage/interacts/statistics.py
    new file mode 100644
    - +  
     1"""
     2Interacts for Statistics
     3
     4"""
     5
     6
     7#*****************************************************************************
     8#     Copyright (C) 2010 Harald Schilly <harald.schilly@gmail.com>
     9#
     10#  Distributed under the terms of the GNU General Public License (GPL)
     11#                  http://www.gnu.org/licenses/
     12#*****************************************************************************
     13
     14from library import coin