mirror of
https://github.com/3b1b/manim.git
synced 2025-04-13 09:47:07 +00:00
985 lines
32 KiB
Python
985 lines
32 KiB
Python
from big_ol_pile_of_manim_imports import *
|
|
from old_projects.eola.chapter5 import get_det_text
|
|
from old_projects.eola.chapter8 import *
|
|
|
|
|
|
class OpeningQuote(Scene):
|
|
def construct(self):
|
|
words = TextMobject(
|
|
"From [Grothendieck], I have also learned not",
|
|
"to take glory in the ",
|
|
"difficulty of a proof:",
|
|
"difficulty means we have not understood.",
|
|
"The idea is to be able to ",
|
|
"paint a landscape",
|
|
"in which the proof is obvious.",
|
|
arg_separator = " "
|
|
)
|
|
words.set_color_by_tex("difficulty of a proof:", RED)
|
|
words.set_color_by_tex("paint a landscape", GREEN)
|
|
words.set_width(FRAME_WIDTH - 2)
|
|
words.to_edge(UP)
|
|
author = TextMobject("-Pierre Deligne")
|
|
author.set_color(YELLOW)
|
|
author.next_to(words, DOWN, buff = 0.5)
|
|
|
|
self.play(FadeIn(words))
|
|
self.wait(4)
|
|
self.play(Write(author, run_time = 3))
|
|
self.wait()
|
|
|
|
class CrossProductSymbols(Scene):
|
|
def construct(self):
|
|
v_tex, w_tex, p_tex = get_vect_tex(*"vwp")
|
|
equation = TexMobject(
|
|
v_tex, "\\times", w_tex, "=", p_tex
|
|
)
|
|
equation.set_color_by_tex(v_tex, V_COLOR)
|
|
equation.set_color_by_tex(w_tex, W_COLOR)
|
|
equation.set_color_by_tex(p_tex, P_COLOR)
|
|
brace = Brace(equation[-1])
|
|
brace.stretch_to_fit_width(0.7)
|
|
vector_text = brace.get_text("Vector")
|
|
vector_text.set_color(RED)
|
|
self.add(equation)
|
|
self.play(*list(map(Write, [brace, vector_text])))
|
|
self.wait()
|
|
|
|
class DeterminantTrickCopy(DeterminantTrick):
|
|
pass
|
|
|
|
class BruteForceVerification(Scene):
|
|
def construct(self):
|
|
v = Matrix(["v_1", "v_2", "v_3"])
|
|
w = Matrix(["w_1", "w_2", "w_3"])
|
|
v1, v2, v3 = v.get_entries()
|
|
w1, w2, w3 = w.get_entries()
|
|
v.set_color(V_COLOR)
|
|
w.set_color(W_COLOR)
|
|
def get_term(e1, e2, e3, e4):
|
|
group = VGroup(
|
|
e1.copy(), e2.copy(),
|
|
TexMobject("-"),
|
|
e3.copy(), e4.copy(),
|
|
)
|
|
group.arrange()
|
|
return group
|
|
cross = Matrix(list(it.starmap(get_term, [
|
|
(v2, w3, v3, w2),
|
|
(v3, w1, v1, w3),
|
|
(v2, w3, v3, w2),
|
|
])))
|
|
cross_product = VGroup(
|
|
v.copy(), TexMobject("\\times"), w.copy(),
|
|
TexMobject("="), cross.copy()
|
|
)
|
|
cross_product.arrange()
|
|
cross_product.scale(0.75)
|
|
|
|
formula_word = TextMobject("Numerical formula")
|
|
computation_words = TextMobject("""
|
|
Facts you could (painfully)
|
|
verify computationally
|
|
""")
|
|
computation_words.scale(0.75)
|
|
h_line = Line(LEFT, RIGHT).scale(FRAME_X_RADIUS)
|
|
v_line = Line(UP, DOWN).scale(FRAME_Y_RADIUS)
|
|
computation_words.to_edge(UP, buff = MED_SMALL_BUFF/2)
|
|
h_line.next_to(computation_words, DOWN)
|
|
formula_word.next_to(h_line, UP, buff = MED_SMALL_BUFF)
|
|
computation_words.shift(FRAME_X_RADIUS*RIGHT/2)
|
|
formula_word.shift(FRAME_X_RADIUS*LEFT/2)
|
|
|
|
cross_product.next_to(formula_word, DOWN, buff = LARGE_BUFF)
|
|
|
|
self.add(formula_word, computation_words)
|
|
self.play(
|
|
ShowCreation(h_line),
|
|
ShowCreation(v_line),
|
|
Write(cross_product)
|
|
)
|
|
|
|
v_tex, w_tex = get_vect_tex(*"vw")
|
|
v_dot, w_dot = [
|
|
TexMobject(
|
|
tex, "\\cdot",
|
|
"(", v_tex, "\\times", w_tex, ")",
|
|
"= 0"
|
|
)
|
|
for tex in (v_tex, w_tex)
|
|
]
|
|
theta_def = TexMobject(
|
|
"\\theta",
|
|
"= \\cos^{-1} \\big(", v_tex, "\\cdot", w_tex, "/",
|
|
"(||", v_tex, "||", "\\cdot", "||", w_tex, "||)", "\\big)"
|
|
)
|
|
|
|
length_check = TexMobject(
|
|
"||", "(", v_tex, "\\times", w_tex, ")", "|| = ",
|
|
"(||", v_tex, "||)",
|
|
"(||", w_tex, "||)",
|
|
"\\sin(", "\\theta", ")"
|
|
)
|
|
last_point = h_line.get_center()+FRAME_X_RADIUS*RIGHT/2
|
|
max_width = FRAME_X_RADIUS-1
|
|
for mob in v_dot, w_dot, theta_def, length_check:
|
|
mob.set_color_by_tex(v_tex, V_COLOR)
|
|
mob.set_color_by_tex(w_tex, W_COLOR)
|
|
mob.set_color_by_tex("\\theta", GREEN)
|
|
mob.next_to(last_point, DOWN, buff = MED_SMALL_BUFF)
|
|
if mob.get_width() > max_width:
|
|
mob.set_width(max_width)
|
|
last_point = mob
|
|
self.play(FadeIn(mob))
|
|
self.wait()
|
|
|
|
class ButWeCanDoBetter(TeacherStudentsScene):
|
|
def construct(self):
|
|
self.teacher_says("But we can do \\\\ better than that")
|
|
self.change_student_modes(*["happy"]*3)
|
|
self.random_blink(3)
|
|
|
|
class Prerequisites(Scene):
|
|
def construct(self):
|
|
title = TextMobject("Prerequisites")
|
|
title.to_edge(UP)
|
|
title.set_color(YELLOW)
|
|
|
|
rect = Rectangle(width = 16, height = 9, color = BLUE)
|
|
rect.set_width(FRAME_X_RADIUS - 1)
|
|
left_rect, right_rect = [
|
|
rect.copy().shift(DOWN/2).to_edge(edge)
|
|
for edge in (LEFT, RIGHT)
|
|
]
|
|
chapter5 = TextMobject("""
|
|
\\centering
|
|
Chapter 5
|
|
Determinants
|
|
""")
|
|
chapter7 = TextMobject("""
|
|
\\centering
|
|
Chapter 7:
|
|
Dot products and duality
|
|
""")
|
|
|
|
self.add(title)
|
|
for chapter, rect in (chapter5, left_rect), (chapter7, right_rect):
|
|
if chapter.get_width() > rect.get_width():
|
|
chapter.set_width(rect.get_width())
|
|
chapter.next_to(rect, UP)
|
|
self.play(
|
|
Write(chapter5),
|
|
ShowCreation(left_rect)
|
|
)
|
|
self.play(
|
|
Write(chapter7),
|
|
ShowCreation(right_rect)
|
|
)
|
|
self.wait()
|
|
|
|
class DualityReview(TeacherStudentsScene):
|
|
def construct(self):
|
|
words = TextMobject("Quick", "duality", "review")
|
|
words[1].set_color_by_gradient(BLUE, YELLOW)
|
|
self.teacher_says(words, target_mode = "surprised")
|
|
self.change_student_modes("pondering")
|
|
self.random_blink(2)
|
|
|
|
class DotProductToTransformSymbol(Scene):
|
|
CONFIG = {
|
|
"vect_coords" : [2, 1]
|
|
}
|
|
def construct(self):
|
|
v_mob = TexMobject(get_vect_tex("v"))
|
|
v_mob.set_color(V_COLOR)
|
|
|
|
matrix = Matrix([self.vect_coords])
|
|
vector = Matrix(self.vect_coords)
|
|
matrix.set_column_colors(X_COLOR, Y_COLOR)
|
|
vector.set_column_colors(YELLOW)
|
|
_input = Matrix(["x", "y"])
|
|
_input.get_entries().set_color_by_gradient(X_COLOR, Y_COLOR)
|
|
left_input, right_input = [_input.copy() for x in range(2)]
|
|
dot, equals = list(map(TexMobject, ["\\cdot", "="]))
|
|
equation = VGroup(
|
|
vector, dot, left_input, equals,
|
|
matrix, right_input
|
|
)
|
|
equation.arrange()
|
|
left_brace = Brace(VGroup(vector, left_input))
|
|
right_brace = Brace(matrix, UP)
|
|
left_words = left_brace.get_text("Dot product")
|
|
right_words = right_brace.get_text("Transform")
|
|
right_words.set_width(right_brace.get_width())
|
|
|
|
right_v_brace = Brace(right_input, UP)
|
|
right_v_mob = v_mob.copy()
|
|
right_v_brace.put_at_tip(right_v_mob)
|
|
right_input.add(right_v_brace, right_v_mob)
|
|
left_v_brace = Brace(left_input, UP)
|
|
left_v_mob = v_mob.copy()
|
|
left_v_brace.put_at_tip(left_v_mob)
|
|
left_input.add(left_v_brace, left_v_mob)
|
|
|
|
|
|
self.add(matrix, right_input)
|
|
self.play(
|
|
GrowFromCenter(right_brace),
|
|
Write(right_words, run_time = 1)
|
|
)
|
|
self.wait()
|
|
self.play(
|
|
Write(equals),
|
|
Write(dot),
|
|
Transform(matrix.copy(), vector),
|
|
Transform(right_input.copy(), left_input)
|
|
)
|
|
self.play(
|
|
GrowFromCenter(left_brace),
|
|
Write(left_words, run_time = 1)
|
|
)
|
|
self.wait()
|
|
|
|
class MathematicalWild(Scene):
|
|
def construct(self):
|
|
title = TextMobject("In the mathematical wild")
|
|
title.to_edge(UP)
|
|
self.add(title)
|
|
|
|
randy = Randolph()
|
|
randy.shift(DOWN)
|
|
bubble = ThoughtBubble(width = 5, height = 4)
|
|
bubble.write("""
|
|
\\centering
|
|
Some linear
|
|
transformation
|
|
to the number line
|
|
""")
|
|
bubble.content.set_color(BLUE)
|
|
bubble.content.shift(MED_SMALL_BUFF*UP/2)
|
|
bubble.remove(*bubble[:-1])
|
|
bubble.add(bubble.content)
|
|
bubble.next_to(randy.get_corner(UP+RIGHT), RIGHT)
|
|
vector = Vector([1, 2])
|
|
vector.move_to(randy.get_corner(UP+LEFT), aligned_edge = DOWN+LEFT)
|
|
dual_words = TextMobject("Dual vector")
|
|
dual_words.set_color_by_gradient(BLUE, YELLOW)
|
|
dual_words.next_to(vector, LEFT)
|
|
|
|
self.add(randy)
|
|
self.play(Blink(randy))
|
|
self.play(FadeIn(bubble))
|
|
self.play(randy.change_mode, "sassy")
|
|
self.play(Blink(randy))
|
|
self.wait()
|
|
self.play(randy.look, UP+LEFT)
|
|
self.play(
|
|
ShowCreation(vector),
|
|
randy.change_mode, "raise_right_hand"
|
|
)
|
|
self.wait()
|
|
self.play(Write(dual_words))
|
|
self.play(Blink(randy))
|
|
self.wait()
|
|
|
|
class ThreeStepPlan(Scene):
|
|
def construct(self):
|
|
title = TextMobject("The plan")
|
|
title.set_color(YELLOW)
|
|
title.to_edge(UP)
|
|
h_line = Line(LEFT, RIGHT).scale(FRAME_X_RADIUS)
|
|
h_line.next_to(title, DOWN)
|
|
|
|
v_tex, w_tex = get_vect_tex(*"vw")
|
|
v_text, w_text, cross_text = [
|
|
"$%s$"%s
|
|
for s in (v_tex, w_tex, v_tex + "\\times" + w_tex)
|
|
]
|
|
steps = [
|
|
TextMobject(
|
|
"1. Define a 3d-to-1d", "linear \\\\", "transformation",
|
|
"in terms of", v_text, "and", w_text
|
|
),
|
|
TextMobject(
|
|
"2. Find its", "dual vector"
|
|
),
|
|
TextMobject(
|
|
"3. Show that this dual is", cross_text
|
|
)
|
|
]
|
|
linear, transformation = steps[0][1:1+2]
|
|
steps[0].set_color_by_tex(v_text, V_COLOR)
|
|
steps[0].set_color_by_tex(w_text, W_COLOR)
|
|
steps[1][1].set_color_by_gradient(BLUE, YELLOW)
|
|
steps[2].set_color_by_tex(cross_text, P_COLOR)
|
|
VGroup(*steps).arrange(
|
|
DOWN, aligned_edge = LEFT, buff = LARGE_BUFF
|
|
).next_to(h_line, DOWN, buff = MED_SMALL_BUFF)
|
|
|
|
self.add(title)
|
|
self.play(ShowCreation(h_line))
|
|
for step in steps:
|
|
self.play(Write(step, run_time = 2))
|
|
self.wait()
|
|
|
|
linear_transformation = TextMobject("Linear", "transformation")
|
|
linear_transformation.next_to(h_line, DOWN, MED_SMALL_BUFF)
|
|
det = self.get_det()
|
|
rect = Rectangle(width = 16, height = 9, color = BLUE)
|
|
rect.set_height(3.5)
|
|
left_right_arrow = TexMobject("\\Leftrightarrow")
|
|
left_right_arrow.shift(DOWN)
|
|
det.next_to(left_right_arrow, LEFT)
|
|
rect.next_to(left_right_arrow, RIGHT)
|
|
|
|
steps[0].remove(linear, transformation)
|
|
self.play(
|
|
Transform(
|
|
VGroup(linear, transformation),
|
|
linear_transformation
|
|
),
|
|
*list(map(FadeOut, steps))
|
|
)
|
|
self.wait()
|
|
self.play(Write(left_right_arrow))
|
|
self.play(Write(det))
|
|
self.play(ShowCreation(rect))
|
|
self.wait(0)
|
|
|
|
def get_det(self):
|
|
matrix = Matrix(np.array([
|
|
["\\hat{\\imath}", "\\hat{\\jmath}", "\\hat{k}"],
|
|
["v_%d"%d for d in range(1, 4)],
|
|
["w_%d"%d for d in range(1, 4)],
|
|
]).T)
|
|
matrix.set_column_colors(X_COLOR, V_COLOR, W_COLOR)
|
|
matrix.get_mob_matrix()[1, 0].set_color(Y_COLOR)
|
|
matrix.get_mob_matrix()[2, 0].set_color(Z_COLOR)
|
|
VGroup(*matrix.get_mob_matrix()[1, 1:]).shift(0.15*DOWN)
|
|
VGroup(*matrix.get_mob_matrix()[2, 1:]).shift(0.35*DOWN)
|
|
det_text = get_det_text(matrix)
|
|
det_text.add(matrix)
|
|
return det_text
|
|
|
|
class DefineDualTransform(Scene):
|
|
def construct(self):
|
|
self.add_title()
|
|
self.show_triple_cross_product()
|
|
self.write_function()
|
|
self.introduce_dual_vector()
|
|
self.expand_dot_product()
|
|
self.ask_question()
|
|
|
|
def add_title(self):
|
|
title = TextMobject("What a student might think")
|
|
title.not_real = TextMobject("Not the real cross product")
|
|
for mob in title, title.not_real:
|
|
mob.set_width(FRAME_X_RADIUS - 1)
|
|
mob.set_color(RED)
|
|
mob.to_edge(UP)
|
|
self.add(title)
|
|
self.title = title
|
|
|
|
def show_triple_cross_product(self):
|
|
colors = [WHITE, ORANGE, W_COLOR]
|
|
tex_mobs = list(map(TexMobject, get_vect_tex(*"uvw")))
|
|
u_tex, v_tex, w_tex = tex_mobs
|
|
arrays = [
|
|
Matrix(["%s_%d"%(s, d) for d in range(1, 4)])
|
|
for s in "uvw"
|
|
]
|
|
defs_equals = VGroup()
|
|
definitions = VGroup()
|
|
for array, tex_mob, color in zip(arrays, tex_mobs, colors):
|
|
array.set_column_colors(color)
|
|
tex_mob.set_color(color)
|
|
equals = TexMobject("=")
|
|
definition = VGroup(tex_mob, equals, array)
|
|
definition.arrange(RIGHT)
|
|
definitions.add(definition)
|
|
defs_equals.add(equals)
|
|
definitions.arrange(buff = MED_SMALL_BUFF)
|
|
definitions.shift(2*DOWN)
|
|
|
|
mobs_with_targets = list(it.chain(
|
|
tex_mobs, *[a.get_entries() for a in arrays]
|
|
))
|
|
for mob in mobs_with_targets:
|
|
mob.target = mob.copy()
|
|
matrix = Matrix(np.array([
|
|
[e.target for e in array.get_entries()]
|
|
for array in arrays
|
|
]).T)
|
|
det_text = get_det_text(matrix, background_rect = False)
|
|
syms = times1, times2, equals = [
|
|
TexMobject(sym)
|
|
for sym in ("\\times", "\\times", "=",)
|
|
]
|
|
triple_cross = VGroup(
|
|
u_tex.target, times1, v_tex.target, times2, w_tex.target, equals
|
|
)
|
|
triple_cross.arrange()
|
|
|
|
final_mobs = VGroup(triple_cross, VGroup(det_text, matrix))
|
|
final_mobs.arrange()
|
|
final_mobs.next_to(self.title, DOWN, buff = MED_SMALL_BUFF)
|
|
|
|
for mob in definitions, final_mobs:
|
|
mob.set_width(FRAME_X_RADIUS - 1)
|
|
|
|
for array in arrays:
|
|
brackets = array.get_brackets()
|
|
brackets.target = matrix.get_brackets()
|
|
mobs_with_targets.append(brackets)
|
|
for def_equals in defs_equals:
|
|
def_equals.target = equals
|
|
mobs_with_targets.append(def_equals)
|
|
|
|
self.play(FadeIn(
|
|
definitions,
|
|
run_time = 2,
|
|
lag_ratio = 0.5
|
|
))
|
|
self.wait(2)
|
|
self.play(*[
|
|
Transform(mob.copy(), mob.target)
|
|
for mob in tex_mobs
|
|
] + [
|
|
Write(times1),
|
|
Write(times2),
|
|
])
|
|
triple_cross.add(*self.get_mobjects_from_last_animation()[:3])
|
|
self.play(*[
|
|
Transform(mob.copy(), mob.target)
|
|
for mob in mobs_with_targets
|
|
if mob not in tex_mobs
|
|
])
|
|
u_entries = self.get_mobjects_from_last_animation()[:3]
|
|
v_entries = self.get_mobjects_from_last_animation()[3:6]
|
|
w_entries = self.get_mobjects_from_last_animation()[6:9]
|
|
self.play(Write(det_text))
|
|
self.wait(2)
|
|
|
|
self.det_text = det_text
|
|
self.definitions = definitions
|
|
self.u_entries = u_entries
|
|
self.v_entries = v_entries
|
|
self.w_entries = w_entries
|
|
self.matrix = matrix
|
|
self.triple_cross = triple_cross
|
|
self.v_tex, self.w_tex = v_tex, w_tex
|
|
self.equals = equals
|
|
|
|
def write_function(self):
|
|
brace = Brace(self.det_text, DOWN)
|
|
number_text = brace.get_text("Number")
|
|
self.play(Transform(self.title, self.title.not_real))
|
|
self.wait()
|
|
self.play(FadeOut(self.definitions))
|
|
self.play(
|
|
GrowFromCenter(brace),
|
|
Write(number_text)
|
|
)
|
|
self.wait()
|
|
|
|
x, y, z = variables = list(map(TexMobject, "xyz"))
|
|
for var, entry in zip(variables, self.u_entries):
|
|
var.scale(0.8)
|
|
var.move_to(entry)
|
|
entry.target = var
|
|
brace.target = Brace(z)
|
|
brace.target.stretch_to_fit_width(0.5)
|
|
number_text.target = brace.target.get_text("Variable")
|
|
v_brace = Brace(self.matrix.get_mob_matrix()[0, 1], UP)
|
|
w_brace = Brace(self.matrix.get_mob_matrix()[0, 2], UP)
|
|
for vect_brace, tex in (v_brace, self.v_tex), (w_brace, self.w_tex):
|
|
vect_brace.stretch_to_fit_width(brace.target.get_width())
|
|
new_tex = tex.copy()
|
|
vect_brace.put_at_tip(new_tex)
|
|
vect_brace.tex = new_tex
|
|
func_tex = TexMobject(
|
|
"f\\left(%s\\right)"%matrix_to_tex_string(list("xyz"))
|
|
)
|
|
func_tex.scale(0.7)
|
|
func_input = Matrix(list("xyz"))
|
|
func_input_template = VGroup(*func_tex[3:-2])
|
|
func_input.set_height(func_input_template.get_height())
|
|
func_input.next_to(VGroup(*func_tex[:3]), RIGHT)
|
|
VGroup(*func_tex[-2:]).next_to(func_input, RIGHT)
|
|
func_tex[0].scale_in_place(1.5)
|
|
|
|
func_tex = VGroup(
|
|
VGroup(*[func_tex[i] for i in (0, 1, 2, -2, -1)]),
|
|
func_input
|
|
)
|
|
func_tex.next_to(self.equals, LEFT)
|
|
|
|
self.play(
|
|
FadeOut(self.title),
|
|
FadeOut(self.triple_cross),
|
|
*[
|
|
Transform(mob, mob.target)
|
|
for mob in [brace, number_text]
|
|
]
|
|
)
|
|
self.play(*[
|
|
Transform(mob, mob.target)
|
|
for mob in self.u_entries
|
|
])
|
|
self.play(*[
|
|
Write(VGroup(vect_brace, vect_brace.tex))
|
|
for vect_brace in (v_brace, w_brace)
|
|
])
|
|
self.wait()
|
|
self.play(Write(func_tex))
|
|
self.wait()
|
|
|
|
self.func_tex = func_tex
|
|
self.variables_text = VGroup(brace, number_text)
|
|
|
|
def introduce_dual_vector(self):
|
|
everything = VGroup(*self.get_mobjects())
|
|
colors = [X_COLOR, Y_COLOR, Z_COLOR]
|
|
q_marks = VGroup(*list(map(TextMobject, "???")))
|
|
q_marks.scale(2)
|
|
q_marks.set_color_by_gradient(*colors)
|
|
|
|
title = VGroup(TextMobject("This function is linear"))
|
|
title.set_color(GREEN)
|
|
title.to_edge(UP)
|
|
matrix = Matrix([list(q_marks.copy())])
|
|
matrix.set_height(self.func_tex.get_height()/2)
|
|
dual_vector = Matrix(list(q_marks))
|
|
dual_vector.set_height(self.func_tex.get_height())
|
|
dual_vector.get_brackets()[0].shift(0.2*LEFT)
|
|
dual_vector.get_entries().shift(0.1*LEFT)
|
|
dual_vector.scale(1.25)
|
|
dual_dot = VGroup(
|
|
dual_vector,
|
|
TexMobject("\\cdot").next_to(dual_vector)
|
|
)
|
|
matrix_words = TextMobject("""
|
|
$1 \\times 3$ matrix encoding the
|
|
3d-to-1d linear transformation
|
|
""")
|
|
|
|
self.play(
|
|
Write(title, run_time = 2),
|
|
everything.shift, DOWN
|
|
)
|
|
self.remove(everything)
|
|
self.add(*everything)
|
|
self.wait()
|
|
|
|
func, func_input = self.func_tex
|
|
func_input.target = func_input.copy()
|
|
func_input.target.scale(1.2)
|
|
func_input.target.move_to(self.func_tex, aligned_edge = RIGHT)
|
|
matrix.next_to(func_input.target, LEFT)
|
|
dual_dot.next_to(func_input.target, LEFT)
|
|
matrix_words.next_to(matrix, DOWN, buff = 1.5)
|
|
matrix_words.shift_onto_screen()
|
|
matrix_arrow = Arrow(
|
|
matrix_words.get_top(),
|
|
matrix.get_bottom(),
|
|
color = WHITE
|
|
)
|
|
|
|
self.play(
|
|
Transform(func, matrix),
|
|
MoveToTarget(func_input),
|
|
FadeOut(self.variables_text),
|
|
)
|
|
self.wait()
|
|
self.play(
|
|
Write(matrix_words),
|
|
ShowCreation(matrix_arrow)
|
|
)
|
|
self.wait(2)
|
|
self.play(*list(map(FadeOut, [matrix_words, matrix_arrow])))
|
|
self.play(
|
|
Transform(func, dual_vector),
|
|
Write(dual_dot[1])
|
|
)
|
|
self.wait()
|
|
|
|
p_coords = VGroup(*list(map(TexMobject, [
|
|
"p_%d"%d for d in range(1, 4)
|
|
])))
|
|
p_coords.set_color(RED)
|
|
p_array = Matrix(list(p_coords))
|
|
p_array.set_height(dual_vector.get_height())
|
|
p_array.move_to(dual_vector, aligned_edge = RIGHT)
|
|
p_brace = Brace(p_array, UP)
|
|
p_tex = TexMobject(get_vect_tex("p"))
|
|
p_tex.set_color(P_COLOR)
|
|
p_brace.put_at_tip(p_tex)
|
|
|
|
self.play(
|
|
GrowFromCenter(p_brace),
|
|
Write(p_tex)
|
|
)
|
|
self.play(Transform(
|
|
func, p_array,
|
|
run_time = 2,
|
|
lag_ratio = 0.5
|
|
))
|
|
self.remove(func)
|
|
self.add(p_array)
|
|
self.wait()
|
|
self.play(FadeOut(title))
|
|
self.wait()
|
|
|
|
self.p_array = p_array
|
|
self.input_array = func_input
|
|
|
|
def expand_dot_product(self):
|
|
everything = VGroup(*self.get_mobjects())
|
|
self.play(everything.to_edge, UP)
|
|
self.remove(everything)
|
|
self.add(*everything)
|
|
to_fade = VGroup()
|
|
|
|
p_entries = self.p_array.get_entries()
|
|
input_entries = self.input_array.get_entries()
|
|
dot_components = VGroup()
|
|
for p, x, i in zip(p_entries, input_entries, it.count()):
|
|
if i == 2:
|
|
x.sym = TexMobject("=")
|
|
else:
|
|
x.sym = TexMobject("+")
|
|
p.sym = TexMobject("\\cdot")
|
|
p.target = p.copy().scale(2)
|
|
x.target = x.copy().scale(2)
|
|
component = VGroup(p.target, p.sym, x.target, x.sym)
|
|
component.arrange()
|
|
dot_components.add(component)
|
|
dot_components.arrange()
|
|
dot_components.next_to(ORIGIN, LEFT)
|
|
dot_components.shift(1.5*DOWN)
|
|
dot_arrow = Arrow(self.p_array.get_corner(DOWN+RIGHT), dot_components)
|
|
to_fade.add(dot_arrow)
|
|
self.play(ShowCreation(dot_arrow))
|
|
new_ps = VGroup()
|
|
for p, x in zip(p_entries, input_entries):
|
|
self.play(
|
|
MoveToTarget(p.copy()),
|
|
MoveToTarget(x.copy()),
|
|
Write(p.sym),
|
|
Write(x.sym)
|
|
)
|
|
mobs = self.get_mobjects_from_last_animation()
|
|
new_ps.add(mobs[0])
|
|
to_fade.add(*mobs[1:])
|
|
self.wait()
|
|
|
|
x, y, z = self.u_entries
|
|
v1, v2, v3 = self.v_entries
|
|
w1, w2, w3 = self.w_entries
|
|
cross_components = VGroup()
|
|
quints = [
|
|
(x, v2, w3, v3, w2),
|
|
(y, v3, w1, v1, w3),
|
|
(z, v1, w2, v2, w1),
|
|
]
|
|
quints = [
|
|
[m.copy() for m in quint]
|
|
for quint in quints
|
|
]
|
|
for i, quint in enumerate(quints):
|
|
sym_strings = ["(", "\\cdot", "-", "\\cdot", ")"]
|
|
if i < 2:
|
|
sym_strings[-1] += "+"
|
|
syms = list(map(TexMobject, sym_strings))
|
|
for mob, sym in zip(quint, syms):
|
|
mob.target = mob.copy()
|
|
mob.target.scale(1.5)
|
|
mob.sym = sym
|
|
quint_targets = [mob.target for mob in quint]
|
|
component = VGroup(*it.chain(*list(zip(quint_targets, syms))))
|
|
component.arrange()
|
|
cross_components.add(component)
|
|
to_fade.add(syms[0], syms[-1], quint[0])
|
|
cross_components.arrange(DOWN, aligned_edge = LEFT, buff = MED_SMALL_BUFF)
|
|
cross_components.next_to(dot_components, RIGHT)
|
|
for quint in quints:
|
|
self.play(*[
|
|
ApplyMethod(mob.set_color, YELLOW)
|
|
for mob in quint
|
|
])
|
|
self.wait(0.5)
|
|
self.play(*[
|
|
MoveToTarget(mob)
|
|
for mob in quint
|
|
] + [
|
|
Write(mob.sym)
|
|
for mob in quint
|
|
])
|
|
self.wait()
|
|
self.play(
|
|
ApplyFunction(
|
|
lambda m : m.arrange(
|
|
DOWN, buff = MED_SMALL_BUFF+SMALL_BUFF
|
|
).next_to(cross_components, LEFT),
|
|
new_ps
|
|
),
|
|
*list(map(FadeOut, to_fade))
|
|
)
|
|
self.play(*[
|
|
Write(TexMobject("=").next_to(p, buff = 2*SMALL_BUFF))
|
|
for p in new_ps
|
|
])
|
|
equals = self.get_mobjects_from_last_animation()
|
|
self.wait(2)
|
|
|
|
everything = everything.copy()
|
|
self.play(
|
|
FadeOut(VGroup(*self.get_mobjects())),
|
|
Animation(everything)
|
|
)
|
|
self.clear()
|
|
self.add(everything)
|
|
|
|
def ask_question(self):
|
|
everything = VGroup(*self.get_mobjects())
|
|
p_tex = "$%s$"%get_vect_tex("p")
|
|
question = TextMobject(
|
|
"What vector",
|
|
p_tex,
|
|
"has \\\\ the property that"
|
|
)
|
|
question.to_edge(UP)
|
|
question.set_color(YELLOW)
|
|
question.set_color_by_tex(p_tex, P_COLOR)
|
|
everything.target = everything.copy()
|
|
everything.target.next_to(
|
|
question, DOWN, buff = MED_SMALL_BUFF
|
|
)
|
|
self.play(
|
|
MoveToTarget(everything),
|
|
Write(question)
|
|
)
|
|
self.wait()
|
|
|
|
class WhyAreWeDoingThis(TeacherStudentsScene):
|
|
def construct(self):
|
|
self.student_says(
|
|
"Um...why are \\\\ we doing this?",
|
|
target_mode = "confused"
|
|
)
|
|
self.random_blink()
|
|
self.play(self.get_teacher().change_mode, "erm")
|
|
self.change_student_modes("plain", "confused", "raise_left_hand")
|
|
self.random_blink()
|
|
self.change_student_modes("pondering", "confused", "raise_left_hand")
|
|
self.random_blink(5)
|
|
|
|
class ThreeDTripleCrossProduct(Scene):
|
|
pass #Simple parallelepiped
|
|
|
|
class ThreeDMovingVariableVector(Scene):
|
|
pass #white u moves around
|
|
|
|
class ThreeDMovingVariableVectorWithCrossShowing(Scene):
|
|
pass #white u moves around, red p is present
|
|
|
|
class NowForTheCoolPart(TeacherStudentsScene):
|
|
def construct(self):
|
|
self.teacher_says(
|
|
"Now for the\\\\",
|
|
"cool part"
|
|
)
|
|
self.change_student_modes(*["happy"]*3)
|
|
self.random_blink(2)
|
|
self.teacher_says(
|
|
"Let's answer the same question,\\\\",
|
|
"but this time geometrically"
|
|
)
|
|
self.change_student_modes(*["pondering"]*3)
|
|
self.random_blink(2)
|
|
|
|
class ThreeDDotProductProjection(Scene):
|
|
pass #
|
|
|
|
class DotProductWords(Scene):
|
|
def construct(self):
|
|
p_tex = "$%s$"%get_vect_tex("p")
|
|
p_mob = TextMobject(p_tex)
|
|
p_mob.scale(1.5)
|
|
p_mob.set_color(P_COLOR)
|
|
input_array = Matrix(list("xyz"))
|
|
dot_product = VGroup(p_mob, Dot(radius = 0.07), input_array)
|
|
dot_product.arrange(buff = MED_SMALL_BUFF/2)
|
|
equals = TexMobject("=")
|
|
dot_product.next_to(equals, LEFT)
|
|
words = VGroup(*it.starmap(TextMobject, [
|
|
("(Length of projection)",),
|
|
("(Length of ", p_tex, ")",)
|
|
]))
|
|
times = TexMobject("\\times")
|
|
words[1].set_color_by_tex(p_tex, P_COLOR)
|
|
words[0].next_to(equals, RIGHT)
|
|
words[1].next_to(words[0], DOWN, aligned_edge = LEFT)
|
|
times.next_to(words[0], RIGHT)
|
|
|
|
everyone = VGroup(dot_product, equals, times, words)
|
|
everyone.center().set_width(FRAME_X_RADIUS - 1)
|
|
self.add(dot_product)
|
|
self.play(Write(equals))
|
|
self.play(Write(words[0]))
|
|
self.wait()
|
|
self.play(
|
|
Write(times),
|
|
Write(words[1])
|
|
)
|
|
self.wait()
|
|
|
|
class ThreeDProjectToPerpendicular(Scene):
|
|
pass #
|
|
|
|
class GeometricVolumeWords(Scene):
|
|
def construct(self):
|
|
v_tex, w_tex = [
|
|
"$%s$"%s
|
|
for s in get_vect_tex(*"vw")
|
|
]
|
|
|
|
words = VGroup(
|
|
TextMobject("(Area of", "parallelogram", ")$\\times$"),
|
|
TextMobject(
|
|
"(Component of $%s$"%matrix_to_tex_string(list("xyz")),
|
|
"perpendicular to", v_tex, "and", w_tex, ")"
|
|
)
|
|
)
|
|
words[0].set_color_by_tex("parallelogram", BLUE)
|
|
words[1].set_color_by_tex(v_tex, ORANGE)
|
|
words[1].set_color_by_tex(w_tex, W_COLOR)
|
|
words.arrange(RIGHT)
|
|
words.set_width(FRAME_WIDTH - 1)
|
|
words.to_edge(DOWN, buff = SMALL_BUFF)
|
|
for word in words:
|
|
self.play(Write(word))
|
|
self.wait()
|
|
|
|
class WriteXYZ(Scene):
|
|
def construct(self):
|
|
self.play(Write(Matrix(list("xyz"))))
|
|
self.wait()
|
|
|
|
class ThreeDDotProductWithCross(Scene):
|
|
pass
|
|
|
|
class CrossVectorEmphasisWords(Scene):
|
|
def construct(self):
|
|
v_tex, w_tex = ["$%s$"%s for s in get_vect_tex(*"vw")]
|
|
words = [
|
|
TextMobject("Perpendicular to", v_tex, "and", w_tex),
|
|
TextMobject("Length = (Area of ", "parallelogram", ")")
|
|
]
|
|
for word in words:
|
|
word.set_color_by_tex(v_tex, ORANGE)
|
|
word.set_color_by_tex(w_tex, W_COLOR)
|
|
word.set_color_by_tex("parallelogram", BLUE)
|
|
self.play(Write(word))
|
|
self.wait()
|
|
self.play(FadeOut(word))
|
|
|
|
class NextVideo(Scene):
|
|
def construct(self):
|
|
title = TextMobject("""
|
|
Next video: Change of basis
|
|
""")
|
|
title.to_edge(UP, buff = MED_SMALL_BUFF/2)
|
|
rect = Rectangle(width = 16, height = 9, color = BLUE)
|
|
rect.set_height(6)
|
|
rect.next_to(title, DOWN)
|
|
|
|
self.add(title)
|
|
self.play(ShowCreation(rect))
|
|
self.wait()
|
|
|
|
class ChangeOfBasisPreview(LinearTransformationScene):
|
|
CONFIG = {
|
|
"include_background_plane" : False,
|
|
"foreground_plane_kwargs" : {
|
|
"x_radius" : FRAME_WIDTH,
|
|
"y_radius" : FRAME_WIDTH,
|
|
"secondary_line_ratio" : 0
|
|
},
|
|
"t_matrix" : [[2, 1], [-1, 1]],
|
|
"i_target_color" : YELLOW,
|
|
"j_target_color" : MAROON_B,
|
|
"sum_color" : PINK,
|
|
"vector" : [-1, 2],
|
|
}
|
|
def construct(self):
|
|
randy = Randolph()
|
|
pinky = Mortimer(color = PINK)
|
|
randy.to_corner(DOWN+LEFT)
|
|
pinky.to_corner(DOWN+RIGHT)
|
|
self.plane.fade()
|
|
|
|
self.add_foreground_mobject(randy, pinky)
|
|
coords = Matrix(self.vector)
|
|
coords.add_to_back(BackgroundRectangle(coords))
|
|
self.add_foreground_mobject(coords)
|
|
coords.move_to(
|
|
randy.get_corner(UP+RIGHT),
|
|
aligned_edge = DOWN+LEFT
|
|
)
|
|
coords.target = coords.copy()
|
|
coords.target.move_to(
|
|
pinky.get_corner(UP+LEFT),
|
|
aligned_edge = DOWN+RIGHT
|
|
)
|
|
self.play(
|
|
Write(coords),
|
|
randy.change_mode, "speaking"
|
|
)
|
|
self.scale_basis_vectors()
|
|
self.apply_transposed_matrix(
|
|
self.t_matrix,
|
|
added_anims = [
|
|
MoveToTarget(coords),
|
|
ApplyMethod(pinky.change_mode, "speaking"),
|
|
ApplyMethod(randy.change_mode, "plain"),
|
|
]
|
|
)
|
|
self.play(
|
|
randy.change_mode, "erm",
|
|
self.i_hat.set_color, self.i_target_color,
|
|
self.j_hat.set_color, self.j_target_color,
|
|
)
|
|
self.i_hat.color = self.i_target_color
|
|
self.j_hat.color = self.j_target_color
|
|
self.scale_basis_vectors()
|
|
|
|
def scale_basis_vectors(self):
|
|
for vect in self.i_hat, self.j_hat:
|
|
vect.save_state()
|
|
self.play(self.i_hat.scale, self.vector[0])
|
|
self.play(self.j_hat.scale, self.vector[1])
|
|
self.play(self.j_hat.shift, self.i_hat.get_end())
|
|
sum_vect = Vector(self.j_hat.get_end(), color = self.sum_color)
|
|
self.play(ShowCreation(sum_vect))
|
|
self.wait(2)
|
|
self.play(
|
|
FadeOut(sum_vect),
|
|
self.i_hat.restore,
|
|
self.j_hat.restore,
|
|
)
|
|
self.wait()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|