DefaultTreeBuilder implements TreeBuilder { protected static int[] randomAttributes(Random rng, boolean[] selected, int m) { int nbNonSelected = 0; for (boolean sel : selected) { if (!sel) { nbNonSelected++; } } if (nbNonSelected == 0) { log.warn("All attributes are selected !"); return NO_ATTRIBUTES; } int[] result; if (nbNonSelected <= m) { result = new int[nbNonSelected]; int index = 0; for (int attr = 0; attr < selected.length; attr++) { if (!selected[attr]) { result[index++] = attr; } } } else { result = new int[m]; for (int index = 0; index < m; index++) { int rind; do { rind = rng.nextInt(selected.length); } while (selected[rind]); result[index] = rind; selected[rind] = true; } for (int attr : result) { selected[attr] = false; } } return result; } DefaultTreeBuilder(); void setM(int m); @Override Node build(Random rng, Data data);  }
@Test public void testRandomAttributes() throws Exception { Random rng = RandomUtils.getRandom(); int nbAttributes = rng.nextInt(100) + 1; boolean[] selected = new boolean[nbAttributes]; for (int nloop = 0; nloop < 100; nloop++) { Arrays.fill(selected, false); int nbSelected = rng.nextInt(nbAttributes - 1); for (int index = 0; index < nbSelected; index++) { int attr; do { attr = rng.nextInt(nbAttributes); } while (selected[attr]); selected[attr] = true; } int m = rng.nextInt(nbAttributes); int[] attrs = DefaultTreeBuilder.randomAttributes(rng, selected, m); assertNotNull(attrs); assertEquals(Math.min(m, nbAttributes - nbSelected), attrs.length); for (int attr : attrs) { assertFalse("an attribute has already been selected", selected[attr]); assertTrue(attr >= 0); assertTrue(attr < nbAttributes); assertEquals(ArrayUtils.indexOf(attrs, attr), ArrayUtils.lastIndexOf(attrs, attr)); } } }