void doConstrainedOutsideScores(Grammar grammar,boolean viterbi,boolean logScores){
  short[] numSubStatesArray=grammar.numSubStates;
  double initVal=(logScores) ? Double.NEGATIVE_INFINITY : 0.0;
  for (int diff=length; diff >= 1; diff--) {
    for (int start=0; start + diff <= length; start++) {
      int end=start + diff;
      double[][] scoresAfterUnaries=new double[numStates][];
      boolean somethingChanged=false;
      for (int cState=0; cState < numStates; cState++) {
        if (diff > 1 && !grammar.isGrammarTag[cState])         continue;
        if (oScore[start][end][cState] == null) {
          continue;
        }
        UnaryRule[] rules=null;
        if (viterbi)         rules=grammar.getClosedViterbiUnaryRulesByChild(cState);
 else         rules=grammar.getClosedSumUnaryRulesByChild(cState);
        final int nChildStates=numSubStatesArray[cState];
        final int numRules=rules.length;
        for (int r=0; r < numRules; r++) {
          UnaryRule ur=rules[r];
          int pState=ur.parentState;
          if ((pState == cState))           continue;
          if (oScore[start][end][pState] == null) {
            continue;
          }
          double[][] scores=ur.getScores2();
          final int nParentStates=numSubStatesArray[pState];
          for (int cp=0; cp < nChildStates; cp++) {
            if (scores[cp] == null)             continue;
            if (!allowedSubStates[start][end][cState][cp])             continue;
            for (int np=0; np < nParentStates; np++) {
              double pS=scores[cp][np];
              if (pS == initVal)               continue;
              double oS=oScore[start][end][pState][np];
              if (oS == initVal)               continue;
              double thisRound=(logScores) ? oS + pS : oS * pS;
              if (scoresAfterUnaries[cState] == null) {
                scoresAfterUnaries[cState]=new double[numSubStatesArray[cState]];
                if (viterbi)                 Arrays.fill(scoresAfterUnaries[cState],initVal);
              }
              if (viterbi)               scoresAfterUnaries[cState][cp]=Math.max(thisRound,scoresAfterUnaries[cState][cp]);
 else               scoresAfterUnaries[cState][cp]+=thisRound;
              somethingChanged=true;
            }
          }
        }
      }
      if (somethingChanged) {
        for (int cState=0; cState < numStates; cState++) {
          double[] thisCell=scoresAfterUnaries[cState];
          if (thisCell == null)           continue;
          for (int cp=0; cp < numSubStatesArray[cState]; cp++) {
            if (thisCell[cp] > initVal) {
              if (viterbi)               oScore[start][end][cState][cp]=Math.max(oScore[start][end][cState][cp],thisCell[cp]);
 else               oScore[start][end][cState][cp]+=thisCell[cp];
            }
          }
        }
      }
      for (int pState=0; pState < numSubStatesArray.length; pState++) {
        if (oScore[start][end][pState] == null) {
          continue;
        }
        final int nParentChildStates=numSubStatesArray[pState];
        BinaryRule[] rules=grammar.splitRulesWithP(pState);
        final int numRules=rules.length;
        for (int r=0; r < numRules; r++) {
          BinaryRule br=rules[r];
          int lState=br.leftChildState;
          int min1=narrowRExtent[start][lState];
          if (end < min1) {
            continue;
          }
          int rState=br.rightChildState;
          int max1=narrowLExtent[end][rState];
          if (max1 < min1) {
            continue;
          }
          int min=min1;
          int max=max1;
          if (max - min > 2) {
            int min2=wideLExtent[end][rState];
            min=(min1 > min2 ? min1 : min2);
            if (max1 < min) {
              continue;
            }
            int max2=wideRExtent[start][lState];
            max=(max1 < max2 ? max1 : max2);
            if (max < min) {
              continue;
            }
          }
          double[][][] scores=br.getScores2();
          final int nLeftChildStates=numSubStatesArray[lState];
          final int nRightChildStates=numSubStatesArray[rState];
          for (int split=min; split <= max; split++) {
            if (oScore[start][split][lState] == null)             continue;
            if (oScore[split][end][rState] == null)             continue;
            double[] rightScores=new double[nRightChildStates];
            if (viterbi)             Arrays.fill(rightScores,initVal);
            Arrays.fill(scoresToAdd,initVal);
            somethingChanged=false;
            for (int lp=0; lp < nLeftChildStates; lp++) {
              double lS=iScore[start][split][lState][lp];
              if (lS == initVal) {
                continue;
              }
              for (int rp=0; rp < nRightChildStates; rp++) {
                if (scores[lp][rp] == null)                 continue;
                double rS=iScore[split][end][rState][rp];
                if (rS == initVal) {
                  continue;
                }
                for (int np=0; np < nParentChildStates; np++) {
                  double pS=scores[lp][rp][np];
                  if (pS == initVal)                   continue;
                  double oS=oScore[start][end][pState][np];
                  if (oS == initVal)                   continue;
                  double thisRoundL=(logScores) ? pS + rS + oS : pS * rS * oS;
                  double thisRoundR=(logScores) ? pS + lS + oS : pS * lS * oS;
                  if (viterbi) {
                    scoresToAdd[lp]=Math.max(thisRoundL,scoresToAdd[lp]);
                    rightScores[rp]=Math.max(thisRoundR,rightScores[rp]);
                  }
 else {
                    scoresToAdd[lp]+=thisRoundL;
                    rightScores[rp]+=thisRoundR;
                  }
                  somethingChanged=true;
                }
              }
            }
            if (!somethingChanged)             continue;
            for (int cp=0; cp < nLeftChildStates; cp++) {
              if (scoresToAdd[cp] > initVal) {
                if (viterbi)                 oScore[start][split][lState][cp]=Math.max(oScore[start][split][lState][cp],scoresToAdd[cp]);
 else                 oScore[start][split][lState][cp]+=scoresToAdd[cp];
              }
            }
            for (int cp=0; cp < nRightChildStates; cp++) {
              if (rightScores[cp] > initVal) {
                if (viterbi)                 oScore[split][end][rState][cp]=Math.max(oScore[split][end][rState][cp],rightScores[cp]);
 else                 oScore[split][end][rState][cp]+=rightScores[cp];
              }
            }
          }
        }
      }
    }
  }
}

void doConstrainedOutsideScores ( Grammar grammar , boolean viterbi , boolean logScores ) { short [ ] numSubStatesArray = grammar . numSubStates ; double initVal = ( logScores ) ? Double . NEGATIVE_INFINITY : 0.0 ; for ( int diff = length ; diff >= 1 ; diff -- ) { for ( int start = 0 ; start + diff <= length ; start ++ ) { int end = start + diff ; double [ ] [ ] scoresAfterUnaries = new double [ numStates ] [ ] ; boolean somethingChanged = false ; for ( int cState = 0 ; cState < numStates ; cState ++ ) { if ( diff > 1 && ! grammar . isGrammarTag [ cState ] ) continue ; if ( oScore [ start ] [ end ] [ cState ] == null ) { continue ; } UnaryRule [ ] rules = null ; if ( viterbi ) rules = grammar . getClosedViterbiUnaryRulesByChild ( cState ) ; else rules = grammar . getClosedSumUnaryRulesByChild ( cState ) ; final int nChildStates = numSubStatesArray [ cState ] ; final int numRules = rules . length ; for ( int r = 0 ; r < numRules ; r ++ ) { UnaryRule ur = rules [ r ] ; int pState = ur . parentState ; if ( ( pState == cState ) ) continue ; if ( oScore [ start ] [ end ] [ pState ] == null ) { continue ; } double [ ] [ ] scores = ur . getScores2 ( ) ; final int nParentStates = numSubStatesArray [ pState ] ; for ( int cp = 0 ; cp < nChildStates ; cp ++ ) { if ( scores [ cp ] == null ) continue ; if ( ! allowedSubStates [ start ] [ end ] [ cState ] [ cp ] ) continue ; for ( int np = 0 ; np < nParentStates ; np ++ ) { double pS = scores [ cp ] [ np ] ; if ( pS == initVal ) continue ; double oS = oScore [ start ] [ end ] [ pState ] [ np ] ; if ( oS == initVal ) continue ; double thisRound = ( logScores ) ? oS + pS : oS * pS ; if ( scoresAfterUnaries [ cState ] == null ) { scoresAfterUnaries [ cState ] = new double [ numSubStatesArray [ cState ] ] ; if ( viterbi ) Arrays . fill ( scoresAfterUnaries [ cState ] , initVal ) ; } if ( viterbi ) scoresAfterUnaries [ cState ] [ cp ] = Math . max ( thisRound , scoresAfterUnaries [ cState ] [ cp ] ) ; else scoresAfterUnaries [ cState ] [ cp ] += thisRound ; somethingChanged = true ; } } } } if ( somethingChanged ) { for ( int cState = 0 ; cState < numStates ; cState ++ ) { double [ ] thisCell = scoresAfterUnaries [ cState ] ; if ( thisCell == null ) continue ; for ( int cp = 0 ; cp < numSubStatesArray [ cState ] ; cp ++ ) { if ( thisCell [ cp ] > initVal ) { if ( viterbi ) oScore [ start ] [ end ] [ cState ] [ cp ] = Math . max ( oScore [ start ] [ end ] [ cState ] [ cp ] , thisCell [ cp ] ) ; else oScore [ start ] [ end ] [ cState ] [ cp ] += thisCell [ cp ] ; } } } } for ( int pState = 0 ; pState < numSubStatesArray . length ; pState ++ ) { if ( oScore [ start ] [ end ] [ pState ] == null ) { continue ; } final int nParentChildStates = numSubStatesArray [ pState ] ; BinaryRule [ ] rules = grammar . splitRulesWithP ( pState ) ; final int numRules = rules . length ; for ( int r = 0 ; r < numRules ; r ++ ) { BinaryRule br = rules [ r ] ; int lState = br . leftChildState ; int min1 = narrowRExtent [ start ] [ lState ] ; if ( end < min1 ) { continue ; } int rState = br . rightChildState ; int max1 = narrowLExtent [ end ] [ rState ] ; if ( max1 < min1 ) { continue ; } int min = min1 ; int max = max1 ; if ( max - min > 2 ) { int min2 = wideLExtent [ end ] [ rState ] ; min = ( min1 > min2 ? min1 : min2 ) ; if ( max1 < min ) { continue ; } int max2 = wideRExtent [ start ] [ lState ] ; max = ( max1 < max2 ? max1 : max2 ) ; if ( max < min ) { continue ; } } double [ ] [ ] [ ] scores = br . getScores2 ( ) ; final int nLeftChildStates = numSubStatesArray [ lState ] ; final int nRightChildStates = numSubStatesArray [ rState ] ; for ( int split = min ; split <= max ; split ++ ) { if ( oScore [ start ] [ split ] [ lState ] == null ) continue ; if ( oScore [ split ] [ end ] [ rState ] == null ) continue ; double [ ] rightScores = new double [ nRightChildStates ] ; if ( viterbi ) Arrays . fill ( rightScores , initVal ) ; Arrays . fill ( scoresToAdd , initVal ) ; somethingChanged = false ; for ( int lp = 0 ; lp < nLeftChildStates ; lp ++ ) { double lS = iScore [ start ] [ split ] [ lState ] [ lp ] ; if ( lS == initVal ) { continue ; } for ( int rp = 0 ; rp < nRightChildStates ; rp ++ ) { if ( scores [ lp ] [ rp ] == null ) continue ; double rS = iScore [ split ] [ end ] [ rState ] [ rp ] ; if ( rS == initVal ) { continue ; } for ( int np = 0 ; np < nParentChildStates ; np ++ ) { double pS = scores [ lp ] [ rp ] [ np ] ; if ( pS == initVal ) continue ; double oS = oScore [ start ] [ end ] [ pState ] [ np ] ; if ( oS == initVal ) continue ; double thisRoundL = ( logScores ) ? pS + rS + oS : pS * rS * oS ; double thisRoundR = ( logScores ) ? pS + lS + oS : pS * lS * oS ; if ( viterbi ) { scoresToAdd [ lp ] = Math . max ( thisRoundL , scoresToAdd [ lp ] ) ; rightScores [ rp ] = Math . max ( thisRoundR , rightScores [ rp ] ) ; } else { scoresToAdd [ lp ] += thisRoundL ; rightScores [ rp ] += thisRoundR ; } somethingChanged = true ; } } } if ( ! somethingChanged ) continue ; for ( int cp = 0 ; cp < nLeftChildStates ; cp ++ ) { if ( scoresToAdd [ cp ] > initVal ) { if ( viterbi ) oScore [ start ] [ split ] [ lState ] [ cp ] = Math . max ( oScore [ start ] [ split ] [ lState ] [ cp ] , scoresToAdd [ cp ] ) ; else oScore [ start ] [ split ] [ lState ] [ cp ] += scoresToAdd [ cp ] ; } } for ( int cp = 0 ; cp < nRightChildStates ; cp ++ ) { if ( rightScores [ cp ] > initVal ) { if ( viterbi ) oScore [ split ] [ end ] [ rState ] [ cp ] = Math . max ( oScore [ split ] [ end ] [ rState ] [ cp ] , rightScores [ cp ] ) ; else oScore [ split ] [ end ] [ rState ] [ cp ] += rightScores [ cp ] ; } } } } } } } }
fills in the oscore array of each category over each span of length 2 or more . this version computes the posterior outside scores , not the viterbi outside scores .
