if (m_DebugVektorsFile != null) initDebugVektorsInput();
if (m_DebugVectorsFile.exists() && m_DebugVectorsFile.isFile()) initDebugVectorsInput();
  public void buildClusterer(Instances data) throws Exception {    // can clusterer handle the data?    getCapabilities().testWithFail(data);    m_NumSplits = 0;    m_NumSplitsDone = 0;    m_NumSplitsStillDone = 0;    // replace missing values    m_ReplaceMissingFilter = new ReplaceMissingValues();    m_ReplaceMissingFilter.setInputFormat(data);    m_Instances = Filter.useFilter(data, m_ReplaceMissingFilter);        // initialize random function    Random random0 = new Random(m_Seed);    // num of clusters to start with    m_NumClusters =  m_MinNumClusters;    // set distance function to default    if (m_DistanceF == null) {      m_DistanceF = new EuclideanDistance();    }    m_DistanceF.setInstances(m_Instances);    checkInstances();    if (m_DebugVektorsFile != null)      initDebugVektorsInput();    // make list of indexes for m_Instances    int [] allInstList = new int[m_Instances.numInstances()];     for (int i = 0; i < m_Instances.numInstances(); i++) {      allInstList[i] = i;    }        // set model used (just for convenience)    m_Model = new Instances(m_Instances, 0);    // produce the starting centers    if (m_CenterInput != null) {      // read centers from file      m_ClusterCenters = new Instances(m_CenterInput);      m_NumClusters = m_ClusterCenters.numInstances();    }    else      // makes the first centers randomly      m_ClusterCenters = makeCentersRandomly(random0,					     m_Instances, m_NumClusters);    PFD(D_FOLLOWSPLIT, "\n*** Starting centers ");    for (int k = 0; k < m_ClusterCenters.numInstances(); k++) {      PFD(D_FOLLOWSPLIT, "Center " + k + ": " + m_ClusterCenters.instance(k));    }    PrCentersFD(D_PRINTCENTERS);    boolean finished = false;    Instances children;     // builds up a KDTree    if (m_KDTree != null) {      m_KDTree.setInstances(m_Instances);    }      // loop counter of main loop    m_IterationCount = 0;    /**     * "finished" does get true as soon as:     * 1. number of clusters gets >= m_MaxClusters,      * 2. in the last round, none of the centers have been split     *      * if number of clusters is already >= m_MaxClusters      * part 1 (= Improve-Params) is done at least once.     */    while (!finished &&           !stopIteration(m_IterationCount, m_MaxIterations)) {            /* ====================================================================       * 1. Improve-Params                         *    conventional K-means       */      PFD(D_FOLLOWSPLIT, "\nBeginning of main loop - centers:");      PrCentersFD(D_FOLLOWSPLIT);      PFD(D_ITERCOUNT, "\n*** 1. Improve-Params " + m_IterationCount + 	  ". time");      m_IterationCount++;      // prepare to converge      boolean converged = false;      // initialize assignments to -1      m_ClusterAssignments = initAssignments(m_Instances.numInstances());      // stores a list of indexes of instances belonging to each center      int [][] instOfCent = new int[m_ClusterCenters.numInstances()][];      // KMeans loop counter      int kMeansIteration = 0;      // converge in conventional K-means ----------------------------------      PFD(D_FOLLOWSPLIT, "\nConverge in K-Means:");      while (!converged && 	     !stopKMeansIteration(kMeansIteration, m_MaxKMeans)) {		kMeansIteration++;	converged = true;	        // assign instances to centers -------------------------------------        converged = assignToCenters(m_KDTree,				    m_ClusterCenters, 				    instOfCent,				    allInstList, 				    m_ClusterAssignments,				    kMeansIteration);		PFD(D_FOLLOWSPLIT, "\nMain loop - Assign - centers:");	PrCentersFD(D_FOLLOWSPLIT);	// compute new centers = centers of mass of points        converged = recomputeCenters(m_ClusterCenters, // clusters				     instOfCent,       // their instances				     m_Model);         // model information      PFD(D_FOLLOWSPLIT, "\nMain loop - Recompute - centers:");      PrCentersFD(D_FOLLOWSPLIT);      }      PFD(D_FOLLOWSPLIT, "");      PFD(D_FOLLOWSPLIT, "End of Part: 1. Improve-Params - conventional K-means");      /** =====================================================================       * 2. Improve-Structur       */      // BIC before split distortioning the centres      m_Mle = distortion(instOfCent, m_ClusterCenters);      m_Bic = calculateBIC(instOfCent, m_ClusterCenters, m_Mle);      PFD(D_FOLLOWSPLIT, "m_Bic " + m_Bic);      int currNumCent = m_ClusterCenters.numInstances();      Instances splitCenters = new Instances(m_ClusterCenters, 					     currNumCent * 2);            // store BIC values of parent and children      double [] pbic = new double [currNumCent];      double [] cbic = new double [currNumCent];                  // split each center      for (int i = 0; i < currNumCent 	   // this could help to optimize the algorithm	   //	     && currNumCent + numSplits <= m_MaxNumClusters           ; 	   i++) {		PFD(D_FOLLOWSPLIT, "\nsplit center " + i +		      " " + m_ClusterCenters.instance(i));	Instance currCenter = m_ClusterCenters.instance(i);	int [] currInstList = instOfCent[i];	int currNumInst = instOfCent[i].length;		// not enough instances; than continue with next	if (currNumInst <= 2) {	  pbic[i] = Double.MAX_VALUE;	  cbic[i] = 0.0;	  // add center itself as dummy	  splitCenters.add(currCenter);	  splitCenters.add(currCenter);	  continue;	}		// split centers  ----------------------------------------------	double variance = m_Mle[i] / (double)currNumInst;	children = splitCenter(random0, currCenter, variance, m_Model);		// initialize assignments to -1	int[] oneCentAssignments = initAssignments(currNumInst);	int[][] instOfChCent = new int [2][]; // todo maybe split didn't work		// converge the children  --------------------------------------	converged = false;	int kMeansForChildrenIteration = 0;	PFD(D_FOLLOWSPLIT, "\nConverge, K-Means for children: " + i);	while (!converged &&           !stopKMeansIteration(kMeansForChildrenIteration, 			       m_MaxKMeansForChildren)) {	  kMeansForChildrenIteration++;	  	  converged =	    assignToCenters(children, instOfChCent,			    currInstList, oneCentAssignments);	  if (!converged) {       	    recomputeCentersFast(children, instOfChCent, m_Model);	  }	} 	// store new centers for later decision if they are taken	splitCenters.add(children.instance(0));	splitCenters.add(children.instance(1));	PFD(D_FOLLOWSPLIT, "\nconverged cildren ");	PFD(D_FOLLOWSPLIT, " " + children.instance(0));	PFD(D_FOLLOWSPLIT, " " + children.instance(1));	// compare parent and children model by their BIC-value	pbic[i] = calculateBIC(currInstList, currCenter,  m_Mle[i], m_Model);	double [] chMLE = distortion(instOfChCent, children);	cbic[i] = calculateBIC(instOfChCent, children, chMLE);      } // end of loop over clusters      // decide which one to split and make new list of cluster centers      Instances newClusterCenters = null;      newClusterCenters = newCentersAfterSplit(pbic, cbic, m_CutOffFactor,                                                 splitCenters);      /**       * Compare with before Improve-Structure       */      int newNumClusters = newClusterCenters.numInstances();      if (newNumClusters != m_NumClusters) {		PFD(D_FOLLOWSPLIT, "Compare with non-split");	// initialize assignments to -1	int [] newClusterAssignments = 	  initAssignments(m_Instances.numInstances());		// stores a list of indexes of instances belonging to each center	int [][] newInstOfCent = new int[newClusterCenters.numInstances()][];		// assign instances to centers -------------------------------------	converged = assignToCenters(m_KDTree,				    newClusterCenters, 				    newInstOfCent,				    allInstList, 				    newClusterAssignments,				    m_IterationCount);		double [] newMle = distortion(newInstOfCent, newClusterCenters);	double newBic = calculateBIC(newInstOfCent, newClusterCenters, newMle);	PFD(D_FOLLOWSPLIT, "newBic " + newBic);	if (newBic > m_Bic) {          PFD(D_FOLLOWSPLIT, "*** decide for new clusters");	  m_Bic = newBic;	  m_ClusterCenters = newClusterCenters;	  m_ClusterAssignments = newClusterAssignments;	} else {          PFD(D_FOLLOWSPLIT, "*** keep old clusters");        }      }      newNumClusters = m_ClusterCenters.numInstances();      // decide if finished: max num cluster reached       // or last centers where not split at all       if ((newNumClusters >= m_MaxNumClusters) 	  || (newNumClusters == m_NumClusters)) {	finished = true;      }      m_NumClusters = newNumClusters;    }  }