source: proiecte/Parallel-DT/R8/Src/subset.c @ 24

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

blabla

File size: 9.5 KB
Line 
1/*************************************************************************/
2/*                                                                       */
3/*      Evaluation of the subsetting of a discrete attribute             */
4/*      ----------------------------------------------------             */
5/*                                                                       */
6/*************************************************************************/
7
8
9#include "buildex.i"
10
11
12ItemCount
13        *Slice1,        /* Slice1[c]    = saved values of Freq[x][c] in subset.c */
14        *Slice2;        /* Slice2[c]    = saved values of Freq[y][c] */
15
16Set
17        **Subset;       /* Subset[a][s] = subset s for att a */
18
19short
20        *Subsets;       /* Subsets[a] = no. subsets for att a */
21
22
23
24/*************************************************************************/
25/*                                                                       */
26/*  Evaluate subsetting a discrete attribute and form the chosen         */
27/*  subsets Subset[Att][], setting Subsets[Att] to the number of         */
28/*  subsets, and the Info[] and Gain[] of a test on the attribute        */
29/*                                                                       */
30/*************************************************************************/
31
32
33    EvalSubset(Att, Fp, Lp, Items)
34/*  ----------  */ 
35    Attribute Att;
36    ItemNo Fp, Lp; 
37    ItemCount Items;
38{ 
39    DiscrValue V1, V2, BestV1, BestV2, Barred;
40    ItemCount KnownItems;
41    ClassNo c;
42    float BaseInfo, MinGain, ThisGain, ThisInfo,
43        Val, BestVal, BestGain, BestInfo,
44        PrevVal, PrevGain, PrevInfo,
45        DiscrKnownBaseInfo(), Worth(), ComputeGain(), TotalInfo();
46    short Blocks=0, MissingValues=0, ReasonableSubsets, Bytes, b;
47    Boolean MergedSubsets = false;
48    int SaveMINOBJS;
49
50    SaveMINOBJS = MINOBJS;
51    MINOBJS = 1;
52
53    /*  First compute Freq[][], ValFreq[], base info, and the gain
54        and total info of a split on discrete attribute Att  */
55
56    ComputeFrequencies(Att, Fp, Lp);
57
58    KnownItems = Items - ValFreq[0];
59    if ( KnownItems < Epsilon )
60    {
61        Verbosity(2) printf("\tAtt %s: no known values\n", AttName[Att]);
62
63        Gain[Att] = -Epsilon;
64        Info[Att] = 0;
65        return;
66    }
67
68    BaseInfo = DiscrKnownBaseInfo(KnownItems, MaxAttVal[Att]);
69
70    PrevGain = ComputeGain(BaseInfo, UnknownRate[Att], MaxAttVal[Att],KnownItems);
71    PrevInfo = TotalInfo(ValFreq, 0, MaxAttVal[Att]) / Items;
72    PrevVal = Worth(PrevInfo, PrevGain, Epsilon);
73
74    Verbosity(2)
75    {
76        printf("\tAtt %s", AttName[Att]);
77
78        Verbosity(3) PrintDistribution(Att, MaxAttVal[Att], true);
79
80        printf("\tinf %.3f, gain %.3f, val=%.3f\n",
81                PrevInfo, PrevGain, PrevVal);
82    }
83
84    /*  Eliminate unrepresented attribute values from Freq[] and ValFreq[]
85        and form a separate subset for each represented attribute value  */
86
87    Bytes = (MaxAttVal[Att]>>3) + 1;
88    ClearBits(Bytes, Subset[Att][0]);
89
90    ForEach(V1, 1, MaxAttVal[Att])
91    {
92        if ( ValFreq[V1] > 0.5 )
93        {
94            if ( ++Blocks < V1 )
95            {
96                ValFreq[Blocks] = ValFreq[V1];
97                ForEach(c, 0, MaxClass)
98                {
99                    Freq[Blocks][c] = Freq[V1][c];
100                }
101            }
102            ClearBits(Bytes, Subset[Att][Blocks]);
103            SetBit(V1, Subset[Att][Blocks]);
104        }
105        else
106        {
107            SetBit(V1, Subset[Att][0]);
108            MissingValues++;
109        }
110    }
111
112    /*  Merge any single-class subsets with others of the same class  */
113    /*  Note: have ValFreq[V] > 0 for all V  */
114
115    ForEach(V1, 1, Blocks-1)
116    {
117        for ( c = 0 ; Freq[V1][c] < 0.1 ; c++ )
118            ;
119
120        if ( Freq[V1][c] < ValFreq[V1] - 0.1 ) continue;
121
122        /*  Now have a single class -- look for others  */
123
124        for ( V2 = V1+1 ; V2 <= Blocks ; )
125        {
126            if ( Freq[V2][c] < ValFreq[V2] - 0.1 )
127            {
128                V2++;
129            }
130            else
131            {
132                /*  Merge these subsets  */
133
134                Combine(V1, V2, Blocks);
135
136                ForEach(b, 0, Bytes-1)
137                {
138                    Subset[Att][V1][b] |= Subset[Att][V2][b];
139                    Subset[Att][V2][b] = Subset[Att][Blocks][b];
140                }
141
142                Blocks--;
143                MergedSubsets = true;
144            }
145        }
146    }
147
148    if ( MergedSubsets )
149    {
150        PrevGain = ComputeGain(BaseInfo, UnknownRate[Att], Blocks, KnownItems);
151        PrevInfo = TotalInfo(ValFreq, 0, Blocks) / Items;
152        PrevVal = Worth(PrevInfo, PrevGain, Epsilon);
153
154        Verbosity(2)
155        {
156            printf("\tAfter merging single-class subsets:");
157
158            Verbosity(3) PrintDistribution(Att, Blocks, false);
159
160            printf("\tinf %.3f, gain %.3f, val=%.3f\n",
161                    PrevInfo, PrevGain, PrevVal);
162        }
163    }
164
165    /*  Examine possible pair mergers and hill-climb  */
166
167    MinGain = PrevGain / 2;
168
169    while ( Blocks > 2 )
170    {
171        BestVal = BestV1 = 0;
172        BestGain = -Epsilon;
173
174        /*  Check reasonable subsets; if less than 3, bar mergers
175            involving the largest block  */
176
177        ReasonableSubsets = 0;
178        Barred = 1;
179
180        ForEach(V1, 1, Blocks)
181        {
182            if ( ValFreq[V1] >= SaveMINOBJS ) ReasonableSubsets++;
183
184            if ( ValFreq[V1] > ValFreq[Barred] ) Barred = V1;
185        }
186
187        if ( ReasonableSubsets >= 3 ) Barred = 0;
188
189        /*  For each possible pair of values, calculate the gain and
190            total info of a split in which they are treated as one.
191            Keep track of the pair with the best gain.  */
192
193        ForEach(V1, 1, Blocks-1)
194        {
195            ForEach(V2, V1+1, Blocks)
196            {
197                if ( V1 == Barred || V2 == Barred ) continue;
198
199                Combine(V1, V2, Blocks);
200
201                ThisGain = ComputeGain(BaseInfo, UnknownRate[Att],
202                                        Blocks-1, KnownItems);
203                ThisInfo = TotalInfo(ValFreq, 0, Blocks-1) / Items;
204                Val      = Worth(ThisInfo, ThisGain, Epsilon);
205
206                Verbosity(4)
207                {
208                    printf("\tcombine %d %d info %.3f gain %.3f val %.3f",
209                           V1, V2, ThisInfo, ThisGain, Val);
210                    PrintDistribution(Att, Blocks-1, false);
211                }
212
213                /*  Force a split if
214                        less than two reasonable subsets, or
215                        using GAIN criterion
216                    Prefer this split to the previous one if
217                        gain >= MinGain (and previous < MinGain), or
218                        val >= previous best val  */
219
220                if ( ThisGain >= MinGain && BestGain < MinGain ||
221                     Val >= BestVal ||
222                     ! BestV1 && ( ! GAINRATIO || ReasonableSubsets < 2 ) )
223                {
224                    BestVal  = Val;
225                    BestGain = ThisGain;
226                    BestInfo = ThisInfo;
227                    BestV1   = V1;
228                    BestV2   = V2;
229                }
230
231                Uncombine(V1, V2);
232            }
233        }
234
235        if ( GAINRATIO &&
236             ReasonableSubsets >= 2 &&
237             ( ! BestV1 ||
238               BestVal < PrevVal + 1E-5 ||
239               BestVal == PrevVal && BestGain < PrevGain ) ) break;
240
241        PrevGain = BestGain;
242        PrevInfo = BestInfo;
243        PrevVal = BestVal;
244
245        Combine(BestV1, BestV2, Blocks);
246
247        ForEach(b, 0, Bytes-1)
248        {
249            Subset[Att][BestV1][b] |= Subset[Att][BestV2][b];
250            Subset[Att][BestV2][b] = Subset[Att][Blocks][b];
251        }
252
253        Blocks--;
254
255        Verbosity(2)
256        {
257            printf("\t\tform subset ");
258            PrintSubset(Att, Subset[Att][BestV1]);
259            printf(": %d subsets, inf %.3f, gain %.3f, val %.3f\n",
260                   Blocks, BestInfo, BestGain, BestVal);
261            Verbosity(3)
262            {
263                printf("\t\tcombine %d, %d", BestV1, BestV2);
264                PrintDistribution(Att, Blocks, false);
265            }
266        }
267    }
268
269    MINOBJS = SaveMINOBJS;
270
271    if ( PrevVal <= 0 )
272    {
273        Gain[Att] = -Epsilon;
274        Info[Att] = 0;
275    }
276    else
277    {
278        Gain[Att] = ComputeGain(BaseInfo, UnknownRate[Att], Blocks, KnownItems);
279        Info[Att] = PrevInfo;
280
281        if ( MissingValues )
282        {
283            Blocks++;
284            CopyBits(Bytes, Subset[Att][0], Subset[Att][Blocks]);
285        }
286
287        Subsets[Att] = Blocks;
288
289        Verbosity(2) printf("\tFinal subsets:");
290        Verbosity(3) PrintDistribution(Att, Blocks, false);
291        Verbosity(2)
292            printf("\tinf %.3f gain %.3f val %.3f\n", 
293                   Info[Att], Gain[Att], Worth(Info[Att], Gain[Att], Epsilon));
294    }
295}
296
297
298
299/*************************************************************************/
300/*                                                                       */
301/*  Combine the distribution figures of discrete attribute values        */
302/*  x and y, putting the combined figures in Freq[x][] and               */
303/*  ValFreq[x][], and saving old values in Slice1 and Slice2             */
304/*                                                                       */
305/*************************************************************************/
306
307
308    Combine(x, y, Last)
309/*  -------  */
310    DiscrValue x, y, Last;
311{
312    ClassNo c;
313
314    ForEach(c, 0, MaxClass)
315    {
316        Slice1[c] = Freq[x][c];
317        Slice2[c] = Freq[y][c];
318
319        Freq[x][c] += Freq[y][c];
320        Freq[y][c]  = Freq[Last][c];
321    }
322
323    Slice1[MaxClass+1] = ValFreq[x];
324    Slice2[MaxClass+1] = ValFreq[y];
325
326    ValFreq[x] += ValFreq[y];
327    ValFreq[y]  = ValFreq[Last];
328}
329
330
331
332/*************************************************************************/
333/*                                                                       */
334/*  Restore old class distribution figures of discrete attribute         */
335/*  values x and y from Slice1 and Slice2                                */
336/*                                                                       */
337/*************************************************************************/
338
339
340    Uncombine(x, y)
341/*  ---------  */
342    DiscrValue x, y;
343{
344    ClassNo c;
345
346    ForEach(c, 0, MaxClass)
347    {
348        Freq[x][c] = Slice1[c];
349        Freq[y][c] = Slice2[c];
350    }
351
352    ValFreq[x] = Slice1[MaxClass+1];
353    ValFreq[y] = Slice2[MaxClass+1];
354}
355
356
357
358/*************************************************************************/
359/*                                                                       */
360/*  Print the values of attribute Att which are in the subset Ss         */
361/*                                                                       */
362/*************************************************************************/
363
364
365    PrintSubset(Att, Ss)
366/*  -----------  */
367    Attribute Att;
368    Set Ss;
369{
370    DiscrValue V1;
371    Boolean First=true;
372
373    ForEach(V1, 1, MaxAttVal[Att])
374    {
375        if ( In(V1, Ss) )
376        {
377            if ( First )
378            {
379                First = false;
380            }
381            else
382            {
383                printf(", ");
384            }
385
386            printf("%s", AttValName[Att][V1]);
387        }
388    }
389}
390
391
392
393/*************************************************************************/
394/*                                                                       */
395/*  Construct and return a node for a test on a subset of values         */
396/*                                                                       */
397/*************************************************************************/
398
399
400    SubsetTest(Node, Att)
401/*  -----------  */
402    Tree Node;
403    Attribute Att;
404{ 
405    ItemCount CountItems();
406    short S, Bytes;
407
408    Sprout(Node, Subsets[Att]);
409
410    Node->NodeType      = BrSubset;
411    Node->Tested        = Att;
412    Node->Errors        = 0;
413   
414    Bytes = (MaxAttVal[Att]>>3) + 1;
415    Node->Subset = (Set *) calloc(Subsets[Att] + 1, sizeof(Set));
416    ForEach(S, 1, Node->Forks)
417    {
418        Node->Subset[S] = (Set) malloc(Bytes);
419        CopyBits(Bytes, Subset[Att][S], Node->Subset[S]);
420    }
421} 
Note: See TracBrowser for help on using the repository browser.