sample#
Functions#
|
Draw one exact forward-simulation sample of the (possibly-augmented) |
|
The state-array indices (into |
|
Project a full state trajectory (shape |
|
Project a full state trajectory (shape |
|
Merge new delta=0 (instantaneous) test times into an existing sorted |
|
Build an extended kernel and a merged, sorted timeline for jointly |
|
Read out the prior sample at |
Module Contents#
- smolgp.solvers.sample.sample_prior_trajectory(kernel, state_coords: smolgp.solvers.state_coords.StateCoords, key: jax.random.KeyArray) tinygp.helpers.JAXArray[source]#
Draw one exact forward-simulation sample of the (possibly-augmented) latent state trajectory at every state in
state_coords.This is the “prior sampling” half of the residual/Matheron’s-rule conditional-sampling method (see
smolgp.gp.GaussianProcess.sample()): a pure forward SDE simulation using the sametransition_matrix/process_noise/stationary_covariance/reset_matrixthe Kalman filter itself uses, but with no Kalman gain/update logic.Mirrors
kalman_filter()’s own conventions exactly: the first state is drawn directly from the stationary distribution (matching that filter’sm0=zeros/P0=stationary_covariance()initialization) rather than via a transition from a nonexistent previous state, andreset_matrixis applied atstateid==0states exactly asintegrated_kalman_filter()’supdate_startdoes. For non-integrated kernels, pass the same “unified” fallback used elsewhere (StateCoords.instantaneous(), i.e.instid=zeros,obsid=arange(K),stateid=ones(K)) – sinceStateSpaceModel.reset_matrixdefaults to the identity, thestateid==0branch is then a harmless no-op.- Parameters:
kernel – The (possibly-augmented) state space model.
state_coords – a
StateCoords, as held bysolver.state_coords/ returned bysolver.condition().key – A
jaxrandom number key.
- Returns:
The sampled trajectory, shape
(K, kernel.dimension), in the same order asstate_coords.
- smolgp.solvers.sample.data_order_indices(state_coords: smolgp.solvers.state_coords.StateCoords, N: int) tinygp.helpers.JAXArray[source]#
The state-array indices (into
state_coords’ ownK-length arrays) of theNreal data points, sorted into data order (obsid0..N-1).Mirrors
smolgp.gp.ConditionedStates.project_at_data()’s select-stateid==1/sort-by-obsidlogic exactly.
- smolgp.solvers.sample.project_trajectory_at_positions(X: tinygp.helpers.JAXArray, positions: tinygp.helpers.JAXArray, x_traj: tinygp.helpers.JAXArray, observation_model) tinygp.helpers.JAXArray[source]#
Project a full state trajectory (shape
(K_total, dim)) at explicitpositionsinto it, applyingobservation_modelat the correspondingXcoordinates (X’s own leading dimension must matchpositions).
- smolgp.solvers.sample.project_trajectory_at_data(X: tinygp.helpers.JAXArray, state_coords: smolgp.solvers.state_coords.StateCoords, x_traj: tinygp.helpers.JAXArray, observation_model, N: int) tinygp.helpers.JAXArray[source]#
Project a full state trajectory (shape
(K, dim)) down to theNreal data points, in data order.For the non-integrated fallback
state_coords(stateidall1,obsid=arange(K)), this reduces to the identity permutation.
- smolgp.solvers.sample.merge_test_coords(state_coords: smolgp.solvers.state_coords.StateCoords, t_test: tinygp.helpers.JAXArray) tuple[smolgp.solvers.state_coords.StateCoords, tinygp.helpers.JAXArray, tinygp.helpers.JAXArray][source]#
Merge new delta=0 (instantaneous) test times into an existing sorted
state_coordstimeline, for a joint prior-trajectory sample covering both the original states and the new test points.Test points are inserted with
stateid=1(no reset) and a dummy in-boundsobsid=0(the reset branch is traced-but-discarded viajax.lax.condeven when unused, so it must not index out of bounds). Sorting uses the same(t, -stateid)tie-break conventionIntegratedStateSpaceSolveralready uses, so a test point exactly at an existing state’s time gets a zero-length transition to/from it and gets identically copied.- Parameters:
state_coords – the training timeline’s
StateCoords(Kstates).t_test – sortable test times to insert, length
M.
- Returns:
- the merged, sorted
StateCoords, withK+M states.
instidis passed through unchanged (lengthN): test points add new states, not new observations.- train_positions: length
K, the new position of each original state (in
state_coords’ own order) within the merged arrays.- test_positions: length
M, the new position of eacht_test[i] within the merged arrays.
- the merged, sorted
- Return type:
merged_state_coords
- smolgp.solvers.sample.merge_exposure_test_coords(kernel, state_coords, t_test, delta_test, instid_test, num_test_insts)[source]#
Build an extended kernel and a merged, sorted timeline for jointly sampling the prior at (possibly) exposure-integrated (
delta>0) test points. Generalizesmerge_test_coords()to include exposures.Each test window is simulated with a “virtual probe instrument”, the same idea
predict_exposure()uses for filtering (simulation needs less machinery, since a prior draw has no data/update step at all). Concretely:Probe dimensions.
kernel_extextendskernelbynum_test_insts + 1instruments. Test points sharing aninstid_testshare one probe dimension, exactly as repeated real exposures from one physical instrument already share onezslot, enabling overlapping test exposures to be simulated simultaneously with correct covariances.Two states per test point. A reset at
a_i = t_i - delta_i/2(stateid=0), and a readout atb_i = t_i + delta_i/2(stateid=1).One joint simulation. Running
sample_prior_trajectory()once over the merged timeline gives a single draw covering the real states and every probe, correctly correlated with each other and with any overlapping real observations (independent per-point simulations would not give).
Extending
num_instsleaves the dynamics of the originaln-dim block unchanged, so only the projection changes: usekernel_ext.observation_model(its extra probe columns are zero by construction) to match the extended trajectory’s dimension.- Parameters:
kernel – the original (non-extended) kernel.
state_coords – the training timeline’s
StateCoords(Kstates,instidof lengthN).t_test – exposure midpoints, length
M.delta_test – exposure widths (
0for instantaneous), lengthM.instid_test – length
M, which probe group (0..num_test_insts-1) each test point belongs to.num_test_insts – the number of distinct probe groups, i.e.
int(jnp.max(instid_test)) + 1. Must be a static Python int (concrete outside any enclosingjax.jit), since it determineskernel_ext’s dimension
- Returns:
- kernel with
num_instsextended bynum_test_insts + 1 (the
+1being the shared trash dimension).- merged_state_coords: the merged, sorted
StateCoords, with K + 2Mstates and aninstidof lengthN + M(each test point contributes one new probe “observation”).
train_positions: length
K, new position of each original state. b_positions: lengthM, new position of each test point’sb_i. probe_dims: lengthM, the state dimension to read each testpoint’s probe value from at
b_positions[i](equal across test points sharing aninstid_test).- kernel with
- Return type:
kernel_ext
- smolgp.solvers.sample.project_exposure_test_points(X_test: tinygp.helpers.JAXArray, kernel_ext, x_traj_ext: tinygp.helpers.JAXArray, b_positions: tinygp.helpers.JAXArray, probe_dims: tinygp.helpers.JAXArray, delta_test: tinygp.helpers.JAXArray) tinygp.helpers.JAXArray[source]#
Read out the prior sample at
M(possibly exposure-integrated) test points from a trajectory produced by simulating overmerge_exposure_test_coords()’s merged timeline.For
delta_test[i] == 0, uses the ordinarykernel_ext.observation_model-based readout atX_test[i](matchingproject_trajectory_at_positions()). Fordelta_test[i] > 0, readsx_traj_ext[b_positions[i], probe_dims[i]] / delta_test[i]directly – the simulation analog ofpredict_exposure()’sz_mean = m_final[probe_idx]readout. Both are computed for every point and combined withjnp.where(rather than a data-dependent partition, which JAX’s static shapes don’t allow); the discarded branch for each point is finite but otherwise meaningless.