/**
   * Builds the classifier.
   *
   * @param data the data to train with
   * @throws Exception if classifier can't be built successfully
   */
  public void buildClassifier(Instances data) throws Exception {

    // can classifier handle the data?
    getCapabilities().testWithFail(data);

    // remove instances with missing class
    Instances filteredData = new Instances(data);
    filteredData.deleteWithMissingClass();

    // replace missing values
    m_replaceMissing = new ReplaceMissingValues();
    m_replaceMissing.setInputFormat(filteredData);
    filteredData = Filter.useFilter(filteredData, m_replaceMissing);

    // possibly convert nominal attributes globally
    if (m_convertNominal) {
      m_nominalToBinary = new NominalToBinary();
      m_nominalToBinary.setInputFormat(filteredData);
      filteredData = Filter.useFilter(filteredData, m_nominalToBinary);
    }

    int minNumInstances = 2;

    // create a FT  tree root
    if (m_modelType == 0)
      m_tree =
          new FTNode(
              m_errorOnProbabilities,
              m_numBoostingIterations,
              m_minNumInstances,
              m_weightTrimBeta,
              m_useAIC);

    // create a FTLeaves  tree root
    if (m_modelType == 1) {
      m_tree =
          new FTLeavesNode(
              m_errorOnProbabilities,
              m_numBoostingIterations,
              m_minNumInstances,
              m_weightTrimBeta,
              m_useAIC);
    }
    // create a FTInner  tree root
    if (m_modelType == 2)
      m_tree =
          new FTInnerNode(
              m_errorOnProbabilities,
              m_numBoostingIterations,
              m_minNumInstances,
              m_weightTrimBeta,
              m_useAIC);

    // build tree
    m_tree.buildClassifier(filteredData);
    // prune tree
    m_tree.prune();
    m_tree.assignIDs(0);
    m_tree.cleanup();
  }
 /**
  * Returns a description of the classifier.
  *
  * @return a string representation of the classifier
  */
 public String toString() {
   if (m_tree != null) {
     if (m_modelType == 0) return "FT tree \n------------------\n" + m_tree.toString();
     else {
       if (m_modelType == 1) return "FT Leaves tree \n------------------\n" + m_tree.toString();
       else return "FT Inner tree \n------------------\n" + m_tree.toString();
     }
   } else {
     return "No tree built";
   }
 }
  /**
   * Returns class probabilities for an instance.
   *
   * @param instance the instance to compute the distribution for
   * @return the class probabilities
   * @throws Exception if distribution can't be computed successfully
   */
  public double[] distributionForInstance(Instance instance) throws Exception {

    // replace missing values
    m_replaceMissing.input(instance);
    instance = m_replaceMissing.output();

    // possibly convert nominal attributes
    if (m_convertNominal) {
      m_nominalToBinary.input(instance);
      instance = m_nominalToBinary.output();
    }
    return m_tree.distributionForInstance(instance);
  }
 /**
  * Returns the number of leaves in the tree
  *
  * @return the number of leaves in the tree
  */
 public int measureNumLeaves() {
   return m_tree.numLeaves();
 }
 /**
  * Returns the size of the tree
  *
  * @return the size of the tree
  */
 public int measureTreeSize() {
   return m_tree.numNodes();
 }
  /**
   * Returns graph describing the tree.
   *
   * @return the graph describing the tree
   * @throws Exception if graph can't be computed
   */
  public String graph() throws Exception {

    return m_tree.graph();
  }