package edu.berkeley.nlp.syntax;
import java.text.NumberFormat;
import edu.berkeley.nlp.math.DoubleArrays;
import edu.berkeley.nlp.util.Numberer;
import edu.berkeley.nlp.util.ScalingTools;
/**
* Represent parsetrees, with each node consisting of a label and a list of children.
* The score tables are not allocated by the constructor and allocate() and deallocate()
* must be called manually. This is to allow more control over memory usage.
* @author Slav Petrov
* @author Romain Thibaux
*/
public class StateSet {
public static final double SCALE = Math.exp(100);
double[] iScores; // the log-probabilities for each sublabels
double[] oScores;
int iScale;
int oScale;
String word; /** the word of this node, if it is a terminal node; else null*/
public int wordIndex, sigIndex;
short numSubStates;
short state;
public short from, to;
// Run allocate() before any other operation
public void allocate() {
iScores = new double[numSubStates];
oScores = new double[numSubStates];
}
// run deallocate() if the scores are no longer needed and
// this object will not be used for a long time
public void deallocate() {
iScores = null;
oScores = null;
}
@Override
public String toString(){
if (word!=null) return word+" "+from+"-"+to;// + " " + substates.length;
String s = Numberer.getGlobalNumberer("tags").object(state)+" ";//"[";
// for (int i = 0; i < numSubStates; i++){
// NumberFormat f = NumberFormat.getInstance();
// f.setMaximumFractionDigits(5);
// String iS = "";
// String oS = "";
// if (iScores != null && iScores[i]!=0)
// iS = ": iS="+f.format(iScores[i]);//Math.log(iScores[i])+100*iScale);
// if (oScores != null && oScores[i]!=0)
// oS = " oS="+f.format(oScores[i]);//Math.log(oScores[i])+100*oScale);
//// String iS = Double.toString(Math.log(iScores[i])+100*iScale);
//// String oS = Double.toString(Math.log(oScores[i])+100*oScale);
//// String iS = "";
//// String oS = "";
// if (iScores != null && DoubleArrays.max(iScores)==0) iS = ", iS=0";
// if (oScores != null && DoubleArrays.max(oScores)==0) oS = ", oS=0";
// s=s.concat(" ["+state+"-"+i+iS+oS+"]");
// }
// s=s.concat(" ]");
return s;
}
public final short getState(){
return state;
}
public final double getIScore(int i){
return iScores[i];
}
public final double[] getIScores() {
return iScores;
}
public final double getOScore(int i){
return oScores[i];
}
public final double[] getOScores() {
return oScores;
}
public final void setIScores(double[] s) {
iScores = s;
}
public final void setIScore(int i, double s) {
if (iScores == null) iScores = new double[numSubStates];
iScores[i] = s;
}
public final void setOScores(double[] s) {
oScores = s;
}
public final void setOScore(int i, double s) {
if (oScores == null) oScores = new double[numSubStates];
oScores[i] = s;
}
/* public void logAddIScore(short i, double s) {
iScores[i] = SloppyMath.logAdd(iScores[i], s);
}
public void logAddOScore(short i,double s) {
oScores[i] = SloppyMath.logAdd(oScores[i], s);
}
*/
public final int numSubStates() {
return numSubStates;
}
/*
public StateSet(int nSubStates) {
this.numSubStates = nSubStates;
this.iScores = new double[nSubStates];
this.oScores = new double[nSubStates];
for ( int i = 0; i < nSubStates; i++ ) {
iScores[i] = Double.NEGATIVE_INFINITY;
oScores[i] = Double.NEGATIVE_INFINITY;
}
}*/
public StateSet(short state, short nSubStates) {
this.numSubStates = nSubStates;
this.state = state;
}
public StateSet(short s, short nSubStates, String word, short from, short to) {
this.numSubStates = nSubStates;
this.state = s;
this.word = word;
this.from = from;
this.to = to;
}
public StateSet(StateSet oldS, short nSubStates) {
this.numSubStates = nSubStates;
this.state = oldS.state;
this.word = oldS.word;
this.from = oldS.from;
this.to = oldS.to;
}
public String getWord() {
return word;
}
public void setWord(String word) {
this.word = word;
}
public void scaleIScores(int previousScale){
iScale = ScalingTools.scaleArray(iScores, previousScale);
// int logScale = 0;
// double scale = 1.0;
// double max = ArrayMath.max(iScores);
// //if (max==0) System.out.println("All iScores are 0!");
// if (SloppyMath.isVeryDangerous(max)) return;
// while (max > SCALE) {
// max /= SCALE;
// scale *= SCALE;
// logScale += 1;
// }
// while (max > 0.0 && max < 1.0 / SCALE) {
// max *= SCALE;
// scale /= SCALE;
// logScale -= 1;
// }
// if (logScale != 0) {
// for (int i = 0; i < numSubStates; i++) {
// iScores[i] /= scale;
// }
// }
// if ((max!=0) && ArrayMath.max(iScores)==0){
// System.out.println("Undeflow when scaling iScores!");
// }
// iScale = previousScale + logScale;
}
public void scaleOScores(int previousScale){
oScale = ScalingTools.scaleArray(oScores, previousScale);
// int logScale = 0;
// double scale = 1.0;
// double max = ArrayMath.max(oScores);
// if (SloppyMath.isVeryDangerous(max)) return;
// //if (max==0) System.out.println("All oScores are 0!");
// while (max > SCALE) {
// max /= SCALE;
// scale *= SCALE;
// logScale += 1;
// }
// while (max > 0.0 && max < 1.0 / SCALE) {
// max *= SCALE;
// scale /= SCALE;
// logScale -= 1;
// }
// if (logScale != 0) {
// for (int i = 0; i < numSubStates; i++) {
// oScores[i] /= scale;
// }
// }
// if ((max!=0) && ArrayMath.max(oScores)==0){
// System.out.println("Undeflow when scaling oScores!");
// }
// oScale = previousScale + logScale;
}
public int getIScale() {
return iScale;
}
public void setIScale(int scale) {
iScale = scale;
}
public int getOScale() {
return oScale;
}
public void setOScale(int scale) {
oScale = scale;
}
/**
* @return
*/
public StateSet copy() {
return new StateSet(this, this.numSubStates);
}
}