|
13 | 13 | #include <numeric> |
14 | 14 |
|
15 | 15 | #include "lp_data/HConst.h" |
| 16 | +#include "lp_data/HighsModelUtils.h" // For debugging |
16 | 17 | #include "lp_data/HighsOptions.h" |
17 | 18 | #include "util/HighsCDouble.h" |
18 | 19 | #include "util/HighsUtils.h" |
@@ -1381,42 +1382,54 @@ void HighsPostsolveStack::SlackColSubstitution::undo( |
1381 | 1382 | double(rowValue + colCoef * solution.col_value[col]); |
1382 | 1383 |
|
1383 | 1384 | solution.col_value[col] = double((rhs - rowValue) / colCoef); |
| 1385 | + double rowLower = colCoef > 0 ? rhs - colCoef * slackUpper : rhs - colCoef * slackLower; |
| 1386 | + double rowUpper = colCoef > 0 ? rhs - colCoef * slackLower : rhs - colCoef * slackUpper; |
| 1387 | + |
1384 | 1388 | printf( |
1385 | | - "\nHighsPostsolveStack::SlackColSubstitution::undo rowValue = %g; " |
1386 | | - "colValue = %g\n", |
1387 | | - double(rowValue), solution.col_value[col]); |
| 1389 | + "\nHighsPostsolveStack::SlackColSubstitution::undo rowValue = %11.5g; " |
| 1390 | + "bounds [%11.5g, %11.5g] colCoef = %11.6g\n", |
| 1391 | + double(rowValue), rowLower, rowUpper, colCoef); |
| 1392 | + printf( |
| 1393 | + "HighsPostsolveStack::SlackColSubstitution::undo colValue = %11.5g, bounds [%11.5g, %11.5g]\n", |
| 1394 | + solution.col_value[col], slackLower, slackUpper); |
1388 | 1395 |
|
1389 | | - // if no dual values requested, return here |
| 1396 | + // If no dual values requested, return here |
1390 | 1397 | if (!solution.dual_valid) return; |
1391 | 1398 |
|
1392 | | - // compute the row dual value such that reduced cost of basic column is 0 |
1393 | | - double save_row_dual = solution.row_dual[row]; |
| 1399 | + // Row retains its dual value, and column has this dual value scaled by coeff |
1394 | 1400 | if (isModelRow) { |
1395 | | - solution.row_dual[row] = 0; |
1396 | | - HighsCDouble dualval = HighsCDouble(colCost); |
1397 | | - dualval = -colCoef * solution.row_dual[row]; |
1398 | | - solution.row_dual[row] = double(dualval / colCoef); |
| 1401 | + solution.col_dual[col] = - solution.row_dual[row] / colCoef; |
| 1402 | + printf( |
| 1403 | + "HighsPostsolveStack::SlackColSubstitution::undo rowDual = %11.5g; colDual = %11.5g\n", |
| 1404 | + solution.row_dual[row], solution.col_dual[col]); |
1399 | 1405 | } |
1400 | 1406 |
|
1401 | | - solution.col_dual[col] = 0; |
1402 | | - printf( |
1403 | | - "HighsPostsolveStack::SlackColSubstitution::undo OgRowDual = %g; rowDual " |
1404 | | - "= %g; colDual = %g\n", |
1405 | | - save_row_dual, solution.row_dual[row], solution.col_dual[col]); |
1406 | | - |
1407 | | - // set basis status if necessary |
| 1407 | + // Set basis status if necessary |
1408 | 1408 | if (!basis.valid) return; |
1409 | 1409 |
|
1410 | | - basis.col_status[col] = HighsBasisStatus::kBasic; |
1411 | | - HighsBasisStatus save_row_basis_status = basis.row_status[row]; |
1412 | | - if (isModelRow) |
1413 | | - basis.row_status[row] = |
1414 | | - computeRowStatus(solution.row_dual[row], RowType::kEq); |
1415 | | - printf( |
1416 | | - "HighsPostsolveStack::SlackColSubstitution::undo OgRowStatus = %d; " |
1417 | | - "RowStatus = %d; ColStatus = %d\n", |
1418 | | - int(save_row_basis_status), int(basis.row_status[row]), |
1419 | | - int(basis.col_status[col])); |
| 1410 | + // If row is basic, then slack is basic, otherwise row retains its status |
| 1411 | + if (isModelRow) { |
| 1412 | + HighsBasisStatus save_row_basis_status = basis.row_status[row]; |
| 1413 | + if (basis.row_status[row] == HighsBasisStatus::kBasic) { |
| 1414 | + basis.col_status[col] = HighsBasisStatus::kBasic; |
| 1415 | + basis.row_status[row] = computeRowStatus(solution.row_dual[row], RowType::kEq); |
| 1416 | + } else if (basis.row_status[row] == HighsBasisStatus::kLower) { |
| 1417 | + basis.col_status[col] = colCoef > 0 ? HighsBasisStatus::kUpper : HighsBasisStatus::kLower; |
| 1418 | + } else { |
| 1419 | + basis.col_status[col] = colCoef > 0 ? HighsBasisStatus::kLower : HighsBasisStatus::kUpper; |
| 1420 | + } |
| 1421 | + printf("HighsPostsolveStack::SlackColSubstitution::undo OgRowStatus = %s; " |
| 1422 | + "RowStatus = %s; ColStatus = %s\n", |
| 1423 | + utilBasisStatusToString(save_row_basis_status).c_str(), utilBasisStatusToString(basis.row_status[row]).c_str(), |
| 1424 | + utilBasisStatusToString(basis.col_status[col]).c_str()); |
| 1425 | + if (basis.col_status[col] == HighsBasisStatus::kLower) { |
| 1426 | + assert(solution.col_dual[col] > 0); |
| 1427 | + } else if (basis.col_status[col] == HighsBasisStatus::kUpper) { |
| 1428 | + assert(solution.col_dual[col] < 0); |
| 1429 | + } |
| 1430 | + } else { |
| 1431 | + basis.col_status[col] = HighsBasisStatus::kNonbasic; |
| 1432 | + } |
1420 | 1433 | } |
1421 | 1434 |
|
1422 | 1435 | } // namespace presolve |
0 commit comments