def bisection (function, a, b, threshold=constants.epsilon): x = Symbol('x') try: f = lambdify(x, eval(function)) except: raise ExpressionError("Falhou ao executar a seguinte função: {}. Favor verificar a expressão.".format(function)) while (abs(b - a) >= threshold): xi = (a + b) / 2 fi = f(xi) if (fi > 0): b = xi else: a = xi return xi
def newton (function, x0, threshold=constants.epsilon, max_iter=constants.max_iter): x = Symbol('x') try: func = eval(function) f = lambdify(x, func) f_prime = func.diff(x) f_prime = lambdify(x, f_prime) except: raise ExpressionError("Falhou ao executar a seguinte função: {}. Favor verificar a expressão.".format(function)) xk1 = x0 for k in range(max_iter): xk = xk1 - f(xk1) / f_prime(xk1) if (abs(xk-xk1) <= threshold): return xk xk1 = xk raise ValueError("Método de Newton não convergiu (threshold={:e}, max_iter={}).".format(threshold, max_iter))
def inverse_interpolation (function, x1, x2, x3, threshold=constants.epsilon, max_iter=constants.max_iter): def sort_pairs (x1, x2, x3, y1, y2, y3): x = [x1, x2, x3] y = [y1, y2, y3] for passnum in range(len(y)-1, 0, -1): for i in range(passnum): if y[i] > y[i+1]: tmp_x = x[i] tmp_y = y[i] x[i] = x[i+1] y[i] = y[i+1] x[i+1] = tmp_x y[i+1] = tmp_y return x[0], x[1], x[2], y[0], y[1], y[2] def replace_greater (x1, x2, x3, y1, y2, y3, new_x, new_y): greater = max([y1, y2, y3]) if y1 == greater: x1 = new_x y1 = new_y elif y2 == greater: x2 = new_x y2 = new_y elif y3 == greater: x3 = new_x y3 = new_y return sort_pairs(x1, x2, x3, y1, y2, y3) x = Symbol('x') try: f = lambdify(x, eval(function)) except: raise ExpressionError("Falhou ao executar a seguinte função: {}. Favor verificar a expressão.".format(function)) xk1 = float('inf') for k in range(max_iter): y1 = f(x1) y2 = f(x2) y3 = f(x3) xk = (y2*y3*x1) / ((y1-y2)*(y1-y3)) + (y1*y3*x2) / ((y2-y1)*(y2-y3)) + (y1*y2*x3) / ((y3-y1)*(y3-y2)) # print ("Iter {} => x1={:.3f}, x2={:.3f}, x3={:.3f}, y1={:.3f}, y2={:.3f}, y3={:.3f}, x*={:.3f}, |x(k) - x(k-1)|={:.3f}".format(k, x1, x2, x3, y1, y2, y3, xk, abs(xk-xk1))) if (abs(xk-xk1) <= threshold): return xk x1, x2, x3, y1, y2, y3 = replace_greater(x1, x2, x3, y1, y2, y3, xk, f(xk)) xk1 = xk raise ValueError("Método da interpolação inversa não convergiu (threshold={:e}, max_iter={}).".format(threshold, max_iter))
def newton_secant (function, x0, threshold=constants.epsilon, max_iter=constants.max_iter): x = Symbol('x') try: f = lambdify(x, eval(function)) except: raise ExpressionError("Falhou ao executar a seguinte função: {}. Favor verificar a expressão.".format(function)) delta_x = 1e-3 xk1 = x0 xk = xk1 + delta_x fa = f(xk1) for k in range(max_iter): fi = f(xk) new_xk = xk - fi*(xk-xk1)/(fi-fa) # print ("Iter {} => x(k-1) = {}, x(k) = {}, x(k+1) = {}, |x(k+1)-x(k)|={}".format(k, xk1, xk, new_xk, abs(new_xk-xk))) if (abs(new_xk-xk) <= threshold): return xk fa = fi xk1 = xk xk = new_xk raise ValueError("Método de Newton secante não convergiu (threshold={:e}, max_iter={}).".format(threshold, max_iter))
def diff(function, x0, delta_x=constants.epsilon, method='center', p=2, q=2): x = Symbol('x') try: f = lambdify(x, eval(function)) except: raise ExpressionError( "Falhou ao executar a seguinte função: {}. Favor verificar a expressão." .format(function)) if (method == 'step_back'): d1 = (f(x0) - f(x0 - delta_x)) / delta_x delta_x /= q d2 = (f(x0) - f(x0 - delta_x)) / delta_x elif (method == 'step_forward'): d1 = (f(x0 + delta_x) - f(x0)) / delta_x delta_x /= q d2 = (f(x0 + delta_x) - f(x0)) / delta_x elif (method == 'center'): d1 = (f(x0 + delta_x) - f(x0 - delta_x)) / (2 * delta_x) delta_x /= q d2 = (f(x0 + delta_x) - f(x0 - delta_x)) / (2 * delta_x) else: raise NameError("Method {} not allowed".format(method)) return d1 + ((d1 - d2) / (q**(-p) - 1))
def equations (eq_list, symbols, x0, threshold=constants.epsilon, max_iter=constants.max_iter, method='newton'): func_vars = [] eqs = [] if (len(symbols) != len(x0)): raise ValueError("Symbols length ({}) differs from x0 length ({})".format(len(symbols), len(x0))) for symbol in symbols: exec("{0} = Symbol('{0}')".format(symbol)) exec("func_vars.append({})".format(symbol)) for w in range(len(eq_list)): try: eqs.append(eval(eq_list[w])) except: raise ExpressionError("Falhou ao executar a seguinte função: {}. Favor verificar a expressão.".format(function)) F = Matrix(eqs) Y = Matrix(func_vars) J = F.jacobian(Y) xk1 = Matrix(x0) if (method == 'newton'): for k in range(max_iter): j = J f = F for i, var in enumerate(func_vars): j = j.limit(var, xk1[i]) f = f.limit(var, xk1[i]) j = j.n() f = f.n() delta_x = - j.inv() * f xk = xk1 + delta_x xk1 = xk tol = delta_x.norm() / xk.norm() if tol <= threshold: ret_arr = [] for w in range(len(eq_list)): ret_arr.append(float(xk.n()[w])) return Array(ret_arr) raise ValueError("Método de Newton não convergiu (threshold={:e}, max_iter={}).".format(threshold, max_iter)) elif (method == 'broyden'): bk1 = J f = F for i, var in enumerate(func_vars): bk1 = bk1.limit(var, xk1[i]) f = f.limit(var, xk1[i]) bk1 = bk1.n() f = f.n() for k in range(max_iter): j = bk1 delta_x = - j.inv() * f xk = xk1 + delta_x fxk = F for i, var in enumerate(func_vars): fxk = fxk.limit(var, xk[i]) fxk = fxk.n() yk = fxk - f tol = delta_x.norm().n() / xk.norm().n() if tol <= threshold: ret_arr = [] for w in range(len(eq_list)): ret_arr.append(float(xk.n()[w])) return Array(ret_arr) bk = bk1 + (yk-bk1*delta_x)*delta_x.transpose()/(delta_x.transpose()*delta_x).n()[0] xk1 = xk.n() bk1 = bk f = fxk else: raise NameError("Solving method {} not allowed!".format(method))
def integrate(function, a, b, n_points=10, method='polynomial'): if ((n_points < 1) or (n_points > 10)): raise ValueError("n_points must be between 1 and 10") x = Symbol('x') try: f = lambdify(x, eval(function)) except: raise ExpressionError( "Falhou ao executar a seguinte função: {}. Favor verificar a expressão." .format(function)) if (n_points == 1): return f(abs(a + b) / 2) * (abs(b - a)) def laguerre_function(x): return f(x) / math.exp(-x) def hermite_function(x): return f(x) / math.exp(-x**2) # Getting hermite sum sum_hermite = 0 points = constants.hermite[n_points]['points'] weights = constants.hermite[n_points]['weights'] for i in range(n_points): sum_hermite += hermite_function(points[i]) * weights[i] # Getting laguerre sum sum_laguerre = 0 points = constants.laguerre[n_points]['points'] weights = constants.laguerre[n_points]['weights'] for i in range(n_points): sum_laguerre += laguerre_function(points[i]) * weights[i] if (a == float("-inf")): # B is positive infinite if (b == float("inf")): return sum_hermite # B is positive elif (b >= 0): return sum_hermite - sum_laguerre + integrate( function, 0, b, n_points, method='gauss_quadrature') # B is negative else: return sum_hermite - sum_laguerre - integrate( function, b, 0, n_points, method='gauss_quadrature') elif (b == float("inf")): if (a == 0): return sum_laguerre elif (a > 0): return sum_laguerre - integrate( function, 0, a, n_points, method='gauss_quadrature') else: return sum_hermite - sum_laguerre - integrate( function, a, 0, n_points, method='gauss_quadrature') if (method == 'polynomial'): delta_x = abs(b - a) / (n_points - 1) B = [] integration_points = [] res = 0 for i in range(1, n_points + 1): integration_points.append(a + (i - 1) * delta_x) B.append((b**i - a**i) / i) vandermonde = zeros((n_points, n_points)) B = Array([[b] for b in B]) for i in range(n_points): for j in range(n_points): vandermonde[i][j] = integration_points[j]**i x = solve(vandermonde, B) for i in range(n_points): res += x[i][0] * f(integration_points[i]) return res elif (method == 'gauss_quadrature'): weights = constants.legendre[n_points]['weights'] points = constants.legendre[n_points]['points'] L = b - a res = 0 integration_points = [] for i in range(n_points): integration_points.append((a + b + points[i] * L) / 2) for i in range(n_points): res += f(integration_points[i]) * weights[i] return res * L / 2 else: raise NameError("Method {} not allowed.".format(method))