/// <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> internal OrderAnalysis(SafetyAnalysisResults results, AnalysisConfiguration configuration) { Requires.NotNull(results, nameof(results)); _results = results; _backend.InitializeModel(configuration, results.Model, results.Hazard); }
/// <summary> /// Initializes a new instance. /// </summary> internal OrderAnalysisResults(SafetyAnalysisResults safetyAnalysisResults, TimeSpan time, IDictionary<ISet<Fault>, IEnumerable<OrderRelationship>> orderRelationships) { SafetyAnalysisResults = safetyAnalysisResults; Time = time; OrderRelationships = orderRelationships; }
/// <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 ComputeOrderRelationships(SafetyAnalysisResults safetyAnalysisResults, AnalysisConfiguration configuration) { var analysis = new OrderAnalysis(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 ComputeOrderRelationships(SafetyAnalysisResults safetyAnalysisResults) { return ComputeOrderRelationships(safetyAnalysisResults, AnalysisConfiguration.Default); }
/// <summary> /// Computes the minimal critical sets for the <paramref name="hazard" />. /// </summary> /// <param name="model">The model the safety analysis should be conducted for.</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 ComputeMinimalCriticalSets(ModelBase model, Formula hazard, int maxCardinality = Int32.MaxValue) { Requires.NotNull(model, nameof(model)); Requires.NotNull(hazard, nameof(hazard)); ConsoleHelpers.WriteLine("Running Deductive Cause Consequence Analysis."); var heuristicWatch = new Stopwatch(); var stopwatch = new Stopwatch(); stopwatch.Start(); var allFaults = model.Faults; 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(model); // Initialize the backend, the model, and the analysis results switch (Backend) { case SafetyAnalysisBackend.FaultOptimizedOnTheFly: _backend = new FaultOptimizationBackend(); break; case SafetyAnalysisBackend.FaultOptimizedStateGraph: _backend = new StateGraphBackend(); break; default: throw new ArgumentOutOfRangeException(); } _backend.OutputWritten += output => OutputWritten?.Invoke(output); _backend.InitializeModel(Configuration, model, hazard); _results = new SafetyAnalysisResults(model, 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); } // 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); } } // 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, _checkedSets, _counterExamples, _exceptions); return _results; }