Models
Coming soon.
Discrete state models
Codon models
Continuous models
Compound models
Lazy models
LazyPartition
MolecularEvolution.LazyPartition
— TypeConstructor
LazyPartition{PType}()
Initialize an empty LazyPartition
that is meant for wrapping a partition of type PType
.
Description
With this data structure, you can wrap a partition of choice. The idea is that in some message passing algorithms, there is only a wave of partitions which need to actualize. For instance, a wave following a root-leaf path, or a depth-first traversal. In which case, we can be more economical with our memory consumption. With a worst case memory complexity of O(log(n)), where n is the number of nodes, functionality is provided for:
log_likelihood!
felsenstein!
sample_down!
For successive felsenstein!
calls, we need to extract the information at the root somehow after each call. This can be done with e.g. total_LL
or site_LLs
.
Further requirements
Suppose you want to wrap a partition of PType
with LazyPartition
:
- If you're calling
log_likelihood!
andfelsenstein!
:obs2partition!(partition::PType, obs)
that transforms an observation to a partition.
- If you're calling
sample_down!
:partition2obs(partition::PType)
that returns the most likely state from a partition, invertsobs2partition!
.
Examples
Example 1: Initializing for an upward pass
Now, we show how to wrap the CodonPartition
s from Example 3: FUBAR with LazyPartition
:
You simply go from initializing messages like this:
initial_partition = CodonPartition(Int64(length(seqs[1])/3))
initial_partition.state .= eq_freqs
populate_tree!(tree,initial_partition,seqnames,seqs)
To this
initial_partition = CodonPartition(Int64(length(seqs[1])/3))
initial_partition.state .= eq_freqs
lazy_initial_partition = LazyPartition{CodonPartition}()
populate_tree!(tree,lazy_initial_partition,seqnames,seqs)
lazyprep!(tree, initial_partition)
By this slight modification, we go from initializing and using 554 partitions to 6 during the subsequent log_likelihood!
and felsenstein!
calls. There is no significant decrease in performance recorded from this switch.
Example 2: Initializing for a downward pass
Now, we show how to wrap the GaussianPartition
s from Quick example: Likelihood calculations under phylogenetic Brownian motion: with LazyPartition
:
You simply go from initializing messages like this:
internal_message_init!(tree, GaussianPartition())
To this (technically we only add 1 LOC)
initial_partition = GaussianPartition()
lazy_initial_partition = LazyPartition{GaussianPartition}()
internal_message_init!(tree, lazy_initial_partition)
lazyprep!(tree, initial_partition, direction=LazyDown(isleafnode))
Now, we provided a direction for lazyprep!
. The direction is an instance of LazyDown
, which was initialized with the isleafnode
function. The function isleafnode
dictates if a node saves its sampled observation after a down pass. If you use direction=LazyDown()
, every node saves its observation.
Surrounding LazyPartition
MolecularEvolution.lazyprep!
— Functionlazyprep!(tree::FelNode, initial_message::Vector{<:Partition}; partition_list = 1:length(tree.message), direction::LazyDirection = LazyUp())
Extra, intermediate step of tree preparations between initializing messages across the tree and calling message passing algorithms with LazyPartition
.
- Perform a
lazysort!
on tree to obtain the optimal tree for a lazyfelsenstein!
prop, or asample_down!
. - Fix
tree.parent_message
to an initial message. - Preallocate sufficiently many inner partitions needed for a
felsenstein!
prop, or asample_down!
. - Specialized preparations based on the direction of the operations (
forward!
,backward!
).LazyDown
orLazyUp
.
See also LazyDown
, LazyUp
.
MolecularEvolution.LazyUp
— TypeConstructor
LazyUp()
Description
Indicate that we want to do an upward pass, e.g. felsenstein!
.
MolecularEvolution.LazyDown
— TypeConstructors
LazyDown(stores_obs)
LazyDown() = LazyDown(x::FelNode -> true)
Description
Indicate that we want to do a downward pass, e.g. sample_down!
. The function passed to the constructor takes a node::FelNode
as input and returns a Bool
that decides if node
stores its observations.