2

I'm trying to implement conditional logic in Gekko using "if3" but am unsure how to successfully layer 2 conditions at different levels of granularity.

"x1" is vector of binary values (0/1) that controls when an alternative rhs value should be used on element i to constrain x2 and x3.

"x2" is a vector of floats where I want to make the lower and upper bounds dynamic for element i based on the binary values in "x1" above. If the value for x1 for element i is = 1, I want to use "window_lnuc_min_promo_price" (vector of same length) as the lower bound and "window_lnuc_max_promo_price" as the upper bound. If the value for x1 for element i is = 0, I want to use "min_promo_price" as the lower bound and "max_promo_price" as the upper bound.

Similarly, "x3" is a vector of floats where I want to apply the same logic but just to the lower bound using values from "window_lnuc" when element i in x1 is = 1 and values from "lnuc" when it is = 0.

Lastly, I want to limit how many times X1 can be = 1 (4 in the example below). This would mean the alternative values are limited to 4 occurrences in total.

The problem I think I'm having is that because x1 is a variable with a 0-1 range, the optimizer is changing the default "0" values in "lnuc_weeks" (which I don't want it to do). I want the optimizer to basically keep anything that is 0 in "lnuc_weeks" as is and only select a maximum of 4 values from the elements in "lnuc_weeks" that are = 1 initially.

There is probably a better way to write this, but any help/feedback is appreciated. The full solution is a bit long to display for reproducibility of output, but hopefully the above/below sufficiently describe the problem.

x1 = m.Array(m.Var,(n), integer=True) #LNUC weeks

i = 0
for xi in x1:
    xi.value = lnuc_weeks[i]
    xi.lower = 0
    xi.upper = 1
    i += 1

x2 = m.Array(m.Var,(n)) #Blended SRP

i = 0
for xi in x2:
    xi.value = blended_srp[i]
    xi.lower = m.if3((x1[i]) - 1, min_promo_price[i], window_lnuc_min_promo_price[i])
    xi.upper = m.if3((x1[i]) - 1, max_promo_price[i], window_lnuc_max_promo_price[i])
    i += 1

x3 = m.Array(m.Var,(n)) #Blended NUC

i = 0
for xi in x3:
    xi.value = blended_nuc[i]
    xi.lower = m.if3((x1[i]) - 1, lnuc[i], window_lnuc[i])
    xi.upper = 10
    i += 1


#Limit max lnuc weeks
m.Equation(sum(x1)<=4)

1 Answer 1

1

The .lower and .upper bounds are defined when the model is initialized and do not change to reflect newly optimized values. To implement these, use an inequality expression. Use a switching point of 0.5 instead of 1 to avoid numerical issues with an integer value >1 or >=1. The solver tolerance is 1e-6 by default so a value of 0.999999 is considered the same as 1.000001 for convergence of equations.

i = 0
for xi in x2:
    xi.value = blended_srp[i]
    m.Equation(xi >= m.if3((x1[i]) - 0.5, min_promo_price[i], window_lnuc_min_promo_price[i]))
    m.Equation(xi <= m.if3((x1[i]) - 0.5, max_promo_price[i], window_lnuc_max_promo_price[i]))
    i += 1

and

i = 0
for xi in x3:
    xi.value = blended_nuc[i]
    m.Equation(xi >= m.if3((x1[i]) - 0.5, lnuc[i], window_lnuc[i]))
    xi.upper = 10
    i += 1

The select of any four elements with m.Equation(sum(x1)<=4) is correct.

Sign up to request clarification or add additional context in comments.

1 Comment

Awesome, works as expected!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.