Example #1
0
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
Example #2
0
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
Example #3
0
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
Example #4
0
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
Example #5
0
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