function [ restrictFCVARoptions ] = RestrictEstnOptions(db0, k, r, p, defaultFCVARoptions)
% 
% function [ restrictFCVARoptions ] = RestrictEstnOptions(db0, k, r, p, defaultFCVARoptions)
% Lee Morin & Morten Nielsen
% August 26, 2011
%
% 
% RestrictEstnOptions(db0, k, r, p, defaultFCVARoptions) returns a set of preliminary 
%       setings corresponding to the restrictions on parameters specified below.
% 
% These options are later processed by AdjustEstnOptions(db0, k, r, p, initialFCVARoptions),
%       which completes the specification of the options array.
% 
% 
% 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 defaultFCVARoptions contains the preliminary specification
%           of FCVARoptions, which is output from DefaultEstnOptions(db0, k, r, p).
% 
% 
% output = cell array restrictFCVARoptions of options for use in estimation routines.
% 
% restrictFCVARoptions = { dbEstnOptions, EstnOptions }, an array of 2 arrays.
% 
% 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 (numerical optimization) 
%		functions for the optimization over d and b.
% 
% EstnOptions is a cell array of options for estimating the remaining parameters.
% EstnOptions = { N, M, deterministics, R_Gamma, r_Gamma, [], [], [],
%                   nCols, A, H, a, b, [], Abar, Aperp, replaceCols, keepCols,
%                   [], [], [], print2screen, printGammas,
%                   restrictFminOptions }
%   scalar N is the number of initial values of x that are conditioned upon in the estimation.
%   scalar M is the number of MA lags in the fractional differencing operator.
%       If M is positive, the fractional differencing filter is truncated at lag M.
%   string deterministics is a switch to determine if, eg. a 'restricted constant'
%       term should be added to the model.
%   R_Gamma and r_Gamma are optional matrices for defining restrictions of the
%       form R_Gamma*Gamma = r_Gamma (intended for exclusion restrictions only).
%   nCols, A, H, a, b are optional matrices for use when estimating with Johansens's switching algorithm.
%       nCols is a vector of dimensions r_i of the partitioned matrices of alpha and beta,
%       	where sum(r_i) = r.
%   	A is an array of linear restrictions on each alpha such that alpha_i = A_i*psi_i.
%   	H is an array of linear restrictions on each beta such that beta_i = H_i*phi_i.
%			Note that if there is a constant in the model, beta_i is really betaStar_i = ( beta_i', rho_i')'
%   	a is an array of values of alpha considered known.
%   	b is an array of values of beta considered known.
%			Note that if there is a constant in the model, beta_i is really betaStar_i = ( beta_i', rho_i')'
%   print2screen is a scalar indicator to print results (in RankTests and FCVARestn) 
%      to screen and to generate graphs of characteristic roots.
%   printGammas is a scalar indicator to print coefficients of lagged differences as well.
%   printRoots is a scalar indicator to also print and plot roots of the characteristic polynomial.
%   restrictFminOptions is an array of options for optimization over alpha and beta in the 
%       switching algorithm implemented in GetParamsSwitching.
%______________________________________________________



% Extract array of options from unrestricted model.
dbEstnOptions = defaultFCVARoptions{1};
EstnOptions = defaultFCVARoptions{2};

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


% Specify constraints for optimization with fractional differencing parameters.
% Specify linear restrictions on d and b: R_db*dbHat = r_db.
R_db = [];
r_db = [];
% Example1: d = 0.7 (for case of two fractional parameters).
% R_db = [ 1 0 ];
% r_db = 0.7;
% Example2: d = b = 1 (for case of one fractional parameter).
% R_db = [ 1 ];
% r_db = 1;
dbEstnOptions{4} = R_db;
dbEstnOptions{5} = r_db;


% Additional restrictions can be set to impose the restriction.
C_db = dbEstnOptions{2};
c_db = dbEstnOptions{3};
% Modify C_db and c_db as desired here to impose linear inequality restrictions.
% Note: If C_db is a matrix, AdjustEstnOptions does not modify C_db or c_db, so
%	that the only linear inequality restrictions imposed are those given here (i.e.
%	the constraint indicated by 'constrained' would need to be imposed manually).
% C_db = ...
% c_db = ...
dbEstnOptions{2} = C_db;
dbEstnOptions{3} = c_db;



% Specify additional options in case Gamma or [ alpha, beta, rho ] are restriced.

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

% Example1: Restrict the top row of all Gamma matrices to be zero:
% R_Gamma = [ eye(p*k) zeros(p*k, (p-1)*p*k) ];
% Example2: Restrict the first 2 rows of the first Gamma matrix to be zero:
% R_Gamma = [ eye(p) zeros(p, p*p*k-p);...
%             zeros(p,p*k) eye(p) zeros(p, (p-1)*p*k-p) ];

% Note that only zero restrictions are permitted (only ones and zeros 
% 	in the entries in R_Gamma).
% Note that the dimensions must conform to the data.
% Otherwise, if no restrictions, leave R_Gamma blank.
R_Gamma = [];
% r_Gamma left blank here and created automatically by AdjustEsntOptions.



% Specify restrictions designed for switching algorithm.

% Specify as an array of matrices, { nCols, A, H, a, b }, each of which have blanks
%   wherever not specified.
% AdjustEsntOptions will fill in zeros and identities where appropriate
%   and produce Abar and APerp, etc as needed.

% First set list of column widths for partitions of alpha and beta matrices.
% Note that each of { nCols, A, H, a, b } must have the same number of elements.
% Elements of nCols correspond to r_i's below.
nCols = [ 1 ];
% No restrictions implied if nCols is left blank.
% Examples for r=2:
% nCols = [ 1 1 ];  % Partition alpha and beta into 2 matrices, each with one column.
% nCols = [ 2 ];    % Keep alpha and beta as single matrices with 2 (=r) columns.
% nCols = [  ];     % Ignores any restrictions below in { A, H, a, b }.



% Choose linear restrictions for alpha.
% Hypotheses of the form alpha = (A_1*psi_1, ... , A_rA*psi_rA)
%   where A_i is p x s_i, psi_i is s_i x r_i and sum(r_i) = r.
% Note that alpha partition must conform to that for beta (same r_i's).
A1 = [1 0; 0 1; 0 0; 0 0];
A2 = [];
A = { A1, A2 };


% Choose linear restrictions for beta.
% Hypotheses of the form beta = (H_1*phi_1,...H_rH*phi_rH)
%   where H_i is p x s_i, phi_i is s_i x r_i and sum(r_i) = r.
H1 = [1 0 0; -1 0 0; 0 1 0; 0 -1 0; 0 0 1];
H2 = [];
H = { H1, H2 };
% Note that if there is a constant in the model, beta_i is really betaStar_i = ( beta_i', rho_i')'


% Choose restrictions for known parameters.
% a and b allow for columns of alpha and/or beta to be fixed and considered known.
% AdjustEsntOptions will later organize the a, b, A and H matrices.
% User must take care not to jointly specify linear and known restrictions
% 	on the same columns of beta or alpha (if both are specified, only the known
%	alpha/beta restriction will be applied).

% Restrict some columns of alpha to known values.
a1 = [];
a2 = [];
a = { a1, a2 };

% Restrict some columns of beta to known values.
b1 = [];
b2 = [];
b = { b1, b2 };
% Note that if there is a constant in the model, beta_i is really betaStar_i = ( beta_i', rho_i')'




% Collect these options in a single array.
% EstnOptions = { N, M, deterministics, R_Gamma, r_Gamma, [], [], [],
%                   nCols, A, H, a, b, [], [], [], [], [], 
%                   [], [], [], print2screen, printGammas, restrictFminOptions },
%     the rest of which is filled in by the function AdjustEstnOptions.
EstnOptions{4} = R_Gamma;
EstnOptions{5} = [];
EstnOptions{9} = nCols;
EstnOptions{10} = A;
EstnOptions{11} = H;
EstnOptions{12} = a;
EstnOptions{13} = b;


% The options are carried through all functions as needed.
% dbEstnOptions carries the options for the estimation of fractional parameters.
% EstnOptions carries the options for all other functions and restrictions.
restrictFCVARoptions = { dbEstnOptions, EstnOptions };


% Complete the specification of options using AdjustEstnOptions.
[ restrictFCVARoptions ] = AdjustEstnOptions(db0, k, r, p, restrictFCVARoptions);

% Print restrictions.
fprintf(1, '-----------------------------------------------------------------------------------------------------\n');
fprintf(1, '-----------------------------------------------------------------------------------------------------\n');
fprintf(1, '       Restrictions Imposed\n');
fprintf(1, '-----------------------------------------------------------------------------------------------------\n');
% Print restrictions imposed on d,b.
if length(r_db) > 0
    fprintf(1, 'Restrictions on db:');
    R_db = R_db
    r_db = r_db
end

% Print restrictions imposed on Gamma.
if size(R_Gamma,2) > 0
    fprintf(1, 'Restrictions on Gamma:');
    R_Gamma = R_Gamma
    r_Gamma = r_Gamma
end

% Print restrictions imposed on alpha,beta,rho.
nRestns = length(nCols);
if nRestns > 0
    for j = 1:nRestns
        if size(H{j}, 2) < p1
            fprintf(1, 'Linear restrictions on beta[%d', j);
            fprintf(1, ']:');
            H{j}
        end
        if size(A{j}, 2) < p
            fprintf(1, 'Linear restrictions on alpha[%d', j);
            fprintf(1, ']:');
            A{j}
        end
        if ~isempty(b{j})
            fprintf(1, 'Known values for beta[%d', j);
            fprintf(1, ']:');
            b{j}
        end
        if ~isempty(a{j})
            fprintf(1, 'Known values for alpha[%d', j);
            fprintf(1, ']:');
            a{j}
        end
    end
end



% end