1function [W_red, state_map] = eliminate_immediate_matrix(W, sn, options)
2% [W_RED, STATE_MAP] = ELIMINATE_IMMEDIATE_MATRIX(W, SN, OPTIONS)
4% Eliminate immediate states from infinitesimal generator matrix W
7% W: [n_states x n_states] infinitesimal generator matrix
9% options: Solver options
12% W_red: Reduced generator matrix
13% state_map: Mapping from reduced to original state indices
15% Copyright (c) 2012-2026, Imperial College London
18% Get immediate detection threshold
19if isfield(options.config,
'immediate_tol')
20 imm_tol = options.config.immediate_tol;
22 imm_tol = GlobalConstants.Immediate / 10; % Default: 1e7
25% Identify immediate states (those with very high outgoing rates)
26max_rate_per_state = max(abs(W), [], 2);
27imm_states = find(max_rate_per_state >= imm_tol);
29% If no immediate states, return unchanged
32 state_map = 1:size(W, 1);
36% Identify timed states
37timed_states = setdiff(1:size(W,1), imm_states);
39% Check that we have enough timed states remaining
40if isempty(timed_states) || length(timed_states) <= 1
41 % Too few timed states - elimination would produce a trivial system.
42 % Fall back to the original system without elimination.
44 state_map = 1:size(W, 1);
49 % Apply stochastic complement
50 [W_red, ~, ~, ~, Q22, ~] = ctmc_stochcomp(W, timed_states);
53 if rcond(full(Q22)) < 1e-12
54 warning('LINE:Fluid:IllConditioned', ...
55 'Immediate transition matrix ill-conditioned (rcond = %g)', rcond(full(Q22)));
58 state_map = timed_states;
61 if isfield(options, 'verbose') && options.verbose > 0
62 reduction_pct = 100 * (1 - length(timed_states)/size(W,1));
63 line_printf(sprintf('State space reduced from %d to %d states (%.1f%% reduction)\n', ...
64 size(W,1), length(timed_states), reduction_pct));
68 % Elimination failed - fall back to original
69 warning('LINE:Fluid:EliminationFailed', ...
70 'Immediate transition elimination failed: %s. Using original system.', ME.message);
72 state_map = 1:size(W, 1);
75end % eliminate_immediate_matrix