Hopfield neural network to solve TSP problem (Java)

Posted by batfastad on Fri, 31 Dec 2021 20:20:36 +0100

catalogue

1, Network principle

II. Algorithm steps

3, Code implementation (Java)

4, jar package used

1, Network principle

Hopfield neural network (HNN) is a fully interconnected feedback neural network, in which each neuron is connected with other neurons.

Hopfield neural network is mainly divided into discrete Hopfield neural network (DHNN) and continuous Hopfield neural network (CHNN). Neurons in discrete Hopfield neural network are quite different from biological neurons because the input and output of biological neurons are continuous and have time delay. Continuous Hopfield neural network is a continuous time neural network model, In this network, the state of neurons can take any real value between 0 and 1. Because the network associative memory process of Hopfield neural network is the process that the nonlinear dynamic system runs towards a stable state. Changing the state of neurons according to the dynamic rules will eventually make the neural network in a stable state.

Discrete Hopfield neural network is a two-state nonlinear dynamic system with multiple input and multiple output generation thresholds. Continuous Hopfield neural network not only simplifies the properties of biological neurons, but also accurately retains the dynamic and nonlinear characteristics of biological neural network. According to its characteristics, discrete Hopfield neural network is usually used to deal with associative memory problems, and continuous Hopfield neural network is usually used to deal with combinatorial optimization problems. TSP problem is a typical combinatorial optimization problem. Therefore, after comprehensive judgment, continuous Hopfield neural network is selected as the algorithm model of this problem.

The key of using neural network to solve the optimization problem is how to map the optimization problem to be solved into a neural network. Generally, each feasible solution of the problem can be expressed by transposition matrix. Another key problem is to construct the energy function so that its minimum value corresponds to the optimal solution of the problem, which determines whether a specific problem can be solved by neural network. Lagrange function and sub multiplication or penalty function method in optimization theory are usually used to construct energy function (formula (1)).

(1)

Where Is a penalty function for violating constraints,Is the objective function of optimizationAndFor balance and The proportional constant of the action in the total energy function, and if minimized , then; If maximization, then;.

In TSP problem, the energy function often reflects the length of the path. If the subscripts x and y represent the city and i represent the ith visit, the path length can be expressed in the following general form:

(2)

WhereRepresents the element in row X and column i of the transposition matrix, and when its value is 1, it means that step i accesses city x, and when its value is 0, it means that step i does not access City X.

In the transposition matrix, only one element in each row and column can be 1, and the rest are 0. Otherwise, it represents an invalid path. Only one element in each column is 1, which means passing through only one city at a time (formula (3)), and only one element in each row is 1, which means passing through each city and only once (formula (4)).

(3)

(4)

Using the penalty function method, the above constrained optimization problem is expressed as the following unconstrained optimization problem:

(5)

At this time, the dynamic equation of Hopfield neural network is:

(6)

Then = calculated by the first-order Euler methodThe input of time is:

(7)

In order to ensure convergence to the correct solution, that is, only one element in each row and column of transposition matrix V is 1 and the rest is 0, it is calculated by Sigmoid function.

(8)

The steady-state solution of the neural network can be obtained by solving the above formula until it converges.

II. Algorithm steps

The algorithm steps of Hopfield neural network to solve TSP problem are as follows:

Step 1: set initial value, initial voltage, penalty parameters A and D, number of iterations T;

Step 2: calculate the distance between N cities

Step 3: set neural network input near 0 Initialization value of;

Step 4: calculate according to the dynamic equation (formula (6))

Step 5: calculation by first-order Euler method

Step 6: calculate the output transposition matrix

Step 7: calculate the energy function J by applying formula (5);

Step 8: check the validity of the path. Judge whether it ends according to the number of iterations. If it ends, it ends. Otherwise, return to Step 4.

 

 

3, Code implementation (Java)

Hopfield class: mainly used for module and interface design

package Hopfield;

import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import jxl.NumberCell;
import jxl.Sheet;
import jxl.Workbook;
import jxl.read.biff.BiffException;

public class hopfield {
	private static final double R = 6371.004;
	private int cityNum;//Number of cities
	private int MAX;//Number of iterations
	//private double bestLength;
	private int[] bestTour;
	private double[][] distance;//Distance matrix
	//private double[][] time;// Time matrix
	double[] xx;//Used to output the best path to each city location
	double[] yy;//Used to output the best path to each city location
	private String filepath;
	private double A,D;
	private double U0;
	//private double[][][][] W;// weight matrix 
	private double[][] deltaU;//Dynamic results
	private double[][] V;//Transposition matrix
	private double[][] Ut;//Next moment input
	private double[][] U;//Initial value
	private double step;//Step size, i.e. delta t
	private double E;//Energy value
	
	public hopfield(int MAX,int cityNum,double U0,double step,double A,double D,String filepath) {
		this.MAX = MAX;
		this.cityNum = cityNum;
		this.U0 = U0;
		this.step = step;
		this.A = A;
		this.D = D;
		this.filepath = filepath;
		bestTour = new int [cityNum];
		distance = new double[cityNum][cityNum];
		W = new double[cityNum][cityNum][cityNum][cityNum];
		V = new double[cityNum][cityNum];
		deltaU = new double[cityNum][cityNum];
		Ut = new double[cityNum][cityNum];
		U = new double[cityNum][cityNum];
		xx = new double[cityNum];
		yy = new double[cityNum];
	}
	
	private static double rad(double d) {
		return d * Math.PI / 180.0;
	}
	
	//Calculate distance matrix
	public double[][] Distance() throws BiffException, IOException{
		double[] x = new double[cityNum];
		double[] y = new double[cityNum];
		distance = new double[cityNum][cityNum];
		//Create input stream
		InputStream stream = new FileInputStream(filepath);
		//Get Excel file object
		Workbook  rwb = Workbook.getWorkbook(stream);
		//Gets the default first of the specified worksheets of the file
	    Sheet sheet = rwb.getSheet("Sheet2");
	    
	    for(int i=0;i<sheet.getRows();i++) {
	    	NumberCell cell = null;//It solves the problem that Cell only retains three decimal places
	        cell = (NumberCell) sheet.getCell(0,i); 
		    x[i] = cell.getValue();
		    xx[i] = x[i];
		    cell = (NumberCell) sheet.getCell(1,i);
		    y[i] = cell.getValue();
		    yy[i] = y[i];
		    
	    }
	    //Calculate the distance between each city
	    for (int i = 0; i < cityNum - 1; i++) {
			distance[i][i] = 0; // Diagonal 0
			//Convert latitude and longitude to plane distance
			for (int j = i + 1; j < cityNum; j++) {
				double rij = 2*R*Math.asin(Math.sqrt(Math.pow(Math.sin((rad(y[j])-rad(y[i]))/2), 2) + Math.cos(rad(y[j]))*Math.cos(rad(y[i]))*Math.pow(Math.sin((rad(x[j])-rad(x[i]))/2), 2)));
				distance[i][j] = rij;
				distance[j][i] = distance[i][j];
			}
		}
		distance[cityNum - 1][cityNum - 1] = 0;
		return distance;
	}

	//Neural network dynamic equation
	public double[][] calc_du(double[][] V,double[][] distance) {
		double[] a1 = new double[cityNum];
		double[] a2 = new double[cityNum];
		double[] b = new double[cityNum];
		double[][] t1 = new double[cityNum][cityNum];
		double[][] t2 = new double[cityNum][cityNum];
		double[][] d = new double[distance.length][V[0].length];				
		//Add by column
		for(int x=0;x<cityNum;x++) {
			for(int i=0;i<cityNum;i++) {
				a1[x] += V[x][i];
			}
		}
		for(int i=0;i<cityNum;i++) {
			for(int j=0;j<cityNum;j++) {
				t1[i][j] = a1[j];
			}
		}
		//Add by row
		for(int y=0;y<cityNum;y++) {
			for(int i=0;i<cityNum;i++) {
				a2[i] += V[i][y];
			}
		}
		for(int i=0;i<cityNum;i++) {
			for(int j=0;j<cityNum;j++) {
				t2[j][i] = a2[j];
			}
		}
		//Place the first column in the last column
		for(int i=0;i<cityNum;i++) {
			b[i] = V[i][0];
		}
		for(int i=0;i<cityNum;i++) {
			for(int j=0;j<cityNum-1;j++) {
				V[i][j] = V[i][j+1];
			}
		}
		for(int i=0;i<cityNum;i++) {
			V[i][cityNum-1] = b[i];
		}
		
		double sum=0;
		for(int j=0;j<V[0].length;j++) {  
			for(int k=0;k<distance.length;k++) {  
				for(int i=0;i<distance[0].length;i++) {
					sum=sum+distance[k][i]*V[i][j];
				}
				d[k][j]=sum;
				sum=0;
			}
		}
		for(int i=0;i<cityNum;i++) {
			for(int j=0;j<cityNum;j++) {
				deltaU[i][j] = -1*A*((t1[i][j]-1)+(t2[i][j]-1))-D*d[i][j];
			}
		}
		return deltaU;
	}
	
	//Calculated output equation
	public double[][] calc_V(double[][] U) {
		for(int x=0;x<cityNum;x++) {
			for(int i=0;i<cityNum;i++) {
				V[x][i] = (1+Math.tanh(U[x][i]/U0))/2;
			}
		}
		return V;
	}
	
	//Status update: next moment status Uxi(t0+step)
	public double[][] calc_Ut(double[][] deltaU,double[][] U) {
		for(int x=0;x<cityNum;x++) {
			for(int i=0;i<cityNum;i++) {
				Ut[x][i] = deltaU[x][i]*step + U[x][i];
			}
		}
		return Ut;
	}
	
	//Energy formula
	public double calc_E(double[][] V,double[][] dis) {
		double[] a1 = new double[cityNum];
		double[] a2 = new double[cityNum];
		double[] b = new double[cityNum];
		double J;
		double t1=0,t2=0,t3=0;
		double[][] V1 = new double[cityNum][cityNum];
		double[][] d = new double[distance.length][V[0].length];
		//Add by column
		for(int x=0;x<cityNum;x++) {
			for(int i=0;i<cityNum;i++) {
				a1[x] += V[x][i];
			}
		}
		for(int i=0;i<cityNum;i++) {
			t1 += (a1[i]-1)*(a1[i]-1);
		}
		//Add by row
		for(int y=0;y<cityNum;y++) {
			for(int i=0;i<cityNum;i++) {
				a2[i] += V[i][y];
			}
		}
		for(int i=0;i<cityNum;i++) {
			t2 += (a2[i]-1)*(a2[i]-1);
		}
		
		//Place the first column in the last column
		for(int i=0;i<cityNum;i++) {
			b[i] = V[i][0];
		}
		for(int i=0;i<cityNum;i++) {
			for(int j=0;j<cityNum-1;j++) {
				V1[i][j] = V[i][j+1];
			}
		}
		for(int i=0;i<cityNum;i++) {
			V1[i][cityNum-1] = b[i];
		}
		
		double sum=0;
		for(int j=0;j<V[0].length;j++) {  
			for(int k=0;k<distance.length;k++) {  
				for(int i=0;i<distance[0].length;i++) {
					sum=sum+distance[k][i]*V1[i][j];
				}
				d[k][j]=sum;
				sum=0;
			}
		}
		for(int j=0;j<V[0].length;j++) {  
			for(int k=0;k<distance.length;k++) {  
				for(int i=0;i<distance[0].length;i++) {
					t3 += d[k][i]*V[i][j];
				}
			}
		}
		J = (A*t1+A*t2+D*t3)/2;
		return J;
		
	}
	
	public int[] getpath(double[][] V) {
		double[] max = new double[cityNum];
		//Maximum value per column
		for(int j=0;j<cityNum;j++) {
			double a=0;
			for(int i=0;i<cityNum;i++) {
				if(V[i][j] > a) {
					a = V[i][j];
				}
			}
			max[j] = a;
			//System.out.print(max[j]+",");
		}
		
		int j=0;
		for(int i=0;i<cityNum;i++) {
			if(max[j] == V[i][j]) {
				bestTour[j] = i;
				j++;
				break;
			}	
		}
		return bestTour;
	}
	
	public static Object[] szqc(int[] a) {
        List list = new ArrayList();
        //Traversing an array to store elements in a collection
        for(int i=0;i<a.length;i++){
            //If there is no same element in the collection, it will be saved
            if(!list.contains(a[i])){
                list.add(a[i]);
            }
        }
        //The toArray() method returns an array of Object types that contains all the elements of the collection
        Object[] newArr = list.toArray();
        return newArr;
}


	public void solve() throws BiffException, IOException {
		int tt[] = new int[cityNum];
		distance = Distance();
		//Initialize Uxi
		System.out.println("U");
		for(int x=0;x<cityNum;x++) {
			for(int i=0;i<cityNum;i++) {
				U[x][i] = 1/2*U0*Math.log(cityNum - 1) + (Math.random()*2-1)/10;
				System.out.print(U[x][i]+"\t");
			}
			System.out.println();
		}
		
		//Initialize output status
		System.out.println("V");
		V = calc_V(U);
		for(int x=0;x<cityNum;x++) {
			for(int i=0;i<cityNum;i++) {
				System.out.print(V[x][i]+"\t");
			}
			System.out.println();
		}
		//Start iteration
		for(int i=0;i<MAX;i++) {
			deltaU = calc_du(V,distance);
			Ut = calc_Ut(deltaU, U);
			U = Ut;
			V = calc_V(U);
			for(int x=0;x<cityNum;x++) {
				for(int i1=0;i1<cityNum;i1++) {
					V[x][i1]=Math.round(V[x][i1]);
				}
			}
			E = calc_E(V,distance);
			bestTour = getpath(V);
			Object[] tour = szqc(bestTour);
			if(tour.length == bestTour.length) {
				for(int i1=0;i1<cityNum;i1++) {
					//int x = bestTour[i];
					System.out.print(bestTour[i1]+",");
					tt[i1] = bestTour[i1];
				}
				System.out.println();
				double sum1=0;
				for(int i1=0;i1<cityNum-1;i1++) {
					
					sum1 +=distance[bestTour[i1]][bestTour[i1+1]];
				}
				sum1 += distance[bestTour[0]][bestTour[cityNum-1]];
				System.out.println("Distance:"+sum1);
				System.out.println("E:"+E);
			}
		}
		for(int i=0;i<cityNum;i++) {
			System.out.print(tt[i]+",");
		}
	}
}

hopmain class: calling the launcher

package Hopfield;

import java.io.IOException;
import jxl.read.biff.BiffException;

public class hopmain {
	public static void main(String[] args) throws BiffException, IOException {
		//Enter the number of iterations, number of cities, U0, step size, A and D parameter values and file path in turn
		hopfield hop =new hopfield(50000, 38, 0.02, 0.0001, 1.5, 0.5 ,"D:\\2.xls");
		hop.solve();
	}
}

4, jar package used

jxl package is a special toolkit for reading Excel files. If necessary, you can download it directly on maven's official website.

Topics: Java AI neural networks