import numpy as np
import matplotlib.pyplot as plt

def f(x, y):
    return np.sin(np.sqrt(x**2 + y**2))

def grad_f(x, y):
    dist = np.sqrt(x**2 + y**2)
    if dist == 0:
        return 0, 0
    dx = (x / dist) * np.cos(dist)
    dy = (y / dist) * np.cos(dist)
    return dx, dy

learning_rate = 0.1
steps = 30
x, y = 4, 4  # Start point

path_x, path_y = [x], [y]  # To store points visited

for _ in range(steps):
    dx, dy = grad_f(x, y)
    x -= learning_rate * dx  # Move opposite to gradient
    y -= learning_rate * dy
    path_x.append(x)
    path_y.append(y)

x_vals = np.linspace(-5, 5, 100)
y_vals = np.linspace(-5, 5, 100)
X, Y = np.meshgrid(x_vals, y_vals)
Z = f(X, Y)

plt.contour(X, Y, Z, levels=20, cmap='viridis')
plt.plot(path_x, path_y, 'ro-', label='Gradient Descent Path')
plt.title('Simple Gradient Descent on sin(sqrt(x² + y²))')
plt.xlabel('X-axis')
plt.ylabel('Y-axis')
plt.colorbar(label='Function value')
plt.legend()
plt.grid(True)
plt.show()