Pair hidden Markov models
DefinitionFuel-bounded enumeration of two-alphabet alignments#✓fully proved
All alignments of xs : List α with ys : List β, by fuel recursion on the first column
(the same recursion as Cslib.Algorithms.Lean.alignmentsAux, for two alphabets). Implementation
detail: use alignmentsOf, whose fuel xs.length + ys.length + 1 is enough.
def alignmentsOfAux {α β : Type*} : ℕ → List α → List β → List (List (Option α × Option β))
| 0, _, _ => []
| _ + 1, [], [] => [[]]
| n + 1, [], b :: ys => (alignmentsOfAux n [] ys).map fun A => (none, some b) :: A
| n + 1, a :: xs, [] => (alignmentsOfAux n xs []).map fun A => (some a, none) :: A
| n + 1, a :: xs, b :: ys =>
(alignmentsOfAux n xs ys).map (fun A => (some a, some b) :: A) ++
(alignmentsOfAux n xs (b :: ys)).map (fun A => (some a, none) :: A) ++
(alignmentsOfAux n (a :: xs) ys).map (fun A => (none, some b) :: A)
Used by 10
alignmentsOf is validity · Each alignment is listed once · The sum recursion is the sum over alignmentsDefinitionAll alignments of sequences over two alphabets#✓fully proved
All alignments of a sequence over α with a sequence over β: lists of columns
Option α × Option β with no (none, none) column whose rows filter to xs and ys
(mem_alignmentsOf), each listed once (nodup_alignmentsOf). For β = α this is
Cslib.Algorithms.Lean.alignments (alignmentsOf_eq_alignments).
def alignmentsOf {α β : Type*} (xs : List α) (ys : List β) : List (List (Option α × Option β)) :=
alignmentsOfAux (xs.length + ys.length + 1) xs ys
def alignmentsOfAux {α β : Type*} : ℕ → List α → List β → List (List (Option α × Option β))
| 0, _, _ => []
| _ + 1, [], [] => [[]]
| n + 1, [], b :: ys => (alignmentsOfAux n [] ys).map fun A => (none, some b) :: A
| n + 1, a :: xs, [] => (alignmentsOfAux n xs []).map fun A => (some a, none) :: A
| n + 1, a :: xs, b :: ys =>
(alignmentsOfAux n xs ys).map (fun A => (some a, some b) :: A) ++
(alignmentsOfAux n xs (b :: ys)).map (fun A => (some a, none) :: A) ++
(alignmentsOfAux n (a :: xs) ys).map (fun A => (none, some b) :: A)
CSLibExt/Bioinformatics/HMM/PairHMM.lean:96
Uses 1 · Used by 18
alignmentsOf is validity · Each alignment is listed once · Sum recursion on two nonempty sequences · Sum recursion with an empty second sequence · The sum recursion is the sum over alignments · Sum recursion with an empty first sequence · The Viterbi value is attained · Forward computes the total path weight · Every path weighs at most the Viterbi valueTheoremAlignments of two nonempty sequences by first column#✓fully proved
The alignments of two nonempty sequences, by their first column.
theorem alignmentsOf_cons_cons {α β : Type*} (a : α) (b : β) (xs : List α) (ys : List β) :
alignmentsOf (a :: xs) (b :: ys) =
(alignmentsOf xs ys).map (fun A => (some a, some b) :: A) ++
(alignmentsOf xs (b :: ys)).map (fun A => (some a, none) :: A) ++
(alignmentsOf (a :: xs) ys).map (fun A => (none, some b) :: A)
def alignmentsOf {α β : Type*} (xs : List α) (ys : List β) : List (List (Option α × Option β)) :=
alignmentsOfAux (xs.length + ys.length + 1) xs ys
CSLibExt/Bioinformatics/HMM/PairHMM.lean:110
Uses 2 · Used by 2
TheoremAlignments of the empty sequence with a nonempty one#✓fully proved
The alignments of the empty sequence with a nonempty one.
theorem alignmentsOf_nil_cons {α β : Type*} (b : β) (ys : List β) :
alignmentsOf ([] : List α) (b :: ys) =
(alignmentsOf [] ys).map (fun A => (none, some b) :: A)
def alignmentsOf {α β : Type*} (xs : List α) (ys : List β) : List (List (Option α × Option β)) :=
alignmentsOfAux (xs.length + ys.length + 1) xs ys
CSLibExt/Bioinformatics/HMM/PairHMM.lean:110
Uses 2 · Used by 2
TheoremAlignments of a nonempty sequence with the empty one#✓fully proved
The alignments of a nonempty sequence with the empty one.
theorem alignmentsOf_cons_nil {α β : Type*} (a : α) (xs : List α) :
alignmentsOf (a :: xs) ([] : List β) =
(alignmentsOf xs []).map (fun A => (some a, none) :: A)
def alignmentsOf {α β : Type*} (xs : List α) (ys : List β) : List (List (Option α × Option β)) :=
alignmentsOfAux (xs.length + ys.length + 1) xs ys
CSLibExt/Bioinformatics/HMM/PairHMM.lean:110
Uses 2 · Used by 2
TheoremMembership in alignmentsOf is validity#✓fully proved
No (none, none) column, and the rows filter
to the two sequences.
theorem mem_alignmentsOf {α β : Type*} (xs : List α) (ys : List β)
(A : List (Option α × Option β)) :
A ∈ alignmentsOf xs ys ↔
(∀ c ∈ A, c ≠ (none, none)) ∧ A.filterMap Prod.fst = xs ∧ A.filterMap Prod.snd = ys
def alignmentsOf {α β : Type*} (xs : List α) (ys : List β) : List (List (Option α × Option β)) :=
alignmentsOfAux (xs.length + ys.length + 1) xs ys
CSLibExt/Bioinformatics/HMM/PairHMM.lean:110
TheoremEach alignment is listed once#✓fully proved
Each alignment is listed once.
theorem nodup_alignmentsOf {α β : Type*} (xs : List α) (ys : List β) :
(alignmentsOf xs ys).Nodup
def alignmentsOf {α β : Type*} (xs : List α) (ys : List β) : List (List (Option α × Option β)) :=
alignmentsOfAux (xs.length + ys.length + 1) xs ys
CSLibExt/Bioinformatics/HMM/PairHMM.lean:110
Uses 2
TheoremTwo-alphabet alignments agree with single-alphabet alignments#✓fully proved
On one alphabet, alignmentsOf is Cslib.Algorithms.Lean.alignments.
theorem alignmentsOf_eq_alignments {α : Type*} (xs ys : List α) :
alignmentsOf xs ys = alignments xs ys
def alignmentsOf {α β : Type*} (xs : List α) (ys : List β) : List (List (Option α × Option β)) :=
alignmentsOfAux (xs.length + ys.length + 1) xs ys
CSLibExt/Bioinformatics/HMM/PairHMM.lean:110
def alignments (xs ys : List α) : List (Alignment α) :=
alignmentsAux (xs.length + ys.length + 1) xs ys
CSLibExt/Algorithms/Lean/DynamicProgramming/SequenceAlignment.lean:226
Uses 5 · Used by 3
StructureWeighted alignment automaton#✓fully proved
A weighted automaton reading an alignment of a sequence over α with a sequence over β
column by column with a control state in Q: the weight of reading a column in a control
state, the next control state, and the final weight of a control state. Weights are in R.
structure AlignmentAutomaton (Q α β R : Type*) where
/-- The weight of reading a column in a control state. -/
weight : Q → Option α × Option β → R
/-- The control state after reading a column. -/
next : Q → Option α × Option β → Q
/-- The weight of ending in a control state. -/
final : Q → R
Used by 22
DefinitionWeight of an alignment read by an automaton#✓fully proved
The weight of an alignment read from control state q: the product of the column weights
along the alignment, then the final weight.
def alignWeight : Q → List (Option α × Option β) → R
| q, [] => M.final q
| q, c :: A => M.weight q c * alignWeight (M.next q c) A
Uses 1 · Used by 12
DefinitionFuel-bounded sum recursion over alignments#✓fully proved
The sum recursion with fuel (the fuel bounds the recursion depth). Implementation detail:
use sumDP, whose fuel xs.length + ys.length + 1 is enough.
def sumDPAux : ℕ → Q → List α → List β → R
| 0, _, _, _ => 0
| _ + 1, q, [], [] => M.final q
| n + 1, q, [], b :: ys =>
M.weight q (none, some b) * sumDPAux n (M.next q (none, some b)) [] ys
| n + 1, q, a :: xs, [] =>
M.weight q (some a, none) * sumDPAux n (M.next q (some a, none)) xs []
| n + 1, q, a :: xs, b :: ys =>
M.weight q (some a, some b) * sumDPAux n (M.next q (some a, some b)) xs ys +
M.weight q (some a, none) * sumDPAux n (M.next q (some a, none)) xs (b :: ys) +
M.weight q (none, some b) * sumDPAux n (M.next q (none, some b)) (a :: xs) ys
Uses 1 · Used by 2
DefinitionTotal alignment weight by first-column recursion#✓fully proved
The total weight of all alignments of xs and ys read from control state q, by the
first-column recursion (sumDP_eq_sum).
def sumDP (q : Q) (xs : List α) (ys : List β) : R :=
sumDPAux M (xs.length + ys.length + 1) q xs ys
def sumDPAux : ℕ → Q → List α → List β → R
| 0, _, _, _ => 0
| _ + 1, q, [], [] => M.final q
| n + 1, q, [], b :: ys =>
M.weight q (none, some b) * sumDPAux n (M.next q (none, some b)) [] ys
| n + 1, q, a :: xs, [] =>
M.weight q (some a, none) * sumDPAux n (M.next q (some a, none)) xs []
| n + 1, q, a :: xs, b :: ys =>
M.weight q (some a, some b) * sumDPAux n (M.next q (some a, some b)) xs ys +
M.weight q (some a, none) * sumDPAux n (M.next q (some a, none)) xs (b :: ys) +
M.weight q (none, some b) * sumDPAux n (M.next q (none, some b)) (a :: xs) ys
CSLibExt/Bioinformatics/HMM/PairHMM.lean:292
Uses 2 · Used by 8
TheoremThe sum recursion is the sum over alignments#✓fully proved
The sum recursion is the sum over alignments.
theorem sumDP_eq_sum (q : Q) (xs : List α) (ys : List β) :
sumDP M q xs ys = ((alignmentsOf xs ys).map (alignWeight M q)).sum
def sumDP (q : Q) (xs : List α) (ys : List β) : R :=
sumDPAux M (xs.length + ys.length + 1) q xs ys
CSLibExt/Bioinformatics/HMM/PairHMM.lean:306
def alignmentsOf {α β : Type*} (xs : List α) (ys : List β) : List (List (Option α × Option β)) :=
alignmentsOfAux (xs.length + ys.length + 1) xs ys
CSLibExt/Bioinformatics/HMM/PairHMM.lean:110
def alignWeight : Q → List (Option α × Option β) → R
| q, [] => M.final q
| q, c :: A => M.weight q c * alignWeight (M.next q c) A
CSLibExt/Bioinformatics/HMM/PairHMM.lean:286
Uses 6 · Used by 5
TheoremSum recursion on two nonempty sequences#✓fully proved
The sum recursion on two nonempty sequences.
theorem sumDP_cons_cons (q : Q) (a : α) (b : β) (xs : List α) (ys : List β) :
sumDP M q (a :: xs) (b :: ys) =
M.weight q (some a, some b) * sumDP M (M.next q (some a, some b)) xs ys +
M.weight q (some a, none) * sumDP M (M.next q (some a, none)) xs (b :: ys) +
M.weight q (none, some b) * sumDP M (M.next q (none, some b)) (a :: xs) ys
def sumDP (q : Q) (xs : List α) (ys : List β) : R :=
sumDPAux M (xs.length + ys.length + 1) q xs ys
CSLibExt/Bioinformatics/HMM/PairHMM.lean:306
Uses 6
TheoremSum recursion with an empty first sequence#✓fully proved
The sum recursion when the first sequence is empty.
theorem sumDP_nil_cons (q : Q) (b : β) (ys : List β) :
sumDP M q ([] : List α) (b :: ys) =
M.weight q (none, some b) * sumDP M (M.next q (none, some b)) [] ys
def sumDP (q : Q) (xs : List α) (ys : List β) : R :=
sumDPAux M (xs.length + ys.length + 1) q xs ys
CSLibExt/Bioinformatics/HMM/PairHMM.lean:306
Uses 6
TheoremSum recursion with an empty second sequence#✓fully proved
The sum recursion when the second sequence is empty.
theorem sumDP_cons_nil (q : Q) (a : α) (xs : List α) :
sumDP M q (a :: xs) ([] : List β) =
M.weight q (some a, none) * sumDP M (M.next q (some a, none)) xs []
def sumDP (q : Q) (xs : List α) (ys : List β) : R :=
sumDPAux M (xs.length + ys.length + 1) q xs ys
CSLibExt/Bioinformatics/HMM/PairHMM.lean:306
Uses 6
TheoremSum recursion on two empty sequences is the final weight#✓fully proved
The sum recursion on two empty sequences is the final weight.
theorem sumDP_nil_nil (q : Q) : sumDP M q ([] : List α) ([] : List β) = M.final q
def sumDP (q : Q) (xs : List α) (ys : List β) : R :=
sumDPAux M (xs.length + ys.length + 1) q xs ys
CSLibExt/Bioinformatics/HMM/PairHMM.lean:306
Uses 2
DefinitionFuel-bounded max recursion over alignments#✓fully proved
The max recursion with fuel. Implementation detail: use maxDP.
def maxDPAux : ℕ → Q → List α → List β → R
| 0, _, _, _ => 0
| _ + 1, q, [], [] => M.final q
| n + 1, q, [], b :: ys =>
M.weight q (none, some b) * maxDPAux n (M.next q (none, some b)) [] ys
| n + 1, q, a :: xs, [] =>
M.weight q (some a, none) * maxDPAux n (M.next q (some a, none)) xs []
| n + 1, q, a :: xs, b :: ys =>
max (max (M.weight q (some a, some b) * maxDPAux n (M.next q (some a, some b)) xs ys)
(M.weight q (some a, none) * maxDPAux n (M.next q (some a, none)) xs (b :: ys)))
(M.weight q (none, some b) * maxDPAux n (M.next q (none, some b)) (a :: xs) ys)
Uses 1 · Used by 6
DefinitionMax-recursion alignment value from a control state#✓fully proved
The max-recursion value of an alignment of xs and ys read from control state q, by
the first-column recursion (alignWeight_le_maxDP, exists_alignWeight_eq_maxDP). It is the
largest alignment weight only when the weights are nonnegative; in general it is the value of
the recursively chosen alignment.
def maxDP (q : Q) (xs : List α) (ys : List β) : R :=
maxDPAux M (xs.length + ys.length + 1) q xs ys
def maxDPAux : ℕ → Q → List α → List β → R
| 0, _, _, _ => 0
| _ + 1, q, [], [] => M.final q
| n + 1, q, [], b :: ys =>
M.weight q (none, some b) * maxDPAux n (M.next q (none, some b)) [] ys
| n + 1, q, a :: xs, [] =>
M.weight q (some a, none) * maxDPAux n (M.next q (some a, none)) xs []
| n + 1, q, a :: xs, b :: ys =>
max (max (M.weight q (some a, some b) * maxDPAux n (M.next q (some a, some b)) xs ys)
(M.weight q (some a, none) * maxDPAux n (M.next q (some a, none)) xs (b :: ys)))
(M.weight q (none, some b) * maxDPAux n (M.next q (none, some b)) (a :: xs) ys)
CSLibExt/Bioinformatics/HMM/PairHMM.lean:362
Uses 2 · Used by 9
DefinitionNonnegative column weights of an alignment automaton#✓fully proved
Nonnegative column weights. The final weights may have any sign: the max recursion bounds
every alignment weight without that (alignWeight_le_maxDP).
def Nonneg : Prop := ∀ q c, 0 ≤ M.weight q c
TheoremEvery alignment weighs at most the max recursion#✓fully proved
Every alignment weighs at most the max recursion (nonnegative weights).
theorem alignWeight_le_maxDP [IsOrderedRing R] {M : AlignmentAutomaton Q α β R}
(hM : M.Nonneg) (q : Q) {xs : List α} {ys : List β} {A : List (Option α × Option β)}
(hA : A ∈ alignmentsOf xs ys) :
alignWeight M q A ≤ maxDP M q xs ys
structure AlignmentAutomaton (Q α β R : Type*) where
/-- The weight of reading a column in a control state. -/
weight : Q → Option α × Option β → R
/-- The control state after reading a column. -/
next : Q → Option α × Option β → Q
/-- The weight of ending in a control state. -/
final : Q → R
CSLibExt/Bioinformatics/HMM/PairHMM.lean:268
def alignmentsOf {α β : Type*} (xs : List α) (ys : List β) : List (List (Option α × Option β)) :=
alignmentsOfAux (xs.length + ys.length + 1) xs ys
CSLibExt/Bioinformatics/HMM/PairHMM.lean:110
def alignWeight : Q → List (Option α × Option β) → R
| q, [] => M.final q
| q, c :: A => M.weight q c * alignWeight (M.next q c) A
CSLibExt/Bioinformatics/HMM/PairHMM.lean:286
def maxDP (q : Q) (xs : List α) (ys : List β) : R :=
maxDPAux M (xs.length + ys.length + 1) q xs ys
CSLibExt/Bioinformatics/HMM/PairHMM.lean:378
Uses 7 · Used by 2
TheoremThe max recursion is attained#✓fully proved
The max recursion is attained by an alignment.
theorem exists_alignWeight_eq_maxDP (q : Q) (xs : List α) (ys : List β) :
∃ A ∈ alignmentsOf xs ys, alignWeight M q A = maxDP M q xs ys
def alignmentsOf {α β : Type*} (xs : List α) (ys : List β) : List (List (Option α × Option β)) :=
alignmentsOfAux (xs.length + ys.length + 1) xs ys
CSLibExt/Bioinformatics/HMM/PairHMM.lean:110
def alignWeight : Q → List (Option α × Option β) → R
| q, [] => M.final q
| q, c :: A => M.weight q c * alignWeight (M.next q c) A
CSLibExt/Bioinformatics/HMM/PairHMM.lean:286
def maxDP (q : Q) (xs : List α) (ys : List β) : R :=
maxDPAux M (xs.length + ys.length + 1) q xs ys
CSLibExt/Bioinformatics/HMM/PairHMM.lean:378
Uses 6 · Used by 2
TheoremMax recursion on two nonempty sequences#✓fully proved
The max recursion on two nonempty sequences.
theorem maxDP_cons_cons (q : Q) (a : α) (b : β) (xs : List α) (ys : List β) :
maxDP M q (a :: xs) (b :: ys) =
max (max (M.weight q (some a, some b) * maxDP M (M.next q (some a, some b)) xs ys)
(M.weight q (some a, none) * maxDP M (M.next q (some a, none)) xs (b :: ys)))
(M.weight q (none, some b) * maxDP M (M.next q (none, some b)) (a :: xs) ys)
def maxDP (q : Q) (xs : List α) (ys : List β) : R :=
maxDPAux M (xs.length + ys.length + 1) q xs ys
CSLibExt/Bioinformatics/HMM/PairHMM.lean:378
Uses 3
TheoremMax recursion with an empty first sequence#✓fully proved
The max recursion when the first sequence is empty.
theorem maxDP_nil_cons (q : Q) (b : β) (ys : List β) :
maxDP M q ([] : List α) (b :: ys) =
M.weight q (none, some b) * maxDP M (M.next q (none, some b)) [] ys
def maxDP (q : Q) (xs : List α) (ys : List β) : R :=
maxDPAux M (xs.length + ys.length + 1) q xs ys
CSLibExt/Bioinformatics/HMM/PairHMM.lean:378
Uses 3
TheoremMax recursion with an empty second sequence#✓fully proved
The max recursion when the second sequence is empty.
theorem maxDP_cons_nil (q : Q) (a : α) (xs : List α) :
maxDP M q (a :: xs) ([] : List β) =
M.weight q (some a, none) * maxDP M (M.next q (some a, none)) xs []
def maxDP (q : Q) (xs : List α) (ys : List β) : R :=
maxDPAux M (xs.length + ys.length + 1) q xs ys
CSLibExt/Bioinformatics/HMM/PairHMM.lean:378
Uses 3
TheoremMax recursion on two empty sequences is the final weight#✓fully proved
The max recursion on two empty sequences is the final weight.
theorem maxDP_nil_nil (q : Q) : maxDP M q ([] : List α) ([] : List β) = M.final q
def maxDP (q : Q) (xs : List α) (ys : List β) : R :=
maxDPAux M (xs.length + ys.length + 1) q xs ys
CSLibExt/Bioinformatics/HMM/PairHMM.lean:378
Uses 2
Pair HMMs
InductiveEmitting states of a pair HMM#✓fully proved
The emitting states of a pair HMM: M emits an aligned pair, X a letter of the first
sequence only, Y a letter of the second sequence only.
inductive PairState
/-- Emit an aligned pair `(a, b)`. -/
| M
/-- Emit a letter of the first sequence against a gap. -/
| X
/-- Emit a letter of the second sequence against a gap. -/
| Y
deriving DecidableEq, Repr
Used by 15
DefinitionPair HMM state emitting an alignment column#✓fully proved
The state that emits an alignment column: M for (some a, some b), X for
(some a, none), Y for (none, some b) (and M, unused, for the invalid (none, none)).
def colState {α : Type*} : Option α × Option α → PairState
| (some _, none) => .X
| (none, some _) => .Y
| _ => .M
inductive PairState
/-- Emit an aligned pair `(a, b)`. -/
| M
/-- Emit a letter of the first sequence against a gap. -/
| X
/-- Emit a letter of the second sequence against a gap. -/
| Y
deriving DecidableEq, Repr
CSLibExt/Bioinformatics/HMM/PairHMM.lean:520
Uses 1 · Used by 4
StructurePair hidden Markov model#✓fully proved
A pair HMM over the alphabet α with weights in R (Durbin et al., chapter 4): the
transition weights from the silent begin state (start) and between emitting states (trans),
to the silent end state (stop from an emitting state, startStop for the empty alignment),
and the emission weights of the three emitting states.
Cslib.Bioinformatics.HMM.PairHMM · 15 lines
structure PairHMM (α R : Type*) where
/-- The weight of the transition from the begin state to an emitting state. -/
start : PairState → R
/-- The weight of the transition from the begin state directly to the end state. -/
startStop : R
/-- The weight of a transition between emitting states (from the first to the second). -/
trans : PairState → PairState → R
/-- The weight of the transition from an emitting state to the end state. -/
stop : PairState → R
/-- The emission weight of an aligned pair from `M`. -/
emitM : α → α → R
/-- The emission weight of a letter of the first sequence from `X`. -/
emitX : α → R
/-- The emission weight of a letter of the second sequence from `Y`. -/
emitY : α → R
inductive PairState
/-- Emit an aligned pair `(a, b)`. -/
| M
/-- Emit a letter of the first sequence against a gap. -/
| X
/-- Emit a letter of the second sequence against a gap. -/
| Y
deriving DecidableEq, Repr
CSLibExt/Bioinformatics/HMM/PairHMM.lean:520
Uses 1 · Used by 14
DefinitionEmission weight of an alignment column#✓fully proved
The emission weight of an alignment column (0 for the invalid (none, none)).
def emitCol : Option α × Option α → R
| (some a, some b) => h.emitM a b
| (some a, none) => h.emitX a
| (none, some b) => h.emitY b
| (none, none) => 0
Uses 1 · Used by 4
DefinitionPair HMM as an alignment automaton#✓fully proved
The pair HMM as an alignment automaton: the control state is the previous HMM state
(none for the begin state).
def toAutomaton : AlignmentAutomaton (Option PairState) α α R where
weight q c := (match q with
| none => h.start (colState c)
| some s => h.trans s (colState c)) * h.emitCol c
next _ c := some (colState c)
final q := match q with
| none => h.startStop
| some s => h.stop s
structure AlignmentAutomaton (Q α β R : Type*) where
/-- The weight of reading a column in a control state. -/
weight : Q → Option α × Option β → R
/-- The control state after reading a column. -/
next : Q → Option α × Option β → Q
/-- The weight of ending in a control state. -/
final : Q → R
CSLibExt/Bioinformatics/HMM/PairHMM.lean:268
inductive PairState
/-- Emit an aligned pair `(a, b)`. -/
| M
/-- Emit a letter of the first sequence against a gap. -/
| X
/-- Emit a letter of the second sequence against a gap. -/
| Y
deriving DecidableEq, Repr
CSLibExt/Bioinformatics/HMM/PairHMM.lean:520
weight : Q → Option α × Option β → R
CSLibExt/Bioinformatics/HMM/PairHMM.lean:270
def colState {α : Type*} : Option α × Option α → PairState
| (some _, none) => .X
| (none, some _) => .Y
| _ => .M
CSLibExt/Bioinformatics/HMM/PairHMM.lean:531
next : Q → Option α × Option β → Q
CSLibExt/Bioinformatics/HMM/PairHMM.lean:272
final : Q → R
CSLibExt/Bioinformatics/HMM/PairHMM.lean:274
Uses 5 · Used by 9
DefinitionJoint weight of sequences and an alignment's state path#✓fully proved
The joint weight of the sequences and the state path of an alignment A (the path visits
colState c for each column c): the product of the transition and emission weights along the
path, from the begin state to the end state.
def alignProb (A : Alignment α) : R := h.toAutomaton.alignWeight none A
abbrev Alignment (α : Type*) := List (Option α × Option α)
CSLibExt/Algorithms/Lean/DynamicProgramming/SequenceAlignment.lean:69
Uses 5 · Used by 5
DefinitionTotal weight of a sequence pair under a pair HMM#✓fully proved
The total weight P(xs, ys) of a pair HMM: the total weight of all state paths that emit
xs and ys (likelihood_eq_sum), by the first-column recursion.
Uses 4 · Used by 1
TheoremThe pair-HMM recursion computes the total weight#✓fully proved
The sum over all alignments of
xs and ys of the joint weight of the sequences and the alignment.
theorem likelihood_eq_sum (xs ys : List α) :
h.likelihood xs ys = ((alignments xs ys).map h.alignProb).sum
def alignments (xs ys : List α) : List (Alignment α) :=
alignmentsAux (xs.length + ys.length + 1) xs ys
CSLibExt/Algorithms/Lean/DynamicProgramming/SequenceAlignment.lean:226
Uses 12
DefinitionViterbi value of a pair HMM#✓fully proved
The Viterbi value of a pair HMM: the max-recursion value for xs, ys. It is the
largest joint weight over alignments when the HMM weights are nonnegative
(see alignProb_le_viterbi).
Uses 4 · Used by 3
StructureNonnegative weights of a pair HMM#✓fully proved
Nonnegative transition weights into emitting states and nonnegative emission weights (the transitions into the end state may have any sign: the Viterbi bound does not need them).
structure Nonneg : Prop where
/-- Begin-state transitions are nonnegative. -/
start : ∀ s, 0 ≤ h.start s
/-- Transitions between emitting states are nonnegative. -/
trans : ∀ s t, 0 ≤ h.trans s t
/-- Match emissions are nonnegative. -/
emitM : ∀ a b, 0 ≤ h.emitM a b
/-- `X` emissions are nonnegative. -/
emitX : ∀ a, 0 ≤ h.emitX a
/-- `Y` emissions are nonnegative. -/
emitY : ∀ b, 0 ≤ h.emitY b
TheoremNonnegative pair HMM gives a nonnegative alignment automaton#✓fully proved
A pair HMM with nonnegative weights is a nonnegative alignment automaton.
theorem toAutomaton_nonneg [IsOrderedRing R] (hn : h.Nonneg) : h.toAutomaton.Nonneg
Uses 7 · Used by 1
TheoremEvery alignment weighs at most the Viterbi value#✓fully proved
Every alignment weighs at most the Viterbi value.
theorem alignProb_le_viterbi [IsOrderedRing R] (hn : h.Nonneg) {xs ys : List α} {A : Alignment α}
(hA : IsAlignment A xs ys) : h.alignProb A ≤ h.viterbi xs ys
abbrev Alignment (α : Type*) := List (Option α × Option α)
CSLibExt/Algorithms/Lean/DynamicProgramming/SequenceAlignment.lean:69
def IsAlignment (A : Alignment α) (xs ys : List α) : Prop :=
(∀ c ∈ A, c ≠ (none, none)) ∧ A.filterMap Prod.fst = xs ∧ A.filterMap Prod.snd = ys
CSLibExt/Algorithms/Lean/DynamicProgramming/SequenceAlignment.lean:73
Uses 14 · Used by 1
TheoremThe Viterbi value is attained#✓fully proved
The Viterbi value is attained by an alignment: the Viterbi alignment.
theorem exists_alignProb_eq_viterbi (xs ys : List α) :
∃ A, IsAlignment A xs ys ∧ h.alignProb A = h.viterbi xs ys
def IsAlignment (A : Alignment α) (xs ys : List α) : Prop :=
(∀ c ∈ A, c ≠ (none, none)) ∧ A.filterMap Prod.fst = xs ∧ A.filterMap Prod.snd = ys
CSLibExt/Algorithms/Lean/DynamicProgramming/SequenceAlignment.lean:73
Uses 14 · Used by 1
Log-odds scores and Needleman–Wunsch
StructureMemoryless pair HMM#✓fully proved
The pair HMM's transition weights do not depend on the current state: every transition into
an emitting state s (from the begin state or from any emitting state) has weight π s, and
every transition into the end state has weight τ.
structure IsMemoryless (h : PairHMM α ℝ) (π : PairState → ℝ) (τ : ℝ) : Prop where
/-- Begin-state transitions. -/
start : ∀ s, h.start s = π s
/-- Transitions between emitting states. -/
trans : ∀ s t, h.trans s t = π t
/-- Transitions to the end state from an emitting state. -/
stop : ∀ s, h.stop s = τ
/-- The begin-to-end transition. -/
startStop : h.startStop = τ
structure PairHMM (α R : Type*) where
/-- The weight of the transition from the begin state to an emitting state. -/
start : PairState → R
/-- The weight of the transition from the begin state directly to the end state. -/
startStop : R
/-- The weight of a transition between emitting states (from the first to the second). -/
trans : PairState → PairState → R
/-- The weight of the transition from an emitting state to the end state. -/
stop : PairState → R
/-- The emission weight of an aligned pair from `M`. -/
emitM : α → α → R
/-- The emission weight of a letter of the first sequence from `X`. -/
⋯
CSLibExt/Bioinformatics/HMM/PairHMM.lean:540
inductive PairState
/-- Emit an aligned pair `(a, b)`. -/
| M
/-- Emit a letter of the first sequence against a gap. -/
| X
/-- Emit a letter of the second sequence against a gap. -/
| Y
deriving DecidableEq, Repr
CSLibExt/Bioinformatics/HMM/PairHMM.lean:520
Uses 2 · Used by 3
DefinitionIndependence-model weight of a sequence pair#✓fully proved
The independence-model weight for xs and ys (Durbin et al., chapter 4):
η² (1 - η)^(|xs| + |ys|) ∏ q xs ∏ q ys. This is a probability when q is a
normalized nonnegative distribution and 0 < η < 1, as required by LinearGapLogOdds.
noncomputable def background (q : α → ℝ) (η : ℝ) (xs ys : List α) : ℝ :=
η ^ 2 * (1 - η) ^ (xs.length + ys.length) * (xs.map q).prod * (ys.map q).prod
Used by 2
StructureHypotheses of the linear-gap log-odds correspondence#✓fully proved
The hypotheses of the log-odds correspondence: a memoryless pair HMM with normalized
positive transition and emission probabilities, normalized positive background frequencies
and 0 < η < 1, whose per-column log-odds scores against the independence model are the
integer scores σ a b (aligned pair) and gap (gap column).
Cslib.Bioinformatics.HMM.PairHMM.LinearGapLogOdds · 37 lines
structure LinearGapLogOdds (h : PairHMM α ℝ) (π : PairState → ℝ) (τ : ℝ) (q : α → ℝ) (η : ℝ)
(σ : α → α → ℤ) (gap : ℤ) : Prop where
/-- The transition weights do not depend on the current state. -/
memoryless : h.IsMemoryless π τ
/-- The begin row and every emitting-state transition row sum to one. -/
transition_sum : π .M + π .X + π .Y + τ = 1
/-- The background frequencies sum to one over the finite alphabet. -/
q_sum : ∑ a, q a = 1
/-- The match emission probabilities sum to one. -/
emitM_sum : ∑ a, ∑ b, h.emitM a b = 1
/-- The `X` emission probabilities sum to one. -/
emitX_sum : ∑ a, h.emitX a = 1
/-- The `Y` emission probabilities sum to one. -/
emitY_sum : ∑ b, h.emitY b = 1
/-- Positive transition weights. -/
π_pos : ∀ s, 0 < π s
/-- A positive end transition. -/
τ_pos : 0 < τ
/-- Positive background frequencies. -/
q_pos : ∀ a, 0 < q a
/-- The background stopping probability is in `(0, 1)`. -/
η_pos : 0 < η
/-- The background stopping probability is in `(0, 1)`. -/
η_lt_one : η < 1
/-- Positive match emissions. -/
emitM_pos : ∀ a b, 0 < h.emitM a b
/-- Positive `X` emissions. -/
emitX_pos : ∀ a, 0 < h.emitX a
/-- Positive `Y` emissions. -/
emitY_pos : ∀ b, 0 < h.emitY b
/-- The log-odds score of an aligned pair is `σ a b`. -/
logOdds_M : ∀ a b,
Real.log (π .M * h.emitM a b / ((1 - η) ^ 2 * q a * q b)) = σ a b
/-- The log-odds score of a letter of the first sequence against a gap is `gap`. -/
logOdds_X : ∀ a, Real.log (π .X * h.emitX a / ((1 - η) * q a)) = gap
/-- The log-odds score of a letter of the second sequence against a gap is `gap`. -/
logOdds_Y : ∀ b, Real.log (π .Y * h.emitY b / ((1 - η) * q b)) = gap
structure PairHMM (α R : Type*) where
/-- The weight of the transition from the begin state to an emitting state. -/
start : PairState → R
/-- The weight of the transition from the begin state directly to the end state. -/
startStop : R
/-- The weight of a transition between emitting states (from the first to the second). -/
trans : PairState → PairState → R
/-- The weight of the transition from an emitting state to the end state. -/
stop : PairState → R
/-- The emission weight of an aligned pair from `M`. -/
emitM : α → α → R
/-- The emission weight of a letter of the first sequence from `X`. -/
⋯
CSLibExt/Bioinformatics/HMM/PairHMM.lean:540
inductive PairState
/-- Emit an aligned pair `(a, b)`. -/
| M
/-- Emit a letter of the first sequence against a gap. -/
| X
/-- Emit a letter of the second sequence against a gap. -/
| Y
deriving DecidableEq, Repr
CSLibExt/Bioinformatics/HMM/PairHMM.lean:520
Uses 3 · Used by 2
TheoremLog-odds of one alignment#✓fully proved
For a memoryless pair HMM, the log-odds of an alignment
against the independence model is its linear-gap alignment score plus log (τ / η²).
theorem log_alignProb_div_background {h : PairHMM α ℝ} {π : PairState → ℝ} {τ : ℝ}
{q : α → ℝ} {η : ℝ} {σ : α → α → ℤ} {gap : ℤ} (H : LinearGapLogOdds h π τ q η σ gap)
{xs ys : List α} {A : Alignment α} (hA : IsAlignment A xs ys) :
Real.log (h.alignProb A / background q η xs ys) =
alignmentScore σ gap A + Real.log (τ / η ^ 2)
structure PairHMM (α R : Type*) where
/-- The weight of the transition from the begin state to an emitting state. -/
start : PairState → R
/-- The weight of the transition from the begin state directly to the end state. -/
startStop : R
/-- The weight of a transition between emitting states (from the first to the second). -/
trans : PairState → PairState → R
/-- The weight of the transition from an emitting state to the end state. -/
stop : PairState → R
/-- The emission weight of an aligned pair from `M`. -/
emitM : α → α → R
/-- The emission weight of a letter of the first sequence from `X`. -/
⋯
CSLibExt/Bioinformatics/HMM/PairHMM.lean:540
inductive PairState
/-- Emit an aligned pair `(a, b)`. -/
| M
/-- Emit a letter of the first sequence against a gap. -/
| X
/-- Emit a letter of the second sequence against a gap. -/
| Y
deriving DecidableEq, Repr
CSLibExt/Bioinformatics/HMM/PairHMM.lean:520
structure LinearGapLogOdds (h : PairHMM α ℝ) (π : PairState → ℝ) (τ : ℝ) (q : α → ℝ) (η : ℝ)
(σ : α → α → ℤ) (gap : ℤ) : Prop where
/-- The transition weights do not depend on the current state. -/
memoryless : h.IsMemoryless π τ
/-- The begin row and every emitting-state transition row sum to one. -/
transition_sum : π .M + π .X + π .Y + τ = 1
/-- The background frequencies sum to one over the finite alphabet. -/
q_sum : ∑ a, q a = 1
/-- The match emission probabilities sum to one. -/
emitM_sum : ∑ a, ∑ b, h.emitM a b = 1
/-- The `X` emission probabilities sum to one. -/
emitX_sum : ∑ a, h.emitX a = 1
⋯
CSLibExt/Bioinformatics/HMM/PairHMM.lean:679
abbrev Alignment (α : Type*) := List (Option α × Option α)
CSLibExt/Algorithms/Lean/DynamicProgramming/SequenceAlignment.lean:69
def IsAlignment (A : Alignment α) (xs ys : List α) : Prop :=
(∀ c ∈ A, c ≠ (none, none)) ∧ A.filterMap Prod.fst = xs ∧ A.filterMap Prod.snd = ys
CSLibExt/Algorithms/Lean/DynamicProgramming/SequenceAlignment.lean:73
noncomputable def background (q : α → ℝ) (η : ℝ) (xs ys : List α) : ℝ :=
η ^ 2 * (1 - η) ^ (xs.length + ys.length) * (xs.map q).prod * (ys.map q).prod
CSLibExt/Bioinformatics/HMM/PairHMM.lean:670
def alignmentScore (σ : α → α → ℤ) (gap : ℤ) (A : Alignment α) : ℤ :=
(A.map (columnScore σ gap)).sum
CSLibExt/Algorithms/Lean/DynamicProgramming/SequenceAlignment.lean:84
Uses 15 · Used by 1
TheoremLog-odds Viterbi is linear-gap Needleman–Wunsch#✓fully proved
For a memoryless pair HMM whose
per-column log-odds scores are σ a b and gap, the log-odds Viterbi score against the
independence model is the Needleman–Wunsch score with substitution scores σ and linear gap
score gap, plus the length term log (τ / η²).
theorem log_viterbi_div_background {h : PairHMM α ℝ} {π : PairState → ℝ} {τ : ℝ}
{q : α → ℝ} {η : ℝ} {σ : α → α → ℤ} {gap : ℤ} (H : LinearGapLogOdds h π τ q η σ gap)
(xs ys : List α) :
Real.log (h.viterbi xs ys / background q η xs ys) =
nwScore σ gap xs ys + Real.log (τ / η ^ 2)
structure PairHMM (α R : Type*) where
/-- The weight of the transition from the begin state to an emitting state. -/
start : PairState → R
/-- The weight of the transition from the begin state directly to the end state. -/
startStop : R
/-- The weight of a transition between emitting states (from the first to the second). -/
trans : PairState → PairState → R
/-- The weight of the transition from an emitting state to the end state. -/
stop : PairState → R
/-- The emission weight of an aligned pair from `M`. -/
emitM : α → α → R
/-- The emission weight of a letter of the first sequence from `X`. -/
⋯
CSLibExt/Bioinformatics/HMM/PairHMM.lean:540
inductive PairState
/-- Emit an aligned pair `(a, b)`. -/
| M
/-- Emit a letter of the first sequence against a gap. -/
| X
/-- Emit a letter of the second sequence against a gap. -/
| Y
deriving DecidableEq, Repr
CSLibExt/Bioinformatics/HMM/PairHMM.lean:520
structure LinearGapLogOdds (h : PairHMM α ℝ) (π : PairState → ℝ) (τ : ℝ) (q : α → ℝ) (η : ℝ)
(σ : α → α → ℤ) (gap : ℤ) : Prop where
/-- The transition weights do not depend on the current state. -/
memoryless : h.IsMemoryless π τ
/-- The begin row and every emitting-state transition row sum to one. -/
transition_sum : π .M + π .X + π .Y + τ = 1
/-- The background frequencies sum to one over the finite alphabet. -/
q_sum : ∑ a, q a = 1
/-- The match emission probabilities sum to one. -/
emitM_sum : ∑ a, ∑ b, h.emitM a b = 1
/-- The `X` emission probabilities sum to one. -/
emitX_sum : ∑ a, h.emitX a = 1
⋯
CSLibExt/Bioinformatics/HMM/PairHMM.lean:679
noncomputable def background (q : α → ℝ) (η : ℝ) (xs ys : List α) : ℝ :=
η ^ 2 * (1 - η) ^ (xs.length + ys.length) * (xs.map q).prod * (ys.map q).prod
CSLibExt/Bioinformatics/HMM/PairHMM.lean:670
def nwScore (xs ys : List α) : ℤ := nwScoreAux σ gap (xs.length + ys.length) xs ys
CSLibExt/Algorithms/Lean/DynamicProgramming/SequenceAlignment.lean:128
Uses 23
Loading dependency explorer…
The dependency explorer needs JavaScript and its graph data.