private BoolExpr ReduceComparison(TermModelOperation type, ArithExpr[] operands) { var context = _solver.Context; Debug.Assert(operands.Length >= 2); Func <ArithExpr, ArithExpr, BoolExpr> mkComparison; switch (type) { case TermModelOperation.Greater: mkComparison = (x, y) => context.MkGt(x, y); break; case TermModelOperation.Less: mkComparison = (x, y) => context.MkLt(x, y); break; case TermModelOperation.GreaterEqual: mkComparison = (x, y) => context.MkGe(x, y); break; case TermModelOperation.LessEqual: mkComparison = (x, y) => context.MkLe(x, y); break; case TermModelOperation.Equal: mkComparison = (x, y) => context.MkEq(x, y); break; default: throw new NotSupportedException(); } BoolExpr current = mkComparison(operands[0], operands[1]); for (int i = 1; i < operands.Length - 1; ++i) { current = context.MkAnd(current, mkComparison(operands[i], operands[i + 1])); } return(current); }
private bool IsBoolTerm(int rid) { if (IsConstant(rid)) { Rational lower, upper; GetBounds(rid, out lower, out upper); Debug.Assert(lower == upper); return(lower.IsOne || lower.IsZero); } if (IsOperation(rid)) { TermModelOperation op = GetOperation(rid); switch (op) { case TermModelOperation.And: case TermModelOperation.Or: case TermModelOperation.Not: case TermModelOperation.LessEqual: case TermModelOperation.Less: case TermModelOperation.Greater: case TermModelOperation.GreaterEqual: case TermModelOperation.Unequal: case TermModelOperation.Equal: return(true); case TermModelOperation.If: return(IsBoolTerm(GetOperand(rid, 1)) && IsBoolTerm(GetOperand(rid, 2))); case TermModelOperation.Identity: return(IsBoolTerm(GetOperand(rid, 0))); default: return(false); } } return(false); }
private BoolExpr MkBool(int rid) { var context = _solver.Context; if (IsConstant(rid)) { Rational lower, upper; GetBounds(rid, out lower, out upper); Debug.Assert(lower == upper); if (lower.IsZero) { return(context.MkFalse()); } return(context.MkTrue()); } if (IsOperation(rid)) { BoolExpr[] children; ArithExpr[] operands; TermModelOperation op = GetOperation(rid); switch (op) { case TermModelOperation.And: Debug.Assert(GetOperandCount(rid) >= 2, "Conjunction requires at least two operands."); children = (GetOperands(rid)).Select(x => MkBool(x)).ToArray(); return(context.MkAnd(children)); case TermModelOperation.Or: Debug.Assert(GetOperandCount(rid) >= 2, "Disjunction requires at least two operands."); children = (GetOperands(rid)).Select(x => MkBool(x)).ToArray(); return(context.MkOr(children)); case TermModelOperation.Not: Debug.Assert(GetOperandCount(rid) == 1, "Negation is unary."); return(context.MkNot(MkBool(GetOperand(rid, 0)))); case TermModelOperation.If: Debug.Assert(GetOperandCount(rid) == 3, "If is ternary."); BoolExpr b = MkBool(GetOperand(rid, 0)); Expr x1 = MkBool(GetOperand(rid, 1)); Expr x2 = MkBool(GetOperand(rid, 2)); return((BoolExpr)context.MkITE(b, x1, x2)); case TermModelOperation.Unequal: Debug.Assert(GetOperandCount(rid) >= 2, "Distinct should have at least two operands."); return(context.MkDistinct((GetOperands(rid)).Select(x => MkTerm(x)).ToArray())); case TermModelOperation.Greater: case TermModelOperation.Less: case TermModelOperation.GreaterEqual: case TermModelOperation.LessEqual: case TermModelOperation.Equal: Debug.Assert(GetOperandCount(rid) >= 2, "Comparison should have at least two operands."); operands = (GetOperands(rid)).Select(x => MkTerm(x)).ToArray(); return(ReduceComparison(GetOperation(rid), operands)); case TermModelOperation.Identity: Debug.Assert(GetOperandCount(rid) == 1, "Identity takes exactly one operand."); return(MkBool(GetOperand(rid, 0))); default: return(context.MkEq(MkTerm(rid), _solver.GetNumeral(Rational.One))); } } return(context.MkEq(MkTerm(rid), _solver.GetNumeral(Rational.One))); }
private ArithExpr MkTerm(int rid) { var context = _solver.Context; if (IsConstant(rid)) { Rational lower, upper; GetBounds(rid, out lower, out upper); Debug.Assert(lower == upper); return(_solver.GetNumeral(lower)); } else if (IsOperation(rid)) { ArithExpr[] operands; TermModelOperation op = GetOperation(rid); switch (op) { case TermModelOperation.And: case TermModelOperation.Or: case TermModelOperation.Not: case TermModelOperation.Unequal: case TermModelOperation.Greater: case TermModelOperation.Less: case TermModelOperation.GreaterEqual: case TermModelOperation.LessEqual: case TermModelOperation.Equal: return(MkBoolToArith(MkBool(rid))); case TermModelOperation.If: Debug.Assert(GetOperandCount(rid) == 3, "If is ternary."); BoolExpr b = MkBool(GetOperand(rid, 0)); Expr x1 = MkTerm(GetOperand(rid, 1)); Expr x2 = MkTerm(GetOperand(rid, 2)); return((ArithExpr)context.MkITE(b, x1, x2)); case TermModelOperation.Plus: Debug.Assert(GetOperandCount(rid) >= 2, "Plus takes at least two operands."); operands = (GetOperands(rid)).Select(x => MkTerm(x)).ToArray(); return(context.MkAdd(operands)); case TermModelOperation.Minus: Debug.Assert(GetOperandCount(rid) == 1, "Minus takes exactly one operand."); return(context.MkUnaryMinus(MkTerm(GetOperand(rid, 0)))); case TermModelOperation.Times: Debug.Assert(GetOperandCount(rid) >= 2, "Times requires at least two operands."); operands = (GetOperands(rid)).Select(x => MkTerm(x)).ToArray(); return(context.MkMul(operands)); case TermModelOperation.Identity: Debug.Assert(GetOperandCount(rid) == 1, "Identity takes exactly one operand."); return(MkTerm(GetOperand(rid, 0))); case TermModelOperation.Abs: Debug.Assert(GetOperandCount(rid) == 1, "Abs takes exactly one operand."); ArithExpr e = MkTerm(GetOperand(rid, 0)); ArithExpr minusE = context.MkUnaryMinus(e); ArithExpr zero = _solver.GetNumeral(Rational.Zero); return((ArithExpr)context.MkITE(context.MkGe(e, zero), e, minusE)); default: Console.Error.WriteLine("{0} operation isn't supported.", op); throw new NotSupportedException(); } } else { return(_solver.GetVariable(rid)); } }
private BoolExpr ReduceComparison(TermModelOperation type, ArithExpr[] operands) { var context = _solver.Context; Debug.Assert(operands.Length >= 2); Func<ArithExpr, ArithExpr, BoolExpr> mkComparison; switch (type) { case TermModelOperation.Greater: mkComparison = (x, y) => context.MkGt(x, y); break; case TermModelOperation.Less: mkComparison = (x, y) => context.MkLt(x, y); break; case TermModelOperation.GreaterEqual: mkComparison = (x, y) => context.MkGe(x, y); break; case TermModelOperation.LessEqual: mkComparison = (x, y) => context.MkLe(x, y); break; case TermModelOperation.Equal: mkComparison = (x, y) => context.MkEq(x, y); break; default: throw new NotSupportedException(); } BoolExpr current = mkComparison(operands[0], operands[1]); for (int i = 1; i < operands.Length - 1; ++i) current = context.MkAnd(current, mkComparison(operands[i], operands[i + 1])); return current; }