/// <summary> /// Creates a <see cref="RuntimeModel" /> instance from the model and the <paramref name="formulas" />. /// </summary> /// <param name="formulas">The formulas the model should be able to check.</param> internal RuntimeModel ToRuntimeModel(params Formula[] formulas) { Requires.NotNull(formulas, nameof(formulas)); var serializer = new RuntimeModelSerializer(); serializer.Serialize(this, formulas); return(serializer.Load()); }
/// <summary> /// Initizializes the model that should be analyzed. /// </summary> /// <param name="configuration">The configuration that should be used for the analyses.</param> /// <param name="hazard">The hazard that should be analyzed.</param> protected override void InitializeModel(AnalysisConfiguration configuration, Formula hazard) { var serializer = new RuntimeModelSerializer(); serializer.Serialize(Model, !hazard); Func<AnalysisModel> createModel = () => new ActivationMinimalExecutedModel(CreateModel(hazard), configuration.SuccessorCapacity); _invariantChecker = new InvariantChecker(createModel, OnOutputWritten, configuration, formulaIndex: 0); }
/// <summary> /// Checks whether the <paramref name="invariant" /> holds in all states of the <paramref name="model" />. /// </summary> /// <param name="model">The model that should be checked.</param> /// <param name="invariant">The invariant that should be checked.</param> public AnalysisResult CheckInvariant(ModelBase model, Formula invariant) { Requires.NotNull(model, nameof(model)); Requires.NotNull(invariant, nameof(invariant)); var serializer = new RuntimeModelSerializer(); serializer.Serialize(model, invariant); return(CheckInvariant(serializer.Load)); }
/// <summary> /// Gets a function that initializes the runtime model. /// </summary> private Func<RuntimeModel> CreateModel(Formula hazard) { var serializer = new RuntimeModelSerializer(); serializer.Serialize(Model, !hazard); return () => { var serializedData = serializer.LoadSerializedData(); return new RuntimeModel(serializedData, _stateHeaderBytes); }; }
protected void GenerateStateSpace(params IComponent[] components) { var serializer = new RuntimeModelSerializer(); serializer.Serialize(TestModel.InitializeModel(components), new StateFormula(() => true)); var configuration = AnalysisConfiguration.Default; configuration.StateCapacity = 10000; configuration.StackCapacity = 10000; configuration.CpuCount = 1; var checker = new InvariantChecker(serializer.Load, s => Output.Log("{0}", s), configuration); _result = checker.Check(); CounterExample.ShouldBe(null); Output.Log($"States: {_result.StateCount}"); Output.Log($"Actual Transitions: {_result.TransitionCount}"); Output.Log($"Computed Transitions: {_result.ComputedTransitionCount}"); }
public static CoupledExecutableModelCreator <SafetySharpRuntimeModel> CreateExecutedModelCreator(ModelBase model, params Formula[] formulasToCheckInBaseModel) { Requires.NotNull(model, nameof(model)); Requires.NotNull(formulasToCheckInBaseModel, nameof(formulasToCheckInBaseModel)); Func <int, SafetySharpRuntimeModel> creatorFunc; // serializer.Serialize has potentially a side effect: Model binding. The model gets bound when it isn't // bound already. The lock ensures that this binding is only made by one thread because model.EnsureIsBound // is not reentrant. lock (model) { var serializer = new RuntimeModelSerializer(); model.EnsureIsBound(); // Bind the model explicitly. Otherwise serialize.Serializer makes it implicitly. serializer.Serialize(model, formulasToCheckInBaseModel); creatorFunc = serializer.Load; } var faults = model.Faults; return(new CoupledExecutableModelCreator <SafetySharpRuntimeModel>(creatorFunc, model, formulasToCheckInBaseModel, faults)); }
/// <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 Result ComputeMinimalCriticalSets(ModelBase model, Formula hazard, int maxCardinality = Int32.MaxValue) { Requires.NotNull(model, nameof(model)); Requires.NotNull(hazard, nameof(hazard)); _modelChecker.Configuration = Configuration; ConsoleHelpers.WriteLine("Running Deductive Cause Consequence Analysis."); 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 suppressedSet = new FaultSet(suppressedFaults); var forcedSet = new FaultSet(forcedFaults); var isComplete = true; var safeSets = new HashSet <FaultSet>(); var criticalSets = new HashSet <FaultSet>(); var checkedSets = new HashSet <FaultSet>(); var counterExamples = new Dictionary <FaultSet, CounterExample>(); var exceptions = new Dictionary <FaultSet, Exception>(); // Store the serialized model to improve performance var serializer = new RuntimeModelSerializer(); serializer.Serialize(model, !hazard); // 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 <= allFaults.Length; ++cardinality) { // Generate the sets for the current level that we'll have to check var sets = GeneratePowerSetLevel(safeSets, criticalSets, cardinality, allFaults); // Clear the safe sets, we don't need the previous level to generate the next one safeSets.Clear(); // If there are no sets to check, we're done; this happens when there are so many critical sets // that this level does not contain any set that is not a super set of any of those critical sets if (sets.Count == 0) { break; } // 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, suppressedSet, forcedSet, safeSets); 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}..."); } // We have to check each set; if one of them is a critical set, it has no effect on the other // sets we have to check foreach (var set in sets) { // Enable or disable the faults that the set represents set.SetActivation(nondeterministicFaults); // If there was a counter example, the set is a critical set try { var result = _modelChecker.CheckInvariant(CreateRuntimeModel(serializer, allFaults)); if (!result.FormulaHolds) { ConsoleHelpers.WriteLine($" critical: {{ {set.ToString(allFaults)} }}", ConsoleColor.DarkRed); criticalSets.Add(set); } else { safeSets.Add(set); } checkedSets.Add(set); if (result.CounterExample != null) { counterExamples.Add(set, result.CounterExample); } } catch (AnalysisException e) { ConsoleHelpers.WriteLine($" critical: {{ {set.ToString(allFaults)} }} [exception thrown]", ConsoleColor.DarkRed); checkedSets.Add(set); criticalSets.Add(set); exceptions.Add(set, e.InnerException); if (e.CounterExample != null) { counterExamples.Add(set, e.CounterExample); } } } } // Reset the nondeterministic faults so as to not influence subsequent analyses foreach (var fault in nondeterministicFaults) { fault.Activation = Activation.Nondeterministic; } return(new Result( model, isComplete, criticalSets, checkedSets, allFaults, suppressedFaults, forcedFaults, counterExamples, exceptions, stopwatch.Elapsed)); }
/// <summary> /// Creates a <see cref="RuntimeModel" /> instance from the <paramref name="model" /> and the <paramref name="formulas" />. /// </summary> /// <param name="model">The model the runtime model should be created for.</param> /// <param name="formulas">The formulas the model should be able to check.</param> internal static RuntimeModel Create(ModelBase model, params Formula[] formulas) { Requires.NotNull(formulas, nameof(formulas)); var serializer = new RuntimeModelSerializer(); serializer.Serialize(model, formulas); return serializer.Load(); }
/// <summary> /// Generates a <see cref="StateGraph" /> for the <paramref name="model" />. /// </summary> /// <param name="model">The model the state graph should be generated for.</param> /// <param name="stateFormulas">The state formulas that should be evaluated during state graph generation.</param> internal StateGraph GenerateStateGraph(ModelBase model, params Formula[] stateFormulas) { Requires.NotNull(model, nameof(model)); Requires.NotNull(stateFormulas, nameof(stateFormulas)); var serializer = new RuntimeModelSerializer(); serializer.Serialize(model, stateFormulas); return GenerateStateGraph((Func<RuntimeModel>)serializer.Load, stateFormulas); }
/// <summary> /// Checks whether the <paramref name="invariant" /> holds in all states of the <paramref name="model" />. /// </summary> /// <param name="model">The model that should be checked.</param> /// <param name="invariant">The invariant that should be checked.</param> public AnalysisResult CheckInvariant(ModelBase model, Formula invariant) { Requires.NotNull(model, nameof(model)); Requires.NotNull(invariant, nameof(invariant)); var serializer = new RuntimeModelSerializer(); serializer.Serialize(model, invariant); return CheckInvariant((Func<RuntimeModel>)serializer.Load, formulaIndex: 0); }