/// <summary>
        /// Returns a new table that is the union of the input tables.
        /// </summary>
        /// <param name="parameters">The model's parameters</param>
        /// <param name="first">First table</param>
        /// <param name="second">Second table</param>
        /// <param name="newState">Function to calculate state of merged value combinations</param>
        /// <returns>The new table</returns>
        public static ParameterInteraction Merge <T>(IList <ParameterBase> parameters, ParameterInteraction first, ParameterInteraction second, Func <ValueCombinationState, ValueCombinationState, ValueCombinationState> newState)
            where T : new()
        {
            List <int> parameterIndices = first.Parameters.Union(second.Parameters).ToList();

            parameterIndices.Sort();

            var mergedInteraction = new ParameterInteraction(parameterIndices);

            var valueTable = ParameterInteractionTable <T> .GenerateValueTable(parameters, mergedInteraction);

            foreach (var value in valueTable)
            {
                mergedInteraction.Combinations.Add(new ValueCombination(value, mergedInteraction));
            }

            foreach (var combination in mergedInteraction.Combinations)
            {
                var firstMatch  = first.Combinations.First((c) => ParameterInteractionTable <T> .MatchCombination(c, combination));
                var secondMatch = second.Combinations.First((c) => ParameterInteractionTable <T> .MatchCombination(c, combination));
                combination.State = newState(firstMatch.State, secondMatch.State);
            }

            return(mergedInteraction);
        }
Esempio n. 2
0
 public ParameterInteraction(ParameterInteraction interaction)
 {
     this.parameters = new List <int>(interaction.Parameters);
     foreach (var combination in interaction.Combinations)
     {
         var newCombination = new ValueCombination(combination);
         Combinations.Add(newCombination);
     }
 }
Esempio n. 3
0
        public ValueCombination(IList <int> values, ParameterInteraction interaction)
        {
            if (values.Count != interaction.Parameters.Count)
            {
                throw new ArgumentOutOfRangeException("values", "values and interaction must be the same length.");
            }

            for (int i = 0; i < values.Count; i++)
            {
                parameterToValueMap[interaction.Parameters[i]] = values[i];
            }
            State = ValueCombinationState.Uncovered;
        }
Esempio n. 4
0
        public ValueCombination(IList <int> values, ParameterInteraction interaction)
        {
            if (values.Count != interaction.Parameters.Count)
            {
                throw new ArgumentOutOfRangeException("values", "values and interaction must be the same length.");
            }

            this.parameterToValueMap = new Dictionary <int, int>(interaction.Parameters.Count);
            for (int i = 0; i < values.Count; i++)
            {
                parameterToValueMap[interaction.Parameters[i]] = values[i];
            }
            State = ValueCombinationState.Uncovered;
            keys  = new KeyCollection(parameterToValueMap.Keys);
        }
        // adds an interaction generated from a constraint to the table
        private void MergeConstraintInteraction(int order, ParameterInteraction constraintInteraction)
        {
            // is the constraint already in the table
            if (!Interactions.Contains(constraintInteraction))
            {
                // if the interaction has more parameters than the order we can't mark any of the existing combinations excluded
                // if the interaction is shorter we need to mark the existing combinations excluded
                if (constraintInteraction.Parameters.Count > order)
                {
                    Interactions.Add(constraintInteraction);
                }
                else
                {
                    var excludedValues = constraintInteraction.Combinations.Where((c) => c.State == ValueCombinationState.Excluded);

                    var candidateInteractions =
                        from interaction in Interactions
                        where constraintInteraction.Parameters.All((i) => interaction.Parameters.Contains(i))
                        select interaction;

                    var excludedCombinations =
                        from interaction in candidateInteractions
                        from combination in interaction.Combinations
                        where excludedValues.Any((c) => MatchCombination(c, combination))
                        select combination;

                    foreach (var combination in excludedCombinations)
                    {
                        combination.State = ValueCombinationState.Excluded;
                    }
                }
            }
            else
            {
                // mark combinations excluded by the constraint excluded in the table
                var interaction = Interactions.First((i) => i.Equals(constraintInteraction));

                var excludedValues = constraintInteraction.Combinations.Where((c) => c.State == ValueCombinationState.Excluded);

                var combinations = interaction.Combinations.Where((c) => excludedValues.Any((excluded) => MatchCombination(excluded, c)));
                foreach (var combination in combinations)
                {
                    combination.State = ValueCombinationState.Excluded;
                }
            }
        }
Esempio n. 6
0
        private void GenerateHigherOrderDependentExclusions(Model <T> model, int order, List <int> parameterInteractionCounts, ParameterInteraction completeInteraction, IEnumerable <ValueCombination> allowedCombinations)
        {
            // generate the combinations for orders between order and completerInteraction.Parameters.Count
            foreach (var count in parameterInteractionCounts)
            {
                IList <int[]> parameterCombinations = GenerateCombinations(completeInteraction.Parameters.Count, count);
                foreach (var combinations in parameterCombinations)
                {
                    var interaction    = new ParameterInteraction(combinations.Select((i) => completeInteraction.Parameters[i]));
                    var possibleValues = ParameterInteractionTable <T> .GenerateValueTable(model.Parameters, interaction);

                    foreach (var value in possibleValues)
                    {
                        interaction.Combinations
                        .Add(new ValueCombination(value, interaction)
                        {
                            State = ValueCombinationState.Covered
                        });
                    }

                    // find combinations that should be excluded
                    var excludedCombinations = new List <ValueCombination>();
                    foreach (var combination in interaction.Combinations)
                    {
                        if (!combination.ParameterToValueMap.Any((p) => !completeInteraction.Parameters.Contains(p.Key)) &&
                            !allowedCombinations.Any((c) => MatchCombination(combination, c)))
                        {
                            excludedCombinations.Add(combination);
                        }
                    }

                    if (excludedCombinations.Count() > 0)
                    {
                        foreach (var combination in excludedCombinations)
                        {
                            combination.State = ValueCombinationState.Excluded;
                        }

                        MergeConstraintInteraction(order, interaction);
                    }
                }
            }
        }
        // helper to implement Constraint.GetExcludeCombinations
        internal static ParameterInteraction GetExcludedCombinations <T>(Model model, Constraint constraint, Parameter first, Parameter second, T value, Func <T, T, bool> comparison)
        {
            Debug.Assert(first != null && model != null && constraint != null && comparison != null);
            List <int> parameterIndices = new List <int>();

            parameterIndices.Add(model.Parameters.IndexOf(first));
            if (second != null)
            {
                parameterIndices.Add(model.Parameters.IndexOf(second));
            }
            parameterIndices.Sort();

            ParameterInteraction interaction = new ParameterInteraction(parameterIndices);
            List <int[]>         valueTable  = ParameterInteractionTable.GenerateValueTable(model.Parameters, interaction);

            foreach (var valueIndices in valueTable)
            {
                T value1, value2;

                value1 = (T)first[valueIndices[0]];
                if (second == null)
                {
                    value2 = value;
                }
                else
                {
                    value2 = (T)second[valueIndices[1]];
                }

                ValueCombinationState comboState = comparison(value1, value2) ? ValueCombinationState.Covered : ValueCombinationState.Excluded;
                interaction.Combinations.Add(new ValueCombination(valueIndices, interaction)
                {
                    State = comboState
                });
            }

            return(interaction);
        }
        // returns a table with all possible value combinations for the given interaction
        internal static List <int[]> GenerateValueTable(IList <Parameter> parameters, ParameterInteraction interaction)
        {
            List <int[]> possibleValueTable = new List <int[]>();

            for (int i = 0; i < interaction.Parameters.Count; i++)
            {
                possibleValueTable.Add(GenerateOrderedArray(parameters[interaction.Parameters[i]].Count));
            }

            int valueTableCount = possibleValueTable.Aggregate(1, (seed, array) => seed * array.Length);

            var table = new List <int[]>(valueTableCount);

            for (int i = 0; i < valueTableCount; i++)
            {
                table.Add(new int[possibleValueTable.Count]);
            }

            int[] repeats = new int[possibleValueTable.Count];
            for (int i = possibleValueTable.Count - 1; i >= 0; i--)
            {
                int repeat = 1;
                if (i < possibleValueTable.Count - 1)
                {
                    repeat = possibleValueTable[i + 1].Length * repeats[i + 1];
                }

                repeats[i] = repeat;
            }

            for (int i = 0; i < table.Count; i++)
            {
                for (int j = 0; j < table[i].Length; j++)
                {
                    table[i][j] = possibleValueTable[j][(i / repeats[j]) % possibleValueTable[j].Length];
                }
            }

            return(table);
        }
        // for the following system:
        // if A == 0 then B == 0
        // if B == 0 then C == 0
        // if C == 0 then A == 1
        // all combinations with A == 0 need to be excluded, but this is impossible to determine when looking at individual constraints
        // to do this:
        //      - create groups of constraints where all members have a parameter that overlaps with another constraint
        //      - create ParameterInteraction for each group of constraints
        //      - for the existing uncovered combinations, if they excluded in every matching combination in the group interaction, mark excluded
        //      - higher order combinations that match the order of a constraint's interaction can also need to be exculded
        private void GenerateDependentConstraintInteractions(Model model, int order, List <ParameterInteraction> constraintInteractions)
        {
            // group all the constraint parameter interactions that share parameters
            var dependentConstraintSets = new List <List <ParameterInteraction> >();

            while (constraintInteractions.Count > 0)
            {
                var dependentConstraintSet = new List <ParameterInteraction>();
                var interactionsToExplore  = new List <ParameterInteraction>();

                interactionsToExplore.Add(constraintInteractions[0]);
                constraintInteractions.RemoveAt(0);

                while (interactionsToExplore.Count > 0)
                {
                    ParameterInteraction current = interactionsToExplore[0];
                    interactionsToExplore.RemoveAt(0);
                    dependentConstraintSet.Add(current);

                    var dependentInteractions =
                        (from constraint in constraintInteractions
                         where constraint.Parameters.Any((i) => current.Parameters.Contains(i))
                         select constraint).ToList();

                    foreach (var dependentInteraction in dependentInteractions)
                    {
                        constraintInteractions.Remove(dependentInteraction);
                    }

                    interactionsToExplore.AddRange(dependentInteractions);
                }

                dependentConstraintSets.Add(dependentConstraintSet);
            }

            // walk over the groups of constraints
            foreach (var dependentConstraintSet in dependentConstraintSets)
            {
                // if there's only one constraint no more processing is necessary
                if (dependentConstraintSet.Count <= 1)
                {
                    continue;
                }

                // merge the interactions of all the constraints
                var uniqueParameters           = new Dictionary <int, bool>();
                var parameterInteractionCounts = new List <int>();
                for (int i = 0; i < dependentConstraintSet.Count; i++)
                {
                    foreach (var parameter in dependentConstraintSet[i].Parameters)
                    {
                        uniqueParameters[parameter] = true;
                    }

                    if (dependentConstraintSet[i].Parameters.Count > order)
                    {
                        parameterInteractionCounts.Add(dependentConstraintSet[i].Parameters.Count);
                    }
                }

                var sortedParameters = uniqueParameters.Keys.ToList();
                sortedParameters.Sort();

                ParameterInteraction completeInteraction = new ParameterInteraction(sortedParameters);
                var valueTable = ParameterInteractionTable.GenerateValueTable(model.Parameters, completeInteraction);
                foreach (var value in valueTable)
                {
                    completeInteraction.Combinations
                    .Add(new ValueCombination(value, completeInteraction)
                    {
                        State = ValueCombinationState.Covered
                    });
                }

                // calculate the excluded combinations in the new uber interaction
                var completeInteractionExcludedCombinations = new List <ValueCombination>();

                // find the combinations from the uber interaction that aren't excluded
                // if a combination is a subset of any of these it is not excluded
                var allowedCombinations = new List <ValueCombination>();

                foreach (var combination in completeInteraction.Combinations)
                {
                    bool exclude = false;
                    foreach (var constraint in completeConstraints)
                    {
                        if (constraint.SatisfiesContraint(model, combination) == ConstraintSatisfaction.Unsatisfied)
                        {
                            exclude = true;
                            break;
                        }
                    }

                    if (exclude)
                    {
                        combination.State = ValueCombinationState.Excluded;
                        completeInteractionExcludedCombinations.Add(combination);
                    }
                    else
                    {
                        allowedCombinations.Add(combination);
                    }
                }

                // find the existing combinations that are never allowed in the uber interaction
                var individualInteractionExcludedCombinations =
                    from interaction in Interactions
                    from combination in interaction.Combinations
                    where !combination.ParameterToValueMap.Any((p) => !completeInteraction.Parameters.Contains(p.Key)) &&
                    !allowedCombinations.Any((c) => MatchCombination(combination, c))
                    select combination;

                // mark the combinations in the table as excluded
                foreach (var combination in individualInteractionExcludedCombinations)
                {
                    combination.State = ValueCombinationState.Excluded;
                }

                GenerateHigherOrderDependentExclusions(model, order, parameterInteractionCounts, completeInteraction, allowedCombinations);
            }
        }
Esempio n. 10
0
        // helper to implement Constraint.SatisfiesConstraint
        internal static ConstraintSatisfaction SatisfiesContraint(Model model, ValueCombination combination, ParameterInteraction interaction)
        {
            Debug.Assert(model != null && combination != null && interaction != null);

            if (!interaction.Parameters.All((i) => combination.ParameterToVaueMap.ContainsKey(i)))
            {
                return(ConstraintSatisfaction.InsufficientData);
            }

            var matches = interaction.Combinations.Where((c) => ParameterInteractionTable.MatchCombination(c, combination));

            if (matches.Any((c) => c.State == ValueCombinationState.Excluded))
            {
                return(ConstraintSatisfaction.Unsatisfied);
            }

            return(ConstraintSatisfaction.Satisfied);
        }
Esempio n. 11
0
        // helper to implement Constraint.SatisfiesConstraint
        internal static ConstraintSatisfaction SatisfiesContraint <T>(Model <T> model, ValueCombination combination, ParameterInteraction interaction) where T : new()
        {
            Debug.Assert(model != null && combination != null && interaction != null);

            var parameterMap = combination.ParameterToValueMap;

            for (int i = 0; i < interaction.Parameters.Count; i++)
            {
                if (!parameterMap.ContainsKey(interaction.Parameters[i]))
                {
                    return(ConstraintSatisfaction.InsufficientData);
                }
            }

            for (int i = 0; i < interaction.Combinations.Count; i++)
            {
                if (ParameterInteractionTable <T> .MatchCombination(interaction.Combinations[i], combination))
                {
                    if (interaction.Combinations[i].State == ValueCombinationState.Excluded)
                    {
                        return(ConstraintSatisfaction.Unsatisfied);
                    }
                }
            }

            return(ConstraintSatisfaction.Satisfied);
        }