binary_extremum_manim.py
1from manim import *2import numpy as np3 4class BinaryExtremumDemo(ThreeDScene):5 def construct(self):6 # 第一部分:Hessian矩阵的构造7 # 创建标题8 title1 = Text("Hessian矩阵的构造", font="PingFang SC", font_size=36)9 title1.to_edge(UP, buff=0.5)10 self.add_fixed_in_frame_mobjects(title1)11 self.play(Write(title1))12 self.wait()13 14 # 显示一般形式的二元函数15 func = MathTex(16 "z = f(x,y)",17 color=BLUE,18 font_size=3219 )20 func.to_edge(LEFT, buff=1)21 func.shift(UP * 1)22 self.add_fixed_in_frame_mobjects(func)23 self.play(Write(func))24 self.wait()25 26 # 显示Hessian矩阵27 hessian = MathTex(28 "H = \\begin{bmatrix} f_{xx} & f_{xy} \\\\ f_{yx} & f_{yy} \\end{bmatrix}",29 color=YELLOW,30 font_size=3231 )32 hessian.next_to(func, DOWN, buff=1)33 self.add_fixed_in_frame_mobjects(hessian)34 self.play(Write(hessian))35 self.wait()36 37 # 显示判断方法(右侧)38 right_group = VGroup(39 Text("Hessian矩阵的正定性判断:", font="PingFang SC", font_size=28, color=WHITE),40 Text("• 正定矩阵 → 极小值", font="PingFang SC", font_size=28, color=GREEN),41 Text("• 负定矩阵 → 极大值", font="PingFang SC", font_size=28, color=RED),42 Text("• 不定矩阵 → 鞍点", font="PingFang SC", font_size=28, color=YELLOW)43 )44 right_group.arrange(DOWN, aligned_edge=LEFT, buff=0.3)45 right_group.to_edge(RIGHT, buff=1)46 right_group.shift(UP * 1)47 self.add_fixed_in_frame_mobjects(right_group)48 self.play(Write(right_group))49 self.wait(2)50 51 # 淡出第一部分52 self.play(53 *[FadeOut(mob) for mob in self.mobjects],54 run_time=255 )56 57 # 第二部分:3D曲面演示58 # 设置3D场景59 self.set_camera_orientation(phi=75 * DEGREES, theta=30 * DEGREES)60 61 # 创建标题62 title2 = Text("Hessian矩阵判断极值", font="PingFang SC", font_size=36)63 title2.to_corner(UL, buff=0.5)64 self.add_fixed_in_frame_mobjects(title2)65 self.play(Write(title2))66 self.wait()67 68 # 创建3D坐标系69 axes = ThreeDAxes(70 x_range=[-3, 3, 1],71 y_range=[-3, 3, 1],72 z_range=[-2, 10, 2],73 axis_config={"color": GRAY}74 )75 self.add(axes)76 self.wait()77 78 # 创建函数表达式和Hessian矩阵显示79 func = MathTex(80 "f(x,y) = x^2 + 2y^2",81 color=BLUE,82 font_size=3283 )84 func.to_corner(UR, buff=0.5)85 self.add_fixed_in_frame_mobjects(func)86 self.play(Write(func))87 88 hessian = MathTex(89 "H = \\begin{bmatrix} 2 & 0 \\\\ 0 & 4 \\end{bmatrix}",90 color=YELLOW,91 font_size=2892 )93 hessian.next_to(func, DOWN, buff=0.5)94 self.add_fixed_in_frame_mobjects(hessian)95 self.play(Write(hessian))96 97 # 添加判断结果和说明98 judgment_group = VGroup(99 Text("正定矩阵 → 极小值", font="PingFang SC", font_size=28, color=GREEN),100 Text("在点(0,0)处取得极小值", font="PingFang SC", font_size=24, color=WHITE)101 )102 judgment_group.arrange(DOWN, aligned_edge=LEFT, buff=0.3)103 judgment_group.next_to(hessian, DOWN, buff=0.5)104 self.add_fixed_in_frame_mobjects(judgment_group)105 self.play(Write(judgment_group))106 self.wait()107 108 # 创建曲面109 def create_surface(a, c):110 return Surface(111 lambda u, v: np.array([112 u, v, a*u**2 + c*v**2113 ]),114 u_range=[-3, 3],115 v_range=[-3, 3],116 resolution=(40, 40),117 should_make_jagged=False118 )119 120 # 创建初始曲面 (a=1, c=2, 极小值)121 surface = create_surface(1, 2)122 surface.set_style(fill_opacity=0.8, stroke_width=0.5)123 surface.set_fill_by_checkerboard(ORANGE, BLUE, opacity=0.5)124 self.add(surface)125 self.wait()126 127 # 从极小值(a=1, c=2)到鞍点(a=1, c=-2)128 def update_surface1(surface, alpha):129 c = 2 - 4*alpha130 surface.become(create_surface(1, c))131 surface.set_style(fill_opacity=0.8, stroke_width=0.5)132 surface.set_fill_by_checkerboard(ORANGE, BLUE, opacity=0.5)133 134 def update_hessian1(hessian, alpha):135 c = 2 - 4*alpha136 hessian.become(MathTex(137 f"H = \\begin{{bmatrix}} 2 & 0 \\\\ 0 & {2*c:.1f} \\end{{bmatrix}}",138 color=YELLOW,139 font_size=28140 ))141 hessian.next_to(func, DOWN, buff=0.5)142 self.add_fixed_in_frame_mobjects(hessian)143 144 def update_func1(func, alpha):145 c = 2 - 4*alpha146 func.become(MathTex(147 f"f(x,y) = x^2 + {c:.1f}y^2",148 color=BLUE,149 font_size=32150 ))151 func.to_corner(UR, buff=0.5)152 self.add_fixed_in_frame_mobjects(func)153 154 def update_judgment1(group, alpha):155 if alpha < 0.5:156 group.become(VGroup(157 Text("正定矩阵 → 极小值", font="PingFang SC", font_size=28, color=GREEN),158 Text("在点(0,0)处取得极小值", font="PingFang SC", font_size=24, color=WHITE)159 ))160 else:161 group.become(VGroup(162 Text("不定矩阵 → 鞍点", font="PingFang SC", font_size=28, color=YELLOW),163 Text("点(0,0)是鞍点", font="PingFang SC", font_size=24, color=WHITE)164 ))165 group.arrange(DOWN, aligned_edge=LEFT, buff=0.3)166 group.next_to(hessian, DOWN, buff=0.5)167 self.add_fixed_in_frame_mobjects(group)168 169 self.play(170 UpdateFromAlphaFunc(surface, update_surface1),171 UpdateFromAlphaFunc(hessian, update_hessian1),172 UpdateFromAlphaFunc(func, update_func1),173 UpdateFromAlphaFunc(judgment_group, update_judgment1),174 run_time=3175 )176 self.wait()177 178 # 从鞍点(a=1, c=-2)到极大值(a=-1, c=-2)179 def update_surface2(surface, alpha):180 a = 1 - 2*alpha181 surface.become(create_surface(a, -2))182 surface.set_style(fill_opacity=0.8, stroke_width=0.5)183 surface.set_fill_by_checkerboard(ORANGE, BLUE, opacity=0.5)184 185 def update_hessian2(hessian, alpha):186 a = 1 - 2*alpha187 hessian.become(MathTex(188 f"H = \\begin{{bmatrix}} {2*a:.1f} & 0 \\\\ 0 & -4 \\end{{bmatrix}}",189 color=YELLOW,190 font_size=28191 ))192 hessian.next_to(func, DOWN, buff=0.5)193 self.add_fixed_in_frame_mobjects(hessian)194 195 def update_func2(func, alpha):196 a = 1 - 2*alpha197 func.become(MathTex(198 f"f(x,y) = {a:.1f}x^2 - 2y^2",199 color=BLUE,200 font_size=32201 ))202 func.to_corner(UR, buff=0.5)203 self.add_fixed_in_frame_mobjects(func)204 205 def update_judgment2(group, alpha):206 if alpha < 0.5:207 group.become(VGroup(208 Text("不定矩阵 → 鞍点", font="PingFang SC", font_size=28, color=YELLOW),209 Text("点(0,0)是鞍点", font="PingFang SC", font_size=24, color=WHITE)210 ))211 else:212 group.become(VGroup(213 Text("负定矩阵 → 极大值", font="PingFang SC", font_size=28, color=RED),214 Text("在点(0,0)处取得极大值", font="PingFang SC", font_size=24, color=WHITE)215 ))216 group.arrange(DOWN, aligned_edge=LEFT, buff=0.3)217 group.next_to(hessian, DOWN, buff=0.5)218 self.add_fixed_in_frame_mobjects(group)219 220 self.play(221 UpdateFromAlphaFunc(surface, update_surface2),222 UpdateFromAlphaFunc(hessian, update_hessian2),223 UpdateFromAlphaFunc(func, update_func2),224 UpdateFromAlphaFunc(judgment_group, update_judgment2),225 run_time=3226 )227 self.wait()228 229 # 从极大值(a=-1, c=-2)回到极小值(a=1, c=2)230 def update_surface3(surface, alpha):231 a = -1 + 2*alpha232 c = -2 + 4*alpha233 surface.become(create_surface(a, c))234 surface.set_style(fill_opacity=0.8, stroke_width=0.5)235 surface.set_fill_by_checkerboard(ORANGE, BLUE, opacity=0.5)236 237 def update_hessian3(hessian, alpha):238 a = -1 + 2*alpha239 c = -2 + 4*alpha240 hessian.become(MathTex(241 f"H = \\begin{{bmatrix}} {2*a:.1f} & 0 \\\\ 0 & {2*c:.1f} \\end{{bmatrix}}",242 color=YELLOW,243 font_size=28244 ))245 hessian.next_to(func, DOWN, buff=0.5)246 self.add_fixed_in_frame_mobjects(hessian)247 248 def update_func3(func, alpha):249 a = -1 + 2*alpha250 c = -2 + 4*alpha251 func.become(MathTex(252 f"f(x,y) = {a:.1f}x^2 + {c:.1f}y^2",253 color=BLUE,254 font_size=32255 ))256 func.to_corner(UR, buff=0.5)257 self.add_fixed_in_frame_mobjects(func)258 259 def update_judgment3(group, alpha):260 if alpha < 0.4:261 group.become(VGroup(262 Text("负定矩阵 → 极大值", font="PingFang SC", font_size=28, color=RED),263 Text("在点(0,0)处取得极大值", font="PingFang SC", font_size=24, color=WHITE)264 ))265 elif alpha < 0.8:266 group.become(VGroup(267 Text("不定矩阵 → 鞍点", font="PingFang SC", font_size=28, color=YELLOW),268 Text("点(0,0)是鞍点", font="PingFang SC", font_size=24, color=WHITE)269 ))270 else:271 group.become(VGroup(272 Text("正定矩阵 → 极小值", font="PingFang SC", font_size=28, color=GREEN),273 Text("在点(0,0)处取得极小值", font="PingFang SC", font_size=24, color=WHITE)274 ))275 group.arrange(DOWN, aligned_edge=LEFT, buff=0.3)276 group.next_to(hessian, DOWN, buff=0.5)277 self.add_fixed_in_frame_mobjects(group)278 279 self.play(280 UpdateFromAlphaFunc(surface, update_surface3),281 UpdateFromAlphaFunc(hessian, update_hessian3),282 UpdateFromAlphaFunc(func, update_func3),283 UpdateFromAlphaFunc(judgment_group, update_judgment3),284 run_time=3285 )286 self.wait()287 288 # 改变视角以更好地观察289 self.move_camera(phi=60 * DEGREES, theta=60 * DEGREES, run_time=2)290 self.wait()291 292 # 旋转3D视图293 self.begin_ambient_camera_rotation(rate=0.2)294 self.wait(4)295 self.stop_ambient_camera_rotation()296 self.wait()297 298 # 总结299 summary = Text(300 "通过Hessian矩阵的正定性判断极值类型",301 font="PingFang SC",302 color=WHITE,303 font_size=32304 )305 summary.to_edge(DOWN, buff=0.5)306 self.add_fixed_in_frame_mobjects(summary)307 self.play(Write(summary))308 self.wait(2)309 310 # 淡出所有元素311 self.play(312 *[FadeOut(mob) for mob in self.mobjects],313 run_time=2314 ) 讲解
这个视频围绕「Hessian矩阵的构造」展开。画面把问题、图像和公式放在同一条理解路径中,让抽象关系先被看见。
开头先建立问题背景和主要对象,让观察从标题、坐标或第一组关系进入。
画面中出现的文字「Hessian矩阵的构造」给出视觉入口。随后画面通过对象创建、移动、淡入淡出和高亮,把抽象命题拆成可以跟随的步骤。
随后出现更具体的图像或公式提示,动画会把局部对象和整体结论联系起来。这里可以重点观察变量、曲线、区域或向量如何随镜头推进而变化。
观察路径
观察路径可以分三步:先锁定「Hessian矩阵的构造」中的核心对象,尤其留意Hessian 矩阵、二阶判别法、多元函数极值之间的联系;再跟随画面中变量、图像或向量的变化;最后回到公式或结论,判断局部变化如何支撑整体关系。
本页可以从Hessian 矩阵、二阶判别法、多元函数极值这些概念进入,继续沿相邻问题观察同一类数学结构。