<SYSTEM_TASK:>
Solve the following problem using Python, implementing the functions described below, one line at a time
<END_TASK>
<USER_TASK:>
Description:
 def coarse_grain(self, user_sets):
 r"""Coarse-grains the flux onto user-defined sets. Parameters user_sets : list of int-iterables sets of states that shall be distinguished in the coarse-grained flux. Returns ------- (sets, tpt) : (list of int-iterables, tpt-object) sets contains the sets tpt is computed on. The tpt states of the new tpt object correspond to these sets of states in this order. Sets might be identical, if the user has already provided a complete partition that respects the boundary between A, B and the intermediates. If not, Sets will have more members than provided by the user, containing the "remainder" states and reflecting the splitting at the A and B boundaries. tpt contains a new tpt object for the coarse-grained flux. All its quantities (gross_flux, net_flux, A, B, committor, backward_committor) are coarse-grained to sets. Notes ----- All user-specified sets will be split (if necessary) to preserve the boundary between A, B and the intermediate states. """

        # coarse-grain sets
        (tpt_sets, Aindexes, Bindexes) = self._compute_coarse_sets(user_sets)
        nnew = len(tpt_sets)

        # coarse-grain fluxHere we should branch between sparse and dense implementations, but currently there is only a
        F_coarse = tptapi.coarsegrain(self._gross_flux, tpt_sets)
        Fnet_coarse = tptapi.to_netflux(F_coarse)

        # coarse-grain stationary probability and committors - this can be done all dense
        pstat_coarse = np.zeros((nnew))
        forward_committor_coarse = np.zeros((nnew))
        backward_committor_coarse = np.zeros((nnew))
        for i in range(0, nnew):
            I = list(tpt_sets[i])
            muI = self._mu[I]
            pstat_coarse[i] = np.sum(muI)
            partialI = muI / pstat_coarse[i]  # normalized stationary probability over I
            forward_committor_coarse[i] = np.dot(partialI, self._qplus[I])
            backward_committor_coarse[i] = np.dot(partialI, self._qminus[I])

        res = ReactiveFlux(Aindexes, Bindexes, Fnet_coarse, mu=pstat_coarse,
                           qminus=backward_committor_coarse, qplus=forward_committor_coarse, gross_flux=F_coarse)
        return (tpt_sets, res)