Skip to content

Commit 6188114

Browse files
committed
Add additional documentation
1 parent c782d75 commit 6188114

File tree

2 files changed

+49
-2
lines changed

2 files changed

+49
-2
lines changed

highs/mip/HighsCutGeneration.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1588,6 +1588,7 @@ bool HighsCutGeneration::preprocessSNFRelaxation() {
15881588
// numerical troubles, use bound constraints to cancel them and
15891589
// reject base inequalities where that is not possible due to unbounded
15901590
// variables
1591+
// 4. Don't consider any inequality with too many non-zeros
15911592

15921593
HighsInt numZeros = 0;
15931594
double maxact = -feastol;

highs/mip/HighsTransformedLp.cpp

Lines changed: 48 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -565,7 +565,7 @@ bool HighsTransformedLp::untransform(std::vector<double>& vals,
565565
// Create a single node flow relaxation (SNFR) from an aggregated
566566
// mixed-integer row and find a valid flow cover.
567567
// Turn \sum c_i x_i + \sum a_i y_i <= a_0 (x_i binary, y_i real non-neg)
568-
// into \sum_{j \in N+} y_j - \sum_{j \in N-} y_j <= b, where y_j <= u_j x_j
568+
// into \sum_{j \in N+} y'_j - \sum_{j \in N-} y'_j <= b, where y'_j <= u_j x_j
569569
bool HighsTransformedLp::transformSNFRelaxation(
570570
std::vector<HighsInt>& inds, std::vector<double>& vals, double& rhs,
571571
HighsCutGeneration::SNFRelaxation& snfr) {
@@ -626,6 +626,26 @@ bool HighsTransformedLp::transformSNFRelaxation(
626626
auto checkValidityVB = [&](HighsInt bincol, HighsImplications::VarBound vb,
627627
double coef, double origbincoef, double lb,
628628
double ub, bool isVub) {
629+
// a_j coefficient of y_j in row. c_j coefficient of x_j in row.
630+
// u_j, l_j, closest simple bounds imposed on y_j.
631+
// y_j <= l'_j x_j + d_j || y_j >= u'_j x_j + d_j
632+
// variable bound can only be used if following properties respected:
633+
// |l'_j| <= 1e6 && |u'_j| <= 1e6
634+
// if a_j > 0
635+
// !isVub: (1) u_j <= d_j
636+
// (2) a_j (u_j - d_j) + c_j <= 0
637+
// (3) a_j l'_j + c_j <= 0
638+
// isVub: (1) l_j >= d_j
639+
// (2) a_j (l_j - d_j) + c_j >= 0
640+
// (3) a_j u'_j + c_j >= 0
641+
// if a_j < 0
642+
// !isVub: (1) u_j <= d_j
643+
// (2) a_j (u_j - d_j) + c_j >= 0
644+
// (3) a_j l'_j + c_j >= 0
645+
// isVub: (1) l_j >= d_j
646+
// (2) a_j (l_j - d_j) + c_j <= 0
647+
// (3) a_j u'_j + c_j <= 0
648+
// Note: c_j may change during transform if two columns use same bin col
629649
if (bincol == -1) return false;
630650
if (abs(vb.coef) >= 1e+6) return false;
631651
if (isVub && lb < vb.constant) return false;
@@ -664,7 +684,8 @@ bool HighsTransformedLp::transformSNFRelaxation(
664684
snfr.numNnzs++;
665685
};
666686

667-
// Place the non-binary variables to the front (all general ints relaxed)
687+
// Place the non-binary columns to the front (all general ints relaxed)
688+
// Use vectorsum to track original row coefficients of binary columns.
668689
HighsInt i = 0;
669690
while (i < numNz - numBinCols) {
670691
HighsInt col = inds[i];
@@ -737,6 +758,7 @@ bool HighsTransformedLp::transformSNFRelaxation(
737758

738759
// Transform entry into the SNFR
739760
if (colIsBinary(col, lb, ub)) {
761+
// Binary columns can be added directly to the SNFR
740762
if (vals[i] >= 0) {
741763
addSNFRentry(col, -1, getLpSolution(col),
742764
getLpSolution(col) * vals[i], 1, vals[i], 0, vals[i], 0);
@@ -746,6 +768,7 @@ bool HighsTransformedLp::transformSNFRelaxation(
746768
0);
747769
}
748770
} else {
771+
// Decide whether to use {simple, variable} {lower, upper} bound
749772
if (lbDist[col] < ubDist[col] - mip.mipdata_->feastol) {
750773
if (!checkValidityVB(bestVlb[col].first, bestVlb[col].second, vals[i],
751774
vectorsum.getValue(bestVlb[col].first), lb, ub,
@@ -789,6 +812,10 @@ bool HighsTransformedLp::transformSNFRelaxation(
789812
HighsInt vbcol;
790813
switch (boundTypes[col]) {
791814
case BoundType::kSimpleLb:
815+
// Case (1) -> a_j > 0, y'_j -> N- Case (2) -> a_j < 0, y'_j ->N+
816+
// (1) y'_j = -a_j(y_j - u_j), 0 <= y'_j <= a_j(u_j - l_j)x_j, x_j = 1
817+
// (2) y'_j = a_j(y_j - u_j), 0 <= y'_j <= -a_j(u_j - l_j)x_j, x_j = 1
818+
// rhs -= a_j * u_j
792819
substsolval = static_cast<double>(
793820
vals[i] * (HighsCDouble(getLpSolution(col)) - ub));
794821
vbcoef = static_cast<double>(vals[i] * (HighsCDouble(ub) - lb));
@@ -803,6 +830,11 @@ bool HighsTransformedLp::transformSNFRelaxation(
803830
tmpSnfrRhs -= aggrconstant;
804831
break;
805832
case BoundType::kSimpleUb:
833+
// Case (1) -> a_j > 0, y'_j -> N+ Case (2) -> a_j < 0, y'_j ->N-
834+
// (1) y'_j = a_j(y_j - l_j), 0 <= y'_j <= a_j(u_j - l_j)x_j, x_j = 1
835+
// (2) y'_j = -a_j(y_j - l_j), 0 <= y'_j <= -a_j(u_j - l_j)x_j,
836+
// x_j = 1
837+
// rhs -= a_j * l_j
806838
substsolval = static_cast<double>(
807839
vals[i] * (HighsCDouble(getLpSolution(col)) - lb));
808840
vbcoef = static_cast<double>(vals[i] * (HighsCDouble(ub) - lb));
@@ -817,6 +849,13 @@ bool HighsTransformedLp::transformSNFRelaxation(
817849
tmpSnfrRhs -= aggrconstant;
818850
break;
819851
case BoundType::kVariableLb:
852+
// vlb: l'_j x_j + d_j <= y_j. c_j is the coefficient of x_j in row
853+
// Case (1) -> a_j > 0, y'_j -> N- Case (2) -> a_j < 0, y'_j ->N+
854+
// (1) y'_j = -(a_j(y_j - d_j) + c_j * x_j),
855+
// 0 <= y'_j <= -(a_j l'_j + c_j)x_j
856+
// (2) y'_j = a_j(y_j - d_j) + c_j * x_j,
857+
// 0 <= y'_j <= (a_j l'_j + c_j)x_j
858+
// rhs -= a_j * d_j
820859
vbcol = bestVlb[col].first;
821860
substsolval = static_cast<double>(
822861
vals[i] * (HighsCDouble(getLpSolution(col)) -
@@ -841,6 +880,13 @@ bool HighsTransformedLp::transformSNFRelaxation(
841880
tmpSnfrRhs -= aggrconstant;
842881
break;
843882
case BoundType::kVariableUb:
883+
// vub: y_j >= u'_j x_j + d_j. c_j is the coefficient of x_j in row
884+
// Case (1) -> a_j > 0, y'_j -> N+ Case (2) -> a_j < 0, y'_j ->N-
885+
// (1) y'_j = a_j(y_j - d_j) + c_j * x_j),
886+
// 0 <= y'_j <= (a_j u'_j + c_j)x_j
887+
// (2) y'_j = -(a_j(y_j - d_j) + c_j * x_j),
888+
// 0 <= y'_j <= -(a_j u'_j + c_j)x_j
889+
// rhs -= a_j * d_j
844890
vbcol = bestVub[col].first;
845891
substsolval = static_cast<double>(
846892
vals[i] * (HighsCDouble(getLpSolution(col)) -

0 commit comments

Comments
 (0)