static public ComputationTree ToComputationTrees(STb <FuncDecl, Expr, Sort> stb, bool includeOutput)
        {
            var ctx = ((Z3Provider)stb.Solver).Z3;

            var states         = stb.States.Select((State, Index) => new { State, Index, Name = "S" + State });
            var csEnumSort     = ctx.IntSort;
            var outputListSort = stb.OutputListSort as ListSort;
            var resultSort     = ctx.MkTupleSort(ctx.MkSymbol(stb.Name + "#STATE"),
                                                 new[] { ctx.MkSymbol("#CS"), ctx.MkSymbol("#OUT"), ctx.MkSymbol("#VARS") },
                                                 new[] { csEnumSort, outputListSort, stb.RegisterSort });
            var csField       = resultSort.FieldDecls[0];
            var outputField   = resultSort.FieldDecls[1];
            var registerField = resultSort.FieldDecls[2];

            var inputVar       = stb.Solver.MkVar(0, stb.InputSort);
            var registerVar    = stb.Solver.MkVar(1, stb.RegisterSort);
            var computationVar = stb.Solver.MkVar(2, resultSort);

            var csProjection       = csField.Apply(computationVar);
            var outputProjection   = outputField.Apply(computationVar);
            var registerProjection = registerField.Apply(computationVar);

            Func <int, Expr[], Expr, Expr> createResult = (state, yields, register) =>
            {
                Expr output;

                if (includeOutput)
                {
                    output = yields.Length == 0 ? outputProjection : ctx.MkFuncDecl("Append", new Sort[] { outputListSort, outputListSort }, outputListSort).Apply(
                        outputProjection, ctx.MkFuncDecl("List", yields.Select(x => x.Sort).ToArray(), outputListSort).Apply(yields));
                }
                else
                {
                    output = outputProjection;
                }
                var result = resultSort.MkDecl.Apply(
                    ctx.MkInt(state),
                    output,
                    register != null ? register : registerProjection);
                return(result.Substitute(registerVar, registerProjection));
            };

            ComputationNode ruleNode;
            var             stateComps = stb.States.Select(State => new { State, Computation = ToComputationTree(ctx, stb.GetRuleFrom(State), registerVar, registerProjection, createResult) }).ToList();

            if (stateComps.Count == 0)
            {
                ruleNode = new UndefinedNode();
            }
            else
            {
                ruleNode = new SwitchNode(stateComps.Select(x => ctx.MkEq(csProjection, ctx.MkInt(x.State))).ToArray(), stateComps.Select(x => x.Computation).ToArray());
            }

            ComputationNode finalNode;
            var             finalComps = stb.States.Where(s => stb.IsFinalState(s))
                                         .Select(State => new { State, Computation = ToComputationTree(ctx, stb.GetFinalRuleFrom(State), registerVar, registerProjection, createResult) }).ToList();

            if (finalComps.Count == 0)
            {
                finalNode = new UndefinedNode();
            }
            else
            {
                finalNode = new SwitchNode(finalComps.Select(x => ctx.MkEq(csProjection, ctx.MkInt(x.State))).ToArray(), finalComps.Select(x => x.Computation).ToArray());
            }

            var initialState = resultSort.MkDecl.Apply(
                ctx.MkInt(stb.InitialState),
                outputListSort.Nil,
                stb.InitialRegister);

            return(new ComputationTree
            {
                Move = ruleNode,
                Finish = finalNode,
                InitialState = initialState,
                EnumSorts = new EnumSort[] { },
            });
        }