예제 #1
0
        public static string NonRegularGetRandomWord(ArithmeticLanguage language, int n)
        {
            HashSet <Dictionary <VariableType, int> > usedAssigments = new HashSet <Dictionary <VariableType, int> >();
            HashSet <VariableType> vars = language.constraint.GetVariables();

            for (int i = 0; i < Math.Pow(n, vars.Count); i++)
            {
                Dictionary <VariableType, int> newAssigment = new Dictionary <VariableType, int>();
                foreach (VariableType v in vars)
                {
                    newAssigment.Add(v, randInt(0, n));
                }
                if (usedAssigments.Contains(newAssigment))
                {
                    i--;
                }
                else
                {
                    usedAssigments.Add(newAssigment);
                    //check sat
                    HashSet <BooleanExpression> ops = new HashSet <BooleanExpression>();
                    ops.Add(language.constraint);
                    foreach (var entry in newAssigment)
                    {
                        ops.Add(ComparisonExpression.Equal(LinearIntegerExpression.Variable(entry.Key.ToString()), entry.Value));
                    }
                    BooleanExpression expr = LogicalExpression.And(ops);
                    if (expr.isSatisfiable())
                    {
                        return(pumpedWord(language.symbolic_string, newAssigment));
                    }
                }
            }
            return(wordError());
        }
예제 #2
0
        public static SymbolicString repeatLast(SymbolicString s, LinearIntegerExpression e)
        {
            if (s == null || e == null)
            {
                return(null);
            }

            switch (s.expression_type)
            {
            case SymbolicString.SymbolicStringType.Symbol:
                return(SymbolicString.Repeat(s, e));

            case SymbolicString.SymbolicStringType.Repeat:
                return(SymbolicString.Repeat(s, e));

            case SymbolicString.SymbolicStringType.Concat:
                List <SymbolicString> sub_strings = new List <SymbolicString>();
                sub_strings.AddRange(s.sub_strings.Take(s.sub_strings.Count - 1));
                var last = s.sub_strings[s.sub_strings.Count - 1];
                sub_strings.Add(SymbolicString.Repeat(last, e));
                return(SymbolicString.Concat(sub_strings));

            default:
                throw new ArgumentOutOfRangeException();
            }
        }
예제 #3
0
        private static IEnumerable <Match> matchRepeatRepeat(SymbolicString s1, SymbolicString s2)
        {
            Debug.Assert(s1.root.isWord());
            Debug.Assert(s2.root.isWord());

            // Assume s1 is fully consumed
            foreach (var m in allLeftMatches(s1, s2))
            {
                yield return(m);
            }

            // Assume s2 is fully consumed
            foreach (var m in allLeftMatches(s2, s1))
            {
                yield return(m.reverse());
            }

            // Assume both are fully consumed
            if (omegaEqual(s1.root, s2.root))
            {
                yield return(Match.FullMatch(ComparisonExpression.Equal(
                                                 LinearIntegerExpression.Times(s1.root.wordLength(), s1.repeat),
                                                 LinearIntegerExpression.Times(s2.root.wordLength(), s2.repeat)
                                                 )));
            }
            else
            {
                yield return(Match.FullMatch(LogicalExpression.And(
                                                 ComparisonExpression.Equal(s2.length(), 0),
                                                 ComparisonExpression.Equal(s1.length(), 0)
                                                 )));
            }
        }
예제 #4
0
 private void Copy(SymbolicString that)
 {
     this.expression_type = that.expression_type;
     this.atomic_symbol   = that.atomic_symbol;
     this.root            = that.root;
     this.repeat          = that.repeat;
     this.sub_strings     = that.sub_strings;
 }
 public static bool canMismatchWitness(
     SymbolicString midLanguage,
     SymbolicString midSplit,
     BooleanExpression fullConstraint,
     LinearIntegerExpression pumpingWitness
     )
 {
     throw new NotImplementedException();
 }
예제 #6
0
        public static SymbolicString repeat(SymbolicString s, LinearIntegerExpression e)
        {
            if (s == null || e == null)
            {
                return(null);
            }

            return(SymbolicString.Repeat(s, e));
        }
        // Returns true if start.(mid)^witness.end is not in the language for all models
        // that satisfy the additionalConstraint
        public static bool splitGoodWithWitness(
            Split split,
            ArithmeticLanguage language,
            BooleanExpression additionalConstraint,
            LinearIntegerExpression pumpingWitness)
        {
            // We just need to find a k such that (x y^k z) \not\in L
            // If we cannot find such a k for some p, it is a bad split

            // Say i, j are the variables in the language constraint and
            // v_1, v_2 are variables in split constraints
            // Therefore, if for all p, v_1, \ldots, v_n that satisfies split constraints
            // and additional constraints and exists k such that for all i, j language
            // constraint does not hold, then split is bad
            Console.WriteLine("\t\tSplit is good if none of the following mids can be pumped: ");

            // We will definitely go through the loop at least once as match is working
            var beginningMatches = Matcher
                                   .match(split.start, language.symbolic_string)
                                   .Where(x => !x.FirstRemaining)
                                   .Select(x => x.withAdditionalConstraint(language.constraint))
                                   .Select(x => x.withAdditionalConstraint(additionalConstraint))
                                   .Where(x => x.isFeasible());

            foreach (var beginMatch in beginningMatches)
            {
                var remainingLanguage = beginMatch.remaining2;
                var endMatches        = Matcher
                                        .match(split.end.reverse(), remainingLanguage.reverse())
                                        .Where(x => !x.FirstRemaining)
                                        .Select(x => x.withAdditionalConstraint(language.constraint))
                                        .Select(x => x.withAdditionalConstraint(additionalConstraint))
                                        .Where(x => x.isFeasible());

                foreach (var endMatch in endMatches)
                {
                    var fullConstraint = LogicalExpression.And(beginMatch.constraint, endMatch.constraint);
                    if (!fullConstraint.isSatisfiable())
                    {
                        continue;
                    }
                    var midLanguage = endMatch.remaining2.reverse();
                    var midSplit    = split.mid;
                    var ctx         = new Context();
                    // Console.WriteLine("\t\t" + midLanguage + " ===== " + midSplit + " when " + fullConstraint);
                    // var z3exp = fullConstraint.toZ3(ctx).Simplify();
                    // Console.WriteLine("\t\t" + midLanguage + " ===== " + midSplit + " when " + z3exp);
                    if (!canMismatchWitness(midLanguage, midSplit, fullConstraint, pumpingWitness))
                    {
                        return(false);
                    }
                }
            }
            return(true);
        }
예제 #8
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))
                                     ));
                }
            }
        }
        public static LinearIntegerExpression Times(int multiplier, LinearIntegerExpression b)
        {
            int constant     = b.constant * multiplier;
            var coefficients = new Dictionary <VariableType, int>();

            foreach (var kv in b.coefficients)
            {
                coefficients[kv.Key] = kv.Value * multiplier;
            }
            return(new LinearIntegerExpression(constant, coefficients));
        }
예제 #10
0
        public static bool checkPumping(
            ArithmeticLanguage language,
            SymbolicString pumpingString,
            Split split,
            LinearIntegerExpression pump)
        {
            if (pump.isConstant())
            {
                var k = pump.constant;
                var pumpedMid = SymbolicString.Concat(Enumerable.Repeat(split.mid, k));
                var pumpedString = SymbolicString.Concat(split.start, pumpedMid, split.end);

                return checkNonContainment(pumpedString, language, split.constraints);
            }
            else
            {
                throw new NotImplementedException();
            }
        }
        public static bool checkPumping(
            ArithmeticLanguage language,
            SymbolicString pumpingString,
            Split split,
            LinearIntegerExpression pump)
        {
            if (pump.isConstant())
            {
                var k            = pump.constant;
                var pumpedMid    = SymbolicString.Concat(Enumerable.Repeat(split.mid, k));
                var pumpedString = SymbolicString.Concat(split.start, pumpedMid, split.end);

                return(checkNonContainment(pumpedString, language, split.constraints));
            }
            else
            {
                throw new NotImplementedException();
            }
        }
예제 #12
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();
            }
        }
예제 #13
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);
                }
            }
        }
        private ComparisonExpression(ComparisonOperator op, LinearIntegerExpression oper1, LinearIntegerExpression oper2)
        {
            boolean_expression_type = OperatorType.Comparison;
            switch (op)
            {
            case ComparisonOperator.LEQ:
                boolean_operation_arity = OperatorArity.Two;
                break;

            case ComparisonOperator.LT:
                boolean_operation_arity = OperatorArity.Two;
                break;

            case ComparisonOperator.GEQ:
                boolean_operation_arity = OperatorArity.Two;
                break;

            case ComparisonOperator.GT:
                boolean_operation_arity = OperatorArity.Two;
                break;

            case ComparisonOperator.EQ:
                boolean_operation_arity = OperatorArity.Two;
                break;

            case ComparisonOperator.NEQ:
                boolean_operation_arity = OperatorArity.Two;
                break;

            default:
                throw new ArgumentOutOfRangeException();
            }

            comparison_operator = op;
            operand1            = oper1;
            operand2            = oper2;
            arithmetic_operand1 = oper1;
            arithmetic_operand2 = oper2;
        }
예제 #15
0
 public static bool canMismatchWitness(
     SymbolicString midLanguage,
     SymbolicString midSplit,
     BooleanExpression fullConstraint,
     LinearIntegerExpression pumpingWitness
     )
 {
     throw new NotImplementedException();
 }
예제 #16
0
        // Generate TwoSplit's where either one may be empty
        // Generates the splits in order, i.e., by length of the prefix
        // So, for s being symbol and concat, first one will always be (\epsilon, s) and last one always (s, \epsilon)
        // So, for s being repeat (abc)^n, first will be ((abc)^i,(abc)^j) and last one always ((abc)^i ab, c(abc)^j)
        // Requires a flat symbolic string
        public IEnumerable <TwoSplit> TwoSplits()
        {
            SymbolicString prefix, suffix;

            // Contract.Requires(this.isFlat());


            switch (this.expression_type)
            {
            case SymbolicStringType.Symbol:
                yield return(TwoSplit.MakeSplit(SymbolicString.Epsilon(), this, LogicalExpression.True()));

                yield return(TwoSplit.MakeSplit(this, SymbolicString.Epsilon(), LogicalExpression.True()));

                break;

            case SymbolicStringType.Concat:
                yield return(TwoSplit.MakeSplit(SymbolicString.Epsilon(), this, LogicalExpression.True()));

                for (int i = 0; i < this.sub_strings.Count; i++)
                {
                    prefix = SymbolicString.Concat(this.sub_strings.Take(i).ToList());
                    suffix = SymbolicString.Concat(this.sub_strings.Skip(i + 1).ToList());
                    foreach (var split in this.sub_strings[i].TwoSplits())
                    {
                        if (!split.start.isEpsilon())
                        {
                            yield return(split.extend(prefix, suffix));
                        }
                    }
                }
                break;

            case SymbolicStringType.Repeat:
                var v1 = LinearIntegerExpression.FreshVariable();
                var v2 = LinearIntegerExpression.FreshVariable();
                var sanityConstraint = LogicalExpression.And(
                    ComparisonExpression.GreaterThanOrEqual(v1, 0),
                    ComparisonExpression.GreaterThanOrEqual(v2, 0)
                    );
                prefix = SymbolicString.Repeat(this.root, v1);
                suffix = SymbolicString.Repeat(this.root, v2);
                yield return(TwoSplit.MakeSplit(
                                 prefix,
                                 suffix,
                                 LogicalExpression.And(sanityConstraint, ComparisonExpression.Equal(v1 + v2, this.repeat))
                                 ));

                if (this.root.expression_type != SymbolicStringType.Concat)
                {
                    break;
                }
                for (int i = 1; i < this.root.sub_strings.Count; i++)
                {
                    var split = TwoSplit.MakeSplit(
                        SymbolicString.Concat(this.root.sub_strings.Take(i)),
                        SymbolicString.Concat(this.root.sub_strings.Skip(i)),
                        LogicalExpression.And(
                            ComparisonExpression.Equal(v1 + v2 + 1, this.repeat),
                            sanityConstraint
                            )
                        );
                    yield return(split.extend(prefix, suffix));
                }
                break;

            default:
                throw new ArgumentOutOfRangeException();
            }
        }
예제 #17
0
 private SymbolicString(SymbolicString root, LinearIntegerExpression repeat)
 {
     this.expression_type = SymbolicStringType.Repeat;
     this.root = root;
     this.repeat = repeat;
 }
예제 #18
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 ComparisonExpression GreaterThanOrEqual(LinearIntegerExpression op1, LinearIntegerExpression op2)
 {
     return new ComparisonExpression(ComparisonOperator.GEQ, op1, op2);
 }
 public static ComparisonExpression LessThan(LinearIntegerExpression op1, LinearIntegerExpression op2)
 {
     return new ComparisonExpression(ComparisonOperator.LT, op1, op2);
 }
        private ComparisonExpression(ComparisonOperator op, LinearIntegerExpression oper1, LinearIntegerExpression oper2)
        {
            boolean_expression_type = OperatorType.Comparison;
            switch (op)
            {
                case ComparisonOperator.LEQ:
                    boolean_operation_arity = OperatorArity.Two;
                    break;
                case ComparisonOperator.LT:
                    boolean_operation_arity = OperatorArity.Two;
                    break;
                case ComparisonOperator.GEQ:
                    boolean_operation_arity = OperatorArity.Two;
                    break;
                case ComparisonOperator.GT:
                    boolean_operation_arity = OperatorArity.Two;
                    break;
                case ComparisonOperator.EQ:
                    boolean_operation_arity = OperatorArity.Two;
                    break;
                case ComparisonOperator.NEQ:
                    boolean_operation_arity = OperatorArity.Two;
                    break;
                default:
                    throw new ArgumentOutOfRangeException();
            }

            comparison_operator = op;
            operand1 = oper1;
            operand2 = oper2;
            arithmetic_operand1 = oper1;
            arithmetic_operand2 = oper2;
        }
 public static LinearIntegerExpression operator -(LinearIntegerExpression a, int b)
 {
     return(Plus(a, LinearIntegerExpression.Constant(-b)));
 }
 public static LinearIntegerExpression operator -(LinearIntegerExpression a, LinearIntegerExpression b)
 {
     return(Plus(a, LinearIntegerExpression.Times(-1, b)));
 }
 public static LinearIntegerExpression Plus(LinearIntegerExpression a, LinearIntegerExpression b)
 {
     return(Plus(new List <LinearIntegerExpression> {
         a, b
     }));
 }
 public static ComparisonExpression LessThan(LinearIntegerExpression op1, int op2)
 {
     return(LessThan(op1, LinearIntegerExpression.Constant(op2)));
 }
 public static ComparisonExpression NotEqual(LinearIntegerExpression op1, int op2)
 {
     return(NotEqual(op1, LinearIntegerExpression.Constant(op2)));
 }
예제 #27
0
        private static SymbolicString splitToSymbStr(List <string> alphabet, string start, string mid, string end)
        {
            VariableType          freshVar = VariableType.FreshVariable();
            List <SymbolicString> strings  = new List <SymbolicString>();

            if (!start.Equals(""))
            {
                strings.Add(SymbolicString.FromTextDescription(alphabet, start));
            }
            SymbolicString pumpedMid = SymbolicString.Repeat(SymbolicString.FromTextDescription(alphabet, mid), LinearIntegerExpression.Variable(freshVar.ToString()));

            strings.Add(pumpedMid);
            if (!end.Equals(""))
            {
                strings.Add(SymbolicString.FromTextDescription(alphabet, end));
            }

            SymbolicString matchingString = SymbolicString.Concat(strings);

            return(matchingString);
        }
 public static ComparisonExpression NotEqual(LinearIntegerExpression op1, LinearIntegerExpression op2)
 {
     return new ComparisonExpression(ComparisonOperator.NEQ, op1, op2);
 }
예제 #29
0
 private void Copy(SymbolicString that)
 {
     this.expression_type = that.expression_type;
     this.atomic_symbol = that.atomic_symbol;
     this.root = that.root;
     this.repeat = that.repeat;
     this.sub_strings = that.sub_strings;
 }
 public static ComparisonExpression LessThan(LinearIntegerExpression op1, int op2)
 {
     return LessThan(op1, LinearIntegerExpression.Constant(op2));
 }
예제 #31
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 ComparisonExpression NotEqual(LinearIntegerExpression op1, LinearIntegerExpression op2)
 {
     return(new ComparisonExpression(ComparisonOperator.NEQ, op1, op2));
 }
예제 #33
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);
        }
예제 #34
0
        public static SymbolicString repeatLast(SymbolicString s, LinearIntegerExpression e)
        {
            if (s == null || e == null)
                return null;

            switch(s.expression_type)
            {
                case SymbolicString.SymbolicStringType.Symbol:
                    return SymbolicString.Repeat(s, e);
                case SymbolicString.SymbolicStringType.Repeat:
                    return SymbolicString.Repeat(s, e);
                case SymbolicString.SymbolicStringType.Concat:
                    List<SymbolicString> sub_strings = new List<SymbolicString>();
                    sub_strings.AddRange(s.sub_strings.Take(s.sub_strings.Count - 1));
                    var last = s.sub_strings[s.sub_strings.Count - 1];
                    sub_strings.Add(SymbolicString.Repeat(last, e));
                    return SymbolicString.Concat(sub_strings);
                default:
                    throw new ArgumentOutOfRangeException();
            }
        }
예제 #35
0
        // Generates splits where all three parts may be empty
        public IEnumerable <Split> Splits()
        {
            // Contract.Requires<ArgumentException>(this.isFlat());
            switch (this.expression_type)
            {
            case SymbolicStringType.Symbol:
                yield return(Split.MakeSplit(this, SymbolicString.Epsilon(), SymbolicString.Epsilon(), LogicalExpression.True()));

                yield return(Split.MakeSplit(SymbolicString.Epsilon(), this, SymbolicString.Epsilon(), LogicalExpression.True()));

                yield return(Split.MakeSplit(SymbolicString.Epsilon(), SymbolicString.Epsilon(), this, LogicalExpression.True()));

                break;

            case SymbolicStringType.Repeat:
                var v1 = LinearIntegerExpression.FreshVariable();
                var v2 = LinearIntegerExpression.FreshVariable();
                var v3 = LinearIntegerExpression.FreshVariable();
                var sanityConstraint = LogicalExpression.And(
                    ComparisonExpression.GreaterThanOrEqual(v1, 0),
                    ComparisonExpression.GreaterThanOrEqual(v2, 0),
                    ComparisonExpression.GreaterThanOrEqual(v3, 0)
                    );
                // Suppose the word w = a_0 a_1 \ldots a_{n-1}
                // All splits are of the form
                //    BEG: (a_0 \ldots a_{n-1})^i (a_0 \ldots a_p)                              = w^i . w_1
                //    MID: (a_{p+1} \ldots a_{n-1} a_0 \ldots a_p)^j (a_{p+1} \ldots a_q)       = (w_2 w_1)^j  w_3
                //    END: (a_{q+1} \ldots a_{n-1}) (a_0 \ldots a_{n-1})^k                          = w_4 w^k
                var w  = this.root.wordSymbols();
                var ww = w.Concat(w);
                int n  = w.Count();
                for (int w1len = 0; w1len < n; w1len++)
                {
                    var w_1 = w.Take(w1len);
                    var w_2 = w.Skip(w1len);
                    var beg = SymbolicString.Concat(
                        SymbolicString.Repeat(this.root, v1),
                        SymbolicString.Concat(w_1));
                    var mid_root = SymbolicString.Concat(
                        SymbolicString.Concat(w_2),
                        SymbolicString.Concat(w_1));
                    var mid_beg = SymbolicString.Repeat(mid_root, v2);
                    for (int w3len = 0; w3len < n; w3len++)
                    {
                        var w_3 = ww.Skip(w1len).Take(w3len);
                        var mid = SymbolicString.Concat(mid_beg, SymbolicString.Concat(w_3.ToList()));

                        IEnumerable <SymbolicString> w_4;
                        if (w1len + w3len == 0)
                        {
                            w_4 = new List <SymbolicString>();
                        }
                        else if (w1len + w3len <= n)
                        {
                            w_4 = w.Skip(w1len).Skip(w3len);
                        }
                        else
                        {
                            w_4 = ww.Skip(w1len).Skip(w3len);
                        }
                        var end = SymbolicString.Concat(
                            SymbolicString.Concat(w_4.ToList()),
                            SymbolicString.Repeat(this.root, v3)
                            );

                        var consumed = (w_1.Count() + w_3.Count() + w_4.Count()) / w.Count();
                        yield return(Split.MakeSplit(
                                         beg,
                                         mid,
                                         end,
                                         LogicalExpression.And(
                                             ComparisonExpression.Equal(v1 + v2 + v3 + consumed, this.repeat),
                                             sanityConstraint
                                             )
                                         ));
                    }
                }
                break;

            case SymbolicStringType.Concat:
                foreach (var beg_midend in this.TwoSplits())
                {
                    foreach (var mid_end in beg_midend.end.TwoSplits())
                    {
                        yield return(Split.MakeSplit(
                                         beg_midend.start,
                                         mid_end.start,
                                         mid_end.end,
                                         LogicalExpression.And(beg_midend.constraints, mid_end.constraints)));
                    }
                }
                break;

            default:
                throw new ArgumentOutOfRangeException();
            }
        }
        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));
        }
예제 #37
0
 private SymbolicString(SymbolicString root, LinearIntegerExpression repeat)
 {
     this.expression_type = SymbolicStringType.Repeat;
     this.root            = root;
     this.repeat          = repeat;
 }
예제 #38
0
        // Returns true if start.(mid)^witness.end is not in the language for all models
        // that satisfy the additionalConstraint
        public static bool splitGoodWithWitness(
            Split split,
            ArithmeticLanguage language,
            BooleanExpression additionalConstraint, 
            LinearIntegerExpression pumpingWitness)
        {
            // We just need to find a k such that (x y^k z) \not\in L
            // If we cannot find such a k for some p, it is a bad split

            // Say i, j are the variables in the language constraint and 
            // v_1, v_2 are variables in split constraints
            // Therefore, if for all p, v_1, \ldots, v_n that satisfies split constraints
            // and additional constraints and exists k such that for all i, j language 
            // constraint does not hold, then split is bad
            Console.WriteLine("\t\tSplit is good if none of the following mids can be pumped: ");

            // We will definitely go through the loop at least once as match is working
            var beginningMatches = Matcher
                .match(split.start, language.symbolic_string)
                .Where(x => !x.FirstRemaining)
                .Select(x => x.withAdditionalConstraint(language.constraint))
                .Select(x => x.withAdditionalConstraint(additionalConstraint))
                .Where(x => x.isFeasible());
            foreach (var beginMatch in beginningMatches)
            {
                var remainingLanguage = beginMatch.remaining2;
                var endMatches = Matcher
                    .match(split.end.reverse(), remainingLanguage.reverse())
                    .Where(x => !x.FirstRemaining)
                    .Select(x => x.withAdditionalConstraint(language.constraint))
                    .Select(x => x.withAdditionalConstraint(additionalConstraint))
                    .Where(x => x.isFeasible());

                foreach (var endMatch in endMatches)
                {
                    var fullConstraint = LogicalExpression.And(beginMatch.constraint, endMatch.constraint);
                    if (!fullConstraint.isSatisfiable())
                        continue;
                    var midLanguage = endMatch.remaining2.reverse();
                    var midSplit = split.mid;
                    var ctx = new Context();
                    // Console.WriteLine("\t\t" + midLanguage + " ===== " + midSplit + " when " + fullConstraint);
                    // var z3exp = fullConstraint.toZ3(ctx).Simplify();
                    // Console.WriteLine("\t\t" + midLanguage + " ===== " + midSplit + " when " + z3exp);
                    if (!canMismatchWitness(midLanguage, midSplit, fullConstraint, pumpingWitness))
                    {
                        return false;
                    }
                }
            }
            return true;
        }
예제 #39
0
 public static SymbolicString Repeat(SymbolicString root, LinearIntegerExpression repeat)
 {
     return(new SymbolicString(root, repeat));
 }
예제 #40
0
 public static SymbolicString Repeat(SymbolicString root, LinearIntegerExpression repeat)
 {
     return new SymbolicString(root, repeat);
 }
 public static ComparisonExpression GreaterThanOrEqual(LinearIntegerExpression op1, int op2)
 {
     return GreaterThanOrEqual(op1, LinearIntegerExpression.Constant(op2));
 }
 public static ComparisonExpression GreaterThanOrEqual(LinearIntegerExpression op1, int op2)
 {
     return(GreaterThanOrEqual(op1, LinearIntegerExpression.Constant(op2)));
 }
예제 #43
0
        public static SymbolicString repeat(SymbolicString s, LinearIntegerExpression e)
        {
            if (s == null || e == null)
                return null;

            return SymbolicString.Repeat(s, e);
        }
 public static ComparisonExpression NotEqual(LinearIntegerExpression op1, int op2)
 {
     return NotEqual(op1, LinearIntegerExpression.Constant(op2));
 }
        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);
        }
 public static LinearIntegerExpression Times(int multiplier, LinearIntegerExpression b)
 {
     int constant = b.constant * multiplier;
     var coefficients = new Dictionary<VariableType, int>();
     foreach (var kv in b.coefficients)
         coefficients[kv.Key] = kv.Value * multiplier;
     return new LinearIntegerExpression(constant, coefficients);
 }
        private static Tuple <NFA <string, string>, HashSet <TwoTuple <State <string>, State <string> > > > epsNFA(SymbolicString symbolicString, HashSet <string> alphabet, Dictionary <VariableType, UnaryComparison> comparisons)
        {
            var states             = new HashSet <State <string> >();
            var delta              = new Dictionary <TwoTuple <State <string>, string>, HashSet <State <string> > >();
            var Q_0                = new HashSet <State <string> >();
            var F                  = new HashSet <State <string> >();
            var epsilonTransitions = new HashSet <TwoTuple <State <string>, State <string> > >();
            var nfa                = new NFA <string, string>(states, alphabet, delta, Q_0, F);

            switch (symbolicString.expression_type)
            {
            case SymbolicString.SymbolicStringType.Symbol:
                var symbol = symbolicString.atomic_symbol;
                var q_0    = createState();
                Q_0.Add(q_0);
                states.Add(q_0);
                var q_1 = createState();
                states.Add(q_1);
                F.Add(q_1);
                var twoTuple = new TwoTuple <State <string>, string>(q_0, symbol);
                var to       = new HashSet <State <string> >();
                to.Add(q_1);
                delta.Add(twoTuple, to);
                nfa = new NFA <string, string>(states, alphabet, delta, Q_0, F);
                return(Tuple.Create(nfa, epsilonTransitions));

            case SymbolicString.SymbolicStringType.Concat:
                var listOfNFAs = new LinkedList <Tuple <NFA <string, string>, HashSet <TwoTuple <State <string>, State <string> > > > >();
                foreach (SymbolicString str in symbolicString.sub_strings)
                {
                    listOfNFAs.AddLast(epsNFA(str, alphabet, comparisons));
                }
                return(concatAutomata(listOfNFAs));

            case SymbolicString.SymbolicStringType.Repeat:
                LinearIntegerExpression lie = symbolicString.repeat;
                var lisNFAs = new LinkedList <Tuple <NFA <string, string>, HashSet <TwoTuple <State <string>, State <string> > > > >();
                for (int i = 0; i < lie.constant; i++)
                {
                    lisNFAs.AddLast(epsNFA(symbolicString.root, alphabet, comparisons));
                }
                foreach (var coeff in lie.coefficients)
                {
                    var compar = comparisons[coeff.Key];
                    switch (compar.comparisonType)
                    {
                    case UnaryComparison.ComparisonType.EQUAL:
                        for (int i = 0; i < coeff.Value * compar.constant; i++)
                        {
                            lisNFAs.AddLast(epsNFA(symbolicString.root, alphabet, comparisons));
                        }
                        break;

                    case UnaryComparison.ComparisonType.GREATER:
                        for (int i = 0; i < coeff.Value * (compar.min + 1) - 1; i++)
                        {
                            lisNFAs.AddLast(epsNFA(symbolicString.root, alphabet, comparisons));
                        }
                        var autom       = epsNFA(symbolicString.root, alphabet, comparisons);
                        var autom_start = autom.Item1.Q_0.First();
                        var newEpsTrans = new HashSet <TwoTuple <State <string>, State <string> > >();
                        newEpsTrans.UnionWith(autom.Item2);
                        foreach (var acceptingState in autom.Item1.F)
                        {
                            newEpsTrans.Add(new TwoTuple <State <string>, State <string> >(acceptingState, autom_start));
                        }
                        lisNFAs.AddLast(Tuple.Create(autom.Item1, newEpsTrans));
                        break;

                    case UnaryComparison.ComparisonType.BETWEEN:
                        for (int i = 0; i < coeff.Value * compar.min; i++)
                        {
                            lisNFAs.AddLast(epsNFA(symbolicString.root, alphabet, comparisons));
                        }
                        var rememberedStates = new HashSet <State <string> >();

                        int upperbound = 0;
                        if (compar.min == -1 || compar.min == 0)
                        {
                            upperbound = compar.max - 1;
                        }
                        else
                        {
                            upperbound = compar.max - compar.min - 1;
                        }

                        for (int i = 0; i < coeff.Value * upperbound; i++)
                        {
                            var aut = epsNFA(symbolicString.root, alphabet, comparisons);
                            foreach (var q_f in aut.Item1.F)
                            {
                                rememberedStates.Add(q_f);
                            }
                            lisNFAs.AddLast(aut);
                        }
                        if (compar.min == -1)
                        {
                            rememberedStates.Add(lisNFAs.First.Value.Item1.Q_0.First());
                        }

                        var epsTrans = new HashSet <TwoTuple <State <string>, State <string> > >();
                        var lastAut  = lisNFAs.Last.Value;
                        foreach (var state in rememberedStates)
                        {
                            foreach (var q_f in lastAut.Item1.F)
                            {
                                epsTrans.Add(new TwoTuple <State <string>, State <string> >(state, q_f));
                            }
                        }
                        lisNFAs.RemoveLast();
                        lisNFAs.AddLast(Tuple.Create(lastAut.Item1, new HashSet <TwoTuple <State <string>, State <string> > >(epsTrans.Union(lastAut.Item2))));
                        break;
                    }
                }

                return(concatAutomata(lisNFAs));

            default:
                throw new ArgumentException();
            }
        }
 public static LinearIntegerExpression Plus(LinearIntegerExpression a, LinearIntegerExpression b)
 {
     return Plus(new List<LinearIntegerExpression> { a, b });
 }