/// <summary> /// Token replay technique /// </summary> /// <param name="minedNet">Mined model</param> /// <param name="trace_frequencies">Dictionary holding the frequencies from the trance</param> /// <returns>Fitness E [0;1]</returns> public static double TokenReplayFitness(PetriNet minedNet, Dictionary <List <string>, int> trace_frequencies) { var result = new TokenReplayInfo(); foreach (KeyValuePair <List <string>, int> trace in trace_frequencies) { minedNet.InitializeTokens(); minedNet.AddMarking(1); var sequenceTokenInfo = new TokenReplayInfo(produced: 1); foreach (var step in trace.Key) { var transitionId = minedNet.TransitionNameToId(step); var isEnabled = minedNet.IsEnabled(transitionId); if (!isEnabled) { // produce the correct amount of missing tokens var placesBefore = minedNet.GetIdsOfParentPlaces(transitionId); foreach (var placeId in placesBefore) { if (0 == minedNet.GetTokens(placeId)) { minedNet.AddMarking(placeId); sequenceTokenInfo.missed++; } } } sequenceTokenInfo.consumed += minedNet.GetNumberOfParents(transitionId); sequenceTokenInfo.produced += minedNet.GetNumberOfChildren(transitionId); minedNet.FireTransition(transitionId); } var lastTransitionId = minedNet.TransitionNameToId(trace.Key[trace.Key.Count - 1]); if (1 != minedNet.GetNumberOfChildren(lastTransitionId)) { Console.WriteLine("Error, the last transition should have only one out place"); return(-1); } // consume the tokens from the out place sequenceTokenInfo.consumed += minedNet.GetTokens(minedNet.GetIdsOfChildPlaces(lastTransitionId)[0]); // check if there are any tokens left behind in the net foreach (var step in trace.Key) { var transitionId = minedNet.TransitionNameToId(step); sequenceTokenInfo.remained += minedNet.GetIdsOfParentPlaces(transitionId) .Select(x => minedNet.GetTokens(x)).ToList().Sum(); } sequenceTokenInfo.MultiplyBy(trace.Value); result.SumUp(sequenceTokenInfo); } return(result.ComputeFitness()); }