Logo
Fully annotated reference manual - version 1.8.12
Loading...
Searching...
No Matches
discretedistribution.cpp
Go to the documentation of this file.
1/*
2 Copyright (C) 2020 Quaternion Risk Management Ltd
3 All rights reserved.
4
5 This file is part of ORE, a free-software/open-source library
6 for transparent pricing and risk analysis - http://opensourcerisk.org
7
8 ORE is free software: you can redistribute it and/or modify it
9 under the terms of the Modified BSD License. You should have received a
10 copy of the license along with this program.
11 The license is also available online at <http://opensourcerisk.org>
12
13 This program is distributed on the basis that it will form a useful
14 contribution to risk analytics and model standardisation, but WITHOUT
15 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
16 FITNESS FOR A PARTICULAR PURPOSE. See the license for more details.
17*/
18
19/*! \file discretedistribution.hpp
20 \brief Discretized probability density and cumulative probability
21 */
22
24
25using namespace std;
26using namespace QuantLib;
27
28namespace QuantExt {
29
30DiscreteDistribution::DiscreteDistribution(const vector<Distributionpair>& data) : data_(data) {
31 // do checks here
32}
33
35
36DiscreteDistribution::DiscreteDistribution(const vector<Real>& dataPoints, const vector<Real>& probabilities) {
37 QL_REQUIRE(dataPoints.size() == probabilities.size(), "Must be the same number of data points and probabilities");
38
39 for (Size i = 0; i < dataPoints.size(); i++) {
40 data_.push_back(Distributionpair(dataPoints[i], probabilities[i]));
41 }
42}
43
44Size DiscreteDistribution::size() const { return data_.size(); }
45
46vector<Distributionpair> DiscreteDistribution::get() const { return data_; }
47
49 // checks here
50 return data_[i];
51}
52
54 // Check that index i is in bounds
55 QL_REQUIRE(0 <= i && i < data_.size(), "Asked for probability outside range of distribution");
56 return data_[i].y_;
57}
58
59Real DiscreteDistribution::data(Size i) const {
60 // Check that index i is in bounds
61 QL_REQUIRE(0 <= i && i < data_.size(), "Asked for data point outside range of distribution");
62 return data_[i].x_;
63}
64
65//-------------------------------------------
67 //-------------------------------------------
68 vector<Distributionpair> result(buckets);
69
70 vector<Distributionpair> x1pm1 = a.get();
71 vector<Distributionpair> x2pm2 = b.get();
72 vector<Distributionpair> xpconvtemp;
73
74 for (Size i = 0; i < x1pm1.size(); i++) {
75 for (Size j = 0; j < x2pm2.size(); j++) {
76 Distributionpair xp(x1pm1[i].x_ + x2pm2[j].x_, x1pm1[i].y_ * x2pm2[j].y_);
77 xpconvtemp.push_back(xp);
78 // cout << i << " " << x1pm1[i].x_ << " " << x1pm1[i].y_ << " " << x2pm2[j].x_ << " " << x2pm2[j].y_ <<
79 // endl;
80 }
81 }
82
83 std::sort(xpconvtemp.begin(), xpconvtemp.end());
84 //---------
85 // rebucket
86 //---------
87
88 vector<Distributionpair> xpconv(buckets, Distributionpair(0.0, 0.0));
89
90 Real xmin = xpconvtemp.front().x_;
91 Real xmax = xpconvtemp.back().x_;
92 Real Bucketsize = (xmax - xmin) / buckets;
93 // cout << "Bucketsize " << Bucketsize << "xMax "<< xmax<< "xmin "<< xmin <<endl;
94
95 if (xmin == xmax) {
96 buckets = 1;
97 Bucketsize = 1.;
98 }
99
100 for (Size i = 0; i < buckets; i++) {
101 xpconv[i].x_ = xmin + i * Bucketsize;
102 }
103
104 for (Size j = 0; j < xpconvtemp.size(); j++) {
105 Size bucket = static_cast<Size>((xpconvtemp[j].x_ - xmin) / Bucketsize);
106 QL_REQUIRE(bucket <= buckets, "Number of buckets in Convolution incorrect");
107 if (bucket == buckets) {
108 bucket -= 1;
109 }
110
111 Real probs = xpconv[bucket].y_ + xpconvtemp[j].y_;
112
113 // deal with zero probability
114
115 if (probs < 1.0e-20) {
116 xpconv[bucket].y_ = 0.0;
117 xpconv[bucket].x_ += 0.0;
118 } else {
119 Real intermed = (xpconv[bucket].x_ * xpconv[bucket].y_ + xpconvtemp[j].x_ * xpconvtemp[j].y_) / probs;
120 xpconv[bucket].y_ += xpconvtemp[j].y_;
121 xpconv[bucket].x_ = intermed;
122 }
123
124 /*cout << j << " bucket " << bucket
125 << " " << xpconvtemp[j].x_
126 << " " << xpconvtemp[j].y_
127 << " " << xpconv[bucket].x_
128 << " " << xpconv[bucket].y_
129 << " Bucketsize " << Bucketsize
130 << " xmin "<< xmin
131 <<" xmax " << xmax
132 << " test "<<xpconv[bucket].x_ - xmin+(bucket)*Bucketsize
133 << endl;*/
134
135 /*QL_REQUIRE( (xpconv[bucket].x_ - xmin+(bucket)*Bucketsize > -1.0e-8) and
136 ( xmin+(bucket+1)*Bucketsize - xpconv[bucket].x_ > -1.0e-8 ),"Convolve:: Fell out of bucket "<< bucket)
137 */
138 }
139
140 /* for (Size i = 0; i < xpconv.size() ;i++){
141 cout << i << " " << i*Bucketsize << " " << xpconv[i].x_ << " "<< xpconv[i].y_ <<
142 endl;
143 }
144 */
145 return DiscreteDistribution(xpconv);
146}
147
148//-------------------------------------------
150 //-------------------------------------------
151 vector<Distributionpair> xptemp = a.get();
152
153 std::sort(xptemp.begin(), xptemp.end());
154
155 Real xmin = xptemp.front().x_;
156 Real xmax = xptemp.back().x_;
157 Real Bucketsize = (xmax - xmin) / buckets;
158
159 if (xmin == xmax) {
160 buckets = 1;
161 Bucketsize = 1.;
162 }
163
164 //---------
165 // rebucket
166 //---------
167
168 vector<Distributionpair> xp(buckets, Distributionpair(0.0, 0.0));
169
170 // cout << "Bucketsize " << Bucketsize << "xMax "<< xmax<< "xmin "<< xmin <<endl;
171
172 for (Size i = 0; i < buckets; i++) {
173 xp[i].x_ = xmin + i * Bucketsize;
174 }
175
176 for (Size j = 0; j < xptemp.size(); j++) {
177 Size bucket = static_cast<Size>((xptemp[j].x_ - xmin) / Bucketsize);
178 QL_REQUIRE(bucket <= buckets, "Number of buckets in Rebucket incorrect");
179 if (bucket == buckets) {
180 bucket -= 1;
181 }
182
183 Real probs = xp[bucket].y_ + xptemp[j].y_;
184
185 // deal with zero probability
186
187 if (probs < 1.0e-30) {
188 xp[bucket].y_ = 0.0;
189 xp[bucket].x_ += 0.0;
190 } else {
191 Real intermed = (xp[bucket].x_ * xp[bucket].y_ + xptemp[j].x_ * xptemp[j].y_) / probs;
192 xp[bucket].y_ += xptemp[j].y_;
193 xp[bucket].x_ = intermed;
194 }
195 }
196
197 return DiscreteDistribution(xp);
198}
199
200//-------------------------------------------
202 //-------------------------------------------
203 vector<Distributionpair> xptemp = a.get();
204
205 std::sort(xptemp.begin(), xptemp.end());
206
207 Size buckets;
208 Real xmin = xptemp.front().x_;
209 Real xmax = xptemp.back().x_;
210
211 if (xmin == xmax) {
212 buckets = 1;
213 } else {
214 buckets = static_cast<Size>(ceil((xmax - xmin) / step));
215 }
216
217 //---------
218 // rebucket
219 //---------
220
221 vector<Distributionpair> xp(buckets, Distributionpair(0.0, 0.0));
222
223 // cout << "Bucketsize " << Bucketsize << "xMax "<< xmax<< "xmin "<< xmin <<endl;
224
225 for (Size i = 0; i < buckets; i++) {
226 xp[i].x_ = xmin + i * step;
227 }
228
229 for (Size j = 0; j < xptemp.size(); j++) {
230 Size bucket = static_cast<Size>((xptemp[j].x_ - xmin) / step);
231 QL_REQUIRE(bucket <= buckets, "Number of buckets in Rebucket incorrect");
232 if (bucket == buckets) {
233 bucket -= 1;
234 }
235
236 Real probs = xp[bucket].y_ + xptemp[j].y_;
237
238 // deal with zero probability
239
240 if (probs < 1.0e-30) {
241 xp[bucket].y_ = 0.0;
242 xp[bucket].x_ += 0.0;
243 } else {
244 Real intermed = (xp[bucket].x_ * xp[bucket].y_ + xptemp[j].x_ * xptemp[j].y_) / probs;
245 xp[bucket].y_ += xptemp[j].y_;
246 xp[bucket].x_ = intermed;
247 }
248 }
249
250 return DiscreteDistribution(xp);
251}
252
253//-------------------------------------------
255 //-------------------------------------------
256
257 vector<Distributionpair> x1pm1 = a.get();
258 vector<Distributionpair> x2pm2 = b.get();
259 vector<Distributionpair> xpsumtemp;
260
261 for (Size i = 0; i < x1pm1.size(); i++) {
262 Distributionpair xp(x1pm1[i].x_, x1pm1[i].y_);
263 xpsumtemp.push_back(xp);
264 }
265
266 for (Size i = 0; i < x2pm2.size(); i++) {
267 Distributionpair xp(x2pm2[i].x_, x2pm2[i].y_);
268 xpsumtemp.push_back(xp);
269 }
270
271 std::sort(xpsumtemp.begin(), xpsumtemp.end());
272 //---------
273 // rebucket
274 //---------
275
276 vector<Distributionpair> xpsum(buckets, Distributionpair(0.0, 0.0));
277
278 Real xmin = xpsumtemp.front().x_;
279 Real xmax = xpsumtemp.back().x_;
280 Real Bucketsize = (xmax - xmin) / buckets;
281 // cout << "Bucketsize " << Bucketsize << "xMax "<< xmax<< "xmin "<< xmin <<endl;
282
283 if (xmin == xmax) {
284 xpsum[0].x_ = xmin;
285 xpsum[0].y_ = 1.0;
286 } else {
287 for (Size i = 0; i < buckets; i++) {
288 xpsum[i].x_ = i * Bucketsize;
289 }
290
291 for (Size j = 0; j < xpsumtemp.size(); j++) {
292 Size bucket = static_cast<Size>((xpsumtemp[j].x_ - xmin) / Bucketsize);
293 QL_REQUIRE(bucket <= buckets, "Number of buckets in Convolution incorrect: " << bucket);
294 if (bucket == buckets) {
295 bucket -= 1;
296 }
297
298 Real probs = xpsum[bucket].y_ + xpsumtemp[j].y_;
299
300 // deal with zero probability
301
302 if (probs < 1.0e-30) {
303 xpsum[bucket].y_ = 0.0;
304 xpsum[bucket].x_ += 0.0;
305 } else {
306 Real intermed = (xpsum[bucket].x_ * xpsum[bucket].y_ + xpsumtemp[j].x_ * xpsumtemp[j].y_) / probs;
307 xpsum[bucket].y_ += xpsumtemp[j].y_;
308 xpsum[bucket].x_ = intermed;
309 }
310
311 /*cout << j << " bucket " << bucket << " " <<
312 xpsumtemp[j].x_ << " " <<
313 xpsumtemp[j].y_ << " " <<
314 xpsum[bucket].x_ << " " <<
315 xpsum[bucket].y_ <<
316 endl; */
317 }
318
319 /* for (Size i = 0; i < xpsum.size() ;i++){
320 cout << i << " " << i*Bucketsize << " " << xpsum[i].x_ << " "<< xpsum[i].y_ <<
321 endl;
322 }
323 */
324 }
325 return DiscreteDistribution(xpsum);
326}
327//-------------------------------------------
328Real MDD::probabilitymatch(const DiscreteDistribution& a, const DiscreteDistribution& b, Real c, bool forward) {
329 //-------------------------------------------
330
331 vector<Distributionpair> x1pm1 = a.get();
332 vector<Distributionpair> x2pm2 = b.get();
333 Real c_ = c;
334 Real target(0.);
335 std::sort(x2pm2.begin(), x2pm2.end());
336 if (forward) {
337 std::sort(x1pm1.begin(), x1pm1.end());
338 } else {
339 std::sort(x1pm1.rbegin(), x1pm1.rend());
340 }
341 Real cuma = 0.0;
342 Real cumb = 0.0;
343
344 for (Size i = 0; i < x2pm2.size(); i++) {
345 if (x2pm2[i].x_ <= c_) {
346 cumb += x2pm2[i].y_;
347 }
348 }
349 for (Size i = 0; i < x1pm1.size(); i++) {
350 cuma += x1pm1[i].y_;
351 if (cuma <= cumb) {
352 target = x1pm1[i].x_;
353 }
354 }
355
356 return target;
357}
358
360
361 // Sort both distributions and calculate their cumulative distributions
362 vector<Distributionpair> aData = a.get();
363 vector<Distributionpair> bData = b.get();
364 sort(aData.begin(), aData.end());
365 sort(bData.begin(), bData.end());
366
367 // Find P_b(c)
368 Real probability = 0.0;
369 Distributionpair dummy(c);
370 vector<Distributionpair>::iterator itVar = lower_bound(bData.begin(), bData.end(), dummy);
371 if (itVar == bData.end()) {
372 for (Size i = 0; i < bData.size(); i++)
373 probability += bData[i].y_;
374 } else if (itVar == bData.begin()) {
375 probability = itVar->y_;
376 } else {
377 Size startIndex = itVar - bData.begin() - 1;
378 for (Size i = 0; i <= startIndex; i++)
379 probability += bData[i].y_;
380 probability += (c - bData[startIndex].x_) * itVar->y_ / (itVar->x_ - bData[startIndex].x_);
381 }
382
383 // Find target such that P_a(target) = P_b(c)
384 Real sum = 0.0;
385 vector<Real> aCumulative(aData.size());
386 vector<Real> aValues(aData.size());
387 for (Size i = 0; i < aData.size(); i++) {
388 sum += aData[i].y_;
389 aCumulative[i] = sum;
390 aValues[i] = aData[i].x_;
391 }
392
393 vector<Real>::iterator itProb = lower_bound(aCumulative.begin(), aCumulative.end(), probability);
394 if (itProb == aCumulative.end()) {
395 return aValues.back();
396 } else if (itProb == aCumulative.begin()) {
397 return aValues.front();
398 } else {
399 Size low = itProb - aCumulative.begin() - 1;
400 Real target = aValues[low];
401 target += (aValues[low + 1] - aValues[low]) * (probability - aCumulative[low]) /
402 (aCumulative[low + 1] - aCumulative[low]);
403 return target;
404 }
405}
406
407//-------------------------------------------
409 //-------------------------------------------
410
411 vector<Distributionpair> x1pm1 = a.get();
412 vector<Distributionpair> x2pm2 = b.get();
413 Real c_ = c;
414 vector<Distributionpair> xpsumtemp;
415
416 // std::sort (x1pm1.begin(), x1pm1.end());
417 // std::sort (x2pm2.begin(), x2pm2.end());
418
419 Real cumLast = 0.0;
420 Real cumNow = 0.0;
421
422 for (Size i = 0; i < x2pm2.size(); i++) {
423 cumNow += x2pm2[i].y_;
424 Real cumX1 = 0.0;
425 for (Size j = 0; j < x1pm1.size(); j++) {
426 cumX1 += x1pm1[j].y_;
427 if ((cumX1 > cumLast) && (cumX1 <= cumNow)) {
428 x1pm1[j].x_ += x2pm2[i].x_ * c_;
429 }
430 }
431 // cout<<"Cum X1"<< cumX1<<" Cum now" << cumNow<<endl;
432 // QL_REQUIRE( cumNow <= cumX1, "Cumulative probability of Distribution b exceeds a");
433 cumLast = cumNow;
434 }
435 return x1pm1;
436}
437
438//-------------------------------------------
440 //-------------------------------------------
441
442 vector<Distributionpair> x1pm1 = a.get();
443 vector<Distributionpair> x2pm2 = b.get();
444 Real c_ = c;
445 vector<Distributionpair> xpsumtemp;
446
447 std::sort(x1pm1.begin(), x1pm1.end());
448 std::sort(x2pm2.begin(), x2pm2.end());
449
450 Real cumLast = 0.0;
451 Real cumNow = 0.0;
452
453 for (Size i = 0; i < x2pm2.size(); i++) {
454 cumNow += x2pm2[i].y_;
455 Real cumX1 = 0.0;
456 for (Size j = 0; j < x1pm1.size(); j++) {
457 cumX1 += x1pm1[j].y_;
458 if ((cumX1 >= cumLast) && (cumX1 < cumNow)) {
459 x1pm1[j].x_ += x2pm2[i].x_ * c_;
460 }
461 }
462 // cout<<"Cum X1"<< cumX1<<" Cum now" << cumNow<<endl;
463 // QL_REQUIRE( cumNow <= cumX1, "Cumulative probability of Distribution b exceeds a");
464 cumLast = cumNow;
465 }
466 return x1pm1;
467}
468
469//-------------------------------------------
471 //-------------------------------------------
472
473 vector<Distributionpair> x1pm1 = a.get();
474 vector<Distributionpair> x2pm2 = b.get();
475 Real c_ = c;
476 vector<Distributionpair> xpsumtemp;
477
478 std::sort(x1pm1.begin(), x1pm1.end());
479 std::sort(x2pm2.begin(), x2pm2.end());
480
481 Real cumLast = 0.0;
482 Real cumNow = 0.0;
483
484 for (Size i = x2pm2.size(); i > 0; i--) {
485 cumNow += x2pm2[i - 1].y_;
486 Real cumX1 = 0.0;
487 for (Size j = x1pm1.size(); j > 0; j--) {
488 cumX1 += x1pm1[j - 1].y_;
489 if ((cumX1 >= cumLast) && (cumX1 < cumNow)) {
490 x1pm1[j - 1].x_ += x2pm2[i - 1].x_ * c_;
491 }
492 }
493 // cout<<"Cum X1"<< cumX1<<" Cum now" << cumNow<<endl;
494 // QL_REQUIRE( cumNow <= cumX1, "Cumulative probability of Distribution b exceeds a");
495 cumLast = cumNow;
496 }
497 return x1pm1;
498}
499
500//-------------------------------------------
502 //-------------------------------------------
503
504 vector<Distributionpair> x1pm1 = a.get();
505 vector<Distributionpair> x2pm2 = b.get();
506 vector<Distributionpair> xpsumtemp;
507 Real probmNNzero = 0.;
508 Real probKicker = 0.;
509
510 // Splices together the mezz and equity distributions to form the kicker
511
512 for (Size i = 0; i < x1pm1.size(); i++) {
513
514 Distributionpair xp(x1pm1[i].x_, x1pm1[i].y_);
515 if (x1pm1[i].x_ >= 0) {
516 xpsumtemp.push_back(xp);
517 } else {
518 probmNNzero += x1pm1[i].y_;
519 }
520 }
521
522 for (Size i = 0; i < x2pm2.size(); i++) {
523 Distributionpair xp((1. - kR) * x2pm2[i].x_, x2pm2[i].y_);
524 if (x2pm2[i].x_ < 0) {
525 xpsumtemp.push_back(xp);
526 probKicker += x2pm2[i].y_;
527 }
528 }
529 Distributionpair xp(0.0, probmNNzero - probKicker);
530 QL_REQUIRE(xp.y_ >= 0, "Problem with probabilities in Mezz Splice");
531 xpsumtemp.push_back(xp);
532
533 std::sort(xpsumtemp.begin(), xpsumtemp.end());
534
535 return DiscreteDistribution(xpsumtemp);
536}
537
538//-------------------------------------------
540 //-------------------------------------------
541
542 vector<Distributionpair> x1pm1 = a.get();
543 Real b_ = b;
544 vector<Distributionpair> scalarmult;
545
546 for (Size i = 0; i < x1pm1.size(); i++) {
547
548 Distributionpair xp(x1pm1[i].x_, x1pm1[i].y_ * b_);
549 scalarmult.push_back(xp);
550 }
551 return DiscreteDistribution(scalarmult);
552}
553
554//-------------------------------------------
556 //-------------------------------------------
557
558 vector<Distributionpair> x1pm1 = a.get();
559 Real b_ = b;
560 vector<Distributionpair> scalarmult;
561
562 for (Size i = 0; i < x1pm1.size(); i++) {
563
564 Distributionpair xp(b_ * x1pm1[i].x_, x1pm1[i].y_);
565 scalarmult.push_back(xp);
566 }
567 return DiscreteDistribution(scalarmult);
568}
569
570//-------------------------------------------
572 //-------------------------------------------
573
574 vector<Distributionpair> x1pm1 = a.get();
575 Real b_ = b;
576 vector<Distributionpair> scalarmult;
577
578 for (Size i = 0; i < x1pm1.size(); i++) {
579
580 Distributionpair xp(x1pm1[i].x_ + b_, x1pm1[i].y_);
581 scalarmult.push_back(xp);
582 }
583 return DiscreteDistribution(scalarmult);
584}
585
586//-------------------------------------------
588 //-------------------------------------------
589
590 vector<Distributionpair> x1pm1 = a.get();
591 Real b_ = b;
592 vector<Distributionpair> func;
593
594 std::sort(x1pm1.begin(), x1pm1.end());
595
596 Real temp = 0.;
597
598 for (Size i = 0; i < x1pm1.size(); i++) {
599 if (x1pm1[i].x_ <= b_) {
600 temp += x1pm1[i].y_;
601 }
602 }
603 Distributionpair xp(b_, temp);
604 func.push_back(xp);
605
606 for (Size i = 0; i < x1pm1.size(); i++) {
607 if (x1pm1[i].x_ > b_) {
608 Distributionpair xp(max(x1pm1[i].x_, b_), x1pm1[i].y_);
609 func.push_back(xp);
610 }
611 }
612
613 return DiscreteDistribution(func);
614}
615
616//-------------------------------------------
618 //-------------------------------------------
619
620 vector<Distributionpair> x1pm1 = a.get();
621 Real b_ = b;
622 vector<Distributionpair> func;
623
624 std::sort(x1pm1.begin(), x1pm1.end());
625
626 for (Size i = 0; i < x1pm1.size(); i++) {
627 if (x1pm1[i].x_ < b_) {
628 Distributionpair xp(min(x1pm1[i].x_, b_), x1pm1[i].y_);
629 func.push_back(xp);
630 }
631 }
632
633 Real temp = 0.;
634
635 for (Size i = 0; i < x1pm1.size(); i++) {
636 if (x1pm1[i].x_ >= b_) {
637 temp += x1pm1[i].y_;
638 }
639 }
640 Distributionpair xp(b_, temp);
641 func.push_back(xp);
642
643 return DiscreteDistribution(func);
644}
645
646//-------------------------------------------
648 //-------------------------------------------
649
650 vector<Distributionpair> x1pm1 = a.get();
651 Real exp = 0.0;
652
653 for (Size i = 0; i < x1pm1.size(); i++) {
654
655 exp += x1pm1[i].x_ * x1pm1[i].y_;
656 }
657 return exp;
658}
659
660//-------------------------------------------
662 //-------------------------------------------
663
664 vector<Distributionpair> x1pm1 = a.get();
665 Real mu = MDD::expectation(a);
666 Real variance = 0.0;
667
668 for (Size i = 0; i < x1pm1.size(); i++) {
669
670 variance += pow((x1pm1[i].x_ - mu), 2) * x1pm1[i].y_;
671 }
672 Real stdev = sqrt(variance);
673 return stdev;
674}
675
676//-------------------------------------------
678 //-------------------------------------------
679
680 vector<Distributionpair> x1pm1 = a.get();
681 Real mu = MDD::expectation(a);
682 Real variance = 0.0;
683
684 for (Size i = 0; i < x1pm1.size(); i++) {
685 if (x1pm1[i].x_ - mu < 0.0)
686 variance += pow((x1pm1[i].x_ - mu), 2) * x1pm1[i].y_;
687 }
688 Real stdev = sqrt(variance);
689 return stdev;
690}
691
692//-------------------------------------------
693Real MDD::print(const DiscreteDistribution& a, const ostringstream& o) {
694 //-------------------------------------------
695
696 ofstream file;
697 file.open(o.str().c_str());
698 if (!file.is_open())
699 QL_FAIL("error opening file " << o.str());
700 file.setf(ios::scientific, ios::floatfield);
701 file.setf(ios::showpoint);
702 file.precision(4);
703 for (Size k = 0; k < a.size(); k++) {
704 file << k << " " << a.get(k).x_ << " " << a.get(k).y_ << endl;
705 }
706 file.close();
707
708 return 0;
709}
710
711} // namespace QuantExt
DiscreteDistribution()
Default constructor with probability 1.0 at 0.0.
virtual vector< Distributionpair > get() const
Real data(Size i) const
Return data at index i.
Real probability(Size i) const
Return probability for data at index i.
vector< Distributionpair > data_
Distributionpair is a helper class for DiscretDistribution.
static DiscreteDistribution scalarshiftx(const DiscreteDistribution &a, const Real &b)
static DiscreteDistribution scalarmultprob(const DiscreteDistribution &a, const Real &b)
static DiscreteDistribution scalarmultx(const DiscreteDistribution &a, const Real &b)
static DiscreteDistribution splicemezz(const DiscreteDistribution &a, const DiscreteDistribution &b, Real c)
static DiscreteDistribution functionmax(const DiscreteDistribution &a, const Real &b)
static DiscreteDistribution sum(const DiscreteDistribution &a, const DiscreteDistribution &b, Size buckets)
static DiscreteDistribution sumspecialunsorted(const DiscreteDistribution &a, const DiscreteDistribution &b, Real c)
static DiscreteDistribution rebucketfixedstep(const DiscreteDistribution &a, Real step)
static Real probabilitymatch(const DiscreteDistribution &a, const DiscreteDistribution &b, Real c, bool forward)
static DiscreteDistribution sumspecialright(const DiscreteDistribution &a, const DiscreteDistribution &b, Real c)
static Real expectation(const DiscreteDistribution &a)
static Real stdev(const DiscreteDistribution &a)
static DiscreteDistribution rebucketfixednumber(const DiscreteDistribution &a, Size buckets)
static DiscreteDistribution functionmin(const DiscreteDistribution &a, const Real &b)
static DiscreteDistribution sumspecial(const DiscreteDistribution &a, const DiscreteDistribution &b, Real c)
static Real leftstdev(const DiscreteDistribution &a)
static DiscreteDistribution convolve(const DiscreteDistribution &a, const DiscreteDistribution &b, Size buckets)
static Real print(const DiscreteDistribution &a, const ostringstream &o)
Discretized probability density and cumulative probability.
RandomVariable sqrt(RandomVariable x)
RandomVariable variance(const RandomVariable &r)
CompiledFormula exp(CompiledFormula x)
CompiledFormula min(CompiledFormula x, const CompiledFormula &y)
CompiledFormula pow(CompiledFormula x, const CompiledFormula &y)
CompiledFormula max(CompiledFormula x, const CompiledFormula &y)