Skip to content

Commit

Permalink
Merge branch 'reorder_uels' into 'master'
Browse files Browse the repository at this point in the history
reorder uels w.r.t. record order

Closes #30

See merge request devel/gams-transfer-matlab!61
  • Loading branch information
renkekuhlmann committed Sep 28, 2023
2 parents 795e0c8 + 82ee489 commit 1ea9a89
Show file tree
Hide file tree
Showing 3 changed files with 117 additions and 52 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ GAMS Transfer Matlab v0.7.0
- Breaking: Renamed records field `text` of Sets to `element_text`.
- Added symbol `UniverseAlias` to represent alises to the universe set.
- Added possibility to change symbol name case with `Container.renameSymbol`.
- Added possibility to reorder UELs by record order with `Symbol.reorderUELs` (passing no
arguments).
- Added `Container.getSets`, `Container.getParameters`, `Container.getVariables`,
`Container.getEquations` and `Container.getAliases` to get list of symbol objects of corresponding
type.
Expand Down
124 changes: 73 additions & 51 deletions src/Symbol.m
Original file line number Diff line number Diff line change
Expand Up @@ -344,7 +344,7 @@
end

n = 0;
for i = 1:numel(rec_labels)
for i = 1:numel(rec_labels)
switch rec_labels{i}
case obj.TEXT_FIELDS
case obj.VALUE_FIELDS
Expand All @@ -355,7 +355,7 @@

domain_labels = cell(1, n);
n = 0;
for i = 1:numel(rec_labels)
for i = 1:numel(rec_labels)
switch rec_labels{i}
case obj.TEXT_FIELDS
case obj.VALUE_FIELDS
Expand Down Expand Up @@ -1724,6 +1724,13 @@ function resolveDomainViolations(obj, varargin)
return;
end

if ~obj.isValid()
error('Symbol must be valid in order to manage UELs.');
end
if obj.container.indexed
error('UELs not supported in indexed mode.');
end

is_parname = @(x) strcmpi(x, 'ignore_unused');

% check optional arguments
Expand Down Expand Up @@ -1774,13 +1781,6 @@ function resolveDomainViolations(obj, varargin)
error('Invalid number of arguments');
end

if ~obj.isValid()
error('Symbol must be valid in order to manage UELs.');
end
if obj.container.indexed
error('UELs not supported in indexed mode.');
end

uels = {};
domain_labels = obj.domain_labels;
for i = dim
Expand Down Expand Up @@ -1857,8 +1857,16 @@ function setUELs(obj, uels, dim, varargin)
%
% See also: GAMSTransfer.Container.indexed, GAMSTransfer.Symbol.isValid

% check required arguments
if ~isnumeric(dim) || ~isvector(dim) || all(dim ~= round(dim)) || min(dim) < 1 || max(dim) > obj.dimension_
if ~obj.isValid()
error('Symbol must be valid in order to manage UELs.');
end
if obj.container.indexed
error('UELs not supported in indexed mode.');
end

if nargin <= 2
dim = 1:obj.dimension_;
elseif ~isnumeric(dim) || ~isvector(dim) || all(dim ~= round(dim)) || min(dim) < 1 || max(dim) > obj.dimension_
error('Argument ''dimension'' must be integer vector with elements in [1,%d]', obj.dimension_);
end
if ~(isstring(uels) && numel(uels) == 1) && ~ischar(uels) && ~iscellstr(uels);
Expand Down Expand Up @@ -1887,13 +1895,6 @@ function setUELs(obj, uels, dim, varargin)
error('Invalid number of arguments');
end

if ~obj.isValid()
error('Symbol must be valid in order to manage UELs.');
end
if obj.container.indexed
error('UELs not supported in indexed mode.');
end

switch obj.format_
case {GAMSTransfer.RecordsFormat.STRUCT, GAMSTransfer.RecordsFormat.TABLE}
case {GAMSTransfer.RecordsFormat.DENSE_MATRIX, GAMSTransfer.RecordsFormat.SPARSE_MATRIX}
Expand Down Expand Up @@ -1937,29 +1938,50 @@ function setUELs(obj, uels, dim, varargin)
%> Same functionality as `setUELs(uels, dim)`, but checks that no new
%> categories are added. The meaning of records does not change.
%>
%> - `reorderUELs()` reorders UELs by record order for each dimension. Unused UELs are
%> appended.
%>
%> @see \ref GAMSTransfer::Symbol::setUELs "Symbol.setUELs"
function reorderUELs(obj, uels, dim)
% Reorders UELs
%
% Same functionality as setUELs(uels, dim), but checks that no new
% categories are added. The meaning of records does not change.
%
% - `reorderUELs()` reorders UELs by record order for each dimension. Unused UELs are
% appended.
%
% See also: GAMSTransfer.Symbol.setUELs

if ~isnumeric(dim) || ~isvector(dim) || all(dim ~= round(dim)) || min(dim) < 1 || max(dim) > obj.dimension_
error('Argument ''dimension'' must be integer vector with elements in [1,%d]', obj.dimension_);
end
if ~(isstring(uels) && numel(uels) == 1) && ~ischar(uels) && ~iscellstr(uels);
error('Argument ''uels'' must be ''char'' or ''cellstr''.');
end

if ~obj.isValid()
error('Symbol must be valid in order to manage UELs.');
end
if obj.container.indexed
error('UELs not supported in indexed mode.');
end

if nargin == 1
domain_labels = obj.domain_labels;
for i = 1:obj.dimension_
uels = obj.getUELs(i);
rec_uels_ids = uint64(obj.records.(domain_labels{i}));
[~,uidx,~] = unique(rec_uels_ids, 'first');
rec_uels_ids = rec_uels_ids(sort(uidx));
rec_uels_ids = rec_uels_ids(rec_uels_ids ~= nan);
obj.setUELs(uels(rec_uels_ids), i);
obj.addUELs(uels, i);
end
return
end
if nargin <= 2
dim = 1:obj.dimension_;
elseif ~isnumeric(dim) || ~isvector(dim) || all(dim ~= round(dim)) || min(dim) < 1 || max(dim) > obj.dimension_
error('Argument ''dimension'' must be integer vector with elements in [1,%d]', obj.dimension_);
end
if ~(isstring(uels) && numel(uels) == 1) && ~ischar(uels) && ~iscellstr(uels);
error('Argument ''uels'' must be ''char'' or ''cellstr''.');
end

for i = dim
current_uels = obj.getUELs(i);

Expand Down Expand Up @@ -1999,6 +2021,13 @@ function addUELs(obj, uels, dim)
%
% See also: GAMSTransfer.Container.indexed, GAMSTransfer.Symbol.isValid

if ~obj.isValid()
error('Symbol must be valid in order to manage UELs.');
end
if obj.container.indexed
error('UELs not supported in indexed mode.');
end

if nargin < 3
dim = 1:obj.dimension_;
end
Expand All @@ -2009,13 +2038,6 @@ function addUELs(obj, uels, dim)
error('Argument ''uels'' must be ''char'' or ''cellstr''.');
end

if ~obj.isValid()
error('Symbol must be valid in order to manage UELs.');
end
if obj.container.indexed
error('UELs not supported in indexed mode.');
end

switch obj.format_
case GAMSTransfer.RecordsFormat.EMPTY
if obj.container.features.categorical
Expand Down Expand Up @@ -2083,6 +2105,13 @@ function removeUELs(obj, uels, dim)
return
end

if ~obj.isValid()
error('Symbol must be valid in order to manage UELs.');
end
if obj.container.indexed
error('UELs not supported in indexed mode.');
end

if nargin < 2
uels = {};
end
Expand All @@ -2096,13 +2125,6 @@ function removeUELs(obj, uels, dim)
error('Argument ''dimension'' must be integer vector with elements in [1,%d]', obj.dimension_);
end

if ~obj.isValid()
error('Symbol must be valid in order to manage UELs.');
end
if obj.container.indexed
error('UELs not supported in indexed mode.');
end

switch obj.format_
case GAMSTransfer.RecordsFormat.EMPTY
if obj.container.features.categorical
Expand Down Expand Up @@ -2187,6 +2209,13 @@ function renameUELs(obj, uels, varargin)
return
end

if ~obj.isValid()
error('Symbol must be valid in order to manage UELs.');
end
if obj.container.indexed
error('UELs not supported in indexed mode.');
end

p = inputParser();
is_dim = @(x) isnumeric(x) && isvector(x) && all(x == round(x)) && min(x) >= 1 && max(x) <= obj.dimension_;
addOptional(p, 'dim', 1:obj.dimension_, is_dim);
Expand All @@ -2200,13 +2229,6 @@ function renameUELs(obj, uels, varargin)
error('Argument ''uels'' must be ''char'', ''cellstr'', ''struct'' or ''containers.Map''.');
end

if ~obj.isValid()
error('Symbol must be valid in order to manage UELs.');
end
if obj.container.indexed
error('UELs not supported in indexed mode.');
end

switch obj.format_
case GAMSTransfer.RecordsFormat.EMPTY
if obj.container.features.categorical
Expand Down Expand Up @@ -2289,7 +2311,7 @@ function renameUELs(obj, uels, varargin)
%> Converts UELs to lower case
%>
%> - `lowerUELs()` converts the UELs for all dimension(s).
%> - `lowerUELs(d)` converts the UELs for dimension(s) `d`.
%> - `lowerUELs(d)` converts the UELs for dimension(s) `d`.
%>
%> See \ref GAMSTRANSFER_MATLAB_RECORDS_UELS for more information.
%>
Expand All @@ -2303,7 +2325,7 @@ function lowerUELs(obj, dim)
% Converts UELs to lower case
%
% lowerUELs() converts the UELs for all dimension(s).
% lowerUELs(d) converts the UELs for dimension(s) d.
% lowerUELs(d) converts the UELs for dimension(s) d.
%
% If an old UEL is provided in struct or containers.Map that is
% not present in the symbol UELs, it will be silently ignored.
Expand Down Expand Up @@ -2334,7 +2356,7 @@ function lowerUELs(obj, dim)
%> Converts UELs to upper case
%>
%> - `upperUELs()` converts the UELs for all dimension(s).
%> - `upperUELs(d)` converts the UELs for dimension(s) `d`.
%> - `upperUELs(d)` converts the UELs for dimension(s) `d`.
%>
%> See \ref GAMSTRANSFER_MATLAB_RECORDS_UELS for more information.
%>
Expand All @@ -2348,7 +2370,7 @@ function upperUELs(obj, dim)
% Converts UELs to upper case
%
% upperUELs() converts the UELs for all dimension(s).
% upperUELs(d) converts the UELs for dimension(s) d.
% upperUELs(d) converts the UELs for dimension(s) d.
%
% If an old UEL is provided in struct or containers.Map that is
% not present in the symbol UELs, it will be silently ignored.
Expand Down Expand Up @@ -2414,7 +2436,7 @@ function unsetDomain(obj, unset_domains)
if numel(unique(domain_labels)) ~= numel(domain_labels)
for i = n
domain_labels{i} = sprintf('%s_%d', domain_labels{i}, i);
end
end
end
end

Expand Down
43 changes: 42 additions & 1 deletion test/test_uels.m
Original file line number Diff line number Diff line change
Expand Up @@ -1223,7 +1223,48 @@ function test_symbol_uels(t, cfg)
t.assert(ids(5) == 4);
t.assert(ids(6) == 2);

t.add('symbol_uels_reorder_2');
t.add('symbol_uels_reorder_2')
x.addUELs({'unused1', 'unused2'}, 1);
x.reorderUELs({'i3', 'unused1', 'i10', 'i1', 'unused2', 'i6'}, 1);
uels = x.getUELs(1);
t.assert(numel(uels) == 6);
t.assertEquals(uels{1}, 'i3');
t.assertEquals(uels{2}, 'unused1');
t.assertEquals(uels{3}, 'i10');
t.assertEquals(uels{4}, 'i1');
t.assertEquals(uels{5}, 'unused2');
t.assertEquals(uels{6}, 'i6');
ids = int64(x.records.i);
t.assert(numel(ids) == 6);
t.assert(ids(1) == 4);
t.assert(ids(2) == 1);
t.assert(ids(3) == 1);
t.assert(ids(4) == 6);
t.assert(ids(5) == 6);
t.assert(ids(6) == 3);
c.modified = false;
x.reorderUELs();
t.assert(c.modified);
t.assert(x.modified);
uels = x.getUELs(1);
t.assert(numel(uels) == 6);
t.assertEquals(uels{1}, 'i1');
t.assertEquals(uels{2}, 'i3');
t.assertEquals(uels{3}, 'i6');
t.assertEquals(uels{4}, 'i10');
t.assertEquals(uels{5}, 'unused1');
t.assertEquals(uels{6}, 'unused2');
ids = int64(x.records.i);
t.assert(numel(ids) == 6);
t.assert(ids(1) == 1);
t.assert(ids(2) == 2);
t.assert(ids(3) == 2);
t.assert(ids(4) == 3);
t.assert(ids(5) == 3);
t.assert(ids(6) == 4);

t.add('symbol_uels_reorder_3');
x.removeUELs({'unused1', 'unused2'}, 1);
try
t.assert(false);
x.reorderUELs({'i6', 'i3'}, 1);
Expand Down

0 comments on commit 1ea9a89

Please sign in to comment.