mirror of
https://github.com/3b1b/manim.git
synced 2025-08-05 16:49:03 +00:00
Up to motivation for analytic continuation
This commit is contained in:
parent
b4af73616f
commit
7f71829ce1
2 changed files with 768 additions and 32 deletions
|
@ -126,9 +126,10 @@ class Homotopy(Animation):
|
||||||
**self.apply_function_kwargs
|
**self.apply_function_kwargs
|
||||||
)
|
)
|
||||||
|
|
||||||
def update_mobject(self, alpha):
|
class SmoothedVectorizedHomotopy(Homotopy):
|
||||||
Animation.update_mobject(self, alpha)
|
def update_submobject(self, submob, start, alpha):
|
||||||
|
Homotopy.update_submobject(self, submob, start, alpha)
|
||||||
|
submob.make_smooth()
|
||||||
|
|
||||||
|
|
||||||
class PhaseFlow(Animation):
|
class PhaseFlow(Animation):
|
||||||
|
|
793
zeta.py
793
zeta.py
|
@ -108,13 +108,13 @@ class ComplexTransformationScene(Scene):
|
||||||
|
|
||||||
def add_transformable_plane(self, animate = False):
|
def add_transformable_plane(self, animate = False):
|
||||||
self.plane_config.update({
|
self.plane_config.update({
|
||||||
"x_radius" : (self.x_max - self.x_min)/2,
|
"x_radius" : (self.x_max - self.x_min)/2.,
|
||||||
"y_radius" : (self.y_max - self.y_min)/2,
|
"y_radius" : (self.y_max - self.y_min)/2.,
|
||||||
})
|
})
|
||||||
plane = NumberPlane(**self.plane_config)
|
plane = NumberPlane(**self.plane_config)
|
||||||
plane.shift(
|
plane.shift(
|
||||||
(self.x_max+self.x_min)*RIGHT/2,
|
(self.x_max+self.x_min)*RIGHT/2.,
|
||||||
(self.y_max+self.y_min)*UP/2,
|
(self.y_max+self.y_min)*UP/2.,
|
||||||
)
|
)
|
||||||
self.paint_plane(plane)
|
self.paint_plane(plane)
|
||||||
if animate:
|
if animate:
|
||||||
|
@ -141,16 +141,23 @@ class ComplexTransformationScene(Scene):
|
||||||
self.horiz_start_color,
|
self.horiz_start_color,
|
||||||
self.vert_start_color
|
self.vert_start_color
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def z_to_point(self, z):
|
||||||
|
return self.background.num_pair_to_point((z.real, z.imag))
|
||||||
|
|
||||||
def apply_complex_function(self, func, **kwargs):
|
def get_transformer(self, **kwargs):
|
||||||
transform_kwargs = dict(self.default_apply_complex_function_kwargs)
|
transform_kwargs = dict(self.default_apply_complex_function_kwargs)
|
||||||
transform_kwargs.update(kwargs)
|
transform_kwargs.update(kwargs)
|
||||||
|
|
||||||
plane = self.plane
|
plane = self.plane
|
||||||
self.add_points_to_plane(plane)
|
self.add_points_to_plane(plane)
|
||||||
transformer = VGroup(
|
transformer = VGroup(
|
||||||
plane, *self.transformable_mobjects
|
plane, *self.transformable_mobjects
|
||||||
)
|
)
|
||||||
|
return transformer, transform_kwargs
|
||||||
|
|
||||||
|
|
||||||
|
def apply_complex_function(self, func, added_anims = [], **kwargs):
|
||||||
|
transformer, transform_kwargs = self.get_transformer(**kwargs)
|
||||||
transformer.generate_target()
|
transformer.generate_target()
|
||||||
transformer.target.apply_complex_function(func)
|
transformer.target.apply_complex_function(func)
|
||||||
for mob in transformer.target[0].family_members_with_points():
|
for mob in transformer.target[0].family_members_with_points():
|
||||||
|
@ -158,17 +165,31 @@ class ComplexTransformationScene(Scene):
|
||||||
if mob.get_stroke_width() == 1 and self.thincken_lines_after_transformation:
|
if mob.get_stroke_width() == 1 and self.thincken_lines_after_transformation:
|
||||||
mob.set_stroke(width = 2)
|
mob.set_stroke(width = 2)
|
||||||
self.play(
|
self.play(
|
||||||
MoveToTarget(transformer),
|
MoveToTarget(transformer, **transform_kwargs),
|
||||||
**transform_kwargs
|
*added_anims
|
||||||
|
)
|
||||||
|
|
||||||
|
def apply_complex_homotopy(self, complex_homotopy, added_anims = [], **kwargs):
|
||||||
|
transformer, transform_kwargs = self.get_transformer(**kwargs)
|
||||||
|
def homotopy(x, y, z, t):
|
||||||
|
output = complex_homotopy(complex(x, y), t)
|
||||||
|
return (output.real, output.imag, z)
|
||||||
|
|
||||||
|
self.play(
|
||||||
|
SmoothedVectorizedHomotopy(
|
||||||
|
homotopy, transformer,
|
||||||
|
**transform_kwargs
|
||||||
|
),
|
||||||
|
*added_anims
|
||||||
)
|
)
|
||||||
|
|
||||||
class ZetaTransformationScene(ComplexTransformationScene):
|
class ZetaTransformationScene(ComplexTransformationScene):
|
||||||
CONFIG = {
|
CONFIG = {
|
||||||
"num_anchors_to_add_per_line" : 300,
|
"num_anchors_in_extra_lines" : 300,
|
||||||
|
"num_anchors_to_add_per_line" : 75,
|
||||||
"thincken_lines_after_transformation" : True,
|
"thincken_lines_after_transformation" : True,
|
||||||
"default_apply_complex_function_kwargs" : {
|
"default_apply_complex_function_kwargs" : {
|
||||||
"submobject_mode" : "lagged_start",
|
"run_time" : 5,
|
||||||
"run_time" : 8,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
def add_extra_plane_lines_for_zeta(self, step_size = 1./16, animate = False):
|
def add_extra_plane_lines_for_zeta(self, step_size = 1./16, animate = False):
|
||||||
|
@ -197,6 +218,9 @@ class ZetaTransformationScene(ComplexTransformationScene):
|
||||||
)
|
)
|
||||||
for lines in horiz_lines, vert_lines:
|
for lines in horiz_lines, vert_lines:
|
||||||
lines.set_stroke(width = 1)
|
lines.set_stroke(width = 1)
|
||||||
|
for line in lines:
|
||||||
|
line.insert_n_anchor_points(self.num_anchors_in_extra_lines)
|
||||||
|
lines.make_smooth()
|
||||||
if animate:
|
if animate:
|
||||||
self.play(*[
|
self.play(*[
|
||||||
ShowCreation(lines)
|
ShowCreation(lines)
|
||||||
|
@ -205,6 +229,16 @@ class ZetaTransformationScene(ComplexTransformationScene):
|
||||||
self.plane.add(vert_lines, horiz_lines)
|
self.plane.add(vert_lines, horiz_lines)
|
||||||
self.add(self.plane)
|
self.add(self.plane)
|
||||||
|
|
||||||
|
def get_reflected_plane(self):
|
||||||
|
reflected_plane = self.plane.copy()
|
||||||
|
reflected_plane.rotate(np.pi, UP)
|
||||||
|
reflected_plane.move_to(self.z_to_point(1), RIGHT)
|
||||||
|
for mob in reflected_plane.family_members_with_points():
|
||||||
|
mob.highlight(
|
||||||
|
Color(rgb = 1-0.5*color_to_rgb(mob.get_color()))
|
||||||
|
)
|
||||||
|
return reflected_plane
|
||||||
|
|
||||||
def apply_zeta_function(self, **kwargs):
|
def apply_zeta_function(self, **kwargs):
|
||||||
transform_kwargs = dict(self.default_apply_complex_function_kwargs)
|
transform_kwargs = dict(self.default_apply_complex_function_kwargs)
|
||||||
transform_kwargs.update(kwargs)
|
transform_kwargs.update(kwargs)
|
||||||
|
@ -231,13 +265,21 @@ class TestZetaOnHalfPlane(ZetaTransformationScene):
|
||||||
self.apply_zeta_function()
|
self.apply_zeta_function()
|
||||||
self.dither(3)
|
self.dither(3)
|
||||||
|
|
||||||
|
class TestZetaOnLine(ZetaTransformationScene):
|
||||||
|
def construct(self):
|
||||||
|
line = Line(UP+20*LEFT, UP+20*RIGHT)
|
||||||
|
self.add_transformable_plane()
|
||||||
|
self.plane.submobjects = [line]
|
||||||
|
self.apply_zeta_function()
|
||||||
|
self.dither(2)
|
||||||
|
self.play(ShowCreation(line, run_time = 10))
|
||||||
|
self.dither(3)
|
||||||
|
|
||||||
######################
|
######################
|
||||||
|
|
||||||
class IntroduceZeta(ZetaTransformationScene):
|
class IntroduceZeta(ZetaTransformationScene):
|
||||||
CONFIG = {
|
CONFIG = {
|
||||||
"num_anchors_to_add_per_line" : 300,
|
|
||||||
"default_apply_complex_function_kwargs" : {
|
"default_apply_complex_function_kwargs" : {
|
||||||
"submobject_mode" : "lagged_start",
|
|
||||||
"run_time" : 8,
|
"run_time" : 8,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -803,6 +845,7 @@ class FromRealToComplex(ComplexTransformationScene):
|
||||||
},
|
},
|
||||||
"background_label_scale_val" : 0.7,
|
"background_label_scale_val" : 0.7,
|
||||||
"output_color" : GREEN_B,
|
"output_color" : GREEN_B,
|
||||||
|
"num_lines_in_spiril_sum" : 1000,
|
||||||
}
|
}
|
||||||
def construct(self):
|
def construct(self):
|
||||||
self.handle_background()
|
self.handle_background()
|
||||||
|
@ -814,6 +857,7 @@ class FromRealToComplex(ComplexTransformationScene):
|
||||||
self.transition_to_spiril_sum()
|
self.transition_to_spiril_sum()
|
||||||
self.vary_complex_input()
|
self.vary_complex_input()
|
||||||
self.show_domain_of_convergence()
|
self.show_domain_of_convergence()
|
||||||
|
self.ask_about_visualizing_all()
|
||||||
|
|
||||||
def handle_background(self):
|
def handle_background(self):
|
||||||
self.remove(self.background)
|
self.remove(self.background)
|
||||||
|
@ -1014,13 +1058,14 @@ class FromRealToComplex(ComplexTransformationScene):
|
||||||
self.play(FadeOut(self.input_label))
|
self.play(FadeOut(self.input_label))
|
||||||
self.dither(2)
|
self.dither(2)
|
||||||
inputs = [
|
inputs = [
|
||||||
complex(1.2, 1),
|
complex(1.5, 1.8),
|
||||||
complex(1.2, -1),
|
complex(1.5, -1),
|
||||||
complex(3, -1),
|
complex(3, -1),
|
||||||
complex(1, 1),
|
complex(1.5, 1.8),
|
||||||
complex(0.8, -1),
|
complex(1.5, -1.8),
|
||||||
complex(0.8, -14.135),
|
complex(1.4, -1.8),
|
||||||
# complex(2, 1),
|
complex(1.5, 0),
|
||||||
|
complex(2, 1),
|
||||||
]
|
]
|
||||||
for s in inputs:
|
for s in inputs:
|
||||||
input_point = self.z_to_point(s)
|
input_point = self.z_to_point(s)
|
||||||
|
@ -1032,9 +1077,81 @@ class FromRealToComplex(ComplexTransformationScene):
|
||||||
run_time = 2
|
run_time = 2
|
||||||
)
|
)
|
||||||
self.dither()
|
self.dither()
|
||||||
|
self.dither()
|
||||||
|
|
||||||
def show_domain_of_convergence(self):
|
def show_domain_of_convergence(self, opacity = 0.2):
|
||||||
pass
|
domain = Rectangle(
|
||||||
|
width = SPACE_WIDTH-2,
|
||||||
|
height = 2*SPACE_HEIGHT,
|
||||||
|
stroke_width = 0,
|
||||||
|
fill_color = YELLOW,
|
||||||
|
fill_opacity = opacity,
|
||||||
|
)
|
||||||
|
domain.to_edge(RIGHT, buff = 0)
|
||||||
|
anti_domain = Rectangle(
|
||||||
|
width = SPACE_WIDTH+2,
|
||||||
|
height = 2*SPACE_HEIGHT,
|
||||||
|
stroke_width = 0,
|
||||||
|
fill_color = RED,
|
||||||
|
fill_opacity = opacity,
|
||||||
|
)
|
||||||
|
anti_domain.to_edge(LEFT, buff = 0)
|
||||||
|
|
||||||
|
domain_words = TextMobject("""
|
||||||
|
$\\zeta(s)$ happily
|
||||||
|
converges and
|
||||||
|
makes sense
|
||||||
|
""")
|
||||||
|
domain_words.to_corner(UP+RIGHT, buff = 2*MED_BUFF)
|
||||||
|
|
||||||
|
anti_domain_words = TextMobject("""
|
||||||
|
Not so much...
|
||||||
|
""")
|
||||||
|
anti_domain_words.next_to(ORIGIN, LEFT, buff = LARGE_BUFF)
|
||||||
|
anti_domain_words.shift(1.5*DOWN)
|
||||||
|
|
||||||
|
self.play(FadeIn(domain))
|
||||||
|
self.play(Write(domain_words))
|
||||||
|
self.dither()
|
||||||
|
self.play(FadeIn(anti_domain))
|
||||||
|
self.play(Write(anti_domain_words))
|
||||||
|
self.dither(2)
|
||||||
|
self.play(*map(FadeOut, [
|
||||||
|
anti_domain, anti_domain_words,
|
||||||
|
]))
|
||||||
|
self.domain_words = domain_words
|
||||||
|
|
||||||
|
def ask_about_visualizing_all(self):
|
||||||
|
morty = Mortimer().flip()
|
||||||
|
morty.scale(0.7)
|
||||||
|
morty.to_corner(DOWN+LEFT)
|
||||||
|
bubble = morty.get_bubble("speech", height = 4)
|
||||||
|
bubble.set_fill(BLACK, opacity = 0.5)
|
||||||
|
bubble.write("""
|
||||||
|
How can we visualize
|
||||||
|
this for all inputs?
|
||||||
|
""")
|
||||||
|
|
||||||
|
self.play(FadeIn(morty))
|
||||||
|
self.play(
|
||||||
|
morty.change_mode, "speaking",
|
||||||
|
ShowCreation(bubble),
|
||||||
|
Write(bubble.content)
|
||||||
|
)
|
||||||
|
self.play(Blink(morty))
|
||||||
|
self.dither(3)
|
||||||
|
self.play(
|
||||||
|
morty.change_mode, "pondering",
|
||||||
|
morty.look_at, self.input_dot,
|
||||||
|
*map(FadeOut, [
|
||||||
|
bubble, bubble.content, self.domain_words
|
||||||
|
])
|
||||||
|
)
|
||||||
|
arrow = Arrow(self.input_dot, self.output_dot, buff = SMALL_BUFF)
|
||||||
|
arrow.highlight(WHITE)
|
||||||
|
self.play(ShowCreation(arrow))
|
||||||
|
self.play(Blink(morty))
|
||||||
|
self.dither()
|
||||||
|
|
||||||
def get_zeta_definition(self, input_string, output_string, input_color = YELLOW):
|
def get_zeta_definition(self, input_string, output_string, input_color = YELLOW):
|
||||||
inputs = VGroup()
|
inputs = VGroup()
|
||||||
|
@ -1068,20 +1185,19 @@ class FromRealToComplex(ComplexTransformationScene):
|
||||||
group.add_to_back(BackgroundRectangle(group))
|
group.add_to_back(BackgroundRectangle(group))
|
||||||
return group
|
return group
|
||||||
|
|
||||||
def z_to_point(self, z):
|
|
||||||
return self.background.num_pair_to_point((z.real, z.imag))
|
|
||||||
|
|
||||||
def get_sum_lines(self, exponent, line_thickness = 6):
|
def get_sum_lines(self, exponent, line_thickness = 6):
|
||||||
num_lines = 200
|
powers = [0] + [
|
||||||
powers = [0] + [x**(-exponent) for x in range(1, num_lines)]
|
x**(-exponent)
|
||||||
|
for x in range(1, self.num_lines_in_spiril_sum)
|
||||||
|
]
|
||||||
power_sums = np.cumsum(powers)
|
power_sums = np.cumsum(powers)
|
||||||
lines = VGroup(*[
|
lines = VGroup(*[
|
||||||
Line(*map(self.z_to_point, z_pair))
|
Line(*map(self.z_to_point, z_pair))
|
||||||
for z_pair in zip(power_sums, power_sums[1:])
|
for z_pair in zip(power_sums, power_sums[1:])
|
||||||
])
|
])
|
||||||
lines.set_stroke(width = line_thickness)
|
widths = np.linspace(line_thickness, 0, len(list(lines)))
|
||||||
# VGroup(*lines[:4]).gradient_highlight(RED, GREEN_B)
|
for line, width in zip(lines, widths):
|
||||||
# VGroup(*lines[4:]).gradient_highlight(GREEN_B, MAROON_B)
|
line.set_stroke(width = width)
|
||||||
VGroup(*lines[::2]).highlight(MAROON_B)
|
VGroup(*lines[::2]).highlight(MAROON_B)
|
||||||
VGroup(*lines[1::2]).highlight(RED)
|
VGroup(*lines[1::2]).highlight(RED)
|
||||||
|
|
||||||
|
@ -1092,6 +1208,625 @@ class FromRealToComplex(ComplexTransformationScene):
|
||||||
|
|
||||||
return lines, final_dot
|
return lines, final_dot
|
||||||
|
|
||||||
|
class ComplexExponentiation(Scene):
|
||||||
|
def construct(self):
|
||||||
|
self.extract_pure_imaginary_part()
|
||||||
|
self.add_on_planes()
|
||||||
|
self.show_imaginary_powers()
|
||||||
|
|
||||||
|
def extract_pure_imaginary_part(self):
|
||||||
|
original = TexMobject(
|
||||||
|
"\\left(\\frac{1}{2}\\right)", "^{2+i}"
|
||||||
|
)
|
||||||
|
split = TexMobject(
|
||||||
|
"\\left(\\frac{1}{2}\\right)", "^{2}",
|
||||||
|
"\\left(\\frac{1}{2}\\right)", "^{i}",
|
||||||
|
)
|
||||||
|
VGroup(original[-1], split[1], split[3]).highlight(YELLOW)
|
||||||
|
VGroup(original, split).shift(UP)
|
||||||
|
real_part = VGroup(*split[:2])
|
||||||
|
imag_part = VGroup(*split[2:])
|
||||||
|
|
||||||
|
brace = Brace(real_part)
|
||||||
|
we_understand = brace.get_text(
|
||||||
|
"We understand this"
|
||||||
|
)
|
||||||
|
VGroup(brace, we_understand).highlight(GREEN_B)
|
||||||
|
|
||||||
|
self.add(original)
|
||||||
|
self.dither()
|
||||||
|
self.play(*[
|
||||||
|
Transform(*pair)
|
||||||
|
for pair in [
|
||||||
|
(original[0], split[0]),
|
||||||
|
(original[1][0], split[1]),
|
||||||
|
(original[0].copy(), split[2]),
|
||||||
|
(VGroup(*original[1][1:]), split[3]),
|
||||||
|
]
|
||||||
|
])
|
||||||
|
self.remove(*self.get_mobjects_from_last_animation())
|
||||||
|
self.add(real_part, imag_part)
|
||||||
|
self.dither()
|
||||||
|
self.play(
|
||||||
|
GrowFromCenter(brace),
|
||||||
|
FadeIn(we_understand),
|
||||||
|
real_part.highlight, GREEN_B
|
||||||
|
)
|
||||||
|
self.dither()
|
||||||
|
self.play(
|
||||||
|
imag_part.move_to, imag_part.get_left(),
|
||||||
|
*map(FadeOut, [brace, we_understand, real_part])
|
||||||
|
)
|
||||||
|
self.dither()
|
||||||
|
self.imag_exponent = imag_part
|
||||||
|
|
||||||
|
def add_on_planes(self):
|
||||||
|
left_plane = NumberPlane(x_radius = (SPACE_WIDTH-1)/2)
|
||||||
|
left_plane.to_edge(LEFT, buff = 0)
|
||||||
|
imag_line = Line(DOWN, UP).scale(SPACE_HEIGHT)
|
||||||
|
imag_line.highlight(YELLOW).fade(0.3)
|
||||||
|
imag_line.move_to(left_plane.get_center())
|
||||||
|
left_plane.add(imag_line)
|
||||||
|
left_title = TextMobject("Input space")
|
||||||
|
left_title.add_background_rectangle()
|
||||||
|
left_title.highlight(YELLOW)
|
||||||
|
left_title.next_to(left_plane.get_top(), DOWN)
|
||||||
|
|
||||||
|
right_plane = NumberPlane(x_radius = (SPACE_WIDTH-1)/2)
|
||||||
|
right_plane.to_edge(RIGHT, buff = 0)
|
||||||
|
unit_circle = Circle()
|
||||||
|
unit_circle.highlight(MAROON_B).fade(0.3)
|
||||||
|
unit_circle.shift(right_plane.get_center())
|
||||||
|
right_plane.add(unit_circle)
|
||||||
|
right_title = TextMobject("Output space")
|
||||||
|
right_title.add_background_rectangle()
|
||||||
|
right_title.highlight(MAROON_B)
|
||||||
|
right_title.next_to(right_plane.get_top(), DOWN)
|
||||||
|
|
||||||
|
for plane in left_plane, right_plane:
|
||||||
|
labels = VGroup()
|
||||||
|
for x in range(-2, 3):
|
||||||
|
label = TexMobject(str(x))
|
||||||
|
label.move_to(plane.num_pair_to_point((x, 0)))
|
||||||
|
labels.add(label)
|
||||||
|
for y in range(-3, 4):
|
||||||
|
if y == 0:
|
||||||
|
continue
|
||||||
|
label = TexMobject(str(y) + "i")
|
||||||
|
label.move_to(plane.num_pair_to_point((0, y)))
|
||||||
|
labels.add(label)
|
||||||
|
for label in labels:
|
||||||
|
label.scale_in_place(0.5)
|
||||||
|
label.next_to(
|
||||||
|
label.get_center(), DOWN+RIGHT,
|
||||||
|
buff = SMALL_BUFF
|
||||||
|
)
|
||||||
|
plane.add(labels)
|
||||||
|
|
||||||
|
arrow = Arrow(LEFT, RIGHT)
|
||||||
|
|
||||||
|
self.play(
|
||||||
|
ShowCreation(left_plane),
|
||||||
|
Write(left_title),
|
||||||
|
run_time = 3
|
||||||
|
)
|
||||||
|
self.play(
|
||||||
|
ShowCreation(right_plane),
|
||||||
|
Write(right_title),
|
||||||
|
run_time = 3
|
||||||
|
)
|
||||||
|
self.play(ShowCreation(arrow))
|
||||||
|
self.dither()
|
||||||
|
self.left_plane = left_plane
|
||||||
|
self.right_plane = right_plane
|
||||||
|
|
||||||
|
def show_imaginary_powers(self):
|
||||||
|
i = complex(0, 1)
|
||||||
|
input_dot = Dot(self.z_to_point(i))
|
||||||
|
input_dot.highlight(YELLOW)
|
||||||
|
output_dot = Dot(self.z_to_point(0.5**(i), is_input = False))
|
||||||
|
output_dot.highlight(MAROON_B)
|
||||||
|
|
||||||
|
output_dot.save_state()
|
||||||
|
output_dot.move_to(input_dot)
|
||||||
|
output_dot.highlight(input_dot.get_color())
|
||||||
|
|
||||||
|
curr_base = 0.5
|
||||||
|
def output_dot_update(ouput_dot):
|
||||||
|
y = input_dot.get_center()[1]
|
||||||
|
output_dot.move_to(self.z_to_point(
|
||||||
|
curr_base**complex(0, y), is_input = False
|
||||||
|
))
|
||||||
|
return output_dot
|
||||||
|
|
||||||
|
def walk_up_and_down():
|
||||||
|
for vect in 3*DOWN, 5*UP, 5*DOWN, 2*UP:
|
||||||
|
self.play(
|
||||||
|
input_dot.shift, vect,
|
||||||
|
UpdateFromFunc(output_dot, output_dot_update),
|
||||||
|
run_time = 3
|
||||||
|
)
|
||||||
|
|
||||||
|
exp = self.imag_exponent[-1]
|
||||||
|
new_exp = TexMobject("ti")
|
||||||
|
new_exp.highlight(exp.get_color())
|
||||||
|
new_exp.scale_to_fit_height(exp.get_height())
|
||||||
|
new_exp.move_to(exp, LEFT)
|
||||||
|
|
||||||
|
nine = TexMobject("9")
|
||||||
|
nine.highlight(BLUE)
|
||||||
|
denom = self.imag_exponent[0][3]
|
||||||
|
denom.save_state()
|
||||||
|
nine.replace(denom)
|
||||||
|
|
||||||
|
self.play(Transform(exp, new_exp))
|
||||||
|
self.play(input_dot.shift, 2*UP)
|
||||||
|
self.play(input_dot.shift, 2*DOWN)
|
||||||
|
self.dither()
|
||||||
|
self.play(output_dot.restore)
|
||||||
|
self.dither()
|
||||||
|
walk_up_and_down()
|
||||||
|
self.dither()
|
||||||
|
curr_base = 1./9
|
||||||
|
self.play(Transform(denom, nine))
|
||||||
|
walk_up_and_down()
|
||||||
|
self.dither()
|
||||||
|
|
||||||
|
def z_to_point(self, z, is_input = True):
|
||||||
|
if is_input:
|
||||||
|
plane = self.left_plane
|
||||||
|
else:
|
||||||
|
plane = self.right_plane
|
||||||
|
return plane.num_pair_to_point((z.real, z.imag))
|
||||||
|
|
||||||
|
class SeeLinksInDescription(TeacherStudentsScene):
|
||||||
|
def construct(self):
|
||||||
|
self.teacher_says("""
|
||||||
|
See links in the
|
||||||
|
description for more.
|
||||||
|
""")
|
||||||
|
self.play(*it.chain(*[
|
||||||
|
[pi.change_mode, "hooray", pi.look, DOWN]
|
||||||
|
for pi in self.get_students()
|
||||||
|
]))
|
||||||
|
self.random_blink(3)
|
||||||
|
|
||||||
|
class ShowMultiplicationOfRealAndImaginaryExponentialParts(FromRealToComplex):
|
||||||
|
def construct(self):
|
||||||
|
self.break_up_exponent()
|
||||||
|
self.show_multiplication()
|
||||||
|
|
||||||
|
def break_up_exponent(self):
|
||||||
|
original = TexMobject(
|
||||||
|
"\\left(\\frac{1}{2}\\right)", "^{2+i}"
|
||||||
|
)
|
||||||
|
split = TexMobject(
|
||||||
|
"\\left(\\frac{1}{2}\\right)", "^{2}",
|
||||||
|
"\\left(\\frac{1}{2}\\right)", "^{i}",
|
||||||
|
)
|
||||||
|
VGroup(original[-1], split[1], split[3]).highlight(YELLOW)
|
||||||
|
VGroup(original, split).to_corner(UP+LEFT)
|
||||||
|
rect = BackgroundRectangle(split)
|
||||||
|
real_part = VGroup(*split[:2])
|
||||||
|
imag_part = VGroup(*split[2:])
|
||||||
|
|
||||||
|
self.add(rect, original)
|
||||||
|
self.dither()
|
||||||
|
self.play(*[
|
||||||
|
Transform(*pair)
|
||||||
|
for pair in [
|
||||||
|
(original[0], split[0]),
|
||||||
|
(original[1][0], split[1]),
|
||||||
|
(original[0].copy(), split[2]),
|
||||||
|
(VGroup(*original[1][1:]), split[3]),
|
||||||
|
]
|
||||||
|
])
|
||||||
|
self.remove(*self.get_mobjects_from_last_animation())
|
||||||
|
self.add(real_part, imag_part)
|
||||||
|
self.dither()
|
||||||
|
self.real_part = real_part
|
||||||
|
self.imag_part = imag_part
|
||||||
|
|
||||||
|
def show_multiplication(self):
|
||||||
|
real_part = self.real_part.copy()
|
||||||
|
imag_part = self.imag_part.copy()
|
||||||
|
for part in real_part, imag_part:
|
||||||
|
part.add_to_back(BackgroundRectangle(part))
|
||||||
|
|
||||||
|
fourth_point = self.z_to_point(0.25)
|
||||||
|
fourth_line = Line(ORIGIN, fourth_point)
|
||||||
|
brace = Brace(fourth_line, UP, buff = SMALL_BUFF)
|
||||||
|
fourth_dot = Dot(fourth_point)
|
||||||
|
fourth_group = VGroup(fourth_line, brace, fourth_dot)
|
||||||
|
fourth_group.highlight(RED)
|
||||||
|
|
||||||
|
circle = Circle(radius = 2, color = MAROON_B)
|
||||||
|
circle.fade(0.3)
|
||||||
|
imag_power_point = self.z_to_point(0.5**complex(0, 1))
|
||||||
|
imag_power_dot = Dot(imag_power_point)
|
||||||
|
imag_power_line = Line(ORIGIN, imag_power_point)
|
||||||
|
VGroup(imag_power_dot, imag_power_line).highlight(MAROON_B)
|
||||||
|
|
||||||
|
full_power_tex = TexMobject(
|
||||||
|
"\\left(\\frac{1}{2}\\right)", "^{2+i}"
|
||||||
|
)
|
||||||
|
full_power_tex[-1].highlight(YELLOW)
|
||||||
|
full_power_tex.add_background_rectangle()
|
||||||
|
full_power_tex.scale(0.7)
|
||||||
|
full_power_tex.next_to(
|
||||||
|
0.5*self.z_to_point(0.5**complex(2, 1)),
|
||||||
|
UP+RIGHT
|
||||||
|
)
|
||||||
|
|
||||||
|
self.play(
|
||||||
|
real_part.scale, 0.7,
|
||||||
|
real_part.next_to, brace, UP, SMALL_BUFF, LEFT,
|
||||||
|
ShowCreation(fourth_dot)
|
||||||
|
)
|
||||||
|
self.play(
|
||||||
|
GrowFromCenter(brace),
|
||||||
|
ShowCreation(fourth_line),
|
||||||
|
)
|
||||||
|
self.dither()
|
||||||
|
self.play(
|
||||||
|
imag_part.scale, 0.7,
|
||||||
|
imag_part.next_to, imag_power_dot, DOWN+RIGHT, SMALL_BUFF,
|
||||||
|
ShowCreation(imag_power_dot)
|
||||||
|
)
|
||||||
|
self.play(ShowCreation(circle), Animation(imag_power_dot))
|
||||||
|
self.play(ShowCreation(imag_power_line))
|
||||||
|
self.dither(2)
|
||||||
|
self.play(
|
||||||
|
fourth_group.rotate, imag_power_line.get_angle()
|
||||||
|
)
|
||||||
|
real_part.generate_target()
|
||||||
|
imag_part.generate_target()
|
||||||
|
real_part.target.next_to(brace, UP+RIGHT, buff = 0)
|
||||||
|
imag_part.target.next_to(real_part.target, buff = 0)
|
||||||
|
self.play(*map(MoveToTarget, [real_part, imag_part]))
|
||||||
|
self.dither()
|
||||||
|
|
||||||
|
class VisualizingSSquared(ComplexTransformationScene):
|
||||||
|
CONFIG = {
|
||||||
|
"num_anchors_to_add_per_line" : 100,
|
||||||
|
"horiz_end_color" : GOLD,
|
||||||
|
"y_min" : 0,
|
||||||
|
}
|
||||||
|
def construct(self):
|
||||||
|
self.add_title()
|
||||||
|
self.plug_in_specific_values()
|
||||||
|
self.show_transformation()
|
||||||
|
self.comment_on_two_dimensions()
|
||||||
|
|
||||||
|
def add_title(self):
|
||||||
|
title = TexMobject("f(", "s", ") = ", "s", "^2")
|
||||||
|
title.highlight_by_tex("s", YELLOW)
|
||||||
|
title.add_background_rectangle()
|
||||||
|
title.scale(1.5)
|
||||||
|
title.to_corner(UP+LEFT)
|
||||||
|
self.play(Write(title))
|
||||||
|
self.add_foreground_mobject(title)
|
||||||
|
self.dither()
|
||||||
|
self.title = title
|
||||||
|
|
||||||
|
def plug_in_specific_values(self):
|
||||||
|
inputs = map(complex, [2, -1, complex(0, 1)])
|
||||||
|
input_dots = VGroup(*[
|
||||||
|
Dot(self.z_to_point(z), color = YELLOW)
|
||||||
|
for z in inputs
|
||||||
|
])
|
||||||
|
output_dots = VGroup(*[
|
||||||
|
Dot(self.z_to_point(z**2), color = BLUE)
|
||||||
|
for z in inputs
|
||||||
|
])
|
||||||
|
arrows = VGroup()
|
||||||
|
VGroup(*[
|
||||||
|
ParametricFunction(
|
||||||
|
lambda t : self.z_to_point(z**(1.1+0.8*t))
|
||||||
|
)
|
||||||
|
for z in inputs
|
||||||
|
])
|
||||||
|
for z, dot in zip(inputs, input_dots):
|
||||||
|
path = ParametricFunction(
|
||||||
|
lambda t : self.z_to_point(z**(1+t))
|
||||||
|
)
|
||||||
|
dot.path = path
|
||||||
|
arrow = ParametricFunction(
|
||||||
|
lambda t : self.z_to_point(z**(1.1+0.8*t))
|
||||||
|
)
|
||||||
|
stand_in_arrow = Arrow(
|
||||||
|
arrow.points[-2], arrow.points[-1],
|
||||||
|
tip_length = 0.2
|
||||||
|
)
|
||||||
|
arrow.add(stand_in_arrow.tip)
|
||||||
|
arrows.add(arrow)
|
||||||
|
arrows.highlight(WHITE)
|
||||||
|
|
||||||
|
for input_dot, output_dot, arrow in zip(input_dots, output_dots, arrows):
|
||||||
|
input_dot.save_state()
|
||||||
|
input_dot.move_to(self.title[1][1])
|
||||||
|
input_dot.set_fill(opacity = 0)
|
||||||
|
|
||||||
|
self.play(input_dot.restore)
|
||||||
|
self.dither()
|
||||||
|
self.play(ShowCreation(arrow))
|
||||||
|
self.play(ShowCreation(output_dot))
|
||||||
|
self.dither()
|
||||||
|
self.add_foreground_mobjects(arrows, output_dots, input_dots)
|
||||||
|
self.input_dots = input_dots
|
||||||
|
self.output_dots = output_dots
|
||||||
|
|
||||||
|
def show_transformation(self):
|
||||||
|
self.add_transformable_plane(animate = False)
|
||||||
|
self.plane.next_to(ORIGIN, UP, buff = 0.01)
|
||||||
|
self.plane.add(self.plane.copy().rotate(np.pi, RIGHT))
|
||||||
|
self.plane.add(
|
||||||
|
Line(ORIGIN, SPACE_WIDTH*RIGHT, color = self.horiz_end_color),
|
||||||
|
Line(ORIGIN, SPACE_WIDTH*LEFT, color = self.horiz_end_color),
|
||||||
|
)
|
||||||
|
self.play(ShowCreation(self.plane, run_time = 3))
|
||||||
|
|
||||||
|
self.dither()
|
||||||
|
self.apply_complex_homotopy(
|
||||||
|
lambda z, t : z**(1+t),
|
||||||
|
added_anims = [
|
||||||
|
MoveAlongPath(dot, dot.path, run_time = 5)
|
||||||
|
for dot in self.input_dots
|
||||||
|
],
|
||||||
|
run_time = 5
|
||||||
|
)
|
||||||
|
self.dither(2)
|
||||||
|
|
||||||
|
|
||||||
|
def comment_on_two_dimensions(self):
|
||||||
|
morty = Mortimer().flip()
|
||||||
|
morty.scale(0.7)
|
||||||
|
morty.to_corner(DOWN+LEFT)
|
||||||
|
bubble = morty.get_bubble("speech", height = 2, width = 4)
|
||||||
|
bubble.set_fill(BLACK, opacity = 0.9)
|
||||||
|
bubble.write("""
|
||||||
|
It all happens
|
||||||
|
in two dimensions!
|
||||||
|
""")
|
||||||
|
self.foreground_mobjects = []
|
||||||
|
|
||||||
|
self.play(FadeIn(morty))
|
||||||
|
self.play(
|
||||||
|
morty.change_mode, "hooray",
|
||||||
|
ShowCreation(bubble),
|
||||||
|
Write(bubble.content),
|
||||||
|
)
|
||||||
|
self.play(Blink(morty))
|
||||||
|
self.dither(2)
|
||||||
|
|
||||||
|
class ShowZetaOnHalfPlane(ZetaTransformationScene):
|
||||||
|
CONFIG = {
|
||||||
|
"x_min" : 1,
|
||||||
|
"x_max" : int(SPACE_WIDTH+2),
|
||||||
|
"num_anchors_in_extra_lines" : 300,
|
||||||
|
}
|
||||||
|
def construct(self):
|
||||||
|
self.add_title()
|
||||||
|
self.initial_transformation()
|
||||||
|
self.react_to_transformation()
|
||||||
|
self.show_cutoff()
|
||||||
|
self.highlight_i_line()
|
||||||
|
self.show_continuation()
|
||||||
|
self.emphsize_sum_doesnt_make_sense()
|
||||||
|
|
||||||
|
|
||||||
|
def add_title(self):
|
||||||
|
zeta = TexMobject(
|
||||||
|
"\\zeta(", "s", ")=",
|
||||||
|
*[
|
||||||
|
"\\frac{1}{%d^s} + "%d
|
||||||
|
for d in range(1, 5)
|
||||||
|
] + ["\\cdots"]
|
||||||
|
)
|
||||||
|
zeta[1].highlight(YELLOW)
|
||||||
|
for mob in zeta[3:3+4]:
|
||||||
|
mob[-2].highlight(YELLOW)
|
||||||
|
zeta.add_background_rectangle()
|
||||||
|
zeta.scale(0.8)
|
||||||
|
zeta.to_corner(UP+LEFT)
|
||||||
|
self.add_foreground_mobjects(zeta)
|
||||||
|
self.zeta = zeta
|
||||||
|
|
||||||
|
def initial_transformation(self):
|
||||||
|
self.add_transformable_plane()
|
||||||
|
self.dither()
|
||||||
|
self.add_extra_plane_lines_for_zeta(animate = True)
|
||||||
|
self.dither(2)
|
||||||
|
self.plane.save_state()
|
||||||
|
self.apply_zeta_function()
|
||||||
|
self.dither(2)
|
||||||
|
|
||||||
|
def react_to_transformation(self):
|
||||||
|
morty = Mortimer().flip()
|
||||||
|
morty.to_corner(DOWN+LEFT)
|
||||||
|
bubble = morty.get_bubble("speech")
|
||||||
|
bubble.set_fill(BLACK, 0.5)
|
||||||
|
bubble.write("\\emph{Damn}!")
|
||||||
|
bubble.resize_to_content()
|
||||||
|
bubble.pin_to(morty)
|
||||||
|
|
||||||
|
self.play(FadeIn(morty))
|
||||||
|
self.play(
|
||||||
|
morty.change_mode, "surprised",
|
||||||
|
ShowCreation(bubble),
|
||||||
|
Write(bubble.content)
|
||||||
|
)
|
||||||
|
self.play(Blink(morty))
|
||||||
|
self.play(morty.look_at, self.plane.get_top())
|
||||||
|
self.dither()
|
||||||
|
self.play(
|
||||||
|
morty.change_mode, "happy",
|
||||||
|
morty.look_at, self.plane.get_bottom(),
|
||||||
|
*map(FadeOut, [bubble, bubble.content])
|
||||||
|
)
|
||||||
|
self.play(Blink(morty))
|
||||||
|
self.play(FadeOut(morty))
|
||||||
|
|
||||||
|
def show_cutoff(self):
|
||||||
|
words = TextMobject("Such an abrupt stop...")
|
||||||
|
words.add_background_rectangle()
|
||||||
|
words.next_to(ORIGIN, UP+LEFT)
|
||||||
|
words.shift(LEFT+UP)
|
||||||
|
|
||||||
|
line = Line(*map(self.z_to_point, [
|
||||||
|
complex(np.euler_gamma, u*SPACE_HEIGHT)
|
||||||
|
for u in 1, -1
|
||||||
|
]))
|
||||||
|
line.highlight(YELLOW)
|
||||||
|
arrows = [
|
||||||
|
Arrow(words.get_right(), point)
|
||||||
|
for point in line.get_start_and_end()
|
||||||
|
]
|
||||||
|
|
||||||
|
self.play(Write(words, run_time = 2))
|
||||||
|
self.play(ShowCreation(arrows[0]))
|
||||||
|
self.play(
|
||||||
|
Transform(*arrows),
|
||||||
|
ShowCreation(line),
|
||||||
|
run_time = 2
|
||||||
|
)
|
||||||
|
self.play(FadeOut(arrows[0]))
|
||||||
|
self.dither(2)
|
||||||
|
self.play(*map(FadeOut, [words, line]))
|
||||||
|
|
||||||
|
def highlight_i_line(self):
|
||||||
|
right_i_lines, left_i_lines = [
|
||||||
|
VGroup(*[
|
||||||
|
Line(
|
||||||
|
vert_vect+RIGHT,
|
||||||
|
vert_vect+(SPACE_WIDTH+1)*horiz_vect
|
||||||
|
)
|
||||||
|
for vert_vect in UP, DOWN
|
||||||
|
])
|
||||||
|
for horiz_vect in RIGHT, LEFT
|
||||||
|
]
|
||||||
|
right_i_lines.highlight(YELLOW)
|
||||||
|
left_i_lines.highlight(BLUE)
|
||||||
|
for lines in right_i_lines, left_i_lines:
|
||||||
|
for line in lines:
|
||||||
|
line.insert_n_anchor_points(self.num_anchors_to_add_per_line)
|
||||||
|
|
||||||
|
self.restore_mobjects(self.plane)
|
||||||
|
self.plane.add(*right_i_lines)
|
||||||
|
colored_plane = self.plane.copy()
|
||||||
|
right_i_lines.set_stroke(width = 0)
|
||||||
|
self.play(
|
||||||
|
self.plane.set_stroke, GREY, 1,
|
||||||
|
)
|
||||||
|
right_i_lines.set_stroke(YELLOW, width = 3)
|
||||||
|
self.play(ShowCreation(right_i_lines))
|
||||||
|
self.plane.save_state()
|
||||||
|
self.dither(2)
|
||||||
|
self.apply_zeta_function()
|
||||||
|
self.dither(2)
|
||||||
|
|
||||||
|
left_i_lines.save_state()
|
||||||
|
left_i_lines.apply_complex_function(zeta)
|
||||||
|
self.play(ShowCreation(left_i_lines, run_time = 2))
|
||||||
|
self.dither(2)
|
||||||
|
self.restore_mobjects(self.plane, left_i_lines)
|
||||||
|
self.add_transformable_mobjects(left_i_lines)
|
||||||
|
self.play(Transform(self.plane, colored_plane))
|
||||||
|
self.dither()
|
||||||
|
|
||||||
|
def show_continuation(self):
|
||||||
|
reflected_plane = self.get_reflected_plane()
|
||||||
|
self.play(ShowCreation(reflected_plane, run_time = 5))
|
||||||
|
|
||||||
|
self.add_transformable_mobjects(reflected_plane)
|
||||||
|
self.dither()
|
||||||
|
self.apply_zeta_function()
|
||||||
|
self.dither(2)
|
||||||
|
self.play(ShowCreation(
|
||||||
|
reflected_plane,
|
||||||
|
run_time = 6,
|
||||||
|
rate_func = lambda t : 1-there_and_back(t)
|
||||||
|
))
|
||||||
|
self.dither(2)
|
||||||
|
|
||||||
|
def emphsize_sum_doesnt_make_sense(self):
|
||||||
|
brace = Brace(VGroup(*self.zeta[1][3:]))
|
||||||
|
words = brace.get_text("""
|
||||||
|
Still fails to converge
|
||||||
|
when Re$(s) < 1$
|
||||||
|
""", buff = SMALL_BUFF)
|
||||||
|
words.add_background_rectangle()
|
||||||
|
words.scale_in_place(0.8)
|
||||||
|
divergent_sum = TexMobject("1+2+3+4+\\cdots")
|
||||||
|
divergent_sum.next_to(ORIGIN, UP)
|
||||||
|
divergent_sum.to_edge(LEFT)
|
||||||
|
divergent_sum.add_background_rectangle()
|
||||||
|
|
||||||
|
self.play(
|
||||||
|
GrowFromCenter(brace),
|
||||||
|
Write(words)
|
||||||
|
)
|
||||||
|
self.dither(2)
|
||||||
|
self.play(Write(divergent_sum))
|
||||||
|
self.dither(2)
|
||||||
|
|
||||||
|
def restore_mobjects(self, *mobjects):
|
||||||
|
self.play(*it.chain(*[
|
||||||
|
[m.restore, m.make_smooth]
|
||||||
|
for m in mobjects
|
||||||
|
]), run_time = 2)
|
||||||
|
for m in mobjects:
|
||||||
|
self.remove(m)
|
||||||
|
m.restore()
|
||||||
|
self.add(m)
|
||||||
|
|
||||||
|
class ShowConditionalDefinition(Scene):
|
||||||
|
def construct(self):
|
||||||
|
zeta = TexMobject("\\zeta(s)=")
|
||||||
|
zeta[2].highlight(YELLOW)
|
||||||
|
sigma = TexMobject("\\sum_{n=1}^\\infty \\frac{1}{n^s}")
|
||||||
|
sigma[-1].highlight(YELLOW)
|
||||||
|
something_else = TextMobject("Something else...")
|
||||||
|
conditions = VGroup(*[
|
||||||
|
TextMobject("if Re$(s) %s 1$"%s)
|
||||||
|
for s in ">", "\\le"
|
||||||
|
])
|
||||||
|
definitions = VGroup(sigma, something_else)
|
||||||
|
definitions.arrange(DOWN, buff = MED_BUFF)
|
||||||
|
conditions.arrange(DOWN, buff = MED_BUFF)
|
||||||
|
conditions.next_to(definitions, RIGHT, buff = LARGE_BUFF)
|
||||||
|
brace = Brace(definitions, LEFT)
|
||||||
|
zeta.next_to(brace, LEFT)
|
||||||
|
|
||||||
|
sigma.save_state()
|
||||||
|
sigma.next_to(zeta)
|
||||||
|
self.add(zeta, sigma)
|
||||||
|
self.dither()
|
||||||
|
self.play(
|
||||||
|
sigma.restore,
|
||||||
|
GrowFromCenter(brace)
|
||||||
|
)
|
||||||
|
self.play(*map(Write, [conditions, something_else]))
|
||||||
|
self.dither()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue