def test_ascent_method_asymmetric_2():
    """
    Tests the ascent method using a truly asymmetric graph for which the
    solution has been brute forced
    """
    import networkx.algorithms.approximation.traveling_salesman as tsp

    np = pytest.importorskip("numpy")

    G_array = np.array([
        [0, 45, 39, 92, 29, 31],
        [72, 0, 4, 12, 21, 60],
        [81, 6, 0, 98, 70, 53],
        [49, 71, 59, 0, 98, 94],
        [74, 95, 24, 43, 0, 47],
        [56, 43, 3, 65, 22, 0],
    ])

    solution_edges = [(0, 5), (5, 4), (1, 3), (3, 0), (2, 1), (4, 2)]

    G = nx.from_numpy_array(G_array, create_using=nx.DiGraph)
    opt_hk, z_star = tsp.held_karp_ascent(G)

    # Check that the optimal weights are the same
    assert round(opt_hk, 2) == 144.00
    # Check that the z_stars match.
    solution = nx.DiGraph()
    solution.add_edges_from(solution_edges)
    assert nx.utils.edges_equal(z_star.edges, solution.edges)
def test_ascent_method_asymmetric():
    """
    Tests the ascent method using a truly asymmetric graph for which the
    solution has been brute forced
    """
    import networkx.algorithms.approximation.traveling_salesman as tsp

    np = pytest.importorskip("numpy")

    G_array = np.array([
        [0, 26, 63, 59, 69, 31, 41],
        [62, 0, 91, 53, 75, 87, 47],
        [47, 82, 0, 90, 15, 9, 18],
        [68, 19, 5, 0, 58, 34, 93],
        [11, 58, 53, 55, 0, 61, 79],
        [88, 75, 13, 76, 98, 0, 40],
        [41, 61, 55, 88, 46, 45, 0],
    ])

    solution_edges = [(0, 1), (1, 3), (3, 2), (2, 5), (5, 6), (4, 0), (6, 4)]

    G = nx.from_numpy_array(G_array, create_using=nx.DiGraph)
    opt_hk, z_star = tsp.held_karp_ascent(G)

    # Check that the optimal weights are the same
    assert round(opt_hk, 2) == 190.00
    # Check that the z_stars match.
    solution = nx.DiGraph()
    solution.add_edges_from(solution_edges)
    assert nx.utils.edges_equal(z_star.edges, solution.edges)
def test_held_karp_ascent():
    """
    Test the Held-Karp relaxation with the ascent method
    """
    import networkx.algorithms.approximation.traveling_salesman as tsp

    np = pytest.importorskip("numpy")

    # Adjacency matrix from page 1153 of the 1970 Held and Karp paper
    # which have been edited to be directional, but also symmetric
    G_array = np.array([
        [0, 97, 60, 73, 17, 52],
        [97, 0, 41, 52, 90, 30],
        [60, 41, 0, 21, 35, 41],
        [73, 52, 21, 0, 95, 46],
        [17, 90, 35, 95, 0, 81],
        [52, 30, 41, 46, 81, 0],
    ])

    solution_edges = [(1, 3), (2, 4), (3, 2), (4, 0), (5, 1), (0, 5)]

    G = nx.from_numpy_array(G_array, create_using=nx.DiGraph)
    opt_hk, z_star = tsp.held_karp_ascent(G)

    # Check that the optimal weights are the same
    assert round(opt_hk, 2) == 207.00
    # Check that the z_stars are the same
    solution = nx.DiGraph()
    solution.add_edges_from(solution_edges)
    assert nx.utils.edges_equal(z_star.edges, solution.edges)
def test_ascent_fractional_solution():
    """
    Test the ascent method using a modified version of Figure 2 on page 1140
    in 'The Traveling Salesman Problem and Minimum Spanning Trees' by Held and
    Karp
    """
    import networkx.algorithms.approximation.traveling_salesman as tsp

    np = pytest.importorskip("numpy")
    pytest.importorskip("scipy")

    # This version of Figure 2 has all of the edge weights multiplied by 100
    # and is a complete directed graph with infinite edge weights for the
    # edges not listed in the original graph
    G_array = np.array([
        [0, 100, 100, 100000, 100000, 1],
        [100, 0, 100, 100000, 1, 100000],
        [100, 100, 0, 1, 100000, 100000],
        [100000, 100000, 1, 0, 100, 100],
        [100000, 1, 100000, 100, 0, 100],
        [1, 100000, 100000, 100, 100, 0],
    ])

    solution_z_star = {
        (0, 1): 5 / 12,
        (0, 2): 5 / 12,
        (0, 5): 5 / 6,
        (1, 0): 5 / 12,
        (1, 2): 1 / 3,
        (1, 4): 5 / 6,
        (2, 0): 5 / 12,
        (2, 1): 1 / 3,
        (2, 3): 5 / 6,
        (3, 2): 5 / 6,
        (3, 4): 1 / 3,
        (3, 5): 1 / 2,
        (4, 1): 5 / 6,
        (4, 3): 1 / 3,
        (4, 5): 1 / 2,
        (5, 0): 5 / 6,
        (5, 3): 1 / 2,
        (5, 4): 1 / 2,
    }

    G = nx.from_numpy_array(G_array, create_using=nx.DiGraph)
    opt_hk, z_star = tsp.held_karp_ascent(G)

    # Check that the optimal weights are the same
    assert round(opt_hk, 2) == 303.00
    # Check that the z_stars are the same
    assert {key: round(z_star[key], 4)
            for key in z_star} == {
                key: round(solution_z_star[key], 4)
                for key in solution_z_star
            }
def test_held_karp_ascent_fractional_asymmetric():
    """
    Tests the ascent method using a truly asymmetric graph with a fractional
    solution for which the solution has been brute forced
    """
    import networkx.algorithms.approximation.traveling_salesman as tsp

    np = pytest.importorskip("numpy")
    pytest.importorskip("scipy")

    G_array = np.array([
        [0, 100, 150, 100000, 100000, 1],
        [150, 0, 100, 100000, 1, 100000],
        [100, 150, 0, 1, 100000, 100000],
        [100000, 100000, 1, 0, 150, 100],
        [100000, 2, 100000, 100, 0, 150],
        [2, 100000, 100000, 150, 100, 0],
    ])

    solution_z_star = {
        (0, 1): 5 / 12,
        (0, 2): 5 / 12,
        (0, 5): 5 / 6,
        (1, 0): 5 / 12,
        (1, 2): 5 / 12,
        (1, 4): 5 / 6,
        (2, 0): 5 / 12,
        (2, 1): 5 / 12,
        (2, 3): 5 / 6,
        (3, 2): 5 / 6,
        (3, 4): 5 / 12,
        (3, 5): 5 / 12,
        (4, 1): 5 / 6,
        (4, 3): 5 / 12,
        (4, 5): 5 / 12,
        (5, 0): 5 / 6,
        (5, 3): 5 / 12,
        (5, 4): 5 / 12,
    }

    G = nx.from_numpy_array(G_array, create_using=nx.DiGraph)
    opt_hk, z_star = tsp.held_karp_ascent(G)

    # Check that the optimal weights are the same
    assert round(opt_hk, 2) == 304.00
    # Check that the z_stars are the same
    assert {key: round(z_star[key], 4)
            for key in z_star} == {
                key: round(solution_z_star[key], 4)
                for key in solution_z_star
            }
def test_held_karp_ascent_asymmetric_3():
    """
    Tests the ascent method using a truly asymmetric graph with a fractional
    solution for which the solution has been brute forced.

    In this graph their are two different optimal, integral solutions (which
    are also the overall atsp solutions) to the Held Karp relaxation. However,
    this particular graph has two different tours of optimal value and the
    possible solutions in the held_karp_ascent function are not stored in an
    ordered data structure.
    """
    import networkx.algorithms.approximation.traveling_salesman as tsp

    np = pytest.importorskip("numpy")
    pytest.importorskip("scipy")

    G_array = np.array([
        [0, 1, 5, 2, 7, 4],
        [7, 0, 7, 7, 1, 4],
        [4, 7, 0, 9, 2, 1],
        [7, 2, 7, 0, 4, 4],
        [5, 5, 4, 4, 0, 3],
        [3, 9, 1, 3, 4, 0],
    ])

    solution1_edges = [(0, 3), (1, 4), (2, 5), (3, 1), (4, 2), (5, 0)]

    solution2_edges = [(0, 3), (3, 1), (1, 4), (4, 5), (2, 0), (5, 2)]

    G = nx.from_numpy_array(G_array, create_using=nx.DiGraph)
    opt_hk, z_star = tsp.held_karp_ascent(G)

    assert round(opt_hk, 2) == 13.00
    # Check that the z_stars are the same
    solution1 = nx.DiGraph()
    solution1.add_edges_from(solution1_edges)
    solution2 = nx.DiGraph()
    solution2.add_edges_from(solution2_edges)
    assert nx.utils.edges_equal(z_star.edges,
                                solution1.edges) or nx.utils.edges_equal(
                                    z_star.edges, solution2.edges)