/// <include file='FactorDocs.xml' path='factor_docs/message_op_class[@name="SingleOp"]/message_doc[@name="CharacterAverageConditional(StringDistribution)"]/*'/> public static DiscreteChar CharacterAverageConditional(StringDistribution str) { Argument.CheckIfNotNull(str, "str"); if (str.IsPointMass) { return(CharacterAverageConditional(str.Point)); } Vector resultLogProb = PiecewiseVector.Constant(char.MaxValue + 1, double.NegativeInfinity); StringAutomaton probFunc = str.GetWorkspaceOrPoint(); StringAutomaton.EpsilonClosure startEpsilonClosure = probFunc.Start.GetEpsilonClosure(); for (int stateIndex = 0; stateIndex < startEpsilonClosure.Size; ++stateIndex) { StringAutomaton.State state = startEpsilonClosure.GetStateByIndex(stateIndex); Weight stateLogWeight = startEpsilonClosure.GetStateWeightByIndex(stateIndex); for (int transitionIndex = 0; transitionIndex < state.TransitionCount; ++transitionIndex) { StringAutomaton.Transition transition = state.GetTransition(transitionIndex); if (!transition.IsEpsilon) { StringAutomaton.State destState = probFunc.States[transition.DestinationStateIndex]; StringAutomaton.EpsilonClosure destStateClosure = destState.GetEpsilonClosure(); if (!destStateClosure.EndWeight.IsZero) { Weight weight = Weight.Product(stateLogWeight, transition.Weight, destStateClosure.EndWeight); var logProbs = transition.ElementDistribution.GetProbs(); logProbs.SetToFunction(logProbs, Math.Log); resultLogProb = LogSumExp(resultLogProb, logProbs, weight); } } } } if (resultLogProb.All(double.IsNegativeInfinity)) { throw new AllZeroException("An input distribution assigns zero probability to all single character strings."); } Vector resultProb = PiecewiseVector.Zero(char.MaxValue + 1); double logNormalizer = resultLogProb.LogSumExp(); resultProb.SetToFunction(resultLogProb, lp => Math.Exp(lp - logNormalizer)); return(DiscreteChar.FromVector(resultProb)); }
/// <summary>EP message to <c>character</c>.</summary> /// <param name="str">Incoming message from <c>str</c>.</param> /// <returns>The outgoing EP message to the <c>character</c> argument.</returns> /// <remarks> /// <para>The outgoing message is a distribution matching the moments of <c>character</c> as the random arguments are varied. The formula is <c>proj[p(character) sum_(str) p(str) factor(character,str)]/p(character)</c>.</para> /// </remarks> public static DiscreteChar CharacterAverageConditional(StringDistribution str) { Argument.CheckIfNotNull(str, "str"); Vector resultlogProb = PiecewiseVector.Constant(char.MaxValue + 1, double.NegativeInfinity); StringAutomaton probFunc = str.GetProbabilityFunction(); StringAutomaton.EpsilonClosure startEpsilonClosure = probFunc.Start.GetEpsilonClosure(); for (int stateIndex = 0; stateIndex < startEpsilonClosure.Size; ++stateIndex) { StringAutomaton.State state = startEpsilonClosure.GetStateByIndex(stateIndex); double stateLogWeight = startEpsilonClosure.GetStateLogWeightByIndex(stateIndex); for (int transitionIndex = 0; transitionIndex < state.Transitions.Count; ++transitionIndex) { StringAutomaton.Transition transition = state.Transitions[transitionIndex]; if (!transition.IsEpsilon) { StringAutomaton.State destState = probFunc.States[transition.DestinationStateIndex]; StringAutomaton.EpsilonClosure destStateClosure = destState.GetEpsilonClosure(); if (!double.IsNegativeInfinity(destStateClosure.EndLogWeight)) { double logWeight = stateLogWeight + transition.LogWeight + destStateClosure.EndLogWeight; resultlogProb = LogSumExp(resultlogProb, transition.ElementDistribution.GetInternalDiscrete().GetLogProbs(), logWeight); } } } } if (resultlogProb.All(double.IsNegativeInfinity)) { throw new AllZeroException("An input distribution assigns zero probability to all single character strings."); } Vector resultProb = PiecewiseVector.Zero(char.MaxValue + 1); resultProb.SetToFunction(resultlogProb, Math.Exp); return(DiscreteChar.FromVector(resultProb)); }