Repository: sympy/sympy
File: sympy/solvers/recurr.py (Python)

Code before:
            similar = {}

            for g in f.expand().args:
                if not g.is_hypergeometric(n):
                    return None

                for h in similar.keys():
                    if hypersimilar(g, h, n):
                        similar[h] += g
                        break
                else:
                    similar[g] = S.Zero

            inhomogeneous = [g + h for g, h in similar.items()]
        elif f.is_hypergeometric(n):
            inhomogeneous = [f]
        else:
            return None

        for i, g in enumerate(inhomogeneous):
            coeff, polys = S.One, coeffs[:]
            denoms = [S.One]*(r + 1)

            s = hypersimp(g, n)

            if s is None:
                return None

            for j in range(1, r + 1):
                coeff *= s.subs(n, n + j - 1)

                p, q = coeff.as_numer_denom()

                polys[j] *= p
                denoms[j] = q

            for j in range(r + 1):
                polys[j] *= Mul(*(denoms[:j] + denoms[j + 1:]))

            # FIXME: The call to rsolve_ratio below should suffice (rsolve_poly
            # call can be removed) but the XFAIL test_rsolve_ratio_missed must
            # be fixed first.
            R = rsolve_ratio(polys, Mul(*denoms), n, symbols=True)
            if R is not None:
                R, syms = R
                if syms:
                    R = R.subs(zip(syms, [0]*len(syms)))
            else:
                R = rsolve_poly(polys, Mul(*denoms), n)

            if R:

Review comment (bug):
Just so we are clear here. This is the actual fix for bug in the cited issue.

I would be happy to merge a PR that only has this fix along with a regression test for the case in the issue.

Improving hypersimp is a separate more complicated question which is why this is turning into a lengthier discussion.

Code after:
            similar = {}

            for g in f.expand().args:
                if not g.is_hypergeometric(n):
                    return None

                for h in similar.keys():
                    if hypersimilar(g, h, n):
                        similar[h] += g
                        break
                else:
                    similar[g] = S.Zero

            inhomogeneous = [g + h for g, h in similar.items()]
        elif f.is_hypergeometric(n):
            inhomogeneous = [f]
        else:
            return None

        for i, g in enumerate(inhomogeneous):
            coeff, polys = S.One, coeffs[:]
            denoms = [S.One]*(r + 1)

            s = hypersimp(g, n)
            if s is None:
                return None

            for j in range(1, r + 1):
                coeff *= s.subs(n, n + j - 1)

                p, q = coeff.as_numer_denom()

                polys[j] *= p
                denoms[j] = q

            for j in range(r + 1):
                polys[j] *= Mul(*(denoms[:j] + denoms[j + 1:]))

            # FIXME: The call to rsolve_ratio below should suffice (rsolve_poly
            # call can be removed) but the XFAIL test_rsolve_ratio_missed must
            # be fixed first.
            R = rsolve_ratio(polys, Mul(*denoms), n, symbols=True)
            if R is not None:
                R, syms = R
                if syms:
                    R = R.subs(zip(syms, [0]*len(syms)))
            else:
                R = rsolve_poly(polys, Mul(*denoms), n)

            if R:
                inhomogeneous[i] *= R