private double computeFinalWeight(final int outputStateId,
                                    final DetStateTuple targetTuple,
                                    Deque<DetElement> finalQueue) {
    UnionWeight<GallicWeight> result = this.unionSemiring.zero();
    for (DetElement detElement : targetTuple.getElements()) {
      State inputState = this.getInputStateForId(detElement.inputStateId);
      if (this.semiring.isZero(inputState.getFinalWeight())) {
        continue; // not final so it wont contribute
      }
      UnionWeight<GallicWeight> origFinal = UnionWeight.createSingle(GallicWeight.createEmptyLabels(
        inputState.getFinalWeight()));
      result = this.unionSemiring.plus(result, this.unionSemiring.times(detElement.residual, origFinal));
    }
    if (this.unionSemiring.isZero(result)) {
      return this.semiring.zero();
    }
    if (result.size() == 1 && result.get(0).getLabels().isEmpty()) {
      // by good fortune the residual is just a weight, no path to expand so this new state can have a final weight
      // set now! with nothing to enqueue
      return result.get(0).getWeight();
    }
    // this state can't be a final state because we have more path to emit so defer until later; we know that we cant
    // have any duplicate elements in the finalQueue since we only call computeFinalWeight once for each outputStateId
    finalQueue.addLast(new DetElement(outputStateId, result));
    return this.semiring.zero(); // since we're deferring this weight can't be a final weight
  }
private double computeFinalWeight ( final int outputStateId , final DetStateTuple targetTuple , Deque < DetElement > finalQueue ) { UnionWeight < GallicWeight > result = this . unionSemiring . zero ( ) ; for ( DetElement detElement : targetTuple . getElements ( ) ) { State inputState = this . getInputStateForId ( detElement . inputStateId ) ; if ( this . semiring . isZero ( inputState . getFinalWeight ( ) ) ) { continue ; } UnionWeight < GallicWeight > origFinal = UnionWeight . createSingle ( GallicWeight . createEmptyLabels ( inputState . getFinalWeight ( ) ) ) ; result = this . unionSemiring . plus ( result , this . unionSemiring . times ( detElement . residual , origFinal ) ) ; } if ( this . unionSemiring . isZero ( result ) ) { return this . semiring . zero ( ) ; } if ( result . size ( ) == 1 && result . get ( 0 ) . getLabels ( ) . isEmpty ( ) ) { return result . get ( 0 ) . getWeight ( ) ; } finalQueue . addLast ( new DetElement ( outputStateId , result ) ) ; return this . semiring . zero ( ) ; }
_this_ new outState a final state, and instead we queue it into a separate queue for later expansion