function [ FCVARoptions ] = AdjustEstnOptions(db0, k, r, p, initialFCVARoptions)
% 
% function [ FCVARoptions ] = AdjustEstnOptions(db0, k, r, p, initialFCVARoptions)
% Lee Morin & Morten Nielsen
% August 26, 2011
%
% 
% AdjustEstnOptions(db0, k, r, p, initialFCVARoptions) completes the specification 
%   of the options array, initialized by DefaultEstnOptions(db0, k, r, p)
%   or RestrictEstnOptions(db0, k, r, p, defaultFCVARoptions).
% 
% 
% input = vector or scalar db0 of fractional differencing parameters.
%       The size of db0 indicates whether or not restriction d = b is imposed
%           based on the number of free parameters.
%       scalars k, r and p denote the number of lags, cointegrating rank
%           and the number of variables, respectively.
%       array of arrays initialFCVARoptions contains the preliminary
%           specification of FCVARoptions initialized by DefaultEstnOptions(db0, k, r, p)
%           or RestrictEstnOptions(db0, k, r, p, defaultFCVARoptions).
%
% 
% output = cell array FCVARoptions = { dbEstnOptions, EstnOptions }, an array 
%	of 2 arrays of options with the same form as initialFCVARoptions.
% 
% dbEstnOptions is an array of options for the estimation of the fractional differencing parameters d and b.
% dbEstnOptions = { constrained, C_db, c_db, R_db, r_db, dbFminOptions }
%   constrained is an indicator for the restriction that dbMax >= d >= b >= dbMin.
%   C_db and c_db are the matrices that specify the above restriction.
%   dbMax is an upper bound for the estimation of d and b.
%   dbMin is a lower bound for the estimation of d and b.
%   R_db and r_db are optional matrices for defining restrictions of the form R_db*db = r_db.
%   dbFminOptions is an array of options for built-in matlab functions.
% 
%   EstnOptions is an array of options for estimating the remaining parameters.
%   EstnOptions = { N, M, deterministics, R_Gamma, r_Gamma, [], [], [],
%                   nCols, A, H, a, b, [], {}, {}, {}, {}, 
%                   [], [], [], print2screen, printGammas, printRoots,
%                   restrictFminOptions }
%       which is changed to 
%   EstnOptions = { N, M, deterministics, R_Gamma, r_Gamma, [], [], [],
%                   nCols, A, H, a, b, [], Abar, Aperp, replaceCols, keepCols,
%                   [], [], [], print2screen, printGammas, printRoots,
%                   restrictFminOptions }
%
%   A and H are replaced with identities where no restrictions are specified.
%   Abar is an array of matrices such that Abar_i'*A_i = I.
%   Aperp is an array of matrices such that Aperp_i'*A_i = 0.
%       Note that Abar and Aperp are defined using lower case a in case
%       known restrictions are placed on alpha.
%   replaceCols and keepCols are arrays of vectors specifying the column
%       numbers that are replaced or assumed known in each stage of the switching algorithm.
% 
%   The rest of the options are as defined in DefaultEstnOptions.
%______________________________________________________



% Set numerical optimization settings for the optimization over d and b.
dbEstnOptions = initialFCVARoptions{1};

% Constrain optimization so that dbMax > d >= b > 0.
constrained = dbEstnOptions{1};
dbMax = dbEstnOptions{2};
dbMin = dbEstnOptions{3};

% For default case, dbMax should be the scalar dbMax, 
%   then the matrices C_db and c_db will be generated here
%   and will replace dbMax and dbMin,
%   else for restricted case, C_db and c_db are already adjusted.
if (numel(dbMax) == 1) && (numel(dbMin) == 1)
    
    if ( length(db0) == 1 ) && constrained
        C_db = [ -1; 1 ];
        c_db = [ -dbMin; dbMax ];
    elseif ( length(db0) == 2 ) && constrained
        C_db = [ -1 1; 0 -1; 1 0 ];
        c_db = [ 0; -dbMin; dbMax ];
    else
        C_db = [];
        c_db = [];
    end
    % Constrains d and b so that C_db*dbHat <= c_db.

    dbEstnOptions{2} = C_db;
    dbEstnOptions{3} = c_db;
end






% Now generate restriction matrices corresponding to primary specifications.
EstnOptions = initialFCVARoptions{2};
% EstnOptions = { N, M, deterministics, R_Gamma, r_Gamma, [], [], [],...
%                   nCols, A, H, a, b, [], Abar, Aperp, replaceCols, keepCols, 
%                   [], [], [], print2screen, printGammas, printRoots, RestFminOptions };



% Set restrictions on Gamma (pk x p) matrix if required.

deterministics = EstnOptions{3};
R_Gamma = EstnOptions{4};
if ~isempty(R_Gamma)
    r_Gamma = zeros(size(R_Gamma, 1), 1);
    EstnOptions{5} = r_Gamma;
end
% Note: Does not allow user to impose nonzero restrictions.




% Now adjust the array of arrays, { nCols, A, H, a, b }, each element of which has blanks
% wherever not specified.

% Recall:
% EstnOptions = { N, M, deterministics, R_Gamma, r_Gamma, [], [], [],...
%                   nCols, A, H, a, b, [], Abar, Aperp, replaceCols, keepCols, 
%                   [], [], [], print2screen, printGammas, printRoots, RestFminOptions };
nCols = EstnOptions{9};
nRestns = length(nCols);    % Note: nRestns = 0 when nCols = [].
A = EstnOptions{10};
H = EstnOptions{11};
a = EstnOptions{12};
b = EstnOptions{13};
% To be filled in from blanks.
% Note: All the arrays above must be the same length.
%   Initialized with empty arrays to allow additional elements.
Abar = EstnOptions{15};
Aperp = EstnOptions{16};
replaceCols = EstnOptions{17};
keepCols = EstnOptions{18};

% Define p1 to be number of rows of betaStar.
p1 = p + strcmp(deterministics, 'restricted constant');


% Modify the specification of restrictions.
% Loop on j for usual case (special cases later).
% Note: nRestns = 0 when nCols = [] so this step is skipped if no restrictions are specified.
for j = 1:nRestns 
    
    % Hypotheses of the form alpha = (A_1*psi_1,...A_rA*psi_rA)
    %   where A_i is p x m_i, psi_i is m_i x r_i and sum(r_i) = r.
    if isempty(A{j})
        A{j} = eye(p);
    end
    
    % Hypotheses of the form beta = (H_1*phi_1,...H_rH*phi_rH)
    %   where H_i is p1 x s_i, phi_i is s_i x r_i and sum(r_i) = r.
    if isempty(H{j})
        H{j} = eye(p1);
    end
    
    % Choose restrictions for known parameters.
    % a and b allow for a  column of alpha or beta to be fixed.
    % Note that known restrictions override linear restrictions in case the
    % user specifies both.
    
    
    % Calculate M-P inverse of Aj.
    Abar{j} = A{j}*inv(A{j}'*A{j});
    if ~isempty(a{j})
        % In this case, Abar{j} is defined from the lower case (known) a{j}.
        Abar{j} = a{j}*inv(a{j}'*a{j});
    end

    % Calculate matrix spanning orthogonal subspace of Aj.
    if size(A{j},2) == p
        % Blank if Aj = eye(p) (ie: no restrictions).
        Aperp{j} = [];
    elseif size(A{j},2) < p
        Aperp{j} = null( A{j}' );
    end
    if ~isempty(a{j})
        % In this case, Aperp{j} is orthogonal to the lower case (known) a{j}.
        Aperp{j} = null( Abar{j}' );
    end
    
    % Determine relevant columns of beta0 to keep or drop on each iteration.
    replaceCols{j} = sum(nCols( (1:r) < j )) + 1 : sum(nCols( (1:r) < j + 1 ));
    keepCols{j} = [ ( 1 : sum(nCols( (1:r) < j )) )     ( sum(nCols( (1:r) < j + 1 )) + 1 : r ) ];
    
end




% Now replace and create the restriction arrays as outputs.
EstnOptions{10} = A;
EstnOptions{11} = H;
% Unchanged:
% a = EstnOptions{12};
% b = EstnOptions{13};
% Newly created:
EstnOptions{15} = Abar;
EstnOptions{16} = Aperp;
EstnOptions{17} = replaceCols;
EstnOptions{18} = keepCols;




% Now put together the adjusted version of the options array.
% dbEstnOptions carries the options for the estimation of fractional parameters.
% EstnOptions carries the options for all other functions and restrictions.
FCVARoptions = { dbEstnOptions, EstnOptions};



% end