function this = runSerial(this)
%

%   Copyright 2016-2023 The MathWorks, Inc.

checkForOptimizableVariables(this);
checkXConstraintFcnSatisfiability(this);
this = processInitializationData(this);
this.IterationStartTime = tic;
this = callPlotFcn(this, 'initial');
this = callOutputFcn(this, 'initial');
this = fitModels(this);
[this.IncumbentF, this.IncumbentX] = findIncumbent(this);
this = chooseNextPoint(this);
iteration = this.NumObjectiveEvaluations + 1;
if iteration == 1 && this.PrivOptions.Verbose >= 1
    printVerboseSummary(this.PrivOptions.BayesOptPrint, this);
end
while ~optimizationFinished(this, iteration)
    % Maybe print verbose line
    verboseXNextDisplay(this);
    % Do a function evaluation and record results
    [Objective, ConstraintViolations, UserData, ErrorConstraintViolation, ...
        ObjectiveFcnObjectiveEvaluationTime, ObjectiveNargout] = callObjFcn(this, this.XNext);
    this = recordFEvalResults(this, this.XNext, Objective, ConstraintViolations, ...
        UserData, ErrorConstraintViolation, ObjectiveFcnObjectiveEvaluationTime, ObjectiveNargout);
    % Refit models
    FitModelsT = tic;
    this = fitModels(this);
    ModelFitTime = toc(FitModelsT);
    % Update traces
    this = updateTraces(this, iteration);
    % Find incumbent
    PointSelectionT = tic;
    [this.IncumbentF, this.IncumbentX] = findIncumbent(this);
    % Choose next point
    this = chooseNextPoint(this);
    % If gridsearch exhausted the grid, reset SampledGridIndices so we can
    % start another grid pass, and choose a point again
    if isempty(this.XNext) && doingGridsearch(this) && gridFullySampled(this)
        if this.PrivOptions.Verbose >= 2
            bayesoptim.printInfo('GridFullySampled');
        end
        this.SampledGridIndices = [];
        this = chooseNextPoint(this);
    end
    if this.PrivOptions.Verbose >= 2
        bayesoptim.printInfo('PointSelectionTime', num2str(toc(PointSelectionT)));
    end
    % Update timing, plots and output
    if this.PrivOptions.Verbose >= 2
        bayesoptim.printInfo('ModelFitTime', num2str(ModelFitTime));
    end
    this = updateTimingPlotsAndOutput(this, iteration);
    iteration = iteration + 1;
end
this = pruneGridIndices(this);
this = callPlotFcn(this, 'done');
this = callOutputFcn(this, 'done');
showStoppingReason(this);
showBestPoints(this);
showVerboseDocHelp(this);
end
