LINE Solver
MATLAB API documentation
Loading...
Searching...
No Matches
rap_sample.m
1function sample = rap_sample(RAP, n)
2% SAMPLE = RAP_SAMPLE(RAP, N) - Generate a correlated sample path from a RAP
3%
4% Generate N successive inter-event times along one sample path of a
5% Rational Arrival Process. A RAP has no underlying Markov chain over the
6% phases to walk, so the sampler carries the conditional phase vector V
7% across events instead of a phase index.
8%
9% Input:
10% RAP: RAP distribution as either:
11% - RAP object
12% - Process cell array {H0, H1}
13% N: Number of samples to generate (default: 1)
14%
15% Output:
16% SAMPLE: Column vector of N inter-event times along a single sample path
17%
18% Algorithm:
19% Let V be a row vector with V*e = 1, initialized to the arrival-embedded
20% equilibrium vector map_pie. For each draw:
21% 1. Draw U ~ Uniform(0,1) and solve the conditional survival equation
22% S(X) = V*expm(H0*X)*e = 1-U for X, by bracket expansion followed by
23% safeguarded Newton iteration. S is monotone decreasing from 1 to 0,
24% and its derivative is S'(X) = V*expm(H0*X)*H0*e, so the conditional
25% density is -S'(X) = V*expm(H0*X)*H1*e.
26% 2. Update V <- V*expm(H0*X)*H1 / (V*expm(H0*X)*H1*e).
27%
28% Step 2 is what reproduces the autocorrelation of the process. Sampling
29% from the ME marginal alone (me_sample) yields independent inter-event
30% times with the correct marginal but zero autocorrelation, and the MAP
31% CTMC walk (map_sample) is invalid here because a general RAP has
32% negative off-diagonal entries, for which the walk has no probabilistic
33% interpretation. A MAP is the special case in which H0 and H1 are
34% nonnegative, and on that input this sampler agrees with map_sample.
35%
36% Examples:
37% rap = RAP([-2, 1; 0.5, -1.5], [0.5, 0.5; 0.5, 0.5]);
38% samples = rap_sample(rap, 10000);
39%
40% % Or use process representation directly
41% RAP_proc = {[-2, 1; 0.5, -1.5], [0.5, 0.5; 0.5, 0.5]};
42% samples = rap_sample(RAP_proc, 10000);
43%
44% Copyright (c) 2012-2026, Imperial College London
45% All rights reserved.
46
47if nargin < 2
48 n = 1;
49end
50
51% Extract process representation
52if isa(RAP, 'RAP')
53 RAP_proc = RAP.getProcess();
54elseif iscell(RAP)
55 RAP_proc = RAP;
56else
57 error('RAP must be either a RAP object or a cell array {H0, H1}');
58end
59
60H0 = RAP_proc{1};
61H1 = RAP_proc{2};
62nphases = size(H0, 1);
63e = ones(nphases, 1);
64
65% Conditional phase vector, normalized so that v*e = 1. The arrival-embedded
66% equilibrium vector is the stationary choice for the first inter-event time.
67v = map_pie(RAP_proc);
68v = v / (v * e);
69
70% Scale for the initial bracket and for the Newton safeguard.
71meanval = map_mean(RAP_proc);
72if ~isfinite(meanval) || meanval <= 0
73 meanval = 1;
74end
75
76sample = zeros(n, 1);
77for i = 1:n
78 target = 1 - rand(); % target survival level in (0,1]
79
80 x = invert_survival(v, H0, e, target, meanval);
81 sample(i) = x;
82
83 % Advance the conditional vector across the event.
84 vnext = v * expm(H0 * x) * H1;
85 mass = vnext * e;
86 if mass <= 0 || ~isfinite(mass)
87 % The conditional vector has lost its normalization to roundoff,
88 % which can only happen at survival levels far into the tail. Restart
89 % from the embedded equilibrium rather than propagate a meaningless
90 % vector.
91 v = map_pie(RAP_proc);
92 v = v / (v * e);
93 else
94 v = vnext / mass;
95 end
96end
97
98end
99
100function x = invert_survival(v, H0, e, target, scale)
101% Solve v*expm(H0*x)*e = target for x, with target in (0,1].
102
103surv = @(t) v * expm(H0 * t) * e;
104
105% Bracket the root: survival is 1 at t = 0 and decreases to 0.
106lo = 0;
107hi = scale;
108smax = 200;
109k = 0;
110while surv(hi) > target && k < smax
111 lo = hi;
112 hi = hi * 2;
113 k = k + 1;
114end
115if k >= smax
116 x = hi;
117 return;
118end
119
120% Bisection to a tight bracket, then Newton polish. Bisection alone is used
121% first because the conditional density of a RAP need not be monotone, so an
122% unguarded Newton step from an arbitrary start can leave the bracket.
123for k = 1:60
124 mid = 0.5 * (lo + hi);
125 if surv(mid) > target
126 lo = mid;
127 else
128 hi = mid;
129 end
130 if (hi - lo) <= 1e-12 * max(1, hi)
131 break;
132 end
133end
134
135x = 0.5 * (lo + hi);
136for k = 1:3
137 ex = expm(H0 * x);
138 s = v * ex * e;
139 d = v * ex * H0 * e; % derivative of the survival function, negative
140 if ~(d < 0)
141 break;
142 end
143 xn = x - (s - target) / d;
144 if xn <= lo || xn >= hi
145 break;
146 end
147 if abs(xn - x) <= 1e-14 * max(1, abs(x))
148 x = xn;
149 break;
150 end
151 x = xn;
152end
153
154end
Definition Station.m:245