@Override
 public SparseFeatureVector calculateFeature(
     Instance instance,
     Label y,
     int lastIndex,
     int target,
     LabelUnit candidateLabelUnit,
     boolean local) {
   // TODO cache strings
   SparseFeatureVector fv = new SparseFeatureVector(params);
   if (instance.getSequence().get(target) instanceof Word) {
     Word word = (Word) instance.getSequence().get(target);
     String candidateLabel = ((WordLabelUnit) candidateLabelUnit).getLabel();
     assert word.getWord().getCache() != null
         : word.getWord().getId() + ":" + word.getWord().getRealBase();
     fv.add(word.getWord().getCache().getNodeFeatures(), candidateLabel);
     if (params.getUseGlobalFeatures() && !local) {
       SparseFeatureVector globalFv =
           calcWordGlobalFeatures(
               word, instance, y, lastIndex, (WordLabelUnit) candidateLabelUnit);
       assert params.getAverageNumWords() > 0.;
       globalFv.scale(params.getGlobalWeight());
       fv.add(globalFv, "GLOBAL");
     }
   } else {
     assert instance.getSequence().get(target) instanceof Pair;
     Pair pair = (Pair) instance.getSequence().get(target);
     PairLabelUnit candidatePairLabelUnit = (PairLabelUnit) candidateLabelUnit;
     Node w1 = pair.getW1().getWord();
     Node w2 = pair.getW2().getWord();
     fv.add(
         w1.getCache().getFullPathFeatures(w2), candidatePairLabelUnit.getLabel().concat("PATH"));
     if (params.getUseGlobalFeatures() && !local) {
       SparseFeatureVector globalFv =
           calcPairGlobalFeatures(pair, instance, y, lastIndex, candidatePairLabelUnit);
       assert params.getAverageNumWords() > 0.;
       globalFv.scale(params.getGlobalWeight());
       fv.add(globalFv, "GLOBAL");
     }
   }
   assert fv.size() > 0;
   return fv;
 }
 protected void addParallelInfoToFV(
     SparseFeatureVector fv,
     String wBase,
     String wPOS,
     Node w1,
     String label1,
     Node w2,
     String label2,
     String header) {
   SparseFeatureVector paraFv = new SparseFeatureVector(params);
   paraFv.add(
       w1.getCache().getShortestPathFeatures(w2),
       header.concat(label1).concat(wBase).concat(label2));
   paraFv.add(
       w1.getCache().getShortestPathFeatures(w2),
       header.concat(label1).concat(wPOS).concat(label2));
   paraFv.add(w1.getCache().getShortestPathFeatures(w2), header.concat(label1).concat(label2));
   paraFv.normalize(1.);
   fv.add(paraFv);
 }