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 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)); } }
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); }
private RelationMatrix MakeEasyNonMatchingIndicesMatrix() { List <string> activities = new List <string>() { "c", "b", "a", "d" }; HashSet <string> startActivities = new HashSet <string>() { "a" }; HashSet <string> endActivities = new HashSet <string>() { "c" }; RelationMatrix matrix = new RelationMatrix(activities, startActivities, endActivities); matrix.Footprint[0, 1] = Relation.Predecession; // d <- c matrix.Footprint[0, 3] = Relation.Predecession; // b <- c matrix.Footprint[1, 0] = Relation.Succession; // d -> c matrix.Footprint[1, 2] = Relation.Predecession; // a <- d matrix.Footprint[2, 1] = Relation.Succession; // a -> d matrix.Footprint[2, 3] = Relation.Succession; // a -> b matrix.Footprint[3, 0] = Relation.Succession; // b -> c matrix.Footprint[3, 2] = Relation.Predecession; // a <- b return(matrix); }
private RelationMatrix MakeCycleNetRelationMatrix() { List <string> activities = new List <string>() { "a", "b", "c", "d", "e" }; HashSet <string> startActivities = new HashSet <string>() { "a" }; HashSet <string> endActivities = new HashSet <string>() { "e" }; RelationMatrix matrix = new RelationMatrix(activities, startActivities, endActivities); matrix.Footprint[0, 1] = Relation.Succession; // a -> b matrix.Footprint[1, 0] = Relation.Predecession; // b <- a matrix.Footprint[1, 2] = Relation.Succession; // b -> c matrix.Footprint[2, 1] = Relation.Predecession; // c <- b matrix.Footprint[2, 3] = Relation.Succession; // c -> d matrix.Footprint[3, 2] = Relation.Predecession; // d <- c matrix.Footprint[3, 1] = Relation.Succession; // d -> b matrix.Footprint[1, 3] = Relation.Predecession; // d <- b matrix.Footprint[2, 4] = Relation.Succession; // c -> e matrix.Footprint[4, 2] = Relation.Predecession; // c <- e return(matrix); }
/// <summary> /// Calculates causal footprint comparison of two Relation Matrices. /// </summary> /// <param name="matrixA">First RelationMatrix to be compared.</param> /// <param name="matrixB">Second RelationMatrix to be compared.</param> /// <returns>Fitness metric of both matrices.</returns> public static double Compare(RelationMatrix matrixA, RelationMatrix matrixB) { if (IndicesAreMatching(matrixA.ActivityIndices, matrixB.ActivityIndices)) { return(CalculateWhenIndicesMatch(matrixA, matrixB)); } return(Calculate(matrixA, matrixB)); }
//Метод получения первичной информации о связях таблиц из БД private bool GetDBTablesRelations(RelationMatrix relationMatrix) { ; using (var sConn = new NpgsqlConnection(sConnStr)) { //Проверка подключения try { sConn.Open(); } catch { return(false); } //Формируем команду var sCommand = new NpgsqlCommand { Connection = sConn, CommandText = @" SELECT t1.table_name AS base_table, t1.column_name AS base_column, t2.table_name AS aim_table, t2.column_name AS aim_column FROM information_schema.key_column_usage AS t1 JOIN information_schema.constraint_column_usage AS t2 ON t1.constraint_schema = t2.constraint_schema AND t1.constraint_name = t2.constraint_name JOIN information_schema.table_constraints AS t3 ON t2.constraint_schema = t3.constraint_schema AND t2.constraint_name = t3.constraint_name WHERE t3.constraint_type = 'FOREIGN KEY' AND t1.constraint_schema = 'public' " }; //Запрос и заполнение списка using (var reader = sCommand.ExecuteReader()) { while (reader.Read()) { var baseTableName = (string)reader["base_table"]; var baseColumnName = (string)reader["base_column"]; var aimTableName = (string)reader["aim_table"]; var aimColumnName = (string)reader["aim_column"]; string connectionCondition = $"\"{baseTableName}\".\"{baseColumnName}\" = \"{aimTableName}\".\"{aimColumnName}\""; //Создаём двухстороннюю связь relationMatrix[baseTableName][aimTableName] = new RelationMatixElem { ViaTable = aimTableName, ConnectionCondition = connectionCondition }; relationMatrix[aimTableName][baseTableName] = new RelationMatixElem { ViaTable = baseTableName, ConnectionCondition = connectionCondition }; } } } return(true); }
public void CompareDifferentMatricesTest() { // Arrange RelationMatrix matrixA = MakeEasyRelationMatrix(); RelationMatrix matrixB = MakeHardRelationMatrix(); // Act double fitness = FootprintComparer.Compare(matrixA, matrixB); // Assert Assert.AreNotEqual(1.0, fitness); }
public void AnalyzeMatricesWithNonMatchingIndicesTest() { // Arrange RelationMatrix matrixA = MakeEasyRelationMatrix(); RelationMatrix matrixB = MakeEasyNonMatchingIndicesMatrix(); // Act double fitness = FootprintComparer.Compare(matrixA, matrixB); // Assert Assert.AreEqual(1.0, fitness); }
/// <summary> /// Creates a Petri Net from given relation matrix. /// </summary> /// <param name="matrix">A RelationMatrix used for creating a Petri Net.</param> /// <returns>Created PetriNet object.</returns> public static PetriNet MakePetriNet(RelationMatrix matrix) { List <ITransition> transitions = GetTransitions(matrix.Activities); List <IPlace> places = new List <IPlace>(); HashSet <HashSet <string> > independentSets = IndependentSetUtils.FindIndependentSets(matrix.Footprint, matrix.Activities); HashSet <Tuple <HashSet <string>, HashSet <string> > > setsAB = IndependentSetUtils.FindMaximalIndependentSetsAB(independentSets, matrix.Footprint, matrix.ActivityIndices); int id = SetupStartPlace(places, matrix.StartActivities, transitions); id = SetupPlaces(setsAB, places, transitions, id); SetupEndPlace(places, matrix.EndActivities, transitions, id); return(new PetriNet(transitions, places, places[0], places[^ 1]));
/// <summary> /// Goes through all fields in Relation matrix and marks predecessions accordingly. /// Successions and parallelism needs to be already marked. /// </summary> /// <param name="matrix">A relation matrix of analyzed Petri Net.</param> private static void UpdatePredecessions(ref RelationMatrix matrix) { for (int from = 0; from < matrix.Activities.Count; from++) { for (int to = 0; to < matrix.Activities.Count; to++) { if (matrix.Footprint[from, to] == Relation.Succession) { matrix.Footprint[to, from] = Relation.Predecession; } } } }
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 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> /// Calculates causal footprint comparison when indices of both matrices match. /// </summary> /// <param name="matrixA">First RelationMatrix to be compared.</param> /// <param name="matrixB">Second RelationMatrix to be compared.</param> /// <returns>Fitness metric of both matrices.</returns> private static double CalculateWhenIndicesMatch(RelationMatrix matrixA, RelationMatrix matrixB) { int bound = matrixA.Activities.Count; int match = 0; int size = bound * bound; for (int i = 0; i < bound; i++) { for (int j = 0; j < bound; j++) { if (matrixA.Footprint[i, j] == matrixB.Footprint[i, j]) { match++; } } } return(match / size); }
public void MakeRelationMatrixFromActivitiesTest() { // 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" }; Relation[,] exampleFootprint = new Relation[7, 7]; // Act RelationMatrix matrix = new RelationMatrix(activities, startActivities, endActivities); // Assert Assert.AreEqual(matrix.Activities.Count, 7); for (int i = 0; i < matrix.Activities.Count; i++) { Assert.AreEqual(activities[i], matrix.Activities[i]); Assert.AreEqual(i, matrix.ActivityIndices[matrix.Activities[i]]); } Assert.AreEqual(1, matrix.StartActivities.Count); Assert.IsTrue(matrix.StartActivities.Contains("wake up")); Assert.AreEqual(2, matrix.EndActivities.Count); Assert.IsTrue(matrix.EndActivities.Contains("go sleep")); Assert.IsTrue(matrix.EndActivities.Contains("play witcher")); for (int i = 0; i < matrix.Activities.Count; i++) { for (int j = 0; j < matrix.Activities.Count; j++) { Assert.AreEqual(exampleFootprint[i, j], matrix.Footprint[i, j]); } } }
/// <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); }
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)); }
//Метод формирования матрицы связей таблиц БД. (параметр)(матрица достижимости) public RelationMatrix GetRelationMatrix(List <TableInfo> tables) { RelationMatrix relationMatrix = new RelationMatrix(tables); //Заполним матрицу первоначальными данными. Не смогли - ошибка if (!GetDBTablesRelations(relationMatrix)) { return(null); } //Составляем список имён всех таблиц var allTableNames = new List <string>(); foreach (var table in tables) { allTableNames.Add(table.TableName); } //Заполняем матрицу foreach (var baseTableName in allTableNames) { //Получаем список соседей этой таблицы var neighborTableNames = relationMatrix.GetNeighborTablesNames(baseTableName); //Для каждого соседа ищем достижимые вершины foreach (var neighborTableName in neighborTableNames) { var reachebleTables = new HashSet <string>(); //множество достижимых из соседней таблицы таблиц reachebleTables.Add(baseTableName); //базовая таблица достижима - в неё идти не надо relationMatrix.GetConnectedTablesNames(reachebleTables, neighborTableName); reachebleTables.Remove(baseTableName); //убираем базовую таблицу из множества достижимых - здесь она нам не нужна //Помечаем достижимые из соседа вершины как достижимые из базовой таблицы, делаем в матрице соотв. запись foreach (var reachebleTableName in reachebleTables) { relationMatrix[baseTableName][reachebleTableName] = new RelationMatixElem { ViaTable = neighborTableName, ConnectionCondition = relationMatrix[baseTableName][neighborTableName].ConnectionCondition } } ; } } return(relationMatrix); }
/// <summary> /// Calculates causal footprint comparison when it is unknown if indices of both matrices match or when they don't match. /// </summary> /// <param name="matrixA">First RelationMatrix to be compared.</param> /// <param name="matrixB">Second RelationMatrix to be compared.</param> /// <returns>Fitness metric of both matrices.</returns> private static double Calculate(RelationMatrix matrixA, RelationMatrix matrixB) { Dictionary <int, int> indexMapping = new Dictionary <int, int>(); foreach (KeyValuePair <string, int> logIndex in matrixA.ActivityIndices) { int modelIndex = matrixB.ActivityIndices[logIndex.Key]; if (modelIndex != logIndex.Value) { indexMapping.Add(logIndex.Value, modelIndex); } } int bound = matrixA.Activities.Count; int match = 0; int size = bound * bound; for (int i = 0; i < bound; i++) { for (int j = 0; j < bound; j++) { int from = i; int to = j; if (indexMapping.ContainsKey(i)) { from = indexMapping[i]; } if (indexMapping.ContainsKey(j)) { to = indexMapping[j]; } if (matrixA.Footprint[i, j] == matrixB.Footprint[from, to]) { match++; } } } return(match / size); }
/// <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); } } }
public void MakeRelationMatrixFromEventLogTest() { // Arrange ImportedEventLog elog = CSVImport.MakeDataFrame(easyCsv); elog.SetActivity("act"); elog.SetCaseId("id"); WorkflowLog wlog = new WorkflowLog(elog); List <string> exampleActivities = new List <string>() { "a", "b", "c", "d" }; Relation[,] exampleFootprint = MakeEasyRelationMatrix(); // Act RelationMatrix matrix = new RelationMatrix(wlog); // Assert Assert.AreEqual(matrix.Activities.Count, 4); for (int i = 0; i < matrix.Activities.Count; i++) { Assert.AreEqual(exampleActivities[i], matrix.Activities[i]); Assert.AreEqual(i, matrix.ActivityIndices[matrix.Activities[i]]); } Assert.AreEqual(1, matrix.StartActivities.Count); Assert.IsTrue(matrix.StartActivities.Contains("a")); Assert.AreEqual(1, matrix.EndActivities.Count); Assert.IsTrue(matrix.EndActivities.Contains("c")); for (int i = 0; i < matrix.Activities.Count; i++) { for (int j = 0; j < matrix.Activities.Count; j++) { Assert.AreEqual(exampleFootprint[i, j], matrix.Footprint[i, j]); } } }
/// <summary> /// Finds parallelism in Petri Net overlay and updates given Relation DirectDependencyMatrix accordingly. /// </summary> /// <param name="matrix">A relation matrix of analyzed Petri Net.</param> /// <param name="net">Petri Net overlay.</param> private static void FindParallelism(ref RelationMatrix matrix, PetriNetTokenTraverseOverlay net) { foreach (var fromTransition in net.TransitionsWithFootprints) { foreach (var toTransition in net.TransitionsWithFootprints) { if (fromTransition.Id != toTransition.Id) { HashSet <string> fromTransitionGlobalIds = new HashSet <string>( TokenManipulationUtils.GetActiveGlobalIds(fromTransition.TokenFootprint)); HashSet <string> toTransitionGlobalIds = new HashSet <string>( TokenManipulationUtils.GetActiveGlobalIds(toTransition.TokenFootprint)); if (fromTransitionGlobalIds.Overlaps(toTransitionGlobalIds) && !IsFalseParallelism(fromTransition, toTransition)) { int fromIndex = matrix.ActivityIndices[fromTransition.Activity]; int toIndex = matrix.ActivityIndices[toTransition.Activity]; matrix.Footprint[fromIndex, toIndex] = Relation.Parallelism; matrix.Footprint[toIndex, fromIndex] = Relation.Parallelism; } } } } }
private IPetriNet MakeEasyPetriNet() { RelationMatrix matrix = MakeEasyRelationMatrix(); return(Alpha.MakePetriNet(matrix)); }
private IPetriNet MakeVeryHardPetriNet() { RelationMatrix matrix = MakeVeryHardRelationMatrix(); return(Alpha.MakePetriNet(matrix)); }