LPPRoblemStatus lpengine::DualSimplexStep() { // Step1: Check if Dual is feasible then dictionary is optimal if (IsSemiPositive(p_.x_b_hat_)) { // current dictionary is optimal return LPPRoblemStatus::STATUS_OPTIMAL; } // Step2: Select Entring Variable p_.entering_var_ = ChooseEnteringVar(p_.x_b_hat_); // Step3: compute Dual step direction delta(z_n_) Eigen::MatrixXd tmp(p_.dim_m_, p_.dim_n_); tmp = p_.a_b_.inverse() * p_.a_n_; Eigen::VectorXd ei(p_.dim_m_); ei.setZero(ei.rows()); ei[p_.entering_var_] = 1; p_.delta_z_n_ = -tmp.transpose() * ei; // Step4&5: Compute primal step length and leaving var ChooseLeavingVar(p_.delta_z_n_, p_.z_n_hat_, &p_.leaving_var_, &p_.s_); // if s_ is not positive then dual is unbounded (primal is infeasible) if (p_.s_ <= 0) { return LPPRoblemStatus::STATUS_UNBOUNDED; } // Step6: choose primal step direction. dual_enteringvar=dual_leavingvar Eigen::VectorXd ej(p_.dim_n_); ej.setZero(ej.rows()); ej[p_.leaving_var_] = 1; p_.delta_x_b_ = tmp * ej; // Step7: Compute primal step length dual_leavingvar=primal_enteringvar p_.t_ = p_.x_b_hat_[p_.entering_var_] / p_.delta_x_b_[p_.entering_var_]; // Step8: Update current primal and dual solutions p_.x_b_hat_ = p_.x_b_hat_ - p_.t_ * p_.delta_x_b_; p_.z_n_hat_ = p_.z_n_hat_ - p_.s_ * p_.delta_z_n_; // Step9: Update Basis SwapCols(p_.a_b_, p_.entering_var_,p_.a_n_ , p_.leaving_var_); p_.x_b_hat_[p_.entering_var_] = p_.t_; p_.z_n_hat_[p_.leaving_var_] = p_.s_; // Calc Objective Function Value // p_.obj_value_ = TODO: c_b_.transpose * a_b_.inverse() * b_; p_.dic_number_++; return LPPRoblemStatus::STATUS_ITTERATING; }
bool ON_Matrix::Invert( double zero_tolerance ) { ON_Workspace ws; int i, j, k, ix, jx, rank; double x; const int n = MinCount(); if ( n < 1 ) return false; ON_Matrix I(m_col_count, m_row_count); int* col = ws.GetIntMemory(n); I.SetDiagonal(1.0); rank = 0; double** this_m = ThisM(); for ( k = 0; k < n; k++ ) { // find largest value in sub matrix ix = jx = k; x = fabs(this_m[ix][jx]); for ( i = k; i < n; i++ ) { for ( j = k; j < n; j++ ) { if ( fabs(this_m[i][j]) > x ) { ix = i; jx = j; x = fabs(this_m[ix][jx]); } } } SwapRows( k, ix ); I.SwapRows( k, ix ); SwapCols( k, jx ); col[k] = jx; if ( x <= zero_tolerance ) { break; } x = 1.0/this_m[k][k]; this_m[k][k] = 1.0; ON_ArrayScale( m_col_count-k-1, x, &this_m[k][k+1], &this_m[k][k+1] ); I.RowScale( k, x ); // zero this_m[!=k][k]'s for ( i = 0; i < n; i++ ) { if ( i != k ) { x = -this_m[i][k]; this_m[i][k] = 0.0; if ( fabs(x) > zero_tolerance ) { ON_Array_aA_plus_B( m_col_count-k-1, x, &this_m[k][k+1], &this_m[i][k+1], &this_m[i][k+1] ); I.RowOp( i, x, k ); } } } } // take care of column swaps for ( i = k-1; i >= 0; i-- ) { if ( i != col[i] ) I.SwapRows(i,col[i]); } *this = I; return (k == n) ? true : false; }