Subset of multiple subsets

Problems with syntax of GAMS
Post Reply
mkbonde
User
User
Posts: 8
Joined: 3 years ago

Subset of multiple subsets

Post by mkbonde » 1 month ago

Dear GAMS forum

I regularly run into an issue where we have a set structure in which a set is a subset of two different sets which are both subsets of the same super set, for example:

Code: Select all

sets
  abc /a, b, c/
  ab[abc] /a, b/
  a[abc] /a/
  ac[abc] /a, c/
  c[abc] /c/
;
The problem is when I define a variable over ab, in this case, but want to use the sub-sub-set:

Code: Select all

parameter foo[ab], bar[ac];
foo[a] = 1;
****       $171
**** 171  Domain violation for set
Note that defining a[ab] instead of a[abc] does not help, as I instead get an error here:

Code: Select all

bar[a] = 1;
We currently get around this issue by defining variables on the superset (abc), but this makes the definitions less clear and gives us extra dollar-conditions.

Is there a way of turning off domain checking errors of the above kind? While still checking for errors like the following:

Code: Select all

foo[c] = 1;
****       $171
**** 171  Domain violation for set
where an element is used, which is not contained in the set.

Best regards,
Martin

Fred
Posts: 313
Joined: 6 years ago

Re: Subset of multiple subsets

Post by Fred » 1 month ago

Hi Martin,

While there are ways to turn off domain checking (e.g. via $onUni), this won't help here because the following domain violation would then also be accepted.

Code: Select all

foo[c] = 1;
Since all subsets are based on the same superset, you could use the symbol's domain explicitly but then take only a subset of it:

Code: Select all

parameter foo[ab], bar[ac];
foo[ab(a)] = 1;
bar[ac(a)] = 1;
If you consistently use the symbol's domain

Code: Select all

foo[ab(c)] = 1;
will not throw an error but since ab(c) is empty, no assignment will be made.

This is not as compact as your notation but in the end it should give you the records you want (foo('a')=1 and bar('a')=1).

I hope this helps!

Fred

User avatar
dirkse
Moderator
Moderator
Posts: 188
Joined: 6 years ago
Location: Fairfax, VA

Re: Subset of multiple subsets

Post by dirkse » 1 month ago

Martin,

The situation you describe has appeared in practice a few times, but fortunately not so often. I usually take the approach of declaring subsets, parameters and variables over the larger set, like this:

Code: Select all

sets
  abc /a, b, c/
  ab[abc] /a, b/
  a[abc] /a/
  ac[abc] /a, c/
  c[abc] /c/
;
parameter
  foo[abc] 'really ab'
  bar[abc] 'really ac'
  ;
foo[a] = 1;
bar[a] = 1;

* but this now becomes acceptable, and you do not want it:
foo[c] = 7;
The problem is that the domain checking is incomplete, so the GAMS compilation-time checks are not as extensive as they could be.

You mentioned that this approach leads to extra dollar-conditions. What dollar-conditions do you put in?

-Steve

User avatar
bussieck
Moderator
Moderator
Posts: 832
Joined: 6 years ago

Re: Subset of multiple subsets

Post by bussieck » 1 month ago

Martin,

This won't work with referential integrity/domain checking. The domains build a tree:

Code: Select all

          *
	  |
	 abc
	 / \
	ab  ac
and you either put a under ab or ac but not under both. You can avoid GAMS domain checking by doing controlled a $on/offUni (see https://www.gams.com/40/docs/UG_DollarC ... ARonoffuni) but I am not recommending this:

Code: Select all

sets
  abc /a, b, c/
  ab[abc] /a, b/
  a[abc] /a/
  ac[abc] /a, c/
  c[abc] /c/
;
parameter foo[ab], bar[ac];
$onUni
foo[a] = 1;
bar[c] = 1;
$offUni
display foo, bar;
I usually don't use subsets as domain sets (in such a case). I understand that we loose some clarity by defining everything under abc, but why do you need extra dollar constraints?

-Michael

mkbonde
User
User
Posts: 8
Joined: 3 years ago

Re: Subset of multiple subsets

Post by mkbonde » 1 month ago

Thank you for the replies and explanation.

@Fred I did not know about the superset(subset) syntax (only the other way around) - that could be very useful!


You are all right that there are no extra dollar conditions if I just define everything over the superset (except those stemming from interaction with our own macro processing extensions).
When I choose to define my variable over a subset though, I get extra dollar conditions as in this example:

Code: Select all

sets
  abc /a, b, c/
  ab[abc] /a, b/
  a[abc] /a/
;
variable foo[ab];
equation E_foo;
E_foo[ab]$(a[ab]).. foo[ab] =E= 1;
compared with

Code: Select all

E_foo[a].. foo[a] =E= 1;
which results in a domain error here.

I suppose the "one parent only" is an integral part of the domain checking process, but wanted to check if there was a way of explicitly assigning multiple "parents" to one set.

Post Reply