function PrintStateSpaceForm(ResFile,DSGEModel,CurrINI,A,H,R,F,B0,NumEstParam,NumParam,EstType)
% PrintStateSpaceForm: Prints the state space form of the DSGE model to textfile for the
%                      initial or the posterior mode parameter values.
%
% USAGE:
%
%       PrintStateSpaceForm(ResFile,DSGEModel,CurrINI,A,H,R,F,B0,NumEstParam,NumParam,EstType)
%
% REQUIRED INPUT: ResFile (string vector) with the full path+name of the file to be printed.
%
%                 DSGEModel (structure) with fields containing all the information about a DSGE Model for YADA.
%
%                 CurrINI (structure) with initialization information.
%
%                 A (kxn) matrix with coefficients on the exogenous variables in the measurement equation.
%
%                 H (rxn) matrix with cofficients on the state variables in the measurement equation.
%
%                 R (nxn) matrix with the covariances of the measurement errors.
%
%                 F (rxr) transition matrix for the state variables.
%
%                 B0 (rxq) matrix with coefficients on the economic shocks in the state equation.
%
%                 NumEstParam (integer) with the number of parameters to estimate.
%
%                 NumParam (integer) with the total number of parameters.
%
%                 EstType (string vector) that takes on the values "Initial Values" or "Posterior Mode".
%
%
%                       Written by: Anders Warne
%                                   New Area Wide Model Project
%                                   DG-R/EMO
%                                   European Central Bank (ECB)
%                                   Email: anders.warne@ecb.europa.eu
%                                   Copyright © 2006-2009 European Central Bank.
%
%                       First version: December 12, 2007.
%                        This version: January 21, 2009.
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% LICENSE INFORMATION:
%
%      YADA is free software: you can redistribute it and/or modify
%      it under the terms of the GNU General Public License as published by
%      the Free Software Foundation, either version 3 of the License, or
%      (at your option) any later version.
%
%      This program is distributed in the hope that it will be useful,
%      but WITHOUT ANY WARRANTY; without even the implied warranty of
%      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
%      GNU General Public License for more details.
%
%      You should have received a copy of the GNU General Public License
%      along with this program.  If not, see <http://www.gnu.org/licenses/>.
%
%      YADA is released under the GNU General Public License, Version 3,
%      29 June 2007 <http://www.gnu.org/licenses/>. The current release of
%      the program was last modified by the ECB on the "This version" date
%      above.
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% CHANGELOG:
%
% * 23-5-2008:  Updated the documentation.
%
% * 3-7-2008:   Made sure that a state variable that is zero is also displayed as being equal to sero.
%
% * 23-10-2008: Added the input variables "NumEstParam" and "NumParam".
%
% * 21-01-2009: Updated the documentation.
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%

%
% first remove redundant columns from B0
%
[B0,KeepShocks] = RemoveRedundantColumns(B0);
if isempty(B0)==1;
   %
   % if the output file exists, delete it
   %
   if FileExist(ResFile)==1;
      stat = dos(['del /Q "' ResFile '"']);
   end;
   %
   txt = ['All economic shocks are redundant, i.e., the B0 matrix is a zero matrix. YADA is therefore unable to display the state-space form at ' lower(EstType) '.'];
   About(txt,'information','YADA - State Space Form',120,500,CurrINI);
   return;
end;
ShockNames = DSGEModel.StateShockNames(KeepShocks,:);
if rank(R)>0;
   [Rm,Lm] = SchurDecomposition(R);
   Rmeasure = TinyToZero(Rm*sqrt(Lm));
   NumMeasure = size(Lm,1);
else;
   Rmeasure = [];
   NumMeasure = 0;
end;
n = size(DSGEModel.Y,1);
k = size(DSGEModel.X,1);
r = size(F,1);
q = length(KeepShocks);
%
% make sure that very small numbers are set to zero
%
B0 = TinyToZero(B0);
F = TinyToZero(F);
if k>0;
   A = TinyToZero(A);
end;
H = TinyToZero(H);
%
% open the file
%
fid = fopen(ResFile,'wt');
%
fprintf(fid,'********************************************************************************\n');
fprintf(fid,'*                                                                              *\n');
fprintf(fid,'*                       S T A T E - S P A C E   F O R M                        *\n');
fprintf(fid,'*                                                                              *\n');
fprintf(fid,'********************************************************************************\n\n');
%
% Model info
%
fprintf(fid,'Name of model:                    %s\n',DSGEModel.NameOfModel);
fprintf(fid,'Data construction file:           %s\n',GetFilename(DSGEModel.DataConstructionFile));
fprintf(fid,'Measurement equation file:        %s\n',GetFilename(DSGEModel.MeasurementEquationFile));
fprintf(fid,'Prior distribution data file:     %s\n',GetFilename(DSGEModel.PriorFile));
fprintf(fid,'Sheet name:                       %s\n',DSGEModel.PriorFileSheet);
if FileExist(DSGEModel.UpdateParameterFile)==1;
   fprintf(fid,'Update parameters file:           %s\n',GetFilename(DSGEModel.UpdateParameterFile));
end;
if FileExist(DSGEModel.InitializeParameterFile)==1;
   fprintf(fid,'Initialize parameters file:       %s\n',GetFilename(DSGEModel.InitializeParameterFile));
end;
fprintf(fid,'AiM model file:                   %s\n\n',GetFilename(DSGEModel.AIMFile));
%
% data information
%
fprintf(fid,'Number of observed variables:     %0.0f\n',n);
fprintf(fid,'Number of exogenous variables:    %0.0f\n',k);
fprintf(fid,'Number of state variables:        %0.0f\n',r);
fprintf(fid,'Number of non-zero state shocks:  %0.0f\n',q);
fprintf(fid,'Number of measurement errors:     %0.0f\n\n',NumMeasure);
%
% observed variable names, state variable names and state shocks
%
VarNames = StrWrap(vecstr(DSGEModel.VariableNames,' '),40);
fprintf(fid,'Names of observed variables:      %s\n',VarNames(1,:));
for i=2:size(VarNames,1);
   if strcmp(StringTrim(VarNames(i,:)),'')==0;
      fprintf(fid,'                                  %s\n',VarNames(i,:));
   end;
end;
if min(size(DSGEModel.X))>0;
   XVarNames = StrWrap(vecstr(DSGEModel.XVariableNames,' '),40);
   fprintf(fid,'Names of exogenous variables:     %s\n',XVarNames(1,:));
   for i=2:size(XVarNames,1);
      if strcmp(StringTrim(XVarNames(i,:)),'')==0;
         fprintf(fid,'                                  %s\n',XVarNames(i,:));
      end;
   end;
end;
StateVarNames = StrWrap(vecstr(DSGEModel.StateVariableNames,' '),40);
fprintf(fid,'Names of state variables:         %s\n',StateVarNames(1,:));
for i=2:size(StateVarNames,1);
   if strcmp(StringTrim(StateVarNames(i,:)),'')==0;
      fprintf(fid,'                                  %s\n',StateVarNames(i,:));
   end;
end;
StateShockNames = StrWrap(vecstr(ShockNames,' '),40);
fprintf(fid,'Names of the state shocks:        %s\n',StateShockNames(1,:));
for i=2:size(StateShockNames,1);
   if strcmp(StringTrim(StateShockNames(i,:)),'')==0;
      fprintf(fid,'                                  %s\n',StateShockNames(i,:));
   end;
end;
%
% parameter info
%
fprintf(fid,'\nNumber of parameters to estimate: %0.0f\n',NumEstParam);
fprintf(fid,'Total number of parameters:       %0.0f\n',NumParam);
%
% First we print the measurement equation
%
fprintf(fid,'\n********************************************************************************\n');
fprintf(fid,'*                                                                              *\n');
fprintf(fid,'*                   M E A S U R E M E N T   E Q U A T I O N                    *\n');
fprintf(fid,'*                                                                              *\n');
fprintf(fid,'********************************************************************************\n\n');
%
for i=1:n;
   %
   % set up a string vector that we shall wrap before we print to file
   %
   VariableName = StringTrim(DSGEModel.VariableNames(i,:));
   if size(VariableName,2)<size(DSGEModel.VariableNames,2);
      VariableName = [VariableName '(t)' SpaceStr(size(DSGEModel.VariableNames,2)-size(VariableName,2))];
   else;
      VariableName = [VariableName '(t)'];
   end;
   MEStr = [VariableName ' = '];
   InitStr = SpaceStr(size(MEStr,2));
   for j=1:k;
      if isequal(A(j,i),0)==0;
         XVariableName = StringTrim(DSGEModel.XVariableNames(j,:));
         if (length(XVariableName)>=3)&(strcmp(lower(XVariableName(1,1:3)),'con')==1);
            MEStr = [MEStr sprintf('%0.4f*%s + ',A(j,i),XVariableName)];
         else;
            MEStr = [MEStr sprintf('%0.4f*%s(t) + ',A(j,i),XVariableName)];
         end;
      end;
   end;
   for j=1:r;
      if isequal(H(j,i),0)==0;
         MEStr = [MEStr sprintf('%0.4f*%s(t) + ',H(j,i),StringTrim(DSGEModel.StateVariableNames(j,:)))];
      end;
   end;
   for j=1:NumMeasure;
      if isequal(Rmeasure(i,j),0)==0;
         MEStr = [MEStr sprintf('%0.4f*Error%0.0f(t) + ',Rmeasure(i,j),j)];
      end;
   end;
   %
   % remove the last 2 characters
   %
   MEStr = MEStr(1:length(MEStr)-3);
   %
   % wrap the string
   %
   MEStr = StrWrap(MEStr,80);
   for j=1:size(MEStr,1);
      if j>1;
         fprintf(fid,'%s%s\n',InitStr,MEStr(j,:));
      else;
         fprintf(fid,'%s\n',MEStr(1,:));
      end;
   end;
   fprintf(fid,'\n');
end;
%
% now we turn to the state equations
%
fprintf(fid,'********************************************************************************\n');
fprintf(fid,'*                                                                              *\n');
fprintf(fid,'*                         S T A T E   E Q U A T I O N                          *\n');
fprintf(fid,'*                                                                              *\n');
fprintf(fid,'********************************************************************************\n\n');
%
for i=1:r;
   %
   % set up a string vector that we shall wrap before we print to file
   %
   StateVariableName = StringTrim(DSGEModel.StateVariableNames(i,:));
   if size(StateVariableName,2)<size(DSGEModel.StateVariableNames,2);
      StateVariableName = [StateVariableName '(t)' SpaceStr(size(DSGEModel.StateVariableNames,2)-size(StateVariableName,2))];
   else;
      StateVariableName = [StateVariableName '(t)'];
   end;
   SEStr = [StateVariableName ' = '];
   InitStr = SpaceStr(size(SEStr,2));
   NumPrt = 0;
   for j=1:r;
      if isequal(F(i,j),0)==0;
         SEStr = [SEStr sprintf('%0.4f*%s(t-1) + ',F(i,j),StringTrim(DSGEModel.StateVariableNames(j,:)))];
         NumPrt = 1;
      end;
   end;
   %
   for j=1:q;
      if isequal(B0(i,j),0)==0;
         SEStr = [SEStr sprintf('%0.4f*%s(t) + ',B0(i,j),StringTrim(ShockNames(j,:)))];
         NumPrt = 1;
      end;
   end;
   %
   % remove the last 2 characters
   %
   if NumPrt==1;
      SEStr = SEStr(1:length(SEStr)-3);
   else;
      SEStr = [SEStr '0'];
   end;
   %
   % wrap the string
   %
   SEStr = StrWrap(SEStr,80);
   for j=1:size(SEStr,1);
      if j>1;
         fprintf(fid,'%s%s\n',InitStr,SEStr(j,:));
      else;
         fprintf(fid,'%s\n',SEStr(1,:));
      end;
   end;
   fprintf(fid,'\n');
end;
%
%
% bottom file data
%
fprintf(fid,'********************************************************************************\n\n');
fprintf(fid,'Directory for file: %s\n',GetPath(ResFile));
fprintf(fid,'Name of file:       %s\n',GetFilename(ResFile));
fprintf(fid,'Output created on:  %s\n\n',datestr(now,0));
fclose(fid);

%
% end of PrintStateSpaceForm.m
%
