Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Ok-landscape
GitHub Repository: Ok-landscape/computational-pipeline
Path: blob/main/latex-templates/templates/biology/evolutionary_dynamics.tex
51 views
unlisted
1
% Evolutionary Dynamics Template
2
% Topics: Fitness landscapes, natural selection, genetic drift, mutation-selection balance
3
% Style: Textbook chapter with theoretical foundations
4
5
\documentclass[a4paper, 11pt]{article}
6
\usepackage[utf8]{inputenc}
7
\usepackage[T1]{fontenc}
8
\usepackage{amsmath, amssymb}
9
\usepackage{graphicx}
10
\usepackage{siunitx}
11
\usepackage{booktabs}
12
\usepackage{subcaption}
13
\usepackage[makestderr]{pythontex}
14
15
% Theorem environments
16
\newtheorem{definition}{Definition}[section]
17
\newtheorem{theorem}{Theorem}[section]
18
\newtheorem{example}{Example}[section]
19
\newtheorem{remark}{Remark}[section]
20
21
\title{Evolutionary Dynamics: Selection, Drift, and Fitness Landscapes}
22
\author{Theoretical Population Genetics}
23
\date{\today}
24
25
\begin{document}
26
\maketitle
27
28
\begin{abstract}
29
This chapter explores the fundamental forces driving evolutionary change in populations.
30
We analyze natural selection under various fitness schemes, examine the stochastic effects
31
of genetic drift in finite populations, and investigate the interplay between mutation
32
and selection. Computational simulations illustrate fitness landscapes, fixation
33
probabilities, and the dynamics of allele frequency change under different evolutionary
34
scenarios.
35
\end{abstract}
36
37
\section{Introduction}
38
39
Evolution operates through the interplay of deterministic forces (selection, mutation) and
40
stochastic processes (genetic drift). Understanding these dynamics requires both analytical
41
theory and computational simulation.
42
43
\begin{definition}[Fitness]
44
The fitness $w$ of a genotype is its relative reproductive success. For a diploid organism
45
with alleles $A$ and $a$, genotype fitnesses are denoted $w_{AA}$, $w_{Aa}$, and $w_{aa}$.
46
\end{definition}
47
48
\section{Theoretical Framework}
49
50
\subsection{Natural Selection}
51
52
\begin{theorem}[Change in Allele Frequency Under Selection]
53
For a population with allele frequency $p$ (for allele $A$) and genotype fitnesses
54
$w_{AA}$, $w_{Aa}$, $w_{aa}$, the change in one generation is:
55
\begin{equation}
56
\Delta p = \frac{p q [p(w_{AA} - w_{Aa}) + q(w_{Aa} - w_{aa})]}{\bar{w}}
57
\end{equation}
58
where $q = 1 - p$ and $\bar{w} = p^2 w_{AA} + 2pq w_{Aa} + q^2 w_{aa}$ is the mean fitness.
59
\end{theorem}
60
61
\subsection{Selection Schemes}
62
63
\begin{definition}[Types of Selection]
64
Different selection regimes produce distinct dynamics:
65
\begin{itemize}
66
\item \textbf{Directional}: One homozygote has highest fitness; allele goes to fixation
67
\item \textbf{Overdominance}: Heterozygote advantage; stable polymorphism
68
\item \textbf{Underdominance}: Heterozygote disadvantage; unstable equilibrium
69
\item \textbf{Frequency-dependent}: Fitness depends on allele frequency
70
\end{itemize}
71
\end{definition}
72
73
\subsection{Genetic Drift}
74
75
\begin{theorem}[Wright-Fisher Model]
76
In a finite population of size $N$, allele frequencies change stochastically. The
77
variance in allele frequency change per generation is:
78
\begin{equation}
79
\text{Var}(\Delta p) = \frac{p(1-p)}{2N}
80
\end{equation}
81
The probability of eventual fixation for a neutral allele at initial frequency $p_0$ is $p_0$.
82
\end{theorem}
83
84
\begin{remark}[Effective Population Size]
85
Real populations often have $N_e < N$ due to variance in reproductive success, unequal
86
sex ratios, and population fluctuations.
87
\end{remark}
88
89
\subsection{Mutation-Selection Balance}
90
91
\begin{theorem}[Equilibrium Frequency]
92
For a deleterious recessive allele with mutation rate $\mu$ and selection coefficient $s$:
93
\begin{equation}
94
\hat{q} \approx \sqrt{\frac{\mu}{s}}
95
\end{equation}
96
For a deleterious dominant allele: $\hat{q} \approx \mu/s$.
97
\end{theorem}
98
99
\section{Computational Analysis}
100
101
\begin{pycode}
102
import numpy as np
103
import matplotlib.pyplot as plt
104
from scipy.integrate import odeint
105
106
np.random.seed(42)
107
108
def selection_dynamics(p, t, w_AA, w_Aa, w_aa):
109
"""Continuous-time selection dynamics."""
110
if p <= 0 or p >= 1:
111
return 0
112
q = 1 - p
113
w_bar = p**2 * w_AA + 2*p*q * w_Aa + q**2 * w_aa
114
dp = p * q * (p*(w_AA - w_Aa) + q*(w_Aa - w_aa)) / w_bar
115
return dp
116
117
def wright_fisher(p0, N, generations):
118
"""Wright-Fisher genetic drift simulation."""
119
p = np.zeros(generations)
120
p[0] = p0
121
for i in range(1, generations):
122
if p[i-1] <= 0 or p[i-1] >= 1:
123
p[i] = p[i-1]
124
else:
125
n_A = np.random.binomial(2*N, p[i-1])
126
p[i] = n_A / (2*N)
127
return p
128
129
def fixation_probability_simulation(p0, N, s, n_sims=1000):
130
"""Estimate fixation probability by simulation."""
131
fixed = 0
132
for _ in range(n_sims):
133
p = p0
134
while 0 < p < 1:
135
# Selection
136
w_bar = (1 + s) * p**2 + p*(1-p) + (1-p)**2
137
p_sel = ((1 + s) * p**2 + p*(1-p)) / w_bar
138
# Drift
139
n_A = np.random.binomial(2*N, p_sel)
140
p = n_A / (2*N)
141
if p >= 1:
142
fixed += 1
143
return fixed / n_sims
144
145
# Parameters
146
generations = 200
147
t = np.linspace(0, generations, 1000)
148
149
# Selection scenarios
150
# Directional selection
151
p_dir = odeint(selection_dynamics, 0.1, t, args=(1.0, 0.95, 0.8))
152
# Overdominance
153
p_over = odeint(selection_dynamics, 0.1, t, args=(0.8, 1.0, 0.9))
154
# Underdominance (two initial conditions)
155
p_under1 = odeint(selection_dynamics, 0.4, t, args=(1.0, 0.8, 1.0))
156
p_under2 = odeint(selection_dynamics, 0.6, t, args=(1.0, 0.8, 1.0))
157
# Frequency-dependent (simplified)
158
p_freq = odeint(selection_dynamics, 0.3, t, args=(0.9, 1.0, 0.9))
159
160
# Genetic drift simulations
161
N_values = [20, 100, 500]
162
n_reps = 20
163
drift_results = {}
164
for N in N_values:
165
drift_results[N] = [wright_fisher(0.5, N, generations) for _ in range(n_reps)]
166
167
# Fitness landscape
168
p_range = np.linspace(0.001, 0.999, 200)
169
w_bar_dir = p_range**2 * 1.0 + 2*p_range*(1-p_range) * 0.95 + (1-p_range)**2 * 0.8
170
w_bar_over = p_range**2 * 0.8 + 2*p_range*(1-p_range) * 1.0 + (1-p_range)**2 * 0.9
171
w_bar_under = p_range**2 * 1.0 + 2*p_range*(1-p_range) * 0.8 + (1-p_range)**2 * 1.0
172
173
# Mutation-selection balance
174
mu = 1e-5
175
s_values = np.logspace(-4, -1, 50)
176
q_eq_recessive = np.sqrt(mu / s_values)
177
q_eq_dominant = mu / s_values
178
179
# Fixation probability (theoretical)
180
N_fix = 100
181
s_fix = np.linspace(-0.1, 0.1, 50)
182
# Kimura's formula: P_fix = (1 - exp(-4Ns*p0)) / (1 - exp(-4Ns))
183
p0_fix = 1 / (2 * N_fix) # New mutation
184
P_fix_theory = np.zeros_like(s_fix)
185
for i, s in enumerate(s_fix):
186
if abs(s) < 1e-6:
187
P_fix_theory[i] = p0_fix
188
else:
189
P_fix_theory[i] = (1 - np.exp(-4*N_fix*s*p0_fix)) / (1 - np.exp(-4*N_fix*s))
190
191
# Create figure
192
fig = plt.figure(figsize=(14, 12))
193
194
# Plot 1: Selection dynamics
195
ax1 = fig.add_subplot(3, 3, 1)
196
ax1.plot(t, p_dir, 'b-', linewidth=2, label='Directional')
197
ax1.plot(t, p_over, 'g-', linewidth=2, label='Overdominance')
198
ax1.plot(t, p_under1, 'r-', linewidth=1.5, label='Underdominance')
199
ax1.plot(t, p_under2, 'r--', linewidth=1.5)
200
ax1.set_xlabel('Generation')
201
ax1.set_ylabel('Allele frequency $p$')
202
ax1.set_title('Selection Dynamics')
203
ax1.legend(fontsize=8)
204
ax1.set_ylim([0, 1])
205
206
# Plot 2: Fitness landscape
207
ax2 = fig.add_subplot(3, 3, 2)
208
ax2.plot(p_range, w_bar_dir, 'b-', linewidth=2, label='Directional')
209
ax2.plot(p_range, w_bar_over, 'g-', linewidth=2, label='Overdominance')
210
ax2.plot(p_range, w_bar_under, 'r-', linewidth=2, label='Underdominance')
211
ax2.set_xlabel('Allele frequency $p$')
212
ax2.set_ylabel('Mean fitness $\\bar{w}$')
213
ax2.set_title('Fitness Landscape')
214
ax2.legend(fontsize=8)
215
216
# Plot 3: Genetic drift (small N)
217
ax3 = fig.add_subplot(3, 3, 3)
218
gen = np.arange(generations)
219
for traj in drift_results[20]:
220
ax3.plot(gen, traj, linewidth=0.8, alpha=0.5)
221
ax3.set_xlabel('Generation')
222
ax3.set_ylabel('Allele frequency $p$')
223
ax3.set_title(f'Genetic Drift (N = 20)')
224
ax3.set_ylim([0, 1])
225
226
# Plot 4: Genetic drift (medium N)
227
ax4 = fig.add_subplot(3, 3, 4)
228
for traj in drift_results[100]:
229
ax4.plot(gen, traj, linewidth=0.8, alpha=0.5)
230
ax4.set_xlabel('Generation')
231
ax4.set_ylabel('Allele frequency $p$')
232
ax4.set_title(f'Genetic Drift (N = 100)')
233
ax4.set_ylim([0, 1])
234
235
# Plot 5: Genetic drift (large N)
236
ax5 = fig.add_subplot(3, 3, 5)
237
for traj in drift_results[500]:
238
ax5.plot(gen, traj, linewidth=0.8, alpha=0.5)
239
ax5.set_xlabel('Generation')
240
ax5.set_ylabel('Allele frequency $p$')
241
ax5.set_title(f'Genetic Drift (N = 500)')
242
ax5.set_ylim([0, 1])
243
244
# Plot 6: Mutation-selection balance
245
ax6 = fig.add_subplot(3, 3, 6)
246
ax6.loglog(s_values, q_eq_recessive, 'b-', linewidth=2, label='Recessive')
247
ax6.loglog(s_values, q_eq_dominant, 'r-', linewidth=2, label='Dominant')
248
ax6.set_xlabel('Selection coefficient $s$')
249
ax6.set_ylabel('Equilibrium frequency $\\hat{q}$')
250
ax6.set_title(f'Mutation-Selection Balance ($\\mu = {mu}$)')
251
ax6.legend()
252
253
# Plot 7: Fixation probability
254
ax7 = fig.add_subplot(3, 3, 7)
255
ax7.plot(s_fix, P_fix_theory, 'b-', linewidth=2)
256
ax7.axhline(y=p0_fix, color='gray', linestyle='--', alpha=0.7, label='Neutral')
257
ax7.axvline(x=0, color='gray', linestyle=':', alpha=0.5)
258
ax7.set_xlabel('Selection coefficient $s$')
259
ax7.set_ylabel('Fixation probability')
260
ax7.set_title(f'Fixation Probability (N = {N_fix})')
261
ax7.legend(fontsize=8)
262
263
# Plot 8: Hardy-Weinberg frequencies
264
ax8 = fig.add_subplot(3, 3, 8)
265
ax8.plot(p_range, p_range**2, 'b-', linewidth=2, label='$p^2$ (AA)')
266
ax8.plot(p_range, 2*p_range*(1-p_range), 'g-', linewidth=2, label='$2pq$ (Aa)')
267
ax8.plot(p_range, (1-p_range)**2, 'r-', linewidth=2, label='$q^2$ (aa)')
268
ax8.set_xlabel('Allele frequency $p$')
269
ax8.set_ylabel('Genotype frequency')
270
ax8.set_title('Hardy-Weinberg Equilibrium')
271
ax8.legend(fontsize=8)
272
273
# Plot 9: Variance in allele frequency
274
ax9 = fig.add_subplot(3, 3, 9)
275
N_range = np.logspace(1, 4, 100)
276
p_test = 0.5
277
var_deltap = p_test * (1 - p_test) / (2 * N_range)
278
ax9.loglog(N_range, var_deltap, 'b-', linewidth=2)
279
ax9.set_xlabel('Population size $N$')
280
ax9.set_ylabel('Var($\\Delta p$)')
281
ax9.set_title('Drift Variance vs Population Size')
282
283
plt.tight_layout()
284
plt.savefig('evolutionary_dynamics_analysis.pdf', dpi=150, bbox_inches='tight')
285
plt.close()
286
287
# Calculate equilibrium for overdominance
288
p_eq_over = (1.0 - 0.9) / (2*1.0 - 0.8 - 0.9)
289
\end{pycode}
290
291
\begin{figure}[htbp]
292
\centering
293
\includegraphics[width=\textwidth]{evolutionary_dynamics_analysis.pdf}
294
\caption{Evolutionary dynamics analysis: (a) Selection dynamics under different fitness
295
schemes; (b) Fitness landscapes showing mean fitness as function of allele frequency;
296
(c-e) Genetic drift in populations of different sizes; (f) Mutation-selection balance;
297
(g) Fixation probability as function of selection coefficient; (h) Hardy-Weinberg
298
genotype frequencies; (i) Drift variance versus population size.}
299
\label{fig:evolution}
300
\end{figure}
301
302
\section{Results}
303
304
\subsection{Selection Equilibria}
305
306
\begin{pycode}
307
print(r"\begin{table}[htbp]")
308
print(r"\centering")
309
print(r"\caption{Selection Equilibria for Different Fitness Schemes}")
310
print(r"\begin{tabular}{lcccc}")
311
print(r"\toprule")
312
print(r"Selection Type & $w_{AA}$ & $w_{Aa}$ & $w_{aa}$ & Equilibrium $\hat{p}$ \\")
313
print(r"\midrule")
314
print(r"Directional & 1.00 & 0.95 & 0.80 & 1.00 (fixation) \\")
315
print(f"Overdominance & 0.80 & 1.00 & 0.90 & {p_eq_over:.2f} \\\\")
316
print(r"Underdominance & 1.00 & 0.80 & 1.00 & 0.00 or 1.00 \\")
317
print(r"\bottomrule")
318
print(r"\end{tabular}")
319
print(r"\label{tab:equilibria}")
320
print(r"\end{table}")
321
\end{pycode}
322
323
\subsection{Drift Statistics}
324
325
\begin{pycode}
326
print(r"\begin{table}[htbp]")
327
print(r"\centering")
328
print(r"\caption{Genetic Drift Statistics After " + str(generations) + r" Generations}")
329
print(r"\begin{tabular}{cccc}")
330
print(r"\toprule")
331
print(r"$N$ & Fixed & Lost & Polymorphic \\")
332
print(r"\midrule")
333
334
for N in N_values:
335
fixed = sum(1 for traj in drift_results[N] if traj[-1] >= 0.99)
336
lost = sum(1 for traj in drift_results[N] if traj[-1] <= 0.01)
337
poly = n_reps - fixed - lost
338
print(f"{N} & {fixed} & {lost} & {poly} \\\\")
339
340
print(r"\bottomrule")
341
print(r"\end{tabular}")
342
print(r"\label{tab:drift}")
343
print(r"\end{table}")
344
\end{pycode}
345
346
\section{Discussion}
347
348
\begin{example}[Overdominance and Stable Polymorphism]
349
Heterozygote advantage (overdominance) maintains genetic variation in populations.
350
The equilibrium allele frequency for our example is:
351
\begin{equation}
352
\hat{p} = \frac{w_{Aa} - w_{aa}}{2w_{Aa} - w_{AA} - w_{aa}} = \frac{1.0 - 0.9}{2(1.0) - 0.8 - 0.9} = \py{f"{p_eq_over:.2f}"}
353
\end{equation}
354
Classic examples include sickle-cell anemia and MHC diversity.
355
\end{example}
356
357
\begin{remark}[Effective Population Size]
358
The variance in allele frequency change is $\text{Var}(\Delta p) = pq/(2N_e)$. Factors
359
reducing $N_e$ below census size include:
360
\begin{itemize}
361
\item Unequal sex ratios
362
\item Variance in reproductive success
363
\item Population bottlenecks
364
\item Overlapping generations
365
\end{itemize}
366
\end{remark}
367
368
\section{Conclusions}
369
370
This analysis demonstrates the fundamental forces of evolutionary change:
371
\begin{enumerate}
372
\item Selection drives systematic allele frequency change toward fitness peaks
373
\item Overdominance equilibrium at $\hat{p} = \py{f"{p_eq_over:.2f}"}$ maintains polymorphism
374
\item Genetic drift is stronger in small populations, with variance $\propto 1/N$
375
\item Mutation-selection balance maintains deleterious alleles at low frequencies
376
\item Fixation probability depends on both selection and population size
377
\end{enumerate}
378
379
\section*{Further Reading}
380
381
\begin{itemize}
382
\item Hartl, D.L. \& Clark, A.G. \textit{Principles of Population Genetics}, 4th ed. Sinauer, 2007.
383
\item Gillespie, J.H. \textit{Population Genetics: A Concise Guide}, 2nd ed. Johns Hopkins, 2004.
384
\item Nowak, M.A. \textit{Evolutionary Dynamics}. Harvard University Press, 2006.
385
\end{itemize}
386
387
\end{document}
388
389