package joshua.discriminative.semiring_parsingv2;
import joshua.decoder.hypergraph.HGNode;
import joshua.decoder.hypergraph.HyperEdge;
import joshua.discriminative.semiring_parsingv2.pmodule.PModule;
import joshua.discriminative.semiring_parsingv2.semiring.Semiring;
/**This implements the algorithm of Figure-4 in the emnlp paper (Li and Eisner, 2009).
* To compute a new second-order statistics, we just need to specifiy a weight for each hyperedge.
* Specifically, we need to implement the following four functions
* 1. createNewKWeight
* 2. createNewXWeight
* 3. getEdgeKWeight
* 4. getEdgeXWeight
* */
/** In addition to run the regular inside-outside algorithm,
* this also collects the posterior count along with the outside parsing pass
* */
/**should be an ExpectationSemiring<K,X>*/
public abstract class DefaultIOParserWithXLinearCombinator<K extends Semiring<K>, X extends PModule<K,X>>
extends DefaultInsideOutsideSemiringParser<K> {
protected X goalX; //the x weight at the root, this is the total sum of posterior
public DefaultIOParserWithXLinearCombinator() {
super();
goalX = createNewXWeight();
goalX.setToZero();
}
protected abstract X getEdgeXWeight(HyperEdge dt, HGNode parent_item);
protected abstract X createNewXWeight();
/**since K and X are not concrete yet, only
* the extended class knows how to normalize*/
public abstract void normalizeGoal();
/** hyperedgeX = hyperedgeX* exclusiveWeight
* */
final protected void moduleMultiSemiring(X hyperedgeX, K exclusiveWeight){
hyperedgeX.multiSemiring(exclusiveWeight);
}
/**for correctness and saving memory,
* external class should call this method*/
public void clearState(){
super.clearState();
goalX.setToZero();
}
public void runInsideOutside(){
insideEstimationOverHG();
outsideEstimationOverHG();
}
/**this will run outside,
* and collect posterior counts*/
@Override
final protected void outsideEstimationOverHyperedge(HyperEdge dt, HGNode parentNode, K parentNodeOutsideWeight){
//==== compute the exclusive weight in the P-semiring
K exclusiveKWeight = createNewKWeight();//\overline{k_e}
exclusiveKWeight.setToOne();
exclusiveKWeight.multi(parentNodeOutsideWeight);
//we do not need to compute outside prob if no ant nodes
if(dt.getAntNodes()!=null){
//=== deduction specific prob
K edgeWeight = getEdgeKWeight(dt, parentNode);
//=== recursive call on each ant node
for(HGNode antNode : dt.getAntNodes()){
exclusiveKWeight.multi( insideSemiringWeightsTable.get(antNode) );
outsideEstimationOverNode(antNode, parentNodeOutsideWeight, dt, edgeWeight);
}
}
//== collect posterior count: x += \overline{k_e} x_e
X edgeX = getEdgeXWeight(dt, parentNode);
moduleMultiSemiring(edgeX, exclusiveKWeight);
goalX.add( edgeX );
}
public void printGoalX(){
goalX.printInfor();
}
public X getGoalX(){
return goalX;
}
}