/// <summary> /// Initializes a new instance. /// </summary> /// <param name="createModel">Creates the model that should be checked.</param> /// <param name="output">The callback that should be used to output messages.</param> /// <param name="configuration">The analysis configuration that should be used.</param> internal ModelTraverser(AnalysisModelCreator createModel, AnalysisConfiguration configuration, int transitionSize, bool createStutteringState) { Requires.NotNull(createModel, nameof(createModel)); var stopwatch = new Stopwatch(); stopwatch.Start(); TransitionCollection.ValidateTransitionSizes(); var tasks = new Task[configuration.CpuCount]; var stacks = new StateStack[configuration.CpuCount]; _loadBalancer = new LoadBalancer(stacks); Context = new TraversalContext(_loadBalancer, configuration); _workers = new Worker[configuration.CpuCount]; for (var i = 0; i < configuration.CpuCount; ++i) { var index = i; tasks[i] = Task.Factory.StartNew(() => { stacks[index] = new StateStack(configuration.StackCapacity); _workers[index] = new Worker(index, Context, stacks[index], createModel.Create()); }); } Task.WaitAll(tasks); var firstModel = _workers[0].Model; if (transitionSize == DeriveTransitionSizeFromModel) { transitionSize = firstModel.TransitionSize; } if (configuration.WriteStateVectorLayout) { firstModel.WriteStateVectorLayout(configuration.DefaultTraceOutput); } var modelCapacity = configuration.ModelCapacity.DeriveModelByteSize(firstModel.ModelStateVectorSize, transitionSize); Context.ModelCapacity = modelCapacity; if (configuration.UseCompactStateStorage) { _states = new CompactStateStorage(modelCapacity.SizeOfState, modelCapacity.NumberOfStates); } else { _states = new SparseStateStorage(modelCapacity.SizeOfState, modelCapacity.NumberOfStates); } Context.States = _states; if (createStutteringState) { Context.StutteringStateIndex = _states.ReserveStateIndex(); } _initializationTime = stopwatch.Elapsed; stopwatch.Stop(); }
/// <summary> /// Optionally modifies the <paramref name="transitions" />, changing any of their values. However, no new transitions can be /// added; transitions can be removed by setting their <see cref="CandidateTransition.IsValid" /> flag to <c>false</c>. /// During subsequent traversal steps, only valid transitions and target states reached by at least one valid transition /// are considered. /// </summary> /// <param name="context">The context of the model traversal.</param> /// <param name="worker">The worker that found the transition.</param> /// <param name="transitions">The transitions that should be checked.</param> /// <param name="sourceState">The source state of the transitions.</param> /// <param name="sourceStateIndex">The unique index of the transition's source state.</param> /// <param name="isInitial">Indicates whether the transitions are initial transitions not starting in any valid source state.</param> public void ModifyTransitions(TraversalContext context, Worker worker, TransitionCollection transitions, byte *sourceState, int sourceStateIndex, bool isInitial) { foreach (CandidateTransition *transition in transitions) { if (TransitionFlags.IsValid(transition->Flags) && _terminateEarlyCondition(transition->Formulas)) { transition->Flags = TransitionFlags.SetToStutteringStateFlag(transition->Flags); } } }
/// <summary> /// Initializes a new instance. /// </summary> /// <param name="index">The zero-based index of the worker.</param> /// <param name="context">The context the model is traversed in.</param> /// <param name="stateStack">The state stack that should be used by the worker.</param> /// <param name="model">The model that the worker should analyze.</param> public Worker(int index, TraversalContext <TExecutableModel> context, StateStack stateStack, AnalysisModel <TExecutableModel> model) { Requires.NotNull(context, nameof(context)); Requires.NotNull(stateStack, nameof(stateStack)); Requires.NotNull(model, nameof(model)); _index = index; _context = context; _stateStack = stateStack; Model = model; }
/// <summary> /// Initializes a new instance. /// </summary> /// <param name="createModel">Creates the model that should be checked.</param> /// <param name="output">The callback that should be used to output messages.</param> /// <param name="configuration">The analysis configuration that should be used.</param> internal ModelTraverser(AnalysisModelCreator <TExecutableModel> createModel, Action <string> output, AnalysisConfiguration configuration, int transitionSize) { Requires.NotNull(createModel, nameof(createModel)); Requires.NotNull(output, nameof(output)); var stopwatch = new Stopwatch(); stopwatch.Start(); TransitionCollection.ValidateTransitionSizes(); var tasks = new Task[configuration.CpuCount]; var stacks = new StateStack[configuration.CpuCount]; _loadBalancer = new LoadBalancer(stacks); Context = new TraversalContext <TExecutableModel>(_loadBalancer, configuration, output); _workers = new Worker <TExecutableModel> [configuration.CpuCount]; for (var i = 0; i < configuration.CpuCount; ++i) { var index = i; tasks[i] = Task.Factory.StartNew(() => { stacks[index] = new StateStack(configuration.StackCapacity); _workers[index] = new Worker <TExecutableModel>(index, Context, stacks[index], createModel.Create()); }); } Task.WaitAll(tasks); var firstModel = _workers[0].Model; if (transitionSize == DeriveTransitionSizeFromModel) { transitionSize = firstModel.TransitionSize; } var modelCapacity = configuration.ModelCapacity.DeriveModelByteSize(firstModel.StateVectorSize, transitionSize); Context.ModelCapacity = modelCapacity; _states = new StateStorage(modelCapacity.SizeOfState, modelCapacity.NumberOfStates); Context.States = _states; Context.StutteringStateIndex = _states.ReserveStateIndex(); _initializationTime = stopwatch.Elapsed; stopwatch.Stop(); }