1    	/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2    	/*                                                                           */
3    	/*                  This file is part of the class library                   */
4    	/*       SoPlex --- the Sequential object-oriented simPlex.                  */
5    	/*                                                                           */
6    	/*  Copyright (c) 1996-2023 Zuse Institute Berlin (ZIB)                      */
7    	/*                                                                           */
8    	/*  Licensed under the Apache License, Version 2.0 (the "License");          */
9    	/*  you may not use this file except in compliance with the License.         */
10   	/*  You may obtain a copy of the License at                                  */
11   	/*                                                                           */
12   	/*      http://www.apache.org/licenses/LICENSE-2.0                           */
13   	/*                                                                           */
14   	/*  Unless required by applicable law or agreed to in writing, software      */
15   	/*  distributed under the License is distributed on an "AS IS" BASIS,        */
16   	/*  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */
17   	/*  See the License for the specific language governing permissions and      */
18   	/*  limitations under the License.                                           */
19   	/*                                                                           */
20   	/*  You should have received a copy of the Apache-2.0 license                */
21   	/*  along with SoPlex; see the file LICENSE. If not email to soplex@zib.de.  */
22   	/*                                                                           */
23   	/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
24   	
25   	/**@file  mpsinput.h
26   	 * @brief Read MPS format files.
27   	 */
28   	#ifndef _MPSINPUT_H_
29   	#define _MPSINPUT_H_
30   	
31   	#include <iostream>
32   	
33   	#include "soplex/spxout.h"
34   	
35   	namespace soplex
36   	{
37   	
38   	/**@class MPSInput
39   	
40   	   Reads MPS input files. A right-hand side for the objective function is
41   	   allowed but ignored.
42   	 */
43   	class MPSInput
44   	{
45   	public:
46   	
47   	   //-----------------------------------
48   	   /**@name Types */
49   	   ///@{
50   	   ///
51   	
52   	   enum Section
53   	   {
54   	      NAME, OBJSEN, OBJNAME, ROWS, COLUMNS, RHS, RANGES, BOUNDS, ENDATA
55   	   };
56   	   ///
57   	
58   	   /// optimization sense.
59   	   enum Sense
60   	   {
61   	      MAXIMIZE = 1,
62   	      MINIMIZE = -1
63   	   };
64   	
65   	   enum { MAX_LINE_LEN = 256 };
66   	
67   	   ///@}
68   	
69   	private:
70   	
71   	   //-----------------------------------
72   	   /**@name Private data */
73   	   ///@{
74   	   ///
75   	   Section         m_section;
76   	   /// the input stream from which the file is read
77   	   std::istream&   m_input;
78   	   /// line number
79   	   int             m_lineno;
80   	   /// objctive sense (maximization or minimization)
81   	   Sense           m_objsense;
82   	   /// is set to \c true upon a syntax error
83   	   bool            m_has_error;
84   	   /// the line buffer
85   	   char            m_buf[MAX_LINE_LEN];
86   	   /// first field in a line
87   	   const char*     m_f0;
88   	   /// second field in a line
89   	   const char*     m_f1;
90   	   /// third field in a line
91   	   const char*     m_f2;
92   	   /// fourth field in a line
93   	   const char*     m_f3;
94   	   /// fifth field in a line
95   	   const char*     m_f4;
96   	   /// sixth field in a line
97   	   const char*     m_f5;
98   	   /// problem name
99   	   char            m_probname[MAX_LINE_LEN];
100  	   /// objective name
101  	   char            m_objname [MAX_LINE_LEN];
102  	   ///
103  	   bool            m_is_integer;
104  	   /// new MPS format?
105  	   bool            m_is_new_format;
106  	   /// Number of already ignored entries.
107  	   int             m_ignored;
108  	   /// Maximal number of ignored entries for which a warning will be issued.
109  	   static const int m_max_ignore = 1000;
110  	   ///@}
111  	
112  	public:
113  	
114  	   //-----------------------------------
115  	   /**@name Construction / destruction */
116  	   ///@{
117  	   ///
118  	   explicit
119  	   MPSInput(std::istream& p_input)
120  	      : m_section(NAME)
121  	      , m_input(p_input)
122  	      , m_lineno(0)
123  	      , m_objsense(MPSInput::MINIMIZE)
124  	      , m_has_error(false)
125  	      , m_is_integer(false)
126  	      , m_is_new_format(false)
127  	      , m_ignored(0)
128  	   {
129  	      m_f0 = m_f1 = m_f2 = m_f3 = m_f4 = m_f5 = 0;
130  	
131  	      m_buf     [0] = '\0';
132  	      m_probname[0] = '\0';
133  	      m_objname [0] = '\0';
134  	   }
135  	   ///
136  	   virtual
137  	   ~MPSInput()
138  	   {
139  	      // only to signal to flexelint that the pointers do
140  	      // not point to anything that has to be freed.
141  	      m_f0 = m_f1 = m_f2 = m_f3 = m_f4 = m_f5 = 0;
142  	   }
143  	   ///@}
144  	
145  	   //-----------------------------------
146  	   /**@name Access */
147  	   ///@{
148  	   ///
149  	   Section         section()   const
150  	   {
151  	      return m_section;
152  	   }
153  	   ///
154  	   int             lineno()    const
155  	   {
156  	      return m_lineno;
157  	   }
158  	   ///
159  	   const char*     field0()    const
160  	   {
161  	      return m_f0;
162  	   }
163  	   ///
164  	   const char*     field1()    const
165  	   {
166  	      return m_f1;
167  	   }
168  	   ///
169  	   const char*     field2()    const
170  	   {
171  	      return m_f2;
172  	   }
173  	   ///
174  	   const char*     field3()    const
175  	   {
176  	      return m_f3;
177  	   }
178  	   ///
179  	   const char*     field4()    const
180  	   {
181  	      return m_f4;
182  	   }
183  	   ///
184  	   const char*     field5()    const
185  	   {
186  	      return m_f5;
187  	   }
188  	   ///
189  	   const char*     probName()  const
190  	   {
191  	      return m_probname;
192  	   }
193  	   ///
194  	   const char*     objName()   const
195  	   {
196  	      return m_objname;
197  	   }
198  	   ///
199  	   Sense           objSense()  const
200  	   {
201  	      return m_objsense;
202  	   }
203  	   ///
204  	   bool            hasError()  const
205  	   {
206  	      return m_has_error;
207  	   }
208  	   ///
209  	   bool            isInteger() const
210  	   {
211  	      return m_is_integer;
212  	   }
213  	   ///@}
214  	
215  	   //-----------------------------------
216  	   /**@name Modification */
217  	   ///@{
218  	   ///
219  	   void setSection(Section p_section)
220  	   {
221  	      m_section = p_section;
222  	   }
223  	   ///
224  	   void setProbName(const char* p_probname)
225  	   {
226  	      assert(strlen(p_probname) < MAX_LINE_LEN);
227  	      spxSnprintf(m_probname, MAX_LINE_LEN, "%s", p_probname);
228  	   }
229  	   ///
230  	   void setObjName(const char* p_objname)
231  	   {
232  	      assert(strlen(p_objname) < MAX_LINE_LEN);
233  	      spxSnprintf(m_objname, MAX_LINE_LEN, "%s", p_objname);
234  	   }
235  	   ///
236  	   void setObjSense(Sense sense)
237  	   {
238  	      m_objsense = sense;
239  	   }
240  	   ///@}
241  	
242  	   //-----------------------------------
243  	   /**@name Warnings and Errors */
244  	   ///@{
245  	   ///
246  	   void syntaxError()
247  	   {
248  	      SPX_MSG_ERROR(std::cerr << "Syntax error in line " << m_lineno << std::endl;)
249  	      m_section = ENDATA;
250  	      m_has_error = true;
251  	   }
252  	   ///
253  	   void entryIgnored(
254  	      const char* what, const char* what_name,
255  	      const char* entity, const char* entity_name)
256  	   {
257  	      if(m_ignored < m_max_ignore)
258  	      {
259  	         SPX_MSG_ERROR(std::cerr << "Warning: line " << m_lineno << ": "
260  	                       << what << " \"" << what_name << "\""
261  	                       << " for " << entity << " \""
262  	                       << entity_name << "\" ignored" << std::endl;)
263  	         ++m_ignored;
264  	
265  	         if(m_ignored == m_max_ignore)
266  	            SPX_MSG_ERROR(std::cerr << "Warning: This was the " << m_max_ignore
267  	                          << " ignored entry. No further warnings on "
268  	                          << "ignored entries will be given." << std::endl;)
269  	         }
270  	   }
271  	   ///@}
272  	
273  	   //-----------------------------------
274  	   /**@name Helpers */
275  	   ///@{
276  	   /// reads an MPS format data line and parse the fields.
277  	   bool readLine();
278  	   /// Inserts \p name as field 1 and shifts all other fields up.
279  	   void insertName(const char* name,
280  	                   bool second = false);
281  	   ///@}
282  	};
283  	} // namespace soplex
284  	#endif // _MPSINPUT_H_
285