@abc.abstractmethod<EOL><INDENT>def M(self, t, tips=None, gaps=None):<DEDENT>
pass<EOL>
Matrix exponential `M(mu * t) = exp(mu * t * P)`.

        If we are considering branch to tip node, you can use
        `tips` and `gaps` to get only the column needed for
        likelihood calculation. This is computationally cheaper.

        Args:
            `t` (float > 0)
                The branch length.
            `tips` (`None` or `numpy.ndarray` of `int`, length `nsites`)
                If `None`, return the full matrix exponential.
                Otherwise, should be an array with element `r`
                giving the codon at tip node `r` (just put 0
                if codon is a gap and see `gaps` below).
            `gaps` (`None` or `numpy.ndarray` of `int`)
                Only meaningful if using `tips`. In this case,
                array should list `r` for all sites where tip
                node codon is a gap. `None` is equivalent to
                no gaps (also can be empty array).

        Returns:
            `M` (`numpy.ndarray` of floats)
                If not using `tips`, shape is `(nsites, N_CODON, N_CODON)`
                    with `M(t)[r][x][y]` probability `r` changes from `x`
                    to `y` in time `t`.
                If using `tips`, shape is `(nsites, N_CODON)` with
                    `M(t)[r][x] probability r changes from `x` to `tips[r]`
                    in time `t`. If `r` is in `gap`, then `M(t)[r][x]` is
                    one.