示例#1
0
        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]]);
                }
            }
        }
示例#2
0
        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));
            }
        }
示例#3
0
        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);
        }
示例#4
0
        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));
            }
        }
示例#5
0
        /// <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));
        }
示例#6
0
        /// <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);
            }
        }
示例#8
0
        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);
        }
示例#9
0
 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());
     }
 }
示例#11
0
        /// <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();
 }
示例#14
0
 /// <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;
         }
     }
 }
示例#15
0
        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);
        }
示例#16
0
        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);
        }
示例#17
0
        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);
        }
示例#18
0
        /// <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;
        }
示例#19
0
        /// <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);
        }
示例#20
0
        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));
        }
示例#21
0
        /// <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;
 }
示例#24
0
 public TraceGenerator(IPetriNet net, int maxLength = 10)
 {
     Net       = net;
     MaxLength = maxLength;
 }
示例#25
0
        /// <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);
                }
            }
        }
示例#26
0
 /// <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));
 }
示例#27
0
 public PetriNetSimulator(IPetriNet net)
 {
     this.net = net;
 }