/// <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> /// 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 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> /// 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> /// 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> /// 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 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> /// 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> /// 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; }