/// <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); }