Example #1
0
    def __init__(self, scipy_solution: OdeSolution, rvs: list):
        self.scipy_solution = scipy_solution

        # rvs is of the type `list` of `RandomVariable` and can therefore be
        # directly transformed into a _RandomVariableList
        rv_states = randvars._RandomVariableList(rvs)
        super().__init__(locations=scipy_solution.ts, states=rv_states)
Example #2
0
    def test_inputs(self):
        """Inputs rejected or accepted according to expected types."""
        numpy_array = np.ones(3) * Constant(0.1)
        constant_list = [Constant(0.1), Constant(0.4)]
        number_list = [0.5, 0.41]
        inputs = [numpy_array, constant_list, number_list]
        inputs_acceptable = [False, True, False]

        for inputs, is_acceptable in zip(inputs, inputs_acceptable):
            with self.subTest(input=inputs, is_acceptable=is_acceptable):

                if is_acceptable:
                    _RandomVariableList(inputs)
                else:
                    with self.assertRaises(TypeError):
                        _RandomVariableList(inputs)
Example #3
0
    def __init__(self, kalman_posterior: filtsmooth.gaussian.KalmanPosterior):
        self.kalman_posterior = kalman_posterior

        # Pre-compute projection matrices.
        # The prior must be an integrator, if not, an error is thrown in 'ODEFilter'.
        self.proj_to_y = self.kalman_posterior.transition.proj2coord(coord=0)
        self.proj_to_dy = self.kalman_posterior.transition.proj2coord(coord=1)

        states = randvars._RandomVariableList(
            [_project_rv(self.proj_to_y, rv) for rv in self.kalman_posterior.states]
        )
        derivatives = randvars._RandomVariableList(
            [_project_rv(self.proj_to_dy, rv) for rv in self.kalman_posterior.states]
        )
        super().__init__(
            locations=kalman_posterior.locations, states=states, derivatives=derivatives
        )
Example #4
0
 def __init__(
     self,
     locations: np.ndarray,
     states: randvars._RandomVariableList,
     derivatives: Optional[randvars._RandomVariableList] = None,
 ):
     super().__init__(locations=locations, states=states)
     self.derivatives = (
         randvars._RandomVariableList(derivatives)
         if derivatives is not None
         else None
     )
Example #5
0
    def smooth_list(self,
                    rv_list,
                    locations,
                    _diffusion_list,
                    _previous_posterior=None):
        """Apply smoothing to a list of random variables, according to the present
        transition.

        Parameters
        ----------
        rv_list : randvars._RandomVariableList
            List of random variables to be smoothed.
        locations :
            Locations :math:`t` of the random variables in the time-domain. Used for
            continuous-time transitions.
        _diffusion_list :
            List of diffusions that correspond to the intervals in the locations.
            If `locations=(t0, ..., tN)`, then `_diffusion_list=(d1, ..., dN)`, i.e. it
            contains one element less.
        _previous_posterior :
            Specify a previous posterior to improve linearisation in approximate
            backward passes. Used in iterated smoothing based on posterior
            linearisation.

        Returns
        -------
        randvars._RandomVariableList
            List of smoothed random variables.
        """

        final_rv = rv_list[-1]
        curr_rv = final_rv
        out_rvs = [curr_rv]
        for idx in reversed(range(1, len(locations))):
            unsmoothed_rv = rv_list[idx - 1]

            _linearise_smooth_step_at = (None if _previous_posterior is None
                                         else _previous_posterior(
                                             locations[idx - 1]))
            squared_diffusion = _diffusion_list[idx - 1]

            # Actual smoothing step
            curr_rv, _ = self.backward_rv(
                curr_rv,
                unsmoothed_rv,
                t=locations[idx - 1],
                dt=locations[idx] - locations[idx - 1],
                _diffusion=squared_diffusion,
                _linearise_at=_linearise_smooth_step_at,
            )
            out_rvs.append(curr_rv)
        out_rvs.reverse()
        return randvars._RandomVariableList(out_rvs)
Example #6
0
    def __call__(self, t: DenseOutputLocationArgType) -> DenseOutputValueType:
        """Evaluate the time-continuous solution at time t.

        Parameters
        ----------
        t
        Location / time at which to evaluate the continuous ODE solution.

        Returns
        -------
        randvars.RandomVariable or randvars._RandomVariableList
            Estimate of the states at time ``t`` based on a fourth order polynomial.
        """

        states = self.scipy_solution(t).T
        if np.isscalar(t):
            solution_as_rv = randvars.Constant(states)
        else:
            solution_as_rv = randvars._RandomVariableList(
                [randvars.Constant(state) for state in states])
        return solution_as_rv
Example #7
0
 def setUp(self):
     self.rv_list = _RandomVariableList([Constant(0.1), Constant(0.2)])
Example #8
0
 def setUp(self):
     self.rv_list = _RandomVariableList([])
    def __call__(self, t: DenseOutputLocationArgType) -> DenseOutputValueType:
        """Evaluate the time-continuous posterior at location `t`

        Algorithm:
        1. Find closest t_prev and t_next, with t_prev < t < t_next
        2. Predict from t_prev to t
        3. (if `self._with_smoothing=True`) Predict from t to t_next
        4. (if `self._with_smoothing=True`) Smooth from t_next to t
        5. Return random variable for time t

        Parameters
        ----------
        t :
            Location, or time, at which to evaluate the posterior.

        Returns
        -------
        randvars.RandomVariable or randvars._RandomVariableList
            Estimate of the states at time ``t``.
        """
        # The variable "squeeze_eventually" indicates whether
        # the dimension of the time-array has been promoted
        # (which is there for a well-behaved loop).
        # If this has been the case, the final result needs to be
        # reshaped ("squeezed") accordingly.
        if np.isscalar(t):
            t = np.atleast_1d(t)
            t_has_been_promoted = True
        else:
            t_has_been_promoted = False

        if not np.all(np.diff(t) >= 0.0):
            raise ValueError("Time-points have to be sorted.")

        # Split left-extrapolation, interpolation, right_extrapolation
        t0, tmax = np.amin(self.locations), np.amax(self.locations)
        t_extra_left = t[t < t0]
        t_extra_right = t[t > tmax]
        t_inter = t[(t0 <= t) & (t <= tmax)]

        # Indices of t where they would be inserted
        # into self.locations ("left": right-closest states -- this is the default in searchsorted)
        indices = np.searchsorted(self.locations, t_inter, side="left")
        interpolated_values = [
            self.interpolate(
                t=ti,
                previous_index=previdx,
                next_index=nextidx,
            ) for ti, previdx, nextidx in zip(
                t_inter,
                indices - 1,
                indices,
            )
        ]
        extrapolated_values_left = [
            self.interpolate(t=ti, previous_index=None, next_index=0)
            for ti in t_extra_left
        ]

        extrapolated_values_right = [
            self.interpolate(t=ti, previous_index=-1, next_index=None)
            for ti in t_extra_right
        ]
        dense_output_values = extrapolated_values_left
        dense_output_values.extend(interpolated_values)
        dense_output_values.extend(extrapolated_values_right)

        if t_has_been_promoted:
            return dense_output_values[0]
        return randvars._RandomVariableList(dense_output_values)
Example #10
0
 def states(self):
     return randvars._RandomVariableList(self._states)
Example #11
0
 def states(self):
     """States of the posterior."""
     return randvars._RandomVariableList(self._states)