diff --git a/cmake/sources-python.cmake b/cmake/sources-python.cmake index 2002418225..3d6b3ea684 100644 --- a/cmake/sources-python.cmake +++ b/cmake/sources-python.cmake @@ -369,6 +369,7 @@ set(highs_headers_python src/qpsolver/devexpricing.hpp src/qpsolver/eventhandler.hpp src/qpsolver/factor.hpp + src/qpsolver/feasibility_bounded.hpp src/qpsolver/feasibility_highs.hpp src/qpsolver/feasibility_quass.hpp src/qpsolver/feasibility.hpp diff --git a/cmake/sources.cmake b/cmake/sources.cmake index cdf1096991..f8011b86f1 100644 --- a/cmake/sources.cmake +++ b/cmake/sources.cmake @@ -372,6 +372,7 @@ set(highs_headers qpsolver/devexpricing.hpp qpsolver/eventhandler.hpp qpsolver/factor.hpp + qpsolver/feasibility_bounded.hpp qpsolver/feasibility_highs.hpp qpsolver/feasibility_quass.hpp qpsolver/feasibility.hpp diff --git a/src/lp_data/Highs.cpp b/src/lp_data/Highs.cpp index 3acf7a760f..482ab3f47c 100644 --- a/src/lp_data/Highs.cpp +++ b/src/lp_data/Highs.cpp @@ -3462,6 +3462,20 @@ HighsStatus Highs::callSolveQp() { settings.iterationlimit = options_.simplex_iteration_limit; settings.lambda_zero_threshold = options_.dual_feasibility_tolerance; + switch (options_.simplex_primal_edge_weight_strategy) { + case 0: + settings.pricing = PricingStrategy::DantzigWolfe; + break; + case 1: + settings.pricing = PricingStrategy::Devex; + break; + case 2: + settings.pricing = PricingStrategy::SteepestEdge; + break; + default: + settings.pricing = PricingStrategy::Devex; + } + // print header for QP solver output highsLogUser(options_.log_options, HighsLogType::kInfo, "Iteration, Runtime, ObjVal, NullspaceDim\n"); diff --git a/src/qpsolver/a_asm.cpp b/src/qpsolver/a_asm.cpp index cd48273cde..6a289aad97 100644 --- a/src/qpsolver/a_asm.cpp +++ b/src/qpsolver/a_asm.cpp @@ -2,8 +2,7 @@ #include "qpsolver/quass.hpp" QpAsmStatus solveqp_actual(Instance& instance, Settings& settings, QpHotstartInformation& startinfo, Statistics& stats, QpModelStatus& status, QpSolution& solution, HighsTimer& qp_timer) { - Runtime rt(instance); - rt.statistics = stats; + Runtime rt(instance, stats); rt.settings = settings; Quass quass(rt); diff --git a/src/qpsolver/a_quass.cpp b/src/qpsolver/a_quass.cpp index f89f4506de..06eaa93b0d 100644 --- a/src/qpsolver/a_quass.cpp +++ b/src/qpsolver/a_quass.cpp @@ -2,6 +2,7 @@ #include "qpsolver/a_asm.hpp" #include "qpsolver/feasibility_highs.hpp" +#include "qpsolver/feasibility_bounded.hpp" @@ -26,10 +27,21 @@ QpAsmStatus solveqp(Instance& instance, Settings& settings, Statistics& stats, Q // compute initial feasible point QpHotstartInformation startinfo(instance.num_var, instance.num_con); - computestartingpoint_highs(instance, settings, stats, modelstatus, startinfo, qp_timer); - if (modelstatus == QpModelStatus::INFEASIBLE) { - return QpAsmStatus::OK; - } + if (instance.num_con == 0 && instance.num_var <= 15000) { + computestartingpoint_bounded(instance, settings, stats, modelstatus, startinfo, qp_timer); + if (modelstatus == QpModelStatus::OPTIMAL) { + solution.primal = startinfo.primal; + return QpAsmStatus::OK; + } + if (modelstatus == QpModelStatus::UNBOUNDED) { + return QpAsmStatus::OK; + } + } else { + computestartingpoint_highs(instance, settings, stats, modelstatus, startinfo, qp_timer); + if (modelstatus == QpModelStatus::INFEASIBLE) { + return QpAsmStatus::OK; + } + } // solve QpAsmStatus status = solveqp_actual(instance, settings, startinfo, stats, modelstatus, solution, qp_timer); diff --git a/src/qpsolver/basis.cpp b/src/qpsolver/basis.cpp index 987a5f1caa..24541c2405 100644 --- a/src/qpsolver/basis.cpp +++ b/src/qpsolver/basis.cpp @@ -88,6 +88,7 @@ void Basis::rebuild() { i < activeconstraintidx.size() + nonactiveconstraintsidx.size(); i++) { constraintindexinbasisfactor[baseindex[i]] = i; } + reinversion_hint = false; } void Basis::report() { @@ -166,7 +167,7 @@ void Basis::updatebasis(const Settings& settings, HighsInt newactivecon, HighsIn updatessinceinvert++; if (updatessinceinvert >= settings.reinvertfrequency || hint != 99999) { - rebuild(); + reinversion_hint = true; } // since basis changed, buffered values are no longer valid buffered_p = -1; diff --git a/src/qpsolver/basis.hpp b/src/qpsolver/basis.hpp index aa40ed3dd1..96411bd0dd 100644 --- a/src/qpsolver/basis.hpp +++ b/src/qpsolver/basis.hpp @@ -73,7 +73,6 @@ class Basis { std::vector constraintindexinbasisfactor; void build(); - void rebuild(); // buffer to avoid recreating vectors Vector buffer_column_aq; @@ -85,10 +84,17 @@ class Basis { HVector row_ep; HVector col_aq; + bool reinversion_hint = false; public: + + Basis(Runtime& rt, std::vector active, std::vector atlower, std::vector inactive); + bool getreinversionhint() { return reinversion_hint; } + + void rebuild(); + HighsInt getnupdatessinceinvert() { return updatessinceinvert; } HighsInt getnumactive() const { return activeconstraintidx.size(); }; diff --git a/src/qpsolver/dantzigpricing.hpp b/src/qpsolver/dantzigpricing.hpp index e1f601a387..f043437cea 100644 --- a/src/qpsolver/dantzigpricing.hpp +++ b/src/qpsolver/dantzigpricing.hpp @@ -59,6 +59,10 @@ class DantzigPricing : public Pricing { return minidx; } + void recompute() { + // do nothing + } + void update_weights(const Vector& aq, const Vector& ep, HighsInt p, HighsInt q) { // does nothing diff --git a/src/qpsolver/devexharrispricing.hpp b/src/qpsolver/devexharrispricing.hpp index 3ee854106b..3a9b64126b 100644 --- a/src/qpsolver/devexharrispricing.hpp +++ b/src/qpsolver/devexharrispricing.hpp @@ -63,6 +63,10 @@ class DevexHarrisPricing : public Pricing { return minidx; } + void recompute() { + // do nothing + } + void update_weights(const Vector& aq, const Vector& ep, HighsInt p, HighsInt q) { HighsInt rowindex_p = basis.getindexinfactor()[p]; diff --git a/src/qpsolver/devexpricing.hpp b/src/qpsolver/devexpricing.hpp index 744ca3f726..d3ba6a03dd 100644 --- a/src/qpsolver/devexpricing.hpp +++ b/src/qpsolver/devexpricing.hpp @@ -73,6 +73,10 @@ class DevexPricing : public Pricing { return minidx; } + void recompute() { + // do nothing + } + void update_weights(const Vector& aq, const Vector& ep, HighsInt p, HighsInt q) { HighsInt rowindex_p = basis.getindexinfactor()[p]; diff --git a/src/qpsolver/factor.hpp b/src/qpsolver/factor.hpp index 6892aeeeb0..3df7bff334 100644 --- a/src/qpsolver/factor.hpp +++ b/src/qpsolver/factor.hpp @@ -26,6 +26,33 @@ class CholeskyFactor { bool has_negative_eigenvalue = false; std::vector a; + void resize(HighsInt new_k_max) { + std::vector L_old = L; + L.clear(); + L.resize((new_k_max) * (new_k_max)); + const HighsInt l_size = L.size(); + // Driven by #958, changes made in following lines to avoid array + // bound error when new_k_max < current_k_max + HighsInt min_k_max = min(new_k_max, current_k_max); + for (HighsInt i = 0; i < min_k_max; i++) { + for (HighsInt j = 0; j < min_k_max; j++) { + assert(i * (new_k_max) + j < l_size); + L[i * (new_k_max) + j] = L_old[i * current_k_max + j]; + } + } + current_k_max = new_k_max; + } + + public: + CholeskyFactor(Runtime& rt, Basis& bas) : runtime(rt), basis(bas) { + uptodate = false; + current_k_max = + max(min((HighsInt)ceil(rt.instance.num_var / 16.0), (HighsInt)1000), + basis.getnuminactive()); + L.resize(current_k_max * current_k_max); + } + + void recompute() { std::vector> orig; HighsInt dim_ns = basis.getinactive().size(); @@ -70,32 +97,6 @@ class CholeskyFactor { uptodate = true; } - void resize(HighsInt new_k_max) { - std::vector L_old = L; - L.clear(); - L.resize((new_k_max) * (new_k_max)); - const HighsInt l_size = L.size(); - // Driven by #958, changes made in following lines to avoid array - // bound error when new_k_max < current_k_max - HighsInt min_k_max = min(new_k_max, current_k_max); - for (HighsInt i = 0; i < min_k_max; i++) { - for (HighsInt j = 0; j < min_k_max; j++) { - assert(i * (new_k_max) + j < l_size); - L[i * (new_k_max) + j] = L_old[i * current_k_max + j]; - } - } - current_k_max = new_k_max; - } - - public: - CholeskyFactor(Runtime& rt, Basis& bas) : runtime(rt), basis(bas) { - uptodate = false; - current_k_max = - max(min((HighsInt)ceil(rt.instance.num_var / 16.0), (HighsInt)1000), - basis.getnuminactive()); - L.resize(current_k_max * current_k_max); - } - QpSolverStatus expand(const Vector& yp, Vector& gyp, Vector& l, Vector& m) { if (!uptodate) { return QpSolverStatus::OK; @@ -203,7 +204,7 @@ class CholeskyFactor { } void solve(Vector& rhs) { - if (!uptodate || (numberofreduces >= runtime.instance.num_con / 2 && + if (!uptodate || (numberofreduces >= runtime.instance.num_var / 2 && !has_negative_eigenvalue)) { recompute(); } diff --git a/src/qpsolver/feasibility.hpp b/src/qpsolver/feasibility.hpp index 91265bb97b..e393b3a7ec 100644 --- a/src/qpsolver/feasibility.hpp +++ b/src/qpsolver/feasibility.hpp @@ -3,6 +3,7 @@ #include "runtime.hpp" #include "crashsolution.hpp" +#include "feasibility_bounded.hpp" #include "feasibility_highs.hpp" #include "feasibility_quass.hpp" @@ -16,6 +17,9 @@ void computestartingpoint(Runtime& runtime, QpHotstartInformation& result) { case Phase1Strategy::QUASS: computestartingpoint_quass(runtime, result); break; + case Phase1Strategy::BOUNDED: + computestartingpoint_bounded(runtime.instance, runtime.settings, runtime.statistics, runtime.status, result, qp_timer); + break; } } diff --git a/src/qpsolver/feasibility_bounded.hpp b/src/qpsolver/feasibility_bounded.hpp new file mode 100644 index 0000000000..5aa32d203b --- /dev/null +++ b/src/qpsolver/feasibility_bounded.hpp @@ -0,0 +1,100 @@ +#ifndef __SRC_LIB_FEASIBILITYBOUNDED_HPP__ +#define __SRC_LIB_FEASIBILITYBOUNDED_HPP__ + +#include "Highs.h" +#include "qpsolver/a_asm.hpp" +#include "qpsolver/crashsolution.hpp" + +static void computestartingpoint_bounded(Instance& instance, Settings& settings, Statistics& stats, QpModelStatus& modelstatus, QpHotstartInformation& result, HighsTimer& timer) { + // compute initial feasible point for problems with bounds only (no general linear constraints) + + // compute Qx + c = 0 --> x = Q^-1c + std::vector L; + L.resize(instance.num_var * instance.num_var); + + // compute cholesky factorization of Q + for (size_t col = 0; col < instance.num_var; col++) { + for (size_t idx = instance.Q.mat.start[col]; idx < instance.Q.mat.start[col+1]; idx++) { + double sum = 0; + size_t row = instance.Q.mat.index[idx]; + if (row == col) { + for (size_t k = 0; k < row; k++) + sum += L[k * instance.num_var + row] * L[k * instance.num_var + row]; + L[row * instance.num_var + row] = sqrt(instance.Q.mat.value[idx] - sum); + } else { + for (size_t k = 0; k < row; k++) + sum += (L[k * instance.num_var + col] * L[k * instance.num_var + row]); + L[row * instance.num_var + col] = + (instance.Q.mat.value[idx] - sum) / L[row * instance.num_var + row]; + } + } + } + + // solve for c + Vector res = -instance.c; + for (HighsInt r = 0; r = 0; i--) { + double sum = 0.0; + for (HighsInt j = res.dim - 1; j > i; j--) { + sum += res.value[j] * L[i * instance.num_var + j]; + } + res.value[i] = (res.value[i] - sum) / L[i * instance.num_var + i]; + } + + // project solution to bounds and collect active bounds + Vector x0(instance.num_var); + Vector ra(instance.num_con); + std::vector initialactive; + std::vector initialinactive; + std::vector atlower; + + for (int i=0; i 0.5/settings.hessianregularizationfactor + && instance.var_up[i] == std::numeric_limits::infinity() + && instance.c.value[i] < 0.0) { + modelstatus = QpModelStatus::UNBOUNDED; + return; + } else if (res.value[i] < 0.5/settings.hessianregularizationfactor + && instance.var_lo[i] == std::numeric_limits::infinity() + && instance.c.value[i] > 0.0) { + modelstatus = QpModelStatus::UNBOUNDED; + return; + } else if (res.value[i] <= instance.var_lo[i]) { + res.value[i] = instance.var_lo[i]; + initialactive.push_back(i + instance.num_con); + atlower.push_back(BasisStatus::ActiveAtLower); + } else if (res.value[i] >= instance.var_up[i]) { + res.value[i] = instance.var_up[i]; + initialactive.push_back(i + instance.num_con); + atlower.push_back(BasisStatus::ActiveAtUpper); + } else { + initialinactive.push_back(i + instance.num_con); + } + if (fabs(res.value[i]) > 10E-5) { + x0.value[i] = res.value[i]; + x0.index[x0.num_nz++] = i; + } + } + + // if no bounds are active, solution lies in the interior -> optimal + if (initialactive.size() == 0) { + modelstatus = QpModelStatus::OPTIMAL; + } + + assert((HighsInt)(initialactive.size() + initialinactive.size()) == + instance.num_var); + + result.status = atlower; + result.active = initialactive; + result.inactive = initialinactive; + result.primal = x0; + result.rowact = ra; +} + +#endif diff --git a/src/qpsolver/gradient.hpp b/src/qpsolver/gradient.hpp index fea6a3616e..839c93ced3 100644 --- a/src/qpsolver/gradient.hpp +++ b/src/qpsolver/gradient.hpp @@ -11,6 +11,10 @@ class Gradient { bool uptodate; HighsInt numupdates = 0; + public: + Gradient(Runtime& rt) + : runtime(rt), gradient(Vector(rt.instance.num_var)), uptodate(false) {} + void recompute() { runtime.instance.Q.vec_mat(runtime.primal, gradient); gradient += runtime.instance.c; @@ -18,10 +22,6 @@ class Gradient { numupdates = 0; } - public: - Gradient(Runtime& rt) - : runtime(rt), gradient(Vector(rt.instance.num_var)), uptodate(false) {} - Vector& getGradient() { if (!uptodate || numupdates >= runtime.settings.gradientrecomputefrequency) { diff --git a/src/qpsolver/pricing.hpp b/src/qpsolver/pricing.hpp index 293bc505d0..85fdae3bb4 100644 --- a/src/qpsolver/pricing.hpp +++ b/src/qpsolver/pricing.hpp @@ -8,6 +8,7 @@ class Pricing { virtual HighsInt price(const Vector& x, const Vector& gradient) = 0; virtual void update_weights(const Vector& aq, const Vector& ep, HighsInt p, HighsInt q) = 0; + virtual void recompute() = 0; virtual ~Pricing() {} }; diff --git a/src/qpsolver/quass.cpp b/src/qpsolver/quass.cpp index 91df50f965..cb0d94442d 100644 --- a/src/qpsolver/quass.cpp +++ b/src/qpsolver/quass.cpp @@ -171,6 +171,9 @@ static QpSolverStatus reduce(Runtime& rt, Basis& basis, const HighsInt newactive static std::unique_ptr getPricing(Runtime& runtime, Basis& basis, ReducedCosts& redcosts) { switch (runtime.settings.pricing) { + case PricingStrategy::SteepestEdge: + return std::unique_ptr( + new SteepestEdgePricing(runtime, basis, redcosts)); case PricingStrategy::Devex: return std::unique_ptr( new DevexPricing(runtime, basis, redcosts)); @@ -263,6 +266,20 @@ static double compute_dual_violation(Instance& instance, Vector& primal, Vector& } #endif +bool check_reinvert_due(Basis& basis) { + // reinvert can be triggered by basis + return basis.getreinversionhint(); +} + +void reinvert(Basis& basis, CholeskyFactor& factor, Gradient& grad, ReducedCosts& rc, ReducedGradient& rg, std::unique_ptr& pricing) { + basis.rebuild(); + factor.recompute(); + grad.recompute(); + rc.recompute(); + rg.recompute(); + //pricing->recompute(); +} + void Quass::solve(const Vector& x0, const Vector& ra, Basis& b0, HighsTimer& timer) { //feenableexcept(FE_ALL_EXCEPT & ~FE_INEXACT & ~FE_UNDERFLOW); @@ -299,11 +316,6 @@ void Quass::solve(const Vector& x0, const Vector& ra, Basis& b0, HighsTimer& tim runtime.relaxed_for_ratiotest = ratiotest_relax_instance(runtime); - if (basis.getnuminactive() > 4000) { - printf("nullspace too large %" HIGHSINT_FORMAT "\n", basis.getnuminactive()); - runtime.status = QpModelStatus::LARGE_NULLSPACE; - return; - } bool atfsep = basis.getnumactive() == runtime.instance.num_var; @@ -320,6 +332,12 @@ void Quass::solve(const Vector& x0, const Vector& ra, Basis& b0, HighsTimer& tim break; } + if (basis.getnuminactive() > 4000) { + printf("nullspace too large %" HIGHSINT_FORMAT "\n", basis.getnuminactive()); + runtime.status = QpModelStatus::LARGE_NULLSPACE; + return; + } + // LOGGING if (runtime.statistics.num_iterations % runtime.settings.reportingfequency == @@ -329,6 +347,11 @@ void Quass::solve(const Vector& x0, const Vector& ra, Basis& b0, HighsTimer& tim } runtime.statistics.num_iterations++; + // REINVERSION + if (check_reinvert_due(basis)) { + reinvert(basis, factor, gradient, redcosts, redgrad, pricing); + } + QpSolverStatus status; bool zero_curvature_direction = false; diff --git a/src/qpsolver/reducedcosts.hpp b/src/qpsolver/reducedcosts.hpp index 36a165a4d5..f3286a2c6c 100644 --- a/src/qpsolver/reducedcosts.hpp +++ b/src/qpsolver/reducedcosts.hpp @@ -14,11 +14,6 @@ class ReducedCosts { Vector reducedcosts; bool uptodate; - void recompute() { - basis.ftran(gradient.getGradient(), reducedcosts); - uptodate = true; - } - public: ReducedCosts(Runtime& rt, Basis& bas, Gradient& grad) : basis(bas), @@ -26,6 +21,11 @@ class ReducedCosts { reducedcosts(Vector(rt.instance.num_var)), uptodate(false) {} + void recompute() { + basis.ftran(gradient.getGradient(), reducedcosts); + uptodate = true; + } + Vector& getReducedCosts() { if (!uptodate) { recompute(); diff --git a/src/qpsolver/reducedgradient.hpp b/src/qpsolver/reducedgradient.hpp index 0ddd11f0de..b16c9bfb4a 100644 --- a/src/qpsolver/reducedgradient.hpp +++ b/src/qpsolver/reducedgradient.hpp @@ -11,12 +11,6 @@ class ReducedGradient { Gradient& gradient; Basis& basis; - void recompute() { - rg.dim = basis.getinactive().size(); - basis.Ztprod(gradient.getGradient(), rg); - uptodate = true; - } - public: ReducedGradient(Runtime& rt, Basis& bas, Gradient& grad) : rg(rt.instance.num_var), gradient(grad), basis(bas) {} @@ -28,6 +22,12 @@ class ReducedGradient { return rg; } + void recompute() { + rg.dim = basis.getinactive().size(); + basis.Ztprod(gradient.getGradient(), rg); + uptodate = true; + } + void reduce(const Vector& buffer_d, const HighsInt maxabsd) { if (!uptodate) { return; diff --git a/src/qpsolver/runtime.hpp b/src/qpsolver/runtime.hpp index 3a9cd361e2..9c694ba950 100644 --- a/src/qpsolver/runtime.hpp +++ b/src/qpsolver/runtime.hpp @@ -13,7 +13,7 @@ struct Runtime { Instance scaled; Instance perturbed; Settings settings; - Statistics statistics; + Statistics& statistics; Vector primal; Vector rowactivity; @@ -24,14 +24,15 @@ struct Runtime { std::vector status_var; std::vector status_con; - Runtime(Instance& inst) + Runtime(Instance& inst, Statistics& stats) : instance(inst), primal(Vector(instance.num_var)), rowactivity(Vector(instance.num_con)), dualvar(instance.num_var), dualcon(instance.num_con), status_var(instance.num_var), - status_con(instance.num_con) {} + status_con(instance.num_con), + statistics(stats) {} }; #endif diff --git a/src/qpsolver/settings.hpp b/src/qpsolver/settings.hpp index 9108badf24..5aa8080867 100644 --- a/src/qpsolver/settings.hpp +++ b/src/qpsolver/settings.hpp @@ -6,11 +6,11 @@ enum class RatiotestStrategy { TwoPass, Textbook }; -enum class PricingStrategy { DantzigWolfe, Devex }; +enum class PricingStrategy { SteepestEdge, DantzigWolfe, Devex }; enum class OutputLevel { LIGHT, MEDIUM, HEAVY }; -enum class Phase1Strategy { HIGHS, QUASS }; +enum class Phase1Strategy { HIGHS, QUASS, BOUNDED }; struct Settings { RatiotestStrategy ratiotest = RatiotestStrategy::TwoPass; @@ -36,7 +36,7 @@ struct Settings { HighsInt reportingfequency = 1; Eventhandler endofiterationevent; - HighsInt reinvertfrequency = 100; + HighsInt reinvertfrequency = 1000; HighsInt gradientrecomputefrequency = 100; HighsInt reducedgradientrecomputefrequency = std::numeric_limits::infinity(); diff --git a/src/qpsolver/steepestedgepricing.hpp b/src/qpsolver/steepestedgepricing.hpp index 4c30c692db..6a4fbcd86b 100644 --- a/src/qpsolver/steepestedgepricing.hpp +++ b/src/qpsolver/steepestedgepricing.hpp @@ -56,31 +56,112 @@ class SteepestEdgePricing : public Pricing { : runtime(rt), basis(bas), redcosts(rc), - weights(std::vector(rt.instance.num_var, 1.0)) {}; + weights(std::vector(rt.instance.num_var, 1.0)) { + compute_exact_weights(); + }; HighsInt price(const Vector& x, const Vector& gradient) { HighsInt minidx = chooseconstrainttodrop(redcosts.getReducedCosts()); return minidx; } + + double compute_exact_weight(HighsInt i) { + Vector y_i = basis.btran(Vector::unit(runtime.instance.num_var, i)); + return y_i.dot(y_i); + } + + void compute_exact_weights() { + for (int i=0; i 10E-3) { + //printf("weights[%d] = %lf, should be %lf\n", i, weight_is, weight_comp); + return false; + } + return true; + } + + bool check_weights() { + + std::vector correct_weights; + std::vector incorrect_weights; + bool ret = true; + for (int i=0; i= 10E-3) { + // printf("old weight[p] discrepancy: updated = %lf, computed=%lf\n", old_weight_p_updated, old_weight_p_computed); + //} - Vector v = basis.btran(aq); + double weight_p = old_weight_p_computed; - double weight_p = weights[rowindex_p]; + + double t_p = aq.value[rowindex_p]; for (HighsInt i = 0; i < runtime.instance.num_var; i++) { - if (i == rowindex_p) { - weights[i] = weight_p / (aq.value[rowindex_p] * aq.value[rowindex_p]); - } else { - weights[i] = weights[i] - - 2 * (aq.value[i] / aq.value[rowindex_p]) * (v.value[i]) + - (aq.value[i] * aq.value[i]) / - (aq.value[rowindex_p] * aq.value[rowindex_p]) * - weight_p; + if (i != rowindex_p) { + double t_i = aq.value[i]; + weights[i] = weights[i] + - 2 * (t_i / t_p) * delta.value[i] + + ((t_i * t_i) / (t_p * t_p)) * weight_p; + //printf("weights[%d] = %lf\n", i, weights[i]); } } + //Vector new_ep = basis.btran(Vector::unit(runtime.instance.num_var, rowindex_p)); + //double computed_weight = new_ep.dot(new_ep); + double new_weight_p_updated = weight_p / (t_p * t_p); + + //if (fabs(updated_weight - computed_weight) > 10E-5) { + // printf("updated weight %lf vs computed weight %lf. aq[p] = %lf\n", updated_weight, computed_weight, t_p); + // printf("old weight = %lf, aq[p] = %lf, ^2 = %lf, new weight = %lf\n", weight_p, t_p, t_p*t_p, updated_weight); + //} + weights[rowindex_p] = new_weight_p_updated; } };