Exemplo n.º 1
0
        /// <summary>
        ///   Initializes a new instance.
        /// </summary>
        /// <param name="runtimeModelCreator">A factory function that creates the model instance that should be executed.</param>
        /// <param name="formulas">The formulas that should be evaluated for each state.</param>
        /// <param name="configuration">The analysis configuration that should be used.</param>
        /// <param name="stateHeaderBytes">
        ///   The number of bytes that should be reserved at the beginning of each state vector for the model checker tool.
        /// </param>
        internal ActivationMinimalExecutedModel(CoupledExecutableModelCreator <TExecutableModel> runtimeModelCreator, int stateHeaderBytes, Func <bool>[] formulas, AnalysisConfiguration configuration)
            : base(runtimeModelCreator, stateHeaderBytes, configuration)
        {
            formulas = formulas ?? RuntimeModel.Formulas.Select(formula => FormulaCompilationVisitor <TExecutableModel> .Compile(RuntimeModel, formula)).ToArray();

            _transitions      = new ActivationMinimalTransitionSetBuilder <TExecutableModel>(TemporaryStateStorage, configuration.SuccessorCapacity, formulas);
            _stateConstraints = RuntimeModel.StateConstraints;

            bool useForwardOptimization;

            switch (configuration.MomentOfIndependentFaultActivation)
            {
            case MomentOfIndependentFaultActivation.AtStepBeginning:
            case MomentOfIndependentFaultActivation.OnFirstMethodWithoutUndo:
                useForwardOptimization = false;
                break;

            case MomentOfIndependentFaultActivation.OnFirstMethodWithUndo:
                useForwardOptimization = true;
                break;

            default:
                throw new ArgumentOutOfRangeException();
            }

            ChoiceResolver = new NondeterministicChoiceResolver(useForwardOptimization);
            FaultSet.CheckFaultCount(RuntimeModel.Faults.Length);

            RuntimeModel.SetChoiceResolver(ChoiceResolver);

            _allowFaultsOnInitialTransitions = configuration.AllowFaultsOnInitialTransitions;
        }
Exemplo n.º 2
0
        /// <summary>
        ///   Initializes a new instance.
        /// </summary>
        /// <param name="runtimeModelCreator">A factory function that creates the model instance that should be executed.</param>
        /// <param name="formulas">The formulas that should be evaluated for each state.</param>
        /// <param name="configuration">The analysis configuration that should be used.</param>
        /// <param name="stateHeaderBytes">
        ///   The number of bytes that should be reserved at the beginning of each state vector for the model checker tool.
        /// </param>
        internal ActivationMinimalExecutedModel(CoupledExecutableModelCreator <TExecutableModel> runtimeModelCreator, int stateHeaderBytes, Func <bool>[] formulas, AnalysisConfiguration configuration)
            : base(runtimeModelCreator, stateHeaderBytes, configuration)
        {
            formulas = formulas ?? RuntimeModel.Formulas.Select(formula => FormulaCompilationVisitor <TExecutableModel> .Compile(RuntimeModel, formula)).ToArray();

            _transitions      = new ActivationMinimalTransitionSetBuilder <TExecutableModel>(TemporaryStateStorage, configuration.SuccessorCapacity, formulas);
            _stateConstraints = RuntimeModel.StateConstraints;

            var useForwardOptimization = configuration.EnableStaticPruningOptimization;

            ChoiceResolver = new NondeterministicChoiceResolver(useForwardOptimization);
            FaultSet.CheckFaultCount(RuntimeModel.Faults.Length);

            RuntimeModel.SetChoiceResolver(ChoiceResolver);

            _allowFaultsOnInitialTransitions = configuration.AllowFaultsOnInitialTransitions;
        }
Exemplo n.º 3
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));
        }
Exemplo n.º 4
0
        /// <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);
        }
 protected void CheckConsistencyAfterInitialization()
 {
     FaultSet.CheckFaultCount(Faults.Length);
     StateFormulaSet.CheckFormulaCount(AtomarPropositionFormulas.Length);
 }