public static VariableType Variable(String name)
 {
     if (allVariables.ContainsKey(name))
         return allVariables[name];
     var ret = new VariableType(name);
     allVariables[name] = ret;
     return ret;
 }
 public static LinearIntegerExpression SingleTerm(int coefficient, VariableType v)
 {
     var coefficients = new Dictionary<VariableType, int>();
     coefficients[v] = coefficient;
     return new LinearIntegerExpression(0, coefficients);
 }
 public static LinearIntegerExpression FreshVariable()
 {
     return(SingleTerm(1, VariableType.FreshVariable()));
 }
 public static LinearIntegerExpression Variable(string name)
 {
     return(SingleTerm(1, VariableType.Variable(name)));
 }
 public bool containsVariable(VariableType v)
 {
     return(arithmetic_operand1.GetVariables().Contains(v) || arithmetic_operand2.GetVariables().Contains(v));
 }
 public static UnaryComparison greater(VariableType variable, int constant, IEnumerable <int> neq)
 {
     return(new UnaryComparison(ComparisonType.GREATER, constant, constant, variable, neq));
 }
 public static UnaryComparison equal(VariableType variable, int constant)
 {
     return(new UnaryComparison(ComparisonType.EQUAL, constant, constant, variable, new HashSet <int>()));
 }
        // 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);
        }
        // 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;
        }