SSJ API Documentation
Stochastic Simulation in Java
Loading...
Searching...
No Matches
BrownianMotionBridge.java
1/*
2 * Class: BrownianMotionBridge
3 * Description:
4 * Environment: Java
5 * Software: SSJ
6 * Copyright (C) 2001 Pierre L'Ecuyer and Universite de Montreal
7 * Organization: DIRO, Universite de Montreal
8 * @author
9 * @since
10 *
11 *
12 * Licensed under the Apache License, Version 2.0 (the "License");
13 * you may not use this file except in compliance with the License.
14 * You may obtain a copy of the License at
15 *
16 * http://www.apache.org/licenses/LICENSE-2.0
17 *
18 * Unless required by applicable law or agreed to in writing, software
19 * distributed under the License is distributed on an "AS IS" BASIS,
20 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
21 * See the License for the specific language governing permissions and
22 * limitations under the License.
23 *
24 */
25package umontreal.ssj.stochprocess;
26
27import umontreal.ssj.rng.*;
28import umontreal.ssj.probdist.*;
29import umontreal.ssj.randvar.*;
30
75 protected int bridgeCounter = -1; // Before 1st observ
76
77 // For precomputations for B Bridge
78 protected double[] wMuDt, wSqrtDt;
79 protected int[] wIndexList, ptIndex;
80
87 public BrownianMotionBridge(double x0, double mu, double sigma, RandomStream stream) {
88 super(x0, mu, sigma, stream);
89 }
90
97 public BrownianMotionBridge(double x0, double mu, double sigma, NormalGen gen) {
98 super(x0, mu, sigma, gen);
99 }
100
101 public double nextObservation() {
102 double x;
103 if (bridgeCounter == -1) {
104 x = x0 + mu * (t[d] - t[0]) + wSqrtDt[0] * gen.nextDouble();
105 bridgeCounter = 0;
106 observationIndex = d;
107 } else {
108 int j = bridgeCounter * 3;
109 int oldIndexL = wIndexList[j];
110 int newIndex = wIndexList[j + 1];
111 int oldIndexR = wIndexList[j + 2];
112
113 x = path[oldIndexL] + (path[oldIndexR] - path[oldIndexL]) * wMuDt[newIndex]
114 + wSqrtDt[newIndex] * gen.nextDouble();
115
116 bridgeCounter++;
117 observationIndex = newIndex;
118 }
119 observationCounter = bridgeCounter + 1;
120 path[observationIndex] = x;
121 return x;
122 }
123
124 public double nextObservation(double nextTime) {
125 double x;
126 if (bridgeCounter == -1) {
127 t[d] = nextTime;
128
129 wMuDt[0] = 0.0; // The end point of the Wiener process
130 // w/ Brownian bridge has expectation = 0
131 wSqrtDt[0] = sigma * Math.sqrt(t[d] - t[0]);
132 // = sigma*sqrt(Dt) of end point
133
134 x = x0 + mu * (t[d] - t[0]) + wSqrtDt[0] * gen.nextDouble();
135
136 bridgeCounter = 0;
137 observationIndex = d;
138 } else {
139 int j = bridgeCounter * 3;
140 int oldIndexL = wIndexList[j];
141 int newIndex = wIndexList[j + 1];
142 int oldIndexR = wIndexList[j + 2];
143
144 t[newIndex] = nextTime;
145
146 double dtRL = t[oldIndexR] - t[oldIndexL];
147 if (dtRL != 0.0) {
148 wMuDt[newIndex] = (t[newIndex] - t[oldIndexL]) / dtRL;
149 } else {
150 wMuDt[newIndex] = 0.0;
151 }
152 wSqrtDt[newIndex] = sigma * Math.sqrt(wMuDt[newIndex] * (t[oldIndexR] - t[newIndex]));
153
154 x = path[oldIndexL] + (path[oldIndexR] - path[oldIndexL]) * wMuDt[newIndex]
155 + wSqrtDt[newIndex] * gen.nextDouble();
156
157 bridgeCounter++;
158 observationIndex = newIndex;
159 }
160 observationCounter = bridgeCounter + 1;
161 path[observationIndex] = x;
162 return x;
163 }
164
165 public double[] generatePath() {
166 // Generation of Brownian bridge process
167 int oldIndexL, oldIndexR, newIndex;
168 path[d] = x0 + mu * (t[d] - t[0]) + wSqrtDt[0] * gen.nextDouble();
169
170 for (int j = 0; j < 3 * (d - 1); j += 3) {
171 oldIndexL = wIndexList[j];
172 newIndex = wIndexList[j + 1];
173 oldIndexR = wIndexList[j + 2];
174
175 path[newIndex] = path[oldIndexL] + (path[oldIndexR] - path[oldIndexL]) * wMuDt[newIndex]
176 + wSqrtDt[newIndex] * gen.nextDouble();
177 }
178
179 // resetStartProcess();
180 observationIndex = d;
181 observationCounter = d;
182 return path;
183 }
184
185 public double[] generatePath(double[] uniform01) {
186 int oldIndexL, oldIndexR, newIndex;
187 path[d] = x0 + mu * (t[d] - t[0]) + wSqrtDt[0] * NormalDist.inverseF01(uniform01[0]);
188
189 for (int j = 0; j < 3 * (d - 1); j += 3) {
190 oldIndexL = wIndexList[j];
191 newIndex = wIndexList[j + 1];
192 oldIndexR = wIndexList[j + 2];
193
194 path[newIndex] = path[oldIndexL] + (path[oldIndexR] - path[oldIndexL]) * wMuDt[newIndex]
195 + wSqrtDt[newIndex] * NormalDist.inverseF01(uniform01[1 + j / 3]);
196 }
197
198 // resetStartProcess();
199 observationIndex = d;
200 observationCounter = d;
201 return path;
202 }
203
204 public void resetStartProcess() {
205 observationIndex = 0;
206 observationCounter = 0;
207 bridgeCounter = -1;
208 }
209
210 protected void init() {
211 super.init();
212
213 /* For Brownian Bridge */
214
215 // Quantities for Brownian Bridge process
216 wMuDt = new double[d + 1];
217 wSqrtDt = new double[d + 1];
218 wIndexList = new int[3 * (d)];
219 ptIndex = new int[d + 1];
220 double tem = 0;
221
222 int indexCounter = 0;
223 int newIndex, oldLeft, oldRight;
224
225 ptIndex[0] = 0;
226 ptIndex[1] = d;
227
228 wMuDt[0] = 0.0; // The end point of the Wiener process
229 // w/ Brownian bridge has expectation = 0
230 if (t[d] < t[0])
231 throw new IllegalStateException(" t[d] < t[0]");
232 wSqrtDt[0] = sigma * Math.sqrt(t[d] - t[0]);
233 // = sigma*sqrt(Dt) of end point
234
235 for (int powOfTwo = 1; powOfTwo <= d / 2; powOfTwo *= 2) {
236 /* Make room in the indexing array "ptIndex" */
237 for (int j = powOfTwo; j >= 1; j--) {
238 ptIndex[2 * j] = ptIndex[j];
239 }
240
241 /* Insert new indices and Calculate constants */
242 for (int j = 1; j <= powOfTwo; j++) {
243 oldLeft = 2 * j - 2;
244 oldRight = 2 * j;
245 newIndex = (int) (0.5 * (ptIndex[oldLeft] + ptIndex[oldRight]));
246
247 wMuDt[newIndex] = (t[newIndex] - t[ptIndex[oldLeft]]) / (t[ptIndex[oldRight]] - t[ptIndex[oldLeft]]);
248 tem = (t[newIndex] - t[ptIndex[oldLeft]]) * (t[ptIndex[oldRight]] - t[newIndex])
249 / (t[ptIndex[oldRight]] - t[ptIndex[oldLeft]]);
250
251 // Test for NaN (z != z); 0/0 gives a NaN
252 if (tem < 0 || tem != tem) {
253 System.out.printf("t[newIndex] - t[ptIndex[oldLeft]] = %g%n", t[newIndex] - t[ptIndex[oldLeft]]);
254 System.out.printf("t[ptIndex[oldRight]] - t[newIndex] = %g%n", t[ptIndex[oldRight]] - t[newIndex]);
255 System.out.printf("t[ptIndex[oldRight]] - t[ptIndex[oldLeft]] = %g%n",
256 t[ptIndex[oldRight]] - t[ptIndex[oldLeft]]);
257 System.out.printf("t[ptIndex[oldRight]] = %g%n", t[ptIndex[oldRight]]);
258 System.out.printf("t[ptIndex[oldLeft]] = %g%n", t[ptIndex[oldLeft]]);
259 throw new IllegalStateException(" tem < 0 or NaN");
260 }
261 wSqrtDt[newIndex] = sigma * Math.sqrt(tem);
262
263 ptIndex[oldLeft + 1] = newIndex;
264 wIndexList[indexCounter] = ptIndex[oldLeft];
265 wIndexList[indexCounter + 1] = newIndex;
266 wIndexList[indexCounter + 2] = ptIndex[oldRight];
267
268 indexCounter += 3;
269 }
270 }
271 /* Check if there are holes remaining and fill them */
272 for (int k = 1; k < d; k++) {
273 if (ptIndex[k - 1] + 1 < ptIndex[k]) {
274 // there is a hole between (k-1) and k.
275 wMuDt[ptIndex[k - 1] + 1] = (t[ptIndex[k - 1] + 1] - t[ptIndex[k - 1]])
276 / (t[ptIndex[k]] - t[ptIndex[k - 1]]);
277 tem = (t[ptIndex[k - 1] + 1] - t[ptIndex[k - 1]]) * (t[ptIndex[k]] - t[ptIndex[k - 1] + 1])
278 / (t[ptIndex[k]] - t[ptIndex[k - 1]]);
279
280 // Test for NaN (z != z); 0/0 gives a NaN
281 if (tem < 0 || tem != tem) {
282 System.out.printf("t[ptIndex[k-1]+1] - t[ptIndex[k-1]] = %g%n",
283 t[ptIndex[k - 1] + 1] - t[ptIndex[k - 1]]);
284 System.out.printf("t[ptIndex[k]] - t[ptIndex[k-1]+1] = %g%n", t[ptIndex[k]] - t[ptIndex[k - 1] + 1]);
285 System.out.printf("t[ptIndex[k]] - t[ptIndex[k-1]] = %g%n", t[ptIndex[k]] - t[ptIndex[k - 1]]);
286 System.out.printf("t[ptIndex[k]] = %20.16g%n", t[ptIndex[k]]);
287 System.out.printf("t[ptIndex[k-1]] = %20.16g%n", t[ptIndex[k - 1]]);
288 throw new IllegalStateException(" tem < 0 or NaN");
289 }
290 wSqrtDt[ptIndex[k - 1] + 1] = sigma * Math.sqrt(tem);
291 wIndexList[indexCounter] = ptIndex[k] - 2;
292 wIndexList[indexCounter + 1] = ptIndex[k] - 1;
293 wIndexList[indexCounter + 2] = ptIndex[k];
294 indexCounter += 3;
295 }
296 }
297 }
298}
Extends the class ContinuousDistribution for the normal distribution (e.g., tjoh95a  (page 80)).
static double inverseF01(double u)
Same as inverseF(0, 1, u).
This class implements methods for generating random variates from the normal distribution .
double nextObservation()
Generates and returns the next observation of the stochastic process.
BrownianMotionBridge(double x0, double mu, double sigma, NormalGen gen)
Constructs a new BrownianMotionBridge with parameters , and initial value .
double[] generatePath(double[] uniform01)
Same as generatePath(), but a vector of uniform random numbers must be provided to the method.
double nextObservation(double nextTime)
Generates and returns the next observation at time nextTime.
BrownianMotionBridge(double x0, double mu, double sigma, RandomStream stream)
Constructs a new BrownianMotionBridge with parameters , and initial value .
double[] generatePath()
Generates, returns, and saves the sample path .
void resetStartProcess()
Resets the observation counter to its initial value , so that the current observation becomes .
BrownianMotion(double x0, double mu, double sigma, RandomStream stream)
Constructs a new BrownianMotion with parameters mu,.
This interface defines the basic structures to handle multiple streams of uniform (pseudo)random numb...