int main(void) { LPX *lp; int ia[1+1000], ja[1+1000]; double ar[1+1000], Z, x1, x2, x3; s1: lp = lpx_create_prob(); s2: lpx_set_prob_name(lp, "sample"); s3: lpx_set_obj_dir(lp, LPX_MAX); s4: lpx_add_rows(lp, 3); s5: lpx_set_row_name(lp, 1, "p"); s6: lpx_set_row_bnds(lp, 1, LPX_UP, 0.0, 100.0); s7: lpx_set_row_name(lp, 2, "q"); s8: lpx_set_row_bnds(lp, 2, LPX_UP, 0.0, 600.0); s9: lpx_set_row_name(lp, 3, "r"); s10: lpx_set_row_bnds(lp, 3, LPX_UP, 0.0, 300.0); s11: lpx_add_cols(lp, 3); s12: lpx_set_col_name(lp, 1, "x1"); s13: lpx_set_col_bnds(lp, 1, LPX_LO, 0.0, 0.0); s14: lpx_set_obj_coef(lp, 1, 10.0); s15: lpx_set_col_name(lp, 2, "x2"); s16: lpx_set_col_bnds(lp, 2, LPX_LO, 0.0, 0.0); s17: lpx_set_obj_coef(lp, 2, 6.0); s18: lpx_set_col_name(lp, 3, "x3"); s19: lpx_set_col_bnds(lp, 3, LPX_LO, 0.0, 0.0); s20: lpx_set_obj_coef(lp, 3, 4.0); s21: ia[1] = 1, ja[1] = 1, ar[1] = 1.0; /* a[1,1] = 1 */ s22: ia[2] = 1, ja[2] = 2, ar[2] = 1.0; /* a[1,2] = 1 */ s23: ia[3] = 1, ja[3] = 3, ar[3] = 1.0; /* a[1,3] = 1 */ s24: ia[4] = 2, ja[4] = 1, ar[4] = 10.0; /* a[2,1] = 10 */ s25: ia[5] = 3, ja[5] = 1, ar[5] = 2.0; /* a[3,1] = 2 */ s26: ia[6] = 2, ja[6] = 2, ar[6] = 4.0; /* a[2,2] = 4 */ s27: ia[7] = 3, ja[7] = 2, ar[7] = 2.0; /* a[3,2] = 2 */ s28: ia[8] = 2, ja[8] = 3, ar[8] = 5.0; /* a[2,3] = 5 */ s29: ia[9] = 3, ja[9] = 3, ar[9] = 6.0; /* a[3,3] = 6 */ s30: lpx_load_matrix(lp, 9, ia, ja, ar); s31: lpx_simplex(lp); s32: Z = lpx_get_obj_val(lp); s33: x1 = lpx_get_col_prim(lp, 1); s34: x2 = lpx_get_col_prim(lp, 2); s35: x3 = lpx_get_col_prim(lp, 3); s36: printf("\nZ = %g; x1 = %g; x2 = %g; x3 = %g\n", Z, x1, x2, x3); s37: lpx_delete_prob(lp); return 0; }
int TankBlendOptimiser::go() { lp = lpx_create_prob(); lpx_set_int_parm(lp, LPX_K_MSGLEV, 0); // 0 = no output lpx_set_int_parm(lp, LPX_K_SCALE, 3); // 3 = geometric mean scaling, then equilibration scaling lpx_set_int_parm(lp, LPX_K_DUAL, 1); // 1 = if initial basic solution is dual feasible, use the dual simplex lpx_set_int_parm(lp, LPX_K_ROUND, 1); // 1 = replace tiny primal and dual values by exact zero lpx_set_int_parm(lp, LPX_K_PRESOL, 1); // 1 = use the built-in presolver. lpx_set_prob_name(lp, "Blend Optimiser"); lpx_set_obj_dir(lp, LPX_MIN); // Columns... lpx_add_cols(lp, cols); for (int i=0; i<tanks; i++) // 0.0 < x < tankMax { if (tankMax[i]>0.0) lpx_set_col_bnds(lp, col, LPX_DB, 0.0, tankMax[i]); else lpx_set_col_bnds(lp, col, LPX_FX, 0.0, 0.0); col++; } for (int i=0; i<tanks; i++) // 0.0 < slackTankLow { lpx_set_col_bnds(lp, col, LPX_LO, 0.0, 0.0); lpx_set_obj_coef(lp, col, tankLowPenalty[i]); // penalty weight. col++; } for (int i=0; i<tanks; i++) // 0.0 < slackTankHigh { lpx_set_col_bnds(lp, col, LPX_LO, 0.0, 0.0); lpx_set_obj_coef(lp, col, tankHighPenalty[i]); // penalty weight. col++; } for (int i=0; i<assays; i++) // 0.0 < slackAssayLow { lpx_set_col_bnds(lp, col, LPX_LO, 0.0, 0.0); lpx_set_obj_coef(lp, col, assayLowPenalty[i]); // penalty weight. col++; } for (int i=0; i<assays; i++) // 0.0 < slackAssayHigh { lpx_set_col_bnds(lp, col, LPX_LO, 0.0, 0.0); lpx_set_obj_coef(lp, col, assayHighPenalty[i]); // penalty weight. col++; } for (int i=0; i<assays; i++) // 0.0 < slackAssayRatioLow for (int j=0; j<assays; j++) { lpx_set_col_bnds(lp, col, LPX_LO, 0.0, 0.0); lpx_set_obj_coef(lp, col, assayRatioLowPenalty[i][j]); // penalty weight. col++; } for (int i=0; i<assays; i++) // 0.0 < slackAssayRatioHigh for (int j=0; j<assays; j++) { lpx_set_col_bnds(lp, col, LPX_LO, 0.0, 0.0); lpx_set_obj_coef(lp, col, assayRatioHighPenalty[i][j]); // penalty weight. col++; } // Rows... lpx_add_rows(lp, rows); { // x1 + ... + xn = 1.0 lpx_set_row_bnds(lp, row, LPX_FX, 1.0, 1.0); for (int i=0; i<tanks; i++) ia[constraint] = row, ja[constraint] = 1+i, ar[constraint++] = 1.0; row++; } for (int i=0; i<tanks; i++) // tankLow < tank + slackTankLow { lpx_set_row_bnds(lp, row, LPX_LO, tankLow[i], 0.0); ia[constraint] = row, ja[constraint] = 1+i, ar[constraint++] = 1.0; ia[constraint] = row, ja[constraint] = 1+i+tanks, ar[constraint++] = 1.0; row++; } for (int i=0; i<tanks; i++) // tank - slackTankHigh < tankHigh { lpx_set_row_bnds(lp, row, LPX_UP, 0.0, tankHigh[i]); ia[constraint] = row, ja[constraint] = 1+i, ar[constraint++] = 1.0; ia[constraint] = row, ja[constraint] = 1+i+2*tanks, ar[constraint++] = -1.0; row++; } for (int i=0; i<assays; i++) // assayLow < assay + slackAssayLow { lpx_set_row_bnds(lp, row, LPX_LO, assayLow[i], 0.0); for (int j=0; j<tanks; j++) { if (assayConc[i][j]>0.0) ia[constraint] = row, ja[constraint] = 1+j, ar[constraint++] = assayConc[i][j]; } ia[constraint] = row, ja[constraint] = 1+i+3*tanks, ar[constraint++] = 1.0; row++; } for (int i=0; i<assays; i++) // assay - slackAssayHigh < assayHigh { lpx_set_row_bnds(lp, row, LPX_UP, 0.0, assayHigh[i]); for (int j=0; j<tanks; j++) { if (assayConc[i][j]>0.0) ia[constraint] = row, ja[constraint] = 1+j, ar[constraint++] = assayConc[i][j]; } ia[constraint] = row, ja[constraint] = 1+i+3*tanks+assays, ar[constraint++] = -1.0; row++; } for (int i=0; i<assays; i++) // 0 < assayNum - assayRatioLow*assayDen + slackAssayLow for (int j=0; j<assays; j++) { if (assayRatioLowEnabled[i][j]) lpx_set_row_bnds(lp, row, LPX_LO, 0.0, 0.0); else lpx_set_row_bnds(lp, row, LPX_FR, 0.0, 0.0); for (int k=0; k<tanks; k++) { if (assayConc[i][k] - assayRatioLow[i][j]*assayConc[j][k]!=0.0) ia[constraint] = row, ja[constraint] = 1+k, ar[constraint++] = assayConc[i][k] - assayRatioLow[i][j]*assayConc[j][k]; } ia[constraint] = row, ja[constraint] = 1+i*assays+j+3*tanks+2*assays, ar[constraint++] = 1.0; row++; } for (int i=0; i<assays; i++) // assayNum - assayRatioHigh*assayDen - slackAssayHigh < 0 for (int j=0; j<assays; j++) { if (assayRatioHighEnabled[i][j]) lpx_set_row_bnds(lp, row, LPX_UP, 0.0, 0.0); else lpx_set_row_bnds(lp, row, LPX_FR, 0.0, 0.0); for (int k=0; k<tanks; k++) { if (assayConc[i][k] - assayRatioHigh[i][j]*assayConc[j][k]!=0.0) ia[constraint] = row, ja[constraint] = 1+k, ar[constraint++] = assayConc[i][k] - assayRatioHigh[i][j]*assayConc[j][k]; } ia[constraint] = row, ja[constraint] = 1+i*assays+j+3*tanks+2*assays+assays*assays, ar[constraint++] = -1.0; row++; } lpx_load_matrix(lp, constraint-1, ia, ja, ar); int exitCode = lpx_simplex(lp); for (int i=0; i<tanks; i++) tank[i] = lpx_get_col_prim(lp, 1+i); for (int i=0; i<assays; i++) { assay[i] = 0.0; for (int j=0; j<tanks; j++) assay[i] += lpx_get_col_prim(lp, 1+j)*assayConc[i][j]; } return exitCode; // LPX_E_OK 200 /* success */ // LPX_E_FAULT 204 /* unable to start the search */ // LPX_E_ITLIM 207 /* iterations limit exhausted */ // LPX_E_TMLIM 208 /* time limit exhausted */ // LPX_E_SING 211 /* problems with basis matrix */ // LPX_E_NOPFS 213 /* no primal feas. sol. (LP presolver) */ // LPX_E_NODFS 214 /* no dual feas. sol. (LP presolver) */ // Usually: // LPX_E_OK = Solution found. // LPX_E_NOPFS = Sum-to-1.0 or tank-max constraints not met. // Others = Some major fault has occurred. }