从本期开始阅读开源求解器coin_or的源码。整体项目介绍见https://blog.csdn.net/kittyzc/article/details/100182189
第一篇从clp开始。
首先是简单的调用测试,在mac上首先安装clp的库:brew install coin-or-tools/coinor/clp
,然后新建项目进行调用,各项配置如下:
使用这种方法没有办法debug细节。
>>> Clp
>>> Clp:import p0033.mps
>>> Clp: dualS
>>> Clp: solu sol.txt
或者干脆写成一行:
>>> clp p0033.mps -primalS
Coin LP version 1.17.3, build Dec 4 2020
command line - clp p0033.mps -primalS
At line 15 NAME P0033
At line 16 ROWS
At line 34 COLUMNS
At line 109 RHS
At line 118 BOUNDS
At line 152 ENDATA
Problem P0033 has 16 rows, 33 columns and 98 elements
Model was imported from ./p0033.mps in 0.000231 seconds
Presolve 15 (-1) rows, 32 (-1) columns and 97 (-1) elements
0 Obj 0 Primal inf 18.49249 (10) Dual inf 5.5987499e+11 (32)
26 Obj 2520.5717
Optimal - objective value 2520.5717
After Postsolve, objective 2520.5717, infeasibilities - dual 0 (0), primal 0 (0)
Optimal objective 2520.571739 - 26 iterations time 0.002, Presolve 0.00
关键词清单如下:
allS(lack) barr(ier) basisI(n) basisO(ut) directory dualS(implex)
either(Simplex) end exit export gsolu(tion) guess import max(imize) min(imize)
para(metrics) primalS(implex) printM(ask) quit restoreS(olution) saveS(olution)
solu(tion) solv(e) stat(istics) stop
调用求解的函数为primal(),求解后的信息可以通过下列函数获取:
// Get row status...
Status status=model.getRowStatus(sequenceNumber)
// ... or get column status.
Status status=model.getColumnStatus(sequenceNumber)
// Set row status to basic (for example)...
model.setRowStatus(sequenceNumber,ClpSimplex::basic)
// ... or column status to basic.
model.setColumnStatus(sequenceNumber,ClpSimplex::basic)
在prime simplex中,任何非基变量都可以用作pivot;在dual simplex中,任何基变量都可以用于pivot。
对于dual simplex,基础类叫做ClpDualRowPivot,实现的两个instances是ClpDualRowDantzig 和 ClpDualRowSteepest。
调用方法如下:
ClpDualRowSteepest steep(1); // 0 uninitialized, 1 compute weights
model.setDualRowPivotAlgorithm(steep);
如果全是正负1,可以用ClpPlusMinusOneMatrix。建立一个CoinPackedMatrix的instance:matrix,调用方法如下:
ClpPlusMinusOneMatrix plusMinus(matrix);
assert (plusMinus.getIndices()); // would be zero if not +- one
model.loadProblem(plusMinus, lowerColumn,upperColumn, objective, lower,upper);
对于网络流问题,每一列只有一个参数,可以用ClpNetworkMatrix,调用方法如下:
ClpNetworkMatrix network(numberColumns,head,tail);
model.loadProblem(network, lowerColumn, upperColumn, objective, lower, upper);
此时clp会使用网络流的方法去求解。
如果什么都不想打印,可以设置model.setLogLevel(int value)中的value为0。
也可以自定义文件日志:
FILE * fp; // assumed open
CoinMessageHandler handler(fp);
model.passInMessageHandler(&handler);
按照说明文档进行分类说明:
/* Status of problem:
0 - optimal
1 - primal infeasible
2 - dual infeasible
3 - stopped on iterations etc
4 - stopped due to errors
*/
std::cout << "Model status is " << model.status()
ClpSolve solvectl;
solvectl.setSolveType(ClpSolve::useDual);
# solvectl.setSolveType(ClpSolve::useBarrier);
solvectl.setPresolveType(ClpSolve::presolveOn);
model.initialSolve(solvectl);
ClpSimplex model;
CoinPackedMatrix matrix;
int * lengths = NULL;
matrix.assignMatrix(true, numberRows, numberColumns, 2 * numberColumns, element, row, start, lengths);
ClpNetworkMatrix network(matrix);
model.loadProblem(network, lowerColumn, upperColumn, objective,
lower, upper);
ClpInterior model;
int status = model.readMps( "../p0033.mps", true);
ClpCholeskyDense * cholesky = new ClpCholeskyDense();
model.setCholesky(cholesky);
model.primalDual();
// crossover的后处理算法,保证用内点法求解到的是一个顶点,而且是最近的那个顶点。
ClpSimplex model2(model);
model2.createStatus();
model2.primal(1);