protected Parse[] advanceParses(Parse p, double probMass) {
double q = 1 - probMass;
/** The index of the node which will be labeled in this iteration of advancing the parse. */
int advanceNodeIndex;
/** The node which will be labeled in this iteration of advancing the parse. */
Parse advanceNode=null;
Parse[] originalChildren = p.getChildren();
Parse[] children = collapsePunctuation(originalChildren,punctSet);
int numNodes = children.length;
if (numNodes == 0) {
return null;
}
else if (numNodes == 1) { //put sentence initial and final punct in top node
if (children[0].isPosTag()) {
return null;
}
else {
p.expandTopNode(children[0]);
return new Parse[] { p };
}
}
//determines which node needs to adanced.
for (advanceNodeIndex = 0; advanceNodeIndex < numNodes; advanceNodeIndex++) {
advanceNode = children[advanceNodeIndex];
if (!isBuilt(advanceNode)) {
break;
}
}
int originalZeroIndex = mapParseIndex(0,children,originalChildren);
int originalAdvanceIndex = mapParseIndex(advanceNodeIndex,children,originalChildren);
List<Parse> newParsesList = new ArrayList<Parse>();
//call build model
buildModel.eval(buildContextGenerator.getContext(children, advanceNodeIndex), bprobs);
double doneProb = bprobs[doneIndex];
if (debugOn) System.out.println("adi="+advanceNodeIndex+" "+advanceNode.getType()+"."+advanceNode.getLabel()+" "+advanceNode+" choose build="+(1-doneProb)+" attach="+doneProb);
if (1-doneProb > q) {
double bprobSum = 0;
while (bprobSum < probMass) {
/** The largest unadvanced labeling. */
int max = 0;
for (int pi = 1; pi < bprobs.length; pi++) { //for each build outcome
if (bprobs[pi] > bprobs[max]) {
max = pi;
}
}
if (bprobs[max] == 0) {
break;
}
double bprob = bprobs[max];
bprobs[max] = 0; //zero out so new max can be found
bprobSum += bprob;
String tag = buildModel.getOutcome(max);
if (!tag.equals(DONE)) {
Parse newParse1 = (Parse) p.clone();
Parse newNode = new Parse(p.getText(),advanceNode.getSpan(),tag,bprob,advanceNode.getHead());
newParse1.insert(newNode);
newParse1.addProb(Math.log(bprob));
newParsesList.add(newParse1);
if (checkComplete) {
cprobs = checkModel.eval(checkContextGenerator.getContext(newNode,children,advanceNodeIndex,false));
if (debugOn) System.out.println("building "+tag+" "+bprob+" c="+cprobs[completeIndex]);
if (cprobs[completeIndex] > probMass) { //just complete advances
setComplete(newNode);
newParse1.addProb(Math.log(cprobs[completeIndex]));
if (debugOn) System.out.println("Only advancing complete node");
}
else if (1-cprobs[completeIndex] > probMass) { //just incomplete advances
setIncomplete(newNode);
newParse1.addProb(Math.log(1-cprobs[completeIndex]));
if (debugOn) System.out.println("Only advancing incomplete node");
}
else { //both complete and incomplete advance
if (debugOn) System.out.println("Advancing both complete and incomplete nodes");
setComplete(newNode);
newParse1.addProb(Math.log(cprobs[completeIndex]));
Parse newParse2 = (Parse) p.clone();
Parse newNode2 = new Parse(p.getText(),advanceNode.getSpan(),tag,bprob,advanceNode.getHead());
newParse2.insert(newNode2);
newParse2.addProb(Math.log(bprob));
newParsesList.add(newParse2);
newParse2.addProb(Math.log(1-cprobs[completeIndex]));
setIncomplete(newNode2); //set incomplete for non-clone
}
}
else {
if (debugOn) System.out.println("building "+tag+" "+bprob);
}
}
}
}
//advance attaches
if (doneProb > q) {
Parse newParse1 = (Parse) p.clone(); //clone parse
//mark nodes as built
if (checkComplete) {
if (isComplete(advanceNode)) {
newParse1.setChild(originalAdvanceIndex,Parser.BUILT+"."+Parser.COMPLETE); //replace constituent being labeled to create new derivation
}
else {
newParse1.setChild(originalAdvanceIndex,Parser.BUILT+"."+Parser.INCOMPLETE); //replace constituent being labeled to create new derivation
}
}
else {
newParse1.setChild(originalAdvanceIndex,Parser.BUILT); //replace constituent being labeled to create new derivation
}
newParse1.addProb(Math.log(doneProb));
if (advanceNodeIndex == 0) { //no attach if first node.
newParsesList.add(newParse1);
}
else {
List<Parse> rf = getRightFrontier(p,punctSet);
for (int fi=0,fs=rf.size();fi<fs;fi++) {
Parse fn = rf.get(fi);
attachModel.eval(attachContextGenerator.getContext(children, advanceNodeIndex,rf,fi), aprobs);
if (debugOn) {
//List cs = java.util.Arrays.asList(attachContextGenerator.getContext(children, advanceNodeIndex,rf,fi,punctSet));
System.out.println("Frontier node("+fi+"): "+fn.getType()+"."+fn.getLabel()+" "+fn+" <- "+advanceNode.getType()+" "+advanceNode+" d="+aprobs[daughterAttachIndex]+" s="+aprobs[sisterAttachIndex]+" ");
}
for (int ai=0;ai<attachments.length;ai++) {
double prob = aprobs[attachments[ai]];
//should we try an attach if p > threshold and
// if !checkComplete then prevent daughter attaching to chunk
// if checkComplete then prevent daughter attacing to complete node or
// sister attaching to an incomplete node
if (prob > q && (
(!checkComplete && (attachments[ai]!= daughterAttachIndex || !isComplete(fn)))
||
(checkComplete && ((attachments[ai]== daughterAttachIndex && !isComplete(fn)) || (attachments[ai] == sisterAttachIndex && isComplete(fn)))))) {
Parse newParse2 = newParse1.cloneRoot(fn,originalZeroIndex);
Parse[] newKids = Parser.collapsePunctuation(newParse2.getChildren(),punctSet);
//remove node from top level since were going to attach it (including punct)
for (int ri=originalZeroIndex+1;ri<=originalAdvanceIndex;ri++) {
//System.out.println(at"-removing "+(originalZeroIndex+1)+" "+newParse2.getChildren()[originalZeroIndex+1]);
newParse2.remove(originalZeroIndex+1);
}
List<Parse> crf = getRightFrontier(newParse2,punctSet);
Parse updatedNode;
if (attachments[ai] == daughterAttachIndex) {//attach daughter
updatedNode = crf.get(fi);
updatedNode.add(advanceNode,headRules);
}
else { //attach sister
Parse psite;
if (fi+1 < crf.size()) {
psite = crf.get(fi+1);
updatedNode = psite.adjoin(advanceNode,headRules);
}
else {
psite = newParse2;
updatedNode = psite.adjoinRoot(advanceNode,headRules,originalZeroIndex);
newKids[0] = updatedNode;
}
}
//update spans affected by attachment
for (int ni=fi+1;ni<crf.size();ni++) {
Parse node = crf.get(ni);
node.updateSpan();
}
//if (debugOn) {System.out.print(ai+"-result: ");newParse2.show();System.out.println();}
newParse2.addProb(Math.log(prob));
newParsesList.add(newParse2);
if (checkComplete) {
cprobs = checkModel.eval(checkContextGenerator.getContext(updatedNode,newKids,advanceNodeIndex,true));
if (cprobs[completeIndex] > probMass) {
setComplete(updatedNode);
newParse2.addProb(Math.log(cprobs[completeIndex]));
if (debugOn) System.out.println("Only advancing complete node");
}
else if (1-cprobs[completeIndex] > probMass) {
setIncomplete(updatedNode);
newParse2.addProb(Math.log(1-cprobs[completeIndex]));
if (debugOn) System.out.println("Only advancing incomplete node");
}
else {
setComplete(updatedNode);
Parse newParse3 = newParse2.cloneRoot(updatedNode,originalZeroIndex);
newParse3.addProb(Math.log(cprobs[completeIndex]));
newParsesList.add(newParse3);
setIncomplete(updatedNode);
newParse2.addProb(Math.log(1-cprobs[completeIndex]));
if (debugOn) System.out.println("Advancing both complete and incomplete nodes; c="+cprobs[completeIndex]);
}