public void AnalyzeCyclePetriNetTest() { // Arrange RelationMatrix originalMatrix = MakeCycleNetRelationMatrix(); IPetriNet originalNet = MakeCycleNetPetriNet(); // Act RelationMatrix matrix = PetriNetAnalyzer.MakeRelationMatrix(originalNet); // Assert Assert.AreEqual(5, matrix.Activities.Count); foreach (string act in matrix.Activities) { Assert.IsTrue(originalMatrix.Activities.Contains(act)); } Assert.AreEqual(1, matrix.StartActivities.Count); Assert.IsTrue(matrix.StartActivities.Contains("a")); Assert.AreEqual(1, matrix.EndActivities.Count); Assert.IsTrue(matrix.EndActivities.Contains("e")); foreach (string actI in matrix.Activities) { foreach (string actJ in matrix.Activities) { Assert.AreEqual(originalMatrix.Footprint[originalMatrix.ActivityIndices[actI], originalMatrix.ActivityIndices[actJ]], matrix.Footprint[matrix.ActivityIndices[actI], matrix.ActivityIndices[actJ]]); } } }
public void PNMLImportTest() { // Arrange IPetriNet loadedNet; IPetriNet exampleNet = MakeEasyPetriNet(); // Act loadedNet = PNMLImport.Deserialize(PNMLpath); // Assert Assert.IsNotNull(loadedNet); Assert.AreEqual(loadedNet.EndPlace.Id, exampleNet.EndPlace.Id); Assert.AreEqual(loadedNet.StartPlace.Id, exampleNet.StartPlace.Id); Assert.AreEqual(loadedNet.Places.Count, exampleNet.Places.Count); Assert.AreEqual(loadedNet.Transitions.Count, exampleNet.Transitions.Count); foreach (IPlace p in loadedNet.Places) { Assert.IsTrue(exampleNet.Places.Exists(a => a.Id == p.Id)); } foreach (ITransition t in loadedNet.Transitions) { Assert.IsTrue(exampleNet.Transitions.Exists(a => a.Id == t.Id && a.Activity == t.Activity && a.InputPlaces.Count == t.InputPlaces.Count && a.OutputPlaces.Count == t.OutputPlaces.Count)); } }
public void MakeEmptyPetriNetTest() { // Arrange List <string> activities = new List <string>() { "wake up", "have coffee", "have tea", "work", "go home", "go sleep", "play witcher" }; HashSet <string> startActivities = new HashSet <string>() { "wake up" }; HashSet <string> endActivities = new HashSet <string>() { "go sleep", "play witcher" }; RelationMatrix matrix = new RelationMatrix(activities, startActivities, endActivities); // Act IPetriNet madeNet = Alpha.MakePetriNet(matrix); // Assert Assert.IsNotNull(madeNet); Assert.AreEqual("p1", madeNet.EndPlace.Id); Assert.AreEqual("p0", madeNet.StartPlace.Id); Assert.AreEqual(2, madeNet.Places.Count); Assert.AreEqual(7, madeNet.Transitions.Count); }
public void MakeEasyPetriNetTest() { // Arrange ImportedEventLog elog = CSVImport.MakeDataFrame(easyCsv); elog.SetActivity("act"); elog.SetCaseId("id"); WorkflowLog wlog = new WorkflowLog(elog); RelationMatrix matrix = new RelationMatrix(wlog); IPetriNet exampleNet = MakeEasyPetriNet(); // Act IPetriNet madeNet = Alpha.MakePetriNet(matrix); // Assert Assert.IsNotNull(exampleNet); Assert.AreEqual(exampleNet.EndPlace.Id, madeNet.EndPlace.Id); Assert.AreEqual(exampleNet.StartPlace.Id, madeNet.StartPlace.Id); Assert.AreEqual(exampleNet.Places.Count, madeNet.Places.Count); Assert.AreEqual(exampleNet.Transitions.Count, madeNet.Transitions.Count); foreach (IPlace p in exampleNet.Places) { Assert.IsTrue(madeNet.Places.Exists(a => a.Id == p.Id)); } foreach (ITransition t in exampleNet.Transitions) { Assert.IsTrue(madeNet.Transitions.Exists(a => a.Id == t.Id && a.Activity == t.Activity && a.InputPlaces.Count == t.InputPlaces.Count && a.OutputPlaces.Count == t.OutputPlaces.Count)); } }
/// <summary> /// Computes token-based replay fitness of given event log to a given Petri Net. /// </summary> /// <param name="log">Event log to be replayed.</param> /// <param name="net">Petri net used for replaying given traces.</param> /// <returns>Fitness metric of given event log to given Petri Net.</returns> public static double ComputeFitness(ImportedEventLog log, IPetriNet net) { PetriNetTokenDiagnosticsOverlay netDiagnostics = new PetriNetTokenDiagnosticsOverlay(net); WorkflowLog eventLog = new WorkflowLog(log); foreach (WorkflowTrace t in eventLog.WorkflowTraces) { netDiagnostics.ReplayTrace(t); } double sumProduced = 0; double sumConsumed = 0; double sumMissing = 0; double sumRemaining = 0; foreach (PlaceTokenDiagnosticsOverlay diagnostics in netDiagnostics.Diagnostics.Values) { sumProduced += diagnostics.Produced; sumConsumed += diagnostics.Consumed; sumMissing += diagnostics.Missing; sumRemaining += diagnostics.Remaining; } if (sumConsumed == 0 && sumProduced == sumRemaining && sumProduced == sumMissing) // this should only be true if compared log is 100% different from given Petri Net. { return(0.0); } return(0.5 * (1 - sumMissing / sumConsumed) + 0.5 * (1 - sumRemaining / sumProduced)); }
/// <summary> /// Serializes given Petri Net compliant with IPetriNet interface to a PNML file with .xml extension. /// </summary> /// <param name="net">An IPetriNet compliant Petri Net.</param> /// <returns>Filename of created file.</returns> public static string Serialize(IPetriNet net) { XNamespace ns = "http://www.pnml.org/version-2009/grammar/pnml"; XElement xRoot = GetPnmlHeader(ns); XElement xNet = GetNetNode(ns); xRoot.Add(xNet); XElement xPage = GetPageNode(ns); xNet.Add(xPage); AddPlaces(xPage, net.Places, ns); AddTransitions(xPage, net.Transitions, ns); AddArcs(xPage, net.Transitions, ns); XmlWriterSettings settings = new XmlWriterSettings { Indent = true, IndentChars = ("\t") }; string filename = "petrinet" + DateTime.Now.ToString().Replace('.', '-').Replace(':', '-') + ".xml"; using (XmlWriter writer = XmlWriter.Create(filename, settings)) { xRoot.Save(writer); } return(filename); }
/// <summary> /// Init transitions from the Petri net /// </summary> /// <param name="pNet">Petri net</param> /// <param name="cost">Cost</param> /// <param name="moveOnModel">Model Petri net (true), Trace Petri net (false)</param> private void InitTransitionsFromPNet(IPetriNet pNet, int cost, bool moveOnModel) { foreach (var transition in pNet.Transitions) { var productTransition = new Transition( moveOnModel ? $"(>>,{transition.Id})" : $"({transition.Id},>>)", transition.Activity); if (transition.Invisible) { productTransition.ChangeVisibility(); } foreach (var iPlace in transition.InputPlaces) { productTransition.InputPlaces.Add(iPlace); } foreach (var oPlace in transition.OutputPlaces) { productTransition.OutputPlaces.Add(oPlace); } // cost 0 for "invisible" transitions var syncTransition = new STransition(productTransition, transition.Invisible ? 0 : cost); foreach (var place in transition.InputPlaces) { PlacesToTransitions[place].Add(Transitions.Count); } Transitions.Add(syncTransition); } }
public void PNMLExportTest() { // Arrange IPetriNet loadedNet; IPetriNet exampleNet = MakeEasyPetriNet(); // Act string filepath = "." + separator + PNMLExport.Serialize(exampleNet); loadedNet = PNMLImport.Deserialize(filepath); // Assert Assert.IsNotNull(loadedNet); Assert.AreEqual(loadedNet.EndPlace.Id, exampleNet.EndPlace.Id); Assert.AreEqual(loadedNet.StartPlace.Id, exampleNet.StartPlace.Id); Assert.AreEqual(loadedNet.Places.Count, exampleNet.Places.Count); Assert.AreEqual(loadedNet.Transitions.Count, exampleNet.Transitions.Count); foreach (IPlace p in loadedNet.Places) { exampleNet.Places.Exists(a => a.Id == p.Id); } foreach (ITransition t in loadedNet.Transitions) { exampleNet.Transitions.Exists(a => a.Id == t.Id && a.Activity == t.Activity && a.InputPlaces.Count == t.InputPlaces.Count && a.OutputPlaces.Count == t.OutputPlaces.Count); } // Cleanup File.Delete(filepath); }
public PetriNetSimulator(IPetriNet <Token> net) { if (net == null) { throw new ArgumentNullException("net"); } this.net = net; }
public PetriNetTokenDiagnosticsOverlay(IPetriNet net) { PetriNet = net; Diagnostics = new Dictionary <string, PlaceTokenDiagnosticsOverlay>(); foreach (IPlace p in net.Places) { Diagnostics.Add(p.Id, new PlaceTokenDiagnosticsOverlay()); } }
/// <summary> /// Gets called when the parent model element of the current model element is about to change /// </summary> /// <param name="oldParent">The old parent model element</param> /// <param name="newParent">The new parent model element</param> protected override void OnParentChanging(IModelElement newParent, IModelElement oldParent) { IPetriNet oldNet = ModelHelper.CastAs <IPetriNet>(oldParent); IPetriNet newNet = ModelHelper.CastAs <IPetriNet>(newParent); ValueChangedEventArgs e = new ValueChangedEventArgs(oldNet, newNet); this.OnNetChanging(e); this.OnPropertyChanging("Net", e, _netReference); }
/// <summary> /// Creates Synchronous net from the Petri net itself /// </summary> /// <param name="pNet">Petri net</param> /// <param name="modelMoveCost">Model move cost</param> public SynchronousProductNet(IPetriNet pNet, int modelMoveCost = 1) { StartPlaces.Add(pNet.StartPlace); EndPlaces.Add(pNet.EndPlace); Places = pNet.Places; PlacesToTransitions = Places.ToDictionary(p => p, p => new List <int>()); InitTransitionsFromPNet(pNet, modelMoveCost, true); }
public PetriNetTokenTraverseOverlay(IPetriNet petriNet) { PetriNet = petriNet; TransitionsWithFootprints = new List <TransitionTokenTraverseOverlay>(); PlacesWithFootprints = new List <PlaceTokenTraverseOverlay>(); SetUpPlacesOverlay(petriNet.Places); SetUpTransitionsOverlay(petriNet.Transitions); TraverseAndMakeFootprints(); }
/// <summary> /// Adds the given element to the collection /// </summary> /// <param name="item">The item to add</param> public override void Add(IModelElement item) { if ((this._parent.Net == null)) { IPetriNet netCasted = item.As <IPetriNet>(); if ((netCasted != null)) { this._parent.Net = netCasted; return; } } }
public void CompareEasyPetriNetWithSameMatrixTest() { // Arrange RelationMatrix matrixA = MakeEasyRelationMatrix(); IPetriNet net = MakeEasyPetriNet(); RelationMatrix matrixB = PetriNetAnalyzer.MakeRelationMatrix(net); // Act double fitness = FootprintComparer.Compare(matrixA, matrixB); // Assert Assert.AreEqual(1.0, fitness); }
public void DOTExportImportTest() { // Arrange IPetriNet exampleNet = MakeEasyPetriNet(); string exampleDot = MakeEasyDOT(); // Act string filepath = DOTExport.Serialize(exampleNet); string loadedDot = File.ReadAllText("." + separator + filepath); // Assert Assert.AreEqual(exampleDot, loadedDot); // Cleanup File.Delete(filepath); }
public void CompareLogWithAccordingPetriNetTest() { // Arrange ImportedEventLog elog = CSVImport.MakeDataFrame(hardCsv); elog.SetActivity("act"); elog.SetCaseId("id"); WorkflowLog wlog = new WorkflowLog(elog); RelationMatrix matrix = new RelationMatrix(wlog); IPetriNet madeNet = Alpha.MakePetriNet(matrix); // Act double fitness = Computations.ComputeFitness(elog, madeNet); // Assert Assert.AreEqual(1.0, fitness); }
/// <summary> /// Serializes given Petri Net compliant with IPetriNet interface to a .DOT file. /// </summary> /// <param name="net">An IPetriNet compliant Petri Net.</param> /// <param name="indentation">Indentation symbol, this class uses "\t" as default.</param> /// <returns>Filename of created file.</returns> public static string Serialize(IPetriNet net, string indentation = "\t") { StringBuilder outStr = new StringBuilder(""); outStr.Append(GetGraphHeader()); outStr.Append(GetPlaces(net.Places, indentation)); outStr.Append(GetTransitions(net.Transitions, indentation)); outStr.Append(GetArcs(net.Transitions, indentation)); string filename = "petrinet" + DateTime.Now.ToString().Replace('.', '-').Replace(':', '-') + ".dot"; using (var fileStream = new FileStream(filename, FileMode.Create)) { using (var streamWriter = new StreamWriter(fileStream)) { streamWriter.Write(outStr.ToString()); } } return filename; }
/// <summary> /// Gets called when the parent model element of the current model element changes /// </summary> /// <param name="oldParent">The old parent model element</param> /// <param name="newParent">The new parent model element</param> protected override void OnParentChanged(IModelElement newParent, IModelElement oldParent) { IPetriNet oldNet = ModelHelper.CastAs <IPetriNet>(oldParent); IPetriNet newNet = ModelHelper.CastAs <IPetriNet>(newParent); if ((oldNet != null)) { oldNet.Elements.Remove(this); } if ((newNet != null)) { newNet.Elements.Add(this); } ValueChangedEventArgs e = new ValueChangedEventArgs(oldNet, newNet); this.OnNetChanged(e); this.OnPropertyChanged("Net", e, _netReference); base.OnParentChanged(newParent, oldParent); }
public void CompareMildlyTamperedLogWithHardPetriNetTest() { // Arrange ImportedEventLog elog = CSVImport.MakeDataFrame(hardCsv); elog.SetActivity("act"); elog.SetCaseId("id"); WorkflowLog wlog = new WorkflowLog(elog); RelationMatrix matrix = new RelationMatrix(wlog); IPetriNet madeNet = Alpha.MakePetriNet(matrix); ImportedEventLog tamperedLog = CSVImport.MakeDataFrame(tamperedHardCsv); tamperedLog.SetActivity("act"); tamperedLog.SetCaseId("id"); // Act double fitness = Computations.ComputeFitness(tamperedLog, madeNet); // Assert Assert.AreEqual(96, (int)(fitness*100)); }
/// <summary> /// Creates a relation matrix accordingly to given Petri Net. /// </summary> /// <param name="net">Petri Net to be analyzed.</param> /// <returns>RelationMatrix of given Petri Net.</returns> public static RelationMatrix MakeRelationMatrix(IPetriNet net) { List <string> activities = GetActivities(net.Transitions); HashSet <string> startActivities = GetStartActivities(net.Transitions, net.StartPlace); HashSet <string> endActivities = GetEndActivities(net.Transitions, net.EndPlace); RelationMatrix matrix = new RelationMatrix(activities, startActivities, endActivities); foreach (ITransition t in net.GetStartTransitions()) { FindSuccessions(ref matrix, t, net); } var analysisOverlay = new PetriNetTokenTraverseOverlay(net); FindParallelism(ref matrix, analysisOverlay); UpdatePredecessions(ref matrix); return(matrix); }
/// <param name="tNet">Petri net of the trace</param> /// <param name="pNet">Petri net of the model</param> /// <param name="traceMoveCost">Trace move cost</param> /// <param name="modelMoveCost">Model move cost</param> public SynchronousProductNet(IPetriNet tNet, IPetriNet pNet, int traceMoveCost = 1, int modelMoveCost = 1) { StartPlaces.Add(tNet.StartPlace); StartPlaces.Add(pNet.StartPlace); EndPlaces.Add(tNet.EndPlace); EndPlaces.Add(pNet.EndPlace); Places.AddRange(tNet.Places.Union(pNet.Places)); PlacesToTransitions = Places.ToDictionary(p => p, p => new List <int>()); InitTransitionsFromPNet(tNet, traceMoveCost, false); InitTransitionsFromPNet(pNet, modelMoveCost, true); //Add transitions for synchronous move as cost 0 + addition to make all costs positive foreach (var t1 in tNet.Transitions) { foreach (var t2 in pNet.Transitions) { if (!t1.Activity.Equals(t2.Activity)) { continue; } var transition = new Transition($"({t1.Id},{t2.Id})", t1.Activity); transition.InputPlaces.AddRange(t1.InputPlaces.Union(t2.InputPlaces)); transition.OutputPlaces.AddRange(t1.OutputPlaces.Union(t2.OutputPlaces)); var syncTransition = new STransition(transition, 0); foreach (var place in transition.InputPlaces) { PlacesToTransitions[place].Add(Transitions.Count); } Transitions.Add(syncTransition); } } }
public PetriNetSimulator(IPetriNet net) { this.net = net; }
public TraceGenerator(IPetriNet net, int maxLength = 10) { Net = net; MaxLength = maxLength; }
/// <summary> /// Finds all transitions that come directly after the beginningTransition in given Petri Net and updates given Relation DirectDependencyMatrix accordingly. /// </summary> /// <param name="matrix">A relation matrix of analyzed Petri Net.</param> /// <param name="beginningTransition">A beginning transition.</param> /// <param name="net">Analyzed Petri Net.</param> private static void FindSuccessions(ref RelationMatrix matrix, ITransition beginningTransition, IPetriNet net) { int fromIndex = matrix.ActivityIndices[beginningTransition.Activity]; List <int> toIndices = new List <int>(); List <ITransition> nextTransitions = new List <ITransition>(); foreach (ITransition t in net.Transitions) { foreach (IPlace op in beginningTransition.OutputPlaces) { if (t.InputPlaces.Contains(op)) { toIndices.Add(matrix.ActivityIndices[t.Activity]); nextTransitions.Add(t); } } } foreach (int toIndex in toIndices) { matrix.Footprint[fromIndex, toIndex] = Relation.Succession; } foreach (ITransition t in nextTransitions) { bool visited = false; for (int i = 0; i < matrix.Activities.Count; i++) { if (matrix.Footprint[matrix.ActivityIndices[t.Activity], i] == Relation.Succession) { visited = true; } } if (!visited) { FindSuccessions(ref matrix, t, net); } } }
/// <summary> /// Initializes a new instance of the <see cref="PetriNetSimulator{TToken}"/> class. /// </summary> /// <param name="net">Petri net to simulate.</param> /// <exception cref="T:System.ArgumentNullException"><paramref name="net"/> is <see langword="null"/>.</exception> public PetriNetSimulator([NotNull] IPetriNet <TToken> net) { Net = net ?? throw new ArgumentNullException(nameof(net)); }