// Path: src/edu/stanford/nlp/semparse/open/dataset/Example.java
// public class Example {
//   public String displayId;  // For debugging
//   
//   public final String phrase;
//   public final ExpectedAnswer expectedAnswer;
//   public KNode tree;  // Deterministic function of the phrase
//   public List<CandidateGroup> candidateGroups;
//   public List<Candidate> candidates;  // Candidate predictions
//   public AveragedWordVector averagedWordVector;
// 
//   public Example(String phrase) {
//     this(phrase, null);
//   }
//   
//   public Example(String phrase, ExpectedAnswer expectedAnswer) {
//     this.phrase = phrase;
//     this.expectedAnswer = expectedAnswer;
//   }
//   
//   @Override public String toString() {
//     return "[" + phrase + "]";
//   }
//   
//   public void initAveragedWordVector() {
//     if (averagedWordVector == null)
//       averagedWordVector = new AveragedWordVector(phrase);
//   }
// }
// 
// Path: src/edu/stanford/nlp/semparse/open/model/candidate/Candidate.java
// public class Candidate {
//   public final Example ex;
//   public final CandidateGroup group;
//   public final TreePattern pattern;
//   public final List<String> predictedEntities;
//   public FeatureVector features;
//   
//   public Candidate(CandidateGroup group, TreePattern pattern) {
//     this.pattern = pattern;
//     this.group = group;
//     group.candidates.add(this);
//     // Perform shallow copy
//     this.ex = group.ex;
//     this.predictedEntities = group.predictedEntities;
//   }
//   
//   public int numEntities() {
//     return group.numEntities();
//   }
//   
//   public double getReward() {
//     return group.ex.expectedAnswer.reward(this);
//   }
//   
//   public Map<String, Double> getCombinedFeatures() {
//     Map<String, Double> map = new HashMap<>();
//     features.increment(1, map);
//     group.features.increment(1, map);
//     return map;
//   }
//   
//   // ============================================================
//   // Debug Print
//   // ============================================================
//   
//   public String sampleEntities() {
//     return group.sampleEntities();
//   }
//   
//   public String allEntities() {
//     return group.allEntities();
//   }
// }


import java.util.*;
import edu.stanford.nlp.semparse.open.dataset.Example;
import edu.stanford.nlp.semparse.open.model.candidate.Candidate;
import fig.basic.LogInfo;
import fig.basic.Option;
import fig.basic.Pair;
package edu.stanford.nlp.semparse.open.model;



public class LearnerMaxEntWithBeamSearch extends LearnerMaxEnt {
  public static class Options {
    @Option public int beamSize = 500;
    @Option public int beamTrainStartIter = 1;
    @Option public String beamCandidateType = "cutrange";
  }
  public static Options opts = new Options();
  
  @Override
  protected List<Candidate> getCandidates(Example example) {
    if (trainIter <= opts.beamTrainStartIter) {
      return super.getCandidates(example);
    } else {
      return getBeamSearchedCandidates(example);
    }
  }
  
  protected List<Candidate> getBeamSearchedCandidates(Example example) {
    List<Pair<Candidate, Double>> rankedCandidates = super.getRankedCandidates(example);
    rankedCandidates = rankedCandidates.subList(0, Math.min(opts.beamSize, rankedCandidates.size()));
    List<Candidate> derivedCandidates = new ArrayList<>();
    for (Pair<Candidate, Double> entry : rankedCandidates) {
      derivedCandidates.addAll(getDerivedCandidates(entry.getFirst()));
    }
    return derivedCandidates;
  }
  
  protected List<Candidate> getDerivedCandidates(Candidate original) {
// Path: src/edu/stanford/nlp/semparse/open/dataset/Example.java
// public class Example {
//   public String displayId;  // For debugging
//   
//   public final String phrase;
//   public final ExpectedAnswer expectedAnswer;
//   public KNode tree;  // Deterministic function of the phrase
//   public List<CandidateGroup> candidateGroups;
//   public List<Candidate> candidates;  // Candidate predictions
//   public AveragedWordVector averagedWordVector;
// 
//   public Example(String phrase) {
//     this(phrase, null);
//   }
//   
//   public Example(String phrase, ExpectedAnswer expectedAnswer) {
//     this.phrase = phrase;
//     this.expectedAnswer = expectedAnswer;
//   }
//   
//   @Override public String toString() {
//     return "[" + phrase + "]";
//   }
//   
//   public void initAveragedWordVector() {
//     if (averagedWordVector == null)
//       averagedWordVector = new AveragedWordVector(phrase);
//   }
// }
// 
// Path: src/edu/stanford/nlp/semparse/open/model/candidate/Candidate.java
// public class Candidate {
//   public final Example ex;
//   public final CandidateGroup group;
//   public final TreePattern pattern;
//   public final List<String> predictedEntities;
//   public FeatureVector features;
//   
//   public Candidate(CandidateGroup group, TreePattern pattern) {
//     this.pattern = pattern;
//     this.group = group;
//     group.candidates.add(this);
//     // Perform shallow copy
//     this.ex = group.ex;
//     this.predictedEntities = group.predictedEntities;
//   }
//   
//   public int numEntities() {
//     return group.numEntities();
//   }
//   
//   public double getReward() {
//     return group.ex.expectedAnswer.reward(this);
//   }
//   
//   public Map<String, Double> getCombinedFeatures() {
//     Map<String, Double> map = new HashMap<>();
//     features.increment(1, map);
//     group.features.increment(1, map);
//     return map;
//   }
//   
//   // ============================================================
//   // Debug Print
//   // ============================================================
//   
//   public String sampleEntities() {
//     return group.sampleEntities();
//   }
//   
//   public String allEntities() {
//     return group.allEntities();
//   }
// }


// Path: src/edu/stanford/nlp/semparse/open/model/LearnerMaxEntWithBeamSearch.java
import java.util.*;
import edu.stanford.nlp.semparse.open.dataset.Example;
import edu.stanford.nlp.semparse.open.model.candidate.Candidate;
import fig.basic.LogInfo;
import fig.basic.Option;
import fig.basic.Pair;

package edu.stanford.nlp.semparse.open.model;



public class LearnerMaxEntWithBeamSearch extends LearnerMaxEnt {
  public static class Options {
    @Option public int beamSize = 500;
    @Option public int beamTrainStartIter = 1;
    @Option public String beamCandidateType = "cutrange";
  }
  public static Options opts = new Options();
  
  @Override
  protected List<Candidate> getCandidates(Example example) {
    if (trainIter <= opts.beamTrainStartIter) {
      return super.getCandidates(example);
    } else {
      return getBeamSearchedCandidates(example);
    }
  }
  
  protected List<Candidate> getBeamSearchedCandidates(Example example) {
    List<Pair<Candidate, Double>> rankedCandidates = super.getRankedCandidates(example);
    rankedCandidates = rankedCandidates.subList(0, Math.min(opts.beamSize, rankedCandidates.size()));
    List<Candidate> derivedCandidates = new ArrayList<>();
    for (Pair<Candidate, Double> entry : rankedCandidates) {
      derivedCandidates.addAll(getDerivedCandidates(entry.getFirst()));
    }
    return derivedCandidates;
  }
  
  protected List<Candidate> getDerivedCandidates(Candidate original) {
    switch (opts.beamCandidateType) {