source: proiecte/Parallel-DT/R8/Src/trees.c @ 26

Last change on this file since 26 was 26, checked in by (none), 14 years ago

blabla

File size: 13.8 KB
Line 
1/*************************************************************************/
2/*                                                                       */
3/*      Routines for displaying, building, saving and restoring trees    */
4/*      -------------------------------------------------------------    */
5/*                                                                       */
6/*************************************************************************/
7
8
9#include "defns.i"
10#include "types.i"
11#include "extern.i"
12
13
14#define Tab             "|   "
15#define TabSize         4
16#define Width           80      /* approx max width of printed trees */
17
18        /*  If lines look like getting too long while a tree is being
19            printed, subtrees are broken off and printed separately after
20            the main tree is finished    */
21
22short   Subtree;                /* highest subtree to be printed */
23Tree    Subdef[100];            /* pointers to subtrees */
24
25FILE    *TRf = 0, *fopen();     /* file pointer for tree i/o */
26char    Fn[500];                /* file name */
27
28
29
30/*************************************************************************/
31/*                                                                       */
32/*      Display entire decision tree T                                   */
33/*                                                                       */
34/*************************************************************************/
35
36
37    PrintTree(T)
38/*  ----------  */
39    Tree T;
40{
41    short s;
42
43    Subtree=0;
44    printf("Decision Tree:\n");
45    Show(T, 0);
46    printf("\n");
47
48    ForEach(s, 1, Subtree)
49    {
50        printf("\n\nSubtree [S%d]\n", s);
51        Show(Subdef[s], 0);
52        printf("\n");
53    }
54    printf("\n");
55}
56
57
58
59/*************************************************************************/
60/*                                                                       */
61/*      Display the tree T with offset Sh                                */
62/*                                                                       */
63/*************************************************************************/
64
65
66    Show(T, Sh)
67/*  ---- */
68    Tree T;
69    short Sh;
70{
71    DiscrValue v, MaxV;
72    short MaxLine();
73
74    if ( T->NodeType )
75    {
76        /*  See whether separate subtree needed  */
77
78        if ( T != Nil && Sh && Sh * TabSize + MaxLine(T) > Width )
79        {
80            if ( Subtree < 99 )
81            {
82                Subdef[++Subtree] = T;
83                printf("[S%d]", Subtree);
84            }
85            else
86            {
87                printf("[S??]");
88            }
89        }
90        else
91        {
92            MaxV = T->Forks;
93
94            /*  Print simple cases first */
95
96            ForEach(v, 1, MaxV)
97            {
98                if ( ! T->Branch[v]->NodeType )
99                {
100                    ShowBranch(Sh, T, v);
101                }
102            }
103
104            /*  Print subtrees  */
105
106            ForEach(v, 1, MaxV)
107            {
108                if ( T->Branch[v]->NodeType )
109                {
110                    ShowBranch(Sh, T, v);
111                }
112            }
113        }
114    }
115    else
116    {
117        printf(" %s (%.1f", ClassName[T->Leaf], T->Items);
118        if ( T->Errors > 0 ) printf("/%.1f", T->Errors);
119        printf(")");
120    }
121}
122
123
124
125/*************************************************************************/
126/*                                                                       */
127/*      Print a node T with offset Sh, branch value v, and continue      */
128/*                                                                       */
129/*************************************************************************/
130
131
132    ShowBranch(Sh, T, v)
133/*  -----------  */
134    short Sh;
135    Tree T;
136    DiscrValue v;
137{
138    DiscrValue Pv, Last;
139    Attribute Att;
140    Boolean FirstValue;
141    short TextWidth, Skip, Values=0, i;
142   
143    Att = T->Tested;
144
145    switch ( T->NodeType )
146    {
147        case BrDiscr:
148
149            Indent(Sh, Tab);
150
151            printf("%s = %s:", AttName[Att], AttValName[Att][v]);
152            break;
153
154        case ThreshContin:
155
156            Indent(Sh, Tab);
157
158            printf("%s %s %g ",
159                    AttName[Att], ( v == 1 ? "<=" : ">" ), T->Cut);
160
161            if ( T->Lower != T->Upper )
162            {
163                printf("[%g,%g]", T->Lower, T->Upper);
164            }
165
166            printf(":");
167            break;
168
169        case BrSubset:
170
171            /*  Count values at this branch  */
172
173            ForEach(Pv, 1, MaxAttVal[Att])
174            {
175                if ( In(Pv, T->Subset[v]) )
176                {
177                    Last = Pv;
178                    Values++;
179                }
180            }
181            if ( ! Values ) return;
182
183            Indent(Sh, Tab);
184
185            if ( Values == 1 )
186            {
187                printf("%s = %s:", AttName[Att], AttValName[Att][Last]);
188                break;
189            }
190
191            printf("%s in {", AttName[Att]);
192            FirstValue = true;
193            Skip = TextWidth = strlen(AttName[Att]) + 5;
194
195            ForEach(Pv, 1, MaxAttVal[Att])
196            {
197                if ( In(Pv, T->Subset[v]) )
198                {
199                    if ( ! FirstValue &&
200                         TextWidth + strlen(AttValName[Att][Pv]) + 11 > Width )
201                    {
202                        Indent(Sh, Tab);
203                        ForEach(i, 1, Skip) putchar(' ');
204
205                        TextWidth = Skip;
206                        FirstValue = true;
207                    }
208
209                    printf("%s%c", AttValName[Att][Pv], Pv == Last ? '}' : ',');
210                    TextWidth += strlen(AttValName[Att][Pv]) + 1;
211                    FirstValue = false;
212                }
213            }
214            putchar(':');
215    }
216
217    Show(T->Branch[v], Sh+1);
218}
219
220
221
222/*************************************************************************/
223/*                                                                       */
224/*      Find the maximum single line size for non-leaf subtree St.       */
225/*      The line format is                                               */
226/*                      <attribute> <> X.xx:[ <class (<Items>)], or      */
227/*                      <attribute> = <DVal>:[ <class> (<Items>)]        */
228/*                                                                       */
229/*************************************************************************/
230
231
232short MaxLine(St)
233/*    --------  */
234    Tree St;
235{
236    Attribute a;
237    DiscrValue v, MaxV, Next;
238    short Ll, MaxLl=0;
239
240    a = St->Tested;
241
242    MaxV = St->Forks;
243    ForEach(v, 1, MaxV)
244    {
245        Ll = ( St->NodeType == 2 ? 4 : strlen(AttValName[a][v]) ) + 1;
246
247        /*  Find the appropriate branch  */
248
249        Next = v;
250
251        if ( ! St->Branch[Next]->NodeType )
252        {
253            Ll += strlen(ClassName[St->Branch[Next]->Leaf]) + 6;
254        }
255        MaxLl = Max(MaxLl, Ll);
256    }
257
258    return strlen(AttName[a]) + 4 + MaxLl;
259}
260
261
262
263/*************************************************************************/
264/*                                                                       */
265/*      Indent Sh columns                                                */
266/*                                                                       */
267/*************************************************************************/
268
269    Indent(Sh, Mark)
270/*  ------  */
271    short Sh;
272    char *Mark;
273{
274    printf("\n");
275    while ( Sh-- ) printf("%s", Mark);
276}
277
278
279
280/*************************************************************************/
281/*                                                                       */
282/*      Save entire decision tree T in file with extension Extension     */
283/*                                                                       */
284/*************************************************************************/
285
286
287    SaveTree(T, Extension)
288/*  ---------  */
289    Tree T;
290    String Extension;
291{
292    static char *LastExt="";
293
294    if ( strcmp(LastExt, Extension) )
295    {
296        LastExt = Extension;
297
298        if ( TRf ) fclose(TRf);
299
300        strcpy(Fn, FileName);
301        strcat(Fn, Extension);
302        if ( ! ( TRf = fopen(Fn, "w") ) )
303            Error(0, Fn, " for writing");
304    }
305
306    putc('\n', TRf);
307    OutTree(T);
308
309    SaveDiscreteNames();
310}
311
312
313
314/*************************************************************************/
315/*                                                                       */
316/*      Save tree T as characters                                        */
317/*                                                                       */
318/*************************************************************************/
319
320
321    OutTree(T)
322/*  --------  */
323    Tree T;
324{
325    DiscrValue v;
326    int Bytes;
327
328    StreamOut((char *) &T->NodeType, sizeof(short));
329    StreamOut((char *) &T->Leaf, sizeof(ClassNo));
330    StreamOut((char *) &T->Items, sizeof(ItemCount));
331    StreamOut((char *) &T->Errors, sizeof(ItemCount));
332    StreamOut((char *) T->ClassDist, (MaxClass + 1) * sizeof(ItemCount));
333
334    if ( T->NodeType )
335    {
336        StreamOut((char *) &T->Tested, sizeof(Attribute));
337        StreamOut((char *) &T->Forks, sizeof(short));
338
339        switch ( T->NodeType )
340        {
341            case BrDiscr:
342                break;
343
344            case ThreshContin:
345                StreamOut((char *) &T->Cut, sizeof(float));
346                StreamOut((char *) &T->Lower, sizeof(float));
347                StreamOut((char *) &T->Upper, sizeof(float));
348                break;
349
350            case BrSubset:
351                Bytes = (MaxAttVal[T->Tested]>>3) + 1;
352                ForEach(v, 1, T->Forks)
353                {
354                    StreamOut((char *) T->Subset[v], Bytes);
355                }
356                break;
357        }
358
359        ForEach(v, 1, T->Forks)
360        {
361            OutTree(T->Branch[v]);
362        }
363    }
364}
365
366
367
368/*************************************************************************/
369/*                                                                       */
370/*      Retrieve entire decision tree with extension Extension           */
371/*                                                                       */
372/*************************************************************************/
373
374
375Tree GetTree(Extension)
376/*   --------  */
377    String Extension;
378{
379    Tree Hold, InTree();
380    static char *LastExt="";
381
382    if ( strcmp(LastExt, Extension) )
383    {
384        LastExt = Extension;
385
386        if ( TRf ) fclose(TRf);
387
388        strcpy(Fn, FileName);
389        strcat(Fn, Extension);
390        if ( ! ( TRf = fopen(Fn, "r") ) ) Error(0, Fn, "");
391    }
392
393    if ( ! TRf || getc(TRf) == EOF ) return Nil;
394
395    Hold = InTree();
396
397    RecoverDiscreteNames();
398
399    return Hold;
400}
401
402
403
404/*************************************************************************/
405/*                                                                       */
406/*      Retrieve tree from saved characters                              */
407/*                                                                       */
408/*************************************************************************/
409
410
411Tree InTree()
412/*   -------  */
413{
414    Tree T;
415    DiscrValue v;
416    int Bytes;
417
418    T = (Tree) malloc(sizeof(TreeRec));
419
420    StreamIn((char *) &T->NodeType, sizeof(short));
421    StreamIn((char *) &T->Leaf, sizeof(ClassNo));
422    StreamIn((char *) &T->Items, sizeof(ItemCount));
423    StreamIn((char *) &T->Errors, sizeof(ItemCount));
424
425    T->ClassDist = (ItemCount *) calloc(MaxClass+1, sizeof(ItemCount));
426    StreamIn((char *) T->ClassDist, (MaxClass + 1) * sizeof(ItemCount));
427
428    if ( T->NodeType )
429    {
430        StreamIn((char *) &T->Tested, sizeof(Attribute));
431        StreamIn((char *) &T->Forks, sizeof(short));
432
433        switch ( T->NodeType )
434        {
435            case BrDiscr:
436                break;
437
438            case ThreshContin:
439                StreamIn((char *) &T->Cut, sizeof(float));
440                StreamIn((char *) &T->Lower, sizeof(float));
441                StreamIn((char *) &T->Upper, sizeof(float));
442                break;
443
444            case BrSubset:
445                T->Subset = (Set *) calloc(T->Forks + 1, sizeof(Set));
446
447                Bytes = (MaxAttVal[T->Tested]>>3) + 1;
448                ForEach(v, 1, T->Forks)
449                {
450                    T->Subset[v] = (Set) malloc(Bytes);
451                    StreamIn((char *) T->Subset[v], Bytes);
452                }
453        }
454
455        T->Branch = (Tree *) calloc(T->Forks + 1, sizeof(Tree));
456        ForEach(v, 1, T->Forks)
457        {
458            T->Branch[v] = InTree();
459        }
460    }
461
462    return T;
463}
464
465
466
467/*************************************************************************/
468/*                                                                       */
469/*      Stream characters to/from file TRf from/to an address            */
470/*                                                                       */
471/*************************************************************************/
472
473
474    StreamOut(s, n)
475/*  ---------  */
476    String s;
477    int n;
478{
479    while ( n-- ) putc(*s++, TRf);
480}
481
482
483
484    StreamIn(s, n)
485/*  ---------  */
486    String s;
487    int n;
488{
489    while ( n-- ) *s++ = getc(TRf);
490}
491
492
493
494/*************************************************************************/
495/*                                                                       */
496/*      Free up space taken up by tree Node                              */
497/*                                                                       */
498/*************************************************************************/
499
500
501    ReleaseTree(Node)
502/*  -------  */
503    Tree Node;
504{
505    DiscrValue v;
506
507    if ( Node->NodeType )
508    {
509        ForEach(v, 1, Node->Forks)
510        {
511            ReleaseTree(Node->Branch[v]);
512        }
513
514        cfree(Node->Branch);
515
516        if ( Node->NodeType == BrSubset )
517        {
518            cfree(Node->Subset);
519        }
520
521    }
522
523    cfree(Node->ClassDist);
524    cfree(Node);
525}
526
527
528
529/*************************************************************************/
530/*                                                                       */
531/*      Construct a leaf in a given node                                 */
532/*                                                                       */
533/*************************************************************************/
534
535
536Tree Leaf(ClassFreq, NodeClass, Cases, Errors)
537/*   ----  */
538    ItemCount *ClassFreq;
539    ClassNo NodeClass;
540    ItemCount Cases, Errors;
541{
542    Tree Node;
543
544    Node = (Tree) calloc(1, sizeof(TreeRec));
545
546    Node->ClassDist = (ItemCount *) calloc(MaxClass+1, sizeof(ItemCount));
547    memcpy(Node->ClassDist, ClassFreq, (MaxClass+1) * sizeof(ItemCount));
548   
549    Node->NodeType      = 0; 
550    Node->Leaf          = NodeClass;
551    Node->Items         = Cases;
552    Node->Errors        = Errors;
553
554    return Node; 
555}
556
557
558
559/*************************************************************************/
560/*                                                                       */
561/*      Insert branches in a node                                        */
562/*                                                                       */
563/*************************************************************************/
564
565
566    Sprout(Node, Branches)
567/*  ------  */
568    Tree Node;
569    DiscrValue Branches;
570{
571    Node->Forks = Branches;
572   
573    Node->Branch = (Tree *) calloc(Branches+1, sizeof(Tree));
574}
575
576
577
578/*************************************************************************/
579/*                                                                       */
580/*      Count the nodes in a tree                                        */
581/*                                                                       */
582/*************************************************************************/
583
584       
585    TreeSize(Node)
586/*  --------  */
587    Tree Node;
588{
589    int Sum=0;
590    DiscrValue v;
591
592    if ( Node->NodeType )
593    {
594        ForEach(v, 1, Node->Forks)
595        {
596            Sum += TreeSize(Node->Branch[v]);
597        }
598    }
599
600    return Sum + 1;
601}
602
603
604
605/*************************************************************************/
606/*                                                                       */
607/*      Return a copy of tree T                                          */
608/*                                                                       */
609/*************************************************************************/
610
611
612Tree CopyTree(T)
613/*   ---------  */
614    Tree T;
615{
616    DiscrValue v;
617    Tree New;
618
619    New = (Tree) malloc(sizeof(TreeRec));
620    memcpy(New, T, sizeof(TreeRec));
621
622    New->ClassDist = (ItemCount *) calloc(MaxClass+1, sizeof(ItemCount));
623    memcpy(New->ClassDist, T->ClassDist, (MaxClass + 1) * sizeof(ItemCount));
624
625    if ( T->NodeType )
626    {
627        New->Branch = (Tree *) calloc(T->Forks + 1, sizeof(Tree));
628        ForEach(v, 1, T->Forks)
629        {
630            New->Branch[v] = CopyTree(T->Branch[v]);
631        }
632    }
633
634    return New;
635}
636
637
638
639/*************************************************************************/
640/*                                                                       */
641/*      Save attribute values read with "discrete N"                     */
642/*                                                                       */
643/*************************************************************************/
644
645
646    SaveDiscreteNames()
647/*  -----------------  */
648{
649    Attribute Att;
650    DiscrValue v;
651    int Length;
652
653    ForEach(Att, 0, MaxAtt)
654    {
655        if ( SpecialStatus[Att] != DISCRETE ) continue;
656
657        StreamOut((char *) &MaxAttVal[Att], sizeof(int));
658
659        ForEach(v, 1, MaxAttVal[Att])
660        {
661            Length = strlen(AttValName[Att][v]) + 1;
662
663            StreamOut((char *) &Length, sizeof(int));
664            StreamOut((char *) AttValName[Att][v], Length);
665        }
666    }
667}
668
669
670
671/*************************************************************************/
672/*                                                                       */
673/*      Recover attribute values read with "discrete N"                  */
674/*                                                                       */
675/*************************************************************************/
676
677
678    RecoverDiscreteNames()
679/*  --------------------  */
680{
681    Attribute Att;
682    DiscrValue v;
683    int Length;
684
685    ForEach(Att, 0, MaxAtt)
686    {
687        if ( SpecialStatus[Att] != DISCRETE ) continue;
688
689        StreamIn(&MaxAttVal[Att], sizeof(int));
690
691        ForEach(v, 1, MaxAttVal[Att])
692        {
693            StreamIn(&Length, sizeof(int));
694
695            AttValName[Att][v] = (char *) malloc(Length);
696            StreamIn(AttValName[Att][v], Length);
697        }
698    }
699}
Note: See TracBrowser for help on using the repository browser.