最近在学习运筹学,因此尝试使用c++调用cplex来求解一些经典运筹学模型,也是对最近知识 的一次总结,由于某些原因,目标函数就暂不列出了。
Cplex是IBM公司的通用数学模型求解工具,通过掌握一些特定的方法,可以在c++进行傻瓜式编辑数学模型,然后进行求解。
注释已经相对详细了,直接上代码:
#include
typedef IloArray NumVarMatrix;//声明二维变量矩阵,我要使用二维变量了。
ILOSTLBEGIN
using namespace std;
int main(){
IloEnv env;//定义环境
IloInt n,m;//定义n行m列二维变量,var_jk
IloModel model(env);//定义模型
NumVarMatrix var(env, n);//定义n行一维变量,var_j即为j行一维变量
IloRangeArray con(env);//定义约束条件组
IloObjective obj;//定义目标值
for (int j = 0; j < n; j++) {
var[j] = IloNumVarArray(env, m, 0, 1, ILOBOOL);//定义n列,整型二维变量var[j][k]
}
for (int j = 0; j < n; j++) {//此处我们将添加约束条件,以及复杂的约束条件表达式
con.add(IloRange(env, 1.0, 1.0));//约束条件j:空==1
IloNumExpr expr(env);//定义表达式
for (int k = 0; k < m + 1; k++) {//循环,将每个变量写入表达式,即sum(yjk)==1;
expr += var[j][k];
//给变量起个名吧:
string s = "y" + to_string(j + 1) + to_string(k);
const char* ss = s.c_str();
var[j][k].setName(ss);//命名
}
//将表达式放到约束条件j的“空”位置。
con[j].setExpr(expr);
}
//还可以再加一条约束:
con.add(IloRange(env, 0, m));// 0<= c<=m
IloExpr expr2(env);//写复杂表达式
for (int j = 0; j < wta.n; j++) {
for (int k = 0; k < wta.m + 1; k++) {
expr2 += var[j][k];
}
}
con[n].setExpr(expr2);//写入表达式给n约束。
//同样,obj也支持写入复杂表达式。
IloExpr expr3(env);
obj=IloMinimize(env,expr3)//极小值
//将模型、目标函数加入模型中
model.add(con);
model.add(obj);
IloCplex cplex(model)
cplex.solve();//求解
}
补充定义二维表达式的方法:
IloExprArray expr(env,n);//定义n维expr空句柄,仅有空句柄没有实际值,想要使用还需要赋值。
for (int i = 0; i < n; i++) {
expr[i] = IloExpr(env);//给句柄赋值,索引至第n个表达式。
}
补充逻辑判断(可以实现根据变量不同取值有不同的表达式):
IloExpr expr(env);
//使用()表达判断
expr +=(var[i][j]==1)*cost[0]+(var[i][j]>=2)*(1+cost[1]*(var[i][j]-1))//分段函数
补充修改变量、目标函数和约束的方法
#使用如下添加方法:
IloObjective obj= IloAdd(model, IloMinimize(env, e1, "obj1"));
#多目标添加方法:
IloObjective obj=IloAdd(model, IloMinimize(env, IloStaticLex(env, e1, e2), "obj1"))
#调用remove方法移除并重新添加即可。
model.remove(var);
model.remove(obj);
model.remove(con);