예제 #1
0
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
예제 #2
0
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))
예제 #3
0
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))
예제 #4
0
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))
예제 #5
0
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))
예제 #6
0
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))
예제 #7
0
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))