diff --git a/matlab/+occbin/DSGE_smoother.m b/matlab/+occbin/DSGE_smoother.m index 5bd5f9098dc2dcce839f09a32d3e6e9781aaf01d..384fa57bdf8be48c24c3f2dfdd9618b43b01ff6d 100644 --- a/matlab/+occbin/DSGE_smoother.m +++ b/matlab/+occbin/DSGE_smoother.m @@ -106,6 +106,7 @@ opts_simul.maxit = options_.occbin.smoother.maxit; opts_simul.waitbar = options_.occbin.smoother.waitbar; opts_simul.periods = options_.occbin.smoother.periods; opts_simul.check_ahead_periods = options_.occbin.smoother.check_ahead_periods; +opts_simul.max_check_ahead_periods = options_.occbin.smoother.max_check_ahead_periods; opts_simul.periodic_solution = options_.occbin.smoother.periodic_solution; opts_simul.full_output = options_.occbin.smoother.full_output; opts_simul.piecewise_only = options_.occbin.smoother.piecewise_only; @@ -254,7 +255,7 @@ while is_changed && maxiter>iter && ~is_periodic err_TT(iter-1) = max(max(max(abs(TT-sto_TT)))); end - if occbin_smoother_debug + if occbin_smoother_debug || is_periodic regime_ = cell(0); regime_new = regime_; start_ = regime_; @@ -332,18 +333,26 @@ regime_history0(max(iter+1,1),:) = regime_history; oo_.occbin.smoother.regime_history=regime_history0(end,:); oo_.occbin.smoother.regime_history_iter=regime_history0; if occbin_smoother_debug -save('info1','regime_history0') + save('info1','regime_history0') end if (maxiter==iter && is_changed) || is_periodic - disp(['Occbin smoother did not converge.']) + disp('occbin.DSGE_smoother: smoother did not converge.') + fprintf('occbin.DSGE_smoother: The algorithm did not reach a fixed point for the smoothed regimes.\n') if is_periodic - disp(['Occbin smoother algo loops between two solutions.']) + oo_.occbin.smoother.error_flag=0; + fprintf('occbin.DSGE_smoother: For the periods indicated above, regimes loops between the "regime_" and the "regime_new_" pattern displayed above.\n') + fprintf('occbin.DSGE_smoother: We provide smoothed shocks consistent with "regime_" in oo_.\n') + else + fprintf('occbin.DSGE_smoother: The respective fields in oo_ will be left empty.\n') + oo_.occbin.smoother=[]; + oo_.occbin.smoother.error_flag=1; end else - disp(['Occbin smoother converged.']) + disp('occbin.DSGE_smoother: smoother converged.') + oo_.occbin.smoother.error_flag=0; if occbin_smoother_fast && is_changed_start - disp('WARNING: fast algo is used, regime(s) duration(s) was not forced to converge') + disp('occbin.DSGE_smoother: WARNING: fast algo is used, regime duration was not forced to converge') end end if (~is_changed || occbin_smoother_debug) && nargin==12 diff --git a/matlab/+occbin/IVF_core.m b/matlab/+occbin/IVF_core.m index 31e56e3c0f712d57b26e062f1a5412bf538b4aba..1ffe0a153515810cdc992906a6b0cae5fc17b1de 100644 --- a/matlab/+occbin/IVF_core.m +++ b/matlab/+occbin/IVF_core.m @@ -60,6 +60,7 @@ opts_simul.maxit = options_.occbin.likelihood.maxit; opts_simul.waitbar = false; opts_simul.periods = options_.occbin.likelihood.periods; opts_simul.check_ahead_periods = options_.occbin.likelihood.check_ahead_periods; +opts_simul.max_check_ahead_periods = options_.occbin.likelihood.max_check_ahead_periods; opts_simul.periodic_solution = options_.occbin.likelihood.periodic_solution; opts_simul.restrict_state_space = options_.occbin.likelihood.restrict_state_space; opts_simul.piecewise_only = 1; diff --git a/matlab/+occbin/set_default_options.m b/matlab/+occbin/set_default_options.m index ea02b1a1f2bc83c0d996f6056eff0fe2291c0c53..68d90928c792d8a40b942f3c855dde8a7ba5c615 100644 --- a/matlab/+occbin/set_default_options.m +++ b/matlab/+occbin/set_default_options.m @@ -76,6 +76,7 @@ if ismember(flag,{'likelihood','all'}) options_occbin_.likelihood.IVF_shock_observable_mapping = []; options_occbin_.likelihood.maxit = 30; % this is for occbin solver algo options_occbin_.likelihood.max_number_of_iterations = 10; % this is for occbin_kalman_update loop + options_occbin_.likelihood.max_check_ahead_periods=inf; options_occbin_.likelihood.periods = 100; options_occbin_.likelihood.check_ahead_periods=200; options_occbin_.likelihood.periodic_solution=false; @@ -170,11 +171,12 @@ if ismember(flag,{'simul','all'}) options_occbin_.simul.init_binding_indicator=false(0); options_occbin_.simul.exo_pos=1:M_.exo_nbr; options_occbin_.simul.maxit=30; - options_occbin_.simul.max_periods=inf; + options_occbin_.simul.max_check_ahead_periods=inf; options_occbin_.simul.periods=100; options_occbin_.simul.check_ahead_periods=200; options_occbin_.simul.periodic_solution=false; options_occbin_.simul.piecewise_only = false; + options_occbin_.simul.reset_check_ahead_periods_in_new_period = false; options_occbin_.simul.reset_regime_in_new_period = false; options_occbin_.simul.restrict_state_space=false; options_occbin_.simul.SHOCKS=zeros(1,M_.exo_nbr); @@ -193,6 +195,7 @@ if ismember(flag,{'smoother','all'}) options_occbin_.smoother.inversion_filter = false; options_occbin_.smoother.linear_smoother = true; options_occbin_.smoother.maxit = 30; % this is for occbin solver algo + options_occbin_.smoother.max_check_ahead_periods=inf; options_occbin_.smoother.max_number_of_iterations = 10; % this is for smoother loop options_occbin_.smoother.periods = 100; options_occbin_.smoother.check_ahead_periods=200; diff --git a/matlab/+occbin/setup.m b/matlab/+occbin/setup.m index 77c984c22f7435ef1db9b9145987aee5d175dd54..67db5bdb14dd6bbc95860f53d769df5820117448 100644 --- a/matlab/+occbin/setup.m +++ b/matlab/+occbin/setup.m @@ -2,12 +2,12 @@ function [M_, options_] = setup(M_,options_, options_occbin_) % function [M_, options_] = setup(M_, options_, options_occbin_) % Sets up run of Occbin: creates shock matrix, sets options % -% INPUT: +% INPUT: % - M_ [structure] Matlab's structure describing the model % - options_ [structure] Matlab's structure containing the options % - options_occbin_ [structure] Matlab's structure containing Occbin options % -% OUTPUT: +% OUTPUT: % - M_ [structure] Matlab's structure describing the model % - options_occbin_ [structure] Matlab's structure containing Occbin options @@ -55,7 +55,7 @@ if isfield(M_,'surprise_shocks') && ~isempty(M_.surprise_shocks) for ii = 1:length(M_.surprise_shocks) ivar = M_.surprise_shocks(ii).exo_id; temp(M_.surprise_shocks(ii).periods,ivar) = M_.surprise_shocks(ii).value; - end + end shock_index=~all(temp==0,1); options_.occbin.simul.SHOCKS=temp(:,shock_index); options_.occbin.simul.exo_pos=find(shock_index); diff --git a/matlab/+occbin/solve_one_constraint.m b/matlab/+occbin/solve_one_constraint.m index 0801f8c1ebfab61a3b8e4658b30fee5bd22454a2..f5f0c1446c79ff6edf9b1c829e8b98c90f2216ca 100644 --- a/matlab/+occbin/solve_one_constraint.m +++ b/matlab/+occbin/solve_one_constraint.m @@ -125,21 +125,29 @@ for shock_period = 1:n_shocks_periods regime_change_this_iteration=true; iter = 0; + nperiods_endogenously_increased = false; guess_history_it = false; if guess_history && (shock_period<=length(regime_history_guess)) %beyond guess regime history guess_history_it = true; end is_periodic=false; + is_periodic_loop=false; binding_indicator_history={}; max_err = NaN(max_iter,1); + regime_violates_constraint_in_expectation = false(max_iter,1); - while (regime_change_this_iteration && iter<max_iter && ~is_periodic) + while (regime_change_this_iteration && iter<max_iter && ~is_periodic && ~is_periodic_loop) iter = iter +1; - if binding_indicator(end) && nperiods_0<opts_simul_.max_periods + if binding_indicator(end) && nperiods_0<opts_simul_.max_check_ahead_periods binding_indicator = [binding_indicator; false ]; nperiods_0 = nperiods_0 + 1; + nperiods_endogenously_increased = true; disp_verbose(['nperiods has been endogenously increased up to ' int2str(nperiods_0) '.'],opts_simul_.debug) + elseif nperiods_0>=opts_simul_.max_check_ahead_periods + % enforce endogenously increased nperiods to not violate max_check_ahead_periods + binding_indicator = binding_indicator(1:opts_simul_.max_check_ahead_periods+1); + binding_indicator(end)=false; end if length(binding_indicator)<(nperiods_0 + 1) binding_indicator=[binding_indicator; false(nperiods_0 + 1-length(binding_indicator),1)]; @@ -164,7 +172,13 @@ for shock_period = 1:n_shocks_periods % get the hypothesized piece wise linear solution if shock_period==1 || shock_period>1 && any(data.shocks_sequence(shock_period,:)) if iter==1 && opts_simul_.reset_regime_in_new_period - binding_indicator=false(size(binding_indicator)); + if opts_simul_.reset_check_ahead_periods_in_new_period + % I re-set check ahead periods to initial value, when in previous period it was endogenously increased + nperiods_0 = max(opts_simul_.check_ahead_periods,n_periods-n_shocks_periods); + binding_indicator = false(nperiods_0+1,1); + else + binding_indicator=false(size(binding_indicator)); + end binding_indicator_history{iter}=binding_indicator; % analyse violvec and isolate contiguous periods in the other regime. [regime, regime_start, error_code_period]=occbin.map_regime(binding_indicator,opts_simul_.debug); @@ -178,42 +192,81 @@ for shock_period = 1:n_shocks_periods [binding, relax, err]=feval([M_.fname,'.occbin_difference'],zdatalinear_+repmat(dr_base.ys',size(zdatalinear_,1),1),M_.params,dr_base.ys); + if ~isinf(opts_simul_.max_check_ahead_periods) && opts_simul_.max_check_ahead_periods<length(binding_indicator) + end_periods = opts_simul_.max_check_ahead_periods; + last_indicator = false(length(binding_indicator)-end_periods,1); + else + end_periods = length(binding_indicator); + last_indicator = false(0); + end % check if changes to the hypothesis of the duration for each % regime - if any(binding.constraint_1 & ~binding_indicator) || any(relax.constraint_1 & binding_indicator) - err_viol = err.binding_constraint_1(binding.constraint_1 & ~binding_indicator); - err_relax = err.relax_constraint_1(relax.constraint_1 & binding_indicator); + if any(binding.constraint_1(1:end_periods) & ~binding_indicator(1:end_periods)) || any(relax.constraint_1(1:end_periods) & binding_indicator(1:end_periods)) + + err_viol = err.binding_constraint_1(binding.constraint_1(1:end_periods) & ~binding_indicator(1:end_periods)); + err_relax = err.relax_constraint_1(relax.constraint_1(1:end_periods) & binding_indicator(1:end_periods)); max_err(iter) = max(abs([err_viol;err_relax])); regime_change_this_iteration = true; + regime_violates_constraint_in_expectation(iter) = any(binding.constraint_1(1:end_periods) & ~binding_indicator(1:end_periods)); else regime_change_this_iteration = false; max_err(iter) = 0; end + % if max_check_ahead_periods<inf, enforce unconstrained regime for period larger than max_check_ahead_periods + binding_constraint_new=[binding.constraint_1(1:end_periods);last_indicator]; + relaxed_constraint_new = [relax.constraint_1(1:end_periods);not(last_indicator)]; if curb_retrench % apply Gauss-Seidel idea of slowing down the change in the guess % for the constraint -- only relax one % period at a time starting from the last % one when each of the constraints is true. retrench = false(numel(binding_indicator),1); - max_relax_constraint_1=find(relax.constraint_1 & binding_indicator,1,'last'); - if ~isempty(max_relax_constraint_1) && find(relax.constraint_1,1,'last')>=find(binding_indicator,1,'last') + max_relax_constraint_1=find(relax.constraint_1(1:end_periods) & binding_indicator(1:end_periods),1,'last'); + if ~isempty(max_relax_constraint_1) && find(relax.constraint_1(1:end_periods),1,'last')>=find(binding_indicator(1:end_periods),1,'last') retrench(max_relax_constraint_1) = true; end - binding_indicator = (binding_indicator | binding.constraint_1) & ~ retrench; + binding_indicator = (binding_indicator | binding_constraint_new) & ~ retrench; else - binding_indicator= (binding_indicator | binding.constraint_1) & ~(binding_indicator & relax.constraint_1); + binding_indicator = (binding_indicator | binding_constraint_new) & ~(binding_indicator & relaxed_constraint_new); end - if iter>1 && regime_change_this_iteration + if iter>1 && regime_change_this_iteration && ~nperiods_endogenously_increased + % check for periodic solution only if nperiods is not + % increased endogenously + % first check for infinite loop + is_periodic_loop = false(iter-1,1); for kiter=1:iter-1 - vvv = [binding_indicator_history{kiter}; false(size(binding_indicator,1)- size(binding_indicator_history{kiter},1), 1)]; - is_periodic(kiter) = isequal(vvv, binding_indicator); + if size(binding_indicator,1)== size(binding_indicator_history{kiter},1) + % vvv = [binding_indicator_history{kiter}; false(size(binding_indicator,1)- size(binding_indicator_history{kiter},1), 1)]; + % is_periodic(kiter) = isequal(vvv, binding_indicator); + is_periodic_loop(kiter) = isequal(binding_indicator_history{kiter}, binding_indicator); + else + is_periodic_loop(kiter) = false; + end + end + is_periodic_loop_all =is_periodic_loop; + is_periodic_loop = any(is_periodic_loop); + % only accept periodicity where regimes differ by one + % period! + is_periodic = false(iter-1,1); + for kiter=iter-1 + if size(binding_indicator,1)== size(binding_indicator_history{kiter},1) + % vvv = [binding_indicator_history{kiter}; false(size(binding_indicator,1)- size(binding_indicator_history{kiter},1), 1)]; + % is_periodic(kiter) = isequal(vvv, binding_indicator); + is_periodic(kiter) = isequal(binding_indicator_history{kiter}, binding_indicator) && length(find(binding_indicator_history{iter}-binding_indicator))==1; + else + is_periodic(kiter)=false; + end end is_periodic_all =is_periodic; is_periodic = any(is_periodic); if is_periodic && periodic_solution - [merr,imerr]=min(max_err(find(is_periodic_all,1):end)); inx = find(is_periodic_all,1):iter; + inx1 = inx(find(~regime_violates_constraint_in_expectation(inx))); + if not(isempty(inx1)) + inx=inx1; + end + [merr,imerr]=min(max_err(inx)); inx = inx(imerr); binding_indicator=binding_indicator_history{inx}; if inx<iter @@ -265,9 +318,14 @@ for shock_period = 1:n_shocks_periods return end else + if is_periodic_loop + disp_verbose('Did not converge -- infinite loop of guess regimes.',opts_simul_.debug) + error_flag = 313; + else disp_verbose('Did not converge -- increase maxit.',opts_simul_.debug) + error_flag = 311; + end if opts_simul_.waitbar; dyn_waitbar_close(hh); end - error_flag = 311; return end else diff --git a/matlab/+occbin/solve_two_constraints.m b/matlab/+occbin/solve_two_constraints.m index 234aaa78b510dfc93cc14d6b6c4b1532fc5c621c..80744ac50943fa24b2e3ee285cb7ad3d3c587152 100644 --- a/matlab/+occbin/solve_two_constraints.m +++ b/matlab/+occbin/solve_two_constraints.m @@ -133,23 +133,35 @@ for shock_period = 1:n_shocks_periods dyn_waitbar(shock_period/n_shocks_periods, hh, sprintf('Period %u of %u', shock_period,n_shocks_periods)); end regime_change_this_iteration=true; + nperiods_endogenously_increased = false; iter = 0; guess_history_it = false; if guess_history && (shock_period<=length(regime_history_guess)) %beyond guess regime history guess_history_it = true; end is_periodic=false; + is_periodic_loop=false; binding_indicator_history={}; max_err = NaN(max_iter,1); + regime_violates_constraint_in_expectation = false(max_iter,1); - while (regime_change_this_iteration && iter<max_iter && ~is_periodic) + while (regime_change_this_iteration && iter<max_iter && ~is_periodic && ~is_periodic_loop) iter = iter +1; - if any(binding_indicator(end,:)) && nperiods_0<opts_simul_.max_periods + if any(binding_indicator(end,:)) && nperiods_0<opts_simul_.max_check_ahead_periods binding_indicator = [binding_indicator; false(1,2)]; nperiods_0 = nperiods_0 + 1; + nperiods_endogenously_increased = true; disp_verbose(['nperiods has been endogenously increased up to ' int2str(nperiods_0) '.'],opts_simul_.debug) + elseif nperiods_0>=opts_simul_.max_check_ahead_periods + % enforce endogenously increased nperiods to not violate max_check_ahead_periods + binding_indicator = binding_indicator(1:opts_simul_.max_check_ahead_periods+1,:); + binding_indicator(end,:)=false(1,2); end if size(binding_indicator,1)<(nperiods_0 + 1) + % to ensure the simulation is run for the required nperiods + % even beyond max_check_ahead_periods: the latter controls check ahead periods + % and NOT how many periods we simulate after we are back to + % unconstrained regime (nperiods_0) binding_indicator=[binding_indicator; false(nperiods_0 + 1-size(binding_indicator,1),2)]; end binding_indicator_history{iter}=binding_indicator; @@ -178,7 +190,13 @@ for shock_period = 1:n_shocks_periods regime_history(shock_period).regimestart2 = regime_start_2; if shock_period==1 || shock_period>1 && any(data.shocks_sequence(shock_period,:)) % first period or shock happening if iter==1 && opts_simul_.reset_regime_in_new_period - binding_indicator=false(size(binding_indicator)); + if opts_simul_.reset_check_ahead_periods_in_new_period + % I re-set check ahead periods to initial value, when in previous period it was endogenously increased + nperiods_0 = max(opts_simul_.check_ahead_periods,n_periods-n_shocks_periods); + binding_indicator = false(nperiods_0+1,2); + else + binding_indicator=false(size(binding_indicator)); + end binding_indicator_history{iter}=binding_indicator; % analyse violvec and isolate contiguous periods in the other regime. [regime_1, regime_start_1, error_code_period(1)]=occbin.map_regime(binding_indicator(:,1),opts_simul_.debug); @@ -195,53 +213,91 @@ for shock_period = 1:n_shocks_periods data.exo_pos,data.shocks_sequence(shock_period,:),endo_init, update_flag); [binding, relax, err]=feval([M_.fname,'.occbin_difference'],zdatalinear_+repmat(dr.ys',size(zdatalinear_,1),1),M_.params,dr.ys); - binding_constraint_new=[binding.constraint_1;binding.constraint_2]; - relaxed_constraint_new = [relax.constraint_1;relax.constraint_2]; + + if ~isinf(opts_simul_.max_check_ahead_periods) && opts_simul_.max_check_ahead_periods<length(binding_indicator) + end_periods = opts_simul_.max_check_ahead_periods; + last_indicator = false(length(binding_indicator)-end_periods,1); + else + end_periods = length(binding_indicator); + last_indicator = false(0); + end + binding_constraint_new=[binding.constraint_1(1:end_periods); binding.constraint_2(1:end_periods)]; + relaxed_constraint_new = [relax.constraint_1(1:end_periods); relax.constraint_2(1:end_periods)]; + my_binding_indicator = binding_indicator(1:end_periods,:); - err_binding_constraint_new = [err.binding_constraint_1; err.binding_constraint_2]; - err_relaxed_constraint_new = [err.relax_constraint_1; err.relax_constraint_2]; + err_binding_constraint_new = [err.binding_constraint_1(1:end_periods); err.binding_constraint_2(1:end_periods)]; + err_relaxed_constraint_new = [err.relax_constraint_1(1:end_periods); err.relax_constraint_2(1:end_periods)]; % check if changes_ - if any(binding_constraint_new & ~binding_indicator(:)) || any(relaxed_constraint_new & binding_indicator(:)) - err_violation = err_binding_constraint_new(binding_constraint_new & ~binding_indicator(:)); - err_relax = err_relaxed_constraint_new(relaxed_constraint_new & binding_indicator(:)); + if any(binding_constraint_new & ~my_binding_indicator(:)) || any(relaxed_constraint_new & my_binding_indicator(:)) + err_violation = err_binding_constraint_new(binding_constraint_new & ~my_binding_indicator(:)); + err_relax = err_relaxed_constraint_new(relaxed_constraint_new & my_binding_indicator(:)); max_err(iter) = max(abs([err_violation;err_relax])); regime_change_this_iteration = true; + regime_violates_constraint_in_expectation(iter) = any(binding_constraint_new & ~binding_indicator(:)); else regime_change_this_iteration = false; max_err(iter) = 0; end + binding_constraint_new=[binding.constraint_1(1:end_periods);last_indicator; binding.constraint_2(1:end_periods);last_indicator]; + relaxed_constraint_new = [relax.constraint_1(1:end_periods);not(last_indicator); relax.constraint_2(1:end_periods);not(last_indicator)]; if curb_retrench % apply Gauss-Seidel idea of slowing down the change in the guess % for the constraint -- only relax one % period at a time starting from the last % one when each of the constraints is true. retrench = false(numel(binding_indicator),1); - max_relax_constraint_1=find(relax.constraint_1 & binding_indicator(:,1),1,'last'); - if ~isempty(max_relax_constraint_1) && find(relax.constraint_1,1,'last')>=find(binding_indicator(:,1),1,'last') + max_relax_constraint_1=find(relax.constraint_1(1:end_periods) & binding_indicator(1:end_periods,1),1,'last'); + if ~isempty(max_relax_constraint_1) && find(relax.constraint_1(1:end_periods),1,'last')>=find(binding_indicator(1:end_periods,1),1,'last') retrench(max_relax_constraint_1) = true; end - max_relax_constraint_2=find(relax.constraint_2 & binding_indicator(:,2),1,'last'); - if ~isempty(max_relax_constraint_2) && find(relax.constraint_2,1,'last')>=find(binding_indicator(:,2),1,'last') + max_relax_constraint_2=find(relax.constraint_2(1:end_periods) & binding_indicator(1:end_periods,2),1,'last'); + if ~isempty(max_relax_constraint_2) && find(relax.constraint_2(1:end_periods),1,'last')>=find(binding_indicator(1:end_periods,2),1,'last') retrench(max_relax_constraint_2+nperiods_0+1) = true; end binding_indicator = (binding_indicator(:) | binding_constraint_new) & ~ retrench; else - binding_indicator= (binding_indicator(:) | binding_constraint_new) & ~(binding_indicator(:) & relaxed_constraint_new); + binding_indicator = (binding_indicator(:) | binding_constraint_new) & ~(binding_indicator(:) & relaxed_constraint_new); end binding_indicator = reshape(binding_indicator,nperiods_0+1,2); - if iter>1 && regime_change_this_iteration - is_periodic=false(1,iter-1); + if iter>1 && regime_change_this_iteration && ~nperiods_endogenously_increased + % check for periodic solution only if nperiods is not + % increased endogenously + % first check for infinite loop + is_periodic_loop = false(iter-1,1); for kiter=1:iter-1 - vvv = [binding_indicator_history{kiter}; false(size(binding_indicator,1)- size(binding_indicator_history{kiter},1), 2)]; - is_periodic(kiter) = isequal(vvv, binding_indicator); + if size(binding_indicator,1)== size(binding_indicator_history{kiter},1) + % vvv = [binding_indicator_history{kiter}; false(size(binding_indicator,1)- size(binding_indicator_history{kiter},1), 1)]; + % is_periodic(kiter) = isequal(vvv, binding_indicator); + is_periodic_loop(kiter) = isequal(binding_indicator_history{kiter}, binding_indicator); + else + is_periodic_loop(kiter) = false; + end + end +% is_periodic_loop_all =is_periodic_loop; + is_periodic_loop = any(is_periodic_loop); + % only accept periodicity where regimes differ by one + % period! + is_periodic=false(1,iter-1); + for kiter=iter-1 + if size(binding_indicator,1)== size(binding_indicator_history{kiter},1) + % vvv = [binding_indicator_history{kiter}; false(size(binding_indicator,1)- size(binding_indicator_history{kiter},1), 1)]; + % is_periodic(kiter) = isequal(vvv, binding_indicator); + is_periodic(kiter) = isequal(binding_indicator_history{kiter}, binding_indicator) && length(find(binding_indicator_history{iter}(:,1)-binding_indicator(:,1)))<=1 && length(find(binding_indicator_history{iter}(:,2)-binding_indicator(:,2)))<=1; + else + is_periodic(kiter)=false; + end end is_periodic_all = is_periodic; is_periodic = any(is_periodic); if is_periodic && periodic_solution - [min_err,index_min_err]=min(max_err(find(is_periodic_all,1):end)); inx = find(is_periodic_all,1):iter; + inx1 = inx(find(~regime_violates_constraint_in_expectation(inx))); + if not(isempty(inx1)) + inx=inx1; + end + [min_err,index_min_err]=min(max_err(inx)); inx = inx(index_min_err); binding_indicator=binding_indicator_history{inx}; %select regime history with same result, but smallest error if inx<iter %update if needed @@ -295,8 +351,13 @@ for shock_period = 1:n_shocks_periods return; end else - disp_verbose('Did not converge -- increase maxit.',opts_simul_.debug) - error_flag = 311; + if is_periodic_loop + disp_verbose('Did not converge -- infinite loop of guess regimes.',opts_simul_.debug) + error_flag = 313; + else + disp_verbose('Did not converge -- increase maxit.',opts_simul_.debug) + error_flag = 311; + end if opts_simul_.waitbar; dyn_waitbar_close(hh); end return; end diff --git a/matlab/+occbin/solver.m b/matlab/+occbin/solver.m index 6b08d8a1f15a9941e5bb6d0ab8253a721764ffc5..11ac70eafa860dc806753c2fa63a3e9bb7b2d1fc 100644 --- a/matlab/+occbin/solver.m +++ b/matlab/+occbin/solver.m @@ -68,6 +68,12 @@ else oo_.dr=sto_dr; end +if options_.occbin.simul.check_ahead_periods>options_.occbin.simul.max_check_ahead_periods + options_.occbin.simul.check_ahead_periods=options_.occbin.simul.max_check_ahead_periods; + disp(['occbin::options::' simul '_check_ahead_periods cannot exceed ' simul '_max_check_ahead_periods']) + disp(['occbin::options::' simul '_check_ahead_periods is re-set to be equal to ' simul '_max_check_ahead_periods']) +end + if M_.occbin.constraint_nbr==1 [out, ss, error_flag ] = occbin.solve_one_constraint(M_,oo_.dr,options_.occbin.simul,solve_dr); elseif M_.occbin.constraint_nbr==2 diff --git a/matlab/dsge_likelihood.m b/matlab/dsge_likelihood.m index c3e86a08e8a736af4ab298c534db6d44f7d3ecad..c31e1e6dd97d608e5b9d8add63e48b8310583f91 100644 --- a/matlab/dsge_likelihood.m +++ b/matlab/dsge_likelihood.m @@ -974,6 +974,7 @@ occbin_options.opts_simul.curb_retrench = DynareOptions.occbin.likelihood.curb_r occbin_options.opts_simul.maxit = DynareOptions.occbin.likelihood.maxit; 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.max_check_ahead_periods = DynareOptions.occbin.likelihood.max_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; diff --git a/matlab/dynare_estimation_1.m b/matlab/dynare_estimation_1.m index 5f2801a4ac91342027c0a1285ac8ea91577c1ad5..44a77ede2697d5b75f57b9cab722c6f4e678b942 100644 --- a/matlab/dynare_estimation_1.m +++ b/matlab/dynare_estimation_1.m @@ -185,11 +185,14 @@ if isequal(options_.mode_compute,0) && isempty(options_.mode_file) && ~options_. else if options_.occbin.smoother.status [atT,innov,measurement_error,updated_variables,ys,trend_coeff,aK,T,R,P,PK,decomp,Trend,state_uncertainty,M_,oo_,bayestopt_] = occbin.DSGE_smoother(xparam1,gend,transpose(data),data_index,missing_value,M_,oo_,options_,bayestopt_,estim_params_,dataset_,dataset_info); + if oo_.occbin.smoother.error_flag==0 + [oo_]=store_smoother_results(M_,oo_,options_,bayestopt_,dataset_,dataset_info,atT,innov,measurement_error,updated_variables,ys,trend_coeff,aK,P,PK,decomp,Trend,state_uncertainty); + end else [atT,innov,measurement_error,updated_variables,ys,trend_coeff,aK,T,R,P,PK,decomp,Trend,state_uncertainty,M_,oo_,bayestopt_] = DsgeSmoother(xparam1,gend,transpose(data),data_index,missing_value,M_,oo_,options_,bayestopt_,estim_params_); - end [oo_]=store_smoother_results(M_,oo_,options_,bayestopt_,dataset_,dataset_info,atT,innov,measurement_error,updated_variables,ys,trend_coeff,aK,P,PK,decomp,Trend,state_uncertainty); end + end if options_.forecast > 0 oo_.forecast = dyn_forecast(var_list_,M_,options_,oo_,'smoother',dataset_info); end @@ -597,8 +600,12 @@ if (~((any(bayestopt_.pshape > 0) && options_.mh_replic) || (any(bayestopt_.psha else if options_.occbin.smoother.status [atT,innov,measurement_error,updated_variables,ys,trend_coeff,aK,T,R,P,PK,decomp,Trend,state_uncertainty,M_,oo_,bayestopt_] = occbin.DSGE_smoother(xparam1,dataset_.nobs,transpose(dataset_.data),dataset_info.missing.aindex,dataset_info.missing.state,M_,oo_,options_,bayestopt_,estim_params_,dataset_,dataset_info); + if oo_.occbin.smoother.error_flag==0 + [oo_,yf]=store_smoother_results(M_,oo_,options_,bayestopt_,dataset_,dataset_info,atT,innov,measurement_error,updated_variables,ys,trend_coeff,aK,P,PK,decomp,Trend,state_uncertainty); + end else [atT,innov,measurement_error,updated_variables,ys,trend_coeff,aK,T,R,P,PK,decomp,Trend,state_uncertainty,M_,oo_,bayestopt_] = DsgeSmoother(xparam1,dataset_.nobs,transpose(dataset_.data),dataset_info.missing.aindex,dataset_info.missing.state,M_,oo_,options_,bayestopt_,estim_params_); + [oo_,yf]=store_smoother_results(M_,oo_,options_,bayestopt_,dataset_,dataset_info,atT,innov,measurement_error,updated_variables,ys,trend_coeff,aK,P,PK,decomp,Trend,state_uncertainty); end [oo_,yf]=store_smoother_results(M_,oo_,options_,bayestopt_,dataset_,dataset_info,atT,innov,measurement_error,updated_variables,ys,trend_coeff,aK,P,PK,decomp,Trend,state_uncertainty); end diff --git a/matlab/evaluate_smoother.m b/matlab/evaluate_smoother.m index f1a1fe39473ecd505c354d2b904fbd40962d7207..fd94f8027bb5814b51397bd4e6c7ccf1f6d3460d 100644 --- a/matlab/evaluate_smoother.m +++ b/matlab/evaluate_smoother.m @@ -120,7 +120,9 @@ else DsgeSmoother(parameters,dataset_.nobs,transpose(dataset_.data),dataset_info.missing.aindex,dataset_info.missing.state,M_,oo_,options_,bayestopt_,estim_params_); end if ~(options_.occbin.smoother.status && options_.occbin.smoother.inversion_filter) - [oo_]=store_smoother_results(M_,oo_,options_,bayestopt_,dataset_,dataset_info,atT,innov,measurement_error,updated_variables,ys,trend_coeff,aK,P,PK,decomp,Trend,state_uncertainty); + if ~options_.occbin.smoother.status || (options_.occbin.smoother.status && oo_.occbin.smoother.error_flag==0) + [oo_]=store_smoother_results(M_,oo_,options_,bayestopt_,dataset_,dataset_info,atT,innov,measurement_error,updated_variables,ys,trend_coeff,aK,P,PK,decomp,Trend,state_uncertainty); + end else [oo_]=store_smoother_results(M_,oo_,options_,bayestopt_,dataset_,dataset_info,atT,innov,measurement_error,updated_variables,ys,trend_coeff); end diff --git a/matlab/get_error_message.m b/matlab/get_error_message.m index 1013184d69aeabf1c1434238082a4a718742bfee..72b95ac76f6f691d50c3e341797945960afbf04a 100644 --- a/matlab/get_error_message.m +++ b/matlab/get_error_message.m @@ -188,6 +188,8 @@ switch info(1) message = 'Occbin: Simulation did not converge, increase maxit or check_ahead_periods.'; case 312 message = 'Occbin: Constraint(s) are binding at the end of the sample.'; + case 313 + message = 'Occbin: Simulation did not converge -- infinite loop of guess regimes'; case 320 message = 'Piecewise linear Kalman filter: There was a problem in obtaining the likelihood.'; otherwise diff --git a/matlab/plot_shock_decomposition.m b/matlab/plot_shock_decomposition.m index ac8a8cbb1deb537175ad4417737f03f008e598a3..2bdb0c6ebc97fa7f945c52c4cb13e68766b2e437 100644 --- a/matlab/plot_shock_decomposition.m +++ b/matlab/plot_shock_decomposition.m @@ -470,13 +470,14 @@ switch type q2a.aux.yss=steady_state_aux; end i_var0 = i_var; + steady_state_0 = steady_state; [za, endo_names, endo_names_tex, steady_state, i_var, oo_] = ... annualized_shock_decomposition(z,M_, options_, i_var, t0, options_.nobs, realtime_, vintage_, steady_state,q2a); if options_.plot_shock_decomp.interactive && ~isempty(options_.plot_shock_decomp.use_shock_groups) mygroup = options_.plot_shock_decomp.use_shock_groups; options_.plot_shock_decomp.use_shock_groups=''; zafull = ... - annualized_shock_decomposition(zfull(i_var0,:,:),M_, options_, i_var, t0, options_.nobs, realtime_, vintage_, steady_state,q2a); + annualized_shock_decomposition(zfull(i_var0,:,:),M_, options_, i_var, t0, options_.nobs, realtime_, vintage_, steady_state_0(i_var0),q2a); options_.plot_shock_decomp.use_shock_groups = mygroup; end end diff --git a/tests/occbin/model_irrcap_twoconstraints/dynrbc_common.inc b/tests/occbin/model_irrcap_twoconstraints/dynrbc_common.inc index 768dac606c5471ac7826bd1cb92d069703e21c60..9f504605efd4f75964e107a9d7d05db38afcdcdf 100644 --- a/tests/occbin/model_irrcap_twoconstraints/dynrbc_common.inc +++ b/tests/occbin/model_irrcap_twoconstraints/dynrbc_common.inc @@ -30,7 +30,7 @@ steady; % Option=2: random simulation @#for option_val in [1, 2] - + option=@{option_val}; %%%%%%%%%%%%%%%% Inputs stop here %%%%%%%%%%%%%%%%%%%%% @@ -41,28 +41,28 @@ if option==1 periods 1:9, 10, 50, 90, 130, 131:169; values -0.0001, -0.01,-0.02, 0.01, 0.02, 0; end; - - + + elseif option==2 - nperiods = 100; + nperiods = 40; randn('seed',1); - shockssequence = 1*randn(nperiods,1)*0.02 ; - + shockssequence = 1*randn(nperiods,1)*0.02 ; + shocks(surprise,overwrite); var erra; - periods 1:100; + periods 1:40; values (shockssequence); end; end -% set inputs +% set inputs occbin_setup(smoother_debug); occbin_solver(simul_debug,simul_periodic_solution,simul_periods=200,simul_maxit=300,simul_curb_retrench,simul_check_ahead_periods=300); -occbin_write_regimes(filename='test',periods=[1:100]); +occbin_write_regimes(filename='test',periods=[1:40]); -%% Modify to plot IRFs +%% Modify to plot IRFs titlelist = char('c','lambdak','k','i','a'); percent = 'Percent'; value = 'value'; @@ -85,7 +85,7 @@ occbin_graph(noconstant) c erra lambdak k i a k; end; save('datasim.mat','c'); varobs c; - + occbin_solver(simul_periods=200,simul_maxit=200,simul_curb_retrench,simul_check_ahead_periods=200); occbin_setup(smoother_periods=200,smoother_maxit=200,smoother_curb_retrench,smoother_check_ahead_periods=200); calib_smoother(datafile=datasim); @@ -110,4 +110,4 @@ occbin_graph(noconstant) c erra lambdak k i a k; line2=100*[oo_.occbin.linear_smoother.SmoothedVariables.c-oo_.occbin.endo_ss.c,oo_.occbin.linear_smoother.SmoothedVariables.lambdak/100,oo_.occbin.linear_smoother.SmoothedVariables.k-oo_.occbin.endo_ss.k,oo_.occbin.linear_smoother.SmoothedVariables.i-oo_.occbin.endo_ss.i,oo_.occbin.linear_smoother.SmoothedVariables.a-oo_.occbin.endo_ss.a, oo_.occbin.linear_smoother.SmoothedShocks.erra/100]; occbin.make_chart(titlelist,legendlist,figtitle,ylabels,cat(3,line1,line2)); @#endif -@#endfor \ No newline at end of file +@#endfor