コード例 #1
0
        private static bool testIfValidConfiguration(string configuration
                                                     , List <NumericOption> participatingOptions, NonBooleanConstraint constraintToTest)
        {
            Dictionary <NumericOption, double> numericSelection = new Dictionary <NumericOption, double>();

            string[] values = configuration.Split(new char[] { '$' });
            for (int i = 0; i < participatingOptions.Count; i++)
            {
                numericSelection.Add(participatingOptions.ElementAt(i), Double.Parse(values[i]));
            }
            return(constraintToTest.configIsValid(numericSelection));
        }
コード例 #2
0
        /// <summary>
        /// The non-boolean constraints are constraints among binary and numeric configuration options.
        /// Currently, these constraints are implemented as inequation of multiplicative terms.
        /// However, z3 does not support the multiplication among boolean variables (i.e., binary configuration options)
        /// and numeric variables (i.e., numeric configuration options).
        /// Thus, the approach is as follows:
        /// (1) Create a numeric variable for each binary configuration option in the mixed constraint and add a constraint
        /// for each of them, so that the numeric variable has the value 1 when the binary configuration option is true; 0 otherwise
        /// (2) Translate the constraints into z3
        /// </summary>
        /// <param name="constr">The <see cref="NonBooleanConstraint"/> to translate.</param>
        /// <param name="optionMapping">The mapping of already used binary options and their <see cref="Expr"/> counterparts.</param>
        /// <param name="context">The z3 <see cref="Context"/> needed for the translatation of these constraints.</param>
        /// <param name="optionToTerm">A mapping that maps the given option to a term.</param>
        /// <returns>A <see cref="BoolExpr"/> that represents this constraint.</returns>
        private static BoolExpr ProcessMixedConstraint(NonBooleanConstraint constr, Dictionary <BinaryOption, Expr> optionMapping, Context context, Dictionary <ConfigurationOption, Expr> optionToTerm)
        {
            List <BoolExpr> constraints = new List <BoolExpr>();

            // Process the binary options in the formula
            HashSet <BinaryOption> binOpts = constr.leftHandSide.participatingBoolOptions;

            foreach (BinaryOption binOpt in constr.rightHandSide.participatingBoolOptions)
            {
                if (!binOpts.Contains(binOpt))
                {
                    binOpts.Add(binOpt);
                }
            }
            foreach (BinaryOption binOpt in binOpts)
            {
                if (!optionMapping.ContainsKey(binOpt))
                {
                    Expr newExpr = GenerateDoubleVariable(context, binOpt.Name + "_num");
                    optionMapping[binOpt] = newExpr;

                    // Add the constraints to ensure that the values of the binary and the numeric variable correspond to each other.
                    BoolExpr constraint = (BoolExpr)optionToTerm[binOpt];
                    constraints.Add(context.MkImplies(constraint, context.MkEq(newExpr, context.MkFPNumeral(1, context.MkFPSortDouble()))));
                    constraints.Add(context.MkImplies(context.MkNot(constraint), context.MkEq(newExpr, context.MkFPNumeral(0, context.MkFPSortDouble()))));
                }
            }

            // Note: The 'require'-tag is ignored here, as it does not make sense when translating the mixed constraints for z3

            // Translate the mixed constraint
            FPExpr leftSide  = (FPExpr)TranslateMixedConstraint(constr.leftHandSide, optionMapping, context, optionToTerm);
            FPExpr rightSide = (FPExpr)TranslateMixedConstraint(constr.rightHandSide, optionMapping, context, optionToTerm);


            // Next, check if the constraint has to evaluate to true or not
            string comparator = constr.comparator;

            if (constr.GetType() == typeof(MixedConstraint) &&
                ((MixedConstraint)constr).negativeOrPositiveExpr.Equals(MixedConstraint.NEGATIVE))
            {
                comparator = GetNegatedInequation(comparator);
            }

            switch (comparator)
            {
            case ">=":
                return(context.MkFPGEq(leftSide, rightSide));

            case "<=":
                return(context.MkFPLEq(leftSide, rightSide));

            case "!=":
                return(context.MkNot(context.MkEq(leftSide, rightSide)));

            case "=":
                return(context.MkEq(leftSide, rightSide));

            case ">":
                return(context.MkFPGt(leftSide, rightSide));

            case "<":
                return(context.MkFPLt(leftSide, rightSide));

            default:
                throw new ArgumentException("The inequation sign " + comparator + " is not supported.");
            }
        }
コード例 #3
0
        private static List <string> transformToBooleanConstraints(NonBooleanConstraint constraint)
        {
            List <string> constraints            = new List <string>();
            List <ConfigurationOption> options   = constraint.ParticipatingOptions();
            List <List <double> >      allValues = options.Select(option =>
            {
                switch (option)
                {
                case BinaryOption _:
                    return(new List <double> {
                        0, 1
                    });

                case NumericOption numericOption:
                    return(numericOption.getAllValues());

                default:
                    throw new NotImplementedException();
                }
            }).ToList();

            foreach (List <double> values in CartesianProduct(allValues))
            {
                Dictionary <BinaryOption, BinaryOption.BinaryValue> binarySelection =
                    new Dictionary <BinaryOption, BinaryOption.BinaryValue>();
                Dictionary <NumericOption, double> numericSelection = new Dictionary <NumericOption, double>();
                for (int i = 0; i < options.Count; i++)
                {
                    switch (options[i])
                    {
                    case BinaryOption binaryOption:
                        binarySelection[binaryOption] = values[i] == 0
                                ? BinaryOption.BinaryValue.Deselected
                                : BinaryOption.BinaryValue.Selected;
                        break;

                    case NumericOption numericOption:
                        numericSelection[numericOption] = values[i];
                        break;

                    default:
                        throw new NotImplementedException();
                    }
                }
                if (!constraint.configIsValid(new Configuration(binarySelection, numericSelection, false)))
                {
                    List <string> terms = values.Zip(options, (value, option) =>
                    {
                        switch (option)
                        {
                        case BinaryOption _:
                            return(value == 0 ? option.Name : "!" + option.Name);

                        case NumericOption _:
                            return("!" + option.Name + "_" + value);

                        default:
                            throw new NotImplementedException();
                        }
                    }).ToList();
                    string newConstraint = String.Join(" | ", terms);
                    constraints.Add(newConstraint);
                }
            }
            return(constraints);
        }