SDDS ToolKit Programs and Libraries for C and Python
All Classes Files Functions Variables Macros Pages
convert_to_bdd.c
Go to the documentation of this file.
1/**
2 * @file convert_to_bdd.c
3 * @brief Converts a fault tree database in SDDS format to a Binary Decision Diagram (BDD) representation.
4 *
5 * @details
6 * This program processes a fault tree database, computes the fault probabilities of each base element
7 * within the fault sub-trees, and outputs the results in a specified format. It supports various options
8 * to customize the processing, including specifying known good or bad elements, piping input/output,
9 * and verbose output for detailed processing information.
10 *
11 * @section Usage
12 * ```
13 * convert_to_bdd <database_file> <output_file>
14 * [-pipe=[input][,output]]
15 * [-goodElements=<list_of_base_IDs>]
16 * [-badElements=<list_of_base_IDs>]
17 * [-verbose]
18 * [-failedSubTrees=<list_of_sub_tree_IDs>]
19 * ```
20 *
21 * @section Options
22 * | Optional | Description |
23 * |---------------------------------------|--------------------------------------------------|
24 * | `-pipe` | Enables piping for input and/or output. |
25 * | `-goodElements` | Base elements with fault probability 0. |
26 * | `-badElements` | Base elements with fault probability 1. |
27 * | `-verbose` | Enables verbose output. |
28 * | `-failedSubTrees` | List of sub-trees to compute (default: all). |
29 *
30 * @subsection Incompatibilities
31 * - Only one of the following can be specified:
32 * - `-goodElements`
33 * - `-badElements`
34 *
35 * @copyright
36 * - (c) 2002 The University of Chicago, as Operator of Argonne National Laboratory.
37 * - (c) 2002 The Regents of the University of California, as Operator of Los Alamos National Laboratory.
38 *
39 * @license
40 * This file is distributed under the terms of the Software License Agreement
41 * found in the file LICENSE included with this distribution.
42 *
43 * @author
44 * H. Shang, R. Soliday
45 */
46
47#include "mdb.h"
48#include "scan.h"
49#include "SDDS.h"
50#include <sys/types.h>
51
52/* Enumeration for option types */
53enum option_type {
54 CLO_GOOD_ELEMENTS,
55 CLO_BAD_ELEMENTS,
56 CLO_FAILED_SUB_TREES,
57 CLO_PIPE,
58 CLO_VERBOSE,
59 N_OPTIONS
60};
61
62char *option[N_OPTIONS] = {
63 "goodElements",
64 "badElements",
65 "failedSubTrees",
66 "pipe",
67 "verbose"
68};
69
70static char *USAGE =
71 "Usage: convert_to_bdd [<database_file>] [<output_file>]\n"
72 " [-pipe=[input][,output]]\n"
73 " [-goodElements=<list_of_base_IDs>]\n"
74 " [-badElements=<list_of_base_IDs>]\n"
75 " [-verbose]\n"
76 " [-failedSubTrees=<list_of_sub_tree_IDs>]\n"
77 "Options:\n"
78 " -pipe=<input>,<output> Enable piping for input and/or output.\n"
79 " -goodElements=<base_IDs> Comma-separated list of base elements with fault probability 0.\n"
80 " -badElements=<base_IDs> Comma-separated list of base elements with fault probability 1.\n"
81 " -failedSubTrees=<sub_tree_IDs> Comma-separated list of sub-trees to compute.\n"
82 " -verbose Enable verbose output for detailed processing information.\n\n";
83
84/* Structure Definitions */
85typedef struct {
86 long id;
87 double probability, ps, pes, MIF, DIF;
88 char *label;
89 char *guidance, *description;
90} BASE;
91
92typedef struct {
93 BASE *base; /* First element is base */
94 void *left; /* Second element is a pointer, could be base or ITE */
95 void *right; /* Third element is a pointer, could be base or ITE */
96 short is_base;
97 double probability, p1, p0, ps, pes;
98 double MIF, DIF;
99 char *description, *guidance, *label;
100 long ID;
101} ITE;
102
103typedef struct {
104 ITE **ite_ptr;
105 long ites;
106 long *tree_ID;
107 int32_t ID;
108 char *description, *tree_name, *typeDesc;
109 short type; /* 0 for AND, 1 for OR */
110 short all_base; /* Members of sub-tree are all base elements */
111 short calculated;
112 double p1, p0, ps;
113 ITE *CAL_ITE;
114} SUB_TREE;
115
116/* Function Prototypes */
117ITE *bdd_ite_cal(ITE *ite1, ITE *ite2, short type);
118ITE *bdd_base_ite_cal(BASE *base, ITE *ite, short type);
119ITE *bdd_base_base_cal(BASE *base1, BASE *base2, short type);
120void load_data_base(char *filename);
121void print_sub_tree(ITE *ite);
122short is_base(ITE *ite);
123void free_cal_ite(ITE *ite);
124void locate_tree_id();
125double compute_ps(ITE *ite);
126void SetupOutputFile(char *outputFile, SDDS_DATASET *outData);
127
128/* Stack Definitions */
129#define STACKSIZE 2000
130long treeStack1[STACKSIZE];
131long treeStackptr1 = 0;
132long treeStack[STACKSIZE];
133long treeStackptr = 0;
134
135long push_node(long ID);
136long pop_node(void);
137void push_sub_tree(ITE *ite);
138void push_sub_tree1(ITE *ite);
139double compute_ps(ITE *ite);
140void compute_sub_tree_ps(ITE *ite, SDDS_DATASET *outData, long treeIndex);
141long push_node1(long ID);
142long pop_node1(void);
143
144/* Global Variables */
145static BASE **base = NULL;
146static long bases = 0;
147static SUB_TREE *sub_tree = NULL;
148static long sub_trees = 0;
149static ITE **ite = NULL;
150static long ites = 0;
151
152static ITE **ite_ptr = NULL;
153static long ite_ptrs = 0;
154static long verbose = 0;
155
156int main(int argc, char **argv) {
157 SCANNED_ARG *s_arg;
158 SDDS_DATASET outData;
159 long i, j, alldone = 0, ready, tree_ID;
160 char *inputFile = NULL, *outputFile = NULL;
161 ITE *ite1, *ite2;
162 char **badBase = NULL, **goodBase = NULL, **failedTree = NULL;
163 long badBases = 0, goodBases = 0, failedTrees = 0, i_arg, tmpfile_used = 0, compute = 0;
164 unsigned long pipeFlags = 0;
165
166 argc = scanargs(&s_arg, argc, argv);
167 if (argc < 3) {
168 fprintf(stderr, "Error: Insufficient arguments provided.\n\n%s", USAGE);
169 exit(EXIT_FAILURE);
170 }
171
172 for (i_arg = 1; i_arg < argc; i_arg++) {
173 if (s_arg[i_arg].arg_type == OPTION) {
174 delete_chars(s_arg[i_arg].list[0], "_");
175 switch (match_string(s_arg[i_arg].list[0], option, N_OPTIONS, 0)) {
176 case CLO_GOOD_ELEMENTS:
177 goodBases = s_arg[i_arg].n_items - 1;
178 goodBase = malloc(sizeof(*goodBase) * goodBases);
179 if (!goodBase) {
180 fprintf(stderr, "Error: Memory allocation failed for goodBase.\n");
181 exit(EXIT_FAILURE);
182 }
183 for (i = 0; i < goodBases; i++)
184 goodBase[i] = s_arg[i_arg].list[i + 1];
185 break;
186 case CLO_BAD_ELEMENTS:
187 badBases = s_arg[i_arg].n_items - 1;
188 badBase = malloc(sizeof(*badBase) * badBases);
189 if (!badBase) {
190 fprintf(stderr, "Error: Memory allocation failed for badBase.\n");
191 exit(EXIT_FAILURE);
192 }
193 for (i = 0; i < badBases; i++)
194 badBase[i] = s_arg[i_arg].list[i + 1];
195 break;
196 case CLO_FAILED_SUB_TREES:
197 failedTrees = s_arg[i_arg].n_items - 1;
198 failedTree = malloc(sizeof(*failedTree) * failedTrees);
199 if (!failedTree) {
200 fprintf(stderr, "Error: Memory allocation failed for failedTree.\n");
201 exit(EXIT_FAILURE);
202 }
203 for (i = 0; i < failedTrees; i++)
204 failedTree[i] = s_arg[i_arg].list[i + 1];
205 break;
206 case CLO_PIPE:
207 if (!processPipeOption(s_arg[i_arg].list + 1, s_arg[i_arg].n_items - 1, &pipeFlags)) {
208 fprintf(stderr, "Error: Invalid -pipe syntax.\n");
209 exit(EXIT_FAILURE);
210 }
211 break;
212 case CLO_VERBOSE:
213 verbose = 1;
214 break;
215 default:
216 fprintf(stderr, "Unknown option: %s\n", s_arg[i_arg].list[0]);
217 exit(EXIT_FAILURE);
218 }
219 } else {
220 if (!inputFile)
221 inputFile = s_arg[i_arg].list[0];
222 else if (!outputFile)
223 outputFile = s_arg[i_arg].list[0];
224 else {
225 fprintf(stderr, "Error: Too many filenames provided (%s).\n", s_arg[i_arg].list[0]);
226 exit(EXIT_FAILURE);
227 }
228 }
229 }
230
231 processFilenames("convert_to_bdd", &inputFile, &outputFile, pipeFlags, 1, &tmpfile_used);
232
233 load_data_base(inputFile);
234 locate_tree_id();
235
236 if (goodBases) {
237 for (i = 0; i < goodBases; i++) {
238 for (j = 0; j < bases; j++) {
239 if (strcmp(goodBase[i], base[j]->label) == 0) {
240 base[j]->probability = 0.0;
241 break;
242 }
243 }
244 }
245 free(goodBase);
246 }
247
248 if (badBases) {
249 for (i = 0; i < badBases; i++) {
250 for (j = 0; j < bases; j++) {
251 if (strcmp(badBase[i], base[j]->label) == 0) {
252 base[j]->probability = 1.0;
253 break;
254 }
255 }
256 }
257 free(badBase);
258 }
259
260 SetupOutputFile(outputFile, &outData);
261
262 for (i = 0; i < sub_trees; i++) {
263 compute = 0;
264 if (sub_tree[i].all_base) {
265 if (verbose) {
266 fprintf(stdout, "\nSub-tree Name: %s, ID: %d, ITE Structure:\n", sub_tree[i].tree_name, sub_tree[i].ID);
267 print_sub_tree(sub_tree[i].CAL_ITE);
268 }
269 if (failedTrees) {
270 for (j = 0; j < failedTrees; j++) {
271 if (strcmp(sub_tree[i].tree_name, failedTree[j]) == 0) {
272 compute = 1;
273 break;
274 }
275 }
276 } else {
277 compute = 1;
278 }
279 if (compute)
280 compute_sub_tree_ps(sub_tree[i].CAL_ITE, &outData, i);
281 }
282 }
283
284 while (1) {
285 alldone = 1;
286 for (i = 0; i < sub_trees; i++) {
287 if (sub_tree[i].calculated)
288 continue;
289 else {
290 alldone = 0;
291 ready = 1;
292 for (j = 0; j < sub_tree[i].ites; j++) {
293 tree_ID = sub_tree[i].tree_ID[j];
294 if (tree_ID >= 0 && sub_tree[tree_ID].calculated == 0) {
295 ready = 0;
296 break;
297 }
298 }
299 if (ready) {
300 if (sub_tree[i].ites == 1)
301 sub_tree[i].CAL_ITE = sub_tree[i].ite_ptr[0];
302 else {
303 if (sub_tree[i].ite_ptr[0]->base && is_base(sub_tree[i].ite_ptr[0]))
304 ite1 = sub_tree[i].ite_ptr[0];
305 else
306 ite1 = sub_tree[sub_tree[i].tree_ID[0]].CAL_ITE;
307
308 if (sub_tree[i].ite_ptr[1]->base && is_base(sub_tree[i].ite_ptr[1]))
309 ite2 = sub_tree[i].ite_ptr[1];
310 else
311 ite2 = sub_tree[sub_tree[i].tree_ID[1]].CAL_ITE;
312
313 sub_tree[i].CAL_ITE = bdd_ite_cal(ite1, ite2, sub_tree[i].type);
314
315 for (j = 2; j < sub_tree[i].ites; j++) {
316 if (sub_tree[i].ite_ptr[j]->base && is_base(sub_tree[i].ite_ptr[j]))
317 ite1 = sub_tree[i].ite_ptr[j];
318 else
319 ite1 = sub_tree[sub_tree[i].tree_ID[j]].CAL_ITE;
320
321 sub_tree[i].CAL_ITE = bdd_ite_cal(sub_tree[i].CAL_ITE, ite1, sub_tree[i].type);
322 }
323
324 if (verbose) {
325 fprintf(stdout, "\nSub-tree Name: %s, ID: %d, ITE Structure:\n", sub_tree[i].tree_name, sub_tree[i].ID);
326 print_sub_tree(sub_tree[i].CAL_ITE);
327 }
328
329 compute = 0;
330 if (failedTrees) {
331 for (j = 0; j < failedTrees; j++) {
332 if (strcmp(sub_tree[i].tree_name, failedTree[j]) == 0) {
333 compute = 1;
334 break;
335 }
336 }
337 } else {
338 compute = 1;
339 }
340 if (compute)
341 compute_sub_tree_ps(sub_tree[i].CAL_ITE, &outData, i);
342 }
343 sub_tree[i].calculated = 1;
344 }
345 }
346 }
347 if (alldone)
348 break;
349 }
350
351 if (failedTrees)
352 free(failedTree);
353
354 if (!SDDS_Terminate(&outData))
355 SDDS_PrintErrors(stdout, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
356
357 /* Freeing allocated memory */
358 for (i = 0; i < bases; i++) {
359 free(base[i]->guidance);
360 free(base[i]->label);
361 free(base[i]->description);
362 free(base[i]);
363 }
364 free(base);
365
366 for (i = 0; i < ites; i++) {
367 if (ite[i]->left)
368 free((ITE *)(ite[i]->left));
369 if (ite[i]->right)
370 free((ITE *)(ite[i]->right));
371 free(ite[i]->description);
372 free(ite[i]->guidance);
373 free(ite[i]->label);
374 free(ite[i]);
375 }
376 free(ite);
377
378 for (i = 0; i < sub_trees; i++) {
379 free(sub_tree[i].description);
380 free(sub_tree[i].tree_name);
381 free(sub_tree[i].typeDesc);
382 free(sub_tree[i].ite_ptr);
383 free(sub_tree[i].tree_ID);
384 }
385 free(sub_tree);
386
387 for (i = 0; i < ite_ptrs; i++) {
388 if (ite_ptr[i]->guidance)
389 free(ite_ptr[i]->guidance);
390 if (ite_ptr[i]->description)
391 free(ite_ptr[i]->description);
392 if (ite_ptr[i]->label)
393 free(ite_ptr[i]->label);
394 free(ite_ptr[i]);
395 }
396 free(ite_ptr);
397 free_scanargs(&s_arg, argc);
398
399 return EXIT_SUCCESS;
400}
401
402short is_base(ITE *ite) {
403 return (ite->left == NULL && ite->right == NULL) || ite->is_base;
404}
405
406ITE *bdd_base_base_cal(BASE *base1, BASE *base2, short type) {
407 ITE *tmp = calloc(1, sizeof(*tmp));
408 BASE *base_s, *base_b;
409
410 if (!tmp) {
411 fprintf(stderr, "Error: Memory allocation failed in bdd_base_base_cal.\n");
412 exit(EXIT_FAILURE);
413 }
414
415 tmp->left = tmp->right = NULL;
416
417 /* Remember allocated ITE pointers for later freeing */
418 ite_ptr = SDDS_Realloc(ite_ptr, sizeof(*ite_ptr) * (ite_ptrs + 1));
419 if (!ite_ptr) {
420 fprintf(stderr, "Error: Memory reallocation failed in bdd_base_base_cal.\n");
421 exit(EXIT_FAILURE);
422 }
423 ite_ptr[ite_ptrs++] = tmp;
424
425 if (base1->id == base2->id) {
426 /* a + a = a; a * a = a */
427 tmp->base = base1;
428 tmp->is_base = 1;
429 return tmp;
430 }
431
432 if (base1->id < base2->id) {
433 base_s = base1;
434 base_b = base2;
435 } else {
436 base_s = base2;
437 base_b = base1;
438 }
439
440 if (type == 0) {
441 /* AND logic: ITE(base_s, base_b, 0) */
442 tmp->base = base_s;
443 tmp->left = calloc(1, sizeof(ITE));
444 if (!tmp->left) {
445 fprintf(stderr, "Error: Memory allocation failed for tmp->left in bdd_base_base_cal.\n");
446 exit(EXIT_FAILURE);
447 }
448 ((ITE *)tmp->left)->base = base_b;
449 ((ITE *)tmp->left)->left = ((ITE *)tmp->left)->right = NULL;
450
451 tmp->right = NULL;
452
453 ite_ptr = SDDS_Realloc(ite_ptr, sizeof(*ite_ptr) * (ite_ptrs + 1));
454 if (!ite_ptr) {
455 fprintf(stderr, "Error: Memory reallocation failed for tmp->left in bdd_base_base_cal.\n");
456 exit(EXIT_FAILURE);
457 }
458 ite_ptr[ite_ptrs++] = (ITE *)tmp->left;
459 } else {
460 /* OR logic: ITE(base_s, 1, base_b) */
461 tmp->base = base_s;
462 tmp->left = NULL;
463 tmp->right = calloc(1, sizeof(ITE));
464 if (!tmp->right) {
465 fprintf(stderr, "Error: Memory allocation failed for tmp->right in bdd_base_base_cal.\n");
466 exit(EXIT_FAILURE);
467 }
468 ((ITE *)tmp->right)->base = base_b;
469 ((ITE *)tmp->right)->left = ((ITE *)tmp->right)->right = NULL;
470
471 ite_ptr = SDDS_Realloc(ite_ptr, sizeof(*ite_ptr) * (ite_ptrs + 1));
472 if (!ite_ptr) {
473 fprintf(stderr, "Error: Memory reallocation failed for tmp->right in bdd_base_base_cal.\n");
474 exit(EXIT_FAILURE);
475 }
476 ite_ptr[ite_ptrs++] = (ITE *)tmp->right;
477 }
478
479 return tmp;
480}
481
482ITE *bdd_base_ite_cal(BASE *base, ITE *ite, short type) {
483 ITE *tmp = calloc(1, sizeof(*tmp));
484 ITE *left, *right;
485 BASE *base1 = ite->base;
486
487 if (!tmp) {
488 fprintf(stderr, "Error: Memory allocation failed in bdd_base_ite_cal.\n");
489 exit(EXIT_FAILURE);
490 }
491
492 ite_ptr = SDDS_Realloc(ite_ptr, sizeof(*ite_ptr) * (ite_ptrs + 1));
493 if (!ite_ptr) {
494 fprintf(stderr, "Error: Memory reallocation failed in bdd_base_ite_cal.\n");
495 exit(EXIT_FAILURE);
496 }
497 ite_ptr[ite_ptrs++] = tmp;
498
499 left = (ITE *)ite->left;
500 right = (ITE *)ite->right;
501
502 if (base->id < base1->id) {
503 tmp->base = base;
504 if (type == 1) {
505 /* OR logic: ITE(base, 1, ite) */
506 tmp->left = NULL;
507 tmp->right = ite;
508 } else {
509 /* AND logic: ITE(base, ite, 0) */
510 tmp->left = ite;
511 tmp->right = NULL;
512 }
513 } else if (base->id > base1->id) {
514 tmp->base = ite->base;
515 if (!left) {
516 if (type == 0) {
517 tmp->left = calloc(1, sizeof(ITE));
518 if (!tmp->left) {
519 fprintf(stderr, "Error: Memory allocation failed for tmp->left in bdd_base_ite_cal.\n");
520 exit(EXIT_FAILURE);
521 }
522 ((ITE *)tmp->left)->base = base;
523 ((ITE *)tmp->left)->left = ((ITE *)tmp->left)->right = NULL;
524
525 ite_ptr = SDDS_Realloc(ite_ptr, sizeof(*ite_ptr) * (ite_ptrs + 1));
526 if (!ite_ptr) {
527 fprintf(stderr, "Error: Memory reallocation failed for tmp->left in bdd_base_ite_cal.\n");
528 exit(EXIT_FAILURE);
529 }
530 ite_ptr[ite_ptrs++] = (ITE *)tmp->left;
531 } else {
532 tmp->left = NULL; /* OR logic: 1 */
533 }
534 } else {
535 tmp->left = bdd_base_ite_cal(base, (ITE *)ite->left, type);
536 }
537
538 if (!right) {
539 if (type == 0)
540 tmp->right = NULL; /* AND logic: 0 */
541 else {
542 tmp->right = calloc(1, sizeof(ITE));
543 if (!tmp->right) {
544 fprintf(stderr, "Error: Memory allocation failed for tmp->right in bdd_base_ite_cal.\n");
545 exit(EXIT_FAILURE);
546 }
547 ((ITE *)tmp->right)->base = base;
548 ((ITE *)tmp->right)->left = ((ITE *)tmp->right)->right = NULL;
549
550 ite_ptr = SDDS_Realloc(ite_ptr, sizeof(*ite_ptr) * (ite_ptrs + 1));
551 if (!ite_ptr) {
552 fprintf(stderr, "Error: Memory reallocation failed for tmp->right in bdd_base_ite_cal.\n");
553 exit(EXIT_FAILURE);
554 }
555 ite_ptr[ite_ptrs++] = (ITE *)tmp->right;
556 }
557 } else {
558 tmp->right = bdd_base_ite_cal(base, (ITE *)ite->right, type);
559 }
560 } else {
561 tmp->base = base;
562 if (type == 0) {
563 tmp->left = left; /* AND logic: 1 * left */
564 tmp->right = NULL; /* AND logic: 0 */
565 } else {
566 tmp->left = NULL; /* OR logic: 1 */
567 tmp->right = right; /* OR logic: right */
568 }
569 }
570
571 return tmp;
572}
573
574ITE *bdd_ite_cal(ITE *ite1, ITE *ite2, short type) {
575 ITE *ite = calloc(1, sizeof(*ite));
576 ITE *ite_l, *ite_r;
577 BASE *base1 = NULL, *base2 = NULL;
578
579 if (!ite) {
580 fprintf(stderr, "Error: Memory allocation failed in bdd_ite_cal.\n");
581 exit(EXIT_FAILURE);
582 }
583
584 if (!ite1 || !ite2) {
585 fprintf(stderr, "Error: Null pointer provided to bdd_ite_cal().\n");
586 exit(EXIT_FAILURE);
587 }
588
589 if (is_base(ite1) && is_base(ite2))
590 return bdd_base_base_cal(ite1->base, ite2->base, type);
591
592 if (is_base(ite1))
593 return bdd_base_ite_cal(ite1->base, ite2, type);
594 if (is_base(ite2))
595 return bdd_base_ite_cal(ite2->base, ite1, type);
596
597 base1 = ite1->base;
598 base2 = ite2->base;
599
600 ite_ptr = SDDS_Realloc(ite_ptr, sizeof(*ite_ptr) * (ite_ptrs + 1));
601 if (!ite_ptr) {
602 fprintf(stderr, "Error: Memory reallocation failed in bdd_ite_cal.\n");
603 exit(EXIT_FAILURE);
604 }
605 ite_ptr[ite_ptrs++] = ite;
606
607 if (base1->id == base2->id) {
608 ite->base = ite1->base;
609 if (ite1->left && ite2->left)
610 ite->left = bdd_ite_cal((ITE *)ite1->left, (ITE *)ite2->left, type);
611 else {
612 if (type == 1)
613 ite->left = NULL; /* OR logic: 1 */
614 else {
615 /* AND logic: any left */
616 ite->left = ite1->left ? ite1->left : ite2->left;
617 }
618 }
619
620 if (ite1->right && ite2->right)
621 ite->right = bdd_ite_cal((ITE *)ite1->right, (ITE *)ite2->right, type);
622 else {
623 if (type == 0)
624 ite->right = NULL; /* AND logic: 0 */
625 else {
626 /* OR logic: any right */
627 ite->right = ite1->right ? ite1->right : ite2->right;
628 }
629 }
630 } else {
631 if (base1->id < base2->id) {
632 ite_l = ite1;
633 ite_r = ite2;
634 } else {
635 ite_l = ite2;
636 ite_r = ite1;
637 }
638 ite->base = ite_l->base;
639
640 if (ite_l->left)
641 ite->left = bdd_ite_cal(ite_l->left, ite_r, type);
642 else {
643 if (type == 0)
644 ite->left = ite_r;
645 else
646 ite->left = NULL;
647 }
648
649 if (ite_l->right)
650 ite->right = bdd_ite_cal(ite_l->right, ite_r, type);
651 else {
652 if (type == 0)
653 ite->right = NULL;
654 else
655 ite->right = ite_r;
656 }
657 }
658
659 return ite;
660}
661
662void load_data_base(char *filename) {
663 int32_t i, rows, pages, j, allbase, index;
664 int32_t *id = NULL;
665 double *prob = NULL;
666 char **guid = NULL, **desc = NULL, **label = NULL;
667 SDDS_DATASET table;
668
669 if (!SDDS_InitializeInput(&table, filename))
670 SDDS_PrintErrors(stdout, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
671
672 pages = 0;
673 sub_tree = NULL;
674 ite = NULL;
675
676 while (SDDS_ReadPage(&table) > 0) {
677 if (!(rows = SDDS_CountRowsOfInterest(&table)))
678 continue;
679
680 sub_tree = SDDS_Realloc(sub_tree, sizeof(*sub_tree) * (pages + 1));
681 if (!sub_tree) {
682 fprintf(stderr, "Error: Memory reallocation failed for sub_tree.\n");
683 exit(EXIT_FAILURE);
684 }
685
686 sub_tree[pages].ites = rows;
687 sub_tree[pages].ite_ptr = malloc(sizeof(ITE *) * rows);
688 if (!sub_tree[pages].ite_ptr) {
689 fprintf(stderr, "Error: Memory allocation failed for sub_tree[%" PRId32 "].ite_ptr.\n", pages);
690 exit(EXIT_FAILURE);
691 }
692
693 sub_tree[pages].calculated = 0;
694
695 if (!SDDS_GetParameter(&table, "Description", &sub_tree[pages].description) ||
696 !SDDS_GetParameter(&table, "ID", &sub_tree[pages].ID) ||
697 !SDDS_GetParameter(&table, "LogicalType", &sub_tree[pages].type) ||
698 !SDDS_GetParameter(&table, "LogicalTypeDesc", &sub_tree[pages].typeDesc) ||
699 !SDDS_GetParameter(&table, "TreeName", &sub_tree[pages].tree_name))
700 SDDS_PrintErrors(stdout, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
701
702 if (!(id = SDDS_GetColumn(&table, "ID")) ||
703 !(prob = SDDS_GetColumn(&table, "Probability")) ||
704 !(desc = SDDS_GetColumn(&table, "Description")) ||
705 !(guid = SDDS_GetColumn(&table, "Guidance")) ||
706 !(label = SDDS_GetColumn(&table, "Label")))
707 SDDS_PrintErrors(stdout, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
708
709 allbase = 1;
710 for (i = 0; i < rows; i++) {
711 if (id[i] > 1000) {
712 /* Base element */
713 index = -1;
714 if (bases) {
715 for (j = 0; j < bases; j++) {
716 if (id[i] == base[j]->id) {
717 index = j;
718 break;
719 }
720 }
721 }
722
723 if (index < 0) {
724 base = SDDS_Realloc(base, sizeof(*base) * (bases + 1));
725 if (!base) {
726 fprintf(stderr, "Error: Memory reallocation failed for base.\n");
727 exit(EXIT_FAILURE);
728 }
729 base[bases] = calloc(1, sizeof(**base));
730 if (!base[bases]) {
731 fprintf(stderr, "Error: Memory allocation failed for base[%ld].\n", bases);
732 exit(EXIT_FAILURE);
733 }
734 base[bases]->id = id[i];
735 base[bases]->probability = prob[i];
736 SDDS_CopyString(&base[bases]->guidance, guid[i]);
737 SDDS_CopyString(&base[bases]->label, label[i]);
738 SDDS_CopyString(&base[bases]->description, desc[i]);
739 index = bases;
740 bases++;
741 }
742
743 sub_tree[pages].ite_ptr[i] = calloc(1, sizeof(ITE));
744 if (!sub_tree[pages].ite_ptr[i]) {
745 fprintf(stderr, "Error: Memory allocation failed for sub_tree[%" PRId32 "].ite_ptr[%d].\n", pages, i);
746 exit(EXIT_FAILURE);
747 }
748
749 sub_tree[pages].ite_ptr[i]->base = base[index];
750 sub_tree[pages].ite_ptr[i]->left = sub_tree[pages].ite_ptr[i]->right = NULL;
751 sub_tree[pages].ite_ptr[i]->ID = id[i];
752 sub_tree[pages].ite_ptr[i]->probability = prob[i];
753 sub_tree[pages].ite_ptr[i]->is_base = 1;
754 SDDS_CopyString(&sub_tree[pages].ite_ptr[i]->guidance, guid[i]);
755 SDDS_CopyString(&sub_tree[pages].ite_ptr[i]->label, label[i]);
756 SDDS_CopyString(&sub_tree[pages].ite_ptr[i]->description, desc[i]);
757
758 /* Remember allocated ITE pointers for later freeing */
759 ite_ptr = SDDS_Realloc(ite_ptr, sizeof(*ite_ptr) * (ite_ptrs + 1));
760 if (!ite_ptr) {
761 fprintf(stderr, "Error: Memory reallocation failed for ite_ptr in load_data_base.\n");
762 exit(EXIT_FAILURE);
763 }
764 ite_ptr[ite_ptrs++] = sub_tree[pages].ite_ptr[i];
765 } else {
766 /* Non-base ITE */
767 index = -1;
768 if (ites) {
769 for (j = 0; j < ites; j++) {
770 if (id[i] == ite[j]->ID) {
771 index = j;
772 break;
773 }
774 }
775 }
776
777 if (index < 0) {
778 ite = SDDS_Realloc(ite, sizeof(*ite) * (ites + 1));
779 if (!ite) {
780 fprintf(stderr, "Error: Memory reallocation failed for ite.\n");
781 exit(EXIT_FAILURE);
782 }
783 ite[ites] = calloc(1, sizeof(ITE));
784 if (!ite[ites]) {
785 fprintf(stderr, "Error: Memory allocation failed for ite[%ld].\n", ites);
786 exit(EXIT_FAILURE);
787 }
788 ite[ites]->ID = id[i];
789 ite[ites]->base = NULL;
790 ite[ites]->probability = prob[i];
791 ite[ites]->is_base = 0;
792 SDDS_CopyString(&ite[ites]->guidance, guid[i]);
793 SDDS_CopyString(&ite[ites]->description, desc[i]);
794 SDDS_CopyString(&ite[ites]->label, label[i]);
795 index = ites;
796 ites++;
797 }
798
799 sub_tree[pages].ite_ptr[i] = ite[index];
800 allbase = 0;
801 }
802 }
803
804 sub_tree[pages].ites = rows;
805 sub_tree[pages].all_base = allbase;
806
807 /* Compute base sub-tree */
808 if (allbase) {
809 if (rows == 1) {
810 sub_tree[pages].CAL_ITE = sub_tree[pages].ite_ptr[0];
811 } else {
812 sub_tree[pages].CAL_ITE = bdd_ite_cal(sub_tree[pages].ite_ptr[0], sub_tree[pages].ite_ptr[1], sub_tree[pages].type);
813 for (j = 2; j < rows; j++) {
814 sub_tree[pages].CAL_ITE = bdd_ite_cal(sub_tree[pages].CAL_ITE, sub_tree[pages].ite_ptr[j], sub_tree[pages].type);
815 }
816 }
817 sub_tree[pages].calculated = 1;
818 }
819
820 /* Free temporary arrays */
821 free(id);
822 free(prob);
823 SDDS_FreeStringArray(guid, rows);
824 SDDS_FreeStringArray(desc, rows);
825 SDDS_FreeStringArray(label, rows);
826 free(label);
827 free(guid);
828 free(desc);
829
830 pages++;
831 }
832
833 if (verbose)
834 fprintf(stdout, "Total Bases: %ld, Total ITEs: %ld\n", bases, ites);
835
836 sub_trees = pages;
837
838 if (!SDDS_Terminate(&table))
839 SDDS_PrintErrors(stdout, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
840}
841
842long push_node(long ID) {
843 if (treeStackptr >= STACKSIZE) {
844 fprintf(stderr, "Error: Stack overflow.\n");
845 exit(EXIT_FAILURE);
846 }
847 treeStack[treeStackptr++] = ID;
848 return 1;
849}
850
851long pop_node(void) {
852 if (treeStackptr < 1) {
853 fprintf(stderr, "Error: Too few items on stack.\n");
854 exit(EXIT_FAILURE);
855 }
856 return treeStack[--treeStackptr];
857}
858
859void print_sub_tree(ITE *ite) {
860 ITE *left, *right;
861 if (!ite->base)
862 return;
863 push_node(ite->base->id);
864 fprintf(stdout, "%ld\n", pop_node());
865 left = (ITE *)ite->left;
866 right = (ITE *)ite->right;
867 if (!left)
868 push_node(1);
869 else
870 push_node(left->base->id);
871 fprintf(stdout, "%ld ", pop_node());
872 if (!right)
873 push_node(0);
874 else
875 push_node(right->base->id);
876 fprintf(stdout, "%ld \n", pop_node());
877 if (left)
878 print_sub_tree(left);
879 if (right)
880 print_sub_tree(right);
881}
882
883void free_cal_ite(ITE *ite) {
884 ITE *left, *right;
885 if (!ite)
886 return;
887 left = (ITE *)(ite->left);
888 right = (ITE *)(ite->right);
889 if (!left && !right) {
890 free(ite);
891 return;
892 }
893 if (left) {
894 if (is_base(left)) {
895 free(left);
896 } else {
897 free_cal_ite(left);
898 }
899 }
900 if (right) {
901 if (is_base(right)) {
902 free(right);
903 } else {
904 free_cal_ite(right);
905 }
906 }
907}
908
909void locate_tree_id() {
910 long i, j, k;
911 for (i = 0; i < sub_trees; i++) {
912 sub_tree[i].tree_ID = malloc(sizeof(long) * sub_tree[i].ites);
913 if (!sub_tree[i].tree_ID) {
914 fprintf(stderr, "Error: Memory allocation failed for sub_tree[%ld].tree_ID.\n", i);
915 exit(EXIT_FAILURE);
916 }
917 for (j = 0; j < sub_tree[i].ites; j++) {
918 sub_tree[i].tree_ID[j] = -1;
919 if (!(sub_tree[i].ite_ptr[j]->base)) {
920 for (k = 0; k < sub_trees; k++) {
921 if (sub_tree[i].ite_ptr[j]->ID == sub_tree[k].ID) {
922 sub_tree[i].tree_ID[j] = k;
923 break;
924 }
925 }
926 if (sub_tree[i].tree_ID[j] < 0) {
927 fprintf(stderr, "Error: No tree_ID found for ITE %ld of tree %ld (%s).\n",
928 j, i, sub_tree[i].tree_name);
929 exit(EXIT_FAILURE);
930 }
931 }
932 }
933 }
934}
935
936void push_sub_tree(ITE *ite) {
937 ITE *left, *right;
938 push_node((long)ite);
939 left = ite->left;
940 right = ite->right;
941 if (!left)
942 push_node(1);
943 else
944 push_node((long)left);
945 if (!right)
946 push_node(0);
947 else
948 push_node((long)right);
949 if (left)
950 push_sub_tree(left);
951 if (right)
952 push_sub_tree(right);
953}
954
955double compute_ps(ITE *ite) {
956 ITE *left, *right, *c_ite = NULL;
957 long left_adr, right_adr;
958 double p;
959 push_sub_tree1(ite);
960 while (treeStackptr1 > 0) {
961 right_adr = pop_node1();
962 left_adr = pop_node1();
963 c_ite = (ITE *)pop_node1();
964 p = c_ite->base->probability;
965 if (left_adr == 1) {
966 c_ite->p1 = 1.0;
967 } else {
968 left = (ITE *)left_adr;
969 c_ite->p1 = left->ps;
970 }
971 if (right_adr == 0) {
972 c_ite->p0 = 0.0;
973 } else {
974 right = (ITE *)right_adr;
975 c_ite->p0 = right->ps;
976 }
977 c_ite->ps = p * c_ite->p1 + (1.0 - p) * c_ite->p0;
978 }
979 return c_ite->ps;
980}
981
982void compute_sub_tree_ps(ITE *ite, SDDS_DATASET *outData, long treeIndex) {
983 ITE *t_ite;
984 long this_adr;
985 long t_bases = 0, i, index;
986 BASE **t_base = NULL, *base1;
987 double prob, PS;
988
989 /* First compute system PS */
990 PS = compute_ps(ite);
991
992 push_sub_tree(ite);
993 while (treeStackptr > 0) {
994 this_adr = pop_node();
995 if (this_adr != 1 && this_adr != 0) {
996 t_ite = (ITE *)this_adr;
997 base1 = t_ite->base;
998 index = -1;
999 if (!t_bases) {
1000 t_base = SDDS_Realloc(t_base, sizeof(*t_base) * (t_bases + 1));
1001 if (!t_base) {
1002 fprintf(stderr, "Error: Memory reallocation failed for t_base in compute_sub_tree_ps.\n");
1003 exit(EXIT_FAILURE);
1004 }
1005 t_base[t_bases] = base1;
1006 t_bases++;
1007 } else {
1008 for (i = 0; i < t_bases; i++) {
1009 if (base1->id == t_base[i]->id) {
1010 index = i;
1011 break;
1012 }
1013 }
1014 if (index < 0) {
1015 t_base = SDDS_Realloc(t_base, sizeof(*t_base) * (t_bases + 1));
1016 if (!t_base) {
1017 fprintf(stderr, "Error: Memory reallocation failed for t_base in compute_sub_tree_ps.\n");
1018 exit(EXIT_FAILURE);
1019 }
1020 t_base[t_bases] = base1;
1021 t_bases++;
1022 }
1023 }
1024 if (index >= 0)
1025 continue;
1026
1027 prob = base1->probability; /* Remember original probability */
1028
1029 /* Compute ps when probability = 1 */
1030 base1->probability = 1.0;
1031 base1->ps = compute_ps(ite);
1032
1033 /* Compute pes when probability = 0 */
1034 base1->probability = 0.0;
1035 base1->pes = compute_ps(ite);
1036
1037 /* Restore original probability */
1038 base1->probability = prob;
1039
1040 base1->MIF = base1->ps - base1->pes;
1041 base1->DIF = prob + prob * (1.0 - prob) * base1->MIF / PS;
1042
1043 if (verbose)
1044 fprintf(stdout, "Base %ld: prob=%.6f, ps=%.6f, pes=%.6f, MIF=%.6f, DIF=%.6f\n",
1045 base1->id, base1->probability, base1->ps, base1->pes, base1->MIF, base1->DIF);
1046 }
1047 }
1048
1049 if (!SDDS_StartPage(outData, t_bases))
1050 SDDS_PrintErrors(stdout, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
1051
1052 if (!SDDS_SetParameters(outData, SDDS_SET_BY_NAME | SDDS_PASS_BY_VALUE,
1053 "TreeName", sub_tree[treeIndex].tree_name,
1054 "Description", sub_tree[treeIndex].description,
1055 "LogicalType", sub_tree[treeIndex].type,
1056 "LogicalTypeDesc", sub_tree[treeIndex].typeDesc,
1057 "ID", sub_tree[treeIndex].ID, NULL))
1058 SDDS_PrintErrors(stderr, SDDS_EXIT_PrintErrors | SDDS_VERBOSE_PrintErrors);
1059
1060 for (i = 0; i < t_bases; i++) {
1061 if (!SDDS_SetRowValues(outData, SDDS_SET_BY_NAME | SDDS_PASS_BY_VALUE, i,
1062 "BaseID", t_base[i]->id,
1063 "Label", t_base[i]->label,
1064 "Probability", t_base[i]->probability,
1065 "DIF", t_base[i]->DIF,
1066 "MIF", t_base[i]->MIF,
1067 "PS", t_base[i]->ps,
1068 "PES", t_base[i]->pes,
1069 "Description", t_base[i]->description,
1070 "Guidance", t_base[i]->guidance, NULL))
1071 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
1072 }
1073
1074 if (!SDDS_WritePage(outData))
1075 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
1076
1077 if (t_base)
1078 free(t_base);
1079}
1080
1081long push_node1(long ID) {
1082 if (treeStackptr1 >= STACKSIZE) {
1083 fprintf(stderr, "Error: Stack overflow in push_node1.\n");
1084 exit(EXIT_FAILURE);
1085 }
1086 treeStack1[treeStackptr1++] = ID;
1087 return 1;
1088}
1089
1090long pop_node1(void) {
1091 if (treeStackptr1 < 1) {
1092 fprintf(stderr, "Error: Too few items on stack in pop_node1.\n");
1093 exit(EXIT_FAILURE);
1094 }
1095 return treeStack1[--treeStackptr1];
1096}
1097
1098void push_sub_tree1(ITE *ite) {
1099 ITE *left, *right;
1100 push_node1((long)ite);
1101 left = ite->left;
1102 right = ite->right;
1103 if (!left)
1104 push_node1(1);
1105 else
1106 push_node1((long)left);
1107 if (!right)
1108 push_node1(0);
1109 else
1110 push_node1((long)right);
1111 if (left)
1112 push_sub_tree1(left);
1113 if (right)
1114 push_sub_tree1(right);
1115}
1116
1117void SetupOutputFile(char *outputFile, SDDS_DATASET *outData) {
1118 if (!SDDS_InitializeOutput(outData, SDDS_ASCII, 1, NULL, NULL, outputFile))
1119 SDDS_PrintErrors(stdout, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
1120
1121 if (!SDDS_DefineSimpleParameter(outData, "TreeName", NULL, SDDS_STRING) ||
1122 !SDDS_DefineSimpleParameter(outData, "Description", NULL, SDDS_STRING) ||
1123 !SDDS_DefineSimpleParameter(outData, "LogicalType", NULL, SDDS_SHORT) ||
1124 !SDDS_DefineSimpleParameter(outData, "LogicalTypeDesc", NULL, SDDS_STRING) ||
1125 !SDDS_DefineSimpleParameter(outData, "ID", NULL, SDDS_LONG) ||
1126 !SDDS_DefineSimpleColumn(outData, "BaseID", NULL, SDDS_LONG) ||
1127 !SDDS_DefineSimpleColumn(outData, "Label", NULL, SDDS_STRING) ||
1128 !SDDS_DefineSimpleColumn(outData, "Probability", NULL, SDDS_DOUBLE) ||
1129 !SDDS_DefineSimpleColumn(outData, "DIF", NULL, SDDS_DOUBLE) ||
1130 !SDDS_DefineSimpleColumn(outData, "MIF", NULL, SDDS_DOUBLE) ||
1131 !SDDS_DefineSimpleColumn(outData, "PS", NULL, SDDS_DOUBLE) ||
1132 !SDDS_DefineSimpleColumn(outData, "PES", NULL, SDDS_DOUBLE) ||
1133 !SDDS_DefineSimpleColumn(outData, "Description", NULL, SDDS_STRING) ||
1134 !SDDS_DefineSimpleColumn(outData, "Guidance", NULL, SDDS_STRING))
1135 SDDS_PrintErrors(stdout, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
1136
1137 if (!SDDS_WriteLayout(outData))
1138 SDDS_PrintErrors(stdout, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
1139}
SDDS (Self Describing Data Set) Data Types Definitions and Function Prototypes.
int32_t SDDS_SetRowValues(SDDS_DATASET *SDDS_dataset, int32_t mode, int64_t row,...)
int32_t SDDS_StartPage(SDDS_DATASET *SDDS_dataset, int64_t expected_n_rows)
int32_t SDDS_SetParameters(SDDS_DATASET *SDDS_dataset, int32_t mode,...)
void * SDDS_GetColumn(SDDS_DATASET *SDDS_dataset, char *column_name)
Retrieves a copy of the data for a specified column, including only rows marked as "of interest".
int64_t SDDS_CountRowsOfInterest(SDDS_DATASET *SDDS_dataset)
Counts the number of rows marked as "of interest" in the current data table.
void * SDDS_GetParameter(SDDS_DATASET *SDDS_dataset, char *parameter_name, void *memory)
Retrieves the value of a specified parameter from the current data table of a data set.
int32_t SDDS_InitializeInput(SDDS_DATASET *SDDS_dataset, char *filename)
Definition SDDS_input.c:49
int32_t SDDS_Terminate(SDDS_DATASET *SDDS_dataset)
int32_t SDDS_ReadPage(SDDS_DATASET *SDDS_dataset)
int32_t SDDS_InitializeOutput(SDDS_DATASET *SDDS_dataset, int32_t data_mode, int32_t lines_per_row, const char *description, const char *contents, const char *filename)
Initializes the SDDS output dataset.
int32_t SDDS_DefineSimpleColumn(SDDS_DATASET *SDDS_dataset, const char *name, const char *unit, int32_t type)
Defines a simple data column within the SDDS dataset.
int32_t SDDS_DefineSimpleParameter(SDDS_DATASET *SDDS_dataset, const char *name, const char *unit, int32_t type)
Defines a simple data parameter within the SDDS dataset.
int32_t SDDS_WritePage(SDDS_DATASET *SDDS_dataset)
Writes the current data table to the output file.
int32_t SDDS_WriteLayout(SDDS_DATASET *SDDS_dataset)
Writes the SDDS layout header to the output file.
int32_t SDDS_FreeStringArray(char **string, int64_t strings)
Frees an array of strings by deallocating each individual string.
void SDDS_PrintErrors(FILE *fp, int32_t mode)
Prints recorded error messages to a specified file stream.
Definition SDDS_utils.c:432
int32_t SDDS_CopyString(char **target, const char *source)
Copies a source string to a target string with memory allocation.
Definition SDDS_utils.c:856
void * SDDS_Realloc(void *old_ptr, size_t new_size)
Reallocates memory to a new size.
Definition SDDS_utils.c:677
#define SDDS_STRING
Identifier for the string data type.
Definition SDDStypes.h:85
#define SDDS_LONG
Identifier for the signed 32-bit integer data type.
Definition SDDStypes.h:61
#define SDDS_SHORT
Identifier for the signed short integer data type.
Definition SDDStypes.h:73
#define SDDS_DOUBLE
Identifier for the double data type.
Definition SDDStypes.h:37
char * delete_chars(char *s, char *t)
Removes all occurrences of characters found in string t from string s.
long match_string(char *string, char **option, long n_options, long mode)
Matches a given string against an array of option strings based on specified modes.
int scanargs(SCANNED_ARG **scanned, int argc, char **argv)
Definition scanargs.c:36
long processPipeOption(char **item, long items, unsigned long *flags)
Definition scanargs.c:356
void processFilenames(char *programName, char **input, char **output, unsigned long pipeFlags, long noWarnings, long *tmpOutputUsed)
Definition scanargs.c:390
void free_scanargs(SCANNED_ARG **scanned, int argc)
Definition scanargs.c:584