public static Grammar doTheMerges(Grammar grammar,Lexicon lexicon,boolean[][][] mergeThesePairs,double[][] mergeWeights){
  short[] numSubStatesArray=grammar.numSubStates;
  short[] newNumSubStatesArray=grammar.numSubStates;
  Grammar newGrammar=null;
  while (true) {
    boolean somethingToMerge=false;
    for (int tag=0; tag < numSubStatesArray.length; tag++) {
      for (int i=0; i < newNumSubStatesArray[tag]; i++) {
        for (int j=0; j < newNumSubStatesArray[tag]; j++) {
          somethingToMerge=somethingToMerge || mergeThesePairs[tag][i][j];
        }
      }
    }
    if (!somethingToMerge)     break;
    boolean[][][] mergeThisIteration=new boolean[newNumSubStatesArray.length][][];
    for (int tag=0; tag < numSubStatesArray.length; tag++) {
      mergeThisIteration[tag]=new boolean[mergeThesePairs[tag].length][mergeThesePairs[tag].length];
      for (int i=0; i < mergeThesePairs[tag].length; i++) {
        for (int j=0; j < mergeThesePairs[tag].length; j++) {
          mergeThisIteration[tag][i][j]=mergeThesePairs[tag][i][j];
        }
      }
    }
    for (int tag=0; tag < numSubStatesArray.length; tag++) {
      boolean[] alreadyDecidedToMerge=new boolean[mergeThesePairs[tag].length];
      for (int i=0; i < mergeThesePairs[tag].length; i++) {
        for (int j=0; j < mergeThesePairs[tag].length; j++) {
          if (alreadyDecidedToMerge[i] || alreadyDecidedToMerge[j])           mergeThisIteration[tag][i][j]=false;
          alreadyDecidedToMerge[i]=alreadyDecidedToMerge[i] || mergeThesePairs[tag][i][j];
          alreadyDecidedToMerge[j]=alreadyDecidedToMerge[j] || mergeThesePairs[tag][i][j];
        }
      }
    }
    for (int tag=0; tag < numSubStatesArray.length; tag++) {
      for (int i=0; i < mergeThesePairs[tag].length; i++) {
        for (int j=0; j < mergeThesePairs[tag].length; j++) {
          mergeThesePairs[tag][i][j]=mergeThesePairs[tag][i][j] && !mergeThisIteration[tag][i][j];
        }
      }
    }
    newGrammar=grammar.mergeStates(mergeThisIteration,mergeWeights);
    lexicon.mergeStates(mergeThisIteration,mergeWeights);
    grammar.fixMergeWeightsEtc(mergeThesePairs,mergeWeights,mergeThisIteration);
    grammar=newGrammar;
    newNumSubStatesArray=grammar.numSubStates;
  }
  grammar.makeCRArrays();
  return grammar;
}

public static Grammar doTheMerges ( Grammar grammar , Lexicon lexicon , boolean [ ] [ ] [ ] mergeThesePairs , double [ ] [ ] mergeWeights ) { short [ ] numSubStatesArray = grammar . numSubStates ; short [ ] newNumSubStatesArray = grammar . numSubStates ; Grammar newGrammar = null ; while ( true ) { boolean somethingToMerge = false ; for ( int tag = 0 ; tag < numSubStatesArray . length ; tag ++ ) { for ( int i = 0 ; i < newNumSubStatesArray [ tag ] ; i ++ ) { for ( int j = 0 ; j < newNumSubStatesArray [ tag ] ; j ++ ) { somethingToMerge = somethingToMerge || mergeThesePairs [ tag ] [ i ] [ j ] ; } } } if ( ! somethingToMerge ) break ; boolean [ ] [ ] [ ] mergeThisIteration = new boolean [ newNumSubStatesArray . length ] [ ] [ ] ; for ( int tag = 0 ; tag < numSubStatesArray . length ; tag ++ ) { mergeThisIteration [ tag ] = new boolean [ mergeThesePairs [ tag ] . length ] [ mergeThesePairs [ tag ] . length ] ; for ( int i = 0 ; i < mergeThesePairs [ tag ] . length ; i ++ ) { for ( int j = 0 ; j < mergeThesePairs [ tag ] . length ; j ++ ) { mergeThisIteration [ tag ] [ i ] [ j ] = mergeThesePairs [ tag ] [ i ] [ j ] ; } } } for ( int tag = 0 ; tag < numSubStatesArray . length ; tag ++ ) { boolean [ ] alreadyDecidedToMerge = new boolean [ mergeThesePairs [ tag ] . length ] ; for ( int i = 0 ; i < mergeThesePairs [ tag ] . length ; i ++ ) { for ( int j = 0 ; j < mergeThesePairs [ tag ] . length ; j ++ ) { if ( alreadyDecidedToMerge [ i ] || alreadyDecidedToMerge [ j ] ) mergeThisIteration [ tag ] [ i ] [ j ] = false ; alreadyDecidedToMerge [ i ] = alreadyDecidedToMerge [ i ] || mergeThesePairs [ tag ] [ i ] [ j ] ; alreadyDecidedToMerge [ j ] = alreadyDecidedToMerge [ j ] || mergeThesePairs [ tag ] [ i ] [ j ] ; } } } for ( int tag = 0 ; tag < numSubStatesArray . length ; tag ++ ) { for ( int i = 0 ; i < mergeThesePairs [ tag ] . length ; i ++ ) { for ( int j = 0 ; j < mergeThesePairs [ tag ] . length ; j ++ ) { mergeThesePairs [ tag ] [ i ] [ j ] = mergeThesePairs [ tag ] [ i ] [ j ] && ! mergeThisIteration [ tag ] [ i ] [ j ] ; } } } newGrammar = grammar . mergeStates ( mergeThisIteration , mergeWeights ) ; lexicon . mergeStates ( mergeThisIteration , mergeWeights ) ; grammar . fixMergeWeightsEtc ( mergeThesePairs , mergeWeights , mergeThisIteration ) ; grammar = newGrammar ; newNumSubStatesArray = grammar . numSubStates ; } grammar . makeCRArrays ( ) ; return grammar ; }
this function was written to have the ability to also merge non - sibling pairs , however this functionality is not used anymore since it seemed tricky to determine an appropriate threshold for merging non - siblings . the function returns a new grammar object and changes the lexicon in place !
