Skip to content

Commit 5353cad

Browse files
committed
Corrected IIS LP generation and checking when incumbent LP is stored rowwise; corrected some HiGHS typos elsewhere; formatted
1 parent ebf25a4 commit 5353cad

File tree

3 files changed

+55
-41
lines changed

3 files changed

+55
-41
lines changed

highs/lp_data/HighsIis.cpp

Lines changed: 52 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -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+
787790
bool 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+
935949
bool 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
}

highs/util/HFactorRefactor.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -185,7 +185,7 @@ HighsInt HFactor::rebuild(HighsTimerClock* factor_timer_clock_pointer) {
185185
//
186186
// First of all complete the L factor with identity columns so
187187
// that FtranL counts the RHS entries in rows that don't yet have
188-
// picots by running to completion. In the hyper-sparse code,
188+
// pivots by running to completion. In the hyper-sparse code,
189189
// these will HOPEFULLY be skipped
190190
//
191191
// There are already l_start entries for the first stage rows, but

highs/util/HighsSparseMatrix.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -890,12 +890,12 @@ void HighsSparseMatrix::considerRowScaling(
890890
row_scale_value =
891891
min(max(min_allow_row_scale, row_scale_value), max_allow_row_scale);
892892
row_scale[iRow] = row_scale_value;
893-
// Scale the rowumn
893+
// Scale the row
894894
for (HighsInt iEl = this->start_[iRow]; iEl < this->start_[iRow + 1];
895895
iEl++)
896896
this->value_[iEl] *= row_scale[iRow];
897897
} else {
898-
// Empty rowumn
898+
// Empty row
899899
row_scale[iRow] = 1;
900900
}
901901
}

0 commit comments

Comments
 (0)