Ejemplo n.º 1
0
        /// <summary>
        ///     Build a List of Columns from a PetriNet
        /// </summary>
        /// <param name="petriNet"></param>
        /// <returns></returns>
        /// <author>Jannik Arndt</author>
        public static List <Column> Build(PetriNet petriNet)
        {
            // Initialize
            GlobalColumnList.Clear();

            Column firstColumn = new Column(0);
            Place  startPlace  = (Place)petriNet.GetSources()[0];

            firstColumn.HashSetOfNodes.Add(startPlace);
            GlobalColumnList.Add(firstColumn);

            // Recursively add all columns
            AddPlace(startPlace, 1);

            // Correct the end-place
            Place  endPlace = (Place)petriNet.GetSinks()[0];
            Column temp     = FindNode(endPlace);

            if (temp != null && temp.ColumnNumber < GlobalColumnList.Count)
            {
                temp.HashSetOfNodes.Remove(endPlace);
                TrimGlobalColumnList();
                GetOrCreateColumn(GlobalColumnList.Count).HashSetOfNodes.Add(endPlace);
            }

            return(GlobalColumnList);
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Remove old "End"-Places, combine sinks and add new "End"-Place
        /// </summary>
        /// <param name="petriNet">The petrinet to work on</param>
        /// <author>Jannik Arndt</author>
        public void FixEnding(PetriNet petriNet)
        {
            foreach (Place endPlace in petriNet.Places.Where(place => place.Name.Equals("End")))
            {
                endPlace.Name = "";
            }

            List <Place> endPlaces = (from sink in petriNet.GetSinks() where sink.GetType() == typeof(Place) select sink as Place).ToList();

            if (endPlaces.Count > 1)
            {
                foreach (Place endPlace in endPlaces.Skip(1))
                {
                    foreach (Transition incomingTransition in endPlace.IncomingTransitions)
                    {
                        endPlaces[0].IncomingTransitions.Add(incomingTransition);
                        incomingTransition.OutgoingPlaces.Clear();
                        incomingTransition.OutgoingPlaces.Add(endPlaces[0]);
                    }
                    petriNet.Places.Remove(endPlace);
                }
            }
            endPlaces[0].Name = "End";
        }
Ejemplo n.º 3
0
        /// <summary>
        /// Goes through the steps of the (improved) HeuristicMiner Algorithm:
        /// Find starting-events => build adjacency-matrix => convert into petrinet
        /// </summary>
        /// <returns>A PetriNet as a ProcessModel</returns>
        /// <exception cref="ArgumentNullException">If the field-parameter is null.</exception>
        /// <author>Jannik Arndt</author>
        public ProcessModel Mine()
        {
            if (_field == null)
            {
                throw new Exception("The field parameter was null");
            }

            // Get parameters from MinerSettings
            var threshold = MinerSettings.GetAsDouble("AdjacencyThresholdSlider") / 100;
            var maxDepth  = MinerSettings.GetAsInt("MaximumRecursionDepthSlider");

            if (threshold < 0 || threshold > 1)
            {
                throw new Exception("Threshold must be between 0 and 1.");
            }
            if (maxDepth < 1)
            {
                throw new Exception("Maximum recursion depth must be more greater than 1.");
            }

            // Statistics
            var processingTimeStart = Process.GetCurrentProcess().TotalProcessorTime;

            // 1. Create Adjacency Matrix
            var adjacencyMatrix = CreateAdjacencyMatrix(_field);

            // 2. Calculate the indexes of the first events
            var startindexes = GetColumnsWithOnlyNegativeEntries(adjacencyMatrix);

            // for every sub-processmodel
            foreach (var startindex in startindexes)
            {
                // 3. Create the dependency-Graph
                var rootNode = CreateDependencyGraph(_field.EventLog.ListOfUniqueEvents, adjacencyMatrix, threshold, 0.0, startindex, maxDepth);

                // 4. Turn the dependency-graph into a petri-net
                _listOfSubPetriNets.Add(CreatePetriNetFromDependencyGraph(rootNode, _field.EventLog, _field.Infotext));
            }

            // 5. Connect all Petrinets by one XOR-Split
            if (_listOfSubPetriNets.Count > 1)
            {
                // 5a. Connect all subnets to one start
                var startingPlace = _finalPetriNet.AddPlace("Start");
                foreach (var petriNet in _listOfSubPetriNets)
                {
                    var xorTransition = _finalPetriNet.AddTransition(incomingPlace: startingPlace);
                    _finalPetriNet.MergeWithPetriNet(petriNet, xorTransition);
                }
                // 5b. Add following transitions to all subnet-endings
                foreach (var openEndPlace in _finalPetriNet.GetSinks())
                {
                    if (openEndPlace.GetType() == typeof(Place))
                    {
                        _finalPetriNet.AddTransition(incomingPlace: (Place)openEndPlace);
                    }
                }
            }
            else
            {
                _finalPetriNet = _listOfSubPetriNets[0];
            }

            // 6. Connect all open endings
            _finalPetriNet = FixEnding(_finalPetriNet);

            // 7. Delete empty transitions
            _finalPetriNet = PetriNetOperation.CleanUpPetriNet(_finalPetriNet);

            // 8. Save information about the mining-process
            var processingTimeEnd = Process.GetCurrentProcess().TotalProcessorTime;
            var processingTime    = Math.Abs((processingTimeEnd - processingTimeStart).TotalMilliseconds) < 1 ? "< 15 ms" : (processingTimeEnd - processingTimeStart).TotalMilliseconds + " ms";

            _field.Information.Add("Processing Time", processingTime);
            _field.Information.Add("Number of Events", _finalPetriNet.Transitions.Count(s => s.IsLoop == false).ToString(CultureInfo.InvariantCulture));
            _field.Information.Add("Number of Transitions", _finalPetriNet.Transitions.Count.ToString(CultureInfo.InvariantCulture));
            _field.Information.Add("Number of Places", _finalPetriNet.Places.Count.ToString(CultureInfo.InvariantCulture));
            _field.Information.Add("Loops in the net", _finalPetriNet.CountLoops().ToString(CultureInfo.InvariantCulture));
            _field.Information.Add("Events used", _finalPetriNet.CountTransitionsWithoutANDs() - _finalPetriNet.CountLoops() + " of " + _field.EventLog.ListOfUniqueEvents.Count);
            _field.Information.Add("Parallel Models", startindexes.Count.ToString(CultureInfo.InvariantCulture));
            if (_listOfNodes.Count > 0)
            {
                _field.Information.Add("Minimal Adjacency", _listOfNodes.Min().ToString(CultureInfo.InvariantCulture));
                _field.Information.Add("Average Adjacency", Math.Round(_listOfNodes.Average(), 3).ToString(CultureInfo.InvariantCulture));
                if (Math.Abs(_listOfNodes.Min() - _listOfNodes.Average()) > 0.0001)
                {
                    _field.Information.Add("Standard Deviation", CalculateStandardDeviation(_listOfNodes).ToString(CultureInfo.InvariantCulture));
                }
            }

            return(_finalPetriNet);
        }