1313
1414namespace hipo {
1515
16- Int Numeric::solve (std::vector<double >& x, Int* solve_count,
17- double * omega) const {
16+ Int Numeric::solve (std::vector<double >& x) const {
1817 // Return the number of solves performed
1918
2019 if (!sn_columns_ || !S_) return kRetInvalidPointer ;
@@ -31,13 +30,8 @@ Int Numeric::solve(std::vector<double>& x, Int* solve_count,
3130#if HIPO_TIMING_LEVEL >= 2
3231 Clock clock_fine{};
3332#endif
34-
3533 // permute rhs
3634 permuteVectorInverse (x, S_->iperm ());
37-
38- // make a copy of permuted rhs, for refinement
39- const std::vector<double > rhs (x);
40-
4135#if HIPO_TIMING_LEVEL >= 2
4236 if (data_) data_->sumTime (kTimeSolvePrepare , clock_fine.stop ());
4337 clock_fine.start ();
@@ -52,16 +46,11 @@ Int Numeric::solve(std::vector<double>& x, Int* solve_count,
5246 if (data_) data_->sumTime (kTimeSolveSolve , clock_fine.stop ());
5347#endif
5448
55- // iterative refinement
56- auto refine_data = refine (rhs, x);
57-
5849#if HIPO_TIMING_LEVEL >= 2
5950 clock_fine.start ();
6051#endif
61-
6252 // unpermute solution
6353 permuteVector (x, S_->iperm ());
64-
6554#if HIPO_TIMING_LEVEL >= 2
6655 if (data_) data_->sumTime (kTimeSolvePrepare , clock_fine.stop ());
6756#endif
@@ -70,168 +59,7 @@ Int Numeric::solve(std::vector<double>& x, Int* solve_count,
7059 if (data_) data_->sumTime (kTimeSolve , clock.stop ());
7160#endif
7261
73- if (solve_count) *solve_count = refine_data.first + 1 ;
74- if (omega) *omega = refine_data.second ;
75-
7662 return kRetOk ;
7763}
7864
79- std::vector<double > Numeric::residual (const std::vector<double >& rhs,
80- const std::vector<double >& x) const {
81- // Compute the residual rhs - A * x - Reg * x
82- std::vector<double > res (rhs);
83- symProduct (ptrA_, rowsA_, valA_, x, res, -1.0 );
84- for (Int i = 0 ; i < x.size (); ++i) res[i] -= total_reg_[i] * x[i];
85-
86- return res;
87- }
88-
89- std::vector<double > Numeric::residualQuad (const std::vector<double >& rhs,
90- const std::vector<double >& x) const {
91- std::vector<HighsCDouble> res (rhs.size ());
92- for (Int i = 0 ; i < rhs.size (); ++i) res[i] = rhs[i];
93-
94- symProductQuad (ptrA_, rowsA_, valA_, x, res, -1.0 );
95-
96- for (Int i = 0 ; i < x.size (); ++i)
97- res[i] -= (HighsCDouble)total_reg_[i] * (HighsCDouble)x[i];
98-
99- std::vector<double > result (res.size ());
100- for (Int i = 0 ; i < res.size (); ++i) {
101- result[i] = (double )res[i];
102- }
103-
104- return result;
105- }
106-
107- std::pair<Int, double > Numeric::refine (const std::vector<double >& rhs,
108- std::vector<double >& x) const {
109- // Return the number of solver performed
110-
111- double old_omega{};
112- Int solves_counter{};
113-
114- #if HIPO_TIMING_LEVEL >= 2
115- Clock clock{};
116- #endif
117-
118- // compute residual
119- std::vector<double > res = residualQuad (rhs, x);
120-
121- #if HIPO_TIMING_LEVEL >= 2
122- if (data_) data_->sumTime (kTimeSolveResidual , clock.stop ());
123- clock.start ();
124- #endif
125-
126- double omega = computeOmega (rhs, x, res);
127-
128- #if HIPO_TIMING_LEVEL >= 2
129- if (data_) data_->sumTime (kTimeSolveOmega , clock.stop ());
130- #endif
131-
132- // if(log_) log_->printDevVerbose(" # start %.2e\n", omega);
133-
134- Int iter = 0 ;
135- for (; iter < kMaxRefinementIter ; ++iter) {
136- // termination criterion
137- if (omega < kRefinementTolerance ) break ;
138-
139- #if HIPO_TIMING_LEVEL >= 2
140- clock.start ();
141- #endif
142-
143- // compute correction
144- SH_->forwardSolve (res);
145- SH_->diagSolve (res);
146- SH_->backwardSolve (res);
147- ++solves_counter;
148-
149- #if HIPO_TIMING_LEVEL >= 2
150- if (data_) data_->sumTime (kTimeSolveSolve , clock.stop ());
151- clock.start ();
152- #endif
153-
154- // add correction
155- std::vector<double > temp (x);
156- vectorAdd (temp, res);
157-
158- #if HIPO_TIMING_LEVEL >= 2
159- if (data_) data_->sumTime (kTimeSolvePrepare , clock.stop ());
160- clock.start ();
161- #endif
162-
163- // compute new residual
164- res = residualQuad (rhs, temp);
165-
166- #if HIPO_TIMING_LEVEL >= 2
167- if (data_) data_->sumTime (kTimeSolveResidual , clock.stop ());
168- clock.start ();
169- #endif
170-
171- old_omega = omega;
172- omega = computeOmega (rhs, temp, res);
173-
174- // if(log_) log_->printDevVerbose(" # refine %.2e\n", omega);
175-
176- #if HIPO_TIMING_LEVEL >= 2
177- if (data_) data_->sumTime (kTimeSolveOmega , clock.stop ());
178- #endif
179-
180- if (omega < old_omega) {
181- x = temp;
182- } else {
183- omega = old_omega;
184- // if(log_) log_->printDevVerbose(" ## reject\n");
185- break ;
186- }
187- }
188-
189- return {solves_counter, omega};
190- }
191-
192- double Numeric::computeOmega (const std::vector<double >& b,
193- const std::vector<double >& x,
194- const std::vector<double >& res) const {
195- // Termination of iterative refinement based on "Solving sparse linear systems
196- // with sparse backward error", Arioli, Demmel, Duff.
197-
198- const Int n = x.size ();
199-
200- // infinity norm of x
201- const double inf_norm_x = infNorm (x);
202-
203- // |A|*|x|
204- std::vector<double > abs_prod (n);
205- for (Int col = 0 ; col < n; ++col) {
206- for (Int el = ptrA_[col]; el < ptrA_[col + 1 ]; ++el) {
207- Int row = rowsA_[el];
208- double val = valA_[el];
209- abs_prod[row] += std::abs (val) * std::abs (x[col]);
210- if (row != col) abs_prod[col] += std::abs (val) * std::abs (x[row]);
211- }
212- }
213-
214- double omega_1{};
215- double omega_2{};
216-
217- for (Int i = 0 ; i < n; ++i) {
218- // threshold 1000 * n * eps * (||Ai|| * ||x|| + |bi|)
219- double tau =
220- 1000.0 * n * 1e-16 * (inf_norm_cols_[i] * inf_norm_x + std::abs (b[i]));
221-
222- if (abs_prod[i] + std::abs (b[i]) > tau) {
223- // case 1, denominator is large enough
224- double omega = std::abs (res[i]) / (abs_prod[i] + std::abs (b[i]));
225- omega_1 = std::max (omega_1, omega);
226- } else {
227- // case 2, denominator would be small, change it
228- double omega =
229- std::abs (res[i]) / (abs_prod[i] + one_norm_cols_[i] * inf_norm_x);
230- omega_2 = std::max (omega_2, omega);
231- }
232- }
233-
234- return omega_1 + omega_2;
235- }
236-
23765} // namespace hipo
0 commit comments