public override string GetResultString() { StringBuilder sb = new StringBuilder(); sb.AppendLine(Constants.VERFICATION_RESULT_STRING); if (VerificationOutput.VerificationResult == VerificationResultType.INVALID) { sb.AppendLine("The Assertion (" + ToString() + ") is NOT valid."); if (FailureType != RefinementCheckingResultType.FailuresRefinementFailure) { sb.AppendLine("The following trace is allowed in " + StartingProcess + ", but not in " + SpecProcess + "."); } else { sb.AppendLine("After the following trace: failures refinement checking failed."); } VerificationOutput.GetCounterxampleString(sb); } else { sb.AppendLine("The Assertion (" + ToString() + ") is VALID."); } sb.AppendLine(); sb.AppendLine("********Verification Setting********"); sb.AppendLine("Admissible Behavior: " + SelectedBahaviorName); sb.AppendLine("Search Engine: " + SelectedEngineName); sb.AppendLine("System Abstraction: " + MustAbstract); sb.AppendLine(); return(sb.ToString()); }
public override string GetResultString() { StringBuilder sb = new StringBuilder(); sb.AppendLine(Constants.VERFICATION_RESULT_STRING); if (VerificationOutput.VerificationResult == VerificationResultType.VALID) { sb.AppendLine("The Assertion (" + ToString() + ") is VALID."); sb.AppendLine("The following trace leads to a state where the condition is satisfied."); VerificationOutput.GetCounterxampleString(sb); } else { if (VerificationOutput.VerificationResult == VerificationResultType.UNKNOWN) { sb.AppendLine("The Assertion (" + ToString() + ") is NEITHER PROVED NOR DISPROVED."); } else { sb.AppendLine("The Assertion (" + ToString() + ") is NOT valid."); } } sb.AppendLine(); sb.AppendLine("********Verification Setting********"); sb.AppendLine("Admissible Behavior: " + SelectedBahaviorName); sb.AppendLine("Search Engine: " + SelectedEngineName); sb.AppendLine("System Abstraction: " + MustAbstract); sb.AppendLine(); return(sb.ToString()); }
public override string GetResultString() { StringBuilder sb = new StringBuilder(); sb.AppendLine(Constants.VERFICATION_RESULT_STRING); if (this.VerificationOutput.VerificationResult == VerificationResultType.VALID) { sb.AppendLine("The Assertion (" + ToString() + ") is VALID."); } else { sb.AppendLine("The Assertion (" + ToString() + ") is NOT valid."); sb.AppendLine("A state reached via the following trace is divergent."); VerificationOutput.GetCounterxampleString(sb); } sb.AppendLine(); sb.AppendLine("********Verification Setting********"); sb.AppendLine("Admissible Behavior: " + SelectedBahaviorName); sb.AppendLine("Search Engine: " + SelectedEngineName); sb.AppendLine("System Abstraction: " + MustAbstract); sb.AppendLine(); return(sb.ToString()); }
private bool StatisticVerificationMinReach(MDPStat mdp, VerificationOutput verificationOutput) { mdp.setNonZeroStates(); var sml = new Simulation(mdp); var pl = new Policy(mdp); var tst = new RunTest(); tst.initRunTest(StatisticalParameters[1], StatisticalParameters[2], StatisticalParameters[3], StatisticalParameters[0]); // string str; return(tst.verifyMDPSPRT(sml, pl, out str)); }
public double MinProbability(VerificationOutput VerificationOutput) { if (TargetStates.Count == 0) { return(0); } if (TargetStates.Contains(InitState)) { return(1); } //return BuildQuotientMDP(VerificationOutput).MinProbabilityWork(); //return BuildQuotientMDPBisimulation(VerificationOutput).MinProbabilityWork(VerificationOutput); return(MinProbabilityWork(VerificationOutput)); }
/// <summary> /// GetResultStringForUnfinishedSearching /// </summary> /// <returns></returns> public override string GetResultStringForUnfinishedSearching(Exception ex) { StringBuilder sb = new StringBuilder(); sb.AppendLine(Constants.VERFICATION_RESULT_STRING); if (ex != null) { sb.AppendLine(Resources.Exception_happened_during_the_verification); string trace = ""; if (ex.Data.Contains("trace")) { trace = Environment.NewLine + "Trace leads to exception:" + Environment.NewLine + ex.Data["trace"].ToString(); } sb.AppendLine(ex.Message + trace); } else { sb.AppendLine("Verification cancelled"); } if (ExtremValue != null) { sb.AppendLine("During the incomplete search:"); sb.AppendLine("The Assertion (" + ToString() + ") is VALID and " + Contraint.ToString().ToLower() + "(" + ConstraintCondition + ") = " + this.ExtremValue + " among " + ReachableCount + " reachable states."); sb.AppendLine("The following trace leads to a state where the condition is satisfied with the above value."); VerificationOutput.GetCounterxampleString(sb); if (SelectedEngineName == Constants.ENGINE_BREADTH_FIRST_SEARCH_MONO) { sb.AppendLine("Warning: the correctness of the verification result requires the value of " + ConstraintCondition + " changes monotonically during the system execution. "); } } sb.AppendLine(); sb.AppendLine("********Verification Setting********"); sb.AppendLine("Admissible Behavior: " + SelectedBahaviorName); sb.AppendLine("Search Engine: " + SelectedEngineName); sb.AppendLine("System Abstraction: " + MustAbstract); sb.AppendLine(); return(sb.ToString()); }
public override string GetResultString() { StringBuilder sb = new StringBuilder(); sb.AppendLine(Constants.VERFICATION_RESULT_STRING); if (VerificationOutput.VerificationResult == VerificationResultType.VALID) { sb.AppendLine("The Assertion (" + ToString() + ") is VALID."); } else if (VerificationOutput.VerificationResult == VerificationResultType.UNKNOWN) { sb.AppendLine("The Assertion (" + ToString() + ") is NEITHER PROVED NOR DISPROVED."); } else { sb.AppendLine("The Assertion (" + ToString() + ") is NOT valid."); if (isNotTerminationTesting) { sb.AppendLine("The following trace leads to a terminating situation."); } else { sb.Append("The following trace leads to a functional decomposition situation."); foreach (String seq in singleInterfaceInvokeSequence) { sb.Append(seq + " -> "); } sb.AppendLine(); } VerificationOutput.GetCounterxampleString(sb); } sb.AppendLine(); sb.AppendLine("********Verification Setting********"); sb.AppendLine("Admissible Behavior: " + SelectedBahaviorName); sb.AppendLine("Search Engine: " + SelectedEngineName); sb.AppendLine("System Abstraction: " + MustAbstract); sb.AppendLine(); return(sb.ToString()); }
public virtual string GetResultStringSafety() { StringBuilder sb = new StringBuilder(); sb.AppendLine(Constants.VERFICATION_RESULT_STRING); if (this.VerificationOutput.VerificationResult == VerificationResultType.VALID) { sb.AppendLine("The Assertion (" + ToString() + ") is VALID."); } else { if (this.VerificationOutput.VerificationResult == VerificationResultType.UNKNOWN) { sb.AppendLine("The Assertion (" + ToString() + ") is NEITHER PROVED NOR DISPROVED."); } else { sb.AppendLine("The Assertion (" + ToString() + ") is NOT valid."); sb.AppendLine("A counterexample is presented as follows."); //GetCounterxampleString(sb); VerificationOutput.GetCounterxampleString(sb); } } sb.AppendLine(); sb.AppendLine("********Verification Setting********"); sb.AppendLine("Admissible Behavior: " + SelectedBahaviorName); if (SelectedEngineName == Constants.ENGINE_DEPTH_FIRST_SEARCH) { sb.AppendLine("Method: Refinement Based Safety Analysis using DFS - The LTL formula is a safety property!"); } else { sb.AppendLine("Method: Refinement Based Safety Analysis using BFS - The LTL formula is a safety property!"); } sb.AppendLine("System Abstraction: " + MustAbstract); sb.AppendLine(); return(sb.ToString()); }
public override string GetResultString() { StringBuilder sb = new StringBuilder(); //original reachability testing sb.AppendLine(Constants.VERFICATION_RESULT_STRING); if (VerificationOutput.VerificationResult == VerificationResultType.VALID) { sb.AppendLine("The Assertion (" + ToString() + ") is VALID and " + Contraint.ToString().ToLower() + "(" + ConstraintCondition + ") = " + this.ExtremValue + " among " + ReachableCount + " reachable states."); sb.AppendLine("The following trace leads to a state where the condition is satisfied with the above value."); VerificationOutput.GetCounterxampleString(sb); } else { if (VerificationOutput.VerificationResult == VerificationResultType.UNKNOWN) { sb.AppendLine("The Assertion (" + ToString() + ") is NEITHER PROVED NOR DISPROVED."); } else { sb.AppendLine("The Assertion is NOT valid."); } } if (SelectedEngineName == Constants.ENGINE_BREADTH_FIRST_SEARCH_MONO) { sb.AppendLine("Warning: the correctness of the verification result requires the value of " + ConstraintCondition + " changes monotonically during the system execution. "); } sb.AppendLine(); sb.AppendLine("********Verification Setting********"); sb.AppendLine("Admissible Behavior: " + SelectedBahaviorName); sb.AppendLine("Search Engine: " + SelectedEngineName); sb.AppendLine("System Abstraction: " + MustAbstract); sb.AppendLine(); return(sb.ToString()); }
public static void TraceInclusionCheck(ConfigurationBase currentImpl, Automata spec, VerificationOutput VerificationOutput) { FAState[] states = spec.States.Values.ToArray(); //bool[] isFinal = new bool[states.Length]; bool[,] fsim = new bool[states.Length, states.Length]; // sim[u][v]=true iff v in sim(u) iff v simulates u //for (int i = 0; i < states.Length; i++) //{ // isFinal[i] = spec.F.Contains(states[i]); //} for (int i = 0; i < states.Length; i++) { for (int j = i; j < states.Length; j++) { fsim[i, j] = states[j].covers(states[i]); //(!isFinal[i] || isFinal[j]) && fsim[j, i] = states[i].covers(states[j]); //(isFinal[i] || !isFinal[j]) && } } Dictionary <string, HashSet <FAState> > rel_spec = FastFSimRelNBW(spec, fsim); StringHashTable Visited = new StringHashTable(Ultility.Ultility.MC_INITIAL_SIZE); List <ConfigurationBase> toReturn = new List <ConfigurationBase>(); Stack <ConfigurationBase> pendingImpl = new Stack <ConfigurationBase>(1024); Stack <NormalizedFAState> pendingSpec = new Stack <NormalizedFAState>(1024); //The following are for identifying a counterexample trace. Stack <int> depthStack = new Stack <int>(1024); depthStack.Push(0); List <int> depthList = new List <int>(1024); //The above are for identifying a counterexample trace. //implementation initial state pendingImpl.Push(currentImpl); //specification initial state NormalizedFAState currentSpec = new NormalizedFAState(spec.InitialState, rel_spec); #if TEST pendingSpec.Push(currentSpec.TauReachable()); #else pendingSpec.Push(currentSpec); #endif while (pendingImpl.Count > 0) { currentImpl = pendingImpl.Pop(); currentSpec = pendingSpec.Pop(); string ID = currentImpl.GetID() + Constants.SEPARATOR + currentSpec.GetID(); if (Visited.ContainsKey(ID)) { continue; } Visited.Add(ID); //The following are for identifying a counterexample trace. int depth = depthStack.Pop(); while (depth > 0 && depthList[depthList.Count - 1] >= depth) { int lastIndex = depthList.Count - 1; depthList.RemoveAt(lastIndex); toReturn.RemoveAt(lastIndex); } toReturn.Add(currentImpl); depthList.Add(depth); //If the specification has no corresponding state, then it implies that the trace is allowed by the //implementation but not the specification -- which means trace-refinement is failed. if (currentSpec.States.Count == 0) { VerificationOutput.NoOfStates = Visited.Count; VerificationOutput.CounterExampleTrace = toReturn; VerificationOutput.VerificationResult = VerificationResultType.INVALID; return; } ConfigurationBase[] nextImpl = currentImpl.MakeOneMove(); VerificationOutput.Transitions += nextImpl.Length; for (int k = 0; k < nextImpl.Length; k++) { ConfigurationBase next = nextImpl[k]; if (next.Event != Constants.TAU) { NormalizedFAState nextSpec = currentSpec.Next(next.Event, rel_spec); pendingImpl.Push(next); pendingSpec.Push(nextSpec); depthStack.Push(depth + 1); } else { pendingImpl.Push(next); pendingSpec.Push(currentSpec); depthStack.Push(depth + 1); } } } VerificationOutput.NoOfStates = Visited.Count; VerificationOutput.VerificationResult = VerificationResultType.VALID; //return null; }
public MDPStat BuildQuotientMDP(VerificationOutput VerificationOutput) { //return this; MDPStat toReturn = new MDPStat(Precision, MAX_DIFFERENCE); //todo change to set List <KeyValuePair <string, string> > BoundaryOneTransition = new List <KeyValuePair <string, string> >(); //todo change to set List <DistributionStat> ProbTransitions = new List <DistributionStat>(); Dictionary <string, List <DistributionStat> > GlobalProbTransitions = new Dictionary <string, List <DistributionStat> >(); StringDictionary <bool> visited = new StringDictionary <bool>(States.Count); List <KeyValuePair <HashSet <string>, MDPStateStat> > sccs = new List <KeyValuePair <HashSet <string>, MDPStateStat> >(); Dictionary <string, int> preorder = new Dictionary <string, int>(); Dictionary <string, int> lowlink = new Dictionary <string, int>(); //HashSet<string> scc_found = new HashSet<string>(); Stack <MDPStateStat> TaskStack = new Stack <MDPStateStat>(); //Dictionary<string, List<string>> OutgoingTransitionTable = new Dictionary<string, List<string>>(); Stack <MDPStateStat> stepStack = new Stack <MDPStateStat>(1024); visited.Add(InitState.ID, false); TaskStack.Push(InitState); //# Preorder counter int preor = 0; do { while (TaskStack.Count > 0) { MDPStateStat pair = TaskStack.Peek(); string v = pair.ID; if (visited.GetContainsKey(v) && visited.GetContainsKey(v)) { TaskStack.Pop(); continue; } if (!preorder.ContainsKey(v)) { preorder.Add(v, preor); preor++; } bool done = true; List <DistributionStat> list = pair.Distributions; List <MDPStateStat> nonProbTrans = new List <MDPStateStat>(); List <DistributionStat> ProbTrans = new List <DistributionStat>(); for (int i = 0; i < list.Count; i++) { if (list[i].IsTrivial()) { nonProbTrans.Add(list[i].States[0].Value); } else { ProbTrans.Add(list[i]); } } if (ProbTrans.Count > 0 && !GlobalProbTransitions.ContainsKey(v)) { GlobalProbTransitions.Add(v, ProbTrans); ProbTransitions.AddRange(ProbTrans); } for (int k = nonProbTrans.Count - 1; k >= 0; k--) { MDPStateStat step = nonProbTrans[k]; string tmp = step.ID; if (visited.ContainsKey(tmp)) { //if this node is still not visited if (!preorder.ContainsKey(tmp)) { //only put the first one to the work list stack. //if there are more than one node to be visited, //simply ignore them and keep its event step in the list. if (done) { TaskStack.Push(step); done = false; } } } else { visited.Add(tmp, false); //OutgoingTransitionTable.Add(tmp, new List<string>(8)); //only put the first one into the stack. if (done) { TaskStack.Push(step); done = false; } } } if (done) { int lowlinkV = preorder[v]; int preorderV = preorder[v]; bool selfLoop = false; for (int j = 0; j < nonProbTrans.Count; j++) { string w = nonProbTrans[j].ID; if (w == v) { selfLoop = true; } if (!visited.GetContainsKey(w)) { if (preorder[w] > preorderV) { lowlinkV = Math.Min(lowlinkV, lowlink[w]); } else { lowlinkV = Math.Min(lowlinkV, preorder[w]); } } else //in this case, there is a tau transition leading to an SCC; must add the transition into the toReturn automaton { BoundaryOneTransition.Add(new KeyValuePair <string, string>(v, w)); } } lowlink[v] = lowlinkV; TaskStack.Pop(); HashSet <string> scc = new HashSet <string>(); if (lowlinkV == preorderV) { scc.Add(v); visited.SetValue(v, true); while (stepStack.Count > 0 && preorder[stepStack.Peek().ID] > preorderV) { string s = stepStack.Pop().ID; scc.Add(s); visited.SetValue(s, true); } MDPStateStat newstate = new MDPStateStat(toReturn.States.Count.ToString()); if (scc.Count > 1 || (scc.Count == 1 && selfLoop)) { newstate.AddDistribution(new DistributionStat(Constants.TAU, newstate)); //add self loop: sun jun } sccs.Add(new KeyValuePair <HashSet <string>, MDPStateStat>(scc, newstate)); toReturn.AddState(newstate); if (scc.Contains(InitState.ID)) { toReturn.SetInit(newstate); } foreach (MDPStateStat state in TargetStates) { if (scc.Contains(state.ID)) { toReturn.AddTargetStates(newstate); } } } else { stepStack.Push(pair); } } } if (ProbTransitions.Count > 0) { foreach (DistributionStat step in ProbTransitions) { foreach (KeyValuePair <double, MDPStateStat> pair in step.States) { string stateID = pair.Value.ID; if (!visited.ContainsKey(stateID)) { TaskStack.Push(pair.Value); visited.Add(stateID, false); } } } ProbTransitions.Clear(); } } while (TaskStack.Count > 0); foreach (KeyValuePair <string, string> pair in BoundaryOneTransition) { MDPStateStat source = null; MDPStateStat target = null; foreach (KeyValuePair <HashSet <string>, MDPStateStat> sccstate in sccs) { if (sccstate.Key.Contains(pair.Key)) { source = sccstate.Value; } if (sccstate.Key.Contains(pair.Value)) { target = sccstate.Value; } } toReturn.AddDistribution(source.ID, new DistributionStat(Constants.TAU, target)); VerificationOutput.ReducedMDPTransitions++; } foreach (KeyValuePair <string, List <DistributionStat> > pair in GlobalProbTransitions) { MDPStateStat source = null; foreach (KeyValuePair <HashSet <string>, MDPStateStat> sccstate in sccs) { if (sccstate.Key.Contains(pair.Key)) { source = sccstate.Value; break; } } foreach (DistributionStat distribution in pair.Value) { DistributionStat disNew = new DistributionStat(distribution.Event); foreach (KeyValuePair <double, MDPStateStat> state in distribution.States) { foreach (KeyValuePair <HashSet <string>, MDPStateStat> sccstate in sccs) { if (sccstate.Key.Contains(state.Value.ID)) { disNew.AddProbStatePair(state.Key, sccstate.Value); VerificationOutput.ReducedMDPTransitions++; break; } } } toReturn.AddDistribution(source.ID, disNew); } } VerificationOutput.ReducedMDPStates = toReturn.States.Count; return(toReturn); }
public MDPStat BuildQuotientMDPBisimulation(VerificationOutput VerificationOutput) { MDPStat toReturn = new MDPStat(Precision, MAX_DIFFERENCE); //calculate the nonsafe states, whose maximal prob is not 0 Stack <MDPStateStat> NonSafe = new Stack <MDPStateStat>(TargetStates); Stack <MDPStateStat> helper = new Stack <MDPStateStat>(TargetStates); //backward checking from target states while (helper.Count != 0) { MDPStateStat t = helper.Pop(); foreach (MDPStateStat s in t.Pre) { bool addState = false; //check each distribution; as long as s has a post state in NonSafe, then s should be added. foreach (DistributionStat distribution in s.Distributions) { foreach (KeyValuePair <double, MDPStateStat> pair in distribution.States) { if (NonSafe.Contains(pair.Value)) { addState = true; //s.Distributions.Remove(distribution); break; } } if (addState) { break; } } if (addState && !NonSafe.Contains(s)) { helper.Push(s); NonSafe.Push(s); } } } //note here remaining doesn't include the target states and initial states HashSet <MDPStateStat> remaining = new HashSet <MDPStateStat>(); foreach (MDPStateStat mdpState in NonSafe) { if (!TargetStates.Contains(mdpState) && InitState != mdpState) { remaining.Add(mdpState); } } //add Initial MDPStateStat Initial = new MDPStateStat(InitState.ID); toReturn.AddState(Initial); toReturn.SetInit(Initial); //add target MDPStateStat Target = new MDPStateStat("target"); toReturn.AddState(Target); toReturn.AddTargetStates(Target); //add safe MDPStateStat Safe = new MDPStateStat("safe"); toReturn.AddState(Safe); //add remaining //MDPStateStat Remaining = new MDPStateStat("remaining"); //toReturn.AddState(Remaining); //add selfloop at Target. //Target.AddDistribution(new DistributionStat(Constants.TAU, Target)); //add selfloop at Safe. //Safe.AddDistribution(new DistributionStat(Constants.TAU, Safe)); //add the group distributions in Remaining List <HashSet <MDPStateStat> > SeperatingRemaining = new List <HashSet <MDPStateStat> >(); SeperatingRemaining.Add(remaining); bool refinement = true; while (refinement) { refinement = false; for (int i = 0; i < SeperatingRemaining.Count; i++) { HashSet <MDPStateStat> mdpStates = SeperatingRemaining[i]; if (mdpStates.Count > 1) { Dictionary <string, HashSet <MDPStateStat> > groups = SeperateGroup(SeperatingRemaining, mdpStates, Initial, Target, Safe); if (groups.Count > 1) { SeperatingRemaining.RemoveAt(i--); foreach (KeyValuePair <string, HashSet <MDPStateStat> > keyValuePair in groups) { SeperatingRemaining.Add(keyValuePair.Value); } refinement = true; } } } //List<HashSet<MDPStateStat>> NewSeperating = new List<HashSet<MDPStateStat>>(); //foreach (HashSet<MDPStateStat> mdpStates in SeperatingRemaining) //{ // if (mdpStates.Count > 1) // { // int counter = 0; // foreach (HashSet<MDPStateStat> grouped in SeperateGroup(SeperatingRemaining, mdpStates, Initial, Target, Safe).Values) // { // counter++; // NewSeperating.Add(grouped); // } // if (counter > 1) // { // refinement = true; // } // } // else // { // NewSeperating.Add(mdpStates); // } // } ////todo: reduce the loop number //SeperatingRemaining = NewSeperating; } //add distributions after all the refinement foreach (HashSet <MDPStateStat> mdpStates in SeperatingRemaining) { MDPStateStat Grouped = StateFromHashset(mdpStates); //MDPStateStat Grouped = mdpStates[0]; toReturn.AddState(new MDPStateStat(Grouped.ID)); //FinalgroupedDistribution(SeperatingRemaining, mdpStates, Target, Safe, toReturn); } foreach (HashSet <MDPStateStat> mdpStates in SeperatingRemaining) { FinalgroupedDistribution(SeperatingRemaining, mdpStates, Target, Safe, toReturn); } //note: add initial state's distributions after refinement FinalgroupedDistribution(SeperatingRemaining, InitState, Target, Safe, toReturn); return(toReturn); }
public double MinProbabilityWork(VerificationOutput VerificationOutput) { ////calculate the nonsafe states, whose minimal prob is not 0 //Stack<MDPStateStat> NonSafe = new Stack<MDPStateStat>(TargetStates); //Stack<MDPStateStat> helper = new Stack<MDPStateStat>(TargetStates); ////backward checking from target states //while (helper.Count != 0) //{ // MDPStateStat t = helper.Pop(); // foreach (MDPStateStat s in t.Pre) // { // bool addState = true; // foreach (DistributionStat distribution in s.Distributions) // { // bool keepDistr = false; // //check each distribution; if states in s.distribution are not included in NonSafe, then s should not be added. // foreach (KeyValuePair<double, MDPStateStat> pair in distribution.States) // { // if (NonSafe.Contains(pair.Value)) // { // keepDistr = true; // //s.Distributions.Remove(distribution); // break; // } // } // if (!keepDistr) // { // addState = false; // break; // } // } // if (addState && !NonSafe.Contains(s))//add a state to NonSafe // { // helper.Push(s); // NonSafe.Push(s); // } // } //} //HashSet<MDPStateStat> nonSafe = new HashSet<MDPStateStat>(NonSafe); HashSet <MDPStateStat> working = new HashSet <MDPStateStat>(TargetStates); double maxDifference = 1; while (maxDifference > MAX_DIFFERENCE) { VerificationOutput.MDPIterationNumber++; maxDifference = 0; //get the nodes which should be re-calculated. HashSet <MDPStateStat> newWorking = new HashSet <MDPStateStat>(); foreach (MDPStateStat state in working) { foreach (MDPStateStat mdpState in state.Pre) { //if (nonSafe.Contains(mdpState)) //note changed here //{ newWorking.Add(mdpState); //} } } List <MDPStateStat> toRemove = new List <MDPStateStat>(); foreach (MDPStateStat node in newWorking) { double newMin = 1; foreach (DistributionStat distribution in node.Distributions) { double result = 0; bool hasNewValues = false; foreach (KeyValuePair <double, MDPStateStat> pair in distribution.States) { result += pair.Value.CurrentProb * pair.Key; hasNewValues = true; } if (hasNewValues) { newMin = Math.Min(newMin, result); } } if (node.CurrentProb < newMin) { maxDifference = Math.Max(maxDifference, (newMin - node.CurrentProb) / node.CurrentProb);///relative difference node.CurrentProb = newMin; } else { toRemove.Add(node); } } foreach (MDPStateStat i in toRemove) { newWorking.Remove(i); } working = newWorking; } return(Ultility.Ultility.RoundProbWithPrecision(InitState.CurrentProb, Precision)); }