// Path: src/com/rcwang/seal/util/StringFactory.java
// public static class SID implements Iterable<String> {
//     
//   String[] array;
//     
//   public SID(List<String> strs) {
//     array = strs.toArray(new String[strs.size()]);
//   }
// 
//   public SID(SID id) {
//     this(id.array);
//   }
// 
//   public SID(String[] array) {
//     this.array = array.clone();
//   }
//     
//   public void append(SID sid) {
//     append(sid.array);
//   }
//     
//   public void append(String s) {
//     append(StringFactory.toID(s));
//   }
//     
//   public void append(String[] array) {
//     String[] array2 = new String[this.array.length+array.length];
//     System.arraycopy(this.array, 0, array2, 0, this.array.length);
//     System.arraycopy(array, 0, array2, this.array.length, array.length);
//     this.array = array2;
//   }
//     
//   @Override
//   public boolean equals(Object obj) {
//     if (this == obj) return true;
//     if (obj == null) return false;
//     if (getClass() != obj.getClass()) return false;
//     final SID other = (SID) obj;
//     if (!Arrays.equals(array, other.array))
//       return false;
//     return true;
//   }
//     
//   @Override
//   public int hashCode() {
//     return 31 + Arrays.hashCode(array);
//   }
//     
//   public Iterator<String> iterator() {
//     return Arrays.asList(array).iterator();
//   }
//     
//   public int length() {
//     int length = 0;
//     for (String s : this)
//       length += s.length();
//     return length;
//   }
// 
//   @Override
//   public String toString() {
//     return StringFactory.toName(this);
//   }
//     
//   public EntityLiteral toLiteral() { return new EntityLiteral(StringFactory.toName(this)); }
//     
//   public SID toLower() {
//   	return StringFactory.toID(new EntityLiteral(StringFactory.toName(this).toLowerCase()));
//   }
// }


import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import org.apache.log4j.Logger;
import com.rcwang.seal.util.StringFactory.SID;

          i = numEpochs;
          break;
        } else if (binaryTrueLabel != binaryPredictedLabel) {
          // incorrect prediction; so update and create a new perceptron
          weightedPerceptron = update(weightedPerceptron, instance, binaryTrueLabel);
//          log.info(epochID + instance.id + " New Perceptrion: " + weightedPerceptron + ", Weight: " + weightedPerceptron.weight);
        } else {
          // correct prediction; so increment current perceptron's weight
          weightedPerceptron.weight++;
        }
      }
    }
    Helper.printElapsedTime(startTime);
    Helper.printMemoryUsed();
  }
  
  private WeightedPerceptron update(WeightedPerceptron weightedPerceptron, SparseVector instance, double trueLabel) {
    boolean makeNewPerceptron = (weightedPerceptron.weight >= MIN_PERCEPTRON_WEIGHT);
    double[] oldPerceptron = weightedPerceptron.perceptron;
    double[] newPerceptron = makeNewPerceptron ? new double[oldPerceptron.length] : oldPerceptron;

    int index = 0;
    for (SID featureID : matrix.getColumnIDs()) {
      double v = oldPerceptron[index];
      Cell cell = instance.get(featureID);
      double x = (cell == null) ? 0 : cell.value;
      newPerceptron[index++] = v + trueLabel * x;
    }
    
    if (makeNewPerceptron) {

// Path: src/com/rcwang/seal/util/StringFactory.java
// public static class SID implements Iterable<String> {
//     
//   String[] array;
//     
//   public SID(List<String> strs) {
//     array = strs.toArray(new String[strs.size()]);
//   }
// 
//   public SID(SID id) {
//     this(id.array);
//   }
// 
//   public SID(String[] array) {
//     this.array = array.clone();
//   }
//     
//   public void append(SID sid) {
//     append(sid.array);
//   }
//     
//   public void append(String s) {
//     append(StringFactory.toID(s));
//   }
//     
//   public void append(String[] array) {
//     String[] array2 = new String[this.array.length+array.length];
//     System.arraycopy(this.array, 0, array2, 0, this.array.length);
//     System.arraycopy(array, 0, array2, this.array.length, array.length);
//     this.array = array2;
//   }
//     
//   @Override
//   public boolean equals(Object obj) {
//     if (this == obj) return true;
//     if (obj == null) return false;
//     if (getClass() != obj.getClass()) return false;
//     final SID other = (SID) obj;
//     if (!Arrays.equals(array, other.array))
//       return false;
//     return true;
//   }
//     
//   @Override
//   public int hashCode() {
//     return 31 + Arrays.hashCode(array);
//   }
//     
//   public Iterator<String> iterator() {
//     return Arrays.asList(array).iterator();
//   }
//     
//   public int length() {
//     int length = 0;
//     for (String s : this)
//       length += s.length();
//     return length;
//   }
// 
//   @Override
//   public String toString() {
//     return StringFactory.toName(this);
//   }
//     
//   public EntityLiteral toLiteral() { return new EntityLiteral(StringFactory.toName(this)); }
//     
//   public SID toLower() {
//   	return StringFactory.toID(new EntityLiteral(StringFactory.toName(this).toLowerCase()));
//   }
// }


// Path: src/com/rcwang/seal/util/VotedPerceptron.java
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import org.apache.log4j.Logger;
import com.rcwang.seal.util.StringFactory.SID;

          i = numEpochs;
          break;
        } else if (binaryTrueLabel != binaryPredictedLabel) {
          // incorrect prediction; so update and create a new perceptron
          weightedPerceptron = update(weightedPerceptron, instance, binaryTrueLabel);
//          log.info(epochID + instance.id + " New Perceptrion: " + weightedPerceptron + ", Weight: " + weightedPerceptron.weight);
        } else {
          // correct prediction; so increment current perceptron's weight
          weightedPerceptron.weight++;
        }
      }
    }
    Helper.printElapsedTime(startTime);
    Helper.printMemoryUsed();
  }
  
  private WeightedPerceptron update(WeightedPerceptron weightedPerceptron, SparseVector instance, double trueLabel) {
    boolean makeNewPerceptron = (weightedPerceptron.weight >= MIN_PERCEPTRON_WEIGHT);
    double[] oldPerceptron = weightedPerceptron.perceptron;
    double[] newPerceptron = makeNewPerceptron ? new double[oldPerceptron.length] : oldPerceptron;

    int index = 0;
    for (SID featureID : matrix.getColumnIDs()) {
      double v = oldPerceptron[index];
      Cell cell = instance.get(featureID);
      double x = (cell == null) ? 0 : cell.value;
      newPerceptron[index++] = v + trueLabel * x;
    }
    
    if (makeNewPerceptron) {

      weightedPerceptron = new WeightedPerceptron(newPerceptron);
