aspartik.b3.likelihoods

Felsenstein's tree likelihood calculators.

class Likelihood:

class Likelihood(Stateful, Protocol):
    """
    Tree likelihood calculator

    This object calculates the likelihood of a tree given the sequence data
    using Felsenstein's tree pruning algorithm.

    There are several implementations, each with its own options.
    """

    def propose(self) -> None:
        """
        Fetches the current model state and starts the calculations.

        Each implementations are responsible for pulling the state.

        Depending on the implementation, `propose` might start the calculation
        in parallel and return.  In this case `likelihood` will block on it.
        """
        ...

    def likelihood(self) -> float:
        """
        Returns the tree likelihood calculated.

        If `propose` was called during this epoch, this must the likelihood as
        a result of the proposal.  If `accept` or `reject` was called last,
        this method must return the last accepted likelihood.
        """
        ...
#

Tree likelihood calculator

This object calculates the likelihood of a tree given the sequence data using Felsenstein's tree pruning algorithm.

There are several implementations, each with its own options.

def propose(self) -> None

    def propose(self) -> None:
        """
        Fetches the current model state and starts the calculations.

        Each implementations are responsible for pulling the state.

        Depending on the implementation, `propose` might start the calculation
        in parallel and return.  In this case `likelihood` will block on it.
        """
        ...
#

Fetches the current model state and starts the calculations.

Each implementations are responsible for pulling the state.

Depending on the implementation, propose might start the calculation in parallel and return. In this case likelihood will block on it.

def likelihood(self) -> float

    def likelihood(self) -> float:
        """
        Returns the tree likelihood calculated.

        If `propose` was called during this epoch, this must the likelihood as
        a result of the proposal.  If `accept` or `reject` was called last,
        this method must return the last accepted likelihood.
        """
        ...
#

Returns the tree likelihood calculated.

If propose was called during this epoch, this must the likelihood as a result of the proposal. If accept or reject was called last, this method must return the last accepted likelihood.

def accept(self) -> None

    def accept(self) -> None:
        """Accept changes made during the current step"""
#

Accept changes made during the current step

def reject(self) -> None

    def reject(self) -> None:
        """Reject changes made during the current step

        This method must roll the state of the object back to how it was at the
        beginning of the MCMC step.
        """
#

Reject changes made during the current step

This method must roll the state of the object back to how it was at the beginning of the MCMC step.

class CompoundLikelihood:

@dataclass(slots=True)
class CompoundLikelihood(Likelihood):
    """
    Combines several likelihoods.

    `CompoundLikelihood` doesn't use a thread pool, but depending on the
    `Likelihood` implementers, calculations might be done in parallel.
    """

    likelihoods: list[Likelihood]

    def propose(self) -> None:
        for likelihood in self.likelihoods:
            likelihood.propose()

    def likelihood(self) -> float:
        return sum(l.likelihood() for l in self.likelihoods)

    def accept(self) -> None:
        for likelihood in self.likelihoods:
            likelihood.accept()

    def reject(self) -> None:
        for likelihood in self.likelihoods:
            likelihood.reject()
#

Combines several likelihoods.

CompoundLikelihood doesn't use a thread pool, but depending on the Likelihood implementers, calculations might be done in parallel.

likelihoods: list

#

def propose(self) -> None

    def propose(self) -> None:
        for likelihood in self.likelihoods:
            likelihood.propose()
#

Fetches the current model state and starts the calculations.

Each implementations are responsible for pulling the state.

Depending on the implementation, propose might start the calculation in parallel and return. In this case likelihood will block on it.

def likelihood(self) -> float

    def likelihood(self) -> float:
        return sum(l.likelihood() for l in self.likelihoods)
#

Returns the tree likelihood calculated.

If propose was called during this epoch, this must the likelihood as a result of the proposal. If accept or reject was called last, this method must return the last accepted likelihood.

def accept(self) -> None

    def accept(self) -> None:
        for likelihood in self.likelihoods:
            likelihood.accept()
#

Accept changes made during the current step

def reject(self) -> None

    def reject(self) -> None:
        for likelihood in self.likelihoods:
            likelihood.reject()
#

Reject changes made during the current step

This method must roll the state of the object back to how it was at the beginning of the MCMC step.

class WeightedLikelihood:

@dataclass(slots=True)
class WeightedLikelihood(Likelihood):
    """
    Combines several likelihoods with dynamic weights.

    The formula is `Σ l_i * w_i`.  It is inspired [GHOST] and can be used to
    analyse several sequence evolution models.  Much like `CompoundLikelihood`,
    most likelihood implementations will be

    [GHOST]: https://doi.org/10.1093/sysbio/syz051
    """

    likelihoods: list[Likelihood]
    weights: Weights

    def propose(self) -> None:
        for likelihood in self.likelihoods:
            likelihood.propose()

    def likelihood(self) -> float:
        out = 0
        for likelihood, weight in zip(self.likelihoods, self.weights):
            out += likelihood.likelihood() * weight
        return out

    def accept(self) -> None:
        for likelihood in self.likelihoods:
            likelihood.accept()

    def reject(self) -> None:
        for likelihood in self.likelihoods:
            likelihood.reject()
#

Combines several likelihoods with dynamic weights.

The formula is Σ l_i * w_i. It is inspired GHOST and can be used to analyse several sequence evolution models. Much like CompoundLikelihood, most likelihood implementations will be

likelihoods: list

#

weights: aspartik.b3.parameters.Weights

#

def propose(self) -> None

    def propose(self) -> None:
        for likelihood in self.likelihoods:
            likelihood.propose()
#

Fetches the current model state and starts the calculations.

Each implementations are responsible for pulling the state.

Depending on the implementation, propose might start the calculation in parallel and return. In this case likelihood will block on it.

def likelihood(self) -> float

    def likelihood(self) -> float:
        out = 0
        for likelihood, weight in zip(self.likelihoods, self.weights):
            out += likelihood.likelihood() * weight
        return out
#

Returns the tree likelihood calculated.

If propose was called during this epoch, this must the likelihood as a result of the proposal. If accept or reject was called last, this method must return the last accepted likelihood.

def accept(self) -> None

    def accept(self) -> None:
        for likelihood in self.likelihoods:
            likelihood.accept()
#

Accept changes made during the current step

def reject(self) -> None

    def reject(self) -> None:
        for likelihood in self.likelihoods:
            likelihood.reject()
#

Reject changes made during the current step

This method must roll the state of the object back to how it was at the beginning of the MCMC step.

class CPU4Likelihood:

#

4-state DNA likelihood calculator.

It's synchronous. CUDALikelihood should be used for parallel calculations for alingments larger than 100Kb.

def propose(self, /)

#

def likelihood(self, /)

#

def accept(self, /)

#

def reject(self, /)

#

class CUDALikelihood:

#

Likelihood calculations on NVIDIA graphics cards.

Only supports 4-state DNA models. cuda_device allows selecting the device index.

def propose(self, /)

#

def likelihood(self, /)

#

def accept(self, /)

#

def reject(self, /)

#

class Parallel4Likelihood:

#

def propose(self, /)

#

def likelihood(self, /)

#

def accept(self, /)

#

def reject(self, /)

#