コード例 #1
0
            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);
            }
コード例 #2
0
        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);
        }
コード例 #3
0
            /// <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);
            }
コード例 #4
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
                    });
                }
            }
コード例 #5
0
        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);
        }
コード例 #6
0
        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);
        }
コード例 #7
0
            /// <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);
                }
            }
コード例 #8
0
        /// <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);
        }
コード例 #9
0
        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);
        }