3b1b-manim/old_projects/eoc/chapter6.py

2728 lines
82 KiB
Python
Raw Normal View History

from big_ol_pile_of_manim_imports import *
2017-03-22 15:06:17 -07:00
SPACE_UNIT_TO_PLANE_UNIT = 0.75
class Chapter6OpeningQuote(OpeningQuote):
CONFIG = {
"quote" : [
"Do not ask whether a ",
"statement is true until",
"you know what it means."
],
"author" : "Errett Bishop"
}
class ThisWasConfusing(TeacherStudentsScene):
def construct(self):
words = TextMobject("Implicit differentiation")
words.move_to(self.get_teacher().get_corner(UP+LEFT), DOWN+RIGHT)
words.set_fill(opacity = 0)
self.play(
self.get_teacher().change_mode, "raise_right_hand",
words.set_fill, None, 1,
words.shift, 0.5*UP
)
self.change_student_modes(
*["confused"]*3,
look_at_arg = words,
added_anims = [Animation(self.get_teacher())]
)
2018-01-15 19:15:05 -08:00
self.wait()
2017-03-22 15:06:17 -07:00
self.play(
self.get_teacher().change_mode, "confused",
self.get_teacher().look_at, words,
)
2018-01-15 19:15:05 -08:00
self.wait(3)
2017-03-22 15:06:17 -07:00
class SlopeOfCircleExample(ZoomedScene):
CONFIG = {
"plane_kwargs" : {
"x_radius" : FRAME_X_RADIUS/SPACE_UNIT_TO_PLANE_UNIT,
"y_radius" : FRAME_Y_RADIUS/SPACE_UNIT_TO_PLANE_UNIT,
2017-03-22 15:06:17 -07:00
"space_unit_to_x_unit" : SPACE_UNIT_TO_PLANE_UNIT,
"space_unit_to_y_unit" : SPACE_UNIT_TO_PLANE_UNIT,
},
"example_point" : (3, 4),
"circle_radius" : 5,
"circle_color" : YELLOW,
"example_color" : MAROON_B,
"zoom_factor" : 20,
"zoomed_canvas_corner" : UP+LEFT,
"zoomed_canvas_corner_buff" : MED_SMALL_BUFF,
}
def construct(self):
self.setup_plane()
self.introduce_circle()
self.talk_through_pythagorean_theorem()
self.draw_example_slope()
self.show_perpendicular_radius()
self.show_dx_and_dy()
self.write_slope_as_dy_dx()
self.point_out_this_is_not_a_graph()
self.perform_implicit_derivative()
self.show_final_slope()
def setup_plane(self):
self.plane = NumberPlane(**self.plane_kwargs)
self.plane.main_lines.fade()
self.plane.add(self.plane.get_axis_labels())
self.plane.add_coordinates()
self.add(self.plane)
def introduce_circle(self):
circle = Circle(
radius = self.circle_radius*SPACE_UNIT_TO_PLANE_UNIT,
color = self.circle_color,
)
equation = TexMobject("x^2 + y^2 = 5^2")
equation.add_background_rectangle()
equation.next_to(
circle.point_from_proportion(1./8),
UP+RIGHT
)
equation.to_edge(RIGHT)
self.play(ShowCreation(circle, run_time = 2))
self.play(Write(equation))
2018-01-15 19:15:05 -08:00
self.wait()
2017-03-22 15:06:17 -07:00
self.circle = circle
self.circle_equation = equation
def talk_through_pythagorean_theorem(self):
point = self.plane.num_pair_to_point(self.example_point)
x_axis_point = point[0]*RIGHT
dot = Dot(point, color = self.example_color)
x_line = Line(ORIGIN, x_axis_point, color = GREEN)
y_line = Line(x_axis_point, point, color = RED)
radial_line = Line(ORIGIN, point, color = self.example_color)
lines = VGroup(radial_line, x_line, y_line)
labels = VGroup()
self.play(ShowCreation(dot))
for line, tex in zip(lines, "5xy"):
label = TexMobject(tex)
2018-03-30 11:51:31 -07:00
label.set_color(line.get_color())
2017-03-22 15:06:17 -07:00
label.add_background_rectangle()
label.next_to(
line.get_center(),
rotate_vector(UP, line.get_angle()),
buff = SMALL_BUFF
)
self.play(
ShowCreation(line),
Write(label)
)
labels.add(label)
full_group = VGroup(dot, lines, labels)
start_angle = angle_of_vector(point)
end_angle = np.pi/12
spatial_radius = np.linalg.norm(point)
def update_full_group(group, alpha):
dot, lines, labels = group
angle = interpolate(start_angle, end_angle, alpha)
new_point = spatial_radius*rotate_vector(RIGHT, angle)
new_x_axis_point = new_point[0]*RIGHT
dot.move_to(new_point)
radial_line, x_line, y_line = lines
x_line.put_start_and_end_on(ORIGIN, new_x_axis_point)
y_line.put_start_and_end_on(new_x_axis_point, new_point)
radial_line.put_start_and_end_on(ORIGIN, new_point)
for line, label in zip(lines, labels):
label.next_to(
line.get_center(),
rotate_vector(UP, line.get_angle()),
buff = SMALL_BUFF
)
return group
self.play(UpdateFromAlphaFunc(
full_group, update_full_group,
rate_func = there_and_back,
run_time = 5,
))
2018-01-15 19:15:05 -08:00
self.wait(2)
2017-03-22 15:06:17 -07:00
#Move labels to equation
movers = labels.copy()
pairs = zip(
[movers[1], movers[2], movers[0]],
self.circle_equation[1][0:-1:3]
)
self.play(*[
ApplyMethod(m1.replace, m2)
for m1, m2 in pairs
])
2018-01-15 19:15:05 -08:00
self.wait()
2017-03-22 15:06:17 -07:00
self.play(*map(FadeOut, [lines, labels, movers]))
self.remove(full_group)
self.add(dot)
2018-01-15 19:15:05 -08:00
self.wait()
2017-03-22 15:06:17 -07:00
self.example_point_dot = dot
def draw_example_slope(self):
point = self.example_point_dot.get_center()
line = Line(ORIGIN, point)
2018-03-30 11:51:31 -07:00
line.set_color(self.example_color)
2017-03-22 15:06:17 -07:00
line.rotate(np.pi/2)
line.scale(2)
line.move_to(point)
word = TextMobject("Slope?")
word.next_to(line.get_start(), UP, aligned_edge = LEFT)
word.add_background_rectangle()
coords = TexMobject("(%d, %d)"%self.example_point)
coords.add_background_rectangle()
coords.scale(0.7)
coords.next_to(point, LEFT)
coords.shift(SMALL_BUFF*DOWN)
2018-03-30 11:51:31 -07:00
coords.set_color(self.example_color)
2017-03-22 15:06:17 -07:00
self.play(GrowFromCenter(line))
self.play(Write(word))
2018-01-15 19:15:05 -08:00
self.wait()
2017-03-22 15:06:17 -07:00
self.play(Write(coords))
2018-01-15 19:15:05 -08:00
self.wait()
2017-03-22 15:06:17 -07:00
self.tangent_line = line
self.slope_word = word
self.example_point_coords_mob = coords
def show_perpendicular_radius(self):
point = self.example_point_dot.get_center()
radial_line = Line(ORIGIN, point, color = RED)
perp_mark = VGroup(
Line(UP, UP+RIGHT),
Line(UP+RIGHT, RIGHT),
)
perp_mark.scale(0.2)
perp_mark.set_stroke(width = 2)
perp_mark.rotate(radial_line.get_angle()+np.pi)
perp_mark.shift(point)
self.play(ShowCreation(radial_line))
self.play(ShowCreation(perp_mark))
2018-01-15 19:15:05 -08:00
self.wait()
2017-03-22 15:06:17 -07:00
self.play(Indicate(perp_mark))
2018-01-15 19:15:05 -08:00
self.wait()
2017-03-22 15:06:17 -07:00
morty = Mortimer().flip().to_corner(DOWN+LEFT)
self.play(FadeIn(morty))
self.play(PiCreatureBubbleIntroduction(
morty, "Suppose you \\\\ don't know this.",
))
to_fade =self.get_mobjects_from_last_animation()
self.play(Blink(morty))
2018-01-15 19:15:05 -08:00
self.wait()
2017-03-22 15:06:17 -07:00
self.play(*map(FadeOut, to_fade))
self.play(*map(FadeOut, [radial_line, perp_mark]))
2018-01-15 19:15:05 -08:00
self.wait()
2017-03-22 15:06:17 -07:00
def show_dx_and_dy(self):
dot = self.example_point_dot
point = dot.get_center()
step_vect = rotate_vector(point, np.pi/2)
step_length = 1./self.zoom_factor
step_vect *= step_length/np.linalg.norm(step_vect)
step_line = Line(ORIGIN, LEFT)
2018-03-30 11:51:31 -07:00
step_line.set_color(WHITE)
2017-03-22 15:06:17 -07:00
brace = Brace(step_line, DOWN)
step_text = brace.get_text("Step", buff = SMALL_BUFF)
step_group = VGroup(step_line, brace, step_text)
step_group.rotate(angle_of_vector(point) - np.pi/2)
step_group.scale(1./self.zoom_factor)
step_group.shift(point)
interim_point = step_line.get_corner(UP+RIGHT)
dy_line = Line(point, interim_point)
dx_line = Line(interim_point, point+step_vect)
2018-03-30 11:51:31 -07:00
dy_line.set_color(RED)
dx_line.set_color(GREEN)
2017-03-22 15:06:17 -07:00
for line, tex in (dx_line, "dx"), (dy_line, "dy"):
label = TexMobject(tex)
label.scale(1./self.zoom_factor)
next_to_vect = np.round(
rotate_vector(DOWN, line.get_angle())
)
label.next_to(
line, next_to_vect,
buff = MED_SMALL_BUFF/self.zoom_factor
)
2018-03-30 11:51:31 -07:00
label.set_color(line.get_color())
2017-03-22 15:06:17 -07:00
line.label = label
self.activate_zooming()
self.little_rectangle.move_to(step_line.get_center())
self.little_rectangle.save_state()
self.little_rectangle.scale_in_place(self.zoom_factor)
2018-01-15 19:15:05 -08:00
self.wait()
2017-03-22 15:06:17 -07:00
self.play(
self.little_rectangle.restore,
dot.scale_in_place, 1./self.zoom_factor,
run_time = 2
)
2018-01-15 19:15:05 -08:00
self.wait()
2017-03-22 15:06:17 -07:00
self.play(ShowCreation(step_line))
self.play(GrowFromCenter(brace))
self.play(Write(step_text))
2018-01-15 19:15:05 -08:00
self.wait()
2017-03-22 15:06:17 -07:00
for line in dy_line, dx_line:
self.play(ShowCreation(line))
self.play(Write(line.label))
2018-01-15 19:15:05 -08:00
self.wait()
self.wait()
2017-03-22 15:06:17 -07:00
self.step_group = step_group
self.dx_line = dx_line
self.dy_line = dy_line
def write_slope_as_dy_dx(self):
slope_word = self.slope_word
new_slope_word = TextMobject("Slope =")
new_slope_word.add_background_rectangle()
new_slope_word.next_to(ORIGIN, RIGHT)
new_slope_word.shift(slope_word.get_center()[1]*UP)
dy_dx = TexMobject("\\frac{dy}{dx}")
2018-03-30 11:51:31 -07:00
VGroup(*dy_dx[:2]).set_color(RED)
VGroup(*dy_dx[-2:]).set_color(GREEN)
2017-03-22 15:06:17 -07:00
dy_dx.next_to(new_slope_word, RIGHT)
dy_dx.add_background_rectangle()
self.play(Transform(slope_word, new_slope_word))
self.play(Write(dy_dx))
2018-01-15 19:15:05 -08:00
self.wait()
2017-03-22 15:06:17 -07:00
self.dy_dx = dy_dx
def point_out_this_is_not_a_graph(self):
equation = self.circle_equation
x = equation[1][0]
y = equation[1][3]
brace = Brace(equation, DOWN)
brace_text = brace.get_text(
"Not $y = f(x)$",
buff = SMALL_BUFF
)
2018-03-30 11:51:31 -07:00
brace_text.set_color(RED)
2017-03-22 15:06:17 -07:00
alt_brace_text = brace.get_text("Implicit curve")
for text in brace_text, alt_brace_text:
text.add_background_rectangle()
text.to_edge(RIGHT, buff = MED_SMALL_BUFF)
new_circle = self.circle.copy()
2018-03-30 11:51:31 -07:00
new_circle.set_color(BLUE)
2017-03-22 15:06:17 -07:00
self.play(
GrowFromCenter(brace),
Write(brace_text)
)
2018-01-15 19:15:05 -08:00
self.wait()
2017-03-22 15:06:17 -07:00
self.play(Indicate(x))
2018-01-15 19:15:05 -08:00
self.wait()
2017-03-22 15:06:17 -07:00
self.play(Indicate(y))
2018-01-15 19:15:05 -08:00
self.wait()
2017-03-22 15:06:17 -07:00
self.play(Transform(brace_text, alt_brace_text))
2018-01-15 19:15:05 -08:00
self.wait()
2017-03-22 15:06:17 -07:00
self.play(
ShowCreation(new_circle, run_time = 2),
Animation(brace_text)
)
self.play(new_circle.set_stroke, None, 0)
2018-01-15 19:15:05 -08:00
self.wait()
2017-03-22 15:06:17 -07:00
self.play(*map(FadeOut, [brace, brace_text]))
2018-01-15 19:15:05 -08:00
self.wait()
2017-03-22 15:06:17 -07:00
def perform_implicit_derivative(self):
equation = self.circle_equation
morty = Mortimer()
morty.flip()
morty.next_to(ORIGIN, LEFT)
morty.to_edge(DOWN, buff = SMALL_BUFF)
q_marks = TexMobject("???")
q_marks.next_to(morty, UP)
rect = Rectangle(
width = FRAME_X_RADIUS - SMALL_BUFF,
height = FRAME_Y_RADIUS - SMALL_BUFF,
2017-03-22 15:06:17 -07:00
stroke_width = 0,
fill_color = BLACK,
fill_opacity = 0.8,
)
rect.to_corner(DOWN+RIGHT, buff = 0)
derivative = TexMobject("2x\\,dx + 2y\\,dy = 0")
dx = VGroup(*derivative[2:4])
dy = VGroup(*derivative[7:9])
2018-03-30 11:51:31 -07:00
dx.set_color(GREEN)
dy.set_color(RED)
2017-03-22 15:06:17 -07:00
self.play(
FadeIn(rect),
FadeIn(morty),
equation.next_to, ORIGIN, DOWN, MED_LARGE_BUFF,
equation.shift, FRAME_X_RADIUS*RIGHT/2,
2017-03-22 15:06:17 -07:00
)
self.play(
morty.change_mode, "confused",
morty.look_at, equation
)
self.play(Blink(morty))
derivative.next_to(equation, DOWN)
derivative.shift(
equation[1][-3].get_center()[0]*RIGHT - \
derivative[-2].get_center()[0]*RIGHT
)
#Differentiate
self.play(
morty.look_at, derivative[0],
*[
ReplacementTransform(
equation[1][i].copy(),
derivative[j],
)
for i, j in (1, 0), (0, 1)
]
)
self.play(Write(dx, run_time = 1))
2018-01-15 19:15:05 -08:00
self.wait()
2017-03-22 15:06:17 -07:00
self.play(*[
ReplacementTransform(
equation[1][i].copy(),
derivative[j],
)
for i, j in (2, 4), (3, 6), (4, 5)
])
self.play(Write(dy, run_time = 1))
self.play(Blink(morty))
self.play(*[
ReplacementTransform(
equation[1][i].copy(),
derivative[j],
)
for i, j in (-3, -2), (-2, -1), (-1, -1)
])
2018-01-15 19:15:05 -08:00
self.wait()
2017-03-22 15:06:17 -07:00
#React
self.play(morty.change_mode, "erm")
self.play(Blink(morty))
self.play(Write(q_marks))
2018-01-15 19:15:05 -08:00
self.wait()
2017-03-22 15:06:17 -07:00
self.play(Indicate(dx), morty.look_at, dx)
self.play(Indicate(dy), morty.look_at, dy)
2018-01-15 19:15:05 -08:00
self.wait()
2017-03-22 15:06:17 -07:00
self.play(
morty.change_mode, "shruggie",
FadeOut(q_marks)
)
self.play(Blink(morty))
self.play(
morty.change_mode, "pondering",
morty.look_at, derivative,
)
#Rearrange
x, y, eq = np.array(derivative)[[1, 6, 9]]
final_form = TexMobject(
"\\frac{dy}{dx} = \\frac{-x}{y}"
)
new_dy = VGroup(*final_form[:2])
new_dx = VGroup(*final_form[3:5])
2018-03-30 11:51:31 -07:00
new_dy.set_color(dy.get_color())
new_dx.set_color(dx.get_color())
2017-03-22 15:06:17 -07:00
new_dy.add(final_form[2])
new_x = VGroup(*final_form[6:8])
new_y = VGroup(*final_form[8:10])
new_eq = final_form[5]
final_form.next_to(derivative, DOWN)
final_form.shift((eq.get_center()[0]-new_eq.get_center()[0])*RIGHT)
self.play(*[
ReplacementTransform(
mover.copy(), target,
run_time = 2,
path_arc = np.pi/2,
)
for mover, target in [
(dy, new_dy),
(dx, new_dx),
(eq, new_eq),
(x, new_x),
(y, new_y)
]
] + [
morty.look_at, final_form
])
2018-01-15 19:15:05 -08:00
self.wait(2)
2017-03-22 15:06:17 -07:00
self.morty = morty
self.neg_x_over_y = VGroup(*final_form[6:])
def show_final_slope(self):
morty = self.morty
dy_dx = self.dy_dx
coords = self.example_point_coords_mob
x, y = coords[1][1].copy(), coords[1][3].copy()
frac = self.neg_x_over_y.copy()
frac.generate_target()
eq = TexMobject("=")
eq.add_background_rectangle()
eq.next_to(dy_dx, RIGHT)
frac.target.next_to(eq, RIGHT)
frac.target.shift(SMALL_BUFF*DOWN)
rect = BackgroundRectangle(frac.target)
self.play(
FadeIn(rect),
MoveToTarget(frac),
Write(eq),
morty.look_at, rect,
run_time = 2,
)
2018-01-15 19:15:05 -08:00
self.wait()
2017-03-22 15:06:17 -07:00
self.play(FocusOn(coords), morty.look_at, coords)
self.play(Indicate(coords))
scale_factor = 1.4
self.play(
x.scale, scale_factor,
2018-03-30 11:51:31 -07:00
x.set_color, GREEN,
2017-03-22 15:06:17 -07:00
x.move_to, frac[1],
FadeOut(frac[1]),
y.scale, scale_factor,
2018-03-30 11:51:31 -07:00
y.set_color, RED,
2017-03-22 15:06:17 -07:00
y.move_to, frac[3], DOWN,
y.shift, SMALL_BUFF*UP,
FadeOut(frac[3]),
morty.look_at, frac,
run_time = 2
)
2018-01-15 19:15:05 -08:00
self.wait()
2017-03-22 15:06:17 -07:00
self.play(Blink(morty))
class NameImplicitDifferentation(TeacherStudentsScene):
def construct(self):
title = TextMobject("``Implicit differentiation''")
equation = TexMobject("x^2", "+", "y^2", "=", "5^2")
derivative = TexMobject(
"2x\\,dx", "+", "2y\\,dy", "=", "0"
)
2018-03-30 11:51:31 -07:00
VGroup(*derivative[0][2:]).set_color(GREEN)
VGroup(*derivative[2][2:]).set_color(RED)
2017-03-22 15:06:17 -07:00
arrow = Arrow(ORIGIN, DOWN, buff = SMALL_BUFF)
group = VGroup(title, equation, arrow, derivative)
group.arrange_submobjects(DOWN)
group.to_edge(UP)
self.add(title, equation)
self.play(
self.get_teacher().change_mode, "raise_right_hand",
ShowCreation(arrow)
)
self.change_student_modes(
*["confused"]*3,
look_at_arg = derivative,
added_anims = [ReplacementTransform(equation.copy(), derivative)]
)
2018-01-15 19:15:05 -08:00
self.wait(2)
2017-03-22 15:06:17 -07:00
self.teacher_says(
"Don't worry...",
added_anims = [
group.scale, 0.7,
group.to_corner, UP+LEFT,
]
)
self.change_student_modes(*["happy"]*3)
2018-01-15 19:15:05 -08:00
self.wait(3)
2017-03-22 15:06:17 -07:00
class Ladder(VMobject):
CONFIG = {
"height" : 4,
"width" : 1,
"n_rungs" : 7,
}
def generate_points(self):
left_line, right_line = [
Line(ORIGIN, self.height*UP).shift(self.width*vect/2.0)
for vect in (LEFT, RIGHT)
2017-03-22 15:06:17 -07:00
]
rungs = [
Line(
left_line.point_from_proportion(a),
right_line.point_from_proportion(a),
)
for a in np.linspace(0, 1, 2*self.n_rungs+1)[1:-1:2]
]
self.add(left_line, right_line, *rungs)
self.center()
class RelatedRatesExample(ThreeDScene):
CONFIG = {
"start_x" : 3.0,
"start_y" : 4.0,
"wall_dimensions" : [0.3, 5, 5],
"wall_color" : color_gradient([GREY_BROWN, BLACK], 4)[1],
"wall_center" : 1.5*LEFT+0.5*UP,
}
def construct(self):
self.introduce_ladder()
self.write_related_rates()
self.measure_ladder()
self.slide_ladder()
self.ponder_question()
self.write_equation()
self.isolate_x_of_t()
self.discuss_lhs_as_function()
self.let_dt_pass()
self.take_derivative_of_rhs()
self.take_derivative_of_lhs()
self.bring_back_velocity_arrows()
self.replace_terms_in_final_form()
self.write_final_solution()
def introduce_ladder(self):
ladder = Ladder(height = self.get_ladder_length())
wall = Prism(
dimensions = self.wall_dimensions,
fill_color = self.wall_color,
fill_opacity = 1,
)
wall.rotate(np.pi/12, UP)
wall.shift(self.wall_center)
ladder.generate_target()
ladder.fallen = ladder.copy()
ladder.target.rotate(self.get_ladder_angle(), LEFT)
ladder.fallen.rotate(np.pi/2, LEFT)
for ladder_copy in ladder.target, ladder.fallen:
ladder_copy.rotate(-5*np.pi/12, UP)
ladder_copy.next_to(wall, LEFT, 0, DOWN)
ladder_copy.shift(0.8*RIGHT) ##BAD!
self.play(
ShowCreation(ladder, run_time = 2)
)
2018-01-15 19:15:05 -08:00
self.wait()
2017-03-22 15:06:17 -07:00
self.play(
DrawBorderThenFill(wall),
MoveToTarget(ladder),
run_time = 2
)
2018-01-15 19:15:05 -08:00
self.wait()
2017-03-22 15:06:17 -07:00
self.ladder = ladder
def write_related_rates(self):
words = TextMobject("Related rates")
words.to_corner(UP+RIGHT)
self.play(Write(words))
2018-01-15 19:15:05 -08:00
self.wait()
2017-03-22 15:06:17 -07:00
self.related_rates_words = words
def measure_ladder(self):
ladder = self.ladder
ladder_brace = self.get_ladder_brace(ladder)
x_and_y_lines = self.get_x_and_y_lines(ladder)
x_line, y_line = x_and_y_lines
y_label = TexMobject("%dm"%int(self.start_y))
y_label.next_to(y_line, LEFT, buff = SMALL_BUFF)
2018-03-30 11:51:31 -07:00
y_label.set_color(y_line.get_color())
2017-03-22 15:06:17 -07:00
x_label = TexMobject("%dm"%int(self.start_x))
x_label.next_to(x_line, UP)
2018-03-30 11:51:31 -07:00
x_label.set_color(x_line.get_color())
2017-03-22 15:06:17 -07:00
self.play(Write(ladder_brace))
2018-01-15 19:15:05 -08:00
self.wait()
2017-03-22 15:06:17 -07:00
self.play(ShowCreation(y_line), Write(y_label))
2018-01-15 19:15:05 -08:00
self.wait()
2017-03-22 15:06:17 -07:00
self.play(ShowCreation(x_line), Write(x_label))
2018-01-15 19:15:05 -08:00
self.wait(2)
2017-03-22 15:06:17 -07:00
self.play(*map(FadeOut, [x_label, y_label]))
self.ladder_brace = ladder_brace
self.x_and_y_lines = x_and_y_lines
self.numerical_x_and_y_labels = VGroup(x_label, y_label)
def slide_ladder(self):
ladder = self.ladder
brace = self.ladder_brace
x_and_y_lines = self.x_and_y_lines
x_line, y_line = x_and_y_lines
down_arrow, left_arrow = [
Arrow(ORIGIN, vect, color = YELLOW, buff = 0)
for vect in (DOWN, LEFT)
2017-03-22 15:06:17 -07:00
]
down_arrow.shift(y_line.get_start()+MED_SMALL_BUFF*RIGHT)
left_arrow.shift(x_line.get_start()+SMALL_BUFF*DOWN)
# speed_label = TexMobject("1 \\text{m}/\\text{s}")
speed_label = TexMobject("1 \\frac{\\text{m}}{\\text{s}}")
speed_label.next_to(down_arrow, RIGHT, buff = SMALL_BUFF)
q_marks = TexMobject("???")
q_marks.next_to(left_arrow, DOWN, buff = SMALL_BUFF)
added_anims = [
UpdateFromFunc(brace, self.update_brace),
UpdateFromFunc(x_and_y_lines, self.update_x_and_y_lines),
Animation(down_arrow),
]
self.play(ShowCreation(down_arrow))
self.play(Write(speed_label))
self.let_ladder_fall(ladder, *added_anims)
2018-01-15 19:15:05 -08:00
self.wait()
2017-03-22 15:06:17 -07:00
self.reset_ladder(ladder, *added_anims)
self.play(ShowCreation(left_arrow))
self.play(Write(q_marks))
2018-01-15 19:15:05 -08:00
self.wait()
2017-03-22 15:06:17 -07:00
self.let_ladder_fall(ladder, *added_anims)
2018-01-15 19:15:05 -08:00
self.wait()
2017-03-22 15:06:17 -07:00
self.reset_ladder(ladder, *added_anims)
2018-01-15 19:15:05 -08:00
self.wait()
2017-03-22 15:06:17 -07:00
self.dy_arrow = down_arrow
self.dy_label = speed_label
self.dx_arrow = left_arrow
self.dx_label = q_marks
def ponder_question(self):
randy = Randolph(mode = "pondering")
randy.flip()
randy.to_corner(DOWN+RIGHT)
self.play(FadeIn(randy))
self.play(Blink(randy))
2018-01-15 19:15:05 -08:00
self.wait()
2017-03-22 15:06:17 -07:00
self.play(
randy.change_mode, "confused",
randy.look_at, self.ladder.get_top()
)
self.play(randy.look_at, self.ladder.get_bottom())
self.play(randy.look_at, self.ladder.get_top())
self.play(Blink(randy))
2018-01-15 19:15:05 -08:00
self.wait()
2017-03-22 15:06:17 -07:00
self.play(PiCreatureSays(
randy, "Give names"
))
self.play(Blink(randy))
self.play(*map(FadeOut, [
randy, randy.bubble, randy.bubble.content
]))
def write_equation(self):
self.x_and_y_labels = self.get_x_and_y_labels()
x_label, y_label = self.x_and_y_labels
equation = TexMobject(
"x(t)", "^2", "+", "y(t)", "^2", "=", "5^2"
)
2018-03-30 11:51:31 -07:00
equation[0].set_color(GREEN)
equation[3].set_color(RED)
2017-03-22 15:06:17 -07:00
equation.next_to(self.related_rates_words, DOWN, buff = MED_LARGE_BUFF)
equation.to_edge(RIGHT, buff = LARGE_BUFF)
self.play(Write(y_label))
2018-01-15 19:15:05 -08:00
self.wait()
2017-03-22 15:06:17 -07:00
self.let_ladder_fall(
self.ladder,
y_label.shift, self.start_y*DOWN/2,
*self.get_added_anims_for_ladder_fall()[:-1],
rate_func = lambda t : 0.2*there_and_back(t),
run_time = 3
)
self.play(FocusOn(x_label))
self.play(Write(x_label))
2018-01-15 19:15:05 -08:00
self.wait(2)
2017-03-22 15:06:17 -07:00
self.play(
ReplacementTransform(x_label.copy(), equation[0]),
ReplacementTransform(y_label.copy(), equation[3]),
Write(VGroup(*np.array(equation)[[1, 2, 4, 5, 6]]))
)
2018-01-15 19:15:05 -08:00
self.wait(2)
2017-03-22 15:06:17 -07:00
self.let_ladder_fall(
self.ladder,
*self.get_added_anims_for_ladder_fall(),
rate_func = there_and_back,
run_time = 6
)
2018-01-15 19:15:05 -08:00
self.wait()
2017-03-22 15:06:17 -07:00
self.equation = equation
def isolate_x_of_t(self):
alt_equation = TexMobject(
"x(t)", "=", "\\big(5^2", "-", "y(t)", "^2 \\big)", "^{1/2}",
)
2018-03-30 11:51:31 -07:00
alt_equation[0].set_color(GREEN)
alt_equation[4].set_color(RED)
2017-03-22 15:06:17 -07:00
alt_equation.next_to(self.equation, DOWN, buff = MED_LARGE_BUFF)
alt_equation.to_edge(RIGHT)
randy = Randolph()
randy.next_to(
alt_equation, DOWN,
buff = MED_LARGE_BUFF,
aligned_edge = LEFT,
)
randy.look_at(alt_equation)
find_dx_dt = TexMobject("\\text{Find } \\,", "\\frac{dx}{dt}")
find_dx_dt.next_to(randy, RIGHT, aligned_edge = UP)
2018-03-30 11:51:31 -07:00
find_dx_dt[1].set_color(GREEN)
2017-03-22 15:06:17 -07:00
self.play(FadeIn(randy))
self.play(
randy.change_mode, "raise_right_hand",
randy.look_at, alt_equation,
*[
ReplacementTransform(
self.equation[i].copy(),
alt_equation[j],
path_arc = np.pi/2,
run_time = 3,
rate_func = squish_rate_func(
smooth, j/12.0, (j+6)/12.0
)
)
for i, j in enumerate([0, 6, 3, 4, 5, 1, 2])
]
)
self.play(Blink(randy))
2018-01-15 19:15:05 -08:00
self.wait()
2017-03-22 15:06:17 -07:00
self.play(
Write(find_dx_dt),
randy.change_mode, "pondering",
randy.look_at, find_dx_dt,
)
self.let_ladder_fall(
self.ladder, *self.get_added_anims_for_ladder_fall(),
run_time = 8,
rate_func = there_and_back
)
self.play(*map(FadeOut, [
randy, find_dx_dt, alt_equation
]))
2018-01-15 19:15:05 -08:00
self.wait()
2017-03-22 15:06:17 -07:00
def discuss_lhs_as_function(self):
equation = self.equation
lhs = VGroup(*equation[:5])
brace = Brace(lhs, DOWN)
function_of_time = brace.get_text(
"Function of time"
)
constant_words = TextMobject(
"""that happens to
be constant"""
)
2018-03-30 11:51:31 -07:00
constant_words.set_color(YELLOW)
2017-03-22 15:06:17 -07:00
constant_words.next_to(function_of_time, DOWN)
derivative = TexMobject(
"\\frac{d\\left(x(t)^2 + y(t)^2 \\right)}{dt}"
)
derivative.next_to(equation, DOWN, buff = MED_LARGE_BUFF)
derivative.shift( ##Align x terms
equation[0][0].get_center()[0]*RIGHT-\
derivative[2].get_center()[0]*RIGHT
)
derivative_interior = lhs.copy()
derivative_interior.move_to(VGroup(*derivative[2:13]))
derivative_scaffold = VGroup(
*list(derivative[:2])+list(derivative[13:])
)
self.play(
GrowFromCenter(brace),
Write(function_of_time)
)
2018-01-15 19:15:05 -08:00
self.wait()
2017-03-22 15:06:17 -07:00
self.play(Write(constant_words))
self.let_ladder_fall(
self.ladder, *self.get_added_anims_for_ladder_fall(),
run_time = 6,
rate_func = lambda t : 0.5*there_and_back(t)
)
2018-01-15 19:15:05 -08:00
self.wait()
2017-03-22 15:06:17 -07:00
self.play(*map(FadeOut, [
brace, constant_words, function_of_time
]))
self.play(
ReplacementTransform(lhs.copy(), derivative_interior),
Write(derivative_scaffold),
)
2018-01-15 19:15:05 -08:00
self.wait()
2017-03-22 15:06:17 -07:00
self.derivative = VGroup(
derivative_scaffold, derivative_interior
)
def let_dt_pass(self):
dt_words = TextMobject("After", "$dt$", "seconds...")
dt_words.to_corner(UP+LEFT)
dt = dt_words[1]
2018-03-30 11:51:31 -07:00
dt.set_color(YELLOW)
2017-03-22 15:06:17 -07:00
dt_brace = Brace(dt, buff = SMALL_BUFF)
dt_brace_text = dt_brace.get_text("Think 0.01", buff = SMALL_BUFF)
2018-03-30 11:51:31 -07:00
dt_brace_text.set_color(dt.get_color())
2017-03-22 15:06:17 -07:00
shadow_ladder = self.ladder.copy()
shadow_ladder.fade(0.5)
x_line, y_line = self.x_and_y_lines
y_top = y_line.get_start()
x_left = x_line.get_start()
self.play(Write(dt_words, run_time = 2))
self.play(
GrowFromCenter(dt_brace),
Write(dt_brace_text, run_time = 2)
)
self.play(*map(FadeOut, [
self.dy_arrow, self.dy_label,
self.dx_arrow, self.dx_label,
]))
self.add(shadow_ladder)
self.let_ladder_fall(
self.ladder, *self.get_added_anims_for_ladder_fall(),
rate_func = lambda t : 0.1*smooth(t),
run_time = 1
)
new_y_top = y_line.get_start()
new_x_left = x_line.get_start()
dy_line = Line(y_top, new_y_top)
dy_brace = Brace(dy_line, RIGHT, buff = SMALL_BUFF)
dy_label = dy_brace.get_text("$dy$", buff = SMALL_BUFF)
2018-03-30 11:51:31 -07:00
dy_label.set_color(RED)
2017-03-22 15:06:17 -07:00
dx_line = Line(x_left, new_x_left)
dx_brace = Brace(dx_line, DOWN, buff = SMALL_BUFF)
dx_label = dx_brace.get_text("$dx$")
2018-03-30 11:51:31 -07:00
dx_label.set_color(GREEN)
2017-03-22 15:06:17 -07:00
2018-03-30 11:51:31 -07:00
VGroup(dy_line, dx_line).set_color(YELLOW)
2017-03-22 15:06:17 -07:00
for line, brace, label in (dy_line, dy_brace, dy_label), (dx_line, dx_brace, dx_label):
self.play(
ShowCreation(line),
GrowFromCenter(brace),
Write(label),
run_time = 1
)
2018-01-15 19:15:05 -08:00
self.wait()
2017-03-22 15:06:17 -07:00
self.play(Indicate(self.derivative[1]))
2018-01-15 19:15:05 -08:00
self.wait()
2017-03-22 15:06:17 -07:00
self.dy_group = VGroup(dy_line, dy_brace, dy_label)
self.dx_group = VGroup(dx_line, dx_brace, dx_label)
self.shadow_ladder = shadow_ladder
def take_derivative_of_rhs(self):
derivative = self.derivative
equals_zero = TexMobject("= 0")
equals_zero.next_to(derivative)
rhs = self.equation[-1]
self.play(Write(equals_zero))
2018-01-15 19:15:05 -08:00
self.wait()
2017-03-22 15:06:17 -07:00
self.play(FocusOn(rhs))
self.play(Indicate(rhs))
2018-01-15 19:15:05 -08:00
self.wait()
2017-03-22 15:06:17 -07:00
self.reset_ladder(
self.ladder,
*self.get_added_anims_for_ladder_fall()+[
Animation(self.dy_group),
Animation(self.dx_group),
],
rate_func = there_and_back,
run_time = 3
)
2018-01-15 19:15:05 -08:00
self.wait()
2017-03-22 15:06:17 -07:00
self.equals_zero = equals_zero
def take_derivative_of_lhs(self):
derivative_scaffold, equation = self.derivative
equals_zero_copy = self.equals_zero.copy()
lhs_derivative = TexMobject(
"2", "x(t)", "\\frac{dx}{dt}", "+",
"2", "y(t)", "\\frac{dy}{dt}",
)
2018-03-30 11:51:31 -07:00
lhs_derivative[1].set_color(GREEN)
VGroup(*lhs_derivative[2][:2]).set_color(GREEN)
lhs_derivative[5].set_color(RED)
VGroup(*lhs_derivative[6][:2]).set_color(RED)
2017-03-22 15:06:17 -07:00
lhs_derivative.next_to(
derivative_scaffold, DOWN,
aligned_edge = RIGHT,
buff = MED_LARGE_BUFF
)
equals_zero_copy.next_to(lhs_derivative, RIGHT)
pairs = [
(0, 1), (1, 0), #x^2 -> 2x
(2, 3), (3, 5), (4, 4), #+y^2 -> +2y
]
def perform_replacement(index_pairs):
self.play(*[
ReplacementTransform(
equation[i].copy(), lhs_derivative[j],
path_arc = np.pi/2,
run_time = 2
)
for i, j in index_pairs
])
perform_replacement(pairs[:2])
self.play(Write(lhs_derivative[2]))
2018-01-15 19:15:05 -08:00
self.wait()
2017-03-22 15:06:17 -07:00
self.play(Indicate(
VGroup(
*list(lhs_derivative[:2])+\
list(lhs_derivative[2][:2])
),
run_time = 2
))
self.play(Indicate(VGroup(*lhs_derivative[2][3:])))
2018-01-15 19:15:05 -08:00
self.wait(2)
2017-03-22 15:06:17 -07:00
perform_replacement(pairs[2:])
self.play(Write(lhs_derivative[6]))
2018-01-15 19:15:05 -08:00
self.wait()
2017-03-22 15:06:17 -07:00
self.play(FocusOn(self.equals_zero))
self.play(ReplacementTransform(
self.equals_zero.copy(),
equals_zero_copy
))
2018-01-15 19:15:05 -08:00
self.wait(2)
2017-03-22 15:06:17 -07:00
lhs_derivative.add(equals_zero_copy)
self.lhs_derivative = lhs_derivative
def bring_back_velocity_arrows(self):
dx_dy_group = VGroup(self.dx_group, self.dy_group)
arrow_group = VGroup(
self.dy_arrow, self.dy_label,
self.dx_arrow, self.dx_label,
)
ladder_fall_args = [self.ladder] + self.get_added_anims_for_ladder_fall()
self.reset_ladder(*ladder_fall_args + [
FadeOut(dx_dy_group),
FadeOut(self.derivative),
FadeOut(self.equals_zero),
self.lhs_derivative.shift, 2*UP,
])
self.remove(self.shadow_ladder)
self.play(FadeIn(arrow_group))
self.let_ladder_fall(*ladder_fall_args)
2018-01-15 19:15:05 -08:00
self.wait()
2017-03-22 15:06:17 -07:00
self.reset_ladder(*ladder_fall_args)
2018-01-15 19:15:05 -08:00
self.wait()
2017-03-22 15:06:17 -07:00
def replace_terms_in_final_form(self):
x_label, y_label = self.x_and_y_labels
num_x_label, num_y_label = self.numerical_x_and_y_labels
new_lhs_derivative = TexMobject(
"2", "(%d)"%int(self.start_x), "\\frac{dx}{dt}", "+",
"2", "(%d)"%int(self.start_y), "(-1)",
"= 0"
)
2018-03-30 11:51:31 -07:00
new_lhs_derivative[1].set_color(GREEN)
VGroup(*new_lhs_derivative[2][:2]).set_color(GREEN)
new_lhs_derivative[5].set_color(RED)
2017-03-22 15:06:17 -07:00
new_lhs_derivative.next_to(
self.lhs_derivative, DOWN,
buff = MED_LARGE_BUFF,
aligned_edge = RIGHT
)
def fill_in_equation_part(*indices):
self.play(*[
ReplacementTransform(
self.lhs_derivative[i].copy(),
new_lhs_derivative[i],
run_time = 2
)
for i in indices
])
self.play(FadeOut(y_label), FadeIn(num_y_label))
fill_in_equation_part(3, 4, 5)
self.play(FadeOut(x_label), FadeIn(num_x_label))
for indices in [(0, 1), (6,), (2, 7)]:
fill_in_equation_part(*indices)
2018-01-15 19:15:05 -08:00
self.wait()
self.wait()
2017-03-22 15:06:17 -07:00
self.new_lhs_derivative = new_lhs_derivative
def write_final_solution(self):
solution = TexMobject(
"\\frac{dx}{dt} = \\frac{4}{3}"
)
for i in 0, 1, -1:
2018-03-30 11:51:31 -07:00
solution[i].set_color(GREEN)
solution[-3].set_color(RED)
2017-03-22 15:06:17 -07:00
solution.next_to(
self.new_lhs_derivative, DOWN,
buff = MED_LARGE_BUFF,
aligned_edge = RIGHT
)
box = Rectangle(color = YELLOW)
box.replace(solution)
box.scale_in_place(1.5)
self.play(Write(solution))
2018-01-15 19:15:05 -08:00
self.wait()
2017-03-22 15:06:17 -07:00
self.play(ShowCreation(box))
2018-01-15 19:15:05 -08:00
self.wait()
2017-03-22 15:06:17 -07:00
#########
def get_added_anims_for_ladder_fall(self):
return [
UpdateFromFunc(self.ladder_brace, self.update_brace),
UpdateFromFunc(self.x_and_y_lines, self.update_x_and_y_lines),
UpdateFromFunc(self.x_and_y_labels, self.update_x_and_y_labels),
]
def let_ladder_fall(self, ladder, *added_anims, **kwargs):
kwargs["run_time"] = kwargs.get("run_time", self.start_y)
kwargs["rate_func"] = kwargs.get("rate_func", None)
self.play(
Transform(ladder, ladder.fallen),
*added_anims,
**kwargs
)
def reset_ladder(self, ladder, *added_anims, **kwargs):
kwargs["run_time"] = kwargs.get("run_time", 2)
self.play(
Transform(ladder, ladder.target),
*added_anims,
**kwargs
)
def update_brace(self, brace):
Transform(
brace, self.get_ladder_brace(self.ladder)
).update(1)
return brace
def update_x_and_y_lines(self, x_and_y_lines):
Transform(
x_and_y_lines,
self.get_x_and_y_lines(self.ladder)
).update(1)
return x_and_y_lines
def update_x_and_y_labels(self, x_and_y_labels):
Transform(
x_and_y_labels,
self.get_x_and_y_labels()
).update(1)
return x_and_y_labels
def get_ladder_brace(self, ladder):
vect = rotate_vector(LEFT, -self.get_ladder_angle())
brace = Brace(ladder, vect)
length_string = "%dm"%int(self.get_ladder_length())
length_label = brace.get_text(
length_string, use_next_to = False
)
brace.add(length_label)
brace.length_label = length_label
return brace
def get_x_and_y_labels(self):
x_line, y_line = self.x_and_y_lines
x_label = TexMobject("x(t)")
2018-03-30 11:51:31 -07:00
x_label.set_color(x_line.get_color())
2017-03-22 15:06:17 -07:00
x_label.next_to(x_line, DOWN, buff = SMALL_BUFF)
y_label = TexMobject("y(t)")
2018-03-30 11:51:31 -07:00
y_label.set_color(y_line.get_color())
2017-03-22 15:06:17 -07:00
y_label.next_to(y_line, LEFT, buff = SMALL_BUFF)
return VGroup(x_label, y_label)
def get_x_and_y_lines(self, ladder):
bottom_point, top_point = np.array(ladder[1].get_start_and_end())
interim_point = top_point[0]*RIGHT + bottom_point[1]*UP
interim_point += SMALL_BUFF*DOWN
y_line = Line(top_point, interim_point)
2018-03-30 11:51:31 -07:00
y_line.set_color(RED)
2017-03-22 15:06:17 -07:00
x_line = Line(bottom_point, interim_point)
2018-03-30 11:51:31 -07:00
x_line.set_color(GREEN)
2017-03-22 15:06:17 -07:00
return VGroup(x_line, y_line)
def get_ladder_angle(self):
if hasattr(self, "ladder"):
c1 = self.ladder.get_corner(UP+RIGHT)
c2 = self.ladder.get_corner(DOWN+LEFT)
vect = c1-c2
return np.pi/2 - angle_of_vector(vect)
else:
return np.arctan(self.start_x/self.start_y)
def get_ladder_length(self):
return np.linalg.norm([self.start_x, self.start_y])
class LightweightLadderScene(RelatedRatesExample):
CONFIG = {
"skip_animations" : True
}
def construct(self):
self.introduce_ladder()
self.measure_ladder()
self.add(self.numerical_x_and_y_labels)
class LightweightCircleExample(SlopeOfCircleExample):
CONFIG = {
"skip_animations" : True,
"plane_kwargs" : {
"x_radius" : 5,
"y_radius" : 5,
"space_unit_to_x_unit" : SPACE_UNIT_TO_PLANE_UNIT,
"space_unit_to_y_unit" : SPACE_UNIT_TO_PLANE_UNIT,
},
}
def construct(self):
self.setup_plane()
self.introduce_circle()
self.talk_through_pythagorean_theorem()
self.draw_example_slope()
self.remove(self.circle_equation)
self.remove(self.slope_word)
self.example_point_coords_mob.scale(
1.5, about_point = self.example_point_coords_mob.get_corner(UP+RIGHT)
)
self.plane.axis_labels[0].shift(3*LEFT)
class CompareLadderAndCircle(PiCreatureScene, ThreeDScene):
def construct(self):
self.introduce_both_scenes()
self.show_derivatives()
self.comment_on_ladder_derivative()
self.comment_on_circle_derivative()
def introduce_both_scenes(self):
ladder_scene = LightweightLadderScene()
ladder_mobs = VGroup(*ladder_scene.get_top_level_mobjects())
circle_scene = LightweightCircleExample()
circle_mobs = VGroup(*circle_scene.get_top_level_mobjects())
for mobs, vect in (ladder_mobs, LEFT), (circle_mobs, RIGHT):
mobs.set_height(FRAME_Y_RADIUS-MED_LARGE_BUFF)
2017-03-22 15:06:17 -07:00
mobs.next_to(
self.pi_creature.get_corner(UP+vect), UP,
buff = SMALL_BUFF,
aligned_edge = -vect
)
ladder_mobs.save_state()
ladder_mobs.fade(1)
ladder_mobs.rotate_in_place(np.pi/3, UP)
self.play(
self.pi_creature.change_mode, "raise_right_hand",
self.pi_creature.look_at, ladder_mobs,
ApplyMethod(ladder_mobs.restore, run_time = 2)
)
self.play(
self.pi_creature.change_mode, "raise_left_hand",
self.pi_creature.look_at, circle_mobs,
Write(circle_mobs, run_time = 2)
)
2018-01-15 19:15:05 -08:00
self.wait(2)
2017-03-22 15:06:17 -07:00
self.play(
circle_mobs.to_edge, RIGHT,
ladder_mobs.to_edge, LEFT,
)
def show_derivatives(self):
equation = TexMobject(
"x", "^2", "+", "y", "^2", "= 5^2"
)
derivative = TexMobject(
"2", "x", "dx", "+", "2", "y", "dy", "=0"
)
self.color_equations(equation, derivative)
equation.to_edge(UP)
equation.shift(MED_LARGE_BUFF*LEFT)
derivative.next_to(equation, DOWN, buff = MED_LARGE_BUFF)
self.play(
Write(equation),
self.pi_creature.change_mode, "plain",
self.pi_creature.look_at, equation
)
2018-01-15 19:15:05 -08:00
self.wait()
2017-03-22 15:06:17 -07:00
self.play(*[
ReplacementTransform(
equation[i].copy(), derivative[j],
path_arc = np.pi/2
)
for i, j in enumerate([1, 0, 3, 5, 4, 7])
]+[
Write(derivative[j])
for j in (2, 6)
2017-03-22 15:06:17 -07:00
])
self.play(
self.pi_creature.change_mode, "pondering",
self.pi_creature.look_at, derivative
)
2018-01-15 19:15:05 -08:00
self.wait()
2017-03-22 15:06:17 -07:00
self.equation = equation
self.derivative = derivative
def comment_on_ladder_derivative(self):
equation = self.equation
derivative = self.derivative
time_equation = TexMobject(
"x(t)", "^2", "+", "y(t)", "^2", "= 5^2"
)
time_derivative = TexMobject(
"2", "x(t)", "\\frac{dx}{dt}", "+",
"2", "y(t)", "\\frac{dy}{dt}", "=0"
)
self.color_equations(time_equation, time_derivative)
time_equation.move_to(equation)
time_derivative.move_to(derivative, UP)
brace = Brace(time_derivative)
brace_text = brace.get_text("A rate")
equation.save_state()
derivative.save_state()
self.play(Transform(equation, time_equation))
2018-01-15 19:15:05 -08:00
self.wait()
2017-03-22 15:06:17 -07:00
self.play(Transform(derivative, time_derivative))
2018-01-15 19:15:05 -08:00
self.wait()
2017-03-22 15:06:17 -07:00
self.play(GrowFromCenter(brace))
self.play(Write(brace_text))
self.change_mode("hooray")
2018-01-15 19:15:05 -08:00
self.wait(2)
2017-03-22 15:06:17 -07:00
self.play(
equation.restore,
derivative.restore,
FadeOut(brace),
FadeOut(brace_text),
self.pi_creature.change_mode, "confused"
)
2018-01-15 19:15:05 -08:00
self.wait()
2017-03-22 15:06:17 -07:00
def comment_on_circle_derivative(self):
derivative = self.derivative
dx = derivative.get_part_by_tex("dx")
dy = derivative.get_part_by_tex("dy")
for mob in dx, dy:
brace = Brace(mob)
brace.next_to(mob[0], DOWN, buff = SMALL_BUFF, aligned_edge = LEFT)
text = brace.get_text("No $dt$", buff = SMALL_BUFF)
2018-03-30 11:51:31 -07:00
text.set_color(YELLOW)
2017-03-22 15:06:17 -07:00
self.play(
GrowFromCenter(brace),
Write(text)
)
2018-01-15 19:15:05 -08:00
self.wait()
2017-03-22 15:06:17 -07:00
self.play(
self.pi_creature.change_mode, "pondering",
self.pi_creature.look, DOWN+LEFT
)
2018-01-15 19:15:05 -08:00
self.wait(2)
2017-03-22 15:06:17 -07:00
#######
def create_pi_creature(self):
self.pi_creature = Mortimer().to_edge(DOWN)
return self.pi_creature
def color_equations(self, equation, derivative):
for mob in equation[0], derivative[1]:
2018-03-30 11:51:31 -07:00
mob.set_color(GREEN)
2017-03-22 15:06:17 -07:00
for mob in equation[3], derivative[5]:
2018-03-30 11:51:31 -07:00
mob.set_color(RED)
2017-03-22 15:06:17 -07:00
class TwoVariableFunctionAndDerivative(SlopeOfCircleExample):
CONFIG = {
"zoomed_canvas_corner" : DOWN+RIGHT,
"zoomed_canvas_frame_shape" : (3, 4),
2017-03-22 15:06:17 -07:00
}
def construct(self):
self.setup_plane()
self.write_equation()
self.show_example_point()
self.shift_example_point((4, 4))
self.shift_example_point((3, 3))
self.shift_example_point(self.example_point)
self.take_derivative_symbolically()
self.show_dx_dy_step()
self.plug_in_example_values()
self.ask_about_equalling_zero()
self.show_tangent_step()
self.point_out_equalling_zero()
self.show_tangent_line()
def write_equation(self):
equation = TexMobject("x", "^2", "+", "y", "^2")
equation.add_background_rectangle()
brace = Brace(equation, UP, buff = SMALL_BUFF)
s_expression = self.get_s_expression("x", "y")
s_rect, s_of_xy = s_expression
s, xy = s_of_xy
s_expression.next_to(brace, UP, buff = SMALL_BUFF)
group = VGroup(equation, s_expression, brace)
group.shift(FRAME_WIDTH*LEFT/3)
2017-03-22 15:06:17 -07:00
group.to_edge(UP, buff = MED_SMALL_BUFF)
s.save_state()
s.next_to(brace, UP)
self.play(Write(equation))
self.play(GrowFromCenter(brace))
self.play(Write(s))
2018-01-15 19:15:05 -08:00
self.wait()
2017-03-22 15:06:17 -07:00
self.play(
FadeIn(s_rect),
s.restore,
GrowFromCenter(xy)
)
2018-01-15 19:15:05 -08:00
self.wait()
2017-03-22 15:06:17 -07:00
self.equation = equation
self.s_expression = s_expression
def show_example_point(self):
point = self.plane.num_pair_to_point(self.example_point)
dot = Dot(point, color = self.example_color)
new_s_expression = self.get_s_expression(*self.example_point)
new_s_expression.next_to(dot, UP+RIGHT, buff = 0)
2018-03-30 11:51:31 -07:00
new_s_expression.set_color(self.example_color)
2017-03-22 15:06:17 -07:00
equals_25 = TexMobject("=%d"%int(np.linalg.norm(self.example_point)**2))
2018-03-30 11:51:31 -07:00
equals_25.set_color(YELLOW)
2017-03-22 15:06:17 -07:00
equals_25.next_to(new_s_expression, RIGHT, align_using_submobjects = True)
equals_25.add_background_rectangle()
circle = Circle(
radius = self.circle_radius*self.plane.space_unit_to_x_unit,
color = self.circle_color,
)
self.play(
ReplacementTransform(
self.s_expression.copy(),
new_s_expression
),
ShowCreation(dot)
)
self.play(ShowCreation(circle), Animation(dot))
self.play(Write(equals_25))
2018-01-15 19:15:05 -08:00
self.wait()
2017-03-22 15:06:17 -07:00
self.example_point_dot = dot
self.example_point_label = VGroup(
new_s_expression, equals_25
)
def shift_example_point(self, coords):
point = self.plane.num_pair_to_point(coords)
s_expression = self.get_s_expression(*coords)
s_expression.next_to(point, UP+RIGHT, buff = SMALL_BUFF)
2018-03-30 11:51:31 -07:00
s_expression.set_color(self.example_color)
2017-03-22 15:06:17 -07:00
result = coords[0]**2 + coords[1]**2
rhs = TexMobject("=%d"%int(result))
rhs.add_background_rectangle()
2018-03-30 11:51:31 -07:00
rhs.set_color(YELLOW)
2017-03-22 15:06:17 -07:00
rhs.next_to(s_expression, RIGHT, align_using_submobjects = True)
point_label = VGroup(s_expression, rhs)
self.play(
self.example_point_dot.move_to, point,
Transform(self.example_point_label, point_label)
)
2018-01-15 19:15:05 -08:00
self.wait(2)
2017-03-22 15:06:17 -07:00
def take_derivative_symbolically(self):
equation = self.equation
derivative = TexMobject(
"dS =", "2", "x", "\\,dx", "+", "2", "y", "\\,dy",
)
2018-03-30 11:51:31 -07:00
derivative[2].set_color(GREEN)
derivative[6].set_color(RED)
2017-03-22 15:06:17 -07:00
derivative.next_to(equation, DOWN, buff = MED_LARGE_BUFF)
derivative.add_background_rectangle()
derivative.to_edge(LEFT)
self.play(*[
FadeIn(derivative[0])
]+[
ReplacementTransform(
self.s_expression[1][0].copy(),
derivative[1][0],
)
]+[
Write(derivative[1][j])
for j in (3, 7)
2017-03-22 15:06:17 -07:00
])
self.play(*[
ReplacementTransform(
equation[1][i].copy(), derivative[1][j],
path_arc = np.pi/2,
run_time = 2,
rate_func = squish_rate_func(smooth, (j-1)/12., (j+6)/12.)
)
for i, j in enumerate([2, 1, 4, 6, 5])
])
2018-01-15 19:15:05 -08:00
self.wait(2)
2017-03-22 15:06:17 -07:00
self.derivative = derivative
def show_dx_dy_step(self):
dot = self.example_point_dot
s_label = self.example_point_label
rhs = s_label[-1]
s_label.remove(rhs)
point = dot.get_center()
vect = 2*LEFT + DOWN
new_point = point + vect*0.6/self.zoom_factor
interim_point = new_point[0]*RIGHT + point[1]*UP
dx_line = Line(point, interim_point, color = GREEN)
dy_line = Line(interim_point, new_point, color = RED)
for line, tex, vect in (dx_line, "dx", UP), (dy_line, "dy", LEFT):
label = TexMobject(tex)
2018-03-30 11:51:31 -07:00
label.set_color(line.get_color())
2017-03-22 15:06:17 -07:00
label.next_to(line, vect, buff = SMALL_BUFF)
label.add_background_rectangle()
label.scale(
1./self.zoom_factor,
about_point = line.get_center()
)
line.label = label
self.activate_zooming()
lil_rect = self.little_rectangle
lil_rect.move_to(dot)
lil_rect.shift(0.05*lil_rect.get_width()*LEFT)
lil_rect.shift(0.2*lil_rect.get_height()*DOWN)
lil_rect.save_state()
lil_rect.set_height(FRAME_Y_RADIUS - MED_LARGE_BUFF)
2017-03-22 15:06:17 -07:00
lil_rect.move_to(s_label, UP)
lil_rect.shift(MED_SMALL_BUFF*UP)
2018-01-15 19:15:05 -08:00
self.wait()
2017-03-22 15:06:17 -07:00
self.play(
FadeOut(rhs),
dot.scale, 1./self.zoom_factor, point,
s_label.scale, 1./self.zoom_factor, point,
lil_rect.restore,
run_time = 2
)
2018-01-15 19:15:05 -08:00
self.wait()
2017-03-22 15:06:17 -07:00
for line in dx_line, dy_line:
self.play(ShowCreation(line))
self.play(Write(line.label, run_time = 1))
2018-01-15 19:15:05 -08:00
self.wait()
2017-03-22 15:06:17 -07:00
new_dot = Dot(color = dot.get_color())
new_s_label = self.get_s_expression(
"%d + dx"%int(self.example_point[0]),
"%d + dy"%int(self.example_point[1]),
)
new_dot.set_height(dot.get_height())
2017-03-22 15:06:17 -07:00
new_dot.move_to(new_point)
new_s_label.set_height(s_label.get_height())
2017-03-22 15:06:17 -07:00
new_s_label.scale(0.8)
new_s_label.next_to(
new_dot, DOWN,
buff = SMALL_BUFF/self.zoom_factor,
aligned_edge = LEFT
)
new_s_label.shift(MED_LARGE_BUFF*LEFT/self.zoom_factor)
2018-03-30 11:51:31 -07:00
new_s_label.set_color(self.example_color)
VGroup(*new_s_label[1][1][3:5]).set_color(GREEN)
VGroup(*new_s_label[1][1][-3:-1]).set_color(RED)
2017-03-22 15:06:17 -07:00
self.play(ShowCreation(new_dot))
self.play(Write(new_s_label))
2018-01-15 19:15:05 -08:00
self.wait()
2017-03-22 15:06:17 -07:00
ds = self.derivative[1][0]
self.play(FocusOn(ds))
self.play(Indicate(ds))
2018-01-15 19:15:05 -08:00
self.wait()
2017-03-22 15:06:17 -07:00
self.tiny_step_group = VGroup(
dx_line, dx_line.label,
dy_line, dy_line.label,
s_label, new_s_label, new_dot
)
def plug_in_example_values(self):
deriv_example = TexMobject(
"dS =", "2", "(3)", "\\,(-0.02)", "+", "2", "(4)", "\\,(-0.01)",
)
2018-03-30 11:51:31 -07:00
deriv_example[2].set_color(GREEN)
deriv_example[6].set_color(RED)
2017-03-22 15:06:17 -07:00
deriv_example.add_background_rectangle()
deriv_example.scale(0.8)
deriv_example.next_to(ORIGIN, UP, buff = SMALL_BUFF)
deriv_example.to_edge(LEFT, buff = MED_SMALL_BUFF)
def add_example_parts(*indices):
self.play(*[
ReplacementTransform(
self.derivative[1][i].copy(),
deriv_example[1][i],
run_time = 2
)
for i in indices
])
self.play(FadeIn(deriv_example[0]))
add_example_parts(0)
2018-01-15 19:15:05 -08:00
self.wait()
2017-03-22 15:06:17 -07:00
add_example_parts(1, 2, 4, 5, 6)
2018-01-15 19:15:05 -08:00
self.wait(2)
2017-03-22 15:06:17 -07:00
add_example_parts(3)
2018-01-15 19:15:05 -08:00
self.wait()
2017-03-22 15:06:17 -07:00
add_example_parts(7)
2018-01-15 19:15:05 -08:00
self.wait()
2017-03-22 15:06:17 -07:00
#React
randy = Randolph()
randy.next_to(ORIGIN, LEFT)
randy.to_edge(DOWN)
self.play(FadeIn(randy))
self.play(
randy.change_mode, "pondering",
randy.look_at, deriv_example.get_left()
)
self.play(Blink(randy))
self.play(randy.look_at, deriv_example.get_right())
2018-01-15 19:15:05 -08:00
self.wait()
2017-03-22 15:06:17 -07:00
self.play(
Indicate(self.equation),
randy.look_at, self.equation
)
self.play(Blink(randy))
self.play(
randy.change_mode, "thinking",
randy.look_at, self.big_rectangle
)
2018-01-15 19:15:05 -08:00
self.wait(2)
2017-03-22 15:06:17 -07:00
self.play(PiCreatureSays(
randy, "Approximately",
target_mode = "sassy"
))
2018-01-15 19:15:05 -08:00
self.wait()
2017-03-22 15:06:17 -07:00
self.play(RemovePiCreatureBubble(randy))
self.play(randy.look_at, deriv_example)
self.play(FadeOut(deriv_example))
2018-01-15 19:15:05 -08:00
self.wait()
2017-03-22 15:06:17 -07:00
self.randy = randy
def ask_about_equalling_zero(self):
dot = self.example_point_dot
randy = self.randy
equals_zero = TexMobject("=0")
2018-03-30 11:51:31 -07:00
equals_zero.set_color(YELLOW)
2017-03-22 15:06:17 -07:00
equals_zero.add_background_rectangle()
equals_zero.next_to(self.derivative, RIGHT)
self.play(
Write(equals_zero),
randy.change_mode, "confused",
randy.look_at, equals_zero
)
2018-01-15 19:15:05 -08:00
self.wait()
2017-03-22 15:06:17 -07:00
self.play(Blink(randy))
self.play(
randy.change_mode, "plain",
randy.look_at, self.big_rectangle,
)
self.play(
FadeOut(self.tiny_step_group),
self.little_rectangle.move_to, dot,
)
2018-01-15 19:15:05 -08:00
self.wait()
2017-03-22 15:06:17 -07:00
self.equals_zero = equals_zero
def show_tangent_step(self):
dot = self.example_point_dot
randy = self.randy
point = dot.get_center()
step_vect = rotate_vector(point, np.pi/2)/np.linalg.norm(point)
new_point = point + step_vect/self.zoom_factor
interim_point = point[0]*RIGHT + new_point[1]*UP
new_dot = dot.copy().move_to(new_point)
step_line = Line(point, new_point, color = WHITE)
dy_line = Line(point, interim_point, color = RED)
dx_line = Line(interim_point, new_point, color = GREEN)
s_label = TexMobject("S = 25")
2018-03-30 11:51:31 -07:00
s_label.set_color(self.example_color)
2017-03-22 15:06:17 -07:00
s_label.next_to(
point, DOWN,
buff = MED_LARGE_BUFF,
aligned_edge = RIGHT
)
s_label.scale(1./self.zoom_factor, about_point = point)
arrow1, arrow2 = [
Arrow(
s_label.get_top(), mob,
preserve_tip_size_when_scaling = False,
color = self.example_color,
buff = SMALL_BUFF/self.zoom_factor,
tip_length = 0.15/self.zoom_factor
)
for mob in (dot, new_dot)
2017-03-22 15:06:17 -07:00
]
for line, tex, vect in (dy_line, "dy", RIGHT), (dx_line, "dx", UP):
label = TexMobject(tex)
2018-03-30 11:51:31 -07:00
label.set_color(line.get_color())
2017-03-22 15:06:17 -07:00
label.next_to(line, vect)
label.scale(
1./self.zoom_factor,
about_point = line.get_center()
)
line.label = label
self.play(ShowCreation(line))
self.play(Write(label))
self.play(ShowCreation(new_dot))
self.play(
randy.change_mode, "pondering",
randy.look_at, self.big_rectangle
)
self.play(Blink(randy))
2018-01-15 19:15:05 -08:00
self.wait()
2017-03-22 15:06:17 -07:00
self.play(Write(s_label))
self.play(ShowCreation(arrow1))
2018-01-15 19:15:05 -08:00
self.wait()
2017-03-22 15:06:17 -07:00
self.play(ReplacementTransform(arrow1.copy(), arrow2))
2018-01-15 19:15:05 -08:00
self.wait(2)
2017-03-22 15:06:17 -07:00
def point_out_equalling_zero(self):
derivative = self.derivative
equals_zero = self.equals_zero
randy = self.randy
self.play(
FocusOn(equals_zero),
self.randy.look_at, equals_zero
)
self.play(Indicate(equals_zero, color = RED))
self.play(Blink(randy))
self.play(randy.change_mode, "happy")
self.play(randy.look_at, self.big_rectangle)
2018-01-15 19:15:05 -08:00
self.wait(2)
2017-03-22 15:06:17 -07:00
def show_tangent_line(self):
randy = self.randy
point = self.example_point_dot.get_center()
line = Line(ORIGIN, 5*RIGHT)
line.rotate(angle_of_vector(point)+np.pi/2)
line.move_to(point)
self.play(PiCreatureSays(
randy, "Approximately...",
))
self.play(Blink(randy))
self.play(RemovePiCreatureBubble(randy))
self.play(
GrowFromCenter(line),
randy.look_at, line
)
2018-01-15 19:15:05 -08:00
self.wait(2)
2017-03-22 15:06:17 -07:00
self.play(
self.little_rectangle.scale_in_place, self.zoom_factor/2,
run_time = 4,
rate_func = there_and_back
)
2018-01-15 19:15:05 -08:00
self.wait(2)
2017-03-22 15:06:17 -07:00
############
def get_s_expression(self, x, y):
result = TexMobject("S", "(%s, %s)"%(str(x), str(y)))
result.add_background_rectangle()
return result
class TryOtherExamples(TeacherStudentsScene):
def construct(self):
formula = TexMobject("\\sin(x)y^2 = x")
formula.next_to(
self.get_teacher().get_corner(UP+LEFT), UP,
buff = MED_LARGE_BUFF,
aligned_edge = RIGHT
)
self.teacher_says(
"""Nothing special
about $x^2 + y^2 = 25$"""
)
2018-01-15 19:15:05 -08:00
self.wait()
2017-03-22 15:06:17 -07:00
self.play(RemovePiCreatureBubble(
self.get_teacher(),
target_mode = "raise_right_hand"
))
self.play(Write(formula, run_time = 1))
self.change_student_modes(*["pondering"]*3)
2018-01-15 19:15:05 -08:00
self.wait(2)
2017-03-22 15:06:17 -07:00
self.play(formula.to_corner, UP+LEFT)
2018-01-15 19:15:05 -08:00
self.wait()
2017-03-22 15:06:17 -07:00
class AlternateExample(ZoomedScene):
CONFIG = {
"example_color" : MAROON_B,
"zoom_factor" : 10,
"zoomed_canvas_corner" : DOWN+RIGHT,
"zoomed_canvas_frame_shape" : (3, 4),
2017-03-22 15:06:17 -07:00
}
def construct(self):
self.add_plane()
self.draw_graph()
self.emphasize_meaning_of_points()
self.zoom_in()
self.show_tiny_step()
self.ask_about_derivatives()
self.differentiate_lhs()
self.differentiate_rhs()
self.put_step_on_curve()
self.emphasize_equality()
self.manipulate_to_find_dy_dx()
def add_plane(self):
formula = TexMobject("\\sin(x)y^2 = x")
formula.to_corner(UP+LEFT)
formula.add_background_rectangle()
plane = NumberPlane(
space_unit_to_x_unit = 0.75,
x_radius = FRAME_WIDTH,
2017-03-22 15:06:17 -07:00
)
plane.fade()
plane.add_coordinates()
self.add(formula)
self.play(Write(plane, run_time = 2), Animation(formula))
2018-01-15 19:15:05 -08:00
self.wait()
2017-03-22 15:06:17 -07:00
self.plane = plane
self.formula = formula
self.lhs = VGroup(*formula[1][:8])
self.rhs = VGroup(formula[1][-1])
def draw_graph(self):
graphs = VGroup(*[
FunctionGraph(
lambda x : u*np.sqrt(x/np.sin(x)),
num_steps = 200,
x_min = x_min+0.1,
x_max = x_max-0.1,
)
for u in [-1, 1]
for x_min, x_max in [
(-4*np.pi, -2*np.pi),
(-np.pi, np.pi),
(2*np.pi, 4*np.pi),
]
])
graphs.stretch(self.plane.space_unit_to_x_unit, dim = 0)
self.play(
ShowCreation(
graphs,
run_time = 3,
submobject_mode = "all_at_once"
),
Animation(self.formula)
)
2018-01-15 19:15:05 -08:00
self.wait()
2017-03-22 15:06:17 -07:00
self.graphs = graphs
def emphasize_meaning_of_points(self):
graph = self.graphs[4]
dot = Dot(color = self.example_color)
label = TexMobject("(x, y)")
label.add_background_rectangle()
2018-03-30 11:51:31 -07:00
label.set_color(self.example_color)
2017-03-22 15:06:17 -07:00
def update_dot(dot, alpha):
prop = interpolate(0.9, 0.1, alpha)
point = graph.point_from_proportion(prop)
dot.move_to(point)
return dot
def update_label(label):
point = dot.get_center()
vect = np.array(point)/np.linalg.norm(point)
vect[0] *= 2
vect[1] *= -1
label.move_to(
point + vect*0.4*label.get_width()
)
update_dot(dot, 0)
update_label(label)
self.play(
ShowCreation(dot),
Write(label),
run_time = 1
)
self.play(
UpdateFromAlphaFunc(dot, update_dot),
UpdateFromFunc(label, update_label),
run_time = 3,
)
2018-01-15 19:15:05 -08:00
self.wait()
2017-03-22 15:06:17 -07:00
self.play(*[
ApplyMethod(
label[1][i].copy().move_to, self.formula[1][j],
run_time = 3,
rate_func = squish_rate_func(smooth, count/6., count/6.+2./3)
)
for count, (i, j) in enumerate([(1, 4), (1, 9), (3, 6)])
])
movers = self.get_mobjects_from_last_animation()
2018-01-15 19:15:05 -08:00
self.wait()
2017-03-22 15:06:17 -07:00
self.play(
UpdateFromAlphaFunc(dot, update_dot),
UpdateFromFunc(label, update_label),
run_time = 3,
rate_func = lambda t : 1-smooth(t)
)
2018-01-15 19:15:05 -08:00
self.wait()
2017-03-22 15:06:17 -07:00
self.play(*[
ApplyMethod(mover.set_fill, None, 0, remover = True)
for mover in movers
])
self.dot = dot
self.label = label
def zoom_in(self):
dot = self.dot
label = self.label
self.activate_zooming()
self.little_rectangle.scale(self.zoom_factor)
self.little_rectangle.move_to(dot)
2018-01-15 19:15:05 -08:00
self.wait()
2017-03-22 15:06:17 -07:00
for mob in VGroup(dot, label), self.little_rectangle:
self.play(
ApplyMethod(
mob.scale, 1./self.zoom_factor,
method_kwargs = {"about_point" : dot.get_center()},
run_time = 1,
)
)
2018-01-15 19:15:05 -08:00
self.wait()
2017-03-22 15:06:17 -07:00
def show_tiny_step(self):
dot = self.dot
label = self.label
point = dot.get_center()
step_vect = 1.2*(UP+LEFT)/float(self.zoom_factor)
new_point = point + step_vect
interim_point = new_point[0]*RIGHT + point[1]*UP
dx_line = Line(point, interim_point, color = GREEN)
dy_line = Line(interim_point, new_point, color = RED)
for line, tex, vect in (dx_line, "dx", DOWN), (dy_line, "dy", LEFT):
label = TexMobject(tex)
label.next_to(line, vect, buff = SMALL_BUFF)
2018-03-30 11:51:31 -07:00
label.set_color(line.get_color())
2017-03-22 15:06:17 -07:00
label.scale(1./self.zoom_factor, about_point = line.get_center())
label.add_background_rectangle()
line.label = label
arrow = Arrow(
point, new_point, buff = 0,
tip_length = 0.15/self.zoom_factor,
color = WHITE
)
self.play(ShowCreation(arrow))
for line in dx_line, dy_line:
self.play(ShowCreation(line), Animation(arrow))
self.play(Write(line.label, run_time = 1))
2018-01-15 19:15:05 -08:00
self.wait()
2017-03-22 15:06:17 -07:00
self.step_group = VGroup(
arrow, dx_line, dx_line.label, dy_line, dy_line.label
)
def ask_about_derivatives(self):
formula = self.formula
lhs, rhs = self.lhs, self.rhs
word = TextMobject("Change?")
word.add_background_rectangle()
word.next_to(
Line(lhs.get_center(), rhs.get_center()),
DOWN, buff = 1.5*LARGE_BUFF
)
arrows = VGroup(*[
Arrow(word, part)
for part in (lhs, rhs)
2017-03-22 15:06:17 -07:00
])
self.play(FocusOn(formula))
self.play(
Write(word),
ShowCreation(arrows)
)
2018-01-15 19:15:05 -08:00
self.wait()
2017-03-22 15:06:17 -07:00
self.play(*map(FadeOut, [word, arrows]))
def differentiate_lhs(self):
formula = self.formula
lhs = self.lhs
brace = Brace(lhs, DOWN, buff = SMALL_BUFF)
sine_x = VGroup(*lhs[:6])
sine_rect = BackgroundRectangle(sine_x)
y_squared = VGroup(*lhs[6:])
mnemonic = TextMobject(
"``",
"Left", " d-Right", " + ",
"Right", " d-Left"
"''",
arg_separator = ""
)
2018-03-30 11:51:31 -07:00
mnemonic.set_color_by_tex("d-Right", RED)
mnemonic.set_color_by_tex("d-Left", GREEN)
2017-03-22 15:06:17 -07:00
mnemonic.add_background_rectangle()
mnemonic.set_width(FRAME_X_RADIUS-2*MED_LARGE_BUFF)
2017-03-22 15:06:17 -07:00
mnemonic.next_to(ORIGIN, UP)
mnemonic.to_edge(LEFT)
derivative = TexMobject(
"\\sin(x)", "(2y\\,dy)", "+",
"y^2", "(\\cos(x)\\,dx)",
)
2018-03-30 11:51:31 -07:00
derivative.set_color_by_tex("dx", GREEN)
derivative.set_color_by_tex("dy", RED)
derivative.set_width(FRAME_X_RADIUS - 2*MED_LARGE_BUFF)
2017-03-22 15:06:17 -07:00
derivative.next_to(
brace, DOWN,
buff = MED_LARGE_BUFF,
aligned_edge = LEFT
)
derivative_rects = [
BackgroundRectangle(VGroup(*subset))
for subset in (derivative[:2], derivative[2:])
2017-03-22 15:06:17 -07:00
]
derivative_rects[1].stretch(1.05, dim = 0)
self.play(GrowFromCenter(brace))
self.play(Write(mnemonic))
2018-01-15 19:15:05 -08:00
self.wait()
2017-03-22 15:06:17 -07:00
pairs = [
(sine_rect, derivative_rects[0]),
(sine_x, derivative[0]),
(y_squared, derivative[1]),
(sine_rect, derivative_rects[1]),
(y_squared, derivative[2]),
(y_squared, derivative[3]),
(sine_x, derivative[4]),
]
for pairs_subset in pairs[:3], pairs[3:]:
self.play(*[
ReplacementTransform(m1.copy(), m2, path_arc = np.pi/2)
for m1, m2 in pairs_subset
])
2018-01-15 19:15:05 -08:00
self.wait()
2017-03-22 15:06:17 -07:00
self.play(Indicate(pairs_subset[-1][1]))
2018-01-15 19:15:05 -08:00
self.wait()
self.wait()
2017-03-22 15:06:17 -07:00
self.play(FadeOut(mnemonic))
self.lhs_derivative = VGroup(*derivative_rects+[derivative])
self.lhs_brace = brace
def differentiate_rhs(self):
lhs_derivative = self.lhs_derivative
lhs_brace = self.lhs_brace
rhs = self.rhs
equals, dx = equals_dx = TexMobject("=", "dx")
equals_dx.scale(0.9)
2018-03-30 11:51:31 -07:00
equals_dx.set_color_by_tex("dx", GREEN)
2017-03-22 15:06:17 -07:00
equals_dx.add_background_rectangle()
equals_dx.next_to(lhs_derivative, RIGHT, buff = SMALL_BUFF)
circle = Circle(color = GREEN)
circle.replace(self.rhs)
circle.scale_in_place(1.7)
arrow = Arrow(rhs.get_right(), dx.get_top())
2018-03-30 11:51:31 -07:00
arrow.set_color(GREEN)
2017-03-22 15:06:17 -07:00
self.play(ReplacementTransform(lhs_brace, circle))
self.play(ShowCreation(arrow))
self.play(Write(equals_dx))
2018-01-15 19:15:05 -08:00
self.wait()
2017-03-22 15:06:17 -07:00
self.play(*map(FadeOut, [circle, arrow]))
self.equals_dx = equals_dx
def put_step_on_curve(self):
dot = self.dot
point = dot.get_center()
graph = self.graphs[4]
arrow, dx_line, dx_line.label, dy_line, dy_line.label = self.step_group
#Find graph point at right x_val
arrow_end = arrow.get_end()
graph_points = [
graph.point_from_proportion(alpha)
for alpha in np.linspace(0, 1, 1000)
]
distances = np.apply_along_axis(
lambda p : np.abs(p[0] - arrow_end[0]),
1, graph_points
)
index = np.argmin(distances)
new_end_point = graph_points[index]
lil_rect = self.little_rectangle
self.play(
arrow.put_start_and_end_on, point, new_end_point,
dy_line.put_start_and_end_on,
dy_line.get_start(), new_end_point,
MaintainPositionRelativeTo(dy_line.label, dy_line),
lil_rect.shift, lil_rect.get_height()*DOWN/3,
run_time = 2
)
2018-01-15 19:15:05 -08:00
self.wait(2)
2017-03-22 15:06:17 -07:00
def emphasize_equality(self):
self.play(FocusOn(self.lhs))
2018-01-15 19:15:05 -08:00
self.wait()
2017-03-22 15:06:17 -07:00
for mob in self.lhs, self.rhs:
self.play(Indicate(mob))
2018-01-15 19:15:05 -08:00
self.wait()
2017-03-22 15:06:17 -07:00
def manipulate_to_find_dy_dx(self):
full_derivative = VGroup(
self.lhs_derivative, self.equals_dx
)
brace = Brace(full_derivative, DOWN, buff = SMALL_BUFF)
words = brace.get_text(
"Commonly, solve for", "$dy/dx$",
buff = SMALL_BUFF
)
2018-03-30 11:51:31 -07:00
VGroup(*words[1][:2]).set_color(RED)
VGroup(*words[1][3:]).set_color(GREEN)
2017-03-22 15:06:17 -07:00
words.add_background_rectangle()
self.play(GrowFromCenter(brace))
self.play(Write(words))
2018-01-15 19:15:05 -08:00
self.wait()
2017-03-22 15:06:17 -07:00
randy = Randolph()
randy.to_corner(DOWN+LEFT)
randy.look_at(full_derivative)
self.play(FadeIn(randy))
self.play(randy.change_mode, "confused")
self.play(Blink(randy))
2018-01-15 19:15:05 -08:00
self.wait(2)
2017-03-22 15:06:17 -07:00
self.play(randy.change_mode, "pondering")
self.play(Blink(randy))
2018-01-15 19:15:05 -08:00
self.wait()
2017-03-22 15:06:17 -07:00
class AskAboutNaturalLog(TeacherStudentsScene):
def construct(self):
exp_deriv = TexMobject("\\frac{d(e^x)}{dx} = e^x")
for i in 2, 3, 9, 10:
2018-03-30 11:51:31 -07:00
exp_deriv[i].set_color(BLUE)
2017-03-22 15:06:17 -07:00
log_deriv = TexMobject("\\frac{d(\\ln(x))}{dx} = ???")
2018-03-30 11:51:31 -07:00
VGroup(*log_deriv[2:2+5]).set_color(GREEN)
2017-03-22 15:06:17 -07:00
for deriv in exp_deriv, log_deriv:
deriv.next_to(self.get_teacher().get_corner(UP+LEFT), UP)
self.teacher_says(
"""We can find
new derivatives""",
target_mode = "hooray"
)
self.change_student_modes(*["happy"]*3)
self.play(RemovePiCreatureBubble(
self.get_teacher(),
target_mode = "raise_right_hand"
))
self.play(Write(exp_deriv))
2018-01-15 19:15:05 -08:00
self.wait()
2017-03-22 15:06:17 -07:00
self.play(
Write(log_deriv),
exp_deriv.next_to, log_deriv, UP, LARGE_BUFF,
*[
ApplyMethod(pi.change_mode, "confused")
for pi in self.get_pi_creatures()
]
)
2018-01-15 19:15:05 -08:00
self.wait(3)
2017-03-22 15:06:17 -07:00
class DerivativeOfNaturalLog(ZoomedScene):
CONFIG = {
"zoom_factor" : 10,
"zoomed_canvas_corner" : DOWN+RIGHT,
"example_color" : MAROON_B,
}
def construct(self):
should_skip_animations = self.skip_animations
self.skip_animations = True
self.add_plane()
self.draw_graph()
self.describe_as_implicit_curve()
self.slope_gives_derivative()
self.rearrange_equation()
self.take_derivative()
self.show_tiny_nudge()
self.note_derivatives()
self.solve_for_dy_dx()
self.skip_animations = should_skip_animations
self.show_slope_above_x()
def add_plane(self):
plane = NumberPlane()
plane.fade()
plane.add_coordinates()
self.add(plane)
self.plane = plane
def draw_graph(self):
graph = FunctionGraph(
np.log,
x_min = 0.01,
x_max = FRAME_X_RADIUS,
2017-03-22 15:06:17 -07:00
num_steps = 100
)
formula = TexMobject("y = \\ln(x)")
formula.next_to(ORIGIN, LEFT, buff = MED_LARGE_BUFF)
formula.to_edge(UP)
formula.add_background_rectangle()
self.add(formula)
self.play(ShowCreation(graph))
2018-01-15 19:15:05 -08:00
self.wait()
2017-03-22 15:06:17 -07:00
self.formula = formula
self.graph = graph
def describe_as_implicit_curve(self):
formula = self.formula #y = ln(x)
graph = self.graph
dot = Dot(color = self.example_color)
label = TexMobject("(x, y)")
label.add_background_rectangle()
2018-03-30 11:51:31 -07:00
label.set_color(self.example_color)
2017-03-22 15:06:17 -07:00
def update_dot(dot, alpha):
prop = interpolate(0.1, 0.7, alpha)
point = graph.point_from_proportion(prop)
dot.move_to(point)
return dot
def update_label(label):
point = dot.get_center()
vect = point - FRAME_Y_RADIUS*(DOWN+RIGHT)
2017-03-22 15:06:17 -07:00
vect = vect/np.linalg.norm(vect)
label.move_to(
point + vect*0.5*label.get_width()
)
update_dot(dot, 0)
update_label(label)
self.play(*map(FadeIn, [dot, label]))
self.play(
UpdateFromAlphaFunc(dot, update_dot),
UpdateFromFunc(label, update_label),
run_time = 3,
)
2018-01-15 19:15:05 -08:00
self.wait()
2017-03-22 15:06:17 -07:00
xy_start = VGroup(label[1][1], label[1][3]).copy()
xy_end = VGroup(formula[1][5], formula[1][0]).copy()
2018-03-30 11:51:31 -07:00
xy_end.set_color(self.example_color)
2017-03-22 15:06:17 -07:00
self.play(Transform(
xy_start, xy_end,
run_time = 2,
))
2018-01-15 19:15:05 -08:00
self.wait()
2017-03-22 15:06:17 -07:00
self.play(
UpdateFromAlphaFunc(dot, update_dot),
UpdateFromFunc(label, update_label),
run_time = 3,
rate_func = lambda t : 1-0.6*smooth(t),
)
self.play(*map(FadeOut, [xy_start, label]))
self.dot = dot
def slope_gives_derivative(self):
dot = self.dot
point = dot.get_center()
line = Line(LEFT, RIGHT).scale(FRAME_X_RADIUS)
2017-03-22 15:06:17 -07:00
slope = 1./point[0]
line.rotate(np.arctan(slope))
line.move_to(point)
new_point = line.point_from_proportion(0.6)
interim_point = point[0]*RIGHT + new_point[1]*UP
dy_line = Line(point, interim_point, color = RED)
dx_line = Line(interim_point, new_point, color = GREEN)
equation = TexMobject(
"\\text{Slope} = ",
"\\frac{dy}{dx} = ",
"\\frac{d(\\ln(x))}{dx}",
)
2018-03-30 11:51:31 -07:00
VGroup(*equation[1][:2]).set_color(RED)
VGroup(*equation[2][:8]).set_color(RED)
VGroup(*equation[1][3:5]).set_color(GREEN)
VGroup(*equation[2][-2:]).set_color(GREEN)
2017-03-22 15:06:17 -07:00
for part in equation:
rect = BackgroundRectangle(part)
rect.stretch_in_place(1.2, 0)
part.add_to_back(rect)
equation.scale(0.8)
equation.next_to(ORIGIN, RIGHT)
equation.to_edge(UP, buff = MED_SMALL_BUFF)
self.play(
GrowFromCenter(line),
Animation(dot)
)
self.play(ShowCreation(VGroup(dy_line, dx_line)))
for part in equation:
self.play(Write(part, run_time = 2))
2018-01-15 19:15:05 -08:00
self.wait()
2017-03-22 15:06:17 -07:00
self.dx_line, self.dy_line = dx_line, dy_line
self.slope_equation = equation
self.tangent_line = line
def rearrange_equation(self):
formula = self.formula
y, eq = formula[1][:2]
ln = VGroup(*formula[1][2:4])
x = formula[1][5]
new_formula = TexMobject("e", "^y", "=", "x")
e, new_y, new_eq, new_x = new_formula
new_formula.next_to(
formula, DOWN,
buff = MED_LARGE_BUFF,
)
rect = BackgroundRectangle(new_formula)
y = new_y.copy().replace(y)
self.play(Indicate(formula, scale_factor = 1))
self.play(ReplacementTransform(ln.copy(), e))
self.play(ReplacementTransform(y, new_y))
self.play(ReplacementTransform(eq.copy(), new_eq))
self.play(
FadeIn(rect),
Animation(VGroup(e, new_y, new_eq)),
ReplacementTransform(x.copy(), new_x)
)
2018-01-15 19:15:05 -08:00
self.wait(2)
2017-03-22 15:06:17 -07:00
for mob in e, new_y, new_x:
self.play(Indicate(mob))
2018-01-15 19:15:05 -08:00
self.wait()
2017-03-22 15:06:17 -07:00
self.new_formula = new_formula
def take_derivative(self):
new_formula = self.new_formula
e, y, eq, x = new_formula
derivative = TexMobject("e", "^y", "\\,dy", "=", "dx")
new_e, new_y, dy, new_eq, dx = derivative
derivative.next_to(new_formula, DOWN, MED_LARGE_BUFF)
derivative.add_background_rectangle()
2018-03-30 11:51:31 -07:00
dx.set_color(GREEN)
dy.set_color(RED)
2017-03-22 15:06:17 -07:00
pairs = [
(VGroup(e, y), VGroup(new_e, new_y)),
(new_y, dy),
(eq, new_eq),
(x, dx)
]
for start, target in pairs:
self.play(
ReplacementTransform(start.copy(), target)
)
self.play(FadeIn(derivative[0]), Animation(derivative[1]))
self.remove(derivative, pairs[0][1])
self.add(derivative)
2018-01-15 19:15:05 -08:00
self.wait()
2017-03-22 15:06:17 -07:00
self.derivative = derivative
def show_tiny_nudge(self):
dot = self.dot
point = dot.get_center()
dx_line = self.dx_line
dy_line = self.dy_line
group = VGroup(dot, dx_line, dy_line)
self.play(group.scale, 1./self.zoom_factor, point)
for line, tex, vect in (dx_line, "dx", UP), (dy_line, "dy", LEFT):
label = TexMobject(tex)
label.add_background_rectangle()
label.next_to(line, vect, buff = SMALL_BUFF)
2018-03-30 11:51:31 -07:00
label.set_color(line.get_color())
2017-03-22 15:06:17 -07:00
label.scale(
1./self.zoom_factor,
about_point = line.get_center()
)
line.label = label
self.activate_zooming()
lil_rect = self.little_rectangle
lil_rect.move_to(group)
lil_rect.scale_in_place(self.zoom_factor)
self.play(lil_rect.scale_in_place, 1./self.zoom_factor)
self.play(Write(dx_line.label))
self.play(Write(dy_line.label))
2018-01-15 19:15:05 -08:00
self.wait()
2017-03-22 15:06:17 -07:00
def note_derivatives(self):
e, y, dy, eq, dx = self.derivative[1]
self.play(FocusOn(e))
self.play(Indicate(VGroup(e, y, dy)))
2018-01-15 19:15:05 -08:00
self.wait()
2017-03-22 15:06:17 -07:00
self.play(Indicate(dx))
2018-01-15 19:15:05 -08:00
self.wait()
2017-03-22 15:06:17 -07:00
def solve_for_dy_dx(self):
e, y, dy, eq, dx = self.derivative[1]
ey_group = VGroup(e, y)
original_rect = self.derivative[0]
rearranged = TexMobject(
"{dy \\over ", " dx}", "=", "{1 \\over ", "e", "^y}"
)
new_dy, new_dx, new_eq, one_over, new_e, new_y = rearranged
new_ey_group = VGroup(new_e, new_y)
2018-03-30 11:51:31 -07:00
new_dx.set_color(GREEN)
new_dy.set_color(RED)
2017-03-22 15:06:17 -07:00
rearranged.shift(eq.get_center() - new_eq.get_center())
rearranged.shift(MED_SMALL_BUFF*DOWN)
new_rect = BackgroundRectangle(rearranged)
self.play(*[
ReplacementTransform(
m1, m2,
run_time = 2,
path_arc = -np.pi/2,
)
for m1, m2 in [
(original_rect, new_rect),
(dx, new_dx),
(dy, new_dy),
(eq, new_eq),
(ey_group, new_ey_group),
(e.copy(), one_over)
]
])
2018-01-15 19:15:05 -08:00
self.wait()
2017-03-22 15:06:17 -07:00
#Change denominator
e, y, eq, x = self.new_formula
ey_group = VGroup(e, y).copy()
2018-03-30 11:51:31 -07:00
ey_group.set_color(YELLOW)
2017-03-22 15:06:17 -07:00
x_copy = x.copy()
2018-03-30 11:51:31 -07:00
self.play(new_ey_group.set_color, YELLOW)
2017-03-22 15:06:17 -07:00
self.play(Transform(new_ey_group, ey_group))
self.play(
2018-03-30 11:51:31 -07:00
new_ey_group.set_color, WHITE,
x_copy.set_color, YELLOW
2017-03-22 15:06:17 -07:00
)
self.play(x_copy.next_to, one_over, DOWN, MED_SMALL_BUFF)
2018-01-15 19:15:05 -08:00
self.wait(2)
2017-03-22 15:06:17 -07:00
equals_one_over_x = VGroup(
new_eq, one_over, x_copy
).copy()
rect = BackgroundRectangle(equals_one_over_x)
rect.stretch_in_place(1.1, dim = 0)
equals_one_over_x.add_to_back(rect)
self.play(
equals_one_over_x.next_to,
self.slope_equation, RIGHT, 0,
run_time = 2
)
2018-01-15 19:15:05 -08:00
self.wait()
2017-03-22 15:06:17 -07:00
def show_slope_above_x(self):
line = self.tangent_line
start_x = line.get_center()[0]
target_x = 0.2
graph = FunctionGraph(
lambda x : 1./x,
x_min = 0.1,
x_max = FRAME_X_RADIUS,
2017-03-22 15:06:17 -07:00
num_steps = 100,
color = PINK,
)
def update_line(line, alpha):
x = interpolate(start_x, target_x, alpha)
point = x*RIGHT + np.log(x)*UP
angle = np.arctan(1./x)
line.rotate(angle - line.get_angle())
line.move_to(point)
self.play(UpdateFromAlphaFunc(
line, update_line,
rate_func = there_and_back,
run_time = 6
))
2018-01-15 19:15:05 -08:00
self.wait()
2017-03-22 15:06:17 -07:00
self.play(ShowCreation(graph, run_time = 3))
2018-01-15 19:15:05 -08:00
self.wait()
2017-03-22 15:06:17 -07:00
self.play(UpdateFromAlphaFunc(
line, update_line,
rate_func = there_and_back,
run_time = 6
))
2018-01-15 19:15:05 -08:00
self.wait()
2017-03-22 15:06:17 -07:00
class FinalWords(TeacherStudentsScene):
def construct(self):
words = TextMobject(
"This is a peek into \\\\",
"Multivariable", "calculus"
)
mvc = VGroup(*words[1:])
2018-03-30 11:51:31 -07:00
words.set_color_by_tex("Multivariable", YELLOW)
2017-03-22 15:06:17 -07:00
formula = TexMobject("f(x, y) = \\sin(x)y^2")
formula.next_to(self.get_teacher().get_corner(UP+LEFT), UP)
self.teacher_says(words)
self.change_student_modes("erm", "hooray", "sassy")
self.play(
FadeOut(self.teacher.bubble),
FadeOut(VGroup(*words[:1])),
mvc.to_corner, UP+LEFT,
self.teacher.change_mode, "raise_right_hand",
self.teacher.look_at, formula,
Write(formula, run_time = 2),
)
self.change_student_modes("pondering", "confused", "thinking")
2018-01-15 19:15:05 -08:00
self.wait(3)
2017-03-22 15:06:17 -07:00
##Show series
series = VideoSeries()
series.to_edge(UP)
video = series[5]
lim = TexMobject("\\lim_{h \\to 0} \\frac{f(x+h)-f(x)}{h}")
self.play(
FadeOut(mvc),
FadeOut(formula),
self.teacher.change_mode, "plain",
FadeIn(
series, run_time = 2,
submobject_mode = "lagged_start",
),
)
self.play(
2018-03-30 11:51:31 -07:00
video.set_color, YELLOW,
2017-03-22 15:06:17 -07:00
video.shift, video.get_height()*DOWN/2
)
lim.next_to(video, DOWN)
self.play(
Write(lim),
*it.chain(*[
[pi.change_mode, "pondering", pi.look_at, lim]
for pi in self.get_pi_creatures()
])
)
2018-01-15 19:15:05 -08:00
self.wait(3)
2017-03-22 15:06:17 -07:00
2017-04-25 13:17:58 -07:00
class Chapter6PatreonThanks(PatreonThanks):
2017-03-22 15:06:17 -07:00
CONFIG = {
"specific_patrons" : [
"Ali Yahya",
"Meshal Alshammari",
"CrypticSwarm ",
"Nathan Pellegrin",
"Karan Bhargava",
"Justin Helps",
"Ankit Agarwal",
"Yu Jun",
"Dave Nicponski",
"Damion Kistler",
"Juan Benet",
"Othman Alikhan",
"Justin Helps",
"Markus Persson",
"Dan Buchoff",
"Derek Dai",
"Joseph John Cox",
"Luc Ritchie",
"Daan Smedinga",
"Jonathan Eppele",
"Nils Schneider",
"Albert Nguyen",
"Mustafa Mahdi",
"Mathew Bramson",
"Guido Gambardella",
"Jerry Ling",
"Mark Govea",
"Vecht",
"Shimin Kuang",
"Rish Kundalia",
"Achille Brighton",
"Kirk Werklund",
"Ripta Pasay",
"Felipe Diniz",
]
}
class Thumbnail(AlternateExample):
def construct(self):
title = VGroup(*map(TextMobject, [
"Implicit", "Differentiation"
]))
title.arrange_submobjects(DOWN)
title.scale(3)
title.next_to(ORIGIN, UP)
for word in title:
word.add_background_rectangle()
self.add_plane()
self.draw_graph()
self.graphs.set_stroke(width = 8)
self.remove(self.formula)
self.add(title)