/// <summary> /// Initializes a new instance. /// </summary> /// <param name="results">The result of the safety analysis the order analysis should be conducted for.</param> /// <param name="configuration">The model checker's configuration that determines certain model checker settings.</param> public OrderAnalysis(SafetyAnalysisResults <TExecutableModel> results, AnalysisConfiguration configuration) { Requires.NotNull(results, nameof(results)); _results = results; _backend.InitializeModel(configuration, results.RuntimeModelCreator, results.Hazard); }
/// <summary> /// Initializes a new instance. /// </summary> internal OrderAnalysisResults(SafetyAnalysisResults <TExecutableModel> safetyAnalysisResults, TimeSpan time, IDictionary <ISet <Fault>, IEnumerable <OrderRelationship <TExecutableModel> > > orderRelationships) { SafetyAnalysisResults = safetyAnalysisResults; Time = time; OrderRelationships = orderRelationships; }
/// <summary> /// Returns a string representation of the minimal critical fault sets. /// </summary> public override string ToString() { var builder = new StringBuilder(); builder.AppendLine(SafetyAnalysisResults.ToString()); builder.AppendLine(); builder.AppendLine("======================================================================="); builder.AppendLine("======= Fault Activation Order Analysis: Results ======="); builder.AppendLine("======================================================================="); builder.AppendLine(); builder.AppendLine($"Elapsed Time: {Time}"); builder.AppendLine($"Order Relationship Count: {OrderRelationships.Values.SelectMany(r => r).Count()}"); builder.AppendLine(); foreach (var pair in OrderRelationships) { var relationships = pair.Value.ToArray(); builder.AppendLine($"{{ {String.Join(", ", pair.Key.Select(f => f.Name))} }}"); if (relationships.Length == 0) { builder.AppendLine(" no order relationships exist"); } else { var i = 1; foreach (var relationship in pair.Value) { builder.AppendLine($" ({i}) {relationship}"); ++i; } } } return(builder.ToString()); }
/// <summary> /// Computes the minimal critical sets for the <paramref name="hazard" />. /// </summary> /// <param name="createModel">The creator for the model that should be checked.</param> /// <param name="hazard">The hazard the minimal critical sets should be computed for.</param> /// <param name="maxCardinality"> /// The maximum cardinality of the fault sets that should be checked. By default, all minimal /// critical fault sets are determined. /// </param> public SafetyAnalysisResults <TExecutableModel> ComputeMinimalCriticalSets(CoupledExecutableModelCreator <TExecutableModel> createModel, Formula hazard, int maxCardinality = Int32.MaxValue) { Requires.NotNull(createModel, nameof(createModel)); Requires.NotNull(hazard, nameof(hazard)); ConsoleHelpers.WriteLine("Running Deductive Cause Consequence Analysis."); var heuristicWatch = new Stopwatch(); var stopwatch = new Stopwatch(); stopwatch.Start(); var allFaults = createModel.FaultsInBaseModel; FaultSet.CheckFaultCount(allFaults.Length); var forcedFaults = allFaults.Where(fault => fault.Activation == Activation.Forced).ToArray(); var suppressedFaults = allFaults.Where(fault => fault.Activation == Activation.Suppressed).ToArray(); var nondeterministicFaults = allFaults.Where(fault => fault.Activation == Activation.Nondeterministic).ToArray(); var nonSuppressedFaults = allFaults.Where(fault => fault.Activation != Activation.Suppressed).ToArray(); ConsoleHelpers.WriteLine(); ConsoleHelpers.WriteLine($"Of the {allFaults.Length} faults contained in the model,"); ConsoleHelpers.WriteLine($" {suppressedFaults.Length} faults are suppressed,"); ConsoleHelpers.WriteLine($" {forcedFaults.Length} faults are forced, and"); ConsoleHelpers.WriteLine($" {nondeterministicFaults.Length} faults are nondeterministically activated."); ConsoleHelpers.WriteLine(); _suppressedSet = new FaultSet(suppressedFaults); _forcedSet = new FaultSet(forcedFaults); var isComplete = true; // Remove information from previous analyses Reset(createModel.FaultsInBaseModel); // Initialize the backend, the model, and the analysis results switch (Backend) { case SafetyAnalysisBackend.FaultOptimizedOnTheFly: _backend = new FaultOptimizationBackend <TExecutableModel>(); break; case SafetyAnalysisBackend.FaultOptimizedStateGraph: _backend = new StateGraphBackend <TExecutableModel>(); break; default: throw new ArgumentOutOfRangeException(); } _backend.Output = Output; _backend.InitializeModel(Configuration, createModel, hazard); _results = new SafetyAnalysisResults <TExecutableModel>(createModel, hazard, suppressedFaults, forcedFaults, Heuristics, FaultActivationBehavior); // Remember all safe sets of current cardinality - we need them to generate the next power set level var currentSafe = new HashSet <FaultSet>(); // We check fault sets by increasing cardinality; this is, we check the empty set first, then // all singleton sets, then all sets with two elements, etc. We don't check sets that we // know are going to be critical sets due to monotonicity for (var cardinality = 0; cardinality <= nonSuppressedFaults.Length; ++cardinality) { // Generate the sets for the current level that we'll have to check var sets = GeneratePowerSetLevel(cardinality, nonSuppressedFaults, currentSafe); currentSafe.Clear(); // Remove all sets that conflict with the forced or suppressed faults; these sets are considered to be safe. // If no sets remain, skip to the next level sets = RemoveInvalidSets(sets, currentSafe); if (sets.Count == 0) { continue; } // Abort if we've exceeded the maximum fault set cardinality; doing the check here allows us // to report the analysis as complete if the maximum cardinality is never reached if (cardinality > maxCardinality) { isComplete = false; break; } if (cardinality == 0) { ConsoleHelpers.WriteLine("Checking the empty fault set..."); } else { ConsoleHelpers.WriteLine($"Checking {sets.Count} sets of cardinality {cardinality}..."); } // use heuristics var setsToCheck = new LinkedList <FaultSet>(sets); foreach (var heuristic in Heuristics) { var count = setsToCheck.Count; heuristicWatch.Restart(); heuristic.Augment((uint)cardinality, setsToCheck); count = setsToCheck.Count - count; if (count > 0) { ConsoleHelpers.WriteLine($" {heuristic.GetType().Name} made {count} suggestions in {heuristicWatch.Elapsed.TotalMilliseconds}ms."); } } // We have to check each set - heuristics may add further during the loop while (setsToCheck.Count > 0) { var set = setsToCheck.First.Value; var isCurrentLevel = sets.Remove(set); // returns true if set was actually contained setsToCheck.RemoveFirst(); // for current level, we already know the set is valid var isValid = isCurrentLevel || IsValid(set); // the set is invalid if it exceeds the maximum cardinality level isValid &= set.Cardinality <= maxCardinality; var isSafe = true; if (isValid) { isSafe = CheckSet(set, allFaults, !isCurrentLevel); } if (isSafe && isCurrentLevel) { currentSafe.Add(set); } // inform heuristics about result and give them the opportunity to add further sets foreach (var heuristic in Heuristics) { heuristic.Update(setsToCheck, set, isSafe); } if (StopOnFirstException && _exceptions.Count > 0) { goto returnResult; } } // in case heuristics removed a set (they shouldn't) foreach (var set in sets) { var isSafe = CheckSet(set, allFaults, false); if (isSafe) { currentSafe.Add(set); } if (StopOnFirstException && _exceptions.Count > 0) { goto returnResult; } } } returnResult: // Reset the nondeterministic faults so as to not influence subsequent analyses foreach (var fault in nondeterministicFaults) { fault.Activation = Activation.Nondeterministic; } // due to heuristics usage, we may have informatiuon on non-minimal critical sets var minimalCritical = RemoveNonMinimalCriticalSets(); _results.IsComplete = isComplete; _results.Time = stopwatch.Elapsed; _results.SetResult(minimalCritical, _checkedSetCount, _checkedSets, _counterExamples, _exceptions); return(_results); }
/// <summary> /// Computes the order relationships for all minimal critical fault sets contained in the /// <paramref name="safetyAnalysisResults" />. /// </summary> /// <param name="safetyAnalysisResults">The results of the safety analysis the order relationships should be computed for.</param> /// <param name="configuration">The configuration settings of the model checker that should be used.</param> public static OrderAnalysisResults <TExecutableModel> ComputeOrderRelationships(SafetyAnalysisResults <TExecutableModel> safetyAnalysisResults, AnalysisConfiguration configuration) { var analysis = new OrderAnalysis <TExecutableModel>(safetyAnalysisResults, configuration); return(analysis.ComputeOrderRelationships()); }
/// <summary> /// Computes the order relationships for all minimal critical fault sets contained in the /// <paramref name="safetyAnalysisResults" />. /// </summary> /// <param name="safetyAnalysisResults">The results of the safety analysis the order relationships should be computed for.</param> public static OrderAnalysisResults <TExecutableModel> ComputeOrderRelationships(SafetyAnalysisResults <TExecutableModel> safetyAnalysisResults) { return(ComputeOrderRelationships(safetyAnalysisResults, AnalysisConfiguration.Default)); }