diff --git a/matlab/+pac/+estimate/init.m b/matlab/+pac/+estimate/init.m
index cfed63b0f616940290cf29ebb8a5792632991fb6..8a63a24ef26bbcea38816faba0d0ef30f498f456 100644
--- a/matlab/+pac/+estimate/init.m
+++ b/matlab/+pac/+estimate/init.m
@@ -30,14 +30,28 @@ pattern = '(\(model_name\s*=\s*)(?<name>\w+)\)';
 pacmodl = regexp(RHS, pattern, 'names');
 pacmodl = pacmodl.name;
 
+pacmodel = M_.pac.(pacmodl);
+
 % Get the transformed equation to be estimated.
 [lhs, rhs, json] = get_lhs_and_rhs(eqname, M_);
 
 % Get definition of aux. variable for pac expectation...
-auxrhs = json.model{strmatch(sprintf('pac_expectation_%s', pacmodl), M_.lhs, 'exact')}.rhs; 
+if isfield(pacmodel, 'aux_id')
+    auxrhs = {M_.lhs{pacmodel.aux_id}, json.model{pacmodel.aux_id}.rhs};
+elseif isfield(pacmodel, 'components')
+    auxrhs = cell(length(pacmodel.components), 2);
+    for i=1:length(pacmodel.components)
+        auxrhs{i,1} = M_.lhs{pacmodel.components(i).aux_id};
+        auxrhs{i,2} = sprintf('(%s)', json.model{pacmodel.components(i).aux_id}.rhs);
+    end
+else
+    error('Cannot find auxiliary variables for PAC expectation.')
+end
 
 % ... and substitute in rhs.
-rhs = strrep(rhs, sprintf('pac_expectation_%s', pacmodl), auxrhs);
+for i=1:rows(auxrhs)
+    rhs = strrep(rhs, auxrhs{i,1}, auxrhs{i,2});
+end
 
 % Get pacmodel properties
 pacmodel = M_.pac.(pacmodl);
diff --git a/matlab/+pac/+update/parameters.m b/matlab/+pac/+update/parameters.m
index 30b454aa0ac693d3b8a90baf898dbe387b8cd3c3..09a5e4ffb234b8e7fd10b5029d4189c54c16ce6e 100644
--- a/matlab/+pac/+update/parameters.m
+++ b/matlab/+pac/+update/parameters.m
@@ -66,56 +66,118 @@ if ~isfield(varcalib, 'CompanionMatrix') || any(isnan(varcalib.CompanionMatrix(:
 end
 
 % Show the equations where this PAC model is used.
-fprintf('PAC model %s is used in equation %s.\n', pacname, pacmodel.eq_name);
-skipline()
+if verbose
+    fprintf('PAC model %s is used in equation %s.\n', pacname, pacmodel.eq_name);
+    skipline()
+end
+
+% Do we need to decompose the PAC expectation?
+if isfield(pacmodel, 'components')
+    numberofcomponents = length(pacmodel.components);
+else
+    numberofcomponents = 0;
+end
 
 % Build the vector of PAC parameters (ECM parameter + autoregressive parameters).
 pacvalues = DynareModel.params([pacmodel.ec.params; pacmodel.ar.params(1:pacmodel.max_lag)']);
+
 % Get the indices for the stationary/nonstationary variables in the VAR system.
-id = find(strcmp(DynareModel.endo_names{pacmodel.ec.vars(pacmodel.ec.istarget)}, varmodel.list_of_variables_in_companion_var));
-if isempty(id)
-    % Find the auxiliary variables if any
-    ad = find(cell2mat(cellfun(@(x) isauxiliary(x, [8 10]), varmodel.list_of_variables_in_companion_var, 'UniformOutput', false)));
-    if isempty(ad)
-        error('Cannot find the trend variable in the Companion VAR/VECM model.')
-    else
-        for i=1:length(ad)
-            auxinfo = DynareModel.aux_vars(get_aux_variable_id(varmodel.list_of_variables_in_companion_var{ad(i)}));
-            if isequal(auxinfo.endo_index, pacmodel.ec.vars(pacmodel.ec.istarget))
-                id = ad(i);
-                break
+if numberofcomponents
+    id = cell(numberofcomponents, 1);
+    for i=1:numberofcomponents
+        id(i) = {find(strcmp(DynareModel.endo_names{pacmodel.components(i).endo_var}, varmodel.list_of_variables_in_companion_var))};
+        if isempty(id{i})
+            % Find the auxiliary variables if any
+            ad = find(cell2mat(cellfun(@(x) isauxiliary(x, [8 10]), varmodel.list_of_variables_in_companion_var, 'UniformOutput', false)));
+            if isempty(ad)
+                error('Cannot find the trend variable in the Companion VAR/VECM model.')
+            else
+                for j=1:length(ad)
+                    auxinfo = DynareModel.aux_vars(get_aux_variable_id(varmodel.list_of_variables_in_companion_var{ad(j)}));
+                    if isequal(auxinfo.endo_index, pacmodel.components(i).endo_var)
+                        id(i) = {ad(j)};
+                        break
+                    end
+                    if isequal(auxinfo.type, 8) && isequal(auxinfo.orig_index, pacmodel.components(i).endo_var)
+                        id(i) = {ad(j)};
+                        break
+                    end
+                end
             end
-            if isequal(auxinfo.type, 8) && isequal(auxinfo.orig_index, pacmodel.ec.vars(pacmodel.ec.istarget))
-                id = ad(i);
-                break
+            if isempty(id{i})
+                error('Cannot find the trend variable in the Companion VAR/VECM model.')
             end
         end
     end
-    if isempty(id)
-        error('Cannot find the trend variable in the Companion VAR/VECM model.')
+else
+    id = {find(strcmp(DynareModel.endo_names{pacmodel.ec.vars(pacmodel.ec.istarget)}, varmodel.list_of_variables_in_companion_var))};
+    if isempty(id{1})
+        % Find the auxiliary variables if any
+        ad = find(cell2mat(cellfun(@(x) isauxiliary(x, [8 10]), varmodel.list_of_variables_in_companion_var, 'UniformOutput', false)));
+        if isempty(ad)
+            error('Cannot find the trend variable in the Companion VAR/VECM model.')
+        else
+            for i=1:length(ad)
+                auxinfo = DynareModel.aux_vars(get_aux_variable_id(varmodel.list_of_variables_in_companion_var{ad(i)}));
+                if isequal(auxinfo.endo_index, pacmodel.ec.vars(pacmodel.ec.istarget))
+                    id = {ad(i)};
+                    break
+                end
+                if isequal(auxinfo.type, 8) && isequal(auxinfo.orig_index, pacmodel.ec.vars(pacmodel.ec.istarget))
+                    id = {ad(i)};
+                    break
+                end
+            end
+        end
+        if isempty(id{1})
+            error('Cannot find the trend variable in the Companion VAR/VECM model.')
+        end
     end
 end
 
-% Infer the kind of PAC exoectation
-if isequal(pacmodel.auxiliary_model_type, 'var')
-    if varmodel.nonstationary(id)
-        kind = 'dd';
-        if varmodel.isconstant
-            id = id+1;
+if ~numberofcomponents
+    % Infer the kind of PAC exoectation
+    if isequal(pacmodel.auxiliary_model_type, 'var')
+        if varmodel.nonstationary(id{1})
+            kind = {'dd'};
+            if varmodel.isconstant
+                id{1} = id{1}+1;
+            end
+        else
+            kind = {'ll'};
+            if varmodel.isconstant
+                id{1} = id{1}+1;
+            end
         end
     else
-        kind = 'll'
-        if varmodel.isconstant
-            id = id+1;
-        end
+        % Trend component model is assumed.
+        kind = {'dd'};
     end
 else
-    % Trend component model is assumed.
-    kind = 'dd';
+    if varmodel.isconstant
+        for i=1:numberofcomponents
+            id{i} = id{i}+1;
+        end
+    end
 end
 
 % Override kind with the information provided by the user or update M_.pac
-
+if ~numberofcomponents
+    if ~isempty(pacmodel.kind)
+        kind = {pacmodel.kind};
+    else
+        pacmodel.kind = kind{1};
+    end
+else
+    kind = cell(numberofcomponents,1);
+    for i=1:numberofcomponents
+        if isempty(pacmodel.components(i).kind)
+            error('kind declaration is mandatory for each component in pac_target_info.')
+        else
+            kind{i} = pacmodel.components(i).kind;
+        end
+    end
+end
 
 % Get the value of the discount factor.
 beta = DynareModel.params(pacmodel.discount_index);
@@ -125,6 +187,12 @@ if isfield(pacmodel, 'growth_str')
     growth_flag = true;
 else
     growth_flag = false;
+    for i=1:numberofcomponents
+        if isfield(pacmodel.components(i), 'growth_str')
+            growth_flag = true;
+            break
+        end
+    end
 end
 
 % Do we have rule of thumb agents? γ is the share of optimizing agents.
@@ -136,84 +204,114 @@ end
 
 % Get h vector (plus the parameter for the growth neutrality correction).
 if growth_flag
-    [h, growthneutrality] = hVectors([pacvalues; beta], varcalib.CompanionMatrix, pacmodel.auxiliary_model_type, kind, id);
+    h = cell(1,length(id));
+    growthneutrality = cell(1,length(id));
+    for i=1:length(id)
+        [h{i}, growthneutrality{i}] = hVectors([pacvalues; beta], varcalib.CompanionMatrix, pacmodel.auxiliary_model_type, kind{i}, id{i});
+    end
 else
-    h = hVectors([pacvalues; beta], varcalib.CompanionMatrix, pacmodel.auxiliary_model_type, kind, id);
+    h = cell(1,length(id));
+    for i=1:length(id)
+        h(i) = {hVectors([pacvalues; beta], varcalib.CompanionMatrix, pacmodel.auxiliary_model_type, kind{i}, id{i})};
+    end
 end
 
 % Update M_.params with h
 if isequal(pacmodel.auxiliary_model_type, 'var')
     if DynareModel.var.(pacmodel.auxiliary_model_name).isconstant
-        DynareModel.params(pacmodel.h_param_indices) = h;
+        if isfield(pacmodel, 'h_param_indices')
+            % No decomposition
+            DynareModel.params(pacmodel.h_param_indices) = h{1};
+        else
+            for i=1:numberofcomponents
+                DynareModel.params(pacmodel.components(i).h_param_indices) = h{i};
+            end
+        end
     else
-        DynareModel.params(pacmodel.h_param_indices(1)) = .0;
-        DynareModel.params(pacmodel.h_param_indices(2:end)) = h;
-    end
+        if isfield(pacmodel, 'h_param_indices')
+            % No decomposition
+            DynareModel.params(pacmodel.h_param_indices(1)) = .0;
+            DynareModel.params(pacmodel.h_param_indices(2:end)) = h{1};
+        else
+            for i=1:numberofcomponents
+                DynareModel.params(pacmodel.components(i).h_param_indices(1)) = .0;
+                DynareModel.params(pacmodel.components(i).h_param_indices(2:end)) = h{i};
+            end
+        end
+    end % If the auxiliary model (VAR) has no constant.
 else
-    DynareModel.params(pacmodel.h_param_indices) = h;
-end
-
+    DynareModel.params(pacmodel.h_param_indices) = h{1};
+end % if auxiliary model is a VAR
 
 % Update the parameter related to the growth neutrality correction.
 if growth_flag
     % Growth neutrality as returned by hVector is valid iff
     % there is no exogenous variables in the model and in the
     % absence of non optimizing agents.
-    gg = -(growthneutrality-1); % Finite sum of autoregressive parameters + infinite sum of the coefficients in the PAC expectation term.
-    cc = 1.0-gg*gamma;          % First adjustment of the growth neutrality correction (should also be divided by gamma, done below at the end of this section).
-                                % We may have to further change the correction if we have nonzero mean exogenous variables.
-    ll = 0.0;
-    if isfield(pacmodel, 'optim_additive')
-        % Exogenous variables are present in the λ part (optimizing agents).
-        tmp0 = 0;
-        for i=1:length(pacmodel.optim_additive.params)
-            if isnan(pacmodel.optim_additive.params(i)) && islogical(pacmodel.optim_additive.bgp{i}) && pacmodel.optim_additive.bgp{i}
-                tmp0 = tmp0 + pacmodel.optim_additive.scaling_factor(i);
-            elseif ~isnan(pacmodel.optim_additive.params(i)) && islogical(pacmodel.optim_additive.bgp{i}) && pacmodel.optim_additive.bgp{i}
-                tmp0 = tmp0 + DynareModel.params(pacmodel.optim_additive.params(i))*pacmodel.optim_additive.scaling_factor(i);
-            elseif ~islogical(pacmodel.optim_additive.bgp{i})
-                error('It is not possible to provide a value for the mean of an exogenous variable appearing in the optimal part of the PAC equation.')
+    for j=1:length(id)
+        if isnan(growthneutrality{j})
+            continue
+        end
+        gg = -(growthneutrality{j}-1); % Finite sum of autoregressive parameters + infinite sum of the coefficients in the PAC expectation term.
+        cc = 1.0-gg*gamma;          % First adjustment of the growth neutrality correction (should also be divided by gamma, done below at the end of this section).
+                                    % We may have to further change the correction if we have nonzero mean exogenous variables.
+        ll = 0.0;
+        if isfield(pacmodel, 'optim_additive')
+            % Exogenous variables are present in the λ part (optimizing agents).
+            tmp0 = 0;
+            for i=1:length(pacmodel.optim_additive.params)
+                if isnan(pacmodel.optim_additive.params(i)) && islogical(pacmodel.optim_additive.bgp{i}) && pacmodel.optim_additive.bgp{i}
+                    tmp0 = tmp0 + pacmodel.optim_additive.scaling_factor(i);
+                elseif ~isnan(pacmodel.optim_additive.params(i)) && islogical(pacmodel.optim_additive.bgp{i}) && pacmodel.optim_additive.bgp{i}
+                    tmp0 = tmp0 + DynareModel.params(pacmodel.optim_additive.params(i))*pacmodel.optim_additive.scaling_factor(i);
+                elseif ~islogical(pacmodel.optim_additive.bgp{i})
+                    error('It is not possible to provide a value for the mean of an exogenous variable appearing in the optimal part of the PAC equation.')
+                end
             end
+            cc = cc - tmp0*gamma;
         end
-        cc = cc - tmp0*gamma;
-    end
-    if gamma<1
-        if isfield(pacmodel, 'non_optimizing_behaviour') && isfield(pacmodel.non_optimizing_behaviour, 'params')
-            % Exogenous variables are present in the 1-λ part (rule of thumb agents).
+        if gamma<1
+            if isfield(pacmodel, 'non_optimizing_behaviour') && isfield(pacmodel.non_optimizing_behaviour, 'params')
+                % Exogenous variables are present in the 1-λ part (rule of thumb agents).
+                tmp0 = 0;
+                tmp1 = 0;
+                for i=1:length(pacmodel.non_optimizing_behaviour.params)
+                    if isnan(pacmodel.non_optimizing_behaviour.params(i)) && islogical(pacmodel.non_optimizing_behaviour.bgp{i}) && pacmodel.non_optimizing_behaviour.bgp{i}
+                        tmp0 = tmp0 + pacmodel.non_optimizing_behaviour.scaling_factor(i);
+                    elseif ~isnan(pacmodel.non_optimizing_behaviour.params(i)) && islogical(pacmodel.non_optimizing_behaviour.bgp{i}) && pacmodel.non_optimizing_behaviour.bgp{i}
+                        tmp0 = tmp0 + DynareModel.params(pacmodel.non_optimizing_behaviour.params(i))*pacmodel.non_optimizing_behaviour.scaling_factor(i);
+                    elseif ~islogical(pacmodel.non_optimizing_behaviour.bgp{i}) && isnumeric(pacmodel.non_optimizing_behaviour.bgp{i}) && isnan(pacmodel.non_optimizing_behaviour.params(i))
+                        tmp1 = tmp1 + pacmodel.non_optimizing_behaviour.scaling_factor(i)*pacmodel.non_optimizing_behaviour.bgp{i};
+                    elseif ~islogical(pacmodel.non_optimizing_behaviour.bgp{i}) && isnumeric(pacmodel.non_optimizing_behaviour.bgp{i}) && ~isnan(pacmodel.non_optimizing_behaviour.params(i))
+                        tmp1 = tmp1 + pacmodel.non_optimizing_behaviour.scaling_factor(i)*pacmodel.non_optimizing_behaviour.params(i)*pacmodel.non_optimizing_behaviour.bgp{i};
+                    end
+                end
+                cc = cc - (1.0-gamma)*tmp0;
+                ll = -(1.0-gamma)*tmp1/gamma; % TODO: ll should be added as a constant in the PAC equation (under the λ part) when unrolling pac_expectation.
+            end
+        end
+        if isfield(pacmodel, 'additive')
+            % Exogenous variables are present outside of the λ and (1-λ) parts (or we have exogenous variables in a "pure" PAC equation.
             tmp0 = 0;
             tmp1 = 0;
-            for i=1:length(pacmodel.non_optimizing_behaviour.params)
-                if isnan(pacmodel.non_optimizing_behaviour.params(i)) && islogical(pacmodel.non_optimizing_behaviour.bgp{i}) && pacmodel.non_optimizing_behaviour.bgp{i}
-                    tmp0 = tmp0 + pacmodel.non_optimizing_behaviour.scaling_factor(i);
-                elseif ~isnan(pacmodel.non_optimizing_behaviour.params(i)) && islogical(pacmodel.non_optimizing_behaviour.bgp{i}) && pacmodel.non_optimizing_behaviour.bgp{i}
-                    tmp0 = tmp0 + DynareModel.params(pacmodel.non_optimizing_behaviour.params(i))*pacmodel.non_optimizing_behaviour.scaling_factor(i);
-                elseif ~islogical(pacmodel.non_optimizing_behaviour.bgp{i}) && isnumeric(pacmodel.non_optimizing_behaviour.bgp{i}) && isnan(pacmodel.non_optimizing_behaviour.params(i))
-                    tmp1 = tmp1 + pacmodel.non_optimizing_behaviour.scaling_factor(i)*pacmodel.non_optimizing_behaviour.bgp{i};
-                elseif ~islogical(pacmodel.non_optimizing_behaviour.bgp{i}) && isnumeric(pacmodel.non_optimizing_behaviour.bgp{i}) && ~isnan(pacmodel.non_optimizing_behaviour.params(i))
-                    tmp1 = tmp1 + pacmodel.non_optimizing_behaviour.scaling_factor(i)*pacmodel.non_optimizing_behaviour.params(i)*pacmodel.non_optimizing_behaviour.bgp{i};
+            for i=1:length(pacmodel.additive.params)
+                if isnan(pacmodel.additive.params(i)) && islogical(pacmodel.additive.bgp{i}) && pacmodel.additive.bgp{i}
+                    tmp0 = tmp0 + pacmodel.additive.scaling_factor(i);
+                elseif ~isnan(pacmodel.additive.params(i)) && islogical(pacmodel.additive.bgp{i}) && pacmodel.additive.bgp{i}
+                    tmp0 = tmp0 + DynareModel.params(pacmodel.additive.params(i))*pacmodel.additive.scaling_factor(i);
+                elseif ~islogical(pacmodel.additive.bgp{i}) && isnumeric(pacmodel.additive.bgp{i}) && isnan(pacmodel.additive.params(i))
+                    tmp1 = tmp1 + pacmodel.additive.scaling_factor(i)*pacmodel.additive.bgp{i};
+                elseif ~islogical(pacmodel.additive.bgp{i}) && isnumeric(pacmodel.additive.bgp{i}) && ~isnan(pacmodel.additive.params(i))
+                    tmp1 = tmp1 + pacmodel.additive.scaling_factor(i)*pacmodel.additive.params(i)*pacmodel.additive.bgp{i};
                 end
             end
-            cc = cc - (1.0-gamma)*tmp0;
-            ll = -(1.0-gamma)*tmp1/gamma; % TODO: ll should be added as a constant in the PAC equation (under the λ part) when unrolling pac_expectation.
+            cc = cc - tmp0;
+            ll = ll - tmp1/gamma; % TODO: ll should be added as a constant in the PAC equation (under the λ part) when unrolling pac_expectation.
         end
-    end
-    if isfield(pacmodel, 'additive')
-        % Exogenous variables are present outside of the λ and (1-λ) parts (or we have exogenous variables in a "pure" PAC equation.
-        tmp0 = 0;
-        tmp1 = 0;
-        for i=1:length(pacmodel.additive.params)
-            if isnan(pacmodel.additive.params(i)) && islogical(pacmodel.additive.bgp{i}) && pacmodel.additive.bgp{i}
-                tmp0 = tmp0 + pacmodel.additive.scaling_factor(i);
-            elseif ~isnan(pacmodel.additive.params(i)) && islogical(pacmodel.additive.bgp{i}) && pacmodel.additive.bgp{i}
-                tmp0 = tmp0 + DynareModel.params(pacmodel.additive.params(i))*pacmodel.additive.scaling_factor(i);
-            elseif ~islogical(pacmodel.additive.bgp{i}) && isnumeric(pacmodel.additive.bgp{i}) && isnan(pacmodel.additive.params(i))
-                tmp1 = tmp1 + pacmodel.additive.scaling_factor(i)*pacmodel.additive.bgp{i};
-            elseif ~islogical(pacmodel.additive.bgp{i}) && isnumeric(pacmodel.additive.bgp{i}) && ~isnan(pacmodel.additive.params(i))
-                tmp1 = tmp1 + pacmodel.additive.scaling_factor(i)*pacmodel.additive.params(i)*pacmodel.additive.bgp{i};
-            end
+        if isfield(pacmodel, 'growth_neutrality_param_index')
+            DynareModel.params(pacmodel.growth_neutrality_param_index) = cc/gamma; % Multiplies the variable or expression provided though the growth option in command pac_model.
+        else
+            DynareModel.params(pacmodel.components(j).growth_neutrality_param_index) = cc/gamma; % Multiplies the variable or expression provided though the growth option in command pac_model.
         end
-        cc = cc - tmp0;
-        ll = ll - tmp1/gamma; % TODO: ll should be added as a constant in the PAC equation (under the λ part) when unrolling pac_expectation.
     end
-    DynareModel.params(pacmodel.growth_neutrality_param_index) = cc/gamma; % Multiplies the variable or expression provided though the growth option in command pac_model.
-end
+end
\ No newline at end of file
diff --git a/matlab/aggregate.m b/matlab/aggregate.m
index 38ff663a08f724c09a60116045b5a00701835423..9fdd676705955e837782a14fbf6f0bc467b281dc 100644
--- a/matlab/aggregate.m
+++ b/matlab/aggregate.m
@@ -90,7 +90,7 @@ for i=1:length(varargin)
                     model{j} = strrep(model{j}, eqtagname{1}, eqtagname_);
                 end
             else
-                model{j} = eqtagname_;
+                model{j} = strcat('[', eqtagname_, ']');
             end
             % Add equation tag with block name.
             if ~isempty(rootfolder)
diff --git a/matlab/cherrypick.m b/matlab/cherrypick.m
index 0f4fabed276c0a74675384b7fb0100a6389e3dd5..c1f4d983b56e69e5527f7e41b75644409b4a7d78 100644
--- a/matlab/cherrypick.m
+++ b/matlab/cherrypick.m
@@ -82,10 +82,10 @@ try
         % Get the original equation.
         [LHS, RHS] = get_lhs_and_rhs(eqtags{i}, M_, true, json);
         % Get the parameters, endogenous and exogenous variables in the current equation.
-        [pnames, ~, xnames] = get_variables_and_parameters_in_equation(LHS, RHS, M_);
+        [pnames, enames, xnames] = get_variables_and_parameters_in_equation(LHS, RHS, M_);
         lhs_expression = LHS;
         LHS = get_variables_and_parameters_in_expression(LHS);
-        enames = LHS;
+        enames = union(enames, LHS);
         if length(LHS)>1
             error('Expressions with more than one variable on the LHS are not allowed.')
         end
@@ -111,7 +111,11 @@ try
         end
         % Remove residual from equation if required.
         if noresids
-            exogenous_variables_to_be_removed = ~ismember(xnames, M_.simulation_exo_names);
+            if isfield(M_, 'simulation_exo_names')
+                exogenous_variables_to_be_removed = ~ismember(xnames, M_.simulation_exo_names);
+            else
+                exogenous_variables_to_be_removed = false(size(xnames));
+            end
             if any(exogenous_variables_to_be_removed)
                 switch sum(exogenous_variables_to_be_removed)
                   case 1
@@ -128,31 +132,77 @@ try
         % Unroll expectation terms if any.
         isvar = regexp(RHS, 'var_expectation\(model_name = (?<name>\w+)\)', 'names');
         ispac = regexp(RHS, 'pac_expectation\(model_name = (?<name>\w+)\)', 'names');
+        istar = regexp(RHS, 'pac_target_nonstationary\(model_name = (?<name>\w+)\)', 'names');
         if ~isempty(isvar)
             rhs = write_expectations(isvar.name, 'var');
-            lhs = sprintf('%s_VE', eqtags{i});
-            RHS = strrep(RHS, sprintf('var_expectation(model_name = %s)', isvar.name), lhs);
+            auxlhs = sprintf('%s_VE', eqtags{i});
+            RHS = strrep(RHS, sprintf('var_expectation(model_name = %s)', isvar.name), auxlhs);
         end
         if ~isempty(ispac)
-            [rhs, growthneutralitycorrection] = write_expectations(ispac.name, 'pac');
+            if isfield(M_.pac.(ispac.name), 'components')
+                [rhs, growthneutralitycorrection] = write_expectations(ispac.name, 'pac', false, false);
+            else
+                [rhs, growthneutralitycorrection] = write_expectations(ispac.name, 'pac');
+            end
             if ~isempty(rhs)
-                lhs = sprintf('%s_PE', eqtags{i});
-                if isempty(growthneutralitycorrection)
+                if iscell(rhs) % PAC expectations are decomposed.
+                    auxlhs = cell(size(rhs));
+                    for k=1:length(M_.pac.(ispac.name).components)
+                        if isequal(k, 1)
+                            lhs = M_.lhs{M_.pac.(ispac.name).components(k).aux_id};
+                            auxlhs{k} = lhs;
+                            if ~isempty(growthneutralitycorrection{k})
+                                lhs = sprintf('%s+%s', lhs, growthneutralitycorrection{k});
+                            end
+                            if  ~isequal(M_.pac.(ispac.name).components(k).coeff_str, '1')
+                                if isempty(growthneutralitycorrection{k})
+                                    lhs = sprintf('%s*%s', M_.pac.(ispac.name).components(k).coeff_str, lhs);
+                                else
+                                    lhs = sprintf('%s*(%s)', M_.pac.(ispac.name).components(k).coeff_str, lhs);
+                                end
+                            end
+                        else
+                            lhs_ = M_.lhs{M_.pac.(ispac.name).components(k).aux_id};
+                            auxlhs{k} = lhs_;
+                            if ~isempty(growthneutralitycorrection{k})
+                                lhs_ = sprintf('%s+%s', lhs_, growthneutralitycorrection{k});
+                            end
+                            if  ~isequal(M_.pac.(ispac.name).components(k).coeff_str, '1')
+                                if isempty(growthneutralitycorrection{k})
+                                    lhs_ = sprintf('%s*%s', M_.pac.(ispac.name).components(k).coeff_str, lhs_);
+                                else
+                                    lhs_ = sprintf('%s*(%s)', M_.pac.(ispac.name).components(k).coeff_str, lhs_);
+                                end
+                            end
+                            lhs = sprintf('%s+%s', lhs, lhs_);
+                        end
+                    end
                     RHS = strrep(RHS, sprintf('pac_expectation(model_name = %s)', ispac.name), lhs);
                 else
-                    RHS = strrep(RHS, sprintf('pac_expectation(model_name = %s)', ispac.name), sprintf('%s+%s', lhs, growthneutralitycorrection));
+                    auxlhs = M_.lhs{M_.pac.(ispac.name).aux_id};
+                    if isempty(growthneutralitycorrection)
+                        RHS = strrep(RHS, sprintf('pac_expectation(model_name = %s)', ispac.name), auxlhs);
+                    else
+                        RHS = strrep(RHS, sprintf('pac_expectation(model_name = %s)', ispac.name), sprintf('%s+%s', auxlhs, growthneutralitycorrection));
+                    end
                 end
             else
                 % MCE version of the PAC equation.
                 [rhs, growthneutralitycorrection] = write_pac_mce_expectations(eqtags{i}, ispac.name);
-                lhs = sprintf('%s_Z', eqtags{i});
+                auxlhs = sprintf('%s_Z', eqtags{i});
                 if isempty(growthneutralitycorrection)
-                    RHS = strrep(RHS, sprintf('pac_expectation(model_name = %s)', ispac.name), lhs);
+                    RHS = strrep(RHS, sprintf('pac_expectation(model_name = %s)', ispac.name), auxlhs);
                 else
-                    RHS = strrep(RHS, sprintf('pac_expectation(model_name = %s)', ispac.name), sprintf('%s+%s', lhs, growthneutralitycorrection));
+                    RHS = strrep(RHS, sprintf('pac_expectation(model_name = %s)', ispac.name), sprintf('%s+%s', auxlhs, growthneutralitycorrection));
                 end
             end
         end
+        if ~isempty(istar)
+            % Note that auxlhs and rhs are already defined in the previous block, it is not possible to be here if isempty(ispac) is true.
+            auxlhs{end+1} = M_.endo_names{M_.pac.(ispac.name).ec.vars(M_.pac.(ispac.name).ec.istarget)};
+            rhs{end+1} = M_.aux_vars(strmatch(auxlhs{end}, M_.endo_names, 'exact')==[M_.aux_vars(:).endo_index]).orig_expr;
+            RHS = strrep(RHS, sprintf('pac_target_nonstationary(model_name = %s)', ispac.name), sprintf('%s(-1)', auxlhs{end}));
+        end
         % Print equation for unrolled PAC/VAR-expectation and update
         % list of parameters and endogenous variables (if any).
         if ~isempty(rhs)
@@ -160,13 +210,28 @@ try
             % will not return the lhs variable in expectation_enames since
             % the name is created on the fly and is not a  member of M_.endo_names.
             expectation_pnames = get_variables_and_parameters_in_equation('', rhs, M_);
-            expectation_enames = get_variables_and_parameters_in_expression(lhs);
+            expectation_enames = get_variables_and_parameters_in_expression(auxlhs);
             expectation_xnames = get_variables_and_parameters_in_expression(rhs);
             pnames = union(pnames, expectation_pnames);
             xnames = union(xnames, setdiff(expectation_xnames, expectation_pnames));
             enames = union(enames, expectation_enames);
-            fprintf(fid, '[name=''%s'']\n', lhs);
-            fprintf(fid, '%s = %s;\n\n', lhs, rhs);
+            if ischar(rhs)
+                fprintf(fid, '[name=''%s'']\n', auxlhs);
+                fprintf(fid, '%s = %s;\n\n', auxlhs, rhs);
+            else
+                for k=1:length(rhs)
+                    fprintf(fid, '[name=''%s'']\n', auxlhs{k});
+                    fprintf(fid, '%s = %s;\n\n', auxlhs{k}, rhs{k});
+                end
+            end
+            if isfield(M_.pac.(ispac.name), 'components')
+                for k=1:length(M_.pac.(ispac.name).components)
+                    if ~isequal(M_.pac.(ispac.name).components(k).coeff_str, '1')
+                        params = get_variables_and_parameters_in_expression(M_.pac.(ispac.name).components(k).coeff_str);
+                        pnames = union(pnames, params);
+                    end
+                end
+            end
         else
             pRHS = get_variables_and_parameters_in_equation('', RHS, M_);
             xRHS = get_variables_and_parameters_in_expression(RHS);
diff --git a/matlab/get_variables_and_parameters_in_expression.m b/matlab/get_variables_and_parameters_in_expression.m
index c12d69b24802562f08e682d03968ea47ea5df21a..26af543c07e09c36c193ac5bc4799b37d878d53e 100644
--- a/matlab/get_variables_and_parameters_in_expression.m
+++ b/matlab/get_variables_and_parameters_in_expression.m
@@ -8,7 +8,7 @@ function objects = get_variables_and_parameters_in_expression(expr)
 % OUTPUTS
 % - objects    [cell]             cell of row char arrays, names of the variables and parameters in expr.
 
-% Copyright (C) 2020 Dynare Team
+% Copyright © 2020-2021 Dynare Team
 %
 % This file is part of Dynare.
 %
@@ -25,16 +25,27 @@ function objects = get_variables_and_parameters_in_expression(expr)
 % You should have received a copy of the GNU General Public License
 % along with Dynare.  If not, see <https://www.gnu.org/licenses/>.
 
-objects = strsplit(expr, {'+','-','*','/','^', ...
+if iscell(expr)
+    objects = splitexpr(expr{1});
+    for i=2:length(expr)
+        objects = [objects, splitexpr(expr{i})];
+    end
+else
+    objects = splitexpr(expr);
+end
+
+% Filter out the numbers, punctuation.
+objects(cellfun(@(x) all(isstrprop(x, 'digit')+isstrprop(x, 'punct')), objects)) = [];
+
+                        % Filter out empty elements.
+                        objects(cellfun(@(x) all(isempty(x)), objects)) = [];
+
+
+                        function o = splitexpr(expr)
+                        o = strsplit(expr, {'+','-','*','/','^', ...
                     'log(', 'log10(', 'ln(', 'exp(', ...
                     'sqrt(', 'abs(', 'sign(', ...
                     'sin(', 'cos(', 'tan(', 'asin(', 'acos(', 'atan(', ...
                     'min(', 'max(', ...
                     'normcdf(', 'normpdf(', 'erf(', ...
-                    'diff(', 'adl(', '(', ')', '\n', '\t', ' '});
-
-% Filter out the numbers, punctuation.
-objects(cellfun(@(x) all(isstrprop(x, 'digit')+isstrprop(x, 'punct')), objects)) = [];
-
-% Filter out empty elements.
-objects(cellfun(@(x) all(isempty(x)), objects)) = [];
\ No newline at end of file
+                    'diff(', 'adl(', '(', ')', '\n', '\t', ' '});
\ No newline at end of file
diff --git a/matlab/print_expectations.m b/matlab/print_expectations.m
index 783baa05f23803729607d7032c08f578eae8f381..816b0be734ab88a2494990de139493a991b70af4 100644
--- a/matlab/print_expectations.m
+++ b/matlab/print_expectations.m
@@ -127,13 +127,29 @@ switch expectationmodelkind
     end
   case 'pac'
     parameter_declaration = 'parameters';
-    for i=1:length(expectationmodel.h_param_indices)
-        parameter_declaration = sprintf('%s %s', parameter_declaration, M_.param_names{expectationmodel.h_param_indices(i)});
+    if isfield(expectationmodel, 'h_param_indices')
+        for i=1:length(expectationmodel.h_param_indices)
+            parameter_declaration = sprintf('%s %s', parameter_declaration, M_.param_names{expectationmodel.h_param_indices(i)});
+        end
+    else
+        for j=1:length(expectationmodel.components)
+            for i=1:length(expectationmodel.components(j).h_param_indices)
+                parameter_declaration = sprintf('%s %s', parameter_declaration, M_.param_names{expectationmodel.components(j).h_param_indices(i)});
+            end
+        end
     end
     fprintf(fid, '%s;\n\n', parameter_declaration);
     if withcalibration
-        for i=1:length(expectationmodel.h_param_indices)
-            fprintf(fid, '%s = %1.16f;\n', M_.param_names{expectationmodel.h_param_indices(i)}, M_.params(expectationmodel.h_param_indices(i)));
+        if isfield(expectationmodel, 'h_param_indices')
+            for i=1:length(expectationmodel.h_param_indices)
+                fprintf(fid, '%s = %1.16f;\n', M_.param_names{expectationmodel.h_param_indices(i)}, M_.params(expectationmodel.h_param_indices(i)));
+            end
+        else
+            for j=1:length(expectationmodel.components)
+                for i=1:length(expectationmodel.components(j).h_param_indices)
+                    fprintf(fid, '%s = %1.16f;\n', M_.param_names{expectationmodel.components(j).h_param_indices(i)}, M_.params(expectationmodel.components(j).h_param_indices(i)));
+                end
+            end
         end
     end
     if isfield(expectationmodel, 'growth_neutrality_param_index')
@@ -145,10 +161,20 @@ switch expectationmodelkind
         growth_correction = true;
     else
         growth_correction = false;
+        if isfield(expectationmodel, 'components')
+            for j=1:length(expectationmodel.components)
+                if isfield(expectationmodel.components(j), 'growth_neutrality_param_index') && ~isempty(expectationmodel.components(j).growth_neutrality_param_index)
+                    fprintf(fid, '\n');
+                    fprintf(fid, 'parameters %s;\n\n', M_.param_names{expectationmodel.components(j).growth_neutrality_param_index});
+                    if withcalibration
+                        fprintf(fid, '%s = %1.16f;\n', M_.param_names{expectationmodel.components(j).growth_neutrality_param_index}, M_.params(expectationmodel.components(j).growth_neutrality_param_index));
+                    end
+                    growth_correction = true;
+                end
+            end
+        end
     end
-  otherwise
 end
-
 fclose(fid);
 
 skipline()
@@ -211,6 +237,13 @@ fprintf(fid, 'ds = dseries();\n\n');
 
 id = 0;
 
+clear('expression');
+
+% Get coefficient values in the target (if any)
+if exist(sprintf('+%s/pac_target_coefficients.m', M_.fname), 'file')
+    targetcoefficients = feval(sprintf('%s.pac_target_coefficients', M_.fname), expectationmodelname, M_.params);
+end
+
 maxlag = max(auxmodel.max_lag);
 if isequal(expectationmodel.auxiliary_model_type, 'trend_component')
     % Need to add a lag since the error correction equations are rewritten in levels.
@@ -222,13 +255,23 @@ if isequal(expectationmodelkind, 'var')
 end
 
 if isequal(expectationmodelkind, 'var') && isequal(expectationmodel.auxiliary_model_type, 'var')
+    % Constant in the VAR auxiliary model
     id = id+1;
     expression = sprintf('%1.16f', M_.params(expectationmodel.param_indices(id)));
 end
 
 if isequal(expectationmodelkind, 'pac') && isequal(expectationmodel.auxiliary_model_type, 'var')
+    % Constant in the VAR auxiliary model
     id = id+1;
-    expression = sprintf('%1.16f', M_.params(expectationmodel.h_param_indices(id)));
+    if isfield(expectationmodel, 'h_param_indices')
+        constant = M_.params(expectationmodel.h_param_indices(id));
+    else
+        constant = 0;
+        for j=1:length(expectationmodel.components)
+            constant = constant + targetcoefficients(j)*M_.params(expectationmodel.components(j).h_param_indices(id));
+        end
+    end
+    expression = sprintf('%1.16f', constant);
 end
 
 for i=1:maxlag
@@ -256,7 +299,14 @@ for i=1:maxlag
           case 'var'
             parameter = M_.params(expectationmodel.param_indices(id));
           case 'pac'
-            parameter = M_.params(expectationmodel.h_param_indices(id));
+            if isfield(expectationmodel, 'h_param_indices')
+                parameter = M_.params(expectationmodel.h_param_indices(id));
+            else
+                parameter = 0;
+                for k=1:length(expectationmodel.components)
+                    parameter = parameter+targetcoefficients(k)*M_.params(expectationmodel.components(k).h_param_indices(id));
+                end
+            end
           otherwise
         end
         switch expectationmodelkind
@@ -275,61 +325,115 @@ for i=1:maxlag
                 variable = sprintf('%s.%s()', variable, transformations{k});
             end
         end
-        if isequal(id, 1)
-            if isequal(expectationmodelkind, 'pac') && growth_correction
-                pgrowth = M_.params(expectationmodel.growth_neutrality_param_index);
-                linearCombination = '';
-                for iter = 1:numel(expectationmodel.growth_linear_comb)
+        if exist('expression','var')
+            if parameter>=0
+                expression = sprintf('%s+%1.16f*%s', expression, parameter, variable);
+            elseif parameter<0
+                expression = sprintf('%s-%1.16f*%s', expression, -parameter, variable);
+            end
+        else
+            if parameter>=0
+                expression = sprintf('%1.16f*%s', parameter, variable);
+            elseif parameter<0
+                expression = sprintf('-%1.16f*%s', -parameter, variable);
+            end
+        end
+    end
+end
+
+if isequal(expectationmodelkind, 'pac') && growth_correction
+    if isfield(expectationmodel, 'growth_neutrality_param_index')
+        pgrowth = M_.params(expectationmodel.growth_neutrality_param_index);
+        for iter = 1:numel(expectationmodel.growth_linear_comb)
+            vgrowth='';
+            if expectationmodel.growth_linear_comb(iter).exo_id > 0
+                vgrowth = strcat('dbase.', M_.exo_names{expectationmodel.growth_linear_comb(iter).exo_id});
+            elseif expectationmodel.growth_linear_comb(iter).endo_id > 0
+                vgrowth = strcat('dbase.', M_.endo_names{expectationmodel.growth_linear_comb(iter).endo_id});
+            end
+            if expectationmodel.growth_linear_comb(iter).lag ~= 0
+                vgrowth = sprintf('%s(%d)', vgrowth, expectationmodel.growth_linear_comb(iter).lag);
+            end
+            if expectationmodel.growth_linear_comb(iter).param_id > 0
+                if ~isempty(vgrowth)
+                    vgrowth = sprintf('%1.16f*%s',M_.params(expectationmodel.growth_linear_comb(iter).param_id), vgrowth);
+                else
+                    vgrowth = num2str(M_.params(expectationmodel.growth_linear_comb(iter).param_id), '%1.16f');
+                end
+            end
+            if abs(expectationmodel.growth_linear_comb(iter).constant) ~= 1
+                if ~isempty(vgrowth)
+                    vgrowth = sprintf('%1.16f*%s', expectationmodel.growth_linear_comb(iter).constant, vgrowth);
+                else
+                    vgrowth = num2str(expectationmodel.growth_linear_comb(iter).constant, '%1.16f');
+                end
+            end
+            if iter > 1
+                if expectationmodel.growth_linear_comb(iter).constant > 0
+                    linearCombination = sprintf('%s+%s', linearCombination, vgrowth);
+                else
+                    linearCombination = sprintf('%s-%s', linearCombination, vgrowth);
+                end
+            else
+                linearCombination = vgrowth;
+            end
+        end % loop over growth linear combination elements
+        growthcorrection = sprintf('%1.16f*(%s)', pgrowth, linearCombination);
+    else
+        first = true;
+        for i=1:length(expectationmodel.components)
+            if ~isequal(expectationmodel.components(i).kind, 'll') && isfield(expectationmodel.components(i), 'growth_neutrality_param_index') && isfield(expectationmodel.components(i), 'growth_linear_comb') && ~isempty(expectationmodel.components(i).growth_linear_comb) 
+                pgrowth = targetcoefficients(i)*M_.params(expectationmodel.components(i).growth_neutrality_param_index);
+                for iter = 1:numel(expectationmodel.components(i).growth_linear_comb)
                     vgrowth='';
-                    if expectationmodel.growth_linear_comb(iter).exo_id > 0
-                        vgrowth = strcat('dbase.', M_.exo_names{expectationmodel.growth_linear_comb(iter).exo_id});
-                    elseif expectationmodel.growth_linear_comb(iter).endo_id > 0
-                        vgrowth = strcat('dbase.', M_.endo_names{expectationmodel.growth_linear_comb(iter).endo_id});
+                    if expectationmodel.components(i).growth_linear_comb(iter).exo_id > 0
+                        vgrowth = strcat('dbase.', M_.exo_names{expectationmodel.components(i).growth_linear_comb(iter).exo_id});
+                    elseif expectationmodel.components(i).growth_linear_comb(iter).endo_id > 0
+                        vgrowth = strcat('dbase.', M_.endo_names{expectationmodel.components(i).growth_linear_comb(iter).endo_id});
+                        % TODO Check if we should not substitute auxiliary variables with original transformed variables here.
                     end
-                    if expectationmodel.growth_linear_comb(iter).lag ~= 0
-                        vgrowth = sprintf('%s(%d)', vgrowth, expectationmodel.growth_linear_comb(iter).lag);
+                    if expectationmodel.components(i).growth_linear_comb(iter).lag ~= 0
+                        vgrowth = sprintf('%s(%d)', vgrowth, expectationmodel.components(i).growth_linear_comb(iter).lag);
                     end
-                    if expectationmodel.growth_linear_comb(iter).param_id > 0
+                    if expectationmodel.components(i).growth_linear_comb(iter).param_id > 0
                         if ~isempty(vgrowth)
-                            vgrowth = sprintf('%1.16f*%s',M_.params(expectationmodel.growth_linear_comb(iter).param_id), vgrowth);
+                            vgrowth = sprintf('%1.16f*%s',M_.params(expectationmodel.components(i).growth_linear_comb(iter).param_id), vgrowth);
                         else
-                            vgrowth = num2str(M_.params(expectationmodel.growth_linear_comb(iter).param_id), '%1.16f');
+                            vgrowth = num2str(M_.params(expectationmodel.components(i).growth_linear_comb(iter).param_id), '%1.16f');
                         end
                     end
-                    if abs(expectationmodel.growth_linear_comb(iter).constant) ~= 1
+                    if abs(expectationmodel.components(i).growth_linear_comb(iter).constant) ~= 1
                         if ~isempty(vgrowth)
-                            vgrowth = sprintf('%1.16f*%s', expectationmodel.growth_linear_comb(iter).constant, vgrowth);
+                            vgrowth = sprintf('%1.16f*%s', expectationmodel.components(i).growth_linear_comb(iter).constant, vgrowth);
                         else
-                            vgrowth = num2str(expectationmodel.growth_linear_comb(iter).constant, '%1.16f');
+                            vgrowth = num2str(expectationmodel.components(i).growth_linear_comb(iter).constant, '%1.16f');
                         end
                     end
                     if iter > 1
-                        if expectationmodel.growth_linear_comb(iter).constant > 0
+                        if expectationmodel.components(i).growth_linear_comb(iter).constant > 0
                             linearCombination = sprintf('%s+%s', linearCombination, vgrowth);
                         else
                             linearCombination = sprintf('%s-%s', linearCombination, vgrowth);
                         end
                     else
-                        linearCombination=vgrowth;
+                        linearCombination = vgrowth;
                     end
-                end
-                if parameter >= 0
-                    expression = sprintf('%1.16f*(%s)+%1.16f*%s', pgrowth, linearCombination, parameter, variable);
+                end % loop over growth linear combination elements
+                if first
+                    growthcorrection = sprintf('%1.16f*(%s)', pgrowth, linearCombination);
+                    first = false;
                 else
-                    expression = sprintf('%1.16f*(%s)-%1.16f*%s', pgrowth, linearCombination, -parameter, variable);
+                    if pgrowth>0
+                        growthcorrection = sprintf('%s+%1.16f*(%s)', growthcorrection, pgrowth, linearCombination);
+                    elseif pgrowth<0
+                        growthcorrection = sprintf('%s-%1.16f*(%s)', growthcorrection, -pgrowth, linearCombination);
+                    end
                 end
-            else
-                expression = sprintf('%1.16f*%s', parameter, variable);
-            end
-        else
-            if parameter>=0
-                expression = sprintf('%s+%1.16f*%s', expression, parameter, variable);
-            else
-                expression = sprintf('%s-%1.16f*%s', expression, -parameter, variable);
             end
         end
     end
-end
+    expression = sprintf('%s+%s', expression, growthcorrection);
+end % growth_correction
 
 fprintf(fid, 'ds.%s = %s;', expectationmodelname, expression);
 fclose(fid);
diff --git a/matlab/write_expectations.m b/matlab/write_expectations.m
index 5312e42a6f738537b6ba4b4c39614b2c39e7ea2c..8186527b36180d66706bd039aa23c58e79d8c8ec 100644
--- a/matlab/write_expectations.m
+++ b/matlab/write_expectations.m
@@ -1,4 +1,4 @@
-function [expression, growthneutralitycorrection] = write_expectations(expectationmodelname, expectationmodelkind, iscrlf)
+function [expression, growthneutralitycorrection] = write_expectations(expectationmodelname, expectationmodelkind, iscrlf, aggregate)
 
 % Prints the exansion of the VAR_EXPECTATION or PAC_EXPECTATION term in files.
 %
@@ -48,6 +48,16 @@ end
 
 if nargin<3
     iscrlf = false;
+    aggregate = true;
+end
+
+if nargin<4
+    aggregate = true;
+end
+
+if isfield(expectationmodel, 'h_param_indices')
+    % Disaggregation requires components...
+    aggregate = true;
 end
 
 % Get the name of the associated VAR model and test its existence.
@@ -82,7 +92,29 @@ end
 
 if isequal(expectationmodelkind, 'pac') && isequal(expectationmodel.auxiliary_model_type, 'var')
     id = id+1;
-    expression = sprintf('%s', M_.param_names{expectationmodel.h_param_indices(id)});
+    if isfield(expectationmodel, 'h_param_indices')
+        expression = sprintf('%s', M_.param_names{expectationmodel.h_param_indices(id)});
+    else
+        if aggregate
+            if isequal(expectationmodel.components(1).coeff_str, '1')
+                expression = sprintf('%s', M_.param_names{expectationmodel.components(1).h_param_indices(id)});
+            else
+                expression = sprintf('%s*%s', expectationmodel.components(1).coeff_str, M_.param_names{expectationmodel.components(1).h_param_indices(id)});
+            end
+            for i=2:length(expectationmodel.components)
+                if isequal(expectationmodel.components(i).coeff_str, '1')
+                    expression = sprintf('%s+%s', expression, M_.param_names{expectationmodel.components(i).h_param_indices(id)});
+                else
+                    expression = sprintf('%s+%s*%s', expression, expectationmodel.components(i).coeff_str, M_.param_names{expectationmodel.components(i).h_param_indices(id)});
+                end
+            end
+        else
+            expression = cell(length(expectationmodel.components), 1);
+            for i=1:length(expectationmodel.components)
+                expression(i) = {M_.param_names{expectationmodel.components(i).h_param_indices(id)}};
+            end
+        end
+    end
 end
 
 for i=1:maxlag
@@ -110,7 +142,31 @@ for i=1:maxlag
           case 'var'
             parameter = M_.param_names{expectationmodel.param_indices(id)};
           case 'pac'
-            parameter = M_.param_names{expectationmodel.h_param_indices(id)};
+            if isfield(expectationmodel, 'h_param_indices')
+                parameter = M_.param_names{expectationmodel.h_param_indices(id)};
+            else
+                if aggregate
+                    % TODO Check if we can have parameters entering with a minus sign in the linear combination defining the target.
+                    if isequal(expectationmodel.components(1).coeff_str, '1')
+                        parameter = M_.param_names{expectationmodel.components(1).h_param_indices(id)};
+                    else
+                        parameter = sprintf('%s*%s', expectationmodel.components(1).coeff_str, M_.param_names{expectationmodel.components(1).h_param_indices(id)});
+                    end
+                    for k=2:length(expectationmodel.components)
+                        if isequal(expectationmodel.components(k).coeff_str, '1')
+                            parameter = sprintf('%s+%s', parameter, M_.param_names{expectationmodel.components(k).h_param_indices(id)});
+                        else
+                            parameter = sprintf('%s+%s*%s', parameter, expectationmodel.components(k).coeff_str, M_.param_names{expectationmodel.components(k).h_param_indices(id)});
+                        end
+                    end
+                    parameter = sprintf('(%s)', parameter);
+                else
+                    parameter = cell(length(expectationmodel.components), 1);
+                    for k=1:length(expectationmodel.components)
+                        parameter(k) = {M_.param_names{expectationmodel.components(k).h_param_indices(id)}};
+                    end
+                end
+            end
           otherwise
         end
         switch expectationmodelkind
@@ -128,21 +184,47 @@ for i=1:maxlag
             end
         end
         if isequal(id, 1)
-            if iscrlf
-                expression = sprintf('%s*%s\n', parameter, variable);
+            if aggregate
+                if iscrlf
+                    expression = sprintf('%s*%s\n', parameter, variable);
+                else
+                    expression = sprintf('%s*%s', parameter, variable);
+                end
             else
-                expression = sprintf('%s*%s', parameter, variable);
+                for k=1:length(expectationmodel.components)
+                    if iscrlf
+                        expression(k) = {sprintf('%s*%s\n', parameter{k}, variable)};
+                    else
+                        expression(k) = {sprintf('%s*%s', parameter{k}, variable)};
+                    end
+                end
             end
         else
-            if iscrlf
-                expression = sprintf('%s + %s*%s\n', expression, parameter, variable);
+            if aggregate
+                if iscrlf
+                    expression = sprintf('%s + %s*%s\n', expression, parameter, variable);
+                else
+                    expression = sprintf('%s + %s*%s', expression, parameter, variable);
+                end
             else
-                expression = sprintf('%s + %s*%s', expression, parameter, variable);
+                for k=1:length(expectationmodel.components)
+                    if iscrlf
+                        expression(k) = {sprintf('%s + %s*%s\n', expression{k}, parameter{k}, variable)};
+                    else
+                        expression(k) = {sprintf('%s + %s*%s', expression{k}, parameter{k}, variable)};
+                    end
+                end
             end
         end
     end
 end
 
+if aggregate
+    growthneutralitycorrection = ''
+else
+    growthneutralitycorrection = {};
+end
+
 if isfield(expectationmodel, 'growth_neutrality_param_index')
     if numel(expectationmodel.growth_linear_comb) == 1
         growthneutralitycorrection = sprintf('%s*%s', M_.param_names{expectationmodel.growth_neutrality_param_index}, expectationmodel.growth_str);
@@ -150,7 +232,65 @@ if isfield(expectationmodel, 'growth_neutrality_param_index')
         growthneutralitycorrection = sprintf('%s*(%s)', M_.param_names{expectationmodel.growth_neutrality_param_index}, expectationmodel.growth_str);
     end
 else
-    growthneutralitycorrection = '';
+    if isfield(expectationmodel, 'components')
+        if aggregate
+            growthneutralitycorrection = '';
+            for i=1:length(expectationmodel.components)
+                if ~isequal(expectationmodel.components(i).kind, 'll')
+                    if isfield(expectationmodel.components(i), 'growth_neutrality_param_index')
+                        if isempty(growthneutralitycorrection)
+                            if ~isempty(expectationmodel.components(i).growth_str)
+                                if isequal(expectationmodel.components(i).coeff_str, '1')
+                                    if numel(expectationmodel.components(i).growth_linear_comb) == 1
+                                        growthneutralitycorrection = sprintf('%s*%s', M_.param_names{expectationmodel.components(i).growth_neutrality_param_index}, expectationmodel.components(i).growth_str);
+                                    else
+                                        growthneutralitycorrection = sprintf('%s*(%s)', M_.param_names{expectationmodel.components(i).growth_neutrality_param_index}, expectationmodel.components(i).growth_str);
+                                    end
+                                else
+                                    if numel(expectationmodel.components(i).growth_linear_comb) == 1
+                                        growthneutralitycorrection = sprintf('%s*%s*%s', expectationmodel.components(i).coeff_str, M_.param_names{expectationmodel.components(i).growth_neutrality_param_index}, expectationmodel.components(i).growth_str);
+                                    else
+                                        growthneutralitycorrection = sprintf('%s*%s*(%s)', expectationmodel.components(i).coeff_str, M_.param_names{expectationmodel.components(i).growth_neutrality_param_index}, expectationmodel.components(i).growth_str);
+                                    end
+                                end
+                            end
+                        else
+                            if ~isempty(expectationmodel.components(i).growth_str)
+                                if isequal(expectationmodel.components(i).coeff_str, '1')
+                                    if numel(expectationmodel.components(i).growth_linear_comb) == 1
+                                        growthneutralitycorrection = sprintf('%s+%s*%s', growthneutralitycorrection, M_.param_names{expectationmodel.components(i).growth_neutrality_param_index}, expectationmodel.components(i).growth_str);
+                                    else
+                                        growthneutralitycorrection = sprintf('%s+%s*(%s)', growthneutralitycorrection, M_.param_names{expectationmodel.components(i).growth_neutrality_param_index}, expectationmodel.components(i).growth_str);
+                                    end
+                                else
+                                    if numel(expectationmodel.components(i).growth_linear_comb) == 1
+                                        growthneutralitycorrection = sprintf('%s+%s*%s*%s', growthneutralitycorrection, expectationmodel.components(i).coeff_str, M_.param_names{expectationmodel.components(i).growth_neutrality_param_index}, expectationmodel.components(i).growth_str);
+                                    else
+                                        growthneutralitycorrection = sprintf('%s+%s*%s*(%s)', growthneutralitycorrection, expectationmodel.components(i).coeff_str, M_.param_names{expectationmodel.components(i).growth_neutrality_param_index}, expectationmodel.components(i).growth_str);
+                                    end
+                                end
+                            end
+                        end
+                    end % if growth neutrality correction for this component
+                end % if non stationary component
+            end
+        else
+            growthneutralitycorrection = repmat({''}, length(expectationmodel.components), 1);
+            for i=1:length(growthneutralitycorrection)
+                if ~isequal(expectationmodel.components(i).kind, 'll')
+                    if isfield(expectationmodel.components(i), 'growth_neutrality_param_index')
+                        if ~isempty(expectationmodel.components(i).growth_str)
+                            if numel(expectationmodel.components(i).growth_linear_comb) == 1
+                                growthneutralitycorrection(i) = {sprintf('%s*%s', M_.param_names{expectationmodel.components(i).growth_neutrality_param_index}, expectationmodel.components(i).growth_str)};
+                            else
+                                growthneutralitycorrection(i) = {sprintf('%s*(%s)', M_.param_names{expectationmodel.components(i).growth_neutrality_param_index}, expectationmodel.components(i).growth_str)};
+                            end
+                        end
+                    end % if growth neutrality correction for this component
+                end % if non stationary component
+            end
+        end % if aggregate
+    end
 end
 
 if nargout==1 && ~isempty(growthneutralitycorrection)
diff --git a/preprocessor b/preprocessor
index 7dde09169ecd4b5e32b3cd35bef88958a262ec11..a8fce06dc46ca09329e6899e1fde47f2cd81809b 160000
--- a/preprocessor
+++ b/preprocessor
@@ -1 +1 @@
-Subproject commit 7dde09169ecd4b5e32b3cd35bef88958a262ec11
+Subproject commit a8fce06dc46ca09329e6899e1fde47f2cd81809b
diff --git a/scripts/dynare.el b/scripts/dynare.el
index 39ae6dd11c8e1c723f3a131ad1dda82fe207fbfe..c3fe64a61bfefd8ba10bd8fc18c300207c93de41 100644
--- a/scripts/dynare.el
+++ b/scripts/dynare.el
@@ -102,7 +102,7 @@
       "osr_params_bounds" "observation_trends" "deterministic_trends" "optim_weights"
       "homotopy_setup" "conditional_forecast_paths" "svar_identification"
       "moment_calibration" "irf_calibration" "ramsey_constraints" "generate_irfs"
-      "matched_moments" "occbin_constraints" "model_replace" "verbatim")
+      "matched_moments" "occbin_constraints" "model_replace" "verbatim" "pac_target_info")
     "Dynare block keywords."))
 
 ;; Mathematical functions and operators used in model equations (see "hand_side" in Bison file)
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 9bff02c43de83906d6bcd4594d340a04b3dbec46..37fecb676ce09b7a2692ff10bd2a1a921d743b7f 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -518,6 +518,15 @@ ECB_MODFILES = \
 	pac/var-6/substitution.mod \
 	pac/var-7/example1.mod \
 	pac/var-7/substitution.mod \
+	pac/var-8/example1.mod \
+	pac/var-8/substitution.mod \
+	pac/var-8e/example1.mod \
+	pac/var-9/example1.mod \
+	pac/var-9/substitution.mod \
+	pac/var-9e/example1.mod \
+	pac/var-10e/example1.mod \
+	pac/var-10e/example2.mod \
+	pac/var-11e/example1.mod \
 	pac/trend-component-1/example1.mod \
 	pac/trend-component-2/example1.mod \
 	pac/trend-component-3/example1.mod \
@@ -878,6 +887,12 @@ pac/var-6/substitution.m.trs: pac/var-6/example1.m.trs
 pac/var-6/substitution.o.trs: pac/var-6/example1.o.trs
 pac/var-7/substitution.m.trs: pac/var-7/example1.m.trs
 pac/var-7/substitution.o.trs: pac/var-7/example1.o.trs
+pac/var-8/substitution.m.trs: pac/var-8/example1.m.trs
+pac/var-8/substitution.o.trs: pac/var-8/example1.o.trs
+pac/var-9/substitution.m.trs: pac/var-9/example1.m.trs
+pac/var-9/substitution.o.trs: pac/var-9/example1.o.trs
+pac/var-10e/example2.m.trs: pac/var-10e/example1.m.trs
+pac/var-10e/example2.o.trs: pac/var-10e/example1.o.trs
 pac/trend-component-14/substitution.m.trs: pac/trend-component-14/example1.m.trs
 pac/trend-component-14/substitution.o.trs: pac/trend-component-14/example1.o.trs
 
diff --git a/tests/ecb/cherrypick/test1.mod b/tests/ecb/cherrypick/test1.mod
index be64d23f256628a08917e972acde3e795527abe0..d8c063a37c1c227bc2e6133bf26196742d0a0089 100644
--- a/tests/ecb/cherrypick/test1.mod
+++ b/tests/ecb/cherrypick/test1.mod
@@ -45,7 +45,7 @@ c_z_2 = -.1;
 c_z_dx2 = .3;
 c_z_u = .3;
 c_z_dv = .4;
-c_z_s  = -.2; 
+c_z_s  = -.2;
 cx = 1.0;
 cy = 1.0;
 
@@ -54,7 +54,7 @@ lambda = 0.5; // Share of optimizing agents.
 
 trend_component_model(model_name=toto, eqtags=['eq:x1', 'eq:x2', 'eq:x1bar', 'eq:x2bar'], targets=['eq:x1bar', 'eq:x2bar']);
 
-pac_model(auxiliary_model_name=toto, discount=beta, model_name=pacman);
+pac_model(auxiliary_model_name=toto, discount=beta, model_name=pacman, auxname=rototo);
 
 model;
 
@@ -125,7 +125,7 @@ pac.update.expectation('pacman');
 // variables and exogenous variables in .inc files under ./simulation-files folder. Note that
 // innovations ex1bar and ex2bar will not appear in the equations.
 verbatim;
-  cherrypick('test1', 'simulation-files1', {'z1', 'z2', 'z3'}, true);
-  cherrypick('test1', 'simulation-files2', {'zpac', 'eq:x1', 'eq:x', 'eq:y'}, true);
-  aggregate('toto.mod', {}, '', 'simulation-files1', 'simulation-files2');
+  cherrypick('test1', 'simulation-files-1-a', {'z1', 'z2', 'z3'}, true);
+  cherrypick('test1', 'simulation-files-1-b', {'zpac', 'eq:x1', 'eq:x', 'eq:y'}, true);
+  aggregate('toto1.mod', {}, '', 'simulation-files-1-a', 'simulation-files-1-b');
 end;
diff --git a/tests/ecb/cherrypick/test2.mod b/tests/ecb/cherrypick/test2.mod
index 57ace0d9669d74f1227331593a958e87c5dfe2a9..d78621d6cf598027cd899380a56947508c7aa0c9 100644
--- a/tests/ecb/cherrypick/test2.mod
+++ b/tests/ecb/cherrypick/test2.mod
@@ -1,36 +1,100 @@
-var x y z;
+// --+ options: json=compute, stochastic +--
 
-model;
+var y x z v u w z1 z2 z3;
+
+varexo ex ey ez eu ew;
+
+parameters a_y_1 a_y_2 b_y_1 b_y_2 a_u_1 a_u_2 b_u_1 b_u_2 b_x_1 b_x_2 d_y;
+
+parameters beta e_c_m c_z_1 c_z_2;               // PAC equation parameters
+
+a_y_1 =  .2;
+a_y_2 =  .3;
+b_y_1 =  .1;
+b_y_2 =  .4;
+a_u_1 =  .2;
+a_u_2 =  .3;
+b_u_1 =  .1;
+b_u_2 =  .4;
+b_x_1 = -.1;
+b_x_2 = -.2;
+d_y = .5;
+
+beta  =  .9;
+e_c_m =  .1;
+c_z_1 =  .7;
+c_z_2 = -.3;
 
-x = y(-1)+z(1);
+var_model(model_name=toto, structural, eqtags=['eq:x', 'eq:y']);
 
-y = x-z;
+pac_model(auxiliary_model_name=toto, discount=beta, model_name=pacman);
 
-diff(z) = 0;
+pac_target_info(pacman);
+
+  target v;
+  auxname_target_nonstationary vns;
+
+  component y;
+  auxname pv_y_;
+  kind ll;
+
+  component x;
+  auxname pv_dx_;
+  growth diff(x(-1));
+  kind dl;
 
 end;
 
+model;
+
+  [name='eq:u']
+  u = a_u_1*u(-1) + a_u_2*diff(x(-1)) + b_u_1*y(-2) + b_u_2*diff(x(-2)) + eu ;
 
-if ~isfield(M_, 'exo_names')
-   error('M_.exo_names not defined.')
-end
+  [name='eq:y']
+  y = a_y_1*y(-1) + a_y_2*diff(x(-1)) + b_y_1*y(-2) + b_y_2*diff(x(-2)) + ey ;
 
-if ~iscell(M_.exo_names)
-   error('M_.exo_names not a cell array.')
-end
+  [name='eq:x']
+  diff(x) = b_x_1*y(-2) + b_x_2*diff(x(-1)) + ex ;
 
-if ~isempty(M_.exo_names)
-   error('M_.exo_names not an empty cell array.')
-end
+  [name='eq:v']
+  v = x + d_y*y ;
 
-if ~isfield(M_, 'param_names')
-   error('M_.param_names not defined.')
-end
+  [name='eq:pac']
+  diff(z) = e_c_m*(pac_target_nonstationary(pacman)-z(-1)) + c_z_1*diff(z(-1))  + c_z_2*diff(z(-2)) + pac_expectation(pacman) + ez;
 
-if ~iscell(M_.param_names)
-   error('M_.param_names not a cell array.')
-end
+  [name='eq:w']
+  diff(w) = -.1*w + ew ;
 
-if ~isempty(M_.param_names)
-   error('M_.param_names not an empty cell array.')
-end
\ No newline at end of file
+  [name='eq:z1']
+  z1 = z+y-x+u;
+
+  [name='eq:z2']
+  z2 = z-y+x-u;
+
+  [name='eq:z3']
+  z3 = u-diff(v);
+
+end;
+
+shocks;
+  var ex = 1.0;
+  var ey = 1.0;
+  var ez = 1.0;
+  var ew = 1.0;
+  var eu = 1.0;
+end;
+
+// Initialize the PAC model (build the Companion VAR representation for the auxiliary model).
+pac.initialize('pacman');
+
+// Update the parameters of the PAC expectation model (h0 and h1 vectors).
+pac.update.expectation('pacman');
+
+// Select a subset of the equations and print the equations, the list of parameters, endogenous
+// variables and exogenous variables in .inc files under ./simulation-files folder. Note that
+// innovations ex1bar and ex2bar will not appear in the equations.
+verbatim;
+  cherrypick('test2', 'simulation-files-2-a', {'eq:z1', 'eq:z2', 'eq:z3'}, true);
+  cherrypick('test2', 'simulation-files-2-b', {'eq:pac', 'eq:x', 'eq:y'}, true);
+  aggregate('toto2.mod', {}, '', 'simulation-files-2-a', 'simulation-files-2-b');
+end;
diff --git a/tests/pac/var-10e/example1.mod b/tests/pac/var-10e/example1.mod
new file mode 100644
index 0000000000000000000000000000000000000000..b185d7345a77763afcb0a5d40924e349496c98e6
--- /dev/null
+++ b/tests/pac/var-10e/example1.mod
@@ -0,0 +1,103 @@
+// --+ options: json=compute, stochastic +--
+
+var y x z v;
+
+varexo ex ey ez ;
+
+parameters a_y_1 a_y_2 b_y_1 b_y_2 b_x_1 b_x_2 d_y; // VAR parameters
+
+parameters beta e_c_m c_z_1 c_z_2;               // PAC equation parameters
+
+a_y_1 =  .2;
+a_y_2 =  .3;
+b_y_1 =  .1;
+b_y_2 =  .4;
+b_x_1 = -.1;
+b_x_2 = -.2;
+d_y = .5;
+
+
+beta  =  .9;
+e_c_m =  .1;
+c_z_1 =  .7;
+c_z_2 = -.3;
+
+var_model(model_name=toto, structural, eqtags=['eq:x', 'eq:y']);
+
+pac_model(auxiliary_model_name=toto, discount=beta, model_name=pacman);
+
+pac_target_info(pacman);
+  target v;
+  auxname_target_nonstationary vns;
+
+  component y;
+  growth diff(y(-1));
+  auxname pv_y_;
+  kind dd;
+
+  component x;
+  growth diff(x(-1));
+  auxname pv_dx_;
+  kind dd;
+
+end;
+
+model(use_dll);
+
+  [name='eq:y']
+  diff(y) = .01 + a_y_1*diff(y(-1)) + a_y_2*diff(x(-1)) + b_y_1*diff(y(-2)) + b_y_2*diff(x(-2)) + ey ;
+
+
+  [name='eq:x']
+  diff(x) = .05 + b_x_1*diff(y(-2)) + b_x_2*diff(x(-1)) + ex ;
+
+  [name='eq:v']
+  v = x + d_y*y ;
+
+  [name='zpac']
+  diff(z) = e_c_m*(pac_target_nonstationary(pacman)-z(-1)) + c_z_1*diff(z(-1))  + c_z_2*diff(z(-2)) + pac_expectation(pacman) + ez;
+
+end;
+
+shocks;
+  var ex = 1.0;
+  var ey = 1.0;
+  var ez = 1.0;
+end;
+
+// Initialize the PAC model (build the Companion VAR representation for the auxiliary model).
+pac.initialize('pacman');
+
+// Update the parameters of the PAC expectation model (h0 and h1 vectors).
+pac.update.expectation('pacman');
+
+// Set initial conditions to zero. Please use more sensible values if any...
+initialconditions = dseries(zeros(10, M_.endo_nbr+M_.exo_nbr), 2000Q1, vertcat(M_.endo_names,M_.exo_names));
+
+// Simulate the model for 500 periods
+TrueData = simul_backward_model(initialconditions, 500);
+
+TrueData.save('example1.data')
+
+// Print expanded PAC_EXPECTATION term.
+pac.print('pacman', 'eq:pac');
+
+clear eparams
+eparams.e_c_m   =  .9;
+eparams.c_z_1   =  .5;
+eparams.c_z_2   =  .2;
+
+// Define the dataset used for estimation
+edata = TrueData;
+edata.ez = dseries(NaN(TrueData.nobs, 1), 2000Q1, 'ez');
+pac.estimate.nls('zpac', eparams, edata, 2005Q1:2005Q1+400, 'fmincon');
+
+e_c_m_nls = M_.params(strmatch('e_c_m', M_.param_names, 'exact'));
+c_z_1_nls = M_.params(strmatch('c_z_1', M_.param_names, 'exact'));
+c_z_2_nls = M_.params(strmatch('c_z_2', M_.param_names, 'exact'));
+
+disp(sprintf('Estimate of e_c_m: %f', e_c_m_nls))
+disp(sprintf('Estimate of c_z_1: %f', c_z_1_nls))
+disp(sprintf('Estimate of c_z_2: %f', c_z_2_nls))
+
+save('example1.estimation.mat', 'e_c_m_nls', 'c_z_1_nls', 'c_z_2_nls')
diff --git a/tests/pac/var-10e/example2.mod b/tests/pac/var-10e/example2.mod
new file mode 100644
index 0000000000000000000000000000000000000000..ddc56ad8cfdf010d8ac07833919e44ebe7098d22
--- /dev/null
+++ b/tests/pac/var-10e/example2.mod
@@ -0,0 +1,104 @@
+// --+ options: json=compute, stochastic +--
+
+var y x z v;
+
+varexo ex ey ez ;
+
+parameters a_y_1 a_y_2 b_y_1 b_y_2 b_x_1 b_x_2 d_y; // VAR parameters
+
+parameters beta e_c_m c_z_1 c_z_2;               // PAC equation parameters
+
+a_y_1 =  .2;
+a_y_2 =  .3;
+b_y_1 =  .1;
+b_y_2 =  .4;
+b_x_1 = -.1;
+b_x_2 = -.2;
+d_y = .5;
+
+
+beta  =  .9;
+e_c_m =  .1;
+c_z_1 =  .7;
+c_z_2 = -.3;
+
+var_model(model_name=toto, structural, eqtags=['eq:x', 'eq:y', 'eq:v']);
+
+pac_model(auxiliary_model_name=toto, discount=beta, kind=dd, growth=diff(v(-1)), model_name=pacman);
+
+model(use_dll);
+
+  [name='eq:y']
+  diff(y) = .01 + a_y_1*diff(y(-1)) + a_y_2*diff(x(-1)) + b_y_1*diff(y(-2)) + b_y_2*diff(x(-2)) + ey ;
+
+
+  [name='eq:x']
+  diff(x) = .05 + b_x_1*diff(y(-2)) + b_x_2*diff(x(-1)) + ex ;
+
+  [name='eq:v']
+  diff(v) = diff(x) + d_y*diff(y) ;
+
+  [name='zpac']
+  diff(z) = e_c_m*(v(-1)-z(-1)) + c_z_1*diff(z(-1))  + c_z_2*diff(z(-2)) + pac_expectation(pacman) + ez;
+
+end;
+
+shocks;
+  var ex = 1.0;
+  var ey = 1.0;
+  var ez = 1.0;
+end;
+
+// Initialize the PAC model (build the Companion VAR representation for the auxiliary model).
+pac.initialize('pacman');
+
+// Update the parameters of the PAC expectation model (h0 and h1 vectors).
+pac.update.expectation('pacman');
+
+// Set initial conditions to zero. Please use more sensible values if any...
+initialconditions = dseries(zeros(10, M_.endo_nbr+M_.exo_nbr), 2000Q1, vertcat(M_.endo_names,M_.exo_names));
+
+// Simulate the model for 500 periods
+TrueData = simul_backward_model(initialconditions, 500);
+
+TrueData.save('example2.data')
+
+// Print expanded PAC_EXPECTATION term.
+pac.print('pacman', 'eq:pac');
+
+clear eparams
+eparams.e_c_m   =  .9;
+eparams.c_z_1   =  .5;
+eparams.c_z_2   =  .2;
+
+// Define the dataset used for estimation
+edata = TrueData;
+edata.ez = dseries(NaN(TrueData.nobs, 1), 2000Q1, 'ez');
+pac.estimate.nls('zpac', eparams, edata, 2005Q1:2005Q1+400, 'fmincon');
+
+e_c_m_nls = M_.params(strmatch('e_c_m', M_.param_names, 'exact'));
+c_z_1_nls = M_.params(strmatch('c_z_1', M_.param_names, 'exact'));
+c_z_2_nls = M_.params(strmatch('c_z_2', M_.param_names, 'exact'));
+
+disp(sprintf('Estimate of e_c_m: %f', e_c_m_nls))
+disp(sprintf('Estimate of c_z_1: %f', c_z_1_nls))
+disp(sprintf('Estimate of c_z_2: %f', c_z_2_nls))
+
+% Check consistency with disaggregated target
+ts1 = dseries('example1.data.mat');
+ts2 = dseries('example2.data.mat');
+
+if max(abs(ts1.z.data-ts2.z.data))>1e-12
+    error('Simulations in example1 and example2 are not consistent.')
+end
+
+e1 = load('example1.estimation.mat');
+
+if abs(e_c_m_nls-e1.e_c_m_nls)>1e-6 || abs(c_z_1_nls-e1.c_z_1_nls)>1e-6 || abs(c_z_2_nls-e1.c_z_2_nls)>1e-6
+    error('Estimations in example1 and example2 are not consistent.')
+end
+
+delete example1.data.mat
+delete example2.data.mat
+
+delete example1.estimation.mat
diff --git a/tests/pac/var-11e/example1.mod b/tests/pac/var-11e/example1.mod
new file mode 100644
index 0000000000000000000000000000000000000000..89a56773dcfdd11708487fbb67a08cbecb4edb0a
--- /dev/null
+++ b/tests/pac/var-11e/example1.mod
@@ -0,0 +1,100 @@
+// --+ options: json=compute, stochastic +--
+
+var y x z v;
+
+varexo ex ey ez ;
+
+parameters a_y_1 a_y_2 b_y_1 b_y_2 b_x_1 b_x_2 d_y cst; // VAR parameters
+
+parameters beta e_c_m c_z_1 c_z_2;               // PAC equation parameters
+
+a_y_1 =  .2;
+a_y_2 =  .3;
+b_y_1 =  .1;
+b_y_2 =  .4;
+b_x_1 = -.1;
+b_x_2 = -.2;
+d_y = .5;
+
+
+beta  =  .9;
+e_c_m =  .1;
+c_z_1 =  .7;
+c_z_2 = -.3;
+
+cst = .1;
+
+var_model(model_name=toto, structural, eqtags=['eq:x', 'eq:y']);
+
+pac_model(auxiliary_model_name=toto, discount=beta, model_name=pacman);
+
+pac_target_info(pacman);
+  target v;
+  auxname_target_nonstationary vns;
+
+  component y;
+  auxname pv_y_;
+  kind ll;
+
+  component x;
+  growth diff(x(-1));
+  auxname pv_dx_;
+  kind dd;
+
+end;
+
+model;
+
+  [name='eq:y']
+  y = a_y_1*y(-1) + a_y_2*diff(x(-1)) + b_y_1*y(-2) + b_y_2*diff(x(-2)) + ey ;
+
+
+  [name='eq:x']
+  diff(x) = b_x_1*y(-2) + b_x_2*diff(x(-1)) + ex ;
+
+  [name='eq:v']
+  v = .01 + x + d_y*y ;
+
+  [name='zpac']
+  diff(z) = e_c_m*(pac_target_nonstationary(pacman)-z(-1)) + c_z_1*diff(z(-1))  + c_z_2*diff(z(-2)) + pac_expectation(pacman) + ez;
+
+end;
+
+shocks;
+  var ex = 1.0;
+  var ey = 1.0;
+  var ez = 1.0;
+end;
+
+// Initialize the PAC model (build the Companion VAR representation for the auxiliary model).
+pac.initialize('pacman');
+
+// Update the parameters of the PAC expectation model (h0 and h1 vectors).
+pac.update.expectation('pacman');
+
+// Set initial conditions to zero. Please use more sensible values if any...
+initialconditions = dseries(zeros(10, M_.endo_nbr+M_.exo_nbr), 2000Q1, vertcat(M_.endo_names,M_.exo_names));
+
+// Simulate the model for 500 periods
+TrueData = simul_backward_model(initialconditions, 5000);
+
+// Print expanded PAC_EXPECTATION term.
+pac.print('pacman', 'eq:pac');
+
+clear eparams
+eparams.e_c_m   =  .9;
+eparams.c_z_1   =  .5;
+eparams.c_z_2   =  .2;
+
+// Define the dataset used for estimation
+edata = TrueData;
+edata.ez = dseries(NaN(TrueData.nobs, 1), 2000Q1, 'ez');
+pac.estimate.nls('zpac', eparams, edata, 2005Q1:2005Q1+4000, 'fmincon');
+
+e_c_m_nls = M_.params(strmatch('e_c_m', M_.param_names, 'exact'));
+c_z_1_nls = M_.params(strmatch('c_z_1', M_.param_names, 'exact'));
+c_z_2_nls = M_.params(strmatch('c_z_2', M_.param_names, 'exact'));
+
+disp(sprintf('Estimate of e_c_m: %f', e_c_m_nls))
+disp(sprintf('Estimate of c_z_1: %f', c_z_1_nls))
+disp(sprintf('Estimate of c_z_2: %f', c_z_2_nls))
diff --git a/tests/pac/var-8/example1.mod b/tests/pac/var-8/example1.mod
new file mode 100644
index 0000000000000000000000000000000000000000..8885873b5884564d1841098ce708c4ccf115ff53
--- /dev/null
+++ b/tests/pac/var-8/example1.mod
@@ -0,0 +1,90 @@
+// --+ options: json=compute, stochastic +--
+
+var y x z v;
+
+varexo ex ey ez ;
+
+parameters a_y_1 a_y_2 b_y_1 b_y_2 b_x_1 b_x_2 d_y; // VAR parameters
+
+parameters beta e_c_m c_z_1 c_z_2;               // PAC equation parameters
+
+a_y_1 =  .2;
+a_y_2 =  .3;
+b_y_1 =  .1;
+b_y_2 =  .4;
+b_x_1 = -.1;
+b_x_2 = -.2;
+d_y = .5;
+
+
+beta  =  .9;
+e_c_m =  .1;
+c_z_1 =  .7;
+c_z_2 = -.3;
+
+var_model(model_name=toto, structural, eqtags=['eq:x', 'eq:y']);
+
+pac_model(auxiliary_model_name=toto, discount=beta, model_name=pacman);
+
+pac_target_info(pacman);
+  target v;
+  auxname_target_nonstationary vns;
+
+  component y;
+  auxname pv_y_;
+  kind ll;
+
+  component x;
+  auxname pv_dx_;
+  kind dd;
+
+end;
+
+model;
+
+  [name='eq:y']
+  y = a_y_1*y(-1) + a_y_2*diff(x(-1)) + b_y_1*y(-2) + b_y_2*diff(x(-2)) + ey ;
+
+
+  [name='eq:x']
+  diff(x) = b_x_1*y(-2) + b_x_2*diff(x(-1)) + ex ;
+
+  [name='eq:v']
+  v = x + d_y*y ;
+
+  [name='eq:pac']
+  diff(z) = e_c_m*(pac_target_nonstationary(pacman)-z(-1)) + c_z_1*diff(z(-1))  + c_z_2*diff(z(-2)) + pac_expectation(pacman) + ez;
+
+end;
+
+shocks;
+  var ex = 1.0;
+  var ey = 1.0;
+  var ez = 1.0;
+end;
+
+// Initialize the PAC model (build the Companion VAR representation for the auxiliary model).
+pac.initialize('pacman');
+
+// Update the parameters of the PAC expectation model (h0 and h1 vectors).
+pac.update.expectation('pacman');
+
+// Set initial conditions to zero. Please use more sensible values if any...
+initialconditions = dseries(zeros(10, M_.endo_nbr+M_.exo_nbr), 2000Q1, vertcat(M_.endo_names,M_.exo_names));
+
+// Simulate the model for 500 periods
+TrueData = simul_backward_model(initialconditions, 20);
+
+// Print expanded PAC_EXPECTATION term.
+pac.print('pacman', 'eq:pac');
+
+verbatim;
+  set_dynare_seed('default');
+  y = zeros(M_.endo_nbr,1);
+  y(1:M_.orig_endo_nbr) = rand(M_.orig_endo_nbr, 1);
+  x = randn(M_.exo_nbr,1);
+  y = example1.set_auxiliary_variables(y, x, M_.params);
+  y = [y(find(M_.lead_lag_incidence(1,:))); y];
+  [residual, g1] = example1.dynamic(y, x', M_.params, oo_.steady_state, 1);
+  save('example1.mat', 'residual', 'g1', 'TrueData');
+end;
diff --git a/tests/pac/var-8/substitution.mod b/tests/pac/var-8/substitution.mod
new file mode 100644
index 0000000000000000000000000000000000000000..9f909dbb32a68d60790d84ccbfa29cc05d42cb91
--- /dev/null
+++ b/tests/pac/var-8/substitution.mod
@@ -0,0 +1,83 @@
+// --+ options: json=compute, stochastic +--
+
+var y x z v;
+
+varexo ex ey ez ;
+
+parameters a_y_1 a_y_2 b_y_1 b_y_2 b_x_1 b_x_2 d_y; // VAR parameters
+
+parameters beta e_c_m c_z_1 c_z_2;               // PAC equation parameters
+
+a_y_1 =  .2;
+a_y_2 =  .3;
+b_y_1 =  .1;
+b_y_2 =  .4;
+b_x_1 = -.1;
+b_x_2 = -.2;
+d_y = .5;
+
+
+beta  =  .9;
+e_c_m =  .1;
+c_z_1 =  .7;
+c_z_2 = -.3;
+
+
+@#include "example1/model/pac-expectations/pacman-parameters.inc"
+
+model;
+
+  [name='eq:y']
+  y = a_y_1*y(-1) + a_y_2*diff(x(-1)) + b_y_1*y(-2) + b_y_2*diff(x(-2)) + ey ;
+
+
+  [name='eq:x']
+  diff(x) = b_x_1*y(-2) + b_x_2*diff(x(-1)) + ex ;
+
+  [name='eq:v']
+  v = x + d_y*y ;
+
+  [name='eq:pac']
+  diff(z) = e_c_m*(x(-1)-z(-1)) + c_z_1*diff(z(-1))  + c_z_2*diff(z(-2)) +
+  @#include "example1/model/pac-expectations/pacman-expression.inc"
+  + ez;
+
+end;
+
+shocks;
+  var ex = 1.0;
+  var ey = 1.0;
+  var ez = 1.0;
+end;
+
+// Set initial conditions to zero. Please use more sensible values if any...
+initialconditions = dseries(zeros(10, M_.endo_nbr+M_.exo_nbr), 2000Q1, vertcat(M_.endo_names,M_.exo_names));
+
+// Simulate the model for 20 periods
+set_dynare_seed('default');
+TrueData = simul_backward_model(initialconditions, 20);
+
+verbatim;
+
+  set_dynare_seed('default');
+  y = zeros(M_.endo_nbr,1);
+  y(1:M_.orig_endo_nbr) = rand(M_.orig_endo_nbr, 1);
+  x = randn(M_.exo_nbr,1);
+  y = substitution.set_auxiliary_variables(y, x, M_.params);
+  y = [y(find(M_.lead_lag_incidence(1,:))); y];
+  example1 = load('example1.mat');
+  [residual, g1] = substitution.dynamic(y, x', M_.params, oo_.steady_state, 1);
+
+  if max(abs(example1.TrueData.data(:)-TrueData.data(:)))>1e-9
+    error('Simulations do not match.')
+  end
+
+  if ~isequal(length(residual), length(example1.residual)) || max(abs(example1.residual-residual))>1e-8
+    warning('Residuals do not match!')
+  end
+
+  if ~isequal(length(g1(:)), length(example1.g1(:))) || max(abs(example1.g1(:)-g1(:)))>1e-8
+    warning('Jacobian matrices do not match!')
+  end
+
+end;
diff --git a/tests/pac/var-8e/example1.mod b/tests/pac/var-8e/example1.mod
new file mode 100644
index 0000000000000000000000000000000000000000..9fb1bbc9badd9eae3b65999f0484810805bd46db
--- /dev/null
+++ b/tests/pac/var-8e/example1.mod
@@ -0,0 +1,94 @@
+// --+ options: json=compute, stochastic +--
+
+var y x z v;
+
+varexo ex ey ez ;
+
+parameters a_y_1 a_y_2 b_y_1 b_y_2 b_x_1 b_x_2 d_y; // VAR parameters
+
+parameters beta e_c_m c_z_1 c_z_2;               // PAC equation parameters
+
+a_y_1 =  .2;
+a_y_2 =  .3;
+b_y_1 =  .1;
+b_y_2 =  .4;
+b_x_1 = -.1;
+b_x_2 = -.2;
+d_y = .5;
+
+
+beta  =  .9;
+e_c_m =  .1;
+c_z_1 =  .7;
+c_z_2 = -.3;
+
+var_model(model_name=toto, structural, eqtags=['eq:x', 'eq:y']);
+
+pac_model(auxiliary_model_name=toto, discount=beta, model_name=pacman);
+
+pac_target_info(pacman);
+  target v;
+  auxname_target_nonstationary vns;
+
+  component y;
+  auxname pv_y_;
+  kind ll;
+
+  component x;
+  auxname pv_dx_;
+  kind dd;
+
+end;
+
+model;
+
+  [name='eq:y']
+  y = a_y_1*y(-1) + a_y_2*diff(x(-1)) + b_y_1*y(-2) + b_y_2*diff(x(-2)) + ey ;
+
+
+  [name='eq:x']
+  diff(x) = b_x_1*y(-2) + b_x_2*diff(x(-1)) + ex ;
+
+  [name='eq:v']
+  v = x + d_y*y ;
+
+  [name='zpac']
+  diff(z) = e_c_m*(pac_target_nonstationary(pacman)-z(-1)) + c_z_1*diff(z(-1))  + c_z_2*diff(z(-2)) + pac_expectation(pacman) + ez;
+
+end;
+
+shocks;
+  var ex = 1.0;
+  var ey = 1.0;
+  var ez = 1.0;
+end;
+
+// Initialize the PAC model (build the Companion VAR representation for the auxiliary model).
+pac.initialize('pacman');
+
+// Update the parameters of the PAC expectation model (h0 and h1 vectors).
+pac.update.expectation('pacman');
+
+// Set initial conditions to zero. Please use more sensible values if any...
+initialconditions = dseries(zeros(10, M_.endo_nbr+M_.exo_nbr), 2000Q1, vertcat(M_.endo_names,M_.exo_names));
+
+// Simulate the model for 500 periods
+TrueData = simul_backward_model(initialconditions, 5000);
+
+clear eparams
+eparams.e_c_m   =  .9;
+eparams.c_z_1   =  .5;
+eparams.c_z_2   =  .2;
+
+// Define the dataset used for estimation
+edata = TrueData;
+edata.ez = dseries(NaN(TrueData.nobs, 1), 2000Q1, 'ez');
+pac.estimate.nls('zpac', eparams, edata, 2005Q1:2005Q1+4000, 'fmincon');
+
+e_c_m_nls = M_.params(strmatch('e_c_m', M_.param_names, 'exact'));
+c_z_1_nls = M_.params(strmatch('c_z_1', M_.param_names, 'exact'));
+c_z_2_nls = M_.params(strmatch('c_z_2', M_.param_names, 'exact'));
+
+disp(sprintf('Estimate of e_c_m: %f', e_c_m_nls))
+disp(sprintf('Estimate of c_z_1: %f', c_z_1_nls))
+disp(sprintf('Estimate of c_z_2: %f', c_z_2_nls))
diff --git a/tests/pac/var-9/example1.mod b/tests/pac/var-9/example1.mod
new file mode 100644
index 0000000000000000000000000000000000000000..0a5fcda4a19a2e17b8398ef31699b9bc6bada074
--- /dev/null
+++ b/tests/pac/var-9/example1.mod
@@ -0,0 +1,94 @@
+// --+ options: json=compute, stochastic +--
+
+var y x z v;
+
+varexo ex ey ez ;
+
+parameters a_y_1 a_y_2 b_y_1 b_y_2 b_x_1 b_x_2 d_y; // VAR parameters
+
+parameters beta e_c_m c_z_1 c_z_2;               // PAC equation parameters
+
+a_y_1 =  .2;
+a_y_2 =  .3;
+b_y_1 =  .1;
+b_y_2 =  .4;
+b_x_1 = -.1;
+b_x_2 = -.2;
+d_y = .5;
+
+
+beta  =  .9;
+e_c_m =  .1;
+c_z_1 =  .7;
+c_z_2 = -.3;
+
+var_model(model_name=toto, structural, eqtags=['eq:x', 'eq:y']);
+
+pac_model(auxiliary_model_name=toto, discount=beta, model_name=pacman);
+
+pac_target_info(pacman);
+  target v;
+  auxname_target_nonstationary vns;
+
+  component y;
+  auxname pv_y_;
+  kind ll;
+
+  component x;
+  growth diff(x(-1));
+  auxname pv_dx_;
+  kind dd;
+
+end;
+
+model;
+
+  [name='eq:y']
+  y = a_y_1*y(-1) + a_y_2*diff(x(-1)) + b_y_1*y(-2) + b_y_2*diff(x(-2)) + ey ;
+
+
+  [name='eq:x']
+  diff(x) = b_x_1*y(-2) + b_x_2*diff(x(-1)) + ex ;
+
+  [name='eq:v']
+  v = x + d_y*y ;
+
+  [name='eq:pac']
+  diff(z) = e_c_m*(pac_target_nonstationary(pacman)-z(-1)) + c_z_1*diff(z(-1))  + c_z_2*diff(z(-2)) + pac_expectation(pacman) + ez;
+
+end;
+
+shocks;
+  var ex = 1.0;
+  var ey = 1.0;
+  var ez = 1.0;
+end;
+
+// Initialize the PAC model (build the Companion VAR representation for the auxiliary model).
+pac.initialize('pacman');
+
+// Update the parameters of the PAC expectation model (h0 and h1 vectors).
+pac.update.expectation('pacman');
+
+// Set initial conditions to zero. Please use more sensible values if any...
+initialconditions = dseries(zeros(10, M_.endo_nbr+M_.exo_nbr), 2000Q1, vertcat(M_.endo_names,M_.exo_names));
+
+// Simulate the model for 500 periods
+TrueData = simul_backward_model(initialconditions, 20);
+
+// Print expanded PAC_EXPECTATION term.
+pac.print('pacman', 'eq:pac');
+
+// Print expanded PAC_EXPECTATION term.
+pac.print('pacman', 'eq:pac');
+
+verbatim;
+  set_dynare_seed('default');
+  y = zeros(M_.endo_nbr,1);
+  y(1:M_.orig_endo_nbr) = rand(M_.orig_endo_nbr, 1);
+  x = randn(M_.exo_nbr,1);
+  y = example1.set_auxiliary_variables(y, x, M_.params);
+  y = [y(find(M_.lead_lag_incidence(1,:))); y];
+  [residual, g1] = example1.dynamic(y, x', M_.params, oo_.steady_state, 1);
+  save('example1.mat', 'residual', 'g1', 'TrueData');
+end;
diff --git a/tests/pac/var-9/substitution.mod b/tests/pac/var-9/substitution.mod
new file mode 100644
index 0000000000000000000000000000000000000000..d9e70378b6759b1bb374108a04e4c1e25da19f24
--- /dev/null
+++ b/tests/pac/var-9/substitution.mod
@@ -0,0 +1,84 @@
+// --+ options: json=compute, stochastic +--
+
+var y x z v;
+
+varexo ex ey ez ;
+
+parameters a_y_1 a_y_2 b_y_1 b_y_2 b_x_1 b_x_2 d_y; // VAR parameters
+
+parameters beta e_c_m c_z_1 c_z_2;               // PAC equation parameters
+
+a_y_1 =  .2;
+a_y_2 =  .3;
+b_y_1 =  .1;
+b_y_2 =  .4;
+b_x_1 = -.1;
+b_x_2 = -.2;
+d_y = .5;
+
+
+beta  =  .9;
+e_c_m =  .1;
+c_z_1 =  .7;
+c_z_2 = -.3;
+
+@#include "example1/model/pac-expectations/pacman-parameters.inc"
+
+model;
+
+  [name='eq:y']
+  y = a_y_1*y(-1) + a_y_2*diff(x(-1)) + b_y_1*y(-2) + b_y_2*diff(x(-2)) + ey ;
+
+
+  [name='eq:x']
+  diff(x) = b_x_1*y(-2) + b_x_2*diff(x(-1)) + ex ;
+
+  [name='eq:v']
+  v = x + d_y*y ;
+
+  [name='eq:pac']
+  diff(z) = e_c_m*(x(-1)-z(-1)) + c_z_1*diff(z(-1))  + c_z_2*diff(z(-2)) +
+  @#include "example1/model/pac-expectations/pacman-expression.inc"
+  +
+  @#include "example1/model/pac-expectations/pacman-growth-neutrality-correction.inc"
+  + ez;
+
+end;
+
+shocks;
+  var ex = 1.0;
+  var ey = 1.0;
+  var ez = 1.0;
+end;
+
+// Set initial conditions to zero. Please use more sensible values if any...
+initialconditions = dseries(zeros(10, M_.endo_nbr+M_.exo_nbr), 2000Q1, vertcat(M_.endo_names,M_.exo_names));
+
+// Simulate the model for 20 periods
+set_dynare_seed('default');
+TrueData = simul_backward_model(initialconditions, 20);
+
+verbatim;
+
+  set_dynare_seed('default');
+  y = zeros(M_.endo_nbr,1);
+  y(1:M_.orig_endo_nbr) = rand(M_.orig_endo_nbr, 1);
+  x = randn(M_.exo_nbr,1);
+  y = substitution.set_auxiliary_variables(y, x, M_.params);
+  y = [y(find(M_.lead_lag_incidence(1,:))); y];
+  example1 = load('example1.mat');
+  [residual, g1] = substitution.dynamic(y, x', M_.params, oo_.steady_state, 1);
+
+  if max(abs(example1.TrueData.data(:)-TrueData.data(:)))>1e-9
+    error('Simulations do not match.')
+  end
+
+  if ~isequal(length(residual), length(example1.residual)) || max(abs(example1.residual-residual))>1e-8
+    warning('Residuals do not match!')
+  end
+
+  if ~isequal(length(g1(:)), length(example1.g1(:))) || max(abs(example1.g1(:)-g1(:)))>1e-8
+    warning('Jacobian matrices do not match!')
+  end
+
+end;
diff --git a/tests/pac/var-9e/example1.mod b/tests/pac/var-9e/example1.mod
new file mode 100644
index 0000000000000000000000000000000000000000..4d0169f339335c66127e20c5d7784527f091d1b3
--- /dev/null
+++ b/tests/pac/var-9e/example1.mod
@@ -0,0 +1,98 @@
+// --+ options: json=compute, stochastic +--
+
+var y x z v;
+
+varexo ex ey ez ;
+
+parameters a_y_1 a_y_2 b_y_1 b_y_2 b_x_1 b_x_2 d_y; // VAR parameters
+
+parameters beta e_c_m c_z_1 c_z_2;               // PAC equation parameters
+
+a_y_1 =  .2;
+a_y_2 =  .3;
+b_y_1 =  .1;
+b_y_2 =  .4;
+b_x_1 = -.1;
+b_x_2 = -.2;
+d_y = .5;
+
+
+beta  =  .9;
+e_c_m =  .1;
+c_z_1 =  .7;
+c_z_2 = -.3;
+
+var_model(model_name=toto, structural, eqtags=['eq:x', 'eq:y']);
+
+pac_model(auxiliary_model_name=toto, discount=beta, model_name=pacman);
+
+pac_target_info(pacman);
+  target v;
+  auxname_target_nonstationary vns;
+
+  component y;
+  auxname pv_y_;
+  kind ll;
+
+  component x;
+  growth diff(x(-1));
+  auxname pv_dx_;
+  kind dd;
+
+end;
+
+model;
+
+  [name='eq:y']
+  y = a_y_1*y(-1) + a_y_2*diff(x(-1)) + b_y_1*y(-2) + b_y_2*diff(x(-2)) + ey ;
+
+
+  [name='eq:x']
+  diff(x) = b_x_1*y(-2) + b_x_2*diff(x(-1)) + ex ;
+
+  [name='eq:v']
+  v = x + d_y*y ;
+
+  [name='zpac']
+  diff(z) = e_c_m*(pac_target_nonstationary(pacman)-z(-1)) + c_z_1*diff(z(-1))  + c_z_2*diff(z(-2)) + pac_expectation(pacman) + ez;
+
+end;
+
+shocks;
+  var ex = 1.0;
+  var ey = 1.0;
+  var ez = 1.0;
+end;
+
+// Initialize the PAC model (build the Companion VAR representation for the auxiliary model).
+pac.initialize('pacman');
+
+// Update the parameters of the PAC expectation model (h0 and h1 vectors).
+pac.update.expectation('pacman');
+
+// Set initial conditions to zero. Please use more sensible values if any...
+initialconditions = dseries(zeros(10, M_.endo_nbr+M_.exo_nbr), 2000Q1, vertcat(M_.endo_names,M_.exo_names));
+
+// Simulate the model for 500 periods
+TrueData = simul_backward_model(initialconditions, 5000);
+
+// Print expanded PAC_EXPECTATION term.
+pac.print('pacman', 'eq:pac');
+
+clear eparams
+eparams.e_c_m   =  .9;
+eparams.c_z_1   =  .5;
+eparams.c_z_2   =  .2;
+
+// Define the dataset used for estimation
+edata = TrueData;
+edata.ez = dseries(NaN(TrueData.nobs, 1), 2000Q1, 'ez');
+pac.estimate.nls('zpac', eparams, edata, 2005Q1:2005Q1+4000, 'fmincon');
+
+e_c_m_nls = M_.params(strmatch('e_c_m', M_.param_names, 'exact'));
+c_z_1_nls = M_.params(strmatch('c_z_1', M_.param_names, 'exact'));
+c_z_2_nls = M_.params(strmatch('c_z_2', M_.param_names, 'exact'));
+
+disp(sprintf('Estimate of e_c_m: %f', e_c_m_nls))
+disp(sprintf('Estimate of c_z_1: %f', c_z_1_nls))
+disp(sprintf('Estimate of c_z_2: %f', c_z_2_nls))