-
Notifications
You must be signed in to change notification settings - Fork 10
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Added instance generator for KEP #224
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That Looks good for me!
# ensure that all pairs have at least one in edge and one out edge | ||
indexes = [(i,j) for i = 1:nb_nodes for j = 1:nb_nodes] | ||
permutation = shuffle([i for i=1:nb_nodes]) # permutation[i] = j => x[i, j] is branchable | ||
flat_index_required_branchable = [permutation[i] + (i-1)*nb_nodes for i in 1:nb_nodes] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can you briefly explain this ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That transform the permutation [2, 1, 3] such that : [2, 1, 3] -> [2, 4, 6]
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
alright got it, that's because indexes[i+nb_nodes*j]= (i,j)
? or the contrary ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Your last message is right! The idea is that in first place we assign one branchable variable in each line of the matrix with a different column index each time. permutation
ensures that each column index is different each time. In that way we ensure that all pairs have at least one incoming arc and one outgoing arc.
### Variables ### | ||
x = Matrix{SeaPearl.AbstractIntVar}(undef, nb_nodes, nb_nodes) | ||
minus_x = Matrix{SeaPearl.AbstractIntVar}(undef, nb_nodes, nb_nodes) | ||
|
||
for i = 1:nb_nodes | ||
for j = 1:nb_nodes | ||
if (i,j) in index_branchable | ||
x[i, j] = SeaPearl.IntVar(0, 1, "x_"*string(i)*"_"*string(j), model.trailer) | ||
SeaPearl.addVariable!(model, x[i, j]; branchable=true) | ||
minus_x[i, j] = SeaPearl.IntVarViewOpposite(x[i, j], "-x_"*string(i)*"_"*string(j)) | ||
else | ||
x[i, j] = SeaPearl.IntVar(0, 0, "x_"*string(i)*"_"*string(j), model.trailer) | ||
SeaPearl.addVariable!(model, x[i, j]; branchable=false) | ||
minus_x[i, j] = SeaPearl.IntVarViewOpposite(x[i, j], "-x_"*string(i)*"_"*string(j)) | ||
end | ||
end | ||
end | ||
|
||
### Constraints ### | ||
for i = 1:nb_nodes | ||
#Check that any pair receives more than 1 kidney | ||
SeaPearl.addConstraint!(model, SeaPearl.SumLessThan(x[i, :], 1, model.trailer)) | ||
|
||
#Check that any pair gives more than 1 kidney | ||
SeaPearl.addConstraint!(model, SeaPearl.SumLessThan(x[:, i], 1, model.trailer)) | ||
|
||
#Check that for each pair: give a kidney <=> receive a kidney | ||
SeaPearl.addConstraint!(model, SeaPearl.SumToZero(hcat(x[:, i], minus_x[i, :]), model.trailer)) | ||
end | ||
|
||
### Objective ### | ||
|
||
#SeaPearl's solver minimize the objective variable, so we use minusNumberOfExchanges in order to maximize the number of exchanges | ||
minusNumberOfExchanges = SeaPearl.IntVar(-nb_nodes, 0, "minusNumberOfExchanges", model.trailer) | ||
SeaPearl.addVariable!(model, minusNumberOfExchanges; branchable=false) | ||
vars = SeaPearl.AbstractIntVar[] | ||
|
||
#Concatenate all values of x and minusNumberOfExchanges | ||
for i in 1:nb_nodes | ||
vars = cat(vars, x[i, :]; dims=1) | ||
end | ||
push!(vars, minusNumberOfExchanges) | ||
|
||
#minusNumberOfExchanges will take the necessary value to compensate the occurences of "1" in x | ||
objective = SeaPearl.SumToZero(vars, model.trailer) | ||
SeaPearl.addConstraint!(model, objective) | ||
SeaPearl.addObjective!(model, minusNumberOfExchanges) | ||
|
||
nothing |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I trust you on the model definition as long as is doesn't differ from what has been previously done !
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have used the same model
|
||
# the remaining edges are assigned randomly between the non-asssigned elements of the decision matrix | ||
nb_unassigned_edges = total_edges - nb_nodes | ||
append!(index_branchable, sample(indexes, nb_unassigned_edges)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
very elegant syntax! The fact that splice!
removes the value at index i
from the array ensures that you cannot append twice the same edge.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks :)
Fill a CPModel with the variables and constraints generated. We fill it directly instead of
creating temporary files for efficiency purpose!
The decision matrix
x
is the adjacent matrix of the graph (i.e. the instance).x[i, j] is branchable => pair i can receive a kidney from pair j
x[i, j] is not branchable => pair i can not receive a kidney from pair j
The generator ensure that all pairs have at least one in edge and one out edge (i.e. one branchable variable per row and column).
For this we first place one branchable variable in each line of the matrix with a different column index each time.
Then, the remaining edges are assigned randomly between the non-asssigned elements of the decision matrix.