For supplied connected components (this connected components is assumed to be pre-filtered before hand)
     for every regular edge in it (which after pre-filtration would correspond to "supporting" edge only)
     computes an summands ("before" and "after") for its "assembly score" (which is defined as "before" - "after")
     where "before" is a score for a pair of irregular edges under observation and their support
        (every support edge corresponds to a pair of irregular edges), as if assembly DID NOT happened
     where "after" is a score for a pair of irregular edges under observation and their support
        (every support edge corresponds to a pair of irregular edges), as if assembly DID happened

def get_support_edge_scores(graph, subnet, target_multicolor, tree, verbose=False, verbose_destination=None):
    """
    For supplied connected components (this connected components is assumed to be pre-filtered before hand)
     for every regular edge in it (which after pre-filtration would correspond to "supporting" edge only)
     computes an summands ("before" and "after") for its "assembly score" (which is defined as "before" - "after")
     where "before" is a score for a pair of irregular edges under observation and their support
        (every support edge corresponds to a pair of irregular edges), as if assembly DID NOT happened
     where "after" is a score for a pair of irregular edges under observation and their support
        (every support edge corresponds to a pair of irregular edges), as if assembly DID happened
    """
    result = []
    # we iterate over all regular edges in pre-filtered connected component,
    # as all of them correspond to possible assembly points
    if verbose:
        print(">Getting support edge scores", file=verbose_destination)
    for edge in filter(lambda e: not e.is_irregular_edge, subnet.edges()):
        ex_data = {}
        if verbose:
            print("Possible assembly point", edge.vertex1.name, edge.vertex2.name,
                  [color.name for color in edge.multicolor.multicolors.elements()], file=verbose_destination)

        # basic references to most important parts of the observed possible assembly point
        v1, v2 = edge.vertex1, edge.vertex2
        sedge, iedge1, iedge2 = edge, None, None

        # since each vertex has at most 1 irregular edge incident to it, we can safely retrieve
        #   the first one for each vertex
        iedge1 = get_irregular_edge_by_vertex(subnet, v1)
        iedge2 = get_irregular_edge_by_vertex(subnet, v2)

        if verbose:
            print("irregular edge 1:", iedge1.vertex1.name, iedge1.vertex2.name,
                  [color.name for color in iedge1.multicolor.multicolors.elements()], file=verbose_destination)
            print("irregular edge 2:", iedge2.vertex1.name, iedge2.vertex2.name,
                  [color.name for color in iedge2.multicolor.multicolors.elements()], file=verbose_destination)

        # we need a full multicolor to determine which colors are missing (indels) on both vertices,
        #   that determine an assembly point
        full_multicolor = max(tree.consistent_multicolors, key=lambda multicolor: len(list(multicolor.multicolors.elements())))
        full_multicolor = Multicolor(*full_multicolor.colors)

        # we accumulated multicolors for both vertices,
        #   that are present in all edges combined, that are incident to them
        # we need to retrieve that information from the original whole graph, and not from the filtered one
        surrounding1 = Multicolor(*get_vertex_surrounding_multicolor(graph, v1).colors)
        surrounding2 = Multicolor(*get_vertex_surrounding_multicolor(graph, v2).colors)

        # we compute complementary multicolors for each vertex
        #   (multicolors, that are not present in edges, that are incident to respective vertices)
        c_1_multicolor = full_multicolor - surrounding1
        c_2_multicolor = full_multicolor - surrounding2

        # their intersection correspond to multicolors, that are not present at both vertices
        c = c_1_multicolor.intersect(c_2_multicolor)

        # and these colors correspond to colors, that are lacking uniquely at each vertex
        c_a = c_1_multicolor - c
        c_b = c_2_multicolor - c

        # a list of tree consistent multicolors, that are used to split any given multicolor into a smallest set of
        #   T-consistent multicolors
        guidance = tree.consistent_multicolors

        if verbose:
            print("\tfull multicolor:", [color.name for color in full_multicolor.multicolors.elements()],
                  file=verbose_destination)
            print("\ts1 multicolor:", [color.name for color in surrounding1.multicolors.elements()],
                  file=verbose_destination)
            print("\ts2 multicolor:", [color.name for color in surrounding2.multicolors.elements()],
                  file=verbose_destination)
            print("\tc_1 multicolor:", [color.name for color in c_1_multicolor.multicolors.elements()],
                  file=verbose_destination)
            print("\tc_2 multicolor:", [color.name for color in c_2_multicolor.multicolors.elements()],
                  file=verbose_destination)
            print("\tc multicolor:", [color.name for color in c.multicolors.elements()],
                  file=verbose_destination)
            print("\tc_a multicolor:", [color.name for color in c_a.multicolors.elements()],
                  file=verbose_destination)
            print("\tc_b multicolor:", [color.name for color in c_b.multicolors.elements()],
                  file=verbose_destination)

        # we compute summands for the "before" score for respective three edges
        # we add lacking colors to the edges multicolors during this computation

        ###################################################
        # we don't account for multiplicity in guidance, as in guidance we have each colors present exactly once,
        # as it is when no information about whole genome duplication is available,
        # but since there might be duplications in the multicolors on the edges, we would like to interpret
        # those multicolors as multicolors, where each present colors has multiplicity 1
        ###################################################
        ie1_score = len(Multicolor.split_colors(Multicolor(*iedge1.multicolor.colors) + c_a, guidance=guidance,
                                                account_for_color_multiplicity_in_guidance=False))
        ie2_score = len(Multicolor.split_colors(Multicolor(*iedge2.multicolor.colors) + c_b, guidance=guidance,
                                                account_for_color_multiplicity_in_guidance=False))
        s_multicolor = (Multicolor(*sedge.multicolor.colors))
        ex_data["s_support"] = sorted(sorted([color.name for color in target_multicolor.intersect(s_multicolor).colors]))
        if target_multicolor <= s_multicolor:
            s_multicolor -= target_multicolor
        se_score = len(Multicolor.split_colors(s_multicolor + c, guidance=guidance,
                                               account_for_color_multiplicity_in_guidance=False))
        before = ie1_score + ie2_score + se_score

        if verbose:
            print("score before: iedge1 score =", ie1_score,
                  "iedge2 score =", ie2_score,
                  "support edge score =", se_score,
                  "\"before\" score =", before,
                  file=verbose_destination)

        # we compute summands for the "after" score for respective three edges, as if the assembly was performed
        # we add lacking colors to the edges multicolors during this computation

        ###################################################
        # we don't account for multiplicity in guidance, as in guidance we have each colors present exactly once,
        # as it is when no information about whole genome duplication is available,
        # but since there might be duplications in the multicolors on the edges, we would like to interpret
        # those multicolors as multicolors, where each present colors has multiplicity 1
        ###################################################
        new_ie1_score = len(Multicolor.split_colors(Multicolor(*iedge1.multicolor.colors) - target_multicolor + c_a, guidance=guidance,
                                                    account_for_color_multiplicity_in_guidance=False))
        new_ie2_score = len(Multicolor.split_colors(Multicolor(*iedge2.multicolor.colors) - target_multicolor + c_b, guidance=guidance,
                                                    account_for_color_multiplicity_in_guidance=False))
        new_se_score = len(Multicolor.split_colors(s_multicolor + target_multicolor + c, guidance=guidance,
                                                   account_for_color_multiplicity_in_guidance=False))

        after = new_ie1_score + new_ie2_score + new_se_score

        if verbose:
            print("score after: iedge1 score =", new_ie1_score,
                  "iedge2 score =", new_ie2_score,
                  "support edge score =", new_se_score,
                  "\"after\" score =", after)

        result.append(((v1, v2), before, after, ex_data))

    # we return result as a list of tuples, where each tuple contains information about a pair of vertices
    #   (possible assembly point), and "before" and "after" score for this possible assembly point
    return result