manim进化论:物种演化与生物多样性的数学建模
引言:当数学动画遇见生命科学
你是否曾想过,如何用精确的数学语言来描述生命的演化过程?如何将达尔文的自然选择理论转化为可视化的数学模型?传统的生物学教学往往依赖于静态的图表和文字描述,难以直观展现动态的演化过程。这正是manim数学动画框架大显身手的领域。
manim(Mathematical Animation)是一个由3Blue1Brown创始人Grant Sanderson开发的Python框架,专门用于创建精确的数学可视化内容。本文将带你探索如何利用manim构建物种演化与生物多样性的数学模型,通过编程的方式让进化过程"活"起来。
环境搭建与基础准备
安装manim社区版
pip install manim
基础场景结构
每个manim动画都基于Scene类构建,以下是一个基础的进化模拟场景框架:
from manim import *
import numpy as np
from scipy.stats import norm
class EvolutionSimulation(Scene):
def construct(self):
# 场景构建代码将在这里实现
pass
种群遗传学的基础数学模型
哈迪-温伯格平衡(Hardy-Weinberg Equilibrium)
哈迪-温伯格定律是种群遗传学的基石,描述了在理想条件下基因频率如何保持稳定:
class HardyWeinbergEquation(Scene):
def construct(self):
# 创建数学公式
equation = MathTex(
r"p^2 + 2pq + q^2 = 1",
font_size=48
)
# 解释各项含义
p_sq = MathTex(r"p^2", r"\text{: 纯合显性基因型频率}")
two_pq = MathTex(r"2pq", r"\text{: 杂合子基因型频率}")
q_sq = MathTex(r"q^2", r"\text{: 纯合隐性基因型频率}")
explanations = VGroup(p_sq, two_pq, q_sq).arrange(DOWN, aligned_edge=LEFT)
self.play(Write(equation))
self.wait(1)
self.play(equation.animate.to_edge(UP))
self.play(Write(explanations))
self.wait(2)
基因频率变化的数学描述
构建进化模拟系统
种群类设计
class Population:
def __init__(self, size=100, initial_freq=0.5):
self.size = size
self.gene_frequency = initial_freq
self.genotypes = self._initialize_genotypes()
self.generation = 0
def _initialize_genotypes(self):
"""初始化种群基因型"""
dominant = np.random.binomial(2, self.gene_frequency, self.size)
return dominant
def calculate_fitness(self):
"""计算适应度"""
# 简化模型:显性纯合子适应度最高
fitness_scores = np.where(
self.genotypes == 2, 1.0, # 纯合显性
np.where(self.genotypes == 1, 0.8, # 杂合子
0.6) # 纯合隐性
)
return fitness_scores
def reproduce(self, mutation_rate=0.01):
"""繁殖下一代"""
fitness = self.calculate_fitness()
parents = np.random.choice(
self.size, size=self.size,
p=fitness/fitness.sum()
)
# 基因重组
new_genotypes = np.zeros(self.size, dtype=int)
for i in range(self.size):
parent_genotype = self.genotypes[parents[i]]
# 模拟减数分裂
gamete = np.random.binomial(1, 0.5) # 随机选择一个等位基因
if np.random.random() < mutation_rate:
gamete = 1 - gamete # 突变
# 从另一个亲本获取配子
other_parent = np.random.choice(self.size)
other_gamete = np.random.binomial(1, 0.5)
if np.random.random() < mutation_rate:
other_gamete = 1 - other_gamete
new_genotypes[i] = gamete + other_gamete
self.genotypes = new_genotypes
self.gene_frequency = np.mean(self.genotypes) / 2
self.generation += 1
可视化进化过程
class EvolutionaryProcess(Scene):
def construct(self):
# 初始化种群
population = Population(size=50, initial_freq=0.3)
# 创建基因频率记录器
frequency_recorder = ValueTracker(population.gene_frequency)
# 创建种群可视化
dots = VGroup(*[
Dot(color=BLUE if g == 2 else (GREEN if g == 1 else RED))
for g in population.genotypes
]).arrange_in_grid(rows=5, cols=10, buff=0.1)
# 基因频率显示
freq_text = always_redraw(lambda:
DecimalNumber(frequency_recorder.get_value()).next_to(dots, UP)
)
self.play(Create(dots), Write(freq_text))
# 模拟多代进化
for generation in range(20):
population.reproduce()
self.play(
frequency_recorder.animate.set_value(population.gene_frequency),
*[dot.animate.set_color(
BLUE if g == 2 else (GREEN if g == 1 else RED)
) for dot, g in zip(dots, population.genotypes)],
run_time=0.5
)
自然选择的数学模型
选择系数的数学表达
class NaturalSelectionModel(Scene):
def construct(self):
# 定义选择系数
selection_coefficient = MathTex(
r"s = 1 - \frac{w_{\text{劣势}}}{w_{\text{优势}}}}",
font_size=36
)
# 基因频率变化方程
delta_p_eq = MathTex(
r"\Delta p = \frac{pq[s_1p - s_2q]}{1 - s_1p^2 - s_2q^2}",
font_size=32
)
equations = VGroup(selection_coefficient, delta_p_eq).arrange(DOWN, buff=0.5)
self.play(Write(equations))
self.wait(2)
# 可视化选择过程
self.show_selection_visualization()
def show_selection_visualization(self):
"""展示选择过程的可视化"""
# 创建适应度景观
x_range = [0, 1, 0.01]
fitness_landscape = FunctionGraph(
lambda x: x**2, # 简单的适应度函数
x_range=x_range,
color=BLUE
)
# 添加标签
axes = Axes(
x_range=[0, 1, 0.2],
y_range=[0, 1, 0.2],
x_length=6,
y_length=4
)
labels = axes.get_axis_labels(
MathTex(r"p \text{ (基因频率)}"),
MathTex(r"w \text{ (适应度)}")
)
self.play(Create(axes), Write(labels))
self.play(Create(fitness_landscape))
生物多样性模拟
物种形成模型
class SpeciationProcess(Scene):
def construct(self):
# 创建地理隔离示意图
mainland = Ellipse(width=3, height=2, color=GREEN, fill_opacity=0.3)
island = Circle(radius=0.8, color=BLUE, fill_opacity=0.3).shift(RIGHT*4 + UP*2)
# 种群迁移箭头
migration_arrow = Arrow(
mainland.get_right(), island.get_left(),
color=YELLOW, buff=0.1
)
self.play(Create(mainland), Create(island))
self.play(Create(migration_arrow))
# 显示基因分化
self.show_genetic_divergence()
def show_genetic_divergence(self):
"""展示基因分化过程"""
# 初始种群基因频率
initial_freq = 0.5
mainland_freq = ValueTracker(initial_freq)
island_freq = ValueTracker(initial_freq)
# 创建频率显示
mainland_text = always_redraw(lambda:
MathTex(f"p_{{main}} = {mainland_freq.get_value():.3f}")
)
island_text = always_redraw(lambda:
MathTex(f"p_{{island}} = {island_freq.get_value():.3f}")
)
texts = VGroup(mainland_text, island_text).arrange(DOWN, buff=0.5)
self.play(Write(texts))
# 模拟分化过程
for generation in range(15):
# 模拟遗传漂变
mainland_drift = np.random.normal(0, 0.02)
island_drift = np.random.normal(0, 0.03)
new_mainland = np.clip(mainland_freq.get_value() + mainland_drift, 0, 1)
new_island = np.clip(island_freq.get_value() + island_drift, 0, 1)
self.play(
mainland_freq.animate.set_value(new_mainland),
island_freq.animate.set_value(new_island),
run_time=0.3
)
高级主题:协同进化与生态系统建模
捕食者-猎物模型(Lotka-Volterra方程)
class PredatorPreyModel(Scene):
def construct(self):
# Lotka-Volterra方程
equations = MathTex(
r"\frac{dx}{dt} = \alpha x - \beta xy",
r"\frac{dy}{dt} = \delta xy - \gamma y",
font_size=32
).arrange(DOWN, aligned_edge=LEFT)
# 参数解释
parameters = VGroup(
MathTex(r"\alpha: \text{猎物增长率}"),
MathTex(r"\beta: \text{捕食率}"),
MathTex(r"\delta: \text{捕食者增长率}"),
MathTex(r"\gamma: \text{捕食者死亡率}")
).arrange(DOWN, aligned_edge=LEFT).scale(0.8)
group = VGroup(equations, parameters).arrange(RIGHT, buff=1)
self.play(Write(group))
self.wait(2)
# 展示相位图
self.show_phase_portrait()
def show_phase_portrait(self):
"""展示Lotka-Volterra相位图"""
# 简化版的相位图可视化
t_values = np.linspace(0, 20, 1000)
alpha, beta, delta, gamma = 0.1, 0.02, 0.01, 0.1
# 数值解
def lotka_volterra(t, z):
x, y = z
return [alpha*x - beta*x*y, delta*x*y - gamma*y]
# 创建轨迹
trajectories = VGroup()
for x0 in [10, 20, 30]:
for y0 in [5, 10, 15]:
solution = solve_ivp(lotka_volterra, [0, 20], [x0, y0], t_eval=t_values)
points = [np.array([x, y, 0]) for x, y in zip(solution.y[0], solution.y[1])]
trajectory = VMobject().set_points_smoothly(points)
trajectories.add(trajectory)
trajectories.set_color_by_gradient(BLUE, GREEN, RED)
self.play(Create(trajectories))
实际应用案例
抗生素耐药性演化模拟
class AntibioticResistance(Scene):
def construct(self):
# 创建细菌种群
bacteria = VGroup(*[
Circle(radius=0.1, color=GREEN, fill_opacity=0.7)
for _ in range(50)
]).arrange_in_grid(rows=5, cols=10, buff=0.05)
# 引入抗生素
antibiotic = Text("抗生素引入", font_size=24).to_edge(UP)
self.play(Write(antibiotic))
# 模拟选择过程
resistant_indices = np.random.choice(50, size=5, replace=False) # 5%具有耐药性
for i in range(50):
if i in resistant_indices:
bacteria[i].set_color(RED) # 耐药菌株
else:
bacteria[i].set_fill(opacity=0.2) # 敏感菌株变淡
self.play(*[bacteria[i].animate.set_color(RED) for i in resistant_indices],
*[bacteria[i].animate.set_fill(opacity=0.2) for i in range(50) if i not in resistant_indices])
# 显示种群恢复
recovery_text = Text("耐药种群扩张", font_size=24).to_edge(UP)
self.play(Transform(antibiotic, recovery_text))
# 模拟耐药种群增长
for generation in range(3):
new_resistant = []
for i in resistant_indices:
if np.random.random() < 0.8: # 高繁殖率
neighbor = (i + np.random.choice([-1, 1, -10, 10])) % 50
if neighbor not in resistant_indices:
new_resistant.append(neighbor)
self.play(bacteria[neighbor].animate.set_color(RED), run_time=0.1)
resistant_indices = np.concatenate([resistant_indices, new_resistant])
教学应用与扩展
创建交互式进化模拟
class InteractiveEvolution(Scene):
def construct(self):
# 参数控制面板(概念性)
parameters = VGroup(
Text("突变率: 0.01"),
Text("选择强度: 中等"),
Text("种群大小: 100")
).arrange(DOWN, aligned_edge=LEFT)
# 模拟控制按钮
controls = VGroup(
Text("开始模拟"),
Text("暂停"),
Text("重置")
).arrange(RIGHT, buff=0.5)
panel = VGroup(parameters, controls).arrange(DOWN, buff=1)
self.play(Write(panel))
self.wait()
# 展示如何将这些概念扩展到实际交互应用
self.show_educational_applications()
def show_educational_applications(self):
"""展示教育应用场景"""
applications = VGroup(
Text("• 高中生物学教学"),
Text("• 大学进化生物学课程"),
Text("• 科研可视化"),
Text("• 公众科学教育")
).arrange(DOWN, aligned_edge=LEFT)
self.play(Write(applications))
结论与展望
manim框架为进化生物学和生态学的数学建模提供了强大的可视化工具。通过编程方式构建进化模型,我们能够:
- 直观理解复杂的进化过程
- 验证理论模型的预测结果
- 探索参数变化对系统行为的影响
- 创建交互式的教学材料
未来发展方向
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考



