def test_issue_22606(): fx = Function('f')(x) eq = x + gamma(y) # seems like ans should be `eq`, not `(x*y + gamma(y + 1))/y` ans = gammasimp(eq) assert gammasimp(eq.subs(x, fx)).subs(fx, x) == ans assert gammasimp(eq.subs(x, cos(x))).subs(cos(x), x) == ans assert 1 / gammasimp(1 / eq) == ans assert gammasimp(fx.subs(x, eq)).args[0] == ans
def fixed_point( f: Function, n: float, rational: bool = False, iterated_data: bool = False) -> Union[float, Tuple[float, list]]: """ Using Fixed-Point method, returns float (or tupled with iterated data). - Known as the method of successive submission. ..Note: - Return iterated_data defaults to False - Always use 'x' as a symbol - Originally was to take list of formulae. Modularising thos method means the need to opt it out. ..Usage: * Find all the possible iterative formula of f(x), Transform them to x = f(x) Example: f(x) = x^2-8x+11 can be transformed to: x = (x^2+11)/8; x = sqrt(8x-11) x = (8x-11)/x Algorithm ========= 1. Solve for the new value of n [f(n)] 2. If error % is converging to 0, return n as root 3. if previous n is converging with current n, return n as root Examples ======== ** Non-pythonic expressions will be parsed by SymPy module >>> fixed_point('(x^2+11)/8', 3) 1.7639910281905442 ** Using pythonic expressions is also accepted >>> fixed_point('(x**2+11)/8', 3) 1.7639910281905442 ** Turning rational True >>> fixed_point('(8x-11)/x', 3, rational=True) 153301943/24583261 ** Turning iterated_data True >>> fixed_point('(8x-11)/x', 3, iterated_data=True) (6.236029589402317, {0: {'Xn': 3, 'e%': None}, ...) Iterated data ============= count / iteration : - The first key you see in the dictionary Xn : - Value of the iterated approximate root e% : - Percent error, how accurate the approximate root Exceptions ========== InfiniteIteration : - Raised when the function passed is indefinite and iteration reaches 99, assuming it is indefinite. Parameters ========== f : - Should be STRING - Mathematical expression - A mathematical function - Example: '(x^2+11)/8' '(x**2+11)/8' '(8x-11)/x' n : - the 'x' value of the function rational : - Returns fraction/rational value - Defaults to False iterated_data: - Returns the iterated data in dictionary - Defaults to False """ f = parse_expr(f, transformations=transformations) n = sympify(n) data = {} count = 0 prev_n = 0 while True: error = abs(((n - prev_n) / n) * 100) data[count] = {'Xn': n, 'e%': error if count > 0 else None} prev_n = n n = f.subs(x, n) if isclose(error, 0.0000, rel_tol=1e-4): break elif isclose(prev_n, n, abs_tol=1e-4): break elif count >= 99: raise InfiniteIteration count += 1 if not rational: n = float(n) if iterated_data: return n, data else: return n
def newton_raphson( f: Function, n: float, rational: bool = False, iterated_data: bool = False) -> Union[float, Tuple[float, list]]: """ Using Newton-Raphson method, returns float (or tupled with iterated data). - Utilizes the derivative of f(x) - is an open method that finds the root x of a function such that f(x) ..Note: - Return iterated_data defaults to False - Always use 'x' as a symbol Algorithm ========= 1. Solve f(x), f'(x), error % 2. n = n - (f(x)/f'(x)) 3. if error % is converging to 0, return n as root 4. if previous f'(x) is converging to next f'(x), return n as root Examples ======== ** Non-pythonic expressions will be parsed by SymPy module >>> from newton_raphson import newton_raphson >>> newton_raphson('x^2-8x+11', 1) 1.763932022500022 ** Using pythonic expressions is also accepted >>> newton_raphson('x**2-8*x+11', 1) 1.763932022500022 ** Turning rational True >>> newton_raphson('x^3-3x+1', 0, rational=True) 170999/492372 ** Turning iterated_data True >>> newton_raphson('x^3-3x+1', 0, iterated_data=True) (0.347296353163868, {0: {'Xn': 0, 'fx': 1, 'fpx': -3, 'e%': None}, ...) Iterated data ============= count / iteration : - The first key you see in the dictionary Xn : - Value of the iterated approximate root fx : - Value of the f(n) fpx : - Value of the f'(n) [computed derived f(n)] e% : - Percent error, how accurate the approximate root Exceptions ========== InfiniteIteration : - Raised when the function passed is indefinite and iteration reaches 99, assuming it is indefinite. Parameters ========== f : - Should be STRING - Mathematical expression - A mathematical function - Example: 'x^2-8x+11' 'x**3-3*x+1' 'x^3+10x^2-5' n : - the 'x' value of the function rational : - Returns fraction/rational value - Defaults to False iterated_data: - Returns the iterated data in dictionary - Defaults to False """ f = parse_expr(f, transformations=transformations) n = sympify(n) data = {} count = 0 prev_n = 0 fp = diff(f, x) while True: fXn = f.subs(x, n) fpXn = fp.subs(x, n) error = abs(((n - prev_n) / n) * 100) data[count] = { 'Xn': n, 'fx': fXn, 'fpx': fpXn, 'e%': error if count > 0 else None } prev_n = n n = n - (fXn / fpXn) if isclose(round(error, 4), 0.0, rel_tol=1e-4): break elif isclose(fpXn, fp.subs(x, n), rel_tol=1e-4): break elif count >= 99: raise InfiniteIteration count += 1 if not rational: n = float(n) if iterated_data: return n, data else: return n
def false_position( f: Function, a: float, b: float, rational: bool = False, swap: bool = False, iterated_data: bool = False) -> Union[float, Tuple[float, dict]]: """ Using false-position method, returns root (or tupled with iterated data) - The same as bisection method, because the size of an interval containing a root is reduced through iteration. ..Note: - Return iterated_data defaults to False - Always use 'x' as symbol Algorithm ========= 1. Find two numbers (a, b) of which f(x) has different signs 2. Define c = (a*fb-b*fa)/(fb-fa) 3. if b and c are converging, return c as root 4. if f(a)f(c) <= 0, b = c else a = c Examples ======== ** Non-pythonic expressions will be parsed by SymPy module >>> false_position('x^2-8x+11', 1, 2) 1.7639484978540771 ** Using pythonic expressions is also accepted >>> false_position('x**2-8*x+11', 1, 2) 1.7639484978540771 ** Turning rational True >>> false_position('x^3-3x+1', 0, 1, rational=True) 119624146949151814554649/344443180703677909347131 ** Turning iterated_data True >>> false_position('x^3-3x+1', 0, 1, iterated_data=True) (0.3472971847047936, {1: {'a': 0, 'b': 1, 'fa': 1, 'fb': -1, 'c': 1/2, 'fc': -3/8, 'CoS': '-'}, ...) Iterated data ============= count / iteration : - The first key you see in the dictionary a : - Value of the first interval b : - Value of the second interval fa : - Value of the f(a) fb : - Value of the f(b) c : - Value of (a*fb-b*fa)/(fb-fa) [value of the root] fc : - Value of the f(c) Exceptions ========== SameSign : - Raised when values of f(a) and f(b) has the same sign AGreatB : - Raised when the value of a is greater than b - [Optional flag] - Swap the values Parameters ========== f : - Should be STRING - Mathematical expression - A mathematical function - Example: 'x^2-8x+11' 'x**3-3*x+1' 'x^3+10x^2-5' a : - The first interval b : - The second interval rational : - Returns fraction/rational value - Defaults to False swap : - Flag to prevent AGreatB Exception - Defaults to False iterated_data: - Returns the iterated data in dictionary - Defaults to False """ from math import isclose f = parse_expr(f, transformations=transformations) a = sympify(a) b = sympify(b) if a > b and swap: z = a a = b b = z del z elif a > b: raise AGreatB if f.subs(x, a) * f.subs(x, b) > 0.0: raise SameSigns data = {} count = 1 while True: fa = f.subs(x, a) fb = f.subs(x, b) c = (a * fb - b * fa) / (fb - fa) fc = f.subs(x, c) data[count] = {'a': a, 'b': b, 'fa': fa, 'fb': fb, 'c': c, 'fc': fc} if isclose(b, c, rel_tol=1e-4): break if fa * fc <= 0: b = c else: a = c count += 1 if not rational: c = float(c) if iterated_data: return c, data else: return c
def bisection(f: Function, a: float, b: float, error: float, rational: bool = False, swap: bool = False, iterated_data: bool = False) -> Union[float, Tuple[float, dict]]: """ Using bisection method, returns root (or tupled with iterated data). - Repeatedly bisects an interval and then selects a sub-interval in which a root must lie for further processing. ..Note: - Return iterated_data defaults to False - Always use 'x' as symbol Algorithm ========= 1. Find two numbers (a, b) of which f(x) has different signs 2. Define c = (a+b)/2 3. if (b-c) <= error tolerance, accept c as the root, stop iteration 4. if f(a)f(c) <= 0, b = c else a = c Examples ======== ** Non-pythonic expressions will be parsed by SymPy module >>> from newton_raphson import newton_raphson >>> bisection('x^2-8x+11', 1, 2, 0.001) 1.7646484375 ** Using pythonic expressions is also accepted >>> bisection('x**2-8*x+11', 1, 2, 0.001) 1.7646484375 ** Turning rational True >>> bisection('x^3-3x+1', 0, 1, 0.001, rational=True) 355/1024 ** Turning iterated_data True >>> bisection('x^3-3x+1', 0, 1, 0.001, iterated_data=True) (0.3466796875, {1: {'a': 0, 'b': 1, 'c': 1/2, 'fa': 1, 'fc': -3/8, 'bc': 1/2, 'swap': 'b = c'}, ...) Iterated data ============= count / iteration : - The first key you see in the dictionary a : - Value of the first interval b : - Value of the second interval c : - Value of (a + b)/2 [value of the root] fa : - Value of the f(a) fc : - Value of the f(c) bc : - Value of (b - c) swap : - What values swapped Exceptions ========== SameSign : - Raised when values of f(a) and f(b) has the same sign AGreatB : - Raised when the value of a is greater than b - [Optional flag] - Swap the values Parameters ========== f : - Should be STRING - Mathematical expression - A mathematical function - Example: 'x^2-8x+11' 'x**3-3*x+1' 'x^3+10x^2-5' a : - The first interval b : - The second interval error : - Error tolerance rational : - Returns fraction/rational value - Defaults to False swap : - Flag to prevent AGreatB Exception - Defaults to False iterated_data: - Returns the iterated data in dictionary - Defaults to False """ f = parse_expr(f, transformations=transformations) a = sympify(a) b = sympify(b) error = sympify(error) if a > b and swap: z = a a = b b = z del z elif a > b: raise AGreatB if f.subs(x, a) * f.subs(x, b) > 0.0: raise SameSigns data = {} count = 1 while True: c = (a + b) / 2 fa = f.subs(x, a) fc = f.subs(x, c) bc = b - c data[count] = { 'a': a, 'b': b, 'c': c, 'fa': fa, 'fc': fc, 'bc': bc, 'swap': 'b = c' if fa * fc <= 0 else 'a = c' } if bc <= error or round(bc, 4) <= error: break if fa * fc <= 0: b = c else: a = c count += 1 if not rational: c = float(c) if iterated_data: return c, data else: return c