分支定界算法求解TSP

本文介绍了如何使用分支定界算法(Branch and Bound)实现旅行商问题(TSP)的解决方案,完全脱离求解器。通过讲解节点的分支方式和算法的优越性,展示了算法的运行效果,旨在帮助读者理解该算法在解决TSP问题中的应用。
摘要由CSDN通过智能技术生成

其实精确算法也好,启发式算法也好,都是独立的算法,可以不依赖求解器进行代码实现的,只要过程符合算法框架即可。只不过平常看到的大部分是精确算法在各种整数规划模型上的应用,为此难免脱离不了cplex等求解器。下面我们用分支定界算法求解TSP问题的代码实现,完全脱离求解器。

代码框架如下
在这里插入图片描述
Timer类:计时用

package tspsolver;

public class Timer
{
  private long startTime;
  private long stopTime;
  private boolean running;
  
  private final double nano = 1000000000.0;
  
  public Timer()
  {
    super();
  }

  public void reset()
  {
    this.startTime = 0;
    this.running = false;
  }

  public void start()
  {
    this.startTime = System.nanoTime();
    this.running = true;
  }
  
  public void stop()
  {
    if (running)
    { 
      this.stopTime = System.nanoTime();
      this.running = false;
    }
  }
  
  public double getTime()
  {
    double elapsed;
    if (running)
    {
      elapsed = ((System.nanoTime() - startTime) / nano);
    }
    else
    {
      elapsed = ((stopTime - startTime) / nano);
    }
    return elapsed;
  }
 
}

TSPInstanceReader类:读取实例

package tspsolver;

import java.awt.GraphicsEnvironment;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import javax.swing.JFileChooser;
import javax.swing.JOptionPane;

public class TSPInstanceReader {
	
	ArrayList<City> cities;
	double[][] distanceMatrix;
	
	public TSPInstanceReader(String instanceFile) {
		File file;
		if(instanceFile != null) {
			file = new File(instanceFile);
		}
		else {
			JFileChooser chooser = new JFileChooser();

			int response = chooser.showOpenDialog(null);
			if(response != JFileChooser.APPROVE_OPTION)
				return;

			file = chooser.getSelectedFile();
		}

		BufferedReader reader = null;
		try {
			reader = new BufferedReader(new FileReader(file));
		}
		catch(IOException e) {
			alert("Error loading file " + e);
			System.exit(1);
		}

		int dimension = 0;
		try {
			String line;
			while(!(line = reader.readLine()).equals("NODE_COORD_SECTION")) {
				String[] entry = line.split(":");
				//System.out.println(entry[0].trim());
				switch(entry[0].trim()) {
					case "TYPE":
						if(!entry[1].trim().equals("TSP"))
							throw new Exception("File not in TSP format");
						break;
					case "DIMENSION":
						dimension = Integer.parseInt(entry[1].trim());
						break;
				}
			}
		}
		catch(Exception e) {
			alert("Error parsing header " + e);
			System.exit(1);
		}
		
		System.out.println("DIMENSION = "+dimension);

		this.cities = new ArrayList<City>(dimension);

		try {
			String line;
//			while((line = reader.readLine()) != null && !line.trim().equals("EOF")) {
//				String[] entry = line.
支限界法类又称为剪枝限界法或分支定界法,它类似于回溯法,也是一种在问题的解空间树T上搜索问题解的算法。它与回溯法有两点不同:①回溯法只通过约束条件剪去非可行解,而分支限界法不仅通过约束条件,而且通过目标函数的限界来减少无效搜索,也就是剪掉了某些不包含最优解的可行解。②在解空间树上的搜索方式也不相同。回溯法以深度优先的方式搜索解空间树,而分支限界法则以广度优先或以最小耗费优先的方式搜索解空间树。分支限界法的搜索策略是:在扩展结点处,先生成其所有的儿子结点(分支),然后再从当前的活结点表中选择下一个扩展结点。为了有效地选择下一扩展结点,以加速搜索的进程, 在每一活结点处,计算一个函数值(限界),并根据这些已计算出的函数值,从当前活结点表中选择一个最有利的结点作为扩展结点,使搜索朝着解空间树上有最优解的分支推进,以便尽快地找出一个最优解。 从活结点表中选择下一扩展结点的不同方式导致不同的分支限界法。最常见的有以下两种方式: ①队列式(FIFO)分支限界法:队列式分支限界法将活结点表组织成一个队列,并按队列的先进先出原则选取下一个结点为当前扩展结点。 ②优先队列式分支限界法:优先队列式分支限界法将活结点表按照某个估值函数C(x)的值组织成一个优先队列,并按优先队列中规定的结点优先级选取优先级最高的下一个结点成为当前扩展结点。 影响分支限界法搜索效率的有两个主要因素:一是优先队列Q的优先级由C(x)确定,它能否保证在尽可能早的情况下找到最优解,如果一开始找到的就是最优解,那么搜索的空间就能降低到最小。二是限界函数u(x),它越严格就越可能多地剪去分支,从而减少搜索空间。 在用分支限界法解决TSP问题时,有不少很好的限界函数和估值函数已经构造出来出了(限于篇幅,这里不做详细介绍), 使得分支限界法在大多数情况下的搜索效率大大高于回溯法。但是,在最坏情况下,该算法的时间复杂度仍然是O(n!),而且有可能所有的(n-1)!个结点都要存储在队列中。 近似算法是指不能肯定找到最优解的算法,但通常找到的也是比较好的解,或称近似最优解。[20]一般而言,近似算法的时间复杂度较低,通常都是多项式时间内的。由于近似算法的时间效率高,所以在实际应用中,主要是使用近似算法,这一类算法也一直是研究的主要对象。传统的近似算法以采用贪心策略和局部搜索为主,而几十年来,随着以遗传算法为代表的新型启发式搜索算法的逐步完善,在解决TSP问题上获得了巨大的成功。遗传算法、模拟退火算法、蚁群算法等已经成为公认的好算法。在本节中,将介绍传统的近似算法
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值