/// <summary> /// For each state of the component, computes the total weight of all paths starting at that state. /// Ending weights are taken into account. /// </summary> /// <remarks>The weights are computed using dynamic programming, going up from leafs to the root.</remarks> private void ComputeWeightsToEnd() { // Iterate in the reverse topological order for (int currentComponentIndex = 0; currentComponentIndex < this.components.Count; ++currentComponentIndex) { StronglyConnectedComponent currentComponent = this.components[currentComponentIndex]; // Update end weights in this component based on outgoing transitions to downward components for (int stateIndex = 0; stateIndex < currentComponent.Size; ++stateIndex) { State state = currentComponent.GetStateByIndex(stateIndex); // Aggregate weights of all the outgoing transitions from this state Weight weightToAdd = state.EndWeight; foreach (var transition in state.Transitions) { State destState = this.automaton.States[transition.DestinationStateIndex]; if (this.transitionFilter(transition) && !currentComponent.HasState(destState)) { weightToAdd += transition.Weight * this.stateInfo[transition.DestinationStateIndex].WeightToEnd; } } // We can go from any state of the component to the current state if (!weightToAdd.IsZero) { for (int updatedStateIndex = 0; updatedStateIndex < currentComponent.Size; ++updatedStateIndex) { State updatedState = currentComponent.GetStateByIndex(updatedStateIndex); CondensationStateInfo updatedStateInfo = this.stateInfo[updatedState.Index]; updatedStateInfo.WeightToEnd += currentComponent.GetWeight(updatedStateIndex, stateIndex) * weightToAdd; this.stateInfo.Update(updatedState.Index, updatedStateInfo); } } } } this.weightsToEndComputed = true; }
/// <summary> /// For each state of the component, computes the total weight of all paths starting at the root /// and ending at that state. Ending weights are not taken into account. /// </summary> /// <remarks>The weights are computed using dynamic programming, going down from the root to leafs.</remarks> private void ComputeWeightsFromRoot() { CondensationStateInfo rootInfo = this.stateIdToInfo[this.Root.Index]; rootInfo.UpwardWeightFromRoot = Weight.One; this.stateIdToInfo[this.Root.Index] = rootInfo; // Iterate in the topological order for (int currentComponentIndex = this.components.Count - 1; currentComponentIndex >= 0; --currentComponentIndex) { StronglyConnectedComponent currentComponent = this.components[currentComponentIndex]; // Propagate weights inside the component for (int srcStateIndex = 0; srcStateIndex < currentComponent.Size; ++srcStateIndex) { State srcState = currentComponent.GetStateByIndex(srcStateIndex); CondensationStateInfo srcStateInfo = this.stateIdToInfo[srcState.Index]; if (srcStateInfo.UpwardWeightFromRoot.IsZero) { continue; } for (int destStateIndex = 0; destStateIndex < currentComponent.Size; ++destStateIndex) { State destState = currentComponent.GetStateByIndex(destStateIndex); CondensationStateInfo destStateInfo = this.stateIdToInfo[destState.Index]; destStateInfo.WeightFromRoot = Weight.Sum( destStateInfo.WeightFromRoot, Weight.Product(srcStateInfo.UpwardWeightFromRoot, currentComponent.GetWeight(srcStateIndex, destStateIndex))); this.stateIdToInfo[destState.Index] = destStateInfo; } } // Compute weight contributions to downward components for (int srcStateIndex = 0; srcStateIndex < currentComponent.Size; ++srcStateIndex) { State srcState = currentComponent.GetStateByIndex(srcStateIndex); CondensationStateInfo srcStateInfo = this.stateIdToInfo[srcState.Index]; if (srcStateInfo.WeightFromRoot.IsZero) { continue; } // Aggregate weights of all the outgoing transitions from this state for (int transitionIndex = 0; transitionIndex < srcState.TransitionCount; ++transitionIndex) { Transition transition = srcState.GetTransition(transitionIndex); State destState = srcState.Owner.states[transition.DestinationStateIndex]; if (this.transitionFilter(transition) && !currentComponent.HasState(destState)) { CondensationStateInfo destStateInfo = this.stateIdToInfo[destState.Index]; destStateInfo.UpwardWeightFromRoot = Weight.Sum( destStateInfo.UpwardWeightFromRoot, Weight.Product(srcStateInfo.WeightFromRoot, transition.Weight)); this.stateIdToInfo[transition.DestinationStateIndex] = destStateInfo; } } } } this.weightsFromRootComputed = true; }