code: /**
   * 
   */
  package edu.berkeley.nlp.PCFGLA;
  
  import edu.berkeley.nlp.PCFGLA.smoothing.Smoother;
  import edu.berkeley.nlp.util.PriorityQueue;
  
  /**
   * @author petrov
   * 
   */
  public class HierarchicalAdaptiveGrammar extends HierarchicalGrammar {
  
  	private static final long serialVersionUID = 1L;
  
  	public HierarchicalAdaptiveGrammar(short[] nSubStates,
  			boolean findClosedPaths, Smoother smoother, Grammar oldGrammar,
  			double thresh) {
  		super(nSubStates, findClosedPaths, smoother, oldGrammar, thresh);
  	}
  
  	public HierarchicalAdaptiveGrammar(Grammar gr) {
  		super(gr.numSubStates, gr.findClosedPaths, gr.smoother, gr,
  				gr.threshold);
  
  		for (BinaryRule oldRule : gr.binaryRuleMap.keySet()) {
  			HierarchicalAdaptiveBinaryRule newRule = new HierarchicalAdaptiveBinaryRule(
  					oldRule);
  			addBinary(newRule);
  		}
  		for (UnaryRule oldRule : gr.unaryRuleMap.keySet()) {
  			HierarchicalAdaptiveUnaryRule newRule = new HierarchicalAdaptiveUnaryRule(
  					oldRule);
  			addUnary(newRule);
  		}
  		if (true) {
  			closedSumRulesWithParent = closedViterbiRulesWithParent = unaryRulesWithParent;
  			closedSumRulesWithChild = closedViterbiRulesWithChild = unaryRulesWithC;
  		} else
  			computePairsOfUnaries();
  		makeCRArrays();
  		isGrammarTag = gr.isGrammarTag;
  	}
  
  	@Override
  	public HierarchicalAdaptiveGrammar newInstance(short[] newNumSubStates) {
  		return new HierarchicalAdaptiveGrammar(newNumSubStates,
  				this.findClosedPaths, this.smoother, this, this.threshold);
  	}
  
  	@Override
  	void printLevelCounts() {
  		int nBinaryParams = 0, nUnaryParams = 0, nBinaryFringeParams = 0, nUnaryFringeParams = 0;
  		PriorityQueue<HierarchicalAdaptiveBinaryRule> pQb = new PriorityQueue<HierarchicalAdaptiveBinaryRule>();
  		PriorityQueue<HierarchicalAdaptiveUnaryRule> pQu = new PriorityQueue<HierarchicalAdaptiveUnaryRule>();
  		for (int state = 0; state < numStates; state++) {
  			int[] counts = new int[8];
  			BinaryRule[] parentRules = this.splitRulesWithP(state);
  			if (parentRules.length == 0)
  				continue;
  			double totalParamState = 0, totalRulesState = 0;
  			for (int i = 0; i < parentRules.length; i++) {
  				HierarchicalAdaptiveBinaryRule r = (HierarchicalAdaptiveBinaryRule) parentRules[i];
  				// PennTreeRenderer.render(r.hierarchy);
  				counts[r.hierarchy.getDepth()]++;
  				nBinaryParams += r.countNonZeroFeatures();
  				int n = r.countNonZeroFringeFeatures();
  				nBinaryFringeParams += n;
  				pQb.add(r, n);
  				totalParamState += n;
  				totalRulesState++;
  			}
  			System.out.print(tagNumberer.object(state)
  					+ ", binary rules per level: ");
  
  			for (int i = 1; i < 8; i++) {
  				System.out.print(counts[i] + " ");
  			}
  			System.out.print(" with \n " + tagNumberer.object(state) + "\t"
  					+ totalParamState / totalRulesState
  					+ "\n parameters on average :'\n");
  		}
  		// for (int i=0; i<6; i++){
  		// System.out.println(counts[i]+" binary rules are split upto level "+i);
  		// counts[i] = 0;
  		// }
  		for (int state = 0; state < numStates; state++) {
  			int[] counts = new int[8];
  			UnaryRule[] unaries = this.getClosedSumUnaryRulesByParent(state);
  			// this.getClosedSumUnaryRulesByParent(state);//
  			if (unaries.length == 0)
  				continue;
  			for (int r = 0; r < unaries.length; r++) {
  				HierarchicalAdaptiveUnaryRule ur = (HierarchicalAdaptiveUnaryRule) unaries[r];
  				// ur.toString();
  				// PennTreeRenderer.render(ur.hierarchy);
  				counts[ur.hierarchy.getDepth()]++;
  				nUnaryParams += ur.countNonZeroFeatures();
  				int n = ur.countNonZeroFringeFeatures();
  				nUnaryFringeParams += n;
  				// totalParamState+=n;
  				// totalRulesState++;
  				pQu.add(ur, n);
  			}
  			System.out.print(tagNumberer.object(state)
  					+ ", unary rules per level: ");
  			for (int i = 1; i < 8; i++) {
  				System.out.print(counts[i] + " ");
  			}
  			System.out.print("\n");
  		}
  		System.out.println("There are " + nBinaryParams
  				+ " binary features, of which " + nBinaryFringeParams
  				+ " are on the fringe.");
  		System.out.println("There are " + nUnaryParams
  				+ " unary features, of which " + nUnaryFringeParams
  				+ " are on the fringe.");
  		System.out.println("There are " + (nBinaryParams + nUnaryParams)
  				+ " total features, of which "
  				+ (nBinaryFringeParams + nUnaryFringeParams)
  				+ " are on the fringe.");
  		while (pQb.hasNext()) {
  			HierarchicalAdaptiveBinaryRule r = pQb.next();
  			System.out.println(r.toStringShort() + "\t"
  					+ r.countNonZeroFringeFeatures());
  		}
  		while (pQu.hasNext()) {
  			HierarchicalAdaptiveUnaryRule r = pQu.next();
  			System.out.println(r.toStringShort() + "\t"
  					+ r.countNonZeroFringeFeatures());
  		}
  		// for (int i=0; i<6; i++){
  		// System.out.println(counts[i]+" unary rules are split upto level "+i);
  		// }
  
  	}
  
  }
  