public IDictionary <string, List <object> > Solve() { Dictionary <string, List <object> > variableValues = new Dictionary <string, List <object> >(StringComparer.CurrentCultureIgnoreCase); new Model.ViewModelLocator().MainModel.AddDisplayText("Z3 Solve"); Solver s = this.z3Context.MkSolver(); foreach (BoolExpr sa in this.solverAssertions) { s.Assert(sa); } Console.WriteLine(s.Check()); new Model.ViewModelLocator().MainModel.AddDisplayText(s.Check().ToString()); Microsoft.Z3.Model m = s.Model; foreach (FuncDecl d in m.Decls) { string varName = d.Name.ToString(); Expr valExpr = m.ConstInterp(d); string varValue = valExpr.ToString(); if (valExpr is FPExpr) { FPExpr fp = (FPExpr)valExpr; FPNum fn = (FPNum)fp; double val = Convert.ToDouble(fn.Significand); val = val * System.Math.Pow(2, fn.ExponentInt64); if (fn.Sign) { val = val * -1; } varValue = val.ToString(); if (valExpr.ToString() == "+zero") { varValue = "0.01"; } if (valExpr.ToString() == "-zero") { varValue = "-0.01"; } } string message = varName + " -> " + varValue; new Model.ViewModelLocator().MainModel.AddDisplayText(message); if (!variableValues.ContainsKey(varName)) { variableValues.Add(varName, new List <object>()); } variableValues[varName].Add(varValue); } return(variableValues); }
public void Test_FPTools_BV_2_Doubles() { Context ctx = new Context(); // housekeeping OK! Solver solver = ctx.MkSolver(); FPSort fpSort64 = ctx.MkFPSort64(); FPExpr[] values_FP = new FPExpr[] { ctx.MkFP(2, fpSort64), ctx.MkFP(4, fpSort64) }; BitVecExpr value_BV = ToolsFloatingPoint.FP_2_BV(values_FP, ctx); Console.WriteLine(ToolsZ3.ToStringBin(ToolsZ3.GetTvArray(value_BV, 128, solver, ctx))); IList <FPExpr> results_FP = new List <FPExpr>(ToolsFloatingPoint.BV_2_Doubles(value_BV, ctx)); for (int i = 0; i < values_FP.Length; ++i) { string expected = ToolsZ3.ToStringBin(ToolsZ3.GetTvArray(ctx.MkFPToIEEEBV(values_FP[i]), 64, solver, ctx)); string actual = ToolsZ3.ToStringBin(ToolsZ3.GetTvArray(ctx.MkFPToIEEEBV(results_FP[i]), 64, solver, ctx)); Assert.AreEqual(expected, actual); } ctx.Dispose(); }
private static Expr TranslateMixedConstraint(InfluenceFunction influenceFunction, Dictionary <BinaryOption, Expr> optionMapping, Context context, Dictionary <ConfigurationOption, Expr> optionToTerm) { string[] expression = influenceFunction.getExpressionTree(); if (expression.Length == 0) { return(null); } Stack <Expr> expressionStack = new Stack <Expr>(); for (int i = 0; i < expression.Length; i++) { if (!InfluenceFunction.isOperatorEval(expression[i])) { double value; if (Double.TryParse(expression[i], out value)) { expressionStack.Push(context.MkFPNumeral(value, context.MkFPSortDouble())); } else { ConfigurationOption option = GlobalState.varModel.getOption(expression[i]); Expr expr = null; if (option is BinaryOption && optionMapping.ContainsKey((BinaryOption)option)) { expr = optionMapping[(BinaryOption)option]; } else { expr = optionToTerm[option]; } expressionStack.Push(expr); } } else { // Be aware of the rounding mode FPRMExpr roundingMode = context.MkFPRoundNearestTiesToEven(); switch (expression[i]) { case "+": FPExpr left = (FPExpr)expressionStack.Pop(); FPExpr right = (FPExpr)expressionStack.Pop(); expressionStack.Push(context.MkFPAdd(roundingMode, left, right)); break; case "-": FPExpr leftSub = (FPExpr)expressionStack.Pop(); FPExpr rightSub = (FPExpr)expressionStack.Pop(); expressionStack.Push(context.MkFPSub(roundingMode, leftSub, rightSub)); break; case "/": FPExpr leftDiv = (FPExpr)expressionStack.Pop(); FPExpr rightDiv = (FPExpr)expressionStack.Pop(); expressionStack.Push(context.MkFPDiv(roundingMode, leftDiv, rightDiv)); break; case "*": FPExpr leftMul = (FPExpr)expressionStack.Pop(); FPExpr rightMul = (FPExpr)expressionStack.Pop(); expressionStack.Push(context.MkFPMul(roundingMode, leftMul, rightMul)); break; // Note that the logarithm function is not supported by z3. default: throw new ArgumentException("The operator " + expression[i] + " is currently not supported in mixed constraints by z3."); } } } return(expressionStack.Pop()); }
/// <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."); } }