private Automaton <S> MakeKleeneClosure(Automaton <S> sfa)
        {
            if (sfa.IsEmpty || sfa.IsEpsilon)
            {
                return(this.epsilon);
            }

            if (sfa.IsKleeneClosure())
            {
                return(sfa);
            }


            if (sfa.DoesNotContainWordBoundaries && sfa.InitialStateIsSource && sfa.HasSingleFinalSink)
            {
                //common case, avoid epsilons in this case
                //just destructively make the final state to be the initial state
                sfa.RenameInitialState(sfa.FinalState);
                return(sfa);
            }

            int origInitState = sfa.InitialState;

            if (!sfa.IsFinalState(sfa.InitialState))//the initial state is not final
            {
                if (sfa.InitialStateIsSource)
                {
                    //make the current initial state final
                    sfa.MakeInitialStateFinal();
                }
                else
                {
                    //add a new initial state that is also final
                    sfa.AddNewInitialStateThatIsFinal(this.MkStateId());
                }
            }

            //add epsilon transitions from final states to the original initial state
            foreach (int state in sfa.GetFinalStates())
            {
                if (state != sfa.InitialState && state != origInitState)
                {
                    sfa.AddMove(Move <S> .Epsilon(state, origInitState));
                }
            }

            //epsilon loops might have been created, remove them
            var sfa1 = sfa.RemoveEpsilonLoops();

            if (!sfa.DoesNotContainWordBoundaries)
            {
                sfa1.AddWordBoundaries(sfa.EnumerateWordBoundaries());
            }
            return(sfa1);
        }
 IEnumerable <Move <S> > GenerateMoves(Dictionary <Pair <int, int>, S> condMap, IEnumerable <Pair <int, int> > eMoves)
 {
     foreach (var kv in condMap)
     {
         yield return(Move <S> .Create(kv.Key.First, kv.Key.Second, kv.Value));
     }
     foreach (var emove in eMoves)
     {
         yield return(Move <S> .Epsilon(emove.First, emove.Second));
     }
 }
Beispiel #3
0
 IEnumerable <Move <S> > GenerateMoves(Dictionary <Tuple <int, int>, S> condMap, IEnumerable <Tuple <int, int> > eMoves)
 {
     foreach (var kv in condMap)
     {
         yield return(Move <S> .Create(kv.Key.Item1, kv.Key.Item2, kv.Value));
     }
     foreach (var emove in eMoves)
     {
         yield return(Move <S> .Epsilon(emove.Item1, emove.Item2));
     }
 }
        IEnumerable <Move <S> > EnumMoves(int start, IEnumerable <Automaton <S> > sfas)
        {
            foreach (var sfa in sfas)
            {
                yield return(Move <S> .Epsilon(start, sfa.InitialState));

                foreach (var m in sfa.GetMoves())
                {
                    yield return(m);
                }
            }
        }
Beispiel #5
0
 public IEnumerable <Move <Sequence <T> > > EnumerateRelevantMoves()
 {
     foreach (var entry in witnessMap)
     {
         if (entry.Key.Item1 != entry.Key.Item2) //ignore loops
         {
             if (!entry.Value.IsEmpty)
             {
                 yield return(Move <Sequence <T> > .Create(entry.Key.Item1, entry.Key.Item2, entry.Value));
             }
             else //represent empty sequences as epsilons
             {
                 yield return(Move <Sequence <T> > .Epsilon(entry.Key.Item1, entry.Key.Item2));
             }
         }
     }
     foreach (var pushes in pushMap)
     {
         foreach (var trans in pushes.Value)
         {
             yield return(Move <Sequence <T> > .Epsilon(trans.Item1, trans.Item2));
         }
     }
 }
Beispiel #6
0
        public STb <F, T, S> Mk(string regex, params string[] parseInfo)
        {
            if (parseInfo.Length % 2 != 0)
            {
                throw new AutomataException(AutomataExceptionKind.InvalidArguments);
            }

            var K    = parseInfo.Length / 2;
            var args = new Tuple <string, string> [K];

            for (int i = 0; i < parseInfo.Length; i += 2)
            {
                args[i / 2] = new Tuple <string, string>(parseInfo[i], parseInfo[i + 1]);
            }

            bool isLoop;
            var  patternAutomataPairs = solver.CharSetProvider.ConvertCaptures(regex, out isLoop);
            var  captureAutomata      = new Dictionary <string, Automaton <BDD> >();

            foreach (var pair in patternAutomataPairs)
            {
                if (pair.Item1 != "")
                {
                    captureAutomata[pair.Item1] = pair.Item2;
                }
            }

            var captureSortPos  = new Dictionary <string, int>();
            var captureSortName = new Dictionary <string, string>();

            for (int i = 0; i < args.Length; i += 1)
            {
                captureSortName[args[i].Item1] = args[i].Item2;
                captureSortPos[args[i].Item1]  = i;
            }

            if (Array.Exists(patternAutomataPairs, pair => (pair.Item1 != "" && !captureSortName.ContainsKey(pair.Item1))))
            {
                throw new AutomataException(AutomataExceptionKind.InvalidArguments);
            }

            S[] argSorts = new S[K];
            for (int i = 0; i < K; i++)
            {
                if (!captureAutomata.ContainsKey(args[i].Item1))
                {
                    throw new AutomataException(AutomataExceptionKind.InvalidArguments);
                }
                else if (args[i].Item2 == "int")
                {
                    argSorts[i] = solver.MkBitVecSort(32);
                }
                else if (args[i].Item2 == "last")
                {
                    argSorts[i] = solver.CharSort;
                }
                else if (args[i].Item2 == "length")
                {
                    argSorts[i] = solver.MkBitVecSort(32);
                }
                else if (args[i].Item2 == "bool")
                {
                    argSorts[i] = solver.BoolSort;
                }
                else
                {
                    throw new AutomataException(AutomataExceptionKind.InvalidArguments);
                }
            }

            var regSort = solver.MkTupleSort(argSorts);
            var initReg = solver.MkTuple(Array.ConvertAll(argSorts, s => (s.Equals(solver.BoolSort) ? solver.False : solver.MkNumeral(0, solver.MkBitVecSort(32)))));
            var regVar  = solver.MkVar(1, regSort);
            var inpVar  = solver.MkVar(0, solver.CharSort);

            var stb = new STb <F, T, S>(solver, "stb", solver.CharSort, regSort, regSort, initReg, 0);


            var nextStateId = 0;
            var stateIdMap  = new Dictionary <Tuple <int, int>, int>();
            Func <int, int, int> MkState = (n, q) => {
                int p;
                var nq = new Tuple <int, int>(n, q);
                if (stateIdMap.TryGetValue(nq, out p))
                {
                    return(p);
                }
                else
                {
                    p              = nextStateId;
                    nextStateId   += 1;
                    stateIdMap[nq] = p;
                    return(p);
                }
            };

            var allMoves = new List <Move <Pair <BDD, T> > >();
            var bv32     = solver.MkBitVecSort(32);

            Func <T, T> AddZeros = (c) =>
            {
                uint k = (uint)(32 - (int)solver.CharSetProvider.Encoding);
                if (k == 0)
                {
                    return(c);
                }
                else
                {
                    return(solver.MkZeroExt(k, c));
                }
            };

            Func <int, T> ToInt = (i) =>
            {
                var elems = new T[K];
                for (int j = 0; j < K; j++)
                {
                    if (i == j)
                    {
                        elems[j] = solver.MkBvAdd(solver.MkBvMul(solver.MkNumeral(10, bv32), solver.MkProj(j, regVar)), solver.MkBvSub(AddZeros(inpVar), solver.MkNumeral((int)'0', bv32)));
                    }
                    else
                    {
                        elems[j] = solver.MkProj(j, regVar);
                    }
                }
                var res = solver.MkTuple(elems);
                return(res);
            };

            Func <int, T> ToLen = (i) =>
            {
                var elems = new T[K];
                for (int j = 0; j < K; j++)
                {
                    if (i == j)
                    {
                        elems[j] = solver.MkBvAdd(solver.MkNumeral(1, bv32), solver.MkProj(j, regVar));
                    }
                    else
                    {
                        elems[j] = solver.MkProj(j, regVar);
                    }
                }
                var res = solver.MkTuple(elems);
                return(res);
            };

            Func <int, T> KeepLast = (i) =>
            {
                var elems = new T[K];
                for (int j = 0; j < K; j++)
                {
                    if (i == j)
                    {
                        elems[j] = inpVar;
                    }
                    else
                    {
                        elems[j] = solver.MkProj(j, regVar);
                    }
                }
                var res = solver.MkTuple(elems);
                return(res);
            };

            Func <int, bool, T> AssignBool = (i, b) =>
            {
                var elems = new T[K];
                for (int j = 0; j < K; j++)
                {
                    if (i == j)
                    {
                        elems[j] = (b ? solver.True : solver.False);
                    }
                    else
                    {
                        elems[j] = solver.MkProj(j, regVar);
                    }
                }
                var res = solver.MkTuple(elems);
                return(res);
            };


            for (int i = 0; i < patternAutomataPairs.Length; i++)
            {
                var aut = patternAutomataPairs[i].Item2;
                if (patternAutomataPairs[i].Item1 == "")
                {
                    foreach (var m in aut.GetMoves())
                    {
                        allMoves.Add(Move <Pair <BDD, T> > .Create(MkState(i, m.SourceState), MkState(i, m.TargetState), new Pair <BDD, T>(m.Label, regVar)));
                    }
                }
                else if (captureSortName[patternAutomataPairs[i].Item1] == "int")
                {
                    foreach (var m in aut.GetMoves())
                    {
                        allMoves.Add(Move <Pair <BDD, T> > .Create(MkState(i, m.SourceState), MkState(i, m.TargetState), new Pair <BDD, T>(m.Label, ToInt(captureSortPos[patternAutomataPairs[i].Item1]))));
                    }
                }
                else if (captureSortName[patternAutomataPairs[i].Item1] == "length")
                {
                    foreach (var m in aut.GetMoves())
                    {
                        allMoves.Add(Move <Pair <BDD, T> > .Create(MkState(i, m.SourceState), MkState(i, m.TargetState), new Pair <BDD, T>(m.Label, ToLen(captureSortPos[patternAutomataPairs[i].Item1]))));
                    }
                }
                else if (captureSortName[patternAutomataPairs[i].Item1] == "last")
                {
                    foreach (var m in aut.GetMoves())
                    {
                        allMoves.Add(Move <Pair <BDD, T> > .Create(MkState(i, m.SourceState), MkState(i, m.TargetState), new Pair <BDD, T>(m.Label, KeepLast(captureSortPos[patternAutomataPairs[i].Item1]))));
                    }
                }
                else if (captureSortName[patternAutomataPairs[i].Item1] == "bool")
                {
                    var boolAcceptor = solver.CharSetProvider.Convert("^((T|t)rue|(F|f)alse)$").Intersect(patternAutomataPairs[i].Item2, solver.CharSetProvider).Minimize(solver.CharSetProvider);

                    if (boolAcceptor.IsEmpty)
                    {
                        throw new AutomataException(AutomataExceptionKind.CaptureIsInfeasibleAsBoolean);
                    }

                    patternAutomataPairs[i] = new Tuple <string, Automaton <BDD> >(patternAutomataPairs[i].Item1, boolAcceptor);

                    var _t = solver.CharSetProvider.MkCharSetFromRanges('t', 't', 'T', 'T');
                    var _f = solver.CharSetProvider.MkCharSetFromRanges('f', 'f', 'F', 'F');
                    foreach (var m in boolAcceptor.GetMoves())
                    {
                        if (m.SourceState == boolAcceptor.InitialState)
                        {
                            if (solver.CharSetProvider.IsSatisfiable(solver.CharSetProvider.MkAnd(_t, m.Label)))
                            {
                                allMoves.Add(Move <Pair <BDD, T> > .Create(MkState(i, m.SourceState), MkState(i, m.TargetState), new Pair <BDD, T>(m.Label, AssignBool(captureSortPos[patternAutomataPairs[i].Item1], true))));
                            }
                            else if (solver.CharSetProvider.IsSatisfiable(solver.CharSetProvider.MkAnd(_f, m.Label)))
                            {
                                allMoves.Add(Move <Pair <BDD, T> > .Create(MkState(i, m.SourceState), MkState(i, m.TargetState), new Pair <BDD, T>(m.Label, AssignBool(captureSortPos[patternAutomataPairs[i].Item1], false))));
                            }
                        }
                        else
                        {
                            allMoves.Add(Move <Pair <BDD, T> > .Create(MkState(i, m.SourceState), MkState(i, m.TargetState), new Pair <BDD, T>(m.Label, regVar)));
                        }
                    }
                }
                else
                {
                    throw new NotImplementedException();
                }
            }

            for (int i = 0; i < patternAutomataPairs.Length - 1; i++)
            {
                foreach (var q in patternAutomataPairs[i].Item2.GetFinalStates())
                {
                    allMoves.Add(Move <Pair <BDD, T> > .Epsilon(MkState(i, q), MkState(i + 1, patternAutomataPairs[i + 1].Item2.InitialState)));
                }
            }

            var L = patternAutomataPairs.Length - 1;

            var finalStates = new List <int>();

            foreach (var f in patternAutomataPairs[L].Item2.GetFinalStates())
            {
                finalStates.Add(MkState(L, f));
            }

            var tmpAutE = Automaton <Pair <BDD, T> > .Create(null, MkState(0, patternAutomataPairs[0].Item2.InitialState), finalStates, allMoves);

            Func <Pair <BDD, T>, Pair <BDD, T>, Pair <BDD, T> > error = (f1, f2) =>
            {
                throw new AutomataException(AutomataExceptionKind.InternalError);
            };

            var tmpAut = tmpAutE.RemoveEpsilons(error);

            tmpAut.isDeterministic = true;

            var name = "";

            foreach (var pair in args)
            {
                name = (name == "" ? pair.Item2 : name + "_" + pair.Item2);
            }
            var STB = Automaton2STb(tmpAut, name, regSort, initReg, isLoop);

            return(STB);
        }
Beispiel #7
0
        /// <summary>
        /// Concertize the SFA by including at most k characters in the label.
        /// </summary>
        /// <param name="k">upper limit on the number of included characters in the output automaton, when 0 or negative then include all elements</param>
        /// <returns></returns>
        public Automaton <BDD> Concretize(int k = 0)
        {
            //if (k <= 0)
            //    throw new AutomataException(AutomataExceptionKind.InvalidArgument);

            var mem = new Dictionary <TERM, BDD>();

            var concrete_moves = new List <Move <BDD> >();

            var moveMap = new Dictionary <Tuple <int, int>, BDD>();
            Action <int, int, BDD> AddMove = (from, to, guard) =>
            {
                BDD pred;
                var key = new Tuple <int, int>(from, to);
                if (moveMap.TryGetValue(key, out pred))
                {
                    pred = solver.CharSetProvider.MkOr(pred, guard);
                }
                else
                {
                    pred = guard;
                }
                moveMap[key] = pred;
            };

            Predicate <TERM> IsGround = t =>
            {
                foreach (var v in solver.GetVars(t))
                {
                    return(false);
                }
                return(true);
            };

            foreach (var move in automaton.GetMoves())
            {
                if (move.IsEpsilon)
                {
                    concrete_moves.Add(Move <BDD> .Epsilon(move.SourceState, move.TargetState));
                    continue;
                }
                BDD set;
                if (mem.TryGetValue(move.Label, out set))
                {
                    AddMove(move.SourceState, move.TargetState, set);
                    //concrete_moves.Add(Move<BvSet>.M(move.SourceState, move.TargetState, set));
                    continue;
                }
                if (k > 0)
                {
                    if (IsGround(move.Label))  //must be satisfiable so same as true
                    {
                        set             = solver.CharSetProvider.MkRangeConstraint((char)0, (char)(k - 1));
                        mem[move.Label] = set;
                        AddMove(move.SourceState, move.TargetState, set);
                        //concrete_moves.Add(Move<BvSet>.M(move.SourceState, move.TargetState, set));
                        continue;
                    }
                    var elems = new List <uint>();
                    foreach (var v in solver.MainSolver.FindAllMembers(move.Label))
                    {
                        elems.Add(solver.GetNumeralUInt(v.Value));
                        if (elems.Count == k)
                        {
                            break;
                        }
                    }
                    set             = solver.CharSetProvider.MkSetFromElements(elems, ((int)solver.CharSetProvider.Encoding) - 1);
                    mem[move.Label] = set;
                    AddMove(move.SourceState, move.TargetState, set);
                    //concrete_moves.Add(Move<BvSet>.M(move.SourceState, move.TargetState, set));
                }
                else
                {
                    BDD cond = solver.ConvertToCharSet(solver.CharSetProvider, move.Label);
                    if (cond != null)
                    {
                        throw new AutomataException(AutomataExceptionKind.ConditionCannotBeConvertedToCharSet);
                    }

                    mem[move.Label] = cond;
                    AddMove(move.SourceState, move.TargetState, cond);
                    //concrete_moves.Add(Move<BvSet>.M(move.SourceState, move.TargetState, cond));
                }
            }
            foreach (var entry in moveMap)
            {
                concrete_moves.Add(Move <BDD> .Create(entry.Key.Item1, entry.Key.Item2, entry.Value));
            }

            var res = Automaton <BDD> .Create(this.solver.CharSetProvider, this.automaton.InitialState, this.automaton.GetFinalStates(), concrete_moves);

            return(res);
        }
Beispiel #8
0
        /// <summary>
        /// Explores the PDA and converts it into an automaton,
        /// only stacks up to bounded depth are considered.
        /// </summary>
        /// <param name="stackDepth">upper bound on reached stack depth, nonpositive value means unbounded and may cause nontermination</param>
        public Automaton <T> Explore(int stackDepth = 0)
        {
            var moves       = new List <Move <T> >();
            var stateMap    = new Dictionary <Tuple <int, Sequence <S> >, int>();
            var configMap   = new Dictionary <int, Tuple <int, Sequence <S> > >();
            var finalStates = new HashSet <int>();

            int q0          = 0;
            var config0     = new Tuple <int, Sequence <S> >(this.automaton.InitialState, new Sequence <S>(this.initialStackSymbol));
            int nextStateId = 1;

            stateMap[config0] = q0;
            configMap[q0]     = config0;
            if (automaton.IsFinalState(this.automaton.InitialState))
            {
                finalStates.Add(q0);
            }

            var movemap = new Dictionary <Tuple <int, int>, T>();
            Action <int, int, T> AddMove = (source, target, pred) =>
            {
                var key = new Tuple <int, int>(source, target);
                T   psi;
                if (movemap.TryGetValue(key, out psi))
                {
                    movemap[key] = this.terminalAlgebra.MkOr(psi, pred);
                }
                else
                {
                    movemap[key] = pred;
                }
            };

            var frontier = new SimpleStack <int>();

            frontier.Push(q0);
            while (frontier.IsNonempty)
            {
                int q      = frontier.Pop();
                var config = configMap[q];
                foreach (var move in automaton.GetMovesFrom(config.Item1))
                {
                    if (stackDepth < 1 || (config.Item2.Length - 1 + move.Label.PushSymbols.Length) <= stackDepth)
                    {
                        var pop  = move.Label.PopSymbol;
                        var push = move.Label.PushSymbols;
                        if (config.Item2.First.Equals(pop))
                        {
                            var targetConfig = new Tuple <int, Sequence <S> >(move.TargetState, push.Append(config.Item2.Rest()));
                            int target;
                            if (!stateMap.TryGetValue(targetConfig, out target))
                            {
                                target = nextStateId++;
                                stateMap[targetConfig] = target;
                                configMap[target]      = targetConfig;
                                frontier.Push(target);
                                if (automaton.IsFinalState(move.TargetState))
                                {
                                    finalStates.Add(target);
                                }
                            }
                            Move <T> newmove;
                            if (move.Label.InputIsEpsilon)
                            {
                                newmove = Move <T> .Epsilon(q, target);

                                moves.Add(newmove);
                            }
                            else
                            {
                                //accumulate predicates for transitions
                                AddMove(q, target, move.Label.Input);
                            }
                        }
                    }
                }
            }

            foreach (var entry in movemap)
            {
                moves.Add(Move <T> .Create(entry.Key.Item1, entry.Key.Item2, entry.Value));
            }

            var res = Automaton <T> .Create(this.terminalAlgebra, q0, finalStates, moves, false, true);

            return(res);
        }