package joshua.discriminative.semiring_parsing; import java.util.HashMap; import java.util.Map; public class ExpectationSemiringHashMap implements CompositeSemiring{ // TODO: assuming the following are always in *log* semiring private double logProb; private HashMap<Integer, SignedValue> factor1; //feature index, and feature value public ExpectationSemiringHashMap(){ factor1 = new HashMap<Integer, SignedValue>(); } public ExpectationSemiringHashMap(double logProb_, HashMap<Integer, SignedValue> factor1_){ logProb = logProb_; factor1 = factor1_; } public void setToZero(AtomicSemiring atomic){ logProb = atomic.ATOMIC_ZERO_IN_SEMIRING; for (SignedValue val : factor1.values()) { val.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 * */ for (SignedValue val : factor1.values()) { val.setZero(); } } public void add(CompositeSemiring b, AtomicSemiring atomic){ ExpectationSemiringHashMap b2 = (ExpectationSemiringHashMap)b; this.logProb = atomic.add_in_atomic_semiring(this.logProb, b2.logProb); for(Map.Entry<Integer, SignedValue> entry : b2.factor1.entrySet()){ Integer key = entry.getKey(); SignedValue valB = entry.getValue(); SignedValue valA = this.factor1.get(key); if(valA!=null){ this.factor1.put(key, SignedValue.add(valA, valB)); }else{ //this.factor1.put(key, valB);//@todo should duplicate valB?? this.factor1.put(key, SignedValue.clone(valB)); } } } public void multi(CompositeSemiring b, AtomicSemiring atomic){ ExpectationSemiringHashMap b2 = (ExpectationSemiringHashMap)b; for(Map.Entry<Integer, SignedValue> entry : b2.factor1.entrySet()){ Integer key = entry.getKey(); SignedValue valB = entry.getValue(); SignedValue valA = this.factor1.get(key); if(valA!=null){ this.factor1.put(key, SignedValue.add( SignedValue.multi(this.logProb, valB), SignedValue.multi(b2.logProb, valA) )); }else{ this.factor1.put(key, SignedValue.multi(this.logProb, valB)); } } // now update entries that are in myself, but not in b for(Map.Entry<Integer, SignedValue> entry : this.factor1.entrySet()){ Integer key = entry.getKey(); SignedValue valA = entry.getValue(); SignedValue valB = b2.factor1.get(key); //we already dealed with the case valB!=null above if(valB==null){ this.factor1.put(key, SignedValue.multi(b2.logProb, valA)); } } 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) * */ for(Map.Entry<Integer, SignedValue> entry : this.factor1.entrySet()){ entry.setValue(SignedValue.multi(-logProb, entry.getValue())); } } public void printInfor(){ System.out.println("prob: " + logProb ); System.out.print("factor1:"); for(Map.Entry<Integer, SignedValue> entry : this.factor1.entrySet()){ System.out.print(" " + entry.getKey() + "=" + entry.getValue().convertRealValue()); } System.out.print("\n"); } public void printInfor2(){ } public double getLogProb(){ return logProb; } public HashMap<Integer, SignedValue> getFactor1(){ return factor1; } }