@@ -175,7 +175,6 @@ HighsInt HMpsFF::fillMatrix(const HighsLogOptions& log_options) {
175175}
176176
177177HighsInt HMpsFF::fillHessian (const HighsLogOptions& log_options) {
178- const std::vector<Triplet>& qentries = q_entries;
179178 size_t num_entries = q_entries.size ();
180179 if (!num_entries) {
181180 q_dim = 0 ;
@@ -212,6 +211,7 @@ HighsInt HMpsFF::fillHessian(const HighsLogOptions& log_options) {
212211 q_value[q_length[iCol]] = value;
213212 q_length[iCol]++;
214213 }
214+ q_format = HessianFormat::kSquare ;
215215 return 0 ;
216216}
217217
@@ -1735,120 +1735,23 @@ HMpsFF::Parsekey HMpsFF::parseRanges(const HighsLogOptions& log_options,
17351735typename HMpsFF::Parsekey HMpsFF::parseHessian (
17361736 const HighsLogOptions& log_options, std::istream& file,
17371737 const HMpsFF::Parsekey keyword) {
1738- // Parse Hessian information from QUADOBJ or QMATRIX
1739- // section according to keyword
1740- const bool qmatrix = keyword == HMpsFF::Parsekey::kQmatrix ;
1741- std::string section_name;
1742- if (qmatrix) {
1743- section_name = " QMATRIX" ;
1744- } else if (keyword == HMpsFF::Parsekey::kQuadobj ) {
1745- section_name = " QUADOBJ" ;
1746- }
1747- // Store all nonzeros in the section, but QMATRIX should have all
1748- // entries - so its format is HessianFormat::kSquare format -
1749- // whereas every off-diagonal QUADOBJ entry also defines its entry
1750- // in the opposite triangle, so its format is
1751- // HessianFormat::kTriangular.
1752- q_format = qmatrix ? HessianFormat::kSquare : HessianFormat::kTriangular ;
1753- std::string strline;
1754- std::string col_name;
1755- std::string row_name;
1756- std::string coeff_name;
1757- size_t end_row_name;
1758- size_t end_coeff_name;
1759- HighsInt colidx, rowidx;
1760-
1761- bool skip;
1762- while (getMpsLine (file, strline, skip)) {
1763- if (skip) continue ;
1764- if (timeout ()) return HMpsFF::Parsekey::kTimeout ;
1765-
1766- size_t begin = 0 ;
1767- size_t end = 0 ;
1768- HMpsFF::Parsekey key = checkFirstWord (strline, begin, end, col_name);
1769-
1770- // start of new section?
1771- if (key != Parsekey::kNone ) {
1772- highsLogDev (log_options, HighsLogType::kInfo , " readMPS: Read %s OK\n " ,
1773- section_name.c_str ());
1774- return key;
1775- }
1776-
1777- // Get the column index from the name
1778- colidx = getColIdx (col_name);
1779- assert (colidx >= 0 && colidx < num_col);
1780-
1781- // Loop over the maximum of two entries per row of the file
1782- for (int entry = 0 ; entry < 2 ; entry++) {
1783- // Get the row name
1784- row_name = " " ;
1785- row_name = first_word (strline, end);
1786- end_row_name = first_word_end (strline, end);
1787-
1788- if (row_name == " " ) break ;
1789-
1790- coeff_name = " " ;
1791- coeff_name = first_word (strline, end_row_name);
1792- end_coeff_name = first_word_end (strline, end_row_name);
1793-
1794- if (coeff_name == " " ) {
1795- trim (row_name);
1796- trim (col_name);
1797- highsLogUser (
1798- log_options, HighsLogType::kError ,
1799- " %s has no coefficient for entry \" %s\" in column \" %s\"\n " ,
1800- section_name.c_str (), row_name.c_str (), col_name.c_str ());
1801- return HMpsFF::Parsekey::kFail ;
1802- }
1803-
1804- rowidx = getColIdx (row_name);
1805- assert (rowidx >= 0 && rowidx < num_col);
1806-
1807- bool is_nan = false ;
1808- double coeff = getValue (coeff_name, is_nan); // atof(word.c_str());
1809- if (is_nan) {
1810- highsLogUser (
1811- log_options, HighsLogType::kError ,
1812- " Hessian coefficient for entry \" %s\" in column \" %s\" is NaN\n " ,
1813- row_name.c_str (), col_name.c_str ());
1814- return HMpsFF::Parsekey::kFail ;
1815- }
1816- if (coeff) q_entries.push_back (std::make_tuple (rowidx, colidx, coeff));
1817- end = end_coeff_name;
1818- // Don't read more if end of line reached
1819- if (end == strline.length ()) break ;
1820- }
1821- }
1822-
1823- return HMpsFF::Parsekey::kFail ;
1738+ assert (keyword == HMpsFF::Parsekey::kQuadobj ||
1739+ keyword == HMpsFF::Parsekey::kQmatrix );
1740+ const std::string section_name =
1741+ keyword == HMpsFF::Parsekey::kQuadobj ? " QUADOBJ" : " QMATRIX" ;
1742+ return parseQuadMatrix (log_options, file, section_name, q_entries);
18241743}
18251744
18261745typename HMpsFF::Parsekey HMpsFF::parseQuadRows (
18271746 const HighsLogOptions& log_options, std::istream& file,
18281747 const HMpsFF::Parsekey keyword) {
1829- // Parse Hessian information from QSECTION or QCMATRIX
1830- // section according to keyword
1831- const bool qcmatrix = keyword == HMpsFF::Parsekey::kQcmatrix ;
1832- std::string section_name;
1833- if (qcmatrix) {
1834- section_name = " QCMATRIX" ;
1835- } else {
1836- section_name = " QSECTION" ;
1837- }
1838- // Store all nonzeros in the section, but QCMATRIX should have all
1839- // entries - so its format is HessianFormat::kSquare format -
1840- // whereas every off-diagonal QSECTION entry also defines its entry
1841- // in the opposite triangle, so its format is
1842- // HessianFormat::kTriangular.
1843- q_format = qcmatrix ? HessianFormat::kSquare : HessianFormat::kTriangular ;
1748+ assert (keyword == HMpsFF::Parsekey::kQsection ||
1749+ keyword == HMpsFF::Parsekey::kQcmatrix );
1750+ const std::string section_name =
1751+ keyword == HMpsFF::Parsekey::kQsection ? " QSECTION" : " QCMATRIX" ;
18441752 std::string strline;
18451753 std::string col_name;
1846- std::string row_name;
1847- std::string coeff_name;
1848- size_t end_row_name;
1849- size_t end_coeff_name;
1850- HighsInt rowidx; // index of quadratic row
1851- HighsInt qcolidx, qrowidx; // indices in quadratic coefs matrix
1754+ HighsInt rowidx; // index of quadratic row
18521755
18531756 // Get row name from section argument
18541757 std::string rowname = first_word (section_args, 0 );
@@ -1894,6 +1797,25 @@ typename HMpsFF::Parsekey HMpsFF::parseQuadRows(
18941797 assert (rowidx == -1 || qrows_entries.size () == static_cast <size_t >(num_row));
18951798
18961799 auto & qentries = (rowidx == -1 ? q_entries : qrows_entries[rowidx]);
1800+ return parseQuadMatrix (log_options, file, section_name, qentries);
1801+ }
1802+
1803+ typename HMpsFF::Parsekey HMpsFF::parseQuadMatrix (
1804+ const HighsLogOptions& log_options, std::istream& file,
1805+ const std::string& section_name, std::vector<Triplet>& q_entries) {
1806+ // Store all nonzeros in the section. QMATRIX/QCMATRIX should have
1807+ // all entries, whereas every off-diagonal QUADOBJ/QSECTION entry
1808+ // also defines its entry in the opposite triangle, so add this
1809+ // explicitly to unify the record regardless of section
1810+ const bool triangular =
1811+ section_name == " QUADOBJ" || section_name == " QSECTION" ;
1812+ std::string strline;
1813+ std::string col_name;
1814+ std::string row_name;
1815+ std::string coeff_name;
1816+ size_t end_row_name;
1817+ size_t end_coeff_name;
1818+ HighsInt colidx, rowidx;
18971819
18981820 bool skip;
18991821 while (getMpsLine (file, strline, skip)) {
@@ -1906,14 +1828,14 @@ typename HMpsFF::Parsekey HMpsFF::parseQuadRows(
19061828
19071829 // start of new section?
19081830 if (key != Parsekey::kNone ) {
1909- highsLogDev (log_options, HighsLogType::kInfo , " readMPS: Read %s OK\n " ,
1831+ highsLogDev (log_options, HighsLogType::kInfo , " readMPS: Read %s OK\n " ,
19101832 section_name.c_str ());
19111833 return key;
19121834 }
19131835
1914- // Get the column index
1915- qcolidx = getColIdx (col_name);
1916- assert (qcolidx >= 0 && qcolidx < num_col);
1836+ // Get the column index from the name
1837+ colidx = getColIdx (col_name);
1838+ assert (colidx >= 0 && colidx < num_col);
19171839
19181840 // Loop over the maximum of two entries per row of the file
19191841 for (int entry = 0 ; entry < 2 ; entry++) {
@@ -1938,8 +1860,8 @@ typename HMpsFF::Parsekey HMpsFF::parseQuadRows(
19381860 return HMpsFF::Parsekey::kFail ;
19391861 }
19401862
1941- qrowidx = getColIdx (row_name);
1942- assert (qrowidx >= 0 && qrowidx < num_col);
1863+ rowidx = getColIdx (row_name);
1864+ assert (rowidx >= 0 && rowidx < num_col);
19431865
19441866 bool is_nan = false ;
19451867 double coeff = getValue (coeff_name, is_nan); // atof(word.c_str());
@@ -1950,7 +1872,13 @@ typename HMpsFF::Parsekey HMpsFF::parseQuadRows(
19501872 row_name.c_str (), col_name.c_str ());
19511873 return HMpsFF::Parsekey::kFail ;
19521874 }
1953- if (coeff) q_entries.push_back (std::make_tuple (qrowidx, qcolidx, coeff));
1875+ if (coeff) {
1876+ q_entries.push_back (std::make_tuple (rowidx, colidx, coeff));
1877+ // For a triangular section (QUADOBJ/QSECTION), make a
1878+ // separate record of the entry in the opposite triangle
1879+ if (triangular && rowidx != colidx)
1880+ q_entries.push_back (std::make_tuple (colidx, rowidx, coeff));
1881+ }
19541882 end = end_coeff_name;
19551883 // Don't read more if end of line reached
19561884 if (end == strline.length ()) break ;
0 commit comments