function x0 = stability_mapping(OutputDirectoryName,opt_gsa,M_,oo_,options_,estim_params_)
% x0 = stability_mapping(OutputDirectoryName,opt_gsa,M_,oo_,options_,estim_params_)
% Mapping of stability regions in the prior ranges applying
% Monte Carlo filtering techniques.
%
% Inputs
%  - OutputDirectoryName    [string]        name of the output directory
%  - opt_gsa                [structure]     GSA options structure
%  - M_                     [structure]     MATLAB's structure describing the model
%  - oo_                    [structure]     MATLAB's structure describing the results
%  - options_               [structure]     MATLAB's structure describing the current options
%  - estim_params_          [structure]     characterizing parameters to be estimated
%
% Outputs:
%  - x0                                 one parameter vector for which the model is stable.
%
%
% Inputs from opt_gsa structure
% Nsam = MC sample size
% fload = 0 to run new MC; 1 to load previously generated analysis
% alpha2 =  significance level for bivariate sensitivity analysis
% [abs(corrcoef) > alpha2]
% prepSA = 1: save transition matrices for mapping reduced form
%        = 0: no transition matrix saved (default)
% pprior = 1: sample from prior ranges (default): sample saved in
%            _prior.mat   file
%        = 0: sample from posterior ranges: sample saved in
%            _mc.mat file
%
% GRAPHS
% 1) Pdf's of marginal distributions under the stability (dotted
%     lines) and instability (solid lines) regions
% 2) Cumulative distributions of:
%   - stable subset (dotted lines)
%   - unacceptable subset (solid lines)
% 3) Bivariate plots of significant correlation patterns
%  ( abs(corrcoef) > alpha2) under the stable and unacceptable subsets
%
% USES qmc_sequence, gsa.stability_mapping_univariate, gsa.stability_mapping_bivariate
%
% Written by Marco Ratto
% Joint Research Centre, The European Commission,
% marco.ratto@ec.europa.eu

% Copyright © 2012-2016 European Commission
% Copyright © 2012-2025 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 <https://www.gnu.org/licenses/>.

Nsam   = opt_gsa.Nsam;
fload  = opt_gsa.load_stab;
alpha2 = opt_gsa.alpha2_stab;
pvalue_ks = opt_gsa.pvalue_ks;
pvalue_corr = opt_gsa.pvalue_corr;
prepSA = (opt_gsa.redform | opt_gsa.identification);
pprior = opt_gsa.pprior;
neighborhood_width = opt_gsa.neighborhood_width;
ilptau = opt_gsa.ilptau;
nliv   = opt_gsa.morris_nliv;
ntra   = opt_gsa.morris_ntra;

dr_ = oo_.dr;
ys_ = oo_.dr.ys;
nspred = M_.nspred; %size(dr_.ghx,2);
nboth = M_.nboth;
nfwrd = M_.nfwrd;
fname_ = M_.fname;

np = estim_params_.np;
nshock = estim_params_.nvx + estim_params_.nvn + estim_params_.ncx + estim_params_.ncn;
lpmat0=zeros(Nsam,0);
xparam1=[];

%% prepare prior bounds
[~,~,lb,ub] = set_prior(estim_params_,M_,options_); %Prepare bounds
Prior = dprior(estim_params_, M_, options_.prior_trunc);
if Prior.bayes()
    % Set prior bounds
    if options_.prior_trunc==0
        fprintf('\nstability_mapping: GSA with priors requires bounded support. Setting options_.prior_trunc=1e-10.\n')
        options_.prior_trunc=1e-10;
    end
    bounds = prior_bounds(Prior, options_.prior_trunc);
    bounds.lb = max(bounds.lb,lb);
    bounds.ub = min(bounds.ub,ub);
else  % estimated parameters but no declared priors
      % No priors are declared so Dynare will estimate the model by
      % maximum likelihood with inequality constraints for the parameters.
    bounds.lb = lb;
    bounds.ub = ub;
    if opt_gsa.prior_range==0
        warning('GSA:: When using ML, sampling from the prior is not possible. Setting prior_range=1')
        opt_gsa.prior_range=1;
    end
end

if nargin==0
    OutputDirectoryName='';
end

options_mcf.pvalue_ks = pvalue_ks;
options_mcf.pvalue_corr = pvalue_corr;
options_mcf.alpha2 = alpha2;

%% get LaTeX names
name=cell(np,1);
name_tex=cell(np,1);
for jj=1:np
    if options_.TeX
        [param_name_temp, param_name_tex_temp]= get_the_name(nshock+jj,options_.TeX,M_,estim_params_,options_.varobs);
        name_tex{jj,1} = param_name_tex_temp;
        name{jj,1} = param_name_temp;
    else
        param_name_temp = get_the_name(nshock+jj,options_.TeX,M_,estim_params_,options_.varobs);
        name{jj,1} = param_name_temp;
    end
end
if options_.TeX
    options_mcf.param_names_tex = name_tex;
end
options_mcf.param_names = name;

options_mcf.fname_ = fname_;
options_mcf.OutputDirectoryName = OutputDirectoryName;
options_mcf.xparam1 = [];

options_.periods=0;
options_.nomoments=1;
options_.irf=0;
options_.noprint=1;
if fload==0 %run new MC
    if isfield(dr_,'ghx')
        egg=zeros(length(dr_.eigval),Nsam);
    end
    yys=zeros(length(dr_.ys),Nsam);

    if opt_gsa.morris == 1
        [lpmat] = gsa.Sampling_Function_2(nliv, np+nshock, ntra, ones(np+nshock, 1), zeros(np+nshock,1), []);
        lpmat = lpmat.*(nliv-1)/nliv+1/nliv/2;
        Nsam=size(lpmat,1);
        lpmat0 = lpmat(:,1:nshock);
        lpmat = lpmat(:,nshock+1:end);
    else
        if np<1112 && ilptau>0
            [lpmat] = qmc_sequence(np, int64(1), 0, Nsam)';
            if np>30 || ilptau==2 % scrambled lptau
                for j=1:np
                    lpmat(:,j)=lpmat(randperm(Nsam),j);
                end
            end
        else %ilptau==0
            [lpmat] = NaN(Nsam,np);
            for j=1:np
                lpmat(:,j) = randperm(Nsam)'./(Nsam+1); %latin hypercube
            end
        end
    end
    prior_obj = dprior(estim_params_, M_, options_.prior_trunc, false);
    if pprior
        for j=1:nshock
            if opt_gsa.morris~=1
                lpmat0(:,j) = randperm(Nsam)'./(Nsam+1); %latin hypercube
            end
            if opt_gsa.prior_range
                lpmat0(:,j)=lpmat0(:,j).*(bounds.ub(j)-bounds.lb(j))+bounds.lb(j);
            end
        end
        if opt_gsa.prior_range
            for j=1:np
                lower_bound=max(-options_.huge_number,bounds.lb(j+nshock));
                upper_bound=min(options_.huge_number,bounds.ub(j+nshock));
                lpmat(:,j)=lpmat(:,j).*(upper_bound-lower_bound)+lower_bound;
            end
        else
            % Use new dprior.from_uniform() implementation
            xx = prior_obj.from_uniform([lpmat0 lpmat]);
            lpmat0=xx(:,1:nshock);
            lpmat=xx(:,nshock+1:end);
            clear xx;
        end
    else %posterior analysis
        if neighborhood_width>0 && isempty(options_.mode_file)
            xparam1 = get_all_parameters(estim_params_,M_);
        else
            load([options_.mode_file '.mat'],'hh','xparam1');
        end
        if neighborhood_width>0
            for j=1:nshock
                if opt_gsa.morris ~= 1
                    lpmat0(:,j) = randperm(Nsam)'./(Nsam+1); %latin hypercube
                end
                ub=min([bounds.ub(j) xparam1(j)*(1+neighborhood_width)]);
                lb=max([bounds.lb(j) xparam1(j)*(1-neighborhood_width)]);
                lpmat0(:,j)=lpmat0(:,j).*(ub-lb)+lb;
            end
            for j=1:np
                ub=xparam1(j+nshock)*(1+sign(xparam1(j+nshock))*neighborhood_width);
                lb=xparam1(j+nshock)*(1-sign(xparam1(j+nshock))*neighborhood_width);
                if bounds.ub(j+nshock)>=xparam1(j+nshock) && bounds.lb(j+nshock)<=xparam1(j+nshock)
                    ub=min([bounds.ub(j+nshock) ub]);
                    lb=max([bounds.lb(j+nshock) lb]);
                else
                    fprintf('\nstab_map_:: the calibrated value of param %s for neighborhood_width sampling is outside prior bounds.\nWe allow violation of bounds for this parameter, but if this was not done on purpose, please change calibration before running neighborhood_width sampling\n', Prior.name{j+nshock})
                end
                lpmat(:,j)=lpmat(:,j).*(ub-lb)+lb;
            end
        else
            d = chol(inv(hh));
            lp=randn(Nsam*2,nshock+np)*d+kron(ones(Nsam*2,1),xparam1');
            lnprior=zeros(1,Nsam*2);
            for j=1:Nsam*2
                lnprior(j) = any(lp(j,:)'<=bounds.lb | lp(j,:)'>=bounds.ub);
            end
            ireal=1:2*Nsam;
            ireal=ireal(lnprior==0);
            lp=lp(ireal,:);
            Nsam=min(Nsam, length(ireal));
            lpmat0=lp(1:Nsam,1:nshock);
            lpmat=lp(1:Nsam,nshock+1:end);
            clear lp lnprior ireal;
        end
    end
    %
    [h, length_of_old_string] = wait_bar.run(0,[],'Please wait. Stability mapping ...', options_.console_mode, 0, 'Stability mapping.');
    istable=1:Nsam;
    jstab=0;
    iunstable=1:Nsam;
    iindeterm=zeros(1,Nsam);
    iwrong=zeros(1,Nsam);
    inorestriction=zeros(1,Nsam);
    irestriction=zeros(1,Nsam);
    infox=zeros(Nsam,1);
    for j=1:Nsam
        M_ = set_all_parameters([lpmat0(j,:) lpmat(j,:)]',estim_params_,M_);
        try
            if ~isempty(options_.endogenous_prior_restrictions.moment)
                [Tt,Rr,~,info,oo_.dr,M_.params] = dynare_resolve(M_,options_,oo_.dr,oo_.steady_state,oo_.exo_steady_state,oo_.exo_det_steady_state);
            else
                [Tt,Rr,~,info,oo_.dr,M_.params] = dynare_resolve(M_,options_,oo_.dr,oo_.steady_state,oo_.exo_steady_state,oo_.exo_det_steady_state,'restrict');
            end
            infox(j,1)=info(1);
            if infox(j,1)==0 && ~exist('T','var')
                dr_=oo_.dr;
                if prepSA
                    try
                        T=zeros(size(dr_.ghx,1),size(dr_.ghx,2)+size(dr_.ghu,2),Nsam);
                    catch ME
                        if strcmp('MATLAB:nomem',ME.identifier)
                            prepSA=0;
                            disp('The model is too large for storing state space matrices ...')
                            disp('for mapping reduced form or for identification')
                        end
                        T=[];
                    end
                else
                    T=[];
                end
                egg=zeros(length(dr_.eigval),Nsam);
            end
            if infox(j,1)
                if isfield(oo_.dr,'ghx')
                    oo_.dr=rmfield(oo_.dr,'ghx');
                end
                if (infox(j,1)<3 || infox(j,1)>5) && isfield(oo_.dr,'eigval')
                    oo_.dr=rmfield(oo_.dr,'eigval');
                end
            end
        catch ME
            if isfield(oo_.dr,'eigval')
                oo_.dr=rmfield(oo_.dr,'eigval');
            end
            if isfield(oo_.dr,'ghx')
                oo_.dr=rmfield(oo_.dr,'ghx');
            end
            disp('No solution could be found')
        end
        dr_ = oo_.dr;
        if isfield(dr_,'ghx')
            egg(:,j) = sort(dr_.eigval);
            if prepSA
                jstab=jstab+1;
                T(:,:,jstab) = [dr_.ghx dr_.ghu];
            end
            if ~exist('nspred','var')
                nspred = dr_.nspred; %size(dr_.ghx,2);
                nboth = dr_.nboth;
                nfwrd = dr_.nfwrd;
            end
            info=endogenous_prior_restrictions(Tt,Rr,M_,options_,oo_.dr,oo_.steady_state,oo_.exo_steady_state,oo_.exo_det_steady_state);
            infox(j,1)=info(1);
            if info(1)
                inorestriction(j)=j;
            else
                iunstable(j)=0;
                irestriction(j)=j;
            end
        else
            istable(j)=0;
            if isfield(dr_,'eigval')
                egg(:,j) = sort(dr_.eigval);
                if exist('nspred','var')
                    if any(isnan(egg(1:nspred,j)))
                        iwrong(j)=j;
                    else
                        if (nboth || nfwrd) && abs(egg(nspred+1,j))<=options_.qz_criterium
                            iindeterm(j)=j;
                        end
                    end
                end
            else
                if exist('egg','var')
                    egg(:,j)=ones(size(egg,1),1).*NaN;
                end
                iwrong(j)=j;
            end
        end
        ys_=real(dr_.ys);
        yys(:,j) = ys_;
        if mod(j,3)
            [~,length_of_old_string]=wait_bar.run(j/Nsam,h,['MC iteration ',int2str(j),'/',int2str(Nsam)],options_.console_mode,length_of_old_string);
        end
    end
    wait_bar.close(h,options_.console_mode);
    if prepSA && jstab
        T=T(:,:,1:jstab);
    else
        T=[];
    end
    istable=istable(istable~=0);  % stable params ignoring restrictions
    irestriction=irestriction(irestriction~=0);  % stable params & restrictions OK
    inorestriction=inorestriction(inorestriction~=0);  % stable params violating restrictions
    iunstable=iunstable(iunstable~=0);   % violation of BK & restrictions & solution could not be found (whatever goes wrong)
    iindeterm=iindeterm(iindeterm~=0);  % indeterminacy
    iwrong=iwrong(iwrong~=0);  % Dynare could not find solution
    ixun=iunstable(~ismember(iunstable,[iindeterm,iwrong,inorestriction])); % explosive roots

    bkpprior.pshape=Prior.pshape();
    bkpprior.p1=Prior.p1;
    bkpprior.p2=Prior.p2;
    bkpprior.p3=Prior.p3;
    bkpprior.p4=Prior.p4;
    if pprior
        if ~prepSA
            save([OutputDirectoryName filesep fname_ '_prior.mat'], ...
                 'bkpprior','lpmat','lpmat0','irestriction','iunstable','istable','iindeterm','iwrong','ixun', ...
                 'egg','yys','nspred','nboth','nfwrd','infox')
        else
            save([OutputDirectoryName filesep fname_ '_prior.mat'], ...
                 'bkpprior','lpmat','lpmat0','irestriction','iunstable','istable','iindeterm','iwrong','ixun', ...
                 'egg','yys','T','nspred','nboth','nfwrd','infox')
        end
    else %~pprior
        if ~prepSA
            save([OutputDirectoryName filesep fname_ '_mc.mat'], ...
                 'lpmat','lpmat0','irestriction','iunstable','istable','iindeterm','iwrong','ixun', ...
                 'egg','yys','nspred','nboth','nfwrd','infox')
        else
            save([OutputDirectoryName filesep fname_ '_mc.mat'], ...
                 'lpmat','lpmat0','irestriction','iunstable','istable','iindeterm','iwrong','ixun', ...
                 'egg','yys','T','nspred','nboth','nfwrd','infox')
        end
    end
else %load old run
    if pprior
        filetoload=[OutputDirectoryName filesep fname_ '_prior.mat'];
    else
        filetoload=[OutputDirectoryName filesep fname_ '_mc.mat'];
    end
    load(filetoload,'lpmat','lpmat0','irestriction','iunstable','istable','iindeterm','iwrong','ixun','infox')
    Nsam = size(lpmat,1);
    if pprior==0 && ~isempty(options_.mode_file)
        load([options_.mode_file '.mat'],'xparam1');
    end

    if prepSA && isempty(strmatch('T',who('-file', filetoload),'exact'))
        [h, length_of_old_string] = wait_bar.run(0,[],'Please wait...', options_.console_mode, 0, 'Stability mapping.');

        options_.periods=0;
        options_.nomoments=1;
        options_.irf=0;
        options_.noprint=1;
        [~, oo_, options_] = stoch_simul(M_, options_, oo_, []);
        ntrans=length(istable);
        yys=NaN(length(ys_),ntrans);
        for j=1:ntrans
            M_.params(estim_params_.param_vals(:,1)) = lpmat(istable(j),:)';
            [~,~,~,~,oo_.dr,M_.params] = dynare_resolve(M_,options_,oo_.dr,oo_.steady_state,oo_.exo_steady_state,oo_.exo_det_steady_state,'restrict');
            if ~exist('T','var')
                T=zeros(size(dr_.ghx,1),size(dr_.ghx,2)+size(dr_.ghu,2),ntrans);
            end
            dr_ = oo_.dr;
            T(:,:,j) = [dr_.ghx dr_.ghu];
            ys_=real(dr_.ys);
            yys(:,j) = ys_;
            if mod(j,3)
                [~, length_of_old_string] = wait_bar.run(j/ntrans,h,['MC iteration ',int2str(j),'/',int2str(ntrans)], options_.console_mode, length_of_old_string);
            end
        end
        wait_bar.close(h,options_.console_mode);
        save(filetoload,'T','-append')
    end
end

%% display and save output
if pprior
    aunstname='prior_unstable'; aunsttitle='Prior StabMap: explosiveness of solution';
    aindname='prior_indeterm'; aindtitle='Prior StabMap: Indeterminacy';
    awrongname='prior_wrong'; awrongtitle='Prior StabMap: inability to find solution';
    acalibname='prior_calib'; acalibtitle='Prior StabMap: IRF/moment restrictions';
    asname='prior_stable'; atitle='Prior StabMap: Parameter driving non-existence of unique stable solution (Unacceptable)';
else
    aunstname='mc_unstable'; aunsttitle='MC (around posterior mode) StabMap: explosiveness of solution';
    aindname='mc_indeterm';  aindtitle='MC (around posterior mode) StabMap: Indeterminacy';
    awrongname='mc_wrong'; awrongtitle='MC (around posterior mode) StabMap: inability to find solution';
    acalibname='mc_calib'; acalibtitle='MC (around posterior mode) StabMap: IRF/moment restrictions';
    asname='mc_stable'; atitle='MC (around posterior mode) StabMap: Parameter driving non-existence of unique stable solution (Unacceptable)';
end
delete([OutputDirectoryName,filesep,fname_,'_',asname,'.*']);
delete([OutputDirectoryName,filesep,fname_,'_',acalibname,'.*']);
delete([OutputDirectoryName,filesep,fname_,'_',aindname,'.*']);
delete([OutputDirectoryName,filesep,fname_,'_',aunstname,'.*']);
delete([OutputDirectoryName,filesep,fname_,'_',awrongname,'.*']);

fprintf('\nSensitivity Analysis: Stability mapping:\n')
if ~isempty(iunstable) || ~isempty(iwrong)
    fprintf('%4.1f%% of the prior support gives unique saddle-path solution.\n',length(istable)/Nsam*100)
    fprintf('%4.1f%% of the prior support gives explosive dynamics.\n',(length(ixun) )/Nsam*100)
    if ~isempty(iindeterm)
        fprintf('%4.1f%% of the prior support gives indeterminacy.\n',length(iindeterm)/Nsam*100)
    end
    inorestriction = istable(~ismember(istable,irestriction)); % violation of prior restrictions
    if ~isempty(iwrong) || ~isempty(inorestriction)
        skipline()
        if any(infox==49)
            fprintf('%4.1f%% of the prior support violates prior restrictions.\n',(length(inorestriction) )/Nsam*100)
        end
        if ~isempty(iwrong)
            skipline()
            disp(['For ',num2str(length(iwrong)/Nsam*100,'%4.1f'),'% of the prior support Dynare could not find a solution.'])
            skipline()
        end
        if any(infox==1)
            disp(['    For ',num2str(length(find(infox==1))/Nsam*100,'%4.1f'),'% The model doesn''t determine the current variables uniquely.'])
        end
        if any(infox==2)
            disp(['    For ',num2str(length(find(infox==2))/Nsam*100,'%4.1f'),'% MJDGGES returned an error code.'])
        end
        if any(infox==6)
            disp(['    For ',num2str(length(find(infox==6))/Nsam*100,'%4.1f'),'% The Jacobian evaluated at the deterministic steady state is complex.'])
        end
        if any(infox==19)
            disp(['    For ',num2str(length(find(infox==19))/Nsam*100,'%4.1f'),'% The steadystate routine has thrown an exception (inconsistent deep parameters).'])
        end
        if any(infox==20)
            disp(['    For ',num2str(length(find(infox==20))/Nsam*100,'%4.1f'),'% Cannot find the steady state.'])
        end
        if any(infox==21)
            disp(['    For ',num2str(length(find(infox==21))/Nsam*100,'%4.1f'),'% The steady state is complex.'])
        end
        if any(infox==22)
            disp(['    For ',num2str(length(find(infox==22))/Nsam*100,'%4.1f'),'% The steady has NaNs.'])
        end
        if any(infox==23)
            disp(['    For ',num2str(length(find(infox==23))/Nsam*100,'%4.1f'),'% M_.params has been updated in the steadystate routine and has complex valued scalars.'])
        end
        if any(infox==24)
            disp(['    For ',num2str(length(find(infox==24))/Nsam*100,'%4.1f'),'% M_.params has been updated in the steadystate routine and has some NaNs.'])
        end
        if any(infox==30)
            disp(['    For ',num2str(length(find(infox==30))/Nsam*100,'%4.1f'),'% Ergodic variance can''t be computed.'])
        end

    end
    skipline()
    if length(iunstable)<Nsam || length(istable)>1
        itot = 1:Nsam;
        isolve = itot(~ismember(itot,iwrong)); % Dynare could find a solution
                                                     % Blanchard Kahn
        if neighborhood_width
            options_mcf.xparam1 = xparam1(nshock+1:end);
        end
        itmp = itot(~ismember(itot,istable));
        options_mcf.amcf_name = asname;
        options_mcf.amcf_title = atitle;
        options_mcf.beha_title = 'unique Stable Saddle-Path';
        options_mcf.nobeha_title = 'NO unique Stable Saddle-Path';
        if options_.TeX
            options_mcf.beha_title_latex = 'unique Stable Saddle-Path';
            options_mcf.nobeha_title_latex = 'NO unique Stable Saddle-Path';
        end
        options_mcf.title = 'unique solution';
        gsa.monte_carlo_filtering_analysis(lpmat, istable, itmp, options_mcf, M_, options_, estim_params_);

        if ~isempty(iindeterm)
            itmp = isolve(~ismember(isolve,iindeterm));
            options_mcf.amcf_name = aindname;
            options_mcf.amcf_title = aindtitle;
            options_mcf.beha_title = 'NO indeterminacy';
            options_mcf.nobeha_title = 'indeterminacy';
            if options_.TeX
                options_mcf.beha_title_latex = 'NO indeterminacy';
                options_mcf.nobeha_title_latex = 'indeterminacy';
            end
            options_mcf.title = 'indeterminacy';
            gsa.monte_carlo_filtering_analysis(lpmat, itmp, iindeterm, options_mcf, M_, options_, estim_params_);
        end

        if ~isempty(ixun)
            itmp = isolve(~ismember(isolve,ixun));
            options_mcf.amcf_name = aunstname;
            options_mcf.amcf_title = aunsttitle;
            options_mcf.beha_title = 'NO explosive solution';
            options_mcf.nobeha_title = 'explosive solution';
            if options_.TeX
                options_mcf.beha_title_latex = 'NO explosive solution';
                options_mcf.nobeha_title_latex = 'explosive solution';
            end
            options_mcf.title = 'instability';
            gsa.monte_carlo_filtering_analysis(lpmat, itmp, ixun, options_mcf, M_, options_, estim_params_);
        end

        inorestriction = istable(~ismember(istable,irestriction)); % violation of prior restrictions
        iwrong = iwrong(~ismember(iwrong,inorestriction)); % what went wrong beyond prior restrictions
        if ~isempty(iwrong)
            itmp = itot(~ismember(itot,iwrong));
            options_mcf.amcf_name = awrongname;
            options_mcf.amcf_title = awrongtitle;
            options_mcf.beha_title = 'NO inability to find a solution';
            options_mcf.nobeha_title = 'inability to find a solution';
            if options_.TeX
                options_mcf.beha_title_latex = 'NO inability to find a solution';
                options_mcf.nobeha_title_latex = 'inability to find a solution';
            end
            options_mcf.title = 'inability to find a solution';
            gsa.monte_carlo_filtering_analysis(lpmat, itmp, iwrong, options_mcf, M_, options_, estim_params_);
        end

        if ~isempty(irestriction)
            if neighborhood_width
                options_mcf.xparam1 = xparam1;
            end
            np=length(Prior);
            name=cell(np,1);
            name_tex=cell(np,1);
            for jj=1:np
                if options_.TeX
                    [param_name_temp, param_name_tex_temp]= get_the_name(jj,options_.TeX,M_,estim_params_,options_.varobs);
                    name_tex{jj,1} = param_name_tex_temp;
                    name{jj,1} = param_name_temp;
                else
                    param_name_temp = get_the_name(jj,options_.TeX,M_,estim_params_,options_.varobs);
                    name{jj,1} = param_name_temp;
                end
            end
            if options_.TeX
                options_mcf.param_names_tex = name_tex;
            end
            options_mcf.param_names = name;
            options_mcf.amcf_name = acalibname;
            options_mcf.amcf_title = acalibtitle;
            options_mcf.beha_title = 'prior IRF/moment calibration';
            options_mcf.nobeha_title = 'NO prior IRF/moment calibration';
            if options_.TeX
                options_mcf.beha_title_latex = 'prior IRF/moment calibration';
                options_mcf.nobeha_title_latex = 'NO prior IRF/moment calibration';
            end
            options_mcf.title = 'prior restrictions';
            gsa.monte_carlo_filtering_analysis([lpmat0 lpmat], irestriction, inorestriction, options_mcf, M_, options_, estim_params_);
            iok = irestriction(1);
            x0 = [lpmat0(iok,:)'; lpmat(iok,:)'];
        else
            iok = istable(1);
            x0=0.5.*(bounds.ub(1:nshock)-bounds.lb(1:nshock))+bounds.lb(1:nshock);
            x0 = [x0; lpmat(iok,:)'];
        end

        M_ = set_all_parameters(x0,estim_params_,M_);
        [oo_.dr,~,M_.params] = resol(0,M_,options_,oo_.dr ,oo_.steady_state, oo_.exo_steady_state, oo_.exo_det_steady_state);
    else
        disp('All parameter values in the specified ranges are not acceptable!')
        x0=[];
    end
else
    disp('All parameter values in the specified ranges give unique saddle-path solution,')
    disp('and match prior IRF/moment restriction(s) if any!')
    x0=0.5.*(bounds.ub(1:nshock)-bounds.lb(1:nshock))+bounds.lb(1:nshock);
    x0 = [x0; lpmat(istable(1),:)'];
end
skipline(1);

xparam1=x0;
save([OutputDirectoryName filesep 'prior_ok.mat'],'xparam1');
