mirror of
https://github.com/3b1b/manim.git
synced 2025-08-05 16:49:03 +00:00
End of chapter 6
This commit is contained in:
parent
5b60aa0d7c
commit
36e969b2a9
5 changed files with 903 additions and 41 deletions
858
eola/chapter6.py
858
eola/chapter6.py
|
@ -24,21 +24,15 @@ from ka_playgrounds.circuits import Resistor, Source, LongResistor
|
||||||
|
|
||||||
class OpeningQuote(Scene):
|
class OpeningQuote(Scene):
|
||||||
def construct(self):
|
def construct(self):
|
||||||
words = TextMobject([
|
words = TextMobject(
|
||||||
"The question you raise, ",
|
"To ask the",
|
||||||
"``how can such a formulation lead to computations?''",
|
"right question\\\\",
|
||||||
"doesn't bother me in the least! Throughout my whole life "
|
"is harder than to answer it."
|
||||||
"as a mathematician, the possibility of making explicit, "
|
)
|
||||||
"elegant computations has always come out by itself, as a "
|
|
||||||
"byproduct of a ",
|
|
||||||
"thorough conceptual understanding."
|
|
||||||
], separate_list_arg_with_spaces = False)
|
|
||||||
words.scale_to_fit_width(2*SPACE_WIDTH - 2)
|
|
||||||
words.to_edge(UP)
|
words.to_edge(UP)
|
||||||
words.split()[1].highlight(BLUE)
|
words[1].highlight(BLUE)
|
||||||
words.split()[3].highlight(GREEN)
|
author = TextMobject("-Georg Cantor")
|
||||||
author = TextMobject(["-Grothendieck", "(a hero of mine)"])
|
author.highlight(YELLOW)
|
||||||
author.split()[0].highlight(YELLOW)
|
|
||||||
author.next_to(words, DOWN, buff = 0.5)
|
author.next_to(words, DOWN, buff = 0.5)
|
||||||
|
|
||||||
self.play(FadeIn(words))
|
self.play(FadeIn(words))
|
||||||
|
@ -112,6 +106,10 @@ class NoComputations(TeacherStudentsScene):
|
||||||
])
|
])
|
||||||
self.random_blink()
|
self.random_blink()
|
||||||
|
|
||||||
|
class PuntToSoftware(Scene):
|
||||||
|
def construct(self):
|
||||||
|
self.play(Write("Let the computers do the computing"))
|
||||||
|
|
||||||
class UsefulnessOfMatrices(Scene):
|
class UsefulnessOfMatrices(Scene):
|
||||||
def construct(self):
|
def construct(self):
|
||||||
title = TextMobject("Usefulness of matrices")
|
title = TextMobject("Usefulness of matrices")
|
||||||
|
@ -598,6 +596,32 @@ class LookForX(MentionThatItsATransformation):
|
||||||
self.apply_transposed_matrix(self.t_matrix)
|
self.apply_transposed_matrix(self.t_matrix)
|
||||||
self.dither()
|
self.dither()
|
||||||
|
|
||||||
|
class ThinkAboutWhatsHappening(Scene):
|
||||||
|
def construct(self):
|
||||||
|
randy = Randolph()
|
||||||
|
randy.to_corner()
|
||||||
|
bubble = randy.get_bubble(height = 5)
|
||||||
|
bubble.add_content(TexMobject("""
|
||||||
|
3x + 1y + 4z &= 1 \\\\
|
||||||
|
5x + 9y + 2z &= 6 \\\\
|
||||||
|
5x + 3y + 5z &= 8
|
||||||
|
"""))
|
||||||
|
|
||||||
|
self.play(randy.change_mode, "pondering")
|
||||||
|
self.play(ShowCreation(bubble))
|
||||||
|
self.play(Write(bubble.content, run_time = 2))
|
||||||
|
self.play(Blink(randy))
|
||||||
|
self.dither()
|
||||||
|
everything = VMobject(*self.get_mobjects())
|
||||||
|
self.play(
|
||||||
|
ApplyFunction(
|
||||||
|
lambda m : m.shift(2*DOWN).scale(5),
|
||||||
|
everything
|
||||||
|
),
|
||||||
|
bubble.content.highlight, BLACK,
|
||||||
|
run_time = 2
|
||||||
|
)
|
||||||
|
|
||||||
class SystemOfTwoEquationsTwoUnknowns(Scene):
|
class SystemOfTwoEquationsTwoUnknowns(Scene):
|
||||||
def construct(self):
|
def construct(self):
|
||||||
system = TexMobject("""
|
system = TexMobject("""
|
||||||
|
@ -617,10 +641,25 @@ class SystemOfTwoEquationsTwoUnknowns(Scene):
|
||||||
)
|
)
|
||||||
matrix_system.arrange_submobjects(RIGHT)
|
matrix_system.arrange_submobjects(RIGHT)
|
||||||
matrix_system.next_to(system, DOWN, buff = 1)
|
matrix_system.next_to(system, DOWN, buff = 1)
|
||||||
|
matrix.label = "A"
|
||||||
|
matrix.label_color = WHITE
|
||||||
|
x.label = "\\vec{\\textbf{x}}"
|
||||||
|
x.label_color = PINK
|
||||||
|
v.label = "\\vec{\\textbf{v}}"
|
||||||
|
v.label_color = YELLOW
|
||||||
|
for mob in matrix, x, v:
|
||||||
|
brace = Brace(mob)
|
||||||
|
label = brace.get_text("$%s$"%mob.label)
|
||||||
|
label.highlight(mob.label_color)
|
||||||
|
brace.add(label)
|
||||||
|
mob.brace = brace
|
||||||
|
|
||||||
self.add(system)
|
self.add(system)
|
||||||
self.play(Write(matrix_system))
|
self.play(Write(matrix_system))
|
||||||
self.dither()
|
self.dither()
|
||||||
|
for mob in matrix, v, x:
|
||||||
|
self.play(Write(mob.brace))
|
||||||
|
self.dither()
|
||||||
|
|
||||||
class ShowBijectivity(LinearTransformationScene):
|
class ShowBijectivity(LinearTransformationScene):
|
||||||
CONFIG = {
|
CONFIG = {
|
||||||
|
@ -678,15 +717,18 @@ class LabeledExample(LinearSystemTransformationScene):
|
||||||
CONFIG = {
|
CONFIG = {
|
||||||
"title" : "",
|
"title" : "",
|
||||||
"t_matrix" : [[0, 0], [0, 0]],
|
"t_matrix" : [[0, 0], [0, 0]],
|
||||||
|
"show_square" : False,
|
||||||
}
|
}
|
||||||
def setup(self):
|
def setup(self):
|
||||||
LinearSystemTransformationScene.setup(self)
|
LinearSystemTransformationScene.setup(self)
|
||||||
title = TextMobject(self.title)
|
title = TextMobject(self.title)
|
||||||
title.scale(1.5)
|
title.next_to(self.equation, DOWN, buff = 1)
|
||||||
title.next_to(self.equation, DOWN)
|
|
||||||
title.add_background_rectangle()
|
title.add_background_rectangle()
|
||||||
|
title.shift_onto_screen()
|
||||||
self.add_foreground_mobject(title)
|
self.add_foreground_mobject(title)
|
||||||
self.title = title
|
self.title = title
|
||||||
|
if self.show_square:
|
||||||
|
self.add_unit_square()
|
||||||
|
|
||||||
def construct(self):
|
def construct(self):
|
||||||
self.dither()
|
self.dither()
|
||||||
|
@ -708,20 +750,48 @@ class FullRankExmapleWithWords(LabeledExample):
|
||||||
class SquishExmapleDet(SquishExmapleWithWords):
|
class SquishExmapleDet(SquishExmapleWithWords):
|
||||||
CONFIG = {
|
CONFIG = {
|
||||||
"title" : "$\\det(A) = 0$",
|
"title" : "$\\det(A) = 0$",
|
||||||
|
"show_square" : True,
|
||||||
}
|
}
|
||||||
|
|
||||||
class FullRankExmapleDet(FullRankExmapleWithWords):
|
class FullRankExmapleDet(FullRankExmapleWithWords):
|
||||||
CONFIG = {
|
CONFIG = {
|
||||||
"title" : "$\\det(A) \\ne 0$",
|
"title" : "$\\det(A) \\ne 0$",
|
||||||
|
"show_square" : True,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class StartWithNonzeroDetCase(TeacherStudentsScene):
|
||||||
|
def construct(self):
|
||||||
|
words = TextMobject(
|
||||||
|
"Let's start with \\\\",
|
||||||
|
"the", "$\\det(A) \\ne 0$", "case"
|
||||||
|
)
|
||||||
|
words[2].highlight(TEAL)
|
||||||
|
self.teacher_says(words)
|
||||||
|
self.random_blink()
|
||||||
|
self.play(
|
||||||
|
random.choice(self.get_students()).change_mode,
|
||||||
|
"happy"
|
||||||
|
)
|
||||||
|
self.dither()
|
||||||
|
|
||||||
|
class DeclareNewTransformation(TeacherStudentsScene):
|
||||||
|
def construct(self):
|
||||||
|
words = TextMobject(
|
||||||
|
"Playing a transformation in\\\\",
|
||||||
|
"reverse gives a", "new transformation"
|
||||||
|
)
|
||||||
|
words[-1].highlight(GREEN)
|
||||||
|
self.teacher_says(words)
|
||||||
|
self.change_student_modes("pondering", "sassy")
|
||||||
|
self.random_blink()
|
||||||
|
|
||||||
class PlayInReverse(FullRankExmapleDet):
|
class PlayInReverse(FullRankExmapleDet):
|
||||||
CONFIG = {
|
CONFIG = {
|
||||||
"show_basis_vectors" : False
|
"show_basis_vectors" : False
|
||||||
}
|
}
|
||||||
def construct(self):
|
def construct(self):
|
||||||
FullRankExmapleDet.construct(self)
|
FullRankExmapleDet.construct(self)
|
||||||
v = self.add_vector([-2, -2], color = YELLOW)
|
v = self.add_vector([-4, -1], color = YELLOW)
|
||||||
v_label = self.label_vector(v, "v", color = YELLOW)
|
v_label = self.label_vector(v, "v", color = YELLOW)
|
||||||
self.add(v.copy())
|
self.add(v.copy())
|
||||||
self.apply_inverse_transpose(self.t_matrix)
|
self.apply_inverse_transpose(self.t_matrix)
|
||||||
|
@ -794,9 +864,9 @@ class ShearInverseShear(DescribeInverse):
|
||||||
class MultiplyToIdentity(LinearTransformationScene):
|
class MultiplyToIdentity(LinearTransformationScene):
|
||||||
def construct(self):
|
def construct(self):
|
||||||
self.setup()
|
self.setup()
|
||||||
lhs = TexMobject("A", "A^{-1}", "=")
|
lhs = TexMobject("A^{-1}", "A", "=")
|
||||||
lhs.scale(1.5)
|
lhs.scale(1.5)
|
||||||
A, A_inv, eq = lhs.split()
|
A_inv, A, eq = lhs.split()
|
||||||
identity = Matrix([[1, 0], [0, 1]])
|
identity = Matrix([[1, 0], [0, 1]])
|
||||||
identity.highlight_columns(X_COLOR, Y_COLOR)
|
identity.highlight_columns(X_COLOR, Y_COLOR)
|
||||||
identity.next_to(eq, RIGHT)
|
identity.next_to(eq, RIGHT)
|
||||||
|
@ -816,6 +886,7 @@ class MultiplyToIdentity(LinearTransformationScene):
|
||||||
for mob in A, A_inv, product, identity:
|
for mob in A, A_inv, product, identity:
|
||||||
mob.brace = Brace(mob)
|
mob.brace = Brace(mob)
|
||||||
mob.text = mob.brace.get_text(mob.text)
|
mob.text = mob.brace.get_text(mob.text)
|
||||||
|
mob.text.shift_onto_screen()
|
||||||
mob.text.add_background_rectangle()
|
mob.text.add_background_rectangle()
|
||||||
|
|
||||||
self.add_foreground_mobject(A, A_inv)
|
self.add_foreground_mobject(A, A_inv)
|
||||||
|
@ -847,6 +918,15 @@ class MultiplyToIdentity(LinearTransformationScene):
|
||||||
self.play(Write(col2))
|
self.play(Write(col2))
|
||||||
self.dither()
|
self.dither()
|
||||||
|
|
||||||
|
class ThereAreComputationMethods(TeacherStudentsScene):
|
||||||
|
def construct(self):
|
||||||
|
self.teacher_says("""
|
||||||
|
There are methods
|
||||||
|
to compute $A^{-1}$
|
||||||
|
""")
|
||||||
|
self.random_blink()
|
||||||
|
self.dither()
|
||||||
|
|
||||||
class TwoDInverseFormula(Scene):
|
class TwoDInverseFormula(Scene):
|
||||||
def construct(self):
|
def construct(self):
|
||||||
title = TextMobject("If you're curious...")
|
title = TextMobject("If you're curious...")
|
||||||
|
@ -921,6 +1001,9 @@ class SymbolicInversion(Scene):
|
||||||
self.dither()
|
self.dither()
|
||||||
|
|
||||||
class PlayInReverseWithSolution(PlayInReverse):
|
class PlayInReverseWithSolution(PlayInReverse):
|
||||||
|
CONFIG = {
|
||||||
|
"t_matrix" : [[2, 1], [2, 3]]
|
||||||
|
}
|
||||||
def setup(self):
|
def setup(self):
|
||||||
LinearTransformationScene.setup(self)
|
LinearTransformationScene.setup(self)
|
||||||
equation = TexMobject([
|
equation = TexMobject([
|
||||||
|
@ -964,9 +1047,40 @@ class OneUniqueSolution(Scene):
|
||||||
self.play(Write(words.split()[1], run_time = 1))
|
self.play(Write(words.split()[1], run_time = 1))
|
||||||
self.dither()
|
self.dither()
|
||||||
|
|
||||||
|
class ThreeDTransformXToV(Scene):
|
||||||
|
pass
|
||||||
|
|
||||||
class ThreeDTransformAndReverse(Scene):
|
class ThreeDTransformAndReverse(Scene):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
class DetNEZeroRule(Scene):
|
||||||
|
def construct(self):
|
||||||
|
text = TexMobject("\\det(A) \\ne 0")
|
||||||
|
text.shift(2*UP)
|
||||||
|
A_inv = TextMobject("$A^{-1}$ exists")
|
||||||
|
A_inv.shift(DOWN)
|
||||||
|
arrow = Arrow(text, A_inv)
|
||||||
|
self.play(Write(text))
|
||||||
|
self.dither()
|
||||||
|
self.play(ShowCreation(arrow))
|
||||||
|
self.play(Write(A_inv, run_time = 1))
|
||||||
|
self.dither()
|
||||||
|
|
||||||
|
|
||||||
|
class ThreeDInverseRule(Scene):
|
||||||
|
def construct(self):
|
||||||
|
form = TexMobject("A^{-1} A = ")
|
||||||
|
form.scale(2)
|
||||||
|
matrix = Matrix(np.identity(3, 'int'))
|
||||||
|
matrix.highlight_columns(X_COLOR, Y_COLOR, Z_COLOR)
|
||||||
|
matrix.next_to(form, RIGHT)
|
||||||
|
self.add(form)
|
||||||
|
self.play(Write(matrix))
|
||||||
|
self.dither()
|
||||||
|
|
||||||
|
class ThreeDApplyReverseToV(Scene):
|
||||||
|
pass
|
||||||
|
|
||||||
class InversesDontAlwaysExist(TeacherStudentsScene):
|
class InversesDontAlwaysExist(TeacherStudentsScene):
|
||||||
def construct(self):
|
def construct(self):
|
||||||
self.teacher_says("$A^{-1}$ doesn't always exist")
|
self.teacher_says("$A^{-1}$ doesn't always exist")
|
||||||
|
@ -1080,20 +1194,38 @@ class TowDColumnsDontSpan(LinearTransformationScene):
|
||||||
lambda m : m.scale(-1).shift(self.i_hat.get_end()),
|
lambda m : m.scale(-1).shift(self.i_hat.get_end()),
|
||||||
self.j_hat
|
self.j_hat
|
||||||
))
|
))
|
||||||
for x in range(5):
|
bases = [self.i_hat, self.j_hat]
|
||||||
i_target, j_target = [
|
for mob in bases:
|
||||||
m.copy().scale(random.uniform(-1.2, 1.2))
|
mob.original = mob.copy()
|
||||||
for m in self.i_hat, self.j_hat
|
for x in range(12):
|
||||||
]
|
for mob in bases:
|
||||||
j_target.shift(-j_target.get_start()+i_target.get_end())
|
mob.target = mob.original.copy()
|
||||||
|
mob.target.set_stroke(width = 6)
|
||||||
|
target_len = random.uniform(0.5, 1.5)
|
||||||
|
target_len *= random.choice([-1, 1])
|
||||||
|
mob.target.scale(target_len)
|
||||||
|
self.j_hat.target.shift(
|
||||||
|
-self.j_hat.target.get_start()+ \
|
||||||
|
self.i_hat.target.get_end()
|
||||||
|
)
|
||||||
self.play(Transform(
|
self.play(Transform(
|
||||||
VMobject(self.i_hat, j_hat, VectorizedPoint()),
|
VMobject(*bases),
|
||||||
VMobject(i_target, j_target, VectorizedPoint()),
|
VMobject(*[m.target for m in bases]),
|
||||||
submobject_mode = "lagged_start"
|
run_time = 2
|
||||||
))
|
))
|
||||||
self.dither()
|
if x == 5:
|
||||||
if x == 2:
|
|
||||||
self.play(ShowCreation(Vector([2, -1])))
|
self.play(ShowCreation(Vector([2, -1])))
|
||||||
|
form = TexMobject(
|
||||||
|
"A", "\\vec{\\textbf{x}}", "=", "\\vec{\\textbf{v}}"
|
||||||
|
)
|
||||||
|
form[1].highlight(PINK)
|
||||||
|
form[3].highlight(YELLOW)
|
||||||
|
words = TextMobject("has no solution")
|
||||||
|
words.next_to(form, RIGHT)
|
||||||
|
form.add(words)
|
||||||
|
form.to_corner(UP+RIGHT)
|
||||||
|
form.add_background_rectangle()
|
||||||
|
self.play(Write(form, run_time = 2))
|
||||||
|
|
||||||
class ThreeDColumnsDontSpan(Scene):
|
class ThreeDColumnsDontSpan(Scene):
|
||||||
def construct(self):
|
def construct(self):
|
||||||
|
@ -1118,6 +1250,672 @@ class ThreeDColumnsDontSpan(Scene):
|
||||||
)
|
)
|
||||||
self.dither()
|
self.dither()
|
||||||
|
|
||||||
|
class NameColumnSpace(Scene):
|
||||||
|
def construct(self):
|
||||||
|
matrix = Matrix(np.array([
|
||||||
|
[1, 1, 0],
|
||||||
|
[0, 1, 1],
|
||||||
|
[-1, -2, -1],
|
||||||
|
]).T)
|
||||||
|
matrix.highlight_columns(X_COLOR, Y_COLOR, Z_COLOR)
|
||||||
|
matrix.to_corner(UP+LEFT)
|
||||||
|
cols = list(matrix.copy().get_mob_matrix().T)
|
||||||
|
col_arrays = map(Matrix, cols)
|
||||||
|
|
||||||
|
span_text = TexMobject(
|
||||||
|
"\\text{Span}",
|
||||||
|
"\\Big(",
|
||||||
|
matrix_to_tex_string([1, 2, 3]),
|
||||||
|
",",
|
||||||
|
matrix_to_tex_string([1, 2, 3]),
|
||||||
|
",",
|
||||||
|
matrix_to_tex_string([1, 2, 3]),
|
||||||
|
"\\big)"
|
||||||
|
)
|
||||||
|
for i in 1, -1:
|
||||||
|
span_text[i].stretch(1.5, 1)
|
||||||
|
span_text[i].do_in_place(
|
||||||
|
span_text[i].scale_to_fit_height,
|
||||||
|
span_text.get_height()
|
||||||
|
)
|
||||||
|
for col_array, index in zip(col_arrays, [2, 4, 6]):
|
||||||
|
col_array.replace(span_text[index], dim_to_match = 1)
|
||||||
|
span_text.submobjects[index] = col_array
|
||||||
|
span_text.arrange_submobjects(RIGHT, buff = 0.2)
|
||||||
|
|
||||||
|
arrow = DoubleArrow(LEFT, RIGHT)
|
||||||
|
column_space = TextMobject("``Column space''")
|
||||||
|
for mob in column_space, arrow:
|
||||||
|
mob.highlight(TEAL)
|
||||||
|
text = VMobject(span_text, arrow, column_space)
|
||||||
|
text.arrange_submobjects(RIGHT)
|
||||||
|
text.next_to(matrix, DOWN, buff = 1, aligned_edge = LEFT)
|
||||||
|
|
||||||
|
self.add(matrix)
|
||||||
|
self.dither()
|
||||||
|
self.play(*[
|
||||||
|
Transform(
|
||||||
|
VMobject(*matrix.copy().get_mob_matrix()[:,i]),
|
||||||
|
col_arrays[i].get_entries()
|
||||||
|
)
|
||||||
|
for i in range(3)
|
||||||
|
])
|
||||||
|
self.play(
|
||||||
|
Write(span_text),
|
||||||
|
*map(Animation, self.get_mobjects_from_last_animation())
|
||||||
|
)
|
||||||
|
self.play(
|
||||||
|
ShowCreation(arrow),
|
||||||
|
Write(column_space)
|
||||||
|
)
|
||||||
|
self.dither()
|
||||||
|
self.play(FadeOut(matrix))
|
||||||
|
self.clear()
|
||||||
|
self.add(text)
|
||||||
|
|
||||||
|
words = TextMobject(
|
||||||
|
"To solve",
|
||||||
|
"$A\\vec{\\textbf{x}} = \\vec{\\textbf{v}}$,\\\\",
|
||||||
|
"$\\vec{\\textbf{v}}$",
|
||||||
|
"must be in \\\\ the",
|
||||||
|
"column space."
|
||||||
|
)
|
||||||
|
VMobject(*words[1][1:3]).highlight(PINK)
|
||||||
|
VMobject(*words[1][4:6]).highlight(YELLOW)
|
||||||
|
words[2].highlight(YELLOW)
|
||||||
|
words[4].highlight(TEAL)
|
||||||
|
words.to_corner(UP+LEFT)
|
||||||
|
|
||||||
|
self.play(Write(words))
|
||||||
|
self.dither(2)
|
||||||
|
self.play(FadeOut(words))
|
||||||
|
|
||||||
|
brace = Brace(column_space, UP)
|
||||||
|
rank_words = brace.get_text(
|
||||||
|
"Number of dimensions \\\\ is called",
|
||||||
|
"``rank''"
|
||||||
|
)
|
||||||
|
rank_words[1].highlight(MAROON)
|
||||||
|
self.play(
|
||||||
|
GrowFromCenter(brace),
|
||||||
|
Write(rank_words)
|
||||||
|
)
|
||||||
|
self.dither()
|
||||||
|
self.cycle_through_span_possibilities(span_text)
|
||||||
|
|
||||||
|
def cycle_through_span_possibilities(self, span_text):
|
||||||
|
span_text.save_state()
|
||||||
|
two_d_span = span_text.copy()
|
||||||
|
for index, arr, c in (2, [1, 1], X_COLOR), (4, [0, 1], Y_COLOR):
|
||||||
|
col = Matrix(arr)
|
||||||
|
col.replace(two_d_span[index])
|
||||||
|
two_d_span.submobjects[index] = col
|
||||||
|
col.get_entries().highlight(c)
|
||||||
|
for index in 5, 6:
|
||||||
|
two_d_span[index].scale(0)
|
||||||
|
two_d_span.arrange_submobjects(RIGHT, buff = 0.2)
|
||||||
|
two_d_span[-1].next_to(two_d_span[4], RIGHT, buff = 0.2)
|
||||||
|
two_d_span.move_to(span_text, side_to_align = RIGHT)
|
||||||
|
mob_matrix = np.array([
|
||||||
|
two_d_span[i].get_entries().split()
|
||||||
|
for i in 2, 4
|
||||||
|
])
|
||||||
|
|
||||||
|
self.play(Transform(span_text, two_d_span))
|
||||||
|
#horrible hack
|
||||||
|
span_text.shift(10*DOWN)
|
||||||
|
span_text = span_text.copy().restore()
|
||||||
|
###
|
||||||
|
self.add(two_d_span)
|
||||||
|
self.dither()
|
||||||
|
self.replace_number_matrix(mob_matrix, [[1, 1], [1, 1]])
|
||||||
|
self.dither()
|
||||||
|
self.replace_number_matrix(mob_matrix, [[0, 0], [0, 0]])
|
||||||
|
self.dither()
|
||||||
|
self.play(Transform(two_d_span, span_text))
|
||||||
|
self.dither()
|
||||||
|
self.remove(two_d_span)
|
||||||
|
self.add(span_text)
|
||||||
|
mob_matrix = np.array([
|
||||||
|
span_text[i].get_entries().split()
|
||||||
|
for i in 2, 4, 6
|
||||||
|
])
|
||||||
|
self.replace_number_matrix(mob_matrix, [[1, 1, 0], [0, 1, 1], [1, 0, 1]])
|
||||||
|
self.dither()
|
||||||
|
self.replace_number_matrix(mob_matrix, [[1, 1, 0], [0, 1, 1], [-1, -2, -1]])
|
||||||
|
self.dither()
|
||||||
|
self.replace_number_matrix(mob_matrix, [[1, 1, 0], [2, 2, 0], [3, 3, 0]])
|
||||||
|
self.dither()
|
||||||
|
self.replace_number_matrix(mob_matrix, np.zeros((3, 3)).astype('int'))
|
||||||
|
self.dither()
|
||||||
|
|
||||||
|
|
||||||
|
def replace_number_matrix(self, matrix, new_numbers):
|
||||||
|
starters = matrix.flatten()
|
||||||
|
targets = map(TexMobject, map(str, np.array(new_numbers).flatten()))
|
||||||
|
for start, target in zip(starters, targets):
|
||||||
|
target.move_to(start)
|
||||||
|
target.highlight(start.get_color())
|
||||||
|
self.play(*[
|
||||||
|
Transform(*pair, path_arc = np.pi)
|
||||||
|
for pair in zip(starters, targets)
|
||||||
|
])
|
||||||
|
|
||||||
|
class IHatShear(LinearTransformationScene):
|
||||||
|
CONFIG = {
|
||||||
|
"foreground_plane_kwargs" : {
|
||||||
|
"x_radius" : 2*SPACE_WIDTH,
|
||||||
|
"y_radius" : 2*SPACE_WIDTH,
|
||||||
|
"secondary_line_ratio" : 0
|
||||||
|
},
|
||||||
|
}
|
||||||
|
def construct(self):
|
||||||
|
self.apply_transposed_matrix([[1, 1], [0, 1]])
|
||||||
|
self.dither()
|
||||||
|
|
||||||
|
class DiagonalDegenerate(LinearTransformationScene):
|
||||||
|
def construct(self):
|
||||||
|
self.apply_transposed_matrix([[1, 1], [1, 1]])
|
||||||
|
|
||||||
|
class ZeroMatirx(LinearTransformationScene):
|
||||||
|
def construct(self):
|
||||||
|
origin = Dot(ORIGIN)
|
||||||
|
self.play(Transform(
|
||||||
|
VMobject(self.plane, self.i_hat, self.j_hat),
|
||||||
|
origin,
|
||||||
|
run_time = 3
|
||||||
|
))
|
||||||
|
self.dither()
|
||||||
|
|
||||||
|
class RankNumber(Scene):
|
||||||
|
CONFIG = {
|
||||||
|
"number" : 3,
|
||||||
|
"color" : BLUE
|
||||||
|
}
|
||||||
|
def construct(self):
|
||||||
|
words = TextMobject("Rank", "%d"%self.number)
|
||||||
|
words[1].highlight(self.color)
|
||||||
|
self.add(words)
|
||||||
|
|
||||||
|
class RankNumber2(RankNumber):
|
||||||
|
CONFIG = {
|
||||||
|
"number" : 2,
|
||||||
|
"color" : RED,
|
||||||
|
}
|
||||||
|
|
||||||
|
class RankNumber1(RankNumber):
|
||||||
|
CONFIG = {
|
||||||
|
"number" : 1,
|
||||||
|
"color" : GREEN
|
||||||
|
}
|
||||||
|
|
||||||
|
class RankNumber0(RankNumber):
|
||||||
|
CONFIG = {
|
||||||
|
"number" : 0,
|
||||||
|
"color" : GREY
|
||||||
|
}
|
||||||
|
|
||||||
|
class NameFullRank(Scene):
|
||||||
|
def construct(self):
|
||||||
|
matrix = Matrix([[2, 5, 1], [3, 1, 4], [-4, 0, 0]])
|
||||||
|
matrix.highlight_columns(X_COLOR, Y_COLOR, Z_COLOR)
|
||||||
|
matrix.to_edge(UP)
|
||||||
|
brace = Brace(matrix)
|
||||||
|
top_words = brace.get_text(
|
||||||
|
"When", "rank", "$=$", "number of columns",
|
||||||
|
)
|
||||||
|
top_words[1].highlight(MAROON)
|
||||||
|
low_words = TextMobject(
|
||||||
|
"matrix is", "``full rank''"
|
||||||
|
)
|
||||||
|
low_words[1].highlight(MAROON)
|
||||||
|
low_words.next_to(top_words, DOWN)
|
||||||
|
VMobject(matrix, brace, top_words, low_words).to_corner(UP+LEFT)
|
||||||
|
self.add(matrix)
|
||||||
|
self.play(
|
||||||
|
GrowFromCenter(brace),
|
||||||
|
Write(top_words)
|
||||||
|
)
|
||||||
|
self.dither()
|
||||||
|
self.play(Write(low_words))
|
||||||
|
self.dither()
|
||||||
|
|
||||||
|
class OriginIsAlwaysInColumnSpace(LinearTransformationScene):
|
||||||
|
def construct(self):
|
||||||
|
vector = Matrix([0, 0]).highlight(YELLOW)
|
||||||
|
words = TextMobject("is always in the", "column space")
|
||||||
|
words[1].highlight(TEAL)
|
||||||
|
words.next_to(vector, RIGHT)
|
||||||
|
vector.add_to_back(BackgroundRectangle(vector))
|
||||||
|
words.add_background_rectangle()
|
||||||
|
VMobject(vector, words).center().to_edge(UP)
|
||||||
|
arrow = Arrow(vector.get_bottom(), ORIGIN)
|
||||||
|
dot = Dot(ORIGIN, color = YELLOW)
|
||||||
|
|
||||||
|
self.play(Write(vector), Write(words))
|
||||||
|
self.play(ShowCreation(arrow))
|
||||||
|
self.play(ShowCreation(dot, run_time = 0.5))
|
||||||
|
self.add_foreground_mobject(vector, words, arrow, dot)
|
||||||
|
self.dither()
|
||||||
|
self.apply_transposed_matrix(self.t_matrix)
|
||||||
|
self.dither()
|
||||||
|
self.apply_transposed_matrix([[1./3, -1./2], [-1./3, 1./2]])
|
||||||
|
self.dither()
|
||||||
|
|
||||||
|
class FullRankCase(LinearTransformationScene):
|
||||||
|
CONFIG = {
|
||||||
|
"foreground_plane_kwargs" : {
|
||||||
|
"x_radius" : 2*SPACE_WIDTH,
|
||||||
|
"y_radius" : 2*SPACE_WIDTH,
|
||||||
|
"secondary_line_ratio" : 0
|
||||||
|
},
|
||||||
|
}
|
||||||
|
def construct(self):
|
||||||
|
t_matrices = [
|
||||||
|
[[2, 1], [-3, 2]],
|
||||||
|
[[1./2, 1], [1./3, -1./2]]
|
||||||
|
]
|
||||||
|
vector = Matrix([0, 0]).highlight(YELLOW)
|
||||||
|
title = VMobject(
|
||||||
|
TextMobject("Only"), vector,
|
||||||
|
TextMobject("lands on"), vector.copy()
|
||||||
|
)
|
||||||
|
title.arrange_submobjects(buff = 0.2)
|
||||||
|
title.to_edge(UP)
|
||||||
|
for mob in title:
|
||||||
|
mob.add_to_back(BackgroundRectangle(mob))
|
||||||
|
arrow = Arrow(vector.get_bottom(), ORIGIN)
|
||||||
|
dot = Dot(ORIGIN, color = YELLOW)
|
||||||
|
|
||||||
|
words_on = False
|
||||||
|
for t_matrix in t_matrices:
|
||||||
|
self.apply_transposed_matrix(t_matrix)
|
||||||
|
if not words_on:
|
||||||
|
self.play(Write(title))
|
||||||
|
self.play(ShowCreation(arrow))
|
||||||
|
self.play(ShowCreation(dot, run_time = 0.5))
|
||||||
|
self.add_foreground_mobject(title, arrow, dot)
|
||||||
|
words_on = True
|
||||||
|
self.apply_inverse_transpose(t_matrix)
|
||||||
|
self.dither()
|
||||||
|
|
||||||
|
class NameNullSpace(LinearTransformationScene):
|
||||||
|
CONFIG = {
|
||||||
|
"show_basis_vectors" : False,
|
||||||
|
"t_matrix" : [[1, -1], [-1, 1]]
|
||||||
|
}
|
||||||
|
def construct(self):
|
||||||
|
vectors = self.get_vectors()
|
||||||
|
dot = Dot(ORIGIN, color = YELLOW)
|
||||||
|
line = Line(vectors[0].get_end(), vectors[-1].get_end())
|
||||||
|
line.highlight(YELLOW)
|
||||||
|
null_space_label = TextMobject("``Null space''")
|
||||||
|
kernel_label = TextMobject("``Kernel''")
|
||||||
|
null_space_label.move_to(vectors[13].get_end(), side_to_align = UP+LEFT)
|
||||||
|
kernel_label.next_to(null_space_label, DOWN)
|
||||||
|
for mob in null_space_label, kernel_label:
|
||||||
|
mob.highlight(YELLOW)
|
||||||
|
mob.add_background_rectangle()
|
||||||
|
|
||||||
|
self.play(ShowCreation(vectors, run_time = 3))
|
||||||
|
self.dither()
|
||||||
|
vectors.save_state()
|
||||||
|
self.plane.save_state()
|
||||||
|
self.apply_transposed_matrix(
|
||||||
|
self.t_matrix,
|
||||||
|
added_anims = [Transform(vectors, dot)],
|
||||||
|
path_arc = 0
|
||||||
|
)
|
||||||
|
self.dither()
|
||||||
|
self.play(
|
||||||
|
vectors.restore,
|
||||||
|
self.plane.restore,
|
||||||
|
*map(Animation, self.foreground_mobjects),
|
||||||
|
run_time = 2
|
||||||
|
)
|
||||||
|
self.play(Transform(
|
||||||
|
vectors, line,
|
||||||
|
run_time = 2,
|
||||||
|
submobject_mode = "lagged_start"
|
||||||
|
))
|
||||||
|
self.dither()
|
||||||
|
for label in null_space_label, kernel_label:
|
||||||
|
self.play(Write(label))
|
||||||
|
self.dither()
|
||||||
|
self.apply_transposed_matrix(
|
||||||
|
self.t_matrix,
|
||||||
|
added_anims = [
|
||||||
|
Transform(vectors, dot),
|
||||||
|
ApplyMethod(null_space_label.scale, 0),
|
||||||
|
ApplyMethod(kernel_label.scale, 0),
|
||||||
|
],
|
||||||
|
path_arc = 0
|
||||||
|
)
|
||||||
|
self.dither()
|
||||||
|
|
||||||
|
def get_vectors(self, offset = 0):
|
||||||
|
vect = np.array(UP+RIGHT)
|
||||||
|
vectors = VMobject(*[
|
||||||
|
Vector(a*vect + offset)
|
||||||
|
for a in np.linspace(-5, 5, 18)
|
||||||
|
])
|
||||||
|
vectors.submobject_gradient_highlight(PINK, YELLOW)
|
||||||
|
return vectors
|
||||||
|
|
||||||
|
class ThreeDNullSpaceIsLine(Scene):
|
||||||
|
pass
|
||||||
|
|
||||||
|
class ThreeDNullSpaceIsPlane(Scene):
|
||||||
|
pass
|
||||||
|
|
||||||
|
class NullSpaceSolveForVEqualsZero(NameNullSpace):
|
||||||
|
def construct(self):
|
||||||
|
vec = lambda s : "\\vec{\\textbf{%s}}"%s
|
||||||
|
equation = TexMobject("A", vec("x"), "=", vec("v"))
|
||||||
|
A, x, eq, v = equation
|
||||||
|
x.highlight(PINK)
|
||||||
|
v.highlight(YELLOW)
|
||||||
|
zero_vector = Matrix([0, 0])
|
||||||
|
zero_vector.highlight(YELLOW)
|
||||||
|
zero_vector.scale(0.7)
|
||||||
|
zero_vector.move_to(v, side_to_align = LEFT)
|
||||||
|
VMobject(equation, zero_vector).next_to(ORIGIN, LEFT).to_edge(UP)
|
||||||
|
zero_vector_rect = BackgroundRectangle(zero_vector)
|
||||||
|
equation.add_background_rectangle()
|
||||||
|
|
||||||
|
self.play(Write(equation))
|
||||||
|
self.dither()
|
||||||
|
self.play(
|
||||||
|
ShowCreation(zero_vector_rect),
|
||||||
|
Transform(v, zero_vector)
|
||||||
|
)
|
||||||
|
self.dither()
|
||||||
|
self.add_foreground_mobject(zero_vector_rect, equation)
|
||||||
|
NameNullSpace.construct(self)
|
||||||
|
|
||||||
|
class OffsetNullSpace(NameNullSpace):
|
||||||
|
def construct(self):
|
||||||
|
x = Vector([-2, 1], color = RED)
|
||||||
|
vectors = self.get_vectors()
|
||||||
|
offset_vectors = self.get_vectors(offset = x.get_end())
|
||||||
|
dots = VMobject(*[
|
||||||
|
Dot(v.get_end(), color = v.get_color())
|
||||||
|
for v in offset_vectors
|
||||||
|
])
|
||||||
|
dot = Dot(
|
||||||
|
self.get_matrix_transformation(self.t_matrix)(x.get_end()),
|
||||||
|
color = RED
|
||||||
|
)
|
||||||
|
circle = Circle(color = YELLOW).replace(dot)
|
||||||
|
circle.scale_in_place(5)
|
||||||
|
words = TextMobject("""
|
||||||
|
All vectors still land
|
||||||
|
on the same spot
|
||||||
|
""")
|
||||||
|
words.highlight(YELLOW)
|
||||||
|
words.add_background_rectangle()
|
||||||
|
words.next_to(circle)
|
||||||
|
x_copies = VMobject(*[
|
||||||
|
x.copy().shift(v.get_end())
|
||||||
|
for v in vectors
|
||||||
|
])
|
||||||
|
|
||||||
|
self.play(FadeIn(vectors))
|
||||||
|
self.dither()
|
||||||
|
self.add_vector(x, animate = True)
|
||||||
|
self.dither()
|
||||||
|
x_copy = VMobject(x.copy())
|
||||||
|
self.play(Transform(x_copy, x_copies))
|
||||||
|
self.play(
|
||||||
|
Transform(vectors, offset_vectors),
|
||||||
|
*[
|
||||||
|
Transform(v, VectorizedPoint(v.get_end()))
|
||||||
|
for v in x_copy
|
||||||
|
]
|
||||||
|
)
|
||||||
|
self.remove(x_copy)
|
||||||
|
self.dither()
|
||||||
|
self.play(Transform(vectors, dots))
|
||||||
|
self.dither()
|
||||||
|
self.apply_transposed_matrix(
|
||||||
|
self.t_matrix,
|
||||||
|
added_anims = [Transform(vectors, dot)]
|
||||||
|
)
|
||||||
|
self.dither()
|
||||||
|
self.play(
|
||||||
|
ShowCreation(circle),
|
||||||
|
Write(words)
|
||||||
|
)
|
||||||
|
self.dither()
|
||||||
|
|
||||||
|
class ShowAdditivityProperty(LinearTransformationScene):
|
||||||
|
CONFIG = {
|
||||||
|
"show_basis_vectors" : False,
|
||||||
|
"t_matrix" : [[1, 0.5], [-1, 1]],
|
||||||
|
"include_background_plane" : False,
|
||||||
|
}
|
||||||
|
def construct(self):
|
||||||
|
v = Vector([2, -1])
|
||||||
|
w = Vector([1, 2])
|
||||||
|
v.highlight(YELLOW)
|
||||||
|
w.highlight(MAROON_B)
|
||||||
|
sum_vect = Vector(v.get_end()+w.get_end(), color = PINK)
|
||||||
|
form = TexMobject(
|
||||||
|
"A(",
|
||||||
|
"\\vec{\\textbf{v}}",
|
||||||
|
"+",
|
||||||
|
"\\vec{\\textbf{w}}",
|
||||||
|
")",
|
||||||
|
"=A",
|
||||||
|
"\\vec{\\textbf{v}}",
|
||||||
|
"+A",
|
||||||
|
"\\vec{\\textbf{w}}",
|
||||||
|
)
|
||||||
|
form.to_corner(UP+RIGHT)
|
||||||
|
VMobject(form[1], form[6]).highlight(YELLOW)
|
||||||
|
VMobject(form[3], form[8]).highlight(MAROON_B)
|
||||||
|
initial_sum = VMobject(*form[1:4])
|
||||||
|
transformer = VMobject(form[0], form[4])
|
||||||
|
final_sum = VMobject(*form[5:])
|
||||||
|
form_rect = BackgroundRectangle(form)
|
||||||
|
|
||||||
|
self.add(form_rect)
|
||||||
|
self.add_vector(v, animate = True)
|
||||||
|
self.add_vector(w, animate = True)
|
||||||
|
w_copy = w.copy()
|
||||||
|
self.play(w_copy.shift, v.get_end())
|
||||||
|
self.add_vector(sum_vect, animate = True)
|
||||||
|
self.play(
|
||||||
|
Write(initial_sum),
|
||||||
|
FadeOut(w_copy)
|
||||||
|
)
|
||||||
|
self.add_foreground_mobject(form_rect, initial_sum)
|
||||||
|
self.apply_transposed_matrix(
|
||||||
|
self.t_matrix,
|
||||||
|
added_anims = [Write(transformer)]
|
||||||
|
)
|
||||||
|
self.dither()
|
||||||
|
self.play(w.copy().shift, v.get_end())
|
||||||
|
self.play(Write(final_sum))
|
||||||
|
self.dither()
|
||||||
|
|
||||||
|
class AddJustOneNullSpaceVector(NameNullSpace):
|
||||||
|
def construct(self):
|
||||||
|
vectors = self.get_vectors()
|
||||||
|
self.add(vectors)
|
||||||
|
null_vector = vectors[int(0.7*len(vectors.split()))]
|
||||||
|
vectors.remove(null_vector)
|
||||||
|
null_vector.label = "$\\vec{\\textbf{n}}$"
|
||||||
|
x = Vector([-1, 1], color = RED)
|
||||||
|
x.label = "$\\vec{\\textbf{x}}$"
|
||||||
|
sum_vect = Vector(
|
||||||
|
x.get_end() + null_vector.get_end(),
|
||||||
|
color = PINK
|
||||||
|
)
|
||||||
|
for v in x, null_vector:
|
||||||
|
v.label = TextMobject(v.label)
|
||||||
|
v.label.highlight(v.get_color())
|
||||||
|
v.label.next_to(v.get_end(), UP)
|
||||||
|
v.label.add_background_rectangle()
|
||||||
|
dot = Dot(ORIGIN, color = null_vector.get_color())
|
||||||
|
|
||||||
|
form = TexMobject(
|
||||||
|
"A(",
|
||||||
|
"\\vec{\\textbf{x}}",
|
||||||
|
"+",
|
||||||
|
"\\vec{\\textbf{n}}",
|
||||||
|
")",
|
||||||
|
"=A",
|
||||||
|
"\\vec{\\textbf{x}}",
|
||||||
|
"+A",
|
||||||
|
"\\vec{\\textbf{n}}",
|
||||||
|
)
|
||||||
|
form.to_corner(UP+RIGHT)
|
||||||
|
VMobject(form[1], form[6]).highlight(x.get_color())
|
||||||
|
VMobject(form[3], form[8]).highlight(null_vector.get_color())
|
||||||
|
initial_sum = VMobject(*form[1:4])
|
||||||
|
transformer = VMobject(form[0], form[4])
|
||||||
|
final_sum = VMobject(*form[5:])
|
||||||
|
brace = Brace(VMobject(*form[-2:]))
|
||||||
|
brace.add(brace.get_text("+0").add_background_rectangle())
|
||||||
|
form_rect = BackgroundRectangle(form)
|
||||||
|
sum_vect.label = initial_sum.copy()
|
||||||
|
sum_vect.label.next_to(sum_vect.get_end(), UP)
|
||||||
|
|
||||||
|
self.add_vector(x, animate = True)
|
||||||
|
self.play(Write(x.label))
|
||||||
|
self.dither()
|
||||||
|
self.play(
|
||||||
|
FadeOut(vectors),
|
||||||
|
Animation(null_vector)
|
||||||
|
)
|
||||||
|
self.play(Write(null_vector.label))
|
||||||
|
self.dither()
|
||||||
|
x_copy = x.copy()
|
||||||
|
self.play(x_copy.shift, null_vector.get_end())
|
||||||
|
self.add_vector(sum_vect, animate = True)
|
||||||
|
self.play(
|
||||||
|
FadeOut(x_copy),
|
||||||
|
Write(sum_vect.label)
|
||||||
|
)
|
||||||
|
self.dither()
|
||||||
|
self.play(
|
||||||
|
ShowCreation(form_rect),
|
||||||
|
sum_vect.label.replace, initial_sum
|
||||||
|
)
|
||||||
|
self.add_foreground_mobject(form_rect, sum_vect.label)
|
||||||
|
self.remove(x.label, null_vector.label)
|
||||||
|
self.apply_transposed_matrix(
|
||||||
|
self.t_matrix,
|
||||||
|
added_anims = [
|
||||||
|
Transform(null_vector, dot),
|
||||||
|
Write(transformer)
|
||||||
|
]
|
||||||
|
)
|
||||||
|
self.play(Write(final_sum))
|
||||||
|
self.dither()
|
||||||
|
self.play(Write(brace))
|
||||||
|
self.dither()
|
||||||
|
words = TextMobject(
|
||||||
|
"$\\vec{\\textbf{x}}$",
|
||||||
|
"and the",
|
||||||
|
"$\\vec{\\textbf{x}} + \\vec{\\textbf{n}}$\\\\",
|
||||||
|
"land on the same spot"
|
||||||
|
)
|
||||||
|
words[0].highlight(x.get_color())
|
||||||
|
VMobject(*words[2][:2]).highlight(x.get_color())
|
||||||
|
VMobject(*words[2][3:]).highlight(null_vector.get_color())
|
||||||
|
words.next_to(brace, DOWN)
|
||||||
|
words.to_edge(RIGHT)
|
||||||
|
self.play(Write(words))
|
||||||
|
self.dither()
|
||||||
|
|
||||||
|
class NullSpaceOffsetRule(Scene):
|
||||||
|
def construct(self):
|
||||||
|
vec = lambda s : "\\vec{\\textbf{%s}}"%s
|
||||||
|
equation = TexMobject("A", vec("x"), "=", vec("v"))
|
||||||
|
A, x, equals, v = equation
|
||||||
|
x.highlight(PINK)
|
||||||
|
v.highlight(YELLOW)
|
||||||
|
A_text = TextMobject(
|
||||||
|
"When $A$ is not", "full rank"
|
||||||
|
)
|
||||||
|
A_text[1].highlight(MAROON_C)
|
||||||
|
A_text.next_to(A, UP+LEFT, buff = 1)
|
||||||
|
A_text.shift_onto_screen()
|
||||||
|
A_arrow = Arrow(A_text.get_bottom(), A, color = WHITE)
|
||||||
|
v_text = TextMobject(
|
||||||
|
"If", "$%s$"%vec("v"), "is in the",
|
||||||
|
"column space", "of $A$"
|
||||||
|
)
|
||||||
|
v_text[1].highlight(YELLOW)
|
||||||
|
v_text[3].highlight(TEAL)
|
||||||
|
v_text.next_to(v, DOWN+RIGHT, buff = 1)
|
||||||
|
v_text.shift_onto_screen()
|
||||||
|
v_arrow = Arrow(v_text.get_top(), v, color = YELLOW)
|
||||||
|
|
||||||
|
|
||||||
|
self.add(equation)
|
||||||
|
self.play(Write(A_text, run_time = 2))
|
||||||
|
self.play(ShowCreation(A_arrow))
|
||||||
|
self.dither()
|
||||||
|
self.play(Write(v_text, run_time = 2))
|
||||||
|
self.play(ShowCreation(v_arrow))
|
||||||
|
self.dither()
|
||||||
|
|
||||||
|
class MuchLeftToLearn(TeacherStudentsScene):
|
||||||
|
def construct(self):
|
||||||
|
self.teacher_says(
|
||||||
|
"That's the high \\\\",
|
||||||
|
"level overview"
|
||||||
|
)
|
||||||
|
self.random_blink()
|
||||||
|
self.dither()
|
||||||
|
self.teacher_says(
|
||||||
|
"There is still \\\\",
|
||||||
|
"much to learn"
|
||||||
|
)
|
||||||
|
for pi in self.get_students():
|
||||||
|
target_mode = random.choice([
|
||||||
|
"raise_right_hand", "raise_left_hand"
|
||||||
|
])
|
||||||
|
self.play(pi.change_mode, target_mode)
|
||||||
|
self.random_blink()
|
||||||
|
self.dither()
|
||||||
|
|
||||||
|
class NotToLearnItAllNow(TeacherStudentsScene):
|
||||||
|
def construct(self):
|
||||||
|
self.teacher_says("""
|
||||||
|
The goal is not to
|
||||||
|
learn it all now
|
||||||
|
""")
|
||||||
|
self.random_blink()
|
||||||
|
self.dither()
|
||||||
|
self.random_blink()
|
||||||
|
|
||||||
|
class NextVideo(Scene):
|
||||||
|
def construct(self):
|
||||||
|
title = TextMobject("""
|
||||||
|
Next video: Nonsquare matrices
|
||||||
|
""")
|
||||||
|
title.scale_to_fit_width(2*SPACE_WIDTH - 2)
|
||||||
|
title.to_edge(UP)
|
||||||
|
rect = Rectangle(width = 16, height = 9, color = BLUE)
|
||||||
|
rect.scale_to_fit_height(6)
|
||||||
|
rect.next_to(title, DOWN)
|
||||||
|
|
||||||
|
self.add(title)
|
||||||
|
self.play(ShowCreation(rect))
|
||||||
|
self.dither()
|
||||||
|
|
||||||
|
class WhatAboutNonsquareMatrices(TeacherStudentsScene):
|
||||||
|
def construct(self):
|
||||||
|
self.student_says(
|
||||||
|
"What about \\\\ nonsquare matrices?",
|
||||||
|
pi_creature_target_mode = "raise_right_hand"
|
||||||
|
)
|
||||||
|
self.play(self.get_students()[0].change_mode, "confused")
|
||||||
|
self.random_blink(6)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
42
eola/footnote2.py
Normal file
42
eola/footnote2.py
Normal file
|
@ -0,0 +1,42 @@
|
||||||
|
from mobject.tex_mobject import TexMobject
|
||||||
|
from mobject import Mobject
|
||||||
|
from mobject.image_mobject import ImageMobject
|
||||||
|
from mobject.vectorized_mobject import VMobject
|
||||||
|
|
||||||
|
from animation.animation import Animation
|
||||||
|
from animation.transform import *
|
||||||
|
from animation.simple_animations import *
|
||||||
|
from topics.geometry import *
|
||||||
|
from topics.characters import *
|
||||||
|
from topics.functions import *
|
||||||
|
from topics.number_line import *
|
||||||
|
from topics.numerals import *
|
||||||
|
from scene import Scene
|
||||||
|
from camera import Camera
|
||||||
|
from mobject.svg_mobject import *
|
||||||
|
from mobject.tex_mobject import *
|
||||||
|
from mobject.vectorized_mobject import *
|
||||||
|
|
||||||
|
from eola.matrix import *
|
||||||
|
from eola.two_d_space import *
|
||||||
|
|
||||||
|
from ka_playgrounds.circuits import Resistor, Source, LongResistor
|
||||||
|
|
||||||
|
class OpeningQuote(Scene):
|
||||||
|
def construct(self):
|
||||||
|
words = TextMobject(
|
||||||
|
"On this quiz, I asked you to find the determinant of a",
|
||||||
|
"2x3 matrix.",
|
||||||
|
"Some of you, to my great amusement, actually tried to do this."
|
||||||
|
)
|
||||||
|
words.scale_to_fit_width(2*SPACE_WIDTH - 2)
|
||||||
|
words.to_edge(UP)
|
||||||
|
words[1].highlight(GREEN)
|
||||||
|
author = TextMobject("-(Linear algebra professor whose name I could not track down)")
|
||||||
|
author.highlight(YELLOW)
|
||||||
|
author.next_to(words, DOWN, buff = 0.5)
|
||||||
|
|
||||||
|
self.play(FadeIn(words))
|
||||||
|
self.dither(2)
|
||||||
|
self.play(Write(author, run_time = 3))
|
||||||
|
self.dither()
|
|
@ -74,6 +74,15 @@ class Chapter4p2(Chapter0):
|
||||||
"t_matrix" : [[1, 2], [-1, 1]]
|
"t_matrix" : [[1, 2], [-1, 1]]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class Chapter5(LinearTransformationScene):
|
||||||
|
def construct(self):
|
||||||
|
self.plane.fade()
|
||||||
|
self.add_unit_square()
|
||||||
|
self.plane.set_stroke(width = 6)
|
||||||
|
VMobject(self.i_hat, self.j_hat).set_stroke(width = 10)
|
||||||
|
self.square.set_fill(YELLOW, opacity = 0.7)
|
||||||
|
self.square.set_stroke(width = 0)
|
||||||
|
self.apply_transposed_matrix(self.t_matrix, run_time = 0)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -267,7 +267,7 @@ class Mobject(object):
|
||||||
self.shift(target - point_to_align)
|
self.shift(target - point_to_align)
|
||||||
return self
|
return self
|
||||||
|
|
||||||
def replace(self, mobject, stretch = False):
|
def replace(self, mobject, dim_to_match = 0, stretch = False):
|
||||||
if not mobject.get_num_points() and not mobject.submobjects:
|
if not mobject.get_num_points() and not mobject.submobjects:
|
||||||
raise Warning("Attempting to replace mobject with no points")
|
raise Warning("Attempting to replace mobject with no points")
|
||||||
return self
|
return self
|
||||||
|
@ -275,7 +275,11 @@ class Mobject(object):
|
||||||
self.stretch_to_fit_width(mobject.get_width())
|
self.stretch_to_fit_width(mobject.get_width())
|
||||||
self.stretch_to_fit_height(mobject.get_height())
|
self.stretch_to_fit_height(mobject.get_height())
|
||||||
else:
|
else:
|
||||||
self.scale_to_fit_width(mobject.get_width())
|
self.stretch_to_fit(
|
||||||
|
mobject.length_over_dim(dim_to_match),
|
||||||
|
dim_to_match,
|
||||||
|
stretch = False
|
||||||
|
)
|
||||||
self.shift(mobject.get_center() - self.get_center())
|
self.shift(mobject.get_center() - self.get_center())
|
||||||
return self
|
return self
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,7 @@ from helpers import *
|
||||||
from mobject import Mobject
|
from mobject import Mobject
|
||||||
from mobject.svg_mobject import SVGMobject
|
from mobject.svg_mobject import SVGMobject
|
||||||
from mobject.vectorized_mobject import VMobject
|
from mobject.vectorized_mobject import VMobject
|
||||||
from mobject.tex_mobject import TextMobject
|
from mobject.tex_mobject import TextMobject, TexMobject
|
||||||
|
|
||||||
from animation import Animation
|
from animation import Animation
|
||||||
from animation.transform import Transform, ApplyMethod, FadeOut, FadeIn
|
from animation.transform import Transform, ApplyMethod, FadeOut, FadeIn
|
||||||
|
@ -343,8 +343,12 @@ class TeacherStudentsScene(Scene):
|
||||||
pi_creature_target_mode = None,
|
pi_creature_target_mode = None,
|
||||||
added_anims = [],
|
added_anims = [],
|
||||||
**bubble_kwargs):
|
**bubble_kwargs):
|
||||||
if isinstance(content, str):
|
if all(map(lambda s : isinstance(s, str), content)):
|
||||||
content = TextMobject(content)
|
content = TextMobject(*content)
|
||||||
|
elif len(content) == 1 and isinstance(content[0], TexMobject):
|
||||||
|
content = content[0]
|
||||||
|
else:
|
||||||
|
raise Exception("Invalid content type")
|
||||||
content_intro_anims = self.get_bubble_intro_animation(
|
content_intro_anims = self.get_bubble_intro_animation(
|
||||||
content, bubble_type, pi_creature, **bubble_kwargs
|
content, bubble_type, pi_creature, **bubble_kwargs
|
||||||
)
|
)
|
||||||
|
@ -373,22 +377,22 @@ class TeacherStudentsScene(Scene):
|
||||||
self.play(*anims)
|
self.play(*anims)
|
||||||
return pi_creature.bubble
|
return pi_creature.bubble
|
||||||
|
|
||||||
def teacher_says(self, content = "", **kwargs):
|
def teacher_says(self, *content, **kwargs):
|
||||||
return self.introduce_bubble(
|
return self.introduce_bubble(
|
||||||
content, "speech", self.get_teacher(), **kwargs
|
content, "speech", self.get_teacher(), **kwargs
|
||||||
)
|
)
|
||||||
|
|
||||||
def student_says(self, content = "", student_index = 1, **kwargs):
|
def student_says(self, *content, **kwargs):
|
||||||
student = self.get_students()[student_index]
|
student = self.get_students()[kwargs.get("student_index", 1)]
|
||||||
return self.introduce_bubble(content, "speech", student, **kwargs)
|
return self.introduce_bubble(content, "speech", student, **kwargs)
|
||||||
|
|
||||||
def teacher_thinks(self, content = "", **kwargs):
|
def teacher_thinks(self, *content, **kwargs):
|
||||||
return self.introduce_bubble(
|
return self.introduce_bubble(
|
||||||
content, "thought", self.get_teacher(), **kwargs
|
content, "thought", self.get_teacher(), **kwargs
|
||||||
)
|
)
|
||||||
|
|
||||||
def student_thinks(self, content = "", student_index = 1, **kwargs):
|
def student_thinks(self, *content, **kwargs):
|
||||||
student = self.get_students()[student_index]
|
student = self.get_students()[kwargs.get("student_index", 1)]
|
||||||
return self.introduce_bubble(content, "thought", student, **kwargs)
|
return self.introduce_bubble(content, "thought", student, **kwargs)
|
||||||
|
|
||||||
def random_blink(self, num_times = 1):
|
def random_blink(self, num_times = 1):
|
||||||
|
@ -397,6 +401,11 @@ class TeacherStudentsScene(Scene):
|
||||||
self.play(Blink(pi_creature))
|
self.play(Blink(pi_creature))
|
||||||
self.dither()
|
self.dither()
|
||||||
|
|
||||||
|
def change_student_modes(self, *modes):
|
||||||
|
self.play(*[
|
||||||
|
ApplyMethod(pi.change_mode, mode)
|
||||||
|
for pi, mode in zip(self.get_students(), modes)
|
||||||
|
])
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue