Beginning eola project

This commit is contained in:
Grant Sanderson 2016-07-12 10:36:04 -07:00
parent dfedc6422e
commit c910b00a32
3 changed files with 389 additions and 0 deletions

0
eola/__init__.py Normal file
View file

299
eola/chapter0.py Normal file
View file

@ -0,0 +1,299 @@
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 animation.playground import *
from topics.geometry import *
from topics.characters import *
from topics.functions import *
from topics.number_line import *
from topics.combinatorics import *
from scene import Scene
from camera import Camera
from mobject.svg_mobject import *
from mobject.tex_mobject import *
from eola.utils import *
EXAMPLE_TRANFORM = [[0, 1], [-1, 1]]
TRANFORMED_VECTOR = [[1], [2]]
class OpeningQuote(Scene):
def construct(self):
words = TextMobject(
"""
``There is hardly any theory which is more elementary
than linear algebra, in spite of the fact that generations
of professors and textbook writers have obscured its
simplicity by preposterous calculations with matrices.''
""",
organize_left_to_right = False
)
words.scale_to_fit_width(2*(SPACE_WIDTH-1))
words.to_edge(UP)
for mob in words.submobjects[48:49+13]:
mob.highlight(GREEN)
words.show()
author = TextMobject("-Hermann Weyl")
author.highlight(YELLOW)
author.next_to(words, DOWN)
self.play(Write(words))
self.dither()
self.play(FadeIn(author))
self.dither()
class AboutLinearAlgebra(Scene):
def construct(self):
self.show_dependencies()
self.linalg_is_confusing()
self.ask_questions()
def show_dependencies(self):
linalg = TextMobject("Linear Algebra")
subjects = map(TextMobject, [
"Computer science",
"Physics",
"Electrical engineering",
"Mechanical engineering",
"Statistics",
"\\vdots"
])
prev = subjects[0]
for subject in subjects[1:]:
subject.next_to(prev, DOWN, aligned_edge = LEFT)
prev = subject
all_subs = VMobject(*subjects)
linalg.to_edge(LEFT)
all_subs.next_to(linalg, RIGHT, buff = 2)
arrows = VMobject(*[
Arrow(linalg, sub)
for sub in subjects
])
self.play(Write(linalg, run_time = 1))
self.dither()
self.play(
ShowCreation(arrows, submobject_mode = "lagged_start"),
FadeIn(all_subs),
run_time = 2
)
self.dither()
self.linalg = linalg
def linalg_is_confusing(self):
linalg = self.linalg
all_else = list(self.mobjects)
all_else.remove(linalg)
randy = Randolph()
randy.to_corner()
bubble = randy.get_bubble(width = 10)
new_linalg = bubble.position_mobject_inside(linalg.copy())
self.play(*map(FadeOut, all_else))
self.remove(*all_else)
self.play(
Transform(linalg, new_linalg),
Write(bubble),
FadeIn(randy)
)
self.play(ApplyMethod(randy.change_mode, "confused"))
self.dither()
self.play(Blink(randy))
self.play(FadeOut(linalg))
self.remove(linalg)
self.randy, self.bubble = randy, bubble
def ask_questions(self):
randy, bubble = self.randy, self.bubble
matrix_multiplication = TexMobject("""
\\left[
\\begin{array}{cc}
a & b \\\\
c & d
\\end{array}
\\right]
\\left[
\\begin{array}{cc}
e & f \\\\
g & h
\\end{array}
\\right]
=
\\left[
\\begin{array}{cc}
ae + bg & af + bh \\\\
ce + dg & cf + dh
\\end{array}
\\right]
""")
cross = TexMobject("\\vec{v} \\times \\vec{w}")
left_right_arrow = DoubleArrow(Point(LEFT), Point(RIGHT))
det = TextMobject("Det")
q_mark = TextMobject("?")
left_right_arrow.next_to(cross)
det.next_to(left_right_arrow)
q_mark.next_to(left_right_arrow, UP)
cross_question = VMobject(cross, left_right_arrow, q_mark, det)
cross_question.get_center = lambda : left_right_arrow.get_center()
eigen_q = TextMobject("Eigen?")
for mob in matrix_multiplication, cross_question, eigen_q:
bubble.position_mobject_inside(mob)
self.play(FadeIn(mob))
if randy.mode is not "pondering":
self.play(ApplyMethod(randy.change_mode, "pondering"))
self.dither()
else:
self.dither(2)
self.remove(mob)
class NumericVsGeometric(Scene):
def construct(self):
self.setup()
self.specifics_concepts()
self.clear_way_for_geometric()
self.list_geometric_benefits()
def setup(self):
numeric = TextMobject("Numeric operations")
geometric = TextMobject("Geometric intuition")
for mob in numeric, geometric:
mob.to_corner(UP+LEFT)
geometric.shift(SPACE_WIDTH*RIGHT)
hline = Line(SPACE_WIDTH*LEFT, SPACE_WIDTH*RIGHT)
hline.next_to(numeric, DOWN)
hline.to_edge(LEFT, buff = 0)
vline = Line(SPACE_HEIGHT*UP, SPACE_HEIGHT*DOWN)
for mob in hline, vline:
mob.highlight(GREEN)
self.play(ShowCreation(VMobject(hline, vline)))
digest_locals(self)
def specifics_concepts(self):
matrix_vector_product = TexMobject(" ".join([
matrix_to_tex_string(EXAMPLE_TRANFORM),
matrix_to_tex_string(TRANFORMED_VECTOR),
"&=",
matrix_to_tex_string([
["1 \\cdot 1 + 0 \\cdot 2"],
["1 \\cdot 1 + (-1)\\cdot 2"]
]),
"\\\\ &=",
matrix_to_tex_string([[1], [-1]]),
]))
matrix_vector_product.scale_to_fit_width(SPACE_WIDTH-0.5)
matrix_vector_product.next_to(self.vline, LEFT)
self.play(
Write(self.numeric),
FadeIn(matrix_vector_product),
run_time = 2
)
self.dither()
self.play(Write(self.geometric, run_time = 2))
### Paste in linear transformation
self.dither()
digest_locals(self)
def clear_way_for_geometric(self):
new_line = Line(SPACE_HEIGHT*LEFT, SPACE_HEIGHT*RIGHT)
new_line.shift((SPACE_HEIGHT+1)*DOWN)
self.play(
Transform(self.vline, new_line),
Transform(self.hline, new_line),
ApplyMethod(self.numeric.shift, (2*SPACE_HEIGHT+1)*DOWN),
ApplyMethod(
self.matrix_vector_product.shift,
(2*SPACE_HEIGHT+1)*DOWN
),
ApplyMethod(self.geometric.to_edge, LEFT)
)
def list_geometric_benefits(self):
follow_words = TextMobject("is helpful for \\dots")
follow_words.next_to(self.geometric)
#Ugly hack
diff = follow_words.submobjects[0].get_bottom()[1] - \
self.geometric.submobjects[0].get_bottom()[1]
follow_words.shift(diff*DOWN)
randys = [
Randolph(mode = "speaking"),
Randolph(mode = "surprised"),
Randolph(mode = "pondering")
]
bulb = SVGMobject("light_bulb")
bulb.scale_to_fit_height(1)
bulb.highlight(YELLOW)
thoughts = [
matrix_to_mobject(EXAMPLE_TRANFORM),
bulb,
TextMobject("So therefore...").scale(0.5)
]
self.play(Write(follow_words, run_time = 1.5))
curr_randy = None
for randy, thought in zip(randys, thoughts):
randy.shift(DOWN)
thought.next_to(randy, UP+RIGHT, buff = 0)
if curr_randy:
self.play(
Transform(curr_randy, randy),
Transform(curr_thought, thought)
)
else:
self.play(
FadeIn(randy),
Write(thought, run_time = 1)
)
curr_randy = randy
curr_thought = thought
self.dither(1.5)
class ExampleTransformation(LinearTransformationScene):
def construct(self):
self.setup()
self.apply_matrix(EXAMPLE_TRANFORM)
self.dither()
class NumericToComputations(Scene):
def construct(self):
top = TextMobject("Numeric understanding")
arrow = Arrow(UP, DOWN)
bottom = TextMobject("Actual computations")
top.next_to(arrow, UP)
bottom.next_to(arrow, DOWN)
self.add(top)
self.play(ShowCreation(arrow, submobject_mode = "one_at_a_time"))
self.play(FadeIn(bottom))
self.dither()

90
eola/utils.py Normal file
View file

@ -0,0 +1,90 @@
import numpy as np
from scene import Scene
from mobject.vectorized_mobject import VMobject
from mobject.tex_mobject import TexMobject, TextMobject
from animation.transform import ApplyMatrix, ApplyMethod
from topics.number_line import NumberPlane
from topics.geometry import Vector
from helpers import *
def matrix_to_tex_string(matrix):
matrix = np.array(matrix).astype("string")
n_rows, n_cols = matrix.shape
prefix = "\\left[ \\begin{array}{%s}"%("c"*n_cols)
suffix = "\\end{array} \\right]"
rows = [
" & ".join(row)
for row in matrix
]
return prefix + " \\\\ ".join(rows) + suffix
def matrix_to_mobject(matrix):
return TexMobject(matrix_to_tex_string(matrix))
class LinearTransformationScene(Scene):
CONFIG = {
"include_background_plane" : True,
"include_foreground_plane" : True,
"foreground_plane_kwargs" : {
"x_radius" : 2*SPACE_WIDTH,
"y_radius" : 2*SPACE_HEIGHT,
},
"background_plane_kwargs" : {},
"show_coordinates" : False,
"show_basis_vectors" : True,
"i_hat_color" : GREEN_B,
"j_hat_color" : RED,
}
def setup(self):
self.background_mobjects = []
self.foreground_mobjects = []
self.background_plane = NumberPlane(
color = GREY,
secondary_color = DARK_GREY,
**self.background_plane_kwargs
)
if self.show_coordinates:
self.background_plane.add_coordinates()
if self.include_background_plane:
self.add_to_background(self.background_plane)
if self.include_foreground_plane:
self.plane = NumberPlane(**self.foreground_plane_kwargs)
self.add_to_foreground(self.plane)
if self.show_basis_vectors:
i_hat = Vector(self.background_plane.num_pair_to_point((1, 0)))
j_hat = Vector(self.background_plane.num_pair_to_point((0, 1)))
i_hat.highlight(self.i_hat_color)
j_hat.highlight(self.j_hat_color)
self.add_to_foreground(i_hat, j_hat)
def add_to_background(self, *mobjects):
for mobject in mobjects:
if mobject not in self.background_mobjects:
self.background_mobjects.append(mobject)
self.add(mobject)
def add_to_foreground(self, *mobjects):
for mobject in mobjects:
if mobject not in self.foreground_mobjects:
self.foreground_mobjects.append(mobject)
self.add(mobject)
def apply_matrix(self, matrix, **kwargs):
self.play(ApplyMatrix(
matrix,
VMobject(*self.foreground_mobjects),
**kwargs
))