internal static double Check(BpmGenome genome) { var sum = 0; sum += CheckForConcatenatingGatewaysWithSingleChild(genome.RootGene); sum += CheckForEmptyGateways(genome.RootGene); sum += CheckForMultipleEqualActivitiesInSameNode(genome.RootGene); // TODO sum += CheckForSeveralXorsInLine(genome.RootGene, 5); sum += CheckForTooMuchActivities(genome.RootGene); return(sum); }
private static double CalculateMueNpv(BpmGenome genome, double mueP) { // mue starts at 0.0 var mueNpv = 0.0; // calculate variable costs for new activities in reference to the initial genome var listActivities = new List <BpmnActivity>(); try { // TODO //listActivities = //TreeHelper.ListActivities(TreeHelper.ParseBpmGenome(BpmModel.Model.GetString("startProcess"))); } catch (Exception ex) { Debug.WriteLine(ex.Message); } var currentList = genome.ListActivities(); currentList.RemoveAll(activity => listActivities.Contains(activity)); var countNewActivities = currentList.Count; // define initial costs var I = ModelHelper.GetBpmModel().GetIfix() + countNewActivities * ModelHelper.GetBpmModel().GetIvar(); Debug.WriteLine("initial costs: " + I); // substract initial invest mueNpv -= I; // discont for (var t = 0; t < ModelHelper.GetBpmModel().GetT(); t++) { mueNpv += ModelHelper.GetBpmModel().GetN() * mueP / Math.Pow(1 + ModelHelper.GetBpmModel().GetI(), t); } Debug.WriteLine("mueNPV: " + mueNpv); return(mueNpv); }
/// <summary> /// Validates an Genome for process input, output and attributes, count failtures on the referenced variable /// </summary> /// <param name="genome"></param> /// <param name="failures"></param> /// <returns></returns> public static bool ValidateGenome(BpmGenome genome, ref int failures) { var count = genome.RootGene.CountSpecificNodes(typeof(BpmnXor)); var numberOfPaths = (int)Math.Pow(2, count); failures = 0; for (var i = 0; i < numberOfPaths; i++) { var startObjects = DataHelper.ObjectHelper.Instance().GetProcessInput(); var endObjects = DataHelper.ObjectHelper.Instance().GetProcessOutput(); var allAttributes = DataHelper.ActivityAttributeHelper.Instance().GetAll(); ValidateGenome(genome.RootGene, ref failures, startObjects, allAttributes, i, numberOfPaths, 0); failures += endObjects.Count(x => !startObjects.Contains(x)); } return(failures == 0); }
public PathSplitter(BpmGenome genome) { _root = genome.RootGene; if (DataHelper.ActivityAttributeHelper.Instance().GetAll().Count <= 0) { List <BpmnActivity> path = TreeHelper.ListActivities(genome); paths.Add(new Path { Probability = 1, path = path }); } foreach (var bpa in DataHelper.ActivityAttributeHelper.Instance().GetAll()) { var path = new List <BpmnActivity>(); CalculatePath(bpa, _root, path); paths.Add(new Path { Probability = bpa.DecisionProbability, path = path }); } }
public static XmlDocument BpmnToXml(BpmGenome genome) { var xml = Base(); var process = xml.CreateElement("bpmn", "process", BpmnUri); process.SetAttribute("id", "Process_" + Guid.NewGuid()); process.SetAttribute("isExecutable", "false"); xml.DocumentElement.AppendChild(process); var start = StartEvent(process); var outgoing = GeneToXml(process, genome.RootGene, start); var end = EndEvent(process, outgoing); var diagram = xml.CreateElement("bpmndi", "BPMNDiagram", BpmndiUri); diagram.SetAttribute("id", "BPMNDiagram_" + Guid.NewGuid()); xml.DocumentElement.AppendChild(diagram); var plane = xml.CreateElement("bpmndi", "BPMNPlane", BpmndiUri); plane.SetAttribute("id", "BPMNPlane_" + Guid.NewGuid()); plane.SetAttribute("bpmnElement", process.GetAttribute("id")); diagram.AppendChild(plane); var layouter = new Layouter(xml.DocumentElement); layouter.auto(genome.RootGene, start, end); layouter.flows(process); foreach (var x in layouter.AllElements()) { plane.AppendChild(x); } return(xml); }
public void GenerateGenomes() { var count = 1000000; var maxDepthRandomGenome = ModelHelper.GetBpmModel().GetMaxDepthRandomGenome(); var genomes = new List <string>(); for (var i = 0; i < count; i++) { var genome = new BpmGenome { RootGene = ProcessHelper.ProcessGenerator.GenerateRandomValidBpmGenome2( maxDepthRandomGenome, null) }; genomes.Add(genome.ToString()); } var distinctCount = genomes.Distinct().Count(); Assert.IsTrue(distinctCount >= count * 0.5); }
/// <summary> /// Generates a valid random BpmnGenome. /// </summary> /// <returns>random tree.</returns> public static void GenerateRandomValidBpmGenome(int maxDepth, BpmGene parent, BpmGenome genome, double executionProbability = 1) { if (parent is BpmnXor && parent.Children.Count > 2) { Debug.WriteLine("halt stop! BpmnXor error"); } BpmnXor xor = null; var allDecisions = DataHelper.ActivityAttributeHelper.Instance().GetAll(); if (allDecisions.Count > 0) { var selected = allDecisions.ElementAt(TreeHelper.RandomGenerator.Next(allDecisions.Count)); xor = new BpmnXor(-1, parent, selected.DecisionId, selected.DecisionValue); } // Choose a random gene from all available var gateways = new List <BpmGene>(); if (xor != null) { gateways.Add(xor); } gateways.Add(new BpmnAnd(-1, parent)); gateways.Add(new BpmnSeq(-1, parent)); var activities = new List <BpmnActivity>(); foreach (var model in DataHelper.ActivityHelper.Instance().Models) { activities.Add(new BpmnActivity(-1, parent, model.name)); } var randomGene = ChooseRandomBpmnGene(gateways, activities); // Create genome if parent is null. if (parent == null) { genome.RootGene = randomGene; GenerateRandomValidBpmGenome(maxDepth - 1, randomGene, genome); } // Handle Gateways else if ((parent is BpmnAnd || parent is BpmnSeq || parent is BpmnXor) && maxDepth > 1) { // Handle the deeper levels in the tree if (parent is BpmnAnd) { // Add the random gene to parents children parent.Children.Add(randomGene); randomGene.Parent = parent; // Choose a random number inclusive lower bound, exclusive upper bound. var numberOfChildren = TreeHelper.RandomGenerator.Next(2, Math.Max(2, activities.Count)); // Recursive call for randomly chosen number. for (var i = numberOfChildren - parent.Children.Count; i > 0; i--) { GenerateRandomValidBpmGenome(maxDepth - 1, randomGene, genome); } } else if (parent is BpmnSeq) { // Add the random gene to parents children parent.Children.Add(randomGene); randomGene.Parent = parent; // Choose a random number inclusive lower bound, exclusive upper bound. var numberOfChildren = TreeHelper.RandomGenerator.Next(2, Math.Max(2, activities.Count)); // Recursive call for randomly chosen number. for (var i = numberOfChildren - parent.Children.Count; i > 0; i--) { GenerateRandomValidBpmGenome(maxDepth - 1, randomGene, genome); } } // BPMN-XOR else if (parent is BpmnXor) { // TODO: At the moment only one Decision available. // Get all available decision values. var descitionValues = DataHelper.ActivityAttributeHelper.Instance() .GetDecisionValues( DataHelper.ActivityAttributeHelper.Instance().GetAll().FirstOrDefault().DecisionId); // Choos a random decision value. var rand = TreeHelper.RandomGenerator.Next(descitionValues.Count); // Get the probability of the randomly chosen value. var randomExecProb = DataHelper.ActivityAttributeHelper.Instance() .GetDecisionProbability( DataHelper.ActivityAttributeHelper.Instance().GetAll().FirstOrDefault().DecisionId, descitionValues.ElementAt(rand)); if (parent.Children.Count < 2) { // Add the random gene to parents children parent.Children.Add(randomGene); randomGene.Parent = parent; } if (parent.Children.Count < 2) { GenerateRandomValidBpmGenome(maxDepth, parent, genome, randomExecProb); } GenerateRandomValidBpmGenome(maxDepth, randomGene, genome, randomExecProb); } } else if ((parent is BpmnAnd || parent is BpmnSeq || parent is BpmnXor) && maxDepth == 1) { if (parent is BpmnXor && parent.Children.Count < 2) { // Reached the maximum number of hirarchies. Leafs only can be Actions. var activity = activities[TreeHelper.RandomGenerator.Next(activities.Count - 1)]; parent.Children.Add(activity); activity.Parent = parent; } } if (genome.RootGene.Children != null && maxDepth < 1) { genome.RootGene.RenumberIndicesOfBpmTree(gen => gen.Children); } }
/// <summary> /// Parses a *valid* process into a tree representation /// </summary> /// <param name="s">process string</param> /// <returns>genome</returns> public static BpmGenome ParseBpmGenome(this string s) { if (string.IsNullOrEmpty(s)) { return(null); } Debug.WriteLine("Parsing now the following string: " + s); var genome = new BpmGenome(); BpmGene parent = null; s = s.Replace(" ", ""); var index = 0; while (s.Length > 0) { if (s.StartsWith("<PI;")) { s = s.Substring(4); } else if (s.StartsWith(";PO>")) { s = s.Substring(4); } else if (s.StartsWith("AND(")) { s = s.Substring(4); var and = new BpmnAnd(index, parent); parent?.Children.Add(and); if (genome.RootGene == null) { genome.RootGene = and; } parent = and; index++; } else if (s.StartsWith("SEQ(")) { s = s.Substring(4); var seq = new BpmnSeq(index, parent); // Only necessary if genome is one seq if (parent == null) { genome.RootGene = seq; } else { parent.Children.Add(seq); } parent = seq; index++; } else if (s.StartsWith("XOR(")) { s = s.Substring(4); var decision = s.Substring(0, s.IndexOf(";")); s = s.Substring(decision.Length); decision = decision.Substring(2); decision = decision.Substring(0, decision.Length - 1); var decisionId = decision.Split(',')[0]; var decisionValue = decision.Split(',')[1]; var probability = DataHelper.ActivityAttributeHelper.Instance() .GetDecisionProbability(decisionId, decisionValue); var xor = new BpmnXor(index, parent, decisionId, decisionValue, probability); // Only necessary if genome is one xor if (parent == null) { genome.RootGene = xor; } else { parent.Children.Add(xor); } parent = xor; index++; } else if (s.StartsWith(";")) { s = s.Substring(1); } else if (s.StartsWith(")")) { parent = parent.Parent; s = s.Substring(1); } else { char[] seperators = { ';', ')' }; var name = s.Substring(0, s.IndexOfAny(seperators)); s = s.Substring(s.IndexOfAny(seperators)); var activity = new BpmnActivity(index, parent, name); // Only necessary if genome is one activity if (parent == null) { genome.RootGene = activity; } else { parent.Children.Add(activity); } index++; } } if (parent != null) { throw new Exception("Illegal input string"); } return(genome); }
private BpmSolution Evaluate(BpmGenome genome) { // start time measurement var startTime = DateTime.Now; Debug.WriteLine("Evaluating: " + genome); // load pain factor painFactor = ModelHelper.GetBpmModel().GetPainFactor(); #region costevaluation // calculate all process paths // - splitted by XOR for dependent probabilities var splitterXor = new ProcessHelper.PathSplitter(genome); var pathsForProbabilities = splitterXor.GetPaths(); // remove paths with 0.0 percentage probability pathsForProbabilities.RemoveAll(x => x.Probability == 0); // calculate probabilities for each activity // // [2] Wahrscheinlichkeiten für jede Activity var activitieProbabilities = new HashSet <BpmnActivity>(); var painFactorActivityAttributeCovering = false; var painFactorObjectDependencies = 0; // Calculate probabilities for every activity CalculateActivityProbabilities(ref activitieProbabilities, pathsForProbabilities); // Check resulting probabilities with input data painFactorActivityAttributeCovering = !CheckActivityAttributeCovering(genome.RootGene); // Check input/ouput realtionships from activities to objects //painFactorObjectDependencies = !CheckObjectDependencies(); var valide = ProcessHelper.Validator.ValidateGenome(genome, ref painFactorObjectDependencies); // Calculate µNPV var mueP = CalculateMueP(valide, activitieProbabilities); var mueNpv = CalculateMueNpv(genome, mueP); // Calculate σ^2NPV var sigma2P = CalculateSigma2P(mueP, activitieProbabilities, pathsForProbabilities); var sigma2Npv = CalculateSigma2Npv(sigma2P); // Calculate preference function var costFitness = mueNpv - ModelHelper.GetBpmModel().GetAlpha() / 2 * sigma2Npv; Debug.WriteLine("costFitness: " + costFitness + " = " + mueNpv + " - (" + ModelHelper.GetBpmModel().GetAlpha() + "/2) * " + sigma2Npv); #endregion #region timeevaluation double timeFitness = 0; foreach (var bpa in DataHelper.ActivityAttributeHelper.Instance().GetAll()) { timeFitness += bpa.DecisionProbability * CalculateTime(bpa, genome.RootGene); } if (DataHelper.ActivityAttributeHelper.Instance().GetAll().Count <= 0) { timeFitness = TreeHelper.CalculateLongestTime(genome.RootGene); } #endregion #region fitness merge var fitness = costFitness * ModelHelper.GetBpmModel().GetCostWeight(); fitness += -1 * timeFitness * ModelHelper.GetBpmModel().GetTimeWeight(); #endregion if (painFactorActivityAttributeCovering) { fitness -= ModelHelper.GetBpmModel().GetPainFactor(); } if (painFactorObjectDependencies > 0) { fitness -= ModelHelper.GetBpmModel().GetPainFactor() * painFactorObjectDependencies; } // only when pretty process enabled if (pretty) { fitness -= ModelHelper.GetBpmModel().GetPainFactor() * ProcessHelper.PrettyPrint.Check(genome); } var endTime = DateTime.Now; var activities = activitieProbabilities.Select(x => x.Name).Distinct().ToList(); var index = GeneticAlgorithm.Instance()?.Population?.CurrentGeneration?.GenerationIndex; if (!index.HasValue) { index = -1; } var solution = new BpmSolution( (endTime - startTime).TotalMilliseconds, index.Value, fitness, genome.ToString(), valide, "[" + string.Join(", ", activities.ToArray()) + "]", mueP, mueNpv, sigma2P, sigma2Npv, timeFitness, costFitness ); return(solution); }