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(); } }
// 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(); } }
// Strategy: // a) Match the prefix and suffix of the language with the x and z // b) See if y can be pumped against the middle part // The horrifying part is the quantifiers public static bool splitGood(Split split, ArithmeticLanguage language, BooleanExpression additionalConstraint) { // 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 (!canMismatchOne(midLanguage, midSplit, fullConstraint)) { return false; } } } return true; }