public IntcodeResult Run() { while (_memory[_index] != HaltCode) { var op = _memory[_index]; var(opCode, parameterModes) = ParseOperation(op); if (validInstructions.TryGetValue(opCode, out var instruction)) { if (opCode == OpCodes.Read && Input.Count == 0) { return(IntcodeResult.HALT_FORINPUT); } var @params = GetParameters(instruction.Parameters, parameterModes); instruction.RunInstruction(@params, this); if (opCode == OpCodes.Write) { OutputWritten?.Invoke(this, EventArgs.Empty); } } else { throw new InvalidOperationException($"Invalid op code: {opCode}"); } } if (Output.Count == 0) { Output.Enqueue(_memory[0]); } return(IntcodeResult.HALT_TERMINATE); }
/// <summary> /// Creates a new <see cref="_ltsMin" /> process instance that checks the <paramref name="modelFile" />. /// </summary> /// <param name="modelFile">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 void CreateProcess(string modelFile, string checkArgument) { Requires.That(_ltsMin == null, "An instance of LtsMin is already running."); var loaderAssembly = Path.Combine(Environment.CurrentDirectory, "SafetySharp.LtsMin.dll"); _ltsMin = new ExternalProcess( fileName: "pins2lts-seq.exe", commandLineArguments: $"--loader=\"{loaderAssembly}\" \"{modelFile}\" {checkArgument}", outputCallback: output => OutputWritten?.Invoke(output)) { WorkingDirectory = Environment.CurrentDirectory }; }
/// <summary> /// Runs the <see cref="_ltsMin" /> process instance. /// </summary> private void Run() { var stopwatch = new Stopwatch(); stopwatch.Start(); _ltsMin.Run(); stopwatch.Stop(); OutputWritten?.Invoke(String.Empty); OutputWritten?.Invoke("====================================="); OutputWritten?.Invoke($"Elapsed time: {stopwatch.Elapsed}"); OutputWritten?.Invoke("====================================="); OutputWritten?.Invoke(String.Empty); }
/// <summary> /// Checks the invariant encoded into the model created by <paramref name="createModel" />. /// </summary> internal AnalysisResult CheckInvariant(Func <RuntimeModel> createModel) { Requires.That(IntPtr.Size == 8, "Model checking is only supported in 64bit processes."); var stopwatch = new Stopwatch(); stopwatch.Start(); using (var checker = new InvariantChecker(createModel, message => OutputWritten?.Invoke(message), Configuration)) { var result = default(AnalysisResult); var initializationTime = stopwatch.Elapsed; stopwatch.Restart(); try { result = checker.Check(); return(result); } finally { stopwatch.Stop(); if (!Configuration.ProgressReportsOnly) { OutputWritten?.Invoke(String.Empty); OutputWritten?.Invoke("==============================================="); OutputWritten?.Invoke($"Initialization time: {initializationTime}"); OutputWritten?.Invoke($"Model checking time: {stopwatch.Elapsed}"); OutputWritten?.Invoke($"{(int)(result.StateCount / stopwatch.Elapsed.TotalSeconds):n0} states per second"); OutputWritten?.Invoke($"{(int)(result.TransitionCount / stopwatch.Elapsed.TotalSeconds):n0} transitions per second"); OutputWritten?.Invoke("==============================================="); OutputWritten?.Invoke(String.Empty); } } } }
/// <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.OutputWritten += output => OutputWritten?.Invoke(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> /// Raises the <see cref="OutputWritten" /> for the generated <paramref name="output" />. /// </summary> /// <param name="output">The output the event should be raised for.</param> protected void OnOutputWritten(string output) { OutputWritten?.Invoke(output); }