gt:         for (int i = 0; i < listOfBlocks.size(); i++){
context: /*
   * To change this template, choose Tools | Templates
   * and open the template in the editor.
   */
  
  package ida.ilp.treeLiker;
  
  import ida.ilp.treeLiker.aggregables.VoidAggregablesBuilder;
  import ida.ilp.treeLiker.impl.BlockBuilder;
  import ida.ilp.treeLiker.impl.BlocksWithLiteralsInDomainBuilder;
  import ida.ilp.treeLiker.impl.CombinationsBuilder;
  import ida.ilp.treeLiker.impl.DomainComputing;
  import ida.ilp.treeLiker.impl.FeatureSearchUtils;
  import ida.ilp.treeLiker.impl.HSubsumption;
  import ida.ilp.treeLiker.impl.MaxSizeChecker;
  import ida.ilp.treeLiker.impl.NumAggregatorsChecker;
  import ida.ilp.treeLiker.impl.Pruning;
  import ida.ilp.treeLiker.impl.TermsInDomainsOfBuilder;
  import ida.utils.*;
  import ida.utils.collections.*;
  import ida.utils.tuples.*;
  
  import java.util.*;
  import java.util.concurrent.*;
  
  /**
   * Class implementing algorithm HiFi (Kuzelka, Zelezny, ILP - late breaking papers, 2008).
   * 
   * @author Ondra
   */
  public class HiFi {
  
      private List<ProgressListener> progressListeners = new ArrayList<ProgressListener>();
  
      private Dataset examples;
  
      private int maxSize = Integer.MAX_VALUE;
      
      private int maxAggregators = Integer.MAX_VALUE;
      
      private boolean[] mask;
  
      private boolean[] negMask;
  
      private boolean alive = true;
  
      protected static int LITERALS = 1, TERMS = 2;
      
      private HSubsumption hsubsumptionEngine = new HSubsumption();
      
      private DomainComputing domainComputing;
      
      private Pruning pruning;
      
      private List<SyntaxChecker> syntaxCheckers = new ArrayList<SyntaxChecker>();
      
      private AggregablesBuilder aggregablesBuilder = VoidAggregablesBuilder.construct();
      
      private AggregablesBuilder postProcessingAggregablesBuilder = VoidAggregablesBuilder.construct();
      
      private Block normalizationFactor;
  
      /**
       * Creates a new instance of class HiFi.
       * @param examples datset of examples for which features should be constructed or for which propositionalized table should be constructed.
       */
      public HiFi(Dataset examples){
          this.examples = examples;
          this.domainComputing = new DomainComputing(this.examples.shallowCopy());
          this.mask = new boolean[examples.countExamples()];
          Arrays.fill(this.mask, true);
          this.negMask = VectorUtils.not(mask);
          this.pruning = new Pruning(mask, negMask, 1);
      }
  
      /**
       * Constructs all non-reducible non-redundant features complying with the language bias
       * specified using set <em>definitions</em>
       * @param definitions templates - i.e. specification of language bias (similar to mode declarations)
       * @return List of constructed features
       */
      public List<Block> constructFeatures(Set<PredicateDefinition> definitions){
          if (!alive){
              throw new IllegalStateException("Each instance of class RelF can be used only once.");
          } else {
              alive = false;
          }
          List<Block> constructedFeatures = new ArrayList<Block>();
          MultiList<Integer, Block> mm = new MultiList<Integer, Block>();
          List<PredicateDefinition> open = buildOpenList(definitions);
          this.syntaxCheckers.add(new MaxSizeChecker(this.maxSize, open));
          this.syntaxCheckers.add(new NumAggregatorsChecker(this.maxAggregators));
          for (ProgressListener pl : progressListeners) {
              pl.readingExamples();
          }
          List<PredicateDefinition> inputOnlyDefinitions = new ArrayList<PredicateDefinition>();
          for (PredicateDefinition def : open){
              if (def.isInputOnly()){
                  inputOnlyDefinitions.add(def);
              }
          }
          open = Sugar.listDifference(open, inputOnlyDefinitions);
          for (PredicateDefinition def : inputOnlyDefinitions){
              if (Settings.VERBOSITY > 0){
                  System.out.println("Processing: " + def);
              }
              for (ProgressListener pl : this.progressListeners){
                  pl.processingPredicate(def);
              }
              if (def.isInputOnly()) {
                  List<Block> generatedPosFeatures = new ArrayList<Block>();
                  Block posFeat = new Block(def, this.aggregablesBuilder);
                  int[] modes = def.modes();
                  for (int j = 0; j < modes.length; j++) {
                      if (modes[j] == PredicateDefinition.INPUT){
                          generatedPosFeatures.add(posFeat);
                      }
                  }
                  mm.putAll(def.types()[def.input()], generatedPosFeatures);
              }
          }
          for (Map.Entry<Integer,List<Block>> entry : mm.copy().entrySet()){
              Map<Integer, Domain[]> computedDomains = domainComputing.computeTermDomainsInParallel(entry.getValue());
              Collection<Block> filtered = pruning.filterRedundantBlocksInParallel(entry.getValue(), computedDomains);
              mm.set(entry.getKey(), filtered);
          }
          examples.reset();
          for (int i = 0; i < open.size(); i++) {
              PredicateDefinition def = open.get(i);
              if (Settings.VERBOSITY > 0){
                  System.out.println("Processing: " + def);
              }
              for (ProgressListener pl : this.progressListeners){
                  pl.processingPredicate(def);
              }
              List<Collection<Join>> combinations = Collections.synchronizedList(new ArrayList<Collection<Join>>());
              for (int j = 0; j < def.modes().length; j++) {
                  if (def.modes()[j] == PredicateDefinition.OUTPUT) {
                      combinations.add(combinationsOfPosFeatures(mm, def.types()[j], def.branchingFactors()[j]));
                  } else {
                      combinations.add(new ArrayList<Join>());
                  }
              }
              Collection<Block> newBlocks = buildBlocksFromCombinations(def, combinations);
              if (def.isOutputOnly()){
                  for (Block newFeature : newBlocks){
                      constructedFeatures.add(newFeature);
                  }
              } else {
                  if (mm.containsKey(def.types()[def.input()])){
                      Map<Integer, Domain[]> computedDomains = domainComputing.computeTermDomainsInParallel(Sugar.listFromCollections(newBlocks, mm.get(def.types()[def.input()])));
                      Collection<Block> filtered = pruning.filterRedundantBlocksInParallel(Sugar.setFromCollections(newBlocks, mm.get(def.types()[def.input()])), computedDomains);
                      mm.set(def.types()[def.input()], filtered);
                  } else {
                      mm.putAll(def.types()[def.input()], newBlocks);
                  }
              }
          }
          return constructedFeatures;
      }
      
      /**
       * Given a set of features (instances of class Block), this method computes the propositionalized table.
       * @param constructedFeatures set of constructed features
       * @return propositionalized table (i.e. an attribute-value table) in which the features play the role of attributes.
       */
      public Table<Integer,String> constructTable(List<Block> constructedFeatures){
          examples.reset();
          Table<Integer,String> table = new Table<Integer,String>();
          while (examples.hasNextExample()){
              examples.nextExample();
              table.addClassification(examples.currentIndex(), examples.classificationOfCurrentExample());
          }
          Map<Integer,Domain[]> domains = domainComputing.computeLiteralDomainsInParallel(constructedFeatures);
          if (this.postProcessingAggregablesBuilder != null && !this.aggregablesBuilder.equals(this.postProcessingAggregablesBuilder) && !(this.postProcessingAggregablesBuilder instanceof VoidAggregablesBuilder)){
              FeaturesProcessing.process(constructedFeatures, new Sugar.VoidFun<Block>(){
                  public void apply(Block t) {
                      t.deleteCachedDomains();
                      t.setAggregablesBuilder(postProcessingAggregablesBuilder);
                  }
              });
          }
          if (this.normalizationFactor != null){
              this.normalizationFactor.applyRecursively(new Sugar.Fun<Block,Block>(){
                  public Block apply(Block t) {
                      t.setAggregablesBuilder(postProcessingAggregablesBuilder);
                      return t;
                  }
              });
          }
          examples.reset();
          while (examples.hasNextExample()) {
              Example example = examples.nextExample();
              Double normalizationCoeff = null;
              if (this.normalizationFactor != null){
                  Domain d = this.normalizationFactor.termDomain(-1, example);
                  if (!d.isEmpty() && d.getAggregableByDomainElement(-1) != null){
                      normalizationCoeff = new Double(d.getAggregableByDomainElement(-1).toString());
                  }
              }
              for (Block block : constructedFeatures){
                  if (this.aggregablesBuilder instanceof VoidAggregablesBuilder && this.postProcessingAggregablesBuilder instanceof VoidAggregablesBuilder){
                      if (!block.literalDomain(example).isEmpty()){
                          table.add(examples.currentIndex(), block.toClause(), "+", block.size());
                      } else {
                          table.add(examples.currentIndex(), block.toClause(), "-", block.size());
                      }
                  } else {
                      if (!domains.get(block.id())[examples.currentIndex()].isEmpty()){
                          Domain domain = block.termDomain(-1, example);
                          if (normalizationCoeff == null){
                              table.add(examples.currentIndex(), block.toClause(), domain.getAggregableByDomainElement(-1).toString()); 
                          } else {
                              table.add(examples.currentIndex(), block.toClause(), String.valueOf(Double.parseDouble(domain.getAggregableByDomainElement(-1).toString())/normalizationCoeff)); 
                          }
                      } else {
                          table.add(examples.currentIndex(), block.toClause(), "0", block.size());
                      }
                  }
              }
          }
          for (ProgressListener pl : progressListeners) {
              pl.finished(table.countOfAttributes());
          }
          return table;
      }
  
      private Collection<Join> combinationsOfPosFeatures(MultiList posFeatures, int inputType, int branching){
          //[example,term] -> [pos feature, which has term in its domain]
          MultiMap<Pair<Integer,Integer>,Block> termsInDomainsOf = new MultiMap<Pair<Integer,Integer>,Block>();
          List<Block> listOfBlocks = Sugar.listFromCollections(posFeatures.get(inputType));
          ConcurrentHashMap<Block,Integer> indices = new ConcurrentHashMap<Block,Integer>();
          ConcurrentHashMap<Integer,Block> posFeaturesLookup = new ConcurrentHashMap<Integer,Block>();
  