function [ ] = driver_EX_tbls_1_to_7_UPDATE( )
%
% This is the driver that tests the six experiments with Alg. 4,
% and the five experiments with Alg. 3 from the article
% (in particular it is used to generate the data for tables 1--7)
%
% "Algorithm XXX: SC-SR1: MATLAB Software for Limited-Memory SR1
% Trust-Region Methods",
% (Brust,Burdakov,Erway,Marcia,2018-2022)                               [1]
%
% Copyright (2020-2022): Johannes Brust, Jennifer Erway, and Roummel Marcia
%
% This code is distributed under the terms of the GNU General Public
% License 2.0.
%
% Permission to use, copy, modify, and distribute this software for
% any purpose without fee is hereby granted, provided that this entire
% notice is included in all copies of any software which is or includes
% a copy or modification of this software and in all copies of the
% supporting documentation for such software.
% This software is being provided "as is", without any express or
% implied warranty.  In particular, the authors do not make any
% representation or warranty of any kind concerning the merchantability
% of this software or its fitness for any particular purpose.
%--------------------------------------------------------------------------

clc;

addpath(genpath('../ALGS'));

show = 0; %verbose setting

n = logspace(3,7,5);  %generates problem sizes (1e3 to 1e7)
kp1 = 5;  %number of limited memory updates

%Because time counts can differ, we run each experiment "n_times".
%The "ith" time is recorded in the paper's tables.
n_times = 5;  % number of test runs per experiment
ith  = 3; %saves the third run's results
tol  = 1e-10;

%%% Extend this to a double loop
%%% Loop over subproblem solvers
%%% Loop over experiments

% Information about experiments
%

% Select the norm
% (P,inf)   runs on 5 experiments
% (P,2)     runs on 6 experiments
nExs = [5,6];

% String arrays
nmSolvs = {'Alg. 3 (Solver=0)','Alg. 4 (Solver=1)'};
normSolvs = {'(P,inf)','(P,2)'};
descExs = { '|g_par(i)|<delta |Lambda(i,i)| and Lambda(i,i)>tau',...
    'B is positive definite, constrained case';...
    ...
    '|g_par(i)|<tau and |Lambda(i,i)|<tau',...
    'B is psd with g_i~=0 for some i in [1,r]';...
    ...
    '|g_par(i)|>tau and |Lambda(i,i)|<tau',...
    'B is psd with g_i=0 for all i in [1,r], ||Lambda^dagger g_par||>delta';...
    ...
    '|g_par(i)|<tau and Lambda(i,i)<-tau',...
    'B is indef. with g_i=0 for some i in [1,r], ||(lambda-lambda1I)^dagger g_par||>delta';...
    ...
    '|g_par(i)|>delta |Lambda(i,i)| and Lambda(i,i)>tau',...
    'B is indef. with g_i ne 0 for some i';...
    '',...
    'B is indef. (hard case)'};

tabls = {'VII','I';'VII','II';'VII','III';'VII','IV';'VII','V';'VII','VI'};

norm_type = -1;
fprintf('\nBeginning experiment...\n');

% Loops
for norm_type = 0:1
    for experiment = 1:nExs(norm_type+1)

        % Description when new experiment runs

        fprintf('\n################################################################');
        fprintf('\nSolver: %s ',    nmSolvs{norm_type+1});
        fprintf('\nNorm: %s ',    normSolvs{norm_type+1});
        fprintf('\nTable: %s',      tabls{experiment,norm_type+1});
        fprintf('\nExperiment: %1d', experiment);
        fprintf('\nDescription: %s', descExs{experiment,norm_type+1});
        fprintf('\nRunning Experiment  #############################################');

        %pause(2);

        for i_outer = 1:size(n,2)  %loop on the value of n
            fprintf('\n----------------------');
            fprintf('\nTable: %s', tabls{experiment,norm_type+1});
            fprintf('\nExperiment number: %1d', experiment);
            fprintf('\nSolver: %s ',    nmSolvs{norm_type+1});
            fprintf('\nNorm: %s ',    normSolvs{norm_type+1});
            %fprintf('\nSolver: %1d ', norm_type);
            fprintf('\nProblem size: %1.0e', n(i_outer));
            fprintf('\nRepeating this%2d', n_times);
            fprintf(' times... \n');
            %initialize local variables
            gamma = abs(10*randn(1));
            delta = 1;

            % generate S, Y randomly, ensure Psi is full rank to set up exper #1-6
            S = randn(n(i_outer),kp1);
            Y = randn(n(i_outer),kp1);
            Psi = Y - gamma.*S;
            while rank(Psi)<size(Psi,2)
                S = randn(n(i_outer),kp1);
                Y = randn(n(i_outer),kp1);
                Psi = Y - gamma.*S;
            end
            PsiPsi=Psi'*Psi;

            g = (1e-10)*randn(size(S,2),1);
            g = [g; randn(n(i_outer)-size(g,1),1)];

            % compute eigenvalues of $B$
            SY          = S'*Y;
            SS          = S'*S;
            invM        = tril(SY)+ tril(SY,-1)'-gamma.*SS;
            invM        = (invM+(invM)')./2;  %symmetrize it

            R           = chol(PsiPsi);
            RMR         = R* (invM\R');
            RMR         = (RMR+(RMR)')./2;  %symmetrize it
            [U, D ]      = eig(RMR);  %D is a matrix

            % Eliminate complex roundoff error then sort eigenvalues and eigenvectors
            [D,ind]     = sort(real(diag(D)));   %D is a vector
            U           = U(:,ind);

            if norm_type==1  %(P,2) experiments


                D = diag(D); %matrix

                switch(experiment)



                    case 1
                        %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
                        %    Experiment #1
                        %%%%%%%%%%%%%%%%%%%
                        %   What we need to do to generate a case for experiment #1:
                        %   (1) ensure B is strictly positive definite
                        %   (2) chose delta = mu*\|v_u\|_2,  0<mu<1   (below, mu=3/4)

                        %   (1) modify eigenvalues of $B$ and re-form invM, leaving Psi unchanged
                        D           = diag(max(abs(diag(D)),1e-4));  % threshold eigenvalues
                        invM        = R'*inv(U*D*U')*R;
                        invM        = (invM+(invM)')./2;

                        %    (2) chose delta = .75*\|v_parallel(0)\|_2

                        % compute v_parallel(0) the exact same way that sc_sr1_2.m does
                        % (copying code from sc_sr1_2.m)
                        PsiPsi      = Psi(:,1:kp1)'*Psi(:,1:kp1);
                        [Ldl,Dldl,Pldl] = ldl(PsiPsi,'vector');  %ldl decomposition of PsiPsi'
                        Dldl=diag(Dldl);  %vectorize Dldl
                        maskldl = find(Dldl>(sqrt(eps)*max(Dldl)));
                        rankPsi = length(maskldl);     %compute rank of Psi
                        Pldl_fullRank = Pldl(maskldl);  %index of lin indep columns of Psi (used later)
                        R(1:rankPsi,:) = diag(sqrt(Dldl(maskldl)))*Ldl(:,maskldl)';
                        invP(Pldl)=1:kp1;
                        RMR         = R(1:rankPsi,invP)* (invM(1:kp1,1:kp1)\R(1:rankPsi,invP)');
                        RMR         = (RMR+(RMR)')./2;  %symmetrize RMR' to avoid complex
                        [U, D ]      = eig(RMR);
                        [D,ind]     = sort(real(diag(D)));  %D is now a vector; low to high
                        U           = U(:,ind);
                        Lambda      = D + gamma.*ones(rankPsi,1);
                        Lambda      = Lambda.*(abs(Lambda)>tol); %thresholds
                        g_parallel  = U'*(R(1:rankPsi,maskldl)'\(Psi(:,Pldl_fullRank)'*g));

                        % ||v_parallel(0)||_2 = norm(g_parallel./Lambda);
                        delta = .75*norm(g_parallel./Lambda);  % <---- set delta *****


                        % do n_times runs
                        flag = 1; %handing Psi and invM
                        for testruns = 1:n_times
                            if ith == testruns
                                show = 1;
                            else
                                show = 0;
                            end
                            fprintf('\nSolve %2d', testruns');
                            fprintf(' of %2d:', n_times);
                            [p_star,iExit]= sc_sr1_2( g, Psi,invM,gamma,delta,flag,show);

                            if iExit==1
                                fprintf('\nError detected...\n');
                                return;
                            end
                        end


                    case 2
                        %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
                        %    Experiment #2
                        %%%%%%%%%%%%%%%%%%%

                        %(1) ensure B is positive semidefinite
                        %(2) set g appropriately

                        % (1) modify eigenvalues of $B$ and re-form invM, leaving Psi unchanged
                        D           = max(abs(diag(D)),1e-4);        % threshold eigenvalues
                        [D, ind3]   = sort(D);
                        U           = U(:,ind3);
                        r           = 2;                             % multiplicity of 0 eigenvalue
                        D(1:r)      = -gamma;
                        invM        = R'*U*diag(1./D)*U'*R;
                        invM        = (invM+(invM)')./2;  %symmetrize invM

                        % (2) set g correctly
                        P_parallel  = Psi*(R\U);
                        g_par       = P_parallel'*g;
                        if norm(g_par(1:r),1)<sqrt(eps)
                            g = P_parallel(:,1:r)*(P_parallel(:,1:r)'*g);
                        end

                        delta = rand(1);  % delta can be any positive number

                        % do n_times runs
                        flag = 1; %handing Psi and invM
                        for testruns = 1:n_times
                            if ith == testruns
                                show = 1;
                            else
                                show = 0;
                            end
                            fprintf('\nSolve %2d', testruns');
                            fprintf(' of %2d:', n_times);
                            [p_star,iExit]= sc_sr1_2( g, Psi,invM,gamma,delta,flag,show);

                            if iExit==1
                                fprintf('\nError detected...\n');
                                return;
                            end
                        end



                    case 3
                        %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
                        %    Experiment #3
                        %%%%%%%%%%%%%%%%%%%

                        % (1) ensure B is postive semidefinite
                        % (2) fix g
                        % (3) fix delta

                        % (1) modify eigenvalues of $B$ and re-form invM, leaving Psi unchanged
                        D           = max(abs(diag(D)),1e-4);        % threshold eigenvalues
                        [D, ind3]   = sort(D);
                        U           = U(:,ind3);
                        r           = 2;                             % multiplicity of 0 eigenvalue
                        D(1:r)      = -gamma;
                        invM        = R'*U*diag(1./D)*U'*R;
                        invM        = (invM+(invM)')./2;  %symmetrize invM

                        % (2) set (g_parallel) such that [g_parallel]_i=0 for i=1..r
                        P_parallel  = Psi*(R\U);
                        g           = g-P_parallel(:,1:r)*(P_parallel(:,1:r)'*g);


                        % (3) set delta so that ||v_parallel(0)||>delta
                        % (copying code from sc_sr1_2.m)
                        PsiPsi      = Psi(:,1:kp1)'*Psi(:,1:kp1);
                        [Ldl,Dldl,Pldl] = ldl(PsiPsi,'vector');  %ldl decomposition of PsiPsi'
                        Dldl=diag(Dldl);  %vectorize Dldl
                        maskldl = find(Dldl>(sqrt(eps)*max(Dldl)));
                        rankPsi = length(maskldl);     %compute rank of Psi
                        Pldl_fullRank = Pldl(maskldl); %index of lin indep columns of Psi (used later)
                        R(1:rankPsi,:) = diag(sqrt(Dldl(maskldl)))*Ldl(:,maskldl)';
                        invP(Pldl)=1:kp1; %#ok<*AGROW>
                        RMR         = R(1:rankPsi,invP)* (invM(1:kp1,1:kp1)\R(1:rankPsi,invP)');
                        RMR         = (RMR+(RMR)')./2;  %symmetrize RMR' to avoid complex
                        [U, D ]      = eig(RMR);
                        [D,ind]     = sort(real(diag(D)));  %D is now a vector; low to high
                        U           = U(:,ind);
                        Lambda      = D + gamma.*ones(rankPsi,1);
                        Lambda      = Lambda.*(abs(Lambda)>tol); %thresholds

                        g_parallel = P_parallel'*g;
                        delta = .75*norm(g_parallel(r+1:end)./Lambda(r+1:end));

                        % do n_times runs
                        flag = 1; %handing Psi and invM
                        for testruns = 1:n_times
                            if ith == testruns
                                show = 1;
                            else
                                show = 0;
                            end
                            fprintf('\nSolve %2d', testruns');
                            fprintf(' of %2d:', n_times);

                            [p_star,iExit]= sc_sr1_2( g, Psi,invM,gamma,delta,flag,show); %#ok<*ASGLU>

                            if iExit==1
                                fprintf('\nError detected...\n');
                                return;
                            end
                        end



                    case 4
                        %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
                        %    Experiment #4
                        %%%%%%%%%%%%%%%%%%%

                        % (1) B must be indefinite
                        % (2) fix g
                        % (3) fix delta

                        % (1) modify eigenvalues of $B$ and re-form invM, leaving Psi unchanged
                        D           = max(abs(diag(D)),1e-4);  % threshold eigenvalues
                        r = 2;
                        D(1:r)      = min([-rand(1)-gamma; (-1e-4)-gamma]);        %random value for eigenvalue
                        [D, ind3]   = sort(D);
                        U           = U(:,ind3);
                        invM        = R'*U*diag(1./D)*U'*R;  %modified so that M is still invertible but B is singular
                        invM        = (invM+(invM)')./2; %symmetrize it

                        % (2) set (g_parallel) such that [g_parallel]_i=0 for i=1..r
                        P_parallel  = Psi*(R\U);
                        g           = g-P_parallel(:,1:r)*(P_parallel(:,1:r)'*g);

                        % (3) set delta
                        % (copying code from sc_sr1_2.m)
                        PsiPsi      = Psi(:,1:kp1)'*Psi(:,1:kp1);
                        [Ldl,Dldl,Pldl] = ldl(PsiPsi,'vector');  %ldl decomposition of PsiPsi'
                        Dldl=diag(Dldl);  %vectorize Dldl
                        maskldl = find(Dldl>(sqrt(eps)*max(Dldl)));
                        rankPsi = length(maskldl);     %compute rank of Psi
                        Pldl_fullRank = Pldl(maskldl);  %index of lin indep columns of Psi (used later)
                        R(1:rankPsi,:) = diag(sqrt(Dldl(maskldl)))*Ldl(:,maskldl)';
                        invP(Pldl)=1:kp1;
                        RMR         = R(1:rankPsi,invP)* (invM(1:kp1,1:kp1)\R(1:rankPsi,invP)');
                        RMR         = (RMR+(RMR)')./2;  %symmetrize RMR' to avoid complex
                        [U,D ]      = eig(RMR);
                        [D,ind]     = sort(real(diag(D)));  %D is now a vector; low to high
                        U           = U(:,ind);
                        Lambda      = D + gamma.*ones(rankPsi,1);
                        Lambda      = Lambda.*(abs(Lambda)>tol); %thresholds

                        g_parallel  = U'*(R(1:rankPsi,maskldl)'\(Psi(:,Pldl_fullRank)'*g));
                        v = [zeros(r,1);-g_parallel(r+1:end)./(Lambda(r+1:end)-Lambda(1))];
                        delta = 0.75*norm(v);

                        % do n_times runs
                        flag = 1; %handing Psi and invM
                        for testruns = 1:n_times
                            if ith == testruns
                                show = 1;
                            else
                                show = 0;
                            end
                            fprintf('\nSolve %2d', testruns');
                            fprintf(' of %2d:', n_times);
                            [p_star,iExit]= sc_sr1_2( g, Psi,invM,gamma,delta,flag,show);

                            if iExit==1
                                fprintf('\nError detected...\n');
                                return;
                            end
                        end


                    case 5
                        %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
                        %    Experiment #5
                        %%%%%%%%%%%%%%%%%%%

                        %     (1) B must be indefinite
                        %     (2) set g

                        % (1) modify eigenvalues of $B$ and re-form invM, leaving Psi unchanged
                        D           = max(abs(diag(D)),1e-4);  % threshold eigenvalues
                        r = 2;
                        D(1:r)      = min([-rand(1)-gamma; (-1e-4)-gamma]);        %random value for eigenvalue
                        [D, ind3]   = sort(D);
                        U           = U(:,ind3);
                        invM        = R'*U*diag(1./D)*U'*R;  %modified so that M is still invertible but B is singular
                        invM        = (invM+(invM)')./2; %symmetrize it


                        % (2) set g correctly
                        P_parallel  = Psi*(R\U);
                        g_par       = P_parallel'*g;
                        if norm(g_par(1:r),1)<sqrt(eps)
                            g = P_parallel(:,1:r)*(P_parallel(:,1:r)'*g);
                        end

                        delta = rand(1);


                        % do n_times runs
                        flag = 1; %handing Psi and invM
                        for testruns = 1:n_times
                            if ith == testruns
                                show = 1;
                            else
                                show = 0;
                            end
                            fprintf('\nSolve %2d', testruns');
                            fprintf(' of %2d:', n_times);
                            [p_star,iExit]= sc_sr1_2( g, Psi,invM,gamma,delta,flag,show);

                            if iExit==1
                                fprintf('\nError detected...\n');
                                return;
                            end
                        end



                    case 6
                        %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
                        %    Experiment #6
                        %%%%%%%%%%%%%%%%%%%

                        %  (1) B must be indefinite
                        %  (2) set g
                        %  (3) set delta to get the "hard case"

                        % (1) modify eigenvalues of $B$ and re-form invM, leaving Psi unchanged
                        D           = max(abs(diag(D)),1e-4);  % threshold eigenvalues
                        r = 2;
                        D(1:r)      = min([-rand(1)-gamma; (-1e-4)-gamma]);        %random value for eigenvalue
                        [D, ind3]   = sort(D);
                        U           = U(:,ind3);
                        invM        = R'*U*diag(1./D)*U'*R;  %modified so that M is still invertible but B is singular
                        invM        = (invM+(invM)')./2; %symmetrize it


                        % (2) set (g_parallel) such that [g_parallel]_i=0 for i=1..r
                        P_parallel  = Psi*(R\U);
                        g           = g-P_parallel(:,1:r)*(P_parallel(:,1:r)'*g);


                        % (3) set delta
                        % (copying code from sc_sr1_2.m)
                        PsiPsi      = Psi(:,1:kp1)'*Psi(:,1:kp1);
                        [Ldl,Dldl,Pldl] = ldl(PsiPsi,'vector');  %ldl decomposition of PsiPsi'
                        Dldl=diag(Dldl);  %vectorize Dldl
                        maskldl = find(Dldl>(sqrt(eps)*max(Dldl)));
                        rankPsi = length(maskldl);     %compute rank of Psi
                        Pldl_fullRank = Pldl(maskldl);  %index of lin indep columns of Psi (used later)
                        R(1:rankPsi,:) = diag(sqrt(Dldl(maskldl)))*Ldl(:,maskldl)';
                        invP(Pldl)=1:kp1;
                        RMR         = R(1:rankPsi,invP)* (invM(1:kp1,1:kp1)\R(1:rankPsi,invP)');
                        RMR         = (RMR+(RMR)')./2;  %symmetrize RMR' to avoid complex
                        [U, D ]      = eig(RMR);
                        [D,ind]     = sort(real(diag(D)));  %D is now a vector; low to high
                        U           = U(:,ind);
                        Lambda      = D + gamma.*ones(rankPsi,1);
                        Lambda      = Lambda.*(abs(Lambda)>tol); %thresholds

                        g_parallel  = U'*(R(1:rankPsi,maskldl)'\(Psi(:,Pldl_fullRank)'*g));
                        v = [zeros(r,1);-g_parallel(r+1:end)./(Lambda(r+1:end)-Lambda(1))];
                        delta = 1.75*norm(v);


                        % do n_times runs
                        flag = 1; %handing Psi and invM
                        for testruns = 1:n_times
                            if ith == testruns
                                show = 1;
                            else
                                show = 0;
                            end
                            fprintf('\nSolve %2d', testruns');
                            fprintf(' of %2d:', n_times);
                            [p_star,iExit]= sc_sr1_2( g, Psi,invM,gamma,delta,flag,show);

                            if iExit==1
                                fprintf('\nError detected...\n');
                                return;
                            end
                        end

                end %switch

            else %(P,infinity)


                switch(experiment)
                    case 1
                        %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
                        %    Experiment #1
                        %%%%%%%%%%%%%%%%%%%
                        %   What we need to do to generate a case for experiment #0:
                        %   (1) fix Lambda(i,i)>tau
                        %   (2) set delta

                        i_counter = randi([1 kp1]);  %randomly change one element of g_par

                        % (1) ensure Lambda_ii>tau
                        D(i_counter) = max(abs(D(i_counter)),1e-3);
                        D           = diag(D);
                        invM        = R'*inv(U*D*U')*R; %#ok<*MINV>
                        invM        = (invM+(invM)')./2;

                        % (2) chose delta = 1.5*|g_par(i)|/|Lambda(i)|

                        % compute g_parallel(i) the exact same way that sc_sr1_infty.m does
                        % (copying code from sc_sr1_infty.m)
                        PsiPsi      = Psi(:,1:kp1)'*Psi(:,1:kp1);
                        [Ldl,Dldl,Pldl] = ldl(PsiPsi,'vector');  %ldl decomposition of PsiPsi'
                        Dldl=diag(Dldl);  %vectorize Dldl
                        maskldl = find(Dldl>(sqrt(eps)*max(Dldl)));
                        rankPsi = length(maskldl);     %compute rank of Psi
                        Pldl_fullRank = Pldl(maskldl);  %index of lin indep columns of Psi (used later)
                        R(1:rankPsi,:) = diag(sqrt(Dldl(maskldl)))*Ldl(:,maskldl)';
                        invP(Pldl)=1:kp1;
                        RMR         = R(1:rankPsi,invP)* (invM(1:kp1,1:kp1)\R(1:rankPsi,invP)');
                        RMR         = (RMR+(RMR)')./2;  %symmetrize RMR' to avoid complex
                        [U, D ]      = eig(RMR);
                        [D,ind]     = sort(real(diag(D)));  %D is now a vector; low to high
                        U           = U(:,ind);
                        i_counter   = rankPsi;  %sorted to the end
                        Lambda      = D + gamma.*ones(rankPsi,1);
                        Lambda      = Lambda.*(abs(Lambda)>tol); %thresholds
                        g_parallel  = U'*(R(1:rankPsi,maskldl)'\(Psi(:,Pldl_fullRank)'*g));

                        delta = 1.5*norm(g_parallel(i_counter)./Lambda(i_counter));  % <---- set delta *****

                        % do n_times runs
                        flag = 1; %handing Psi and invM
                        for testruns = 1:n_times
                            if ith == testruns
                                show = 1;
                            else
                                show = 0;
                            end
                            fprintf('\nSolve %2d', testruns');
                            fprintf(' of %2d:', n_times);
                            p_star = sc_sr1_infty( g, Psi,invM,gamma,delta,flag,show);

                        end


                    case 2
                        %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
                        %    Experiment #2
                        %%%%%%%%%%%%%%%%%%%
                        %  We need to ensure for experiment #2:
                        %      1. |Lambda(i,i)|<tau');
                        %      2. |g_par(i)|<tau


                        i_counter = randi([1 kp1]);  %randomly change one element of g_par

                        %  (1) |Lambda(i,i)|<tau
                        D(i_counter)      = -gamma;
                        invM        = R'*U*diag(1./D)*U'*R;
                        invM        = (invM+(invM)')./2;  %symmetrize invM

                        % (2) set (g_parallel(i)) such that [g_parallel(i_counter)=0 for i_counter
                        P_parallel  = Psi*(R\U);
                        g           = g-P_parallel(:,i_counter)*(P_parallel(:,i_counter)'*g);

                        % do n_times runs
                        flag = 1; %handing Psi and invM
                        for testruns = 1:n_times
                            if ith == testruns
                                show = 1;
                            else
                                show = 0;
                            end
                            fprintf('\nSolve %2d', testruns');
                            fprintf(' of %2d:', n_times);
                            i_counter = rank(Psi); %will be sorted in sc_scr1_infty
                            p_star = sc_sr1_infty( g, Psi,invM,gamma,delta,flag,show); %#ok<*NASGU>

                        end

                    case 3
                        %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
                        %    Experiment #3
                        %%%%%%%%%%%%%%%%%%%
                        %  We need to ensure for experiment #3:
                        %      1. |Lambda(i,i)|<tau');
                        %      2. |g_par(i)|>tau

                        i_counter = randi([1 kp1]);  %randomly change one element of g_par

                        %  (1) |Lambda(i,i)|<tau
                        D(i_counter)      = -gamma;
                        invM        = R'*U*diag(1./D)*U'*R;
                        invM        = (invM+(invM)')./2;  %symmetrize invM

                        % (2) |g_par(i)|>tau

                        P_parallel  = Psi*(R\U);
                        g_par       = P_parallel'*g;
                        if norm(g_par(i_counter),1)<1e-4
                            g = P_parallel(:,i_counter)*(P_parallel(i_counter)'*g);
                        end

                        % do n_times runs
                        flag = 1; %handing Psi and invM
                        for testruns = 1:n_times
                            if ith == testruns
                                show = 1;
                            else
                                show = 0;
                            end
                            fprintf('\nSolve %2d', testruns');
                            fprintf(' of %2d:', n_times);
                            i_counter = rank(Psi); %will be sorted in sc_scr1_infty
                            [p_star]= sc_sr1_infty( g, Psi,invM,gamma,delta,flag,show);

                        end

                    case 4
                        %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
                        %    Experiment #4
                        %%%%%%%%%%%%%%%%%%%
                        %  We need to ensure for experiment #4:
                        %      1. Lambda(i,i)<-tau');
                        %      2. |g_par(i)|<tau

                        i_counter = randi([1 kp1]);  %randomly change one element of g_par

                        % (1) modify eigenvalues of $B$ and re-form invM, leaving Psi unchanged
                        D           = max(abs(D),1e-4);  % threshold eigenvalues
                        D(i_counter)      = min([-rand(1)-gamma; (-1e-4)-gamma]);        %random value for eigenvalue
                        [D, ind3]   = sort(D);
                        U           = U(:,ind3);
                        i_counter   = 1;  %sorted to first position
                        invM        = R'*U*diag(1./D)*U'*R;  %modified so that M is still invertible but B is singular
                        invM        = (invM+(invM)')./2; %symmetrize it

                        % (2)
                        P_parallel  = Psi*(R\U);
                        g           = g-P_parallel(:,i_counter)*(P_parallel(:,i_counter)'*g);

                        % do n_times runs
                        flag = 1; %handing Psi and invM
                        for testruns = 1:n_times
                            if ith == testruns
                                show = 1;
                            else
                                show = 0;
                            end
                            fprintf('\nSolve %2d', testruns');
                            fprintf(' of %2d:', n_times);
                            [p_star,iExit]= sc_sr1_infty( g, Psi,invM,gamma,delta,flag,show);

                        end

                    case 5
                        %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
                        %    Experiment #5
                        %%%%%%%%%%%%%%%%%%%
                        %  We need to ensure for experiment #5:
                        %    1. |g_par(i)|>delta*|Lambda(i)|
                        %    2. |Lambda(i)|>tau

                        i_counter = randi([1 kp1]); %randomly change one element of g_par

                        % (1) ensure Lambda_ii>tau
                        D(i_counter) = max(abs(D(i_counter)),1e-3);
                        D           = diag(D);
                        invM        = R'*inv(U*D*U')*R;
                        invM        = (invM+(invM)')./2;

                        % (2) chose delta = 0.5*|g_par(i)|/|Lambda(i)|

                        % compute g_parallel(i) the exact same way that sc_sr1_infty.m does
                        % (copying code from sc_sr1_infty.m)
                        PsiPsi      = Psi(:,1:kp1)'*Psi(:,1:kp1);
                        [Ldl,Dldl,Pldl] = ldl(PsiPsi,'vector');  %ldl decomposition of PsiPsi'
                        Dldl=diag(Dldl);  %vectorize Dldl
                        maskldl = find(Dldl>(sqrt(eps)*max(Dldl)));
                        rankPsi = length(maskldl);     %compute rank of Psi
                        Pldl_fullRank = Pldl(maskldl);  %index of lin indep columns of Psi (used later)
                        R(1:rankPsi,:) = diag(sqrt(Dldl(maskldl)))*Ldl(:,maskldl)';
                        invP(Pldl)=1:kp1;
                        RMR         = R(1:rankPsi,invP)* (invM(1:kp1,1:kp1)\R(1:rankPsi,invP)');
                        RMR         = (RMR+(RMR)')./2;  %symmetrize RMR' to avoid complex
                        [U, D ]      = eig(RMR);
                        [D,ind]     = sort(real(diag(D)));  %D is now a vector; low to high
                        U           = U(:,ind);
                        i_counter   = rankPsi;  %sorted to the end
                        Lambda      = D + gamma.*ones(rankPsi,1);
                        Lambda      = Lambda.*(abs(Lambda)>tol); %thresholds
                        g_parallel  = U'*(R(1:rankPsi,maskldl)'\(Psi(:,Pldl_fullRank)'*g));

                        delta = 0.5*norm(g_parallel(i_counter)./Lambda(i_counter));  % <---- set delta *****

                        % do n_times runs
                        flag = 1; %handing Psi and invM
                        for testruns = 1:n_times
                            if ith == testruns
                                show = 1;
                            else
                                show = 0;
                            end
                            fprintf('\nSolve %2d', testruns');
                            fprintf(' of %2d:', n_times);
                            [p_star,iExit]= sc_sr1_infty( g, Psi,invM,gamma,delta,flag,show);

                        end


                end %switch for (P,infinity) norm

            end %norm_type
        end%for loop

        fprintf('\n');

    end
end

