import numpy as np

# Coefficients of the objective function (Minimize: 3x1 + 2x2 - 4x3)
c = np.array([3, 2, -4])

# Coefficients of the inequality constraints (Ax >= b)
A = np.array([[5, -1, 3],
              [-4, 2, 5],
              [2, 5, -6]])
b = np.array([8, 4, 5])

# Bounds for variables (x1, x2, x3 >= 0)
x_bounds = np.array([0, 0, 0])

# Initialize variables with a feasible starting point
x = np.array([1, 1, 1], dtype=float)  # Initial guess
alpha = 0.1  # Step size

def objective(x):
    return np.dot(c, x)

def gradient(A, b, x):
    return np.dot(A.T, np.linalg.solve(A @ A.T, A @ x - b))

# Iterative optimization using gradient descent-like approach
max_iterations = 1000
tolerance = 1e-6

for i in range(max_iterations):
    grad = gradient(A, b, x)
    x_new = x - alpha * grad
    x_new = np.maximum(x_new, x_bounds)  # Ensure non-negativity
    
    if np.linalg.norm(x_new - x) < tolerance:
        break
    x = x_new

# Output results
if np.all(A @ x >= b):
    print("Optimal solution found:")
    print("x1 =", x[0])
    print("x2 =", x[1])
    print("x3 =", x[2])
    print("Optimal value:", objective(x))
else:
    print("The problem is unbounded.")
