diff --git a/matlab/utilities/estimation/check_varobs_are_endo_and_declared_once.m b/matlab/utilities/estimation/check_varobs_are_endo_and_declared_once.m
index 1cb92635d..874f75b90 100644
--- a/matlab/utilities/estimation/check_varobs_are_endo_and_declared_once.m
+++ b/matlab/utilities/estimation/check_varobs_are_endo_and_declared_once.m
@@ -1,22 +1,15 @@
-function check_varobs_are_endo_and_declared_once(varobs,endo_names)
-% function check_varobs_are_endo_and_declared_once(varobs,endo_names)
-% -------------------------------------------------------------------------
-% Check that each declared observed variable:
-% - is also an endogenous variable
-% - is declared only once
-% -------------------------------------------------------------------------
-% INPUTS
-% o varobs: [cell] list of observed variables
-% o endo_names: [cell] list of endogenous variables
-% -------------------------------------------------------------------------
-% OUTPUTS
-% none, display an error message something is wrong with VAROBS
-% -------------------------------------------------------------------------
-% This function is called by
-% o dynare_estimation_init.m
-% -------------------------------------------------------------------------
+function check_varobs_are_endo_and_declared_once(varobs, endo_names)
-% Copyright © 2023 Dynare Team
+% Check that each declared observed variable is an endogenous variable and is declared only once
+%
+% INPUTS
+% - varobs [cell] list of observed variables
+% - endo_names [cell] list of endogenous variables
+%
+% OUTPUTS
+% None, display an error message something is wrong with VAROBS
+
+% Copyright © 2023-2024 Dynare Team
%
% This file is part of Dynare.
%
@@ -33,18 +26,88 @@ function check_varobs_are_endo_and_declared_once(varobs,endo_names)
% You should have received a copy of the GNU General Public License
% along with Dynare. If not, see .
-number_of_observed_variables = length(varobs);
-for i = 1:number_of_observed_variables
- if ~any(strcmp(varobs{i},endo_names))
- error(['VAROBS: unknown variable (' varobs{i} ')!'])
- end
+cut = @(x) x(1:end-2); % Remove the last two elements of an array.
+
+% Throw an error if an observed variable is not declared as an endogenous variable.
+unknown_varobs = setdiff(varobs, endo_names);
+if ~isempty(unknown_varobs)
+ error('Estimation:varobs:unknown', 'VAROBS: Unknown endogenous variables (%s)\n', cut(sprintf('%s, ', unknown_varobs{:})))
end
% Check that a variable is not declared as observed more than once.
-if length(unique(varobs)) 1
- error(['VAROBS: a variable cannot be declared as observed more than once (' varobs{i} ')!'])
+[varobs_, vi, vj] = unique(varobs);
+if ~isequal(vi, vj)
+ duplicates = {}; j=0;
+ for i=2:length(vi)
+ if vi(i)>vi(i-1)+1
+ j = j+1;
+ duplicates{j} = varobs{vi(i-1)};
end
end
-end
\ No newline at end of file
+ if sum(length(vi)==vj)
+ duplicates{j+1} = varobs{vi(end)};
+ end
+ error('Estimation:varobs:duplicate', 'VAROBS: A variable cannot be declared as observed more than once (%s)\n', cut(sprintf('%s, ', duplicates{:})))
+end
+
+return % --*-- Unit tests --*--
+
+%@test:1
+endovar={'A1','A2','A3','A4','A5'};
+obsvar={'A1','A1','A3','A4','A4','A4','A5'};
+
+
+% Call the tested routine.
+try
+ check_varobs_are_endo_and_declared_once(obsvar, endovar)
+ t(1) = false;
+catch ME
+ t(1) = true;
+end
+
+if t(1)
+ t(2) = strcmp(ME.identifier, 'Estimation:varobs:duplicate');
+end
+
+T = all(t);
+%@eof:1
+
+%@test:2
+endovar={'A1','A2','A3','A4','A5'};
+obsvar={'A1','A3','A4','A5','A5'};
+
+
+% Call the tested routine.
+try
+ check_varobs_are_endo_and_declared_once(obsvar, endovar)
+ t(1) = false;
+catch ME
+ t(1) = true;
+end
+
+if t(1)
+ t(2) = strcmp(ME.identifier, 'Estimation:varobs:duplicate');
+end
+
+T = all(t);
+%@eof:2
+
+%@test:3
+endovar={'A1','A2','A3','A4','A5'};
+obsvar={'A1','A3','A4','B1','A5'};
+
+
+% Call the tested routine.
+try
+ check_varobs_are_endo_and_declared_once(obsvar, endovar)
+ t(1) = false;
+catch ME
+ t(1) = true;
+end
+
+if t(1)
+ t(2) = strcmp(ME.identifier, 'Estimation:varobs:unknown');
+end
+
+T = all(t);
+%@eof:3