<SYSTEM_TASK:>
Solve the following problem using Python, implementing the functions described below, one line at a time
<END_TASK>
<USER_TASK:>
Description:
 def predict_compound_pairs(reaction, compound_formula, pair_weights={}, weight_func=element_weight):
 """Predict compound pairs for a single reaction. Performs greedy matching on reaction compounds using a scoring function that uses generalized Jaccard similarity corrected by the weights in the given dictionary. Returns a tuple of a transfer dictionary and a dictionary of unbalanced compounds. The dictionary of unbalanced compounds is empty only if the reaction is balanced. Args: reaction: :class:`psamm.reaction.Reaction`. compound_formula: Dictionary mapping compound IDs to :class:`psamm.formula.Formula`. Formulas must be flattened. pair_weights: Dictionary mapping pairs of compound IDs to correction values. This value is multiplied by the calculated Jaccard similarity. If a pair is not in the dictionary, the value 1 is used. Pairs are looked up in the weights dictionary as a tuple of compound names (``c1``, ``c2``) where ``c1`` is the left-hand side and ``c2`` is the right-hand side. weight_func: Weight function for caclulating the generalized Jaccard similarity. This function will be given an :class:`psamm.formula.Atom` or :class:`psamm.formula.Radical` and should return a corresponding weight. """

    def score_func(inst1, inst2):
        score = _jaccard_similarity(
            inst1.formula, inst2.formula, weight_func)
        if score is None:
            return None
        pair = inst1.compound.name, inst2.compound.name
        pair_weight = pair_weights.get(pair, 1.0)
        return pair_weight * score

    return _match_greedily(reaction, compound_formula, score_func)