Loading...
Searching...
No Matches
Form1.cs
1using System;
2using System.Collections.Generic;
3using System.ComponentModel;
4using System.Data;
5using System.Drawing;
6using System.Linq;
7using System.Text;
8using System.Windows.Forms;
9using GAMS;
10using System.Reflection;
11using System.Data.OleDb;
12
13namespace CutStockGUI
14{
21 public partial class Form1 : Form
22 {
23 private List<string> cuts = new List<string>() { "i1", "i2", "i3", "i4" };
24 private Dictionary<string, int> d = new Dictionary<string, int>() { { "i1", 97 }, { "i2", 610 }, { "i3", 395 }, { "i4", 211 } };
25 private Dictionary<string, int> w = new Dictionary<string, int>() { { "i1", 47 }, { "i2", 36 }, { "i3", 31 }, { "i4", 14 } };
26 private int r = 100; // raw width
27 private int maxpattern = 35;
28 private int nrCuts = 0;
29 private List<Color> colors = new List<Color>() { Color.FromArgb(255, 192, 255, 255), Color.FromArgb(255, 255, 255, 192),
30 Color.FromArgb(255, 192, 255, 192), Color.FromArgb(255, 255, 224, 192),
31 Color.FromArgb(255, 255, 192, 255), Color.FromArgb(255, 129, 255, 192),
32 Color.FromArgb(255, 192, 192, 255), Color.FromArgb(255, 255, 192, 192),
33 Color.FromArgb(255, 100, 192, 220), Color.FromArgb(255, 129, 100, 192),
34 Color.FromArgb(255, 192, 192, 100), Color.FromArgb(255, 255, 192, 100) };
35
36 public Form1()
37 {
38 InitializeComponent();
39 nudWidth.Value = r;
40 nudMax.Value = maxpattern;
41
42 // add cut widths
43 foreach (string i in cuts)
44 {
45 flowLayoutPanel1.Controls.Add(new CutWidthsControl(i, w[i], (int) nudWidth.Value, d[i], colors[nrCuts%colors.Count], nudWidth));
46 nrCuts++;
47 }
48 }
49
50 //add new cut width
51 private void button3_Click(object sender, EventArgs e)
52 {
53 flowLayoutPanel1.Controls.Add(new CutWidthsControl("i" + (nrCuts + 1), (int)nudWidth.Value, (int)nudWidth.Value, 0, colors[nrCuts % colors.Count], nudWidth));
54 flowLayoutPanel1.VerticalScroll.Value = flowLayoutPanel1.VerticalScroll.Maximum;
55 flowLayoutPanel1.Update();
56 flowLayoutPanel1.VerticalScroll.Value = flowLayoutPanel1.VerticalScroll.Maximum;
57 nrCuts++;
58 }
59
60 //delete last cut width
61 private void button2_Click(object sender, EventArgs e)
62 {
63 if (nrCuts <= 1)
64 MessageBox.Show("Can't delete last cut width because there has to be at least one.");
65 else
66 {
67 flowLayoutPanel1.Controls.RemoveAt(nrCuts-1);
68 flowLayoutPanel1.Update();
69 nrCuts--;
70 }
71 }
72
73 private void button1_Click(object sender, EventArgs e)
74 {
75 richTextBox1.Clear();
76 tabControl1.Visible = false;
77 tabControl1.TabPages.Clear();
78 try
79 {
81
82 // instantiate GAMSOptions and define parameters
83 GAMSOptions opt = ws.AddOptions();
84 GAMSDatabase cutstockData = ws.AddDatabase("csdata");
85 opt.AllModelTypes = "Cbc";
86 opt.OptCR = 0.0; // Solve to optimality
87 opt.Defines.Add("pmax", nudMax.Value.ToString());
88 opt.Defines.Add("solveMasterAs", "RMIP");
89
90 GAMSSet widths = cutstockData.AddSet("i", 1, "widths");
91 GAMSParameter rawWidth = cutstockData.AddParameter("r", 0, "raw width");
92 GAMSParameter demand = cutstockData.AddParameter("d", 1, "demand");
93 GAMSParameter width = cutstockData.AddParameter("w", 1, "width");
94
95 rawWidth.AddRecord().Value = (int)nudWidth.Value;
96
97 foreach(CutWidthsControl cutWidth in flowLayoutPanel1.Controls)
98 {
99 widths.AddRecord(cutWidth.Name);
100 demand.AddRecord(cutWidth.Name).Value = cutWidth.DemandValue;
101 width.AddRecord(cutWidth.Name).Value = cutWidth.WidthValue;
102 }
103
104 // create initial checkpoint
105 GAMSCheckpoint masterCP = ws.AddCheckpoint();
106 GAMSJob masterInitJob = ws.AddJobFromString(GetMasterModel());
107 masterInitJob.Run(opt, masterCP, cutstockData);
108
109 GAMSJob masterJob = ws.AddJobFromString("execute_load 'csdata', aip, pp; solve master min z using %solveMasterAs%;", masterCP);
110
111 GAMSSet pattern = cutstockData.AddSet("pp", 1, "pattern index");
112 GAMSParameter patternData = cutstockData.AddParameter("aip", 2, "pattern data");
113
114 // Initial pattern: pattern i hold width i
115 int patternCount = 0;
116
117 foreach (GAMSParameterRecord rec in width)
118 {
119 patternData.AddRecord(rec.Keys[0], pattern.AddRecord((++patternCount).ToString()).Keys[0]).Value = (int)((int)nudWidth.Value / rec.Value);
120 }
121
122 // create model instance for sub job
123 GAMSCheckpoint subCP = ws.AddCheckpoint();
124 ws.AddJobFromString(GetSubModel()).Run(opt, subCP, cutstockData);
125 GAMSModelInstance subMI = subCP.AddModelInstance();
126
127 // define modifier demdual
128 GAMSParameter demandDual = subMI.SyncDB.AddParameter("demdual", 1, "dual of demand from master");
129 subMI.Instantiate("pricing min z using mip", opt, new GAMSModifier(demandDual));
130
131 // find new pattern
132 bool patternAdded = true;
133 do
134 {
135 masterJob.Run(opt, masterCP, cutstockData);
136 // Copy duals into gmssubMI.SyncDB DB
137 demandDual.Clear();
138 foreach (GAMSEquationRecord dem in masterJob.OutDB.GetEquation("demand"))
139 demandDual.AddRecord(dem.Keys[0]).Value = dem.Marginal;
140
141 subMI.Solve();
142 if (subMI.SyncDB.GetVariable("z").FindRecord().Level < -0.00001)
143 {
144 if (patternCount == maxpattern)
145 {
146 richTextBox1.AppendText("Out of pattern. Increase maxpattern (currently " + nudMax.Value + ")." + Environment.NewLine);
147 patternAdded = false;
148 }
149 else
150 {
151 richTextBox1.AppendText("New pattern! Value: " + subMI.SyncDB.GetVariable("z").FindRecord().Level + Environment.NewLine);
152 richTextBox1.ScrollToCaret();
153 GAMSSetRecord s = pattern.AddRecord((++patternCount).ToString());
154 foreach (GAMSVariableRecord y in subMI.SyncDB.GetVariable("y"))
155 {
156 if (y.Level > 0.5)
157 {
158 patternData.AddRecord(y.Keys[0], s.Keys[0]).Value = Math.Round(y.Level);
159 }
160 }
161 }
162 }
163 else patternAdded = false;
164 } while (patternAdded);
165
166 // solve final MIP
167 opt.Defines["solveMasterAs"] = "MIP";
168 masterJob.Run(opt, cutstockData);
169 richTextBox1.AppendText("Optimal Solution: " + masterJob.OutDB.GetVariable("z").FindRecord().Level + Environment.NewLine); richTextBox1.ScrollToCaret();
170 tabControl1.Visible = true;
171 foreach (GAMSVariableRecord xp in masterJob.OutDB.GetVariable("xp"))
172 {
173 if (xp.Level > 0.5)
174 {
175 richTextBox1.AppendText(String.Format(" pattern {0,2} {1,4} times: ", xp.Keys[0], Math.Round(xp.Level))); richTextBox1.ScrollToCaret();
176 GAMSParameterRecord aip = masterJob.OutDB.GetParameter("aip").FirstRecord(" ", xp.Keys[0]);
177 TabPage tp = new TabPage("pattern " + xp.Keys[0].ToString());
178 tp.BackColor = Color.White;
179 tabControl1.TabPages.Add(tp);
180
181 int x = 0;
182 double scale = tp.Width/masterJob.OutDB.GetParameter("r").FirstRecord().Value;
183 do
184 {
185 richTextBox1.AppendText(" " + aip.Keys[0] + ": " + aip.Value.ToString()); richTextBox1.ScrollToCaret();
186 // draw cuts
187 for (int i = 0; i < aip.Value; i++)
188 {
189 Panel p = new Panel();
190 p.BorderStyle = BorderStyle.FixedSingle;
191 p.BackColor = flowLayoutPanel1.Controls.Find(aip.Keys[0], true)[0].BackColor;
192 p.Height = tp.Height;
193 p.Width = (int) (width.FindRecord(aip.Keys[0]).Value * scale);
194 p.Left = x;
195 x += p.Width - 1;
196 tp.Controls.Add(p);
197 }
198 } while (aip.MoveNext());
199
200 Panel pExcess = new Panel();
201 pExcess.BorderStyle = BorderStyle.FixedSingle;
202 pExcess.BackColor = Color.LightGray;
203 pExcess.Height = tp.Height;
204 pExcess.Width = (int) (rawWidth.FirstRecord().Value*scale - x);
205 pExcess.Left = x;
206 tp.Controls.Add(pExcess);
207
208 richTextBox1.AppendText(Environment.NewLine); richTextBox1.ScrollToCaret();
209 }
210 }
211 // clean up of unmanaged resources
212 cutstockData.Dispose();
213 subMI.Dispose();
214 opt.Dispose();
215 }
216 catch (Exception ex)
217 {
218 richTextBox1.AppendText("Exception: " + ex.Message);
219 }
220 }
221
222 static String GetMasterModel()
223 {
224 String model = @"
225$Title Cutting Stock - Master problem
226
227Set i widths
228Parameter
229 w(i) width
230 d(i) demand
231Scalar
232 r raw width;
233$gdxin csdata
234$load i w d r
235
236$if not set pmax $set pmax 1000
237Set p possible patterns /1*%pmax%/
238 pp(p) dynamic subset of p
239Parameter
240 aip(i,p) number of width i in pattern growing in p;
241
242* Master model
243Variable xp(p) patterns used
244 z objective variable
245Integer variable xp; xp.up(p) = sum(i, d(i));
246
247Equation numpat number of patterns used
248 demand(i) meet demand;
249
250numpat.. z =e= sum(pp, xp(pp));
251demand(i).. sum(pp, aip(i,pp)*xp(pp)) =g= d(i);
252
253model master /numpat, demand/;";
254
255 return model;
256 }
257 static String GetSubModel()
258 {
259 String submodel = @"
260$Title Cutting Stock - Pricing problem is a knapsack model
261
262Set i widths
263Parameter
264 w(i) width;
265Scalar
266 r raw width;
267
268$gdxin csdata
269$load i w r
270
271Parameter
272 demdual(i) duals of master demand constraint /#i eps/;
273
274Variable z, y(i) new pattern;
275Integer variable y; y.up(i) = ceil(r/w(i));
276
277Equation defobj
278 knapsack knapsack constraint;
279
280defobj.. z =e= 1 - sum(i, demdual(i)*y(i));
281knapsack.. sum(i, w(i)*y(i)) =l= r;
282option optcr=0;
283model pricing /defobj, knapsack/; pricing.optfile=1";
284
285 return submodel;
286 }
287
288 private void button4_Click(object sender, EventArgs e)
289 {
290 OpenFileDialog browser = new OpenFileDialog();
291
292 browser.DefaultExt = "accdb";
293 browser.Filter = "Access Database (*.accdb)|*.accdb";
294 browser.InitialDirectory = Environment.CurrentDirectory;
295
296 if (browser.ShowDialog() == DialogResult.OK)
297 {
298 // read from access database
299 OleDbConnection connection = null;
300 try
301 {
302 connection = new OleDbConnection("Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + browser.FileName);
303
304 // delete cut widths
305 while (nrCuts>0)
306 {
307 flowLayoutPanel1.Controls.RemoveAt(nrCuts-1);
308 nrCuts--;
309 }
310 flowLayoutPanel1.Update();
311
312 OleDbCommand cmd = new OleDbCommand("SELECT Width FROM RawWidth", connection);
313 connection.Open();
314 OleDbDataReader reader = cmd.ExecuteReader();
315 while (reader.Read())
316 {
317 nudWidth.Value = (int)reader.GetValue(0);
318 nudWidth.Update();
319 }
320
321 cmd = new OleDbCommand("SELECT Label, Width, Demand FROM CutWidths", connection);
322 reader = cmd.ExecuteReader();
323 while (reader.Read()) {
324 flowLayoutPanel1.Controls.Add(new CutWidthsControl(reader.GetString(0), (int)reader.GetValue(1), (int)nudWidth.Value, (int)reader.GetValue(2), colors[nrCuts % colors.Count], nudWidth));
325 flowLayoutPanel1.VerticalScroll.Value = flowLayoutPanel1.VerticalScroll.Maximum;
326 flowLayoutPanel1.Update();
327 flowLayoutPanel1.VerticalScroll.Value = flowLayoutPanel1.VerticalScroll.Maximum;
328 nrCuts++;
329 }
330 connection.Close();
331 }
332 catch (Exception ex)
333 {
334 MessageBox.Show("Error reading data from database. \n" + ex.Message);
335 connection.Close();
336 Environment.Exit(1);
337 }
338 }
339
340 }
341 }
342}
This example allows to either load data from a database or to enter data manually....
Definition: Form1.cs:22
GAMSModelInstance AddModelInstance(string modelInstanceName=null)
GAMSVariable GetVariable(string variableIdentifier)
GAMSSet AddSet(string identifier, int dimension, string explanatoryText="", SetType setType=SetType.multi)
GAMSParameter AddParameter(string identifier, int dimension, string explanatoryText="")
void Run(GAMSOptions gamsOptions=null, GAMSCheckpoint checkpoint=null, TextWriter output=null, Boolean createOutDB=true)
void Solve(SymbolUpdateType updateType=SymbolUpdateType.BaseCase, TextWriter output=null, GAMSModelInstanceOpt miOpt=null)
void Instantiate(string modelDefinition, params GAMSModifier[] modifiers)
Dictionary< string, string > Defines
new GAMSParameterRecord AddRecord(params string[] keys)
new GAMSSetRecord AddRecord(params string[] keys)
new GAMSVariableRecord FindRecord(params string[] keys)
GAMSJob AddJobFromString(string gamsSource, GAMSCheckpoint checkpoint=null, string jobName=null)
GAMSDatabase AddDatabase(string databaseName=null, string inModelName=null)
GAMSCheckpoint AddCheckpoint(string checkpointName=null)
GAMSOptions AddOptions(GAMSOptions optFrom=null)