예제 #1
0
        public LinearIntegerExpression length()
        {
            switch (this.expression_type)
            {
            case SymbolicStringType.Symbol:
                return(LinearIntegerExpression.Constant(1));

            case SymbolicStringType.Concat:
                return(LinearIntegerExpression.Plus(this.sub_strings.Select(x => x.length())));

            case SymbolicStringType.Repeat:
                var sub = this.root.length();
                Contract.Assert(sub.isConstant());
                return(LinearIntegerExpression.Times(sub.constant, this.repeat));

            default:
                throw new ArgumentOutOfRangeException();
            }
        }
예제 #2
0
        // Generates splits (x, y, z) such that |y| > 0 and |xy| < p
        public IEnumerable <Split> ValidSplits(
            LinearIntegerExpression pumpingLengthVariable,
            BooleanExpression additionalConstraints)
        {
            foreach (var split in this.Splits())
            {
                if (split.mid.isEpsilon())
                {
                    continue;
                }

                var cond1     = ComparisonExpression.GreaterThan(split.mid.length(), LinearIntegerExpression.Constant(0));
                var cond2     = ComparisonExpression.LessThan(split.start.length() + split.mid.length(), pumpingLengthVariable);
                var condition = LogicalExpression.And(additionalConstraints, cond1, cond2);

                if (condition.isMaybeSatisfiable())
                {
                    split.AddConstraint(condition);
                    yield return(split);
                }
            }
        }
        public static ArithmeticLanguage FromTextDescriptions(List <String> alphabet, string symbolicStringText, string constraintText)
        {
            var symbolPattern  = new Regex(@"^[a-zA-Z0-9]$");
            var illegalSymbols = alphabet.FindAll(s => !symbolPattern.IsMatch(s));

            if (illegalSymbols.Count > 0)
            {
                var message = string.Format(
                    "Found illegal symbols {0} in alphabet. Symbols should match [a-zA-Z0-9]",
                    string.Join(", ", illegalSymbols)
                    );
                throw new PumpingLemmaException(message);
            }

            // Parse the language
            var ss = PumpingLemma.Parser.parseSymbolicString(symbolicStringText, alphabet);

            if (ss == null)
            {
                throw new PumpingLemmaException("Unable to parse language");
            }

            // Parse the constraintDesc
            var constraint = PumpingLemma.Parser.parseCondition(constraintText);

            if (constraint == null)
            {
                throw new PumpingLemmaException("Unable to parse constraint");
            }

            // Make sure all the variables are bound
            var boundVariables      = ss.GetIntegerVariables();
            var constraintVariables = constraint.GetVariables();

            // Console.WriteLine("Bound variables: " + String.Join(", ", boundVariables));
            // Console.WriteLine("Constriant variables: " + String.Join(", ", constraintVariables));
            foreach (var consVar in constraintVariables)
            {
                if (!boundVariables.Contains(consVar))
                {
                    throw new PumpingLemmaException(
                              string.Format("Constraint variable {0} not bound", consVar));
                }
            }

            // Add constraints saying that all variables are >= 0
            BooleanExpression defaultConstraint = LogicalExpression.True();

            foreach (var consVar in constraintVariables)
            {
                defaultConstraint = LogicalExpression.And(
                    defaultConstraint,
                    ComparisonExpression.GreaterThanOrEqual(
                        LinearIntegerExpression.SingleTerm(1, consVar),
                        LinearIntegerExpression.Constant(0)
                        )
                    );
            }

            return(new ArithmeticLanguage(alphabet, ss, constraint));
        }
        public Dictionary <VariableType, UnaryComparison> getReducedUnaryConstraints()
        {
            if (!getComparisonExpressions(constraint).All(expr => expr.isUnary()))
            {
                throw new PumpingLemmaException("The Language doesn't contain only unary constraints.");
            }

            if (!constraint.isSatisfiable())
            {
                throw new PumpingLemmaException("The Language constraint is not satisfiable.");
            }

            Dictionary <VariableType, UnaryComparison> comparisonsToReturn = new Dictionary <VariableType, UnaryComparison>();

            IEnumerable <ComparisonExpression> allExpr = getComparisonExpressions(constraint);

            //delete non-constraints
            allExpr = allExpr.Except(allExpr.Where(e => e.arithmetic_operand1.isConstant() && e.arithmetic_operand2.isConstant()));

            //put variable on left side
            //divide, so that coefficient = 1
            HashSet <ComparisonExpression> ToDelete = new HashSet <ComparisonExpression>();
            var exprToAdd = new HashSet <ComparisonExpression>();

            foreach (ComparisonExpression expr in allExpr)
            {
                if (expr.arithmetic_operand1.isConstant())
                {
                    switch (expr.comparison_operator)
                    {
                    case ComparisonExpression.ComparisonOperator.GEQ:
                        exprToAdd.Add(ComparisonExpression.LessThanOrEqual(expr.arithmetic_operand2, expr.arithmetic_operand1));
                        break;

                    case ComparisonExpression.ComparisonOperator.GT:
                        exprToAdd.Add(ComparisonExpression.LessThan(expr.arithmetic_operand2, expr.arithmetic_operand1));
                        break;

                    case ComparisonExpression.ComparisonOperator.LEQ:
                        exprToAdd.Add(ComparisonExpression.GreaterThanOrEqual(expr.arithmetic_operand2, expr.arithmetic_operand1));
                        break;

                    case ComparisonExpression.ComparisonOperator.LT:
                        exprToAdd.Add(ComparisonExpression.GreaterThan(expr.arithmetic_operand2, expr.arithmetic_operand1));
                        break;

                    default:
                        break;
                    }
                }
            }

            ToDelete  = new HashSet <ComparisonExpression>(allExpr.Where(e => e.arithmetic_operand1.isConstant()));
            allExpr   = allExpr.Except(ToDelete);
            allExpr   = allExpr.Union(exprToAdd);
            ToDelete  = new HashSet <ComparisonExpression>();
            exprToAdd = new HashSet <ComparisonExpression>();

            foreach (var expr in allExpr)
            {
                foreach (VariableType variable in expr.GetVariables())
                {
                    int    coefficient = expr.arithmetic_operand1.coefficients[variable];
                    int    constant    = expr.arithmetic_operand2.constant;
                    double divided     = (double)constant / (double)coefficient;

                    switch (expr.comparison_operator)
                    {
                    case ComparisonExpression.ComparisonOperator.EQ:
                    case ComparisonExpression.ComparisonOperator.NEQ:
                        if (!isInt(divided))
                        {
                            ToDelete.Add(expr);
                        }
                        else
                        {
                            expr.arithmetic_operand2 = LinearIntegerExpression.Constant(Convert.ToInt32(divided));
                        }
                        break;

                    case ComparisonExpression.ComparisonOperator.GEQ:
                        expr.arithmetic_operand2 = LinearIntegerExpression.Constant(Convert.ToInt32(Math.Ceiling(divided)));
                        break;

                    case ComparisonExpression.ComparisonOperator.GT:
                        expr.arithmetic_operand2 = LinearIntegerExpression.Constant(Convert.ToInt32(Math.Floor(divided)));
                        break;

                    case ComparisonExpression.ComparisonOperator.LEQ:
                        expr.arithmetic_operand2 = LinearIntegerExpression.Constant(Convert.ToInt32(Math.Floor(divided)));
                        break;

                    case ComparisonExpression.ComparisonOperator.LT:
                        expr.arithmetic_operand2 = LinearIntegerExpression.Constant(Convert.ToInt32(Math.Ceiling(divided)));
                        break;

                    default:
                        throw new ArgumentException();
                    }
                }
            }

            allExpr   = allExpr.Except(ToDelete);
            allExpr   = allExpr.Union(exprToAdd);
            ToDelete  = new HashSet <ComparisonExpression>();
            exprToAdd = new HashSet <ComparisonExpression>();


            //reduce if equal constraint is found
            HashSet <string> varsToDelete = new HashSet <string>();

            foreach (ComparisonExpression expr in allExpr)
            {
                if (expr.comparison_operator == ComparisonExpression.ComparisonOperator.EQ)
                {
                    VariableType variable    = expr.arithmetic_operand1.GetVariables().First();
                    int          coefficient = expr.arithmetic_operand1.coefficients[variable];
                    int          constant    = expr.arithmetic_operand2.constant;
                    int          divided     = divideConstant(constant, coefficient);
                    comparisonsToReturn.Add(variable, UnaryComparison.equal(variable, divided));
                    varsToDelete.Add(variable.ToString());
                }
            }
            IEnumerable <ComparisonExpression> exprToDelete = allExpr.Where(e => varsToDelete.Contains(e.arithmetic_operand1.GetVariables().First().ToString()));

            allExpr = allExpr.Except(exprToDelete);

            //GEQ -> GT, LEQ -> LT
            exprToDelete = new HashSet <ComparisonExpression>();
            exprToAdd    = new HashSet <ComparisonExpression>();
            foreach (ComparisonExpression expr in allExpr)
            {
                if (expr.comparison_operator == ComparisonExpression.ComparisonOperator.GEQ)
                {
                    ComparisonExpression newExpr = ComparisonExpression.GreaterThan(expr.arithmetic_operand1, expr.arithmetic_operand2.constant - 1);
                    exprToAdd.Add(newExpr);
                }
                if (expr.comparison_operator == ComparisonExpression.ComparisonOperator.LEQ)
                {
                    ComparisonExpression newExpr = ComparisonExpression.LessThan(expr.arithmetic_operand1, expr.arithmetic_operand2.constant + 1);
                    exprToAdd.Add(newExpr);
                }
            }
            exprToDelete = allExpr.Where(e => e.comparison_operator == ComparisonExpression.ComparisonOperator.LEQ ||
                                         e.comparison_operator == ComparisonExpression.ComparisonOperator.GEQ);
            allExpr = allExpr.Except(exprToDelete);
            allExpr = allExpr.Union(exprToAdd);

            HashSet <VariableType> allVars = new HashSet <VariableType>();

            foreach (ComparisonExpression expr in allExpr)
            {
                allVars.Add(expr.arithmetic_operand1.GetVariables().First());
            }

            foreach (VariableType variable in allVars)
            {
                IEnumerable <ComparisonExpression> varExpr = allExpr.Where(e => variable.ToString().Equals(e.GetVariables().First().ToString()));

                //reduce to single constraints
                IEnumerable <ComparisonExpression> gtExpr = varExpr.Where(e => e.comparison_operator == ComparisonExpression.ComparisonOperator.GT);
                int gthan = -1;
                foreach (ComparisonExpression expr in gtExpr)
                {
                    int coefficient = expr.arithmetic_operand1.coefficients[variable];
                    int constant    = expr.arithmetic_operand2.constant;
                    //floor
                    int divided = constant / coefficient;
                    if (constant > gthan)
                    {
                        gthan = constant;
                    }
                }

                IEnumerable <ComparisonExpression> ltExpr = varExpr.Where(e => e.comparison_operator == ComparisonExpression.ComparisonOperator.LT);
                int lthan = Int32.MaxValue;
                foreach (ComparisonExpression expr in ltExpr)
                {
                    int coefficient = expr.arithmetic_operand1.coefficients[variable];
                    int constant    = expr.arithmetic_operand2.constant;
                    if (constant < lthan)
                    {
                        lthan = constant;
                    }
                }

                varExpr = varExpr.Except(gtExpr);
                varExpr = varExpr.Except(ltExpr);

                //rest should be NEQ
                HashSet <int> neqInts = new HashSet <int>();
                foreach (ComparisonExpression expr in varExpr)
                {
                    if (expr.comparison_operator != ComparisonExpression.ComparisonOperator.NEQ)
                    {
                        throw new PumpingLemmaException("The programmer is stupid.");
                    }
                    int    coefficient = expr.arithmetic_operand1.coefficients[variable];
                    int    constant    = expr.arithmetic_operand2.constant;
                    double divided     = (double)constant / coefficient;
                    //if not int, discard
                    if (Math.Abs(divided % 1) <= (Double.Epsilon * 100))
                    {
                        int divided_int = (int)divided;
                        neqInts.Add(divided_int);
                    }
                }

                if (gthan > -1 && lthan < Int32.MaxValue)
                {
                    comparisonsToReturn.Add(variable, UnaryComparison.between(variable, gthan, lthan, neqInts));
                }
                else if (gthan > -1 && lthan == Int32.MaxValue)
                {
                    comparisonsToReturn.Add(variable, UnaryComparison.greater(variable, gthan, neqInts));
                }
                else if (gthan == -1 && lthan < Int32.MaxValue)
                {
                    comparisonsToReturn.Add(variable, UnaryComparison.between(variable, -1, lthan, neqInts));
                }
                else
                {
                    comparisonsToReturn.Add(variable, UnaryComparison.greater(variable, -1, neqInts));
                }
            }

            return(comparisonsToReturn);
        }
예제 #5
0
        // Generates XML for the
        public XElement SplitDisplayXML(
            VariableType pumpingLength,
            BooleanExpression additionalConstraints)
        {
            Contract.Assert(additionalConstraints.GetVariables().Count() <= 1);
            if (additionalConstraints.GetVariables().Count == 1)
            {
                Contract.Assert(additionalConstraints.GetVariables().First().Equals(pumpingLength));
            }
            var pumpingLengthVariable = LinearIntegerExpression.SingleTerm(1, pumpingLength);

            var repeatLengths = repeats();

            // For great and inexplicable reasons. Trust me, it looks better this way.
            var displayConstraints = LogicalExpression.And(repeatLengths.Select(x =>
                                                                                ComparisonExpression.GreaterThanOrEqual(x, LinearIntegerExpression.Constant(5))
                                                                                ));

            XElement symbstrings = new XElement("symbstrings");

            foreach (var split in this.ValidSplits(pumpingLengthVariable, additionalConstraints))
            {
                var splitRepeatLengths = split.start.repeats();
                splitRepeatLengths.AddRange(split.mid.repeats());
                splitRepeatLengths.AddRange(split.end.repeats());

                // Get models that don't look terrible
                var splitDisplayConstraints = LogicalExpression.And(splitRepeatLengths.Select(x =>
                                                                                              ComparisonExpression.GreaterThanOrEqual(x, LinearIntegerExpression.Constant(1))
                                                                                              ));
                var constraint = LogicalExpression.And(displayConstraints, split.constraints, splitDisplayConstraints);

                if (!constraint.isSatisfiable())
                {
                    continue;
                }
                var splitModel = constraint.getModel();

                var symbstr = new XElement("symbstr");
                var strings = new XElement("strings");
                var splits  = new XElement("splits");
                var constrs = new XElement("constraints");

                Func <string, Tuple <int, int, SymbolicString>, XElement> handleSegment = (parentTagName, segment) => {
                    var parent = new XElement(parentTagName);
                    var from   = new XElement("from"); from.Value = segment.Item1.ToString();
                    var to     = new XElement("to"); to.Value = segment.Item2.ToString();
                    var label  = new XElement("label"); label.Add(segment.Item3.ToDisplayXML());
                    parent.Add(from);
                    parent.Add(to);
                    parent.Add(label);
                    return(parent);
                };

                int strIndex = 0;
                foreach (var segment in getSegments(splitModel, ref strIndex))
                {
                    strings.Add(handleSegment("string", segment));
                }

                int splitIndex = 0;
                foreach (var segment in new[] { split.start, split.mid, split.end })
                {
                    splits.Add(handleSegment("split", segment.makeSegment(splitModel, ref splitIndex)));
                }

                var constr = new XElement("constraint");
                constr.Add(split.constraints.ToDisplayXML());
                constrs.Add(constr);

                symbstr.Add(strings);
                symbstr.Add(splits);
                symbstr.Add(constrs);
                symbstrings.Add(symbstr);
            }

            return(symbstrings);
        }
예제 #6
0
        private static UnaryComparison compExprToUnaryComp(ComparisonExpression expr)
        {
            if (!expr.isUnary())
            {
                return(null);
            }

            if (expr.arithmetic_operand1.isConstant())
            {
                LinearIntegerExpression tmp = expr.arithmetic_operand1;
                expr.arithmetic_operand1 = expr.arithmetic_operand2;
                expr.arithmetic_operand2 = tmp;
                switch (expr.comparison_operator)
                {
                case ComparisonExpression.ComparisonOperator.GEQ:
                    expr.comparison_operator = ComparisonExpression.ComparisonOperator.LEQ;
                    break;

                case ComparisonExpression.ComparisonOperator.GT:
                    expr.comparison_operator = ComparisonExpression.ComparisonOperator.LT;
                    break;

                case ComparisonExpression.ComparisonOperator.LEQ:
                    expr.comparison_operator = ComparisonExpression.ComparisonOperator.GEQ;
                    break;

                case ComparisonExpression.ComparisonOperator.LT:
                    expr.comparison_operator = ComparisonExpression.ComparisonOperator.GT;
                    break;

                default:
                    break;
                }
            }

            VariableType variable    = expr.GetVariables().First();
            int          coefficient = expr.arithmetic_operand1.coefficients[variable];
            int          constant    = expr.arithmetic_operand2.constant;
            double       divided     = (double)constant / (double)coefficient;

            switch (expr.comparison_operator)
            {
            case ComparisonExpression.ComparisonOperator.EQ:
            case ComparisonExpression.ComparisonOperator.NEQ:
                if (!isInt(divided))
                {
                    return(null);
                }
                else
                {
                    expr.arithmetic_operand2 = LinearIntegerExpression.Constant(Convert.ToInt32(divided));
                }
                break;

            case ComparisonExpression.ComparisonOperator.GEQ:
                expr.arithmetic_operand2 = LinearIntegerExpression.Constant(Convert.ToInt32(Math.Ceiling(divided)));
                break;

            case ComparisonExpression.ComparisonOperator.GT:
                expr.arithmetic_operand2 = LinearIntegerExpression.Constant(Convert.ToInt32(Math.Floor(divided)));
                break;

            case ComparisonExpression.ComparisonOperator.LEQ:
                expr.arithmetic_operand2 = LinearIntegerExpression.Constant(Convert.ToInt32(Math.Floor(divided)));
                break;

            case ComparisonExpression.ComparisonOperator.LT:
                expr.arithmetic_operand2 = LinearIntegerExpression.Constant(Convert.ToInt32(Math.Ceiling(divided)));
                break;

            default:
                throw new ArgumentException();
            }

            if (expr.comparison_operator == ComparisonExpression.ComparisonOperator.GEQ)
            {
                expr.comparison_operator = ComparisonExpression.ComparisonOperator.GT;
                expr.arithmetic_operand2.constant--;
            }
            if (expr.comparison_operator == ComparisonExpression.ComparisonOperator.LEQ)
            {
                expr.comparison_operator = ComparisonExpression.ComparisonOperator.LT;
                expr.arithmetic_operand2.constant++;
            }

            switch (expr.comparison_operator)
            {
            case ComparisonExpression.ComparisonOperator.EQ:
                return(UnaryComparison.equal(variable, expr.arithmetic_operand2.constant));

            case ComparisonExpression.ComparisonOperator.GT:
                return(UnaryComparison.greater(variable, expr.arithmetic_operand2.constant, new HashSet <int>()));

            case ComparisonExpression.ComparisonOperator.LT:
                return(UnaryComparison.between(variable, -1, expr.arithmetic_operand2.constant, new HashSet <int>()));

            default:
                return(null);
            }
        }
 public static LinearIntegerExpression operator -(LinearIntegerExpression a, int b)
 {
     return(Plus(a, LinearIntegerExpression.Constant(-b)));
 }
 public static ComparisonExpression NotEqual(LinearIntegerExpression op1, int op2)
 {
     return(NotEqual(op1, LinearIntegerExpression.Constant(op2)));
 }
 public static ComparisonExpression GreaterThanOrEqual(LinearIntegerExpression op1, int op2)
 {
     return(GreaterThanOrEqual(op1, LinearIntegerExpression.Constant(op2)));
 }
 public static ComparisonExpression LessThan(LinearIntegerExpression op1, int op2)
 {
     return(LessThan(op1, LinearIntegerExpression.Constant(op2)));
 }