private bool solve_phase(int item_count, int num_vars, ref int iterations) { int art_var_index = num_vars - 2; bool use_Blands_rule = false; double increase = 0.0; while (true) { sparse_matrix.multiply(ref _z, _cB, _B_inv); sparse_matrix.multiply(ref _z_c, _z, _N); sparse_matrix.subtract(_z_c, _cN); _z_c.zero_roundoff_errors(); sparse_matrix.multiply(ref _result, _B_inv, _b); _result.zero_roundoff_errors(); int entering_var = -1; double min_neg_coeff = 0.0; double[] z_c_ref = _z_c[0]; if (use_Blands_rule) { for (int cur_var = 0; cur_var < item_count; ++cur_var) { if (z_c_ref[cur_var] < 0.0 && (_vN[cur_var] < art_var_index || _vN[cur_var] >= num_vars)) { min_neg_coeff = z_c_ref[cur_var]; entering_var = cur_var; break; } } } else { for (int cur_var = 0; cur_var < item_count; ++cur_var) { if (min_neg_coeff > z_c_ref[cur_var] && (_vN[cur_var] < art_var_index || _vN[cur_var] >= num_vars)) { min_neg_coeff = z_c_ref[cur_var]; entering_var = cur_var; } } } if (entering_var < 0) { if (engine_control_unit.CALIBRATION_DEBUG) { if (engine_control_unit.FULL_CALIBRATION_DEBUG) { sparse_matrix.multiply(ref _E, _B, _B_inv); _E.log("E"); _E.set_to_identity(); _cB.log("cB"); _cN.log("cN"); _B.log("B"); _N.log("N"); _B_inv.log("B^-1"); _z.log("cB * B^-1"); _z_c.log("cB * B^-1 * N - cN"); _result.log("B^-1 * b"); } MyLog.Default.WriteLine("<< FINISHED >>"); sparse_matrix.multiply(ref _total, _cB, _result); MyLog.Default.WriteLine(string.Format("Iteration = {0}; total = {1}", iterations, _total[0][0])); } return(true); } _entering_column.column_vector_from(_N, entering_var); sparse_matrix.multiply(ref _dividers, _B_inv, _entering_column); _dividers.zero_roundoff_errors(); double min_ratio = double.MaxValue, cur_ratio; int leaving_var = -1; for (int cur_var = 0; cur_var < num_vars; ++cur_var) { if (_dividers[cur_var][0] > 0.0 && _result[cur_var][0] >= 0.0) { cur_ratio = _result[cur_var][0] / _dividers[cur_var][0]; if (min_ratio > cur_ratio) { min_ratio = cur_ratio; leaving_var = cur_var; } } } if (leaving_var < 0) { MyLog.Default.WriteLine("<< ABORTED >>"); sparse_matrix.multiply(ref _total, _cB, _result); log_var("Entering", _vN[entering_var], num_vars); MyLog.Default.WriteLine(string.Format("Iteration = {0}; total = {1}", iterations, _total[0][0])); return(false); } increase -= min_neg_coeff * min_ratio; if (engine_control_unit.CALIBRATION_DEBUG) { if (engine_control_unit.FULL_CALIBRATION_DEBUG) { sparse_matrix.multiply(ref _E, _B, _B_inv); _E.log("E"); _E.set_to_identity(); _cB.log("cB"); _cN.log("cN"); _B.log("B"); _N.log("N"); _B_inv.log("B^-1"); _z.log("cB * B^-1"); _z_c.log("cB * B^-1 * N - cN"); _result.log("B^-1 * b"); _dividers.log("B^-1 * N[e]"); } log_var("Entering", _vN[entering_var], num_vars); log_var("Leaving", _vB[leaving_var], num_vars); sparse_matrix.multiply(ref _total, _cB, _result); MyLog.Default.WriteLine(string.Format("Iteration = {2}; increase = {0}; Bland's rule = {1}; total = {3}", -min_neg_coeff * min_ratio, use_Blands_rule, iterations, _total[0][0] - min_neg_coeff * min_ratio)); } if ((iterations & 3) == 3) { use_Blands_rule = increase < EPSILON; increase = 0.0; } bool singular_B = !perform_pivot(num_vars, entering_var, leaving_var, iterations++); if (singular_B) { MyLog.Default.WriteLine("<< SINGULAR >>"); _cB.log("cB"); _cN.log("cN"); _B.log("B"); _N.log("N"); return(false); } } }
static public bool invert(ref sparse_matrix operand, ref sparse_matrix identity) { if (operand._width != operand._height || identity._width != identity._height || operand._height != identity._height) { throw new ArgumentException("Cannot invert non-square matrix"); } int operand_height = operand._height; Dictionary <int, double>[] operand_contents = operand._contents; for (int cur_item = 0; cur_item < operand_height; ++cur_item) { double cur_element; operand_contents[cur_item].TryGetValue(cur_item, out cur_element); double max_element = Math.Abs(cur_element), test_element, column_element; int max_row = cur_item; for (int cur_row = cur_item + 1; cur_row < operand_height; ++cur_row) { operand_contents[cur_row].TryGetValue(cur_item, out column_element); test_element = Math.Abs(column_element); if (test_element > max_element) { max_element = test_element; max_row = cur_row; } } if (max_row > cur_item) { operand.exchange_rows(cur_item, max_row); identity.exchange_rows(cur_item, max_row); } double divider, multiplier; operand_contents[cur_item].TryGetValue(cur_item, out divider); if (divider != 1.0) { if (divider >= -revised_simplex_solver.EPSILON && divider <= revised_simplex_solver.EPSILON) { MyLog.Default.WriteLine(string.Format("Singular column = {0}; PR = {1}", cur_item, max_row)); operand.log("O"); return(false); } operand.divide_row(cur_item, divider); operand_contents[cur_item][cur_item] = 1.0; identity.divide_row(cur_item, divider); } for (int cur_row = cur_item + 1; cur_row < operand_height; ++cur_row) { if (operand_contents[cur_row].TryGetValue(cur_item, out multiplier)) { operand.subtract_row(cur_row, cur_item, multiplier); operand_contents[cur_row].Remove(cur_item); identity.subtract_row(cur_row, cur_item, multiplier); } } } for (int cur_item = operand_height - 1; cur_item > 0; --cur_item) { double multiplier; for (int cur_row = 0; cur_row < cur_item; ++cur_row) { if (operand_contents[cur_row].TryGetValue(cur_item, out multiplier)) { operand_contents[cur_row].Remove(cur_item); identity.subtract_row(cur_row, cur_item, multiplier); } } } sparse_matrix temp = operand; operand = identity; identity = temp; return(true); }