├── Cplex-Java-API.md ├── Cplex-Parameters-Reference.pdf ├── README.md ├── examples ├── AdMIPex1.java ├── AdMIPex2.java ├── AdMIPex3.java ├── AdMIPex4.java ├── AdMIPex5.java ├── AdMIPex6.java ├── AdMIPex8.java ├── AdMIPex9.java ├── Benders.java ├── BendersAtsp.java ├── BendersAtsp2.java ├── CplexServer.java ├── CutStock.java ├── Diet.java ├── Etsp.java ├── Facility.java ├── FixCost1.java ├── FixNet.java ├── GlobalQPex1.java ├── Goalex1.java ├── Goalex2.java ├── Goalex3.java ├── IndefQPex1.java ├── InputDataReader.java ├── LPex1.java ├── LPex3.java ├── LPex4.java ├── LPex6.java ├── LPex7.java ├── MIPex3.java ├── MIPex4.java ├── Populate.java ├── QCPDual.java ├── QPex3.java ├── SocpEx1.java ├── Transport.java ├── TuneSet.java └── Warehouse.java └── pictures ├── Expressions常用函数.png ├── IloRange的常用函数.png ├── callback_method ├── LazyConstraintCallback.png ├── SolveCallback.png └── UserCutCallback.png ├── context_method.png └── java_api_setting ├── Djava_library_path1.png ├── Djava_library_path2.png ├── finally.png ├── import_cplex_jar1.png ├── import_cplex_jar2.png ├── import_cplex_jar3.png ├── javadoc1.png ├── javadoc2.png ├── javadoc_setting1.png └── javadoc_setting2.png /Cplex-Java-API.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiongwq16/cplex-java-api-tutorial-zh/0a57ebead18ee40cc505af1fc14328dd8bde94c9/Cplex-Java-API.md -------------------------------------------------------------------------------- /Cplex-Parameters-Reference.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiongwq16/cplex-java-api-tutorial-zh/0a57ebead18ee40cc505af1fc14328dd8bde94c9/Cplex-Parameters-Reference.pdf -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # cplex-java-api-tutorial-zh 2 | 3 | ## Introduction 4 | Cplex tutorial in Chinese, contains: 5 | * [Java API learning summary](Cplex-Java-API.md) 6 | * [official examples](examples) 7 | * [parameters references](Cplex-Parameters-Reference.pdf) 8 | 9 | 10 | ## License 11 | * The [code](examples) in examples directory is from IBM's Cplex official examples. 12 | * The parameters references is from IBM's Cplex official documents. 13 | * The content of this project(except the examples and parameters references) is licensed under the [Attribution-NonCommercial 4.0 International](https://creativecommons.org/licenses/by-nc/4.0/). 14 | -------------------------------------------------------------------------------- /examples/AdMIPex1.java: -------------------------------------------------------------------------------- 1 | package examples; 2 | 3 | /* -------------------------------------------------------------------------- 4 | * File: AdMIPex1.java 5 | * Version 12.9.0 6 | * -------------------------------------------------------------------------- 7 | * Licensed Materials - Property of IBM 8 | * 5725-A06 5725-A29 5724-Y48 5724-Y49 5724-Y54 5724-Y55 5655-Y21 9 | * Copyright IBM Corporation 2001, 2019. All Rights Reserved. 10 | * 11 | * US Government Users Restricted Rights - Use, duplication or 12 | * disclosure restricted by GSA ADP Schedule Contract with 13 | * IBM Corp. 14 | * -------------------------------------------------------------------------- 15 | * 16 | * AdMIPex1.java -- Use the node and branch callbacks to optimize 17 | * a MIP problem 18 | * 19 | * To run this example, command line arguments are required. 20 | * i.e., java AdMIPex1 filename 21 | * 22 | * Example: 23 | * java AdMIPex1 example.mps 24 | */ 25 | 26 | import ilog.concert.*; 27 | import ilog.cplex.*; 28 | 29 | public class AdMIPex1 { 30 | static class MyBranch extends IloCplex.BranchCallback { 31 | IloNumVar[] _vars; 32 | 33 | MyBranch(IloNumVar[] vars) { 34 | _vars = vars; 35 | } 36 | 37 | public void main() throws IloException { 38 | if (!getBranchType().equals(IloCplex.BranchType.BranchOnVariable)) 39 | return; 40 | 41 | // Branch on var with largest objective coefficient 42 | // among those with largest infeasibility 43 | double[] x = getValues(_vars); 44 | double[] obj = getObjCoefs(_vars); 45 | IloCplex.IntegerFeasibilityStatus[] feas = getFeasibilities(_vars); 46 | 47 | double maxinf = 0.0; 48 | double maxobj = 0.0; 49 | int bestj = -1; 50 | int cols = _vars.length; 51 | for (int j = 0; j < cols; ++j) { 52 | if (feas[j].equals(IloCplex.IntegerFeasibilityStatus.Infeasible)) { 53 | double xj_inf = x[j] - Math.floor(x[j]); 54 | if (xj_inf > 0.5) 55 | xj_inf = 1.0 - xj_inf; 56 | 57 | // 选择距离整数最远的变量进行分支(如果有多个则选择其中最大目标函数系数最大的变量) 58 | if (xj_inf >= maxinf && (xj_inf > maxinf || Math.abs(obj[j]) >= maxobj)) { 59 | bestj = j; 60 | maxinf = xj_inf; 61 | maxobj = Math.abs(obj[j]); 62 | } 63 | } 64 | } 65 | 66 | if (bestj >= 0) { 67 | // 添加分支,可以以数组形式批量添加 68 | makeBranch(_vars[bestj], x[bestj], IloCplex.BranchDirection.Up, getObjValue()); 69 | makeBranch(_vars[bestj], x[bestj], IloCplex.BranchDirection.Down, getObjValue()); 70 | } 71 | } 72 | } 73 | 74 | static class MySelect extends IloCplex.NodeCallback { 75 | public void main() throws IloException { 76 | // 获取tree中激活的节点数量 77 | long remainingNodes = getNremainingNodes64(); 78 | long bestnode = -1; 79 | int maxdepth = -1; 80 | double maxiisum = 0.0; 81 | 82 | // 选择违反整数约束最多(非整数变量最多)的节点 83 | for (long i = 0; i < remainingNodes; ++i) { 84 | int depth = getDepth(i); 85 | // 获取不满足整数约束的变量的数量 86 | double iisum = getInfeasibilitySum(i); 87 | if ((depth >= maxdepth) && (depth > maxdepth || iisum > maxiisum)) { 88 | bestnode = i; 89 | maxdepth = depth; 90 | maxiisum = iisum; 91 | } 92 | } 93 | if (bestnode >= 0) 94 | selectNode(bestnode); 95 | } 96 | } 97 | 98 | public static void main(String[] args) { 99 | if (args.length != 1) { 100 | System.out.println("Usage: AdMIPex1 filename"); 101 | System.out.println(" where filename is a file with extension "); 102 | System.out.println(" MPS, SAV, or LP (lower case is allowed)"); 103 | System.out.println(" Exiting..."); 104 | System.exit(-1); 105 | } 106 | 107 | try { 108 | IloCplex cplex = new IloCplex(); 109 | 110 | cplex.importModel(args[0]); 111 | IloLPMatrix lp = (IloLPMatrix) cplex.LPMatrixIterator().next(); 112 | 113 | // 使用use调用callBack类函数 114 | cplex.use(new MyBranch(lp.getNumVars())); 115 | cplex.use(new MySelect()); 116 | 117 | // 设置搜索策略 118 | // Traditional: Use traditional branch-and-cut search. 119 | cplex.setParam(IloCplex.Param.MIP.Strategy.Search, IloCplex.MIPSearch.Traditional); 120 | if (cplex.solve()) { 121 | System.out.println("Solution status = " + cplex.getStatus()); 122 | System.out.println("Solution value = " + cplex.getObjValue()); 123 | } 124 | cplex.end(); 125 | } catch (IloException e) { 126 | System.err.println("Concert exception caught: " + e); 127 | } 128 | } 129 | } 130 | -------------------------------------------------------------------------------- /examples/AdMIPex2.java: -------------------------------------------------------------------------------- 1 | package examples; 2 | 3 | /* -------------------------------------------------------------------------- 4 | * File: AdMIPex2.java 5 | * Version 12.9.0 6 | * -------------------------------------------------------------------------- 7 | * Licensed Materials - Property of IBM 8 | * 5725-A06 5725-A29 5724-Y48 5724-Y49 5724-Y54 5724-Y55 5655-Y21 9 | * Copyright IBM Corporation 2001, 2019. All Rights Reserved. 10 | * 11 | * US Government Users Restricted Rights - Use, duplication or 12 | * disclosure restricted by GSA ADP Schedule Contract with 13 | * IBM Corp. 14 | * -------------------------------------------------------------------------- 15 | * 16 | * AdMIPex2.java - Use the heuristic callback for optimizing a MIP problem 17 | * 18 | * To run this example, command line arguments are required. 19 | * i.e., java AdMIPex2 filename 20 | * 21 | * Example: 22 | * java AdMIPex2 example.mps 23 | */ 24 | 25 | import ilog.concert.*; 26 | import ilog.cplex.*; 27 | 28 | public class AdMIPex2 { 29 | static class RoundDown extends IloCplex.HeuristicCallback { 30 | IloNumVar[] _vars; 31 | 32 | RoundDown(IloNumVar[] vars) { 33 | _vars = vars; 34 | } 35 | 36 | public void main() throws IloException { 37 | double[] obj = getObjCoefs(_vars); 38 | double[] x = getValues(_vars); 39 | IloCplex.IntegerFeasibilityStatus[] feas = getFeasibilities(_vars); 40 | 41 | double objval = getObjValue(); 42 | int cols = _vars.length; 43 | for (int j = 0; j < cols; j++) { 44 | // Set the fractional variable to zero and update the objective value 45 | if (feas[j].equals(IloCplex.IntegerFeasibilityStatus.Infeasible)) { 46 | objval -= x[j] * obj[j]; 47 | x[j] = 0.0; 48 | } 49 | } 50 | setSolution(_vars, x, objval); 51 | } 52 | } 53 | 54 | public static void main(String[] args) { 55 | if (args.length != 1) { 56 | System.out.println("Usage: AdMIPex2 filename"); 57 | System.out.println(" where filename is a file with extension "); 58 | System.out.println(" MPS, SAV, or LP (lower case is allowed)"); 59 | System.out.println(" Exiting..."); 60 | System.exit(-1); 61 | } 62 | 63 | try { 64 | IloCplex cplex = new IloCplex(); 65 | 66 | cplex.importModel(args[0]); 67 | 68 | // Check model is all binary except for objective constant variable 69 | if (cplex.getNbinVars() < cplex.getNcols() - 1) { 70 | System.err.println("Problem contains non-binary variables, exiting."); 71 | System.exit(-1); 72 | } 73 | 74 | // 获取问题矩阵 75 | IloLPMatrix lp = (IloLPMatrix) cplex.LPMatrixIterator().next(); 76 | 77 | cplex.use(new RoundDown(lp.getNumVars())); 78 | 79 | cplex.setParam(IloCplex.Param.MIP.Strategy.Search, IloCplex.MIPSearch.Traditional); 80 | if (cplex.solve()) { 81 | System.out.println("Solution status = " + cplex.getStatus()); 82 | System.out.println("Solution value = " + cplex.getObjValue()); 83 | } 84 | cplex.end(); 85 | } catch (IloException e) { 86 | System.err.println("Concert exception caught: " + e); 87 | } 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /examples/AdMIPex3.java: -------------------------------------------------------------------------------- 1 | package examples; 2 | 3 | /* -------------------------------------------------------------------------- 4 | * File: AdMIPex3.java 5 | * Version 12.9.0 6 | * -------------------------------------------------------------------------- 7 | * Licensed Materials - Property of IBM 8 | * 5725-A06 5725-A29 5724-Y48 5724-Y49 5724-Y54 5724-Y55 5655-Y21 9 | * Copyright IBM Corporation 2001, 2019. All Rights Reserved. 10 | * 11 | * US Government Users Restricted Rights - Use, duplication or 12 | * disclosure restricted by GSA ADP Schedule Contract with 13 | * IBM Corp. 14 | * -------------------------------------------------------------------------- 15 | * 16 | * AdMIPex3.java - Using the branch callback for optimizing a MIP 17 | * problem with Special Ordered Sets Type 1, with 18 | * all the variables binary 19 | * 20 | * To run this example, command line arguments are required. 21 | * i.e., AdMIPex3 filename 22 | * 23 | * Example: 24 | * java AdMIPex3 example.mps 25 | */ 26 | 27 | import ilog.concert.*; 28 | import ilog.cplex.*; 29 | import java.util.Iterator; 30 | 31 | public class AdMIPex3 extends Object { 32 | static double EPS = 1.0e-4; 33 | 34 | public static class SOSbranch extends IloCplex.BranchCallback { 35 | IloSOS1[] _sos; 36 | 37 | public SOSbranch(IloSOS1[] sos) { 38 | _sos = sos; 39 | } 40 | 41 | public void main() throws IloException { 42 | double bestx = EPS; 43 | int besti = -1; 44 | int bestj = -1; 45 | int num = _sos.length; 46 | 47 | IloNumVar[] var = null; 48 | double[] x = null; 49 | 50 | for (int i = 0; i < num; ++i) { 51 | if (getSOSFeasibility(_sos[i]).equals(IloCplex.IntegerFeasibilityStatus.Infeasible)) { 52 | var = _sos[i].getNumVars(); 53 | x = getValues(var); 54 | 55 | int n = var.length; 56 | for (int j = 0; j < n; ++j) { 57 | double inf = Math.abs(x[j] - Math.round(x[j])); 58 | if (inf > bestx) { 59 | bestx = inf; 60 | besti = i; 61 | bestj = j; 62 | } 63 | } 64 | } 65 | } 66 | 67 | if (besti >= 0) { 68 | var = _sos[besti].getNumVars(); 69 | int n = var.length; 70 | 71 | IloCplex.BranchDirection[] dir = new IloCplex.BranchDirection[n]; 72 | double[] val = new double[n]; 73 | 74 | for (int j = 0; j < n; ++j) { 75 | if (j != bestj) { 76 | dir[j] = IloCplex.BranchDirection.Down; 77 | val[j] = 0.0; 78 | } else { 79 | dir[j] = IloCplex.BranchDirection.Up; 80 | val[j] = 1.0; 81 | } 82 | } 83 | makeBranch(var, val, dir, getObjValue()); 84 | makeBranch(var[bestj], 0.0, IloCplex.BranchDirection.Down, getObjValue()); 85 | } 86 | } 87 | } 88 | 89 | @SuppressWarnings("rawtypes") 90 | public static void main(String[] args) { 91 | if (args.length != 1) { 92 | System.out.println("Usage: AdMIPex1 filename"); 93 | System.out.println(" where filename is a file with extension "); 94 | System.out.println(" MPS, SAV, or LP (lower case is allowed)"); 95 | System.out.println(" Exiting..."); 96 | System.exit(-1); 97 | } 98 | 99 | try { 100 | IloCplex cplex = new IloCplex(); 101 | 102 | cplex.importModel(args[0]); 103 | 104 | if (cplex.getNSOS1() > 0) { 105 | IloSOS1[] sos1 = new IloSOS1[cplex.getNSOS1()]; 106 | int i = 0; 107 | for (Iterator sosit = cplex.SOS1iterator(); sosit.hasNext(); ++i) { 108 | sos1[i] = (IloSOS1) sosit.next(); 109 | } 110 | cplex.use(new SOSbranch(sos1)); 111 | System.out.println("using SOS branch callback for " + sos1.length + " SOS1s"); 112 | } 113 | 114 | cplex.setParam(IloCplex.Param.MIP.Strategy.Search, IloCplex.MIPSearch.Traditional); 115 | if (cplex.solve()) { 116 | System.out.println("Solution status = " + cplex.getStatus()); 117 | System.out.println("Solution value = " + cplex.getObjValue()); 118 | } 119 | cplex.end(); 120 | } catch (IloException exc) { 121 | System.err.println("Concert exception caught: " + exc); 122 | } 123 | } 124 | } 125 | -------------------------------------------------------------------------------- /examples/AdMIPex4.java: -------------------------------------------------------------------------------- 1 | package examples; 2 | /* -------------------------------------------------------------------------- 3 | * File: AdMIPex4.java 4 | * Version 12.9.0 5 | * -------------------------------------------------------------------------- 6 | * Licensed Materials - Property of IBM 7 | * 5725-A06 5725-A29 5724-Y48 5724-Y49 5724-Y54 5724-Y55 5655-Y21 8 | * Copyright IBM Corporation 2001, 2019. All Rights Reserved. 9 | * 10 | * US Government Users Restricted Rights - Use, duplication or 11 | * disclosure restricted by GSA ADP Schedule Contract with 12 | * IBM Corp. 13 | * -------------------------------------------------------------------------- 14 | * 15 | * AdMIPex4.java -- Solving noswot by adding cuts. 16 | * 17 | * This example solves the MIPLIB 3.0 model noswot.mps by adding user cuts 18 | * and lazy constraints. The example adds these cuts to the cut table before 19 | * the branch-and-cut process begins. For an example that dynamically 20 | * separates user cuts and lazy constraints from a callback during the 21 | * branch-and-cut process, see AdMIPex5.java. 22 | * 23 | * When this example is run the program reads a problem from a file named 24 | * "noswot.mps" either from the directory ../../data, if no argument is 25 | * present, or from the directory that is specified as the first (and only) 26 | * argument to the executable. 27 | */ 28 | 29 | import java.nio.file.Path; 30 | import java.nio.file.Paths; 31 | 32 | import ilog.concert.*; 33 | import ilog.cplex.*; 34 | 35 | 36 | public class AdMIPex4 { 37 | public static IloRange[] makeCuts(IloModeler m, IloLPMatrix lp) 38 | throws IloException { 39 | IloNumVar x11 = null, x12 = null, x13 = null, x14 = null, x15 = null; 40 | IloNumVar x21 = null, x22 = null, x23 = null, x24 = null, x25 = null; 41 | IloNumVar x31 = null, x32 = null, x33 = null, x34 = null, x35 = null; 42 | IloNumVar x41 = null, x42 = null, x43 = null, x44 = null, x45 = null; 43 | IloNumVar x51 = null, x52 = null, x53 = null, x54 = null, x55 = null; 44 | IloNumVar w11 = null, w12 = null, w13 = null, w14 = null, w15 = null; 45 | IloNumVar w21 = null, w22 = null, w23 = null, w24 = null, w25 = null; 46 | IloNumVar w31 = null, w32 = null, w33 = null, w34 = null, w35 = null; 47 | IloNumVar w41 = null, w42 = null, w43 = null, w44 = null, w45 = null; 48 | IloNumVar w51 = null, w52 = null, w53 = null, w54 = null, w55 = null; 49 | 50 | IloNumVar[] vars = lp.getNumVars(); 51 | int num = vars.length; 52 | 53 | for (int i = 0; i < num; ++i) { 54 | if (vars[i].getName().equals("X11")) x11 = vars[i]; 55 | else if (vars[i].getName().equals("X12")) x12 = vars[i]; 56 | else if (vars[i].getName().equals("X13")) x13 = vars[i]; 57 | else if (vars[i].getName().equals("X14")) x14 = vars[i]; 58 | else if (vars[i].getName().equals("X15")) x15 = vars[i]; 59 | else if (vars[i].getName().equals("X21")) x21 = vars[i]; 60 | else if (vars[i].getName().equals("X22")) x22 = vars[i]; 61 | else if (vars[i].getName().equals("X23")) x23 = vars[i]; 62 | else if (vars[i].getName().equals("X24")) x24 = vars[i]; 63 | else if (vars[i].getName().equals("X25")) x25 = vars[i]; 64 | else if (vars[i].getName().equals("X31")) x31 = vars[i]; 65 | else if (vars[i].getName().equals("X32")) x32 = vars[i]; 66 | else if (vars[i].getName().equals("X33")) x33 = vars[i]; 67 | else if (vars[i].getName().equals("X34")) x34 = vars[i]; 68 | else if (vars[i].getName().equals("X35")) x35 = vars[i]; 69 | else if (vars[i].getName().equals("X41")) x41 = vars[i]; 70 | else if (vars[i].getName().equals("X42")) x42 = vars[i]; 71 | else if (vars[i].getName().equals("X43")) x43 = vars[i]; 72 | else if (vars[i].getName().equals("X44")) x44 = vars[i]; 73 | else if (vars[i].getName().equals("X45")) x45 = vars[i]; 74 | else if (vars[i].getName().equals("X51")) x51 = vars[i]; 75 | else if (vars[i].getName().equals("X52")) x52 = vars[i]; 76 | else if (vars[i].getName().equals("X53")) x53 = vars[i]; 77 | else if (vars[i].getName().equals("X54")) x54 = vars[i]; 78 | else if (vars[i].getName().equals("X55")) x55 = vars[i]; 79 | else if (vars[i].getName().equals("W11")) w11 = vars[i]; 80 | else if (vars[i].getName().equals("W12")) w12 = vars[i]; 81 | else if (vars[i].getName().equals("W13")) w13 = vars[i]; 82 | else if (vars[i].getName().equals("W14")) w14 = vars[i]; 83 | else if (vars[i].getName().equals("W15")) w15 = vars[i]; 84 | else if (vars[i].getName().equals("W21")) w21 = vars[i]; 85 | else if (vars[i].getName().equals("W22")) w22 = vars[i]; 86 | else if (vars[i].getName().equals("W23")) w23 = vars[i]; 87 | else if (vars[i].getName().equals("W24")) w24 = vars[i]; 88 | else if (vars[i].getName().equals("W25")) w25 = vars[i]; 89 | else if (vars[i].getName().equals("W31")) w31 = vars[i]; 90 | else if (vars[i].getName().equals("W32")) w32 = vars[i]; 91 | else if (vars[i].getName().equals("W33")) w33 = vars[i]; 92 | else if (vars[i].getName().equals("W34")) w34 = vars[i]; 93 | else if (vars[i].getName().equals("W35")) w35 = vars[i]; 94 | else if (vars[i].getName().equals("W41")) w41 = vars[i]; 95 | else if (vars[i].getName().equals("W42")) w42 = vars[i]; 96 | else if (vars[i].getName().equals("W43")) w43 = vars[i]; 97 | else if (vars[i].getName().equals("W44")) w44 = vars[i]; 98 | else if (vars[i].getName().equals("W45")) w45 = vars[i]; 99 | else if (vars[i].getName().equals("W51")) w51 = vars[i]; 100 | else if (vars[i].getName().equals("W52")) w52 = vars[i]; 101 | else if (vars[i].getName().equals("W53")) w53 = vars[i]; 102 | else if (vars[i].getName().equals("W54")) w54 = vars[i]; 103 | else if (vars[i].getName().equals("W55")) w55 = vars[i]; 104 | } 105 | 106 | IloRange[] cut = new IloRange[8]; 107 | 108 | cut[0] = m.le(m.diff(x21, x22), 0.0); 109 | cut[1] = m.le(m.diff(x22, x23), 0.0); 110 | cut[2] = m.le(m.diff(x23, x24), 0.0); 111 | cut[3] = m.le(m.sum(m.sum(m.prod(2.08, x11), 112 | m.prod(2.98, x21), 113 | m.prod(3.47, x31), 114 | m.prod(2.24, x41), 115 | m.prod(2.08, x51)), 116 | m.sum(m.prod(0.25, w11), 117 | m.prod(0.25, w21), 118 | m.prod(0.25, w31), 119 | m.prod(0.25, w41), 120 | m.prod(0.25, w51))), 20.25); 121 | cut[4] = m.le(m.sum(m.sum(m.prod(2.08, x12), 122 | m.prod(2.98, x22), 123 | m.prod(3.47, x32), 124 | m.prod(2.24, x42), 125 | m.prod(2.08, x52)), 126 | m.sum(m.prod(0.25, w12), 127 | m.prod(0.25, w22), 128 | m.prod(0.25, w32), 129 | m.prod(0.25, w42), 130 | m.prod(0.25, w52))), 20.25); 131 | cut[5] = m.le(m.sum(m.sum(m.prod(2.08, x13), 132 | m.prod(2.98, x23), 133 | m.prod(3.47, x33), 134 | m.prod(2.24, x43), 135 | m.prod(2.08, x53)), 136 | m.sum(m.prod(0.25, w13), 137 | m.prod(0.25, w23), 138 | m.prod(0.25, w33), 139 | m.prod(0.25, w43), 140 | m.prod(0.25, w53))), 20.25); 141 | cut[6] = m.le(m.sum(m.sum(m.prod(2.08, x14), 142 | m.prod(2.98, x24), 143 | m.prod(3.47, x34), 144 | m.prod(2.24, x44), 145 | m.prod(2.08, x54)), 146 | m.sum(m.prod(0.25, w14), 147 | m.prod(0.25, w24), 148 | m.prod(0.25, w34), 149 | m.prod(0.25, w44), 150 | m.prod(0.25, w54))), 20.25); 151 | cut[7] = m.le(m.sum(m.sum(m.prod(2.08, x15), 152 | m.prod(2.98, x25), 153 | m.prod(3.47, x35), 154 | m.prod(2.24, x45), 155 | m.prod(2.08, x55)), 156 | m.sum(m.prod(0.25, w15), 157 | m.prod(0.25, w25), 158 | m.prod(0.25, w35), 159 | m.prod(0.25, w45), 160 | m.prod(0.25, w55))), 16.25); 161 | 162 | return cut; 163 | } 164 | 165 | public static void main(String[] args) { 166 | IloCplex cplex = null; 167 | try { 168 | cplex = new IloCplex(); 169 | 170 | String dataDir = "./data"; 171 | if (args.length >= 1) 172 | dataDir = args[0]; 173 | Path fileName = Paths.get(dataDir, "noswot.mps"); 174 | cplex.importModel(fileName.toString()); 175 | 176 | IloLPMatrix lp = (IloLPMatrix)cplex.LPMatrixIterator().next(); 177 | 178 | // Use addUserCuts when the added constraints strengthen the 179 | // formulation but do not change the integer feasible region. 180 | // Use addLazyConstraints when the added constraints remove part of 181 | // the integer feasible region. 182 | // In the latter case, you can also add the cuts as user cuts AND 183 | // lazy constraints (this is done here). This may improve 184 | // performance in some cases. 185 | IloRange[] cuts = makeCuts(cplex, lp); 186 | cplex.addUserCuts(cuts); 187 | cplex.addLazyConstraints(cuts); 188 | 189 | cplex.setParam(IloCplex.Param.MIP.Interval, 1000); 190 | if (cplex.solve()) { 191 | System.out.println("Solution status = " + cplex.getStatus()); 192 | System.out.println("Solution value = " + cplex.getObjValue()); 193 | } 194 | } 195 | catch (IloException e) { 196 | throw new RuntimeException("Concert exception caught", e); 197 | } 198 | finally { 199 | if (cplex != null) 200 | cplex.end(); 201 | } 202 | } 203 | } 204 | -------------------------------------------------------------------------------- /examples/AdMIPex5.java: -------------------------------------------------------------------------------- 1 | package examples; 2 | 3 | 4 | /* -------------------------------------------------------------------------- 5 | * File: AdMIPex5.java 6 | * Version 12.9.0 7 | * -------------------------------------------------------------------------- 8 | * Licensed Materials - Property of IBM 9 | * 5725-A06 5725-A29 5724-Y48 5724-Y49 5724-Y54 5724-Y55 5655-Y21 10 | * Copyright IBM Corporation 2001, 2019. All Rights Reserved. 11 | * 12 | * US Government Users Restricted Rights - Use, duplication or 13 | * disclosure restricted by GSA ADP Schedule Contract with 14 | * IBM Corp. 15 | * -------------------------------------------------------------------------- 16 | */ 17 | 18 | import ilog.concert.*; 19 | import ilog.cplex.*; 20 | import java.io.File; 21 | import java.util.Vector; 22 | 23 | /** 24 | * Solve a facility location problem with cut callbacks or lazy constraints. 25 | * 26 | * Given a set of locations J and a set of clients C, the following model is 27 | * solved: 28 | * 29 | * Minimize sum(j in J) fixedCost[j]*used[j] + sum(j in J)sum(c in C) 30 | * cost[c][j]*supply[c][j] Subject to sum(j in J) supply[c][j] == 1 for all c in 31 | * C sum(c in C) supply[c][j] <= (|C| - 1) * used[j] for all j in J supply[c][j] 32 | * in {0, 1} for all c in C, j in J used[j] in {0, 1} for all j in J 33 | * 34 | * In addition to the constraints stated above, the code also separates a 35 | * disaggregated version of the capacity constraints (see comments for the cut 36 | * callback) to improve performance. 37 | * 38 | * Optionally, the capacity constraints can be separated from a lazy constraint 39 | * callback instead of being stated as part of the initial model. 40 | * 41 | * See the usage message for how to switch between these options. 42 | */ 43 | public class AdMIPex5 { 44 | /** Epsilon used for violation of cuts. */ 45 | private static double EPS = 1.0e-6; 46 | 47 | /** 48 | * User cut callback to separate the disaggregated capacity constraints. 49 | * 50 | * In the model we have for each location j the constraint sum(c in clients) 51 | * supply[c][j] <= (nbClients-1) * used[j] Clearly, a client can only be 52 | * serviced from a location that is used, so we also have a constraint 53 | * supply[c][j] <= used[j] that must be satisfied by every feasible solution. 54 | * These constraints tend to be violated in LP relaxation. In this callback we 55 | * separate them. 56 | */ 57 | public static class Disaggregated extends IloCplex.UserCutCallback { 58 | private final IloModeler modeler; 59 | private final IloNumVar[] used; 60 | private final IloNumVar[][] supply; 61 | 62 | public Disaggregated(IloModeler modeler, IloNumVar[] used, IloNumVar[][] supply) { 63 | this.modeler = modeler; 64 | this.used = used; 65 | this.supply = supply; 66 | } 67 | 68 | /** 69 | * Separate cuts. 70 | * 71 | * CPLEX invokes this callback when separating cuts at search tree nodes 72 | * (including the root node). The current fractional solution can be obtained 73 | * via {@link #getValue(IloNumVar)} and {@link #getValues(IloNumVar[])}. 74 | * Separated cuts are added via {@link #add(IloRange,int)} or 75 | * {@link #addLocal(IloRange)}. 76 | */ 77 | public void main() throws IloException { 78 | int nbLocations = used.length; 79 | int nbClients = supply.length; 80 | 81 | // For each j and c check whether in the current solution (obtained by 82 | // calls to getValue()) we have supply[c][j]>used[j]. If so, then we have 83 | // found a violated constraint and add it as a cut. 84 | for (int j = 0; j < nbLocations; ++j) { 85 | for (int c = 0; c < nbClients; ++c) { 86 | double s = getValue(supply[c][j]); 87 | double o = getValue(used[j]); 88 | if (s > o + EPS) { 89 | System.out.println( 90 | "Adding: %s <= %s [%f > %f]".format(supply[c][j].getName(), used[j].getName(), s, o)); 91 | add(modeler.le(modeler.diff(supply[c][j], used[j]), 0.0), IloCplex.CutManagement.UseCutPurge); 92 | } 93 | } 94 | } 95 | } 96 | } 97 | 98 | /** 99 | * Variant of the Disaggregated callback that does not look for violated cuts 100 | * dynamically. Instead it uses a static table of cuts and scans this table for 101 | * violated cuts. 102 | */ 103 | public static class CutsFromTable extends IloCplex.UserCutCallback { 104 | private final Vector cuts; 105 | 106 | public CutsFromTable(Vector cuts) { 107 | this.cuts = cuts; 108 | } 109 | 110 | public void main() throws IloException { 111 | for (final IloRange cut : cuts) { 112 | double lhs = getValue(cut.getExpr()); 113 | if (lhs < cut.getLB() - EPS || lhs > cut.getUB() + EPS) { 114 | System.out.println("Adding %s [lhs=%f]".format(cut.toString(), lhs)); 115 | } 116 | } 117 | } 118 | } 119 | 120 | /** 121 | * Lazy constraint callback to enforce the capacity constraints. 122 | * 123 | * If used then the callback is invoked for every integer feasible solution 124 | * CPLEX finds. For each location j it checks whether constraint sum(c in C) 125 | * supply[c][j] <= (|C| - 1) * used[j] is satisfied. If not then it adds the 126 | * violated constraint as lazy constraint. 127 | */ 128 | public static class LazyCallback extends IloCplex.LazyConstraintCallback { 129 | private final IloModeler modeler; 130 | private final IloNumVar[] used; 131 | private final IloNumVar[][] supply; 132 | 133 | public LazyCallback(IloModeler modeler, IloNumVar[] used, IloNumVar[][] supply) { 134 | this.modeler = modeler; 135 | this.used = used; 136 | this.supply = supply; 137 | } 138 | 139 | public void main() throws IloException { 140 | int nbLocations = used.length; 141 | int nbClients = supply.length; 142 | for (int j = 0; j < nbLocations; ++j) { 143 | double isused = getValue(used[j]); 144 | double served = 0.0; // Number of clients currently served from j 145 | for (int c = 0; c < nbClients; ++c) 146 | served += getValue(supply[c][j]); 147 | if (served > (nbClients - 1.0) * isused + EPS) { 148 | IloLinearNumExpr sum = modeler.linearNumExpr(); 149 | for (int c = 0; c < nbClients; ++c) 150 | sum.addTerm(1.0, supply[c][j]); 151 | sum.addTerm(-(nbClients - 1), used[j]); 152 | System.out.println("Adding lazy capacity constraint %s <= 0".format(sum.toString())); 153 | add(modeler.le(sum, 0.0)); 154 | } 155 | } 156 | } 157 | } 158 | 159 | private static void usage() { 160 | System.out.println("Usage: java AdMIPex5 [options...]"); 161 | System.out.println(" By default, a user cut callback is used to dynamically"); 162 | System.out.println(" separate constraints."); 163 | System.out.println(); 164 | System.out.println(" Supported options are:"); 165 | System.out.println(" -table Instead of the default behavior, use a"); 166 | System.out.println(" static table that holds all cuts and"); 167 | System.out.println(" scan that table for violated cuts."); 168 | System.out.println(" -no-cuts Do not separate any cuts."); 169 | System.out.println(" -lazy Do not include capacity constraints in the"); 170 | System.out.println(" model. Instead, separate them from a lazy"); 171 | System.out.println(" constraint callback."); 172 | System.out.println(" -data= Specify the directory in which the data"); 173 | System.out.println(" file facility.dat is located."); 174 | System.exit(2); 175 | } 176 | 177 | public static void main(String[] args) throws Exception { 178 | // Set default arguments and parse command line. 179 | String datadir = "./data"; 180 | boolean fromTable = false; 181 | boolean lazy = false; 182 | boolean useCallback = true; 183 | 184 | for (final String arg : args) { 185 | if (arg.startsWith("-data=")) 186 | datadir = arg.substring(6); 187 | else if (arg.equals("-table")) 188 | fromTable = true; 189 | else if (arg.equals("-lazy")) 190 | lazy = true; 191 | else if (arg.equals("-no-cuts")) 192 | useCallback = false; 193 | else { 194 | System.out.println("Unknown argument " + arg); 195 | usage(); 196 | } 197 | } 198 | 199 | // Setup input file name and used the file. 200 | InputDataReader reader = new InputDataReader(new File(datadir, "facility.dat").getAbsolutePath()); 201 | double[] fixedCost = reader.readDoubleArray(); 202 | double[][] cost = reader.readDoubleArrayArray(); 203 | int nbLocations = fixedCost.length; 204 | int nbClients = cost.length; 205 | 206 | IloCplex cplex = new IloCplex(); 207 | try { 208 | // Create variables. 209 | // - used[j] If location j is used. 210 | // - supply[c][j] Amount shipped from location j to client c. This is a 211 | // number in [0,1] and specifies the percentage of c's 212 | // demand that is served from location i. 213 | IloNumVar[] used = cplex.boolVarArray(nbLocations); 214 | for (int j = 0; j < nbLocations; ++j) 215 | used[j].setName("used(" + j + ")"); 216 | IloNumVar[][] supply = new IloNumVar[nbClients][]; 217 | for (int c = 0; c < nbClients; c++) { 218 | supply[c] = cplex.boolVarArray(nbLocations); 219 | for (int j = 0; j < nbLocations; ++j) 220 | supply[c][j].setName("supply(" + c + ")(" + j + ")"); 221 | } 222 | 223 | // The supply for each client must sum to 1, i.e., the demand of each 224 | // client must be met. 225 | for (int c = 0; c < nbClients; c++) 226 | cplex.addEq(cplex.sum(supply[c], 0, supply[c].length), 1); 227 | 228 | // Capacity constraint for each location. We just require that a single 229 | // location cannot serve all clients, that is, the capacity of each 230 | // location is nbClients-1. This makes the model a little harder to 231 | // solve and allows us to separate more cuts. 232 | if (!lazy) { 233 | for (int j = 0; j < nbLocations; j++) { 234 | IloLinearNumExpr v = cplex.linearNumExpr(); 235 | for (int c = 0; c < nbClients; c++) 236 | v.addTerm(1.0, supply[c][j]); 237 | cplex.addLe(v, cplex.prod(nbClients - 1, used[j])); 238 | } 239 | } 240 | 241 | // Objective function. We have the fixed cost for useding a location 242 | // and the cost proportional to the amount that is shipped from a 243 | // location. 244 | IloLinearNumExpr obj = cplex.scalProd(fixedCost, used); 245 | for (int c = 0; c < nbClients; c++) { 246 | obj.add(cplex.scalProd(cost[c], supply[c])); 247 | } 248 | cplex.addMinimize(obj); 249 | 250 | // Tweak some CPLEX parameters so that CPLEX has a harder time to 251 | // solve the model and our cut separators can actually kick in. 252 | cplex.setParam(IloCplex.Param.Threads, 1); 253 | cplex.setParam(IloCplex.Param.MIP.Strategy.HeuristicFreq, -1); 254 | cplex.setParam(IloCplex.Param.MIP.Cuts.MIRCut, -1); 255 | cplex.setParam(IloCplex.Param.MIP.Cuts.Implied, -1); 256 | cplex.setParam(IloCplex.Param.MIP.Cuts.Gomory, -1); 257 | cplex.setParam(IloCplex.Param.MIP.Cuts.FlowCovers, -1); 258 | cplex.setParam(IloCplex.Param.MIP.Cuts.PathCut, -1); 259 | cplex.setParam(IloCplex.Param.MIP.Cuts.LiftProj, -1); 260 | cplex.setParam(IloCplex.Param.MIP.Cuts.ZeroHalfCut, -1); 261 | cplex.setParam(IloCplex.Param.MIP.Cuts.Cliques, -1); 262 | cplex.setParam(IloCplex.Param.MIP.Cuts.Covers, -1); 263 | 264 | if (useCallback) { 265 | if (fromTable) { 266 | // Generate all disaggregated constraints and put them into a 267 | // table that is scanned by the callback. 268 | Vector cuts = new Vector(); 269 | for (int j = 0; j < nbLocations; ++j) 270 | for (int c = 0; c < nbClients; ++c) 271 | cuts.add(cplex.le(cplex.diff(supply[c][j], used[j]), 0.0)); 272 | cplex.use(new CutsFromTable(cuts)); 273 | } else { 274 | cplex.use(new Disaggregated(cplex, used, supply)); 275 | } 276 | } 277 | if (lazy) 278 | cplex.use(new LazyCallback(cplex, used, supply)); 279 | 280 | if (!cplex.solve()) 281 | throw new RuntimeException("No feasible solution found"); 282 | 283 | System.out.println("Solution status: " + cplex.getStatus()); 284 | System.out.println("Nodes processed: " + cplex.getNnodes()); 285 | System.out.println("Active user cuts/lazy constraints: " + cplex.getNcuts(IloCplex.CutType.User)); 286 | double tolerance = cplex.getParam(IloCplex.Param.MIP.Tolerances.Integrality); 287 | System.out.println("Optimal value: " + cplex.getObjValue()); 288 | for (int j = 0; j < nbLocations; j++) { 289 | if (cplex.getValue(used[j]) >= 1 - tolerance) { 290 | System.out.print("Facility " + j + " is used, it serves clients"); 291 | for (int i = 0; i < nbClients; i++) { 292 | if (cplex.getValue(supply[i][j]) >= 1 - tolerance) 293 | System.out.print(" " + i); 294 | } 295 | System.out.println(); 296 | } 297 | } 298 | } finally { 299 | cplex.end(); 300 | } 301 | } 302 | } 303 | -------------------------------------------------------------------------------- /examples/AdMIPex6.java: -------------------------------------------------------------------------------- 1 | package examples; 2 | /* -------------------------------------------------------------------------- 3 | * File: AdMIPex6.java 4 | * Version 12.9.0 5 | * -------------------------------------------------------------------------- 6 | * Licensed Materials - Property of IBM 7 | * 5725-A06 5725-A29 5724-Y48 5724-Y49 5724-Y54 5724-Y55 5655-Y21 8 | * Copyright IBM Corporation 2001, 2019. All Rights Reserved. 9 | * 10 | * US Government Users Restricted Rights - Use, duplication or 11 | * disclosure restricted by GSA ADP Schedule Contract with 12 | * IBM Corp. 13 | * -------------------------------------------------------------------------- 14 | * 15 | * AdMIPex6.java -- Solving a model by passing in a solution for the root node 16 | * and using that in a solve callback 17 | * 18 | * To run this example, command line arguments are required: 19 | * java AdMIPex6 filename 20 | * where 21 | * filename Name of the file, with .mps, .lp, or .sav 22 | * extension, and a possible additional .gz 23 | * extension. 24 | * Example: 25 | * java AdMIPex6 mexample.mps.gz 26 | */ 27 | 28 | import ilog.concert.*; 29 | import ilog.cplex.*; 30 | 31 | 32 | public class AdMIPex6 { 33 | static class Solve extends IloCplex.SolveCallback { 34 | boolean _done = false; 35 | IloNumVar[] _vars; 36 | double[] _x; 37 | Solve(IloNumVar[] vars, double[] x) { _vars = vars; _x = x; } 38 | 39 | public void main() throws IloException { 40 | if ( !_done ) { 41 | setStart(_x, _vars, null, null); 42 | _done = true; 43 | } 44 | } 45 | } 46 | 47 | public static void main(String[] args) { 48 | try { 49 | IloCplex cplex = new IloCplex(); 50 | 51 | cplex.importModel(args[0]); 52 | IloLPMatrix lp = (IloLPMatrix)cplex.LPMatrixIterator().next(); 53 | 54 | IloConversion relax = cplex.conversion(lp.getNumVars(), 55 | IloNumVarType.Float); 56 | cplex.add(relax); 57 | 58 | cplex.solve(); 59 | System.out.println("Relaxed solution status = " + cplex.getStatus()); 60 | System.out.println("Relaxed solution value = " + cplex.getObjValue()); 61 | 62 | double[] vals = cplex.getValues(lp.getNumVars()); 63 | cplex.use(new Solve(lp.getNumVars(), vals)); 64 | 65 | cplex.delete(relax); 66 | 67 | cplex.setParam(IloCplex.Param.MIP.Strategy.Search, IloCplex.MIPSearch.Traditional); 68 | if ( cplex.solve() ) { 69 | System.out.println("Solution status = " + cplex.getStatus()); 70 | System.out.println("Solution value = " + cplex.getObjValue()); 71 | } 72 | cplex.end(); 73 | } 74 | catch (IloException e) { 75 | System.err.println("Concert exception caught: " + e); 76 | } 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /examples/AdMIPex9.java: -------------------------------------------------------------------------------- 1 | package examples; 2 | /* -------------------------------------------------------------------------- 3 | * File: AdMIPex9.java 4 | * Version 12.9.0 5 | * -------------------------------------------------------------------------- 6 | * Licensed Materials - Property of IBM 7 | * 5725-A06 5725-A29 5724-Y48 5724-Y49 5724-Y54 5724-Y55 5655-Y21 8 | * Copyright IBM Corporation 2001, 2019. All Rights Reserved. 9 | * 10 | * US Government Users Restricted Rights - Use, duplication or 11 | * disclosure restricted by GSA ADP Schedule Contract with 12 | * IBM Corp. 13 | * -------------------------------------------------------------------------- 14 | * 15 | * AdMIPex9.java - Use the heuristic callback for optimizing a MIP problem 16 | * 17 | * To run this example, command line arguments are required. 18 | * i.e., java AdMIPex9 filename 19 | * Note that the code assumes that all variables in the model are binary 20 | * (see the roundDown() function). 21 | * 22 | * Example: 23 | * java AdMIPex9 example.mps 24 | */ 25 | 26 | import ilog.concert.*; 27 | import ilog.cplex.*; 28 | import java.util.HashMap; 29 | import java.util.Map; 30 | 31 | public class AdMIPex9 { 32 | private static class HeuristicCallback implements IloCplex.Callback.Function { 33 | /** All variables in the model. */ 34 | IloNumVar[] _vars; 35 | /** Dense objective vector (aligned with _vars. */ 36 | double[] _obj; 37 | 38 | public HeuristicCallback(IloNumVar[] vars, IloObjective obj) throws IloException { 39 | _vars = vars; 40 | 41 | // Generate the objective as a double array for easy look up 42 | IloLinearNumExpr objexp = (IloLinearNumExpr)obj.getExpr(); 43 | IloLinearNumExprIterator it = objexp.linearIterator(); 44 | 45 | // First create a map with all variables that have non-zero 46 | // coefficients in the objective. 47 | Map _objmap = new HashMap(); 48 | while ( it.hasNext() ) { 49 | IloNumVar v = it.nextNumVar(); 50 | _objmap.put(v, it.getValue()); 51 | } 52 | 53 | // Now turn the map into a dense array. 54 | int cols = _vars.length; 55 | _obj = new double[cols]; 56 | for (int j = 0; j < cols; j++) { 57 | if ( _objmap.containsKey(_vars[j]) ) { 58 | _obj[j] = _objmap.get(_vars[j]); 59 | } 60 | } 61 | } 62 | 63 | private void roundDown(IloCplex.Callback.Context context) throws IloException { 64 | double[] x = context.getRelaxationPoint(_vars); 65 | int cols = _vars.length; 66 | double objrel = context.getRelaxationObjective(); 67 | 68 | 69 | // Heuristic motivated by knapsack constrained problems. 70 | // Rounding down all fractional values will give an integer 71 | // solution that is feasible, since all constraints are <= 72 | // with positive coefficients 73 | 74 | for (int j = 0; j < cols; j++) { 75 | // Set the fractional variable to zero. 76 | // Note that we assume all variables to be binary. If the model 77 | // contains non-binary variable then a different update would 78 | // be required. 79 | if ( x[j] > 0.0 ) { 80 | double frac = Math.abs(Math.round(x[j]) - x[j]); 81 | 82 | if ( frac > 1.0e-6 ) { 83 | objrel -= x[j]*_obj[j]; 84 | x[j] = 0.0; 85 | } 86 | } 87 | } 88 | 89 | // Post the rounded solution, CPLEX will check feasibility. 90 | context.postHeuristicSolution(_vars, x, 0, cols, objrel, 91 | IloCplex.Callback.Context.SolutionStrategy.CheckFeasible); 92 | } 93 | 94 | // This is the function that we have to implement and that CPLEX will call 95 | // during the solution process at the places that we asked for. 96 | @Override 97 | public void invoke (IloCplex.Callback.Context context) throws IloException { 98 | if ( context.inRelaxation() ) { 99 | roundDown(context); 100 | } 101 | } 102 | } 103 | 104 | public static void main(String[] args) throws IloException { 105 | if ( args.length != 1 ) { 106 | System.out.println("Usage: AdMIPex9 filename"); 107 | System.out.println(" where filename is a file with extension "); 108 | System.out.println(" MPS, SAV, or LP (lower case is allowed)"); 109 | System.out.println(" Exiting..."); 110 | System.exit(-1); 111 | } 112 | 113 | IloCplex cplex = new IloCplex(); 114 | try { 115 | cplex.importModel(args[0]); 116 | IloLPMatrix lp = (IloLPMatrix)cplex.LPMatrixIterator().next(); 117 | IloNumVar[] vars = lp.getNumVars(); 118 | 119 | // Now we get to setting up the callback. 120 | // We instanciate a HeuristicCallback and set the wherefrom parameter. 121 | HeuristicCallback heuCallback = new HeuristicCallback(vars, 122 | cplex.getObjective()); 123 | long wherefrom = 0; 124 | wherefrom |= IloCplex.Callback.Context.Id.Relaxation; 125 | 126 | // We add the callback. 127 | cplex.use(heuCallback, wherefrom); 128 | 129 | // Disable heuristics so that our callback has a chance to make a 130 | // difference. 131 | cplex.setParam(IloCplex.Param.MIP.Strategy.HeuristicFreq, -1); 132 | if ( cplex.solve() ) { 133 | System.out.println("Solution status = " + cplex.getStatus()); 134 | System.out.println("Solution value = " + cplex.getObjValue()); 135 | } 136 | } 137 | finally { 138 | cplex.end(); 139 | } 140 | } 141 | } 142 | -------------------------------------------------------------------------------- /examples/Benders.java: -------------------------------------------------------------------------------- 1 | package examples; 2 | 3 | /* -------------------------------------------------------------------------- 4 | * File: Benders.java 5 | * Version 12.9.0 6 | * -------------------------------------------------------------------------- 7 | * Licensed Materials - Property of IBM 8 | * 5725-A06 5725-A29 5724-Y48 5724-Y49 5724-Y54 5724-Y55 5655-Y21 9 | * Copyright IBM Corporation 2001, 2019. All Rights Reserved. 10 | * 11 | * US Government Users Restricted Rights - Use, duplication or 12 | * disclosure restricted by GSA ADP Schedule Contract with 13 | * IBM Corp. 14 | * -------------------------------------------------------------------------- 15 | * 16 | * Read in a model from a file and solve it using Benders decomposition. 17 | * 18 | * If an annotation file is provided, use that annotation file. 19 | * Otherwise, auto-decompose the problem and dump the annotation 20 | * to the file 'benders.ann'. 21 | * 22 | * To run this example, command line arguments are required. 23 | * i.e., java Benders filename [annofile] 24 | * where 25 | * filename is the name of the file, with .mps, .lp, or .sav extension 26 | * annofile is an optional .ann file with model annotations 27 | * 28 | * Example: 29 | * java Benders UFL_25_35_1.mps UFL_25_35_1.ann 30 | */ 31 | 32 | import ilog.concert.*; 33 | import ilog.cplex.*; 34 | 35 | public class Benders { 36 | static void usage() { 37 | System.out.println("usage: Benders filename [annofile]"); 38 | System.out.println(" where filename is a file with extension "); 39 | System.out.println(" MPS, SAV, or LP (lower case is allowed)"); 40 | System.out.println(" and annofile is an optional .ann file with model annotations"); 41 | System.out.println(" If \"create\" is used, the annotation is computed."); 42 | System.out.println(" Exiting..."); 43 | } 44 | 45 | public static void main(String[] args) { 46 | IloCplex cpx = null; 47 | boolean hasAnnoFile = false; 48 | 49 | // Check the arguments. 50 | int argsLength = args.length; 51 | if (argsLength == 2) { 52 | hasAnnoFile = true; 53 | } else if (argsLength != 1) { 54 | usage(); 55 | return; 56 | } 57 | 58 | try { 59 | // Create the modeler/solver object. 60 | cpx = new IloCplex(); 61 | 62 | // Read the problem file. 63 | cpx.importModel(args[0]); 64 | 65 | // If provided, read the annotation file. 66 | if (hasAnnoFile) { 67 | // Generate default annotations if annofile is "create". 68 | if (args[1].equals("create")) { 69 | IloCplex.LongAnnotation benders = cpx.newLongAnnotation(IloCplex.CPX_BENDERS_ANNOTATION, 70 | IloCplex.CPX_BENDERS_MASTERVALUE); 71 | 72 | IloLPMatrix lp = (IloLPMatrix) cpx.LPMatrixIterator().next(); 73 | IloNumVar[] var = lp.getNumVars(); 74 | // 识别连续变量 75 | for (IloNumVar v : var) { 76 | if (v.getType() == IloNumVarType.Float) { 77 | cpx.setAnnotation(benders, v, IloCplex.CPX_BENDERS_MASTERVALUE + 1); 78 | } 79 | } 80 | } else { 81 | // Otherwise, read the annotation file. 82 | cpx.readAnnotations(args[1]); 83 | } 84 | } else { 85 | // Set benders strategy to auto-generate a decomposition. 86 | cpx.setParam(IloCplex.Param.Benders.Strategy, IloCplex.BendersStrategy.Full); 87 | 88 | // Write out the auto-generated annotation. 89 | cpx.writeBendersAnnotation("benders.ann"); 90 | } 91 | 92 | // Solve the problem using Benders' decomposition. 93 | if (!cpx.solve()) { 94 | throw new RuntimeException("Failed to optimize."); 95 | } 96 | 97 | final IloCplex.Status status = cpx.getStatus(); 98 | final double bestObjValue = cpx.getBestObjValue(); 99 | final double objValue = cpx.getObjValue(); 100 | System.out.println("Solution status: " + status); 101 | System.out.println("Best bound: " + bestObjValue); 102 | System.out.println("Best integer: " + objValue); 103 | } catch (IloException e) { 104 | throw new RuntimeException("Concert exception caught", e); 105 | } finally { 106 | if (cpx != null) 107 | cpx.end(); 108 | } 109 | } 110 | } 111 | -------------------------------------------------------------------------------- /examples/CplexServer.java: -------------------------------------------------------------------------------- 1 | package examples; 2 | /* -------------------------------------------------------------------------- 3 | * File: CplexServer.java 4 | * Version 12.9.0 5 | * -------------------------------------------------------------------------- 6 | * Licensed Materials - Property of IBM 7 | * 5725-A06 5725-A29 5724-Y48 5724-Y49 5724-Y54 5724-Y55 5655-Y21 8 | * Copyright IBM Corporation 2001, 2019. All Rights Reserved. 9 | * 10 | * US Government Users Restricted Rights - Use, duplication or 11 | * disclosure restricted by GSA ADP Schedule Contract with 12 | * IBM Corp. 13 | * -------------------------------------------------------------------------- 14 | * 15 | * CplexServer.java - Entering a problem using IloCplexModeler and 16 | * transferring it to another thread for solving 17 | */ 18 | 19 | import ilog.concert.*; 20 | import ilog.cplex.*; 21 | import java.io.*; 22 | 23 | 24 | public class CplexServer { 25 | 26 | // define class to transfer model to server 27 | static class ModelData implements Serializable { 28 | private static final long serialVersionUID = 1021L; 29 | IloModel model; 30 | IloNumVar[] vars; 31 | ModelData(IloModel m, IloNumVar[] v) 32 | { 33 | model = m; 34 | vars = v; 35 | } 36 | } 37 | 38 | // define class to transfer back solution 39 | static class SolutionData implements Serializable { 40 | private static final long serialVersionUID = 1022L; 41 | IloCplex.CplexStatus status; 42 | double obj; 43 | double[] vals; 44 | } 45 | 46 | public static void main(String[] args) 47 | { 48 | try { 49 | // setup pipe to transfer model to server 50 | PipedOutputStream mout = new PipedOutputStream(); 51 | PipedInputStream min = new PipedInputStream(mout); 52 | 53 | // setup pipe to transfer results back 54 | PipedOutputStream sout = new PipedOutputStream(); 55 | PipedInputStream sin = new PipedInputStream(sout); 56 | 57 | // start server 58 | new Server(min, sout).start(); 59 | 60 | // build model 61 | IloNumVar[][] var = new IloNumVar[1][]; 62 | IloRange[][] rng = new IloRange[1][]; 63 | 64 | IloCplexModeler model = new IloCplexModeler(); 65 | populateByRow(model, var, rng); 66 | 67 | ObjectOutputStream os = new ObjectOutputStream(mout); 68 | os.writeObject(new ModelData(model, var[0])); 69 | 70 | ObjectInputStream is = new ObjectInputStream(sin); 71 | SolutionData sol = (SolutionData)is.readObject(); 72 | 73 | System.out.println("Solution status = " + sol.status); 74 | 75 | if ( sol.status.equals(IloCplex.CplexStatus.Optimal) ) { 76 | System.out.println("Solution value = " + sol.obj); 77 | int nvars = var[0].length; 78 | for (int j = 0; j < nvars; ++j) 79 | System.out.println("Variable " + j + ": Value = " + sol.vals[j]); 80 | } 81 | 82 | // signal that we're done 83 | os.writeObject(new ModelData(null, null)); 84 | is.close(); 85 | } 86 | catch (IloException e) { 87 | System.err.println("Concert exception '" + e + "' caught"); 88 | } 89 | catch (Throwable t) { 90 | System.err.println("terminating due to exception " + t); 91 | } 92 | } 93 | 94 | 95 | // The following method populates the problem with data for the 96 | // following linear program: 97 | // 98 | // Maximize 99 | // x1 + 2 x2 + 3 x3 100 | // Subject To 101 | // - x1 + x2 + x3 <= 20 102 | // x1 - 3 x2 + x3 <= 30 103 | // Bounds 104 | // 0 <= x1 <= 40 105 | // End 106 | // 107 | // using the IloModeler API 108 | 109 | static void populateByRow(IloModeler model, 110 | IloNumVar[][] var, 111 | IloRange[][] rng) throws IloException 112 | { 113 | double[] lb = {0.0, 0.0, 0.0}; 114 | double[] ub = {40.0, Double.MAX_VALUE, Double.MAX_VALUE}; 115 | String[] varname = {"x1", "x2", "x3"}; 116 | IloNumVar[] x = model.numVarArray(3, lb, ub, varname); 117 | var[0] = x; 118 | 119 | double[] objvals = {1.0, 2.0, 3.0}; 120 | model.addMaximize(model.scalProd(x, objvals)); 121 | 122 | rng[0] = new IloRange[2]; 123 | rng[0][0] = model.addLe(model.sum(model.prod(-1.0, x[0]), 124 | model.prod( 1.0, x[1]), 125 | model.prod( 1.0, x[2])), 20.0, "c1"); 126 | rng[0][1] = model.addLe(model.sum(model.prod( 1.0, x[0]), 127 | model.prod(-3.0, x[1]), 128 | model.prod( 1.0, x[2])), 30.0, "c2"); 129 | } 130 | 131 | 132 | // The server class 133 | static class Server extends Thread { 134 | PipedInputStream pin; 135 | PipedOutputStream pout; 136 | 137 | Server(PipedInputStream in, PipedOutputStream out) 138 | { 139 | pin = in; 140 | pout = out; 141 | } 142 | 143 | public void run() 144 | { 145 | try { 146 | ObjectInputStream is = new ObjectInputStream(pin); 147 | ObjectOutputStream os = new ObjectOutputStream(pout); 148 | while ( true ) { 149 | ModelData data = (ModelData)is.readObject(); 150 | 151 | if ( data.model == null ) { 152 | is.close(); 153 | return; 154 | } 155 | IloCplex cplex = new IloCplex(); 156 | cplex.setModel(data.model); 157 | 158 | SolutionData sol = new SolutionData(); 159 | if ( cplex.solve() ) { 160 | sol.obj = cplex.getObjValue(); 161 | sol.vals = cplex.getValues(data.vars); 162 | } 163 | sol.status = cplex.getCplexStatus(); 164 | os.writeObject(sol); 165 | 166 | cplex.end(); 167 | } 168 | } 169 | catch (Throwable t) { 170 | System.err.println("server terminates due to " + t); 171 | } 172 | } 173 | } 174 | } 175 | -------------------------------------------------------------------------------- /examples/CutStock.java: -------------------------------------------------------------------------------- 1 | package examples; 2 | 3 | /* -------------------------------------------------------------------------- 4 | * File: CutStock.java 5 | * Version 12.9.0 6 | * -------------------------------------------------------------------------- 7 | * Licensed Materials - Property of IBM 8 | * 5725-A06 5725-A29 5724-Y48 5724-Y49 5724-Y54 5724-Y55 5655-Y21 9 | * Copyright IBM Corporation 2001, 2019. All Rights Reserved. 10 | * 11 | * US Government Users Restricted Rights - Use, duplication or 12 | * disclosure restricted by GSA ADP Schedule Contract with 13 | * IBM Corp. 14 | * -------------------------------------------------------------------------- 15 | */ 16 | 17 | import java.io.*; 18 | import java.util.ArrayList; 19 | import java.util.Arrays; 20 | 21 | import ilog.concert.*; 22 | import ilog.cplex.*; 23 | 24 | class CutStock { 25 | static double RC_EPS = 1.0e-6; 26 | 27 | static double rollWidth; 28 | static double[] size; 29 | static double[] amount; 30 | 31 | static void readData(String fileName) throws IOException, InputDataReader.InputDataReaderException { 32 | InputDataReader reader = new InputDataReader(fileName); 33 | 34 | rollWidth = reader.readDouble(); 35 | size = reader.readDoubleArray(); 36 | amount = reader.readDoubleArray(); 37 | } 38 | 39 | /** 40 | * Description .
41 | * 42 | * @param rmlpSolver 43 | * @param cut 44 | * @param fill 45 | * @throws IloException 46 | */ 47 | static void report1(IloCplex rmlpSolver, IloNumVarArray cut, IloRange[] fill) throws IloException { 48 | System.out.println(); 49 | System.out.println("Using " + rmlpSolver.getObjValue() + " rolls"); 50 | 51 | System.out.println(); 52 | for (int j = 0; j < cut.getSize(); j++) { 53 | System.out.println(" Cut" + j + " = " + rmlpSolver.getValue(cut.getCutNum(j))); 54 | } 55 | System.out.println(); 56 | 57 | for (int i = 0; i < fill.length; i++) { 58 | System.out.println(" Fill" + i + " = " + rmlpSolver.getDual(fill[i])); 59 | } 60 | System.out.println(); 61 | } 62 | 63 | static void report2(IloCplex patSolver, IloNumVar[] times) throws IloException { 64 | System.out.println(); 65 | System.out.println("Reduced cost is " + patSolver.getObjValue()); 66 | 67 | System.out.println(); 68 | if (patSolver.getObjValue() <= -RC_EPS) { 69 | for (int i = 0; i < times.length; i++) { 70 | System.out.println(" Use" + i + " = " + patSolver.getValue(times[i])); 71 | } 72 | System.out.println(); 73 | } 74 | } 75 | 76 | static void report3(IloCplex rmlpSolver, IloNumVarArray cut) throws IloException { 77 | System.out.println(); 78 | System.out.println("Best integer solution uses " + rmlpSolver.getObjValue() + " rolls"); 79 | System.out.println(); 80 | for (int j = 0; j < cut.getSize(); j++) { 81 | System.out.println(" Cut" + j + " = " + rmlpSolver.getValue(cut.getCutNum(j))); 82 | } 83 | } 84 | 85 | /** 86 | * 各切割方案使用的次数 .
87 | * 88 | * @author xiong 89 | * @version v1.0 90 | * @since JDK1.8 91 | */ 92 | static class IloNumVarArray { 93 | int num = 0; 94 | IloNumVar[] array = new IloNumVar[32]; 95 | ArrayList patterns = new ArrayList(); 96 | 97 | void add(IloNumVar ivar) { 98 | // resizing the array 99 | if (num >= array.length) { 100 | IloNumVar[] newArray = new IloNumVar[2 * array.length]; 101 | System.arraycopy(array, 0, newArray, 0, num); 102 | array = newArray; 103 | } 104 | array[num++] = ivar; 105 | } 106 | 107 | void add(double[] pattern) { 108 | patterns.add(pattern); 109 | } 110 | 111 | IloNumVar getCutNum(int i) { 112 | return array[i]; 113 | } 114 | 115 | double[] getPattern(int i) { 116 | return patterns.get(i); 117 | } 118 | 119 | int getSize() { 120 | return num; 121 | } 122 | } 123 | 124 | 125 | public static void main(String[] args) { 126 | String datafile = "./data/cutstock.dat"; 127 | try { 128 | if (args.length > 0) { 129 | datafile = args[0]; 130 | } 131 | readData(datafile); 132 | 133 | // RMLP(MLP)的求解器 134 | IloCplex rmlpSolver = new IloCplex(); 135 | 136 | // RMLP Model 137 | IloObjective rollsUsed = rmlpSolver.addMinimize(); 138 | IloRange[] fill = new IloRange[amount.length]; 139 | for (int f = 0; f < amount.length; f++) { 140 | // MLP Model中的各类木材需求量约束 141 | fill[f] = rmlpSolver.addRange(amount[f], Double.MAX_VALUE); 142 | } 143 | 144 | // 存储列生成过程中的切割方案 145 | IloNumVarArray cutPattern = new IloNumVarArray(); 146 | 147 | /* 148 | * RMLP Model 149 | * 每次添加新的列,包括目标函数的变化、约束条件的变化,这里先初始化: 150 | * 初始化列,得到nWdth列,每列对应一种切割方案——只产生一种长度木材的切割方案 151 | */ 152 | int nWdth = size.length; 153 | for (int j = 0; j < nWdth; j++) { 154 | cutPattern.add(rmlpSolver.numVar( 155 | rmlpSolver.column(rollsUsed, 1.0).and(rmlpSolver.column(fill[j], (int) (rollWidth / size[j]))), 156 | 0.0, Double.MAX_VALUE)); 157 | 158 | double[] pattern = new double[nWdth]; 159 | pattern[j] = (int) (rollWidth / size[j]); 160 | cutPattern.add(pattern); 161 | } 162 | 163 | // 设置求解参数 - 采用单纯形法 164 | rmlpSolver.setParam(IloCplex.Param.RootAlgorithm, IloCplex.Algorithm.Primal); 165 | 166 | // Pricing Model 167 | IloCplex patSolver = new IloCplex(); 168 | IloObjective reducedCost = patSolver.addMinimize(); 169 | // 添加变量,切割方案对应的每种长度的木材的份数 170 | IloNumVar[] times = patSolver.numVarArray(nWdth, 0., Double.MAX_VALUE, IloNumVarType.Int); 171 | // Pricing Problem的原料长度约束 172 | patSolver.addRange(-Double.MAX_VALUE, patSolver.scalProd(size, times), rollWidth); 173 | 174 | // 列生成过程核心步骤 175 | double[] newPatt = new double[nWdth]; 176 | for (;;) { 177 | 178 | // Solve the RMLP to get the primal(upper bound) and dual solution 179 | rmlpSolver.solve(); 180 | report1(rmlpSolver, cutPattern, fill); 181 | 182 | /// Solve the Pricing Problem,产生新的列 183 | double[] price = rmlpSolver.getDuals(fill); 184 | // Pricing Problem 的目标函数更新 185 | reducedCost.setExpr(patSolver.diff(1., patSolver.scalProd(times, price))); 186 | // 求解Pricing Problem 187 | patSolver.solve(); 188 | report2(patSolver, times); 189 | 190 | // 若Pricing Problem的目标值大于0表示MLP问题求解完成,退出循环;否则生成新的列进行求解 191 | if (patSolver.getObjValue() > -RC_EPS) { 192 | break; 193 | } 194 | 195 | newPatt = patSolver.getValues(times); 196 | 197 | // 存储切割方案 198 | cutPattern.add(newPatt); 199 | 200 | /* 201 | * 依据新的切割方案更新RMLP问题,包括: 202 | * 1.目标值 203 | * 2.约束 204 | * 3.变量 205 | * 采用按column添加的方式 206 | */ 207 | IloColumn column = rmlpSolver.column(rollsUsed, 1.); 208 | for (int p = 0; p < newPatt.length; p++) { 209 | // 更新约束 210 | column = column.and(rmlpSolver.column(fill[p], newPatt[p])); 211 | } 212 | // 添加变量,并更新切割方案数组 213 | cutPattern.add(rmlpSolver.numVar(column, 0., Double.MAX_VALUE)); 214 | } 215 | 216 | for (int i = 0; i < cutPattern.getSize(); i++) { 217 | // 将变量转化为int类型 218 | rmlpSolver.add(rmlpSolver.conversion(cutPattern.getCutNum(i), IloNumVarType.Int)); 219 | 220 | } 221 | 222 | rmlpSolver.solve(); 223 | rmlpSolver.exportModel("model2.lp"); 224 | 225 | System.out.println("Solution status: " + rmlpSolver.getStatus()); 226 | 227 | System.out.println("Cut plan: "); 228 | for (int i = 0; i < cutPattern.num; i++) { 229 | System.out.print("Cut" + i + " \n= " + rmlpSolver.getValue(cutPattern.getCutNum(i))); 230 | System.out.println(" Pattern" + " = " + Arrays.toString(cutPattern.getPattern(i))); 231 | } 232 | 233 | // 关闭求解器 234 | rmlpSolver.end(); 235 | patSolver.end(); 236 | } catch (IloException exc) { 237 | System.err.println("Concert exception '" + exc + "' caught"); 238 | } catch (IOException exc) { 239 | System.err.println("Error reading file " + datafile + ": " + exc); 240 | } catch (InputDataReader.InputDataReaderException exc) { 241 | System.err.println(exc); 242 | } 243 | } 244 | } 245 | 246 | /* 247 | * Example Input file: 248 | * 115 249 | * [25, 40, 50, 55, 70] 250 | * [50, 36, 24, 8, 30] 251 | */ 252 | -------------------------------------------------------------------------------- /examples/Diet.java: -------------------------------------------------------------------------------- 1 | package examples; 2 | 3 | /* -------------------------------------------------------------------------- 4 | * File: Diet.java 5 | * Version 12.9.0 6 | * -------------------------------------------------------------------------- 7 | * Licensed Materials - Property of IBM 8 | * 5725-A06 5725-A29 5724-Y48 5724-Y49 5724-Y54 5724-Y55 5655-Y21 9 | * Copyright IBM Corporation 2001, 2019. All Rights Reserved. 10 | * 11 | * US Government Users Restricted Rights - Use, duplication or 12 | * disclosure restricted by GSA ADP Schedule Contract with 13 | * IBM Corp. 14 | * -------------------------------------------------------------------------- 15 | * 16 | * Reads data for a dietary problem, builds the model, and solves it. 17 | * 18 | * Input data: 19 | * foodMin[j] minimum amount of food j to use 20 | * foodMax[j] maximum amount of food j to use 21 | * foodCost[j] cost for one unit of food j 22 | * nutrMin[i] minimum amount of nutrient i 23 | * nutrMax[i] maximum amount of nutrient i 24 | * nutrPerFood[i][j] nutrition amount of nutrient i in food j 25 | * 26 | * Modeling variables: 27 | * buy[j] amount of food j to purchase 28 | * 29 | * Objective: 30 | * minimize sum(j) buy[j] * foodCost[j] 31 | * 32 | * Constraints: 33 | * forall foods i: nutrMin[i] <= sum(j) buy[j] * nutrPer[i][j] <= nutrMax[j] 34 | * 35 | * Options: 36 | * - build the model by column, rather than by row 37 | * - restrict to selecting integral food quantities 38 | * - create a multi-objective model 39 | * 40 | * See the usage message for more details. 41 | */ 42 | 43 | import ilog.concert.*; 44 | import ilog.cplex.*; 45 | import ilog.cplex.IloCplex.MultiObjIntInfo; 46 | import ilog.cplex.IloCplex.MultiObjLongInfo; 47 | import ilog.cplex.IloCplex.MultiObjNumInfo; 48 | 49 | public class Diet { 50 | 51 | /** 52 | * Print a usage message to stderr and abort. 53 | */ 54 | static void usage() { 55 | System.err.println(); 56 | System.err.println("Usage: Diet [options...] "); 57 | System.err.println(" By default, the problem will be generated by rows."); 58 | System.err.println(); 59 | System.err.println(" Supported options are:"); 60 | System.err.println(" -r generate problem by row"); 61 | System.err.println(" -c generate problem by column"); 62 | System.err.println(" -i restrict to integral food quantities (i.e., convert to a MIP)"); 63 | System.err.println(" -m create a multi-objective problem where, in addition to"); 64 | System.err.println(" minimizing cost, the number of unique foods selected is"); 65 | System.err.println(" maximized (can be combined with -i)"); 66 | System.err.println(); 67 | System.exit(2); 68 | } 69 | 70 | /** 71 | * A class to store problem data. 72 | */ 73 | static class Data { 74 | int nFoods; 75 | int nNutrs; 76 | double[] foodCost; 77 | double[] foodMin; 78 | double[] foodMax; 79 | double[] nutrMin; 80 | double[] nutrMax; 81 | double[][] nutrPerFood; 82 | 83 | Data(String filename) throws IloException, java.io.IOException, InputDataReader.InputDataReaderException { 84 | InputDataReader reader = new InputDataReader(filename); 85 | 86 | foodCost = reader.readDoubleArray(); 87 | foodMin = reader.readDoubleArray(); 88 | foodMax = reader.readDoubleArray(); 89 | nutrMin = reader.readDoubleArray(); 90 | nutrMax = reader.readDoubleArray(); 91 | nutrPerFood = reader.readDoubleArrayArray(); 92 | 93 | nFoods = foodMax.length; 94 | nNutrs = nutrMax.length; 95 | 96 | if (nFoods != foodMin.length || nFoods != foodMax.length) 97 | throw new IloException("inconsistent data in file " + filename); 98 | if (nNutrs != nutrMin.length || nNutrs != nutrPerFood.length) 99 | throw new IloException("inconsistent data in file " + filename); 100 | for (int i = 0; i < nNutrs; ++i) { 101 | if (nutrPerFood[i].length != nFoods) 102 | throw new IloException("inconsistent data in file " + filename); 103 | } 104 | } 105 | } 106 | 107 | static void buildModelByRow(IloModeler model, Data data, IloNumVar[] buy, IloObjective cost, IloNumVarType type) 108 | throws IloException { 109 | int nFoods = data.nFoods; 110 | int nNutrs = data.nNutrs; 111 | 112 | for (int j = 0; j < nFoods; j++) { 113 | buy[j] = model.numVar(data.foodMin[j], data.foodMax[j], type); 114 | } 115 | 116 | cost.setExpr(model.scalProd(data.foodCost, buy)); 117 | 118 | for (int i = 0; i < nNutrs; i++) { 119 | model.addRange(data.nutrMin[i], model.scalProd(data.nutrPerFood[i], buy), data.nutrMax[i]); 120 | } 121 | } 122 | 123 | /** 124 | * 按列的形式添加变量 .
125 | */ 126 | static void buildModelByColumn(IloMPModeler model, Data data, IloNumVar[] buy, IloObjective cost, 127 | IloNumVarType type) throws IloException { 128 | int nFoods = data.nFoods; 129 | int nNutrs = data.nNutrs; 130 | 131 | IloRange[] constraint = new IloRange[nNutrs]; 132 | 133 | for (int i = 0; i < nNutrs; i++) { 134 | constraint[i] = model.addRange(data.nutrMin[i], data.nutrMax[i]); 135 | } 136 | 137 | for (int j = 0; j < nFoods; j++) { 138 | IloColumn col = model.column(cost, data.foodCost[j]); 139 | for (int i = 0; i < nNutrs; i++) { 140 | col = col.and(model.column(constraint[i], data.nutrPerFood[i][j])); 141 | } 142 | buy[j] = model.numVar(col, data.foodMin[j], data.foodMax[j], type); 143 | } 144 | } 145 | 146 | static void createMultiObj(IloCplex cplex, IloNumVar[] buy, IloObjective cost, IloObjective variety) 147 | throws IloException { 148 | // Create binary variables for each food. 149 | IloNumVar[] varUsed = cplex.numVarArray(buy.length, 0.0, 1.0, IloNumVarType.Bool); 150 | 151 | // Add indicator constraints that force the binary variables to 1 if 152 | // a food is purchased/used. 153 | for (int i = 0; i < buy.length; ++i) { 154 | cplex.add(cplex.ifThen(cplex.eq(varUsed[i], 0), cplex.eq(buy[i], 0.0))); 155 | cplex.add(cplex.ifThen(cplex.eq(buy[i], 0.0), cplex.eq(varUsed[i], 0))); 156 | } 157 | 158 | // Set up the second objective so that it maximizes the sum of the 159 | // binary variables. 160 | variety.setExpr(cplex.sum(varUsed)); 161 | variety.setSense(IloObjectiveSense.Maximize); 162 | 163 | // Create an array of objectives: 164 | // - the first objective minimizes the cost 165 | // - the second objective maximizes the variety 166 | IloNumExpr[] objArray = new IloNumExpr[] { cost.getExpr(), variety.getExpr() }; 167 | 168 | // Use a negative weight to maximize the second objective. The 169 | // objective senses of all objective functions must match. Hence, we 170 | // have to formulate max(sum) as min(-sum). 171 | double[] weights = new double[] { 1.0, -1.0 }; 172 | 173 | // Adjust priorities such that we optimize the first objective 174 | // first (i.e., give it a higher priority). 175 | int[] priorities = new int[] { 2, 1 }; 176 | 177 | // Allow a small degradation in the first objective. 178 | double[] absTols = new double[] { 0.5, 0.0 }; 179 | double[] relTols = new double[] { 0.0, 0.0 }; 180 | 181 | // 多目标设置 182 | // Add the lexicographic objective to the model. 183 | cplex.add(cplex.minimize(cplex.staticLex(objArray, weights, priorities, absTols, relTols, "staticLex1"))); 184 | } 185 | 186 | static void printSolutionStat(String what, String val) { 187 | System.out.printf(" %s: %s%n", what, (val != null) ? val : "---"); 188 | } 189 | 190 | static void printMultiObjInfo(IloCplex cplex, MultiObjIntInfo what, int subprob) throws IloException { 191 | String valString = null; 192 | try { 193 | valString = Integer.toString(cplex.getMultiObjInfo(what, subprob)); 194 | } catch (IloException ignore) { 195 | } 196 | printSolutionStat(what.toString(), valString); 197 | } 198 | 199 | static void printMultiObjInfo(IloCplex cplex, MultiObjLongInfo what, int subprob) throws IloException { 200 | String valString = null; 201 | try { 202 | valString = Long.toString(cplex.getMultiObjInfo(what, subprob)); 203 | } catch (IloException ignore) { 204 | } 205 | printSolutionStat(what.toString(), valString); 206 | } 207 | 208 | static void printMultiObjInfo(IloCplex cplex, MultiObjNumInfo what, int subprob) throws IloException { 209 | String valString = null; 210 | try { 211 | valString = Double.toString(cplex.getMultiObjInfo(what, subprob)); 212 | } catch (IloException ignore) { 213 | } 214 | printSolutionStat(what.toString(), valString); 215 | } 216 | 217 | static void printSolutionStats(IloCplex cplex) throws IloException { 218 | final int num = cplex.getMultiObjNsolves(); 219 | 220 | for (int i = 0; i < num; ++i) { 221 | int prio = cplex.getMultiObjInfo(MultiObjIntInfo.MultiObjPriority, i); 222 | System.out.printf("subproblem %d [priority %d]:%n", i, prio); 223 | printMultiObjInfo(cplex, MultiObjIntInfo.MultiObjError, i); 224 | printMultiObjInfo(cplex, MultiObjIntInfo.MultiObjStatus, i); 225 | printMultiObjInfo(cplex, MultiObjNumInfo.MultiObjTime, i); 226 | printMultiObjInfo(cplex, MultiObjNumInfo.MultiObjDetTime, i); 227 | printMultiObjInfo(cplex, MultiObjLongInfo.MultiObjNiterations, i); 228 | printMultiObjInfo(cplex, MultiObjNumInfo.MultiObjObjValue, i); 229 | printMultiObjInfo(cplex, MultiObjNumInfo.MultiObjBestObjValue, i); 230 | printMultiObjInfo(cplex, MultiObjLongInfo.MultiObjNnodes, i); 231 | printMultiObjInfo(cplex, MultiObjLongInfo.MultiObjNnodesLeft, i); 232 | } 233 | } 234 | 235 | public static void main(String[] args) throws Exception { 236 | // Set default arguments and parse command line. 237 | String filename = "./data/diet.dat"; 238 | boolean byColumn = false; 239 | IloNumVarType varType = IloNumVarType.Float; 240 | boolean multiobj = false; 241 | 242 | for (int i = 0; i < args.length; i++) { 243 | if (args[i].charAt(0) == '-') { 244 | if (args[i].equals("-r")) 245 | byColumn = false; 246 | else if (args[i].equals("-c")) 247 | byColumn = true; 248 | else if (args[i].equals("-i")) 249 | varType = IloNumVarType.Int; 250 | else if (args[i].equals("-m")) 251 | multiobj = true; 252 | else { 253 | System.err.printf("Unknown argument: %s%n", args[i]); 254 | usage(); 255 | } 256 | } else { 257 | filename = args[i]; 258 | } 259 | } 260 | 261 | // Read the data. 262 | 263 | Data data = new Data(filename); 264 | final int nFoods = data.nFoods; 265 | IloCplex cplex = new IloCplex(); 266 | try { 267 | // Build model 268 | IloNumVar[] buy = new IloNumVar[nFoods]; 269 | IloObjective cost = cplex.minimize(); 270 | cost.setName("cost"); 271 | 272 | if (byColumn) 273 | buildModelByColumn(cplex, data, buy, cost, varType); 274 | else 275 | buildModelByRow(cplex, data, buy, cost, varType); 276 | 277 | // Optionally, create a second objective. 278 | 279 | IloObjective variety = cplex.maximize(); 280 | variety.setName("number of foods"); 281 | if (multiobj) { 282 | createMultiObj(cplex, buy, cost, variety); 283 | } else { 284 | cplex.add(cost); 285 | } 286 | 287 | // Write a copy of the problem to a file. 288 | 289 | cplex.exportModel("Diet.java.lp"); 290 | 291 | // Solve model 292 | 293 | if (multiobj) { 294 | // Set multi-objective display level to "detailed". 295 | cplex.setParam(IloCplex.Param.MultiObjective.Display, 2); 296 | 297 | // Purely for demonstrative purposes, set global and local limits 298 | // using parameter sets. 299 | 300 | // First, set the global deterministic time limit. 301 | cplex.setParam(IloCplex.Param.DetTimeLimit, 60000); 302 | 303 | // Second, create a parameter set for each priority. 304 | IloCplex.ParameterSet[] params = new IloCplex.ParameterSet[2]; 305 | params[0] = new IloCplex.ParameterSet(); 306 | params[1] = new IloCplex.ParameterSet(); 307 | 308 | // Set the local deterministic time limits. Optimization will stop 309 | // whenever either the global or local limit is exceeded. 310 | params[0].setParam(IloCplex.Param.DetTimeLimit, 50000); 311 | params[1].setParam(IloCplex.Param.DetTimeLimit, 25000); 312 | 313 | // Optimize the multi-objective problem and apply the parameter 314 | // sets that were created above. The parameter sets are used 315 | // one-by-one by each optimization. 316 | if (!cplex.solve(params)) 317 | throw new IloException("Failed to optimize"); 318 | } else { 319 | if (!cplex.solve()) 320 | throw new IloException("Failed to optimize"); 321 | } 322 | 323 | // Print the solution status. 324 | 325 | System.out.println(); 326 | System.out.println("Solution status = " + cplex.getStatus()); 327 | 328 | // Print the objective value(s). 329 | 330 | if (multiobj) { 331 | System.out.printf("Solution value 0 (%s) = %f%n", cost.getName(), cplex.getValue(cost.getExpr(), -1)); 332 | System.out.printf("Solution value 1 (%s) = %f%n", variety.getName(), 333 | cplex.getValue(variety.getExpr(), -1)); 334 | System.out.println(); 335 | 336 | printSolutionStats(cplex); 337 | } else { 338 | System.out.printf("Solution value = %f%n", cplex.getObjValue()); 339 | } 340 | System.out.println(); 341 | 342 | // Print the solution values. 343 | 344 | for (int i = 0; i < nFoods; i++) { 345 | System.out.printf("Food %d: Buy = %f%n", i, cplex.getValue(buy[i])); 346 | } 347 | 348 | } finally { 349 | cplex.end(); 350 | } 351 | } 352 | 353 | } 354 | -------------------------------------------------------------------------------- /examples/Etsp.java: -------------------------------------------------------------------------------- 1 | package examples; 2 | /* -------------------------------------------------------------------------- 3 | * File: Etsp.java 4 | * Version 12.9.0 5 | * -------------------------------------------------------------------------- 6 | * Licensed Materials - Property of IBM 7 | * 5725-A06 5725-A29 5724-Y48 5724-Y49 5724-Y54 5724-Y55 5655-Y21 8 | * Copyright IBM Corporation 2001, 2019. All Rights Reserved. 9 | * 10 | * US Government Users Restricted Rights - Use, duplication or 11 | * disclosure restricted by GSA ADP Schedule Contract with 12 | * IBM Corp. 13 | * -------------------------------------------------------------------------- 14 | * 15 | * Etsp.java - Solving an earliness-tardiness scheduling problem 16 | * using CPLEX linearization capabilities. 17 | * 18 | * A command line argument indicating the input data file is required 19 | * to run this example. 20 | * 21 | * java Etsp ../../../examples/data/etsp.dat 22 | */ 23 | 24 | import ilog.concert.*; 25 | import ilog.cplex.*; 26 | 27 | public class Etsp { 28 | static private int Horizon = 10000; 29 | 30 | static private class Data { 31 | int nJobs; 32 | int nResources; 33 | int[][] activityOnResource; 34 | double[][] duration; 35 | double[] dueDate; 36 | double[] earlinessCost; 37 | double[] tardinessCost; 38 | 39 | Data(String filename) throws IloException, java.io.IOException, 40 | InputDataReader.InputDataReaderException 41 | { 42 | InputDataReader reader = new InputDataReader(filename); 43 | 44 | activityOnResource = reader.readIntArrayArray(); 45 | duration = reader.readDoubleArrayArray(); 46 | dueDate = reader.readDoubleArray(); 47 | earlinessCost = reader.readDoubleArray(); 48 | tardinessCost = reader.readDoubleArray(); 49 | 50 | nJobs = dueDate.length; 51 | nResources = activityOnResource.length; 52 | } 53 | } 54 | 55 | public static void main (String args[]) { 56 | try { 57 | String filename; 58 | if ( args.length > 1) filename = args[0]; 59 | else filename = "./data/etsp.dat"; 60 | 61 | Data data = new Data(filename); 62 | IloCplex cplex = new IloCplex(); 63 | 64 | // Create start variables 65 | IloNumVar[][] s = new IloNumVar[data.nJobs][]; 66 | for (int j = 0; j < data.nJobs; j++) 67 | s[j] = cplex.numVarArray(data.nResources, 0.0, Horizon); 68 | 69 | // State precedence constraints 70 | for (int j = 0; j < data.nJobs; j++) { 71 | for (int i = 1; i < data.nResources; i++) 72 | cplex.addGe(s[j][i], cplex.sum(s[j][i-1], data.duration[j][i-1])); 73 | } 74 | 75 | // State disjunctive constraints for each resource 76 | for (int i = 0; i < data.nResources; i++) { 77 | int end = data.nJobs - 1; 78 | for (int j = 0; j < end; j++) { 79 | int a = data.activityOnResource[i][j]; 80 | for (int k = j + 1; k < data.nJobs; k++) { 81 | int b = data.activityOnResource[i][k]; 82 | cplex.add(cplex.or( 83 | cplex.ge(s[j][a], cplex.sum(s[k][b], data.duration[k][b])), 84 | cplex.ge(s[k][b], cplex.sum(s[j][a], data.duration[j][a])) 85 | )); 86 | } 87 | } 88 | } 89 | 90 | // The cost is the sum of earliness or tardiness costs of each job 91 | int last = data.nResources - 1; 92 | IloNumExpr costSum = cplex.numExpr(); 93 | for (int j = 0; j < data.nJobs; j++) { 94 | double[] points = { data.dueDate[j] }; 95 | double[] slopes = { -data.earlinessCost[j], 96 | data.tardinessCost[j] }; 97 | costSum = cplex.sum(costSum, 98 | cplex.piecewiseLinear( 99 | cplex.sum(s[j][last], data.duration[j][last]), 100 | points, slopes, data.dueDate[j], 0) 101 | ); 102 | } 103 | cplex.addMinimize(costSum); 104 | 105 | /* 106 | * 控制 MIP 中速度、可行性、最优性和移动界限之间的折衷 107 | * 0: 在使用缺省设置 BALANCED 时,CPLEX 致力于快速证明最佳解法,但要均衡在优化早期找到高质量可行解法 108 | * 1: 在将此参数设置为 FEASIBILITY 时,CPLEX 将在优化问题时频繁生成更多可行的解法,牺牲一部分最优性证明速度 109 | * 2: 在设置为 OPTIMALITY 时,早期阶段应用于查找可行的解法的工作量较少 110 | * 3: 使用设置 BESTBOUND 时,将通过移动最佳界限值来更着重强调证明最优性,因此顺便检测可行的解法几乎成为成为偶然 111 | * 4: 在参数设置为 HIDDENFEAS 时,MIP 优化器更努力查找非常难于找到的高质量可行的解法,因此在 FEASIBILITY 设置难于找到可接受质量的解法时考虑此设置。 112 | */ 113 | cplex.setParam(IloCplex.Param.Emphasis.MIP, 4); 114 | 115 | if ( cplex.solve() ) { 116 | System.out.println("Solution status: " + cplex.getStatus()); 117 | System.out.println(" Optimal Value = " + cplex.getObjValue()); 118 | } 119 | cplex.end(); 120 | } 121 | catch (IloException e) { 122 | System.err.println("Concert exception caught: " + e); 123 | } 124 | catch (InputDataReader.InputDataReaderException ex) { 125 | System.out.println("Data Error: " + ex); 126 | } 127 | catch (java.io.IOException ex) { 128 | System.out.println("IO Error: " + ex); 129 | } 130 | } 131 | } 132 | 133 | -------------------------------------------------------------------------------- /examples/Facility.java: -------------------------------------------------------------------------------- 1 | package examples; 2 | 3 | /* -------------------------------------------------------------------------- 4 | * File: Facility.java 5 | * Version 12.9.0 6 | * -------------------------------------------------------------------------- 7 | * Licensed Materials - Property of IBM 8 | * 5725-A06 5725-A29 5724-Y48 5724-Y49 5724-Y54 5724-Y55 5655-Y21 9 | * Copyright IBM Corporation 2001, 2019. All Rights Reserved. 10 | * 11 | * US Government Users Restricted Rights - Use, duplication or 12 | * disclosure restricted by GSA ADP Schedule Contract with 13 | * IBM Corp. 14 | * -------------------------------------------------------------------------- 15 | */ 16 | 17 | import ilog.concert.*; 18 | import ilog.cplex.*; 19 | import java.io.*; 20 | 21 | /** 22 | * Solve a capacitated facility location problem, potentially using Benders 23 | * decomposition. The model solved here is 24 | * minimize 25 | * sum(j in locations) fixedCost[j] * open[j] + 26 | * sum(j in locations) sum(i in clients) cost[i][j] * supply[i][j] 27 | * subject to 28 | * sum(j in locations) supply[i][j] == 1 for each 29 | * client i 30 | * sum(i in clients) supply[i][j] <= capacity[j] * open[j] for each 31 | * location j 32 | * supply[i][j] in [0,1] 33 | * open[j] in {0, 1} 34 | * For further details see the {@link usage()} function. 35 | */ 36 | public class Facility { 37 | static double[] capacity; 38 | static double[] fixedCost; 39 | static double[][] cost; 40 | 41 | static int nbLocations; 42 | static int nbClients; 43 | 44 | /** Dump a usage message and exit with error. */ 45 | static void usage() { 46 | for (final String line : new String[] { "Usage: java Facility [options] [inputfile]", " where", 47 | " inputfile describe a capacitated facility location instance as in", 48 | " ../../../examples/data/facility.dat. If no input file", 49 | " is specified read the file in example/data directory.", " Options are:", 50 | " -a solve problem with Benders letting CPLEX do the decomposition", 51 | " -b solve problem with Benders specifying a decomposition", 52 | " -d solve problem without using decomposition (default)", " Exiting..." }) 53 | System.err.println(line); 54 | System.exit(-1); 55 | } 56 | 57 | /** 58 | * Read data from fileName and store it in this class's 59 | * {@link capacity}, {@link fixedCost}, {@link cost}, {@link nbLocations}, and 60 | * {@link nbClients} fields. 61 | * 62 | * @param fileName Name of the file to read. 63 | */ 64 | static void readData(String fileName) throws IOException, InputDataReader.InputDataReaderException { 65 | System.out.println("Reading data from " + fileName); 66 | InputDataReader reader = new InputDataReader(fileName); 67 | 68 | fixedCost = reader.readDoubleArray(); 69 | cost = reader.readDoubleArrayArray(); 70 | capacity = reader.readDoubleArray(); 71 | 72 | nbLocations = capacity.length; 73 | nbClients = cost.length; 74 | 75 | // Check consistency of data. 76 | for (int i = 0; i < nbClients; i++) 77 | if (cost[i].length != nbLocations) 78 | throw new IllegalArgumentException("inconsistent data in file " + fileName); 79 | } 80 | 81 | /** Benders decomposition used for solving the model. */ 82 | private static enum BendersType { 83 | NO_BENDERS, AUTO_BENDERS, ANNO_BENDERS 84 | }; 85 | 86 | /** Solve capacitated facility location problem. */ 87 | public static void main(String[] args) { 88 | try { 89 | // Parse the command line. 90 | String filename = "./data/facility.dat"; 91 | BendersType benders = BendersType.NO_BENDERS; 92 | for (final String arg : args) { 93 | if (arg.startsWith("-")) { 94 | if (arg.equals("-a")) 95 | benders = BendersType.AUTO_BENDERS; 96 | else if (arg.equals("-b")) 97 | benders = BendersType.ANNO_BENDERS; 98 | else if (arg.equals("-d")) 99 | benders = BendersType.NO_BENDERS; 100 | else 101 | usage(); 102 | } else 103 | filename = arg; 104 | } 105 | 106 | // Read data. 107 | readData(filename); 108 | 109 | // Create the modeler/solver. 110 | IloCplex cplex = new IloCplex(); 111 | 112 | // Create variables. We have variables 113 | // open[j] if location j is open. 114 | // supply[i][j]] how much client i is supplied from location j 115 | IloNumVar[] open = cplex.boolVarArray(nbLocations); 116 | IloNumVar[][] supply = new IloNumVar[nbClients][]; 117 | for (int i = 0; i < nbClients; i++) 118 | supply[i] = cplex.numVarArray(nbLocations, 0.0, 1.0); 119 | 120 | // Constraint: Each client i must be assigned to exactly one location: 121 | // sum(j in nbLocations) supply[i][j] == 1 for each i in nbClients 122 | for (int i = 0; i < nbClients; i++) 123 | cplex.addEq(cplex.sum(supply[i]), 1); 124 | // Constraint: For each location j, the capacity of the location must 125 | // be respected: 126 | // sum(i in nbClients) supply[i][j] <= capacity[j] * open[j] 127 | for (int j = 0; j < nbLocations; j++) { 128 | IloLinearNumExpr v = cplex.linearNumExpr(); 129 | for (int i = 0; i < nbClients; i++) 130 | v.addTerm(1., supply[i][j]); 131 | cplex.addLe(v, cplex.prod(capacity[j], open[j])); 132 | } 133 | 134 | // Objective: Minimize the sum of fixed costs for using a location 135 | // and the costs for serving a client from a specific location. 136 | IloLinearNumExpr obj = cplex.scalProd(fixedCost, open); 137 | for (int i = 0; i < nbClients; i++) 138 | obj.add(cplex.scalProd(cost[i], supply[i])); 139 | cplex.addMinimize(obj); 140 | 141 | // Setup Benders decomposition if required. 142 | switch (benders) { 143 | case ANNO_BENDERS: 144 | // We specify the structure for doing a Benders decomposition by 145 | // telling CPLEX which variables are in the master problem using 146 | // annotations. By default variables are assigned value 147 | // CPX_BENDERS_MASTERVALUE+1 and thus go into the workers. 148 | // Variables open[j] should go into the master and therefore 149 | // we assign them value CPX_BENDERS_MASTER_VALUE. 150 | IloCplex.LongAnnotation decomp = cplex.newLongAnnotation(IloCplex.CPX_BENDERS_ANNOTATION, 151 | IloCplex.CPX_BENDERS_MASTERVALUE + 1); 152 | 153 | // 将open[j]放入主问题中 154 | for (int j = 0; j < nbLocations; ++j) 155 | cplex.setAnnotation(decomp, open[j], IloCplex.CPX_BENDERS_MASTERVALUE); 156 | cplex.output().println("Solving with explicit Benders decomposition."); 157 | break; 158 | case AUTO_BENDERS: 159 | // Let CPLEX automatically decompose the problem. In the case of 160 | // a capacitated facility location problem the variables of the 161 | // master problem should be the integer variables. By setting the 162 | // Benders strategy parameter to Full, CPLEX will put all integer 163 | // variables into the master, all continuous varibles into a 164 | // subproblem, and further decompose that subproblem, if possible. 165 | cplex.setParam(IloCplex.Param.Benders.Strategy, IloCplex.BendersStrategy.Full); 166 | cplex.output().println("Solving with automatic Benders decomposition."); 167 | break; 168 | case NO_BENDERS: 169 | cplex.output().println("Solving without Benders decomposition."); 170 | break; 171 | } 172 | 173 | // Solve and display solution. 174 | if (cplex.solve()) { 175 | cplex.output().println("Solution status: " + cplex.getStatus()); 176 | double tolerance = cplex.getParam(IloCplex.Param.MIP.Tolerances.Integrality); 177 | cplex.output().println("Optimal value: " + cplex.getObjValue()); 178 | for (int j = 0; j < nbLocations; j++) { 179 | if (cplex.getValue(open[j]) >= 1 - tolerance) { 180 | cplex.output().print("Facility " + j + " is open, it serves clients"); 181 | for (int i = 0; i < nbClients; i++) 182 | if (cplex.getValue(supply[i][j]) >= 1 - tolerance) 183 | cplex.output().print(" " + i); 184 | cplex.output().println(); 185 | } 186 | } 187 | } 188 | cplex.end(); 189 | } catch (IloException exc) { 190 | System.err.println("Concert exception '" + exc + "' caught"); 191 | System.exit(-1); 192 | } catch (IOException exc) { 193 | System.err.println("Error reading file " + args[0] + ": " + exc); 194 | System.exit(-1); 195 | } catch (InputDataReader.InputDataReaderException exc) { 196 | System.err.println(exc); 197 | System.exit(-1); 198 | } 199 | } 200 | } 201 | -------------------------------------------------------------------------------- /examples/FixCost1.java: -------------------------------------------------------------------------------- 1 | package examples; 2 | /* -------------------------------------------------------------------------- 3 | * File: FixCost1.java 4 | * Version 12.9.0 5 | * -------------------------------------------------------------------------- 6 | * Licensed Materials - Property of IBM 7 | * 5725-A06 5725-A29 5724-Y48 5724-Y49 5724-Y54 5724-Y55 5655-Y21 8 | * Copyright IBM Corporation 2001, 2019. All Rights Reserved. 9 | * 10 | * US Government Users Restricted Rights - Use, duplication or 11 | * disclosure restricted by GSA ADP Schedule Contract with 12 | * IBM Corp. 13 | * -------------------------------------------------------------------------- 14 | * 15 | * Problem Description 16 | * ------------------- 17 | * 18 | * A company must produce a product on a set of machines. 19 | * Each machine has limited capacity. 20 | * Producing a product on a machine has both a fixed cost 21 | * and a cost per unit of production. 22 | * 23 | * Minimize the sum of fixed and variable costs so that the 24 | * company exactly meets demand. 25 | */ 26 | 27 | import ilog.concert.*; 28 | import ilog.cplex.*; 29 | 30 | public class FixCost1 { 31 | static int _nbMachines = 6; 32 | static double[] _cost = { 15.0, 20.0, 45.0, 64.0, 12.0, 56.0 }; 33 | static double[] _capacity = { 100.0, 20.0, 405.0, 264.0, 12.0, 256.0 }; 34 | static double[] _fixedCost = { 1900.0, 820.0, 805.0, 464.0, 3912.0, 556.0 }; 35 | static double _demand = 22.0; 36 | 37 | public static void main(String[] args) { 38 | try { 39 | IloCplex cplex = new IloCplex(); 40 | 41 | IloNumVar[] fused = cplex.boolVarArray(_nbMachines); 42 | IloNumVar[] x = cplex.numVarArray(_nbMachines, 0.0, Double.MAX_VALUE); 43 | 44 | // Objective: minimize the sum of fixed and variable costs 45 | cplex.addMinimize(cplex.sum(cplex.scalProd(_cost, x), cplex.scalProd(fused, _fixedCost))); 46 | 47 | for (int i = 0; i < _nbMachines; i++) { 48 | // Constraint: respect capacity constraint on machine 'i' 49 | cplex.addLe(x[i], _capacity[i]); 50 | 51 | // Constraint: only produce product on machine 'i' if it is 'used' 52 | // (to capture fixed cost of using machine 'i') 53 | cplex.addLe(x[i], cplex.prod(10000, fused[i])); 54 | } 55 | 56 | // Constraint: meet demand 57 | cplex.addEq(cplex.sum(x), _demand); 58 | 59 | if (cplex.solve()) { 60 | System.out.println("Solution status: " + cplex.getStatus()); 61 | System.out.println("Obj " + cplex.getObjValue()); 62 | // 完整性容错,指定整数变量可与某个整数相差且视为可行的偏差 63 | double eps = cplex.getParam(IloCplex.Param.MIP.Tolerances.Integrality); 64 | for (int i = 0; i < _nbMachines; i++) 65 | if (cplex.getValue(fused[i]) > eps) 66 | System.out.println("E" + i + " is used for " + cplex.getValue(x[i])); 67 | 68 | System.out.println(); 69 | System.out.println("----------------------------------------"); 70 | } 71 | cplex.end(); 72 | } catch (IloException exc) { 73 | System.err.println("Concert exception '" + exc + "' caught"); 74 | } 75 | } 76 | } 77 | 78 | /* 79 | * Solution Obj 1788 E5 is used for 22 80 | */ 81 | -------------------------------------------------------------------------------- /examples/FixNet.java: -------------------------------------------------------------------------------- 1 | package examples; 2 | // -------------------------------------------------------------------------- 3 | // File: FixNet.java 4 | // Version 12.9.0 5 | // -------------------------------------------------------------------------- 6 | // Licensed Materials - Property of IBM 7 | // 5725-A06 5725-A29 5724-Y48 5724-Y49 5724-Y54 5724-Y55 5655-Y21 8 | // Copyright IBM Corporation 2018, 2019. All Rights Reserved. 9 | // 10 | // US Government Users Restricted Rights - Use, duplication or 11 | // disclosure restricted by GSA ADP Schedule Contract with 12 | // IBM Corp. 13 | // -------------------------------------------------------------------------- 14 | // 15 | 16 | import ilog.concert.IloException; 17 | import ilog.concert.IloNumVar; 18 | import ilog.concert.IloLinearNumExpr; 19 | import ilog.cplex.IloCplex; 20 | 21 | /** FixNet.java - Use logical constraints to avoid numerical trouble in a 22 | * fixed charge network flow problem. 23 | * 24 | * Find a minimum cost flow in a fixed charge network flow problem. 25 | * The network is as follows: 26 | *
 27 |  *       1 -- 3 ---> demand = 1,000,000
 28 |  *      / \  /       
 29 |  *     /   \/        
 30 |  *    0    /\        
 31 |  *     \  /  \       
 32 |  *      \/    \      
 33 |  *       2 -- 4 ---> demand = 1
 34 |  * 
35 | * A fixed charge of one is incurred for every edge with non-zero flow, 36 | * with the exception of edge <1,4>, which has a fixed charge of ten. 37 | * The cost per unit of flow on an edge is zero, with the exception of 38 | * edge <2,4>, where the cost per unit of flow is five. 39 | */ 40 | 41 | public final class FixNet { 42 | 43 | // Define origin and destination nodes for each edge, as well as 44 | // unit costs and fixed costs for transporting flow on each edge. 45 | // Note that by defining a fixed cost of 0 for each arc you just 46 | // get a regular min-cost flow problem. 47 | private static final int[] orig = new int[]{0,0,1,1,2,2}; 48 | private static final int[] dest = new int[]{1,2,3,4,3,4}; 49 | private static final double[] unitcost = new double[]{0,0,0,0,0,5}; 50 | private static final double[] fixedcost = new double[]{1,1,1,10,1,1}; 51 | 52 | // Define demand (supply) at each node. 53 | private static final double[] demand = new double[]{-1000001, 0, 0, 1000000, 1}; 54 | 55 | public static void main(String[] args) throws IloException { 56 | final IloCplex cplex = new IloCplex(); 57 | 58 | try { 59 | // Create the variables. 60 | // x variables are continuous variables in [0, infinity[, 61 | // f variables are binary variables. 62 | IloNumVar[] x = cplex.numVarArray(orig.length, 0.0, Double.POSITIVE_INFINITY); 63 | for (int i = 0; i < x.length; ++i) 64 | x[i].setName(String.format("x%d%d", orig[i], dest[i])); 65 | IloNumVar[] f = cplex.boolVarArray(orig.length); 66 | for (int i = 0; i < f.length; ++i) 67 | x[i].setName(String.format("f%d%d", orig[i], dest[i])); 68 | 69 | // Create objective function. 70 | cplex.addMinimize(cplex.sum(cplex.scalProd(unitcost, x), 71 | cplex.scalProd(fixedcost, f))); 72 | 73 | // Create constraints. 74 | // There is one constraint for each node. The constraint for a node i 75 | // states that the flow leaving i and the flow entering i must differ 76 | // by at least the demand for i. 77 | for (int i = 0; i < demand.length; ++i) { 78 | IloLinearNumExpr sum = cplex.linearNumExpr(); 79 | for (int j = 0; j < orig.length; ++j) { 80 | if ( orig[j] == i ) 81 | sum.addTerm(-1.0, x[j]); 82 | if ( dest[j] == i) 83 | sum.addTerm(+1.0, x[j]); 84 | } 85 | cplex.addGe(sum, demand[i]); 86 | } 87 | 88 | // Add logical constraints that require x[i]==0 if f[i] is 0. 89 | for (int i = 0; i < orig.length; ++i) 90 | cplex.add(cplex.ifThen(cplex.eq(f[i], 0.0), cplex.eq(x[i], 0.0))); 91 | 92 | // Solve the problem. 93 | cplex.solve(); 94 | 95 | // Write solution value and objective to the screen. 96 | System.out.println("Solution status: " + cplex.getStatus()); 97 | System.out.println("Solution value = " + cplex.getObjValue()); 98 | System.out.println("Solution vector:"); 99 | for (IloNumVar v : x) 100 | System.out.println(String.format("%10s: %15.6f", v.getName(), cplex.getValue(v))); 101 | for (IloNumVar v : f) 102 | System.out.println(String.format("%10s: %15.6f", v.getName(), cplex.getValue(v))); 103 | 104 | // Finally dump the model 105 | cplex.exportModel("FixNet.lp"); 106 | } 107 | finally { 108 | cplex.end(); 109 | } 110 | } 111 | } 112 | 113 | -------------------------------------------------------------------------------- /examples/GlobalQPex1.java: -------------------------------------------------------------------------------- 1 | package examples; 2 | /* -------------------------------------------------------------------------- 3 | * File: GlobalQPex1.java 4 | * Version 12.9.0 5 | * -------------------------------------------------------------------------- 6 | * Licensed Materials - Property of IBM 7 | * 5725-A06 5725-A29 5724-Y48 5724-Y49 5724-Y54 5724-Y55 5655-Y21 8 | * Copyright IBM Corporation 2001, 2019. All Rights Reserved. 9 | * 10 | * US Government Users Restricted Rights - Use, duplication or 11 | * disclosure restricted by GSA ADP Schedule Contract with 12 | * IBM Corp. 13 | * -------------------------------------------------------------------------- 14 | * 15 | * GlobalQPex1.java - Reading in and optimizing a convex or nonconvex (mixed-integer) QP 16 | * with convex, first order or global optimizer. 17 | * 18 | * To run this example, command line arguments are required. 19 | * That is: java GlobalQPex1 filename optimalitytarget 20 | * where 21 | * filename is the name of the file, with .mps, .lp, or .sav extension 22 | * optimalitytarget is the optimality target 23 | * c for a convex qp or miqp 24 | * f for a first order solution (only qp) 25 | * g for the global optimum 26 | * 27 | * Example: 28 | * java GlobalQPex1 nonconvexqp.lp g 29 | */ 30 | 31 | import ilog.concert.*; 32 | import ilog.cplex.*; 33 | 34 | 35 | public class GlobalQPex1 { 36 | static void usage() { 37 | System.out.println("usage: GlobalQPex1 "); 38 | System.out.println(" c convex QP or MIQP"); 39 | System.out.println(" f first order solution (only QP)"); 40 | System.out.println(" g global optimum"); 41 | } 42 | 43 | 44 | public static void main(String[] args) { 45 | IloCplex cplex = null; 46 | try { 47 | cplex = new IloCplex(); 48 | 49 | // Evaluate command line option and set optimality target accordingly. 50 | switch ( args[1].charAt(0) ) { 51 | case 'c': cplex.setParam(IloCplex.Param.OptimalityTarget, 52 | IloCplex.OptimalityTarget.OptimalConvex); 53 | break; 54 | case 'f': cplex.setParam(IloCplex.Param.OptimalityTarget, 55 | IloCplex.OptimalityTarget.FirstOrder); 56 | break; 57 | case 'g': cplex.setParam(IloCplex.Param.OptimalityTarget, 58 | IloCplex.OptimalityTarget.OptimalGlobal); 59 | break; 60 | default: usage(); 61 | return; 62 | } 63 | 64 | cplex.importModel(args[0]); 65 | 66 | // CPLEX may converge to either local optimum 67 | solveAndDisplay(cplex); 68 | } 69 | catch (IloCplexModeler.Exception e) { 70 | if ( args[1].charAt(0) == 'c' && 71 | e.getStatus() == 5002 ) { 72 | /* Status 5002 is CPXERR_Q_NOT_POS_DEF */ 73 | if (cplex.isMIP() == true) { 74 | System.out.println("Problem is not convex. Use argument g to get global optimum."); 75 | } 76 | else { 77 | System.out.print("Problem is not convex. Use argument f to get local optimum "); 78 | System.out.println("or g to get global optimum."); 79 | } 80 | } 81 | else if ( args[1].charAt(0) == 'f' && 82 | e.getStatus() == 1017 && 83 | cplex.isMIP() ) { 84 | /* Status 1017 is CPXERR_NOT_FOR_MIP */ 85 | System.out.print("Problem is a MIP, cannot compute local optima satifying "); 86 | System.out.println("the first order KKT."); 87 | System.out.println("Use argument g to get the global optimum."); 88 | } 89 | else { 90 | System.err.println("Cplex exception '" + e + "' caught"); 91 | } 92 | } 93 | catch (IloException e) { 94 | System.err.println("Concert exception '" + e + "' caught"); 95 | } 96 | finally { 97 | if (cplex != null) 98 | cplex.end(); 99 | } 100 | } 101 | 102 | static void solveAndDisplay(IloCplex cplex) throws IloException { 103 | if ( cplex.solve() ) { 104 | IloLPMatrix lp = (IloLPMatrix)cplex.LPMatrixIterator().next(); 105 | 106 | double[] x = cplex.getValues(lp); 107 | double[] slack = cplex.getSlacks(lp); 108 | 109 | System.out.println("Solution status = " + cplex.getStatus()); 110 | System.out.println("Solution value = " + cplex.getObjValue()); 111 | 112 | int nvars = x.length; 113 | for (int j = 0; j < nvars; ++j) 114 | System.out.println("Variable " + j + ": Value = " + x[j]); 115 | 116 | int ncons = slack.length; 117 | for (int i = 0; i < ncons; ++i) 118 | System.out.println("Constraint " + i + ": Slack = " + slack[i]); 119 | } 120 | } 121 | } 122 | -------------------------------------------------------------------------------- /examples/Goalex1.java: -------------------------------------------------------------------------------- 1 | package examples; 2 | 3 | /* -------------------------------------------------------------------------- 4 | * File: Goalex1.java 5 | * Version 12.9.0 6 | * -------------------------------------------------------------------------- 7 | * Licensed Materials - Property of IBM 8 | * 5725-A06 5725-A29 5724-Y48 5724-Y49 5724-Y54 5724-Y55 5655-Y21 9 | * Copyright IBM Corporation 2001, 2019. All Rights Reserved. 10 | * 11 | * US Government Users Restricted Rights - Use, duplication or 12 | * disclosure restricted by GSA ADP Schedule Contract with 13 | * IBM Corp. 14 | * -------------------------------------------------------------------------- 15 | * 16 | * Goalex1.java - A simple goal example. 17 | * 18 | * Create a branch goal that chooses the variable 19 | * with the largest objective from amongst those 20 | * with the largest integer infeasibility. 21 | */ 22 | 23 | import ilog.cplex.*; 24 | import ilog.concert.*; 25 | 26 | public class Goalex1 { 27 | /** 28 | * Advanced classes,比较难,慎用 29 | * IloCplex.Goal可用于控制Branch-and-Cut的搜索过程,某种程度来说可作为Callback的另一种形式(参见AdMIPex1.java) 30 | * 需要实现execute方法,然后通过cplex.solve(用户定义的Goal子类实例)传入Cplex 31 | * 每一个Node都有一个Goal栈 32 | * 在Node的松弛问题求解之后,excute方法会被调用(基于Goal栈进行Branch-and-Cut搜索) 33 | */ 34 | static class MyBranchGoal extends IloCplex.Goal { 35 | IloNumVar[] _vars; 36 | 37 | MyBranchGoal(IloNumVar[] vars) { 38 | _vars = vars; 39 | } 40 | 41 | // Branch on var with largest objective coefficient 42 | // among those with largest infeasibility 43 | public IloCplex.Goal execute(IloCplex cplex) throws IloException { 44 | double[] x = getValues(_vars); 45 | double[] obj = getObjCoefs(_vars); 46 | IloCplex.IntegerFeasibilityStatus[] feas = getFeasibilities(_vars); 47 | 48 | double maxinf = 0.0; 49 | double maxobj = 0.0; 50 | int bestj = -1; 51 | int cols = _vars.length; 52 | for (int j = 0; j < cols; ++j) { 53 | if (feas[j].equals(IloCplex.IntegerFeasibilityStatus.Infeasible)) { 54 | double xj_inf = x[j] - Math.floor(x[j]); 55 | if (xj_inf > 0.5) 56 | xj_inf = 1.0 - xj_inf; 57 | if (xj_inf >= maxinf && (xj_inf > maxinf || Math.abs(obj[j]) >= maxobj)) { 58 | bestj = j; 59 | maxinf = xj_inf; 60 | maxobj = Math.abs(obj[j]); 61 | } 62 | } 63 | } 64 | 65 | if (bestj >= 0) { 66 | return cplex.and(cplex.or(cplex.geGoal(_vars[bestj], Math.floor(x[bestj]) + 1), 67 | cplex.leGoal(_vars[bestj], Math.floor(x[bestj]))), this); 68 | } else 69 | return null; 70 | } 71 | } 72 | 73 | public static void main(String[] args) { 74 | if (args.length != 1) { 75 | System.out.println("Usage: Goalex1 filename"); 76 | System.out.println(" where filename is a file with extension "); 77 | System.out.println(" MPS, SAV, or LP (lower case is allowed)"); 78 | System.out.println(" Exiting..."); 79 | System.exit(-1); 80 | } 81 | 82 | try { 83 | IloCplex cplex = new IloCplex(); 84 | 85 | cplex.importModel(args[0]); 86 | IloLPMatrix lp = (IloLPMatrix) cplex.LPMatrixIterator().next(); 87 | 88 | cplex.setParam(IloCplex.Param.MIP.Strategy.Search, IloCplex.MIPSearch.Traditional); 89 | if (cplex.solve(new MyBranchGoal(lp.getNumVars()))) { 90 | System.out.println("Solution status = " + cplex.getStatus()); 91 | System.out.println("Solution value = " + cplex.getObjValue()); 92 | } 93 | 94 | cplex.end(); 95 | } catch (IloException e) { 96 | System.err.println("Concert exception caught: " + e); 97 | } 98 | } 99 | } 100 | -------------------------------------------------------------------------------- /examples/Goalex2.java: -------------------------------------------------------------------------------- 1 | package examples; 2 | 3 | /* -------------------------------------------------------------------------- 4 | * File: Goalex2.java 5 | * Version 12.9.0 6 | * -------------------------------------------------------------------------- 7 | * Licensed Materials - Property of IBM 8 | * 5725-A06 5725-A29 5724-Y48 5724-Y49 5724-Y54 5724-Y55 5655-Y21 9 | * Copyright IBM Corporation 2001, 2019. All Rights Reserved. 10 | * 11 | * US Government Users Restricted Rights - Use, duplication or 12 | * disclosure restricted by GSA ADP Schedule Contract with 13 | * IBM Corp. 14 | * -------------------------------------------------------------------------- 15 | * 16 | * Goalex2.java -- Solving noswot by adding cuts with goals 17 | */ 18 | 19 | import ilog.cplex.*; 20 | import ilog.concert.*; 21 | 22 | public class Goalex2 { 23 | static class CutGoal extends IloCplex.Goal { 24 | double eps = 1.0e-6; 25 | IloRange[] cut; 26 | 27 | CutGoal(IloRange[] cuts) { 28 | cut = cuts; 29 | } 30 | 31 | // 可参考AdMIPex4.java 32 | public IloCplex.Goal execute(IloCplex cplex) throws IloException { 33 | if (isIntegerFeasible()) 34 | return null; 35 | 36 | int num = cut.length; 37 | IloCplex.Goal goal = this; 38 | for (int i = 0; i < num; ++i) { 39 | IloRange thecut = cut[i]; 40 | if (thecut != null) { 41 | double val = getValue(thecut.getExpr()); 42 | if (thecut.getLB() > val + eps || val - eps > thecut.getUB()) { 43 | goal = cplex.and(cplex.globalCutGoal(thecut), goal); 44 | cut[i] = null; 45 | } 46 | } 47 | } 48 | 49 | if (goal == this) 50 | goal = cplex.and(cplex.branchAsCplex(), goal); 51 | 52 | return goal; 53 | } 54 | } 55 | 56 | static IloRange[] makeCuts(IloModeler m, IloLPMatrix lp) throws IloException { 57 | IloNumVar x11 = null, x12 = null, x13 = null, x14 = null, x15 = null; 58 | IloNumVar x21 = null, x22 = null, x23 = null, x24 = null, x25 = null; 59 | IloNumVar x31 = null, x32 = null, x33 = null, x34 = null, x35 = null; 60 | IloNumVar x41 = null, x42 = null, x43 = null, x44 = null, x45 = null; 61 | IloNumVar x51 = null, x52 = null, x53 = null, x54 = null, x55 = null; 62 | IloNumVar w11 = null, w12 = null, w13 = null, w14 = null, w15 = null; 63 | IloNumVar w21 = null, w22 = null, w23 = null, w24 = null, w25 = null; 64 | IloNumVar w31 = null, w32 = null, w33 = null, w34 = null, w35 = null; 65 | IloNumVar w41 = null, w42 = null, w43 = null, w44 = null, w45 = null; 66 | IloNumVar w51 = null, w52 = null, w53 = null, w54 = null, w55 = null; 67 | 68 | IloNumVar[] vars = lp.getNumVars(); 69 | int num = vars.length; 70 | 71 | for (int i = 0; i < num; ++i) { 72 | if (vars[i].getName().equals("X11")) 73 | x11 = vars[i]; 74 | else if (vars[i].getName().equals("X12")) 75 | x12 = vars[i]; 76 | else if (vars[i].getName().equals("X13")) 77 | x13 = vars[i]; 78 | else if (vars[i].getName().equals("X14")) 79 | x14 = vars[i]; 80 | else if (vars[i].getName().equals("X15")) 81 | x15 = vars[i]; 82 | else if (vars[i].getName().equals("X21")) 83 | x21 = vars[i]; 84 | else if (vars[i].getName().equals("X22")) 85 | x22 = vars[i]; 86 | else if (vars[i].getName().equals("X23")) 87 | x23 = vars[i]; 88 | else if (vars[i].getName().equals("X24")) 89 | x24 = vars[i]; 90 | else if (vars[i].getName().equals("X25")) 91 | x25 = vars[i]; 92 | else if (vars[i].getName().equals("X31")) 93 | x31 = vars[i]; 94 | else if (vars[i].getName().equals("X32")) 95 | x32 = vars[i]; 96 | else if (vars[i].getName().equals("X33")) 97 | x33 = vars[i]; 98 | else if (vars[i].getName().equals("X34")) 99 | x34 = vars[i]; 100 | else if (vars[i].getName().equals("X35")) 101 | x35 = vars[i]; 102 | else if (vars[i].getName().equals("X41")) 103 | x41 = vars[i]; 104 | else if (vars[i].getName().equals("X42")) 105 | x42 = vars[i]; 106 | else if (vars[i].getName().equals("X43")) 107 | x43 = vars[i]; 108 | else if (vars[i].getName().equals("X44")) 109 | x44 = vars[i]; 110 | else if (vars[i].getName().equals("X45")) 111 | x45 = vars[i]; 112 | else if (vars[i].getName().equals("X51")) 113 | x51 = vars[i]; 114 | else if (vars[i].getName().equals("X52")) 115 | x52 = vars[i]; 116 | else if (vars[i].getName().equals("X53")) 117 | x53 = vars[i]; 118 | else if (vars[i].getName().equals("X54")) 119 | x54 = vars[i]; 120 | else if (vars[i].getName().equals("X55")) 121 | x55 = vars[i]; 122 | else if (vars[i].getName().equals("W11")) 123 | w11 = vars[i]; 124 | else if (vars[i].getName().equals("W12")) 125 | w12 = vars[i]; 126 | else if (vars[i].getName().equals("W13")) 127 | w13 = vars[i]; 128 | else if (vars[i].getName().equals("W14")) 129 | w14 = vars[i]; 130 | else if (vars[i].getName().equals("W15")) 131 | w15 = vars[i]; 132 | else if (vars[i].getName().equals("W21")) 133 | w21 = vars[i]; 134 | else if (vars[i].getName().equals("W22")) 135 | w22 = vars[i]; 136 | else if (vars[i].getName().equals("W23")) 137 | w23 = vars[i]; 138 | else if (vars[i].getName().equals("W24")) 139 | w24 = vars[i]; 140 | else if (vars[i].getName().equals("W25")) 141 | w25 = vars[i]; 142 | else if (vars[i].getName().equals("W31")) 143 | w31 = vars[i]; 144 | else if (vars[i].getName().equals("W32")) 145 | w32 = vars[i]; 146 | else if (vars[i].getName().equals("W33")) 147 | w33 = vars[i]; 148 | else if (vars[i].getName().equals("W34")) 149 | w34 = vars[i]; 150 | else if (vars[i].getName().equals("W35")) 151 | w35 = vars[i]; 152 | else if (vars[i].getName().equals("W41")) 153 | w41 = vars[i]; 154 | else if (vars[i].getName().equals("W42")) 155 | w42 = vars[i]; 156 | else if (vars[i].getName().equals("W43")) 157 | w43 = vars[i]; 158 | else if (vars[i].getName().equals("W44")) 159 | w44 = vars[i]; 160 | else if (vars[i].getName().equals("W45")) 161 | w45 = vars[i]; 162 | else if (vars[i].getName().equals("W51")) 163 | w51 = vars[i]; 164 | else if (vars[i].getName().equals("W52")) 165 | w52 = vars[i]; 166 | else if (vars[i].getName().equals("W53")) 167 | w53 = vars[i]; 168 | else if (vars[i].getName().equals("W54")) 169 | w54 = vars[i]; 170 | else if (vars[i].getName().equals("W55")) 171 | w55 = vars[i]; 172 | } 173 | 174 | IloRange[] cut = new IloRange[8]; 175 | 176 | cut[0] = m.le(m.diff(x21, x22), 0.0); 177 | cut[1] = m.le(m.diff(x22, x23), 0.0); 178 | cut[2] = m.le(m.diff(x23, x24), 0.0); 179 | cut[3] = m.le(m.sum( 180 | m.sum(m.prod(2.08, x11), m.prod(2.98, x21), m.prod(3.47, x31), m.prod(2.24, x41), m.prod(2.08, x51)), 181 | m.sum(m.prod(0.25, w11), m.prod(0.25, w21), m.prod(0.25, w31), m.prod(0.25, w41), m.prod(0.25, w51))), 182 | 20.25); 183 | cut[4] = m.le(m.sum( 184 | m.sum(m.prod(2.08, x12), m.prod(2.98, x22), m.prod(3.47, x32), m.prod(2.24, x42), m.prod(2.08, x52)), 185 | m.sum(m.prod(0.25, w12), m.prod(0.25, w22), m.prod(0.25, w32), m.prod(0.25, w42), m.prod(0.25, w52))), 186 | 20.25); 187 | cut[5] = m.le(m.sum( 188 | m.sum(m.prod(2.08, x13), m.prod(2.98, x23), m.prod(3.47, x33), m.prod(2.24, x43), m.prod(2.08, x53)), 189 | m.sum(m.prod(0.25, w13), m.prod(0.25, w23), m.prod(0.25, w33), m.prod(0.25, w43), m.prod(0.25, w53))), 190 | 20.25); 191 | cut[6] = m.le(m.sum( 192 | m.sum(m.prod(2.08, x14), m.prod(2.98, x24), m.prod(3.47, x34), m.prod(2.24, x44), m.prod(2.08, x54)), 193 | m.sum(m.prod(0.25, w14), m.prod(0.25, w24), m.prod(0.25, w34), m.prod(0.25, w44), m.prod(0.25, w54))), 194 | 20.25); 195 | cut[7] = m.le(m.sum( 196 | m.sum(m.prod(2.08, x15), m.prod(2.98, x25), m.prod(3.47, x35), m.prod(2.24, x45), m.prod(2.08, x55)), 197 | m.sum(m.prod(0.25, w15), m.prod(0.25, w25), m.prod(0.25, w35), m.prod(0.25, w45), m.prod(0.25, w55))), 198 | 16.25); 199 | 200 | return cut; 201 | } 202 | 203 | public static void main(String[] args) { 204 | try { 205 | IloCplex cplex = new IloCplex(); 206 | 207 | cplex.importModel("../../../examples/data/noswot.mps"); 208 | IloLPMatrix lp = (IloLPMatrix) cplex.LPMatrixIterator().next(); 209 | 210 | cplex.setParam(IloCplex.Param.MIP.Interval, 1000); 211 | cplex.setParam(IloCplex.Param.MIP.Strategy.Search, IloCplex.MIPSearch.Traditional); 212 | if (cplex.solve(new CutGoal(makeCuts(cplex, lp)))) { 213 | System.out.println("Solution status = " + cplex.getStatus()); 214 | System.out.println("Solution value = " + cplex.getObjValue()); 215 | } 216 | 217 | cplex.end(); 218 | } catch (IloException e) { 219 | System.err.println("Concert exception caught: " + e); 220 | } 221 | } 222 | } 223 | -------------------------------------------------------------------------------- /examples/Goalex3.java: -------------------------------------------------------------------------------- 1 | package examples; 2 | 3 | /* -------------------------------------------------------------------------- 4 | * File: Goalex3.java 5 | * Version 12.9.0 6 | * -------------------------------------------------------------------------- 7 | * Licensed Materials - Property of IBM 8 | * 5725-A06 5725-A29 5724-Y48 5724-Y49 5724-Y54 5724-Y55 5655-Y21 9 | * Copyright IBM Corporation 2001, 2019. All Rights Reserved. 10 | * 11 | * US Government Users Restricted Rights - Use, duplication or 12 | * disclosure restricted by GSA ADP Schedule Contract with 13 | * IBM Corp. 14 | * -------------------------------------------------------------------------- 15 | * 16 | * Goalex3.java - Node selectors in goal search 17 | * 18 | * This is an extension of example Goalex1.java. 19 | * It adds node evaluators to further control the 20 | * goal based search. The node evaluator chooses 21 | * the node that is deepest in the tree among those 22 | * with maximum sum of integer infeasibilities 23 | */ 24 | 25 | import ilog.cplex.*; 26 | import ilog.concert.*; 27 | 28 | public class Goalex3 { 29 | public static class MyBranchGoal extends IloCplex.Goal { 30 | IloNumVar[] _vars; 31 | 32 | MyBranchGoal(IloNumVar[] vars) { 33 | _vars = vars; 34 | } 35 | 36 | // Branch on var with largest objective coefficient 37 | // among those with largest infeasibility 38 | public IloCplex.Goal execute(IloCplex cplex) throws IloException { 39 | double[] x = getValues(_vars); 40 | double[] obj = getObjCoefs(_vars); 41 | IloCplex.IntegerFeasibilityStatus[] feas = getFeasibilities(_vars); 42 | 43 | double maxinf = 0.0; 44 | double maxobj = 0.0; 45 | int bestj = -1; 46 | int cols = _vars.length; 47 | for (int j = 0; j < cols; ++j) { 48 | if (feas[j].equals(IloCplex.IntegerFeasibilityStatus.Infeasible)) { 49 | double xj_inf = x[j] - Math.floor(x[j]); 50 | if (xj_inf > 0.5) 51 | xj_inf = 1.0 - xj_inf; 52 | if (xj_inf >= maxinf && (xj_inf > maxinf || Math.abs(obj[j]) >= maxobj)) { 53 | bestj = j; 54 | maxinf = xj_inf; 55 | maxobj = Math.abs(obj[j]); 56 | } 57 | } 58 | } 59 | 60 | if (bestj >= 0) { 61 | return cplex.and(cplex.or(cplex.geGoal(_vars[bestj], Math.floor(x[bestj]) + 1), 62 | cplex.leGoal(_vars[bestj], Math.floor(x[bestj]))), this); 63 | } else 64 | return null; 65 | } 66 | } 67 | 68 | public static class MyDepthEvaluator extends IloCplex.NodeEvaluator { 69 | public double evaluate() throws IloException { 70 | return -getDepth(); 71 | } 72 | } 73 | 74 | public static class MyIISEvaluator extends IloCplex.NodeEvaluator { 75 | public double evaluate() throws IloException { 76 | return -getInfeasibilitySum(); 77 | } 78 | } 79 | 80 | public static void main(String[] args) { 81 | if (args.length != 1) { 82 | System.out.println("Usage: Goalex3 filename"); 83 | System.out.println(" where filename is a file with extension "); 84 | System.out.println(" MPS, SAV, or LP (lower case is allowed)"); 85 | System.out.println(" Exiting..."); 86 | System.exit(-1); 87 | } 88 | 89 | try { 90 | IloCplex cplex = new IloCplex(); 91 | 92 | cplex.importModel(args[0]); 93 | IloLPMatrix lp = (IloLPMatrix) cplex.LPMatrixIterator().next(); 94 | 95 | // 对比adMIPex1.java的实现 96 | IloCplex.Goal iiSumGoal = cplex.apply(new MyBranchGoal(lp.getNumVars()), new MyIISEvaluator()); 97 | IloCplex.Goal depthGoal = cplex.apply(iiSumGoal, new MyDepthEvaluator()); 98 | 99 | cplex.setParam(IloCplex.Param.MIP.Strategy.Search, IloCplex.MIPSearch.Traditional); 100 | if (cplex.solve(depthGoal)) { 101 | System.out.println("Solution status = " + cplex.getStatus()); 102 | System.out.println("Solution value = " + cplex.getObjValue()); 103 | } 104 | 105 | cplex.end(); 106 | } catch (IloException e) { 107 | System.err.println("Concert exception caught: " + e); 108 | } 109 | } 110 | } 111 | -------------------------------------------------------------------------------- /examples/IndefQPex1.java: -------------------------------------------------------------------------------- 1 | package examples; 2 | /* -------------------------------------------------------------------------- 3 | * File: IndefQPex1.java 4 | * Version 12.9.0 5 | * -------------------------------------------------------------------------- 6 | * Licensed Materials - Property of IBM 7 | * 5725-A06 5725-A29 5724-Y48 5724-Y49 5724-Y54 5724-Y55 5655-Y21 8 | * Copyright IBM Corporation 2001, 2019. All Rights Reserved. 9 | * 10 | * US Government Users Restricted Rights - Use, duplication or 11 | * disclosure restricted by GSA ADP Schedule Contract with 12 | * IBM Corp. 13 | * -------------------------------------------------------------------------- 14 | * 15 | * IndefQPex1.java - Entering and optimizing an indefinite QP problem 16 | */ 17 | 18 | import ilog.concert.*; 19 | import ilog.cplex.*; 20 | 21 | 22 | public class IndefQPex1 { 23 | public static void main(String[] args) { 24 | try { 25 | IloCplex cplex = new IloCplex(); 26 | IloLPMatrix lp = populateByRow(cplex); 27 | 28 | int[] ind = {0}; 29 | double[] val = {1.0}; 30 | 31 | // When a non-convex objective function is present, CPLEX 32 | // will raise an exception unless the parameter 33 | // IloCplex.Param.OptimalityTarget is set to accept 34 | // first-order optimal solutions 35 | cplex.setParam(IloCplex.Param.OptimalityTarget, 36 | IloCplex.OptimalityTarget.FirstOrder); 37 | 38 | // CPLEX may converge to either local optimum 39 | solveAndDisplay(cplex, lp); 40 | 41 | // Add a constraint that cuts off the solution at (-1, 1) 42 | lp.addRow(0.0, Double.MAX_VALUE, ind, val); 43 | solveAndDisplay(cplex, lp); 44 | 45 | // Remove the newly added constraint and add a new constraint 46 | // with the opposite sense to cut off the solution at (1, 1) 47 | lp.removeRow(lp.getNrows() - 1); 48 | lp.addRow(-Double.MAX_VALUE, 0.0, ind, val); 49 | solveAndDisplay(cplex, lp); 50 | 51 | cplex.exportModel("indefqpex1.lp"); 52 | cplex.end(); 53 | } 54 | catch (IloException e) { 55 | System.err.println("Concert exception '" + e + "' caught"); 56 | } 57 | } 58 | 59 | // To populate by row, we first create the variables, and then use them to 60 | // create the range constraints and objective. The model we create is: 61 | // 62 | // Minimize 63 | // obj: - 0.5 (-3 * x^2 - 3 * y^2 - 1 * x * y) 64 | // Subject To 65 | // c1: -x + y >= 0 66 | // c2: x + y >= 0 67 | // Bounds 68 | // -1 <= x <= 1 69 | // 0 <= y <= 1 70 | // End 71 | 72 | static IloLPMatrix populateByRow(IloMPModeler model) throws IloException { 73 | IloLPMatrix lp = model.addLPMatrix(); 74 | 75 | double[] lb = {-1.0, 0.0}; 76 | double[] ub = { 1.0, 1.0}; 77 | IloNumVar[] x = model.numVarArray(model.columnArray(lp, 2), lb, ub); 78 | 79 | double[] lhs = {0.0, 0.0}; 80 | double[] rhs = {Double.MAX_VALUE, Double.MAX_VALUE}; 81 | double[][] val = {{-1.0, 1.0}, 82 | { 1.0, 1.0}}; 83 | int[][] ind = {{0, 1}, 84 | {0, 1}}; 85 | lp.addRows(lhs, rhs, ind, val); 86 | 87 | IloNumExpr x00 = model.prod(-3.0, x[0], x[0]); 88 | IloNumExpr x11 = model.prod(-3.0, x[1], x[1]); 89 | IloNumExpr x01 = model.prod(-1.0, x[0], x[1]); 90 | IloNumExpr Q = model.prod(0.5, model.sum(x00, x11, x01)); 91 | 92 | model.add(model.minimize(Q)); 93 | 94 | return (lp); 95 | } 96 | 97 | static void solveAndDisplay(IloCplex cplex, IloLPMatrix lp) throws IloException { 98 | 99 | if ( cplex.solve() ) { 100 | double[] x = cplex.getValues(lp); 101 | double[] dj = cplex.getReducedCosts(lp); 102 | double[] pi = cplex.getDuals(lp); 103 | double[] slack = cplex.getSlacks(lp); 104 | 105 | System.out.println("Solution status = " + cplex.getStatus()); 106 | System.out.println("Solution value = " + cplex.getObjValue()); 107 | 108 | int nvars = x.length; 109 | for (int j = 0; j < nvars; ++j) { 110 | System.out.println("Variable " + j + 111 | ": Value = " + x[j] + 112 | " Reduced cost = " + dj[j]); 113 | } 114 | 115 | int ncons = slack.length; 116 | for (int i = 0; i < ncons; ++i) { 117 | System.out.println("Constraint " + i + 118 | ": Slack = " + slack[i] + 119 | " Pi = " + pi[i]); 120 | } 121 | 122 | } 123 | } 124 | } 125 | -------------------------------------------------------------------------------- /examples/InputDataReader.java: -------------------------------------------------------------------------------- 1 | package examples; 2 | /* -------------------------------------------------------------------------- 3 | * File: InputDataReader.java 4 | * Version 12.9.0 5 | * -------------------------------------------------------------------------- 6 | * Licensed Materials - Property of IBM 7 | * 5725-A06 5725-A29 5724-Y48 5724-Y49 5724-Y54 5724-Y55 5655-Y21 8 | * Copyright IBM Corporation 2001, 2019. All Rights Reserved. 9 | * 10 | * US Government Users Restricted Rights - Use, duplication or 11 | * disclosure restricted by GSA ADP Schedule Contract with 12 | * IBM Corp. 13 | * -------------------------------------------------------------------------- 14 | * 15 | * This is a helper class used by several examples to read input data files 16 | * containing arrays in the format [x1, x2, ..., x3]. Up to two-dimensional 17 | * arrays are supported. 18 | */ 19 | 20 | import java.io.*; 21 | 22 | public class InputDataReader { 23 | public static class InputDataReaderException extends Exception { 24 | private static final long serialVersionUID = 1021L; 25 | InputDataReaderException(String file) { 26 | super("'" + file + "' contains bad data format"); 27 | } 28 | } 29 | 30 | StreamTokenizer _tokenizer; 31 | Reader _reader; 32 | String _fileName; 33 | 34 | public InputDataReader(String fileName) throws IOException { 35 | _reader = new FileReader(fileName); 36 | _fileName = fileName; 37 | 38 | _tokenizer = new StreamTokenizer(_reader); 39 | 40 | // State the '"', '\'' as white spaces. 41 | _tokenizer.whitespaceChars('"', '"'); 42 | _tokenizer.whitespaceChars('\'', '\''); 43 | 44 | // State the '[', ']' as normal characters. 45 | _tokenizer.ordinaryChar('['); 46 | _tokenizer.ordinaryChar(']'); 47 | _tokenizer.ordinaryChar(','); 48 | } 49 | 50 | protected void finalize() throws Throwable { 51 | _reader.close(); 52 | } 53 | 54 | double readDouble() throws InputDataReaderException, 55 | IOException { 56 | int ntType = _tokenizer.nextToken(); 57 | 58 | if ( ntType != StreamTokenizer.TT_NUMBER ) 59 | throw new InputDataReaderException(_fileName); 60 | 61 | return _tokenizer.nval; 62 | } 63 | 64 | int readInt() throws InputDataReaderException, 65 | IOException { 66 | int ntType = _tokenizer.nextToken(); 67 | 68 | if ( ntType != StreamTokenizer.TT_NUMBER ) 69 | throw new InputDataReaderException(_fileName); 70 | 71 | return (new Double(_tokenizer.nval)).intValue(); 72 | } 73 | 74 | double[] readDoubleArray() throws InputDataReaderException, 75 | IOException { 76 | int ntType = _tokenizer.nextToken(); // Read the '[' 77 | 78 | if ( ntType != '[' ) 79 | throw new InputDataReaderException(_fileName); 80 | 81 | DoubleArray values = new DoubleArray(); 82 | ntType = _tokenizer.nextToken(); 83 | while (ntType == StreamTokenizer.TT_NUMBER) { 84 | values.add(_tokenizer.nval); 85 | ntType = _tokenizer.nextToken(); 86 | 87 | if ( ntType == ',' ) { 88 | ntType = _tokenizer.nextToken(); 89 | } 90 | else if ( ntType != ']' ) { 91 | throw new InputDataReaderException(_fileName); 92 | } 93 | } 94 | 95 | if ( ntType != ']' ) 96 | throw new InputDataReaderException(_fileName); 97 | 98 | // Allocate and fill the array. 99 | double[] res = new double[values.getSize()]; 100 | for (int i = 0; i < values.getSize(); i++) { 101 | res[i] = values.getElement(i); 102 | } 103 | 104 | return res; 105 | } 106 | 107 | double[][] readDoubleArrayArray() throws InputDataReaderException, 108 | IOException { 109 | int ntType = _tokenizer.nextToken(); // Read the '[' 110 | 111 | if ( ntType != '[' ) 112 | throw new InputDataReaderException(_fileName); 113 | 114 | DoubleArrayArray values = new DoubleArrayArray(); 115 | ntType = _tokenizer.nextToken(); 116 | 117 | while (ntType == '[') { 118 | _tokenizer.pushBack(); 119 | 120 | values.add(readDoubleArray()); 121 | 122 | ntType = _tokenizer.nextToken(); 123 | if ( ntType == ',' ) { 124 | ntType = _tokenizer.nextToken(); 125 | } 126 | else if ( ntType != ']' ) { 127 | throw new InputDataReaderException(_fileName); 128 | } 129 | } 130 | 131 | if ( ntType != ']' ) 132 | throw new InputDataReaderException(_fileName); 133 | 134 | // Allocate and fill the array. 135 | double[][] res = new double[values.getSize()][]; 136 | for (int i = 0; i < values.getSize(); i++) { 137 | res[i] = new double[values.getSize(i)]; 138 | for (int j = 0; j < values.getSize(i); j++) { 139 | res[i][j] = values.getElement(i,j); 140 | } 141 | } 142 | return res; 143 | } 144 | 145 | int[] readIntArray() throws InputDataReaderException, 146 | IOException { 147 | int ntType = _tokenizer.nextToken(); // Read the '[' 148 | 149 | if ( ntType != '[' ) 150 | throw new InputDataReaderException(_fileName); 151 | 152 | IntArray values = new IntArray(); 153 | ntType = _tokenizer.nextToken(); 154 | while (ntType == StreamTokenizer.TT_NUMBER) { 155 | values.add(_tokenizer.nval); 156 | ntType = _tokenizer.nextToken(); 157 | 158 | if ( ntType == ',' ) { 159 | ntType = _tokenizer.nextToken(); 160 | } 161 | else if ( ntType != ']' ) { 162 | throw new InputDataReaderException(_fileName); 163 | } 164 | } 165 | 166 | if ( ntType != ']' ) 167 | throw new InputDataReaderException(_fileName); 168 | 169 | // Allocate and fill the array. 170 | int[] res = new int[values.getSize()]; 171 | for (int i = 0; i < values.getSize(); i++) { 172 | res[i] = values.getElement(i); 173 | } 174 | return res; 175 | } 176 | 177 | int[][] readIntArrayArray() throws InputDataReaderException, 178 | IOException { 179 | int ntType = _tokenizer.nextToken(); // Read the '[' 180 | 181 | if ( ntType != '[' ) 182 | throw new InputDataReaderException(_fileName); 183 | 184 | IntArrayArray values = new IntArrayArray(); 185 | ntType = _tokenizer.nextToken(); 186 | 187 | while (ntType == '[') { 188 | _tokenizer.pushBack(); 189 | 190 | values.add(readIntArray()); 191 | 192 | ntType = _tokenizer.nextToken(); 193 | if ( ntType == ',' ) { 194 | ntType = _tokenizer.nextToken(); 195 | } 196 | else if ( ntType != ']' ) { 197 | throw new InputDataReaderException(_fileName); 198 | } 199 | } 200 | 201 | if ( ntType != ']' ) 202 | throw new InputDataReaderException(_fileName); 203 | 204 | // Allocate and fill the array. 205 | int[][] res = new int[values.getSize()][]; 206 | for (int i = 0; i < values.getSize(); i++) { 207 | res[i] = new int[values.getSize(i)]; 208 | for (int j = 0; j < values.getSize(i); j++) { 209 | res[i][j] = values.getElement(i,j); 210 | } 211 | } 212 | return res; 213 | } 214 | 215 | private class DoubleArray { 216 | int _num = 0; 217 | double[] _array = new double[32]; 218 | 219 | final void add(double dval) { 220 | if ( _num >= _array.length ) { 221 | double[] array = new double[2 * _array.length]; 222 | System.arraycopy(_array, 0, array, 0, _num); 223 | _array = array; 224 | } 225 | _array[_num++] = dval; 226 | } 227 | 228 | final double getElement(int i) { return _array[i]; } 229 | final int getSize() { return _num; } 230 | } 231 | 232 | private class DoubleArrayArray { 233 | int _num = 0; 234 | double[][] _array = new double[32][]; 235 | 236 | final void add(double[] dray) { 237 | 238 | if ( _num >= _array.length ) { 239 | double[][] array = new double[2 * _array.length][]; 240 | for (int i = 0; i < _num; i++) { 241 | array[i] = _array[i]; 242 | } 243 | _array = array; 244 | } 245 | _array[_num] = new double[dray.length]; 246 | System.arraycopy(dray, 0, _array[_num], 0, dray.length); 247 | _num++; 248 | } 249 | 250 | final double getElement(int i, int j) { return _array[i][j]; } 251 | final int getSize() { return _num; } 252 | final int getSize(int i) { return _array[i].length; } 253 | } 254 | 255 | 256 | private class IntArray { 257 | int _num = 0; 258 | int[] _array = new int[32]; 259 | 260 | final void add(double ival) { 261 | if ( _num >= _array.length ) { 262 | int[] array = new int[2 * _array.length]; 263 | System.arraycopy(_array, 0, array, 0, _num); 264 | _array = array; 265 | } 266 | _array[_num++] = (int)Math.round(ival); 267 | } 268 | 269 | final int getElement(int i) { return _array[i]; } 270 | final int getSize() { return _num; } 271 | } 272 | 273 | private class IntArrayArray { 274 | int _num = 0; 275 | int[][] _array = new int[32][]; 276 | 277 | final void add(int[] iray) { 278 | 279 | if ( _num >= _array.length ) { 280 | int[][] array = new int[2 * _array.length][]; 281 | for (int i = 0; i < _num; i++) { 282 | array[i] = _array[i]; 283 | } 284 | _array = array; 285 | } 286 | _array[_num] = new int[iray.length]; 287 | System.arraycopy(iray, 0, _array[_num], 0, iray.length); 288 | _num++; 289 | } 290 | 291 | final int getElement(int i, int j) { return _array[i][j]; } 292 | final int getSize() { return _num; } 293 | final int getSize(int i) { return _array[i].length; } 294 | } 295 | } 296 | -------------------------------------------------------------------------------- /examples/LPex1.java: -------------------------------------------------------------------------------- 1 | package examples; 2 | /* -------------------------------------------------------------------------- 3 | * File: LPex1.java 4 | * Version 12.9.0 5 | * -------------------------------------------------------------------------- 6 | * Licensed Materials - Property of IBM 7 | * 5725-A06 5725-A29 5724-Y48 5724-Y49 5724-Y54 5724-Y55 5655-Y21 8 | * Copyright IBM Corporation 2001, 2019. All Rights Reserved. 9 | * 10 | * US Government Users Restricted Rights - Use, duplication or 11 | * disclosure restricted by GSA ADP Schedule Contract with 12 | * IBM Corp. 13 | * -------------------------------------------------------------------------- 14 | * 15 | * LPex1.java - Entering and optimizing an LP problem 16 | * 17 | * Demonstrates different methods for creating a problem. The user has to 18 | * choose the method on the command line: 19 | * 20 | * java LPex1 -r generates the problem by adding constraints 21 | * java LPex1 -c generates the problem by adding variables 22 | * java LPex1 -n generates the problem by adding expressions 23 | */ 24 | 25 | import ilog.concert.*; 26 | import ilog.cplex.*; 27 | 28 | public class LPex1 { 29 | static void usage() { 30 | System.out.println("usage: LPex1