How can I normalize a variable?
AnsweredHow can I normalize a variable added as a constraint that is been updated by the model? I need to have all values in the dictionary to be normalized at each update.
model = gp.Model('name')
Var = m.addVars(len(A), vtype=GRB.CONTINUOUS, name='var')
for i in range(len(A)):
m.addConstr(gp.quicksum(compute_value(A[i],B[j]) for j in range(len(B)) == Var[i], name=f'var_{i}')
so when having the filled dictionary I want it before to get into the objective to be normalized, that is each value Var[i] should be reassigned as (Var[i]Var_min)/(Var_maxVar_min) where Var_min is the lowest value in the Var dictionary and Var_max is the maximum value.
How can I do this?
P.S. I'm new to Gurobi
And thank you.

Hi WI,
Since \(\texttt{Var_min}\) and \(\texttt{Var_max}\) are variables in your model, normalizing the decision variables as \((\texttt{Var[i]}  \texttt{Var_min})/(\texttt{Var_max}  \texttt{Var_min})\) will make the problem nonlinear. Do you really need to do this? Have you considered defining your decision variables to be between 0 and 1 right from the start? For example, instead of decision variable to represent the amount of money invested in each asset, you can define them to represent the fraction of the total budget invested in each asset. This way, you do not need to map the decision variables to values between 0 and 1.
What the decision variables and the objective function represent in your model in English?
Best regards,
Maliheh
0 
Hi Maliheh,
The decision variables in the objective function are a binary type (0 or 1), and the variable Var is a Euclidean distance between points in a graph that has the x and yaxis bounded between 0 and 1.0 
Hi WI,
Thanks for the response. Sure, I get that your decision variables represent the Euclidean distance between pairs of points (let us refer to them as \(x\) for simplicity) on a grid of 1 by 1 with lower and upper bounds 0 and \(\sqrt{2}\). And there are binary decision variables in the objective function. However, I am still not clear why you want to normalize the variables \(x\) in the objective function and how they are connected to the binary decision variables.
Anyways, assuming \(x_{\tiny \mbox{min}}\) and \(x_{\tiny \mbox{max}}\) are decision variables and are not the lower and upper bounds of the variables \(x\), you need to do the following:
 Define a new continuous variable \(x_{\tiny \mbox{min}}\) and then use the Gurobi min_() general constraint helper API to define \(x_{\tiny \mbox{min}} = \min_{i} x_i \)
 Define a new continuous variable \(x_{\tiny \mbox{max}}\) and then use the Gurobi max_() general constraint helper API to define \(x_{\tiny \mbox{max}} = \max_{i} x_i \)
 Define new continuous variables \(y\) between 0 and 1 and then use the Model.addQConstr() method to model \(y_i (x_{\tiny \mbox{max}}  x_{\tiny \mbox{min}}) = x_i x_{\tiny \mbox{min}}\) for all \(i\). This will make your problem nonconvex and you would need to use NonConvex=2 setting to solve the problem
Best regards,
Maliheh
1 
So I should proceed as:
model = gp.Model('name')
Var = m.addVars(len(A), vtype=GRB.CONTINUOUS, name='var')
xmin=m.addVars(1, vtype=GRB.CONTINUOUS, name='xmin')
xmax=m.addVars(1, vtype=GRB.CONTINUOUS, name='xmax')
y=m.addVars(len(A),ub=1, vtype=GRB.CONTINUOUS, name='xmin')
for i in range(len(A)):
m.addConstr(gp.quicksum(compute_value(A[i],B[j]) for j in range(len(B)) == Var[i], name=f'var_{i}')
xmin=min(Var)
xmax=min(Var)
m.addQConstr(y[i]=x[i]xmin/(xmaxxmin) for i in Var)then I utilize y in the objective function instead of Var, then:
m.params.NonConvex=2
m.optimize()Is that right?
And thank you for your help.0 
Hi WI,
You need a few changes. Please see below.
import gurobipy as gp
from gurobipy import GRB
from math import sqrt
if __name__ == "__main__":
model = gp.Model("name")
Var = model.addVars(len(A), lb=0, ub=sqrt(2), vtype=GRB.CONTINUOUS, name="var")
xmin = model.addVar(lb=0, ub=sqrt(2), vtype=GRB.CONTINUOUS, name="xmin")
xmax = model.addVar(lb=0, ub=sqrt(2), vtype=GRB.CONTINUOUS, name="xmax")
y = model.addVars(len(A), lb=0, ub=1, vtype=GRB.CONTINUOUS, name="y")
model.addConstr(xmin == gp.min_(Var), name="min") # [*]
model.addConstr(xmax == gp.max_(Var), name="max") # [*]
for i in range(len(A)):
model.addConstr(
gp.quicksum(compute_value(A[i], B[j]) forjinrange(len(B))) == Var[i],
name=f"var_{i}",
)
model.addQConstr(y[i] * (xmax  xmin) == Var[i]  xmin, name=f"normalize_{i}"# [*]: EditedBest regards,Maliheh1 
Thank you Maliheh
When runing the code it raises an error:
TypeError: unsupported operand type(s) for : 'GenExprMax' and 'GenExprMin'
at this line:m.addQConstr(y[i]*(xmax  xmin) == h[i]  xmin, name=f"normalize_{i}")
Any idea how to fix it?0 
Hi WI,
The error means that the subtraction is not supported for the general expressions, i.e., we cannot subtract \(x_{\small\mbox{min}}\) from \(x_{\small\mbox{max}}\). We likely need additional auxiliary variables to model this.
Could you please post the snippet that you are running such that I can reproduce the error? If the snippet is too long, you can share the file using Dropbox, Google Drive, or OneDrive.
Best regards,
Maliheh
0 
This code generates the same error:
A=[0,4,3,2,8]
B=[7,9,4,5,2]
model = gp.Model("name")
Var = model.addVars(5, lb=0, ub=sqrt(2), vtype=GRB.CONTINUOUS, name="var")
xmin = model.addVar(lb=0, ub=sqrt(2), vtype=GRB.CONTINUOUS, name="xmin")
xmax = model.addVar(lb=0, ub=sqrt(2), vtype=GRB.CONTINUOUS, name="xmax")
y = model.addVars(5, lb=0, ub=1, vtype=GRB.CONTINUOUS, name="y")
xmin = gp.min_(Var)
xmax = gp.max_(Var)
for i in range(5):
model.addConstr(gp.quicksum(A[i]*B[j] for j in range(5)) == Var[i], name=f"var_{i}")
model.addQConstr(y[i] * (xmax  xmin) == Var[i]  xmin, name=f"normalize_{i}")And thank you for your comprehension
0 
Hi WI,
Please see the snippet edited above. Specifically, below needs to change from:
xmin = gp.min_(Var)
xmax = gp.max_(Var)to:
model.addConstr(xmin == gp.min_(Var), name="min")
model.addConstr(xmax == gp.max_(Var), name="max")Your snippet should build the model without the previous error now.
Best regards,
Maliheh
0 
Thank you very much Maliheh.
0
Please sign in to leave a comment.
Comments
10 comments