问题介绍
给定一个大小不等的整数集合,问是否可以把这些整数划分成两个集合,任何一个整数或者在集合S1中或者在S2中,但不能同时在两个集合中;对任意给的一个整数集合,请设计算法,解决是否存在一个划分,使得S1种整数之和恰好等于S2集合的整数之和。
数学模型
leapms介绍
使用Java+cplex求解问题前,先介绍一种全新且高效的建模工具——Leapms。
Leapms 是一个用于求解整数规划的免费建模语言,具备简洁的建模过程。Leapms 语言设计的原则包括:(1)采用描述性语言形式;(2)尽力与模型的数学表达形式一致。leapms软件应用网站:https://www.cnblogs.com/leapms/
语言开发者:陆教授(yplu@bjtu.edu.cn)
数据定义
// 数据参数定义
class DataParition{
// 整数集合
double[] partSet={11,47,159,137,85,47,142,35,119,61,88,175,13,96,-11,176,126,15,98,46,163};
// 数量
int setNumber=partSet.length;
}
问题建模
public class PartitionDemo {
// 定义数据
DataParition data;
public PartitionDemo(DataParition data){
this.data=data;
}
// 定义cplex内部对象
IloCplex model;
// 定义变量
public IloNumVar[] x;
public IloNumVar[] d;
// 求解函数
public void solve() throws IloException {
if(model.solve()==false){
// 模型不可解
System.out.println("模型不可解");
return;
}
else{
System.out.println("目标值:"+model.getObjValue());
System.out.println("=========集合1===========");
double num1=0;
for(int i=0;i<data.setNumber;i++){
if(model.getValue(x[i])!=0) {
num1+=data.partSet[i];
System.out.print(data.partSet[i]+"\t");
}
}
System.out.print("\n 集合1元素之和为:"+num1);
System.out.println();
System.out.println("=========集合2===========");
double num2=0;
for(int i=0;i<data.setNumber;i++){
if(model.getValue(x[i])==0) {
num2+=data.partSet[i];
System.out.print(data.partSet[i]+"\t");
}
}
System.out.print("\n 集合2元素之和为:"+num2);
}
}
// 根据数学模型建立求解模型
public void BuildModel() throws IloException{
// model
model = new IloCplex();
model.setOut(null);
// variables
x = new IloNumVar[data.setNumber];
d = new IloNumVar[1];
// 定义cplex变量x和d的数据类型及取值范围
for(int i=0;i<data.setNumber;i++){
x[i]=model.numVar(0,1, IloNumVarType.Int,"x["+i+"]");
}
for(int i=0;i<1;i++) {
d[i] = model.numVar(0, 1e15, IloNumVarType.Float, "d["+i+"]");
}
// 设置目标函数
model.addMinimize(d[0]);
// 集合元素之和计算
IloNumExpr expr01 = model.numExpr();
IloNumExpr expr02 = model.numExpr();
for(int i=0;i<data.setNumber;i++){
expr01=model.sum(expr01,model.prod(x[i],data.partSet[i]));
expr02=model.sum(expr02,model.prod(data.partSet[i],model.sum(1,model.prod(-1,x[i]))));
}
// 添加约束1
IloNumExpr expr1 = model.numExpr();
expr1=model.sum(expr01,model.prod(-1,expr02));
model.addGe(d[0],expr1);
// 添加约束2
IloNumExpr expr2 = model.numExpr();
expr2=model.sum(expr02,model.prod(-1,expr01));
model.addGe(d[0],expr2);
}
问题求解
public static void main(String[] args)throws IloException{
DataParition data =new DataParition();
PartitionDemo lp=new PartitionDemo(data);
lp.BuildModel();
lp.solve();
}
求解结果
=======================================
今天到此为止,后续记录其他cplex技术的学习过程。
以上学习笔记,如有侵犯,请立即联系并删除!