def METHOD_NAME(p_x1z: Distr, p_y1z: Distr, p_z: Distr, pt_z: Distr, qt_z1x: Distr, obs_xy: edic, n_mc: int=0, wlogpi: float=1., repar: bool=True) -> tc.Tensor:
    def logpt_z_nograd(dc):
        with tc.no_grad(): return pt_z.logp(dc,dc)
    vwei_p_y1z_logp = lambda dc: p_z.logp(dc,dc) - logpt_z_nograd(dc) + p_y1z.logp(dc,dc) # z, y:
    if n_mc == 0:
        r_y1x_logpval = qt_z1x.expect(vwei_p_y1z_logp, obs_xy, 0, repar) #, reducefn=tc.logsumexp)
        if hasattr(qt_z1x, "entropy"):
            expc_val = qt_z1x.expect(lambda dc: logpt_z_nograd(dc) + p_x1z.logp(dc,dc),
                    obs_xy, 0, repar) + qt_z1x.entropy(obs_xy)
        else:
            expc_val = qt_z1x.expect(lambda dc: logpt_z_nograd(dc) + p_x1z.logp(dc,dc) - qt_z1x.logp(dc,dc), obs_xy, 0, repar)
        return wlogpi * r_y1x_logpval + expc_val
    else:
        r_y1x_pval = qt_z1x.expect(lambda dc: vwei_p_y1z_logp(dc).exp(), obs_xy, n_mc, repar)
        expc_val = qt_z1x.expect( lambda dc: # z, x, y:
                vwei_p_y1z_logp(dc).exp() * (logpt_z_nograd(dc) + p_x1z.logp(dc,dc) - qt_z1x.logp(dc,dc)),
            obs_xy, n_mc, repar)
        return wlogpi * r_y1x_pval.log() + expc_val / r_y1x_pval
        # r_y1x_logpval = qt_z1x.expect(vwei_p_y1z_logp, obs_xy, n_mc, repar,
        #         reducefn=tc.logsumexp) - math.log(n_mc) # z, y:
        # expc_logval = qt_z1x.expect(lambda dc: # z, x, y:
        #         vwei_p_y1z_logp(dc) + (logpt_z_nograd(dc) + p_x1z.logp(dc,dc) - qt_z1x.logp(dc,dc)).log(),
        #     obs_xy, n_mc, repar, reducefn=tc.logsumexp) - math.log(n_mc)
        # return wlogpi * r_y1x_logpval + (expc_logval - r_y1x_logpval).exp()