Logo
Fully annotated reference manual - version 1.8.12
Loading...
Searching...
No Matches
randomastgenerator.cpp
Go to the documentation of this file.
1/*
2 Copyright (C) 2019 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
20
21#include <ql/errors.hpp>
22
23#include <boost/make_shared.hpp>
24
25#include <random>
26
27namespace ore {
28namespace data {
29
30struct RandomASTGenerator {
31 RandomASTGenerator(const Size maxSequenceLength, const Size maxDepth, const Size seed)
32 : maxSequenceLength_(maxSequenceLength), maxDepth_(maxDepth), gen_(seed) {}
33
34 void createInstructionSequence() {
35 std::uniform_int_distribution<> seq(1, maxSequenceLength_);
36 std::uniform_int_distribution<> instr(0, depth >= maxDepth_ ? 4 : 6);
37 ++depth;
38 std::vector<ASTNodePtr> args;
39 for (int i = 0; i < seq(gen_); ++i) {
40 switch (instr(gen_)) {
41 case 0:
42 createRequire();
43 break;
44 case 1:
45 createSort();
46 break;
47 case 2:
48 createPermute();
49 break;
50 case 3:
51 createDeclaration();
52 break;
53 case 4:
54 createAssignment();
55 break;
56 case 5:
57 createIfThenElse();
58 break;
59 case 6:
60 createLoop();
61 break;
62 default:
63 QL_FAIL("internal error:");
64 }
65 args.push_back(current);
66 }
67 current = QuantLib::ext::make_shared<SequenceNode>(args);
68 --depth;
69 }
70
71 void createRequire() {
72 ++depth;
73 createCondition();
74 current = QuantLib::ext::make_shared<RequireNode>(std::vector<ASTNodePtr>(1, current));
75 --depth;
76 }
77
78 void createSort() {
79 std::uniform_int_distribution<> seq(1, 3);
80 std::vector<ASTNodePtr> vars;
81 for (int i = 0; i < seq(gen_); ++i) {
82 vars.push_back(QuantLib::ext::make_shared<VariableNode>(createVariableName()));
83 }
84 current = QuantLib::ext::make_shared<SortNode>(vars);
85 }
86
87 void createPermute() {
88 std::uniform_int_distribution<> seq(2, 3);
89 std::vector<ASTNodePtr> vars;
90 for (int i = 0; i < seq(gen_); ++i) {
91 vars.push_back(QuantLib::ext::make_shared<VariableNode>(createVariableName()));
92 }
93 current = QuantLib::ext::make_shared<PermuteNode>(vars);
94 }
95
96 void createDeclaration() {
97 std::uniform_int_distribution<> seq(1, maxSequenceLength_);
98 ++depth;
99 std::vector<ASTNodePtr> args;
100 for (int i = 0; i < seq(gen_); ++i) {
101 createVarExpr();
102 args.push_back(current);
103 }
104 current = QuantLib::ext::make_shared<DeclarationNumberNode>(args);
105 --depth;
106 }
107
108 void createIfThenElse() {
109 ++depth;
110 std::uniform_int_distribution<> yn(0, 1);
111 std::vector<ASTNodePtr> args;
112 createCondition();
113 args.push_back(current);
114 createInstructionSequence();
115 args.push_back(current);
116 if (yn(gen_)) {
117 createInstructionSequence();
118 args.push_back(current);
119 }
120 current = QuantLib::ext::make_shared<IfThenElseNode>(args);
121 --depth;
122 }
123
124 void createLoop() {
125 ++depth;
126 std::vector<ASTNodePtr> args;
127 createTerm();
128 args.push_back(current);
129 createTerm();
130 args.push_back(current);
131 createTerm();
132 args.push_back(current);
133 createInstructionSequence();
134 args.push_back(current);
135 current = QuantLib::ext::make_shared<LoopNode>(createVariableName(), args);
136 --depth;
137 }
138
139 void createAssignment() {
140 ++depth;
141 std::vector<ASTNodePtr> args;
142 createVarExpr();
143 args.push_back(current);
144 createTerm();
145 args.push_back(current);
146 current = QuantLib::ext::make_shared<AssignmentNode>(args);
147 --depth;
148 }
149
150 void createCondition() {
151 std::uniform_int_distribution<> dep(0, maxDepth_);
152 std::uniform_int_distribution<> cond(0, 5);
153 std::uniform_int_distribution<> andor(0, 1);
154 ++depth;
155 if (depth + dep(gen_) >= maxDepth_) {
156 std::vector<ASTNodePtr> args;
157 createTerm();
158 args.push_back(current);
159 createTerm();
160 args.push_back(current);
161 switch (cond(gen_)) {
162 case 0:
163 current = QuantLib::ext::make_shared<ConditionEqNode>(args);
164 break;
165 case 1:
166 current = QuantLib::ext::make_shared<ConditionNeqNode>(args);
167 break;
168 case 2:
169 current = QuantLib::ext::make_shared<ConditionGeqNode>(args);
170 break;
171 case 3:
172 current = QuantLib::ext::make_shared<ConditionGtNode>(args);
173 break;
174 case 4:
175 current = QuantLib::ext::make_shared<ConditionLeqNode>(args);
176 break;
177 case 5:
178 current = QuantLib::ext::make_shared<ConditionLtNode>(args);
179 break;
180 default:
181 QL_FAIL("internal error");
182 }
183 } else {
184 std::vector<ASTNodePtr> args;
185 createCondition();
186 args.push_back(current);
187 createCondition();
188 args.push_back(current);
189 switch (andor(gen_)) {
190 case 0:
191 current = QuantLib::ext::make_shared<ConditionAndNode>(args);
192 break;
193 case 1:
194 current = QuantLib::ext::make_shared<ConditionOrNode>(args);
195 break;
196 default:
197 QL_FAIL("internal error");
198 }
199 }
200 --depth;
201 }
202
203 void createTerm() {
204 std::uniform_int_distribution<> dep(0, maxDepth_);
205 std::uniform_int_distribution<> pm(0, 3);
206 ++depth;
207 if (depth + dep(gen_) >= maxDepth_) {
208 createFactor();
209 } else {
210 std::vector<ASTNodePtr> args;
211 createTerm();
212 args.push_back(current);
213 createTerm();
214 args.push_back(current);
215 switch (pm(gen_)) {
216 case 0:
217 current = QuantLib::ext::make_shared<OperatorPlusNode>(args);
218 break;
219 case 1:
220 current = QuantLib::ext::make_shared<OperatorMinusNode>(args);
221 break;
222 case 2:
223 current = QuantLib::ext::make_shared<OperatorMultiplyNode>(args);
224 break;
225 case 3:
226 current = QuantLib::ext::make_shared<OperatorDivideNode>(args);
227 break;
228 default:
229 QL_FAIL("internal error");
230 }
231 }
232 --depth;
233 }
234
235 void createFactor() {
236 std::uniform_int_distribution<> dep(0, maxDepth_);
237 std::uniform_int_distribution<> sing(0, 2);
238 std::uniform_int_distribution<> fac(0, 25);
239 std::uniform_int_distribution<> yn(0, 1);
240 std::uniform_int_distribution<> zero123(0, 3);
241 std::uniform_int_distribution<> slot(0, 5);
242 std::uniform_int_distribution<> legNo(0, 5);
243 ++depth;
244 if (depth + dep(gen_) >= maxDepth_) {
245 switch (sing(gen_)) {
246 case 0:
247 current = QuantLib::ext::make_shared<VariableNode>(createVariableName(), std::vector<ASTNodePtr>());
248 break;
249 case 1:
250 current = QuantLib::ext::make_shared<ConstantNumberNode>(createConstantNumber());
251 break;
252 case 2:
253 current = QuantLib::ext::make_shared<SizeOpNode>(createVariableName());
254 break;
255 default:
256 QL_FAIL("internal error");
257 }
258 } else {
259 std::vector<ASTNodePtr> args;
260 switch (fac(gen_)) {
261 case 0:
262 createFactor();
263 args.push_back(current);
264 current = QuantLib::ext::make_shared<NegateNode>(args);
265 break;
266 case 1:
267 createTerm();
268 args.push_back(current);
269 current = QuantLib::ext::make_shared<FunctionAbsNode>(args);
270 break;
271 case 2:
272 createTerm();
273 args.push_back(current);
274 current = QuantLib::ext::make_shared<FunctionExpNode>(args);
275 break;
276 case 3:
277 createTerm();
278 args.push_back(current);
279 current = QuantLib::ext::make_shared<FunctionLogNode>(args);
280 break;
281 case 4:
282 createTerm();
283 args.push_back(current);
284 current = QuantLib::ext::make_shared<FunctionSqrtNode>(args);
285 break;
286 case 5:
287 createTerm();
288 args.push_back(current);
289 current = QuantLib::ext::make_shared<FunctionNormalCdfNode>(args);
290 break;
291 case 6:
292 createTerm();
293 args.push_back(current);
294 current = QuantLib::ext::make_shared<FunctionNormalPdfNode>(args);
295 break;
296 case 7:
297 createTerm();
298 args.push_back(current);
299 createTerm();
300 args.push_back(current);
301 current = QuantLib::ext::make_shared<FunctionMaxNode>(args);
302 break;
303 case 8:
304 createTerm();
305 args.push_back(current);
306 createTerm();
307 args.push_back(current);
308 current = QuantLib::ext::make_shared<FunctionMinNode>(args);
309 break;
310 case 9:
311 createTerm();
312 args.push_back(current);
313 createTerm();
314 args.push_back(current);
315 current = QuantLib::ext::make_shared<FunctionPowNode>(args);
316 break;
317 case 10:
318 createTerm();
319 args.push_back(current);
320 createTerm();
321 args.push_back(current);
322 createTerm();
323 args.push_back(current);
324 createTerm();
325 args.push_back(current);
326 createTerm();
327 args.push_back(current);
328 createTerm();
329 args.push_back(current);
330 current = QuantLib::ext::make_shared<FunctionBlackNode>(args);
331 break;
332 case 11:
333 createVarExpr();
334 args.push_back(current);
335 createVarExpr();
336 args.push_back(current);
337 createVarExpr();
338 args.push_back(current);
339 current = QuantLib::ext::make_shared<FunctionDcfNode>(args);
340 break;
341 case 12:
342 createVarExpr();
343 args.push_back(current);
344 createVarExpr();
345 args.push_back(current);
346 createVarExpr();
347 args.push_back(current);
348 current = QuantLib::ext::make_shared<FunctionDaysNode>(args);
349 break;
350 case 13:
351 createTerm();
352 args.push_back(current);
353 createTerm();
354 args.push_back(current);
355 createTerm();
356 args.push_back(current);
357 createTerm();
358 args.push_back(current);
359 current = QuantLib::ext::make_shared<FunctionPayNode>(args);
360 break;
361 case 14: {
362 createTerm();
363 args.push_back(current);
364 createTerm();
365 args.push_back(current);
366 createTerm();
367 args.push_back(current);
368 createTerm();
369 args.push_back(current);
370 int l = legNo(gen_);
371 if (l) {
372 createTerm();
373 args.push_back(current);
374 args.push_back(QuantLib::ext::make_shared<VariableNode>(createVariableName()));
375 int s = slot(gen_);
376 if (s) {
377 createTerm();
378 args.push_back(current);
379 }
380 }
381 current = QuantLib::ext::make_shared<FunctionLogPayNode>(args);
382 break;
383 }
384 case 15:
385 createTerm();
386 args.push_back(current);
387 createTerm();
388 args.push_back(current);
389 if (yn(gen_)) {
390 createCondition();
391 args.push_back(current);
392 if (yn(gen_)) {
393 createTerm();
394 args.push_back(current);
395 if (yn(gen_)) {
396 createTerm();
397 args.push_back(current);
398 }
399 }
400 }
401 current = QuantLib::ext::make_shared<FunctionNpvNode>(args);
402 break;
403 case 16:
404 createTerm();
405 args.push_back(current);
406 createTerm();
407 args.push_back(current);
408 createTerm();
409 args.push_back(current);
410 if (yn(gen_)) {
411 createCondition();
412 args.push_back(current);
413 if (yn(gen_)) {
414 createTerm();
415 args.push_back(current);
416 if (yn(gen_)) {
417 createTerm();
418 args.push_back(current);
419 }
420 }
421 }
422 current = QuantLib::ext::make_shared<FunctionNpvMemNode>(args);
423 break;
424 case 17:
425 createVarExpr();
426 args.push_back(current);
427 createVarExpr();
428 args.push_back(current);
429 current = QuantLib::ext::make_shared<HistFixingNode>(args);
430 break;
431 case 18:
432 createTerm();
433 args.push_back(current);
434 createTerm();
435 args.push_back(current);
436 createTerm();
437 args.push_back(current);
438 current = QuantLib::ext::make_shared<FunctionDiscountNode>(args);
439 break;
440 case 19:
441 createVarExpr();
442 args.push_back(current);
443 createVarExpr();
444 args.push_back(current);
445 createVarExpr();
446 args.push_back(current);
447 createVarExpr();
448 args.push_back(current);
449 switch (zero123(gen_)) {
450 case 0:
451 // 4 + 4 + 2 optional args
452 createTerm();
453 args.push_back(current);
454 createTerm();
455 args.push_back(current);
456 createTerm();
457 args.push_back(current);
458 createTerm();
459 args.push_back(current);
460 case 1:
461 // 4 +2 optional args
462 createTerm();
463 args.push_back(current);
464 createTerm();
465 args.push_back(current);
466 createTerm();
467 args.push_back(current);
468 createTerm();
469 args.push_back(current);
470 case 2:
471 // 2 optional args
472 createTerm();
473 args.push_back(current);
474 createTerm();
475 args.push_back(current);
476 case 3:
477 // no optional args
478 break;
479 default:
480 QL_FAIL("internal error");
481 }
482 current = QuantLib::ext::make_shared<FunctionFwdCompNode>(args);
483 break;
484 case 20:
485 createVarExpr();
486 args.push_back(current);
487 createVarExpr();
488 args.push_back(current);
489 createVarExpr();
490 args.push_back(current);
491 createVarExpr();
492 args.push_back(current);
493 switch (zero123(gen_)) {
494 case 0:
495 // 4 + 4 + 2 optional args
496 createTerm();
497 args.push_back(current);
498 createTerm();
499 args.push_back(current);
500 createTerm();
501 args.push_back(current);
502 createTerm();
503 args.push_back(current);
504 case 1:
505 // 4 +2 optional args
506 createTerm();
507 args.push_back(current);
508 createTerm();
509 args.push_back(current);
510 createTerm();
511 args.push_back(current);
512 createTerm();
513 args.push_back(current);
514 case 2:
515 // 2 optional args
516 createTerm();
517 args.push_back(current);
518 createTerm();
519 args.push_back(current);
520 case 3:
521 // no optional args
522 break;
523 default:
524 QL_FAIL("internal error");
525 }
526 current = QuantLib::ext::make_shared<FunctionFwdAvgNode>(args);
527 break;
528 case 21:
529 createVarExpr();
530 args.push_back(current);
531 createVarExpr();
532 args.push_back(current);
533 createVarExpr();
534 args.push_back(current);
535 createTerm();
536 args.push_back(current);
537 current = QuantLib::ext::make_shared<FunctionAboveProbNode>(args);
538 break;
539 case 22:
540 createVarExpr();
541 args.push_back(current);
542 createVarExpr();
543 args.push_back(current);
544 createVarExpr();
545 args.push_back(current);
546 createTerm();
547 args.push_back(current);
548 current = QuantLib::ext::make_shared<FunctionBelowProbNode>(args);
549 break;
550 case 23: {
551 createVarExpr();
552 args.push_back(current);
553 boost::fusion::vector<std::string, std::string> p(createVariableName(), createVariableName());
554 current = QuantLib::ext::make_shared<FunctionDateIndexNode>(p, args);
555 break;
556 }
557 case 24:
558 createVarExpr();
559 args.push_back(current);
560 current = QuantLib::ext::make_shared<VariableNode>(createVariableName(), args);
561 break;
562 case 25:
563 createVarExpr();
564 args.push_back(current);
565 createVarExpr();
566 args.push_back(current);
567 if (yn(gen_)) {
568 createVarExpr();
569 args.push_back(current);
570 }
571 current = QuantLib::ext::make_shared<VarEvaluationNode>(args);
572 break;
573 default:
574 QL_FAIL("internal error");
575 }
576 }
577 --depth;
578 }
579
580 void createVarExpr() {
581 std::uniform_int_distribution<> dep(0, maxDepth_);
582 ++depth;
583 if (depth + dep(gen_) > maxDepth_) {
584 current = QuantLib::ext::make_shared<VariableNode>(createVariableName());
585 } else {
586 createTerm();
587 current = QuantLib::ext::make_shared<VariableNode>(createVariableName(), std::vector<ASTNodePtr>{current});
588 }
589 --depth;
590 }
591
592 std::string createVariableName() {
593 std::uniform_int_distribution<> id(1, 999); // does not matter really
594 return "Var" + std::to_string(id(gen_));
595 }
596
597 double createConstantNumber() {
598 std::uniform_int_distribution<> yn(0, 1);
599 std::uniform_int_distribution<> whole(-999, 999);
600 std::uniform_real_distribution<> real(-999, 999);
601 if (yn(gen_))
602 return static_cast<double>(whole(gen_));
603 else
604 return std::stod(std::to_string(real(gen_)));
605 }
606
607 ASTNodePtr current;
608 Size depth = 0;
609
610private:
611 const Size maxSequenceLength_, maxDepth_;
612 //
613 std::mt19937 gen_;
614};
615
616ASTNodePtr generateRandomAST(const Size maxSequenceLength, const Size maxDepth, const Size seed) {
617 RandomASTGenerator gen(maxSequenceLength, maxDepth, seed);
618 gen.createInstructionSequence();
619 return gen.current;
620}
621
622} // namespace data
623} // namespace ore
@ data
Definition: log.hpp:77
ASTNodePtr generateRandomAST(const Size maxSequenceLength, const Size maxDepth, const Size seed)
QuantLib::ext::shared_ptr< ASTNode > ASTNodePtr
Definition: ast.hpp:46
Serializable Credit Default Swap.
Definition: namespaces.docs:23
random ast generator for testing purposes