Cutstock.java
1package com.gams.examples.cutstock;
2
3import java.io.File;
4import java.util.HashMap;
5import java.util.Iterator;
6import java.util.Map;
7import java.util.Map.Entry;
8
12import com.gams.api.GAMSJob;
15import com.gams.api.GAMSOptions;
18import com.gams.api.GAMSSet;
23
32public class Cutstock {
33
34 public static void main(String[] args) {
35 // check workspace info from command line arguments
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
GAMSCheckpoint addCheckpoint()
Provides package namespace for Java interface and examples to General Algebraic Model System (GAMS)...
GAMSModelInstance addModelInstance()
GAMSVariable getVariable(String identifier)
GAMSParameter addParameter(String identifier, int dimension)
This example implements a column generation approach.
Definition: Cutstock.java:32
void instantiate(String modelDefinition, GAMSModifier ... modifiers)
&#160;
GAMSSet addSet(String identifier, int dimension)
GAMSEquation getEquation(String identifier)
GAMSParameter getParameter(String identifier)
void defines(String defStr, String asStr)
void setSystemDirectory(String directory)
T addRecord(Vector< String > keys)
GAMSDatabase OutDB()
GAMSJob addJobFromString(String source)
void setAllModelTypes(String value)
void setWorkingDirectory(String directory)