3

I'm trying to apply Gekko to minimize the norm of a vector (well actually the difference between two vectors as shown in the code below). As you can see, I'd also like integer solutions and I'm also constraining a couple of the variables to be bounded above by 0. Here's some test code:

from gekko import GEKKO

M = np.array([[1, 4, 5], 
    [-5, 8, 9]])

b = np.array([1,2])

m = GEKKO(remote=False)

# create variables
x = m.Array(m.Var, M.shape[1], integer = True)
for i in range(M.shape[1]-M.shape[0]):
  x[i].lower = 0
#   #x[i].upper cannot exceed total Q



m.Obj(m.abs(np.subtract(np.matmul(M,x), b)))
m.solve(disp=False)

When I run, I get the following error:

Exception: @error: Equation Definition
---------------------------------------------------------------------------
Exception                                 Traceback (most recent call last)
<command-2749153836142718> in <module>
     17 
     18 m.Obj(m.abs(np.subtract(np.matmul(M,x), b)))
---> 19 m.solve(disp=False)

/local_disk0/.ephemeral_nfs/envs/pythonEnv-303e2ce6-8c7a-44c3-93be-cebc25e4537a/lib/python3.7/site-packages/gekko/gekko.py in solve(self, disp, debug, GUI, **kwargs)
   2128                 print("Error:", errs)
   2129             if (debug >= 1) and record_error:
-> 2130                 raise Exception(apm_error)
   2131 
   2132         else: #solve on APM server

Exception: @error: Equation Definition
 Equation without an equality (=) or inequality (>,<)
 (((((-5)*(int_v1))+((8)*(int_v2)))+((9)*(int_v3)))-2)])
 STOPPING...

Can gekko handle objective functions like this? Is my set up messed up? Any feedback would be much appreciated.

jim
  • 175
  • 8

1 Answers1

1

There are no problem with these types of objectives. The error is that the m.Obj or m.Minimize function needs to have a scalar variable. A loop or m.sum() is needed to add all of the individual objective function terms into one objective.

obj = np.matmul(M,x)-b
for i in range(nr):
    m.Minimize(m.abs3(obj[i]))

I also recommend m.abs3() instead of m.abs() so that there are continuous first and second derivatives for the solver. Here is the full script.

from gekko import GEKKO
import numpy as np

M = np.array([[1, 4, 5], 
    [-5, 8, 9]])
b = np.array([1,2])

nr = np.size(M,0)  # rows
nc = np.size(M,1)  # columns

# create variables
m = GEKKO(remote=False)
x = m.Array(m.Var, nc, integer = True)
for i in range(nc-nr):
  x[i].lower = 0

obj = M@x-b
for i in range(nr):
    m.Minimize(m.abs3(obj[i]))
m.solve(disp=False)

print('Objective: ' + str(m.options.OBJFCNVAL))
for i in range(nc):
    print('x['+str(i)+'] = '+str(x[i].value[0]))

Integer Solution

Objective: 1.0
x[0] = 2.0
x[1] = 16.0
John Hedengren
  • 12,068
  • 1
  • 21
  • 25
  • 1
    thanks, @John Hedengren!.. Worked like a charm. I suppose there may be many feasible solutions that will lead to the same min value for the objective function – jim Nov 04 '20 at 09:38
  • 1
    I'm also not sure minimizing the components of a vector separately will lead to the same result as minimizing the norm.. I may just have to write out the norm formula in its scalar form, which, as you alluded to, would involve including a sum in the formula. Thanks again! – jim Nov 04 '20 at 10:08
  • 1
    Hi John. Could you clarify how the loop combines the objective functions into 1? For me, it looks as though two objective functions are created (corresponding to two rows of the final vector whose norm we want to minimize). I see there is 1 output for the objective value, so I'm curious how m.Minimize(m.abs3(obj[1])) and m.Minimize(m.abs3(obj[2])) are combined into 1 objective function.. Thanks in advance! – jim Nov 05 '20 at 20:27
  • Multiple objectives are combined as a summation. The solver requires that there is a single scalar objective. – John Hedengren Nov 05 '20 at 21:36