eoc7 just finished LHopitalExample, but might redo a lot

This commit is contained in:
Grant Sanderson
2017-03-27 18:50:01 -07:00
parent 7fca1dac6b
commit 6387d5ee02
2 changed files with 369 additions and 38 deletions

View File

@ -75,7 +75,7 @@ class Write(ShowCreation):
if "run_time" not in kwargs:
self.establish_run_time(mobject)
if "lag_factor" not in kwargs:
min_lag_factor = min(len(mobject)/2.0, 2)
min_lag_factor = min(len(mobject.family_members_with_points())/2.0, 2)
self.lag_factor = max(self.run_time - 1, min_lag_factor)
ShowCreation.__init__(self, mobject, **kwargs)
@ -185,6 +185,9 @@ class ApplyWave(Homotopy):
"direction" : DOWN,
"amplitude" : 0.2,
"run_time" : 1,
"apply_function_kwargs" : {
"maintain_smoothness" : False,
},
}
def __init__(self, mobject, **kwargs):
digest_config(self, kwargs, locals())

View File

@ -763,7 +763,7 @@ class OtherViewsOfDx(TeacherStudentsScene):
])
)
self.dither(3)
class GraphLimitExpression(GraphScene):
CONFIG = {
"start_x" : 2,
@ -1799,7 +1799,7 @@ class TheoryHeavy(TeacherStudentsScene):
self.play(self.get_teacher().change_mode, "happy")
self.dither(2)
class LHopitalExample(LimitCounterExample):
class LHopitalExample(LimitCounterExample, PiCreatureScene):
CONFIG = {
"graph_origin" : ORIGIN,
"x_axis_width" : 2*SPACE_WIDTH,
@ -1808,26 +1808,27 @@ class LHopitalExample(LimitCounterExample):
"x_labeled_nums" : range(-6, 8, 2),
"x_axis_label" : "$x$",
"y_axis_height" : 2*SPACE_HEIGHT,
"y_min" : -3,
"y_max" : 3,
"y_min" : -3.1,
"y_max" : 3.1,
"y_bottom_tick" : -4,
"y_labeled_nums" : range(-2, 4, 2),
"y_axis_label" : "",
"x_color" : RED,
"hole_radius" : 0.07,
"big_delta" : 0.5,
"small_delta" : 0.01,
"dx" : 0.2,
"dx_color" : YELLOW,
"tex_scale_value" : 0.9,
}
def construct(self):
self.force_skipping()
self.remove(*self.get_pi_creatures())
self.setup_axes()
self.introduce_function()
self.show_non_definedness_at_one()
self.plug_in_value_close_to_one()
self.ask_about_systematic_process()
self.mention_derivatives_as_helpful()
self.nudge_by_dx()
self.show_altered_numerator_and_denominator()
def setup_axes(self):
GraphScene.setup_axes(self)
@ -1865,26 +1866,32 @@ class LHopitalExample(LimitCounterExample):
self.func_label = func_label
def show_non_definedness_at_one(self):
morty = Mortimer().flip().to_corner(DOWN+LEFT)
morty = self.get_primary_pi_creature()
words = TexMobject("\\text{Try }", "x", "=1")
words.highlight_by_tex("x", self.x_color, substring = False)
v_line = self.get_vertical_line_to_graph(
1, self.graph,
line_class = DashedLine,
color = self.x_color
v_line, alt_v_line = [
self.get_vertical_line_to_graph(
x, self.graph,
line_class = DashedLine,
color = self.x_color
)
for x in 1, -1
]
hole, alt_hole = [
self.get_hole(x, self.func(x))
for x in 1, -1
]
ed_group = self.get_epsilon_delta_group(
self.big_delta, limit_x = 1,
)
func_1 = self.get_func_label("1")
func_1.next_to(self.func_label, DOWN, buff = MED_LARGE_BUFF)
rhs = TexMobject("= \\frac{0}{0}")
rhs = TexMobject("\\Rightarrow \\frac{0}{0}")
rhs.next_to(func_1, RIGHT)
func_1_group = VGroup(func_1, rhs)
hole = self.get_hole(1, self.func(1))
ed_group = self.get_epsilon_delta_group(
self.big_delta, limit_x = 1,
)
func_1_group.add_to_back(BackgroundRectangle(func_1_group))
lim = TexMobject("\\lim", "_{x", "\\to 1}")
lim.highlight_by_tex("x", self.x_color)
@ -1894,6 +1901,7 @@ class LHopitalExample(LimitCounterExample):
equals_q = TexMobject("= ???")
equals_q.next_to(self.func_label.target, RIGHT)
self.play(FadeIn(morty))
self.play(PiCreatureSays(morty, words))
self.play(
Blink(morty),
@ -1914,10 +1922,15 @@ class LHopitalExample(LimitCounterExample):
self.dither()
self.play(Write(rhs[-1]))
self.dither()
self.play(
GrowFromCenter(hole),
morty.look_at, hole
)
self.play(GrowFromCenter(hole))
self.dither()
self.play(ShowCreation(alt_v_line))
self.play(GrowFromCenter(alt_hole))
self.dither()
alt_group = VGroup(alt_v_line, alt_hole)
self.play(alt_group.set_stroke, GREY, 2)
self.play(FocusOn(hole))
self.dither()
self.play(GrowFromCenter(ed_group.input_range))
@ -1934,7 +1947,7 @@ class LHopitalExample(LimitCounterExample):
ed_group, target_delta = self.small_delta,
run_time = 4
)
self.play(Blink(morty))
self.dither()
self.play(
Write(lim),
MoveToTarget(self.func_label),
@ -1944,29 +1957,295 @@ class LHopitalExample(LimitCounterExample):
)
self.dither(2)
self.play(
func_1_group.to_corner, DOWN+RIGHT,
func_1_group.to_corner, UP+LEFT,
*map(FadeOut, [morty, ed_group])
)
self.dither()
self.lim_group = VGroup(lim, self.func_label, equals_q)
for part in self.lim_group:
part.add_to_back(BackgroundRectangle(part))
self.func_1_group = func_1_group
self.v_line = v_line
def plug_in_value_close_to_one(self):
self.revert_to_original_skipping_status()
pass
num = 1.00001
result = self.func(num)
label = self.get_func_label(num)
rhs = TexMobject("= %.4f\\dots"%result)
rhs.next_to(label, RIGHT)
approx_group = VGroup(label, rhs)
approx_group.scale_to_fit_width(SPACE_WIDTH-2*MED_LARGE_BUFF)
approx_group.next_to(ORIGIN, UP, buff = MED_LARGE_BUFF)
approx_group.to_edge(RIGHT)
self.play(ReplacementTransform(
self.func_label.copy(),
label
))
self.dither()
self.play(Write(rhs))
self.dither()
self.approx_group = approx_group
def ask_about_systematic_process(self):
pass
morty = self.pi_creature
morty.change_mode("plain")
def mention_derivatives_as_helpful(self):
pass
self.func_1_group.save_state()
self.play(
FadeIn(morty),
FadeOut(VGroup(
*self.x_axis.numbers[:len(self.x_axis.numbers)/2]
))
)
self.pi_creature_says(
morty, "Is there a \\\\ better way?",
bubble_kwargs = {
"height" : 3,
"width" : 4,
},
)
self.dither(2)
self.play(
RemovePiCreatureBubble(
morty, target_mode = "raise_left_hand",
look_at_arg = self.func_1_group
),
self.func_1_group.scale, self.tex_scale_value,
self.func_1_group.move_to,
morty.get_corner(UP+LEFT), DOWN+LEFT,
self.func_1_group.shift, MED_LARGE_BUFF*UP,
)
self.dither(2)
self.play(
morty.change_mode, "raise_right_hand",
morty.look, UP+RIGHT,
FadeOut(self.approx_group),
self.func_1_group.restore,
self.lim_group.next_to,
morty.get_corner(UP+RIGHT), RIGHT,
)
self.dither(2)
self.play(
self.lim_group.scale, self.tex_scale_value,
self.lim_group.next_to, ORIGIN, UP,
self.lim_group.to_edge, LEFT,
morty.change_mode, "plain"
)
self.dither()
self.play(FadeOut(morty))
def nudge_by_dx(self):
pass
nudged_v_line = self.get_vertical_line_to_graph(
x = 1 + self.dx,
graph = self.graph,
line_class = DashedLine,
color = RED
)
brace = Brace(
VGroup(self.v_line, nudged_v_line),
direction = UP,
min_num_quads = 1,
)
dx_label = brace.get_text("$dx$")
dx_label.highlight(self.dx_color)
def show_altered_numerator_and_denominator(self):
pass
rect, func_1, to_zero_over_zero = self.func_1_group
to, zero1, over, zero2 = to_zero_over_zero
self.remove(rect)
func_1_plus_dx = self.get_func_label(
"(1 + dx)"
)
lhs_ones = []
for part in func_1_plus_dx.get_parts_by_tex("(1 + dx)"):
VGroup(part[0], part[2], part[5]).highlight(WHITE)
VGroup(*part[3:5]).highlight(self.dx_color)
lhs_ones.append(part[1])
func_1_plus_dx.move_to(func_1, LEFT)
nudged_rhs = TexMobject(
"{0", "+ d\\big(\\sin(\\pi ", "x", ")\\big)",
"\\over \\,",
"0", "+ d\\big(", "x", "^2 - 1\\big)}"
)
d_sine = VGroup(*nudged_rhs[1:4])
d_denom = VGroup(*nudged_rhs[-3:])
nudged_rhs.highlight_by_tex("x", self.x_color)
nudged_rhs.scale(self.tex_scale_value)
nudged_rhs.next_to(
func_1_plus_dx, RIGHT,
buff = to.get_width()+MED_LARGE_BUFF
)
nudged_rhs_rect = BackgroundRectangle(
nudged_rhs, fill_opacity = 1
)
approx = TexMobject("\\approx")
approx.next_to(nudged_rhs, RIGHT)
d_over_d = TexMobject(
"{\\cos(\\pi", "x", ")", "\\pi", "\\, dx",
"\\over\\,",
"2\\,", "x", "\\, dx}"
)
d_over_d.scale(self.tex_scale_value)
cos_dx = VGroup(*d_over_d[:5])
two_x_dx = VGroup(*d_over_d[-3:])
d_over_d.highlight_by_tex("x", self.x_color)
d_over_d.highlight_by_tex("dx", self.dx_color)
d_over_d.next_to(approx, RIGHT)
rhs_ones = []
rhs_xs = d_over_d.get_parts_by_tex("x", substring = False)
for x in rhs_xs:
one = TexMobject("\\cdot \\! 1")
one.highlight(self.x_color)
one.scale(self.tex_scale_value)
one.move_to(x, DOWN+LEFT)
rhs_ones.append(one)
final_rhs = TexMobject("=", "\\frac{-\\pi}{2}")
final_rhs.scale(self.tex_scale_value)
final_rhs.next_to(d_over_d, RIGHT)
def replace_x_by_one(index):
self.play(FocusOn(lhs_ones[index]))
self.play(
Transform(
lhs_ones[index].copy(),
rhs_ones[index],
path_arc = np.pi/2,
run_time = 2,
remover = True
),
Transform(
rhs_xs[index],
rhs_ones[index],
run_time = 2,
rate_func = squish_rate_func(smooth, 0.5, 1)
)
)
def get_brace_shrink_anims():
return [
Transform(nudged_v_line, self.v_line),
brace.stretch_to_fit_width, 0.01,
brace.next_to, self.v_line, UP, SMALL_BUFF,
MaintainPositionRelativeTo(dx_label, brace),
]
self.play(Indicate(self.v_line))
self.play(ReplacementTransform(
self.v_line.copy(),
nudged_v_line
))
self.play(GrowFromCenter(brace))
self.play(Write(dx_label))
self.dither()
self.play(FocusOn(func_1))
self.play(Indicate(func_1))
self.play(
ReplacementTransform(func_1, func_1_plus_dx),
to_zero_over_zero.next_to, func_1_plus_dx, RIGHT
)
self.dither()
self.play(
FadeIn(nudged_rhs_rect),
ReplacementTransform(
over, nudged_rhs.get_part_by_tex("over")
),
Write(d_sine),
*[
ReplacementTransform(VGroup(zero), part)
for zero, part in zip(
[zero1, zero2],
nudged_rhs.get_parts_by_tex("0")
)
]
)
self.dither()
self.play(Write(d_denom))
self.dither()
#Bring in d_over_d
self.play(
Write(approx),
ReplacementTransform(
nudged_rhs.get_part_by_tex("over").copy(),
d_over_d.get_part_by_tex("over")
),
ReplacementTransform(d_sine.copy(), cos_dx)
)
replace_x_by_one(0)
self.dither(2)
##Emphasize meaning of approximation
cosine = VGroup(*cos_dx[:-1])
d_sine_ghost, cosine_ghost = [
mob.copy().set_fill(opacity = 0.2)
for mob in d_sine, cosine
]
self.play(Indicate(d_sine))
self.play(Transform(
d_sine_ghost, cosine_ghost,
run_time = 2,
remover = True,
))
self.play(Indicate(cosine))
self.dither()
self.play(*[
ApplyWave(mob, direction = UP, amplitude = 0.1)
for mob in [
d_over_d.get_part_by_tex("dx"),
dx_label
]
])
self.play(
*get_brace_shrink_anims(),
rate_func = there_and_back,
run_time = 5
)
self.dither()
self.play(ReplacementTransform(d_denom.copy(), two_x_dx))
self.dither()
replace_x_by_one(1)
self.dither()
#Cancel out dx's
dxs = VGroup(*d_over_d.get_parts_by_tex("dx"))
circles = VGroup(*[
Circle(color = GREEN).replace(dx).scale_in_place(1.3)
for dx in dxs
])
self.play(ShowCreation(circles, run_time = 2))
self.dither(2)
self.play(*map(FadeOut, [circles, dxs]))
self.dither(2)
#Write final answer
final_ratio = final_rhs.get_part_by_tex("pi").copy()
final_ratio.add_to_back(BackgroundRectangle(final_ratio))
left_brace = Brace(self.v_line, LEFT)
self.play(Write(final_rhs))
self.play(
*get_brace_shrink_anims(),
run_time = 3
)
self.play(GrowFromCenter(left_brace))
self.play(
final_ratio.next_to, left_brace, LEFT, SMALL_BUFF
)
self.dither(2)
##
def create_pi_creature(self):
self.pi_creature = Mortimer().flip().to_corner(DOWN+LEFT)
return self.pi_creature
def func(self, x):
if abs(x) != 1:
return np.sin(x*np.pi) / (x**2 - 1)
@ -2000,9 +2279,58 @@ class LHopitalExample(LimitCounterExample):
))
return ed_group
class DerivativeLimitReciprocity(Scene):
def construct(self):
arrow = Arrow(LEFT, RIGHT, color = WHITE)
lim = TexMobject("\\lim", "_{h", "\\to 0}")
lim.highlight_by_tex("h", GREEN)
lim.next_to(arrow, LEFT)
deriv = TexMobject("{df", "\\over\\,", "dx}")
deriv.highlight_by_tex("dx", GREEN)
deriv.highlight_by_tex("df", YELLOW)
deriv.next_to(arrow, RIGHT)
self.play(FadeIn(lim, submobject_mode = "lagged_start"))
self.play(ShowCreation(arrow))
self.play(FadeIn(deriv, submobject_mode = "lagged_start"))
self.dither()
self.play(Rotate(arrow, np.pi, run_time = 2))
self.dither()
class NameLHopitalsRule(Scene):
def construct(self):
condition = TexMobject(
"{f", "(", "a", ")",
"\\over\\,",
"g", "(", "a", ")}",
"\\Rightarrow",
"{\\,0\\,", "\\over\\,", "0\\,}"
)
condition.to_edge(UP)
lim = TexMobject(
"\\lim_", "{x", " \\to", "a}",
"{f", "(", "x", ")",
"\\over\\,",
"g", "(", "x", ")}",
)
rhs = TexMobject(
"=",
"{ \\dfrac{df}{dx}", "(", "a", ")"
"\\over\\,",
"\\dfrac{dg}{dx}", "(", "a", ")}"
)
rhs.next_to(lim, RIGHT)
rule = VGroup(lim, rhs)
rule.center()
for tex_mob in condition, lim, rhs:
tex_mob.highlight_by_tex("f", BLUE)
tex_mob.highlight_by_tex("g", GREEN)
tex_mob.highlight_by_tex("a", RED, substring = False)
tex_mob.highlight_by_tex("a}", RED)
tex_mob.highlight_by_tex("arrow", WHITE)
self.add(condition, rule)