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(); } }
// Generates splits (x, y, z) such that |y| > 0 and |xy| < p public IEnumerable <Split> ValidSplits( LinearIntegerExpression pumpingLengthVariable, BooleanExpression additionalConstraints) { foreach (var split in this.Splits()) { if (split.mid.isEpsilon()) { continue; } var cond1 = ComparisonExpression.GreaterThan(split.mid.length(), LinearIntegerExpression.Constant(0)); var cond2 = ComparisonExpression.LessThan(split.start.length() + split.mid.length(), pumpingLengthVariable); var condition = LogicalExpression.And(additionalConstraints, cond1, cond2); if (condition.isMaybeSatisfiable()) { split.AddConstraint(condition); yield return(split); } } }
public static ArithmeticLanguage FromTextDescriptions(List <String> alphabet, string symbolicStringText, string constraintText) { var symbolPattern = new Regex(@"^[a-zA-Z0-9]$"); var illegalSymbols = alphabet.FindAll(s => !symbolPattern.IsMatch(s)); if (illegalSymbols.Count > 0) { var message = string.Format( "Found illegal symbols {0} in alphabet. Symbols should match [a-zA-Z0-9]", string.Join(", ", illegalSymbols) ); throw new PumpingLemmaException(message); } // Parse the language var ss = PumpingLemma.Parser.parseSymbolicString(symbolicStringText, alphabet); if (ss == null) { throw new PumpingLemmaException("Unable to parse language"); } // Parse the constraintDesc var constraint = PumpingLemma.Parser.parseCondition(constraintText); if (constraint == null) { throw new PumpingLemmaException("Unable to parse constraint"); } // Make sure all the variables are bound var boundVariables = ss.GetIntegerVariables(); var constraintVariables = constraint.GetVariables(); // Console.WriteLine("Bound variables: " + String.Join(", ", boundVariables)); // Console.WriteLine("Constriant variables: " + String.Join(", ", constraintVariables)); foreach (var consVar in constraintVariables) { if (!boundVariables.Contains(consVar)) { throw new PumpingLemmaException( string.Format("Constraint variable {0} not bound", consVar)); } } // Add constraints saying that all variables are >= 0 BooleanExpression defaultConstraint = LogicalExpression.True(); foreach (var consVar in constraintVariables) { defaultConstraint = LogicalExpression.And( defaultConstraint, ComparisonExpression.GreaterThanOrEqual( LinearIntegerExpression.SingleTerm(1, consVar), LinearIntegerExpression.Constant(0) ) ); } return(new ArithmeticLanguage(alphabet, ss, constraint)); }
public Dictionary <VariableType, UnaryComparison> getReducedUnaryConstraints() { if (!getComparisonExpressions(constraint).All(expr => expr.isUnary())) { throw new PumpingLemmaException("The Language doesn't contain only unary constraints."); } if (!constraint.isSatisfiable()) { throw new PumpingLemmaException("The Language constraint is not satisfiable."); } Dictionary <VariableType, UnaryComparison> comparisonsToReturn = new Dictionary <VariableType, UnaryComparison>(); IEnumerable <ComparisonExpression> allExpr = getComparisonExpressions(constraint); //delete non-constraints allExpr = allExpr.Except(allExpr.Where(e => e.arithmetic_operand1.isConstant() && e.arithmetic_operand2.isConstant())); //put variable on left side //divide, so that coefficient = 1 HashSet <ComparisonExpression> ToDelete = new HashSet <ComparisonExpression>(); var exprToAdd = new HashSet <ComparisonExpression>(); foreach (ComparisonExpression expr in allExpr) { if (expr.arithmetic_operand1.isConstant()) { switch (expr.comparison_operator) { case ComparisonExpression.ComparisonOperator.GEQ: exprToAdd.Add(ComparisonExpression.LessThanOrEqual(expr.arithmetic_operand2, expr.arithmetic_operand1)); break; case ComparisonExpression.ComparisonOperator.GT: exprToAdd.Add(ComparisonExpression.LessThan(expr.arithmetic_operand2, expr.arithmetic_operand1)); break; case ComparisonExpression.ComparisonOperator.LEQ: exprToAdd.Add(ComparisonExpression.GreaterThanOrEqual(expr.arithmetic_operand2, expr.arithmetic_operand1)); break; case ComparisonExpression.ComparisonOperator.LT: exprToAdd.Add(ComparisonExpression.GreaterThan(expr.arithmetic_operand2, expr.arithmetic_operand1)); break; default: break; } } } ToDelete = new HashSet <ComparisonExpression>(allExpr.Where(e => e.arithmetic_operand1.isConstant())); allExpr = allExpr.Except(ToDelete); allExpr = allExpr.Union(exprToAdd); ToDelete = new HashSet <ComparisonExpression>(); exprToAdd = new HashSet <ComparisonExpression>(); foreach (var expr in allExpr) { foreach (VariableType variable in expr.GetVariables()) { int coefficient = expr.arithmetic_operand1.coefficients[variable]; int constant = expr.arithmetic_operand2.constant; double divided = (double)constant / (double)coefficient; switch (expr.comparison_operator) { case ComparisonExpression.ComparisonOperator.EQ: case ComparisonExpression.ComparisonOperator.NEQ: if (!isInt(divided)) { ToDelete.Add(expr); } else { expr.arithmetic_operand2 = LinearIntegerExpression.Constant(Convert.ToInt32(divided)); } break; case ComparisonExpression.ComparisonOperator.GEQ: expr.arithmetic_operand2 = LinearIntegerExpression.Constant(Convert.ToInt32(Math.Ceiling(divided))); break; case ComparisonExpression.ComparisonOperator.GT: expr.arithmetic_operand2 = LinearIntegerExpression.Constant(Convert.ToInt32(Math.Floor(divided))); break; case ComparisonExpression.ComparisonOperator.LEQ: expr.arithmetic_operand2 = LinearIntegerExpression.Constant(Convert.ToInt32(Math.Floor(divided))); break; case ComparisonExpression.ComparisonOperator.LT: expr.arithmetic_operand2 = LinearIntegerExpression.Constant(Convert.ToInt32(Math.Ceiling(divided))); break; default: throw new ArgumentException(); } } } allExpr = allExpr.Except(ToDelete); allExpr = allExpr.Union(exprToAdd); ToDelete = new HashSet <ComparisonExpression>(); exprToAdd = new HashSet <ComparisonExpression>(); //reduce if equal constraint is found HashSet <string> varsToDelete = new HashSet <string>(); foreach (ComparisonExpression expr in allExpr) { if (expr.comparison_operator == ComparisonExpression.ComparisonOperator.EQ) { VariableType variable = expr.arithmetic_operand1.GetVariables().First(); int coefficient = expr.arithmetic_operand1.coefficients[variable]; int constant = expr.arithmetic_operand2.constant; int divided = divideConstant(constant, coefficient); comparisonsToReturn.Add(variable, UnaryComparison.equal(variable, divided)); varsToDelete.Add(variable.ToString()); } } IEnumerable <ComparisonExpression> exprToDelete = allExpr.Where(e => varsToDelete.Contains(e.arithmetic_operand1.GetVariables().First().ToString())); allExpr = allExpr.Except(exprToDelete); //GEQ -> GT, LEQ -> LT exprToDelete = new HashSet <ComparisonExpression>(); exprToAdd = new HashSet <ComparisonExpression>(); foreach (ComparisonExpression expr in allExpr) { if (expr.comparison_operator == ComparisonExpression.ComparisonOperator.GEQ) { ComparisonExpression newExpr = ComparisonExpression.GreaterThan(expr.arithmetic_operand1, expr.arithmetic_operand2.constant - 1); exprToAdd.Add(newExpr); } if (expr.comparison_operator == ComparisonExpression.ComparisonOperator.LEQ) { ComparisonExpression newExpr = ComparisonExpression.LessThan(expr.arithmetic_operand1, expr.arithmetic_operand2.constant + 1); exprToAdd.Add(newExpr); } } exprToDelete = allExpr.Where(e => e.comparison_operator == ComparisonExpression.ComparisonOperator.LEQ || e.comparison_operator == ComparisonExpression.ComparisonOperator.GEQ); allExpr = allExpr.Except(exprToDelete); allExpr = allExpr.Union(exprToAdd); HashSet <VariableType> allVars = new HashSet <VariableType>(); foreach (ComparisonExpression expr in allExpr) { allVars.Add(expr.arithmetic_operand1.GetVariables().First()); } foreach (VariableType variable in allVars) { IEnumerable <ComparisonExpression> varExpr = allExpr.Where(e => variable.ToString().Equals(e.GetVariables().First().ToString())); //reduce to single constraints IEnumerable <ComparisonExpression> gtExpr = varExpr.Where(e => e.comparison_operator == ComparisonExpression.ComparisonOperator.GT); int gthan = -1; foreach (ComparisonExpression expr in gtExpr) { int coefficient = expr.arithmetic_operand1.coefficients[variable]; int constant = expr.arithmetic_operand2.constant; //floor int divided = constant / coefficient; if (constant > gthan) { gthan = constant; } } IEnumerable <ComparisonExpression> ltExpr = varExpr.Where(e => e.comparison_operator == ComparisonExpression.ComparisonOperator.LT); int lthan = Int32.MaxValue; foreach (ComparisonExpression expr in ltExpr) { int coefficient = expr.arithmetic_operand1.coefficients[variable]; int constant = expr.arithmetic_operand2.constant; if (constant < lthan) { lthan = constant; } } varExpr = varExpr.Except(gtExpr); varExpr = varExpr.Except(ltExpr); //rest should be NEQ HashSet <int> neqInts = new HashSet <int>(); foreach (ComparisonExpression expr in varExpr) { if (expr.comparison_operator != ComparisonExpression.ComparisonOperator.NEQ) { throw new PumpingLemmaException("The programmer is stupid."); } int coefficient = expr.arithmetic_operand1.coefficients[variable]; int constant = expr.arithmetic_operand2.constant; double divided = (double)constant / coefficient; //if not int, discard if (Math.Abs(divided % 1) <= (Double.Epsilon * 100)) { int divided_int = (int)divided; neqInts.Add(divided_int); } } if (gthan > -1 && lthan < Int32.MaxValue) { comparisonsToReturn.Add(variable, UnaryComparison.between(variable, gthan, lthan, neqInts)); } else if (gthan > -1 && lthan == Int32.MaxValue) { comparisonsToReturn.Add(variable, UnaryComparison.greater(variable, gthan, neqInts)); } else if (gthan == -1 && lthan < Int32.MaxValue) { comparisonsToReturn.Add(variable, UnaryComparison.between(variable, -1, lthan, neqInts)); } else { comparisonsToReturn.Add(variable, UnaryComparison.greater(variable, -1, neqInts)); } } return(comparisonsToReturn); }
// 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); }
private static UnaryComparison compExprToUnaryComp(ComparisonExpression expr) { if (!expr.isUnary()) { return(null); } if (expr.arithmetic_operand1.isConstant()) { LinearIntegerExpression tmp = expr.arithmetic_operand1; expr.arithmetic_operand1 = expr.arithmetic_operand2; expr.arithmetic_operand2 = tmp; switch (expr.comparison_operator) { case ComparisonExpression.ComparisonOperator.GEQ: expr.comparison_operator = ComparisonExpression.ComparisonOperator.LEQ; break; case ComparisonExpression.ComparisonOperator.GT: expr.comparison_operator = ComparisonExpression.ComparisonOperator.LT; break; case ComparisonExpression.ComparisonOperator.LEQ: expr.comparison_operator = ComparisonExpression.ComparisonOperator.GEQ; break; case ComparisonExpression.ComparisonOperator.LT: expr.comparison_operator = ComparisonExpression.ComparisonOperator.GT; break; default: break; } } VariableType variable = expr.GetVariables().First(); int coefficient = expr.arithmetic_operand1.coefficients[variable]; int constant = expr.arithmetic_operand2.constant; double divided = (double)constant / (double)coefficient; switch (expr.comparison_operator) { case ComparisonExpression.ComparisonOperator.EQ: case ComparisonExpression.ComparisonOperator.NEQ: if (!isInt(divided)) { return(null); } else { expr.arithmetic_operand2 = LinearIntegerExpression.Constant(Convert.ToInt32(divided)); } break; case ComparisonExpression.ComparisonOperator.GEQ: expr.arithmetic_operand2 = LinearIntegerExpression.Constant(Convert.ToInt32(Math.Ceiling(divided))); break; case ComparisonExpression.ComparisonOperator.GT: expr.arithmetic_operand2 = LinearIntegerExpression.Constant(Convert.ToInt32(Math.Floor(divided))); break; case ComparisonExpression.ComparisonOperator.LEQ: expr.arithmetic_operand2 = LinearIntegerExpression.Constant(Convert.ToInt32(Math.Floor(divided))); break; case ComparisonExpression.ComparisonOperator.LT: expr.arithmetic_operand2 = LinearIntegerExpression.Constant(Convert.ToInt32(Math.Ceiling(divided))); break; default: throw new ArgumentException(); } if (expr.comparison_operator == ComparisonExpression.ComparisonOperator.GEQ) { expr.comparison_operator = ComparisonExpression.ComparisonOperator.GT; expr.arithmetic_operand2.constant--; } if (expr.comparison_operator == ComparisonExpression.ComparisonOperator.LEQ) { expr.comparison_operator = ComparisonExpression.ComparisonOperator.LT; expr.arithmetic_operand2.constant++; } switch (expr.comparison_operator) { case ComparisonExpression.ComparisonOperator.EQ: return(UnaryComparison.equal(variable, expr.arithmetic_operand2.constant)); case ComparisonExpression.ComparisonOperator.GT: return(UnaryComparison.greater(variable, expr.arithmetic_operand2.constant, new HashSet <int>())); case ComparisonExpression.ComparisonOperator.LT: return(UnaryComparison.between(variable, -1, expr.arithmetic_operand2.constant, new HashSet <int>())); default: return(null); } }
public static LinearIntegerExpression operator -(LinearIntegerExpression a, int b) { return(Plus(a, LinearIntegerExpression.Constant(-b))); }
public static ComparisonExpression NotEqual(LinearIntegerExpression op1, int op2) { return(NotEqual(op1, LinearIntegerExpression.Constant(op2))); }
public static ComparisonExpression GreaterThanOrEqual(LinearIntegerExpression op1, int op2) { return(GreaterThanOrEqual(op1, LinearIntegerExpression.Constant(op2))); }
public static ComparisonExpression LessThan(LinearIntegerExpression op1, int op2) { return(LessThan(op1, LinearIntegerExpression.Constant(op2))); }