Skip to main content

Hi,

I think it would be helpful to provide a little bit of background regarding my problem first. I’m currently working on a project where a given set of volunteers should be assigned to a given set of people in need. So basically a simple transport problem, where the demand of all people in need is 1 and the supply of all volunteers is 1. The model in AIMMS always expects a balanced problem. So in case of a surplus on either side, dummy persons will balance the problem.

 

The data for a set containing all persons gets read from a file like this. The first half are the people in need and the second half are volunteers. The last X amount of people in need would be dummies in case of a surplus on the volunteer side. The last X amount of volunteers would  be dummies in case of a surplus on the other side. The example below shows a data set that was already balanced, so without any dummies.

 

Based on the parameters NumberInNeed and NumberVolunteers the AllNodes Set containing all persons is defined like this:

The reason why I would even want all persons together in one set instead of two seperate ones is because this made visualization in a network object easier for me. From here I create two subsets. The first subset InNeed contains all people in need and the second subset Volunteers contains all vonlunteers (both including potential dummies).

 

My problem is:

Now I would like to have two more subsets, one that only contains “Dummies in need” and one that only contains “Volunteer dummies”. Both of these could be empty if the data set was balanced in the first place or one of them would be empty in case of an unbalanced problem that was balanced by introducing dummies on one of the two sides.

 

I tried to create the first one like this:

 

This works fine if there are dummies. Let’s say the the data set from the file above contained 2 InNeed dummies (so that would be the last two persons in need with the indices 11 and 12). That would make {12-2+1 .. 12} so the subset would include person 11 and 12, which would be correct. In case of no dummies this does not work though since the resulting defintion would be {12-0+1..12} = {13..12}.

 

Is there any way I can define this set as empty in case of the parameter NumberInNeedDummies = 0 and define it in the way I did above in case NumberInNeedDummies > 0?

 

I appreciate any help you can provide.

 

Best regards,

Nick

 

Hi, @nick98

You can use a procedure to calculate the subset instead of defining it.. Maybe it would be easier.

 

For instance, set n contains all nodes (including dummies)

Procedure_PopulateSubsets

for n do

if ord(n) <= NumberInNeed then

SetElementAdd(S_CALC_SubsetNumberInNeed,ElementParameter_NumberInNeed,n);

elseif ((ord(n) > NumberInNeed) and (ord(n) <= (NumberInNeed + NumberInNeedDummies)) then
SetElementAdd(S_CALC_SubsetNumberInNeedDummies,ElementParameter_NumberInNeed,n);

elseif ((ord(n) > (NumberInNeed+ NumberInNeedDummies)) and (ord(n) <= (NumberInNeed + NumberInNeedDummies + NumberVolunteers)) then
SetElementAdd(S_CALC_SubsetVolunteers,ElementParameter_NumberInNeed,n);

else
SetElementAdd(S_CALC_SubsetVolunteersDummies,ElementParameter_NumberInNeed,n);

endif;

endfor;

 


Hi, @nick98

You can use a procedure to calculate the subset instead of defining it.. Maybe it would be easier.

 

For instance, set n contains all nodes (including dummies)

Procedure_PopulateSubsets

for n do

if ord(n) <= NumberInNeed then

SetElementAdd(S_CALC_SubsetNumberInNeed,ElementParameter_NumberInNeed,n);

elseif ((ord(n) > NumberInNeed) and (ord(n) <= (NumberInNeed + NumberInNeedDummies)) then
SetElementAdd(S_CALC_SubsetNumberInNeedDummies,ElementParameter_NumberInNeed,n);

elseif ((ord(n) > (NumberInNeed+ NumberInNeedDummies)) and (ord(n) <= (NumberInNeed + NumberInNeedDummies + NumberVolunteers)) then
SetElementAdd(S_CALC_SubsetVolunteers,ElementParameter_NumberInNeed,n);

else
SetElementAdd(S_CALC_SubsetVolunteersDummies,ElementParameter_NumberInNeed,n);

endif;

endfor;

 

Hi @mateusarakawa ,

thank you for your response! I tried to implement this procedure, however I didin't really get it to work yet unfortunately. I’m a beginner with AIMMS and I haven’t really worked with procedures a lot so far.

 

Just to make sure, S_CALC_SubsetNumberInNeedDummies and S_CALC_SubsetVolunteers are subsets of InNeed and Volunteers that I should create manually but without any definition right?

Also I don’t quite understand how the Element Parameter ElementParameter_NumberInNeed is supposed to work. Currently I just have basic paramters NumberInNeed/ Number Volunteers that get initialized by the data file and hold a numeric value. Could you specify how this works and how/ where I should define this Element Parameter?

Thank you!


Hi, @nick98.


S_CALC_SubsetNumberInNeed
S_CALC_SubsetNumberInNeedDummies
S_CALC_SubsetVolunteers
S_CALC_SubsetVolunteersDummies
are all subsets of AllNodes (n). You should create manually but without any definition.

 

Also I don’t quite understand how the Element Parameter is supposed to work.

The element parameter is a mandatory argument to the function SetElementAdd. Without it, the function won’t work. You can define your own element parameter name through this attribute:

Hope it helps.


Hi, @nick98.


S_CALC_SubsetNumberInNeed
S_CALC_SubsetNumberInNeedDummies
S_CALC_SubsetVolunteers
S_CALC_SubsetVolunteersDummies
are all subsets of AllNodes (n). You should create manually but without any definition.

 

Also I don’t quite understand how the Element Parameter is supposed to work.

The element parameter is a mandatory argument to the function SetElementAdd. Without it, the function won’t work. You can define your own element parameter name through this attribute:

Hope it helps.

 

Setting up the Element Parameter properly was the part that I didn’t get right. I got it to work now, thank you so much for your help @mateusarakawa!

This solution is indeed a lot nicer than the definition approach.

 

 

 

 


As an alternative to @mateusarakawa proposal, you can also do a direct generation of subsets based via the ElementRange as you know the number of Volunteers and people InNeed. Full txt and sample project attached, below one statement for determining the possibly DummyInNeed elements.

 

e.g.

Set DummyInNeed {
SubsetOf: AllPeople;
Index: n_d;
Definition: {
if NrVolunteers>NrInNeed then
ElementRange(1, NrVolunteers-NrInNeed, prefix:"n_d-")
else
{}
endif;
}
}

BTW: I have generated 4 sets in total and made them subsets of AllPeople so you can define other parameters (or variables) over the complete set of people, or decide per set to assign values or make network connections such as ‘VolunteerServingPersonInNeed(v,n)’. You can also use each set as a node set in a network object and connect them by arcs going from one set to the other.

 

 


As an alternative to @mateusarakawa proposal, you can also do a direct generation of subsets based via the ElementRange as you know the number of Volunteers and people InNeed. Full txt and sample project attached, below one statement for determining the possibly DummyInNeed elements.

 

e.g.

Set DummyInNeed {
SubsetOf: AllPeople;
Index: n_d;
Definition: {
if NrVolunteers>NrInNeed then
ElementRange(1, NrVolunteers-NrInNeed, prefix:"n_d-")
else
{}
endif;
}
}

BTW: I have generated 4 sets in total and made them subsets of AllPeople so you can define other parameters (or variables) over the complete set of people, or decide per set to assign values or make network connections such as ‘VolunteerServingPersonInNeed(v,n)’. You can also use each set as a node set in a network object and connect them by arcs going from one set to the other.

 

 

Hi @Gertjan ,

thank you very much for this proposal! I had no idea that you could work with conditional statements directly in the definition of a set. A very nice approach together with the ElementRange function. I’ll definitely keep this mind.


Reply


Didn't find what you were looking for? Try searching on our documentation pages:

AIMMS Developer & PRO | AIMMS How-To | AIMMS SC Navigator