import { State , advanceDot , isCompleted } from "./state" ; import { ProbabilitySemiringMapping } from "../../grammar/grammar" ; import { Rule } from "../../grammar/rule" ; import { Chart } from "./chart" ; import { NonTerminal } from "../../grammar/category" ; /**
 * Representing a Viterbi score coming from a certain chart,
 * transition to a result chart computing
 * using a certain semiring
 */ export interface ViterbiScore < S , T > { origin : State < S , T > ; resultingState : State < S , T > ; innerScore : S ; } param stateSets param completedState param originPathTo param m export function setViterbiScores < S , T > ( stateSets , completedState , originPathTo , m ) { const sr = m . semiring ; let newStates = undefined ; let newCompletedStates = undefined ; if ( ! stateSets . hasViterbiScore ( completedState ) ) throw new Error ( "Expected Viterbi score to be set on completed chart. This is a bug." ) ; const completedViterbi = stateSets . getViterbiScore ( completedState ) . innerScore ; const Y = completedState . rule . left ; const pos = completedState . position ; stateSets . getStatesActiveOnNonTerminal ( Y , completedState . ruleStartPosition , pos ) . forEach ( ( stateToAdvance ) => { if ( stateToAdvance . position > pos || stateToAdvance . position != completedState . ruleStartPosition ) throw new Error ( "Index failed. This is a bug." ) ; const ruleStart = stateToAdvance . ruleStartPosition ; const nextDot = advanceDot ( stateToAdvance ) ; const rule = stateToAdvance . rule ; let resultingState = stateSets . getState ( rule , pos , ruleStart , nextDot ) ; if ( ! resultingState ) { resultingState = stateSets . getOrCreate ( pos , ruleStart , nextDot , rule ) ; if ( ! newStates ) newStates = [ ] ; newStates . push ( resultingState ) ; } if ( originPathTo . has ( resultingState ) ) throw new Error ( "This is a bug: Already went past " + resultingState ) ; const viterbiScore = stateSets . getViterbiScore ( resultingState ) ; const prevViterbi = stateSets . getViterbiScore ( stateToAdvance ) ; const prev = ! ! prevViterbi ? prevViterbi . innerScore : sr . multiplicativeIdentity ; const newViterbiScore = { innerScore : sr . times ( completedViterbi , prev ) , origin : completedState , resultingState } ; if ( ! viterbiScore || m . toProbability ( viterbiScore . innerScore ) < m . toProbability ( newViterbiScore . innerScore ) ) { stateSets . setViterbiScore ( newViterbiScore ) ; if ( isCompleted ( resultingState ) ) { if ( ! newCompletedStates ) newCompletedStates = [ ] ; newCompletedStates . push ( resultingState ) ; } } } ) ; if ( ! ! newStates ) newStates . forEach ( a => stateSets . addState ( a ) ) ; if ( ! ! newCompletedStates ) newCompletedStates . forEach ( resultingState => { const path = new Set < State < S , T > > ( originPathTo ) ; path . add ( resultingState ) ; setViterbiScores ( stateSets , resultingState , path , m ) ; } ) ; }