Skip to main content
`Ctrl`+`K`

# simulated_annealing_tsp

simulated_annealing_tsp(G, init_cycle, weight='weight', source=None, temp=100, move='1-1', max_iterations=10, N_inner=100, alpha=0.01, seed=None)

  Returns an approximate solution to the traveling salesman problem.

  This function uses simulated annealing to approximate the minimal cost cycle through the nodes. Starting from a suboptimal solution, simulated annealing perturbs that solution, occasionally accepting changes that make the solution worse to escape from a locally optimal solution. The chance of accepting such changes decreases over the iterations to encourage an optimal result. In summary, the function returns a cycle starting at `source` for which the total cost is minimized. It also returns the cost.

  The chance of accepting a proposed change is related to a parameter called the temperature (annealing has a physical analogue of steel hardening as it cools). As the temperature is reduced, the chance of moves that increase cost goes down.

  Parameters:
    G Graph

      `G` should be a complete weighted graph. The distance between all pairs of nodes should be included.

    init_cycle list of all nodes or “greedy”

      The initial solution (a cycle through all nodes returning to the start). This argument has no default to make you think about it. If “greedy”, use `greedy_tsp(G, weight)`. Other common starting cycles are `list(G) + [next(iter(G))]` or the final result of `simulated_annealing_tsp` when doing `threshold_accepting_tsp`.

    weight string, optional (default=”weight”)

      Edge data key corresponding to the edge weight. If any edge does not have this attribute the weight is set to 1.

    source node, optional (default: first node in list(G))

      Starting node. If None, defaults to `next(iter(G))`

    temp int, optional (default=100)

      The algorithm’s temperature parameter. It represents the initial value of temperature

    move“1-1” or “1-0” or function, optional (default=”1-1”)

      Indicator of what move to use when finding new trial solutions. Strings indicate two special built-in moves:

      - “1-1”: 1-1 exchange which transposes the position of two elements of the current solution. The function called is `swap_two_nodes()`. For example if we apply 1-1 exchange in the solution `A = [3, 2, 1, 4, 3]` we can get the following by the transposition of 1 and 4 elements: `A' = [3, 2, 4, 1, 3]`

      - “1-0”: 1-0 exchange which moves an node in the solution to a new position. The function called is `move_one_node()`. For example if we apply 1-0 exchange in the solution `A = [3, 2, 1, 4, 3]` we can transfer the fourth element to the second position: `A' = [3, 4, 2, 1, 3]`

      You may provide your own functions to enact a move from one solution to a neighbor solution. The function must take the solution as input along with a `seed` input to control random number generation (see the `seed` input here). Your function should maintain the solution as a cycle with equal first and last node and all others appearing once. Your function should return the new solution.

    max_iterations int, optional (default=10)

      Declared done when this number of consecutive iterations of the outer loop occurs without any change in the best cost solution.

    N_inner int, optional (default=100)

      The number of iterations of the inner loop.

    alpha float between (0, 1), optional (default=0.01)

      Percentage of temperature decrease in each iteration of outer loop

    seed integer, random_state, or None (default)

      Indicator of random number generation state. See Randomness.

  Returns:
    cycle list of nodes

      Returns the cycle (list of nodes) that a salesman can follow to minimize total weight of the trip.

  Raises:
    NetworkXError

      If `G` is not complete the algorithm raises an exception.

  Notes

  Simulated Annealing is a metaheuristic local search algorithm. The main characteristic of this algorithm is that it accepts even solutions which lead to the increase of the cost in order to escape from low quality local optimal solutions.

  This algorithm needs an initial solution. If not provided, it is constructed by a simple greedy algorithm. At every iteration, the algorithm selects thoughtfully a neighbor solution. Consider \(c(x)\) cost of current solution and \(c(x')\) cost of a neighbor solution. If \(c(x') - c(x) <= 0\) then the neighbor solution becomes the current solution for the next iteration. Otherwise, the algorithm accepts the neighbor solution with probability \(p = exp - ([c(x') - c(x)] / temp)\). Otherwise the current solution is retained.

  `temp` is a parameter of the algorithm and represents temperature.

  Time complexity: For \(N_i\) iterations of the inner loop and \(N_o\) iterations of the outer loop, this algorithm has running time \(O(N_i * N_o * |V|)\).

  For more information and how the algorithm is inspired see: http://en.wikipedia.org/wiki/Simulated_annealing

  Examples

      >>> from networkx.algorithms import approximation as approx
      >>> G = nx.DiGraph()
      >>> G.add_weighted_edges_from(
      ...     {
      ...         ("A", "B", 3),
      ...         ("A", "C", 17),
      ...         ("A", "D", 14),
      ...         ("B", "A", 3),
      ...         ("B", "C", 12),
      ...         ("B", "D", 16),
      ...         ("C", "A", 13),
      ...         ("C", "B", 12),
      ...         ("C", "D", 4),
      ...         ("D", "A", 14),
      ...         ("D", "B", 15),
      ...         ("D", "C", 2),
      ...     }
      ... )
      >>> cycle = approx.simulated_annealing_tsp(G, "greedy", source="D")
      >>> cost = sum(G[n][nbr]["weight"] for n, nbr in nx.utils.pairwise(cycle))
      >>> cycle
      ['D', 'C', 'B', 'A', 'D']
      >>> cost
      31
      >>> incycle = ["D", "B", "A", "C", "D"]
      >>> cycle = approx.simulated_annealing_tsp(G, incycle, source="D")
      >>> cost = sum(G[n][nbr]["weight"] for n, nbr in nx.utils.pairwise(cycle))
      >>> cycle
      ['D', 'C', 'B', 'A', 'D']
      >>> cost
      31