def backward_sampling_qmc(self, M): """QMC version of backward sampling. Parameters ---------- M : int number of trajectories Note ---- Use this only on the history of a SQMC algorithm. """ self._check_h_orders() u = qmc.sobol(M, self.T) # the final particles have not been sorted hT = hilbert.hilbert_sort(self.X[-1]) # searchsorted to avoid having to sort in place u according to u[:,T-1] idx = np.searchsorted(np.cumsum(self.wgts[-1].W[hT]), u[:, -1]) paths = [ self.X[-1][hT][idx], ] for t in reversed(range(self.T - 1)): idx = np.empty(M, 'int') for m, xn in enumerate(paths[-1]): lwm = self.wgts[t].lw + self.fk.logpt(t + 1, self.X[t], xn) # use ordered version here cw = np.cumsum(rs.exp_and_normalise(lwm[self.h_orders[t]])) idx[m] = np.searchsorted(cw, u[m, t]) paths.append(self.X[t][self.h_orders[t]][idx]) paths.reverse() return paths
def resample_move_qmc(self): self.rs_flag = True # we *always* resample in SQMC u = qmc.sobol(self.N, self.fk.du + 1) tau = np.argsort(u[:, 0]) self.h_order = hilbert.hilbert_sort(self.X) self.A = self.h_order[rs.inverse_cdf(u[tau, 0], self.aux.W[self.h_order])] self.Xp = self.X[self.A] v = u[tau, 1:].squeeze() # v is (N,) if du=1, (N,d) otherwise self.X = self.fk.Gamma(self.t, self.Xp, v) self.reset_weights()