private static void ScenSolve(GAMSWorkspace ws, GAMSCheckpoint cp, Queue <double> bmultQueue, Object queueMutex, Object ioMutex) { GAMSModelInstance mi = cp.AddModelInstance(); GAMSParameter bmult = mi.SyncDB.AddParameter("bmult", 0, "demand multiplier"); GAMSOptions opt = ws.AddOptions(); opt.AllModelTypes = "cplexd"; // instantiate the GAMSModelInstance and pass a model definition and GAMSModifier to declare bmult mutable mi.Instantiate("transport us lp min z", opt, new GAMSModifier(bmult)); bmult.AddRecord().Value = 1.0; while (true) { double b; // dynamically get a bmult value from the queue instead of passing it to the different threads at creation time lock (queueMutex) { if (0 == bmultQueue.Count) { return; } b = bmultQueue.Dequeue(); } bmult.FirstRecord().Value = b; mi.Solve(); // we need to make the ouput a critical section to avoid messed up report informations lock (ioMutex) { Console.WriteLine("Scenario bmult=" + b + ":"); Console.WriteLine(" Modelstatus: " + mi.ModelStatus); Console.WriteLine(" Solvestatus: " + mi.SolveStatus); Console.WriteLine(" Obj: " + mi.SyncDB.GetVariable("z").FindRecord().Level); } } }
// Needs to be called with an uninstantiated GAMSModelInstance static void GUSSCall(GAMSSet dict, GAMSModelInstance mi, string solveStatement, GAMSOptions opt = null, GAMSModelInstanceOpt miOpt = null, TextWriter output = null) { List <Tuple <GAMSModifier, GAMSParameter> > modifierList = new List <Tuple <GAMSModifier, GAMSParameter> >(); if (dict.Dim != 3) { throw new GAMSException("Dict needs to be 3-dimensional"); } string scenName = dict.FirstRecord(new string[] { " ", "scenario", " " }).Keys[0]; GAMSSet scenSymbol = dict.GAMSDatabase.GetSet(scenName); foreach (GAMSSetRecord rec in dict) { if (rec.Keys[1].ToLower() == "scenario") { continue; } if (rec.Keys[1].ToLower() == "param") { int modifierDim = dict.GAMSDatabase.GetParameter(rec.Keys[2]).Dim - scenSymbol.Dim; if (modifierDim < 0) { throw new GAMSException("Dimension of " + rec.Keys[2] + " too small"); } modifierList.Add(new Tuple <GAMSModifier, GAMSParameter> (new GAMSModifier(mi.SyncDB.AddParameter(rec.Keys[0], modifierDim, "")), dict.GAMSDatabase.GetParameter(rec.Keys[2]))); } else if ((rec.Keys[1].ToLower() == "lower") || (rec.Keys[1].ToLower() == "upper") || (rec.Keys[1].ToLower() == "fixed")) { int modifierDim = dict.GAMSDatabase.GetParameter(rec.Keys[2]).Dim - scenSymbol.Dim; if (modifierDim < 0) { throw new GAMSException("Dimension of " + rec.Keys[2] + " too small"); } GAMSVariable modifierVar; try { modifierVar = dict.GAMSDatabase.GetVariable(rec.Keys[0]); } catch (Exception) { modifierVar = mi.SyncDB.AddVariable(rec.Keys[0], modifierDim, VarType.Free, ""); } if (rec.Keys[1].ToLower() == "lower") { modifierList.Add(new Tuple <GAMSModifier, GAMSParameter> (new GAMSModifier(modifierVar, UpdateAction.Lower, mi.SyncDB.AddParameter(rec.Keys[2], modifierDim, "")), dict.GAMSDatabase.GetParameter(rec.Keys[2]))); } else if (rec.Keys[1].ToLower() == "upper") { modifierList.Add(new Tuple <GAMSModifier, GAMSParameter> (new GAMSModifier(modifierVar, UpdateAction.Upper, mi.SyncDB.AddParameter(rec.Keys[2], modifierDim, "")), dict.GAMSDatabase.GetParameter(rec.Keys[2]))); } else // fixed { modifierList.Add(new Tuple <GAMSModifier, GAMSParameter> (new GAMSModifier(modifierVar, UpdateAction.Fixed, mi.SyncDB.AddParameter(rec.Keys[2], modifierDim, "")), dict.GAMSDatabase.GetParameter(rec.Keys[2]))); } } else if ((rec.Keys[1].ToLower() == "level") || (rec.Keys[1].ToLower() == "marginal")) { // Check that parameter exists in GAMSDatabase, will throw an exception if not GAMSParameter x = dict.GAMSDatabase.GetParameter(rec.Keys[2]); } else { throw new GAMSException("Cannot handle UpdateAction " + rec.Keys[1]); } } List <GAMSModifier> mL = new List <GAMSModifier>(); foreach (Tuple <GAMSModifier, GAMSParameter> tup in modifierList) { mL.Add(tup.Item1); } mi.Instantiate(solveStatement, opt, mL.ToArray()); List <Tuple <GAMSSymbol, GAMSParameter, string> > outList = new List <Tuple <GAMSSymbol, GAMSParameter, string> >(); foreach (GAMSSetRecord s in scenSymbol) { foreach (Tuple <GAMSModifier, GAMSParameter> tup in modifierList) { GAMSParameter p; GAMSParameter pscen = tup.Item2; if (tup.Item1.DataSym == null) { p = (GAMSParameter)tup.Item1.GamsSym; } else { p = tup.Item1.DataSym; } // Implemented SymbolUpdateType=BaseCase p.Clear(); GAMSParameterRecord rec; string[] filter = new string[pscen.Dim]; for (int i = 0; i < scenSymbol.Dim; i++) { filter[i] = s.Keys[i]; } for (int i = scenSymbol.Dim; i < pscen.Dim; i++) { filter[i] = " "; } try { rec = pscen.FirstRecord(filter); } catch (GAMSException) { continue; } do { string[] myKeys = new string[p.Dim]; for (int i = 0; i < p.Dim; i++) { myKeys[i] = rec.Keys[scenSymbol.Dim + i]; } p.AddRecord(myKeys).Value = rec.Value; } while (rec.MoveNext()); } mi.Solve(GAMSModelInstance.SymbolUpdateType.BaseCase, output, miOpt); if (outList.Count == 0) { foreach (GAMSSetRecord rec in dict) { if ((rec.Keys[1].ToLower() == "level") || (rec.Keys[1].ToLower() == "marginal")) { outList.Add(new Tuple <GAMSSymbol, GAMSParameter, string>(mi.SyncDB.GetSymbol(rec.Keys[0]), dict.GAMSDatabase.GetParameter(rec.Keys[2]), rec.Keys[1].ToLower())); } } } foreach (Tuple <GAMSSymbol, GAMSParameter, string> tup in outList) { string[] myKeys = new string[scenSymbol.Dim + tup.Item1.FirstRecord().Keys.Length]; for (int i = 0; i < scenSymbol.Dim; i++) { myKeys[i] = s.Keys[i]; } if ((tup.Item3 == "level") && (tup.Item1 is GAMSVariable)) { foreach (GAMSVariableRecord rec in tup.Item1) { for (int i = 0; i < rec.Keys.Length; i++) { myKeys[scenSymbol.Dim + i] = s.Keys[i]; } tup.Item2.AddRecord(myKeys).Value = rec.Level; } } else if ((tup.Item3 == "level") && (tup.Item1 is GAMSEquation)) { foreach (GAMSEquationRecord rec in tup.Item1) { for (int i = 0; i < rec.Keys.Length; i++) { myKeys[scenSymbol.Dim + i] = s.Keys[i]; } tup.Item2.AddRecord(myKeys).Value = rec.Level; } } else if ((tup.Item3 == "marginal") && (tup.Item1 is GAMSVariable)) { foreach (GAMSVariableRecord rec in tup.Item1) { for (int i = 0; i < rec.Keys.Length; i++) { myKeys[scenSymbol.Dim + i] = s.Keys[i]; } tup.Item2.AddRecord(myKeys).Value = rec.Marginal; } } else if ((tup.Item3 == "marginal") && (tup.Item1 is GAMSEquation)) { foreach (GAMSEquationRecord rec in tup.Item1) { for (int i = 0; i < rec.Keys.Length; i++) { myKeys[scenSymbol.Dim + i] = s.Keys[i]; } tup.Item2.AddRecord(myKeys).Value = rec.Marginal; } } } } }
static void Main(string[] args) { GAMSWorkspace ws; if (Environment.GetCommandLineArgs().Length > 1) { ws = new GAMSWorkspace(systemDirectory: Environment.GetCommandLineArgs()[1]); } else { ws = new GAMSWorkspace(); } GAMSCheckpoint cp = ws.AddCheckpoint(); // initialize a GAMSCheckpoint by running a GAMSJob GAMSJob t7 = ws.AddJobFromString(GetModelText()); t7.Run(cp); // create a GAMSModelInstance and solve it multiple times with different scalar bmult GAMSModelInstance mi = cp.AddModelInstance(); GAMSParameter bmult = mi.SyncDB.AddParameter("bmult", 0, "demand multiplier"); GAMSOptions opt = ws.AddOptions(); opt.AllModelTypes = "gurobi"; // instantiate the GAMSModelInstance and pass a model definition and GAMSModifier to declare bmult mutable mi.Instantiate("transport us lp min z", opt, new GAMSModifier(bmult)); bmult.AddRecord().Value = 1.0; double[] bmultlist = new double[] { 0.6, 0.7, 0.8, 0.9, 1.0, 1.1, 1.2, 1.3 }; foreach (double b in bmultlist) { bmult.FirstRecord().Value = b; mi.Solve(); Console.WriteLine("Scenario bmult=" + b + ":"); Console.WriteLine(" Modelstatus: " + mi.ModelStatus); Console.WriteLine(" Solvestatus: " + mi.SolveStatus); Console.WriteLine(" Obj: " + mi.SyncDB.GetVariable("z").FindRecord().Level); } // create a GAMSModelInstance and solve it with single links in the network blocked mi = cp.AddModelInstance(); GAMSVariable x = mi.SyncDB.AddVariable("x", 2, VarType.Positive, ""); GAMSParameter xup = mi.SyncDB.AddParameter("xup", 2, "upper bound on x"); // instantiate the GAMSModelInstance and pass a model definition and GAMSModifier to declare upper bound of X mutable mi.Instantiate("transport us lp min z", modifiers: new GAMSModifier(x, UpdateAction.Upper, xup)); foreach (GAMSSetRecord i in t7.OutDB.GetSet("i")) { foreach (GAMSSetRecord j in t7.OutDB.GetSet("j")) { xup.Clear(); xup.AddRecord(i.Keys[0], j.Keys[0]).Value = 0; mi.Solve(); Console.WriteLine("Scenario link blocked: " + i.Keys[0] + " - " + j.Keys[0]); Console.WriteLine(" Modelstatus: " + mi.ModelStatus); Console.WriteLine(" Solvestatus: " + mi.SolveStatus); Console.WriteLine(" Obj: " + mi.SyncDB.GetVariable("z").FindRecord().Level); } } }
public void ProcessTask(TaskManager.TaskDetails oTask, out List <string> lsLogs, out string sOutput, out string sStatus) { // cast input values CutStockInput oInput = new CutStockInput(); oInput = (CutStockInput)oDF.XmlStringToObject(oTask.InputValues, oInput); CutStockOutput oOutput = new CutStockOutput(); // call processing algorithm GAMSWorkspace ws = new GAMSWorkspace(); lsLog.Add("working directory : " + ws.WorkingDirectory); // instantiate GAMSOptions and define parameters GAMSOptions opt = ws.AddOptions(); GAMSDatabase cutstockData = ws.AddDatabase("csdata"); opt.AllModelTypes = "Cplex"; opt.OptCR = 0.0; // Solve to optimality opt.Defines.Add("pmax", oInput.MaxPattern.ToString()); opt.Defines.Add("solveMasterAs", "RMIP"); GAMSSet widths = cutstockData.AddSet("i", 1, "widths"); GAMSParameter rawWidth = cutstockData.AddParameter("r", 0, "raw width"); GAMSParameter demand = cutstockData.AddParameter("d", 1, "demand"); GAMSParameter width = cutstockData.AddParameter("w", 1, "width"); rawWidth.AddRecord().Value = oInput.RawWidth; foreach (CutItem oI in oInput.Items) { widths.AddRecord(oI.Name); demand.AddRecord(oI.Name).Value = oI.Demand; width.AddRecord(oI.Name).Value = oI.Width; } // create initial checkpoint GAMSCheckpoint masterCP = ws.AddCheckpoint(); GAMSJob masterInitJob = ws.AddJobFromString(GetMasterModel()); masterInitJob.Run(opt, masterCP, cutstockData); GAMSJob masterJob = ws.AddJobFromString("execute_load 'csdata', aip, pp; solve master min z using %solveMasterAs%;", masterCP); GAMSSet pattern = cutstockData.AddSet("pp", 1, "pattern index"); GAMSParameter patternData = cutstockData.AddParameter("aip", 2, "pattern data"); // Initial pattern: pattern i hold width i int patternCount = 0; foreach (GAMSParameterRecord rec in width) { patternData.AddRecord(rec.Keys[0], pattern.AddRecord((++patternCount).ToString()).Keys[0]).Value = (int)(oInput.RawWidth / rec.Value); } // create model instance for sub job GAMSCheckpoint subCP = ws.AddCheckpoint(); ws.AddJobFromString(GetSubModel()).Run(opt, subCP, cutstockData); GAMSModelInstance subMI = subCP.AddModelInstance(); // define modifier demdual GAMSParameter demandDual = subMI.SyncDB.AddParameter("demdual", 1, "dual of demand from master"); subMI.Instantiate("pricing min z using mip", opt, new GAMSModifier(demandDual)); // find new pattern bool patternAdded = true; do { masterJob.Run(opt, masterCP, cutstockData); // Copy duals into gmssubMI.SyncDB DB demandDual.Clear(); foreach (GAMSEquationRecord dem in masterJob.OutDB.GetEquation("demand")) { demandDual.AddRecord(dem.Keys[0]).Value = dem.Marginal; } subMI.Solve(); if (subMI.SyncDB.GetVariable("z").FindRecord().Level < -0.00001) { if (patternCount == oInput.MaxPattern) { lsLog.Add("Out of pattern. Increase maxpattern (currently " + oInput.MaxPattern + ")." + Environment.NewLine); patternAdded = false; } else { lsLog.Add("New pattern! Value: " + subMI.SyncDB.GetVariable("z").FindRecord().Level + Environment.NewLine); GAMSSetRecord s = pattern.AddRecord((++patternCount).ToString()); foreach (GAMSVariableRecord y in subMI.SyncDB.GetVariable("y")) { if (y.Level > 0.5) { patternData.AddRecord(y.Keys[0], s.Keys[0]).Value = Math.Round(y.Level); } } } } else { patternAdded = false; } } while (patternAdded); // solve final MIP opt.Defines["solveMasterAs"] = "MIP"; masterJob.Run(opt, cutstockData); var dlevel = masterJob.OutDB.GetVariable("z").FindRecord().Level; oOutput.OptimalSolution = (int)dlevel; lsLog.Add("Optimal Solution: " + dlevel + Environment.NewLine); List <Pattern> lP = new List <Pattern>(); foreach (GAMSVariableRecord xp in masterJob.OutDB.GetVariable("xp")) { string sPatternLog = ""; if (xp.Level > 0.5) { sPatternLog = string.Format(" pattern {0,2} {1,4} times: ", xp.Keys[0], Math.Round(xp.Level)); GAMSParameterRecord aip = masterJob.OutDB.GetParameter("aip").FirstRecord(" ", xp.Keys[0]); Pattern oP = new Pattern() { Name = "pattern " + xp.Keys[0].ToString(), Count = (int)Math.Round(xp.Level) }; List <PatternPiece> lPP = new List <PatternPiece>(); int x = 0; double scale = 100 / masterJob.OutDB.GetParameter("r").FirstRecord().Value; do { sPatternLog += " " + aip.Keys[0] + ": " + aip.Value.ToString(); // draw cuts for (int i = 0; i < aip.Value; i++) { PatternPiece oPP = new PatternPiece() { Name = aip.Keys[0], Width = (int)(width.FindRecord(aip.Keys[0]).Value *scale), Left = x, Color = oInput.Items.Where(xi => xi.Name == aip.Keys[0]).FirstOrDefault().Color }; lPP.Add(oPP); // x += oPP.Width - 1; x += oPP.Width; } } while (aip.MoveNext()); if (x < 100) { PatternPiece oPExcess = new PatternPiece() { Name = "E", Width = (int)(rawWidth.FirstRecord().Value *scale - x), Left = x, Color = "CCCCCC" }; lPP.Add(oPExcess); } lsLog.Add(sPatternLog); oP.Pieces = lPP.ToArray(); lP.Add(oP); } } oOutput.Patterns = lP.ToArray(); // clean up of unmanaged resources cutstockData.Dispose(); subMI.Dispose(); opt.Dispose(); sOutput = oDF.ObjectToXmlString(oOutput); sStatus = "completed"; lsLogs = lsLog; }