package joshua.discriminative.semiring_parsing; /** This class implements an element in a ConvolutionSemiring * This class does not depend on the structure, e.g., hypergraph, lattice, or nbest * */ /**we should not normalize the probability at each intermediate node * because our model is a global model??? */ /** while the logProb and factor1 are shared by all features, * the second factor is a vector, so does the combinedfactor */ /**@todo: right now, the atomic semiring must be log-sum semiring * */ public class VarianceSemiringVector implements CompositeSemiring { //TODO: assuming the following are always in *log* semiring private double logProb; //TODO: assuming the following are always in *real* semiring private SignedValue factor1; private SignedValue[] factor2; private SignedValue[] combinedfactor; int vectorSize; public VarianceSemiringVector(int vectorSize_){ vectorSize= vectorSize_; factor1 = new SignedValue(); factor2 = new SignedValue[vectorSize]; for(int i=0; i<factor2.length; i++) factor2[i] = new SignedValue(); combinedfactor = new SignedValue[vectorSize]; for(int i=0; i<combinedfactor.length; i++) combinedfactor[i] = new SignedValue(); } public VarianceSemiringVector(double logProb_, SignedValue factor1_, SignedValue[] factor2_, SignedValue[] combinedfactor_){ logProb = logProb_; factor1 = factor1_; factor2 = factor2_; combinedfactor = combinedfactor_; if(factor2.length!=combinedfactor.length){ System.out.println("factor2 and combinedfactor vectors do not have same length"); System.exit(1); } vectorSize = factor2.length; } public void setToZero(AtomicSemiring atomic){ logProb = atomic.ATOMIC_ZERO_IN_SEMIRING; factor1.setZero(); for(int i=0; i<vectorSize; i++){ factor2[i].setZero(); combinedfactor[i].setZero(); } } public void setToOne(AtomicSemiring atomic){ logProb = atomic.ATOMIC_ONE_IN_SEMIRING; /**Note that factor should always set as zero. * For example, when the factor is expected length, it should start from zero * */ factor1.setZero(); for(int i=0; i<vectorSize; i++){ factor2[i].setZero(); combinedfactor[i].setZero(); } } public void add(CompositeSemiring b, AtomicSemiring atomic){ VarianceSemiringVector b2 = (VarianceSemiringVector)b; this.logProb = atomic.add_in_atomic_semiring(this.logProb, b2.logProb); //this.factor1 = this.factor1 + b2.factor1;//real semiring this.factor1 = SignedValue.add(this.factor1, b2.factor1); for(int i=0; i<vectorSize; i++){ //this.factor2[i] = this.factor2[i] + b2.factor2[i];//real semiring this.factor2[i] = SignedValue.add(this.factor2[i],b2.factor2[i]); //this.combinedfactor[i] = this.combinedfactor[i] + b2.combinedfactor[i];//real semiring this.combinedfactor[i] = SignedValue.add(this.combinedfactor[i],b2.combinedfactor[i]); } } public void multi(CompositeSemiring b, AtomicSemiring atomic){ VarianceSemiringVector b2 = (VarianceSemiringVector)b; //first update combinedFactor, then factor2, then factor, and then logProb for(int i=0; i<vectorSize; i++){ // combinedfacotr = a.prob * b.combinedfacotr + a.combinedfacotr * b.prob + a.factor1 * b.factor2 + a.factor2 * b.factor1 //this.combinedfactor[i] = Math.exp(oldLogProb)* b2.combinedfactor[i] + Math.exp(b2.logProb) * oldCombinedfactor[i] + oldFactor1*b2.factor2[i] + oldFactor2[i]* b2.factor1; SignedValue part1 = SignedValue.add( SignedValue.multi(this.logProb, b2.combinedfactor[i]), SignedValue.multi(b2.logProb, this.combinedfactor[i]) ); SignedValue part2 = SignedValue.add( SignedValue.multi( this.factor1, b2.factor2[i]), SignedValue.multi(this.factor2[i], b2.factor1) ); this.combinedfactor[i] = SignedValue.add( part1, part2 ); //this.factor2[i] = Math.exp(oldLogProb)* b2.factor2[i] + Math.exp(b2.logProb) * oldFactor2[i]; this.factor2[i] = SignedValue.add( SignedValue.multi(this.logProb, b2.factor2[i]), SignedValue.multi(b2.logProb, this.factor2[i]) ); } // this.factor1 = Math.exp(oldLogProb)* b2.factor1 + Math.exp(b2.logProb) * oldFactor1; this.factor1 = SignedValue.add( SignedValue.multi(this.logProb, b2.factor1), SignedValue.multi(b2.logProb, this.factor1) ); this.logProb = atomic.multi_in_atomic_semiring(this.logProb, b2.logProb); } public void normalizeFactors(){ /**we should not normalize the probability at each intermediate node * because our model is a global model??? */ /**originallly, the factor value is \sum_x p(x).v(x), where p(x) is not normalized, meaning \sum_x p(x)!=1; * we need to normalize p(x) by divide out Math.exp(prob) * */ //this.factor1 = factor1/Math.exp(logProb); this.factor1 = SignedValue.multi(-logProb, this.factor1); for(int i=0; i<vectorSize; i++){ //this.factor2[i] = factor2[i]/Math.exp(logProb); this.factor2[i] = SignedValue.multi(-logProb, this.factor2[i]); //this.combinedfactor[i] = combinedfactor[i]/Math.exp(logProb); this.combinedfactor[i] = SignedValue.multi(-logProb, this.combinedfactor[i]); } } public void printInfor(){ System.out.println("prob: " + logProb); System.out.println("factor1: " + factor1.convertRealValue()); System.out.print("factor2:"); for(int i=0; i<vectorSize; i++){ System.out.print(" " + factor2[i].convertRealValue()); } System.out.print("\nfactor1*factor2:"); for(int i=0; i<vectorSize; i++){ System.out.print(" " + (factor1.convertRealValue()*factor2[i].convertRealValue())); } System.out.print("\ncombinedfactor: "); for(int i=0; i<vectorSize; i++){ System.out.print(" " + combinedfactor[i].convertRealValue()); } System.out.print("\n"); } public void printInfor2(){ //do nothing } public double getLogProb(){ return logProb; } public SignedValue getFactor1(){ return factor1; } public SignedValue[] getFactor2(){ return factor2; } public SignedValue[] getCombinedfactor(){ return combinedfactor; } }