Topic
• 2 replies
• Latest Post - ‏2014-02-26T22:34:26Z by davidoff
davidoff
51 Posts

# Pinned topic question on inverse

‏2014-02-21T11:54:29Z | bijection inverse

Hello

To my understanding, and after browsing the documentation, I thought this following test with the inverse function would work, but the answer is "no solution"

using CP;

range rcandidats = 0 .. 3;
range ralveoles = 0 .. 9;

dvar int alv[rcandidats] in 0 .. 10;
dvar int can[ralveoles] in 0 .. 4;

constraints{
inverse(alv,can);
}

Here, I want to say that any candidate 0,1,2,3 will have a destination alv among the 10 locations 0,..9. Or a dummy destination 10 otherwise

Reversely, for any destination 0,..9, I will store in can the chosen candidate , that will be between 0 and 3 except if no candidate is chosen for this destination and in this case, the can variable is set to 4.

This seems compatible to me with the documentation :

if the length of the array f is n, and the length of the array invf is m, then the inverse constraint guarantees that:

• for all i in the interval [0,n-1], if f[i] is in [0,m-1], then invf[f[i]]==i;

• for all j in the interval [0,m-1], if invf[j] is in [0,n-1], then f[invf[j]]==j.

However, the program runs with no solution.

Do I miss something here ?

David

• Paul Shaw
8 Posts

#### Re: question on inverse

‏2014-02-24T09:19:22Z

This is an error in the documentation.  In fact, it is always the case that f[invf[i]] == i, which forces m == n too.  To get what you want you can create arrays of size n+m and create m escape values on one side and n escape values on the other side.  Each real value will have an appropriate escape value, and we add some constraints to ensure that the escape values are used in order (to break unless symmetries between escape values).

Here is the resulting model:

using CP;

int nRalveoles = 10;
int nCandidats = 4;

range rcandidats = 0 .. nCandidats-1;
range ralveoles = 0 .. nRalveoles-1;
range R = 0..(nRalveoles + nCandidats)-1;

dvar int alv[R] in R;
dvar int can[R] in R;

constraints {
forall (i in rcandidats)
alv[i] in asSet(ralveoles) union {i + nRalveoles};
forall (i in ralveoles)
can[i] in asSet(rcandidats) union {i + nCandidats};

forall (i in R : i >= nCandidats + 1)
alv[i] < nRalveoles || alv[i] > max(j in nCandidats..i-1) alv[j];
forall (i in R : i >= nRalveoles + 1)
can[i] < nCandidats || can[i] > max(j in nRalveoles..i-1) can[j];

inverse(alv, can);
}

Regards,

Paul

• Paul Shaw
8 Posts

#### Re: question on inverse

‏2014-02-24T09:19:22Z

This is an error in the documentation.  In fact, it is always the case that f[invf[i]] == i, which forces m == n too.  To get what you want you can create arrays of size n+m and create m escape values on one side and n escape values on the other side.  Each real value will have an appropriate escape value, and we add some constraints to ensure that the escape values are used in order (to break unless symmetries between escape values).

Here is the resulting model:

using CP;

int nRalveoles = 10;
int nCandidats = 4;

range rcandidats = 0 .. nCandidats-1;
range ralveoles = 0 .. nRalveoles-1;
range R = 0..(nRalveoles + nCandidats)-1;

dvar int alv[R] in R;
dvar int can[R] in R;

constraints {
forall (i in rcandidats)
alv[i] in asSet(ralveoles) union {i + nRalveoles};
forall (i in ralveoles)
can[i] in asSet(rcandidats) union {i + nCandidats};

forall (i in R : i >= nCandidats + 1)
alv[i] < nRalveoles || alv[i] > max(j in nCandidats..i-1) alv[j];
forall (i in R : i >= nRalveoles + 1)
can[i] < nCandidats || can[i] > max(j in nRalveoles..i-1) can[j];

inverse(alv, can);
}

Regards,

Paul

• davidoff
51 Posts

#### Re: question on inverse

‏2014-02-26T22:34:26Z
• Paul Shaw
• ‏2014-02-24T09:19:22Z

This is an error in the documentation.  In fact, it is always the case that f[invf[i]] == i, which forces m == n too.  To get what you want you can create arrays of size n+m and create m escape values on one side and n escape values on the other side.  Each real value will have an appropriate escape value, and we add some constraints to ensure that the escape values are used in order (to break unless symmetries between escape values).

Here is the resulting model:

using CP;

int nRalveoles = 10;
int nCandidats = 4;

range rcandidats = 0 .. nCandidats-1;
range ralveoles = 0 .. nRalveoles-1;
range R = 0..(nRalveoles + nCandidats)-1;

dvar int alv[R] in R;
dvar int can[R] in R;

constraints {
forall (i in rcandidats)
alv[i] in asSet(ralveoles) union {i + nRalveoles};
forall (i in ralveoles)
can[i] in asSet(rcandidats) union {i + nCandidats};

forall (i in R : i >= nCandidats + 1)
alv[i] < nRalveoles || alv[i] > max(j in nCandidats..i-1) alv[j];
forall (i in R : i >= nRalveoles + 1)
can[i] < nCandidats || can[i] > max(j in nRalveoles..i-1) can[j];

inverse(alv, can);
}

Regards,

Paul

Thanks Paul, it works fine.

David