Cutstock.java
1package com.gams.examples.cutstock;
2 
3 import java.io.File;
4 import java.util.HashMap;
5 import java.util.Iterator;
6 import java.util.Map;
7 import java.util.Map.Entry;
8 
10 import com.gams.api.GAMSDatabase;
12 import com.gams.api.GAMSJob;
14 import com.gams.api.GAMSModifier;
15 import com.gams.api.GAMSOptions;
16 import com.gams.api.GAMSParameter;
18 import com.gams.api.GAMSSet;
19 import com.gams.api.GAMSSetRecord;
21 import com.gams.api.GAMSWorkspace;
23 
32 public class Cutstock {
33 
34  public static void main(String[] args) {
35  // check workspace info from command line arguments
36  GAMSWorkspaceInfo wsInfo = new GAMSWorkspaceInfo();
37  if (args.length > 0)
38  wsInfo.setSystemDirectory( args[0] );
39  // create a directory
40  File workingDirectory = new File(System.getProperty("user.dir"), "Cutstock");
41  workingDirectory.mkdir();
42  wsInfo.setWorkingDirectory(workingDirectory.getAbsolutePath());
43  // create a workspace
44  GAMSWorkspace ws = new GAMSWorkspace(wsInfo);
45 
46  // instantiate GAMSOptions and define parameters
47  GAMSOptions opt = ws.addOptions();
48  GAMSDatabase cutstockData = ws.addDatabase("csdata");
49  opt.setAllModelTypes("Cplex");
50  opt.setOptCR( 0.0 ); // Solve to optimality
51  int maxpattern = 35;
52  opt.defines("pmax", String.valueOf(maxpattern));
53  opt.defines("solveMasterAs", "RMIP");
54 
55  // define input data
56  Map<String, Double> d = new HashMap<String, Double>();
57  {
58  d.put( "i1", Double.valueOf(97) );
59  d.put( "i2", Double.valueOf(610) );
60  d.put( "i3", Double.valueOf(395) );
61  d.put( "i4", Double.valueOf(211) );
62  }
63  Map<String, Double> w = new HashMap<String, Double>();
64  {
65  w.put( "i1", Double.valueOf(45) );
66  w.put( "i2", Double.valueOf(36) );
67  w.put( "i3", Double.valueOf(31) );
68  w.put( "i4", Double.valueOf(14) );
69 
70  }
71  int r = 100; // raw width
72 
73  GAMSSet widths = cutstockData.addSet("i", 1, "widths");
74  GAMSParameter rawWidth = cutstockData.addParameter("r", 0, "raw width");
75  GAMSParameter demand = cutstockData.addParameter("d", 1, "demand");
76  GAMSParameter width = cutstockData.addParameter("w", 1, "width");
77 
78  rawWidth.addRecord().setValue( 100 );
79  for (String i : d.keySet())
80  widths.addRecord(i);
81  for (Entry<String, Double> e : d.entrySet())
82  demand.addRecord( e.getKey() ).setValue( e.getValue() );
83  for (Entry<String, Double> e : w.entrySet())
84  width.addRecord( e.getKey() ).setValue( e.getValue() );
85 
86  // create initial checkpoint
87  GAMSCheckpoint masterCP = ws.addCheckpoint();
88  GAMSJob masterInitJob = ws.addJobFromString(masterModel);
89  masterInitJob.run(opt, masterCP, cutstockData);
90 
91  GAMSJob masterJob = ws.addJobFromString("execute_load 'csdata', aip, pp; solve master min z using %solveMasterAs%;", masterCP);
92 
93  GAMSSet pattern = cutstockData.addSet("pp", 1, "pattern index");
94  GAMSParameter patternData = cutstockData.addParameter("aip", 2, "pattern data");
95 
96  // Initial pattern: pattern i hold width i
97  int patternCount = 0;
98  for (Entry<String, Double> e : w.entrySet()) {
99  String[] keys = new String[] { e.getKey(), pattern.addRecord( new Integer(++patternCount).toString() ).getKey(0) };
100  patternData.addRecord(keys).setValue( (int)(r / e.getValue()) );
101  }
102 
103  // create model instance for sub job
104  GAMSCheckpoint subCP = ws.addCheckpoint();
105  ws.addJobFromString(subModel).run(opt, subCP, cutstockData);
106 
107  GAMSModelInstance subMI = subCP.addModelInstance();
108 
109  // define modifier demdual
110  GAMSParameter demandDual = subMI.SyncDB().addParameter("demdual", 1, "dual of demand from master");
111  subMI.instantiate("pricing min z using mip", opt, new GAMSModifier(demandDual));
112 
113  // find new pattern
114  boolean patternAdded = true;
115  while (patternAdded)
116  {
117  masterJob.run(opt, masterCP, cutstockData);
118  // Copy duals into gmssubMI.SyncDB DB
119  demandDual.clear();
120  for(GAMSEquationRecord dem : masterJob.OutDB().getEquation("demand"))
121  demandDual.addRecord( dem.getKey(0) ).setValue( dem.getMarginal() );
122 
123  subMI.solve();
124 
125  if (subMI.SyncDB().getVariable("z").findRecord().getLevel() < -0.00001) {
126  if (patternCount == maxpattern) {
127  System.out.println("Out of pattern. Increase maxpattern (currently ["+maxpattern+"])");
128  patternAdded = false;
129  }
130  else {
131  System.out.println("New pattern Value: " + subMI.SyncDB().getVariable("z").findRecord().getLevel());
132  GAMSSetRecord s = pattern.addRecord( new Integer(++patternCount).toString() );
133  for (GAMSVariableRecord y : subMI.SyncDB().getVariable("y")) {
134  if (y.getLevel() > 0.5) {
135  String[] keys = new String[] { y.getKey(0), s.getKey(0) };
136  patternData.addRecord( keys ).setValue( Math.round(y.getLevel()) );
137  }
138  }
139  }
140  } else {
141  patternAdded = false;
142  }
143  }
144 
145  // solve final MIP
146  opt.defines("solveMasterAs", "MIP");
147  masterJob.run(opt, cutstockData);
148 
149  System.out.println("Optimal Solution: "+masterJob.OutDB().getVariable("z").findRecord().getLevel());
150 
151  for (GAMSVariableRecord xp : masterJob.OutDB().getVariable("xp")) {
152  if (xp.getLevel() > 0.5) {
153  System.out.println(" pattern ["+xp.getKey(0)+"] ["+xp.getLevel()+"] times: ");
154  GAMSParameter param = masterJob.OutDB().getParameter("aip");
155  @SuppressWarnings("unused")
156  GAMSParameterRecord aip = param.getFirstRecord(new String[] { " ", xp.getKey(0) });
157  Iterator<GAMSParameterRecord> it = param.iterator();
158  while (it.hasNext()) {
159  GAMSParameterRecord rec = it.next();
160  System.out.println(" ["+rec.getKey(0)+"] : ["+ rec.getValue()+"]");
161  }
162  System.out.println();
163  }
164  }
165 
166  // clean up of unmanaged resources
167  cutstockData.dispose();
168  subMI.dispose();
169  opt.dispose();
170 
171  }
172 
173  static String masterModel =
174  "$Title Cutting Stock - Master problem \n" +
175  " \n" +
176  "Set i widths \n" +
177  "Parameter \n" +
178  " w(i) width \n" +
179  " d(i) demand \n" +
180  "Scalar \n" +
181  " r raw width; \n" +
182  "$gdxin csdata \n" +
183  "$load i w d r \n" +
184  " \n" +
185  "$if not set pmax $set pmax 1000 \n" +
186  "Set p possible patterns /1*%pmax%/ \n" +
187  " pp(p) dynamic subset of p \n" +
188  "Parameter \n" +
189  " aip(i,p) number of width i in pattern growing in p;\n" +
190  " \n" +
191  "* Master model \n" +
192  "Variable xp(p) patterns used \n" +
193  " z objective variable \n" +
194  "Integer variable xp; xp.up(p) = sum(i, d(i)); \n" +
195  " \n" +
196  "Equation numpat number of patterns used \n" +
197  " demand(i) meet demand; \n" +
198  " \n" +
199  "numpat.. z =e= sum(pp, xp(pp)); \n" +
200  "demand(i).. sum(pp, aip(i,pp)*xp(pp)) =g= d(i); \n" +
201  " \n" +
202  "model master /numpat, demand/; \n" +
203  " \n";
204 
205  static String subModel =
206  "$Title Cutting Stock - Pricing problem is a knapsack model \n" +
207  " \n" +
208  "Set i widths \n" +
209  "Parameter \n" +
210  " w(i) width; \n" +
211  "Scalar \n" +
212  " r raw width; \n" +
213  " \n" +
214  "$gdxin csdata \n" +
215  "$load i w r \n" +
216  " \n" +
217  "Parameter \n" +
218  " demdual(i) duals of master demand constraint /#i eps/; \n" +
219  " \n" +
220  "Variable z, y(i) new pattern; \n" +
221  "Integer variable y; y.up(i) = ceil(r/w(i)); \n" +
222  " \n" +
223  "Equation defobj \n" +
224  " knapsack; \n" +
225  " \n" +
226  "defobj.. z =e= 1 - sum(i, demdual(i)*y(i)); \n" +
227  "knapsack.. sum(i, w(i)*y(i)) =l= r; \n" +
228  "model pricing /defobj, knapsack/; \n" +
229  " \n";
230 }
231 
GAMSEquation getEquation(String identifier)
GAMSParameter getParameter(String identifier)
void defines(String defStr, String asStr)
void setSystemDirectory(String directory)
GAMSParameter addParameter(String identifier, int dimension)
GAMSSet addSet(String identifier, int dimension)
This example implements a column generation approach.
Definition: Cutstock.java:32
GAMSJob addJobFromString(String source)
void instantiate(String modelDefinition, GAMSModifier ... modifiers)
GAMSCheckpoint addCheckpoint()
GAMSModelInstance addModelInstance()
void setWorkingDirectory(String directory)
GAMSDatabase OutDB()
GAMSVariable getVariable(String identifier)
T addRecord(Vector< String > keys)
void setAllModelTypes(String value)