def fixed_point(expr, arguments, max_err=1e-5, max_iter=50): if len(arguments) != 1: raise ValueError("Error! Invalid number of arguments") xi = arguments[0] f = expr_to_lambda(expr) symbol = get_symbol(expr) output = Output() _init_output(output, "Fixed-Point", f, lambda x: x - f(x)) cur_xi = numpy.empty(0, dtype=numpy.float64) cur_err_i = numpy.empty(0, dtype=numpy.float64) cur_xi = numpy.append(cur_xi, xi) cur_err_i = numpy.append(cur_err_i, float('NaN')) begin = timeit.default_timer() for i in range(0, max_iter): root = xi - f(xi) err = abs((root - xi)) xi = root cur_xi = numpy.append(cur_xi, root) cur_err_i = numpy.append(cur_err_i, err) if err <= max_err: break end = timeit.default_timer() try: x_next = xi - f(xi) output.error_bound = abs(x_next - xi) except (ZeroDivisionError, OverflowError): output.error_bound = 0 output.execution_time = abs(end - begin) output.roots = numpy.append(output.roots, root) output.errors = numpy.append(output.errors, err) output.dataframes.append( create_dataframe(cur_xi, output.function, cur_err_i, symbol)) return output
def gauss_seidel(A: sympy.Matrix, symbols: list, b=None, max_iter=100, max_err=1e-5, x=None): """Gauss-Seidel Iterative Method for Solving A System of Linear Equations: takes a system of linear equations and returns an approximate solution for the system using Gauss-Seidel approximation. Keyword arguments: A: sympy.Matrix -- The augmented matrix representing the system if b = None else the coefficients matrix. A is an [n, n] matrix. symbols: list of sympy.Symbol representing the variables' names. b: sympy.Matrix -- The r.h.s matrix of the system. b is an n-dimensional vector. max_iter: int -- The maximum number of iterations to perform. max_err: float -- The maximum allowed error. x: sympy.Matrix -- The initial value for the variables. x is an n-dimensional vector. return: 1) The n-dimensional vector x containing the final approximate solution. 2) The [n, number_of_iterations] matrix x_hist containing the values of x during each iteration. 3) The numpy array err_hist containing the values of the error during each iteration. """ A = A.as_mutable() n = len(symbols) output = Output() output.title = "Gauss-Seidel" if b is None: A, b = [A[:, :-1], A[:, -1]] if x is None: x = sympy.Matrix.zeros(n, 1) x_prev = x[:, :] err_hist = [float('NaN')] x_hist = sympy.Matrix(x) begin = timeit.default_timer() for _ in range(0, max_iter): for i in range(0, n): xi_new = b[i] for j in range(0, n): if i != j: xi_new -= A[i, j] * x[j] x[i] = xi_new / A[i, i] x_hist = x_hist.row_join(x) diff = (x - x_prev).applyfunc(abs) err = numpy.amax(numpy.array(diff).astype(numpy.float64)) err_hist.append(err) x_prev = x[:, :] if err < max_err: break end = timeit.default_timer() output.execution_time = abs(end - begin) output.roots = numpy.array(x[:]).astype(numpy.float64) output.errors = numpy.append(output.errors, err) output.dataframes.append(create_dataframe_part2(x_hist, err_hist, symbols)) return output
def regula_falsi(expr, arguments, max_err=1e-5, max_iter=50): if len(arguments) != 2: raise ValueError("Error! Invalid number of arguments") xl, xu = min(arguments[0], arguments[1]), max(arguments[0], arguments[1]) f = expr_to_lambda(expr) if f(xl) * f(xu) > 0: raise ValueError("Error! There are no roots in the range [%d, %d]" % (xl, xu)) prev_xr = 0 symbol = get_symbol(expr) output = Output() _init_output(output, "Regula-Falsi", f, expr_to_lambda(diff(expr))) cur_xi = numpy.empty(0, dtype=numpy.float64) cur_err_i = numpy.empty(0, dtype=numpy.float64) cur_xi = numpy.append(cur_xi, xl) cur_err_i = numpy.append(cur_err_i, float('NaN')) begin = timeit.default_timer() for _ in range(0, max_iter): yl = f(xl) yu = f(xu) xr = (xl * yu - xu * yl) / (yu - yl) yr = f(xr) err = abs(xr - prev_xr) if yr * yu < 0: xl = xr elif yr * yl < 0: xu = xr else: err = 0 prev_xr = xr cur_xi = numpy.append(cur_xi, xr) cur_err_i = numpy.append(cur_err_i, err) if err <= max_err: break end = timeit.default_timer() try: yl = f(xl) yu = f(xu) x_next = (xl * yu - xu * yl) / (yu - yl) output.error_bound = abs(x_next - prev_xr) except (ZeroDivisionError, OverflowError): output.error_bound = 0 output.execution_time = abs(end - begin) output.roots = numpy.append(output.roots, xr) output.errors = numpy.append(output.errors, err) output.dataframes.append( create_dataframe(cur_xi, output.function, cur_err_i, symbol)) return output
def bisection(expr, arguments, max_err=1e-5, max_iter=50): if len(arguments) != 2: raise ValueError("Error! Invalid number of arguments") xl, xu = min(arguments[0], arguments[1]), max(arguments[0], arguments[1]) f = expr_to_lambda(expr) if f(xl) * f(xu) > 0: raise ValueError("Error! There are no roots in the range [%d, %d]" % (xl, xu)) prev_xr = 0 symbol = get_symbol(expr) output = Output() _init_output(output, "Bisection", f, lambda x: x / 2) output.error_bound = ceil(abs(log2(abs(xu - xl)) - log2(max_err))) cur_xi = numpy.empty(0, dtype=numpy.float64) cur_err_i = numpy.empty(0, dtype=numpy.float64) cur_xi = numpy.append(cur_xi, xl) cur_err_i = numpy.append(cur_err_i, float('NaN')) begin = timeit.default_timer() for _ in range(0, max_iter): yl = f(xl) yu = f(xu) xr = (xl + xu) / 2 yr = f(xr) err = abs(xr - prev_xr) if yr * yu < 0: xl = xr elif yr * yl < 0: xu = xr else: err = 0 prev_xr = xr cur_xi = numpy.append(cur_xi, xr) cur_err_i = numpy.append(cur_err_i, err) if err <= max_err: break end = timeit.default_timer() output.execution_time = abs(end - begin) output.roots = numpy.append(output.roots, xr) output.errors = numpy.append(output.errors, err) output.dataframes.append( create_dataframe(cur_xi, output.function, cur_err_i, symbol)) return output
def newton_mod2(expr, arguments, max_err=1e-5, max_iter=50): if len(arguments) != 1: raise ValueError("Error! Invalid number of arguments") xi = arguments[0] f = expr_to_lambda(expr) expr_diff = diff(expr) f_diff = expr_to_lambda(expr_diff) f_diff2 = expr_to_lambda(diff(expr_diff)) symbol = get_symbol(expr) output = Output() _init_output(output, "Newton-Raphson Mod#2", f, f_diff) cur_xi = numpy.empty(0, dtype=numpy.float64) cur_err_i = numpy.empty(0, dtype=numpy.float64) cur_xi = numpy.append(cur_xi, xi) cur_err_i = numpy.append(cur_err_i, float('NaN')) begin = timeit.default_timer() for _ in range(0, max_iter): fxi = f(xi) f_diff_xi = f_diff(xi) f_diff_xi2 = f_diff2(xi) root = xi - f_diff_xi * fxi / (f_diff_xi**2 - fxi * f_diff_xi2) err = abs((root - xi)) xi = root cur_xi = numpy.append(cur_xi, root) cur_err_i = numpy.append(cur_err_i, err) if err <= max_err: break end = timeit.default_timer() try: fxi = f(xi) f_diff_xi = f_diff(xi) f_diff_xi2 = f_diff2(xi) x_next = xi - f_diff_xi * fxi / (f_diff_xi**2 - fxi * f_diff_xi2) output.error_bound = abs(x_next - xi) except (ZeroDivisionError, OverflowError): output.error_bound = 0 output.execution_time = abs(end - begin) output.roots = numpy.append(output.roots, root) output.errors = numpy.append(output.errors, err) output.dataframes.append( create_dataframe(cur_xi, output.function, cur_err_i, symbol)) return output
def birge_vieta(expr, arguments, max_err=1e-5, max_iter=50): if len(arguments) != 1: raise ValueError("Error! Invalid number of arguments") xi = arguments[0] output = Output() symbol = get_symbol(expr) _init_output(output, "Birge-Vieta", expr_to_lambda(expr), expr_to_lambda(diff(expr))) poly = sympy.Poly(expr, expr.free_symbols) a = poly.all_coeffs() m = len(a) - 1 n = m + 1 i = 1 begin = timeit.default_timer() while m > 0: cur_xi = numpy.empty(0, dtype=numpy.float64) cur_err_i = numpy.empty(0, dtype=numpy.float64) cur_xi = numpy.append(cur_xi, xi) cur_err_i = numpy.append(cur_err_i, float('NaN')) b = numpy.zeros(m + 1, dtype=numpy.float64) c = numpy.zeros(m + 1, dtype=numpy.float64) err = 0 for _ in range(0, max_iter): find_coeffs(a, b, c, xi) root = xi - b[m] / c[m - 1] err = abs((root - xi)) xi = root cur_xi = numpy.append(cur_xi, xi) cur_err_i = numpy.append(cur_err_i, err) if err <= max_err: break a = b[0:-1] m = len(a) - 1 output.dataframes.append( create_dataframe(cur_xi, output.function, cur_err_i, symbol, i)) i += 1 output.roots = numpy.append(output.roots, xi) output.errors = numpy.append(output.errors, err) end = timeit.default_timer() output.execution_time = abs(end - begin) return output
def _init_output(output: Output, method_name: str, f, f_bound): output.roots = [] output.errors = [] output.title = method_name output.function = f output.boundary_function = f_bound
def illinois(expr, arguments, max_err=1e-5, max_iter=50): delta = 0.1 if len(arguments) == 3: delta = arguments[2] elif len(arguments) != 2: raise ValueError("Error! Invalid number of arguments") start, end = arguments[0], arguments[1] i = 0 f = expr_to_lambda(expr) symbol = get_symbol(expr) counter = 0 output = Output() _init_output(output, "Illinois", f, expr_to_lambda(diff(expr))) begin_time = timeit.default_timer() while start + i * delta < end: xl, xu = start + i * delta, start + (i + 1) * delta f_xl, f_xu = f(xl), f(xu) if f_xl * f_xu > 0: i += 1 continue prev_xi = err = 0 cur_xi = cur_err_i = numpy.empty(0, dtype=numpy.float64) cur_xi = numpy.append(cur_xi, xl) cur_err_i = numpy.append(cur_err_i, float('NaN')) for _ in range(0, max_iter): if f_xl == 0: cur_xi = numpy.append(cur_xi, xl) cur_err_i = numpy.append(cur_err_i, 0.0) break elif f_xu == 0: cur_xi = numpy.append(cur_xi, xu) cur_err_i = numpy.append(cur_err_i, 0.0) i += 1 break step = f_xl * (xl - xu) / (f_xu - f_xl) xi = xl + step f_xi = f(xi) err = abs(xi - prev_xi) if f_xi * f_xu < 0: xl, f_xl = xu, f_xu else: f_xl /= 2 xu, f_xu = xi, f_xi prev_xi = xi cur_xi = numpy.append(cur_xi, xi) cur_err_i = numpy.append(cur_err_i, err) if err <= max_err: break output.dataframes.append( create_dataframe(cur_xi, output.function, cur_err_i, symbol, counter)) i += 1 output.roots = numpy.append(output.roots, prev_xi) output.errors = numpy.append(output.errors, err) counter += 1 end_time = timeit.default_timer() output.execution_time = abs(end_time - begin_time) return output