001: // -------------------------------------------------------------- -*- C++ -*-
002: // File: cutstock_change.cpp
003: // --------------------------------------------------------------------------
004: // Licensed Materials - Property of IBM
005: // 
006: // 5725-A06 5725-A29 5724-Y48 5724-Y49 5724-Y54 5724-Y55 
007: // Copyright IBM Corporation 1998, 2013. All Rights Reserved.
008: //
009: // Note to U.S. Government Users Restricted Rights:
010: // Use, duplication or disclosure restricted by GSA ADP Schedule
011: // Contract with IBM Corp.
012: /////////////////////////////////////////////////////////////////////////////// 
013: 
014: #include <ilopl/iloopl.h>
015: 
016: #define RC_EPS 1.0e-6
017: 
018: #ifdef ILO_WINDOWS
019: #define DIRSEP "\\"
020: #else
021: #define DIRSEP "/"
022: #endif
023: #ifndef DATADIR
024: #define DATADIR ".." DIRSEP ".."  DIRSEP ".." DIRSEP ".." DIRSEP "opl" DIRSEP
025: #endif
026: 
027: ILOSTLBEGIN
028: int main(int argc,char* argv[]) {
029:     IloEnv env;
030:     IloInt i;
031: 
032:     int status = 127;
033:     try {
034:         IloNum best;
035:         IloNum curr = IloInfinity;
036: 
037:         IloOplErrorHandler handler(env,cout);
038: 
039:         IloOplRunConfiguration masterRC(env,
040:             DATADIR "cutstock" DIRSEP "cutstock_change.mod",
041:             DATADIR "cutstock" DIRSEP "cutstock_change.dat");
042:         masterRC.setErrorHandler(handler);
043:         IloCplex masterCplex(env);
044:         masterCplex.setOut(env.getNullStream());
045:         masterRC.setCplex(masterCplex);
046:         IloOplModel masterOpl = masterRC.getOplModel();
047:         masterOpl.generate();
048: 
049:         IloOplDataElements masterDataElements = masterOpl.makeDataElements();
050:         IloInt nWdth = masterDataElements.getElement("Amount").asIntMap().getSize();
051:         IloNumVarArray masterVars(env);
052:         IloNumVarMap cuts = masterOpl.getElement("Cut").asNumVarMap();
053:         for (i=1; i<=nWdth; i++) {
054:             masterVars.add(cuts.get(i));
055:         }
056: 
057:                 IloOplSettings settings(env,handler);
058:                 IloOplModelSource subSource(env, DATADIR "cutstock" DIRSEP "cutstock-sub.mod");
059:                 IloOplModelDefinition subDef(subSource,settings);
060:                 IloCplex subCplex(env);
061: 
062:         do {
063:             best = curr;
064: 
065:             cout << "Solve master." << endl;
066:             if ( masterCplex.solve() ) {
067:                 curr = masterCplex.getObjValue() ;
068:                 cout << endl
069:                     << "MASTER OBJECTIVE: " << fixed << setprecision(2) << curr
070:                     << endl;
071:                 status = 0;
072:             } else {
073:                 cout << "No solution!" << endl;
074:                 status = 1;
075:             }
076: 
077:             // get reduced costs and set them in sub problem
078: 
079:             // make sub model
080:                         subCplex.setOut(env.getNullStream());
081:                         IloOplModel subOpl(subDef,subCplex);
082:                         IloOplDataElements subDataElements(env);
083:                         subDataElements.addElement(masterRC.getOplModel().getElement("RollWidth"));
084:                         subDataElements.addElement(masterRC.getOplModel().getElement("Size"));
085:                         subDataElements.addElement(masterRC.getOplModel().getElement("Duals"));
086: 
087:             IloConstraintMap FillCt = masterOpl.getElement("ctFill").asConstraintMap();
088:             IloNumMap duals = subDataElements.getElement("Duals").asNumMap();
089:             for (i=1; i<nWdth+1; i++) {
090:                 IloForAllRange far = FillCt.get(i);
091:                 duals.set(i, masterCplex.getDual(far));
092:             }
093: 
094:                         subOpl.addDataSource(subDataElements);
095:             subOpl.generate();
096: 
097:             cout << "Solve sub." << endl;
098:             if ( subCplex.solve() ) {
099:                 cout << endl
100:                     << "SUB OBJECTIVE: " << fixed << setprecision(2)
101:                     << subCplex.getObjValue()
102:                     << endl;
103:                 status = 0;
104:             } else {
105:                 cout << "No solution!" << endl;
106:                 status = 1;
107:             }
108: 
109:             if (subCplex.getObjValue() > -RC_EPS) break;
110: 
111:             // Add variable in master model
112: 
113:             IloNumVar newVar(env, 0, IloIntMax);
114:             IloObjective masterObj = masterOpl.getObjective();
115:             masterObj.setLinearCoef(newVar, 1);
116:             IloIntVarMap Use = subOpl.getElement("Use").asIntVarMap();
117:             for (i=1; i<nWdth+1; i++) {
118:                 IloNum coef = subCplex.getValue(Use.get(i));
119:                 IloForAllRange far = FillCt.get(i);
120:                 far.setLinearCoef(newVar, coef);
121:             }
122:             masterVars.add(newVar);
123: 
124:             subOpl.end();
125:         } while ( best != curr && status == 0);
126: 
127:         masterOpl.getModel().add(IloConversion(env, masterVars, ILOINT));
128:         if ( masterCplex.solve() ) {
129:             cout << endl
130:                 << "OBJECTIVE: " << fixed << setprecision(2) << masterCplex.getObjValue()
131:                 << endl;
132:         }
133:     } catch (IloOplException & e) {
134:         cout << "### OPL exception: " << e.getMessage() << endl;
135:     } catch( IloException & e ) {
136:         cout << "### CONCERT exception: ";
137:         e.print(cout);
138:         status = 2;
139:     } catch (...) {
140:         cout << "### UNEXPECTED ERROR ..." << endl;
141:         status = 3;
142:     }
143: 
144:     env.end();
145: 
146:     cout << endl << "--Press <Enter> to exit--" << endl;
147:     getchar();
148: 
149:     return status;
150: }