Пример #1
0
        // Returns only those matches where s1 is consumed fully
        private static IEnumerable <Match> allLeftMatches(SymbolicString s1, SymbolicString s2)
        {
            // First empty
            yield return(Match.PartialSecond(
                             LogicalExpression.And(
                                 ComparisonExpression.Equal(s1.length(), 0),
                                 ComparisonExpression.GreaterThan(s2.length(), 0)
                                 ),
                             s2
                             ));

            // First non-empty
            if (!omegaEqual(s1.root, s2.root))
            { // They will mismatch at some point. So, just get small matches up to that point
                int firstMismatch = getFirstMismatch(s1.root, s2.root);
                foreach (var m in shortLeftMatches(s1, s2, firstMismatch))
                {
                    yield return(m.withAdditionalConstraint(ComparisonExpression.GreaterThan(s1.length(), 0)));
                }
            }
            else
            { // They will never mismatch. So, split s2 into two parts where s1 = first part
                foreach (var m in longLeftMatches(s1, s2))
                {
                    yield return(m.withAdditionalConstraint(ComparisonExpression.GreaterThan(s1.length(), 0)));
                }
            }
        }
Пример #2
0
        private static IEnumerable <Match> longLeftMatches(SymbolicString s1, SymbolicString s2)
        {
            var l1    = s1.root.wordLength();
            var l2    = s2.root.wordLength();
            var g     = gcd(l1, l2);
            var v_beg = LinearIntegerExpression.FreshVariable();
            var v_end = LinearIntegerExpression.FreshVariable();

            // Split exactly at s2 root border
            yield return(Match.PartialSecond(
                             LogicalExpression.And(
                                 // the beginning matches the s1
                                 ComparisonExpression.Equal(
                                     LinearIntegerExpression.Times(l2, v_beg),
                                     LinearIntegerExpression.Times(l1, s1.repeat)
                                     ),
                                 // left over right bit is nonempty
                                 ComparisonExpression.GreaterThan(
                                     LinearIntegerExpression.Times(l2, v_end),
                                     0
                                     ),
                                 // beginning and end match s2
                                 ComparisonExpression.Equal(v_beg + v_end, s2.repeat),
                                 ComparisonExpression.GreaterThanOrEqual(v_beg, 0),
                                 ComparisonExpression.GreaterThanOrEqual(v_end, 0)
                                 ),
                             SymbolicString.Repeat(s2.root, v_end)
                             ));

            // Split in the middle of s2 root
            if (l2 != 1)
            {
                for (int i = g; i < l2; i += g)
                {
                    var suffix = SymbolicString.Concat(s2.root.sub_strings.Skip(i));
                    yield return(Match.PartialSecond(
                                     LogicalExpression.And(
                                         ComparisonExpression.Equal(
                                             LinearIntegerExpression.Times(l2, v_beg) + g,
                                             LinearIntegerExpression.Times(l1, s1.repeat)
                                             ),
                                         ComparisonExpression.GreaterThan(
                                             LinearIntegerExpression.Times(l2, v_beg) + suffix.length(),
                                             0
                                             ),
                                         ComparisonExpression.Equal(v_beg + v_end + 1, s2.repeat),
                                         ComparisonExpression.GreaterThanOrEqual(v_beg, 0),
                                         ComparisonExpression.GreaterThanOrEqual(v_end, 0)
                                         ),
                                     SymbolicString.Concat(suffix, SymbolicString.Repeat(s2.root, v_end))
                                     ));
                }
            }
        }
Пример #3
0
        // Either consume symbol with first symbol of repeat and say repeat is positive
        // Or don't consume symbol and say repeat is zero
        private static IEnumerable <Match> matchSymbolRepeat(SymbolicString s1, SymbolicString s2)
        {
            Debug.Assert(s2.isFlat());

            // When repeat is 0
            yield return(Match.PartialFirst(ComparisonExpression.Equal(s2.repeat, 0), s1));

            // When repeat is non-zero
            foreach (var m in match(s1, s2.root))
            {
                // Because the root is a word, we immediately know if the symbol matches or not
                // and get an m if and only if the symbol matches
                Debug.Assert(!m.FirstRemaining);
                yield return(Match.PartialSecond(
                                 LogicalExpression.And(m.constraint, ComparisonExpression.GreaterThan(s2.repeat, 0)),
                                 SymbolicString.Concat(m.remaining2, SymbolicString.Repeat(s2.root, s2.repeat - 1))
                                 ));
            }
        }
Пример #4
0
        private static IEnumerable <Match> shortLeftMatches(SymbolicString s1, SymbolicString s2, int firstMismatch)
        {
            int l1 = s1.root.wordLength();

            for (int i = 1; l1 *i <= firstMismatch; i++)
            {
                var s1r = SymbolicString.Concat(Enumerable.Repeat(s1.root, i));
                foreach (var m in match(s1r, s2))
                {
                    if (m.FirstRemaining)
                    {
                        continue;
                    }
                    yield return(m.withAdditionalConstraint(LogicalExpression.And(
                                                                ComparisonExpression.Equal(s1.length(), s1r.length()),
                                                                ComparisonExpression.GreaterThan(m.remaining2.length(), 0)
                                                                )));
                }
            }
        }
Пример #5
0
        private static IEnumerable <Match> matchRepeatConcat(SymbolicString s1, SymbolicString s2)
        {
            if (s2.isEpsilon())
            {
                yield return(Match.FullMatch(ComparisonExpression.Equal(s1.length(), 0)));

                yield return(Match.PartialFirst(ComparisonExpression.GreaterThan(s1.length(), 0), s1));

                yield break;
            }
            var first = s2.sub_strings.First();
            var rest  = SymbolicString.Concat(s2.sub_strings.Skip(1));

            foreach (var m in match(s1, first))
            {
                foreach (var mp in m.continueMatch(SymbolicString.Epsilon(), rest))
                {
                    yield return(mp);
                }
            }
        }
Пример #6
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 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);
        }