/// <summary> /// Make a tree rule from the input alphabet to the output alphabet. /// </summary> /// <param name="inputAlphabet">input alphabet</param> /// <param name="outputAlphabet">output alphabet</param> /// <param name="state">source state</param> /// <param name="symbol">a ranked symbol of the input alphabet</param> /// <param name="guard">attribute guard</param> /// <param name="output">output tree</param> /// <param name="lookahead">domain restriction states</param> public TreeRule MkTreeRule(RankedAlphabet inputAlphabet, RankedAlphabet outputAlphabet, int state, string symbol, Expr guard, Expr output, params int[][] lookahead) { var A = inputAlphabet; var B = outputAlphabet; var constr = A.GetConstructor(symbol); CheckAttribute(guard, A); if (A.GetRank(symbol) != lookahead.Length) { throw new AutomataException(AutomataExceptionKind.TreeTheory_RankMismatch); } ExprSet[] la = new ExprSet[lookahead.Length]; int j = 0; for (int i = 0; i < lookahead.Length; i++) { la[i] = new ExprSet(); for (j = 0; j < lookahead[i].Length; j++) { la[i].Add(Z.MkNumeral(lookahead[i][j], Z.IntSort)); } } var outp = (output == null ? null : NormalizeOutput(output, A, B, A.GetRank(symbol))); return(new TreeRule(Z.MkInt(state), constr, guard, outp, la)); }
public TreeRule MkTreeAcceptorRule(RankedAlphabet A, int top, string symbol, Expr guard, params int[] bottom) { int[][] lookahead = new int[bottom.Length][]; for (int i = 0; i < bottom.Length; i++) { lookahead[i] = new int[] { bottom[i] } } ; return(MkTreeRule(A, A, top, symbol, guard, null, lookahead)); }
private void CheckAttribute(Expr term, RankedAlphabet A) { //check that the term does not use any free varibales other than the attribute variable foreach (var v in Z.GetVars(term)) { if (!v.Equals(A.AttrVar)) { throw new AutomataException(AutomataExceptionKind.TreeTheory_UnexpectedVariable); } } }
/// <summary> /// Make a tree rule from the input alphabet to the output alphabet. /// </summary> /// <param name="inputAlphabet">input alphabet</param> /// <param name="outputAlphabet">output alphabet</param> /// <param name="state">source state</param> /// <param name="symbol">a ranked symbol of the input alphabet</param> /// <param name="guard">attribute guard</param> /// <param name="output">output tree</param> public TreeRule MkTreeRule(RankedAlphabet inputAlphabet, RankedAlphabet outputAlphabet, int state, string symbol, Expr guard, Expr output) { var A = inputAlphabet; var B = outputAlphabet; var constr = A.GetConstructor(symbol); CheckAttribute(guard, A); var outp = (output == null ? null : NormalizeOutput(output, A, B, A.GetRank(symbol))); return(new TreeRule(Z.MkInt(state), constr, guard, outp, A.GetRank(symbol))); }
/// <summary> /// Make an output term of applying the given state to the given child subtree. /// </summary> /// <param name="outputAlphabet">the output alphabet sort</param> /// <param name="state">the state from which the child is transduced</param> /// <param name="child">the accessor of the child, must be a positive integer between 1 and MaxRank</param> public Expr MkTrans(RankedAlphabet outputAlphabet, int state, int child) { var f = tt.GetTrans(AlphabetSort, outputAlphabet.AlphabetSort); var s = tt.Z.MkInt(state); if (child < 1 || child > MaxRank) { throw new AutomataException(AutomataExceptionKind.RankedAlphabet_ChildAccessorIsOutOufBounds); } var x = ChildVar(child); var res = tt.Z.MkApp(f, s, x); return(res); }
//adds identity states when A=B and a child is ouput without transformation internal Expr NormalizeOutput(Expr t, RankedAlphabet A, RankedAlphabet B, int rank) { if (Z.IsVar(t)) { if (Z.GetVarIndex(t) > rank || !t.Sort.Equals(A.AlphabetSort)) { throw new AutomataException(AutomataExceptionKind.TreeTheory_UnexpectedVariable); } else { return(Z.MkApp(GetTrans(A.AlphabetSort, B.AlphabetSort), identityState, t)); } } else if (t.ASTKind == Z3_ast_kind.Z3_APP_AST) { var f = t.FuncDecl; var args = t.Args; if (B.ContainsConstructor(f)) { CheckAttribute(args[0], A); var args1 = new Expr[args.Length]; args1[0] = args[0]; for (int j = 1; j < args.Length; j++) { args1[j] = NormalizeOutput(args[j], A, B, rank); } return(Z.MkApp(f, args1)); } else if (IsTrans(f)) { if (args[0].ASTKind != Z3_ast_kind.Z3_NUMERAL_AST || !Z.IsVar(args[1]) || Z.GetVarIndex(args[1]) > rank || Z.GetVarIndex(args[1]) < 1) { throw new AutomataException(AutomataExceptionKind.TreeTheory_UnexpectedVariable); } else { return(t); } } else { throw new AutomataException(AutomataExceptionKind.TreeTheory_UnexpectedOutput); } } else { throw new AutomataException(AutomataExceptionKind.TreeTheory_UnexpectedOutput); } }
/// <summary> /// Make a new tree automaton or tree transducer. /// </summary> /// <param name="initStates">initial states</param> /// <param name="inputAlphabet">input alphabet</param> /// <param name="outputAlphabet">output alphabet</param> /// <param name="rules">rules of the automaton or transducer</param> /// <returns></returns> public TreeTransducer MkTreeAutomaton(IEnumerable <int> initStates, RankedAlphabet inputAlphabet, RankedAlphabet outputAlphabet, IEnumerable <TreeRule> rules) { foreach (var st in initStates) { if (st < 0) { throw new AutomataException(AutomataExceptionKind.TreeTransducer_InvalidStateId); } } var stateList = new List <Expr>(); var stateSet = new HashSet <Expr>(); var rulesList = new List <TreeRule>(rules); var q0_list = new List <Expr>(); foreach (var st in initStates) { q0_list.Add(Z.MkInt(st)); } #region perform basic sanity checks foreach (var rule in rulesList) { if (rule.State.Equals(identityState)) { throw new AutomataException(AutomataExceptionKind.TreeTransducer_InvalidUseOfIdentityState); } if (stateSet.Add(rule.state)) { stateList.Add(rule.state); } } foreach (var rule in rulesList) { if (!rule.IsTrueForAllStates(st => (stateSet.Contains(st) || st.Equals(identityState)))) { throw new AutomataException(AutomataExceptionKind.TreeTransducer_InvalidStateId); } } #endregion var ta = new TreeTransducer(q0_list, inputAlphabet, outputAlphabet, stateList, rulesList); var ta1 = ta.Clean(); return(ta1); }
internal TreeRule MkIdRule(RankedAlphabet A) { if (!IsAcceptorRule) { throw new AutomataException(AutomataExceptionKind.MkIdRule_RuleIsNotAcceptorRule); } Expr[] args = new Expr[this.lookahead.Length + 1]; args[0] = A.AttrVar; for (int i = 1; i <= this.lookahead.Length; i++) { if (!(this.lookahead[i - 1].IsEmptyOrSingleton)) { throw new AutomataException(AutomataExceptionKind.MkIdRule_RuleIsNotFlat); } args[i] = (this.lookahead[i - 1].IsEmpty ? A.tt.Z.MkApp(A.Trans, A.tt.identityState, A.ChildVar(i)) : A.tt.Z.MkApp(A.Trans, this.lookahead[i - 1].SomeElement, A.ChildVar(i))); } var new_output = A.tt.Z.MkApp(symbol, args); var new_rule = new TreeRule(this.state, this.symbol, this.guard, new_output, this.lookahead); return(new_rule); }
internal TreeRule MkIdRule(RankedAlphabet A) { if (!IsAcceptorRule) throw new AutomataException(AutomataExceptionKind.MkIdRule_RuleIsNotAcceptorRule); Expr[] args = new Expr[this.lookahead.Length + 1]; args[0] = A.AttrVar; for (int i = 1; i <= this.lookahead.Length; i++) { if (!(this.lookahead[i-1].IsEmptyOrSingleton)) throw new AutomataException(AutomataExceptionKind.MkIdRule_RuleIsNotFlat); args[i] = (this.lookahead[i-1].IsEmpty ? A.tt.Z.MkApp(A.Trans, A.tt.identityState, A.ChildVar(i)) : A.tt.Z.MkApp(A.Trans, this.lookahead[i-1].SomeElement, A.ChildVar(i))); } var new_output = A.tt.Z.MkApp(symbol, args); var new_rule = new TreeRule(this.state, this.symbol, this.guard, new_output, this.lookahead); return new_rule; }
public RankedAlphabetSort(AlphabetDef def, Z3Provider z3p, FastTransducerInstance fti) { this.z3p = z3p; List<string> alphSymbols = new List<string>(); List<int> alphArities = new List<int>(); // Create list of symbols with corresponding arities foreach (var sym in def.symbols) { alphSymbols.Add(sym.name.text); alphArities.Add(sym.arity - 1); } alphFieldsSorts = new List<Sort>(); tupleKeys = new List<String>(); foreach (var field in def.attrSort.fieldSorts) { tupleKeys.Add(field.Key); switch (field.Value.kind) { case (FastSortKind.Char): { alphFieldsSorts.Add(z3p.CharSort); break; } case (FastSortKind.Real): { alphFieldsSorts.Add(z3p.RealSort); break; } case (FastSortKind.Bool): { alphFieldsSorts.Add(z3p.BoolSort); break; } case (FastSortKind.Int): { alphFieldsSorts.Add(z3p.IntSort); break; } case (FastSortKind.String): { alphFieldsSorts.Add(z3p.MkListSort(z3p.CharSort)); break; } case (FastSortKind.Tree): { foreach (var enumSort in fti.enums) { if (enumSort.name == field.Value.name.text) { alphFieldsSorts.Add(enumSort.sort); break; } } break; } } } this.tupleName = "$" + def.id.text; this.tupleTests = new FuncDecl[alphFieldsSorts.Count]; var tupsymbs = new Symbol[tupleKeys.Count]; int j = 0; foreach(var v in tupleKeys){ tupsymbs[j]= z3p.Z3.MkSymbol(v); j++; } var tup = z3p.Z3.MkTupleSort(z3p.Z3.MkSymbol(tupleName), tupsymbs, alphFieldsSorts.ToArray()); this.tupleSort = tup; this.tupleFuncDec = tup.MkDecl; this.tupleTests = tup.FieldDecls; this.alph = z3p.TT.MkRankedAlphabet(def.id.text, this.tupleSort, alphSymbols.ToArray(), alphArities.ToArray()); this.alphName = def.id.text; this.alphSort = this.alph.AlphabetSort; }
/// <summary> /// Creates a ranked alphabet, a rank of a function symbol is the number of its children (subtrees). /// The rank excludes the node label. Thus, all function symbols have rank + 1 number of arguments. /// The first argument is always the attribute. /// </summary> /// <param name="name">alphabet name</param> /// <param name="attributeSort">attribute sort</param> /// <param name="symbols">function symbols of the alphabet</param> /// <param name="ranks">ranks of the function symbols</param> public RankedAlphabet MkRankedAlphabet(string name, Sort attributeSort, string[] symbols, int[] ranks) { #region validity checks if (string.IsNullOrWhiteSpace(name) || attributeSort == null || symbols == null || ranks == null || symbols.Length == 0 || ranks.Length == 0) { throw new AutomataException(AutomataExceptionKind.InvalidArguments); } var name_nodeSort = new Tuple <string, Sort>(name, attributeSort); if (rankedAlphabetSortMap.ContainsKey(name_nodeSort)) { throw new AutomataException(AutomataExceptionKind.RankedAlphabet_IsAlreadyDefined); } if (symbols.Length != ranks.Length) { throw new AutomataException(AutomataExceptionKind.RankedAlphabet_IsInvalid); } Dictionary <string, int> idMap = new Dictionary <string, int>(symbols.Length); bool containsOneleaf = false; int maxrank = 0; for (int i = 0; i < symbols.Length; i++) { if (string.IsNullOrWhiteSpace(symbols[i]) || idMap.ContainsKey(symbols[i]) || ranks[i] < 0) { throw new AutomataException(AutomataExceptionKind.RankedAlphabet_IsInvalid); } else { idMap.Add(symbols[i], i); containsOneleaf = (containsOneleaf || ranks[i] == 0); maxrank = (maxrank > ranks[i] ? maxrank : ranks[i]); } } if (!containsOneleaf) { throw new AutomataException(AutomataExceptionKind.RankedAlphabet_ContainsNoLeaf); } #endregion int K = symbols.Length; var fieldNames = new string[K][]; var fieldSorts = new Sort[K][]; var testerNames = new string[K]; var constructors = new Constructor[K]; for (int i = 0; i < K; i++) { string symb = symbols[i]; int arity = ranks[i] + 1; fieldNames[i] = new string[arity]; fieldSorts[i] = new Sort[arity]; var field_refs = new uint[arity]; fieldSorts[i][0] = attributeSort; for (int j = 0; j < arity; j++) { fieldNames[i][j] = symb + "@" + j; } constructors[i] = Z.z3.MkConstructor(symb, "$is" + symb, fieldNames[i], fieldSorts[i], field_refs); } Sort datatype = Z.z3.MkDatatypeSort(name, constructors); var constrs = new FuncDecl[K]; var accessors = new FuncDecl[K][]; var testers = new FuncDecl[K]; for (int i = 0; i < K; i++) { constrs[i] = constructors[i].ConstructorDecl; accessors[i] = constructors[i].AccessorDecls; testers[i] = constructors[i].TesterDecl; } rankedAlphabetSortMap[name_nodeSort] = datatype; FuncDecl acceptor = Z.MkFuncDecl(string.Format("$lang_{0}", name), new Sort[] { Z.IntSort, datatype }, Z.BoolSort); Expr[] vars = new Expr[maxrank + 1]; vars[0] = Z.MkVar(0, attributeSort); for (int i = 1; i <= maxrank; i++) { vars[i] = Z.MkVar((uint)i, datatype); } var ra = new RankedAlphabet(this, symbols, idMap, datatype, attributeSort, ranks, constrs, accessors, testers, acceptor, vars); rankedAlphabetInfoMap[datatype] = ra; return(ra); }
/// <summary> /// Make a new tree automaton or tree transducer. /// </summary> /// <param name="q0">initial state</param> /// <param name="inputAlphabet">input alphabet</param> /// <param name="outputAlphabet">output alphabet</param> /// <param name="rules">rules of the automaton or transducer</param> /// <returns></returns> public TreeTransducer MkTreeAutomaton(int q0, RankedAlphabet inputAlphabet, RankedAlphabet outputAlphabet, IEnumerable <TreeRule> rules) { return(MkTreeAutomaton(new List <int>(new int[] { q0 }), inputAlphabet, outputAlphabet, rules)); }
/// <summary> /// Make an output term of applying the given state to the given child subtree. /// </summary> /// <param name="outputAlphabet">the output alphabet sort</param> /// <param name="state">the state from which the child is transduced</param> /// <param name="child">the accessor of the child, must be a positive integer between 1 and MaxRank</param> public Expr MkTrans(RankedAlphabet outputAlphabet, int state, int child) { var f = tt.GetTrans(AlphabetSort, outputAlphabet.AlphabetSort); var s = tt.Z.MkInt(state); if (child < 1 || child > MaxRank) throw new AutomataException(AutomataExceptionKind.RankedAlphabet_ChildAccessorIsOutOufBounds); var x = ChildVar(child); var res = tt.Z.MkApp(f, s, x); return res; }