Source:
public static <D, T, S> List<S> apply(final List<D> data, final List<T> positions, final HiddenMarkovModel<D, T, S> model) { checkApplyArguments(data, positions, model); if (data.size() == 0) { return new ArrayList<>(0); } @SuppressWarnings("unchecked") final S[] states = (S[]) model.hiddenStates().stream().toArray(Object[]::new); final int length = data.size(); final int width = states.length; @SuppressWarnings({"rawtypes", "unchecked"}) final Path<S>[][] bestPaths = (Path<S>[][]) new Path[][] { initializeBestPaths(data, positions, model, states), (Path<S>[]) new Path[width] }; for (int u = 1; u < length; u++) { final int t = u - 1; final Path<S>[] bestUPaths = bestPaths[1 & u]; final Path<S>[] bestTPaths = bestPaths[1 & t]; final T positionT = positions.get(t); final D dataU = data.get(u); final T positionU = positions.get(u); for (int sU = 0; sU < width; sU++) { final S stateU = states[sU]; int bestTStateIndex = 0; double bestTStateLog10Prob = bestTPaths[0].log10Prob + model.logTransitionProbability(states[0], positionT, stateU, positionU); for (int sT = 1; sT < width; sT++) { final double candidateTLog10Prob = bestTPaths[sT].log10Prob + model.logTransitionProbability(states[sT], positionT, stateU, positionU); if (candidateTLog10Prob > bestTStateLog10Prob) { bestTStateLog10Prob = candidateTLog10Prob; bestTStateIndex = sT; } } bestUPaths[sU] = bestTPaths[bestTStateIndex].extend(stateU, bestTStateLog10Prob + model.logEmissionProbability(dataU, stateU, positionU)); } } return composeBestStateSequence(length, bestPaths[(length - 1) & 1]); }

Target:
public static <D, T, S> List<S> apply(final List<D> data, final List<T> positions, final HiddenMarkovModel<D, T, S> model) { checkApplyArguments(data, positions, model); if (data.size() == 0) { return new ArrayList<>(0); } @SuppressWarnings("unchecked") final S[] states = (S[]) model.hiddenStates().stream().toArray(Object[]::new); final int length = data.size(); final int numStates = states.length; @SuppressWarnings({"rawtypes", "unchecked"}) final Path<S>[][] bestPaths = (Path<S>[][]) new Path[][] { initializeBestPaths(data, positions, model, states), (Path<S>[]) new Path[numStates] }; for (int thisPositionIndex = 1; thisPositionIndex < length; thisPositionIndex++) { final int previousPositionIndex = thisPositionIndex - 1; final Path<S>[] bestCurrentPaths = bestPaths[1 & thisPositionIndex]; final Path<S>[] bestPreviousPaths = bestPaths[1 & previousPositionIndex]; final T previousPosition = positions.get(previousPositionIndex); final D thisDatum = data.get(thisPositionIndex); final T thisPosition = positions.get(thisPositionIndex); for (int thisStateIndex = 0; thisStateIndex < numStates; thisStateIndex++) { final S thisState = states[thisStateIndex]; int bestPreviousStateIndex = 0; double bestPreviousStateLogProb = bestPreviousPaths[0].logProb + model.logTransitionProbability(states[0], previousPosition, thisState, thisPosition); for (int previousStateIndex = 1; previousStateIndex < numStates; previousStateIndex++) { final double candidatePreviousStateLogProb = bestPreviousPaths[previousStateIndex].logProb + model.logTransitionProbability(states[previousStateIndex], previousPosition, thisState, thisPosition); if (candidatePreviousStateLogProb > bestPreviousStateLogProb) { bestPreviousStateLogProb = candidatePreviousStateLogProb; bestPreviousStateIndex = previousStateIndex; } } bestCurrentPaths[thisStateIndex] = bestPreviousPaths[bestPreviousStateIndex].extend(thisState, bestPreviousStateLogProb + model.logEmissionProbability(thisDatum, thisState, thisPosition)); } } return composeBestStateSequence(length, bestPaths[(length - 1) & 1]); }