/// <summary> /// Deletes all empty transitions from a Petri Net and redirects the connections /// </summary> /// <param name="petriNet"></param> /// <author>Jannik Arndt</author> public static PetriNet CleanUpPetriNet(PetriNet petriNet) { List<Node> nodesToBeDeleted = new List<Node>(); foreach (Place place in petriNet.Places.Reverse<Place>()) { if (place.IncomingTransitions.Count == 1 && place.IncomingTransitions[0].OutgoingPlaces.Count == 1 && place.OutgoingTransitions.Count == 1 && place.OutgoingTransitions[0].IncomingPlaces.Count == 1) { if (place.IncomingTransitions[0].Name == "") { // Redirect connections around the empty transition place.OutgoingTransitions[0].AddIncomingPlaces(place.IncomingTransitions[0].IncomingPlaces); nodesToBeDeleted.Add(place); nodesToBeDeleted.Add(place.IncomingTransitions[0]); } if (place.OutgoingTransitions[0].Name == "") { // Redirect connections around the empty transition place.IncomingTransitions[0].AddOutgoingPlaces(place.OutgoingTransitions[0].OutgoingPlaces); nodesToBeDeleted.Add(place); nodesToBeDeleted.Add(place.OutgoingTransitions[0]); } } } petriNet.RemoveNodes(nodesToBeDeleted); return petriNet; }
/// <summary> /// Replays the content of the EventLog on the given PetriNet /// </summary> /// <param name="petriNet"></param> /// <param name="eventLog"></param> /// <returns></returns> /// <author>Jannik Arndt</author> public static TokenReplayResult Replay(PetriNet petriNet, EventLog eventLog) { var result = new TokenReplayResult { NumberOfCases = eventLog.Cases.Count }; foreach (var Case in eventLog.Cases) { var exceptionThrown = false; petriNet.ResetTokens(); foreach (var Event in Case.EventList) { try { petriNet.FireTransition(Event.Name); } catch (NullReferenceException) { result.FailedCasesTransitionNotFound.Add(Case); exceptionThrown = true; break; } catch (TransitionNotEnabledException) { result.FailedCasesTransitionNotEnabled.Add(Case); exceptionThrown = true; break; } } if (!exceptionThrown) result.SuccessfulReplays++; } return result; }
/// <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; }
/// <summary> /// Adds all added Transition to the NetWithDifference /// </summary> /// <author>Jannik Arndt,Thomas Meents</author> public void AddAddedTransitions(PetriNet netWithDifference) { // Find all Transitions that have the DiffStatus "added" List<Transition> addedTransitions = ListOfChoosenProcessModels[1].Transitions.Where(transition => transition.DiffStatus == DiffState.Added).ToList(); foreach (Transition addedTransition in addedTransitions) { netWithDifference.Places.AddRange(addedTransition.OutgoingPlaces); addedTransition.DiffStatus = DiffState.Added; // For non-starting transitions if (addedTransition.IncomingPlaces[0].IncomingTransitions != null && addedTransition.IncomingPlaces[0].IncomingTransitions.Count > 0) { List<Transition> listOfFollower = new List<Transition>(); if (addedTransition.OutgoingPlaces[0].OutgoingTransitions.Count > 0) { foreach (Place t in addedTransition.OutgoingPlaces) foreach (Transition newfollower in t.OutgoingTransitions) if (!listOfFollower.Contains(newfollower)) listOfFollower.Add(newfollower); } else { Transition follower = new Transition(); listOfFollower.Add(follower); } if (listOfFollower.Count > 0) { listOfFollower[0].IncomingPlaces.Add(addedTransition.OutgoingPlaces[0]); } else { Place endPlace = new Place("End"); addedTransition.OutgoingPlaces.Add(endPlace); } } // For starting Transitions else { foreach (Place t in addedTransition.OutgoingPlaces) { if (t.OutgoingTransitions.Count <= 0) continue; addedTransition.IncomingPlaces[0].Name = "Start"; netWithDifference.Places.Add(addedTransition.IncomingPlaces[0]); if (addedTransition.IncomingPlaces[0].OutgoingTransitions.Count > 1) addedTransition.IncomingPlaces[0].OutgoingTransitions.RemoveAt(1); if (addedTransition.OutgoingPlaces[0].IncomingTransitions.Count > 1) addedTransition.OutgoingPlaces[0].IncomingTransitions.RemoveAt(1); netWithDifference.Places.RemoveAt(0); } } netWithDifference.Transitions.Add(addedTransition); } }
/// <summary> /// Constructor for the HeuristicMiner, initializes values and sets the "field" that will be mined. /// </summary> /// <param name="field">A field from the DataSelection</param> public HeuristicMiner(Field field) { _field = field; _finalPetriNet = new PetriNet(field.Infotext); _listOfSubPetriNets = new List<PetriNet>(); _openParallelismCount = new Stack<Parallelism>(); _listOfNodes = new HashSet<double>(); }
/// <summary> /// Constructor for a tree node /// </summary> /// <param name="inductiveMiner"></param> /// <param name="operation">node operation</param> /// <param name="associatedEvent"></param> /// <param name="right"></param> /// <param name="left"></param> /// <author>Thomas Meents, Bernd Nottbeck</author> public InductiveMinerTreeNode(InductiveMiner inductiveMiner, OperationsEnum operation, Event associatedEvent = null, InductiveMinerTreeNode right = null, InductiveMinerTreeNode left = null) { Operation = operation; LeftLeaf = left; RightLeaf = right; Event = associatedEvent; petriNet = inductiveMiner.IMPetriNet; }
/// <summary> /// Initialize the InductiveMiner instance. /// </summary> /// <param name="field">Corresponding field</param> /// <author>Krystian Zielonka, Thomas Meents, Bernd Nottbeck</author> public InductiveMiner(Field field) { _field = field; DirectRowList = new List<InductiveMinerRow>(); EventDictionary = new Dictionary<Event, InductiveMinerGraphNode>(); IMPetriNet = new PetriNet(_field.Infotext); StartEvent = new Event("StartEvent"); EndEvent = new Event("EndEvent"); EventuallyRowList = new List<InductiveMinerRow>(); }
public AlphaMiner(Field field) { _field = field; _petriNet = new PetriNet(field.Infotext); _listOfActivities = new HashSet<String>(); _listOfStartActivities = new HashSet<String>(); _listOfEndActivities = new HashSet<String>(); _listOfAlphaPlaces = new List<AlphaMinerPlaces>(); _listOfAllPairs = new Dictionary<String, Tuple<HashSet<String>, HashSet<String>>>(); _listOfLoopsWithTheLengthOfTwo = new Dictionary<String, HashSet<String>>(); _listOfAllParallelPairs = new Dictionary<String, HashSet<String>>(); _listOfAllDoubleActivities = new HashSet<String>(); _listOfActivitiesInCase = new List<List<String>>(); }
/// <summary> /// Constructor for a tree node´used duringt the cutting process. /// </summary> /// <param name="petriNet"></param> /// <param name="graphNode"></param> /// <param name="startEvent"></param> public InductiveMinerTreeNode(PetriNet petriNet, InductiveMinerGraphNode graphNode, Event startEvent) { GraphNode = graphNode; Operation = GraphNode.FollowerList.Count == 0 ? OperationsEnum.isLeaf : OperationsEnum.isUnkown; Event = GraphNode.Name; LeftLeaf = null; RightLeaf = null; this.startEvent = startEvent; visitedNodes = new HashSet<InductiveMinerGraphNode>(); visitedLoopCheckNodes = new HashSet<InductiveMinerGraphNode>(); this.petriNet = petriNet; newStart = new InductiveMinerGraphNode(new Event("NewStart")); DivideAndConquer(); }
/// <summary> /// (1) -> [One] -> (3)-> [Three] -> (5)-> [Five] -> (6) /// Has a corresponding EventLog! /// </summary> /// <author>Thomas Meents</author> public static PetriNet OneThreeFive() { var petriNet = new PetriNet("OneThreeFive"); var place1 = petriNet.AddPlace("1"); var place3 = petriNet.AddPlace("3"); var place5 = petriNet.AddPlace("5"); var place6 = petriNet.AddPlace("6"); petriNet.AddTransition("One", incomingPlace: place1, outgoingPlace: place3); petriNet.AddTransition("Three", incomingPlace: place3, outgoingPlace: place5); petriNet.AddTransition("Five", incomingPlace: place5, outgoingPlace: place6); return petriNet; }
/// <summary> /// Slices a PetriNet into columns and then draws it on the given canvas. /// </summary> /// <param name="petriNet">A petrinet.</param> /// <param name="canvas">The canvas the net is drawn upon.</param> /// <param name="isDragAndDropAllowed">Enables drag and drop for all nodes. Default: true</param> /// <param name="forceRedraw"></param> /// <returns>The given canvas but with a net on it.</returns> /// <author>Jannik Arndt (based on Roman Bauers implementation)</author> public Canvas DrawPetriNet(PetriNet petriNet, Canvas canvas, bool isDragAndDropAllowed = true, bool forceRedraw = false) { Dictionary<Node, Thumb> nodesDictionary = new Dictionary<Node, Thumb>(); List<Column> listOfColumns = ColumnBuilder.Build(petriNet); if (Settings.Default.AutomaticallyAlignNodes) listOfColumns = RowBuilder.CalculateRows(listOfColumns); // 1. Draw Transitions and Places foreach (Column column in listOfColumns) { int positionX = (Settings.Default.ColumnWidth*column.ColumnNumber) + Settings.Default.PlaceRadius; int positionY; foreach (Node node in column.HashSetOfNodes) { // If the node has been drawn before, use the saved values if (node.IsDrawn && forceRedraw == false) { positionX = node.PositionX; } else { node.PositionX = positionX; positionY = Convert.ToInt32(node.Row*Settings.Default.RowHeight); node.PositionY = positionY; node.IsDrawn = true; } Thumb nodeThumb = DrawNode(canvas, node, isDragAndDropAllowed); //Draw the place and cache the drawing. if (!nodesDictionary.ContainsKey(node)) nodesDictionary.Add(node, nodeThumb); } } // 2. Draw arrows between the nodes foreach (KeyValuePair<Node, Thumb> node in nodesDictionary) foreach (Node followingNode in node.Key.OutgoingNodes) ConnectByArrow(canvas, node.Value, nodesDictionary[followingNode]); return canvas; }
/// <summary> /// Adds as many places as following events that each lead to a transition. /// </summary> /// <param name="startingTransition">Contains the starting transition</param> /// <param name="followers">node.followers</param> /// <param name="petriNet">Contains the current petri net</param> /// <returns>The transitions that are in an AND-relation.</returns> /// <author>Jannik Arndt</author> public List<Transition> StartAND(Transition startingTransition, List<EventNode> followers, PetriNet petriNet) { for (var index = 0; index < followers.Count; index++) _openParallelismCount.Push(Parallelism.And); var listOfFollowingTransitions = new List<Transition>(); if (startingTransition.Name == "") startingTransition.Name = "AND Split"; startingTransition.IsANDSplit = true; foreach (var node in followers) { var newPlace = petriNet.AddPlace(); listOfFollowingTransitions.Add(petriNet.AddTransition(node.InnerEvent.Name, incomingPlace: newPlace)); startingTransition.AddOutgoingPlace(newPlace); } return listOfFollowingTransitions; }
/// <summary> /// Resolves a construct of three parallel events: a AND ( b XOR c ) /// </summary> /// <param name="event1">One event</param> /// <param name="a">An event node</param> /// <param name="b">An event node</param> /// <param name="c">An event node</param> /// <param name="petriNet">Current petri net</param> /// <returns>A list with final transitions</returns> /// <author>Jannik Arndt</author> public List<Transition> StartAand_BxorC(Transition event1, EventNode a, EventNode b, EventNode c, PetriNet petriNet) { var finalTransition = petriNet.AddTransition("AND Join"); finalTransition.IsANDJoin = true; var andTransition = StartAND(event1, new List<EventNode> { a }, petriNet); EndAND(andTransition, petriNet, finalTransition); var xorTransition = StartXOR(event1, new List<EventNode> { b, c }, petriNet); EndXOR(xorTransition, petriNet, finalTransition); return new List<Transition> { finalTransition }; }
/// <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; }
/// <summary> /// A recursive function to call the next level of HandleNode. Also closes open XORs and ANDs right away. /// </summary> /// <param name="trans"></param> /// <param name="node"></param> /// <param name="log"></param> /// <param name="petriNet"></param> /// <author>Jannik Arndt</author> public void HandleNodesAndCloseParallelisms(Transition trans, EventNode node, EventLog log, PetriNet petriNet) { var transitions = HandleNode(trans, node, log, petriNet); if (transitions == null) return; foreach (var transition in transitions) foreach (var eventNode in node.ListOfFollowers) if (transition.Name == eventNode.InnerEvent.Name || transition.IsANDJoin) HandleNodesAndCloseParallelisms(transition, eventNode, log, petriNet); }
/// <summary> /// Returns a list of places between two transitions in a petrinet /// </summary> /// <param name="t1">Transitionname</param> /// <param name="t2">Transitionname</param> /// <param name="petriNet">Petrinet</param> /// <returns>Returns a list of places</returns> /// <autor>Andrej Albrecht</autor> private List<Place> GetListOfPlacesBetweenTwoTransitionsFromPetriNet(string t1, string t2, PetriNet petriNet) { Transition transition1 = petriNet.FindTransition(t1); Transition transition2 = petriNet.FindTransition(t2); HashSet<Place> placesInBetween = new HashSet<Place>(); foreach (Place outgoingPlace in transition1.OutgoingPlaces) if (transition2.IncomingPlaces.Contains(outgoingPlace)) placesInBetween.Add(outgoingPlace); return placesInBetween.ToList(); }
/// <summary> /// Adds a place and the transitions it leads to. /// </summary> /// <param name="startingTransition">>Contains the starting transition</param> /// <param name="followers">node.followers</param> /// <param name="petriNet">Contains the current petri net</param> /// <returns>The two transitions that are in an XOR-relation.</returns> /// <author>Jannik Arndt</author> public List<Transition> StartXOR(Transition startingTransition, List<EventNode> followers, PetriNet petriNet) { if (followers.Count > 1) for (var index = 0; index < followers.Count; index++) _openParallelismCount.Push(Parallelism.Xor); var newPlace = petriNet.AddPlace(); var listOfFollowingTransitions = new List<Transition>(); foreach (var eventNode in followers) { if (eventNode == null) break; /* _____________________ __________ ____________________________ * | startingTransition | ---> ( NewPlace ) ---> | NewFollowingTransition | * ''''''''''''''''''''' ********** '''''''''''''''''''''''''''' */ var newFollowingTransition = petriNet.FindTransition(eventNode.InnerEvent.Name); // The following transition already exists => close something if (newFollowingTransition != null) { if (_openParallelismCount.Count > 0) switch (_openParallelismCount.Peek()) { // Close XOR case Parallelism.Xor: newFollowingTransition.IncomingPlaces.Remove(newPlace); startingTransition.AddOutgoingPlace(newFollowingTransition.IncomingPlaces.First()); _openParallelismCount.Pop(); break; // Close AND case Parallelism.And: newFollowingTransition.AddIncomingPlace(newPlace); startingTransition.AddOutgoingPlace(newPlace); _openParallelismCount.Pop(); break; } } // Open XOR else { newFollowingTransition = petriNet.AddTransition(eventNode.InnerEvent.Name, incomingPlace: newPlace); if (newPlace.IncomingTransitions.Count == 0) startingTransition.AddOutgoingPlace(newPlace); } listOfFollowingTransitions.Add(newFollowingTransition); } if (newPlace.IncomingTransitions.Count == 0 && newPlace.OutgoingTransitions.Count == 0) petriNet.Places.Remove(newPlace); return listOfFollowingTransitions; }
/// <summary> /// Adds a place and connects the open transitions to it. Then puts the given transition behind that whole thing. /// </summary> /// <param name="startingTransition">The starting transition</param> /// <param name="petriNet">The current petri net</param> /// <param name="endingTransition">The ending transition, if it exists already. Otherwise a new one is created.</param> /// <returns>The empty transition after the place that combines to XOR.</returns> /// <author>Jannik Arndt</author> public List<Transition> EndXOR(List<Transition> startingTransition, PetriNet petriNet, Transition endingTransition = null) { if (endingTransition == null) endingTransition = petriNet.AddTransition(); if (_openParallelismCount.Count > 0) _openParallelismCount.Pop(); var newPlace = petriNet.AddPlace(); foreach (var transition in startingTransition) transition.AddOutgoingPlace(newPlace); endingTransition.AddIncomingPlace(newPlace); return new List<Transition> { endingTransition }; }
/// <summary> /// Goes through the dependency-graph and creates a petrinet. /// </summary> /// <param name="dependencyGraph">An EventNode from CreateDependencyGraph()</param> /// <param name="eventLog">The EventLog to calculate AND and XOR-relations</param> /// <param name="name">The name of the new PetriNet</param> /// <returns>A complete petrinet</returns> /// <author>Jannik Arndt, Bernhard Bruns</author> public PetriNet CreatePetriNetFromDependencyGraph(EventNode dependencyGraph, EventLog eventLog, string name) { var petriNet = new PetriNet(name); // 1. first event var startingPlace = petriNet.AddPlace("", 1); var firstEvent = petriNet.AddTransition(dependencyGraph.InnerEvent.Name, incomingPlace: startingPlace); // 2. Go through the net and turn Nodes into Places and Transitions, with parallel structures HandleNodesAndCloseParallelisms(firstEvent, dependencyGraph, eventLog, petriNet); // 3. handle loops petriNet = HandleLoops(eventLog, petriNet); return petriNet; }
public void CompareEventLogAndPetriNetTest1() { // //EventLog // //create Case1 Case ca1 = new Case(); ca1.CreateEvent("A"); ca1.CreateEvent("C"); ca1.CreateEvent("D"); ca1.CreateEvent("E"); ca1.CreateEvent("H"); //create Case2 Case ca2 = new Case(); ca2.CreateEvent("A"); ca2.CreateEvent("B"); ca2.CreateEvent("D"); ca2.CreateEvent("E"); ca2.CreateEvent("G"); //create Case3 Case ca3 = new Case(); ca3.CreateEvent("A"); ca3.CreateEvent("D"); ca3.CreateEvent("C"); ca3.CreateEvent("E"); ca3.CreateEvent("H"); //create Case4 Case ca4 = new Case(); ca4.CreateEvent("A"); ca4.CreateEvent("B"); ca4.CreateEvent("D"); ca4.CreateEvent("E"); ca4.CreateEvent("H"); //create Case5 Case ca5 = new Case(); ca5.CreateEvent("A"); ca5.CreateEvent("C"); ca5.CreateEvent("D"); ca5.CreateEvent("E"); ca5.CreateEvent("G"); //create Case6 Case ca6 = new Case(); ca6.CreateEvent("A"); ca6.CreateEvent("D"); ca6.CreateEvent("C"); ca6.CreateEvent("E"); ca6.CreateEvent("G"); //create Case7 Case ca7 = new Case(); ca7.CreateEvent("A"); ca7.CreateEvent("D"); ca7.CreateEvent("B"); ca7.CreateEvent("E"); ca7.CreateEvent("H"); //create Case8 Case ca8 = new Case(); ca8.CreateEvent("A"); ca8.CreateEvent("C"); ca8.CreateEvent("D"); ca8.CreateEvent("E"); ca8.CreateEvent("F"); ca8.CreateEvent("D"); ca8.CreateEvent("B"); ca8.CreateEvent("E"); ca8.CreateEvent("H"); //create Case9 Case ca9 = new Case(); ca9.CreateEvent("A"); ca9.CreateEvent("D"); ca9.CreateEvent("B"); ca9.CreateEvent("E"); ca9.CreateEvent("G"); //create Case10 Case ca10 = new Case(); ca10.CreateEvent("A"); ca10.CreateEvent("C"); ca10.CreateEvent("D"); ca10.CreateEvent("E"); ca10.CreateEvent("F"); ca10.CreateEvent("B"); ca10.CreateEvent("D"); ca10.CreateEvent("E"); ca10.CreateEvent("H"); //create Case11 Case ca11 = new Case(); ca11.CreateEvent("A"); ca11.CreateEvent("C"); ca11.CreateEvent("D"); ca11.CreateEvent("E"); ca11.CreateEvent("F"); ca11.CreateEvent("B"); ca11.CreateEvent("D"); ca11.CreateEvent("E"); ca11.CreateEvent("G"); //create Case12 Case ca12 = new Case(); ca12.CreateEvent("A"); ca12.CreateEvent("C"); ca12.CreateEvent("D"); ca12.CreateEvent("E"); ca12.CreateEvent("F"); ca12.CreateEvent("D"); ca12.CreateEvent("B"); ca12.CreateEvent("E"); ca12.CreateEvent("G"); //create Case13 Case ca13 = new Case(); ca13.CreateEvent("A"); ca13.CreateEvent("D"); ca13.CreateEvent("C"); ca13.CreateEvent("E"); ca13.CreateEvent("F"); ca13.CreateEvent("C"); ca13.CreateEvent("D"); ca13.CreateEvent("E"); ca13.CreateEvent("H"); //create Case14 Case ca14 = new Case(); ca14.CreateEvent("A"); ca14.CreateEvent("D"); ca14.CreateEvent("C"); ca14.CreateEvent("E"); ca14.CreateEvent("F"); ca14.CreateEvent("D"); ca14.CreateEvent("B"); ca14.CreateEvent("E"); ca14.CreateEvent("H"); //create Case15 Case ca15 = new Case(); ca15.CreateEvent("A"); ca15.CreateEvent("D"); ca15.CreateEvent("C"); ca15.CreateEvent("E"); ca15.CreateEvent("F"); ca15.CreateEvent("B"); ca15.CreateEvent("D"); ca15.CreateEvent("E"); ca15.CreateEvent("G"); //create Case16 Case ca16 = new Case(); ca16.CreateEvent("A"); ca16.CreateEvent("C"); ca16.CreateEvent("D"); ca16.CreateEvent("E"); ca16.CreateEvent("F"); ca16.CreateEvent("B"); ca16.CreateEvent("D"); ca16.CreateEvent("E"); ca16.CreateEvent("F"); ca16.CreateEvent("D"); ca16.CreateEvent("B"); ca16.CreateEvent("E"); ca16.CreateEvent("G"); //create Case17 Case ca17 = new Case(); ca17.CreateEvent("A"); ca17.CreateEvent("D"); ca17.CreateEvent("C"); ca17.CreateEvent("E"); ca17.CreateEvent("F"); ca17.CreateEvent("D"); ca17.CreateEvent("B"); ca17.CreateEvent("E"); ca17.CreateEvent("G"); //create Case18 Case ca18 = new Case(); ca18.CreateEvent("A"); ca18.CreateEvent("D"); ca18.CreateEvent("C"); ca18.CreateEvent("E"); ca18.CreateEvent("F"); ca18.CreateEvent("B"); ca18.CreateEvent("D"); ca18.CreateEvent("E"); ca18.CreateEvent("F"); ca18.CreateEvent("B"); ca18.CreateEvent("D"); ca18.CreateEvent("E"); ca18.CreateEvent("G"); //create Case19 Case ca19 = new Case(); ca19.CreateEvent("A"); ca19.CreateEvent("D"); ca19.CreateEvent("C"); ca19.CreateEvent("E"); ca19.CreateEvent("F"); ca19.CreateEvent("D"); ca19.CreateEvent("B"); ca19.CreateEvent("E"); ca19.CreateEvent("F"); ca19.CreateEvent("B"); ca19.CreateEvent("D"); ca19.CreateEvent("E"); ca19.CreateEvent("H"); //create Case20 Case ca20 = new Case(); ca20.CreateEvent("A"); ca20.CreateEvent("D"); ca20.CreateEvent("B"); ca20.CreateEvent("E"); ca20.CreateEvent("F"); ca20.CreateEvent("B"); ca20.CreateEvent("D"); ca20.CreateEvent("E"); ca20.CreateEvent("F"); ca20.CreateEvent("D"); ca20.CreateEvent("B"); ca20.CreateEvent("E"); ca20.CreateEvent("G"); //create Case21 Case ca21 = new Case(); ca21.CreateEvent("A"); ca21.CreateEvent("D"); ca21.CreateEvent("C"); ca21.CreateEvent("E"); ca21.CreateEvent("F"); ca21.CreateEvent("D"); ca21.CreateEvent("B"); ca21.CreateEvent("E"); ca21.CreateEvent("F"); ca21.CreateEvent("C"); ca21.CreateEvent("D"); ca21.CreateEvent("E"); ca21.CreateEvent("F"); ca21.CreateEvent("D"); ca21.CreateEvent("B"); ca21.CreateEvent("E"); ca21.CreateEvent("G"); //create Event Log EventLog eventLog = new EventLog(); eventLog.Cases.Add(ca1); eventLog.Cases.Add(ca2); eventLog.Cases.Add(ca3); eventLog.Cases.Add(ca4); eventLog.Cases.Add(ca5); eventLog.Cases.Add(ca6); eventLog.Cases.Add(ca7); eventLog.Cases.Add(ca8); eventLog.Cases.Add(ca9); eventLog.Cases.Add(ca10); eventLog.Cases.Add(ca11); eventLog.Cases.Add(ca12); eventLog.Cases.Add(ca13); eventLog.Cases.Add(ca14); eventLog.Cases.Add(ca15); eventLog.Cases.Add(ca16); eventLog.Cases.Add(ca17); eventLog.Cases.Add(ca18); eventLog.Cases.Add(ca19); eventLog.Cases.Add(ca20); eventLog.Cases.Add(ca21); // //PetriNet // PetriNet petriNet = new PetriNet("Petri-Net Name"); Place pStart = new Place("Place Start", 0); Place pC1 = new Place("c1", 0); Place pC2 = new Place("c2", 0); Place pC3 = new Place("c3", 0); Place pC4 = new Place("c4", 0); Place pC5 = new Place("c5", 0); Place pEnd = new Place("Place End", 0); Transition tA = new Transition("A"); Transition tB = new Transition("B"); Transition tC = new Transition("C"); Transition tD = new Transition("D"); Transition tE = new Transition("E"); Transition tF = new Transition("F"); Transition tG = new Transition("G"); Transition tH = new Transition("H"); tG.AddOutgoingPlace(pEnd); tG.AddIncomingPlace(pC5); tH.AddOutgoingPlace(pEnd); tH.AddIncomingPlace(pC5); tE.AddIncomingPlace(pC3); tE.AddIncomingPlace(pC4); tE.AddOutgoingPlace(pC5); pC3.AppendIncomingTransition(tB); pC3.AppendIncomingTransition(tC); pC3.AppendOutgoingTransition(tE); pC4.AppendIncomingTransition(tD); pC4.AppendOutgoingTransition(tE); tB.AddIncomingPlace(pC1); tB.AddOutgoingPlace(pC3); tC.AddIncomingPlace(pC1); tC.AddOutgoingPlace(pC3); tD.AddIncomingPlace(pC2); tD.AddOutgoingPlace(pC4); pC1.AppendIncomingTransition(tA); pC1.AppendOutgoingTransition(tB); pC1.AppendOutgoingTransition(tC); pC2.AppendIncomingTransition(tA); pC2.AppendOutgoingTransition(tD); tF.AddIncomingPlace(pC5); tF.AddOutgoingPlace(pC1); tF.AddOutgoingPlace(pC2); // tA.AddIncomingPlace(pStart); tA.AddOutgoingPlace(pC1); tA.AddOutgoingPlace(pC2); pStart.AppendOutgoingTransition(tA); pEnd.AppendIncomingTransition(tG); pEnd.AppendIncomingTransition(tH); //// petriNet.Transitions.Add(tA); petriNet.Transitions.Add(tB); petriNet.Transitions.Add(tC); petriNet.Transitions.Add(tD); petriNet.Transitions.Add(tE); petriNet.Transitions.Add(tF); petriNet.Transitions.Add(tG); petriNet.Transitions.Add(tH); //// petriNet.Places.Add(pStart); petriNet.Places.Add(pC1); petriNet.Places.Add(pC2); petriNet.Places.Add(pC3); petriNet.Places.Add(pC4); petriNet.Places.Add(pC5); petriNet.Places.Add(pEnd); ComparingFootprint footprintEventLog = ComparingFootprintAlgorithm.CreateFootprint(eventLog); ComparingFootprint footprintPetriNet = ComparingFootprintAlgorithm.CreateFootprint(petriNet); ComparingFootprintResultMatrix footprintResultMatrix = new ComparingFootprintResultMatrix(footprintEventLog, footprintPetriNet); if (footprintResultMatrix.HeaderWithEventNames.Count != 8) { Assert.Fail(""); } int y = 0; foreach (String headerNameY in footprintResultMatrix.HeaderWithEventNames) { int x = 0; foreach (String headerNameX in footprintResultMatrix.HeaderWithEventNames) { ResultCellType resultCellType = footprintResultMatrix.ResultMatrix[y, x]; Console.WriteLine("Test headerNameY: " + headerNameY + ", headerNameX: " + headerNameX + " [" + y + "," + x + "].CellType:" + resultCellType); if (!resultCellType.Equals(ResultCellType.NoDifferences)) { Assert.Fail("Test headerNameY: " + headerNameY + ", headerNameX: " + headerNameX + " [" + y + "," + x + "].CellType:" + resultCellType); } x++; } y++; } //Arrange (Create Footprints) ComparingFootprint footPrintEventlog = ComparingFootprintAlgorithm.CreateFootprint(eventLog); ComparingFootprint footPrintPetrinet = ComparingFootprintAlgorithm.CreateFootprint(petriNet); ComparingFootprintResultMatrix resultFootprint = new ComparingFootprintResultMatrix(footPrintEventlog, footPrintPetrinet); // Act (Calculate Fitness) double fitnessComparingFootprint = ComparingFootprintAlgorithm.CalculateFitness(resultFootprint.GetNumberOfDifferences(), resultFootprint.GetNumberOfOpportunities()); if (fitnessComparingFootprint != 1.0) { // Assert Assert.Fail("Fitness not correct! (" + fitnessComparingFootprint + ")"); } }
/// <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"; }
/// <summary> /// Method to change the color of the given list of lines in a canvas /// </summary> /// <param name="listOfLinesToBeRemoved">List of lines that must be removed</param> /// <param name="conformanceCheckingCanvas"></param> /// <param name="petriNet">Petrinet</param> /// <autor>Andrej Albrecht</autor> private void SetColorOnLinesToBeRemoved(IEnumerable<List<string>> listOfLinesToBeRemoved, Canvas conformanceCheckingCanvas, PetriNet petriNet) { foreach (List<String> stringCombination in listOfLinesToBeRemoved) { if (stringCombination.Count == 2) { String transition1 = stringCombination.ElementAt(0); String transition2 = stringCombination.ElementAt(1); IEnumerable<Shape> listWithArrowsToBeMarked = GetArrowsBetweenTransitions(transition1, transition2, conformanceCheckingCanvas, petriNet); foreach (Shape shape in listWithArrowsToBeMarked) { shape.Stroke = Brushes.Red; shape.Fill = Brushes.Red; } } } }
/// <summary> /// Resolves a construct of three parallel events: a XOR ( b AND c ) /// </summary> /// <param name="event1">Event number one</param> /// <param name="a">An Event node</param> /// <param name="b">An Event node</param> /// <param name="c">An Event node</param> /// <param name="petriNet">The current petri net</param> /// <returns>A list with final transition</returns> /// <author>Jannik Arndt</author> public List<Transition> StartAxor_BandC(Transition event1, EventNode a, EventNode b, EventNode c, PetriNet petriNet) { var finalTransition = petriNet.AddTransition(); // empty transition, will possibly be cleaned up finalTransition.Name = FindFirstCommonSuccessor(new List<EventNode> { a, b, c }); var xorTransition = StartXOR(event1, new List<EventNode> { a }, petriNet); EndXOR(xorTransition, petriNet, finalTransition); var andSplit = petriNet.AddTransition(); // no idea where this disappears... andSplit.AddIncomingPlace(xorTransition[0].IncomingPlaces[0]); // XOR-Split-Place var andTransition = StartAND(andSplit, new List<EventNode> { b, c }, petriNet); var andJoin = petriNet.AddTransition("AND Join"); andJoin.IsANDJoin = true; var andTransition2 = EndAND(andTransition, petriNet, andJoin); andTransition2[0].AddOutgoingPlace(finalTransition.IncomingPlaces.FirstOrDefault()); return new List<Transition> { finalTransition }; }
/// <summary> /// Connects all open endings to one end-place. This is useful for multiple processmodels in one net or for loops at the end of the net. /// </summary> /// <param name="petriNet">A petrinet with possible open endings</param> /// <returns>The given PetriNet with a fixed ending</returns> /// <author>Jannik Arndt</author> public PetriNet FixEnding(PetriNet petriNet) { if (petriNet.GetTransitionsWithoutFollowersIgnoreLoops().Count > 0) { var endingPlace = petriNet.AddPlace("End"); foreach (var transition in petriNet.GetTransitionsWithoutFollowersIgnoreLoops()) { if (transition.OutgoingPlaces.Count > 0) { var temporaryTransition = petriNet.AddTransition(); transition.OutgoingPlaces[0].AppendOutgoingTransition(temporaryTransition); temporaryTransition.AddIncomingPlace(transition.OutgoingPlaces[0]); temporaryTransition.AddOutgoingPlace(endingPlace); } else transition.AddOutgoingPlace(endingPlace); } } return petriNet; }
/// <summary> /// Adds an optional Transition to the net, as well as the next mandatory transition. /// </summary> /// <param name="startingTransition">The existing transition</param> /// <param name="optionalAction">The optional transition</param> /// <param name="commonAction">The mandatory transition</param> /// <param name="petriNet"></param> /// <returns></returns> /// <author>Jannik Arndt</author> public List<Transition> StartOptionalTransition(Transition startingTransition, String optionalAction, String commonAction, PetriNet petriNet) { var place1 = petriNet.AddPlace(); var place2 = petriNet.AddPlace(); startingTransition.AddOutgoingPlace(place1); petriNet.AddTransition(optionalAction, incomingPlace: place1, outgoingPlace: place2); var commonTransition = petriNet.AddTransition(commonAction, new List<Place> { place1, place2 }); return new List<Transition> { commonTransition }; }
/// <summary> /// Find loops in the eventlog and add them to the petrinet /// </summary> /// <param name="eventLog">The eventlog that is searched for loops</param> /// <param name="petriNet">The net the loops are added to</param> /// <returns>A petrinet with added loops</returns> /// <author>Jannik Arndt</author> public PetriNet HandleLoops(EventLog eventLog, PetriNet petriNet) { var loopedActivities = FindLoopingActivities(eventLog); foreach (var activity in loopedActivities) petriNet.AddLoop(activity); return petriNet; }
public void CheckCorrectFitnessBetweenEventLogAndPetrinetTest1() { // //EventLog // //create Case1 Case ca1 = new Case(); ca1.CreateEvent("A"); ca1.CreateEvent("C"); ca1.CreateEvent("D"); ca1.CreateEvent("E"); ca1.CreateEvent("H"); //create Case2 Case ca2 = new Case(); ca2.CreateEvent("A"); ca2.CreateEvent("B"); ca2.CreateEvent("D"); ca2.CreateEvent("E"); ca2.CreateEvent("G"); //create Case3 Case ca3 = new Case(); ca3.CreateEvent("A"); ca3.CreateEvent("D"); ca3.CreateEvent("C"); ca3.CreateEvent("E"); ca3.CreateEvent("H"); //create Case4 Case ca4 = new Case(); ca4.CreateEvent("A"); ca4.CreateEvent("B"); ca4.CreateEvent("D"); ca4.CreateEvent("E"); ca4.CreateEvent("H"); //create Case5 Case ca5 = new Case(); ca5.CreateEvent("A"); ca5.CreateEvent("C"); ca5.CreateEvent("D"); ca5.CreateEvent("E"); ca5.CreateEvent("G"); //create Case6 Case ca6 = new Case(); ca6.CreateEvent("A"); ca6.CreateEvent("D"); ca6.CreateEvent("C"); ca6.CreateEvent("E"); ca6.CreateEvent("G"); //create Case7 Case ca7 = new Case(); ca7.CreateEvent("A"); ca7.CreateEvent("D"); ca7.CreateEvent("B"); ca7.CreateEvent("E"); ca7.CreateEvent("H"); //create Case8 Case ca8 = new Case(); ca8.CreateEvent("A"); ca8.CreateEvent("C"); ca8.CreateEvent("D"); ca8.CreateEvent("E"); ca8.CreateEvent("F"); ca8.CreateEvent("D"); ca8.CreateEvent("B"); ca8.CreateEvent("E"); ca8.CreateEvent("H"); //create Case9 Case ca9 = new Case(); ca9.CreateEvent("A"); ca9.CreateEvent("D"); ca9.CreateEvent("B"); ca9.CreateEvent("E"); ca9.CreateEvent("G"); //create Case10 Case ca10 = new Case(); ca10.CreateEvent("A"); ca10.CreateEvent("C"); ca10.CreateEvent("D"); ca10.CreateEvent("E"); ca10.CreateEvent("F"); ca10.CreateEvent("B"); ca10.CreateEvent("D"); ca10.CreateEvent("E"); ca10.CreateEvent("H"); //create Case11 Case ca11 = new Case(); ca11.CreateEvent("A"); ca11.CreateEvent("C"); ca11.CreateEvent("D"); ca11.CreateEvent("E"); ca11.CreateEvent("F"); ca11.CreateEvent("B"); ca11.CreateEvent("D"); ca11.CreateEvent("E"); ca11.CreateEvent("G"); //create Case12 Case ca12 = new Case(); ca12.CreateEvent("A"); ca12.CreateEvent("C"); ca12.CreateEvent("D"); ca12.CreateEvent("E"); ca12.CreateEvent("F"); ca12.CreateEvent("D"); ca12.CreateEvent("B"); ca12.CreateEvent("E"); ca12.CreateEvent("G"); //create Case13 Case ca13 = new Case(); ca13.CreateEvent("A"); ca13.CreateEvent("D"); ca13.CreateEvent("C"); ca13.CreateEvent("E"); ca13.CreateEvent("F"); ca13.CreateEvent("C"); ca13.CreateEvent("D"); ca13.CreateEvent("E"); ca13.CreateEvent("H"); //create Case14 Case ca14 = new Case(); ca14.CreateEvent("A"); ca14.CreateEvent("D"); ca14.CreateEvent("C"); ca14.CreateEvent("E"); ca14.CreateEvent("F"); ca14.CreateEvent("D"); ca14.CreateEvent("B"); ca14.CreateEvent("E"); ca14.CreateEvent("H"); //create Case15 Case ca15 = new Case(); ca15.CreateEvent("A"); ca15.CreateEvent("D"); ca15.CreateEvent("C"); ca15.CreateEvent("E"); ca15.CreateEvent("F"); ca15.CreateEvent("B"); ca15.CreateEvent("D"); ca15.CreateEvent("E"); ca15.CreateEvent("G"); //create Case16 Case ca16 = new Case(); ca16.CreateEvent("A"); ca16.CreateEvent("C"); ca16.CreateEvent("D"); ca16.CreateEvent("E"); ca16.CreateEvent("F"); ca16.CreateEvent("B"); ca16.CreateEvent("D"); ca16.CreateEvent("E"); ca16.CreateEvent("F"); ca16.CreateEvent("D"); ca16.CreateEvent("B"); ca16.CreateEvent("E"); ca16.CreateEvent("G"); //create Case17 Case ca17 = new Case(); ca17.CreateEvent("A"); ca17.CreateEvent("D"); ca17.CreateEvent("C"); ca17.CreateEvent("E"); ca17.CreateEvent("F"); ca17.CreateEvent("D"); ca17.CreateEvent("B"); ca17.CreateEvent("E"); ca17.CreateEvent("G"); //create Case18 Case ca18 = new Case(); ca18.CreateEvent("A"); ca18.CreateEvent("D"); ca18.CreateEvent("C"); ca18.CreateEvent("E"); ca18.CreateEvent("F"); ca18.CreateEvent("B"); ca18.CreateEvent("D"); ca18.CreateEvent("E"); ca18.CreateEvent("F"); ca18.CreateEvent("B"); ca18.CreateEvent("D"); ca18.CreateEvent("E"); ca18.CreateEvent("G"); //create Case19 Case ca19 = new Case(); ca19.CreateEvent("A"); ca19.CreateEvent("D"); ca19.CreateEvent("C"); ca19.CreateEvent("E"); ca19.CreateEvent("F"); ca19.CreateEvent("D"); ca19.CreateEvent("B"); ca19.CreateEvent("E"); ca19.CreateEvent("F"); ca19.CreateEvent("B"); ca19.CreateEvent("D"); ca19.CreateEvent("E"); ca19.CreateEvent("H"); //create Case20 Case ca20 = new Case(); ca20.CreateEvent("A"); ca20.CreateEvent("D"); ca20.CreateEvent("B"); ca20.CreateEvent("E"); ca20.CreateEvent("F"); ca20.CreateEvent("B"); ca20.CreateEvent("D"); ca20.CreateEvent("E"); ca20.CreateEvent("F"); ca20.CreateEvent("D"); ca20.CreateEvent("B"); ca20.CreateEvent("E"); ca20.CreateEvent("G"); //create Case21 Case ca21 = new Case(); ca21.CreateEvent("A"); ca21.CreateEvent("D"); ca21.CreateEvent("C"); ca21.CreateEvent("E"); ca21.CreateEvent("F"); ca21.CreateEvent("D"); ca21.CreateEvent("B"); ca21.CreateEvent("E"); ca21.CreateEvent("F"); ca21.CreateEvent("C"); ca21.CreateEvent("D"); ca21.CreateEvent("E"); ca21.CreateEvent("F"); ca21.CreateEvent("D"); ca21.CreateEvent("B"); ca21.CreateEvent("E"); ca21.CreateEvent("G"); //create Event Log EventLog eventLog = new EventLog(); eventLog.Cases.Add(ca1); eventLog.Cases.Add(ca2); eventLog.Cases.Add(ca3); eventLog.Cases.Add(ca4); eventLog.Cases.Add(ca5); eventLog.Cases.Add(ca6); eventLog.Cases.Add(ca7); eventLog.Cases.Add(ca8); eventLog.Cases.Add(ca9); eventLog.Cases.Add(ca10); eventLog.Cases.Add(ca11); eventLog.Cases.Add(ca12); eventLog.Cases.Add(ca13); eventLog.Cases.Add(ca14); eventLog.Cases.Add(ca15); eventLog.Cases.Add(ca16); eventLog.Cases.Add(ca17); eventLog.Cases.Add(ca18); eventLog.Cases.Add(ca19); eventLog.Cases.Add(ca20); eventLog.Cases.Add(ca21); // //PetriNet // PetriNet petriNet = new PetriNet("Petri-Net Name"); Place pStart = new Place("Place Start", 0); Place pC1 = new Place("c1", 0); Place pC2 = new Place("c2", 0); Place pC3 = new Place("c3", 0); Place pC4 = new Place("c4", 0); Place pC5 = new Place("c5", 0); Place pEnd = new Place("Place End", 0); Transition tA = new Transition("A"); Transition tB = new Transition("B"); Transition tC = new Transition("C"); Transition tD = new Transition("D"); Transition tE = new Transition("E"); Transition tF = new Transition("F"); Transition tG = new Transition("G"); Transition tH = new Transition("H"); tG.AddOutgoingPlace(pEnd); tG.AddIncomingPlace(pC5); tH.AddOutgoingPlace(pEnd); tH.AddIncomingPlace(pC5); tE.AddIncomingPlace(pC3); tE.AddIncomingPlace(pC4); tE.AddOutgoingPlace(pC5); pC3.AppendIncomingTransition(tB); pC3.AppendIncomingTransition(tC); pC3.AppendOutgoingTransition(tE); pC4.AppendOutgoingTransition(tE); tB.AddIncomingPlace(pC1); tB.AddOutgoingPlace(pC3); tC.AddIncomingPlace(pC1); tC.AddOutgoingPlace(pC3); tD.AddIncomingPlace(pC2); tD.AddOutgoingPlace(pC4); pC1.AppendIncomingTransition(tA); pC1.AppendOutgoingTransition(tB); pC1.AppendOutgoingTransition(tC); pC2.AppendIncomingTransition(tA); pC2.AppendOutgoingTransition(tD); tF.AddIncomingPlace(pC5); tF.AddOutgoingPlace(pC1); tF.AddOutgoingPlace(pC2); // tA.AddIncomingPlace(pStart); tA.AddOutgoingPlace(pC1); tA.AddOutgoingPlace(pC2); pStart.AppendOutgoingTransition(tA); pEnd.AppendIncomingTransition(tG); pEnd.AppendIncomingTransition(tH); //// petriNet.Transitions.Add(tA); petriNet.Transitions.Add(tB); petriNet.Transitions.Add(tC); petriNet.Transitions.Add(tD); petriNet.Transitions.Add(tE); petriNet.Transitions.Add(tF); petriNet.Transitions.Add(tG); petriNet.Transitions.Add(tH); //// petriNet.Places.Add(pStart); petriNet.Places.Add(pC1); petriNet.Places.Add(pC2); petriNet.Places.Add(pC3); petriNet.Places.Add(pC4); petriNet.Places.Add(pC5); petriNet.Places.Add(pEnd); ComparingFootprintResultMatrix matrix = new ComparingFootprintResultMatrix(ComparingFootprintAlgorithm.CreateFootprint(eventLog), ComparingFootprintAlgorithm.CreateFootprint(petriNet)); double fitness = ComparingFootprintAlgorithm.CalculateFitness(matrix.GetNumberOfDifferences(), matrix.GetNumberOfOpportunities()); if (Math.Abs(fitness - 1.0) > 0.0001) { Assert.Fail("Fitness not correct! (" + fitness + ")"); } }
/// <summary> /// Depending on the count of followers this adds one (or more) places and their following transitions. /// </summary> /// <param name="event1"></param> /// <param name="node">An event node</param> /// <param name="log">The current event log</param> /// <param name="petriNet"></param> /// <returns>The newly added transitions. This is where you need to continue working.</returns> /// <exception cref="NotImplementedException">If there are more than 3 followers in a non-trivial relation.</exception> /// <author>Jannik Arndt</author> public List<Transition> HandleNode(Transition event1, EventNode node, EventLog log, PetriNet petriNet) { // Case: No followers if (node.ListOfFollowers.Count == 0) return new List<Transition>(); // one or more more followers => count the AND-relations var andRelations = CountANDRelations(node, log); // Case: All nodes are AND-related if (andRelations == node.ListOfFollowers.Count) return StartAND(event1, node.ListOfFollowers, petriNet); // Case: All nodes are XOR-related if (andRelations == 0) return StartXOR(event1, node.ListOfFollowers, petriNet); // Case: 3 Followers if (node.ListOfFollowers.Count == 3) { var x = node; var a = node.ListOfFollowers[0]; var b = node.ListOfFollowers[1]; var c = node.ListOfFollowers[2]; if (andRelations == 2) // XOR-Relations == 1 { // There are two and-relations and one xor-relation. Find the xor and order the parameters accordingly if (IsXorRelation(x.InnerEvent, b.InnerEvent, c.InnerEvent, log)) return StartAand_BxorC(event1, a, b, c, petriNet); if (IsXorRelation(x.InnerEvent, a.InnerEvent, c.InnerEvent, log)) return StartAand_BxorC(event1, b, a, c, petriNet); if (IsXorRelation(x.InnerEvent, a.InnerEvent, b.InnerEvent, log)) return StartAand_BxorC(event1, c, a, b, petriNet); } else // XOR-Relations == 2 && AND-Relations == 1 { // There are two xor-relations and one and-relation. Find the and and order the parameters accordingly if (IsAndRelation(x.InnerEvent, b.InnerEvent, c.InnerEvent, log)) return StartAxor_BandC(event1, a, b, c, petriNet); if (IsAndRelation(x.InnerEvent, a.InnerEvent, c.InnerEvent, log)) return StartAxor_BandC(event1, b, a, c, petriNet); if (IsAndRelation(x.InnerEvent, a.InnerEvent, b.InnerEvent, log)) return StartAxor_BandC(event1, c, a, b, petriNet); } } if (node.ListOfFollowers.Count > 3) return StartXOR(event1, node.ListOfFollowers, petriNet); // optional transition if (node.ListOfFollowers.Count == 2) if (log.EventFollowsEvent(node.ListOfFollowers[0].InnerEvent, node.ListOfFollowers[1].InnerEvent) > 0) return StartOptionalTransition(event1, node.ListOfFollowers[0].InnerEvent.Name, node.ListOfFollowers[1].InnerEvent.Name, petriNet); else if (log.EventFollowsEvent(node.ListOfFollowers[1].InnerEvent, node.ListOfFollowers[0].InnerEvent) > 0) return StartOptionalTransition(event1, node.ListOfFollowers[1].InnerEvent.Name, node.ListOfFollowers[0].InnerEvent.Name, petriNet); return null; }
/// <summary> /// Adds a place for each transition, then combines these places in the given transition. /// </summary> /// <param name="startingTransition">The starting transition</param> /// <param name="petriNet">The current petri net</param> /// <param name="endingTransition">The ending transition, if it exists already. Otherwise a new one is created></param> /// <returns>The transition where the places after the AND-related-events are connected.</returns> /// <author>Jannik Arndt</author> public List<Transition> EndAND(List<Transition> startingTransition, PetriNet petriNet, Transition endingTransition = null) { if (endingTransition == null) endingTransition = petriNet.AddTransition(); if (_openParallelismCount.Count > 0) _openParallelismCount.Pop(); var listOfClosingPlaces = new List<Place>(); foreach (var transition in startingTransition) { var newPlace = petriNet.AddPlace(); transition.AddOutgoingPlace(newPlace); listOfClosingPlaces.Add(newPlace); } endingTransition.AddIncomingPlaces(listOfClosingPlaces); return new List<Transition> { endingTransition }; }
/// <summary> /// This method is not finished yet /// /// The method returns a list of shapes that are between two transitions /// </summary> /// <param name="t1">Transitionname</param> /// <param name="t2">Transitionname</param> /// <param name="conformanceCheckingCanvas"></param> /// <param name="petriNet">Petrinet</param> /// <autor>Andrej Albrecht</autor> private IEnumerable<Shape> GetArrowsBetweenTransitions(String t1, String t2, Canvas conformanceCheckingCanvas, PetriNet petriNet) { List<Place> listOfPlacesWithBadLines = GetListOfPlacesBetweenTwoTransitionsFromPetriNet(t1, t2, petriNet); List<Point2D> listWithPointsTo = GetListWithPointsToFromCanvas(t1, t2, conformanceCheckingCanvas); List<Point2D> listWithPointsFrom = GetListWithPointsFromCanvas(listOfPlacesWithBadLines, conformanceCheckingCanvas); List<Shape> listOfArrowsToBeMarked = GetListOfArrowsToBeMarked(conformanceCheckingCanvas, listWithPointsFrom, listWithPointsTo); List<Shape> listOfLinesToBeMarked = new List<Shape>(); foreach (Object kind in conformanceCheckingCanvas.Children) { if (kind is Line) { // Line KindP = (Line)Kind; foreach (Shape shapeArrow in listOfArrowsToBeMarked) { if (shapeArrow is Arrow) { // Arrow Arrow = (Arrow)ShapeArrow; //Place for the method who gets the lines and not only the arrows of the canvas: //Started with the following algorithm that not worked now. /* //if (pointFrom.Equals(new Point2D(arrow.X1, arrow.Y1)) && pointTo.Equals(new Point2D(arrow.X2, arrow.Y2)) // && KindP.X1==arrow.ArrowX1 && KindP.X2==arrow.ArrowX2 && KindP.Y1==arrow.ArrowY1 && KindP.Y2==arrow.ArrowY2) if (arrow.ArrowX1 == KindP.X1 && arrow.ArrowY1 == KindP.Y1 && arrow.ArrowX2 == KindP.X1 && arrow.ArrowY2 == KindP.Y2) { System.Console.WriteLine("BadLine xFrom:" + arrow.ArrowX1 + " yFrom:" + arrow.ArrowY1 + " xTo:" + arrow.ArrowX2 + " yTo:" + arrow.ArrowY2 + " Name:" + arrow.Name); listOfLinesToBeMarked.Add(KindP); } */ } } } } return listOfArrowsToBeMarked.Union(listOfLinesToBeMarked).ToList(); }