From 229282a1c4752b3245b7c27079cf4c65a589b434 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Villemot?= Date: Tue, 20 Jul 2021 12:35:15 +0200 Subject: [PATCH] Occbin: the +/occbin_difference.m file is now generated by the preprocessor Some fields have also changed under M_.occbin. Ref. #569 --- license.txt | 2 - matlab/+occbin/DSGE_smoother.m | 6 +- matlab/+occbin/check_regimes.m | 7 +- matlab/+occbin/get_info.m | 57 ------------- matlab/+occbin/initialize.m | 75 ----------------- matlab/+occbin/kalman_update_algo_1.m | 25 +++--- matlab/+occbin/kalman_update_algo_3.m | 27 +++---- matlab/+occbin/process_constraint.m | 81 ------------------- matlab/+occbin/process_error_constraint.m | 35 -------- matlab/+occbin/solve_one_constraint.m | 6 +- matlab/+occbin/solve_two_constraints.m | 12 +-- matlab/+occbin/tokenize.m | 66 --------------- matlab/dsge_likelihood.m | 1 - .../missing_observations_kalman_filter.m | 2 +- matlab/missing_DiffuseKalmanSmootherH3_Z.m | 2 +- preprocessor | 2 +- tests/occbin/model_borrcon/borrcon.mod | 6 +- .../model_borrcon/borrcon_0_std_shocks.mod | 4 +- .../model_irrcap_twoconstraints/dynrbc.mod | 0 19 files changed, 47 insertions(+), 369 deletions(-) delete mode 100644 matlab/+occbin/get_info.m delete mode 100644 matlab/+occbin/initialize.m delete mode 100644 matlab/+occbin/process_constraint.m delete mode 100644 matlab/+occbin/process_error_constraint.m delete mode 100644 matlab/+occbin/tokenize.m mode change 100755 => 100644 tests/occbin/model_irrcap_twoconstraints/dynrbc.mod diff --git a/license.txt b/license.txt index 0ea723600..d5488b35a 100644 --- a/license.txt +++ b/license.txt @@ -46,10 +46,8 @@ Files: matlab/+occbin/make_chart.m matlab/+occbin/mkdata.m matlab/+occbin/mkdatap_anticipated_2constraints_dyn.m matlab/+occbin/mkdatap_anticipated_dyn.m - matlab/+occbin/process_constraint.m matlab/+occbin/solve_one_constraint.m matlab/+occbin/solve_two_constraints.m - matlab/+occbin/tokenize.m Copyright: none License: public-domain-occbin Original authors: Luca Guerrieri and Matteo Iacoviello diff --git a/matlab/+occbin/DSGE_smoother.m b/matlab/+occbin/DSGE_smoother.m index 9ab36a10d..3b8935364 100644 --- a/matlab/+occbin/DSGE_smoother.m +++ b/matlab/+occbin/DSGE_smoother.m @@ -108,12 +108,10 @@ opts_simul.periods = options_.occbin.smoother.periods; opts_simul.check_ahead_periods = options_.occbin.smoother.check_ahead_periods; opts_simul.full_output = options_.occbin.smoother.full_output; opts_simul.piecewise_only = options_.occbin.smoother.piecewise_only; -constraints = M_.occbin.constraint; % init_mode = options_.occbin.smoother.init_mode; % 0 = standard; 1 = unconditional frcsts zero shocks+smoothed states in each period % init_mode = 0; occbin_options = struct(); -occbin_options.constraints = constraints; occbin_options.first_period_occbin_update = options_.occbin.smoother.first_period_occbin_update; occbin_options.opts_regime = opts_simul; % this builds the opts_simul options field needed by occbin.solver occbin_options.opts_regime.binding_indicator = options_.occbin.likelihood.init_binding_indicator; @@ -207,7 +205,7 @@ while is_changed && maxiter>iter && ~is_periodic opts_regime.regime_history = regime_history; [TT, RR, CC, regime_history] = occbin.check_regimes(TT, RR, CC, opts_regime, M_, oo_, options_); is_changed = ~isequal(regime_history0(iter,:),regime_history); - if length(constraints)==2 + if M_.occbin.constraint_nbr==2 for k=1:size(regime_history0,2) isdiff_regime(k,1) = ~isequal(regime_history0(end,k).regime1,regime_history(k).regime1); isdiff_start(k,1) = ~isequal(regime_history0(end,k).regimestart1,regime_history(k).regimestart1); @@ -257,7 +255,7 @@ while is_changed && maxiter>iter && ~is_periodic regime_new = regime_; start_ = regime_; start_new = regime_; - if length(constraints)==2 + if M_.occbin.constraint_nbr==2 indx_init_1 = find(isdiff_(:,1)); if ~isempty(indx_init_1) qq={regime_history0(end,indx_init_1).regime1}'; diff --git a/matlab/+occbin/check_regimes.m b/matlab/+occbin/check_regimes.m index 7e49a4a78..18fef84a0 100644 --- a/matlab/+occbin/check_regimes.m +++ b/matlab/+occbin/check_regimes.m @@ -40,9 +40,8 @@ gend = size(binding_indicator,1); if gend ==0 gend = length(regime_history)+1; end -number_of_constraints = length(M_.occbin.constraint); -if number_of_constraints==1 +if M_.occbin.constraint_nbr==1 base_regime.regime = 0; base_regime.regimestart = 1; else @@ -71,7 +70,7 @@ opts_simul.piecewise_only=1; for tp=1:gend-1 change_it = 0; if ~isempty(binding_indicator) - if number_of_constraints==1 + if M_.occbin.constraint_nbr==1 if regime_history(tp).regime(1) > binding_indicator(tp+1,1) regime_history(tp).regime = [0 regime_history(tp).regime]; regime_history(tp).regimestart = [1 regime_history(tp).regimestart+1]; @@ -123,7 +122,7 @@ for tp=1:gend-1 RR(:,:,tp+1) = RR(:,:,jt); CC(:,tp+1) = CC(:,jt); else - if number_of_constraints==1 + if M_.occbin.constraint_nbr==1 nperi = max(regime_history(tp).regimestart); else nperi = max([regime_history(tp).regimestart1 regime_history(tp).regimestart2]); diff --git a/matlab/+occbin/get_info.m b/matlab/+occbin/get_info.m deleted file mode 100644 index 05317299e..000000000 --- a/matlab/+occbin/get_info.m +++ /dev/null @@ -1,57 +0,0 @@ -function M_ = get_info(M_) -%function M_ = get_info(M_) -% Parses constraint to clean spaces and provide information on endogenous variables -% involved in constraints -% -% INPUTS -% - M_ [struct] Definition of the model. -% -% OUTPUTS -% - M_ [struct] Definition of the model. - -% Copyright (C) 2021 Dynare Team -% -% This file is part of Dynare. -% -% Dynare 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. -% -% Dynare 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 Dynare. If not, see . - -delimiters = char(',',';','(',')','+','-','^','*','/','>','<','='); -iwish=0; -indx_=[]; -wish_list=''; -M_.occbin.constraint_nbr=length(M_.occbin.constraint); -for k=1:M_.occbin.constraint_nbr - %get rid of redundant spaces; - M_.occbin.constraint(k).bind=strrep(M_.occbin.constraint(k).bind,' ',''); - M_.occbin.constraint(k).relax=strrep(M_.occbin.constraint(k).relax,' ',''); - bind_clean = occbin.tokenize(M_.occbin.constraint(k).bind,delimiters); - relax_clean = occbin.tokenize(M_.occbin.constraint(k).relax,delimiters); - for j=1:M_.endo_nbr - tmp=ismember(M_.endo_names{j},bind_clean); - tmp1=ismember(M_.endo_names{j},relax_clean); - if tmp || tmp1 - iwish = iwish+1; - indx_(iwish)=j; - if iwish>1 - wish_list = char(wish_list,M_.endo_names{j}); - else - wish_list = M_.endo_names{j}; - end - end - end -end - -M_.occbin.wish_list.endo = wish_list; -M_.occbin.wish_list.iendo = indx_; -end \ No newline at end of file diff --git a/matlab/+occbin/initialize.m b/matlab/+occbin/initialize.m deleted file mode 100644 index bc938d16b..000000000 --- a/matlab/+occbin/initialize.m +++ /dev/null @@ -1,75 +0,0 @@ -function [M_, oo_, options_] = initialize(M_,oo_,options_) -% function [M_, oo_, options_] = initialize(M_,oo_,options_) -% Initializes run of Occbin: sets default options, parses constraints, creates -% eval_difference-file -% -% INPUT: -% - M_ [structure] Matlab's structure describing the model -% - oo_ [structure] Matlab's structure containing the results -% - options_ [structure] Matlab's structure containing the options -% -% OUTPUT: -% - M_ [structure] Matlab's structure describing the model -% - oo_ [structure] Matlab's structure containing the results -% - options_ [structure] Matlab's structure containing the options - -% Copyright (C) 2021 Dynare Team -% -% This file is part of Dynare. -% -% Dynare 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. -% -% Dynare 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 Dynare. If not, see . - -options_.occbin = struct(); -options_.occbin = occbin.set_default_options(options_.occbin, M_); - -oo_.dr=set_state_space(oo_.dr,M_,options_); - -M_ = occbin.get_info(M_); - -if M_.occbin.constraint_nbr>2 - error('Occbin: Only up to two constraints are supported') -end -for k=1:M_.occbin.constraint_nbr - M_.occbin.constraint(k).bind_difference = occbin.process_constraint(M_.occbin.constraint(k).bind,'_difference',M_.endo_names,false,M_.param_names); - M_.occbin.constraint(k).bind_error = occbin.process_error_constraint(M_.occbin.constraint(k).bind_difference); - if isempty(M_.occbin.constraint(k).relax) - M_.occbin.constraint(k).relax_difference = ['~binding.constraint_',int2str(k)]; - else - M_.occbin.constraint(k).relax_difference = occbin.process_constraint(M_.occbin.constraint(k).relax,'_difference',M_.endo_names,false,M_.param_names); - end - M_.occbin.constraint(k).relax_error = occbin.process_error_constraint(M_.occbin.constraint(k).relax_difference); - M_.occbin.constraint(k).pswitch_index = strmatch(M_.occbin.constraint(k).pswitch,M_.param_names); -end -nwishes_ = size(M_.occbin.wish_list.endo,1); -fid = fopen(['+' M_.fname '/eval_difference.m'],'w+'); -fprintf(fid,'function [binding, relax, err]=eval_difference(zdatalinear_,M_,ys);\n'); -for i_indx_=1:nwishes_ - fprintf(fid,'%s_difference=zdatalinear_(:,%i);\r\n',deblank(M_.occbin.wish_list.endo(i_indx_,:)),M_.occbin.wish_list.iendo(i_indx_)); -end -for k=1:M_.occbin.constraint_nbr - fprintf(fid,'binding.constraint_%i = %s;\r\n',k,M_.occbin.constraint(k).bind_difference); - fprintf(fid,'relax.constraint_%i = %s;\r\n',k,M_.occbin.constraint(k).relax_difference); -% fprintf(fid,'try\r\n'); - - fprintf(fid,' err.binding_constraint_%i = abs(%s);\r\n',k,M_.occbin.constraint(k).bind_error); - fprintf(fid,' err.relax_constraint_%i = abs(%s);\r\n',k,M_.occbin.constraint(k).relax_error); - -% fprintf(fid,'catch\r\n'); -% -% fprintf(fid,' err.newviolvecbool_%i = nan(size(err.newviolvecbool_%i));\r\n',k,k); -% fprintf(fid,' err.relaxconstraint_%i = nan(size(err.relaxconstraint_%i));\r\n',k,k); - -% fprintf(fid,'end\r\n'); -end -fclose(fid); diff --git a/matlab/+occbin/kalman_update_algo_1.m b/matlab/+occbin/kalman_update_algo_1.m index c0310dfa5..e7c936670 100644 --- a/matlab/+occbin/kalman_update_algo_1.m +++ b/matlab/+occbin/kalman_update_algo_1.m @@ -66,9 +66,8 @@ sto.a1=a1; sto.P=P; sto.P1=P1; -number_constr = length(M_.occbin.constraint); base_regime = struct(); -if number_constr==1 +if M_.occbin.constraint_nbr==1 base_regime.regime = 0; base_regime.regimestart = 1; else @@ -125,14 +124,14 @@ options_.occbin.simul=opts_simul; [~, out, ss] = occbin.solver(M_,oo_,options_); regimes_ = out.regime_history; -if number_constr==1 +if M_.occbin.constraint_nbr==1 myregime = [regimes_.regime]; else myregime = [regimes_.regime1 regimes_.regime2]; end etahat_hist = {etahat}; regime_hist = {regimes0(1)}; -if number_constr==1 +if M_.occbin.constraint_nbr==1 regime_end = regimes0(1).regimestart(end); end lik_hist=lik; @@ -149,14 +148,14 @@ if any(myregime) || ~isequal(regimes_(1),regimes0(1)) while ~isequal(regimes_(1),regimes0(1)) && ~is_periodic && ~out.error_flag && niter<=options_.occbin.likelihood.max_number_of_iterations niter=niter+1; oldstart=1; - if number_constr==1 && length(regimes0(1).regimestart)>1 + if M_.occbin.constraint_nbr==1 && length(regimes0(1).regimestart)>1 oldstart = regimes0(1).regimestart(end); end newstart=1; - if number_constr==1 && length(regimes_(1).regimestart)>1 + if M_.occbin.constraint_nbr==1 && length(regimes_(1).regimestart)>1 newstart = regimes_(1).regimestart(end); end - if number_constr==1 && (newstart-oldstart)>2 && options_.occbin.filter.use_relaxation + if M_.occbin.constraint_nbr==1 && (newstart-oldstart)>2 && options_.occbin.filter.use_relaxation regimestart = max(oldstart+2,round(0.5*(newstart+oldstart))); regimestart = min(regimestart,oldstart+4); if regimestart<=regimes_(1).regimestart(end-1) @@ -181,7 +180,7 @@ if any(myregime) || ~isequal(regimes_(1),regimes0(1)) end newguess=0; regime_hist(niter) = {regimes_(1)}; - if number_constr==1 + if M_.occbin.constraint_nbr==1 regime_end(niter) = regimes_(1).regimestart(end); end [a, a1, P, P1, v, alphahat, etahat, lik] = occbin_kalman_update0(a,a1,P,P1,data_index,Z,v,Y,H,QQQ,TT,RR,CC,iF,L,mm, options_.rescale_prediction_error_covariance, options_.occbin.likelihood.IF_likelihood); @@ -196,7 +195,7 @@ if any(myregime) || ~isequal(regimes_(1),regimes0(1)) opts_simul.endo_init = alphahat(oo_.dr.inv_order_var,1); end % opts_simul.init_regime=regimes_(1); - if number_constr==1 + if M_.occbin.constraint_nbr==1 myregimestart = [regimes_.regimestart]; else myregimestart = [regimes_.regimestart1 regimes_.regimestart2]; @@ -212,7 +211,7 @@ if any(myregime) || ~isequal(regimes_(1),regimes0(1)) end is_periodic = any(is_periodic); if is_periodic - if nguess<3 && number_constr==1 + if nguess<3 && M_.occbin.constraint_nbr==1 newguess=1; is_periodic=0; nguess=nguess+1; @@ -240,7 +239,7 @@ if any(myregime) || ~isequal(regimes_(1),regimes0(1)) regimes_ = regimes0; % force projection conditional on previous regime opts_simul.init_regime=regimes0(1); - if number_constr==1 + if M_.occbin.constraint_nbr==1 myregimestart = [regimes0.regimestart]; else myregimestart = [regimes0.regimestart1 regimes0.regimestart2]; @@ -258,7 +257,7 @@ end error_flag = out.error_flag; if ~error_flag && niter>options_.occbin.likelihood.max_number_of_iterations && ~isequal(regimes_(1),regimes0(1)) error_flag = 1; - if number_constr==1 % try some other regime + if M_.occbin.constraint_nbr==1 % try some other regime [ll, il]=sort(lik_hist); [ll, il]=sort(regime_end); rr=regime_hist(il(2:3)); @@ -294,7 +293,7 @@ if ~error_flag && niter>options_.occbin.likelihood.max_number_of_iterations && ~ opts_simul.endo_init = alphahat(oo_.dr.inv_order_var,1); end % opts_simul.init_regime=regimes_(1); - if number_constr==1 + if M_.occbin.constraint_nbr==1 myregimestart = [regimes_.regimestart]; else myregimestart = [regimes_.regimestart1 regimes_.regimestart2]; diff --git a/matlab/+occbin/kalman_update_algo_3.m b/matlab/+occbin/kalman_update_algo_3.m index 83de87ced..ca93b187f 100644 --- a/matlab/+occbin/kalman_update_algo_3.m +++ b/matlab/+occbin/kalman_update_algo_3.m @@ -74,9 +74,8 @@ if isempty(nk) end nk=max(nk,1); -number_constr = length(M_.occbin.constraint); opts_simul = occbin_options.opts_regime;base_regime = struct(); -if number_constr==1 +if M_.occbin.constraint_nbr==1 base_regime.regime = 0; base_regime.regimestart = 1; else @@ -124,13 +123,13 @@ options_.occbin.simul=opts_simul; [~, out, ss] = occbin.solver(M_,oo_,options_); regimes_ = out.regime_history; -if number_constr==1 +if M_.occbin.constraint_nbr==1 myregime = [regimes_.regime]; else myregime = [regimes_.regime1 regimes_.regime2]; end regime_hist = {regimes0}; -if number_constr==1 +if M_.occbin.constraint_nbr==1 regime_end = regimes0(1).regimestart(end); end niter=1; @@ -146,14 +145,14 @@ if any(myregime) || ~isequal(regimes_(1),regimes0(1)) while ~isequal(regimes_(1),regimes0(1)) && ~is_periodic && ~out.error_flag && niter<=options_.occbin.likelihood.max_number_of_iterations niter=niter+1; newstart=1; - if number_constr==1 && length(regimes_(1).regimestart)>1 + if M_.occbin.constraint_nbr==1 && length(regimes_(1).regimestart)>1 newstart = regimes_(1).regimestart(end); end oldstart=1; - if number_constr==1 && length(regimes0(1).regimestart)>1 + if M_.occbin.constraint_nbr==1 && length(regimes0(1).regimestart)>1 oldstart = regimes0(1).regimestart(end); end - if number_constr==1 && (newstart-oldstart)>2 && options_.occbin.filter.use_relaxation + if M_.occbin.constraint_nbr==1 && (newstart-oldstart)>2 && options_.occbin.filter.use_relaxation regimestart = max(oldstart+2,round(0.5*(newstart+oldstart))); regimestart = min(regimestart,oldstart+4); if regimestart<=regimes_(1).regimestart(end-1) @@ -182,7 +181,7 @@ if any(myregime) || ~isequal(regimes_(1),regimes0(1)) end newguess=0; regime_hist(niter) = {regimes_}; - if number_constr==1 + if M_.occbin.constraint_nbr==1 regime_end(niter) = regimes_(1).regimestart(end); end [a, a1, P, P1, v, Fi, Ki, alphahat, etahat] = occbin_kalman_update(a,a1,P,P1,data_index,Z,v,Y,H,QQQ,TT,RR,CC,Ki,Fi,mm,kalman_tol); @@ -201,7 +200,7 @@ if any(myregime) || ~isequal(regimes_(1),regimes0(1)) end % end % opts_simul.init_regime=regimes_(1); %% why don't we use this ??? - if number_constr==1 + if M_.occbin.constraint_nbr==1 myregimestart = [regimes_.regimestart]; else myregimestart = [regimes_.regimestart1 regimes_.regimestart2]; @@ -217,7 +216,7 @@ if any(myregime) || ~isequal(regimes_(1),regimes0(1)) end is_periodic = any(is_periodic); if is_periodic - if nguess<3 && number_constr==1 + if nguess<3 && M_.occbin.constraint_nbr==1 newguess=1; is_periodic=0; nguess=nguess+1; @@ -245,7 +244,7 @@ if any(myregime) || ~isequal(regimes_(1),regimes0(1)) regimes_ = regimes0; % force projection conditional on previous regime opts_simul.init_regime=regimes0(1); - if number_constr==1 + if M_.occbin.constraint_nbr==1 myregimestart = [regimes0.regimestart]; else myregimestart = [regimes0.regimestart1 regimes0.regimestart2]; @@ -264,7 +263,7 @@ error_flag = out.error_flag; if error_flag==0 && niter>options_.occbin.likelihood.max_number_of_iterations && ~isequal(regimes_(1),regimes0(1)) %fixed point algorithm did not converge error_flag = 1; - if number_constr==1 + if M_.occbin.constraint_nbr==1 % try some other regime before giving up [ll, il]=sort(regime_end); rr=regime_hist(il(2:3)); @@ -290,7 +289,7 @@ if error_flag==0 && niter>options_.occbin.likelihood.max_number_of_iterations && [a, a1, P, P1, v, Fi, Ki, alphahat, etahat] = occbin_kalman_update(a,a1,P,P1,data_index,Z,v,Y,H,QQQ,TT,RR,CC,Ki,Fi,mm,kalman_tol); opts_simul.SHOCKS(1,:) = etahat(:,2)'; opts_simul.endo_init = alphahat(oo_.dr.inv_order_var,1); - if number_constr==1 + if M_.occbin.constraint_nbr==1 myregimestart = [regimes_.regimestart]; else myregimestart = [regimes_.regimestart1 regimes_.regimestart2]; @@ -389,4 +388,4 @@ while t > 1 ri = T'*ri; % KD (2003), eq. (23), equation for r_{t-1,p_{t-1}} end -end \ No newline at end of file +end diff --git a/matlab/+occbin/process_constraint.m b/matlab/+occbin/process_constraint.m deleted file mode 100644 index 2f308eef6..000000000 --- a/matlab/+occbin/process_constraint.m +++ /dev/null @@ -1,81 +0,0 @@ -function constraint_parsed = process_constraint(constraint,suffix,endo_names,invert_switch,param_names) -%function constraint_parsed = process_constraint(constraint,suffix,endo_names,invert_switch,param_names) -% Processes constraints for use in Occbin, appending endogenous variables -% with suffix and replacing parameters by their value in M_.params -% -% INPUTS -% - constraint [char] constraint to be parsed -% - suffix [char] suffix to be appended -% - endo_names [cell] names of endogenous variables -% - invert_switch [bool] if true, invert direction of the inequality constraint -% - param_names [cell] names of parameters -% -% OUTPUTS -% - constraint_parsed [char] parsed constraint - -% Original authors: Luca Guerrieri and Matteo Iacoviello -% Original file downloaded from: -% https://www.matteoiacoviello.com/research_files/occbin_20140630.zip -% Adapted for Dynare by Dynare Team. -% -% This code is in the public domain and may be used freely. -% However the authors would appreciate acknowledgement of the source by -% citation of any of the following papers: -% -% Luca Guerrieri and Matteo Iacoviello (2015): "OccBin: A toolkit for solving -% dynamic models with occasionally binding constraints easily" -% Journal of Monetary Economics 70, 22-38 - -% create a list of delimiters that can separate parameters and endogenoous -% variables in the string that expresses the constraint -delimiters = char(',',';','(',')','+','-','^','*','/','>','<','='); - -% split the string that holds the constraint into tokens -tokens = occbin.tokenize(constraint,delimiters); - -ntokens = length(tokens); - -endo_ss=strcat(endo_names,repmat('_ss',length(endo_names),1)); - -% search for tokens that match the list of endogenous variables -for i=1:ntokens - valid_token=0; - if ~isempty(find(strcmp(tokens(i),delimiters))) - % if the invert_switch is true - % reverse the direction of the inequality - if invert_switch - if strcmp(tokens(i),cellstr('>')) - tokens(i) = cellstr('<'); - elseif strcmp(tokens(i),cellstr('<')) - tokens(i) = cellstr('>'); - end - end - valid_token=1; - continue; - end - - if ~isempty(find(strcmp(tokens(i),endo_names))) - % when there is a match with an endogenous variable append the suffix - tokens(i) = cellstr([char(tokens(i)),suffix]); - valid_token=1; - continue; - end - par_index=find(strcmp(tokens(i),param_names)); - if ~isempty(par_index) - tokens(i) = {['M_.params(',num2str(par_index),')']}; - valid_token=1; - continue; - end - ss_index=find(strcmp(tokens(i),endo_ss)); - if ~isempty(ss_index) - tokens(i) = {['ys(',num2str(ss_index),')']}; - valid_token=1; - continue; - end - if isnan(str2double(tokens(i))) - error('Occbin: Constraint %s contains the uninterpretable token %s', constraint, tokens{i}); - end -end - -% reassemble the tokens to create a string that expresses the constraint -constraint_parsed = regexprep(strjoin(tokens),' ',''); \ No newline at end of file diff --git a/matlab/+occbin/process_error_constraint.m b/matlab/+occbin/process_error_constraint.m deleted file mode 100644 index 9ae8d012a..000000000 --- a/matlab/+occbin/process_error_constraint.m +++ /dev/null @@ -1,35 +0,0 @@ -function error_parsed = process_error_constraint(constraint) -% function constraint1 = process_error_constraint(constraint) -% Constructs a string with the constraint error, i.e. by how much it is violated -% INPUTS -% - constraint [char] constraint to be parsed -% -% OUTPUTS -% - error_parsed [char] parsed constraint - -% Copyright (C) 2021 Dynare Team -% -% This file is part of Dynare. -% -% Dynare 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. -% -% Dynare 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 Dynare. If not, see . - -error_parsed = constraint; -error_parsed=regexprep(error_parsed,'=',''); -num = length(regexp(error_parsed,'>'))+length(regexp(error_parsed,'<')); -error_parsed=regexprep(error_parsed,'>','-('); -error_parsed=regexprep(error_parsed,'<','-('); -for k=1:num - error_parsed=[error_parsed ')']; -end - diff --git a/matlab/+occbin/solve_one_constraint.m b/matlab/+occbin/solve_one_constraint.m index 83025117d..57e799dfd 100644 --- a/matlab/+occbin/solve_one_constraint.m +++ b/matlab/+occbin/solve_one_constraint.m @@ -76,7 +76,7 @@ if solve_DM [DM.Cbarmat, DM.Bbarmat, DM.Abarmat, DM.Jbarmat] = occbin.get_deriv(M_base,data.ys); Mstar_= M_base; - Mstar_.params(M_.occbin.constraint(1).pswitch_index)= 1; + Mstar_.params(M_.occbin.pswitch(1))= 1; [DM.Cstarbarmat, DM.Bstarbarmat, DM.Astarbarmat, DM.Jstarbarmat, DM.Dstarbarmat] = occbin.get_deriv(Mstar_,data.ys); [DM.decrulea,DM.decruleb]=occbin.get_pq(dr_base); @@ -167,7 +167,7 @@ for shock_period = 1:n_shocks_periods regime_start(end)-1,binding_indicator,... data.exo_pos,data.shocks_sequence(shock_period,:),endo_init,update_flag); - [binding, relax, err]=feval([M_.fname,'.eval_difference'],zdatalinear_,M_,dr_base.ys); + [binding, relax, err]=feval([M_.fname,'.occbin_difference'],zdatalinear_,M_.params,dr_base.ys); % check if changes to the hypothesis of the duration for each % regime @@ -294,4 +294,4 @@ end if opts_simul_.waitbar dyn_waitbar_close(hh); -end \ No newline at end of file +end diff --git a/matlab/+occbin/solve_two_constraints.m b/matlab/+occbin/solve_two_constraints.m index 3b3d267d7..ec81178a9 100644 --- a/matlab/+occbin/solve_two_constraints.m +++ b/matlab/+occbin/solve_two_constraints.m @@ -70,16 +70,16 @@ if solve_DM %recompute solution matrices [DM.Cbarmat ,DM.Bbarmat, DM.Abarmat, DM.Jbarmat] = occbin.get_deriv(M00_,data.ys); M10_ = M00_; - M10_.params(strmatch(M_.occbin.constraint(1).pswitch,M00_.param_names,'exact'))= 1; + M10_.params(strmatch(M_.params(M_.occbin.pswitch(1)),M00_.param_names,'exact'))= 1; [DM.Cbarmat10, DM.Bbarmat10, DM.Abarmat10, DM.Jbarmat10, DM.Dbarmat10] = occbin.get_deriv(M10_,data.ys); M01_ = M00_; - M01_.params(strmatch(M_.occbin.constraint(2).pswitch,M00_.param_names,'exact'))= 1; + M01_.params(strmatch(M_.params(M_.occbin.pswitch(2)),M00_.param_names,'exact'))= 1; [DM.Cbarmat01, DM.Bbarmat01, DM.Abarmat01, DM.Jbarmat01, DM.Dbarmat01] = occbin.get_deriv(M01_,data.ys); M11_ = M00_; - M11_.params(M_.occbin.constraint(1).pswitch_index)= 1; - M11_.params(M_.occbin.constraint(2).pswitch_index)= 1; + M11_.params(M_.occbin.pswitch(1))= 1; + M11_.params(M_.occbin.pswitch(2))= 1; [DM.Cbarmat11, DM.Bbarmat11, DM.Abarmat11, DM.Jbarmat11, DM.Dbarmat11] = occbin.get_deriv(M11_,data.ys); [DM.decrulea,DM.decruleb]=occbin.get_pq(dr); @@ -183,7 +183,7 @@ for shock_period = 1:n_shocks_periods binding_indicator,... data.exo_pos,data.shocks_sequence(shock_period,:),endo_init, update_flag); - [binding, relax, err]=feval([M_.fname,'.eval_difference'],zdatalinear_,M_,dr.ys); + [binding, relax, err]=feval([M_.fname,'.occbin_difference'],zdatalinear_,M_.params,dr.ys); binding_constraint_new=[binding.constraint_1;binding.constraint_2]; relaxed_constraint_new = [relax.constraint_1;relax.constraint_2]; @@ -318,4 +318,4 @@ end if opts_simul_.waitbar dyn_waitbar_close(hh); -end \ No newline at end of file +end diff --git a/matlab/+occbin/tokenize.m b/matlab/+occbin/tokenize.m deleted file mode 100644 index df87c6a13..000000000 --- a/matlab/+occbin/tokenize.m +++ /dev/null @@ -1,66 +0,0 @@ -function tokens = tokenize(source,delimiter) -%function tokens = tokenize(source,delimiter) -% Breaks down strings into its components (tokens) -% INPUTS -% - source [string] string to be broken into tokens -% - delimiter [char array] single character delimiters -% -% OUTPUTS: -% -tokens [cell] array containing the tokens - -% Original authors: Luca Guerrieri and Matteo Iacoviello -% Original file downloaded from: -% https://www.matteoiacoviello.com/research_files/occbin_20140630.zip -% Adapted for Dynare by Dynare Team. -% -% This code is in the public domain and may be used freely. -% However the authors would appreciate acknowledgement of the source by -% citation of any of the following papers: -% -% Luca Guerrieri and Matteo Iacoviello (2015): "OccBin: A toolkit for solving -% dynamic models with occasionally binding constraints easily" -% Journal of Monetary Economics 70, 22-38 - -posdelims = []; - -% assumes that delimiter cannot be in the first position or the last position -ndelimiters = size(delimiter,1); -for i=1:ndelimiters - newpositions = strfind(source,delimiter(i,:)); - if ~isempty(newpositions) - posdelims =[posdelims, newpositions]; - end -end - -% reorder posdelims in ascending order -posdelims = sort(posdelims); - -if isempty(posdelims) - tokens = cellstr(source); -else - ndelims = length(posdelims); - % build positions for substrings - delims = zeros(ndelims+1,2); - for i=1:ndelims+1 - if i==1 - if posdelims(1) == 1 - tokens = cellstr(source(1)); - else - delims(i,:) = [1,posdelims(i)-1]; - tokens = cellstr(source([delims(i,1):delims(i,2)])); - tokens = [tokens, source(posdelims(i))]; - end - elseif i==ndelims+1 - if (posdelims(i-1) < length(source)) - delims(i,:) = [posdelims(i-1)+1,length(source)]; - tokens = [tokens, cellstr(source([delims(i,1):delims(i,2)]))]; - end - else - if posdelims(i)>posdelims(i-1)+1 - delims(i,:) = [posdelims(i-1)+1,posdelims(i)-1]; - tokens = [tokens, cellstr(source([delims(i,1):delims(i,2)]))]; - end - tokens = [tokens, source(posdelims(i))]; - end - end -end \ No newline at end of file diff --git a/matlab/dsge_likelihood.m b/matlab/dsge_likelihood.m index 85b4cc3ea..49a27a7ec 100644 --- a/matlab/dsge_likelihood.m +++ b/matlab/dsge_likelihood.m @@ -969,7 +969,6 @@ occbin_options.opts_simul.periods = DynareOptions.occbin.likelihood.periods; occbin_options.opts_simul.check_ahead_periods = DynareOptions.occbin.likelihood.check_ahead_periods; occbin_options.opts_simul.periodic_solution = DynareOptions.occbin.likelihood.periodic_solution; occbin_options.opts_simul.restrict_state_space = DynareOptions.occbin.likelihood.restrict_state_space; -occbin_options.constraints = Model.occbin.constraint; occbin_options.opts_simul.full_output = DynareOptions.occbin.likelihood.full_output; occbin_options.opts_simul.piecewise_only = DynareOptions.occbin.likelihood.piecewise_only; diff --git a/matlab/kalman/likelihood/missing_observations_kalman_filter.m b/matlab/kalman/likelihood/missing_observations_kalman_filter.m index d90dd66cf..89a1422bf 100644 --- a/matlab/kalman/likelihood/missing_observations_kalman_filter.m +++ b/matlab/kalman/likelihood/missing_observations_kalman_filter.m @@ -107,7 +107,7 @@ if occbin_.status opts_regime.binding_indicator = occbin_options.opts_simul.init_binding_indicator; first_period_occbin_update = max(t+1,options_.occbin.likelihood.first_period_occbin_update); if isempty(opts_regime.binding_indicator) && isempty(opts_regime.regime_history) - opts_regime.binding_indicator=zeros(last+2,length(M_.occbin.constraint)); + opts_regime.binding_indicator=zeros(last+2,M_.occbin.constraint_nbr); end [~, ~, ~, regimes_] = occbin.check_regimes([], [], [], opts_regime, M_, oo_, options_); if length(occbin_.info)>4 diff --git a/matlab/missing_DiffuseKalmanSmootherH3_Z.m b/matlab/missing_DiffuseKalmanSmootherH3_Z.m index d6b2c2ebc..08404b0a4 100644 --- a/matlab/missing_DiffuseKalmanSmootherH3_Z.m +++ b/matlab/missing_DiffuseKalmanSmootherH3_Z.m @@ -168,7 +168,7 @@ else if isfield(opts_regime,'regime_history') && ~isempty(opts_regime.regime_history) opts_regime.regime_history=[opts_regime.regime_history(1) opts_regime.regime_history]; else - opts_regime.binding_indicator=zeros(smpl+2,length(M_.occbin.constraint)); + opts_regime.binding_indicator=zeros(smpl+2,M_.occbin.constraint_nbr); end occbin_options.opts_regime = opts_regime; [~, ~, ~, regimes_] = occbin.check_regimes([], [], [], opts_regime, M_, oo_, options_); diff --git a/preprocessor b/preprocessor index 08ac455fc..81d4fd5d8 160000 --- a/preprocessor +++ b/preprocessor @@ -1 +1 @@ -Subproject commit 08ac455fcddd032058738669ed6a84fda9c76e05 +Subproject commit 81d4fd5d83c08da2403a8faf3d2a006d3ab4bb1e diff --git a/tests/occbin/model_borrcon/borrcon.mod b/tests/occbin/model_borrcon/borrcon.mod index b2535a2d5..fae342096 100644 --- a/tests/occbin/model_borrcon/borrcon.mod +++ b/tests/occbin/model_borrcon/borrcon.mod @@ -26,8 +26,8 @@ y_hat = log(y) - log(steady_state(y)); end; occbin_constraints; -% name 'relax_borrcon'; bind lb<-lb_ss; relax b>M*y; error_bind abs(lb+lb_ss); error_relax abs(b-M*y); -name 'relax_borrcon'; bind lb<-lb_ss; relax b>M*y; + name 'relax_borrcon'; bind lb<-STEADY_STATE(lb); relax b>M*y; error_bind abs(lb+STEADY_STATE(lb)); error_relax abs(b-M*y); +%name 'relax_borrcon'; bind lb<-STEADY_STATE(lb); relax b>M*y; end; steady_state_model; @@ -50,4 +50,4 @@ shocks; var u; stderr SIGMA; end; -@#include "borrcon_common.inc" \ No newline at end of file +@#include "borrcon_common.inc" diff --git a/tests/occbin/model_borrcon/borrcon_0_std_shocks.mod b/tests/occbin/model_borrcon/borrcon_0_std_shocks.mod index 364918e9d..c0e3b2ee4 100644 --- a/tests/occbin/model_borrcon/borrcon_0_std_shocks.mod +++ b/tests/occbin/model_borrcon/borrcon_0_std_shocks.mod @@ -27,7 +27,7 @@ y_hat = log(y) - log(steady_state(y)); end; occbin_constraints; -name 'relax_borrcon'; bind lb<-lb_ss; relax b>M*y; error_bind abs(lb+lb_ss); error_relax abs(b-M*y); +name 'relax_borrcon'; bind lb<-STEADY_STATE(lb); relax b>M*y; error_bind abs(lb+STEADY_STATE(lb)); error_relax abs(b-M*y); end; steady_state_model; @@ -55,4 +55,4 @@ end; orig_results=load('borrcon_results.mat'); if max(max(abs(oo_.occbin.piecewise-orig_results.oo_.occbin.piecewise)))>1e-10 error('Results do not match') -end \ No newline at end of file +end diff --git a/tests/occbin/model_irrcap_twoconstraints/dynrbc.mod b/tests/occbin/model_irrcap_twoconstraints/dynrbc.mod old mode 100755 new mode 100644