public STb <FUNC, TERM, SORT> Compose() { var stack = new SimpleStack <Tuple <int, int> >(); int stateId = 1; var stateIdMap = new Dictionary <Tuple <int, int>, int>(); var revStateIdMap = new Dictionary <int, Tuple <int, int> >(); var q0A_x_q0B = new Tuple <int, int>(A.InitialState, B.InitialState); stack.Push(q0A_x_q0B); stateIdMap[q0A_x_q0B] = 0; revStateIdMap[0] = q0A_x_q0B; Func <int, int, int> ComposeStates = (x, y) => { var xy = new Tuple <int, int>(x, y); int q; if (stateIdMap.TryGetValue(xy, out q)) { return(q); } else { q = stateId; stateId += 1; stateIdMap[xy] = q; revStateIdMap[q] = xy; stack.Push(xy); return(q); } }; var A2B = new STb <FUNC, TERM, SORT>(solver, A.Name + "2" + B.Name, A.InputSort, B.OutputSort, regSort, JoinRegs(A.InitialRegister, B.InitialRegister), 0); //create normal composed rules while (stack.IsNonempty) { var qA_x_qB = stack.Pop(); var qA = qA_x_qB.Item1; var qB = qA_x_qB.Item2; var ruleA = A.GetRuleFrom(qA); if (ruleA.IsNotUndef) { var qAB_rule = Comp(solver.True, ruleA, qB, ComposeStates, false); A2B.AssignRule(stateIdMap[qA_x_qB], qAB_rule); } else { A2B.AssignRule(stateIdMap[qA_x_qB], UndefRule <TERM> .Default); } } foreach (var qAB in A2B.States) { var qA_x_qB = revStateIdMap[qAB]; var qA = qA_x_qB.Item1; var qB = qA_x_qB.Item2; var ruleA = A.GetFinalRuleFrom(qA); if (ruleA.IsNotUndef) { var qAB_Frule = Comp(solver.True, ruleA, qB, (p, q) => qAB, true); A2B.AssignFinalRule(qAB, qAB_Frule); } } A2B.EliminateDeadends(); //Func<Rule<TERM>, Rule<TERM>> ReplaceWithEpsilon = (r) => // { // }; //var aut = A2B.ToST(true).automaton.RelpaceAllGuards(ReplaceWithEpsilon); return(A2B); }