private Partition sIB_OptimizeT(Partition tmpT, Input input) {
    boolean done = false;
    int change = 0, loopCounter = 0;
    if(m_verbose) {
      System.out.println("Optimizing...");
      System.out.println("-------------");
    }
    while (!done) {
      change = 0;
      for (int i = 0; i < m_numInstances; i++) {
	int old_t = tmpT.Pt_x[i];
	// If the current cluster only has one instance left, leave it.
	if (tmpT.size(old_t) == 1) {
	  if(m_verbose){
	    System.out.format("cluster %s has only 1 doc remain\n", old_t);
	  }
	  continue;
	}
	// draw the instance out from its previous cluster
	reduce_x(i, old_t, tmpT, input);
	
	// re-cluster the instance
	int new_t = clusterInstance(i, input, tmpT);	
	if (new_t != old_t) {	  
	  change++;
	  updateAssignment(i, new_t, tmpT, input.Px[i], input.Py_x);
	}
      }
      
      tmpT.counter += change;
      if(m_verbose){
	System.out.format("iteration %s , changes : %s\n", loopCounter, change);
      }
      done = checkConvergence(change, loopCounter);
      loopCounter++;
    }

    // compute the sIB score
    tmpT.L = sIB_local_MI(tmpT.Py_t, tmpT.Pt);
    if(m_verbose){
      System.out.format("score (L) : %s \n", Utils.doubleToString(tmpT.L, 4));
    }
    return tmpT;
  }