1111
1212#include < algorithm>
1313#include < cctype>
14+ #include < cstring>
1415#include < stdexcept>
1516#include < string>
1617#include < string_view>
1718
1819namespace cuopt ::mathematical_optimization::io {
1920
21+ /* *
22+ * @brief Selects which MPS reader implementation should be used by dispatching entry points.
23+ *
24+ * The experimental fast reader is intentionally opt-in. It supports the same free-format
25+ * MPS/QPS scope as read_mps(): LP, MIP, QP (QUADOBJ/QMATRIX), and QCQP/SOCP (QCMATRIX).
26+ */
27+ enum class mps_reader_type_t { default_reader, fast_experimental };
28+
2029/* *
2130 * @brief Reads the equation from an MPS or QPS file.
2231 *
2332 * The input file can be a plain text file in MPS-/QPS-format or a compressed MPS/QPS
24- * file (.mps.gz or .mps.bz2 ).
33+ * file (.mps.gz, .mps.bz2, or .mps.lz4 ).
2534 *
2635 * Read this link http://lpsolve.sourceforge.net/5.5/mps-format.htm for more
2736 * details on both free and fixed MPS format.
@@ -32,8 +41,8 @@ namespace cuopt::mathematical_optimization::io {
3241 * - QMATRIX: Full symmetric quadratic objective matrix (alternative to QUADOBJ)
3342 * - QCMATRIX: Symmetric quadratic terms for a named constraint row (QCQP)
3443 *
35- * Note: Compressed MPS files .mps.gz, .mps.bz2 can only be read if the compression
36- * libraries zlib or libbzip2 are installed, respectively.
44+ * Note: Compressed MPS files .mps.gz, .mps.bz2, and .mps.lz4 can only be read if
45+ * zlib, libbzip2, or liblz4 are installed, respectively.
3746 *
3847 * @param[in] mps_file_path Path to MPS/QPSfile.
3948 * @param[in] fixed_mps_format If MPS/QPS file should be parsed as fixed, false by default
@@ -43,6 +52,19 @@ template <typename i_t, typename f_t>
4352mps_data_model_t <i_t , f_t > read_mps (const std::string& mps_file_path,
4453 bool fixed_mps_format = false );
4554
55+ /* *
56+ * @brief Reads an MPS/QPS problem with the experimental SIMD-optimized reader.
57+ *
58+ * Supports the same free-format LP/MIP/QP/QCQP (SOCP-relevant QCMATRIX) scope as read_mps().
59+ * Fixed MPS format forcing is not supported. Accepts .mps/.qps and their .gz/.bz2/.lz4 variants
60+ * (compression is detected from the file path, same as read_mps()).
61+ *
62+ * @param[in] mps_file_path Path to a raw or compressed .mps or .qps file.
63+ * @return mps_data_model_t A fully formed LP/MIP/QP problem which represents the given file.
64+ */
65+ template <typename i_t , typename f_t >
66+ mps_data_model_t <i_t , f_t > read_mps_fast_experimental (const std::string& mps_file_path);
67+
4668/* *
4769 * @brief Reads an MPS problem from in-memory file contents.
4870 *
@@ -111,38 +133,72 @@ mps_data_model_t<i_t, f_t> read_lp_from_string(std::string_view lp_contents);
111133 * @brief Reads an optimization problem from a file, dispatching on the file
112134 * extension. Extension matching is case-insensitive.
113135 *
114- * Routing:
115- * - .mps, .mps.gz, .mps.bz2, .qps, .qps.gz, .qps.bz2 → read_mps()
116- * - .lp, .lp.gz, .lp.bz2 → read_lp()
136+ * Routing (case-insensitive extensions):
137+ * - .mps, .mps.gz, .mps.bz2, .mps.lz4, .qps, .qps.gz, .qps.bz2, .qps.lz4
138+ * → read_mps() when mps_reader == default_reader, or read_mps_fast_experimental()
139+ * when mps_reader == fast_experimental (fixed_mps_format must be false)
140+ * - .lp, .lp.gz, .lp.bz2, .lp.lz4 → read_lp()
117141 * - anything else → std::logic_error
118142 *
119143 * This is the entry point of choice for user-facing tools (CLI, C API) that
120144 * want both formats to "just work" without an explicit format flag.
121145 *
122146 * @param[in] path Path to the input file.
147+ * @param[in] mps_reader Selects the MPS reader implementation for MPS/QPS inputs.
123148 * @param[in] fixed_mps_format If the MPS/QPS reader should use fixed format;
124149 * ignored for LP inputs. False by default.
125150 * @return mps_data_model_t The parsed problem.
126151 */
127152template <typename i_t , typename f_t >
128- inline mps_data_model_t <i_t , f_t > read (const std::string& path, bool fixed_mps_format = false )
153+ inline mps_data_model_t <i_t , f_t > read (const std::string& path,
154+ mps_reader_type_t mps_reader,
155+ bool fixed_mps_format = false )
129156{
130157 std::string lower (path);
131158 std::transform (lower.begin (), lower.end (), lower.begin (), [](unsigned char c) {
132159 return static_cast <char >(std::tolower (c));
133160 });
134- if (lower.ends_with (" .mps" ) || lower.ends_with (" .mps.gz" ) || lower.ends_with (" .mps.bz2" ) ||
135- lower.ends_with (" .qps" ) || lower.ends_with (" .qps.gz" ) || lower.ends_with (" .qps.bz2" )) {
136- return read_mps<i_t , f_t >(path, fixed_mps_format);
161+ for (const char * compression_suffix : {" .bz2" , " .gz" , " .lz4" }) {
162+ if (lower.ends_with (compression_suffix)) {
163+ lower.resize (lower.size () - std::strlen (compression_suffix));
164+ break ;
165+ }
137166 }
138- if (lower.ends_with (" .lp" ) || lower.ends_with (" .lp.gz" ) || lower.ends_with (" .lp.bz2" )) {
139- return read_lp<i_t , f_t >(path);
167+ if (lower.ends_with (" .mps" ) || lower.ends_with (" .qps" )) {
168+ if (mps_reader == mps_reader_type_t ::fast_experimental) {
169+ if (fixed_mps_format) {
170+ throw std::logic_error (
171+ " experimental fast MPS reader does not support fixed MPS format forcing" );
172+ }
173+ return read_mps_fast_experimental<i_t , f_t >(path);
174+ }
175+ return read_mps<i_t , f_t >(path, fixed_mps_format);
140176 }
177+ if (lower.ends_with (" .lp" )) { return read_lp<i_t , f_t >(path); }
141178 throw std::logic_error (
142179 " read: unrecognized input file extension. Supported (case-insensitive): "
143- " .mps, .mps.gz, .mps.bz2, .qps, .qps.gz, .qps.bz2, .lp, .lp.gz, .lp.bz2. "
180+ " .mps, .mps.gz, .mps.bz2, .mps.lz4, .qps, .qps.gz, .qps.bz2, .qps.lz4, "
181+ " .lp, .lp.gz, .lp.bz2, .lp.lz4. "
144182 " Given path: " +
145183 path);
146184}
147185
186+ /* *
187+ * @brief Reads an optimization problem from a file, dispatching on the file
188+ * extension. Extension matching is case-insensitive.
189+ *
190+ * Uses the default MPS reader. See the 3-argument read() overload for routing
191+ * details and supported extensions.
192+ *
193+ * @param[in] path Path to the input file.
194+ * @param[in] fixed_mps_format If the MPS/QPS reader should use fixed format;
195+ * ignored for LP inputs. False by default.
196+ * @return mps_data_model_t The parsed problem.
197+ */
198+ template <typename i_t , typename f_t >
199+ inline mps_data_model_t <i_t , f_t > read (const std::string& path, bool fixed_mps_format = false )
200+ {
201+ return read<i_t , f_t >(path, mps_reader_type_t ::default_reader, fixed_mps_format);
202+ }
203+
148204} // namespace cuopt::mathematical_optimization::io
0 commit comments