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 Automaton <S> GetAtom(Automaton <S> psi) { if (!IsAtomic) { throw new AutomataException(AutomataExceptionKind.BooleanAlgebraIsNotAtomic); } if (psi.IsEmpty) { return(psi); } var path = new List <S>(psi.ChoosePathToSomeFinalState(new Chooser())); var moves = new List <Move <S> >(); for (int i = 0; i < path.Count; i++) { moves.Add(Move <S> .Create(i, i + 1, solver.GetAtom(path[i]))); } var atom = Automaton <S> .Create(solver, 0, new int[] { path.Count }, moves); return(atom); }
/// <summary> /// Builds an end of line anchor automaton ($ in multiline mode) /// </summary> /// <param name="newLineCond">condition that is true only for a newline character</param> public Automaton <S> MkEol(S newLineCond) { if (!isEnd) { throw new AutomataException(AutomataExceptionKind.MisplacedEndAnchor); } if (isBeg) { return(MkFull()); } var st = this.MkStateId(); var st1 = this.MkStateId(); var minStateId2 = this.MkStateId(); Automaton <S> fa = Automaton <S> .Create(this.solver, st, new int[] { st, st1 }, new Move <S>[] { Move <S> .Create(st, st1, newLineCond), Move <S> .Create(st1, st1, solver.True) }); return(fa); }
public STb <F, T, S> Mk(string regex, params Tuple <string, STb <F, T, S> >[] args) { var K = args.Length; bool isLoop; var patternAutomataPairs = solver.CharSetProvider.ConvertCaptures(regex, out isLoop); var captureAutomata = new Dictionary <string, Automaton <BDD> >(); var stbs = new Dictionary <string, STb <F, T, S> >(); foreach (var arg in args) { if (stbs.ContainsKey(arg.Item1) || string.IsNullOrEmpty(arg.Item1)) { throw new AutomataException(AutomataExceptionKind.InvalidArguments); } stbs[arg.Item1] = arg.Item2; } 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.OutputSort.ToString(); 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); } if (!args[i].Item2.OutputSort.Equals(args[i].Item2.RegisterSort)) { throw new AutomataException(AutomataExceptionKind.InvalidArguments); } argSorts[i] = args[i].Item2.OutputSort; } var regSort = solver.MkTupleSort(argSorts); var regVar = solver.MkVar(1, regSort); var initReg = solver.MainSolver.FindOneMember(solver.MkEq(regVar, regVar)).Value; 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>, int>(); Func <int, int, int, int> MkState = (n, q1, q2) => { int p; var nq = new Tuple <int, int, int>(n, q1, q2); if (stateIdMap.TryGetValue(nq, out p)) { return(p); } else { p = nextStateId; nextStateId += 1; stateIdMap[nq] = p; return(p); } }; var resSTB = new STb <F, T, S>(solver, "STB", solver.CharSort, solver.CharSort, solver.UnitSort, solver.UnitConst, 0); resSTB.AssignRule(0, new BaseRule <T>(new Sequence <T>(solver.MkCharVar(0)), solver.UnitConst, 0)); resSTB.AssignFinalRule(0, new BaseRule <T>(Sequence <T> .Empty, solver.UnitConst, 0)); for (int i = 0; i < patternAutomataPairs.Length; i++) { var aut = patternAutomataPairs[i].Item2; if (patternAutomataPairs[i].Item1 == "") { var autSTMoves = new List <Move <Rule <T> > >(); foreach (var move in aut.GetMoves()) { //move cannot be epsilon here var cond = solver.ConvertFromCharSet(move.Label); autSTMoves.Add(Move <Rule <T> > .Create(move.SourceState, move.TargetState, Rule <T> .Mk(cond, solver.UnitConst))); } foreach (var f in aut.GetFinalStates()) { //collect guards of all moves exitingfrom f var allGuardsFromF = solver.CharSetProvider.False; foreach (var fmove in aut.GetMovesFrom(f)) { allGuardsFromF = solver.CharSetProvider.MkOr(allGuardsFromF, fmove.Label); } var elseFromF = solver.ConvertFromCharSet(solver.CharSetProvider.MkNot(allGuardsFromF)); autSTMoves.Add(Move <Rule <T> > .Create(f, f, Rule <T> .Mk(elseFromF, solver.UnitConst, solver.MkCharVar(0)))); autSTMoves.Add(Move <Rule <T> > .Create(f, f, Rule <T> .MkFinal(solver.True))); } var autST = ST <F, T, S> .Create(solver, patternAutomataPairs[i].Item1, solver.UnitConst, solver.CharSort, solver.CharSort, solver.UnitSort, aut.InitialState, autSTMoves); var autSTb = autST.ToSTb(); resSTB = resSTB.Compose(autSTb); } else { var stb1 = stbs[patternAutomataPairs[i].Item1]; if (!stb1.InputSort.Equals(solver.CharSort)) { throw new AutomataException(AutomataExceptionKind.InvalidArguments); } var autSTMoves = new List <Move <Rule <T> > >(); foreach (var move in aut.GetMoves()) { //move cannot be epsilon here var cond = solver.ConvertFromCharSet(move.Label); autSTMoves.Add(Move <Rule <T> > .Create(move.SourceState, move.TargetState, Rule <T> .Mk(cond, solver.UnitConst, inpVar))); } foreach (var f in aut.GetFinalStates()) { autSTMoves.Add(Move <Rule <T> > .Create(f, f, Rule <T> .MkFinal(solver.True))); } var autST = ST <F, T, S> .Create(solver, patternAutomataPairs[i].Item1, solver.UnitConst, solver.CharSort, solver.CharSort, solver.UnitSort, aut.InitialState, autSTMoves); var autSTb = autST.ToSTb(); var stb2 = autSTb.Compose(stb1); foreach (var f in stb.States) { var frule = stb.GetFinalRuleFrom(f); if (frule.IsNotUndef) { //var frule1 = } } } } throw new NotImplementedException(); }
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> /// Make a move that corresponds to a final rule. This is indicated by IsFinal=true of the condition of the move. /// </summary> /// <param name="finalState">final state</param> /// <param name="finalCondition">guard of the final outputs</param> /// <param name="finalYields">final outputs</param> /// <returns>a move from final state to final state that represents the final outputs yielded from the final state</returns> public Move <Rule <TERM> > MkFinalOutput(int finalState, TERM finalCondition, params TERM[] finalYields) { return(Move <Rule <TERM> > .Create(finalState, finalState, Rule <TERM> .MkFinal(finalCondition, finalYields))); }
/// <summary> /// Make a move that corresponds to a nonfinal rule. This is indicated by IsFinal=false of the label of the move. /// </summary> /// <param name="source">source state of the move</param> /// <param name="target">target state of the move</param> /// <param name="guard">guard of the rule</param> /// <param name="update">update of the rule</param> /// <param name="yields">sequence of output yields of the rule</param> /// <returns>nonfinal move from source to target</returns> public Move <Rule <TERM> > MkRule(int source, int target, TERM guard, TERM update, params TERM[] yields) { return(Move <Rule <TERM> > .Create(source, target, Rule <TERM> .Mk(guard, update, yields))); }
public override IEnumerable <Move <Rule <TERM> > > EnumerateMoves(IContextCore <TERM> solver, int source, TERM guard) { yield return(Move <Rule <TERM> > .Create(source, state, Rule <TERM> .Mk(guard, register, yields.ToArray()))); }
/// <summary> /// Builds an automaton that accepts all words. /// </summary> public Automaton <S> MkFull() { var st = this.MkStateId(); return(Automaton <S> .Create(this.solver, st, new int[] { st }, new Move <S>[] { Move <S> .Create(st, st, solver.True) })); }
public STb <FUNC, TERM, SORT> Minimize() { var s = stb.Solver; var alphaSort = s.MkOptionSort(stb.InputSort); var autoSort = s.MkTupleSort(alphaSort, stb.OutputListSort, stb.RegisterSort, stb.RegisterSort); var autoVar = s.MkVar(3, autoSort); var autoInput = s.MkProj(0, autoVar); var autoSomeInput = s.MkGetSomeValue(autoInput); var autoOutputList = s.MkProj(1, autoVar); var autoOldReg = s.MkProj(2, autoVar); var autoNewReg = s.MkProj(3, autoVar); Func <TERM, TERM> finalSubstitute = (t) => s.ApplySubstitution(t, stb.RegVar, autoOldReg); Func <TERM, TERM> nonFinalSubstitute = (t) => finalSubstitute(s.ApplySubstitution(t, stb.InputVar, autoSomeInput)); int acceptingState = stb.States.Max() + 1; int errorState = stb.States.Max() + 2; var moves = new List <Move <TERM> >(); foreach (var state in stb.States) { var nonFinalConds = new List <TERM>(); foreach (var nonFinal in st.GetNonFinalMovesFrom(state)) { var rule = nonFinal.Label; var conds = new List <TERM>(); conds.Add(s.MkIsSome(autoInput)); conds.Add(nonFinalSubstitute(rule.Guard)); var outputList = autoOutputList; foreach (var yield in rule.Output) { conds.Add(s.MkIsCons(outputList)); conds.Add(s.MkEq(s.MkFirstOfList(outputList), nonFinalSubstitute(yield))); outputList = s.MkRestOfList(outputList); } conds.Add(s.MkIsNil(outputList)); conds.Add(s.MkEq(autoNewReg, nonFinalSubstitute(rule.Update))); var cond = s.MkAnd(conds); moves.Add(Move <TERM> .Create(state, nonFinal.TargetState, cond)); nonFinalConds.Add(cond); } var finalConds = new List <TERM>(); foreach (var rule in st.GetFinalRules(state)) { var conds = new List <TERM>(); conds.Add(s.MkIsNone(autoInput)); conds.Add(finalSubstitute(rule.Guard)); var outputList = autoOutputList; foreach (var yield in rule.Output) { conds.Add(s.MkIsCons(outputList)); conds.Add(s.MkEq(s.MkFirstOfList(outputList), finalSubstitute(yield))); outputList = s.MkRestOfList(outputList); } conds.Add(s.MkIsNil(outputList)); var cond = s.MkAnd(conds); moves.Add(Move <TERM> .Create(state, acceptingState, cond)); finalConds.Add(cond); } } //moves.Add(Move<TERM>.Create(errorState, errorState, s.True)); var auto = Automaton <TERM> .Create(stb.Solver, stb.InitialState, new int[] { acceptingState }, moves); auto.CheckDeterminism(stb.Solver); var blocks = auto.BookkeepingMinimize(stb.Solver); Func <STbRule <TERM>, STbRule <TERM> > redirect = null; redirect = r => { switch (r.RuleKind) { case STbRuleKind.Undef: return(r); case STbRuleKind.Base: return(new BaseRule <TERM>(r.Yields, r.Register, blocks[r.State].GetRepresentative())); case STbRuleKind.Ite: var t = redirect(r.TrueCase); var f = redirect(r.FalseCase); return(new IteRule <TERM>(r.Condition, t, f)); default: throw new NotImplementedException(); } }; var minimized = new STb <FUNC, TERM, SORT>(stb.Solver, stb.Name + "_min", stb.InputSort, stb.OutputSort, stb.RegisterSort, stb.InitialRegister, blocks[stb.InitialState].GetRepresentative()); var representatives = new HashSet <int>(); foreach (var state in stb.States) { representatives.Add(blocks[state].GetRepresentative()); } foreach (var state in representatives) { minimized.AssignRule(state, redirect(stb.GetRuleFrom(state)).CollapseRedundantITEs(s)); minimized.AssignFinalRule(state, redirect(stb.GetFinalRuleFrom(state)).CollapseRedundantITEs(s)); } return(minimized); }
/// <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); }
public static CsAutomaton <S> CreateFrom(CountingAutomaton <S> ca) { var productmoves = new List <Move <CsPred <S> > >(); var counters = ca.counters; var alg = new CsAlgebra <S>(((CABA <S>)ca.Algebra).builder.solver, counters); foreach (var move in ca.GetMoves()) { var ccond = alg.TrueCsConditionSeq; if (ca.IsCountingState(move.SourceState)) { var counter = ca.GetCounter(move.SourceState); var cid = counter.CounterId; if (move.Label.Item2.First.OperationKind == CounterOp.EXIT || move.Label.Item2.First.OperationKind == CounterOp.EXIT_SET0 || move.Label.Item2.First.OperationKind == CounterOp.EXIT_SET1) { if (counter.LowerBound == counter.UpperBound && !ca.HasMovesTo(move.SourceState, move.Label.Item1.Element)) { ccond = ccond.And(cid, CsCondition.HIGH); } else if (counter.LowerBound > 0) { ccond = ccond.And(cid, CsCondition.CANEXIT); } else { ccond.And(cid, CsCondition.NONEMPTY); } } else { if (move.Label.Item2.First.OperationKind != CounterOp.INCR) { throw new AutomataException(AutomataExceptionKind.InternalError); } if (counter.LowerBound == counter.UpperBound && !ca.HasMovesTo(move.SourceState, move.Label.Item1.Element)) { ccond = ccond.And(cid, CsCondition.LOW); } else { ccond = ccond.And(cid, CsCondition.CANLOOP); } } } if (ccond.IsSatisfiable) { var pmove = Move <CsPred <S> > .Create(move.SourceState, move.TargetState, alg.MkPredicate(move.Label.Item1.Element, ccond)); productmoves.Add(pmove); } } var prodaut = Automaton <CsPred <S> > .Create(alg, ca.InitialState, ca.GetFinalStates(), productmoves); PowerSetStateBuilder sb; var det = prodaut.Determinize(out sb); //add predicate that all counters associated with the state are nonempty var counterFilter = new Dictionary <int, CsConditionSeq>(); foreach (var state in det.GetStates()) { var stateCounterFilter = alg.TrueCsConditionSeq; foreach (var q in sb.GetMembers(state)) { if (ca.IsCountingState(q)) { stateCounterFilter = stateCounterFilter.And(ca.GetCounter(q).CounterId, CsCondition.NONEMPTY); } } counterFilter[state] = stateCounterFilter; } var csmoves = new List <Move <CsLabel <S> > >(); //make disjunction of the guards of transitions with same update sequence var trans = new Dictionary <Tuple <int, int>, Dictionary <CsUpdateSeq, CsPred <S> > >(); foreach (var dmove in det.GetMoves()) { foreach (var prodcond in dmove.Label.GetSumOfProducts()) { var upd = CsUpdateSeq.MkNOOP(ca.NrOfCounters); foreach (var q in sb.GetMembers(dmove.SourceState)) { upd = upd | ca.GetCounterUpdate(q, prodcond.Item2, prodcond.Item1); } //make sure all counter guards are nonempty //determinization may create EMPTY counter conditions that are unreachable //while all counters associated with a state are always nonempty var counterGuard = prodcond.Item1 & counterFilter[dmove.SourceState]; if (counterGuard.IsSatisfiable) { #region replace set with incr if possible for (int i = 0; i < upd.Length; i++) { var guard_i = counterGuard[i]; if (guard_i == CsCondition.HIGH) { var upd_i = upd[i]; switch (upd_i) { case CsUpdate.SET0: upd = upd.Set(i, CsUpdate.INCR0); break; case CsUpdate.SET1: upd = upd.Set(i, CsUpdate.INCR1); break; case CsUpdate.SET01: upd = upd.Set(i, CsUpdate.INCR01); break; default: break; } } } #endregion var guard = alg.MkPredicate(prodcond.Item2, counterGuard); var statepair = new Tuple <int, int>(dmove.SourceState, dmove.TargetState); Dictionary <CsUpdateSeq, CsPred <S> > labels; if (!trans.TryGetValue(statepair, out labels)) { labels = new Dictionary <CsUpdateSeq, CsPred <S> >(); trans[statepair] = labels; } CsPred <S> pred; if (!labels.TryGetValue(upd, out pred)) { pred = guard; } else { pred = guard | pred; } labels[upd] = pred; } else { ; } } } Func <S, string> pp = ((CABA <S>)ca.Algebra).builder.solver.PrettyPrint; foreach (var entry in trans) { var s = entry.Key.Item1; var t = entry.Key.Item2; foreach (var label in entry.Value) { var upd = label.Key; var psi = label.Value; csmoves.Add(Move <CsLabel <S> > .Create(s, t, CsLabel <S> .MkTransitionLabel(psi, upd, pp))); } } var csa_aut = Automaton <CsLabel <S> > .Create(null, det.InitialState, det.GetFinalStates(), csmoves, true, true); var fs = new HashSet <int>(ca.GetFinalStates()); var csa = new CsAutomaton <S>(alg, csa_aut, sb, ca.countingStates, fs); return(csa); }
/// <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); }
PushdownAutomaton <S, T> Intersect1(IMinimalAutomaton <T> nfa) { //depth first product construction, PDA may have epsilon moves var stateIdMap = new Dictionary <Pair, int>(); int nextStateId = 1; var stack = new SimpleStack <Pair>(); var moves = new List <Move <PushdownLabel <S, T> > >(); var states = new List <int>(); var finalstates = new List <int>(); #region GetState: push the pair to stack if the state id was new and update final states as needed Func <Pair, int> GetState = (pair) => { int id; if (!stateIdMap.TryGetValue(pair, out id)) { id = nextStateId; nextStateId += 1; stateIdMap[pair] = id; stack.Push(pair); states.Add(id); if (this.automaton.IsFinalState(pair.Item1) && nfa.IsFinalState(pair.Item2)) { finalstates.Add(id); } } return(id); }; #endregion var initPair = new Pair(this.automaton.InitialState, nfa.InitialState); int initState = GetState(initPair); #region compute the product transitions with depth-first search while (stack.IsNonempty) { var sourcePair = stack.Pop(); var source = stateIdMap[sourcePair]; var pda_state = sourcePair.Item1; var aut_state = sourcePair.Item2; foreach (var pda_move in this.automaton.GetMovesFrom(pda_state)) { if (pda_move.IsEpsilon || pda_move.Label.InputIsEpsilon) { var targetPair = new Pair(pda_move.TargetState, aut_state); int target = GetState(targetPair); moves.Add(Move <PushdownLabel <S, T> > .Create(source, target, pda_move.Label)); } else { //assuming here that the automaton does not have epsilons foreach (var aut_move in nfa.GetMovesFrom(aut_state)) { if (aut_move.IsEpsilon) { throw new AutomataException(AutomataExceptionKind.AutomatonIsNotEpsilonfree); } var cond = nfa.Algebra.MkAnd(aut_move.Label, pda_move.Label.Input); //if the joint condition is not satisfiable then the //joint move does effectively not exist if (nfa.Algebra.IsSatisfiable(cond)) { var targetPair = new Pair(pda_move.TargetState, aut_move.TargetState); int target = GetState(targetPair); var label = new PushdownLabel <S, T>(cond, pda_move.Label.PushAndPop); var jointmove = Move <PushdownLabel <S, T> > .Create(source, target, label); moves.Add(jointmove); } } } } } #endregion //note: automaton creation eliminates unreachable states and deadend states from the product var productAutom = Automaton <PushdownLabel <S, T> > .Create(null, initState, finalstates, moves, true, true); var product = new PushdownAutomaton <S, T>(nfa.Algebra, productAutom, this.stackSymbols, this.initialStackSymbol); return(product); }
public static ThreeAutomaton <S> MkProduct(ThreeAutomaton <S> aut1, ThreeAutomaton <S> aut2, IBooleanAlgebra <S> solver, bool inters) { var a = aut1.MakeTotal(); var b = aut2.MakeTotal(); var stateIdMap = new Dictionary <Tuple <int, int>, int>(); var initPair = new Tuple <int, int>(a.InitialState, b.InitialState); var frontier = new Stack <Tuple <int, int> >(); frontier.Push(initPair); stateIdMap[initPair] = 0; var delta = new Dictionary <int, List <Move <S> > >(); delta[0] = new List <Move <S> >(); var states = new List <int>(); states.Add(0); var accStates = new List <int>(); var rejStates = new List <int>(); if (inters) { if (a.IsFinalState(a.InitialState) && b.IsFinalState(b.InitialState)) { accStates.Add(0); } else if (a.IsRejectingState(a.InitialState) || b.IsRejectingState(b.InitialState)) { rejStates.Add(0); } } else { if (a.IsRejectingState(a.InitialState) && b.IsRejectingState(b.InitialState)) { rejStates.Add(0); } else if (a.IsFinalState(a.InitialState) || b.IsFinalState(b.InitialState)) { accStates.Add(0); } } int n = 1; while (frontier.Count > 0) { var currPair = frontier.Pop(); int source = stateIdMap[currPair]; var outTransitions = delta[source]; foreach (var t1 in a.GetMovesFrom(currPair.Item1)) { foreach (var t2 in b.GetMovesFrom(currPair.Item2)) { var cond = solver.MkAnd(t1.Label, t2.Label); if (!solver.IsSatisfiable(cond)) { continue; //ignore the unsatisfiable move } Tuple <int, int> targetPair = new Tuple <int, int>(t1.TargetState, t2.TargetState); int target; if (!stateIdMap.TryGetValue(targetPair, out target)) { //state has not yet been found target = n; n += 1; stateIdMap[targetPair] = target; states.Add(target); delta[target] = new List <Move <S> >(); frontier.Push(targetPair); if (inters) { if (a.IsFinalState(t1.TargetState) && b.IsFinalState(t2.TargetState)) { accStates.Add(target); } else if (a.IsRejectingState(t1.TargetState) || b.IsRejectingState(t2.TargetState)) { rejStates.Add(target); } } else { if (a.IsRejectingState(t1.TargetState) && b.IsRejectingState(t2.TargetState)) { rejStates.Add(target); } else if (a.IsFinalState(t1.TargetState) || b.IsFinalState(t2.TargetState)) { accStates.Add(target); } } } outTransitions.Add(Move <S> .Create(source, target, cond)); } } } var incomingTransitions = new Dictionary <int, List <Move <S> > >(); foreach (int state in states) { incomingTransitions[state] = new List <Move <S> >(); } foreach (int state in states) { foreach (Move <S> t in delta[state]) { incomingTransitions[t.TargetState].Add(t); } } return(ThreeAutomaton <S> .Create(aut1.algebra, 0, rejStates, accStates, EnumerateMoves(delta))); }
/// <summary> /// Builds an automaton equivalent to the regex (), /// Same as MkSeq(). /// </summary> public Automaton <S> MkEmptyWord() { if (isBeg || isEnd) { //may start or end with any characters since no anchor is used var st = this.MkStateId(); return(Automaton <S> .Create(this.solver, st, new int[] { st }, new Move <S>[] { Move <S> .Create(st, st, solver.True) })); } else //an intermediate empty string is just an epsilon transition { return(this.epsilon); } }
/// <summary> /// Extension of standard minimization of FAs, use timeout. /// </summary> ThreeAutomaton <S> MinimizeClassical(IBooleanAlgebra <S> solver, int timeout) { var fa = this.MakeTotal(); Equivalence E = new Equivalence(); //initialize E, all nonfinal states are equivalent //and all final states are equivalent and all dontcare are equivalent List <int> stateList = new List <int>(fa.States); for (int i = 0; i < stateList.Count; i++) { //E.Add(stateList[i], stateList[i]); for (int j = 0; j < stateList.Count; j++) { int p = stateList[i]; int q = stateList[j]; bool pIsFinal = fa.IsFinalState(p); bool qIsFinal = fa.IsFinalState(q); if (pIsFinal == qIsFinal) { if (pIsFinal) { E.Add(p, q); } else { bool pIsRej = fa.IsRejectingState(p); bool qIsRej = fa.IsRejectingState(q); if (pIsRej == qIsRej) { E.Add(p, q); } } } } } //refine E bool continueRefinement = true; List <int> statesList = new List <int>(fa.States); while (continueRefinement) { continueRefinement = false; for (int i = 0; i < statesList.Count; i++) { for (int j = 0; j < statesList.Count; j++) { Tuple <int, int> pq = new Tuple <int, int>(statesList[i], statesList[j]); if (E.Contains(pq)) { if (pq.Item1 != pq.Item2 && AreDistinguishable(fa, E, pq, solver)) { E.Remove(pq); continueRefinement = true; } } } } } //create id's for equivalence classes Dictionary <int, int> equivIdMap = new Dictionary <int, int>(); List <int> mfaStates = new List <int>(); foreach (Tuple <int, int> pq in E) { int equivId; if (equivIdMap.TryGetValue(pq.Item1, out equivId)) { equivIdMap[pq.Item2] = equivId; } else if (equivIdMap.TryGetValue(pq.Item2, out equivId)) { equivIdMap[pq.Item1] = equivId; } else { equivIdMap[pq.Item1] = pq.Item1; equivIdMap[pq.Item2] = pq.Item1; mfaStates.Add(pq.Item1); } } //remaining states map to themselves foreach (int state in fa.States) { if (!equivIdMap.ContainsKey(state)) { equivIdMap[state] = state; mfaStates.Add(state); } } int mfaInitialState = equivIdMap[fa.InitialState]; //group together transition conditions for transitions on equivalent states Dictionary <Tuple <int, int>, S> combinedConditionMap = new Dictionary <Tuple <int, int>, S>(); foreach (int state in fa.States) { int fromStateId = equivIdMap[state]; foreach (Move <S> trans in fa.GetMovesFrom(state)) { int toStateId = equivIdMap[trans.TargetState]; S cond; var p = new Tuple <int, int>(fromStateId, toStateId); if (combinedConditionMap.TryGetValue(p, out cond)) { combinedConditionMap[p] = solver.MkOr(cond, trans.Label); } else { combinedConditionMap[p] = trans.Label; } } } //form the transitions of the mfa List <Move <S> > mfaTransitions = new List <Move <S> >(); foreach (var kv in combinedConditionMap) { mfaTransitions.Add(Move <S> .Create(kv.Key.Item1, kv.Key.Item2, kv.Value)); } //accepting states and rejecting HashSet <int> mfaAccStates = new HashSet <int>(); HashSet <int> mfaRejStates = new HashSet <int>(); foreach (int state in acceptingStateSet) { mfaAccStates.Add(equivIdMap[state]); } foreach (int state in rejectingStateSet) { mfaRejStates.Add(equivIdMap[state]); } return(ThreeAutomaton <S> .Create(algebra, mfaInitialState, mfaRejStates, mfaAccStates, mfaTransitions)); }
void AddPop(int source, int target, S label, T input) { var input_seq = (object.Equals(input, default(T)) ? Sequence <T> .Empty : new Sequence <T>(input)); this.popMap[label].Add(Move <Sequence <T> > .Create(source, target, input_seq)); }