import numpy as np

# Initialisierung der Schwellenwerte
lower_threshold = 0.8
upper_threshold = 1.2

# Lernrate
learning_rate = 0.1

# Trainingsdaten (XOR-Problem)
inputs = [[0, 0], [0, 1], [1, 0], [1, 1]]
targets = [0, 1, 1, 0]

# Trainingsloop mit max. 1000 Iterationen
max_iterations = 1000
epoch = 0
network_trained = False
start_weights = None
final_weights = None
bias = np.random.rand()  # Zufälliger Start-Bias

while epoch < max_iterations:
    epoch += 1
    all_correct = True  # Flag, um zu überprüfen, ob alle Ausgaben korrekt sind
    current_weights = np.random.rand(2)  # Zufällige Startgewichte

    if epoch == 1:  # Die erste Iteration nach Initialisierung
        start_weights = current_weights  # Speichere die Startgewichte

    for input_vector, target in zip(inputs, targets):
        # Berechnung der gewichteten Summe + Bias
        weighted_sum = np.dot(input_vector, current_weights) + bias

        # Aktivierungsfunktion (Schwellenwert)
        if lower_threshold < weighted_sum < upper_threshold:
            output = 1
        else:
            output = 0

        # Fehlerberechnung
        error = target - output

        # Wenn Fehler vorliegt, Gewichte und Bias anpassen
        if error != 0:
            all_correct = False
            current_weights += learning_rate * error * np.array(input_vector)
            bias += learning_rate * error  # Bias anpassen

    # Überprüfe, ob alle Ausgaben korrekt sind
    if all_correct:
        network_trained = True
        final_weights = current_weights  # Speichere die finalen Gewichte
        break  # Stoppe, wenn alle Ausgaben korrekt sind

    # Wenn XOR nach 100 Iterationen nicht gelernt wurde, setze neue zufällige Startgewichte
    if epoch % 100 == 0:  # 100 statt 20
        print(f"Nicht funktionierende Startgewichte: {start_weights}")
        start_weights = np.random.rand(2)  # Setze neue Startgewichte

if network_trained:
    print(f"Das Netzwerk hat XOR korrekt nach {epoch} Iterationen gelernt.")
    print(f"Die Working Startgewichte waren: {start_weights}")
    print(f"Die finalen Gewichte sind: {final_weights}")
    print(f"Der Bias ist: {bias}")
else:
    print(f"Das Netzwerk hat XOR nach {epoch} Iterationen nicht korrekt gelernt.")

# Testen des Netzwerks nach den Lern-Iterationen
print("\nFinal Test Output:")
for input_vector, target in zip(inputs, targets):
    weighted_sum = np.dot(input_vector, final_weights) + bias
    if lower_threshold < weighted_sum < upper_threshold:
        output = 1
    else:
        output = 0
    print(f"Input: {input_vector}, Target: {target}, Output: {output}")
