def METHOD_NAME(self):
    # Convert delayed statements to pyro.factor()
    reduced_vars = []
    log_prob_terms = []
    plates = frozenset()
    for name, site in self.trace.nodes.items():
        if not site["is_observed"]:
            reduced_vars.append(name)
        log_prob_terms.append(site["fn"](value=site["value"]))
        plates |= frozenset(
            f.name for f in site["cond_indep_stack"] if f.vectorized
        )
    name = reduced_vars[0]
    reduced_vars = frozenset(reduced_vars)
    assert log_prob_terms, "nothing to collapse"
    self.trace.nodes.clear()
    reduced_plates = plates - frozenset(self.preserved_plates.values())
    if reduced_plates:
        log_prob = funsor.sum_product.sum_product(
            funsor.ops.logaddexp,
            funsor.ops.add,
            log_prob_terms,
            eliminate=reduced_vars | reduced_plates,
            plates=plates,
        )
        log_joint = NotImplemented
    else:
        log_joint = reduce(funsor.ops.add, log_prob_terms)
        log_prob = log_joint.reduce(funsor.ops.logaddexp, reduced_vars)
    return name, log_prob, log_joint, reduced_vars