# HG changeset patch # User Robert Marik # Date 1282047361 25200 # Node ID a0f7631c1929c3ae35cd5f8d7f12ba6c2190d2be # Parent 510cda682570e93d08470ad221e57cc8b513b73d Trac #9623: Added titles to interacts, two new interacts (Riemann integral and bisection method), alternative input and output forms for simpson and trapezoidal rule and some minor improvements. diff -r 510cda682570 -r a0f7631c1929 sage/interacts/calculus.py --- a/sage/interacts/calculus.py Sat Jul 31 15:20:52 2010 +0200 +++ b/sage/interacts/calculus.py Tue Aug 17 05:16:01 2010 -0700 @@ -14,6 +14,7 @@ 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 trigonometric_properties_triangle +from library import secant_method, newton_method, trapezoid_integration, simpson_integration, bisection_method +from library import riemann_sum from library import function_tool diff -r 510cda682570 -r a0f7631c1929 sage/interacts/library.py --- a/sage/interacts/library.py Sat Jul 31 15:20:52 2010 +0200 +++ b/sage/interacts/library.py Tue Aug 17 05:16:01 2010 -0700 @@ -21,10 +21,10 @@ # http://www.gnu.org/licenses/ #***************************************************************************** -from sagenb.notebook.interact import interact, slider, range_slider, input_box, selector, checkbox +from sagenb.notebook.interact import interact, slider, range_slider, input_box, selector, checkbox, input_grid, text_control from sage.all import sin, cos, asin, acos, tan, sqrt, SR, exp, symbolic_expression, N, derivative, pi from sage.all import factor, srange, Integer, points -from sage.all import point, line2d, text, Graphics, plot, point, html, show, latex, circle, line, parametric_plot +from sage.all import point, line2d, text, Graphics, plot, point, html, show, latex, circle, line, parametric_plot, polygon2d from sage.all import implicit_plot3d, plot3d, cube, integral_numerical, CDF, complex_plot, matrix_plot, disk from sage.ext.fast_callable import fast_callable @@ -71,7 +71,9 @@ x=SR.var('x') @library_interact -def taylor_polynomial(f=input_box(sin(x)*exp(-x)), order=slider(range(1,13))): +def taylor_polynomial( + title = text_control('

Taylor polynomial

'), + f=input_box(sin(x)*exp(-x),label="$f(x)=$"), order=slider(range(1,13))): """ An interact which illustrates the Taylor polynomial approximation of various orders around `x=0`. @@ -95,8 +97,9 @@ @library_interact def definite_integral( - f = input_box(default = "3*x", label = 'f(x)'), - g = input_box(default = "x^2", label = 'g(x)'), + title = text_control('

Definite integral

'), + f = input_box(default = "3*x", label = '$f(x)=$'), + g = input_box(default = "x^2", label = '$g(x)=$'), interval = range_slider(-10,10,default=(0,3), label="Interval"), x_range = range_slider(-10,10,default=(0,3), label = "plot range (x)"), selection = selector(["f", "g", "f and g", "f - g"], default="f and g", label="Select")): @@ -129,7 +132,7 @@ # 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$" % ( + text += r"$\int_{%.2f}^{%.2f}(\color{Blue}{f(x)})\,\mathrm{d}x=\int_{%.2f}^{%.2f}(%s)\,\mathrm{d}x=%.2f$" % ( interval[0], interval[1], interval[0], interval[1], latex(f(x)), @@ -143,7 +146,7 @@ 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$" % ( + text += r"$\int_{%.2f}^{%.2f}(\color{Green}{g(x)})\,\mathrm{d}x=\int_{%.2f}^{%.2f}(%s)\,\mathrm{d}x=%.2f$" % ( interval[0], interval[1], interval[0], interval[1], latex(g(x)), @@ -155,7 +158,7 @@ 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$" % ( + text = r"$\int_{%.2f}^{%.2f}(\color{Red}{f(x)-g(x)})\,\mathrm{d}x=\int_{%.2f}^{%.2f}(%s)\,\mathrm{d}x=%.2f$" % ( interval[0], interval[1], interval[0], interval[1], latex(f(x)-g(x)), @@ -167,6 +170,7 @@ @library_interact def function_derivative( + title = text_control('

Derivative grapher

'), function = input_box(default="x^5-3*x^3+1", label="Function:"), x_range = range_slider(-15,15,0.1, default=(-2,2), label="Range (x)"), y_range = range_slider(-15,15,0.1, default=(-8,6), label="Range (y)")): @@ -201,6 +205,7 @@ @library_interact def difference_quotient( + title = text_control('

Difference quotient

'), f = input_box(default="sin(x)", label='f(x)'), interval= range_slider(0, 10, 0.1, default=(0.0,10.0), label="Range"), a = slider(0, 10, None, 5.5, label = 'a'), @@ -304,58 +309,6 @@ 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"), @@ -531,6 +484,7 @@ @library_interact def special_points( + title = text_control('

Special points in triangle

'), a0 = slider(0, 360, 1, 30, label="A"), a1 = slider(0, 360, 1, 180, label="B"), a2 = slider(0, 360, 1, 300, label="C"), @@ -714,7 +668,73 @@ @library_interact +def bisection_method( + title = text_control('

Bisection method

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

Secant method

'), f = input_box("x^2-2", label='f(x)'), interval = range_slider(-5,5,default=(0, 4), label="range"), d = slider(1, 16, 1, 3, label="10^-d precision"), @@ -728,7 +748,7 @@ - ``f`` -- function - ``interval`` -- range slider for the search interval - - ``slider`` -- slider for the precision (10^-d) + - ``d`` -- slider for the precision (10^-d) - ``maxn`` -- max number of iterations EXAMPLES:: @@ -752,24 +772,29 @@ 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) + if float(f(a)*f(b)) > 0: + print "f must have opposite sign at the endpoints of the interval" + show(plot(f, a, b, color='red'), xmin=a, xmax=b) + else: + c, intervals = _secant_method(f, float(a), float(b), maxn, h) + html(r"$\text{Precision }h = 10^{-d}=10^{-%s}=%.5f$"%(d, float(h))) + html(r"${c = }%s$"%latex(c)) + html(r"${f(c) = }%s"%latex(f(c))) + html(r"$%s \text{ iterations}"%len(intervals)) + P = plot(f, a, b, color='red') + k = (P.ymax() - P.ymin())/ (1.5*len(intervals)) + L = sum(line([(c,k*i), (d,k*i)]) for i, (c,d) in enumerate(intervals) ) + L += sum(line([(c,k*i-k/4), (c,k*i+k/4)]) for i, (c,d) in enumerate(intervals) ) + L += sum(line([(d,k*i-k/4), (d,k*i+k/4)]) for i, (c,d) in enumerate(intervals) ) + S = sum(line([(c,f(c)), (d,f(d)), (d-(d-c)*f(d)/(f(d)-f(c)), 0)], color="green") for (c,d) in intervals) + show(P + L + S, xmin=a, xmax=b) @library_interact def newton_method( + title = text_control('

Newton method

'), f = input_box("x^2 - 2"), c = slider(-10,10, default=6, label='Start (x)'), - hh = slider(-16, -1, 1, -3, label="Precision 2h"), + d = slider(1, 16, 1, 3, label="10^-d precision"), maxn = slider(0, 15, 1, 10, label="max iterations"), interval = range_slider(-10,10, default = (0,6), label="Interval"), list_steps = checkbox(default=False, label="List steps")): @@ -782,9 +807,9 @@ - ``f`` -- function - ``c`` -- starting position (x) + - ``d`` -- slider for the precision (10^-d) + - ``maxn`` -- max number of iterations - ``interval`` -- range slider for the search interval - - ``slider`` -- slider for the precision (10^-d) - - ``maxn`` -- max number of iterations - ``list_steps`` -- checkbox, if true shows the steps numerically EXAMPLES:: @@ -806,19 +831,17 @@ x = SR.var('x') f = symbolic_expression(f).function(x) a, b = interval - h = 10**hh + h = 10**(-d) 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)) + html(r"$\text{Precision } 2h = %s$"%latex(float(h))) + html(r"${c = }%s$"%c) + html(r"${f(c) = }%s"%latex(f(c))) + html(r"$%s \text{ iterations}"%len(midpoints)) if list_steps: - s = "

" - s += "" + s = [["$n$","$x_n$","$f(x_n)$", "$f(x_n-h)\,f(x_n+h)$"]] 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) + s.append([i+1, c, f(c), (c-h)*f(c+h)]) + html.table(s,header=True) else: P = plot(f, x, interval, color="blue") L = sum(line([(c, 0), (c, f(c))], color="green") for c in midpoints[:-1]) @@ -828,9 +851,13 @@ @library_interact def trapezoid_integration( - f = input_box(default = "x^2-5*x + 10", label='f(x)'), + title = text_control('

Trapeziod integration

'), + f = input_box(default = "x^2-5*x + 10", label='$f(x)=$'), n = slider(1,100,1,5, label='# divisions'), - interval = range_slider(-10,10,default=(0,8), label="Integral interval") + interval_input = selector(['from slider','from keyboard'], label='Integration interval', buttons=True), + interval_s = range_slider(-10,10,default=(0,8), label="slider: "), + interval_g = input_grid(1,2,default=[[0,8]], label="keyboard: "), + output_form = selector(['traditional','table','none'], label='Computations form', buttons=True) ): """ Interact explaining the trapezoid method for definite integrals, based on work by @@ -841,7 +868,10 @@ - ``f`` -- function of variable x to integrate - ``n`` -- number of divisions - - ``interval`` -- interval to integrate + - ``interval_input`` -- swithes the input for interval between slider and keyboard + - ``interval_s`` -- slider for interval to integrate + - ``interval_g`` -- input grid for interval to integrate + - ``output_form`` -- the computation is formatted in a traditional form, in a table or missing EXAMPLES:: @@ -850,7 +880,11 @@ """ xs = [] ys = [] - h = (interval[1]-interval[0])/n + if interval_input == 'from slider': + interval = interval_s + else: + interval = interval_g[0] + h = float(interval[1]-interval[0])/n x = SR.var('x') f = symbolic_expression(f).function(x) @@ -865,54 +899,68 @@ xs.append(xi + h) ys.append(f(xi + h)) + html(r'Function $f(x)=%s$'%latex(f(x))) show(plot(f, interval[0], interval[1]) + trapezoids, xmin = interval[0], xmax = interval[1]) numeric_value = integral_numerical(f, interval[0], interval[1])[0] approx = h *(ys[0]/2 + sum([ys[i] for i in range(1,n)]) + ys[n]/2) - - 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) - )) + html(r'$\displaystyle\int_{%.2f}^{%.2f} {f(x) \, \mathrm{d}x} = %.6f$'%( + interval[0], interval[1], N(numeric_value, digits=7)) + ) + if output_form == 'traditional': + sum_formula_html = r"\frac {d}{2} \cdot \left[f(x_0) + %s + f(x_{%s})\right]" % ( + ' + '.join([ "2 f(x_{%s})"%i for i in range(1,n)]), + n + ) + sum_placement_html = r"\frac{%.2f}{2} \cdot \left[f(%.2f) + %s + f(%.2f)\right]" % ( + h, + N(xs[0], digits=5), + ' + '.join([ "2 f(%.2f)" %N(i, digits=5) for i in xs[1:-1]]), + N(xs[n], digits=5) + ) + sum_values_html = r"\frac{%.2f}{2} \cdot \left[%.2f + %s + %.2f\right]" % ( + h, + N(ys[0], digits=5), + ' + '.join([ "2\cdot %.2f" % N(i, digits=5) for i in ys[1:-1]]), + N(ys[n], digits=5) + ) + + html(r''' +
+ \begin{align*} + \int_{%.2f}^{%.2f} {f(x) \, \mathrm{d}x} + & \approx %s \\ + & = %s \\ + & = %s \\ + & = %s + \end{align*} +
+ ''' % ( + interval[0], interval[1], + sum_formula_html, sum_placement_html, sum_values_html, + N(approx, digits=7) + )) + elif output_form == 'table': + s = [['$i$','$x_i$','$f(x_i)$','$m$','$m\cdot f(x_i)$']] + for i in range(0,n+1): + if i==0 or i==n: + j = 1 + else: + j = 2 + s.append([i, xs[i], ys[i],j,N(j*ys[i])]) + html.table(s,header=True) @library_interact def simpson_integration( - 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")): + title = text_control('

Simpson integration

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

Riemann integral

'), + f = input_box("x^2+1", label = "$f(x)=$", width=40), + n = slider(1,30,1,5, label='# divisions'), + hr1 = text_control('
'), + interval_input = selector(['from slider','from keyboard'], label='Integration interval', buttons=True), + interval_s = range_slider(-5,10,default=(0,2), label="slider: "), + interval_g = input_grid(1,2,default=[[0,2]], label="keyboard: "), + hr2 = text_control('
'), + list_table = checkbox(default=False, label="List table"), + auto_update = False): + """ + Interact explaining the definition of Riemann integral - 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) - )) + INPUT: + + - ``f`` -- function of variable x to integrate + - ``n`` -- number of divisions + - ``interval_input`` -- swithes the input for interval between slider and keyboard + - ``interval_s`` -- slider for interval to integrate + - ``interval_g`` -- input grid for interval to integrate + - ``list_table`` -- print table with values of the function + + EXAMPLES:: + + sage: interacts.calculus.riemann_sum() + ... + + AUTHORS: + + - Robert Marik (08-2010) + """ + x = SR.var('x') + from random import random + if interval_input == 'from slider': + a = interval_s[0] + b = interval_s[1] + else: + a = interval_g[0][0] + b = interval_g[0][1] + func = symbolic_expression(f).function(x) + division = [a]+[a+random()*(b-a) for i in range(n-1)]+[b] + division = [i for i in division] + division.sort() + xs = [division[i]+random()*(division[i+1]-division[i]) for i in range(n)] + ys = [func(x_val) for x_val in xs] + rects = Graphics() + for i in range(n): + body=[[division[i],0],[division[i],ys[i]],[division[i+1],ys[i]],[division[i+1],0]] + if ys[i].n()>0: + color_rect='green' + else: + color_rect='red' + rects = rects +polygon2d(body, rgbcolor = color_rect,alpha=0.1)\ + + point((xs[i],ys[i]), rgbcolor = (1,0,0))\ + + line(body,rgbcolor='black',zorder=-1) + html('Adjust your data and click Update button. Click repeatedly for another random values.') + + show(plot(func(x),(x,a,b),zorder=5) + rects) + delka_intervalu=[division[i+1]-division[i] for i in range(n)] + if list_table: + html.table([["$i$","$[x_{i-1},x_i]$","$\eta_i$","$f(\eta_i)$","$x_{i}-x_{i-1}$"]]\ + +[[i+1,[division[i],division[i+1]],xs[i],ys[i],delka_intervalu[i]] for i in range(n)],\ + header=True) + + html('Riemann sum: $\displaystyle\sum_{i=1}^{%s} f(\eta_i)(x_i-x_{i-1})=%s$ '% + (latex(n),latex(sum([ys[i]*delka_intervalu[i] for i in range(n)])))) + html('Exact value of the integral $\displaystyle\int_{%s}^{%s}%s\,\mathrm{d}x=%s$'% + (latex(a),latex(b),latex(func(x)),latex(integral_numerical(func(x),a,b)[0]))) + x = SR.var('x') @library_interact @@ -1044,10 +1185,10 @@ lbl = 'f' elif action == 'df/dx': h = f.derivative(x) - lbl = r'\frac{df}{dx}' + lbl = r'\frac{\mathrm{d}f}{\mathrm{d}x}' elif action == 'int f': h = f.integrate(x) - lbl = r'\int f dx' + lbl = r'\int f \,\mathrm{d}x' elif action == 'num f': h = f.numerator() lbl = r'\text{numer(f)}'