source: src/test/java/weka/attributeSelection/AbstractAttributeSelectionTest.java @ 13

Last change on this file since 13 was 4, checked in by gnappo, 14 years ago

Import di weka.

File size: 26.9 KB
Line 
1/*
2 *    This program is free software; you can redistribute it and/or modify
3 *    it under the terms of the GNU General Public License as published by
4 *    the Free Software Foundation; either version 2 of the License, or
5 *    (at your option) any later version.
6 *
7 *    This program is distributed in the hope that it will be useful,
8 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
9 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10 *    GNU General Public License for more details.
11 *
12 *    You should have received a copy of the GNU General Public License
13 *    along with this program; if not, write to the Free Software
14 *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
15 */
16
17/*
18 * Copyright (C) 2006 University of Waikato
19 */
20
21package weka.attributeSelection;
22
23import weka.core.Attribute;
24import weka.core.CheckGOE;
25import weka.core.CheckOptionHandler;
26import weka.core.Instances;
27import weka.core.CheckScheme.PostProcessor;
28import weka.test.Regression;
29
30import junit.framework.TestCase;
31
32/**
33 * Abstract Test class for attribute selection schemes. Internally it uses the
34 * class <code>CheckAttributeSelection</code> to determine success or failure
35 * of the tests. It follows basically the <code>testsPerClassType</code>
36 * method.
37 *
38 * @author FracPete (fracpete at waikato dot ac dot nz)
39 * @version $Revision: 1.5 $
40 *
41 * @see CheckAttributeSelection
42 * @see CheckAttributeSelection#testsPerClassType(int, boolean, boolean)
43 * @see PostProcessor
44 */
45public abstract class AbstractAttributeSelectionTest 
46  extends TestCase {
47 
48  /** The search scheme to be tested */
49  protected ASSearch m_Search;
50
51  /** The evaluator to test */
52  protected ASEvaluation m_Evaluator;
53 
54  /** For testing the attribute selection scheme */
55  protected CheckAttributeSelection m_Tester;
56
57  /** whether scheme handles weighted instances */
58  protected boolean m_weightedInstancesHandler;
59
60  /** whether scheme handles multi-instance data */
61  protected boolean m_multiInstanceHandler;
62
63  /** the number of classes to test with testNClasses()
64   * @see #testNClasses() */
65  protected int m_NClasses;
66
67  /** whether to run CheckAttributeSelection in DEBUG mode */
68  protected boolean DEBUG = false;
69
70  /** the attribute type with the lowest value */
71  protected final static int FIRST_CLASSTYPE = Attribute.NUMERIC;
72
73  /** the attribute type with the highest value */
74  protected final static int LAST_CLASSTYPE = Attribute.RELATIONAL;
75 
76  /** wether scheme can predict nominal attributes (array index is attribute type of class) */
77  protected boolean[] m_NominalPredictors;
78 
79  /** wether scheme can predict numeric attributes (array index is attribute type of class) */
80  protected boolean[] m_NumericPredictors;
81 
82  /** wether scheme can predict string attributes (array index is attribute type of class) */
83  protected boolean[] m_StringPredictors;
84 
85  /** wether scheme can predict date attributes (array index is attribute type of class) */
86  protected boolean[] m_DatePredictors;
87 
88  /** wether scheme can predict relational attributes (array index is attribute type of class) */
89  protected boolean[] m_RelationalPredictors;
90 
91  /** whether scheme handles missing values */
92  protected boolean[] m_handleMissingPredictors;
93
94  /** whether scheme handles class with only missing values */
95  protected boolean[] m_handleMissingClass;
96
97  /** whether scheme handles class as first attribute */
98  protected boolean[] m_handleClassAsFirstAttribute;
99
100  /** whether scheme handles class as second attribute */
101  protected boolean[] m_handleClassAsSecondAttribute;
102 
103  /** the results of the regression tests */
104  protected String[] m_RegressionResults;
105 
106  /** the OptionHandler tester */
107  protected CheckOptionHandler m_OptionTester;
108 
109  /** for testing GOE stuff */
110  protected CheckGOE m_GOETester;
111 
112  /**
113   * Constructs the <code>AbstractAttributeSelectionTest</code>. Called by subclasses.
114   *
115   * @param name        the name of the test class
116   */
117  public AbstractAttributeSelectionTest(String name) { 
118    super(name); 
119  }
120
121  /**
122   * returns a custom PostProcessor for the CheckAttributeSelection datasets,
123   * currently only null.
124   *
125   * @return            a custom PostProcessor, if necessary
126   * @see               PostProcessor
127   */
128  protected PostProcessor getPostProcessor() {
129    return null;
130  }
131 
132  /**
133   * configures the CheckAttributeSelection instance used throughout the tests
134   *
135   * @return    the fully configured CheckAttributeSelection instance used for testing
136   */
137  protected CheckAttributeSelection getTester() {
138    CheckAttributeSelection     result;
139   
140    result = new CheckAttributeSelection();
141    result.setSilent(true);
142    result.setSearch(m_Search);
143    result.setEvaluator(m_Evaluator);
144    result.setNumInstances(20);
145    result.setDebug(DEBUG);
146    result.setPostProcessor(getPostProcessor());
147   
148    return result;
149  }
150 
151  /**
152   * Configures the CheckOptionHandler uses for testing the optionhandling.
153   * Sets the scheme to test.
154   *
155   * @return    the fully configured CheckOptionHandler
156   */
157  protected CheckOptionHandler getOptionTester() {
158    CheckOptionHandler          result;
159   
160    result = new CheckOptionHandler();
161    result.setOptionHandler(null);
162    result.setUserOptions(new String[0]);
163    result.setSilent(true);
164   
165    return result;
166  }
167 
168  /**
169   * Configures the CheckGOE used for testing GOE stuff.
170   *
171   * @return    the fully configured CheckGOE
172   */
173  protected CheckGOE getGOETester() {
174    CheckGOE            result;
175   
176    result = new CheckGOE();
177    result.setObject(null);
178    result.setSilent(true);
179   
180    return result;
181  }
182 
183  /**
184   * Called by JUnit before each test method. This implementation creates
185   * the default scheme to test and loads a test set of Instances.
186   *
187   * @exception Exception if an error occurs reading the example instances.
188   */
189  protected void setUp() throws Exception {
190    m_Search       = getSearch();
191    m_Evaluator    = getEvaluator();
192    m_Tester       = getTester();
193    m_OptionTester = getOptionTester();
194    m_GOETester    = getGOETester();
195
196    m_weightedInstancesHandler     = m_Tester.weightedInstancesHandler()[0];
197    m_multiInstanceHandler         = m_Tester.multiInstanceHandler()[0];
198    m_NominalPredictors            = new boolean[LAST_CLASSTYPE + 1];
199    m_NumericPredictors            = new boolean[LAST_CLASSTYPE + 1];
200    m_StringPredictors             = new boolean[LAST_CLASSTYPE + 1];
201    m_DatePredictors               = new boolean[LAST_CLASSTYPE + 1];
202    m_RelationalPredictors         = new boolean[LAST_CLASSTYPE + 1];
203    m_handleMissingPredictors      = new boolean[LAST_CLASSTYPE + 1];
204    m_handleMissingClass           = new boolean[LAST_CLASSTYPE + 1];
205    m_handleClassAsFirstAttribute  = new boolean[LAST_CLASSTYPE + 1];
206    m_handleClassAsSecondAttribute = new boolean[LAST_CLASSTYPE + 1];
207    m_RegressionResults            = new String[LAST_CLASSTYPE + 1];
208    m_NClasses                     = 4;
209
210    // initialize attributes
211    checkAttributes(true,  false, false, false, false, false);
212    checkAttributes(false, true,  false, false, false, false);
213    checkAttributes(false, false, true,  false, false, false);
214    checkAttributes(false, false, false, true,  false, false);
215    checkAttributes(false, false, false, false, true,  false);
216   
217    // initialize missing values handling
218    for (int i = FIRST_CLASSTYPE; i <= LAST_CLASSTYPE; i++) {
219      // does the scheme support this type of class at all?
220      if (!canPredict(i))
221        continue;
222     
223      // 20% missing
224      m_handleMissingPredictors[i] = checkMissingPredictors(i, 20, false);
225      m_handleMissingClass[i]      = checkMissingClass(i, 20, false);
226    }
227  }
228
229  /** Called by JUnit after each test method */
230  protected void tearDown() {
231    m_Search       = null;
232    m_Evaluator    = null;
233    m_Tester       = null;
234    m_OptionTester = null;
235    m_GOETester    = null;
236
237    m_weightedInstancesHandler     = false;
238    m_NominalPredictors            = new boolean[LAST_CLASSTYPE + 1];
239    m_NumericPredictors            = new boolean[LAST_CLASSTYPE + 1];
240    m_StringPredictors             = new boolean[LAST_CLASSTYPE + 1];
241    m_DatePredictors               = new boolean[LAST_CLASSTYPE + 1];
242    m_RelationalPredictors         = new boolean[LAST_CLASSTYPE + 1];
243    m_handleMissingPredictors      = new boolean[LAST_CLASSTYPE + 1];
244    m_handleMissingClass           = new boolean[LAST_CLASSTYPE + 1];
245    m_handleClassAsFirstAttribute  = new boolean[LAST_CLASSTYPE + 1];
246    m_handleClassAsSecondAttribute = new boolean[LAST_CLASSTYPE + 1];
247    m_RegressionResults            = new String[LAST_CLASSTYPE + 1];
248    m_NClasses                     = 4;
249  }
250
251  /**
252   * Used to create an instance of a specific search scheme.
253   *
254   * @return a suitably configured <code>ASSearch</code> value
255   */
256  public abstract ASSearch getSearch();
257
258  /**
259   * Used to create an instance of a specific evaluator.
260   *
261   * @return a suitably configured <code>ASEvaluation</code> value
262   */
263  public abstract ASEvaluation getEvaluator();
264
265  /**
266   * checks whether at least one attribute type can be handled with the
267   * given class type
268   *
269   * @param type      the class type to check for
270   * @return          true if at least one attribute type can be predicted with
271   *                  the given class
272   */
273  protected boolean canPredict(int type) {
274    return    m_NominalPredictors[type]
275           || m_NumericPredictors[type]
276           || m_StringPredictors[type]
277           || m_DatePredictors[type]
278           || m_RelationalPredictors[type];
279  }
280
281  /**
282   * returns a string for the class type
283   *
284   * @param type        the class type
285   * @return            the class type as string
286   */
287  protected String getClassTypeString(int type) {
288    return CheckAttributeSelection.attributeTypeToString(type);
289  }
290
291  /**
292   * tests whether the scheme can handle certain attributes and if not,
293   * if the exception is OK
294   *
295   * @param nom         to check for nominal attributes
296   * @param num         to check for numeric attributes
297   * @param str         to check for string attributes
298   * @param dat         to check for date attributes
299   * @param rel         to check for relational attributes
300   * @param allowFail   whether a junit fail can be executed
301   * @see CheckAttributeSelection#canPredict(boolean, boolean, boolean, boolean, boolean, boolean, int)
302   * @see CheckAttributeSelection#testsPerClassType(int, boolean, boolean)
303   */
304  protected void checkAttributes(boolean nom, boolean num, boolean str, 
305                                 boolean dat, boolean rel,
306                                 boolean allowFail) {
307    boolean[]     result;
308    String        att;
309    int           i;
310
311    // determine text for type of attributes
312    att = "";
313    if (nom)
314      att = "nominal";
315    else if (num)
316      att = "numeric";
317    else if (str)
318      att = "string";
319    else if (dat)
320      att = "date";
321    else if (rel)
322      att = "relational";
323   
324    for (i = FIRST_CLASSTYPE; i <= LAST_CLASSTYPE; i++) {
325      result = m_Tester.canPredict(nom, num, str, dat, rel, m_multiInstanceHandler, i);
326      if (nom)
327        m_NominalPredictors[i] = result[0];
328      else if (num)
329        m_NumericPredictors[i] = result[0];
330      else if (str)
331        m_StringPredictors[i] = result[0];
332      else if (dat)
333        m_DatePredictors[i] = result[0];
334      else if (rel)
335        m_RelationalPredictors[i] = result[0];
336
337      if (!result[0] && !result[1] && allowFail)
338        fail("Error handling " + att + " attributes (" + getClassTypeString(i) 
339            + " class)!");
340    }
341  }
342
343  /**
344   * tests whether the scheme can handle different types of attributes and
345   * if not, if the exception is OK
346   *
347   * @see #checkAttributes(boolean, boolean, boolean, boolean, boolean, boolean)
348   */
349  public void testAttributes() {
350    // nominal
351    checkAttributes(true,  false, false, false, false, true);
352    // numeric
353    checkAttributes(false, true,  false, false, false, true);
354    // string
355    checkAttributes(false, false, true,  false, false, true);
356    // date
357    checkAttributes(false, false, false, true,  false, true);
358    // relational
359    if (!m_multiInstanceHandler)
360      checkAttributes(false, false, false, false, true,  true);
361  }
362
363  /**
364   * tests whether the scheme declares a serialVersionUID.
365   */
366  public void testSerialVersionUID() {
367    boolean[]     result;
368
369    result = m_Tester.declaresSerialVersionUID();
370
371    if (!result[0])
372      fail("Doesn't declare serialVersionUID!");
373  }
374
375  /**
376   * tests whether the scheme handles instance weights correctly
377   *
378   * @see CheckAttributeSelection#instanceWeights(boolean, boolean, boolean, boolean, boolean, boolean, int)
379   * @see CheckAttributeSelection#testsPerClassType(int, boolean, boolean)
380   */
381  public void testInstanceWeights() {
382    boolean[]     result;
383    int           i;
384   
385    if (m_weightedInstancesHandler) {
386      for (i = FIRST_CLASSTYPE; i <= LAST_CLASSTYPE; i++) {
387        // does the scheme support this type of class at all?
388        if (!canPredict(i))
389          continue;
390       
391        result = m_Tester.instanceWeights(
392            m_NominalPredictors[i], 
393            m_NumericPredictors[i], 
394            m_StringPredictors[i], 
395            m_DatePredictors[i], 
396            m_RelationalPredictors[i], 
397            m_multiInstanceHandler, 
398            i);
399
400        if (!result[0])
401          System.err.println("Error handling instance weights (" + getClassTypeString(i) 
402              + " class)!");
403      }
404    }
405  }
406
407  /**
408   * tests whether scheme handles N classes
409   *
410   * @see CheckAttributeSelection#canHandleNClasses(boolean, boolean, boolean, boolean, boolean, boolean, int)
411   * @see CheckAttributeSelection#testsPerClassType(int, boolean, boolean)
412   * @see #m_NClasses
413   */
414  public void testNClasses() {
415    boolean[]     result;
416
417    if (!canPredict(Attribute.NOMINAL))
418      return;
419
420    result = m_Tester.canHandleNClasses(
421        m_NominalPredictors[Attribute.NOMINAL],
422        m_NumericPredictors[Attribute.NOMINAL],
423        m_StringPredictors[Attribute.NOMINAL],
424        m_DatePredictors[Attribute.NOMINAL],
425        m_RelationalPredictors[Attribute.NOMINAL],
426        m_multiInstanceHandler,
427        m_NClasses);
428
429    if (!result[0] && !result[1])
430      fail("Error handling " + m_NClasses + " classes!");
431  }
432
433  /**
434   * checks whether the scheme can handle the class attribute at a given
435   * position (0-based index, -1 means last).
436   *
437   * @param type        the class type
438   * @param position    the position of the class attribute (0-based, -1 means last)
439   * @return            true if the scheme can handle it
440   */
441  protected boolean checkClassAsNthAttribute(int type, int position) {
442    boolean[]     result;
443    String        indexStr;
444   
445    result = m_Tester.canHandleClassAsNthAttribute(
446        m_NominalPredictors[type], 
447        m_NumericPredictors[type], 
448        m_StringPredictors[type], 
449        m_DatePredictors[type], 
450        m_RelationalPredictors[type], 
451        m_multiInstanceHandler, 
452        type,
453        position);
454
455    if (position == -1)
456      indexStr = "last";
457    else
458      indexStr = (position + 1) + ".";
459   
460    if (!result[0] && !result[1])
461      fail("Error handling class as " + indexStr + " attribute (" 
462          + getClassTypeString(type) + " class)!");
463   
464    return result[0];
465  }
466
467  /**
468   * Tests whether the scheme can handle class attributes as Nth
469   * attribute. In case of multi-instance handler it performs no tests,
470   * since the multi-instance data has a fixed format (bagID,bag,class).
471   *
472   * @see CheckAttributeSelection#canHandleClassAsNthAttribute(boolean, boolean, boolean, boolean, boolean, boolean, int, int)
473   * @see CheckAttributeSelection#testsPerClassType(int, boolean, boolean)
474   */
475  public void testClassAsNthAttribute() {
476    int           i;
477   
478    // multi-Instance data has fixed format!
479    if (m_multiInstanceHandler)
480      return;
481   
482    for (i = FIRST_CLASSTYPE; i <= LAST_CLASSTYPE; i++) {
483      // does the scheme support this type of class at all?
484      if (!canPredict(i))
485        continue;
486     
487      // first attribute
488      m_handleClassAsFirstAttribute[i] = checkClassAsNthAttribute(i, 0);
489
490      // second attribute
491      m_handleClassAsSecondAttribute[i] = checkClassAsNthAttribute(i, 1);
492    }
493  }
494
495  /**
496   * tests whether the scheme can handle zero training instances
497   *
498   * @see CheckAttributeSelection#canHandleZeroTraining(boolean, boolean, boolean, boolean, boolean, boolean, int)
499   * @see CheckAttributeSelection#testsPerClassType(int, boolean, boolean)
500   */
501  public void testZeroTraining() {
502    boolean[]     result;
503    int           i;
504   
505    for (i = FIRST_CLASSTYPE; i <= LAST_CLASSTYPE; i++) {
506      // does the scheme support this type of class at all?
507      if (!canPredict(i))
508        continue;
509     
510      result = m_Tester.canHandleZeroTraining(
511          m_NominalPredictors[i], 
512          m_NumericPredictors[i], 
513          m_StringPredictors[i], 
514          m_DatePredictors[i], 
515          m_RelationalPredictors[i], 
516          m_multiInstanceHandler, 
517          i);
518
519      if (!result[0] && !result[1])
520        fail("Error handling zero training instances (" + getClassTypeString(i) 
521            + " class)!");
522    }
523  }
524
525  /**
526   * checks whether the scheme can handle the given percentage of
527   * missing predictors
528   *
529   * @param type        the class type
530   * @param percent     the percentage of missing predictors
531   * @param allowFail   if true a fail statement may be executed
532   * @return            true if the scheme can handle it
533   */
534  protected boolean checkMissingPredictors(int type, int percent, boolean allowFail) {
535    boolean[]     result;
536   
537    result = m_Tester.canHandleMissing(
538        m_NominalPredictors[type], 
539        m_NumericPredictors[type], 
540        m_StringPredictors[type], 
541        m_DatePredictors[type], 
542        m_RelationalPredictors[type], 
543        m_multiInstanceHandler, 
544        type,
545        true,
546        false,
547        percent);
548
549    if (allowFail) {
550      if (!result[0] && !result[1])
551        fail("Error handling " + percent + "% missing predictors (" 
552            + getClassTypeString(type) + " class)!");
553    }
554   
555    return result[0];
556  }
557
558  /**
559   * tests whether the scheme can handle missing predictors (20% and 100%)
560   *
561   * @see CheckAttributeSelection#canHandleMissing(boolean, boolean, boolean, boolean, boolean, boolean, int, boolean, boolean, int)
562   * @see CheckAttributeSelection#testsPerClassType(int, boolean, boolean)
563   */
564  public void testMissingPredictors() {
565    int           i;
566   
567    for (i = FIRST_CLASSTYPE; i <= LAST_CLASSTYPE; i++) {
568      // does the scheme support this type of class at all?
569      if (!canPredict(i))
570        continue;
571     
572      // 20% missing
573      checkMissingPredictors(i, 20, true);
574
575      // 100% missing
576      if (m_handleMissingPredictors[i])
577        checkMissingPredictors(i, 100, true);
578    }
579  }
580
581  /**
582   * checks whether the scheme can handle the given percentage of
583   * missing class labels
584   *
585   * @param type        the class type
586   * @param percent     the percentage of missing class labels
587   * @param allowFail   if true a fail statement may be executed
588   * @return            true if the scheme can handle it
589   */
590  protected boolean checkMissingClass(int type, int percent, boolean allowFail) {
591    boolean[]     result;
592   
593    result = m_Tester.canHandleMissing(
594        m_NominalPredictors[type], 
595        m_NumericPredictors[type], 
596        m_StringPredictors[type], 
597        m_DatePredictors[type], 
598        m_RelationalPredictors[type], 
599        m_multiInstanceHandler, 
600        type,
601        false,
602        true,
603        percent);
604
605    if (allowFail) {
606      if (!result[0] && !result[1])
607        fail("Error handling " + percent + "% missing class labels (" 
608            + getClassTypeString(type) + " class)!");
609    }
610   
611    return result[0];
612  }
613
614  /**
615   * tests whether the scheme can handle missing class values (20% and
616   * 100%)
617   *
618   * @see CheckAttributeSelection#canHandleMissing(boolean, boolean, boolean, boolean, boolean, boolean, int, boolean, boolean, int)
619   * @see CheckAttributeSelection#testsPerClassType(int, boolean, boolean)
620   */
621  public void testMissingClass() {
622    int           i;
623   
624    for (i = FIRST_CLASSTYPE; i <= LAST_CLASSTYPE; i++) {
625      // does the scheme support this type of class at all?
626      if (!canPredict(i))
627        continue;
628     
629      // 20% missing
630      checkMissingClass(i, 20, true);
631
632      // 100% missing
633      if (m_handleMissingClass[i])
634        checkMissingClass(i, 100, true);
635    }
636  }
637
638  /**
639   * tests whether the scheme correctly initializes in the
640   * search method
641   *
642   * @see CheckAttributeSelection#correctSearchInitialisation(boolean, boolean, boolean, boolean, boolean, boolean, int)
643   * @see CheckAttributeSelection#testsPerClassType(int, boolean, boolean)
644   */
645  public void testBuildInitialization() {
646    boolean[]     result;
647    int           i;
648   
649    for (i = FIRST_CLASSTYPE; i <= LAST_CLASSTYPE; i++) {
650      // does the scheme support this type of class at all?
651      if (!canPredict(i))
652        continue;
653     
654      result = m_Tester.correctSearchInitialisation(
655          m_NominalPredictors[i], 
656          m_NumericPredictors[i], 
657          m_StringPredictors[i], 
658          m_DatePredictors[i], 
659          m_RelationalPredictors[i], 
660          m_multiInstanceHandler, 
661          i);
662
663      if (!result[0] && !result[1])
664        fail("Incorrect build initialization (" + getClassTypeString(i) 
665            + " class)!");
666    }
667  }
668
669  /**
670   * tests whether the scheme alters the training set during training.
671   *
672   * @see CheckAttributeSelection#datasetIntegrity(boolean, boolean, boolean, boolean, boolean, boolean, int, boolean, boolean)
673   * @see CheckAttributeSelection#testsPerClassType(int, boolean, boolean)
674   */
675  public void testDatasetIntegrity() {
676    boolean[]     result;
677    int           i;
678   
679    for (i = FIRST_CLASSTYPE; i <= LAST_CLASSTYPE; i++) {
680      // does the scheme support this type of class at all?
681      if (!canPredict(i))
682        continue;
683     
684      result = m_Tester.datasetIntegrity(
685          m_NominalPredictors[i], 
686          m_NumericPredictors[i], 
687          m_StringPredictors[i], 
688          m_DatePredictors[i], 
689          m_RelationalPredictors[i], 
690          m_multiInstanceHandler, 
691          i,
692          m_handleMissingPredictors[i],
693          m_handleMissingClass[i]);
694
695      if (!result[0] && !result[1])
696        fail("Dataset is altered during training (" 
697            + getClassTypeString(i) + " class)!");
698    }
699  }
700
701  /**
702   * Builds a model using the current scheme using the given data.
703   *
704   * @param data        the instances to test the selection scheme on
705   * @return            a string containing the results.
706   */
707  protected String useScheme(Instances data) throws Exception {
708    AttributeSelection attsel = null;
709   
710    try {
711      attsel = new AttributeSelection();
712      attsel.setSearch(m_Search);
713      attsel.setEvaluator(m_Evaluator);
714      attsel.setSeed(42);
715    } 
716    catch (Exception e) {
717      e.printStackTrace();
718      fail("Problem setting up attribute selection: " + e);
719    }
720
721    attsel.SelectAttributes(data);
722   
723    return attsel.toResultsString();
724  }
725 
726  /**
727   * Provides a hook for derived classes to further modify the data. Currently,
728   * the data is just passed through.
729   *
730   * @param data        the data to process
731   * @return            the processed data
732   */
733  protected Instances process(Instances data) {
734    return data;
735  }
736
737  /**
738   * Runs a regression test -- this checks that the output of the tested
739   * object matches that in a reference version. When this test is
740   * run without any pre-existing reference output, the reference version
741   * is created.
742   */
743  public void testRegression() throws Exception {
744    int         i;
745    boolean     succeeded;
746    Regression  reg;
747    Instances   train;
748   
749    // don't bother if not working correctly
750    if (m_Tester.hasClasspathProblems())
751      return;
752   
753    reg = new Regression(this.getClass());
754    succeeded = false;
755    train = null;
756   
757    for (i = FIRST_CLASSTYPE; i <= LAST_CLASSTYPE; i++) {
758      // does the scheme support this type of class at all?
759      if (!canPredict(i))
760        continue;
761       
762      train = m_Tester.makeTestDataset(
763          42, m_Tester.getNumInstances(), 
764          m_NominalPredictors[i] ? 2 : 0,
765          m_NumericPredictors[i] ? 1 : 0, 
766          m_StringPredictors[i] ? 1 : 0,
767          m_DatePredictors[i] ? 1 : 0,
768          m_RelationalPredictors[i] ? 1 : 0,
769          2, 
770          i,
771          m_multiInstanceHandler);
772 
773      try {
774        m_RegressionResults[i] = useScheme(train);
775        succeeded = true;
776        reg.println(m_RegressionResults[i]);
777      }
778      catch (Exception e) {
779        String msg = e.getMessage().toLowerCase();
780        if (msg.indexOf("not in classpath") > -1)
781          return;
782
783        m_RegressionResults[i] = null;
784      }
785    }
786   
787    if (!succeeded) {
788      fail("Problem during regression testing: no successful predictions for any class type");
789    }
790
791    try {
792      String diff = reg.diff();
793      if (diff == null) {
794        System.err.println("Warning: No reference available, creating."); 
795      } else if (!diff.equals("")) {
796        fail("Regression test failed. Difference:\n" + diff);
797      }
798    } 
799    catch (java.io.IOException ex) {
800      fail("Problem during regression testing.\n" + ex);
801    }
802  }
803 
804  /**
805   * tests the listing of the options
806   */
807  public void testListOptions() {
808    if (m_OptionTester.getOptionHandler() != null) {
809      if (!m_OptionTester.checkListOptions())
810        fail("Options cannot be listed via listOptions.");
811    }
812  }
813 
814  /**
815   * tests the setting of the options
816   */
817  public void testSetOptions() {
818    if (m_OptionTester.getOptionHandler() != null) {
819      if (!m_OptionTester.checkSetOptions())
820        fail("setOptions method failed.");
821    }
822  }
823 
824  /**
825   * tests whether the default settings are processed correctly
826   */
827  public void testDefaultOptions() {
828    if (m_OptionTester.getOptionHandler() != null) {
829      if (!m_OptionTester.checkDefaultOptions())
830        fail("Default options were not processed correctly.");
831    }
832  }
833 
834  /**
835   * tests whether there are any remaining options
836   */
837  public void testRemainingOptions() {
838    if (m_OptionTester.getOptionHandler() != null) {
839      if (!m_OptionTester.checkRemainingOptions())
840        fail("There were 'left-over' options.");
841    }
842  }
843 
844  /**
845   * tests the whether the user-supplied options stay the same after setting.
846   * getting, and re-setting again.
847   *
848   * @see       #getOptionTester()
849   */
850  public void testCanonicalUserOptions() {
851    if (m_OptionTester.getOptionHandler() != null) {
852      if (!m_OptionTester.checkCanonicalUserOptions())
853        fail("setOptions method failed");
854    }
855  }
856 
857  /**
858   * tests the resetting of the options to the default ones
859   */
860  public void testResettingOptions() {
861    if (m_OptionTester.getOptionHandler() != null) {
862      if (!m_OptionTester.checkSetOptions())
863        fail("Resetting of options failed");
864    }
865  }
866 
867  /**
868   * tests for a globalInfo method
869   */
870  public void testGlobalInfo() {
871    if (!m_GOETester.checkGlobalInfo())
872      fail("No globalInfo method");
873  }
874 
875  /**
876   * tests the tool tips
877   */
878  public void testToolTips() {
879    if (!m_GOETester.checkToolTips())
880      fail("Tool tips inconsistent");
881  }
882}
Note: See TracBrowser for help on using the repository browser.