gridValues   = [15, 17];
ridgeValues  = [1e-4 5e-4 1e-3];
smoothValues = [1e-3 5e-3 1e-2];

bestScore = inf;
bestOpts = [];

for g = gridValues
    for r = ridgeValues
        for s = smoothValues

            opts = struct;
            opts.GridSize = g;
            opts.RidgeLambda = r;
            opts.SmoothnessLambda = s;
            opts.MakePlot = false;
            opts.WriteReport = false;

            [~, results] = preisach_predict_SLsign(10:18, 19:21, opts);

            % Combined prediction error over both prediction runs.
            predRMSE = mean([results.prediction.RMSE]);
            predP95  = mean([results.prediction.P95AbsoluteError]);

            % Score prioritizes staying within absolute tolerance.
            score = predRMSE + predP95;

            if score < bestScore
                bestScore = score;
                bestOpts = opts;
            end
        end
    end
end

disp(bestOpts);