def global_alignment_v2(v,
                        w,
                        scoring_matrix=None,
                        sigma=None,
                        matches=None,
                        mismatches=None):
    # first, build the graph string
    # print("start")
    adj_list, weights, sink = two_strings_to_weighted_graph(
        v, w, scoring_matrix, sigma, matches, mismatches)
    # print("adj_list")
    cost, path = longest_path_in_dag((0, 0), sink, adj_list, weights)
    # print(path)
    for index, n in enumerate(path):
        i = n[0]
        j = n[1]
        if index < len(path) - 1:
            next = path[index + 1]
            k = next[0]
            l = next[1]
            if k == (i + 1) and l == j:  # if the next is horizontal
                v = v[:i] + "-" + v[i:]
            elif k == i and l == (j + 1):  # if the next is vertical
                w = w[:j] + "-" + w[j:]
            # elif k == (i + 1) and l == (j + 1): # if the next is diagonal

    return cost, v, w
def alignment_with_affine_gap_penalty_v2(v,
                                         w,
                                         scoring_matrix=None,
                                         sigma=None,
                                         matches=None,
                                         mismatches=None,
                                         epsilon=None):
    adj_list, weights, sink = two_strings_to_weighted_graph(v,
                                                            w,
                                                            scoring_matrix,
                                                            sigma,
                                                            matches,
                                                            mismatches,
                                                            epsilon=epsilon)
    # print("adj_list")
    cost, path = longest_path_in_dag((0, 0), sink, adj_list, weights)
    # print(path)
    for index, n in enumerate(path):
        i = n[0]
        j = n[1]
        if index < len(path) - 1:
            next = path[index + 1]
            k = next[0]
            l = next[1]
            if k > i and l == j:  # if the next is horizontal
                v = v[:i] + "-" * (k - i) + v[i:]

            elif k == i and l > j:  # if the next is vertical
                w = w[:j] + "-" * (l - j) + w[j:]

            # elif k == (i + 1) and l == (j + 1): # if the next is diagonal

    return cost, v, w
def overlap_alignment_v2(v,
                         w,
                         scoring_matrix=None,
                         sigma=None,
                         matches=None,
                         mismatches=None):
    # print("start")
    adj_list, weights, sink = two_strings_to_weighted_graph(v,
                                                            w,
                                                            scoring_matrix,
                                                            sigma,
                                                            matches,
                                                            mismatches,
                                                            is_overlap=True)
    # print(adj_list)
    # print(weights)
    cost, path = longest_path_in_dag((0, 0),
                                     sink,
                                     adj_list,
                                     weights,
                                     is_overlap=True)
    print(path)
    print(v, w)
    sink = path[-1]

    start = False
    cut = 0

    for index, n in enumerate(path):
        i = n[0]
        j = n[1]
        if index < len(path) - 1:
            next = path[index + 1]
            k = next[0]
            l = next[1]
            if k == (i + 1) and l == j:  # if the next is horizontal
                v = v[:j] + "-" + v[j:]
                start = True
            elif k == i and l == (j + 1):  # if the next is vertical
                if not start:
                    cut += 1
                else:
                    w = w[:i] + "-" + w[i:]
                    start = True
            else:
                start = True
    # print(start)
    v = v[cut:]
    # w = w[:sink[0]]
    w = w[:len(v)]
    return cost, v, w
def fitting_alignment_v2(v,
                         w,
                         scoring_matrix=None,
                         sigma=None,
                         matches=None,
                         mismatches=None):
    """
    correct score and correct right trim .. I need to trim the left side and fix the - added
    """
    # print("start")
    adj_list, weights, sink = two_strings_to_weighted_graph(v,
                                                            w,
                                                            scoring_matrix,
                                                            sigma,
                                                            matches,
                                                            mismatches,
                                                            is_fitted=True)
    # print(adj_list)
    # print(weights)
    cost, path = longest_path_in_dag((0, 0),
                                     sink,
                                     adj_list,
                                     weights,
                                     is_fitting=True)
    start = False
    cut = 0
    for index, n in enumerate(path):
        i = n[0]
        j = n[1]
        if index < len(path) - 1:
            next = path[index + 1]
            k = next[0]
            l = next[1]
            if k == (i + 1) and l == j:  # if the next is horizontal
                v = v[:j] + "-" + v[j:]
                start = True
            elif k == i and l == (j + 1):  # if the next is vertical
                if not start:
                    # print("cut", v, v[1:])
                    cut += 1
                else:
                    w = w[:i] + "-" + w[i:]
                    start = True
            else:
                start = True

    v = v[cut:]
    v = v[:len(w)]

    return cost, v, w
def longest_common_sequence_v2(v, w):
    # first, build the graph string
    # print("start")
    adj_list, weights, sink = two_strings_to_weighted_graph(v, w)
    # print("got adj string")
    path = longest_path_in_dag((0, 0), sink, adj_list, weights)[1]
    # print("got path")
    sequence = ""
    for index, n in enumerate(path):
        i = n[0]
        j = n[1]
        if index < len(path) - 1:  # if the next node is diagonal
            next = path[index + 1]
            k = next[0]
            l = next[1]
            if k == (i + 1) and l == (j + 1) and weights[(i, j), (k, l)] == 1:
                sequence += v[j]
    return sequence
def local_alignment_v2(v,
                       w,
                       scoring_matrix=None,
                       sigma=None,
                       matches=None,
                       mismatches=None):
    # print("start")
    adj_list, weights, sink = two_strings_to_weighted_graph(v,
                                                            w,
                                                            scoring_matrix,
                                                            sigma,
                                                            matches,
                                                            mismatches,
                                                            is_local=True)
    # print(adj_list)
    # print(weights)
    cost, path = longest_path_in_dag((0, 0),
                                     sink,
                                     adj_list,
                                     weights,
                                     is_local=True)
    # print(path)
    sink = path[-1]

    v = v[:sink[1]]
    w = w[:sink[0]]
    start = None
    for index, n in enumerate(path):
        i = n[0]
        j = n[1]
        if index < len(path) - 1:
            next = path[index + 1]
            k = next[0]
            l = next[1]
            if weights[((i, j), (k, l))] != 0:
                if k == (i + 1) and l == j:  # if the next is horizontal
                    v = v[:i] + "-" + v[i:]
                elif k == i and l == (j + 1):  # if the next is vertical
                    w = w[:j] + "-" + w[j:]
                if not start:
                    start = (i, j)
    v = v[start[1]:]
    w = w[start[0]:]
    return cost, v, w
def edit_distance_v2(v, w):
    # first, build the graph string
    # print("start")
    adj_list, weights, sink = two_strings_to_weighted_graph(v, w)
    # print("got adj string")
    path = longest_path_in_dag((0, 0), sink, adj_list, weights)[1]
    # print("got path")
    count = 0
    for index, n in enumerate(path):
        i = n[0]
        j = n[1]
        if index < len(path) - 1:  # if the next node is diagonal
            next = path[index + 1]
            k = next[0]
            l = next[1]
            if k == (i + 1) and l == j:  # if the next is horizontal
                count += 1
            elif k == i and l == (j + 1):  # if the next is vertical
                count += 1
            elif k == (i + 1) and l == (j + 1) and weights[(i, j),
                                                           (k, l)] != 1:
                count += 1
    return count