Example #1
0
        /// <summary>
        ///   Checks whether the <paramref name="formula" /> holds in all states of the <paramref name="model" />.
        /// </summary>
        /// <param name="createModel">The creator for the model that should be checked.</param>
        /// <param name="checkArgument">The argument passed to LtsMin that indicates which kind of check to perform.</param>
        private AnalysisResult <SafetySharpRuntimeModel> Check(CoupledExecutableModelCreator <SafetySharpRuntimeModel> createModel, string checkArgument)
        {
            try
            {
                using (var modelFile = new TemporaryFile("ssharp"))
                {
                    File.WriteAllBytes(modelFile.FilePath, RuntimeModelSerializer.Save((ModelBase)createModel.SourceModel, createModel.StateFormulasToCheckInBaseModel));

                    try
                    {
                        CreateProcess(modelFile.FilePath, checkArgument);
                        Run();
                    }
                    catch (Win32Exception e)
                    {
                        throw new InvalidOperationException(
                                  "Failed to start LTSMin. Ensure that pins2lts-seq.exe can be found by either copying it next " +
                                  "to the executing assembly or by adding it to the system path. The required cygwin dependencies " +
                                  $"must also be available. The original error message was: {e.Message}", e);
                    }

                    var success = InterpretExitCode(_ltsMin.ExitCode);
                    return(new AnalysisResult <SafetySharpRuntimeModel> {
                        FormulaHolds = success
                    });
                }
            }
            finally
            {
                _ltsMin = null;
            }
        }
Example #2
0
        /// <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);
		}
Example #4
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);
			};
		}
Example #6
0
        /// <summary>
        ///   Creates a <see cref="RuntimeModel" /> instance.
        /// </summary>
        private static Func <RuntimeModel> CreateRuntimeModel(RuntimeModelSerializer serializer, Fault[] faultTemplates)
        {
            return(() =>
            {
                var serializedData = serializer.LoadSerializedData();
                var faults = serializedData.ObjectTable.OfType <Fault>().Where(f => f.Identifier >= 0).OrderBy(f => f.Identifier).ToArray();
                Requires.That(faults.Length == faultTemplates.Length, "Unexpected fault count.");

                for (var i = 0; i < faults.Length; ++i)
                {
                    Requires.That(faults[i].Identifier == faultTemplates[i].Identifier, "Fault mismatch.");
                    faults[i].Activation = faultTemplates[i].Activation;
                }

                return new RuntimeModel(serializedData);
            });
        }
Example #7
0
        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}");
        }
Example #8
0
        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));
        }
Example #9
0
        /// <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));
        }
Example #10
0
		/// <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();
		}
Example #11
0
		/// <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);
		}
Example #12
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((Func<RuntimeModel>)serializer.Load, formulaIndex: 0);
		}
Example #13
0
        /// <summary>
        ///   Loads a counter example from the <paramref name="file" />.
        /// </summary>
        /// <param name="file">The path to the file the counter example should be loaded from.</param>
        public static CounterExample Load(string file)
        {
            Requires.NotNullOrWhitespace(file, nameof(file));

            using (var reader = new BinaryReader(File.OpenRead(file), Encoding.UTF8))
            {
                if (reader.ReadInt32() != FileHeader)
                {
                    throw new InvalidOperationException("The file does not contain a counter example that is compatible with this version of S#.");
                }

                var endsWithException      = reader.ReadBoolean();
                var serializedRuntimeModel = reader.ReadBytes(reader.ReadInt32());
                var modelData = RuntimeModelSerializer.LoadSerializedData(serializedRuntimeModel);

                foreach (var fault in modelData.ObjectTable.OfType <Fault>())
                {
                    fault.Activation = (Activation)reader.ReadInt32();
                }

                var runtimeModel   = new RuntimeModel(modelData);
                var metadataStream = new MemoryStream(reader.ReadBytes(reader.ReadInt32()));
                var formatter      = new BinaryFormatter();
                var slotMetadata   = new StateVectorLayout((StateSlotMetadata[])formatter.Deserialize(metadataStream));
                var modelMetadata  = runtimeModel.StateVectorLayout;

                var counterExample = new byte[reader.ReadInt32()][];
                var slotCount      = reader.ReadInt32();

                if (slotCount != runtimeModel.StateVectorSize)
                {
                    throw new InvalidOperationException(
                              $"State slot count mismatch; the instantiated model requires {runtimeModel.StateVectorSize} state slots, " +
                              $"whereas the counter example uses {slotCount} state slots.");
                }

                if (slotMetadata.SlotCount != modelMetadata.SlotCount)
                {
                    throw new InvalidOperationException(
                              $"State slot metadata count mismatch; the instantiated model has {modelMetadata.SlotCount} state slot metadata entries, " +
                              $"whereas the counter example has {slotMetadata.SlotCount} state slot entries.");
                }

                for (var i = 0; i < slotMetadata.SlotCount; ++i)
                {
                    if (modelMetadata[i] != slotMetadata[i])
                    {
                        throw new StateVectorMismatchException(slotMetadata, modelMetadata);
                    }
                }

                for (var i = 0; i < counterExample.Length; ++i)
                {
                    counterExample[i] = new byte[runtimeModel.StateVectorSize];
                    for (var j = 0; j < runtimeModel.StateVectorSize; ++j)
                    {
                        counterExample[i][j] = reader.ReadByte();
                    }
                }

                var replayInfo = new int[reader.ReadInt32()][];
                for (var i = 0; i < replayInfo.Length; ++i)
                {
                    replayInfo[i] = new int[reader.ReadInt32()];
                    for (var j = 0; j < replayInfo[i].Length; ++j)
                    {
                        replayInfo[i][j] = reader.ReadInt32();
                    }
                }

                return(new CounterExample(runtimeModel, counterExample, replayInfo, endsWithException));
            }
        }