Qu

particle_filter

Builtin index · Statistics & ML

result = particle_filter(n_particles, initial_state, [process_noise=0.05], [obs_noise=1.0], [spread=1.0], [seed=])

Input: n_particles, initial_state, process_noise, obs_noise, spread, seed · Output: result

What it is

The specialized constant-velocity tracker: n_particles (integer), initial_state (a length-D position/velocity vector), process_noise/obs_noise (numbers, the built-in noise levels — no Q/R argument needed at predict/update time), spread (number, initial scatter), and an optional integer seed=.

Overloads

One call shape — this function is not overloaded.

CodeInputOutputDescription
result = particle_filter(n_particles, initial_state, [process_noise=0.05], [obs_noise=1.0], [spread=1.0], [seed=])
n_particles vector or numbernot documented yet
initial_state vector or numbernot documented yet
process_noise vector or number, optional (default 0.05)not documented yet
obs_noise vector or number, optional (default 1.0)not documented yet
spread vector or number, optional (default 1.0)not documented yet
seed vector or number, optionalnot documented yet
result Record
Returns a kind="particle_tracker" state Record whose predict step is a single matmul across all particles, so it can go to the GPU.

Examples

From the documentation, and run by the build -- the output and the figure below are what the engine actually produced. Simplest first.

pf = particle_filter(50000, [0, 0], process_noise=0.08, obs_noise=0.4, spread=2.0, seed=3)
for k = 0 to N - 1
    pf = pf.move(dt)
    pf = pf.update([measured[k]])
end for

from tour

How it works

particle_filter(n_particles, initial_state, [process_noise=], [obs_noise=], [spread=1.0], [seed=]) — a SEPARATE, more specialized filter than particle_filter_init just above: that one is fully generic (arbitrary user-defined transition/ likelihood functions, any state layout); this one hardcodes a constant-velocity position/velocity motion model specifically so its predict step is a single matrix multiply — n independent, identical per-particle updates — and can therefore be GPU-dispatched (see particle_tracker_advance's own doc comment for the real, measured GPU-vs-CPU crossover). initial_state must have an EVEN length d = 2*half: the first half entries are position components, the last half are the matching velocity components (e.g. [x, vx] for 1-D tracking, [x, y, vx, vy] for 2-D). Model kind "particle_tracker" — kept distinct from the generic filter's "particle_filter" kind so this filter's own .predict(dt)/.move(dt)/.update(observation)/ .estimate() contract (fixed motion/observation models, no function names) never collides with the generic filter's function-name-based one above. process_noise/obs_noise are stored ON the returned model (unlike the generic filter, which takes Q/R fresh on every call) so .predict(dt)/ .update(z) need only the time-varying argument.

From the note above this builtin in the interpreter, where the reasoning was written down as it was built.