Linearization of a fuzzy triangular membership function
AnsweredHi everyone,
I am currently stuck trying to linearize the following fuzzy triangular membership function.

I already defined the following variables:
t[i] is a decision variable
mu_e[i], mu_u[i], mu_l[i], ls[i] and rs[i] are all binary variables.
mdl.addConstrs((t[i] >= e[i] - M * (1 - mu_e[i])) for i in N)
mdl.addConstrs((t[i] <= e[i] + M * mu_e[i]) for i in N)
mdl.addConstrs((t[i] >= u[i] - M * (1 - mu_u[i])) for i in N)
mdl.addConstrs((t[i] <= u[i] + M * mu_u[i]) for i in N)
mdl.addConstrs((l[i] >= t[i] - M * (1 - mu_l[i])) for i in N)
mdl.addConstrs((l[i] <= t[i] + M * mu_l[i]) for i in N)
mdl.addConstrs(ls[i] == mu_e[i] + mu_l[i] - 1 for i in N)
mdl.addConstrs(rs[i] == mu_l[i] + mu_u[i] - 1 for i in N)
t[i] is the arrival time (variable), e[i], u[i] and l[i] are the time window bounds.
mu_e[i] represents the lower bound (1, if t[i] >= e[i]), mu_u[i] the midpoint (1, if t[i] >= u[i]) and mu_l[i] the upper bound (1, if t[i] <= l[i]).
ls[i] means the constraints for the lefthand-side are fulfilled, rs[i] indicates the same for the righthand-side.
The only problem I now have is how I can use ls[i] and rs[i] to calculate mu[i]. My code currently looks like this:
mdl.addConstrs(mu[i] == ls[i] * ((t[i] - e[i]) / (u[i] - e[i])) + rs[i] * ((l[i] - t[i]) / (l[i] - u[i]) - (t[i] - e[i]) / (u[i] - e[i])) for i in N)
Do you guys have any suggestions regarding my problem? How can I linearize the calculation of mu[i]?
Thank you very much for your help!
Best regards,
Lars
-
Official comment
This post is more than three years old. Some information may not be up to date. For current information, please check the Gurobi Documentation or Knowledge Base. If you need more help, please create a new post in the community forum, or try Gurobot, our chatbot interface offering instant, expert-level support. -
Hi Lars,
I think you can use Gurobi's piecewise linear feature to implement \(\mu\). We discuss how Gurobi handles piecewise linear (objective) functions in the documentation. There is also a similar post which might be helpful.
Best regards,
Jaromił0 -
Hi Jaromił,
thank you for your response.
I already tried using the piecewise linear function, but for my assignment I need to calculate mu[i] using only elaborated linear functions. So my idea was to use binary auxiliary variables to determine if t[i] lies within the left or the right side of the interval and than use these variables to calculate mu[i].
The only part missing now is linearizing the function that actually calculates mu[i]. Do you have any suggestions how to proceed?
Best regards,
Lars0 -
Hi Lars,
You can model piecewise linear functions by hand as described in How do I model piecewise-linear functions?
The definition of an SOS2 constraint can be found, e.g., here.
Best regards,
Jaromił0 -
Hi Jaromił,
thank you very much for linking the definition of the SOS2 constraints. I finally get the same results as for using the addGenConstrPWL-constraint, so I think the model is working the way I want it to do. My code now looks like this:
t = mdl.addVars(N, vtype=GRB.CONTINUOUS, name='t')
mu = mdl.addVars(N, vtype=GRB.CONTINUOUS, name='mu')
t_1 = mdl.addVars(N, vtype=GRB.CONTINUOUS, name='t_1')
t_2 = mdl.addVars(N, vtype=GRB.CONTINUOUS, name='t_2')
t_3 = mdl.addVars(N, vtype=GRB.CONTINUOUS, name='t_3')
t_4 = mdl.addVars(N, vtype=GRB.CONTINUOUS, name='t_4')
t_5 = mdl.addVars(N, vtype=GRB.CONTINUOUS, name='t_5')
y1 = mdl.addVars(N, vtype=GRB.BINARY, name='y1')
y2 = mdl.addVars(N, vtype=GRB.BINARY, name='y2')
y3 = mdl.addVars(N, vtype=GRB.BINARY, name='y3')
y4 = mdl.addVars(N, vtype=GRB.BINARY, name='y4')
y5 = mdl.addVars(N, vtype=GRB.BINARY, name='y5')
mdl.addConstrs((t[i] == 0 * t_1[i] + e[i] * t_2[i] + u[i] * t_3[i] + l[i] * t_4[i] + 240 * t_5[i]) for i in N)
mdl.addConstrs((t_1[i] + t_2[i] + t_3[i] + t_4[i] + t_5[i] == 1) for i in N)
mdl.addConstrs((mu[i] == 0 * t_1[i] + 0 * t_2[i] + 1 * t_3[i] + 0 * t_4[i] + 0 * t_5[i]) for i in N)
mdl.addConstrs(t_1[i] <= y1[i] for i in N)
mdl.addConstrs(t_2[i] <= y2[i] for i in N)
mdl.addConstrs(t_3[i] <= y3[i] for i in N)
mdl.addConstrs(t_4[i] <= y4[i] for i in N)
mdl.addConstrs(t_5[i] <= y5[i] for i in N)
mdl.addConstrs((y1[i] + y2[i] + y3[i] + y4[i] + y5[i] <= 2) for i in N)
mdl.addConstrs((y1[i] + y3[i] <= 1) for i in N)
mdl.addConstrs((y1[i] + y4[i] <= 1) for i in N)
mdl.addConstrs((y1[i] + y5[i] <= 1) for i in N)
mdl.addConstrs((y2[i] + y4[i] <= 1) for i in N)
mdl.addConstrs((y2[i] + y5[i] <= 1) for i in N)
mdl.addConstrs((y3[i] + y5[i] <= 1) for i in N)Thank you again for your help!
Best regards,
Lars0
Post is closed for comments.
Comments
5 comments