package joshua.discriminative.semiring_parsingv2; /**This implements Table-3 in the emnlp paper (Li and Eisner, 2009) * **/ public class SignedValue { private boolean isPostive; private double logValue; public SignedValue(){ } public SignedValue(boolean isPostive_, double logValue_){ this.isPostive = isPostive_; this.logValue = logValue_; } public SignedValue duplicate(){ return new SignedValue(this.isPostive, this.logValue); } public static SignedValue duplicate(SignedValue in){ return new SignedValue(in.isPostive, in.logValue); } //realValue: value in real domain public static SignedValue createSignedValueFromRealNumber(double realValue){ if(realValue>=0) return new SignedValue(true, Math.log(realValue)); else return new SignedValue(false, Math.log(-realValue)); } public double convertToRealValue(){ return convertToRealValue(this); } static public double convertToRealValue(SignedValue x){ if(x.isPostive) return Math.exp(x.logValue); else return -Math.exp(x.logValue); } public void setToZero(){ isPostive =true; logValue = Double.NEGATIVE_INFINITY; } public void setToOne(){ isPostive =true; logValue = 0; } public void add(SignedValue y){ boolean resSign = isPositiveAfterAdd(this, y); double resLogValue = naturalLogAfterAdd(this, y); this.isPostive = resSign; this.logValue = resLogValue; } static public SignedValue add(SignedValue x, SignedValue y){ SignedValue res = new SignedValue(); res.isPostive = isPositiveAfterAdd(x, y); res.logValue = naturalLogAfterAdd(x, y); return res; } public void multi(SignedValue y){ boolean resSign = isPositiveAfterMulti(this, y); double resLogValue = naturalLogAfterMulti(this, y); this.isPostive = resSign; this.logValue = resLogValue; } static public SignedValue multi(SignedValue x, SignedValue y){ SignedValue res = new SignedValue(); res.isPostive = isPositiveAfterMulti(x, y); res.logValue = naturalLogAfterMulti(x, y); return res; } public void negate(){ this.isPostive = ! this.isPostive; } // x is in log domain, so the corresponding real value e^x is always positive public void multiLogNumber(double x){ this.logValue += x; } /* static public SignedValue multiLogNumber(double x, SignedValue y){ return new SignedValue(y.isPostive, x+y.logValue); }*/ public void printInfor(){ System.out.println("isPostive="+isPostive+ "; logValue="+logValue); } //====================== plus and multi operations; see table-3 of emnlp 2009 paper================= static private boolean isPositiveAfterAdd(SignedValue x, SignedValue y){ if(x.logValue>=y.logValue) return x.isPostive; else return y.isPostive; } static private double naturalLogAfterAdd(SignedValue x, SignedValue y){ if(x.logValue==Double.NEGATIVE_INFINITY) return y.logValue; if(y.logValue==Double.NEGATIVE_INFINITY) return x.logValue; SignedValue large, small; if(x.logValue>=y.logValue){ large = x; small = y; }else{ large = y; small = x; } if( large.isPostive == small.isPostive ){ return large.logValue + Math.log(1 + Math.exp(small.logValue-large.logValue)); }else{ return large.logValue + Math.log(1 - Math.exp(small.logValue-large.logValue)); } } static private boolean isPositiveAfterMulti(SignedValue x, SignedValue y){ if( x.isPostive == y.isPostive ) return true; else return false; } static private double naturalLogAfterMulti(SignedValue x, SignedValue y){ return x.logValue+y.logValue; } //============================================================end// }