コード例 #1
0
        /// <summary>
        /// Calculates the distinct count of output values for Collect hit policy
        /// </summary>
        /// <remarks>Based on the collect hit policy, the aggregated count is calculated for the first output.</remarks>
        /// <param name="positiveRules">Rules evaluates as positive match</param>
        /// <param name="results">Evaluated (calculated) results (rule outputs)</param>
        /// <returns><see cref="PositiveRulesCollectValues"/> container where the <see cref="PositiveRulesCollectValues.Count"/> contains the
        /// distinct count of values, the other properties are zeroed</returns>
        private static PositiveRulesCollectValues CalculatePositiveRulesCollectCountValue(
            IEnumerable <DmnDecisionTableRule> positiveRules,
            DmnDecisionTableRuleExecutionResults results)
        {
            var count = positiveRules.ToList()
                        .Select(r => results.GetResult(r, r.Outputs[0])?.Value?.ToString())
                        .Where(v => v != null)
                        .Distinct()
                        .ToList()
                        .Count;

            return(new PositiveRulesCollectValues(0, 0, 0, count));
        }
コード例 #2
0
        //------------------------------------------------------------------------
        // Collect hit policy helpers
        //------------------------------------------------------------------------

        /// <summary>
        /// Calculates the aggregate output values for Collect hit policy
        /// </summary>
        /// <remarks>Based on the collect hit policy, the aggregates are calculated for the first output</remarks>
        /// <param name="positiveRules">Rules evaluates as positive match</param>
        /// <param name="results">Evaluated (calculated) results (rule outputs)</param>
        /// <returns><see cref="PositiveRulesCollectValues"/> container with aggregated output values</returns>
        private static PositiveRulesCollectValues CalculatePositiveRulesCollectValues(
            IEnumerable <DmnDecisionTableRule> positiveRules,
            DmnDecisionTableRuleExecutionResults results)
        {
            double sum = 0;
            var    min = double.MaxValue;
            var    max = double.MinValue;

            var distinctValues = new List <double>();

            foreach (var positiveRule in positiveRules)
            {
                var valueRaw = results.GetResult(positiveRule, positiveRule.Outputs[0])?.Value;
                if (valueRaw == null)
                {
                    continue;                   //ignore null results/values
                }
                double value;
                var    isBool = positiveRule.Outputs[0].Output.Variable.Type == typeof(bool);
                if (isBool)
                {
                    value = (bool)valueRaw ? 1 : 0;
                }
                else
                {
                    value = (double)Convert.ChangeType(valueRaw, typeof(double));
                }

                sum += value;
                if (value < min)
                {
                    min = value;
                }
                if (value > max)
                {
                    max = value;
                }
                if (!distinctValues.Contains(value))
                {
                    distinctValues.Add(value);
                }
            }

            var count = distinctValues.Count;

            return(new PositiveRulesCollectValues(sum, min, max, count));
        }
コード例 #3
0
        /// <summary>
        /// Evaluates the output expressions for  positive rules and stores generates the table execution results ( (rule, output)-&gt;temp variable with result)
        /// </summary>
        /// <param name="context">Engine execution context</param>
        /// <param name="correlationId">Correlation ID used for logging</param>
        /// <param name="positiveRules">List of positive rules</param>
        /// <returns>Table execution results</returns>
        private DmnDecisionTableRuleExecutionResults EvaluateOutputsForPositiveRules(DmnExecutionContext context, string correlationId, IEnumerable <DmnDecisionTableRule> positiveRules)
        {
            Logger.InfoCorr(correlationId, $"Evaluating decision table {Name} positive rules outputs...");
            var results = new DmnDecisionTableRuleExecutionResults();

            foreach (var positiveRule in positiveRules)
            {
                //outputs
                foreach (var ruleOutput in positiveRule.Outputs)
                {
                    if (string.IsNullOrWhiteSpace(ruleOutput.Expression))
                    {
                        results.SetResult(positiveRule, ruleOutput, null);
                        continue;
                    }

                    var result = context.EvalExpression(ruleOutput.Expression, ruleOutput.Output.Variable.Type ?? typeof(object));

                    // check allowed output values
                    var allowedValues = ruleOutput.Output.AllowedValues;
                    if (allowedValues != null && allowedValues.Count > 0 &&
                        !string.IsNullOrWhiteSpace(result?.ToString()))
                    {
                        if (!ruleOutput.Output.AllowedValues.Contains(result.ToString()))
                        {
                            throw Logger.ErrorCorr <DmnExecutorException>(
                                      correlationId,
                                      $"Decision table {Name}, rule {positiveRule}: Output value '{result}' is not in allowed values list ({string.Join(",", allowedValues)})");
                        }
                    }

                    var output = new DmnExecutionVariable(ruleOutput.Output.Variable)
                    {
                        Value = result
                    };
                    results.SetResult(positiveRule, ruleOutput, output);
                    if (Logger.IsTraceEnabled)
                    {
                        Logger.TraceCorr(correlationId,
                                         $"Positive decision table {Name} rule {positiveRule}: output {output.Name}, value {output.Value}");
                    }
                }
            }

            Logger.InfoCorr(correlationId, $"Evaluated decision table {Name} positive rules outputs");
            return(results);
        }
コード例 #4
0
        //------------------------------------------------------------------------
        // Priority and Output order hit policies helpers
        //------------------------------------------------------------------------

        /// <summary>
        /// Orders the positive rules by output priorities for the Priority and Output order hit policies.
        /// </summary>
        /// <remarks>
        /// For the Priority and Output order hit policies, priority is decided in compound output tables over all the outputs for which output values have been provided.
        /// The priority for each output is specified in the ordered list of output values in decreasing order of priority,
        /// and the overall priority is established by considering the ordered outputs from left to right.
        /// Outputs for which no output values are provided are not taken into account in the ordering,
        /// although their output entries are included in the ordered compound output.
        /// </remarks>
        /// <param name="positiveRules">Rules evaluates as positive match</param>
        /// <param name="results">Evaluated (calculated) results (rule outputs)</param>
        /// <param name="correlationId">Correlation ID used for logging</param>
        /// <returns>Positive rules ordered by output priorities for the Priority and Output order hit policies</returns>
        private IOrderedEnumerable <DmnDecisionTableRule> OrderPositiveRulesByOutputPriority(
            IReadOnlyCollection <DmnDecisionTableRule> positiveRules,
            DmnDecisionTableRuleExecutionResults results,
            string correlationId)
        {
            IOrderedEnumerable <DmnDecisionTableRule> ordered = null;

            foreach (var output in Outputs)
            {
                //outputs without allowed values list are not part of ordering
                if (output.AllowedValues == null || output.AllowedValues.Count <= 0)
                {
                    continue;
                }

                if (ordered == null)
                {
                    ordered = positiveRules.OrderBy(i =>
                    {
                        var ruleOutput = i.Outputs.FirstOrDefault(o => o.Output.Index == output.Index);

                        //no such output in positive rule (ruleOutput==null) - at the end of the list
                        //no output result in positive rule (ruleOutput.ResultOutput==null) - at the end of the list
                        //no output result value in positive rule (ruleOutput.ResultOutput.Value==null) - at the end of the list
                        //all handled in GetIndexOfOutputValue: if (value == null) return int.MaxValue;
                        return(GetIndexOfOutputValue(output.AllowedValues, results.GetResult(i, ruleOutput)?.Value, correlationId));
                    });
                }
                else
                {
                    ordered = ordered.ThenBy(i =>
                    {
                        var ruleOutput = i.Outputs.FirstOrDefault(o => o.Output.Index == output.Index);
                        return(GetIndexOfOutputValue(output.AllowedValues, results.GetResult(i, ruleOutput)?.Value, correlationId));
                    });
                }
            }

            return(ordered);
        }
コード例 #5
0
        //------------------------------------------------------------------------
        // Any hit policy helpers
        //------------------------------------------------------------------------

        /// <summary>
        /// Checks whether all positive rule outputs match as required by Any hit policy
        /// </summary>
        /// <param name="positiveRules">Rules evaluates as positive match</param>
        /// <param name="results">Evaluated (calculated) results (rule outputs)</param>
        /// <returns>True when all positive rule outputs match</returns>
        private static bool MatchRuleOutputs(IEnumerable <DmnDecisionTableRule> positiveRules, DmnDecisionTableRuleExecutionResults results)
        {
            var array = positiveRules.ToArray();

            if (array.Length < 2)
            {
                return(true);
            }

            var firstItem = results.GetResultsHashCode(array[0]);
            var allEqual  = array.Skip(1).All(i => Equals(firstItem, results.GetResultsHashCode(i)));

            return(allEqual);
        }