import numpy as np
import matplotlib.pyplot as plt

# Definicija sistema nelinearnih jednačina
def system_equations(x, y):
    eq1 = x**2 + y**2 - 25
    eq2 = x*y - 9
    return eq1, eq2

# Analitičko rešenje
def analytic_solution():
    x1 = 1.96
    y1 = 4.60
    x2 = 4.62
    y2 = 1.95
    return (x1, y1), (x2, y2)

# Genetski algoritam
def genetic_algorithm(population_size, generations):
    # Inicijalizacija populacije
    population = np.random.uniform(low=-5, high=5, size=(population_size, 2))

    for generation in range(generations):
        # Evaluacija prilagođenosti
        fitness = np.sum(np.abs(np.array(system_equations(population[:, 0], population[:, 1]))), axis=0)

        # Selekcija roditelja
        selected_indices = np.argsort(fitness)[:population_size//2]
        parents = population[selected_indices]

        # Ukrštanje (jednostavno u sredini)
        crossover_point = parents.shape[0] // 2
        children = np.vstack((parents[:crossover_point], parents[crossover_point:][::-1]))

        # Mutacija (dodavanje male slučajne vrednosti)
        mutation_rate = 0.1
        mutation = np.random.uniform(low=-0.1, high=0.1, size=children.shape)
        children += mutation

        # Zamena starih jedinki novim
        population[selected_indices] = children

    # Prikaz rezultata
    best_solution_index = np.argmin(fitness)
    best_solution = population[best_solution_index]
    return tuple(best_solution)

# Pokretanje genetskog algoritma
best_solution_genetic = genetic_algorithm(population_size=50, generations=100)

# Analitička rešenja
analytic_solution1, analytic_solution2 = analytic_solution()

# Prikaz rezultata
print("Analytical solutions:", analytic_solution1, analytic_solution2)
print("Genetic algorithm solution:", best_solution_genetic)
print("System values for genetic solution:", system_equations(*best_solution_genetic))

# Grafički prikaz
x_vals = np.linspace(-5, 5, 100)
y_vals = np.linspace(-5, 5, 100)
X, Y = np.meshgrid(x_vals, y_vals)
Z1, Z2 = system_equations(X, Y)

plt.contour(X, Y, Z1, levels=[0], colors='r', label='Equation 1')
plt.contour(X, Y, Z2, levels=[0], colors='b', label='Equation 2')
plt.scatter(*best_solution_genetic, color='green', marker='*', label='Genetic algorithm')
plt.scatter(*analytic_solution1, color='orange', marker='o', label='Analytical solution 1')
plt.scatter(*analytic_solution2, color='purple', marker='o', label='Analytical solution 2')
plt.xlabel('x')
plt.ylabel('y')
plt.legend()
plt.title('Comparison of genetic algorithm solutions and analytical solutions')
plt.show()
