I am trying to solve a nonlinear optimization problem with GEKKO Python. I know that I can pass my own function to an Intermediate or Objective function, but since my intermediate is a piecewise function, I need if-statements.
For example:
def calc_weighted_average(values, characteristic):
# values are the model's variables that are changed by GEKKO.
# characteristic are always the same (they are a constant list I've defined).
sum = 0
for i in range(values):
sum += values[i] * characteristic[i]
return sum / m.sum(values)
weighted_average_density = m.Intermediate(calc_weighted_average(values, density_list))
def calc_weighted_average(values, characteristic):
# values are the model's variables that are changed by GEKKO.
# characteristic are always the same (they are a constant list I've defined).
sum = 0
for i in range(values):
sum += values[i] * characteristic[i]
# Correction factor when too large
if sum > 5:
correction_factor = (sum - 5) * (0.984 ** 2)
else:
correction_factor = 0
return (sum / m.sum(values)) - correction_factor
weighted_average_density = m.Intermediate(calc_weighted_average(values, density_list))
Try the m.if3()
function. Instead of:
if sum > 5:
correction_factor = (sum - 5) * (0.984 ** 2)
else:
correction_factor = 0
try the following code:
correction_factor = m.if3(sum-5,0,(sum-5)*(0.984**2))
The m.if2()
function is also available as a logical condition with a Mathematical Program with Complementary Constraints (MPCC). The m.if3()
function uses a binary variable instead and generally performs better, but can slow down with many binary variables for large scale problems.