Skip to content

Commit 9c7fa6e

Browse files
committed
wip
2 parents 16275c1 + 5a4b356 commit 9c7fa6e

3 files changed

Lines changed: 81 additions & 19 deletions

File tree

highs/pdlp/hipdlp/pdhg.cc

Lines changed: 29 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -645,7 +645,6 @@ if (DEBUG_MODE){
645645
}
646646

647647
CUDA_CHECK(cudaGraphLaunch(graphExec, gpu_stream_));
648-
CUDA_CHECK(cudaStreamSynchronize(gpu_stream_));
649648
#else
650649
for (int i = 2; i <= PDHG_CHECK_INTERVAL - 1; i++) {
651650
performHalpernPdhgStep(false, i);
@@ -1362,7 +1361,8 @@ double PDLPSolver::computePrimalFeasibility(
13621361
}
13631362
}
13641363

1365-
return linalg::vectorNorm(primal_residual);
1364+
return linalg::vectorNorm(primal_residual) /
1365+
scaling_.getConstraintBoundScaling();
13661366
}
13671367

13681368
void PDLPSolver::computeDualSlacks(const std::vector<double>& dualResidual,
@@ -1448,7 +1448,8 @@ double PDLPSolver::computeDualFeasibility(const std::vector<double>& ATy_vector,
14481448
}
14491449
}
14501450

1451-
double dual_feasibility = linalg::vectorNorm(dual_residual);
1451+
double dual_feasibility = linalg::vectorNorm(dual_residual) /
1452+
scaling_.getObjectiveVectorScaling();
14521453

14531454
return dual_feasibility;
14541455
}
@@ -1493,7 +1494,7 @@ PDLPSolver::computeDualityGap(const std::vector<double>& x,
14931494
double PDLPSolver::computeDualObjective(const std::vector<double>& y,
14941495
const std::vector<double>& dSlackPos,
14951496
const std::vector<double>& dSlackNeg) {
1496-
double dual_obj = lp_.offset_;
1497+
double dual_obj = 0.0;
14971498

14981499
// Compute b'y (or rhs'y in cuPDLP notation)
14991500
for (HighsInt i = 0; i < lp_.num_row_; ++i) {
@@ -1514,7 +1515,10 @@ double PDLPSolver::computeDualObjective(const std::vector<double>& y,
15141515
}
15151516
}
15161517

1517-
return dual_obj;
1518+
return dual_obj /
1519+
(scaling_.getConstraintBoundScaling() *
1520+
scaling_.getObjectiveVectorScaling()) +
1521+
lp_.offset_;
15181522
}
15191523

15201524
bool PDLPSolver::checkConvergence(
@@ -1537,27 +1541,31 @@ bool PDLPSolver::checkConvergence(
15371541
results.dual_feasibility = dual_feasibility;
15381542

15391543
// Compute objectives
1540-
double primal_obj = lp_.offset_;
1544+
double primal_obj = 0.0;
15411545
for (HighsInt i = 0; i < lp_.num_col_; ++i) {
15421546
primal_obj += lp_.col_cost_[i] * x[i];
15431547
}
1544-
results.primal_obj = primal_obj;
1548+
primal_obj /=
1549+
scaling_.getConstraintBoundScaling() *
1550+
scaling_.getObjectiveVectorScaling();
1551+
results.primal_obj = primal_obj + lp_.offset_;
15451552

15461553
// Pass the now-populated slack vectors to computeDualObjective
15471554
double dual_obj = computeDualObjective(y, dSlackPos, dSlackNeg);
15481555
results.dual_obj = dual_obj;
15491556

15501557
// Compute duality gap
1551-
double duality_gap = primal_obj - dual_obj;
1558+
double duality_gap = results.primal_obj - dual_obj;
15521559
results.duality_gap = std::abs(duality_gap);
15531560

15541561
// Compute relative gap (matching cuPDLP formula)
15551562
double relative_obj_gap =
1556-
std::abs(duality_gap) / (1.0 + std::abs(primal_obj) + std::abs(dual_obj));
1563+
std::abs(duality_gap) /
1564+
(1.0 + std::abs(results.primal_obj) + std::abs(dual_obj));
15571565
results.relative_obj_gap = relative_obj_gap;
15581566

15591567
#if PDLP_DEBUG_LOG
1560-
debugPdlpFeasOptLog(debug_pdlp_log_file_, iter, primal_obj, dual_obj,
1568+
debugPdlpFeasOptLog(debug_pdlp_log_file_, iter, results.primal_obj, dual_obj,
15611569
relative_obj_gap,
15621570
primal_feasibility / (1.0 + unscaled_rhs_norm_),
15631571
dual_feasibility / (1.0 + unscaled_c_norm_), type);
@@ -1936,10 +1944,11 @@ void PDLPSolver::unscaleSolution(std::vector<double>& x,
19361944
y_current_ = y;
19371945

19381946
const std::vector<double>& col_scale = scaling_.getColScaling();
1947+
const double objective_scale = scaling_.getObjectiveVectorScaling();
19391948
if (!dSlackPos_.empty() && col_scale.size() == dSlackPos_.size()) {
19401949
for (size_t i = 0; i < dSlackPos_.size(); ++i) {
1941-
dSlackPos_[i] *= col_scale[i];
1942-
dSlackNeg_[i] *= col_scale[i];
1950+
dSlackPos_[i] *= col_scale[i] / objective_scale;
1951+
dSlackNeg_[i] *= col_scale[i] / objective_scale;
19431952
}
19441953
}
19451954
}
@@ -1994,7 +2003,7 @@ void PDLPSolver::initializeStepSizes() {
19942003
best_primal_weight_ = primal_weight_;
19952004
stepsize_.beta = primal_weight_ * primal_weight_;
19962005
params_.omega = primal_weight_;
1997-
2006+
19982007
if (params_.step_size_strategy != StepSizeStrategy::FIXED &&
19992008
params_.step_size_strategy != StepSizeStrategy::PID) {
20002009
logger_.info(
@@ -2828,13 +2837,16 @@ bool PDLPSolver::checkConvergenceGpu(const HighsInt iter, const double* d_x,
28282837
cudaMemcpyDeviceToHost, gpu_stream_));
28292838
CUDA_CHECK(cudaStreamSynchronize(gpu_stream_));
28302839

2840+
const double constraint_scale = scaling_.getConstraintBoundScaling();
2841+
const double objective_scale = scaling_.getObjectiveVectorScaling();
2842+
const double combined_scale = constraint_scale * objective_scale;
28312843
double primal_feas_sq = h_results[0];
28322844
double dual_feas_sq = h_results[1];
2833-
double primal_obj = h_results[2] + lp_.offset_;
2834-
double dual_obj = h_results[3] + lp_.offset_;
2845+
double primal_obj = h_results[2] / combined_scale + lp_.offset_;
2846+
double dual_obj = h_results[3] / combined_scale + lp_.offset_;
28352847

2836-
results.primal_feasibility = std::sqrt(primal_feas_sq);
2837-
results.dual_feasibility = std::sqrt(dual_feas_sq);
2848+
results.primal_feasibility = std::sqrt(primal_feas_sq) / constraint_scale;
2849+
results.dual_feasibility = std::sqrt(dual_feas_sq) / objective_scale;
28382850
results.primal_obj = primal_obj;
28392851
results.dual_obj = dual_obj;
28402852

highs/pdlp/hipdlp/scaling.cc

Lines changed: 47 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ void Scaling::initialize(const HighsLp& lp) {
2222
col_scale_.assign(lp.num_col_, 1.0);
2323
row_scale_.assign(lp.num_row_, 1.0);
2424
is_scaled_ = false;
25+
constraint_bound_scale_ = 1.0;
26+
objective_vector_scale_ = 1.0;
2527

2628
// use linalg to compute norms
2729
norm_cost_ = linalg::computeCostNorm(lp, 2.0);
@@ -51,6 +53,10 @@ void Scaling::scaleProblem() {
5153
applyL2Scaling();
5254
is_scaled_ = true;
5355
}
56+
57+
highsLogDev(params_->log_options_, HighsLogType::kInfo,
58+
"Applying bound-objective scaling...\n");
59+
applyBoundObjectiveScaling();
5460
}
5561

5662
void Scaling::applyRuizScaling() {
@@ -228,6 +234,45 @@ void Scaling::applyL2Scaling() {
228234
}
229235
}
230236

237+
void Scaling::applyBoundObjectiveScaling() {
238+
double rhs_norm_sq = 0.0;
239+
for (HighsInt i = 0; i < lp_->num_row_; ++i) {
240+
const double lower = lp_->row_lower_[i];
241+
const double upper = lp_->row_upper_[i];
242+
if (std::isfinite(lower) && lower != upper) rhs_norm_sq += lower * lower;
243+
if (std::isfinite(upper)) rhs_norm_sq += upper * upper;
244+
}
245+
246+
const double rhs_norm = std::sqrt(rhs_norm_sq);
247+
const double obj_norm = computeNorm(lp_->col_cost_.data(), lp_->num_col_, 2.0);
248+
249+
constraint_bound_scale_ = 1.0 / (1.0 + rhs_norm);
250+
objective_vector_scale_ = 1.0 / (1.0 + obj_norm);
251+
252+
for (HighsInt i = 0; i < lp_->num_row_; ++i) {
253+
if (lp_->row_lower_[i] > -kHighsInf) {
254+
lp_->row_lower_[i] *= constraint_bound_scale_;
255+
}
256+
if (lp_->row_upper_[i] < kHighsInf) {
257+
lp_->row_upper_[i] *= constraint_bound_scale_;
258+
}
259+
}
260+
261+
for (HighsInt i = 0; i < lp_->num_col_; ++i) {
262+
lp_->col_cost_[i] *= objective_vector_scale_;
263+
if (lp_->col_lower_[i] > -kHighsInf) {
264+
lp_->col_lower_[i] *= constraint_bound_scale_;
265+
}
266+
if (lp_->col_upper_[i] < kHighsInf) {
267+
lp_->col_upper_[i] *= constraint_bound_scale_;
268+
}
269+
}
270+
271+
if (constraint_bound_scale_ != 1.0 || objective_vector_scale_ != 1.0) {
272+
is_scaled_ = true;
273+
}
274+
}
275+
231276
void Scaling::applyScaling(const std::vector<double>& col_scaling,
232277
const std::vector<double>& row_scaling) {
233278
// Scale cost vector: c_scaled = c / col_scaling
@@ -273,12 +318,12 @@ void Scaling::unscaleSolution(std::vector<double>& x,
273318

274319
// Unscale primal variables: x_original = x_scaled / col_scale
275320
for (size_t i = 0; i < x.size(); ++i) {
276-
x[i] /= col_scale_[i];
321+
x[i] /= (col_scale_[i] * constraint_bound_scale_);
277322
}
278323

279324
// Unscale dual variables: y_original = y_scaled / row_scale
280325
for (size_t i = 0; i < y.size(); ++i) {
281-
y[i] /= row_scale_[i];
326+
y[i] /= (row_scale_[i] * objective_vector_scale_);
282327
}
283328
}
284329

highs/pdlp/hipdlp/scaling.hpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,8 @@ class Scaling {
4141
bool isScaled() const { return is_scaled_; }
4242
const std::vector<double>& getColScaling() const { return col_scale_; }
4343
const std::vector<double>& getRowScaling() const { return row_scale_; }
44+
double getConstraintBoundScaling() const { return constraint_bound_scale_; }
45+
double getObjectiveVectorScaling() const { return objective_vector_scale_; }
4446

4547
double getNormCost() const { return norm_cost_; }
4648
double getNormRhs() const { return norm_rhs_; }
@@ -51,6 +53,8 @@ class Scaling {
5153
std::vector<double> col_scale_;
5254
std::vector<double> row_scale_;
5355
bool is_scaled_ = false;
56+
double constraint_bound_scale_ = 1.0;
57+
double objective_vector_scale_ = 1.0;
5458

5559
double norm_cost_;
5660
double norm_rhs_;
@@ -59,6 +63,7 @@ class Scaling {
5963
void applyRuizScaling();
6064
void applyPockChambolleScaling();
6165
void applyL2Scaling();
66+
void applyBoundObjectiveScaling();
6267

6368
// Helper function to apply scaling factors to the problem
6469
void applyScaling(const std::vector<double>& col_scaling,

0 commit comments

Comments
 (0)