def transpose(self): from alc.utils import zeros new_arr = zeros((self.shape[1], self.shape[0])) for i in range(self.shape[1]): for j in range(self.shape[0]): new_arr[i][j] = self.__iterable[j][i] return new_arr
def forwardsub (L, B): # Initialize y y = zeros((L.shape[0], B.shape[1])) n = L.shape[0] # Forward sub y[0][0] = B[0][0] / L[0][0] for i in range(1, n): y[i][0] = B[i][0] for j in range(0, i): y[i][0] -= L[i][j]*y[j][0] y[i][0] /= L[i][i] return y
def retrosub (A, B): # Initialize x x = zeros((A.shape[0], B.shape[1])) n = A.shape[0] # Retro-substitution x[n-1] = [B[n-1][0]/A[n-1][n-1]] for i in range(n-2, -1, -1): x[i][0] = B[i][0] for j in range(i+1, n): x[i][0] -= A[i][j]*x[j][0] x[i][0] /= A[i][i] return x
def __matmul(self, mat1, mat2): from alc.utils import zeros try: assert mat1.shape[1] == mat2.shape[0] except AssertionError: raise AssertionError( "Matrices can't be multiplied with shapes {} and {}".format( mat1.shape, mat2.shape)) result = zeros((mat1.shape[0], mat2.shape[1])) for i in range(mat1.shape[0]): for j in range(mat2.shape[1]): for k in range(mat2.shape[0]): result[i][j] += mat1[i][k] * mat2[k][j] if (abs(result[i][j]) <= constants.epsilon): result[i][j] = 0.0 return result
def solve (A, B, method='gauss', threshold=constants.epsilon): if method == "gauss": # Turn A into an upper triangular matrix A, intermediates = gauss_elimination (A, return_intermediates=True, show_steps=False, return_pivots=False) # To keep it an equation, apply transformations to B as well for m in intermediates: B = m * B x = retrosub(A, B) return x elif method == "gauss_jordan": # Turn A into an upper triangular matrix A, intermediates = gauss_elimination (A, return_intermediates=True, show_steps=False, return_pivots=False) # To keep it an equation, apply transformations to B as well for m in intermediates: B = m * B # Turn A into diagonal matrix A, intermediates = gauss_jordan_elimination (A, return_intermediates=True, show_steps=False) # Apply transformations to B as well for m in intermediates: B = m * B # Initialize x x = zeros((A.shape[0], B.shape[1])) # Computing x for i in range(A.shape[0]): x[i][0] = B[i][0]/A[i][i] return x elif method == "jacobi": x = jacobi(A, B, threshold=threshold) return x elif method == "gauss_seidel": x = gauss_seidel(A, B, threshold=threshold) return x elif method == "lu": L, U = lu_decomposition (A, return_det=False) y = forwardsub(L, B) x = retrosub(U, y) return x elif method == "cholesky": try: L, Lt = cholesky_decomposition(A) y = forwardsub(L, B) x = retrosub(Lt, y) return x except ValueError as e: raise e else: raise NameError("Solving method not allowed!")
def cholesky_decomposition(arr): from alc.utils import is_definite_positive, is_symmetric if (not is_definite_positive(arr) or not is_symmetric(arr)): raise ValueError( "Não é possível realizar a decomposição de Cholesky. A matriz fornecida não é simétrica positiva definida." ) L = zeros(arr.shape) for i in range(arr.shape[0]): L[i][i] = arr[i][i] for k in range(0, i): L[i][i] -= (L[i][k]**2) L[i][i] = (L[i][i]**(1 / 2)) for j in range(i + 1, arr.shape[1]): L[j][i] = arr[i][j] for k in range(0, i): L[j][i] -= (L[i][k] * L[j][k]) L[j][i] /= L[i][i] return L, L.t
def jacobi(A, B, threshold=constants.epsilon): if (not is_diagonally_dominant(A)): raise ValueError( "A matriz \"A\" não é estritamente diagonal dominante e, portanto, o método de Jacobi não irá convergir!" ) prev_x = random_array(B.shape) r = 1000 n = B.shape[0] while (r > threshold): x = zeros(B.shape) for i in range(x.shape[0]): x[i][0] = B[i][0] for j in range(0, n): if (i != j): x[i][0] -= A[i][j] * prev_x[j][0] x[i][0] /= A[i][i] r = vector_norm(x - prev_x, 2) / vector_norm(x, 2) prev_x = deepcopy(x) return x
def gauss_seidel(A, B, threshold=constants.epsilon): if (not is_diagonally_dominant(A)): if (not is_definite_positive(A)): raise ValueError( "A matriz \"A\" não é estritamente diagonal dominante nem positiva definida e, portanto, o método de Gauss-Seidel não irá convergir!" ) prev_x = random_array(B.shape) r = 1000 n = B.shape[0] while (r > threshold): x = zeros(B.shape) for i in range(x.shape[0]): x[i][0] = B[i][0] for j in range(0, i): x[i][0] -= A[i][j] * x[j][0] for j in range(i + 1, n): x[i][0] -= A[i][j] * prev_x[j][0] x[i][0] /= A[i][i] r = vector_norm(x - prev_x, 2) / vector_norm(x, 2) prev_x = deepcopy(x) return x
def least_squares(x, y): # Length of X and Y samples must be the same try: if (len(x) != len(y)): raise ValueError("Length of X and Y samples must be the same!") except Exception as e: print("Failure while comparing X and Y length") raise e # Start with ones matrix and then just replace with X values on first column P = ones((len(x), 2)) for i, val in enumerate(x): P[i][0] = val # Then, turn y samples into an array Y = zeros((len(y), 1)) for i, val in enumerate(y): Y[i][0] = val # Next, do A = P^T * P, C = P^T * Y A = P.t * P C = P.t * Y # Finally, find B = A^(-1) * C B = ~A * C # a, b are first and second values of B return B[0][0], B[1][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))