/// <summary> /// This method obtains the data from the GAMS file using the low level API /// </summary> /// <param name="_source"></param> /// <param name="file"></param> /// <param name="table"></param> /// <param name="where"></param> /// <returns></returns> public static IEnumerable <QvxDataRow> GetGamsDataLowLevel(string _source, string file, QvxTable table, List <string> selectedFields, List <QueryExtractor.WhereCondition> where) { const int GMS_VAL_LEVEL = 0; const int GMS_VAL_MARGINAL = 1; const int GMS_VAL_LOWER = 2; const int GMS_VAL_UPPER = 3; const int GMS_VAL_SCALE = 4; //const int GMS_VAL_MAX = 5; string msg = string.Empty, VarName = string.Empty, sText = string.Empty, UelName = string.Empty; int ErrNr = 0, SymNr = 0, SymTyp = 0, ADim = 0, ACount = 0, AUser = 0, NRec = 0, FDim = 0, j = 0, i = 0, IDum = 0; using (gdxcs gdx = new gdxcs(ref msg)) { gdx.gdxOpenRead(_source + "\\" + file, ref ErrNr); gdx.gdxFindSymbol(table.TableName, ref SymNr); gdx.gdxSymbolInfo(SymNr, ref VarName, ref ADim, ref SymTyp); gdx.gdxSymbolInfoX(SymNr, ref ACount, ref AUser, ref sText); gdx.gdxDataReadRawStart(SymNr, ref NRec); Dictionary <int, string>[] dimensionCache = new Dictionary <int, string> [ADim]; if (where.Count == 0) { // No WHERE clause double[] Vals = new double[gamsglobals.val_max]; int[] Keys = new int[gamsglobals.maxdim]; while (gdx.gdxDataReadRaw(ref Keys, ref Vals, ref FDim) != 0) { QvxDataRow row = mapRow(Keys, Vals); if (row != null) { yield return(row); } } } else { // WHERE clause string[] strFilter = Enumerable.Repeat("", table.Fields.Count()).ToArray(); var emptyFilters = new List <QvxField>(); foreach (var whereCondition in where) { int m = Array.FindIndex(table.Fields, element => element.FieldName == whereCondition.Field); if (m >= 0) { if (m > (ADim - 1)) { // Only dimensions can be filtered throw new QvxPleaseSendReplyException(QvxResult.QVX_UNSUPPORTED_COMMAND, String.Format("Field \"{0}\" is not a dimension and can't be filtered", whereCondition.Field)); } else if ("".Equals(whereCondition.Value)) { // GAMS API doesn't allow empty filters, so we have to filter them ourselves emptyFilters.Add(table.Fields[m]); } else { strFilter[m] = whereCondition.Value; } } else { throw new QvxPleaseSendReplyException(QvxResult.QVX_FIELD_NOT_FOUND, String.Format("The field \"{0}\" is not valid", whereCondition.Field)); } } using (BlockingCollection <QvxDataRow> buffer = new BlockingCollection <QvxDataRow>()) { // Start reading thread Exception exception = null; var readTask = Task.Run(() => { try { gdx.gdxDataReadRawFastFilt(SymNr, strFilter, FilterProc); } catch (Exception e) { exception = e; } finally { // Signal the end of the data buffer.CompleteAdding(); } }); int FilterProc(IntPtr IndxPtr, IntPtr ValsPtr, IntPtr Uptr) { double[] managedArrayVals = new double[gamsglobals.val_max]; Marshal.Copy(ValsPtr, managedArrayVals, 0, gamsglobals.val_max); int[] managedArrayIndx = new int[gamsglobals.maxdim]; Marshal.Copy(IndxPtr, managedArrayIndx, 0, gamsglobals.maxdim); QvxDataRow row = mapRow(managedArrayIndx, managedArrayVals, emptyFilters); if (row != null) { buffer.Add(row); } return(1); } // Writing process foreach (QvxDataRow row in buffer.GetConsumingEnumerable()) { yield return(row); } if (exception != null) { throw exception; } } } QvxDataRow mapRow(int[] Keys, double[] Vals, List <QvxField> emptyFilters = null) { i = 0; var row = new QvxDataRow(); // Read the dimensions for (j = 0; j < ADim; j++) { if (dimensionCache[j] == null) { dimensionCache[j] = new Dictionary <int, string>(); } UelName = null; if (dimensionCache[j].ContainsKey(Keys[j])) { UelName = dimensionCache[j][Keys[j]]; } else { gdx.gdxUMUelGet(Keys[j], ref UelName, ref IDum); dimensionCache[j][Keys[j]] = UelName; } if (UelName != null) { QvxField field = table.Fields[i++]; if (selectedFields.Contains(field.FieldName)) { row[field] = UelName; } // we check the empty filters, as GAMS API doesn't do it if (emptyFilters != null && emptyFilters.Contains(field) && !string.IsNullOrEmpty(UelName)) { return(null); } } } switch (SymTyp) { // SET case gamsglobals.dt_set: if (gdx.gdxGetElemText((int)Vals[GMS_VAL_LEVEL], ref msg, ref IDum) != 0) { QvxField field2 = table.Fields[i++]; if (selectedFields.Contains(field2.FieldName)) { row[field2] = msg; } } else { QvxField field2 = table.Fields[i++]; if (selectedFields.Contains(field2.FieldName)) { row[field2] = Y_STRING; } } break; // PARAMETER case gamsglobals.dt_par: // Value readValueField(row, table.Fields[i++], table.Fields[i++], Vals[GMS_VAL_LEVEL]); if (!string.IsNullOrEmpty(sText) && ADim == 0) { QvxField field = table.Fields[i++]; if (selectedFields.Contains(field.FieldName)) { row[field] = sText; } } break; // EQUATION and VARIABLE case gamsglobals.dt_equ: case gamsglobals.dt_var: int[] gms_values = { GMS_VAL_LEVEL, GMS_VAL_MARGINAL, GMS_VAL_LOWER, GMS_VAL_UPPER, GMS_VAL_SCALE }; foreach (int gms_value in gms_values) { // Value readValueField(row, table.Fields[i++], table.Fields[i++], Vals[gms_value]); } break; } return(row); } /// <summary>This method reads a value separated in two fields, the first with the numeric value and the second with the special value description.</summary> void readValueField(QvxDataRow pRow, QvxField numberField, QvxField specialField, double pVal) { Boolean isSpecialValue = false; // Value if (selectedFields.Contains(numberField.FieldName)) { pRow[numberField] = val2str(pVal, msg, out isSpecialValue, true, false); } // Value (Special) if (selectedFields.Contains(specialField.FieldName)) { pRow[specialField] = val2str(pVal, msg, out isSpecialValue, false, true); } else if (isSpecialValue) { // If the value is special, but the "Special value" column is not selected, we throw an error throw new QvxPleaseSendReplyException(QvxResult.QVX_FIELD_NOT_FOUND, String.Format("The field \"{0}\" contains special values, so the field \"{1}\" has to be selected", numberField.FieldName, specialField.FieldName)); } } /// <summary>This method generates the final value of a field, that can be a normal number, an acronym, infinite, ...</summary> /// <param name="returnNumber">If true, the value of a number will be returned as a double</param> /// <param name="returnSpecial">If true, the value of a special value (infinite, epsilon, acronym, ...) will be returned as a string</param> dynamic val2str(double val, string s, out Boolean isSpecial, Boolean returnNumber = true, Boolean returnSpecial = true) { string[] gmsSVText = { "UNdef", "NA", "+Inf", "-Inf", "Eps", "0", "AcroN" }; int sv = 0; if (gdx.gdxAcronymName(val, ref s) != 0) { isSpecial = true; return(returnSpecial ? s : null); } else { gdx.gdxMapValue(val, ref sv); if (gamsglobals.sv_normal != sv) { isSpecial = true; return(returnSpecial ? gmsSVText[sv] : null); } else { isSpecial = false; if (returnNumber) { return(val); } else { return(null); } } } } } }
/// <summary> /// Obtains the preview data using the high level API /// </summary> /// <param name="tableName"></param> /// <param name="NumberOfRows"></param> /// <returns></returns> public string[,] GetPreviewData(QvxTable table, int NumberOfRows = int.MaxValue) { string[,] returnTable; GAMSSymbol symbol = Db.GetSymbol(table.TableName); switch (symbol) { case GAMSSet gset: GetPreviewColumnsData(out returnTable, gset, NumberOfRows); break; case GAMSParameter gparam: GetPreviewColumnsData(out returnTable, gparam, NumberOfRows); break; case GAMSEquation geq: GetPreviewColumnsData(out returnTable, geq, NumberOfRows); break; case GAMSVariable gvar: GetPreviewColumnsData(out returnTable, gvar, NumberOfRows); break; default: returnTable = new string[0, 0]; break; } int FinalNumberOfRows = returnTable.GetLength(0); int NumberOfColumns = returnTable.GetLength(1); //Using advanced api for retrieve acronyms if existing string msg = ""; int ErrNr = 0, SymNr = 0; using (gdxcs gdx = new gdxcs(ref msg)) { gdx.gdxOpenRead(GDXFileLocation, ref ErrNr); gdx.gdxFindSymbol(table.TableName, ref SymNr); int dimensions = symbol.Dim; for (int i = 0; i < FinalNumberOfRows; i++) { for (int j = dimensions; j < NumberOfColumns; j++) { if (double.TryParse(returnTable[i, j], out double doubleForParse)) { string value = val2str(doubleForParse, msg, out Boolean isSpecial); if (isSpecial) { // Values use two columns, and special values appear in the second one. So we increase the counter returnTable[i, j++] = ""; } returnTable[i, j] = value; } } } string val2str(double val, string s, out Boolean isSpecial) { string[] gmsSVText = { "UNdef", "NA", "+Inf", "-Inf", "Eps", "0", "AcroN" }; isSpecial = false; int sv = 0; if (gdx.gdxAcronymName(val, ref s) != 0) { isSpecial = true; return(s); } else { gdx.gdxMapValue(val, ref sv); if (gamsglobals.sv_normal != sv) { isSpecial = true; return(gmsSVText[sv]); } else { return(val.ToString("N", new CultureInfo("en-US", false).NumberFormat)); } } } } return(returnTable); }
static bool ReadSolutionData(string fnGDXFile) { int VarNr = 0, NrRecs = 0, FDim = 0, dim = 0, vartype = 0; int status = 0; string VarName; string msg = string.Empty; string[] Indx = new string[gamsglobals.maxdim]; double[] Values = new double[gamsglobals.val_max]; gdx.gdxOpenRead(fnGDXFile, ref status); if (status != 0) { return(GDXError(status, "gdxOpenRead")); } VarName = "result"; if (0 == gdx.gdxFindSymbol(VarName, ref VarNr)) { Console.WriteLine("Could not find variable >" + VarName + "<"); return(false); } gdx.gdxSymbolInfo(VarNr, ref VarName, ref dim, ref vartype); if (2 != dim || gamsglobals.dt_var != vartype) { Console.WriteLine(VarName + " is not a two dimensional variable"); return(false); } if (0 == gdx.gdxDataReadStrStart(VarNr, ref NrRecs)) { return(GDXError(gdx.gdxGetLastError(), "gdxDataReadStrStart")); } while (gdx.gdxDataReadStr(ref Indx, ref Values, ref FDim) != 0) { int i; if (0.0 == Values[gamsglobals.val_level]) { continue; /* skip level = 0.0 is default */ } for (i = 0; i < dim; i++) { Console.Write(Indx[i]); if (i < dim - 1) { Console.Write("."); } } Console.WriteLine(" = " + Values[gamsglobals.val_level]); } Console.WriteLine("All solution values shown"); gdx.gdxDataReadDone(); status = gdx.gdxGetLastError(); if (status != 0) { return(GDXError(status, "GDX")); } if (gdx.gdxClose() != 0) { return(GDXError(gdx.gdxGetLastError(), "gdxClose")); } return(true); }
static int Main(string[] args) { string Msg = string.Empty; string Sysdir; string Producer = string.Empty; int ErrNr = 0; int rc; string[] Indx = new string[gamsglobals.maxdim]; double[] Values = new double[gamsglobals.val_max]; int VarNr = 0; int NrRecs = 0; int N = 0; int Dimen = 0; string VarName = string.Empty; int VarTyp = 0; int D; if (Environment.GetCommandLineArgs().Length != 2 && Environment.GetCommandLineArgs().Length != 3) { Console.WriteLine("**** XP_Example1: incorrect number of parameters"); return 1; } String[] arguments = Environment.GetCommandLineArgs(); Sysdir = arguments[1]; Console.WriteLine("XP_Example1 using GAMS system directory: " + Sysdir); gdx = new gdxcs(Sysdir, ref Msg); if (Msg != string.Empty) { Console.WriteLine("**** Could not load GDX library"); Console.WriteLine("**** " + Msg); return 1; } gdx.gdxGetDLLVersion(ref Msg); Console.WriteLine("Using GDX DLL version: " + Msg); if (Environment.GetCommandLineArgs().Length == 2) { //write demand data gdx.gdxOpenWrite("demanddata.gdx", "xp_example1", ref ErrNr); if (ErrNr != 0) xp_example1.ReportIOError(ErrNr); if (gdx.gdxDataWriteStrStart("Demand", "Demand data", 1, gamsglobals.dt_par, 0) == 0) ReportGDXError(); WriteData("New-York", 324.0); WriteData("Chicago", 299.0); WriteData("Topeka", 274.0); if (gdx.gdxDataWriteDone() == 0) ReportGDXError(); Console.WriteLine("Demand data written by xp_example1"); } else { rc = gdx.gdxOpenRead(arguments[2], ref ErrNr); if (ErrNr != 0) ReportIOError(ErrNr); //read x variable back (non-default level values only) gdx.gdxFileVersion(ref Msg, ref Producer); Console.WriteLine("GDX file written using version: " + Msg); Console.WriteLine("GDX file written by: " + Producer); if (gdx.gdxFindSymbol("x", ref VarNr) == 0) { Console.WriteLine("**** Could not find variable X"); return 1; } gdx.gdxSymbolInfo(VarNr, ref VarName, ref Dimen, ref VarTyp); if (Dimen != 2 || VarTyp != gamsglobals.dt_var) { Console.WriteLine("**** X is not a two dimensional variable"); return 1; } if (gdx.gdxDataReadStrStart(VarNr, ref NrRecs) == 0) ReportGDXError(); Console.WriteLine("Variable X has " + NrRecs + " records"); while (gdx.gdxDataReadStr(ref Indx, ref Values, ref N) != 0) { if(Values[gamsglobals.val_level] == 0.0) //skip level = 0.0 is default continue; for (D=0; D<Dimen; D++) { Console.Write(Indx[D]); if (D < Dimen-1) Console.Write("."); } Console.WriteLine(" = " + Values[gamsglobals.val_level]); } Console.WriteLine("All solution values shown"); gdx.gdxDataReadDone(); } ErrNr = gdx.gdxClose(); if (ErrNr != 0) ReportIOError(ErrNr); return 0; }
static int Main(string[] args) { string Msg = string.Empty; string Sysdir; string Producer = string.Empty; int ErrNr = 0; int rc; string[] Indx = new string[gamsglobals.maxdim]; double[] Values = new double[gamsglobals.val_max]; int VarNr = 0; int NrRecs = 0; int N = 0; int Dimen = 0; string VarName = string.Empty; int VarTyp = 0; int D; if (Environment.GetCommandLineArgs().Length != 2 && Environment.GetCommandLineArgs().Length != 3) { Console.WriteLine("**** XP_Example1: incorrect number of parameters"); return(1); } String[] arguments = Environment.GetCommandLineArgs(); Sysdir = arguments[1]; Console.WriteLine("XP_Example1 using GAMS system directory: " + Sysdir); gdx = new gdxcs(Sysdir, ref Msg); if (Msg != string.Empty) { Console.WriteLine("**** Could not load GDX library"); Console.WriteLine("**** " + Msg); return(1); } gdx.gdxGetDLLVersion(ref Msg); Console.WriteLine("Using GDX DLL version: " + Msg); if (Environment.GetCommandLineArgs().Length == 2) { //write demand data gdx.gdxOpenWrite("demanddata.gdx", "xp_example1", ref ErrNr); if (ErrNr != 0) { xp_example1.ReportIOError(ErrNr); } if (gdx.gdxDataWriteStrStart("Demand", "Demand data", 1, gamsglobals.dt_par, 0) == 0) { ReportGDXError(); } WriteData("New-York", 324.0); WriteData("Chicago", 299.0); WriteData("Topeka", 274.0); if (gdx.gdxDataWriteDone() == 0) { ReportGDXError(); } Console.WriteLine("Demand data written by xp_example1"); } else { rc = gdx.gdxOpenRead(arguments[2], ref ErrNr); if (ErrNr != 0) { ReportIOError(ErrNr); } //read x variable back (non-default level values only) gdx.gdxFileVersion(ref Msg, ref Producer); Console.WriteLine("GDX file written using version: " + Msg); Console.WriteLine("GDX file written by: " + Producer); if (gdx.gdxFindSymbol("x", ref VarNr) == 0) { Console.WriteLine("**** Could not find variable X"); return(1); } gdx.gdxSymbolInfo(VarNr, ref VarName, ref Dimen, ref VarTyp); if (Dimen != 2 || VarTyp != gamsglobals.dt_var) { Console.WriteLine("**** X is not a two dimensional variable"); return(1); } if (gdx.gdxDataReadStrStart(VarNr, ref NrRecs) == 0) { ReportGDXError(); } Console.WriteLine("Variable X has " + NrRecs + " records"); while (gdx.gdxDataReadStr(ref Indx, ref Values, ref N) != 0) { if (Values[gamsglobals.val_level] == 0.0) //skip level = 0.0 is default { continue; } for (D = 0; D < Dimen; D++) { Console.Write(Indx[D]); if (D < Dimen - 1) { Console.Write("."); } } Console.WriteLine(" = " + Values[gamsglobals.val_level]); } Console.WriteLine("All solution values shown"); gdx.gdxDataReadDone(); } ErrNr = gdx.gdxClose(); if (ErrNr != 0) { ReportIOError(ErrNr); } return(0); }