001: // -------------------------------------------------------------- -*- C++ -*-
002: // File: cutstock.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: 
031:     IloInt nbItems = 5;
032:     IloIntRange items(env, 1, 5);
033: 
034:     int status = 127;
035:     try {
036:         IloNum best;
037:         IloNum curr = IloInfinity;
038: 
039: 
040:         IloOplErrorHandler errHandler(env,cout);
041:         IloOplSettings settings(env,errHandler);
042:         IloOplModelSource masterSource(env, DATADIR "cutstock" DIRSEP "cutstock.mod");
043:         IloOplModelDefinition masterDef(masterSource,settings);
044:         IloOplDataSource masterDataSource(env, DATADIR "cutstock" DIRSEP "cutstock.dat");
045:         IloOplDataElements masterDataElements(masterDef,masterDataSource);
046:         IloCplex masterCplex(env);
047:         masterCplex.setOut(env.getNullStream());
048: 
049:         IloOplModelSource subSource(env, DATADIR "cutstock" DIRSEP "cutstock-sub.mod");
050:         IloOplModelDefinition subDef(subSource,settings);
051:         IloCplex subCplex(env);
052: 
053:         IloOplModel oldSubOpl;
054:         do {
055:             best = curr;
056: 
057:             masterCplex.clearModel();
058: 
059:             IloOplRunConfiguration masterRC(masterDef,masterDataElements);
060:             masterRC.setCplex(masterCplex);
061:             masterRC.getOplModel().generate();
062: 
063:             cout << "Solve master." << endl;
064:             if ( masterCplex.solve() ) {
065:                 curr = masterCplex.getObjValue() ;
066:                 cout << endl
067:                     << "MASTER OBJECTIVE: " << fixed << setprecision(2) << curr
068:                     << endl;
069:                 status = 0;
070:             } else {
071:                 cout << "No solution!" << endl;
072:                 status = 1;
073:             }
074: 
075:             // get reduced costs and set them in sub problem
076: 
077:             // make sub model
078:             if ( oldSubOpl.getImpl()!=0 ) {
079:                 oldSubOpl.end();
080:             }
081: 
082:                         subCplex.clearModel();
083:                         subCplex.setOut(env.getNullStream());
084:                         IloOplModel subOpl(subDef,subCplex);
085:                         IloOplDataElements subDataElements(env);
086:                         subDataElements.addElement(masterRC.getOplModel().getElement("RollWidth"));
087:                         subDataElements.addElement(masterRC.getOplModel().getElement("Size"));
088:                         subDataElements.addElement(masterRC.getOplModel().getElement("Duals"));
089: 
090:             IloNumMap duals = subDataElements.getElement("Duals").asNumMap();
091:             IloConstraintMap FillCt = masterRC.getOplModel().getElement("ctFill").asConstraintMap();
092:             for (IloInt i=1; i<nbItems+1; i++) {
093:                 IloForAllRange far = FillCt.get(i);
094:                 duals.set(i, masterCplex.getDual(far));
095:             }
096:             subOpl.addDataSource(subDataElements);
097:             subOpl.generate();
098: 
099:             cout << "Solve sub." << endl;
100:             if ( subCplex.solve() ) {
101:                 cout << endl
102:                     << "SUB OBJECTIVE: " << fixed << setprecision(2)
103:                     << subCplex.getObjValue()
104:                     << endl;
105:                 status = 0;
106:             } else {
107:                 cout << "No solution!" << endl;
108:                 status = 1;
109:             }
110: 
111:             if (subCplex.getObjValue() > -RC_EPS) break;
112: 
113:             // Add variable in master model by simply adding a new tuple in Patterns
114:             IloIntMap newFill = subOpl.getElement("Use").asIntMap().copy();
115: 
116:             IloTupleBuffer buf = masterDataElements.getElement("Patterns").asTupleSet().makeTupleBuffer();
117:             buf.setIntValue("id", masterDataElements.getElement("Patterns").asTupleSet().getSize());
118:             buf.setIntValue("cost", 1);
119:             buf.setIntMapValue("fill", newFill);
120:             buf.commit();
121: 
122:             masterRC.end();
123:                         oldSubOpl = subOpl;
124:         } while ( best != curr && status == 0);
125: 
126:     } catch (IloOplException & e) {
127:         cout << "### OPL exception: " << e.getMessage() << endl;
128:     } catch( IloException & e ) {
129:         cout << "### CONCERT exception: ";
130:         e.print(cout);
131:         status = 2;
132:     } catch (...) {
133:         cout << "### UNEXPECTED ERROR ..." << endl;
134:         status = 3;
135:     }
136: 
137:     env.end();
138: 
139:     cout << endl << "--Press <Enter> to exit--" << endl;
140:     getchar();
141:     
142:     return status;
143: }