/// <summary> /// Removes all invalid sets from <paramref name="sets" /> that conflict with either <paramref name="suppressedFaults" /> or /// <paramref name="forcedFaults" />. /// </summary> private static HashSet <FaultSet> RemoveInvalidSets(HashSet <FaultSet> sets, FaultSet suppressedFaults, FaultSet forcedFaults, HashSet <FaultSet> safeSets) { var validSets = new HashSet <FaultSet>(); foreach (var set in sets) { // The set must contain all forced faults, hence it must be a superset of those if (!forcedFaults.IsSubsetOf(set)) { safeSets.Add(set); continue; } // The set is not allowed to contain any suppressed faults, hence the intersection must be empty if (!suppressedFaults.GetIntersection(set).IsEmpty) { safeSets.Add(set); continue; } validSets.Add(set); } return(validSets); }
private void AddTransition(byte *stateToAdd, StateFormulaSet formulas, FaultSet activatedFaults, double probability) { if (_consolidateOnTheFly) { AddTransitionConsolidate(stateToAdd, formulas, activatedFaults, probability); } else { if (_count >= _capacity) { throw new OutOfMemoryException("Unable to store an additional transition. Try increasing the successor state capacity."); } var successorState = _temporalStateStorage.GetFreeTemporalSpaceAddress(); MemoryBuffer.Copy(stateToAdd, successorState, _temporalStateStorage.StateVectorSize); _transitions[_count] = new LtmcTransition { TargetStatePointer = successorState, Formulas = formulas, //ActivatedFaults = activatedFaults, Flags = TransitionFlags.IsValidFlag, Probability = probability }; ++_count; } }
/// <summary> /// Adds a transition to the <paramref name="model" />'s current state. /// </summary> /// <param name="model">The model the transition should be added for.</param> /// <param name="continuationId">The id of the transition.</param> public void Add(ExecutableModel <TExecutableModel> model, int continuationId) { if (_transitionsWithContinuationIdCount >= _capacity) { throw new OutOfMemoryException("Unable to store an additional transition. Try increasing the successor state capacity."); } // 1. Notify all fault activations, so that the correct activation is set in the run time model // (Needed to persist persistent faults) model.NotifyFaultActivations(); // 2. Serialize the model's computed state; that is the successor state of the transition's source state // _including_ any changes resulting from notifications of fault activations var successorState = _targetStateMemory + _stateVectorSize * _transitionsWithContinuationIdCount; model.Serialize(successorState); // 3. Store the transition var activatedFaults = FaultSet.FromActivatedFaults(model.NondeterministicFaults); var positionOfTransition = _transitionsWithContinuationIdCount; _transitionsWithContinuationIdMemory[positionOfTransition] = new LtmdpTransition { TargetStatePointer = successorState, Formulas = new StateFormulaSet(_formulas), ActivatedFaults = activatedFaults, Flags = TransitionFlags.IsValidFlag, Index = positionOfTransition }; ++_transitionsWithContinuationIdCount; LtmdpStepGraph.SetTargetOfFinalOrUnsplitChoice(continuationId, positionOfTransition); }
/// <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; }
void IFaultSetHeuristic.Update(LinkedList<FaultSet> setsToCheck, FaultSet checkedSet, bool isSafe) { if (!_subsumedSets.Contains(checkedSet)) return; _successCounter += isSafe ? 1 : -1; if (_successCounter != 0) return; // if the subsumed sets are critical more often than they are not, // check the "normal" sets first. for (var node = setsToCheck.First; node != null; node = node.Next) { var set = node.Value; if (_subsumedSets.Contains(set)) { if (isSafe && node.Previous != null) // move subsumed set before set SwitchValues(node, node.Previous); else if (!isSafe && node.Next != null) // move subsumed set after set { SwitchValues(node, node.Next); node = node.Next; // skip iteration for node.Next } } } }
/// <summary> /// Adds the <paramref name="successorState" /> to the transition set if neccessary, reached using the /// <paramref name="activatedFaults" />. /// </summary> /// <param name="successorState">The successor state that should be added.</param> /// <param name="activatedFaults">The faults activated by the transition to reach the state.</param> private bool Add(byte *successorState, FaultSet activatedFaults) { var hash = MemoryBuffer.Hash(successorState, _stateVectorSize, 0); for (var i = 1; i < ProbeThreshold; ++i) { var stateHash = MemoryBuffer.Hash((byte *)&hash, sizeof(int), i * 8345723) % _capacity; var faultIndex = _lookup[stateHash]; // If we don't know the state yet, set everything up and add the transition if (faultIndex == -1) { _successors.Add((uint)stateHash); AddFaultMetadata(stateHash, -1); MemoryBuffer.Copy(successorState, _hashedStateMemory + stateHash * _stateVectorSize, _stateVectorSize); return(true); } // If there is a hash conflict, try again if (!MemoryBuffer.AreEqual(successorState, _hashedStateMemory + stateHash * _stateVectorSize, _stateVectorSize)) { continue; } // The transition has an already-known target state; it might have to be added or invalidate previously found transitions return(UpdateTransitions(stateHash, activatedFaults, faultIndex)); } throw new OutOfMemoryException( "Failed to find an empty hash table slot within a reasonable amount of time. Try increasing the successor state capacity."); }
void IFaultSetHeuristic.Update(LinkedList <FaultSet> setsToCheck, FaultSet checkedSet, bool isSafe) { if (!_subsumedSets.Contains(checkedSet)) { return; } _successCounter += isSafe ? 1 : -1; if (_successCounter != 0) { return; } // if the subsumed sets are critical more often than they are not, // check the "normal" sets first. for (var node = setsToCheck.First; node != null; node = node.Next) { var set = node.Value; if (_subsumedSets.Contains(set)) { if (isSafe && node.Previous != null) // move subsumed set before set { SwitchValues(node, node.Previous); } else if (!isSafe && node.Next != null) // move subsumed set after set { SwitchValues(node, node.Next); node = node.Next; // skip iteration for node.Next } } } }
/// <summary> /// Gets the activation order relationships that exist for the faults contained in /// <paramref name="minimalCriticalFaultSet" />, if any. /// </summary> /// <param name="minimalCriticalFaultSet">The minimal critical fault set the order should be returned for.</param> private IEnumerable <OrderRelationship <TExecutableModel> > GetOrderRelationships(ISet <Fault> minimalCriticalFaultSet) { var checkedSet = new FaultSet(minimalCriticalFaultSet); var activation = _results.FaultActivationBehavior == FaultActivationBehavior.ForceOnly ? Activation.Forced : Activation.Nondeterministic; var checkedFaults = minimalCriticalFaultSet.ToArray(); // Create all pairs of faults contained in minimalCriticalFaultSet such that // we don't get pairs (f,f) and we don't generate duplicate pairs (f1,f2) and (f2,f1) for (var i = 0; i < checkedFaults.Length; ++i) { for (var j = i + 1; j < checkedFaults.Length; ++j) { var fault1 = checkedFaults[i]; var fault2 = checkedFaults[j]; // Check if one can be activated strictly before the other var fault1BeforeFault2 = _backend.CheckOrder(fault1, fault2, checkedSet, activation, forceSimultaneous: false); var fault2BeforeFault1 = _backend.CheckOrder(fault2, fault1, checkedSet, activation, forceSimultaneous: false); // If both can be activated stritly before the other, there is no ordering if (!fault2BeforeFault1.FormulaHolds && !fault1BeforeFault2.FormulaHolds) { continue; } // Check for simultaneous activations var simultaneous = _backend.CheckOrder(fault1, fault2, checkedSet, activation, forceSimultaneous: true); // f1 == f2 if (!simultaneous.FormulaHolds && fault1BeforeFault2.FormulaHolds && fault2BeforeFault1.FormulaHolds) { yield return(new OrderRelationship <TExecutableModel>(simultaneous, fault1, fault2, OrderRelationshipKind.Simultaneously)); } // f1 <= f2 else if (!fault1BeforeFault2.FormulaHolds && !simultaneous.FormulaHolds) { yield return(new OrderRelationship <TExecutableModel>(simultaneous, fault1, fault2, OrderRelationshipKind.Precedes)); } // f1 < f2 else if (!fault1BeforeFault2.FormulaHolds && simultaneous.FormulaHolds) { yield return(new OrderRelationship <TExecutableModel>(simultaneous, fault1, fault2, OrderRelationshipKind.StrictlyPrecedes)); } // f2 <= f1 else if (!fault2BeforeFault1.FormulaHolds && !simultaneous.FormulaHolds) { yield return(new OrderRelationship <TExecutableModel>(simultaneous, fault2, fault1, OrderRelationshipKind.Precedes)); } // f2 < f1 else if (!fault2BeforeFault1.FormulaHolds && simultaneous.FormulaHolds) { yield return(new OrderRelationship <TExecutableModel>(simultaneous, fault2, fault1, OrderRelationshipKind.StrictlyPrecedes)); } } } }
/// <summary> /// Classifies how the transition set must be updated. /// </summary> private void ClassifyActivatedFaults(FaultSet activatedFaults, int faultIndex, out bool addTransition, out bool addFaults, out bool cleanupTransitions) { addFaults = false; cleanupTransitions = false; // Basic invariant of the fault list: it contains only sets of activation-minimal faults while (faultIndex != -1) { var faultSet = &_faults[faultIndex]; faultIndex = faultSet->NextSet; // If the fault set is a subset of the activated faults, the current transition is not activation-minimal; // we can therefore safely ignore the transition; due to the list invariant, none of the remaining // fault sets in the list can be a superset of the activated faults because then the current fault set // would also be a subset of that other fault set, violating the invariant if (faultSet->Transition->ActivatedFaults.IsSubsetOf(activatedFaults)) { addTransition = faultSet->Transition->ActivatedFaults == activatedFaults; return; } // If at least one of the previously added transitions that we assumed to be activation-minimal is // in fact not activation-minimal, we have to clean up the transition set if (activatedFaults.IsSubsetOf(faultSet->Transition->ActivatedFaults)) { cleanupTransitions = true; } } // If we get here, we must add the faults and the transition addTransition = true; addFaults = true; }
void IFaultSetHeuristic.Update(LinkedList <FaultSet> setsToCheck, FaultSet checkedSet, bool isSafe) { var isSuggestion = _currentSuggestions.Remove(checkedSet); if (!isSuggestion) { return; } // subsets of a safe set are safe - do not check them again if (isSafe) { _successCounter++; _nextSuggestions.ExceptWith(GetSubsets(new[] { checkedSet })); } else { _successCounter--; } var tolerance = _allFaults.Length / 4; if (_currentSuggestions.Count == 0 && checkedSet.Cardinality > _minSetSize) { if (_successCounter < -tolerance && isSafe) { _subsetStepSize++; _successCounter = 0; } _currentSuggestions = _nextSuggestions; _nextSuggestions = GetSubsets(_currentSuggestions); } }
/// <summary> /// Updates the activation modes of the faults contained in the model. /// </summary> private void ChangeFaultActivations(FaultSet faults, Activation activation) { foreach (var model in _invariantChecker.AnalyzedModels.Cast <ExecutedModel <TExecutableModel> >()) { model.ChangeFaultActivations(GetUpdateFaultActivations(faults, activation)); } }
/// <summary> /// Adds a transition to the <paramref name="model" />'s current state. /// </summary> /// <param name="model">The model the transition should be added for.</param> /// <param name="probability">The probability of the transition.</param> public void Add(ExecutableModel <TExecutableModel> model, double probability) { if (_count >= _capacity) { throw new OutOfMemoryException("Unable to store an additional transition. Try increasing the successor state capacity."); } // 1. Notify all fault activations, so that the correct activation is set in the run time model // (Needed to persist persistent faults) model.NotifyFaultActivations(); // 2. Serialize the model's computed state; that is the successor state of the transition's source state // _including_ any changes resulting from notifications of fault activations var successorState = _targetStateMemory + _stateVectorSize * _count; model.Serialize(successorState); // 3. Store the transition var activatedFaults = FaultSet.FromActivatedFaults(model.NondeterministicFaults); _transitions[_count] = new LtmcTransition { TargetStatePointer = successorState, Formulas = new StateFormulaSet(_formulas), ActivatedFaults = activatedFaults, Flags = TransitionFlags.IsValidFlag, Probability = probability }; ++_count; }
public void Update(LinkedList<FaultSet> setsToCheck, FaultSet checkedSet, bool isSafe) { if (updated) return; setsToCheck.AddFirst(new FaultSet(C.F2)); updated = true; }
/// <summary> /// Initizializes the model that should be analyzed. /// </summary> /// <param name="configuration">The configuration that should be used for the analyses.</param> /// <param name="model">The model that should be analyzed.</param> /// <param name="hazard">The hazard that should be analyzed.</param> internal void InitializeModel(AnalysisConfiguration configuration, ModelBase model, Formula hazard) { Model = model; ForcedFaults = new FaultSet(Model.Faults.Where(fault => fault.Activation == Activation.Forced)); SuppressedFaults = new FaultSet(Model.Faults.Where(fault => fault.Activation == Activation.Suppressed)); InitializeModel(configuration, hazard); }
/// <summary> /// Initializes a new instance. /// </summary> /// <param name="model">The model the heuristic is created for.</param> /// <param name="cardinalityLevel">The cardinality level where the first suggestions should be made.</param> public MaximalSafeSetHeuristic(ModelBase model, uint cardinalityLevel = 3) { Requires.NotNull(model, nameof(model)); _model = model; _cardinalityLevel = cardinalityLevel; _allFaults = new FaultSet(model.Faults.Where(fault => fault.Activation != Activation.Suppressed).ToArray()); }
/// <summary> /// Initizializes the model that should be analyzed. /// </summary> /// <param name="configuration">The configuration that should be used for the analyses.</param> /// <param name="createFreshModel">The creator for the model that should be checked.</param> /// <param name="hazard">The hazard that should be analyzed.</param> internal void InitializeModel(AnalysisConfiguration configuration, CoupledExecutableModelCreator <TExecutableModel> createFreshModel, Formula hazard) { RuntimeModelCreator = createFreshModel; ForcedFaults = new FaultSet(createFreshModel.FaultsInBaseModel.Where(fault => fault.Activation == Activation.Forced)); SuppressedFaults = new FaultSet(createFreshModel.FaultsInBaseModel.Where(fault => fault.Activation == Activation.Suppressed)); InitializeModel(configuration, hazard); }
/// <summary> /// Finds all subsets of <paramref name="set" /> with the given <paramref name="size" />. /// </summary> private List <FaultSet> GetSubsets(FaultSet set, int size) { var subset = new Fault[size]; var results = new List <FaultSet>(); GetSubsets(set, subset, 0, 0, results); return(results); }
/// <summary> /// Initializes a new instance. /// </summary> /// <param name="modelFaults">All faults in the model the heuristic is created for.</param> /// <param name="cardinalityLevel">The cardinality level where the first suggestions should be made.</param> public MaximalSafeSetHeuristic(Fault[] modelFaults, uint cardinalityLevel = 3) { Requires.NotNull(modelFaults, nameof(modelFaults)); _modelFaults = modelFaults; _cardinalityLevel = cardinalityLevel; _allFaults = new FaultSet(modelFaults.Where(fault => fault.Activation != Activation.Suppressed).ToArray()); }
private bool CheckSet(FaultSet set, Fault[] allFaults, bool isHeuristicSuggestion, Activation activationMode) { try { var result = _backend.CheckCriticality(set, activationMode); if (Configuration.CollectFaultSets) { if (!result.FormulaHolds) { if (!isHeuristicSuggestion) { ConsoleHelpers.WriteLine($" critical: {{ {set.ToString(allFaults)} }}", ConsoleColor.DarkRed); } _criticalSets.Add(set); } else if (isHeuristicSuggestion) { ConsoleHelpers.WriteLine($" safe: {{ {set.ToString(allFaults)} }} [heuristic]", ConsoleColor.Blue); } _checkedSets.Add(set); } _checkedSetCount++; if (result.CounterExample != null) { var executableCounterExample = new ExecutableCounterExample <TExecutableModel>(_backend.RuntimeModelCreator.Create(0), result.CounterExample); _counterExamples.Add(set, executableCounterExample); } return(result.FormulaHolds); } catch (AnalysisException e) { var heuristic = isHeuristicSuggestion ? " [heuristic]" : string.Empty; ConsoleHelpers.WriteLine($" critical: {{ {set.ToString(allFaults)} }} {heuristic} [exception thrown]", ConsoleColor.DarkRed); Console.WriteLine(e.InnerException); if (Configuration.CollectFaultSets) { _checkedSets.Add(set); } _checkedSetCount++; _criticalSets.Add(set); _exceptions.Add(set, e.InnerException); if (e.CounterExample != null) { var executableCounterExample = new ExecutableCounterExample <TExecutableModel>(_backend.RuntimeModelCreator.Create(0), e.CounterExample); _counterExamples.Add(set, executableCounterExample); } return(false); } }
public void Update(LinkedList <FaultSet> setsToCheck, FaultSet checkedSet, bool isSafe) { if (updated) { return; } setsToCheck.AddFirst(new FaultSet(C.F2)); updated = true; }
private ISet <FaultSet> GetSubsets(IEnumerable <FaultSet> sets) { return(new HashSet <FaultSet>( from set in sets // get a subset of size subsetStepSize from subset in GetSubsets(set, _subsetStepSize) // remove all faults in the subset and their subsuming faults let suggestion = set.GetDifference(FaultSet.SubsumingFaults(subset, _allFaults)) select suggestion )); }
/// <summary> /// Informs the heuristic of the result of analyzing <paramref name="checkedSet" /> /// and allows it to adapt the sets to check next. /// </summary> public void Update(LinkedList <FaultSet> setsToCheck, FaultSet checkedSet, bool isSafe) { // Ignore critical sets we've suggested ourself as these are likely not minimal and // would degrade the quality of our suggestions if (isSafe || _suggestedSets.Contains(checkedSet)) { return; } _hasNewMinimalCriticalSets = true; _minimalCriticalSets.Add(checkedSet.ToFaultSequence(_modelFaults).ToArray()); }
/// <summary> /// Initializes a new instance. /// </summary> /// <param name="model">The model the heuristic is created for.</param> /// <param name="minimalCriticalFaultSets">The minimal critical fault sets known from a previous analysis.</param> public MaximalSafeSetHeuristic(ModelBase model, ISet<ISet<Fault>> minimalCriticalFaultSets) { Requires.NotNull(model, nameof(model)); Requires.NotNull(minimalCriticalFaultSets, nameof(minimalCriticalFaultSets)); _model = model; _hasNewMinimalCriticalSets = true; _allFaults = new FaultSet(model.Faults.Where(fault => fault.Activation != Activation.Suppressed).ToArray()); foreach (var set in minimalCriticalFaultSets) _minimalCriticalSets.Add(set.Select(MapFault).ToArray()); }
void IFaultSetHeuristic.Augment(uint cardinalityLevel, LinkedList <FaultSet> setsToCheck) { // for each set, check the set of subsumed faults first for (var node = setsToCheck.First; node != null; node = node.Next) { var subsumed = FaultSet.SubsumedFaults(node.Value, _allFaults); if (!node.Value.Equals(subsumed) && !_subsumedSets.Contains(subsumed)) { setsToCheck.AddBefore(node, subsumed); _subsumedSets.Add(subsumed); } } }
private void CollectSuggestions(IEnumerable <IEnumerable <Fault> > faultGroups) { var faults = new FaultSet(_allFaults); _currentSuggestions = new HashSet <FaultSet>( // one fault of each group is not activated (try all combinations) from excludedFaults in CartesianProduct(faultGroups) // also exclude subsuming faults let subsuming = FaultSet.SubsumingFaults(excludedFaults, _allFaults) orderby subsuming.Cardinality ascending select faults.GetDifference(subsuming) ); }
/// <summary> /// Checks the <see cref="faults" /> for criticality using the <see cref="activation" /> mode. /// </summary> /// <param name="faults">The fault set that should be checked for criticality.</param> /// <param name="activation">The activation mode of the fault set.</param> internal override AnalysisResult CheckCriticality(FaultSet faults, Activation activation) { var suppressedFaults = new FaultSet(); foreach (var fault in Model.Faults) { if (GetEffectiveActivation(fault, faults, activation) == Activation.Suppressed) suppressedFaults = suppressedFaults.Add(fault); } _checker.Context.TraversalParameters.TransitionModifiers.Clear(); _checker.Context.TraversalParameters.TransitionModifiers.Add(() => new FaultSuppressionModifier(suppressedFaults)); return _checker.Check(); }
/// <summary> /// Converts the integer-based set to a set faults. /// </summary> private ISet <Fault> Convert(Dictionary <FaultSet, ISet <Fault> > knownSets, FaultSet set) { ISet <Fault> faultSet; if (knownSets.TryGetValue(set, out faultSet)) { return(faultSet); } faultSet = new HashSet <Fault>(set.ToFaultSequence(RuntimeModelCreator.FaultsInBaseModel)); knownSets.Add(set, faultSet); return(faultSet); }
/// <summary> /// Initializes a new instance. /// </summary> /// <param name="modelFaults">All faults in the model the heuristic is created for.</param> /// <param name="minimalCriticalFaultSets">The minimal critical fault sets known from a previous analysis.</param> public MaximalSafeSetHeuristic(Fault[] modelFaults, ISet <ISet <Fault> > minimalCriticalFaultSets) { Requires.NotNull(modelFaults, nameof(modelFaults)); Requires.NotNull(minimalCriticalFaultSets, nameof(minimalCriticalFaultSets)); _modelFaults = modelFaults; _hasNewMinimalCriticalSets = true; _allFaults = new FaultSet(modelFaults.Where(fault => fault.Activation != Activation.Suppressed).ToArray()); foreach (var set in minimalCriticalFaultSets) { _minimalCriticalSets.Add(set.Select(MapFault).ToArray()); } }
/// <summary> /// Adds a transition to the <paramref name="successorState" /> to the set. /// </summary> /// <param name="successorState">The successor state of the transition that should be added.</param> /// <param name="activatedFaults">The faults activated by the transition that should be added.</param> /// <param name="formulas">The formulas holding in the successor state of the transition that should be added.</param> public void Add(byte* successorState, FaultSet activatedFaults, StateFormulaSet formulas) { var targetState = _targetStateMemory + _count * _stateVectorSize; MemoryBuffer.Copy(successorState, targetState, _stateVectorSize); _transitions[_count] = new CandidateTransition { TargetState = targetState, Formulas = formulas, ActivatedFaults = activatedFaults, IsValid = true, }; ++_count; }
internal void CreateTransition(bool[] isFormulaSatisfied, byte *targetState, double p) { var transition = _transitionCount; _transitionCount++; _transitions[transition] = new LtmcTransition { Probability = p }; var t = _transitions + transition; t->TargetStatePointer = targetState; t->Formulas = new StateFormulaSet(isFormulaSatisfied); t->Flags = TransitionFlags.IsValidFlag | TransitionFlags.IsStateTransformedToIndexFlag; t->ActivatedFaults = new FaultSet(); }
private void CreateTransition(bool isFormulaSatisfied, int targetStateIndex, int continuationId, double p) { var transition = _transitionCount; _transitionCount++; _transitions[transition] = new LtmdpTransition { Probability = p, ContinuationId = continuationId }; var t = (Transition *)(_transitions + transition); t->SourceStateIndex = 0; t->TargetStateIndex = targetStateIndex; t->Formulas = new StateFormulaSet(new Func <bool>[] { () => isFormulaSatisfied }); t->Flags = TransitionFlags.IsValidFlag | TransitionFlags.IsStateTransformedToIndexFlag; t->ActivatedFaults = new FaultSet(); }
private FaultSet CollectSubsumedFaultsTransitive() { IEnumerable <Fault> currentFaults = new[] { this }; var subsumed = new FaultSet(this); uint oldCount; do // fixed-point iteration { oldCount = subsumed.Cardinality; currentFaults = currentFaults.SelectMany(fault => fault.SubsumedFaults); subsumed = subsumed.GetUnion(new FaultSet(currentFaults)); } while (oldCount < subsumed.Cardinality); return(subsumed); }
/// <summary> /// Adds a transition to the <paramref name="successorState" /> to the set. /// </summary> /// <param name="successorState">The successor state of the transition that should be added.</param> /// <param name="activatedFaults">The faults activated by the transition that should be added.</param> /// <param name="formulas">The formulas holding in the successor state of the transition that should be added.</param> public void Add(byte *successorState, FaultSet activatedFaults, StateFormulaSet formulas) { var targetState = _targetStateMemory + _count * _stateVectorSize; MemoryBuffer.Copy(successorState, targetState, _stateVectorSize); _transitions[_count] = new CandidateTransition { TargetStatePointer = targetState, Formulas = formulas, ActivatedFaults = activatedFaults, Flags = TransitionFlags.IsValidFlag, }; ++_count; }
/// <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; }
/// <summary> /// Checks the <see cref="faults" /> for criticality using the <see cref="activation" /> mode. /// </summary> /// <param name="faults">The fault set that should be checked for criticality.</param> /// <param name="activation">The activation mode of the fault set.</param> internal override InvariantAnalysisResult CheckCriticality(FaultSet faults, Activation activation) { var suppressedFaults = new FaultSet(); foreach (var fault in RuntimeModelCreator.FaultsInBaseModel) { if (GetEffectiveActivation(fault, faults, activation) == Activation.Suppressed) { suppressedFaults = suppressedFaults.Add(fault); } } _checker.ModelTraverser.Context.TraversalParameters.TransitionModifiers.Clear(); _checker.ModelTraverser.Context.TraversalParameters.TransitionModifiers.Add(() => new FaultSuppressionModifier(suppressedFaults)); return(_checker.Check()); }
/// <summary> /// Helper function for recursively finding subsets. /// </summary> private void GetSubsets(FaultSet set, Fault[] subset, int index, int minFaultIndex, List <FaultSet> results) { if (index == subset.Length) { results.Add(new FaultSet(subset)); return; } for (var i = minFaultIndex; i < _allFaults.Length - subset.Length + index; ++i) { if (set.Contains(_allFaults[i])) { subset[index] = _allFaults[i]; GetSubsets(set, subset, index + 1, i + 1, results); } } }
internal void CreateTransition(bool[] isFormulaSatisfied, int targetStateIndex, int continuationId) { var transition = _transitionCount; _transitionCount++; _transitions[transition] = new LtmdpTransition { Index = transition }; var t = (Transition *)(_transitions + transition); t->SourceStateIndex = 0; t->TargetStateIndex = targetStateIndex; t->Formulas = new StateFormulaSet(isFormulaSatisfied); t->Flags = TransitionFlags.IsValidFlag | TransitionFlags.IsStateTransformedToIndexFlag; t->ActivatedFaults = new FaultSet(); StepGraph.SetTargetOfFinalOrUnsplitChoice(continuationId, transition); }
private bool CheckSet(FaultSet set, Fault[] allFaults, bool isHeuristicSuggestion, Activation activationMode) { try { var result = _backend.CheckCriticality(set, activationMode); if (!result.FormulaHolds) { if (!isHeuristicSuggestion) ConsoleHelpers.WriteLine($" critical: {{ {set.ToString(allFaults)} }}", ConsoleColor.DarkRed); _criticalSets.Add(set); } else if (isHeuristicSuggestion) { ConsoleHelpers.WriteLine($" safe: {{ {set.ToString(allFaults)} }} [heuristic]", ConsoleColor.Blue); } _checkedSets.Add(set); if (result.CounterExample != null) _counterExamples.Add(set, result.CounterExample); return result.FormulaHolds; } catch (AnalysisException e) { var heuristic = isHeuristicSuggestion ? " [heuristic]" : string.Empty; ConsoleHelpers.WriteLine($" critical: {{ {set.ToString(allFaults)} }} {heuristic} [exception thrown]", ConsoleColor.DarkRed); Console.WriteLine(e.InnerException); _checkedSets.Add(set); _criticalSets.Add(set); _exceptions.Add(set, e.InnerException); if (e.CounterExample != null) _counterExamples.Add(set, e.CounterExample); return false; } }
public void Update(LinkedList<FaultSet> setsToCheck, FaultSet checkedSet, bool isSafe) { setCounter++; }
/// <summary> /// Converts the integer-based set to a set faults. /// </summary> private ISet<Fault> Convert(Dictionary<FaultSet, ISet<Fault>> knownSets, FaultSet set) { ISet<Fault> faultSet; if (knownSets.TryGetValue(set, out faultSet)) return faultSet; faultSet = new HashSet<Fault>(set.ToFaultSequence(Model.Faults)); knownSets.Add(set, faultSet); return faultSet; }
/// <summary> /// Initializes a new instance. /// </summary> /// <param name="suppressedFaults">The suppressed faults that are removed by the modifier.</param> public FaultSuppressionModifier(FaultSet suppressedFaults) { _suppressedFaults = suppressedFaults; }
private bool IsTriviallySafe(FaultSet faultSet) { return _safeSets.ContainsSupersetOf(faultSet); }
private bool IsTriviallyCritical(FaultSet faultSet) { return _criticalSets.ContainsSubsetOf(faultSet); }
private bool CheckSet(FaultSet set, Fault[] allFaults, bool isHeuristicSuggestion) { if (isHeuristicSuggestion) _results.HeuristicSuggestionCount++; var isSafe = true; // check if set is trivially safe or critical // (do not add to safeSets / criticalSets if so, in order to keep them small) if (IsTriviallySafe(set)) { _results.TrivialChecksCount++; if (isHeuristicSuggestion) _results.HeuristicTrivialCount++; // do not add to safeSets: all subsets are subsets of safeSet as well return true; } // trivially critical sets are not generated in GeneratePowerSetLevel, thus only check if set suggested by heuristic if (isHeuristicSuggestion && IsTriviallyCritical(set)) { _results.TrivialChecksCount++; _results.HeuristicTrivialCount++; // do not add to criticalSets: non-minimal, and all supersets are supersets of criticalSet as well return false; } // if configured to do so, check with forced fault activation if (FaultActivationBehavior == FaultActivationBehavior.ForceOnly || FaultActivationBehavior == FaultActivationBehavior.ForceThenFallback) isSafe = CheckSet(set, allFaults, isHeuristicSuggestion, Activation.Forced); if (isSafe && FaultActivationBehavior == FaultActivationBehavior.ForceThenFallback) ConsoleHelpers.WriteLine(" Checking again with nondeterministic activation..."); // check with nondeterministic fault activation if (isSafe && FaultActivationBehavior != FaultActivationBehavior.ForceOnly) isSafe = CheckSet(set, allFaults, isHeuristicSuggestion, Activation.Nondeterministic); if (isSafe) // remember non-trivially safe sets to avoid checking their subsets { _safeSets.Add(set); if (isHeuristicSuggestion) _results.HeuristicNonTrivialSafeCount++; } return isSafe; }
/// <summary> /// Generates a level of the power set. /// </summary> /// <param name="cardinality">The cardinality of the sets that should be generated.</param> /// <param name="faults">The fault set the power set is generated for.</param> /// <param name="previousSafe">The set of safe sets generated at the previous level.</param> private HashSet<FaultSet> GeneratePowerSetLevel(int cardinality, Fault[] faults, HashSet<FaultSet> previousSafe) { var result = new HashSet<FaultSet>(); switch (cardinality) { case 0: // There is only the empty set with a cardinality of 0 result.Add(new FaultSet()); break; case 1: // We have to kick things off by explicitly generating the singleton sets; at this point, // we know that there are no further minimal critical sets if the empty set is already critical. if (previousSafe.Count > 0) { foreach (var fault in faults) { var set = new FaultSet(fault); if (!_criticalSets.Contains(set)) result.Add(set); } } break; default: // We now generate the sets with the requested cardinality based on the sets from the previous level // which had a cardinality that is one less than the sets we're going to generate now. The basic // idea is that we create the union between all safe sets and all singleton sets and discard // the ones we don't want, while avoiding duplicate generation of sets. var setsToRemove = new HashSet<FaultSet>(); for (var i = 0; i < faults.Length; ++i) { var fault = faults[i]; setsToRemove.Clear(); foreach (var safeSet in previousSafe) { // avoid duplicate set generation if (safeSet.Contains(fault)) { setsToRemove.Add(safeSet); continue; } var set = safeSet.Add(fault); // set is trivially critical iff one of the direct subsets is not safe (i.e. critical) // * the faults faults[0], ..., faults[i-1] are not definitely not contained in set (see above) // * faults[i] is definitely in set, but set.Remove(faults[i]) == safeSet and is thus safe. var isTriviallyCritical = _criticalSets.Contains(set); for (var j = i + 1; j < faults.Length && !isTriviallyCritical; ++j) { var f = faults[j]; if (set.Contains(f) && !previousSafe.Contains(set.Remove(f))) isTriviallyCritical = true; } // Check if the newly generated set is a super set of any critical sets; // if so, discard it if (!isTriviallyCritical) result.Add(set); } // all supersets of sets in setsToRemove have either // been previously generated or are critical previousSafe.ExceptWith(setsToRemove); // if no more sets in previousSafe, further iterations are pointless if (previousSafe.Count == 0) break; } break; } return result; }
/// <summary> /// Gets the activation order relationships that exist for the faults contained in /// <paramref name="minimalCriticalFaultSet" />, if any. /// </summary> /// <param name="minimalCriticalFaultSet">The minimal critical fault set the order should be returned for.</param> private IEnumerable<OrderRelationship> GetOrderRelationships(ISet<Fault> minimalCriticalFaultSet) { var checkedSet = new FaultSet(minimalCriticalFaultSet); var activation = _results.FaultActivationBehavior == FaultActivationBehavior.ForceOnly ? Activation.Forced : Activation.Nondeterministic; var checkedFaults = minimalCriticalFaultSet.ToArray(); // Create all pairs of faults contained in minimalCriticalFaultSet such that // we don't get pairs (f,f) and we don't generate duplicate pairs (f1,f2) and (f2,f1) for (var i = 0; i < checkedFaults.Length; ++i) { for (var j = i + 1; j < checkedFaults.Length; ++j) { var fault1 = checkedFaults[i]; var fault2 = checkedFaults[j]; // Check if one can be activated strictly before the other var fault1BeforeFault2 = _backend.CheckOrder(fault1, fault2, checkedSet, activation, forceSimultaneous: false); var fault2BeforeFault1 = _backend.CheckOrder(fault2, fault1, checkedSet, activation, forceSimultaneous: false); // If both can be activated stritly before the other, there is no ordering if (!fault2BeforeFault1.FormulaHolds && !fault1BeforeFault2.FormulaHolds) continue; // Check for simultaneous activations var simultaneous = _backend.CheckOrder(fault1, fault2, checkedSet, activation, forceSimultaneous: true); // f1 == f2 if (!simultaneous.FormulaHolds && fault1BeforeFault2.FormulaHolds && fault2BeforeFault1.FormulaHolds) yield return new OrderRelationship(simultaneous, fault1, fault2, OrderRelationshipKind.Simultaneously); // f1 <= f2 else if (!fault1BeforeFault2.FormulaHolds && !simultaneous.FormulaHolds) yield return new OrderRelationship(simultaneous, fault1, fault2, OrderRelationshipKind.Precedes); // f1 < f2 else if (!fault1BeforeFault2.FormulaHolds && simultaneous.FormulaHolds) yield return new OrderRelationship(simultaneous, fault1, fault2, OrderRelationshipKind.StrictlyPrecedes); // f2 <= f1 else if (!fault2BeforeFault1.FormulaHolds && !simultaneous.FormulaHolds) yield return new OrderRelationship(simultaneous, fault2, fault1, OrderRelationshipKind.Precedes); // f2 < f1 else if (!fault2BeforeFault1.FormulaHolds && simultaneous.FormulaHolds) yield return new OrderRelationship(simultaneous, fault2, fault1, OrderRelationshipKind.StrictlyPrecedes); } } }
/// <summary> /// Gets all combinations of fault sets that have one fault of each minimal critical fault set removed. /// </summary> private IEnumerable<FaultSet> RemoveAllFaults(FaultSet removed, int setIndex) { if (setIndex >= _minimalCriticalSets.Count) yield return removed; else { foreach (var fault in _minimalCriticalSets[setIndex].Where(f => f.Activation != Activation.Forced)) { var next = removed.Contains(fault) ? removed : removed.Add(fault); foreach (var set in RemoveAllFaults(next, setIndex + 1)) yield return set; } } }
/// <summary> /// Informs the heuristic of the result of analyzing <paramref name="checkedSet" /> /// and allows it to adapt the sets to check next. /// </summary> public void Update(LinkedList<FaultSet> setsToCheck, FaultSet checkedSet, bool isSafe) { // Ignore critical sets we've suggested ourself as these are likely not minimal and // would degrade the quality of our suggestions if (isSafe || _suggestedSets.Contains(checkedSet)) return; _hasNewMinimalCriticalSets = true; _minimalCriticalSets.Add(checkedSet.ToFaultSequence(_model.Faults).ToArray()); }
/// <summary> /// Checks the order of <see cref="firstFault" /> and <see cref="secondFault" /> for the /// <see cref="minimalCriticalFaultSet" /> using the <see cref="activation" /> mode. /// </summary> /// <param name="firstFault">The first fault that should be checked.</param> /// <param name="secondFault">The second fault that should be checked.</param> /// <param name="minimalCriticalFaultSet">The minimal critical fault set that should be checked.</param> /// <param name="activation">The activation mode of the fault set.</param> /// <param name="forceSimultaneous">Indicates whether both faults must occur simultaneously.</param> internal override AnalysisResult CheckOrder(Fault firstFault, Fault secondFault, FaultSet minimalCriticalFaultSet, Activation activation, bool forceSimultaneous) { throw new NotImplementedException(); }
/// <summary> /// Adds the <paramref name="successorState" /> to the transition set if neccessary, reached using the /// <paramref name="activatedFaults" />. /// </summary> /// <param name="successorState">The successor state that should be added.</param> /// <param name="activatedFaults">The faults activated by the transition to reach the state.</param> private bool Add(byte* successorState, FaultSet activatedFaults) { var hash = MemoryBuffer.Hash(successorState, _stateVectorSize, 0); for (var i = 1; i < ProbeThreshold; ++i) { var stateHash = MemoryBuffer.Hash((byte*)&hash, sizeof(int), i * 8345723) % _capacity; var faultIndex = _lookup[stateHash]; // If we don't know the state yet, set everything up and add the transition if (faultIndex == -1) { _successors.Add((uint)stateHash); AddFaultMetadata(stateHash, -1); MemoryBuffer.Copy(successorState, _hashedStateMemory + stateHash * _stateVectorSize, _stateVectorSize); return true; } // If there is a hash conflict, try again if (!MemoryBuffer.AreEqual(successorState, _hashedStateMemory + stateHash * _stateVectorSize, _stateVectorSize)) continue; // The transition has an already-known target state; it might have to be added or invalidate previously found transitions return UpdateTransitions(stateHash, activatedFaults, faultIndex); } throw new OutOfMemoryException( "Failed to find an empty hash table slot within a reasonable amount of time. Try increasing the successor state capacity."); }
/// <summary> /// Checks the <see cref="faults" /> for criticality using the <see cref="activation" /> mode. /// </summary> /// <param name="faults">The fault set that should be checked for criticality.</param> /// <param name="activation">The activation mode of the fault set.</param> internal abstract AnalysisResult CheckCriticality(FaultSet faults, Activation activation);
/// <summary> /// Adds the current transition if it is activation-minimal. Previously found transition might have to be removed if they are /// no longer activation-minimal. /// </summary> private bool UpdateTransitions(long stateHash, FaultSet activatedFaults, int faultIndex) { bool addTransition; bool addFaults; bool cleanupTransitions; ClassifyActivatedFaults(activatedFaults, faultIndex, out addTransition, out addFaults, out cleanupTransitions); if (cleanupTransitions) CleanupTransitions(activatedFaults, faultIndex, stateHash); if (addFaults) AddFaultMetadata(stateHash, _lookup[stateHash]); return addTransition; }
/// <summary> /// Checks the <see cref="faults" /> for criticality using the <see cref="activation" /> mode. /// </summary> /// <param name="faults">The fault set that should be checked for criticality.</param> /// <param name="activation">The activation mode of the fault set.</param> internal override AnalysisResult CheckCriticality(FaultSet faults, Activation activation) { ChangeFaultActivations(faults, activation); return _invariantChecker.Check(); }
/// <summary> /// Removes all transitions that are no longer activation minimal due to the current transition. /// </summary> private void CleanupTransitions(FaultSet activatedFaults, int faultIndex, long stateHash) { var current = faultIndex; var nextPointer = &_lookup[stateHash]; while (current != -1) { var faultSet = &_faults[current]; // Remove the fault set and the corresponding transition if it is a proper subset of the activated faults if (activatedFaults.IsSubsetOf(faultSet->Transition->ActivatedFaults) && activatedFaults != faultSet->Transition->ActivatedFaults) { faultSet->Transition->IsValid = false; *nextPointer = faultSet->NextSet; } if (nextPointer != &_lookup[stateHash]) nextPointer = &faultSet->NextSet; current = faultSet->NextSet; } }
/// <summary> /// Creates a function that determines the activation state of a fault. /// </summary> private Func<Fault, Activation> GetUpdateFaultActivations(FaultSet faults, Activation activation) { return fault => GetEffectiveActivation(fault, faults, activation); }
/// <summary> /// Classifies how the transition set must be updated. /// </summary> private void ClassifyActivatedFaults(FaultSet activatedFaults, int faultIndex, out bool addTransition, out bool addFaults, out bool cleanupTransitions) { addFaults = false; cleanupTransitions = false; // Basic invariant of the fault list: it contains only sets of activation-minimal faults while (faultIndex != -1) { var faultSet = &_faults[faultIndex]; faultIndex = faultSet->NextSet; // If the fault set is a subset of the activated faults, the current transition is not activation-minimal; // we can therefore safely ignore the transition; due to the list invariant, none of the remaining // fault sets in the list can be a superset of the activated faults because then the current fault set // would also be a subset of that other fault set, violating the invariant if (faultSet->Transition->ActivatedFaults.IsSubsetOf(activatedFaults)) { addTransition = faultSet->Transition->ActivatedFaults == activatedFaults; return; } // If at least one of the previously added transitions that we assumed to be activation-minimal is // in fact not activation-minimal, we have to clean up the transition set if (activatedFaults.IsSubsetOf(faultSet->Transition->ActivatedFaults)) cleanupTransitions = true; } // If we get here, we must add the faults and the transition addTransition = true; addFaults = true; }
private bool IsValid(FaultSet set) { // The set must contain all forced faults, hence it must be a superset of those // The set is not allowed to contain any suppressed faults, hence the intersection must be empty return _forcedSet.IsSubsetOf(set) && _suppressedSet.GetIntersection(set).IsEmpty; }
/// <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; }
/// <summary> /// Checks the order of <see cref="firstFault" /> and <see cref="secondFault" /> for the /// <see cref="minimalCriticalFaultSet" /> using the <see cref="activation" /> mode. /// </summary> /// <param name="firstFault">The first fault that should be checked.</param> /// <param name="secondFault">The second fault that should be checked.</param> /// <param name="minimalCriticalFaultSet">The minimal critical fault set that should be checked.</param> /// <param name="activation">The activation mode of the fault set.</param> /// <param name="forceSimultaneous">Indicates whether both faults must occur simultaneously.</param> internal abstract AnalysisResult CheckOrder(Fault firstFault, Fault secondFault, FaultSet minimalCriticalFaultSet, Activation activation, bool forceSimultaneous);
/// <summary> /// Determines the effective <see cref="Activation" /> of the <paramref name="fault" /> when <paramref name="faults" /> should /// be checked for criticality. /// </summary> protected Activation GetEffectiveActivation(Fault fault, FaultSet faults, Activation activation) { Assert.That(fault != null && fault.IsUsed, "Invalid fault."); if (SuppressedFaults.Contains(fault)) return Activation.Suppressed; if (ForcedFaults.Contains(fault)) return Activation.Forced; if (faults.Contains(fault)) return activation; return Activation.Suppressed; }