Furthermore, I tried formulating this way:

i_CA1SH = []for ca1sh in CA1SH:    for i in ca1sh.teams:        i_CA1SH.append((i,ca1sh))di_CA1SH = grb_model.addVars(i_CA1SH)for ca1sh in CA1SH:    for i in ca1sh.teams:        grb_model.addConstr(minimumg == (k_RR - quicksum(x_ijsg[i,j,s] for s in ca1sh.slots for j in team_ids if i != j)), name="Min")        grb_model.addConstr(maximumg == (quicksum(x_ijsg[i,j,s] for s in ca1sh.slots for j in team_ids if i != j) - k_RR), name="Max")        grb_model.addConstr(max_valg == max_([minimumg, maximumg], constant=0), name="max")        di_CA1SH[i,ca1sh] = max_valgconstraint_413 = grb_model.addConstrs((quicksum(x[i,j,k] for j in team_ids for k in ca1sh.slots if i != j) - ca1sh.max <= di_CA1SH[i,ca1sh] for ca1sh in CA1SH for i in ca1sh.teams), "Constraint 4.13")

But I am still getting an infeasible solution.

• Gurobi Staff

The Knowledge Base article How do I determine why my model is infeasible? should be helpful here.

Hi. Thanks for this.

About a particular question I asked in the first post, how can I determine hard and soft constraints?

Oleg

• Gurobi Staff

I am no expert on hard/soft constraints but I think that one way to model soft constraints is to add an additional free so-called slack variable (sometimes also called violation variable) which captures the violation of the constraint and add it with a penalty coefficient to the objective function. If in the optimal solution, this additional variable is positive, you know that the soft constraint is violated and you know by how much.

How would you instantiate such slack variables?

Thanks
Oleg

• Gurobi Staff

Hi Oleg,

You define such variables just as normal optimization variables

slack = dev_model.addVars(I,J,K,name="slack")

and then use those in your soft constraints.

Don't forget to add a penalty for those slack in your objective. In case that you are minimizing, this could be something like $$\texttt{10e3 * slack[i,j,k]}$$.

Best regards,
Jaromił

Hi.

How would I assign a slack variable to a constraint?

Thanks

• Gurobi Staff

You have to add the slack variable to the constraint, e.g.,

x[4,0,5] + x[4,1,5] + x[4,2,5] + x[4,3,5] + x[4,5,5] - slack <= 1

You can see that if the $$\texttt{x}$$ variables actually add up to $$>1$$, the slack variable can compensate it.

Depending on the sign of your inequality, you have to either add or subtract a slack variable to catch the violation of the given constraint. For an equality constraint, you will require 2 slack variables and add one and subtract the other.

So it would be along the lines of this:

i_CA1SH = []
for ca1sh in CA1SH:
for i in ca1sh.teams:
i_CA1SH.append((i,ca1sh))
for ca1sh in CA1SH:
for i in ca1sh.teams:
grb_model.addConstr(minimumg == (k_RR - quicksum(x_ijsg[i,j,s] for s in ca1sh.slots for j in team_ids if i != j)), name="Min")
grb_model.addConstr(maximumg == (quicksum(x_ijsg[i,j,s] for s in ca1sh.slots for j in team_ids if i != j) - k_RR), name="Max")
grb_model.addConstr(max_valg == max_([minimumg, maximumg], constant=0), name="max")
di_CA1SH[i,ca1sh] = max_valg
constraint_413 = grb_model.addConstrs((quicksum(x[i,j,k] for j in team_ids for k in ca1sh.slots if i != j) - di_CA1SH[i,ca1sh] <= ca1sh.max for ca1sh in CA1SH for i in ca1sh.teams), "Constraint 4.13")

di_CA1Sh is the slack variable in this case

Also, can I assign values as I did here?

• Gurobi Staff

This will not work. $$\texttt{di_CA1SH}$$ is an optimization variable and you cannot just assign some value to it. It has to be used in a constraint.

grb_model.addConstr(max_valg + di_CA1SH_plus[i,ca1sh] - di_CA1SH_minus[i,ca1sh] == max_([minimumg, maximumg], constant=0), name="max")

Note that I used 2  $$\texttt{di_CA1SH}$$ variables as slacks, because the above is an equality constraint.

When doing what you suggested, it is giving me the following error:

Any ideas?

• Gurobi Staff

Right, that one is on me.

You will have to introduce an additional auxiliary variable because general constraint are limited to exactly one single variable in an equality constraint.

max_valg_aux = grb_model.addVar() # defined with the same properties as max_valggrb_model.addConstr(max_valg_aux == max_([minimumg, maximumg], constant=0), name="max")grb_model.addConstr(max_valg + di_CA1SH_plus[i,ca1sh] - di_CA1SH_minus[i,ca1sh] == max_valg_aux, name="max_aux")

Hi again.

Upon inspection, I noticed that the model is being infeasible because of the following constraints:

grb_model.addConstr((ca1sh.min - quicksum(x[i,j,s] for s in ca1sh.slots for j in team_ids if i != j)) == minimumg, name="Min")grb_model.addConstr((quicksum(x[i,j,s] for s in ca1sh.slots for j in team_ids if i != j) - ca1sh.max) == maximumg, name="Max")

Somehow they are being added to the final solution while I just want them to be temporary so that I can get a value that I will pass to the max_ function. minimumg and maximumg are not being added to the objective function

Any ideas?

• Gurobi Staff

Hi Oleg,

How did you define the variables $$\texttt{maximumg, minimumg}$$? You have to make sure that these are free variables.

maximumg = grb_model.addVar(lb=-GRB.INFINITY, name="maximumg")minimumg = grb_model.addVar(lb=-GRB.INFINITY, name="minimumg")

Best regards,
Jaromił

Hi after doing what you suggested, it is still giving me the same issue when looking at the ilp file

I have added a GitHub link so that you can access the code: https://github.com/oleggrech7/Sports_Scheduling

• Gurobi Staff

You need a different minimumg, maximumg variable for each constraint. Otherwise, you are forcing all equality constraints holding minimumg or maximumg to the same value. This means that you will have to introduce multiple minimumg and maximumg variables, namely one for each equality constraint of interest.

Hi.

Thank you for the suggestion. But I am still getting that the model is infeasible.

Here is my updated code with another constraint:

# Constraints 4.13max_valCA1SH = grb_model.addVar(lb=-GRB.INFINITY, name="max_valCA1SH")minimumCA1SH = grb_model.addVar(lb=-GRB.INFINITY, name="minimumCA1SH")maximumCA1SH = grb_model.addVar(lb=-GRB.INFINITY, name="maximumCA1SH")i_CA1SH = []for ca1sh in CA1SH:    for i in ca1sh.teams:        i_CA1SH.append((i,ca1sh))di_CA1SH = grb_model.addVars(i_CA1SH)for ca1sh in CA1SH:    for i in ca1sh.teams:        grb_model.addConstr(minimumCA1SH == (ca1sh.min - quicksum(x[i,j,s] for s in ca1sh.slots for j in team_ids if i != j)), name="Min")        grb_model.addConstr(maximumCA1SH == (quicksum(x[i,j,s] for s in ca1sh.slots for j in team_ids if i != j) - ca1sh.max), name="Max")        grb_model.addConstr(max_valCA1SH == max_([minimumCA1SH, maximumCA1SH], constant=0), name="max")        grb_model.addConstr(di_CA1SH[i,ca1sh] == max_valCA1SH, name="max_aux")constraint_413 = grb_model.addConstrs((quicksum(x[i,j,k] for j in team_ids for k in ca1sh.slots if i != j) - ca1sh.max <= di_CA1SH[i,ca1sh] for ca1sh in CA1SH for i in ca1sh.teams), "Constraint 4.13")
# Constraint 4.14max_valCA1SA = grb_model.addVar(lb=-GRB.INFINITY, name="max_valCA1SA")minimumCA1SA = grb_model.addVar(lb=-GRB.INFINITY, name="minimumCA1SA")maximumCA1SA = grb_model.addVar(lb=-GRB.INFINITY, name="maximumCA1SA")i_CA1SA = []for ca1sa in CA1SA:    for i in ca1sa.teams:        i_CA1SA.append((i,ca1sa))di_CA1SA = grb_model.addVars(i_CA1SA)for ca1sa in CA1SA:    for i in ca1sa.teams:        grb_model.addConstr(minimumCA1SA == (ca1sa.min - quicksum(x[i,j,s] for s in ca1sa.slots for j in team_ids if i != j)), name="Min")        grb_model.addConstr(maximumCA1SA == (quicksum(x[i,j,s] for s in ca1sa.slots for j in team_ids if i != j) - ca1sa.max), name="Max")        grb_model.addConstr(max_valCA1SA == max_([minimumCA1SA, maximumCA1SA], constant=0), name="max")        grb_model.addConstr(di_CA1SA[i,ca1sa] == max_valCA1SA, name="max_aux")constraint_414 = grb_model.addConstrs((quicksum(x[j,i,k] for j in team_ids for k in ca1sa.slots if i != j) - ca1sa.max <= di_CA1SA[i,ca1sa] for ca1sa in CA1SA for i in ca1sa.teams), "Constraint 4.14")

Any idea?

The code is updated on Git aswell.

• Gurobi Staff

In the LP file Schedule.lp in your github, you are still using the same maximumCA1SH and minimumCA1SH variable for every equality constraint. As mentioned before, you have to introduce multiple of these variable, namely one for each equality constraint.

Hi.

Thanks for your help! Worked like a charm. Wish I knew this beforehand.