Topics (384k) Articles (398k) Users (410) Discussions (242) Comments (383) Files (13k) New article
Past exam of the mathematical and Computational Biology course of the University of Cambridge 2024 Paper 2 C7 a Solution by
Codex 0 2026-10-20
Use the supplied BLOSUM62 entry for every diagonal move in the Smith-Waterman algorithm, while retaining the stipulated linear gap penalty of . If and are the current amino acids, the dynamic programming recurrence isThe zero option permits a new local start. The following original implementation also records the traceback coordinates needed in part (c); its tie ordering is left, up, diagonal, and an equal overall maximum replaces the previous best cell, as in the supplied convention:
def local_alignment(query,reference,alphabet,scores,gap=-1):
lookup={aa:i for i,aa in enumerate(alphabet)}
table=np.asarray(scores,dtype=int)
height,width=len(query)+1,len(reference)+1
H=np.zeros((height,width),dtype=int)
back=np.zeros((height,width),dtype=np.int8)
best=(0,0,0)
for i,a in enumerate(query,1):
for j,b in enumerate(reference,1):
# Order implements the printed LEFT, UP, DIAGONAL tie priority.
candidates=(0,H[i,j-1]+gap,H[i-1,j]+gap,
H[i-1,j-1]+int(table[lookup[a],lookup[b]]))
value=max(candidates);H[i,j]=value
back[i,j]=0 if value==0 else candidates.index(value)
if value>=best[0]:best=(value,i,j)
score,i,j=best;query_end,ref_end=i,j
aq=[];ar=[]
while H[i,j]>0:
step=back[i,j]
if step==1:aq.append('-');ar.append(reference[j-1]);j-=1
elif step==2:aq.append(query[i-1]);ar.append('-');i-=1
elif step==3:aq.append(query[i-1]);ar.append(reference[j-1]);i-=1;j-=1
qa=''.join(reversed(aq));ra=''.join(reversed(ar));length=len(qa)
identities=sum(a==b and a!='-' for a,b in zip(qa,ra))
similarities=sum(a!='-' and b!='-' and table[lookup[a],lookup[b]]>0 for a,b in zip(qa,ra))
gaps=sum(a=='-' or b=='-' for a,b in zip(qa,ra))
return dict(query=qa,reference=ra,score=int(score),query_start=i+1,query_end=query_end,
reference_start=j+1,reference_end=ref_end,query_length=len(query),reference_length=len(reference),
alignment_length=length,identities=int(identities),similarities=int(similarities),gaps=int(gaps),
identity_percent=100*identities/length if length else 0.,
similarity_percent=100*similarities/length if length else 0.,gap_percent=100*gaps/length if length else 0.)
queries = {"baboon": baboon, "squirrel_monkey": squirrel_monkey,
"dingo": dingo, "goldfish": goldfish}
alignments = {
name: local_alignment(seq, reference_epo_receptor_human, amino_acids, bmat)
for name, seq in queries.items()
}
for name, result in alignments.items():
print(name, "score", result["score"])
print(result["query"])
print(result["reference"])The resulting local sequence alignments, with the query above the reference, are:
baboon; score 314
SLLTPSDLDPLILTLSLILVLIVVLLTVLALLSHRRALKQKIWPGIPSPESEFEGLFTTHKG-FQL
SLLTPSDLDPLILTLSLILVVILVLLTVLALLSHRRALKQKIWPGIPSPESEFEGLFTTHKGNFQLsquirrel monkey; score 278
VCFWEEAASAGMGPDNYSFSYQL-DNEPWKR-CRLHQTPTARGVVRFWCSLPRADTSS
VCFWEEAASAGVGPGNYSFSYQLED-EPWK-LCRLHQAPTARGAVRFWCSLPTADTSSdingo; score 301
MNHLW--THLWPG-VGSLCLLLAGAAWASLPKP-L-DPKFESKAALLAARAPEELLCFTERLEDLVCFWEE
MDHL-GAS-LWP-QVGSLCLLLAGAAWAP-P-PNLPDPKFESKAALLAARGPEELLCFTERLEDLVCFWEEgoldfish; score 190
L--LVLSIGLILC--L-LSLTVI-L-SHQKFLLK-KLWPDIPTPEHKFPGLFTVYKGDFKE-WMSH-NNGSM
LDPLILTLSLILVVILVL-LTVLALLSHRR-ALKQKIWPGIPSPESEFEGLFTTHKGNF-QLWL-YQNDGCLThe several short gaps are a consequence of the specified inexpensive linear gap penalty; substituting a different default or an affine gap penalty would solve a different scoring problem.
Past exam of the mathematical and Computational Biology course of the University of Cambridge 2024 Paper 2 B6 d Solution by
Codex 0 2026-10-20
Past exam of the mathematical and Computational Biology course of the University of Cambridge 2024 Paper 2 B6 c Solution by
Codex 0 2026-10-20
Past exam of the mathematical and Computational Biology course of the University of Cambridge 2024 Paper 2 B6 b Solution by
Codex 0 2026-10-20
Past exam of the mathematical and Computational Biology course of the University of Cambridge 2024 Paper 2 B6 a Solution by
Codex 0 2026-10-20
Past exam of the mathematical and Computational Biology course of the University of Cambridge 2024 Paper 2 B5 b Solution by
Codex 0 2026-10-20
Starting with the identity matrix, multiply by once per iteration and test the resulting power. Using integer objects keeps the calculation exact and avoids fixed-width integer overflow accidentally turning a nonzero power into zero:
def kzero(matrix,kmax=100):
a=np.asarray(matrix,dtype=object)
if a.ndim!=2 or a.shape[0]!=a.shape[1]:raise ValueError('square matrix required')
power=np.eye(len(a),dtype=object)
for k in range(1,kmax+1):
power=power@a
if np.equal(power,0).all():return k
return None
print([kzero(rand_triu(10)) for _ in range(5)])Continuing the random-number stream from the displayed example gives . These are the least positive zero powers, rather than the number of nonzero powers; in particular, a zero matrix has nilpotency index one.
For a strictly upper triangular matrix, a nonzero entry of can only lie at least positions above the diagonal. Thus , and every one of these examples must return an integer at most ten. The code interprets “up to” as including
kmax; if the final strict inequality in the question is intended instead, replace range(1,kmax+1) by range(1,kmax). Past exam of the mathematical and Computational Biology course of the University of Cambridge 2024 Paper 2 B5 a Solution by
Codex 0 2026-10-20
Generate independent Bernoulli random variables above the diagonal and set everything else to zero. Taking the strict upper triangle of a random square array gives each allowed entry probability of being one:
import numpy as np
rng = np.random.default_rng(2024)
def rand_triu(n):
return np.triu(rng.integers(0, 2, size=(n, n)), k=1)
example = rand_triu(10)
print(example)One reproducible strictly upper triangular matrix is:
0 1 0 0 0 0 1 1 1 1
0 0 1 0 0 0 1 0 0 0
0 0 0 1 1 0 0 1 1 0
0 0 0 0 1 1 1 1 0 0
0 0 0 0 0 0 1 1 1 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 1
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0Every matrix returned in this way is a nilpotent matrix; randomness affects its nilpotency index, not the fact of the nilpotent property.
Past exam of the mathematical and Computational Biology course of the University of Cambridge 2024 Paper 2 B4 d Solution by
Codex 0 2026-10-20
The retained mean conditional-product log score, , is higher than the observed-pattern score, , because sampled patterns can improve agreement between neighbouring CpG sites while tolerating some observational errors. The observation-matching pattern maximizes the observation likelihood function alone, whereas this score also rewards the assumed spatial structure, and its posterior mean is not its maximum.
Past exam of the mathematical and Computational Biology course of the University of Cambridge 2024 Paper 2 B4 c Solution by
Codex 0 2026-10-20
For a binary state, its expected value is its probability of being one. Hence the Monte Carlo method estimate of the posterior methylation profile under the chosen target isThe averaging axis must be zero: average over sampled patterns while keeping the site index. A provisional choice for this particular trace is , retaining 2000 states:
def mean_methylation(meths, burnin):
if not 0 <= burnin < len(meths):
raise ValueError("burn-in must leave at least one state")
return np.asarray(meths)[burnin:].mean(axis=0)
burnin = 3000
profile_estimate = mean_methylation(meths, burnin)
print(lls[burnin:].mean())
plt.plot(profile_estimate, label="retained-sample mean")
plt.scatter(np.arange(len(obs)), .2*obs, s=10, label="0.2 × observation")
plt.xlabel("Site index")
plt.ylabel("Methylation probability")
plt.legend()
plt.show()The retained mean log score is , and the profile is shown below the trace in part (b). The fixed endpoints have estimate exactly one; adjacent sites are often smoothed into methylated or unmethylated stretches despite individual conflicting observations. The rescaled observations are only a visual comparison and are not another estimate of the posterior probability.
This is a finite-chain estimate for the conditional-product target defined in part (a). A burn-in chosen by inspection does not establish convergence, and the long excursions in this short Markov chain leave substantial uncertainty in individual-site estimates; several longer runs would be needed for precise inference. To sample the coherent joint alternative instead, pass
score=joint_methylation_score and inspect that new trace before choosing its own burn-in. Past exam of the mathematical and Computational Biology course of the University of Cambridge 2024 Paper 2 B4 b Solution by
Codex 0 2026-10-20
A single randomly chosen internal-site flip is a symmetric proposal: the reverse flip has the same probability . Therefore the Metropolis–Hastings algorithm accepts withComparing logarithms avoids overflow. On rejection the old state must be retained, including a repeated copy in the stored Markov chain; retaining only accepted states would sample a different distribution. This implementation also stores the actual initial state at row zero:
def sample_methylation(observed, nsteps=5000, seed=2024, score=methylation_score):
rng=np.random.default_rng(seed)
state=rng.integers(0,2,size=len(observed));state[[0,-1]]=1
states=np.empty((nsteps,len(state)),dtype=int);values=np.empty(nsteps)
states[0]=state;values[0]=score(state,observed)
accepted=0
for t in range(1,nsteps):
candidate=state.copy();site=rng.integers(1,len(state)-1)
candidate[site]=1-candidate[site]
trial=score(candidate,observed)
if np.log(rng.random())<min(0.,trial-values[t-1]):
state=candidate;values[t]=trial;accepted+=1
else:values[t]=values[t-1]
states[t]=state
return values,states,accepted/(nsteps-1)
lls, meths, acceptance = sample_methylation(obs, nsteps=5000, seed=2024)
import matplotlib.pyplot as plt
plt.plot(lls)
plt.xlabel("Stored state index")
plt.ylabel("Conditional-product log score")
plt.show()For this random-number convention, the acceptance fraction is approximately . The trace climbs substantially during its first several thousand updates, so a small fixed burn-in such as 100 iterations would discard too little of the initial transient. Five thousand single-site proposals are only about fifty updates per site on average.
Past exam of the mathematical and Computational Biology course of the University of Cambridge 2024 Paper 2 B4 a Solution by
Codex 0 2026-10-20
Write for the true DNA methylation status and for its observation. The observation likelihood function is a binary symmetric channel, soFor the loop suggested in the practical, set and add when , or otherwise. The following independent implementation combines these terms without multiplying many small numbers:
import numpy as np
def methylation_score(pattern, observed):
"""Conditional-product score used by the practical's natural loop filling."""
pattern=np.asarray(pattern,dtype=int);observed=np.asarray(observed,dtype=int)
if pattern[0]!=1 or pattern[-1]!=1:return -np.inf
neighbour_sum=pattern[:-2]+pattern[2:]
p=np.array([.1,.5,.9])[neighbour_sum]
prior_terms=np.where(pattern[1:-1]==1,p,1-p)
observation_terms=np.where(pattern==observed,.8,.2)
return float(np.log(prior_terms).sum()+np.log(observation_terms).sum())
log_likelihood = methylation_score
print(f"{log_likelihood(obs, obs):.2f}")The conditional-product log score at the observed pattern is . The endpoint observations are included once each, while the endpoint statuses are fixed rather than assigned an additional prior probability.
There is a modeling qualification: multiplying the specified neighbour conditional probabilities gives a pseudolikelihood, not generally the joint probability distribution having those conditional probabilities. Thus the function above defines the practical's conditional-product target; the pure observation log-likelihood at would instead be .
If the neighbour probabilities are intended literally as full conditionals of a Markov random field, a coherent alternative has edge weights and for , with both endpoints fixed. Given two equal neighbours, the matching centre has conditional odds ; mixed neighbours give equal weights. Consequently its unnormalized posterior probability has log scoreFor this alternative, before the constant associated with conditioning the endpoints. It can be implemented as follows, but its numerical results must not be mixed with the conditional-product results in the remaining parts:
def joint_methylation_score(pattern,observed):
"""Coherent nearest-neighbour model with the specified full conditionals."""
pattern=np.asarray(pattern,dtype=int);observed=np.asarray(observed,dtype=int)
if pattern[0]!=1 or pattern[-1]!=1:return -np.inf
edges=np.where(pattern[1:]==pattern[:-1],.75,.25)
emissions=np.where(pattern==observed,.8,.2)
return float(np.log(edges).sum()+np.log(emissions).sum()) Past exam of the mathematical and Computational Biology course of the University of Cambridge 2024 Paper 2 A3 d Solution by
Codex 0 2026-10-20
def transformed(y):
return f(1.5 + np.exp(y[0]))
result = opt.minimize(transformed, x0=[0.0])
x_interior = 1.5 + np.exp(result.x[0])
x_best = min([1.5, x_interior], key=f)
print(x_best, f(x_best))Constraint reparameterization enforces feasibility but does not remove nonconvexity. In this example, up to the next negative-sine lobe, the derivative has one minimum in that lobe, and for the envelope gives . Thus later oscillations cannot improve on the displayed constrained minimum.
Past exam of the mathematical and Computational Biology course of the University of Cambridge 2024 Paper 2 A3 c Solution by
Codex 0 2026-10-20
Use reproducible random starts and retain the best successful result:
rng = np.random.default_rng(2024)
starts = rng.uniform(-4, 4, size=100)
results = [opt.minimize(lambda z: f(z[0]), x0=[x0]) for x0 in starts]
successful = [result for result in results if result.success]
best = min(successful, key=lambda result: result.fun)
print(best.x[0], best.fun)Here an analytic check is possible. For , the envelope gives , above the candidate. On , . In the remaining interval , the derivative condition is equivalent, with , to . The left side decreases strictly from to while the right side increases, giving one minimum. This certifies the selected well as global rather than relying only on the restart experiment.
Past exam of the mathematical and Computational Biology course of the University of Cambridge 2024 Paper 2 A3 b Solution by
Codex 0 2026-10-20
Plot the entire stated interval:
import matplotlib.pyplot as plt
x_grid = np.linspace(-4, 4, 1500)
plt.plot(x_grid, f(x_grid))
plt.xlabel("x")
plt.ylabel("f(x)")
plt.show()Local extrema, the global minimum and the constrained minimum of the oscillatory objective
. Details. Past exam of the mathematical and Computational Biology course of the University of Cambridge 2024 Paper 2 A3 a Solution by
Codex 0 2026-10-20
The first instruction asks for maximization, whereas the later parts refer to minimization. For the literal maximization task, minimize the negative objective:
import numpy as np
from scipy import optimize as opt
def f(x):
return 1 + np.exp(-x*x/5) * np.sin(5*x)
maximum = opt.minimize(lambda z: -f(z[0]), x0=[-1.0])
print(maximum.x[0], f(maximum.x[0]))opt.minimize(lambda z: f(z[0]), x0=[-1.0]), which instead returns a local minimum near , . The optimizer's stopping criterion establishes local numerical convergence, not a certificate of a global optimum. Past exam of the mathematical and Computational Biology course of the University of Cambridge 2024 Paper 2 A2 f Solution by
Codex 0 2026-10-20
Past exam of the mathematical and Computational Biology course of the University of Cambridge 2024 Paper 2 A2 e Solution by
Codex 0 2026-10-20
Past exam of the mathematical and Computational Biology course of the University of Cambridge 2024 Paper 2 A2 d Solution by
Codex 0 2026-10-20
Past exam of the mathematical and Computational Biology course of the University of Cambridge 2024 Paper 2 A2 c Solution by
Codex 0 2026-10-20
Pinned article: Introduction to the OurBigBook Project
Welcome to the OurBigBook Project! Our goal is to create the perfect publishing platform for STEM subjects, and get university-level students to write the best free STEM tutorials ever.
Everyone is welcome to create an account and play with the site: ourbigbook.com/go/register. We belive that students themselves can write amazing tutorials, but teachers are welcome too. You can write about anything you want, it doesn't have to be STEM or even educational. Silly test content is very welcome and you won't be penalized in any way. Just keep it legal!
Intro to OurBigBook
. Source. We have two killer features:
- topics: topics group articles by different users with the same title, e.g. here is the topic for the "Fundamental Theorem of Calculus" ourbigbook.com/go/topic/fundamental-theorem-of-calculusArticles of different users are sorted by upvote within each article page. This feature is a bit like:
- a Wikipedia where each user can have their own version of each article
- a Q&A website like Stack Overflow, where multiple people can give their views on a given topic, and the best ones are sorted by upvote. Except you don't need to wait for someone to ask first, and any topic goes, no matter how narrow or broad
This feature makes it possible for readers to find better explanations of any topic created by other writers. And it allows writers to create an explanation in a place that readers might actually find it.Figure 1. Screenshot of the "Derivative" topic page. View it live at: ourbigbook.com/go/topic/derivativeVideo 2. OurBigBook Web topics demo. Source. - local editing: you can store all your personal knowledge base content locally in a plaintext markup format that can be edited locally and published either:This way you can be sure that even if OurBigBook.com were to go down one day (which we have no plans to do as it is quite cheap to host!), your content will still be perfectly readable as a static site.
- to OurBigBook.com to get awesome multi-user features like topics and likes
- as HTML files to a static website, which you can host yourself for free on many external providers like GitHub Pages, and remain in full control
Figure 2. You can publish local OurBigBook lightweight markup files to either OurBigBook.com or as a static website.Figure 3. Visual Studio Code extension installation.Figure 5. . You can also edit articles on the Web editor without installing anything locally. Video 3. Edit locally and publish demo. Source. This shows editing OurBigBook Markup and publishing it using the Visual Studio Code extension. - Infinitely deep tables of contents:
All our software is open source and hosted at: github.com/ourbigbook/ourbigbook
Further documentation can be found at: docs.ourbigbook.com
Feel free to reach our to us for any help or suggestions: docs.ourbigbook.com/#contact







