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));
            }
        }
Beispiel #5
0
        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;
        }