Search code examples
pythonmathematical-optimizationgekko

Python GEKKO using function in model with if-statement


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:

This works from what I've tested.

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))

This doesn't work and I am not sure how to get this to work?

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))

Solution

  • 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.