@@ -129,12 +129,13 @@ bool HighsIis::trivial(const HighsLp& lp, const HighsOptions& options) {
129129 count.assign (lp.num_row_ , 0 );
130130 for (HighsInt iCol = 0 ; iCol < lp.num_col_ ; iCol++) {
131131 for (HighsInt iEl = lp.a_matrix_ .start_ [iCol];
132- iEl < lp.a_matrix_ .start_ [iCol + 1 ]; iEl++)
133- count[lp.a_matrix_ .index_ [iEl]]++;
132+ iEl < lp.a_matrix_ .start_ [iCol + 1 ]; iEl++)
133+ count[lp.a_matrix_ .index_ [iEl]]++;
134134 }
135135 } else {
136- for (HighsInt iRow = 0 ; iRow < lp.num_row_ ; iRow++)
137- count.push_back (lp.a_matrix_ .start_ [iRow + 1 ]-lp.a_matrix_ .start_ [iRow]);
136+ for (HighsInt iRow = 0 ; iRow < lp.num_row_ ; iRow++)
137+ count.push_back (lp.a_matrix_ .start_ [iRow + 1 ] -
138+ lp.a_matrix_ .start_ [iRow]);
138139 }
139140 assert (this ->row_index_ .size () == 0 );
140141 for (HighsInt iRow = 0 ; iRow < lp.num_row_ ; iRow++) {
@@ -784,17 +785,25 @@ HighsStatus HighsIis::compute(const HighsLp& lp, const HighsOptions& options,
784785 return HighsStatus::kOk ;
785786}
786787
788+ bool lpDataOkReturn (const bool return_value) { return return_value; }
789+
787790bool HighsIis::lpDataOk (const HighsLp& lp, const HighsOptions& options) const {
788791 const HighsLp& iis_lp = this ->model_ .lp_ ;
789792 HighsInt iis_num_col = this ->col_index_ .size ();
790793 HighsInt iis_num_row = this ->row_index_ .size ();
791- if (!(iis_lp.num_col_ == iis_num_col)) return false ;
792- if (!(iis_lp.num_row_ == iis_num_row)) return false ;
794+ if (!(iis_lp.num_col_ == iis_num_col)) return lpDataOkReturn ( false ) ;
795+ if (!(iis_lp.num_row_ == iis_num_row)) return lpDataOkReturn ( false ) ;
793796
794797 const bool colwise = lp.a_matrix_ .isColwise ();
795798
799+ const HighsInt illegal_index = -1 ;
800+ const double illegal_value = kHighsInf ;
801+ // iis_row/col give the row/col in the IIS for each row/col in the
802+ // LP, or an illegal index if the LP row/col isn't in the IIS
796803 std::vector<HighsInt> iis_row;
797- iis_row.assign (lp.num_row_ , -1 );
804+ iis_row.assign (lp.num_row_ , illegal_index);
805+ std::vector<HighsInt> iis_col;
806+ iis_col.assign (lp.num_col_ , illegal_index);
798807 double bound;
799808 for (HighsInt iisRow = 0 ; iisRow < iis_num_row; iisRow++) {
800809 HighsInt iRow = this ->row_index_ [iisRow];
@@ -804,32 +813,31 @@ bool HighsIis::lpDataOk(const HighsLp& lp, const HighsOptions& options) const {
804813 row_bound == kIisBoundStatusLower || row_bound == kIisBoundStatusBoxed
805814 ? lp.row_lower_ [iRow]
806815 : -kHighsInf ;
807- if (iis_lp.row_lower_ [iisRow] != bound) return false ;
816+ if (iis_lp.row_lower_ [iisRow] != bound) return lpDataOkReturn ( false ) ;
808817 bound =
809818 row_bound == kIisBoundStatusUpper || row_bound == kIisBoundStatusBoxed
810819 ? lp.row_upper_ [iRow]
811820 : kHighsInf ;
812- if (iis_lp.row_upper_ [iisRow] != bound) return false ;
821+ if (iis_lp.row_upper_ [iisRow] != bound) return lpDataOkReturn ( false ) ;
813822 }
814823
815824 // Work through the LP columns checking the zero costs and bounds
816825 for (HighsInt iisCol = 0 ; iisCol < iis_num_col; iisCol++) {
817826 HighsInt iCol = this ->col_index_ [iisCol];
818- if (iis_lp.col_cost_ [iisCol]) return false ;
827+ iis_col[iCol] = iisCol;
828+ if (iis_lp.col_cost_ [iisCol]) return lpDataOkReturn (false );
819829 HighsInt col_bound = this ->col_bound_ [iisCol];
820830 bound =
821831 col_bound == kIisBoundStatusLower || col_bound == kIisBoundStatusBoxed
822832 ? lp.col_lower_ [iCol]
823833 : -kHighsInf ;
824- if (iis_lp.col_lower_ [iisCol] != bound) return false ;
834+ if (iis_lp.col_lower_ [iisCol] != bound) return lpDataOkReturn ( false ) ;
825835 bound =
826836 col_bound == kIisBoundStatusUpper || col_bound == kIisBoundStatusBoxed
827837 ? lp.col_upper_ [iCol]
828838 : kHighsInf ;
829- if (iis_lp.col_upper_ [iisCol] != bound) return false ;
839+ if (iis_lp.col_upper_ [iisCol] != bound) return lpDataOkReturn ( false ) ;
830840 }
831- const HighsInt illegal_index = -1 ;
832- const double illegal_value = kHighsInf ;
833841 std::vector<HighsInt> index;
834842 std::vector<double > value;
835843 // Work through the LP matrix, checking the matrix index/value
@@ -851,8 +859,9 @@ bool HighsIis::lpDataOk(const HighsLp& lp, const HighsOptions& options) const {
851859 HighsInt iRow = lp.a_matrix_ .index_ [iEl];
852860 HighsInt iisRow = iis_row[iRow];
853861 if (iisRow >= 0 ) {
854- if (index[iisRow] != iRow) return false ;
855- if (value[iisRow] != lp.a_matrix_ .value_ [iEl]) return false ;
862+ if (index[iisRow] != iRow) return lpDataOkReturn (false );
863+ if (value[iisRow] != lp.a_matrix_ .value_ [iEl])
864+ return lpDataOkReturn (false );
856865 index[iisRow] = illegal_index;
857866 value[iisRow] = illegal_value;
858867 }
@@ -862,22 +871,23 @@ bool HighsIis::lpDataOk(const HighsLp& lp, const HighsOptions& options) const {
862871 for (HighsInt iisRow = 0 ; iisRow < iis_num_row; iisRow++) {
863872 HighsInt iRow = this ->row_index_ [iisRow];
864873 // Use index/value to scatter the IIS matrix row
865- index.assign (iis_num_row , illegal_index);
866- value.assign (iis_num_row , illegal_value);
874+ index.assign (iis_num_col , illegal_index);
875+ value.assign (iis_num_col , illegal_value);
867876 for (HighsInt iEl = iis_lp.a_matrix_ .start_ [iisRow];
868877 iEl < iis_lp.a_matrix_ .start_ [iisRow + 1 ]; iEl++) {
869878 HighsInt iisCol = iis_lp.a_matrix_ .index_ [iEl];
870- HighsInt iCol = this ->row_index_ [iisCol];
879+ HighsInt iCol = this ->col_index_ [iisCol];
871880 index[iisCol] = iCol;
872881 value[iisCol] = iis_lp.a_matrix_ .value_ [iEl];
873882 }
874883 for (HighsInt iEl = lp.a_matrix_ .start_ [iRow];
875884 iEl < lp.a_matrix_ .start_ [iRow + 1 ]; iEl++) {
876885 HighsInt iCol = lp.a_matrix_ .index_ [iEl];
877- HighsInt iisCol = iis_row [iCol];
886+ HighsInt iisCol = iis_col [iCol];
878887 if (iisCol >= 0 ) {
879- if (index[iisCol] != iCol) return false ;
880- if (value[iisCol] != lp.a_matrix_ .value_ [iEl]) return false ;
888+ if (index[iisCol] != iCol) return lpDataOkReturn (false );
889+ if (value[iisCol] != lp.a_matrix_ .value_ [iEl])
890+ return lpDataOkReturn (false );
881891 index[iisCol] = illegal_index;
882892 value[iisCol] = illegal_value;
883893 }
@@ -903,35 +913,39 @@ bool HighsIis::lpDataOk(const HighsLp& lp, const HighsOptions& options) const {
903913 iEl < iis_lp.a_matrix_ .start_ [iisCol + 1 ]; iEl++) {
904914 HighsInt iisRow = iis_lp.a_matrix_ .index_ [iEl];
905915 HighsInt iRow = this ->row_index_ [iisRow];
906- if (index[iRow] != iisRow) return false ;
907- if (value[iRow] != iis_lp.a_matrix_ .value_ [iEl]) return false ;
916+ if (index[iRow] != iisRow) return lpDataOkReturn (false );
917+ if (value[iRow] != iis_lp.a_matrix_ .value_ [iEl])
918+ return lpDataOkReturn (false );
908919 }
909920 }
910921 } else {
911922 for (HighsInt iisRow = 0 ; iisRow < iis_num_row; iisRow++) {
912923 HighsInt iRow = this ->row_index_ [iisRow];
913924 // Use index/value to scatter the LP matrix row
914- index.assign (lp.num_row_ , illegal_index);
915- value.assign (lp.num_row_ , illegal_value);
925+ index.assign (lp.num_col_ , illegal_index);
926+ value.assign (lp.num_col_ , illegal_value);
916927 for (HighsInt iEl = lp.a_matrix_ .start_ [iRow];
917928 iEl < lp.a_matrix_ .start_ [iRow + 1 ]; iEl++) {
918929 HighsInt iCol = lp.a_matrix_ .index_ [iEl];
919- HighsInt iisCol = iis_row [iCol];
930+ HighsInt iisCol = iis_col [iCol];
920931 index[iCol] = iisCol;
921932 value[iCol] = lp.a_matrix_ .value_ [iEl];
922933 }
923934 for (HighsInt iEl = iis_lp.a_matrix_ .start_ [iisRow];
924935 iEl < iis_lp.a_matrix_ .start_ [iisRow + 1 ]; iEl++) {
925936 HighsInt iisCol = iis_lp.a_matrix_ .index_ [iEl];
926- HighsInt iCol = this ->row_index_ [iisCol];
927- if (index[iCol] != iisCol) return false ;
928- if (value[iCol] != iis_lp.a_matrix_ .value_ [iEl]) return false ;
937+ HighsInt iCol = this ->col_index_ [iisCol];
938+ if (index[iCol] != iisCol) return lpDataOkReturn (false );
939+ if (value[iCol] != iis_lp.a_matrix_ .value_ [iEl])
940+ return lpDataOkReturn (false );
929941 }
930942 }
931943 }
932- return true ;
944+ return lpDataOkReturn ( true ) ;
933945}
934946
947+ bool lpOkReturn (const bool return_value) { return return_value; }
948+
935949bool HighsIis::lpOk (const HighsOptions& options) const {
936950 // Check that the IIS LP is OK (infeasible and optimal if
937951 // any bound is relaxed)
@@ -955,7 +969,7 @@ bool HighsIis::lpOk(const HighsOptions& options) const {
955969 if (h.getModelStatus () != HighsModelStatus::kInfeasible ) {
956970 highsLogUser (log_options, HighsLogType::kError ,
957971 " HighsIis: IIS LP is not infeasible\n " );
958- return false ;
972+ return lpOkReturn ( false ) ;
959973 }
960974 auto optimal = [&]() -> bool {
961975 if (options.log_dev_level > 0 ) h.writeModel (" " );
@@ -972,7 +986,7 @@ bool HighsIis::lpOk(const HighsOptions& options) const {
972986 " bound of %g yield IIS LP with status %s\n " ,
973987 int (iisCol), int (iCol), iis_lp.col_lower_ [iisCol],
974988 h.modelStatusToString (h.getModelStatus ()).c_str ());
975- return false ;
989+ return lpOkReturn ( false ) ;
976990 }
977991 h.changeColBounds (iisCol, iis_lp.col_lower_ [iisCol],
978992 iis_lp.col_upper_ [iisCol]);
@@ -985,7 +999,7 @@ bool HighsIis::lpOk(const HighsOptions& options) const {
985999 " bound of %g yield IIS LP with status %s\n " ,
9861000 int (iisCol), int (iCol), iis_lp.col_upper_ [iisCol],
9871001 h.modelStatusToString (h.getModelStatus ()).c_str ());
988- return false ;
1002+ return lpOkReturn ( false ) ;
9891003 }
9901004 h.changeColBounds (iisCol, iis_lp.col_lower_ [iisCol],
9911005 iis_lp.col_upper_ [iisCol]);
@@ -1001,7 +1015,7 @@ bool HighsIis::lpOk(const HighsOptions& options) const {
10011015 " of %g yield IIS LP with status %s\n " ,
10021016 int (iisRow), int (iRow), iis_lp.row_lower_ [iisRow],
10031017 h.modelStatusToString (h.getModelStatus ()).c_str ());
1004- return false ;
1018+ return lpOkReturn ( false ) ;
10051019 }
10061020 h.changeRowBounds (iisRow, iis_lp.row_lower_ [iisRow],
10071021 iis_lp.row_upper_ [iisRow]);
@@ -1010,15 +1024,15 @@ bool HighsIis::lpOk(const HighsOptions& options) const {
10101024 h.changeRowBounds (iisRow, iis_lp.row_lower_ [iisRow], kHighsInf );
10111025 if (!optimal ()) {
10121026 highsLogUser (log_options, HighsLogType::kError ,
1013- " HighsIis: IIS rowumn %d (LP rowumn %d): relaxing upper "
1027+ " HighsIis: IIS row %d (LP row %d): relaxing upper "
10141028 " bound of %g yield IIS LP with status %s\n " ,
10151029 int (iisRow), int (iRow), iis_lp.row_upper_ [iisRow],
10161030 h.modelStatusToString (h.getModelStatus ()).c_str ());
1017- return false ;
1031+ return lpOkReturn ( false ) ;
10181032 }
10191033 h.changeRowBounds (iisRow, iis_lp.row_lower_ [iisRow],
10201034 iis_lp.row_upper_ [iisRow]);
10211035 }
10221036 }
1023- return true ;
1037+ return lpOkReturn ( true ) ;
10241038}
0 commit comments