//private bool AllBackwardPathsContain(IPfcNode from, IPfcNode target, Stack<IPfcNode> path) { // if (from.PredecessorNodes.Count() == 0) { // return false; // } else if (from == target) { // return true; // } else { // foreach (IPfcNode pred in from.PredecessorNodes) { // if (!path.Contains(pred)) { // path.Push(pred); // if (!AllBackwardPathsContain(pred, target, path)) // return false; // path.Pop(); // } // } // return true; // } //} private IPfcNode DivergenceNodeFor(IPfcNode closure) { NodeValidationData nvd = GetValidationData(closure); //if (nvd.DivergenceNode != null) // return nvd.DivergenceNode; List <IPfcNode> possibles = new List <IPfcNode>(); foreach (IPfcTransitionNode trans in m_pfc.Transitions) { if (Node1DependsOnNode2(closure, trans)) { possibles.Add(trans); } } possibles.Sort(new PfcNode.NodeComparer()); possibles.Reverse(); foreach (IPfcNode possible in possibles) { m_pfc.Nodes.ForEach(n => GetValidationData(n).IsInPath = null); if (AllBackwardPathsContain(closure, possible)) { return(possible); } } return(null); }
/// <summary> /// Validates the PFC in this instance, and sets (MUST SET) the m_pfcIsValid to true or false. /// </summary> private void Validate() { try { m_activePath = new Queue <QueueData>(); foreach (IPfcNode node in m_pfc.Nodes) { NodeValidationData.Attach(node); } foreach (IPfcLinkElement link in m_pfc.Links) { LinkValidationData.Attach(link); } BuildDependencies(); Propagate(); Check(); DateTime finish = DateTime.Now; foreach (IPfcNode node in m_pfc.Nodes) { NodeValidationData.Detach(node); } foreach (IPfcLinkElement link in m_pfc.Links) { LinkValidationData.Detach(link); } } catch (Exception e) { m_errorList.Add(new PfcValidationError("Exception while validating.", e.Message, null)); m_pfcIsValid = false; } }
/// <summary> /// Determines whether all backward paths from 'from' contain the node 'target.' If they do, /// and it is the first such encounter for a specific 'from' then it may be said that target /// is the divergence node for 'from.' /// </summary> /// <param name="from">From.</param> /// <param name="target">The target.</param> /// <returns></returns> private bool AllBackwardPathsContain(IPfcNode from, IPfcNode target) { NodeValidationData nvd = GetValidationData(from); if (nvd.IsInPath == null) { if (!from.PredecessorNodes.Any()) { nvd.IsInPath = false; } else if (from == target) { nvd.IsInPath = true; } else { nvd.IsInPath = true; foreach (IPfcNode predecessorNode in from.PredecessorNodes) { if (!AllBackwardPathsContain(predecessorNode, target)) { nvd.IsInPath = false; break; } } } } return(nvd.IsInPath.Value); }
private bool AllForwardPathsContain(IPfcNode from, IPfcNode target, Stack <IPfcNode> path) { NodeValidationData nvd = GetValidationData(from); if (nvd.IsInPath == null) { if (from.SuccessorNodes.Count() == 0) { nvd.IsInPath = false; } else if (from == target) { nvd.IsInPath = true; } else { nvd.IsInPath = true; foreach (IPfcNode succ in from.SuccessorNodes) { if (!AllForwardPathsContain(succ, target, path)) { nvd.IsInPath = false; break; } } } } return(nvd.IsInPath.Value); }
public static void Detach(IPfcNode node) { NodeValidationData vd = node.UserData as NodeValidationData; if (vd != null) { node.UserData = vd.m_userData; } }
private void Enqueue(IPfcNode from, IPfcNode node, ValidationToken vt) { NodeValidationData vd = GetValidationData(node); if (vd.InputRole == InputRole.ParallelConvergence) { GetValidationData(from).ValidationToken.DecrementAlternatePathsOpen(); } vd.ValidationToken = vt; m_activePath.Enqueue(new QueueData(from, node)); if (m_diagnostics) { Console.WriteLine("\tEnqueueing {0} with {1} ({2}).", node.Name, vt, vt.AlternatePathsOpen); } }
private bool AllParallelAndAtLeastOneOfEachSetOfSerialPathsContain(IPfcNode from, IPfcNode target) { NodeValidationData nvd = GetValidationData(from); if (nvd.IsInPath == null) { if (!from.SuccessorNodes.Any()) { nvd.IsInPath = false; } else if (from == target) { nvd.IsInPath = true; } else if (from.SuccessorNodes.Count == 1) { return(AllParallelAndAtLeastOneOfEachSetOfSerialPathsContain(from.SuccessorNodes[0], target)); } else // It's a divergence. { if (from is IPfcStepNode) { // serial divergence. bool retval = false; foreach (IPfcNode successorNode in from.SuccessorNodes) { retval |= AllParallelAndAtLeastOneOfEachSetOfSerialPathsContain(successorNode, target); } return(retval); } else { // parallel divergence. bool retval = true; foreach (IPfcNode successorNode in from.SuccessorNodes) { retval &= AllParallelAndAtLeastOneOfEachSetOfSerialPathsContain(successorNode, target); } return(retval); } } } return(nvd.IsInPath.Value); }
private void Check() { m_errorList = new List <PfcValidationError>(); List <ValidationToken> tokensWithLiveChildren = new List <ValidationToken>(); List <ValidationToken> tokensWithOpenAlternates = new List <ValidationToken>(); List <IPfcNode> unreachableNodes = new List <IPfcNode>(); List <IPfcNode> unexecutedNodes = new List <IPfcNode>(); List <IPfcStepNode> inconsistentSerialConvergences = new List <IPfcStepNode>(); #region Collect errors foreach (IPfcNode node in m_pfc.Nodes) { NodeValidationData nodeVd = GetValidationData(node); ValidationToken nodeVt = nodeVd.ValidationToken; if (nodeVt == null) { unreachableNodes.Add(node); unexecutedNodes.Add(node); } else { if (nodeVt.AlternatePathsOpen > 0 && !tokensWithOpenAlternates.Contains(nodeVt)) { tokensWithOpenAlternates.Add(GetValidationData(node).ValidationToken); } if (!nodeVd.NodeHasRun) { unexecutedNodes.Add(node); } if (node.ElementType == PfcElementType.Step && node.PredecessorNodes.Count() > 1) { ValidationToken vt = GetValidationData(node.PredecessorNodes[0]).ValidationToken; if (!node.PredecessorNodes.TrueForAll(n => GetValidationData(n).ValidationToken.Equals(vt))) { inconsistentSerialConvergences.Add((IPfcStepNode)node); } } if (nodeVt.AnyChildLive) { tokensWithLiveChildren.Add(nodeVt); } } } #endregion m_pfcIsValid = tokensWithLiveChildren.Count() == 0 && tokensWithOpenAlternates.Count() == 0 && unreachableNodes.Count() == 0 && unexecutedNodes.Count() == 0 && inconsistentSerialConvergences.Count() == 0; StringBuilder sb = null; sb = new StringBuilder(); unreachableNodes.Sort(m_nodeByName); unexecutedNodes.Sort(m_nodeByName); inconsistentSerialConvergences.Sort(m_stepNodeByName); foreach (IPfcNode node in unreachableNodes) { if (!node.PredecessorNodes.TrueForAll(n => GetValidationData(n).ValidationToken == null)) { string narrative = string.Format("Node {0}, along with others that follow it, is unreachable.", node.Name); m_errorList.Add(new PfcValidationError("Unreachable PFC Node", narrative, node)); sb.AppendLine(narrative); } } foreach (IPfcNode node in unexecutedNodes) { if (!node.PredecessorNodes.TrueForAll(n => GetValidationData(n).ValidationToken == null)) { string narrative = string.Format("Node {0} failed to run.", node.Name); m_errorList.Add(new PfcValidationError("Unexecuted PFC Node", narrative, node)); sb.AppendLine(narrative); } } inconsistentSerialConvergences.Sort((n1, n2) => Comparer.Default.Compare(n1.Name, n2.Name)); foreach (IPfcStepNode node in inconsistentSerialConvergences) { string narrative = string.Format( "Branch paths (serial convergences) into {0} do not all have the same validation token, meaning they came from different branches (serial divergences).", node.Name); m_errorList.Add(new PfcValidationError("Serial Di/Convergence Mismatch", narrative, node)); sb.AppendLine(narrative); } foreach (ValidationToken vt in tokensWithLiveChildren) { List <IPfcNode> liveNodes = new List <IPfcNode>(); foreach (ValidationToken vt2 in vt.ChildNodes.Where(n => n.AlternatePathsOpen > 0)) { liveNodes.Add(vt2.Origin); } int nParallelsOpen = vt.ChildNodes.Count(); string narrative = string.Format( "Under {0}, there {1} {2} parallel branch{3} that did not complete - {4} began at {5}.", vt.Origin.Name, nParallelsOpen == 1 ? "is" : "are", nParallelsOpen, nParallelsOpen == 1 ? "" : "es", nParallelsOpen == 1 ? "it" : "they", StringOperations.ToCommasAndAndedList <IPfcNode>(liveNodes, n => n.Name) ); m_errorList.Add(new PfcValidationError("Uncompleted Parallel Branches", narrative, vt.Origin)); sb.AppendLine(); } if (m_diagnostics) { Console.WriteLine(sb.ToString()); } }