2-opt algorithm for the Traveling Salesman and/or SRO The Next CEO of Stack OverflowExtracting an adjaceny matrix containing haversine distance from points on mapSolving the travelling salesman problem using a genetic algorithmCalculating Travelling Salesman - memory consumption and speed2-opt algorithm for traveling salesmanTravelling salesman using brute-force and heuristicsTraveling Salesman Planet EditionComparing a recursive and iterative traveling salesman problem algorithms in JavaTraveling Salesman Problem genetic algorithmTraveling Salesman SolutionGenetic algorithm for Traveling SalesmanExtracting an adjaceny matrix containing haversine distance from points on map

The Ultimate Number Sequence Puzzle

Is it okay to majorly distort historical facts while writing a fiction story?

What are the unusually-enlarged wing sections on this P-38 Lightning?

Is there a way to save my career from absolute disaster?

How can I make proper oatmeal cookies?

Computationally populating tables with probability data

In the "Harry Potter and the Order of the Phoenix" video game, what potion is used to sabotage Umbridge's speakers?

Yu-Gi-Oh cards in Python 3

Ising model simulation

Scary film where a woman has vaginal teeth

Does Germany produce more waste than the US?

Spaces in which all closed sets are regular closed

Help understanding this unsettling image of Titan, Epimetheus, and Saturn's rings?

Calculate the Mean mean of two numbers

Small nick on power cord from an electric alarm clock, and copper wiring exposed but intact

Do I need to write [sic] when including a quotation with a number less than 10 that isn't written out?

Won the lottery - how do I keep the money?

IC has pull-down resistors on SMBus lines?

Why do we say 'Un seul M' and not 'Une seule M' even though M is a "consonne"

From jafe to El-Guest

What difference does it make using sed with/without whitespaces?

What CSS properties can the br tag have?

What happened in Rome, when the western empire "fell"?

Is it ever safe to open a suspicious HTML file (e.g. email attachment)?



2-opt algorithm for the Traveling Salesman and/or SRO



The Next CEO of Stack OverflowExtracting an adjaceny matrix containing haversine distance from points on mapSolving the travelling salesman problem using a genetic algorithmCalculating Travelling Salesman - memory consumption and speed2-opt algorithm for traveling salesmanTravelling salesman using brute-force and heuristicsTraveling Salesman Planet EditionComparing a recursive and iterative traveling salesman problem algorithms in JavaTraveling Salesman Problem genetic algorithmTraveling Salesman SolutionGenetic algorithm for Traveling SalesmanExtracting an adjaceny matrix containing haversine distance from points on map










5












$begingroup$


In this question I present a method to solve the Traveling Salesman Problem and/or the Single Route Optimization problem.



I am extracting 100 lat/long points from Google Maps and placing these into a text file. The program should be able to read in the text file, calculate the haversine distance between each point, and store in an adjacency matrix. The adjacency matrix will eventually be fed to a 2-opt algorithm.



Extracting an adjaceny matrix containing haversine distance from points on map has already been dealt with. This question tackles the 2-opt algorithm.



The 2-opt function is called from main as follows. route is a randomly generated list of 100 numbers, which is the path the 2-opt should follow.



def main():
best = two_opt(connect_mat, route) #connectivity/adjacency matrix


And here is the 2-opt function and a cost function that it utilizes. Can they be optimized in any way?



def cost(cost_mat, route):
return cost_mat[np.roll(route, 1), route].sum() # shifts route array by 1 in order to look at pairs of cities


def two_opt(cost_mat, route):
best = route
improved = True
while improved:
improved = False
for i in range(1, len(route) - 2):
for j in range(i + 1, len(route)):
if j - i == 1: continue # changes nothing, skip then
new_route = route[:] # Creates a copy of route
new_route[i:j] = route[j - 1:i - 1:-1] # this is the 2-optSwap since j >= i we use -1
if cost(cost_mat, new_route) < cost(cost_mat, best):
best = new_route
improved = True
route = best
return best


Sample Input:



35.905333, 14.471970
35.896389, 14.477780
35.901281, 14.518173
35.860491, 14.572245
35.807607, 14.535320
35.832267, 14.455894
35.882414, 14.373217
35.983794, 14.336096
35.974463, 14.351006
35.930951, 14.401137
.
.
.


Sample Output



enter image description here



I would like to be able to scale up the points being read to 5000. With the code above it would be painfully slow.



Timer Test:



Starting a timer at the beginning of the function and ending before the return statement gives an average of 1.5s per 100 points. If simple proportion can be used to test algorithm scaling performance, then:



  • 100 points: 1.5s

  • 1000 points: 15s

  • 5000 points: 75s

Please correct me if my above assumption is wrong.



I was wondering whether it could be improved in any way. More information can be added if requested.




EDIT:



I noticed that I was using an extra variable best. This can be removed as such:



def two_opt(connect_mat, route):
improved = True
while improved:
improved = False
for i in range(1, len(route) - 2):
for j in range(i + 1, len(route)):
if j - i == 1:
continue # changes nothing, skip then
new_route = route[:] # Creates a copy of route
new_route[i:j] = route[j - 1:i - 1:-1] # this is the 2-optSwap since j >= i we use -1
if cost(connect_mat, new_route) < cost(connect_mat, route):
route = new_route # change current route to best
improved = True

return route


I doubt how much (if any) this increases efficiency, however it does sacrifice readability to some extent.










share|improve this question











$endgroup$
















    5












    $begingroup$


    In this question I present a method to solve the Traveling Salesman Problem and/or the Single Route Optimization problem.



    I am extracting 100 lat/long points from Google Maps and placing these into a text file. The program should be able to read in the text file, calculate the haversine distance between each point, and store in an adjacency matrix. The adjacency matrix will eventually be fed to a 2-opt algorithm.



    Extracting an adjaceny matrix containing haversine distance from points on map has already been dealt with. This question tackles the 2-opt algorithm.



    The 2-opt function is called from main as follows. route is a randomly generated list of 100 numbers, which is the path the 2-opt should follow.



    def main():
    best = two_opt(connect_mat, route) #connectivity/adjacency matrix


    And here is the 2-opt function and a cost function that it utilizes. Can they be optimized in any way?



    def cost(cost_mat, route):
    return cost_mat[np.roll(route, 1), route].sum() # shifts route array by 1 in order to look at pairs of cities


    def two_opt(cost_mat, route):
    best = route
    improved = True
    while improved:
    improved = False
    for i in range(1, len(route) - 2):
    for j in range(i + 1, len(route)):
    if j - i == 1: continue # changes nothing, skip then
    new_route = route[:] # Creates a copy of route
    new_route[i:j] = route[j - 1:i - 1:-1] # this is the 2-optSwap since j >= i we use -1
    if cost(cost_mat, new_route) < cost(cost_mat, best):
    best = new_route
    improved = True
    route = best
    return best


    Sample Input:



    35.905333, 14.471970
    35.896389, 14.477780
    35.901281, 14.518173
    35.860491, 14.572245
    35.807607, 14.535320
    35.832267, 14.455894
    35.882414, 14.373217
    35.983794, 14.336096
    35.974463, 14.351006
    35.930951, 14.401137
    .
    .
    .


    Sample Output



    enter image description here



    I would like to be able to scale up the points being read to 5000. With the code above it would be painfully slow.



    Timer Test:



    Starting a timer at the beginning of the function and ending before the return statement gives an average of 1.5s per 100 points. If simple proportion can be used to test algorithm scaling performance, then:



    • 100 points: 1.5s

    • 1000 points: 15s

    • 5000 points: 75s

    Please correct me if my above assumption is wrong.



    I was wondering whether it could be improved in any way. More information can be added if requested.




    EDIT:



    I noticed that I was using an extra variable best. This can be removed as such:



    def two_opt(connect_mat, route):
    improved = True
    while improved:
    improved = False
    for i in range(1, len(route) - 2):
    for j in range(i + 1, len(route)):
    if j - i == 1:
    continue # changes nothing, skip then
    new_route = route[:] # Creates a copy of route
    new_route[i:j] = route[j - 1:i - 1:-1] # this is the 2-optSwap since j >= i we use -1
    if cost(connect_mat, new_route) < cost(connect_mat, route):
    route = new_route # change current route to best
    improved = True

    return route


    I doubt how much (if any) this increases efficiency, however it does sacrifice readability to some extent.










    share|improve this question











    $endgroup$














      5












      5








      5


      1



      $begingroup$


      In this question I present a method to solve the Traveling Salesman Problem and/or the Single Route Optimization problem.



      I am extracting 100 lat/long points from Google Maps and placing these into a text file. The program should be able to read in the text file, calculate the haversine distance between each point, and store in an adjacency matrix. The adjacency matrix will eventually be fed to a 2-opt algorithm.



      Extracting an adjaceny matrix containing haversine distance from points on map has already been dealt with. This question tackles the 2-opt algorithm.



      The 2-opt function is called from main as follows. route is a randomly generated list of 100 numbers, which is the path the 2-opt should follow.



      def main():
      best = two_opt(connect_mat, route) #connectivity/adjacency matrix


      And here is the 2-opt function and a cost function that it utilizes. Can they be optimized in any way?



      def cost(cost_mat, route):
      return cost_mat[np.roll(route, 1), route].sum() # shifts route array by 1 in order to look at pairs of cities


      def two_opt(cost_mat, route):
      best = route
      improved = True
      while improved:
      improved = False
      for i in range(1, len(route) - 2):
      for j in range(i + 1, len(route)):
      if j - i == 1: continue # changes nothing, skip then
      new_route = route[:] # Creates a copy of route
      new_route[i:j] = route[j - 1:i - 1:-1] # this is the 2-optSwap since j >= i we use -1
      if cost(cost_mat, new_route) < cost(cost_mat, best):
      best = new_route
      improved = True
      route = best
      return best


      Sample Input:



      35.905333, 14.471970
      35.896389, 14.477780
      35.901281, 14.518173
      35.860491, 14.572245
      35.807607, 14.535320
      35.832267, 14.455894
      35.882414, 14.373217
      35.983794, 14.336096
      35.974463, 14.351006
      35.930951, 14.401137
      .
      .
      .


      Sample Output



      enter image description here



      I would like to be able to scale up the points being read to 5000. With the code above it would be painfully slow.



      Timer Test:



      Starting a timer at the beginning of the function and ending before the return statement gives an average of 1.5s per 100 points. If simple proportion can be used to test algorithm scaling performance, then:



      • 100 points: 1.5s

      • 1000 points: 15s

      • 5000 points: 75s

      Please correct me if my above assumption is wrong.



      I was wondering whether it could be improved in any way. More information can be added if requested.




      EDIT:



      I noticed that I was using an extra variable best. This can be removed as such:



      def two_opt(connect_mat, route):
      improved = True
      while improved:
      improved = False
      for i in range(1, len(route) - 2):
      for j in range(i + 1, len(route)):
      if j - i == 1:
      continue # changes nothing, skip then
      new_route = route[:] # Creates a copy of route
      new_route[i:j] = route[j - 1:i - 1:-1] # this is the 2-optSwap since j >= i we use -1
      if cost(connect_mat, new_route) < cost(connect_mat, route):
      route = new_route # change current route to best
      improved = True

      return route


      I doubt how much (if any) this increases efficiency, however it does sacrifice readability to some extent.










      share|improve this question











      $endgroup$




      In this question I present a method to solve the Traveling Salesman Problem and/or the Single Route Optimization problem.



      I am extracting 100 lat/long points from Google Maps and placing these into a text file. The program should be able to read in the text file, calculate the haversine distance between each point, and store in an adjacency matrix. The adjacency matrix will eventually be fed to a 2-opt algorithm.



      Extracting an adjaceny matrix containing haversine distance from points on map has already been dealt with. This question tackles the 2-opt algorithm.



      The 2-opt function is called from main as follows. route is a randomly generated list of 100 numbers, which is the path the 2-opt should follow.



      def main():
      best = two_opt(connect_mat, route) #connectivity/adjacency matrix


      And here is the 2-opt function and a cost function that it utilizes. Can they be optimized in any way?



      def cost(cost_mat, route):
      return cost_mat[np.roll(route, 1), route].sum() # shifts route array by 1 in order to look at pairs of cities


      def two_opt(cost_mat, route):
      best = route
      improved = True
      while improved:
      improved = False
      for i in range(1, len(route) - 2):
      for j in range(i + 1, len(route)):
      if j - i == 1: continue # changes nothing, skip then
      new_route = route[:] # Creates a copy of route
      new_route[i:j] = route[j - 1:i - 1:-1] # this is the 2-optSwap since j >= i we use -1
      if cost(cost_mat, new_route) < cost(cost_mat, best):
      best = new_route
      improved = True
      route = best
      return best


      Sample Input:



      35.905333, 14.471970
      35.896389, 14.477780
      35.901281, 14.518173
      35.860491, 14.572245
      35.807607, 14.535320
      35.832267, 14.455894
      35.882414, 14.373217
      35.983794, 14.336096
      35.974463, 14.351006
      35.930951, 14.401137
      .
      .
      .


      Sample Output



      enter image description here



      I would like to be able to scale up the points being read to 5000. With the code above it would be painfully slow.



      Timer Test:



      Starting a timer at the beginning of the function and ending before the return statement gives an average of 1.5s per 100 points. If simple proportion can be used to test algorithm scaling performance, then:



      • 100 points: 1.5s

      • 1000 points: 15s

      • 5000 points: 75s

      Please correct me if my above assumption is wrong.



      I was wondering whether it could be improved in any way. More information can be added if requested.




      EDIT:



      I noticed that I was using an extra variable best. This can be removed as such:



      def two_opt(connect_mat, route):
      improved = True
      while improved:
      improved = False
      for i in range(1, len(route) - 2):
      for j in range(i + 1, len(route)):
      if j - i == 1:
      continue # changes nothing, skip then
      new_route = route[:] # Creates a copy of route
      new_route[i:j] = route[j - 1:i - 1:-1] # this is the 2-optSwap since j >= i we use -1
      if cost(connect_mat, new_route) < cost(connect_mat, route):
      route = new_route # change current route to best
      improved = True

      return route


      I doubt how much (if any) this increases efficiency, however it does sacrifice readability to some extent.







      python performance algorithm python-3.x traveling-salesman






      share|improve this question















      share|improve this question













      share|improve this question




      share|improve this question








      edited Nov 27 '18 at 22:24







      Rrz0

















      asked Nov 25 '18 at 16:54









      Rrz0Rrz0

      1586




      1586




















          1 Answer
          1






          active

          oldest

          votes


















          0












          $begingroup$

          You repeatedly evaluate



          cost(cost_mat, best)


          There is an opportunity to memoize this, or at least store it in a temp var.



          You should decide if you want "optimal" TSP, or "good enough" TSP
          that is k-competitive with an optimal solution.



          You suggest you're taking 15ms per city.
          You didn't post profile / timing data, but
          I have to believe that much of the time is taken up by roll + sum,
          rather than by, say, creating route copies.
          Could we pre-compute distances between points, and
          then consider just next hops within some threshold distance?
          Or order by distance, and consider only a fixed number of next hops,
          adjusted upward each time a better route is found?



          Could the cost() function be broken into "near" and "far" components,
          with the advantage that "far" would be substantially constant?
          Usually we do not find a better cost.
          If we do find one, we could then fall back to "carefully"
          computing the detailed "far" cost.






          share|improve this answer









          $endgroup$













            Your Answer





            StackExchange.ifUsing("editor", function ()
            return StackExchange.using("mathjaxEditing", function ()
            StackExchange.MarkdownEditor.creationCallbacks.add(function (editor, postfix)
            StackExchange.mathjaxEditing.prepareWmdForMathJax(editor, postfix, [["\$", "\$"]]);
            );
            );
            , "mathjax-editing");

            StackExchange.ifUsing("editor", function ()
            StackExchange.using("externalEditor", function ()
            StackExchange.using("snippets", function ()
            StackExchange.snippets.init();
            );
            );
            , "code-snippets");

            StackExchange.ready(function()
            var channelOptions =
            tags: "".split(" "),
            id: "196"
            ;
            initTagRenderer("".split(" "), "".split(" "), channelOptions);

            StackExchange.using("externalEditor", function()
            // Have to fire editor after snippets, if snippets enabled
            if (StackExchange.settings.snippets.snippetsEnabled)
            StackExchange.using("snippets", function()
            createEditor();
            );

            else
            createEditor();

            );

            function createEditor()
            StackExchange.prepareEditor(
            heartbeatType: 'answer',
            autoActivateHeartbeat: false,
            convertImagesToLinks: false,
            noModals: true,
            showLowRepImageUploadWarning: true,
            reputationToPostImages: null,
            bindNavPrevention: true,
            postfix: "",
            imageUploader:
            brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
            contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
            allowUrls: true
            ,
            onDemand: true,
            discardSelector: ".discard-answer"
            ,immediatelyShowMarkdownHelp:true
            );



            );













            draft saved

            draft discarded


















            StackExchange.ready(
            function ()
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f208387%2f2-opt-algorithm-for-the-traveling-salesman-and-or-sro%23new-answer', 'question_page');

            );

            Post as a guest















            Required, but never shown

























            1 Answer
            1






            active

            oldest

            votes








            1 Answer
            1






            active

            oldest

            votes









            active

            oldest

            votes






            active

            oldest

            votes









            0












            $begingroup$

            You repeatedly evaluate



            cost(cost_mat, best)


            There is an opportunity to memoize this, or at least store it in a temp var.



            You should decide if you want "optimal" TSP, or "good enough" TSP
            that is k-competitive with an optimal solution.



            You suggest you're taking 15ms per city.
            You didn't post profile / timing data, but
            I have to believe that much of the time is taken up by roll + sum,
            rather than by, say, creating route copies.
            Could we pre-compute distances between points, and
            then consider just next hops within some threshold distance?
            Or order by distance, and consider only a fixed number of next hops,
            adjusted upward each time a better route is found?



            Could the cost() function be broken into "near" and "far" components,
            with the advantage that "far" would be substantially constant?
            Usually we do not find a better cost.
            If we do find one, we could then fall back to "carefully"
            computing the detailed "far" cost.






            share|improve this answer









            $endgroup$

















              0












              $begingroup$

              You repeatedly evaluate



              cost(cost_mat, best)


              There is an opportunity to memoize this, or at least store it in a temp var.



              You should decide if you want "optimal" TSP, or "good enough" TSP
              that is k-competitive with an optimal solution.



              You suggest you're taking 15ms per city.
              You didn't post profile / timing data, but
              I have to believe that much of the time is taken up by roll + sum,
              rather than by, say, creating route copies.
              Could we pre-compute distances between points, and
              then consider just next hops within some threshold distance?
              Or order by distance, and consider only a fixed number of next hops,
              adjusted upward each time a better route is found?



              Could the cost() function be broken into "near" and "far" components,
              with the advantage that "far" would be substantially constant?
              Usually we do not find a better cost.
              If we do find one, we could then fall back to "carefully"
              computing the detailed "far" cost.






              share|improve this answer









              $endgroup$















                0












                0








                0





                $begingroup$

                You repeatedly evaluate



                cost(cost_mat, best)


                There is an opportunity to memoize this, or at least store it in a temp var.



                You should decide if you want "optimal" TSP, or "good enough" TSP
                that is k-competitive with an optimal solution.



                You suggest you're taking 15ms per city.
                You didn't post profile / timing data, but
                I have to believe that much of the time is taken up by roll + sum,
                rather than by, say, creating route copies.
                Could we pre-compute distances between points, and
                then consider just next hops within some threshold distance?
                Or order by distance, and consider only a fixed number of next hops,
                adjusted upward each time a better route is found?



                Could the cost() function be broken into "near" and "far" components,
                with the advantage that "far" would be substantially constant?
                Usually we do not find a better cost.
                If we do find one, we could then fall back to "carefully"
                computing the detailed "far" cost.






                share|improve this answer









                $endgroup$



                You repeatedly evaluate



                cost(cost_mat, best)


                There is an opportunity to memoize this, or at least store it in a temp var.



                You should decide if you want "optimal" TSP, or "good enough" TSP
                that is k-competitive with an optimal solution.



                You suggest you're taking 15ms per city.
                You didn't post profile / timing data, but
                I have to believe that much of the time is taken up by roll + sum,
                rather than by, say, creating route copies.
                Could we pre-compute distances between points, and
                then consider just next hops within some threshold distance?
                Or order by distance, and consider only a fixed number of next hops,
                adjusted upward each time a better route is found?



                Could the cost() function be broken into "near" and "far" components,
                with the advantage that "far" would be substantially constant?
                Usually we do not find a better cost.
                If we do find one, we could then fall back to "carefully"
                computing the detailed "far" cost.







                share|improve this answer












                share|improve this answer



                share|improve this answer










                answered 14 mins ago









                J_HJ_H

                4,592132




                4,592132



























                    draft saved

                    draft discarded
















































                    Thanks for contributing an answer to Code Review Stack Exchange!


                    • Please be sure to answer the question. Provide details and share your research!

                    But avoid


                    • Asking for help, clarification, or responding to other answers.

                    • Making statements based on opinion; back them up with references or personal experience.

                    Use MathJax to format equations. MathJax reference.


                    To learn more, see our tips on writing great answers.




                    draft saved


                    draft discarded














                    StackExchange.ready(
                    function ()
                    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f208387%2f2-opt-algorithm-for-the-traveling-salesman-and-or-sro%23new-answer', 'question_page');

                    );

                    Post as a guest















                    Required, but never shown





















































                    Required, but never shown














                    Required, but never shown












                    Required, but never shown







                    Required, but never shown

































                    Required, but never shown














                    Required, but never shown












                    Required, but never shown







                    Required, but never shown







                    Popular posts from this blog

                    कुँवर स्रोत दिक्चालन सूची"कुँवर""राणा कुँवरके वंशावली"

                    Why is a white electrical wire connected to 2 black wires?How to wire a light fixture with 3 white wires in box?How should I wire a ceiling fan when there's only three wires in the box?Two white, two black, two ground, and red wire in ceiling box connected to switchWhy is there a white wire connected to multiple black wires in my light box?How to wire a light with two white wires and one black wireReplace light switch connected to a power outlet with dimmer - two black wires to one black and redHow to wire a light with multiple black/white/green wires from the ceiling?Ceiling box has 2 black and white wires but fan/ light only has 1 of eachWhy neutral wire connected to load wire?Switch with 2 black, 2 white, 2 ground and 1 red wire connected to ceiling light and a receptacle?

                    चैत्य भूमि चित्र दीर्घा सन्दर्भ बाहरी कडियाँ दिक्चालन सूची"Chaitya Bhoomi""Chaitya Bhoomi: Statue of Equality in India""Dadar Chaitya Bhoomi: Statue of Equality in India""Ambedkar memorial: Centre okays transfer of Indu Mill land"चैत्यभमि