function [bestParams, bestErr, FITNESS, FITNESS_gen] = func3_runDE(model, t, I_exp, U_exp)
% Differential Evolution zur Parameteroptimierung der JA-Parameter + Anregung

    D = 6; % 5 JA-Parameter + 1 Amplitude
    NP = 60;
    F = 0.8;
    CR = 0.9;
    MaxGen = 250;

    % === Parametergrenzen definieren ===
    bounds = [
        1.33e6,  2.7e6;     % Ms
        10,  250;     % a
        10,  250;     % k
        1e-5,    1;       % c
        1e-7, 1e-4;    % alpha
        0.05,  10      % Vexc
    ];

    % === Initialisierung der Population mit Gültigkeitsprüfung ===
    pop = zeros(NP, D);
    i = 1;
    while i <= NP
        candidate = zeros(1, D);
        for d = 1:D
            candidate(d) = bounds(d,1) + rand * (bounds(d,2) - bounds(d,1));
        end

        JA = struct('Ms', candidate(1), 'a', candidate(2), ...
                    'k', candidate(3), 'c', candidate(4), 'alpha', candidate(5));


        if 1%isValid
            pop(i,:) = candidate;
            i = i + 1
        end
    end

    % === Fitness initial berechnen ===
    fitness = zeros(NP,1);
    for i = 1:NP
        fitness(i) = func6_objectiveFunction(pop(i,:), model, t, I_exp, U_exp);
    end
    
    [minErrGen(1), idxGen(1)] = min(fitness);
    FITNESS_LOG = zeros(NP, MaxGen);
    PARAM_LOG = zeros(NP, D, MaxGen);
    FITNESS_LOG(:,1) = fitness;
    PARAM_LOG(:,:,1) = pop;
        
    % === Haupt-Optimierungsschleife ===
    for gen = 2:MaxGen
        fprintf('Generation %d\n', gen)
        for i = 1:NP
            idx = randperm(NP, 3);
            x1 = pop(idx(1),:); x2 = pop(idx(2),:); x3 = pop(idx(3),:);
            trial_valid = false;

            while ~trial_valid
                % === Mutation ===
                mutant = x1 + F * (x2 - x3);
                for d = 1:D
                    mutant(d) = max(min(mutant(d), bounds(d,2)), bounds(d,1));
                end

                % === Crossover ===
                trial = pop(i,:);
                for d = 1:D
                    if rand < CR
                        trial(d) = mutant(d);
                    end
                end

                % === Gültigkeit prüfen ===
                JA = struct('Ms', trial(1), 'a', trial(2), ...
                            'k', trial(3), 'c', trial(4), 'alpha', trial(5));

                trial_valid = 1;%isValid;
            end

            % === Bewertung ===
            fit_trial = func6_objectiveFunction(trial, model, t, I_exp, U_exp);

            % === Selektion ===
            if fit_trial < fitness(i)
                pop(i,:) = trial;
                fitness(i) = fit_trial;
            end
        end
        FITNESS_LOG(:,gen) = fitness;
        PARAM_LOG(:,:,gen) = pop;

        [minErrGen(gen), idxGen(gen)] = min(fitness);
    end

    FITNESS_gen = minErrGen;
    FITNESS = fitness;
    [bestErr, bestIdx] = min(fitness);
    bestParams = pop(bestIdx,:);
    
    figure;
    hold on;
    plot(minErrGen)
    xlabel('Generation')
    ylabel('Fitness')
    grid on;
    box on;
    hold off;
end