// 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.Random;
import edu.stanford.nlp.semparse.open.model.candidate.Candidate;
import fig.basic.Fmt;
import fig.basic.ListUtils;
import fig.basic.LogInfo;
import fig.basic.Option;
package edu.stanford.nlp.semparse.open.model;



public class AdvancedWordVectorParamsLowRank extends AdvancedWordVectorParams {
  public static class Options {
    @Option(gloss = "Rank of advanced word vector feature parameters (ignored when full rank)")
    public int vecRank = 5;
    
    @Option(gloss = "Randomly initialize the weights (ignored when full rank)")
    public boolean vecInitWeightsRandomly = true;
    
    @Option(gloss = "Randomly initialize the weights (ignored when full rank)")
    public Random vecInitRandom = new Random(1);
  }
  public static Options opts = new Options();
  
  // A = sum{u[i] v[i]^T} (i = 0, ..., rank - 1)
  protected final double[][] u, v;

  // Shorthands for rank and word vector dimension
  protected final int rank, dim;

  public AdvancedWordVectorParamsLowRank() {
    rank = opts.vecRank;
    dim = getDim();
    u = new double[rank][dim];
    v = new double[rank][dim];
    if (opts.vecInitWeightsRandomly) {
      for (int i = 0; i < rank; i++) {
        for (int j = 0; j < dim; j++) {
          u[i][j] = 2 * opts.vecInitRandom.nextDouble() - 1;
          v[i][j] = 2 * opts.vecInitRandom.nextDouble() - 1;
        }
      }
    }
    initGradientStats();
  }

  // ============================================================
  // Get score
  // ============================================================

  @Override
// 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/AdvancedWordVectorParamsLowRank.java
import java.util.Random;
import edu.stanford.nlp.semparse.open.model.candidate.Candidate;
import fig.basic.Fmt;
import fig.basic.ListUtils;
import fig.basic.LogInfo;
import fig.basic.Option;

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



public class AdvancedWordVectorParamsLowRank extends AdvancedWordVectorParams {
  public static class Options {
    @Option(gloss = "Rank of advanced word vector feature parameters (ignored when full rank)")
    public int vecRank = 5;
    
    @Option(gloss = "Randomly initialize the weights (ignored when full rank)")
    public boolean vecInitWeightsRandomly = true;
    
    @Option(gloss = "Randomly initialize the weights (ignored when full rank)")
    public Random vecInitRandom = new Random(1);
  }
  public static Options opts = new Options();
  
  // A = sum{u[i] v[i]^T} (i = 0, ..., rank - 1)
  protected final double[][] u, v;

  // Shorthands for rank and word vector dimension
  protected final int rank, dim;

  public AdvancedWordVectorParamsLowRank() {
    rank = opts.vecRank;
    dim = getDim();
    u = new double[rank][dim];
    v = new double[rank][dim];
    if (opts.vecInitWeightsRandomly) {
      for (int i = 0; i < rank; i++) {
        for (int j = 0; j < dim; j++) {
          u[i][j] = 2 * opts.vecInitRandom.nextDouble() - 1;
          v[i][j] = 2 * opts.vecInitRandom.nextDouble() - 1;
        }
      }
    }
    initGradientStats();
  }

  // ============================================================
  // Get score
  // ============================================================

  @Override
  public double getScore(Candidate candidate) {