예제 #1
0
        /// <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->ActivatedFaults.IsSubsetOf(activatedFaults))
                {
                    addTransition = faultSet->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->ActivatedFaults))
                {
                    cleanupTransitions = true;
                }
            }

            // If we get here, we must add the faults and the transition
            addTransition = true;
            addFaults     = true;
        }
예제 #2
0
        /// <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, activatedFaults, -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.");
        }
예제 #3
0
        /// <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>
        public void Add(RuntimeModel model)
        {
            ++ComputedTransitionCount;

            // 1. Serialize the model's computed state; that is the successor state of the transition's source state
            //    modulo any changes resulting from notifications of fault activations
            var successorState  = _targetStateMemory + _stateVectorSize * Count;
            var activatedFaults = FaultSet.FromActivatedFaults(model.Faults);

            model.Serialize(successorState);

            // 2. Make sure the transition we're about to add is activation-minimal
            if (!Add(successorState, activatedFaults))
            {
                return;
            }

            // 3. Execute fault activation notifications and serialize the updated state if necessary
            if (model.NotifyFaultActivations())
            {
                model.Serialize(successorState);
            }

            // 4. Store the transition
            _transitions[Count] = new Transition
            {
                TargetState = successorState,
                Formulas    = new StateFormulaSet(_formulas),
                IsValid     = true,
            };
            ++Count;
        }
예제 #4
0
        /// <summary>
        ///   Initializes a new instance.
        /// </summary>
        /// <param name="serializedData">The serialized data describing the model.</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 RuntimeModel(SerializedRuntimeModel serializedData, int stateHeaderBytes = 0)
        {
            Requires.That(serializedData.Model != null, "Expected a valid model instance.");

            var buffer         = serializedData.Buffer;
            var rootComponents = serializedData.Model.Roots;
            var objectTable    = serializedData.ObjectTable;
            var formulas       = serializedData.Formulas;

            Requires.NotNull(buffer, nameof(buffer));
            Requires.NotNull(rootComponents, nameof(rootComponents));
            Requires.NotNull(objectTable, nameof(objectTable));
            Requires.NotNull(formulas, nameof(formulas));
            Requires.That(stateHeaderBytes % 4 == 0, nameof(stateHeaderBytes), "Expected a multiple of 4.");

            Model                     = serializedData.Model;
            SerializedModel           = buffer;
            RootComponents            = rootComponents.Cast <Component>().ToArray();
            Faults                    = objectTable.OfType <Fault>().Where(fault => fault.Activation == Activation.Nondeterministic && fault.IsUsed).ToArray();
            ActivationSensitiveFaults = Faults.Where(fault => fault.RequiresActivationNotification).ToArray();
            StateFormulas             = objectTable.OfType <StateFormula>().ToArray();
            Formulas                  = formulas;

            // Create a local object table just for the objects referenced by the model; only these objects
            // have to be serialized and deserialized. The local object table does not contain, for instance,
            // the closure types of the state formulas
            var objects             = Model.ReferencedObjects;
            var deterministicFaults = objectTable.OfType <Fault>().Where(fault => fault.Activation != Activation.Nondeterministic);

            _serializedObjects = new ObjectTable(objects.Except(deterministicFaults, ReferenceEqualityComparer <object> .Default));
            Objects            = objectTable;

            StateVectorLayout = SerializationRegistry.Default.GetStateVectorLayout(Model, _serializedObjects, SerializationMode.Optimized);

            _deserialize      = StateVectorLayout.CreateDeserializer(_serializedObjects);
            _serialize        = StateVectorLayout.CreateSerializer(_serializedObjects);
            _restrictRanges   = StateVectorLayout.CreateRangeRestrictor(_serializedObjects);
            _stateHeaderBytes = stateHeaderBytes;

            PortBinding.BindAll(objectTable);
            _choiceResolver = new ChoiceResolver(objectTable);

            ConstructionState = new byte[StateVectorSize];
            fixed(byte *state = ConstructionState)
            {
                Serialize(state);
                _restrictRanges();
            }

            FaultSet.CheckFaultCount(Faults.Length);
            StateFormulaSet.CheckFormulaCount(StateFormulas.Length);
        }
예제 #5
0
        /// <summary>
        ///   Adds the fault metadata of the current transition.
        /// </summary>
        private void AddFaultMetadata(long stateHash, FaultSet activatedFaults, int nextSet)
        {
            if (_nextFaultIndex >= _capacity)
            {
                throw new OutOfMemoryException("Out of memory. Try increasing the successor state capacity.");
            }

            _faults[_nextFaultIndex] = new FaultSetInfo
            {
                ActivatedFaults = activatedFaults,
                NextSet         = nextSet,
                Transition      = &_transitions[Count]
            };

            _lookup[stateHash] = _nextFaultIndex;
            _nextFaultIndex++;
        }
예제 #6
0
        /// <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, activatedFaults, _lookup[stateHash]);
            }

            return(addTransition);
        }
예제 #7
0
        /// <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->ActivatedFaults) && activatedFaults != faultSet->ActivatedFaults)
                {
                    faultSet->Transition->IsValid = false;
                    *nextPointer = faultSet->NextSet;
                }

                if (nextPointer != &_lookup[stateHash])
                {
                    nextPointer = &faultSet->NextSet;
                }

                current = faultSet->NextSet;
            }
        }