def interpolate(ts, xs, t, equidistant, mode=0): if interp1d is not None: if mode == 0: mode_str = 'linear' elif mode == 1: mode_str = 'floor' else: mode_str = 'ceil' return interp1d(ts, xs, t, mode_str, equidistant) else: if mode == 1: xs = xs[:-1] # block-forward else: xs = xs[1:] # block-backward t = ca.MX(t) if t.size1() > 1: t_ = ca.MX.sym('t') xs_ = ca.MX.sym('xs', xs.size1()) f = ca.Function('interpolant', [t_, xs_], [ ca.mtimes(ca.transpose((t_ >= ts[:-1]) * (t_ < ts[1:])), xs_) ]) f = f.map(t.size1(), 'serial') return ca.transpose(f(ca.transpose(t), ca.repmat(xs, 1, t.size1()))) else: return ca.mtimes(ca.transpose((t >= ts[:-1]) * (t < ts[1:])), xs)
def interp(x, xp, fp, left=None, right=None, period=None): """ One-dimensional linear interpolation, analogous to numpy.interp(). Returns the one-dimensional piecewise linear interpolant to a function with given discrete data points (xp, fp), evaluated at x. See syntax here: https://numpy.org/doc/stable/reference/generated/numpy.interp.html Specific notes: xp is assumed to be sorted. """ if not is_casadi_type([x, xp, fp], recursive=True): return _onp.interp(x=x, xp=xp, fp=fp, left=left, right=right, period=period) else: ### If xp or x are CasADi types, this is unsupported :( if is_casadi_type([x, xp], recursive=True): raise NotImplementedError( "Unfortunately, CasADi doesn't yet support a dispatch for x or xp as CasADi types." ) ### Handle period argument if period is not None: if any(logical_or(xp < 0, xp > period)): raise NotImplementedError( "Haven't yet implemented handling for if xp is outside the period." ) # Not easy to implement because casadi doesn't have a sort feature. x = _cas.mod(x, period) ### Make sure x isn't an int if isinstance(x, int): x = float(x) ### Make sure that x is an iterable try: x[0] except TypeError: x = array([x], dtype=float) ### Make sure xp is an iterable xp = array(xp, dtype=float) ### Do the interpolation f = _cas.interp1d(xp, fp, x) ### Handle left/right if left is not None: f = where(x < xp[0], left, f) if right is not None: f = where(x > xp[-1], right, f) ### Return return f
def create_objective(self, model): self.obj_1 = sum( w / len(ov) * ca.sumsqr(self.densities * (ov - cm @ ca.interp1d( model.observation_times, om(model.observation_times, model.ps, * (model.xs[j] for j in oj)), self.observation_times))) for om, oj, ov, w, cm in zip( self.observation_model, self.observation_vector, self.observations, self.weightings, self.collocation_matrices)) self.obj_2 = sum( ca.sumsqr((model.xdash[:, i] - model.model( model.observation_times, *model.cs, *model.ps)[:, i])) for i in range(model.s)) / model.n self.regularisation = ca.sumsqr( (ca.vcat(model.ps) - ca.vcat(self.regularisation_vector)) / (1 + ca.vcat(self.regularisation_vector))) self.objective = self.obj_1 + self.rho * self.obj_2 + self.alpha * self.regularisation