I am studying how to solve one problem with pre-defined variables. For example, variable "x" must be one of the values below.
[2, 5, 6, 13] But, I don't know how to modify my codes.
The original code is as belows.
from gekko import GEKKO
m = GEKKO(remote=False)
x = m.Array(m.Var,9,lb=0,ub=7,integer=True)
def f(x):
return (481.79/(5+x[0]))+(412.04/(4+x[1]))\
+(365.54/(3+x[2]))+(375.88/(3+x[3]))\
+(379.75/(3+x[4]))+(632.92/(5+x[5]))\
+(127.89/(1+x[6]))+(835.71/(6+x[7]))\
+(200.21/(1+x[8]))
m.Minimize(f(x))
m.Equation(sum(x)==7)
m.options.SOLVER=1
m.solve()
print(x)
I modify it as follows, but error message shows " TypeError: GEKKO.Array() takes 3 positional arguments but 4 were given ".
from gekko import GEKKO
m = GEKKO(remote=False)
x = m.Array(m.Var,9,[2, 5, 6, 13])
def f(x):
return (481.79/(5+x[0]))+(412.04/(4+x[1]))\
+(365.54/(3+x[2]))+(375.88/(3+x[3]))\
+(379.75/(3+x[4]))+(632.92/(5+x[5]))\
+(127.89/(1+x[6]))+(835.71/(6+x[7]))\
+(200.21/(1+x[8]))
m.Minimize(f(x))
m.Equation(sum(x)==7)
m.options.SOLVER=1
m.solve()
print(x)
-
1could you post the complete traceback? In the first code you are passing 5 parameters to m.Array(), in the second code you are passing 3 parameters, so the error about 4 parameters doesn't really seem to match any of the codes you posted. So please post the complete traceback of the error, properly formatted, so we can see what is exactly causing the error.Cincinnatus– Cincinnatus2025年01月09日 09:27:26 +00:00Commented Jan 9, 2025 at 9:27
-
@Cincinnatus In the first example, 5 arguments are passed, but 2 positional. In the second example, 3 arguments are passed, all positional. The self is then counted additional in the error description as well. This is normal Python behavior.colidyre– colidyre2025年01月09日 09:53:27 +00:00Commented Jan 9, 2025 at 9:53
2 Answers 2
The error shows that you're using the Array(self, f, dim, **args) with 3 positional arguments (in Python self is counted as well in the error description, but it should not be used if you're having an instance of this class).
So by using x = m.Array(m.Var,9,[2, 5, 6, 13]), you have following positional arguments:
self(counted, but correctly not used)m.Var9[2, 5, 6, 13]
Then, Python wants to distribute arguments m.Var, 9 and [2, 5, 6, 13] to f and dim parameter, i.e. passing 3 arguments to 2 parameters. That's why you're getting this error. The **args parameter means that you can add further keyword arguments, but not more positional ones.
Otherwise it is unclear what you mean by more or less saying: variable "x" must be one of the values [2, 5, 6, 13]? x is an resulting array with multiple values. It cannot be mapped to single values like 2 or 5 etc.
See here for some examples how to use Arrays in Gekko:
Comments
Use the Special Ordered Set m.sos1() type to select from a set of values.
m.sos1([2,5,6,13])
Here is a complete version:
from gekko import GEKKO
def f(x):
return (481.79/(5+x[0]))+(412.04/(4+x[1]))\
+(365.54/(3+x[2]))+(375.88/(3+x[3]))\
+(379.75/(3+x[4]))+(632.92/(5+x[5]))\
+(127.89/(1+x[6]))+(835.71/(6+x[7]))\
+(200.21/(1+x[8]))
m = GEKKO(remote=False)
x = [None]*9
for i in range(len(x)):
x[i] = m.sos1([2,5,6,13])
m.Minimize(f(x))
m.Equation(sum(x)==27)
m.solve()
print(x)
There is no feasible solution when m.Equation(sum(x)==7) because x has an array size of 9 with the minimum value of 2 for each. The minimum summation is therefore 18 for a feasible solution. With m.Equation(sum(x)==27) as an example, there is a feasible solution:
Iter: 132 I: -1 Tm: 0.00 NLPi: 1 Dpth: 6 Lvs: 74 Obj: 5.71E+02 Gap: 1.02E-02
Iter: 133 I: 0 Tm: 0.00 NLPi: 7 Dpth: 6 Lvs: 73 Obj: 5.80E+02 Gap: 1.02E-02
--Integer Solution: 5.76E+02 Lowest Leaf: 5.71E+02 Gap: 8.43E-03
Iter: 134 I: 0 Tm: 0.00 NLPi: 3 Dpth: 6 Lvs: 73 Obj: 5.76E+02 Gap: 8.43E-03
Successful solution
---------------------------------------------------
Solver : APOPT (v1.0)
Solution time : 0.384400000002643 sec
Objective : 575.642338744589
Successful solution
---------------------------------------------------
[[2.0],[2.0],[2.0],[2.0],[5.0],[2.0],[2.0],[5.0],[5.0]]
The m.sos1() function creates a new binary variable for each option (0,1). For future reference, if you have a continuous integer variable such as [2,3,4,5], it is more efficient to use m.Var(lb=2,ub=5,integer=True) instead of m.sos1([2,3,4,5]).