public Instance cleanse(Instance before) throws Exception{

    Instances insts = before.relationalValue(1).stringFreeStructure();
    Instance after = new DenseInstance(before.numAttributes());
    after.setDataset(m_Attributes);

    for(int g=0; g < before.relationalValue(1).numInstances(); g++){
      Instance datum = before.relationalValue(1).instance(g);
      double[] minNoiDists = new double[m_Choose];
      double[] minValDists = new double[m_Choose];
      int noiseCount = 0, validCount = 0;
      double[] nDist = new double[m_Mean.length]; 
      double[] vDist = new double[m_Mean.length]; 

      for(int h=0; h < m_Mean.length; h++){
        if(m_ValidM[h] == null)
          vDist[h] = Double.POSITIVE_INFINITY;
        else
          vDist[h] = distance(datum, m_ValidM[h], m_ValidV[h], h);

        if(m_NoiseM[h] == null)
          nDist[h] = Double.POSITIVE_INFINITY;
        else
          nDist[h] = distance(datum, m_NoiseM[h], m_NoiseV[h], h);
      }

      for(int k=0; k < m_Choose; k++){
        int pos = Utils.minIndex(vDist);
        minValDists[k] = vDist[pos];
        vDist[pos] = Double.POSITIVE_INFINITY;
        pos = Utils.minIndex(nDist);
        minNoiDists[k] = nDist[pos];
        nDist[pos] = Double.POSITIVE_INFINITY;
      }

      int x = 0,y = 0;
      while((x+y) < m_Choose){
        if(minValDists[x] <= minNoiDists[y]){
          validCount++;
          x++;
        }
        else{
          noiseCount++;
          y++;
        }
      }
      if(x >= y)
        insts.add (datum);

    }

    after.setValue(0, before.value( 0));
    after.setValue(1, after.attribute(1).addRelation(insts));
    after.setValue(2, before.value( 2));

    return after;
  }