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)); } }
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); } } }
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)); } } }
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); }
/// <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); }
/// <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); }