/// <summary> /// Generate counter example for reachability and deadlock /// [ REFS: '', DEREFS: automataBDD.transitionBDD, automataBDD.priorityTransitionsBDD, this.traces ] /// </summary> /// <param name="automataBDD"></param> /// <param name="encoder"></param> /// <returns></returns> public void GetMCResult(AutomataBDD automataBDD, BDDEncoder encoder) { VerificationOutput.CounterExampleTrace.Add(InitialStep); if (this.traces.Count > 0) { ExpressionBDDEncoding initEncoding = automataBDD.initExpression.TranslateBoolExpToBDD(encoder.model); this.traces.Insert(0, CUDD.Function.Or(initEncoding.GuardDDs)); Valuation currentValuation = this.InitialStep.GlobalEnv; Valuation lastValuation; List <CUDDNode> allTransitions = new List <CUDDNode>(); allTransitions.AddRange(automataBDD.transitionBDD); allTransitions.AddRange(automataBDD.Ticks); for (int i = 1; i < this.traces.Count; i++) { //Get event information CUDD.Ref(allTransitions); CUDD.Ref(this.traces[i], this.traces[i - 1]); CUDDNode transitionTemp = CUDD.Function.And(this.traces[i - 1], encoder.model.SwapRowColVars(this.traces[i])); CUDDNode transWithEventInfo = CUDD.Function.And(transitionTemp, allTransitions); transWithEventInfo = CUDD.Abstract.ThereExists(transWithEventInfo, encoder.model.AllRowVarsExceptSingleCopy); transWithEventInfo = CUDD.RestrictToFirst(transWithEventInfo, encoder.model.AllColVars); lastValuation = currentValuation; currentValuation = encoder.GetValuationFromBDD(transWithEventInfo, this.InitialStep.GlobalEnv); string eventName = encoder.GetEventChannelName(lastValuation, currentValuation, transWithEventInfo); VerificationOutput.CounterExampleTrace.Add(new ConfigurationBDD(eventName, currentValuation)); // CUDD.Deref(transWithEventInfo); } } // CUDD.Deref(automataBDD.transitionBDD, automataBDD.Ticks, traces); // VerificationOutput.ActualMemoryUsage = CUDD.ReadMemoryInUse(); VerificationOutput.numberOfBoolVars = encoder.model.NumberOfBoolVars; encoder.model.Close(); }
/// <summary> /// Return a computation of a buchi automata in form "prefix (period)*" /// [ REFS: 'prefix, period', DEREFS:] /// </summary> /// <param name="automataBDD"></param> /// <param name="model"></param> public void MC(AutomataBDD automataBDD, Model model) { //Clear the old data this.transitionsNoEvents.Clear(); this.prefix.Clear(); this.period.Clear(); ExpressionBDDEncoding initEncoding = automataBDD.initExpression.TranslateBoolExpToBDD(model); if (initEncoding.GuardDDs.Count == 0) { return; } ExpressionBDDEncoding finalStateEncoding = automataBDD.acceptanceExpression.TranslateBoolExpToBDD(model); if (finalStateEncoding.GuardDDs.Count == 0) { return; } CUDDNode initState = CUDD.Function.Or(initEncoding.GuardDDs); CUDDNode finalState = CUDD.Function.Or(finalStateEncoding.GuardDDs); CUDDNode finalStateWithNoEvent = CUDD.Abstract.ThereExists(finalState, model.GetAllEventVars()); CUDD.Ref(automataBDD.transitionBDD); this.transitionsNoEvents = CUDD.Abstract.ThereExists(automataBDD.transitionBDD, model.GetAllEventVars()); CUDDNode allSCCs = SCCHull(model, initState, finalStateWithNoEvent); if (!allSCCs.Equals(CUDD.ZERO) && VerificationOutput.GenerateCounterExample) { this.VerificationOutput.VerificationResult = VerificationResultType.INVALID; //Transitions out from allSCCs CUDD.Ref(transitionsNoEvents); CUDD.Ref(allSCCs); List <CUDDNode> R = CUDD.Function.And(transitionsNoEvents, allSCCs); //pick one state from the set final CUDD.Ref(allSCCs); CUDDNode s = CUDD.RestrictToFirst(allSCCs, model.AllRowVars); //while the states from which we can reach s are not all states that can be reached from s CUDDNode scc; while (true) { CUDD.Ref(s); CUDDNode backwardOfS = model.PredecessorsStart(s, R); CUDD.Ref(s); CUDDNode forwardOfS = model.SuccessorsStart(s, R); // CUDD.Ref(backwardOfS, forwardOfS); CUDDNode temp = CUDD.Function.Different(backwardOfS, forwardOfS); if (temp.Equals(CUDD.ZERO)) { scc = backwardOfS; CUDD.Deref(forwardOfS, temp); break; } else { CUDD.Deref(backwardOfS, forwardOfS, s); s = CUDD.RestrictToFirst(temp, model.AllRowVars); } } //R now contains only transitions within the SCC scc CUDD.Ref(scc, scc, scc, scc); R[0] = CUDD.Function.And(CUDD.Function.And(R[0], scc), model.SwapRowColVars(scc)); R[1] = CUDD.Function.And(CUDD.Function.And(R[1], scc), model.SwapRowColVars(scc)); CUDD.Ref(scc); CUDDNode notInSCC = CUDD.Function.Not(scc); List <CUDDNode> transitionNotInSCC = new List <CUDDNode>(); CUDD.Ref(transitionsNoEvents, transitionsNoEvents); CUDD.Ref(notInSCC, notInSCC); transitionNotInSCC.AddRange(CUDD.Function.And(transitionsNoEvents, notInSCC)); transitionNotInSCC.AddRange(CUDD.Function.And(transitionsNoEvents, model.SwapRowColVars(notInSCC))); //prefix is now a shortest path from an initial state to a state in final model.Path(initState, scc, transitionNotInSCC, prefix, true); CUDD.Deref(transitionNotInSCC[0], transitionNotInSCC[1]); //Dummy value period.Add((prefix.Count == 0) ? initState : prefix[prefix.Count - 1]); //cycle must pass final state CUDD.Ref(period); CUDD.Ref(finalStateWithNoEvent); CUDDNode temp1 = CUDD.Function.And(CUDD.Function.Or(period), finalStateWithNoEvent); if (temp1.Equals(CUDD.ZERO)) { CUDD.Ref(scc, finalStateWithNoEvent); CUDDNode acceptanceStateInCyle = CUDD.Function.And(scc, finalStateWithNoEvent); model.Path(period[period.Count - 1], acceptanceStateInCyle, R, period, true); CUDD.Deref(acceptanceStateInCyle); } CUDD.Deref(temp1); // bool isEmptyPathAllowed = period.Count != 1; model.Path(period[period.Count - 1], period[0], R, period, isEmptyPathAllowed); //Remove dummy CUDD.Deref(period[0]); period.RemoveAt(0); // CUDD.Deref(initState, finalStateWithNoEvent, allSCCs, s, scc, notInSCC); CUDD.Deref(transitionsNoEvents[0], transitionsNoEvents[1]); CUDD.Deref(R[0], R[1]); } else { this.VerificationOutput.VerificationResult = VerificationResultType.VALID; CUDD.Deref(initState, finalStateWithNoEvent, allSCCs); CUDD.Deref(transitionsNoEvents[0], transitionsNoEvents[1]); } }
/// <summary> /// Return the path from source to destination. If reachable, return true and path contains the path from source to destination /// [ REFS: '', DEREFS:] /// </summary> /// <param name="source"></param> /// <param name="destination"></param> /// <param name="transitions"></param> /// <param name="model"></param> /// <param name="path">not include the init state</param> /// <param name="isEmptyPathAllowed">if false, then the path must be not empty though the source satisfies the destination</param> /// <returns></returns> public bool PathBackWard(CUDDNode source, CUDDNode destination, List <CUDDNode> transitions, List <CUDDNode> path, bool isEmptyPathAllowed) { if (isEmptyPathAllowed) { // CUDD.Ref(source, destination); CUDDNode temp = CUDD.Function.And(source, destination); //In case source already satisfies destination if (!temp.Equals(CUDD.ZERO)) { CUDD.Deref(temp); return(true); } } // bool reachable = false; List <CUDDNode> backtrackingReachability = new List <CUDDNode>(); CUDDNode allReachabeToGoal, currentReachableToGoal; CUDD.Ref(destination, destination); allReachabeToGoal = currentReachableToGoal = destination; int numberOfLoop = 0; CUDDNode commonNode = CUDD.Constant(0); do { //backward numberOfLoop++; Debug.Write(numberOfLoop + " "); //to find source state, now the currentReachableToGoal must be in column form (target state) currentReachableToGoal = this.SwapRowColVars(currentReachableToGoal); CUDD.Ref(transitions); currentReachableToGoal = CUDD.Function.And(currentReachableToGoal, transitions); CUDD.Ref(currentReachableToGoal); backtrackingReachability.Add(currentReachableToGoal); //get source state, but in row-form currentReachableToGoal = CUDD.Abstract.ThereExists(currentReachableToGoal, AllColVars); //Check 2 directions have intersection CUDD.Ref(currentReachableToGoal, source); CUDD.Deref(commonNode); commonNode = CUDD.Function.And(currentReachableToGoal, source); if (!commonNode.Equals(CUDD.ZERO)) { reachable = true; break; } //find fixpoint CUDD.Ref(currentReachableToGoal, allReachabeToGoal); CUDDNode allReachabeToGoalTemp = CUDD.Function.Or(allReachabeToGoal, currentReachableToGoal); if (allReachabeToGoalTemp.Equals(allReachabeToGoal)) { reachable = false; CUDD.Deref(allReachabeToGoalTemp); break; } else { currentReachableToGoal = CUDD.Function.Different(currentReachableToGoal, allReachabeToGoal); allReachabeToGoal = allReachabeToGoalTemp; } } while (true); Debug.WriteLine("\nPath Backward: " + numberOfLoop + " loops."); if (!reachable) { CUDD.Deref(currentReachableToGoal, allReachabeToGoal, commonNode); CUDD.Deref(backtrackingReachability); // backtrackingReachability.Clear(); } else { // CUDD.Deref(currentReachableToGoal, allReachabeToGoal, commonNode); //backtrackingReachability contains transitions from source to destination if (backtrackingReachability.Count > 0) { CUDDNode currentStateDD = source; CUDD.Ref(currentStateDD); for (int i = backtrackingReachability.Count - 1; i >= 0; i--) { //find the intersection currentStateDD = CUDD.Function.And(backtrackingReachability[i], currentStateDD); //remove all boolean variables in the row-form, it is now set of all reachable backward state currentStateDD = CUDD.Abstract.ThereExists(currentStateDD, AllRowVars); currentStateDD = CUDD.RestrictToFirst(currentStateDD, this.AllColVars); currentStateDD = CUDD.Abstract.ThereExists(currentStateDD, this.GetAllEventVars()); //swap to row-variable form currentStateDD = this.SwapRowColVars(currentStateDD); CUDD.Ref(currentStateDD); path.Add(currentStateDD); } // CUDD.Deref(currentStateDD); } } // return(reachable); }
/// <summary> /// Return the path from source to destination. If reachable, return true and path contains the path from source to destination /// [ REFS: '', DEREFS:] /// </summary> /// <param name="source"></param> /// <param name="destination"></param> /// <param name="transitions"></param> /// <param name="model"></param> /// <param name="path">not include the init state</param> /// <param name="isEmptyPathAllowed">if false, then the path must be not empty though the source satisfies the destination</param> /// <returns></returns> public bool PathForward(CUDDNode source, CUDDNode destination, List <CUDDNode> transitions, List <CUDDNode> path, bool isEmptyPathAllowed) { if (isEmptyPathAllowed) { CUDD.Ref(source, destination); CUDDNode temp = CUDD.Function.And(source, destination); //In case source already satisfies destination if (!temp.Equals(CUDD.ZERO)) { CUDD.Deref(temp); return(true); } } // bool reachable = false; List <CUDDNode> forwardReachability = new List <CUDDNode>(); CUDDNode allReachableFromInit, currentReachableFromInit; CUDD.Ref(source, source); allReachableFromInit = currentReachableFromInit = source; int numberOfLoop = 0; CUDDNode commonNode = CUDD.Constant(0); do { //forward numberOfLoop++; Debug.Write(numberOfLoop + " "); CUDD.Ref(transitions); currentReachableFromInit = CUDD.Function.And(currentReachableFromInit, transitions); //Must reference because current value of currentReachableDD belonging to backtrackingReachability CUDD.Ref(currentReachableFromInit); forwardReachability.Add(currentReachableFromInit); currentReachableFromInit = this.SwapRowColVars(currentReachableFromInit); //get target state, in row-form currentReachableFromInit = CUDD.Abstract.ThereExists(currentReachableFromInit, AllColVars); //Check 2 directions have intersection CUDD.Ref(destination, currentReachableFromInit); CUDD.Deref(commonNode); commonNode = CUDD.Function.And(destination, currentReachableFromInit); if (!commonNode.Equals(CUDD.ZERO)) { reachable = true; break; } //find fixpoint CUDD.Ref(currentReachableFromInit, allReachableFromInit); CUDDNode allReachabeFromInitTemp = CUDD.Function.Or(currentReachableFromInit, allReachableFromInit); if (allReachabeFromInitTemp.Equals(allReachableFromInit)) { //reachable = false; CUDD.Deref(allReachabeFromInitTemp); break; } else { currentReachableFromInit = CUDD.Function.Different(currentReachableFromInit, allReachableFromInit); allReachableFromInit = allReachabeFromInitTemp; } } while (true); Debug.WriteLine("\nPath Forward: " + numberOfLoop + " loops."); if (!reachable) { CUDD.Deref(currentReachableFromInit, allReachableFromInit, commonNode); CUDD.Deref(forwardReachability); // forwardReachability.Clear(); } else { // CUDD.Deref(currentReachableFromInit, allReachableFromInit); //in column form commonNode = this.SwapRowColVars(commonNode); for (int i = forwardReachability.Count - 1; i >= 0; i--) { forwardReachability[i] = CUDD.Function.And(forwardReachability[i], commonNode); //in column form CUDD.Ref(forwardReachability[i]); commonNode = CUDD.Abstract.ThereExists(forwardReachability[i], AllColVars); commonNode = this.SwapRowColVars(commonNode); } CUDD.Deref(commonNode); //backtrackingReachability contains transitions from source to destination if (forwardReachability.Count > 0) { CUDDNode currentStateDD = source; CUDD.Ref(currentStateDD); for (int i = 0; i < forwardReachability.Count; i++) { //find the intersection currentStateDD = CUDD.Function.And(forwardReachability[i], currentStateDD); //remove all boolean variables in the row-form, it is now set of all reachable backward state currentStateDD = CUDD.Abstract.ThereExists(currentStateDD, AllRowVars); currentStateDD = CUDD.RestrictToFirst(currentStateDD, this.AllColVars); currentStateDD = CUDD.Abstract.ThereExists(currentStateDD, this.GetAllEventVars()); //swap to row-variable form currentStateDD = this.SwapRowColVars(currentStateDD); CUDD.Ref(currentStateDD); path.Add(currentStateDD); } // CUDD.Deref(currentStateDD); } } // return(reachable); }
/// <summary> /// Return the path from source to destination. /// If reachable, return true and path contains the path from source to destination /// Serach from two direction: forward and backward /// [ REFS: '', DEREFS:] /// </summary> /// <param name="source"></param> /// <param name="destination"></param> /// <param name="transitions">transitions[0]: normal transitions, transitions[1]: priority transition</param> /// <param name="model"></param> /// <param name="path">not include the init state</param> /// <param name="isEmptyPathAllowed">if false, then the path must be not empty though the source satisfies the destination</param> /// <returns></returns> public bool Path(CUDDNode source, CUDDNode destination, List <List <CUDDNode> > transitions, List <CUDDNode> path, bool isEmptyPathAllowed) { if (isEmptyPathAllowed) { CUDD.Ref(source, destination); CUDDNode temp = CUDD.Function.And(source, destination); //In case source already satisfies destination if (!temp.Equals(CUDD.ZERO)) { CUDD.Deref(temp); return(true); } } // bool reachable = false; List <CUDDNode> backtrackingReachability = new List <CUDDNode>(); List <CUDDNode> forwardReachability = new List <CUDDNode>(); CUDDNode allReachabeToGoal, currentReachableToGoal; CUDD.Ref(destination, destination); allReachabeToGoal = currentReachableToGoal = destination; CUDDNode allReachableFromInit, currentReachableFromInit; CUDD.Ref(source, source); allReachableFromInit = currentReachableFromInit = source; int nextStep = 0; int forwardStep = 0; int numberOfForwardNodes = 0; int backwardSteps = 0; int numberOfBackwardNodes = 0; CUDDNode commonNode = CUDD.Constant(0); do { if (nextStep != GoForward) { //backward Debug.WriteLine("Backward: " + numberOfBDDOperation); numberOfBDDOperation++; //to find source state, now the currentReachableToGoal must be in column form (target state) currentReachableToGoal = this.SwapRowColVars(currentReachableToGoal); currentReachableToGoal = TransitionsByTargetStates(currentReachableToGoal, transitions); CUDD.Ref(currentReachableToGoal); backtrackingReachability.Add(currentReachableToGoal); //get source state, but in row-form currentReachableToGoal = CUDD.Abstract.ThereExists(currentReachableToGoal, AllColVars); //Check 2 directions have intersection CUDD.Ref(currentReachableToGoal, currentReachableFromInit); CUDD.Deref(commonNode); commonNode = CUDD.Function.And(currentReachableToGoal, currentReachableFromInit); if (!commonNode.Equals(CUDD.ZERO)) { reachable = true; break; } //find fixpoint CUDD.Ref(currentReachableToGoal, allReachabeToGoal); CUDDNode allReachabeToGoalTemp = CUDD.Function.Or(allReachabeToGoal, currentReachableToGoal); backwardSteps++; numberOfBackwardNodes = CUDD.GetNumNodes(allReachabeToGoalTemp); if (allReachabeToGoalTemp.Equals(allReachabeToGoal)) { reachable = false; CUDD.Deref(allReachabeToGoalTemp); break; } else { currentReachableToGoal = CUDD.Function.Different(currentReachableToGoal, allReachabeToGoal); allReachabeToGoal = allReachabeToGoalTemp; } } if (nextStep != GoBackward) { //forward Debug.WriteLine("Forward: " + numberOfBDDOperation); numberOfBDDOperation++; currentReachableFromInit = TransitionsBySourceStates(currentReachableFromInit, transitions); //Must reference because current value of currentReachableDD belonging to backtrackingReachability CUDD.Ref(currentReachableFromInit); forwardReachability.Add(currentReachableFromInit); currentReachableFromInit = this.SwapRowColVars(currentReachableFromInit); //get target state, in row-form currentReachableFromInit = CUDD.Abstract.ThereExists(currentReachableFromInit, AllColVars); //Check 2 directions have intersection CUDD.Ref(currentReachableToGoal, currentReachableFromInit); CUDD.Deref(commonNode); commonNode = CUDD.Function.And(currentReachableToGoal, currentReachableFromInit); if (!commonNode.Equals(CUDD.ZERO)) { reachable = true; break; } //find fixpoint CUDD.Ref(currentReachableFromInit, allReachableFromInit); CUDDNode allReachabeFromInitTemp = CUDD.Function.Or(currentReachableFromInit, allReachableFromInit); forwardStep++; numberOfForwardNodes = CUDD.GetNumNodes(allReachabeFromInitTemp); if (allReachabeFromInitTemp.Equals(allReachableFromInit)) { reachable = false; CUDD.Deref(allReachabeFromInitTemp); break; } else { currentReachableFromInit = CUDD.Function.Different(currentReachableFromInit, allReachableFromInit); allReachableFromInit = allReachabeFromInitTemp; } } nextStep = GetNextStep(forwardStep, numberOfForwardNodes, backwardSteps, numberOfBackwardNodes); } while (true); if (!reachable) { CUDD.Deref(currentReachableToGoal, allReachabeToGoal, currentReachableFromInit, allReachableFromInit, commonNode); CUDD.Deref(backtrackingReachability); CUDD.Deref(forwardReachability); // backtrackingReachability.Clear(); forwardReachability.Clear(); } else { // CUDD.Deref(currentReachableToGoal, allReachabeToGoal, currentReachableFromInit, allReachableFromInit); //in column form commonNode = this.SwapRowColVars(commonNode); for (int i = forwardReachability.Count - 1; i >= 0; i--) { //Kill commonNode CUDDNode correctTransition = CUDD.Function.And(forwardReachability[i], commonNode); CUDD.Ref(correctTransition); backtrackingReachability.Add(correctTransition); //in column form commonNode = CUDD.Abstract.ThereExists(correctTransition, AllColVars); commonNode = this.SwapRowColVars(commonNode); } CUDD.Deref(commonNode); //backtrackingReachability contains transitions from source to destination if (backtrackingReachability.Count > 0) { CUDDNode currentStateDD = source; CUDD.Ref(currentStateDD); for (int i = backtrackingReachability.Count - 1; i >= 0; i--) { //find the intersection currentStateDD = CUDD.Function.And(backtrackingReachability[i], currentStateDD); //remove all boolean variables in the row-form, it is now set of all reachable backward state currentStateDD = CUDD.Abstract.ThereExists(currentStateDD, AllRowVars); currentStateDD = CUDD.RestrictToFirst(currentStateDD, this.AllColVars); currentStateDD = CUDD.Abstract.ThereExists(currentStateDD, this.GetAllEventVars()); //swap to row-variable form currentStateDD = this.SwapRowColVars(currentStateDD); CUDD.Ref(currentStateDD); path.Add(currentStateDD); } // CUDD.Deref(currentStateDD); } } // return(reachable); }