/* * Walk through subsets in an ordered way. * For all subsets, this is the classic gray code. * * Graycode_init0 is called once at the very beginning with * the maximum number of categories. It allocates a scratch vector. * * Graycode_init1 is called once for each unordered variable. * Graycode_init2 is called once for each orderable variable, * the second argument is a vector that will be used to rank the variables */ #include "rpart.h" #include "rpartproto.h" static int *gray; static int maxc, gsave; void graycode_init0(int maxcat) { gray = (int *) ALLOC(maxcat, sizeof(int)); } void graycode_init1(int numcat, int *count) { int i; maxc = numcat; for (i = 0; i < maxc; i++) gray[i] = count[i] ? 1 : 0; gsave = -2; } void graycode_init2(int numcat, int *count, double *val) { int i, j, k; double temp; maxc = numcat; /* * sort categories with no members first * then order by val */ gray[0] = 0; if (count[0] == 0) k = 1; else k = 0; for (i = 1; i < maxc; i++) { if (count[i] == 0) { for (j = i - 1; j >= k; j--) { gray[j + 1] = gray[j]; val[j + 1] = val[j]; } gray[k++] = i; } else { temp = val[i]; for (j = i - 1; j >= k && val[j] > temp; j--) { gray[j + 1] = gray[j]; val[j + 1] = val[j]; } val[j + 1] = temp; gray[j + 1] = i; } } gsave = k - 1; } /* * Everyone starts in the right hand group * This routine returns the next subject who needs to * change allegiance. * A value of maxc means that we're done. */ int graycode(void) { int i; if (gsave > -2) { /* ordered data */ gsave++; if (gsave < maxc) return gray[gsave]; else return maxc; } else { /* * Form next subgroup. We do this using the classic Gray code. * The initial subset has everyone in the right group. Each * subset varies from the prior by only one member -- the * following item changes groups: 1,2,1,4,1,2,1,8,1,2,1,4,1,... * The outer loop only goes up to maxc-1: we know for rpart that * changing the allegiance of the last subject is never necessary */ for (i = 0; i < maxc - 1; i++) { if (gray[i] == 1) { gray[i] = 2; return i; } else if (gray[i] == 2) gray[i] = 1; } return maxc; /* signal "done" */ } }