How to define special sets to work around network flow?

Dear support team,

I am working on a special network flow problem, something like a n*n grid, and I am having difficulties to define some of its sets. The problem is stated as follows:

Given a directed graph G = (V,E). Each cell of the n×n grid corresponds to a node which is referred to by (i,j). The set of neighbor nodes of a node (i,j) is given by N_{i,j} = \{(i−1,j),(i+1,j),(i,j −1),(i,j +1)\} \cap V . The set E of edges is then obtained by defining an edge (i,j,k,l) between any two neighbor nodes (i,j) \in V and (k,l) \in N_{i,j}.

What I am trying to obtain the corresponding sets is:

set i / i1 * i8 /;
set j / j1 * j8 /;
alias (i,ii),(j,jj);
;
set V(i,j); V(i,j)= yes;
display V;
;
set nb(i,j,ii,jj);
nb(i-1,j,i,j) = yes;
nb(i+1,j,i,j) = yes;
nb(i,j,i,j-1) = yes;
nb(i,j,i,j+1) = yes;
display nb;

However, I am unsure if the result can correspond to what I expected in the following 8*8 grid: (for summarizing, I omitted the rest of the values)

set N[1,1] = (1,2) (2,1);
set N[1,2] = (1,1) (1,3) (2,2);
set N[1,3] = (1,2) (1,4) (2,3);
set N[1,4] = (1,3) (1,5) (2,4);
set N[1,5] = (1,4) (1,6) (2,5);
set N[1,6] = (1,5) (1,7) (2,6);
set N[1,7] = (1,6) (1,8) (2,7);
set N[1,8] = (1,7) (2,8);

Also, I need to define the source and sink nodes as a pair-node like:

Source = (2,1) (2,2) (2,5) (2,6) (6,2) (8,1) (8,5);
sink = (2,3) (2,7) (5,3) (5,5) (6,8) (7,8) (8,8);

where the first element in the source, (2,1), is referred to as the start point of the first commodity, and the first element of the sink, (2,3), would be the endpoint of the first commodity, And so on.

I was wondering if, how can I define the correct corresponding sets?

Best regards
Abbas

If you need any further information, I can provide that and just let me know.

Best

Hi, I think I understand what you are trying to do. Here is how I usually define sets, including sets of neighbors, on a grid. If you have better ideas, let me know!

set i nodes /1*64/;
alias (i,j);

parameter ordi(i);
ordi(i)=ord(i);
*display ordi;

scalars rows number of rows /8/
cols number of columns /8/;

parameters rowind(i) row index
colind(i) col index;
rowind(i)=1+floor((ordi(i)-1)/cols);
colind(i)=ordi(i)-(rowind(i)-1)*cols;
*display rowind, colind;

parameter d(i,j) Euclidean distance between site i and j;
d(i,j)(ordi(i) lt ordi(j))=abs(colind(j)-colind(i))-1+abs(rowind(j)-rowind(i)); d(j,i)(ordi(i) lt ordi(j))=d(i,j);
option d:0:0:1
*display d;

set goodnb(i,j);
goodnb(i,j)=no;
goodnb(i,j)(ordi(i) lt ordi(j) and d(i,j) eq 0)=yes; goodnb(j,i)(ordi(i) lt ordi(j) and goodnb(i,j))=yes;
option goodnb:0:0:1
display goodnb;

set ss(i,j) source and sink;
ss(i,j)=0;
ss(i,j)(rowind(i)=2 and colind(i)=1 and rowind(j)=2 and colind(j)=3)=yes; ss(i,j)(rowind(i)=2 and colind(i)=2 and rowind(j)=2 and colind(j)=7)=yes;

option ss:0:0:1;
display ss;

Dear @ywangqau,

Thank you so much for your comments. Could you please, elaborate more on how I can retrieve the output of the set N_{i,j}, and \text{Sink/Source} parameters based on your snippet code as the outputs are different from what I expected?

All the best

Hi, the key difference between your method and mine is the definition of the set of nodes. You indicated each node using its row number i (i1 to i8 in the figure below) and column number j (j1 to j8 in the figure below), while I indicated each node using its index number i (1 to 64 in the figure below). The definitions of neighbors are basically the same, that is, nodes sharing a common edge are neighbors. You used the relations between row numbers and column numbers to define neighbors, while I find the distance between each pair of nodes and define that nodes with a distance of zero are neighbors. The results are the same.

set i nodes /1*64/;
alias (i,j);

parameter ordi(i);
ordi(i)=ord(i);
*display ordi;

scalars rows number of rows /8/
cols number of columns /8/;

*the code below is to calculate each node’s row index and column index, that is, arrange those 64 nodes into a 8 rows and 8 cols grid.
parameters rowind(i) row index
colind(i) col index;
rowind(i)=1+floor((ordi(i)-1)/cols);
colind(i)=ordi(i)-(rowind(i)-1)*cols;
*display rowind, colind;

*the codes below is to calculate the distance between each pair of nodes.
parameter d(i,j) Euclidean distance between site i and j;
d(i,j) (ordi(i) lt ordi(j))=abs(colind(j)-colind(i))-1+abs(rowind(j)-rowind(i)); d(j,i)(ordi(i) lt ordi(j))=d(i,j);
option d:0:0:1
*display d;

*this code defines neighbors. nodes with a distance of zero are considered neighbors.
set goodnb(i,j);
goodnb(i,j)=no;
goodnb(i,j)(ordi(i) lt ordi(j) and d(i,j) eq 0)=yes; goodnb(j,i)(ordi(i) lt ordi(j) and goodnb(i,j))=yes;
option goodnb:0:0:1
display goodnb;

*this code defines source and sink pairs. these pairs are designated by the user.
set ss(i,j) source and sink;
ss(i,j)=0;
ss(i,j)(rowind(i)=2 and colind(i)=1 and rowind(j)=2 and colind(j)=3)=yes; ss(i,j)(rowind(i)=2 and colind(i)=2 and rowind(j)=2 and colind(j)=7)=yes;

option ss:0:0:1;
display ss;

Dear @ywangqau,

Many thanks for your explanations. Please, let me get back to my first question, and based on what you pointed out I can infer that my implementation of N_{i,j} is correct. Would you confirm that?

BR

Yes, your code is OK, and I ran the code and the results are correct. The definition of the set of source and sink nodes may have to be done by specifying the row number and column number of each source and sink, as I did below using the first three pairs as an example.

set i / i1 * i8 /;
set j / j1 * j8 /;
alias (i,ii),(j,jj);
;
set V(i,j); V(i,j)= yes;
display V;
;
set nb(i,j,ii,jj);
nb(i-1,j,i,j) = yes;
nb(i+1,j,i,j) = yes;
nb(i,j,i,j-1) = yes;
nb(i,j,i,j+1) = yes;
option nb:0:0:1;
display nb;

set ss(i,j,ii,jj) pairs of source and sink nodes;
ss(‘i2’,‘j1’,‘i2’,‘j3’)=yes;
ss(‘i2’,‘j2’,‘i2’,‘j7’)=yes;
ss(‘i2’,‘j5’,‘i5’,‘j3’)=yes;

display ss;

Dear @ywangqau,

Thank you so much for your comments. Please, let me complete the whole model and check the results by both methods and I will get back to you. This may take in the next days.

All the best