[Python] Newton raphson fails to approximate beyond two decimal points

Discussão em 'Python' iniciado por Stack, Janeiro 4, 2025.

  1. Stack

    Stack Membro Participativo

    I've written a program which finds roots of a two function system using the Newton Raphson method. Its goal is to solve for two unknowns of a closed vector loop (sketches below). The issue is that it only works when the error tolerance is 0.01 and greater, in other cases (for example, when it's 0.001) it falls into an oscillation and seemingly never converges. I find this behaviour odd, since the fact that it succeeds in getting to 0.01 precision should prove its ability to land a guess inside the convergence radius, and from there on further approximation shouldn't face any problems...

    import numpy as np
    import random as rnd

    TOLERANCE = 0.01
    ITER_LIMIT = 50

    track_x = 0
    track_y = 0
    track_incline = np.deg2rad(60)

    r41 = 12.2/2
    r1 = 28.88 - 10.95
    r2 = 22.65 - track_x
    r26 = 8/2 - track_y
    r3 = 8
    r4 = 12.2

    theta41 = np.pi
    theta3 = np.deg2rad(30)

    def f1(x, y):
    return r41*np.sin(theta41) + r1*np.cos(theta41) + r2*np.sin(y) + r26*np.cos(y) - x*np.sin(y + track_incline) + r3*np.sin(theta3)

    def f2(x, y):
    return r41*np.cos(theta41) - r1*np.sin(theta41) + r2*np.cos(y) - r26*np.sin(y) - x*np.cos(y + track_incline) + r3*np.cos(theta3) + r4

    def jacobian_mat(x, y):
    return np.array([
    [-np.sin(y + track_incline), r2*np.cos(y) - r26*np.sin(y) - x*np.cos(y + track_incline)],
    [-np.cos(y + track_incline), -r2*np.sin(y) - r26*np.cos(y) + x*np.sin(y + track_incline)]
    ])

    def compute_newton_raphson(x0, y0):
    for i in range(ITER_LIMIT):
    result = -np.matmul(np.array([f1(x0, y0), f2(x0, y0)]), np.linalg.inv(jacobian_mat(x0, y0))) + np.array([x0, y0])
    x = result[0]
    y = result[1]

    print(x, y)

    if max(np.abs(x - x0), np.abs(y - y0)) <= TOLERANCE:
    return (x, y)
    else:
    x0 = x
    y0 = y

    return None

    while True:
    x0 = rnd.randrange(-100, 100)
    y0 = rnd.randrange(-100, 100)

    res = compute_newton_raphson(x0, y0)
    if res != None:
    print(f"RESULT:\nX = {res[0]}mm\nY = {np.rad2deg(res[1])}deg")
    break


    Here's a sketch of the problem that I'm modeling this program for, just in case it proves useful.

    Angles

    I had zero success playing around with the iteration count. Also double checked if f1 and f2 are properly constructed.

    Any insight is greatly appreciated!

    Continue reading...

Compartilhe esta Página