public static BooleanExpression containmentCondition(SymbolicString s, ArithmeticLanguage l, BooleanExpression additionalConstraints)
        {
            // Console.WriteLine("Checking containment of " + s + " in " + l);
            var goodMatches = Matcher
                .match(s, l.symbolic_string)
                .Select(x => x.forceFinish())
                .Select(x => x.withAdditionalConstraint(l.constraint))
                .Where(x => x.isFeasible())
                ;
            if (goodMatches.Count() == 0)
                return LogicalExpression.False();

            var matchCondition = LogicalExpression.False();
            foreach (var match in goodMatches)
            {
                // Console.WriteLine("Got good match: " + match);
                matchCondition = LogicalExpression.Or(matchCondition, match.constraint);
            }
            var condition = LogicalExpression.Implies(additionalConstraints, matchCondition);

            var variables = condition.GetVariables();
            var pVariables = s.GetIntegerVariables(); // Most of the times, should be 1
            var nonPVariables = variables.Where(x => !pVariables.Contains(x));

            var eCondition = QuantifiedExpression.Exists(nonPVariables, condition);
            var aCondition = QuantifiedExpression.Forall(pVariables, eCondition);

            return aCondition;
        }
Exemple #2
0
        private static string pumpedWord(SymbolicString symbStr, Dictionary <VariableType, int> assignment)
        {
            StringBuilder sb = new StringBuilder();

            switch (symbStr.expression_type)
            {
            case SymbolicString.SymbolicStringType.Symbol:
                return(symbStr.atomic_symbol);

            case SymbolicString.SymbolicStringType.Concat:
                foreach (SymbolicString s in symbStr.sub_strings)
                {
                    sb.Append(pumpedWord(s, assignment));
                }
                return(sb.ToString());

            case SymbolicString.SymbolicStringType.Repeat:
                for (int i = 0; i < symbStr.repeat.constant; i++)
                {
                    sb.Append(pumpedWord(symbStr.root, assignment));
                }
                foreach (var v in symbStr.repeat.coefficients)
                {
                    for (int i = 0; i < v.Value * assignment[v.Key]; i++)
                    {
                        sb.Append(pumpedWord(symbStr.root, assignment));
                    }
                }
                return(sb.ToString());

            default:
                throw new ArgumentException();
            }
        }
        private bool checkVariableOnce(SymbolicString symbString)
        {
            switch (symbString.expression_type)
            {
            case SymbolicString.SymbolicStringType.Symbol:
                return(true);

            case SymbolicString.SymbolicStringType.Concat:
                foreach (SymbolicString s in symbString.sub_strings)
                {
                    if (!checkVariableOnce(s))
                    {
                        return(false);
                    }
                }
                return(true);

            case SymbolicString.SymbolicStringType.Repeat:
                HashSet <VariableType> vars = symbString.repeat.GetVariables();
                if (varsSeen.Intersect(vars).Any())
                {
                    return(false);
                }
                varsSeen.UnionWith(vars);
                return(checkVariableOnce(symbString.root));

            default:
                throw new ArgumentException();
            }
        }
        public static BooleanExpression containmentCondition(SymbolicString s, ArithmeticLanguage l, BooleanExpression additionalConstraints)
        {
            // Console.WriteLine("Checking containment of " + s + " in " + l);
            var goodMatches = Matcher
                              .match(s, l.symbolic_string)
                              .Select(x => x.forceFinish())
                              .Select(x => x.withAdditionalConstraint(l.constraint))
                              .Where(x => x.isFeasible())
            ;

            if (goodMatches.Count() == 0)
            {
                return(LogicalExpression.False());
            }

            var matchCondition = LogicalExpression.False();

            foreach (var match in goodMatches)
            {
                System.Diagnostics.Debug.WriteLine("Got good match: " + match);
                matchCondition = LogicalExpression.Or(matchCondition, match.constraint);
            }
            var condition = LogicalExpression.Implies(additionalConstraints, matchCondition);

            var variables     = condition.GetVariables();
            var pVariables    = s.GetIntegerVariables(); // Most of the times, should be 1
            var nonPVariables = variables.Where(x => !pVariables.Contains(x));

            var eCondition = QuantifiedExpression.Exists(nonPVariables, condition);
            var aCondition = QuantifiedExpression.Forall(pVariables, eCondition);

            return(aCondition);
        }
Exemple #5
0
        public static SymbolicString Concat(IEnumerable <SymbolicString> sub_strings)
        {
            var ans = new SymbolicString(sub_strings.ToList());

            ans.flatten();
            return(ans);
        }
Exemple #6
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();
            }
        }
Exemple #7
0
 // Match only if both symbols are same
 private static IEnumerable <Match> matchSymbolSymbol(SymbolicString s1, SymbolicString s2)
 {
     if (s2.atomic_symbol == s1.atomic_symbol)
     {
         yield return(Match.FullMatch(LogicalExpression.True()));
     }
 }
        public static bool checkNonContainment(SymbolicString s, ArithmeticLanguage l, BooleanExpression additionalConstraints)
        {
            var condition = containmentCondition(s, l, additionalConstraints);

            // Check if the containment condition is unsatisfiable
            return(!condition.isSatisfiable());
        }
Exemple #9
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)));
                }
            }
        }
Exemple #10
0
        public static string NonRegularCheckWord(ArithmeticLanguage lang, int n, string word)
        {
            if (word.Length < n)
            {
                return("<false>Word is too short.</false>");
            }

            foreach (char c in word)
            {
                if (!lang.alphabet.Contains(c + ""))
                {
                    return("<false>Word contains illegal letters.</false>");
                }
            }

            if (lang.symbolic_string.isFlat())
            {
                SymbolicString wordSS = Parser.parseSymbolicString(word, lang.alphabet.ToList());
                if (ProofChecker.checkContainment(wordSS, lang, LogicalExpression.True()))
                {
                    return("<true></true>");
                }
                else
                {
                    return("<false>Word is not in the language.</false>");
                }
            }
            else
            {
                throw new PumpingLemmaException("Arithmetic Language must be flat!");
            }
        }
Exemple #11
0
        public static SymbolicString join(SymbolicString a, SymbolicString b)
        {
            if (a == null || b == null)
            {
                return(null);
            }

            if (a.expression_type == SymbolicString.SymbolicStringType.Concat &&
                b.expression_type == SymbolicString.SymbolicStringType.Concat)
            {
                return(SymbolicString.Concat(a.sub_strings.Concat(b.sub_strings)));
            }
            List <SymbolicString> sub_strings = new List <SymbolicString>();

            if (a.expression_type == SymbolicString.SymbolicStringType.Concat)
            {
                sub_strings.AddRange(a.sub_strings);
            }
            else
            {
                sub_strings.Add(a);
            }
            if (b.expression_type == SymbolicString.SymbolicStringType.Concat)
            {
                sub_strings.AddRange(b.sub_strings);
            }
            else
            {
                sub_strings.Add(b);
            }
            return(SymbolicString.Concat(sub_strings));
        }
        public static bool checkContainment(SymbolicString s, ArithmeticLanguage l, BooleanExpression additionalConstraints)
        {
            var condition = containmentCondition(s, l, additionalConstraints);

            // Check if the containment condition is valid
            return(!LogicalExpression.Not(condition).isSatisfiable());
        }
Exemple #13
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)
                                                 )));
            }
        }
Exemple #14
0
        private static int wordLength(SymbolicString symbStr, Dictionary <VariableType, int> assignment)
        {
            int sum;

            switch (symbStr.expression_type)
            {
            case SymbolicString.SymbolicStringType.Symbol:
                return(1);

            case SymbolicString.SymbolicStringType.Concat:
                sum = 0;
                foreach (SymbolicString s in symbStr.sub_strings)
                {
                    sum += wordLength(s, assignment);
                }
                return(sum);

            case SymbolicString.SymbolicStringType.Repeat:
                if (symbStr.repeat.isConstant())
                {
                    return(wordLength(symbStr.root, assignment) * symbStr.repeat.constant);
                }
                sum = 0;
                foreach (var v in symbStr.repeat.coefficients)
                {
                    sum += v.Value * assignment[v.Key] * wordLength(symbStr.root, assignment);
                }
                return(sum);

            default:
                throw new ArgumentException();
            }
        }
 public static Match PartialFirst(BooleanExpression _c, SymbolicString remaining1)
 {
     return new Match(
         _c,
         remaining1,
         SymbolicString.Epsilon()
         );
 }
Exemple #16
0
 public static Match PartialFirst(BooleanExpression _c, SymbolicString remaining1)
 {
     return(new Match(
                _c,
                remaining1,
                SymbolicString.Epsilon()
                ));
 }
Exemple #17
0
 public static Match PartialSecond(BooleanExpression _c, SymbolicString remaining2)
 {
     return(new Match(
                _c,
                SymbolicString.Epsilon(),
                remaining2
                ));
 }
Exemple #18
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 Match PartialSecond(BooleanExpression _c, SymbolicString remaining2)
 {
     return new Match(
         _c,
         SymbolicString.Epsilon(),
         remaining2
         );
 }
Exemple #20
0
 public static Match FullMatch(BooleanExpression _c)
 {
     return(new Match(
                _c,
                SymbolicString.Epsilon(),
                SymbolicString.Epsilon()
                ));
 }
Exemple #21
0
        public static SymbolicString repeat(SymbolicString s, LinearIntegerExpression e)
        {
            if (s == null || e == null)
            {
                return(null);
            }

            return(SymbolicString.Repeat(s, e));
        }
 public static bool canMismatchWitness(
     SymbolicString midLanguage,
     SymbolicString midSplit,
     BooleanExpression fullConstraint,
     LinearIntegerExpression pumpingWitness
     )
 {
     throw new NotImplementedException();
 }
        public TwoSplit extend(SymbolicString prefix, SymbolicString suffix)
        {
            var new_start = SymbolicString.Concat(prefix, start);
            var new_end   = SymbolicString.Concat(end, suffix);

            new_start.flatten();
            new_end.flatten();
            return(MakeSplit(new_start, new_end, constraints));
        }
 internal IEnumerable<Match> continueMatch(SymbolicString rest1, SymbolicString rest2)
 {
     var cont1 = SymbolicString.Concat(this.remaining1, rest1);
     var cont2 = SymbolicString.Concat(this.remaining2, rest2);
     foreach (var mp in Matcher.match(cont1, cont2))
     {
         yield return mp.withAdditionalConstraint(this.constraint);
     }
 }
Exemple #25
0
        /*
         * // If symbols are allowed to be more than one character
         * public static List<String> splitIntoAlphabetSymbols(string text, List<String> alphabet)
         * {
         *      List<String> return_tokens = null;
         *      if (text.Length == 0)
         *      {
         *              return_tokens = new List<string>();
         *      return return_tokens;
         *  }
         *  foreach (string symbol in alphabet)
         *  {
         *          if (text.StartsWith(symbol))
         *              {
         *                      List<String> sub = splitIntoAlphabetSymbols(text.Substring(symbol.Length), alphabet);
         *                      if (sub != null)
         *                      {
         *                              sub.Insert(0, symbol);
         *                      if (return_tokens != null)
         *                          {
         *                                      // Multiple parses
         *                                      return_tokens = null;
         *                                      break;
         *                              }
         *                              else
         *                              {
         *                                      return_tokens = sub;
         *                              }
         *                      }
         *              }
         *  }
         *      return return_tokens;
         * }
         */

        public static SymbolicString wordToSymbolicString(List <String> symbols)
        {
            if (symbols.Count == 1)
            {
                return(SymbolicString.Symbol(symbols[0]));
            }
            return(SymbolicString.Concat(
                       symbols.Select(x => SymbolicString.Symbol(x)).ToList()
                       ));
        }
 private Split(SymbolicString s, SymbolicString m, SymbolicString e, BooleanExpression c)
 {
     start = s;
     mid   = m;
     end   = e;
     start.flatten();
     mid.flatten();
     end.flatten();
     constraints = c;
 }
Exemple #27
0
        internal IEnumerable <Match> continueMatch(SymbolicString rest1, SymbolicString rest2)
        {
            var cont1 = SymbolicString.Concat(this.remaining1, rest1);
            var cont2 = SymbolicString.Concat(this.remaining2, rest2);

            foreach (var mp in Matcher.match(cont1, cont2))
            {
                yield return(mp.withAdditionalConstraint(this.constraint));
            }
        }
Exemple #28
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))
                                     ));
                }
            }
        }
 int getNumberOfMatches(SymbolicString s1, SymbolicString s2)
 {
     Console.WriteLine("Matching " + s1 + " with " + s2);
     int count = 0;
     foreach (var m in Matcher.match(s1, s2))
     {
         Console.WriteLine("\t" + m);
         count++;
     }
     return count;
 }
Exemple #30
0
 public static Tuple <string, string, string> NonRegularGetPumpableSplit(ArithmeticLanguage language, string word, int n)
 {
     foreach (var split in possibleSplits(word, n))
     {
         SymbolicString str = splitToSymbStr(language.alphabet.ToList(), split.Item1, split.Item2, split.Item3);
         if (ProofChecker.checkContainment(str, language, LogicalExpression.True()))
         {
             return(split);
         }
     }
     return(null);
 }
Exemple #31
0
        public static bool NonRegularCheckI(ArithmeticLanguage language, string start, string mid, string end, int i)
        {
            string fullWord = pumpMid(start, mid, end, i);

            if (language.symbolic_string.isFlat())
            {
                SymbolicString wordSS = Parser.parseSymbolicString(fullWord.ToString(), language.alphabet.ToList());
                return(ProofChecker.checkContainment(wordSS, language, LogicalExpression.True()));
            }
            else
            {
                throw new PumpingLemmaException("Arithmetic Language must be flat!");
            }
        }
        public static bool check(ArithmeticLanguage language, SymbolicString pumpingString)
        {
            if (pumpingString.GetIntegerVariables().Count() != 1)
            {
                return(false);
            }
            var pumpingLength         = pumpingString.GetIntegerVariables().First();
            var pumpingLengthVariable = PumpingLemma.LinearIntegerExpression
                                        .SingleTerm(1, pumpingLength);
            var additionalConstraint = LogicalExpression.And(
                PumpingLemma.ComparisonExpression.GreaterThan(pumpingLengthVariable, 0),
                LogicalExpression.And(pumpingString.repeats().Select(x => ComparisonExpression.GreaterThanOrEqual(x, 0)))
                );

            // 0. Need to check if pumping string grows unboundedly with p
            var pumpingStringLength = pumpingString.length();

            if (pumpingStringLength.isConstant() || pumpingStringLength.coefficients[pumpingLength] < 0)
            {
                return(false);
            }
            foreach (var r in pumpingString.repeats())
            {
                if (r.coefficients[pumpingLength] < 0)
                {
                    return(false);
                }
            }

            // 1. Check that the pumping string is in the language for all p
            if (!checkContainment(pumpingString, language, additionalConstraint))
            {
                return(false);
            }

            Console.WriteLine("Language is non-regular if all the following splits are good:");
            int i = 0;

            // 2. Check that each split of the pumping string has an valid pumping length
            foreach (var split in pumpingString.ValidSplits(pumpingLengthVariable, additionalConstraint))
            {
                Console.WriteLine("\t" + (i++) + ": " + split + " when " + additionalConstraint);
                if (!splitGood(split, language, additionalConstraint))
                {
                    return(false);
                }
            }

            return(true);
        }
 public static bool canMismatchOne(SymbolicString language, SymbolicString midSplit, BooleanExpression fullConstraint)
 {
     /*
      * var matches = Matcher
      *  .matchRepeatedFull(language, midSplit)
      *  .Select(x => x.finishMatch());
      * foreach (var match in matches)
      * {
      *  var x = LogicalExpression.And(match.constraint, fullConstraint);
      *  // Do something here
      * }
      */
     throw new NotImplementedException();
 }
Exemple #34
0
        private static IEnumerable <Match> matchConcatConcat(SymbolicString s1, SymbolicString s2)
        {
            if (s1.isEpsilon() || s2.isEpsilon())
            {
                yield return(Match.MakeMatch(LogicalExpression.True(), s1, s2));

                yield break;
            }
            // Quick match prefix symbols
            int i;

            for (i = 0; i < s1.sub_strings.Count && i < s2.sub_strings.Count; i++)
            {
                if (s1.sub_strings[i].expression_type != SymbolicString.SymbolicStringType.Symbol ||
                    s2.sub_strings[i].expression_type != SymbolicString.SymbolicStringType.Symbol)
                {
                    break;
                }
                if (s1.sub_strings[i].atomic_symbol != s2.sub_strings[i].atomic_symbol)
                {
                    yield break;
                }
            }

            var sub1 = s1.sub_strings.Skip(i);
            var sub2 = s2.sub_strings.Skip(i);

            // If we have consumed something fully, just return the remaining bits
            if (i == s1.sub_strings.Count || i == s2.sub_strings.Count)
            {
                yield return(Match.MakeMatch(
                                 LogicalExpression.True(),
                                 SymbolicString.Concat(sub1),
                                 SymbolicString.Concat(sub2)));

                yield break;
            }

            var rest1 = SymbolicString.Concat(sub1.Skip(1));
            var rest2 = SymbolicString.Concat(sub2.Skip(1));

            foreach (var m in match(sub1.First(), sub2.First()))
            {
                foreach (var mp in m.continueMatch(rest1, rest2))
                {
                    yield return(mp);
                }
            }
        }
Exemple #35
0
        public static string NonRegularGetUnpumpableWord(ArithmeticLanguage language, SymbolicString unpumpableWord, int n)
        {
            Dictionary <VariableType, int> assignment = new Dictionary <VariableType, int>();

            assignment.Add(VariableType.Variable("n"), n);
            string         word = pumpedWord(unpumpableWord, assignment);
            SymbolicString ss   = SymbolicString.FromTextDescription(language.alphabet.ToList(), word);

            while (!ProofChecker.checkContainment(ss, language, LogicalExpression.True()))
            {
                assignment[VariableType.Variable("n")]++;
                word = pumpedWord(unpumpableWord, assignment);
                ss   = SymbolicString.FromTextDescription(language.alphabet.ToList(), word);
            }
            return(word);
        }
        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 check(ArithmeticLanguage language, SymbolicString pumpingString)
        {
            if (pumpingString.GetIntegerVariables().Count() != 1)
                return false;
            var pumpingLength = pumpingString.GetIntegerVariables().First();
            var pumpingLengthVariable = PumpingLemma.LinearIntegerExpression
                .SingleTerm(1, pumpingLength);
            var additionalConstraint = LogicalExpression.And(
                PumpingLemma.ComparisonExpression.GreaterThan(pumpingLengthVariable, 0),
                LogicalExpression.And(pumpingString.repeats().Select(x => ComparisonExpression.GreaterThanOrEqual(x, 0)))
            );

            // 0. Need to check if pumping string grows unboundedly with p
            var pumpingStringLength = pumpingString.length();
            if (pumpingStringLength.isConstant() || pumpingStringLength.coefficients[pumpingLength] < 0)
                return false;
            foreach (var r in pumpingString.repeats())
                if (r.coefficients[pumpingLength] < 0)
                    return false;

            // 1. Check that the pumping string is in the language for all p
            if (!checkContainment(pumpingString, language, additionalConstraint))
                return false;

            Console.WriteLine("Language is non-regular if all the following splits are good:");
            int i = 0;
            // 2. Check that each split of the pumping string has an valid pumping length 
            foreach (var split in pumpingString.ValidSplits(pumpingLengthVariable, additionalConstraint))
            {
                Console.WriteLine("\t" + (i++) + ": " + split + " when " + additionalConstraint);
                if (!splitGood(split, language, additionalConstraint))
                    return false;
            }

            return true;
        }
 private Match(BooleanExpression _c, SymbolicString _s1, SymbolicString _s2)
 {
     this.constraint = _c;
     this.remaining1 = _s1;
     this.remaining2 = _s2;
 }
 // Match only if both symbols are same
 private static IEnumerable<Match> matchSymbolSymbol(SymbolicString s1, SymbolicString s2)
 {
     if (s2.atomic_symbol == s1.atomic_symbol)
         yield return Match.FullMatch(LogicalExpression.True());
 }
        // 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))
                    );
            }
        }
 private SymbolicString(SymbolicString root, LinearIntegerExpression repeat)
 {
     this.expression_type = SymbolicStringType.Repeat;
     this.root = root;
     this.repeat = repeat;
 }
        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();
            }
        }
        public static SymbolicString join(SymbolicString a, SymbolicString b)
        {
            if (a == null || b == null)
                return null;

            if (a.expression_type == SymbolicString.SymbolicStringType.Concat
                && b.expression_type == SymbolicString.SymbolicStringType.Concat)
            {
                return SymbolicString.Concat(a.sub_strings.Concat(b.sub_strings));
            }
            List<SymbolicString> sub_strings = new List<SymbolicString>();
            if (a.expression_type == SymbolicString.SymbolicStringType.Concat)
                sub_strings.AddRange(a.sub_strings);
            else
                sub_strings.Add(a);
            if (b.expression_type == SymbolicString.SymbolicStringType.Concat)
                sub_strings.AddRange(b.sub_strings);
            else
                sub_strings.Add(b);
           return SymbolicString.Concat(sub_strings);
        }
 public static SymbolicString Concat(IEnumerable<SymbolicString> sub_strings)
 {
     var ans = new SymbolicString(sub_strings.ToList());
     ans.flatten();
     return ans;
 }
 internal static Match MakeMatch(BooleanExpression _c, SymbolicString remaining1, SymbolicString remaining2)
 {
     return new Match(_c, remaining1, remaining2);
 }
        // s1 and s2 are omega equal if s1^\omega = s2^\omega
        // Theorem: s1 and s2 are omega equal if and only if there
        // exists a w such that s1 = w^(l1/g) and s2 = w^(l2/g)
        // where l1, l2 are lengths of s1 and s2, and g = gcd(l1, l2)
        private static bool omegaEqual(SymbolicString s1, SymbolicString s2)
        {
            Debug.Assert(s1.isWord() && s2.isWord());

            var l1 = s1.wordLength();
            var l2 = s2.wordLength();
            var g = gcd(l1, l2);

            var w1 = s1.word().ToArray();
            for (int i = 0; i < l1; i++)
                if (w1[i] != w1[i % g]) return false;

            var w2 = s2.word().ToArray();
            for (int i = 0; i < l2; i++)
                if (w2[i] != w2[i % g]) return false;

            for (int i = 0; i < g; i++)
                if (w1[i] != w2[i]) return false;

            return true;
        }
        // Call only when omegaEqual(s1, s2) holds
        // TODO: There is definitely a more optimal implementation of this
        private static int getFirstMismatch(SymbolicString s1, SymbolicString s2)
        {
            Debug.Assert(s1.isWord() && s2.isWord());

            var l1 = s1.wordLength();
            var l2 = s2.wordLength();
            var w1 = s1.word().ToArray();
            var w2 = s2.word().ToArray();
            for (int i = 0; true; i++)
            {
                if (w1[i % l1] != w2[i % l2])
                    return i;
            }
        }
 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)
                 ));
         }
     }
 }
        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))
                    );
                }
            }
        }
        // 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));
            }
        }
        // Just dispatches to the appropriate helper method
        public static IEnumerable<Match> match(SymbolicString s1, SymbolicString s2)
        {
            Debug.Assert(s1.isFlat() && s2.isFlat());
            Func<SymbolicString.SymbolicStringType, string> toSignature = (ss_type) => {
                switch(ss_type) {
                    case SymbolicString.SymbolicStringType.Symbol: return "S";
                    case SymbolicString.SymbolicStringType.Repeat: return "R";
                    case SymbolicString.SymbolicStringType.Concat: return "C";
                    default: throw new ArgumentException();
                }
            };

            switch (toSignature(s1.expression_type) + toSignature(s2.expression_type))
            {
                case "RS":
                case "CS":
                case "CR":
                    return match(s2, s1).Select(x => x.reverse());
                case "SS":
                    return matchSymbolSymbol(s1, s2);
                case "SR":
                    return matchSymbolRepeat(s1, s2);
                case "SC":
                    return matchSymbolConcat(s1, s2);
                case "RR":
                    return matchRepeatRepeat(s1, s2);
                case "RC":
                    return matchRepeatConcat(s1, s2);
                case "CC":
                    return matchConcatConcat(s1, s2);
                default:
                    throw new ArgumentException();
            }
        }
        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)
                    ));
            }
        }
 public static SymbolicString Repeat(SymbolicString root, LinearIntegerExpression repeat)
 {
     return new SymbolicString(root, repeat);
 }
 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;
 }
 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;
 }
        private static IEnumerable<Match> matchConcatConcat(SymbolicString s1, SymbolicString s2)
        {
            if (s1.isEpsilon() || s2.isEpsilon())
            {
                yield return Match.MakeMatch(LogicalExpression.True(), s1, s2);
                yield break;
            }
            // Quick match prefix symbols
            int i;
            for (i = 0; i < s1.sub_strings.Count && i < s2.sub_strings.Count; i++)
            {
                if (s1.sub_strings[i].expression_type != SymbolicString.SymbolicStringType.Symbol ||
                    s2.sub_strings[i].expression_type != SymbolicString.SymbolicStringType.Symbol)
                    break;
                if (s1.sub_strings[i].atomic_symbol != s2.sub_strings[i].atomic_symbol)
                    yield break;
            }

            var sub1 = s1.sub_strings.Skip(i);
            var sub2 = s2.sub_strings.Skip(i);
            // If we have consumed something fully, just return the remaining bits
            if (i == s1.sub_strings.Count || i == s2.sub_strings.Count)
            {
                yield return Match.MakeMatch(
                    LogicalExpression.True(),
                    SymbolicString.Concat(sub1),
                    SymbolicString.Concat(sub2));
                yield break;
            }

            var rest1 = SymbolicString.Concat(sub1.Skip(1));
            var rest2 = SymbolicString.Concat(sub2.Skip(1));
            foreach (var m in match(sub1.First(), sub2.First()))
                foreach (var mp in m.continueMatch(rest1, rest2))
                    yield return mp;
        }
        public static SymbolicString repeat(SymbolicString s, LinearIntegerExpression e)
        {
            if (s == null || e == null)
                return null;

            return SymbolicString.Repeat(s, e);
        }
 private static IEnumerable<Match> matchSymbolConcat(SymbolicString s1, SymbolicString s2)
 {
     if (s2.isEpsilon())
     {
         yield return Match.PartialFirst(LogicalExpression.True(), s1);
         yield break;
     }
     var rest = SymbolicString.Concat(s2.sub_strings.Skip(1));
     foreach (var m in match(s1, s2.sub_strings.First()))
         foreach (var mp in m.continueMatch(SymbolicString.Epsilon(), rest))
             yield return mp;
 }
 public static bool checkContainment(SymbolicString s, ArithmeticLanguage l, BooleanExpression additionalConstraints)
 {
     var condition = containmentCondition(s, l, additionalConstraints);
     // Check if the containment condition is valid
     return !LogicalExpression.Not(condition).isSatisfiable();
 }
 private ArithmeticLanguage(IEnumerable<String> _alphabet, SymbolicString _symbolic_string, BooleanExpression _constraint)
 {
     this.alphabet = _alphabet;
     this.symbolic_string = _symbolic_string;
     this.constraint = _constraint;
 }