/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* */ /* This file is part of the HiGHS linear optimization suite */ /* */ /* Written and engineered 2008-2022 at the University of Edinburgh */ /* */ /* Available as open-source under the MIT License */ /* */ /* Authors: Julian Hall, Ivet Galabova, Leona Gottwald and Michael */ /* Feldmeier */ /* */ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /**@file io/HMpsFF.h * @brief */ #ifndef IO_HMPSFF_H_ #define IO_HMPSFF_H_ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "io/HighsIO.h" #include "model/HighsModel.h" //#include "util/HighsInt.h" #include "util/stringutil.h" using Triplet = std::tuple; enum class FreeFormatParserReturnCode { kSuccess, kParserError, kFileNotFound, kFixedFormat, kTimeout, }; namespace free_format_parser { // private: using wall_clock = std::chrono::high_resolution_clock; using time_point = wall_clock::time_point; double getWallTime(); class HMpsFF { public: HMpsFF() {} FreeFormatParserReturnCode loadProblem(const HighsLogOptions& log_options, const std::string filename, HighsModel& model); double time_limit = kHighsInf; private: double start_time; HighsInt num_row; HighsInt num_col; HighsInt num_nz; std::string mps_name; ObjSense obj_sense = ObjSense::kMinimize; // Minimization by default double obj_offset = 0; std::vector a_start; std::vector a_index; std::vector a_value; std::vector col_cost; std::vector col_lower; std::vector col_upper; std::vector row_lower; std::vector row_upper; std::vector row_names; std::vector col_names; std::vector col_integrality; HighsInt q_dim; std::vector q_start; std::vector q_index; std::vector q_value; // Keep track of columns that are binary by default, being columns // that are defined as integer by markers in the column section, or // as binary by having a BV flag in the BOUNDS section, and without // any LI or UI flags in the BOUNDS section std::vector col_binary; // Record where the cost row is encountered HighsInt cost_row_location; // Record whether there are duplicate row or column names, and the // name and indices of the first duplicates bool has_duplicate_row_name_; bool has_duplicate_col_name_; std::string duplicate_row_name_; HighsInt duplicate_row_name_index0_; HighsInt duplicate_row_name_index1_; std::string duplicate_col_name_; HighsInt duplicate_col_name_index0_; HighsInt duplicate_col_name_index1_; // Record whether there is a data entry in the RHS section of an MPS // file for the objective or a row. Have to be class data members so // that they can be used by parseName and addRhs in HMpsFF::parseRhs bool has_obj_entry_; std::vector has_row_entry_; /// load LP from MPS file as transposed triplet matrix HighsInt parseFile(std::string filename); HighsInt fillMatrix(const HighsLogOptions& log_options); HighsInt fillHessian(const HighsLogOptions& log_options); const bool kAnyFirstNonBlankAsStarImpliesComment = false; /// how to treat variables that appear in COLUMNS section first /// assume them to be binary as in the original IBM interpretation /// or integer with default bounds bool kintegerVarsInColumnsAreBinary = true; enum class Parsekey { kName, kObjsense, kMax, kMin, kRows, kCols, kRhs, kBounds, kRanges, kQsection, kQmatrix, kQuadobj, kQcmatrix, kCsection, kDelayedrows, kModelcuts, kIndicators, kSets, kSos, kGencons, kPwlobj, kPwlnam, kPwlcon, kNone, kEnd, kFail, kComment, kFixedFormat, kTimeout }; enum class Boundtype { kLe, kEq, kGe }; //, kFr }; // see https://docs.mosek.com/latest/capi/mps-format.html#csection-optional enum class ConeType { kZero, kQuad, kRQuad, kPExp, kPPow, kDExp, kDPow }; std::string objective_name; std::vector row_type; std::vector integer_column; std::vector entries; std::vector q_entries; std::vector> qrows_entries; std::vector> coeffobj; std::vector sos_name; std::vector sos_type; std::vector>> sos_entries; std::vector cone_name; std::vector cone_type; std::vector cone_param; std::vector> cone_entries; std::unordered_map rowname2idx; std::unordered_map colname2idx; mutable std::string section_args; FreeFormatParserReturnCode parse(const HighsLogOptions& log_options, const std::string& filename); // Checks first word of strline and wraps it by it_begin and it_end HMpsFF::Parsekey checkFirstWord(std::string& strline, HighsInt& start, HighsInt& end, std::string& word) const; // Get index of column from column name, possibly adding new column // if no index is found HighsInt getColIdx(const std::string& colname, const bool add_if_new = true); HMpsFF::Parsekey parseDefault(const HighsLogOptions& log_options, std::istream& file); HMpsFF::Parsekey parseObjsense(const HighsLogOptions& log_options, std::istream& file); HMpsFF::Parsekey parseRows(const HighsLogOptions& log_options, std::istream& file); HMpsFF::Parsekey parseCols(const HighsLogOptions& log_options, std::istream& file); HMpsFF::Parsekey parseRhs(const HighsLogOptions& log_options, std::istream& file); HMpsFF::Parsekey parseRanges(const HighsLogOptions& log_options, std::istream& file); HMpsFF::Parsekey parseBounds(const HighsLogOptions& log_options, std::istream& file); HMpsFF::Parsekey parseHessian(const HighsLogOptions& log_options, std::istream& file, const HMpsFF::Parsekey keyword); HMpsFF::Parsekey parseQuadRows(const HighsLogOptions& log_options, std::istream& file, const HMpsFF::Parsekey keyword); HMpsFF::Parsekey parseCones(const HighsLogOptions& log_options, std::istream& file); HMpsFF::Parsekey parseSos(const HighsLogOptions& log_options, std::istream& file, const HMpsFF::Parsekey keyword); bool cannotParseSection(const HighsLogOptions& log_options, const HMpsFF::Parsekey keyword); bool allZeroed(const std::vector& value); }; } // namespace free_format_parser #endif /* IO_HMPSFF_H_ */