def _match_greedily(reaction, compound_formula, score_func):
uninstantiated_left, uninstantiated_right = _reaction_to_dicts(reaction)<EOL>def compound_instances(uninstantiated):<EOL><INDENT>instances = []<EOL>for compound, value in iteritems(uninstantiated):<EOL><INDENT>if value > <NUM_LIT:0>:<EOL><INDENT>f = compound_formula[compound.name]<EOL>instances.append(_CompoundInstance(compound, value, f))<EOL><DEDENT><DEDENT>for inst in instances:<EOL><INDENT>uninstantiated[inst.compound] -= <NUM_LIT:1><EOL><DEDENT>return instances<EOL><DEDENT>def instantiate(uninstantiated, compound):<EOL><INDENT>n = uninstantiated[compound]<EOL>if n > <NUM_LIT:0>:<EOL><INDENT>f = compound_formula[compound.name]<EOL>inst = _CompoundInstance(compound, n, f)<EOL>uninstantiated[compound] -= <NUM_LIT:1><EOL>return inst<EOL><DEDENT>return None<EOL><DEDENT>left = compound_instances(uninstantiated_left)<EOL>right = compound_instances(uninstantiated_right)<EOL>instances = left + right<EOL>pairs = {}<EOL>for inst1, inst2 in product(left, right):<EOL><INDENT>result = score_func(inst1, inst2)<EOL>if result is not None:<EOL><INDENT>pairs[inst1, inst2] = result<EOL><DEDENT><DEDENT>def inst_pair_sort_key(entry):<EOL><INDENT>"""<STR_LIT>"""<EOL>(inst1, inst2), score = entry<EOL>c1, c2 = inst1.compound, inst2.compound<EOL>same_compound = c1.name == c2.name and c1.compartment != c2.compartment<EOL>return same_compound, score, c1.name, c2.name<EOL><DEDENT>transfer = {}<EOL>while len(pairs) > <NUM_LIT:0>:<EOL><INDENT>(inst1, inst2), _ = max(iteritems(pairs), key=inst_pair_sort_key)<EOL>common = inst1.formula & inst2.formula<EOL>key = (inst1.compound, inst1.index), (inst2.compound, inst2.index)<EOL>if key not in transfer:<EOL><INDENT>transfer[key] = Formula()<EOL><DEDENT>transfer[key] |= common<EOL>for inst in (inst1, inst2):<EOL><INDENT>inst.formula -= common<EOL><DEDENT>to_insert = set()<EOL>inst = instantiate(uninstantiated_left, inst1.compound)<EOL>if inst is not None:<EOL><INDENT>left.append(inst)<EOL>instances.append(inst)<EOL>to_insert.add(inst)<EOL><DEDENT>inst = instantiate(uninstantiated_right, inst2.compound)<EOL>if inst is not None:<EOL><INDENT>right.append(inst)<EOL>instances.append(inst)<EOL>to_insert.add(inst)<EOL><DEDENT>to_update = {inst1, inst2}<EOL>to_delete = set()<EOL>for inst1, inst2 in pairs:<EOL><INDENT>if inst1 in to_update or inst2 in to_update:<EOL><INDENT>if len(inst1.formula) > <NUM_LIT:0> and len(inst2.formula) > <NUM_LIT:0>:<EOL><INDENT>result = score_func(inst1, inst2)<EOL>if result is None:<EOL><INDENT>to_delete.add((inst1, inst2))<EOL><DEDENT>else:<EOL><INDENT>pairs[inst1, inst2] = result<EOL><DEDENT><DEDENT>else:<EOL><INDENT>to_delete.add((inst1, inst2))<EOL><DEDENT><DEDENT><DEDENT>for pair in to_delete:<EOL><INDENT>del pairs[pair]<EOL><DEDENT>for inst1, inst2 in product(left, right):<EOL><INDENT>if inst1 in to_insert or inst2 in to_insert:<EOL><INDENT>result = score_func(inst1, inst2)<EOL>if result is not None:<EOL><INDENT>pairs[inst1, inst2] = result<EOL><DEDENT><DEDENT><DEDENT><DEDENT>balance = {}<EOL>for inst in instances:<EOL><INDENT>if len(inst.formula) > <NUM_LIT:0>:<EOL><INDENT>key = inst.compound, inst.index<EOL>balance[key] = inst.formula<EOL><DEDENT><DEDENT>return transfer, balance<EOL>
Match compounds greedily based on score function.

    Args:
        reaction: Reaction equation :class:`psamm.reaction.Reaction`.
        compound_formula: Dictionary mapping compound IDs to
            :class:`psamm.formula.Formula`. Formulas must be flattened.
        score_func: Function that takes two :class:`_CompoundInstance` and
            returns the score.