title: How to read data in a class to solve a tabu search problem
body: <p>I'm trying to learn search algorithms in order to prepare my master thesis, so I have a TSP problem in which I want to find the best and minimal route to visite all the states , I'm using a <code>.txt</code> file named <strong>cities__coordinates.txt</strong> that contains the coordinates for every state, so to read the data I've found this source code that has a class to read the data you'll find it here:</p>
  <pre><code>import numpy as np 
  import networkx as nx
  import matplotlib.pyplot as plt
  import copy
  import re 
  import math  
  
  class Data():
      '''
      the format of solomon dataset
      '''
      def __init__(self):
          self.customerNum = 0    # the number of customers
          self.nodeNum     = 0    # the sum of customers and depots
          self.vehicleNum  = 0   
          self.capacity    = 0    
          self.cor_X       = []
          self.cor_Y       = []
          self.demand      = []
          self.readyTime   = []
          self.dueTime     = []
          self.serviceTime = []
          self.disMatrix   = {}  
  
      def read_data(self, path, customerNum, depotNum):
          '''
          function to read solomom data from .txt files, notice that it must be solomon dataset    
          INPUT 
              @ data  : class Data
              @ path  : Data path
              @ customerNum  : the number of customer
          OutPut : none
          '''
          self.customerNum = customerNum
          self.nodeNum = customerNum + depotNum
          f = open('cities__coordinates.txt', 'r')
          lines = f.readlines()
          count = 0
          for line in lines:
              count = count + 1
              if(count == 5):  
                  line = line[:-1].strip() 
                  str = re.split(r&quot; +&quot;, line)
                  self.vehicleNum = float(str[0])
                  self.capacity = float(str[1])
              elif(count &gt;= 10 and count &lt;= 10 + customerNum):
                  line = line[:-1]
                  str = re.split(r&quot; +&quot;, line)
                  self.cor_X.append(float(str[2]))
                  self.cor_Y.append(float(str[3]))
                  self.demand.append(float(str[4]))
                  self.readyTime.append(float(str[5]))
                  self.dueTime.append(float(str[6]))
                  self.serviceTime.append(float(str[7]))
  
          # compute the distance matrix
          self.disMatrix = {}
          for i in range(0, self.nodeNum):
              dis_temp={}
              for j in range(0, self.nodeNum):
                  dis_temp[j] =  int(math.hypot(self.cor_X[i] - self.cor_X[j],self.cor_Y[i] - self.cor_Y[j]))
              self.disMatrix[i] = dis_temp
              
  
      def plot_nodes(self):
          '''
          Description: function to plot 
          '''
          Graph = nx.DiGraph()
          nodes_name = [str(x) for x in list(range(self.nodeNum))]
          Graph.add_nodes_from(nodes_name)
          cor_xy = np.array([self.cor_X,self.cor_Y]).T.astype(int)
          pos_location = {nodes_name[i]:x for i,x in enumerate(cor_xy)}
          nodes_color_dict = ['r'] + ['gray'] * (self.nodeNum-1)
          
          nx.draw_networkx(Graph,pos_location,node_size=200,node_color=nodes_color_dict,labels=None)  
          plt.show(Graph)
  
      def plot_route(self,route,color='k'):
          Graph = nx.DiGraph()
          nodes_name = [0]
          cor_xy=[[self.cor_X[0] , self.cor_Y[0]]]
          edge = []
          edges = [[0,route[0]]]
          for i in route : 
              nodes_name.append(i)
              cor_xy.append([self.cor_X[i] , self.cor_Y[i]])
              edge.append(i)
              if len(edge) == 2 :
                  edges.append(copy.deepcopy(edge))
                  edge.pop(0)
          edges.append([route[-1],0])
  
          Graph.add_nodes_from(nodes_name)
          Graph.add_edges_from(edges)
     
          pos_location = {nodes_name[i]:x for i,x in enumerate(cor_xy)}
          nodes_color_dict = ['r'] + ['gray'] * (len(route))
          
          nx.draw_networkx(Graph,pos_location,node_size=200,node_color=nodes_color_dict,edge_color=color, labels=None)  
          plt.show(Graph)
  </code></pre>
  <p>so in read_data function I've changed the path to my .txt file , and for the code which will calculate all the distance and took the tabu search and all the staffs, here it is the code:</p>
  <pre><code>from itertools import combinations
  import os,sys,copy
  import numpy as np
  import time
  from Datareader import Data
  import matplotlib.pyplot as plt
  
  class Tabu():
      def __init__(self,disMatrix,max_iters=200,maxTabuSize=20):
          &quot;&quot;&quot;parameters definition&quot;&quot;&quot;
          self.disMatrix = disMatrix
          self.maxTabuSize = maxTabuSize
          self.max_iters = max_iters
          self.tabu_list=[]
  
      def get_route_distance(self,route):
          '''
          Description: function to calculate total distance of a route. evaluate function.
          parameters: route : list
          return : total distance : folat
          '''        
          routes = [0] + route + [0]    # add the start and end point 
          total_distance = 0
          for i,n in enumerate(routes):
              if i != 0 :
                  total_distance = total_distance +  self.disMatrix[last_pos][n] 
              last_pos = n
          return total_distance
  
      def exchange(self,s1,s2,arr):
          &quot;&quot;&quot;
          function to Swap positions of two elements in an arr
          Args: int,int,list
              s1 : target 1 
              s2 : target 2  
              arr : target array 
          Ouput: list
              current_list : target array 
          &quot;&quot;&quot;
          current_list = copy.deepcopy(arr)
          index1 , index2 = current_list.index(s1) , current_list.index(s2)  # get index
          current_list[index1], current_list[index2]= arr[index2] , arr[index1]
          return current_list
  
      def generate_initial_solution(self,num=10,mode='greedy'):
          &quot;&quot;&quot;
          function to get the initial solution,there two different way to generate route_init.
          Args: 
              num :  int
                  the number of points 
              mode : string
                  &quot;greedy&quot; : advance step by choosing optimal one 
                  &quot;random&quot; : randomly generate a series number
          Ouput: list
              s_init : initial solution route_init
          &quot;&quot;&quot;
          if mode == 'greedy':
              route_init=[0]
              for i in range(num):
                  best_distance = 10000000
                  for j in range(num+1):
                      if self.disMatrix[i][j] &lt; best_distance and j not in route_init:  
                          best_distance = self.disMatrix[i][j]
                          best_candidate = j
                  route_init.append(best_candidate)
              route_init.remove(0)
                              
          if mode == 'random':
              route_init = np.arange(1,num+1)  #init solution from 1 to num
              np.random.shuffle(route_init)  #shuffle the list randomly
  
          return list(route_init)
  
      def tabu_search(self,s_init):   
          &quot;&quot;&quot;tabu search&quot;&quot;&quot;
          s_best = s_init 
          bestCandidate = copy.deepcopy(s_best)
          routes , temp_tabu = [] , []   # init
          routes.append(s_best)
          while(self.max_iters):
              self.max_iters -= 1 # Number of iterations
              neighbors = copy.deepcopy(s_best)
              for s in combinations(neighbors, 2):   
                  sCandidate = self.exchange(s[0],s[1],neighbors)  # exchange number to generate candidates
                  if s not in self.tabu_list and self.get_route_distance(sCandidate) &lt; self.get_route_distance(bestCandidate):
                      bestCandidate = sCandidate
                      temp_tabu = s                           
              if self.get_route_distance(bestCandidate) &lt; self.get_route_distance(s_best): # record the best solution 
                  s_best = bestCandidate
              if  temp_tabu not in self.tabu_list:
                  self.tabu_list.append(temp_tabu)
              if len(self.tabu_list) &gt; self.maxTabuSize :
                  self.tabu_list.pop(0)
              routes.append(bestCandidate)
          return s_best, routes
  
  if __name__ == &quot;__main__&quot;:
  
      data = Data()
      data.read_data(path='cities__coordinates.txt',customerNum=100,depotNum=1)   # change the path
    
      &quot;&quot;&quot; Tabu : 
          disMatrix : the distance matrix from 0 to X , 0 represernt starting and stopping point。 
          for example:   disMatrix = [[0,3,4,...
                                       1,0,5,...
                                       3,5,0,...]]
         that means the distance from 0 to 0 is 0, from 0 to 1 is 3,... from 1 to 3 is 5....      
          max_iters : maximum iterations 
          maxTabuSize : maximum iterations 
      &quot;&quot;&quot;
      tsp = Tabu(disMatrix=data.disMatrix,max_iters=10,maxTabuSize=10) 
      # two different way to generate initial solution
      # num : the number of points   
      s_init = tsp.generate_initial_solution(num=10,mode='greedy') # mode = &quot;greedy&quot;  or &quot;random&quot;
      print('init route : ' , s_init)
      print('init distance : ' , tsp.get_route_distance(s_init))
  
      start = time.time()
      best_route , routes = tsp.tabu_search(s_init)     # tabu search
      end = time.time()
  
      print('best route : ' , best_route)
      print('best best_distance : ' , tsp.get_route_distance(best_route))
      print('the time cost : ',end - start )
  
      # plot the result changes with iterations
      results=[]
      for i in routes:
          results.append(tsp.get_route_distance(i))    
      plt.plot(np.arange(len(results)) , results)
      plt.show()
      # plot the route
      data.plot_route(best_route)
  </code></pre>
  <p>when I execute it, it takes a little time and then it shows me this error :</p>
  <pre><code>Traceback (most recent call last):
    File &quot;C:/Users/malle/OneDrive/Desktop/TS.py&quot;, line 100, in &lt;module&gt;
      data.read_data(path='cities__coordinates.txt',customerNum=100,depotNum=1)   # change the path
    File &quot;C:/Users/malle/OneDrive/Desktop\Datareader.py&quot;, line 49, in read_data
      self.cor_X.append(float(str[2]))
  IndexError: list index out of range
  </code></pre>
  <p>anyone can help to resolve this problem please ?</p>