cauchy_limit_does_not_exist.py
1from manim import *2import numpy as np3 4# 中文 LaTeX 模板与中文主字体5config.tex_template = TexTemplateLibrary.ctex6config.tex_template.add_to_preamble(r"\setCJKmainfont{STSong}")7 8class CauchyLimitDoesNotExist(Scene):9 def construct(self):10 # 统一字体大小11 Text.set_default(font="STSong", font_size=36)12 MathTex.set_default(font_size=34)13 14 # 标题15 title = Text("用柯西收敛原理的反命题证明极限不存在", color=YELLOW).to_edge(UP)16 self.play(FadeIn(title, shift=DOWN), run_time=1.8)17 self.wait(1.2)18 19 # 数列与反命题:放在标题正下,反命题在数列右侧;数学符号使用 MathTex20 seq_def = VGroup(21 Text("数列:", font_size=30),22 MathTex(r"a_n = (-1)^n", font_size=34)23 ).arrange(RIGHT, buff=0.2)24 25 prop_label = Text("柯西收敛原理反命题:", font_size=30, color=GREEN)26 prop_math = MathTex(r"\exists\,\varepsilon>0,\ \forall\,N,\ \exists\,m,n>N:\ |a_n-a_m|\ge \varepsilon", font_size=30)27 prop = VGroup(prop_label, prop_math).arrange(DOWN, aligned_edge=LEFT, buff=0.15)28 29 header_row = VGroup(seq_def, prop).arrange(RIGHT, buff=0.8)30 header_row.next_to(title, DOWN, buff=0.45).to_edge(LEFT, buff=0.7)31 self.play(Write(seq_def), run_time=1.4)32 self.play(Write(prop_label), run_time=1.4)33 self.play(Write(prop_math), run_time=1.4)34 self.wait(1.0)35 36 # 坐标系与点列(整体上移)37 axes = Axes(38 x_range=[1, 20, 1], y_range=[-2, 2, 1],39 x_length=10, y_length=4,40 axis_config={"include_tip": True}41 )42 x_label = axes.get_x_axis_label(MathTex("n", font_size=28))43 y_label = axes.get_y_axis_label(MathTex("a_n", font_size=28))44 axes_group = VGroup(axes, x_label, y_label)45 axes_group.to_edge(DOWN).shift(UP*0.8)46 self.play(Create(axes), FadeIn(x_label, shift=DOWN), FadeIn(y_label, shift=LEFT), run_time=2.0)47 48 dots = VGroup()49 for n in range(1, 21):50 y = (-1)**n51 d = Dot(axes.c2p(n, y), radius=0.06, color=BLUE)52 dots.add(d)53 self.play(LaggedStartMap(FadeIn, dots, lag_ratio=0.07, run_time=3.0))54 self.wait(1.2)55 56 # 取 ε=1 放在图下方(数学符号 MathTex)57 eps_grp = VGroup(58 Text("取:", font_size=30), MathTex(r"\varepsilon = 1", font_size=32, color=ORANGE)59 ).arrange(RIGHT, buff=0.2)60 eps_grp.next_to(axes, DOWN, buff=0.45).to_edge(LEFT, buff=0.7)61 self.play(Write(eps_grp), run_time=1.2)62 self.wait(0.9)63 64 # 演示给定 N,明确说明“对该 N 可取 m=N+1,n=N+2”,所有含符号处使用 MathTex65 def show_case(N: int):66 m, n = N+1, N+267 y_m = (-1)**m68 y_n = (-1)**n69 70 # 在图中明确演示 N71 vline_N = DashedLine(axes.c2p(N, 1.4), axes.c2p(N, -1.4), color=WHITE, stroke_width=2, dashed_ratio=0.55)72 markN = MathTex(fr"N={N}", font_size=26, color=WHITE).next_to(axes.c2p(N, 0), DOWN, buff=0.2)73 Nline = Arrow(axes.c2p(N, -0.15), axes.c2p(N, 0.0), buff=0, color=WHITE, max_tip_length_to_length_ratio=0.18, stroke_width=2)74 75 # 高亮两点与标签76 dm = Dot(axes.c2p(m, y_m), color=RED, radius=0.09)77 dn = Dot(axes.c2p(n, y_n), color=RED, radius=0.09)78 lab_m = MathTex(fr"a_{{{m}}}", font_size=26, color=RED).next_to(dm, UP if y_m>0 else DOWN, buff=0.1)79 lab_n = MathTex(fr"a_{{{n}}}", font_size=26, color=RED).next_to(dn, UP if y_n>0 else DOWN, buff=0.1)80 81 # 辅助竖线、距离与说明82 vline_m = DashedLine(axes.c2p(m, 1.2), axes.c2p(m, -1.2), color=GREY_B, stroke_width=2)83 vline_n = DashedLine(axes.c2p(n, 1.2), axes.c2p(n, -1.2), color=GREY_B, stroke_width=2)84 seg = Line(axes.c2p(m, y_m), axes.c2p(n, y_n), color=YELLOW, stroke_width=4)85 dist_brace = BraceBetweenPoints(axes.c2p(m, y_m), axes.c2p(n, y_n), direction=RIGHT if m<n else LEFT)86 dist_label = MathTex(r"|a_n-a_m| = 2 > 1 = \varepsilon", font_size=28, color=YELLOW).next_to(dist_brace, RIGHT, buff=0.15).shift(UP*0.2)87 88 # 图下说明(使用 MathTex 拼接,确保符号为数学格式,放在epsilon=1右侧)89 expl = VGroup(90 Text("当 ", font_size=28, color=GREEN),91 MathTex(fr"N={N}", font_size=28, color=GREEN),92 Text(" 时:取 ", font_size=28, color=GREEN),93 MathTex(fr"m={m},\ n={n}", font_size=28, color=GREEN),94 Text(",有 ", font_size=28, color=GREEN),95 MathTex(r"|a_n-a_m|=2\ge 1", font_size=28, color=GREEN)96 ).arrange(RIGHT, buff=0.15)97 expl.next_to(eps_grp, RIGHT, buff=0.4)98 99 self.play(Create(vline_N), FadeIn(markN), Create(Nline), run_time=1.2)100 self.play(Create(vline_m), Create(vline_n), FadeIn(dm), FadeIn(dn), Write(lab_m), Write(lab_n), run_time=1.8)101 self.play(Create(seg), run_time=1.2)102 self.play(GrowFromCenter(dist_brace), FadeIn(dist_label), run_time=1.2)103 self.play(FadeIn(expl), run_time=1.1)104 self.wait(1.2)105 106 # 清理为下一轮(保留坐标轴与蓝点、上方文字)107 self.play(108 FadeOut(expl), FadeOut(vline_m), FadeOut(vline_n), FadeOut(seg),109 FadeOut(dist_brace), FadeOut(dist_label),110 FadeOut(dm), FadeOut(dn), FadeOut(lab_m), FadeOut(lab_n),111 FadeOut(markN), FadeOut(Nline), FadeOut(vline_N),112 run_time=1.2113 )114 115 for N in [3, 6, 11, 15]:116 show_case(N)117 118 # 在N=15演示完后,说明对于任意N的通用情况119 general_explanation = VGroup(120 Text("对于任意 ", font_size=28, color=BLUE),121 MathTex("N", font_size=28, color=BLUE),122 Text(",取 ", font_size=28, color=BLUE),123 MathTex("m=N+1", font_size=28, color=BLUE),124 Text(",", font_size=28, color=BLUE),125 MathTex("n=N+2", font_size=28, color=BLUE),126 Text(",有 ", font_size=28, color=BLUE),127 MathTex(r"|a_n-a_m| = 2 \ge 1 = \varepsilon", font_size=24, color=BLUE)128 ).arrange(RIGHT, buff=0.1)129 general_explanation.next_to(eps_grp, RIGHT, buff=0.4)130 131 self.play(Write(general_explanation), run_time=2.0)132 self.wait(1.5)133 134 # 总解释:不同 N 都能找到这样的 m,n(图下;数学符号 MathTex)135 general_note = VGroup(136 Text("因此对任意 ", font_size=28, color=ORANGE),137 MathTex("N", font_size=28, color=ORANGE),138 Text(",总能找到 ", font_size=28, color=ORANGE),139 MathTex(r"m=N+1,\ n=N+2", font_size=28, color=ORANGE),140 Text(" 使 ", font_size=28, color=ORANGE),141 MathTex(r"|a_n-a_m|\ge 1", font_size=28, color=ORANGE),142 Text("。", font_size=28, color=ORANGE)143 ).arrange(RIGHT, buff=0.12).next_to(eps_grp, DOWN, buff=0.6).to_edge(LEFT, buff=0.7)144 self.play(Write(general_note), run_time=1.4)145 self.wait(1.0)146 147 # 总结(放在"对于任意N"上面,一行显示,左右居中)148 summary = VGroup(149 Text("结论:", font_size=30, color=YELLOW),150 MathTex(r"(a_n) \text{ 不是柯西列 } \Rightarrow \text{ 极限不存在}", font_size=32, color=YELLOW)151 ).arrange(RIGHT, buff=0.3).next_to(general_explanation, UP, buff=0.4).move_to(ORIGIN + UP * (general_explanation.get_center()[1] + 0.4))152 box = SurroundingRectangle(summary, color=YELLOW, buff=0.28)153 self.play(Write(summary), run_time=1.5)154 self.play(Create(box), run_time=1.2)155 self.wait(2.0) 讲解
这个视频围绕「用柯西收敛原理的反命题证明极限不存在」展开。画面把问题、图像和公式放在同一条理解路径中,让抽象关系先被看见。
开头先建立问题背景和主要对象,让观察从标题、坐标或第一组关系进入。
画面中出现的文字「用柯西收敛原理的反命题证明极限不存在」给出视觉入口。随后画面通过对象创建、移动、淡入淡出和高亮,把抽象命题拆成可以跟随的步骤。
随后出现更具体的图像或公式提示,动画会把局部对象和整体结论联系起来。这里可以重点观察变量、曲线、区域或向量如何随镜头推进而变化。
核心公式可以写成:
这类公式可以和画面中的符号一一对应。
观察路径
观察路径可以分三步:先锁定「用柯西收敛原理的反命题证明极限不存在」中的核心对象,尤其留意柯西收敛原理、极限不存在、数列极限之间的联系;再跟随画面中变量、图像或向量的变化;最后回到公式或结论,判断局部变化如何支撑整体关系。
本页可以从柯西收敛原理、极限不存在、数列极限这些概念进入,继续沿相邻问题观察同一类数学结构。