Java调用CPLEX解决TSP问题(基于MTZ模型)

MTZ模型理解简单,编码简单,但是对于解决规模较大的问题复杂度较大。我在计算TSP问题时,101个点大概需要15分钟,120个点大概需要2个小时,再往上就没有试过了。

现把对应代码存档于此。值得注意的是约束3中ui和uj不能只添加一个。

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;

import ilog.concert.*;
import ilog.concert.IloCopyManager.Check;
import ilog.cplex.*;

public class Main {
	public static int _cityNum;
	public static double[][] _cityDis;

	public static ArrayList<Integer> _set;
	public static ArrayList<ArrayList<Integer>> _setPool;

	public static ArrayList<Integer> _setCG;// for constraint generation
	public static ArrayList<ArrayList<Integer>> _setCGPool;// for constraint
															// generation

	public static long _time;
	public static double _ansLength;
	public static double[][] _ansCity;

	public static void main(String[] args) {
		
		String filename = "E:\\JAVA\\TSP1\\data\\gr120.tsp";
		// 读取标准化后的文件
		ReadData(filename);
		// 运行算法
		MTZsolve();// MTZ方法
		// 输出结果
		WriteAns(filename + ".ans");
		// 检查是否满足约束
		// checkOpt();
		System.out.println("finish");
	}

	// MTZ方法解决
	public static void MTZsolve() {
		try {
			_ansCity = new double[_cityNum][_cityNum];

			IloCplex cplex = new IloCplex();
			IloIntVar[][] x = new IloIntVar[_cityNum][_cityNum];// 0-1变量
			IloIntVar[] u = new IloIntVar[_cityNum];

			// 设定变量取值范围
			for (int i = 0; i < _cityNum; i++) {
				for (int j = 0; j < _cityNum; j++) {
					if (i != j)
						x[i][j] = cplex.intVar(0, 1);
					else
						x[i][j] = cplex.intVar(0, 0);
				}
			}
			for (int i = 1; i < _cityNum; i++) {
				u[i] = cplex.intVar(1, _cityNum - 1);
			}

			// 目标函数
			IloLinearNumExpr tempObj = cplex.linearNumExpr();
			for (int i = 0; i < _cityNum; i++) {
				tempObj.add(cplex.scalProd(x[i], _cityDis[i]));
			}
			cplex.addMinimize(tempObj);

			// 添加约束 1 和 2
			for (int i = 0; i < _cityNum; i++) {
				IloLinearIntExpr constraint2 = cplex.linearIntExpr();
				for (int j = 0; j < _cityNum; j++) {
					constraint2.addTerm(x[j][i], 1);
				}
				cplex.addEq(cplex.sum(x[i]), 1);
				cplex.addEq(constraint2, 1);
			}
			// 添加约束 3
			for (int i = 1; i < _cityNum; i++) {
				for (int j = i + 1; j < _cityNum; j++) {
					IloLinearIntExpr constraint3_1 = cplex.linearIntExpr();
					constraint3_1.addTerm(u[i], 1);
					constraint3_1.addTerm(u[j], -1);
					constraint3_1.addTerm(x[i][j], _cityNum - 1);
					cplex.addLe(constraint3_1, _cityNum - 2);

					IloLinearIntExpr constraint3_2 = cplex.linearIntExpr();
					constraint3_2.addTerm(u[j], 1);
					constraint3_2.addTerm(u[i], -1);
					constraint3_2.addTerm(x[j][i], _cityNum - 1);
					cplex.addLe(constraint3_2, _cityNum - 2);
				}
			}

			// 输出结果
			long start = System.currentTimeMillis();
			boolean success = cplex.solve();
			long end = System.currentTimeMillis();
			_time = end - start;

			if (success) {
				_ansLength = cplex.getObjValue();
				for (int i = 0; i < _cityNum; i++)
					_ansCity[i] = cplex.getValues(x[i]);
			} else
				System.out.println("cplex.solve() failed.");

		} catch (IloException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	// 检查是否满足条件 绕圈走一遍
	public static boolean checkOpt() {
		System.out.println("check\n--------------");
		_setCGPool = new ArrayList<ArrayList<Integer>>();
		boolean[] flag = new boolean[_cityNum];
		for (int i = 0; i < _cityNum; i++) {
			if (flag[i])
				continue;
			_setCG = new ArrayList<Integer>();
			int st = i;
			int cnt = 0;
			System.out.println("\n");
			while (true) {
				System.out.print(st + " ");
				_setCG.add(st);
				flag[st] = true;
				for (int j = 0; j < _cityNum; j++) {
					if ((int) (_ansCity[st][j] + 0.00001) == 1) {
						st = j;
						break;
					}
				}
				cnt++;
				if (st == i || cnt >= _cityNum)
					break;
			}
			_setCGPool.add(new ArrayList<Integer>(_setCG));
		}
		if (_setCGPool.size() == 1) {
			System.out.println("\nsuccess");
			return true;
		} else {
			System.out.println("\nfail");
			return false;
		}
	}

	// 输出答案
	public static void WriteAns(String filename) {
		System.out.print(filename + "\n------------------------------\n");
		System.out.printf("rum time(sec)= %-10.2f\n", _time / 1000.0);
		System.out.printf("min= %-10.2f\n", _ansLength);
		for (int i = 0; i < _cityNum; i++) {
			for (int j = 0; j < _cityNum; j++)
				System.out.print((int) (_ansCity[i][j] + 0.00001) + " ");
			System.out.println();
		}
	}

	// 读取标准化后的数据
	public static void ReadData(String filename) {
		File file = new File(filename);
		BufferedReader reader = null;
		try {
			System.out.println("正在读取" + filename);
			reader = new BufferedReader(new FileReader(file));
			String tempString = null;
			tempString = reader.readLine();
			_cityNum = Integer.parseInt(tempString.trim());
			_cityDis = new double[_cityNum][_cityNum];
			for (int i = 0; i < _cityNum; i++) {
				tempString = reader.readLine();
				String[] arg = tempString.split(" ");
				for (int j = 0; j < arg.length; j++) {
					_cityDis[i][j] = Double.parseDouble(arg[j]);
					_cityDis[j][i] = _cityDis[i][j];
				}
			}

			reader.close();
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			if (reader != null) {
				try {
					reader.close();
				} catch (IOException e1) {
				}
			}
		}
	}
}

 

  • 0
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
要在Java调用Cplex求解TSP问题,您需要使用Cplex Java API。下面是一个简单的例子,演示如何使用Cplex Java API解决TSP问题: ```java import ilog.concert.*; import ilog.cplex.*; public class TSP { public static void main(String[] args) { int n = 4; // number of cities double[][] c = new double[n][n]; // cost matrix // fill in the cost matrix c[0][1] = 2; c[0][2] = 9; c[0][3] = 10; c[1][2] = 6; c[1][3] = 4; c[2][3] = 3; try { IloCplex cplex = new IloCplex(); // create variables IloNumVar[][] x = new IloNumVar[n][]; for (int i = 0; i < n; i++) { x[i] = cplex.boolVarArray(n); x[i][i].setLB(0); } // create objective function IloLinearNumExpr obj = cplex.linearNumExpr(); for (int i = 0; i < n; i++) { for (int j = 0; j < n; j++) { if (i != j) { obj.addTerm(c[i][j], x[i][j]); } } } cplex.addMinimize(obj); // add constraints for (int i = 0; i < n; i++) { IloLinearNumExpr expr = cplex.linearNumExpr(); for (int j = 0; j < n; j++) { if (i != j) { expr.addTerm(1, x[i][j]); } } cplex.addEq(expr, 1); } for (int j = 0; j < n; j++) { IloLinearNumExpr expr = cplex.linearNumExpr(); for (int i = 0; i < n; i++) { if (i != j) { expr.addTerm(1, x[i][j]); } } cplex.addEq(expr, 1); } // solve the problem if (cplex.solve()) { System.out.println("Solution status: " + cplex.getStatus()); System.out.println("Objective value: " + cplex.getObjValue()); for (int i = 0; i < n; i++) { for (int j = 0; j < n; j++) { if (i != j && cplex.getValue(x[i][j]) > 0.5) { System.out.println("Edge from " + i + " to " + j); } } } } else { System.out.println("No solution found"); } cplex.end(); } catch (IloException e) { System.err.println("Concert exception " + e); } } } ``` 在这个例子中,我们首先定义了一个包含4个城市的TSP问题,然后使用Cplex Java API建立模型,并求解该问题。该模型包括一个目标函数和两个约束条件。目标函数是所有边的代价的总和,约束条件确保每个城市恰好访问一次,并且每个城市离开恰好一次。最后,我们输出找到的最优解。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值