Skip to content

Flexible Sampling

Advanced sampling patterns using SamplingSpec.

Different Grids per Function

Sample each quantity at optimal resolution:

import numpy as np
from gp4c import sample_prior, SamplingSpec

spec = SamplingSpec(
    x_f=np.linspace(0, 5, 100),   # Dense for function
    x_g=np.linspace(0, 5, 50),    # Coarse for integral
    x_h=np.linspace(0.1, 4.9, 80) # Avoid boundaries for derivative
)

result = sample_prior(spec, ell=0.5, n_samples=10)

This is efficient when you need different resolutions for different quantities.

Selective Sampling

Only sample what you need:

# Just the derivative
spec = SamplingSpec(x_h=x)
result = sample_prior(spec, ell=0.5, n_samples=5)

# Function and derivative, skip integral
spec = SamplingSpec(x_f=x, x_h=x)
result = sample_prior(spec, ell=0.5, n_samples=5)

# Function and second derivative
spec = SamplingSpec(x_f=x, x_u=x)
result = sample_prior(spec, ell=0.5, n_samples=5)

Skipping unused quantities improves performance.

Region-Specific Sampling

Sample different quantities in different regions:

# Fine function samples in region of interest
x_f_roi = np.linspace(1.0, 2.0, 200)

# Coarse derivative samples everywhere
x_h_coarse = np.linspace(0, 5, 50)

spec = SamplingSpec(x_f=x_f_roi, x_h=x_h_coarse)
result = sample_prior(spec, ell=0.3, n_samples=10)

Boundary Considerations

Derivatives can be unstable at boundaries:

# Exclude boundaries for derivative
x = np.linspace(0, 5, 100)
x_interior = x[5:-5]  # Drop 5 points on each side

spec = SamplingSpec(x_f=x, x_h=x_interior)
result = sample_prior(spec, ell=0.5, n_samples=5)

Tip

For stable derivative sampling, use interior points or increase length scale.

Posterior with Different Grids

Observe on one grid, predict on another:

from gp4c import sample_posterior, Observations

# Sparse observations
x_obs = np.array([0.5, 1.5, 2.5, 3.5, 4.5])
y_obs = np.sin(x_obs)
obs = Observations(x_f=x_obs, y_f=y_obs, noise_f=0.01)

# Dense predictions for different quantities
spec = SamplingSpec(
    x_f=np.linspace(0, 5, 200),    # Dense function
    x_h=np.linspace(0.2, 4.8, 100) # Dense derivative, interior points
)

result = sample_posterior(obs, spec, ell=1.0, n_samples=10)

Sampling Combinations

The API supports any subset of {f, g, h, u}. Common combinations:

# f only
spec = SamplingSpec(x_f=x)

# f + g (function and integral)
spec = SamplingSpec(x_f=x, x_g=x)

# f + h (function and first derivative)
spec = SamplingSpec(x_f=x, x_h=x)

# f + u (function and second derivative)
spec = SamplingSpec(x_f=x, x_u=x)

# h + u (first and second derivative, no function values)
spec = SamplingSpec(x_h=x, x_u=x)

# f + g + h (all three original quantities)
spec = SamplingSpec(x_f=x, x_g=x, x_h=x)

# f + h + u (function with both derivatives)
spec = SamplingSpec(x_f=x, x_h=x, x_u=x)

# f + g + h + u (all four quantities)
spec = SamplingSpec(x_f=x, x_g=x, x_h=x, x_u=x)

Each combination is tested and numerically stable.

Kernel support for u

Not all kernels support second derivative sampling. Requesting x_u with an unsupported kernel will raise an error:

Kernel Supports u?
'rbf' Yes
'matern52' Yes
'matern32' No
'periodic' Yes
'locally_periodic' Yes

Performance Tips

  1. Sample only what you need - Skip unused quantities
  2. Use coarser grids for integrals (they're smoother)
  3. Avoid very small length scales with derivatives
  4. Interior points for derivatives when possible

Next Steps