BYU-PRISM / GEKKO

GEKKO Python for Machine Learning and Dynamic Optimization
https://machinelearning.byu.edu
Other
573 stars 102 forks source link

APM model error: string > 15000 characters #93

Closed akhilbhat060890 closed 3 years ago

akhilbhat060890 commented 3 years ago

Hi Guys,

I have an equation that I am trying to optimize. The issue is the equation contains multiple data frames that are multiplied with some parameters and then all of them are summed together. example below : m.Obj(-(b1 + 2.10m.log(s1(1+opt[0])+c1) + 1.60(s2(1+opt[1])+c2) + 2.40m.sqrt(s3(1+opt[2])+c3) )

s1,s2...c1,c2 are all dataframes and opt is an array of parameters that need to be optimised

When I am running the code it throws an error APM model error: string > 15000 characters Can you please let me know as to how I can solve this issue. I can't go to another optimisation library at this point.

Thanks,

APMonitor commented 3 years ago

You'll need to add each objective part separately instead of all at once. You can add all of the dataframe values with something like:

for i in range(len(s1)):
   m.Maximize(b1 + 2.10*m.log(s1.values[i]*(1+opt[0])+c1.values[i]) \
                   + 1.60*(s2.values[i]*(1+opt[1])+c2.values[i]) \
                   + 2.40*m.sqrt(s3.values[i]*(1+opt[2])+c3.values[i])

We'll be able to give more specific help if you can post a minimal, reproducible example to Stack Overflow with tag gekko.

akhilbhat060890 commented 3 years ago

Thank You for the prompt reply.

I have however a constraint equation in addition to the objective function I mentioned above

So I have the objective function set up like:

objectivefunction

m.Obj(-(b1 + 2.10m.log(s1(1+opt[0])+c1) + 1.60(s2*(1+opt[1])+c2) + 2.40m.sqrt(s3(1+opt[2])+c3) )

Constraints on objective Problem

m.Equation((s1(1+opt[0])+s2(1+opt[1])+s3(1+opt[2])+s4(1+opt[3])+s5(1+opt[4])+s6(1+opt[5])).sum()== t)

I tried the approach suggested by you and the optimisation runs but it is providing 0 as the optimal solution which shouldn't be the case. Please let me know if this makes sense or else I will put in data as well.

Thanks, Akhil

APMonitor commented 3 years ago

Try the m.sum() function instead. It avoids the equation length issue when constructing the expression for automatic differentiation.

m.Equation(m.sum(s1.values*(1+opt[0])+s2.values*(1+opt[1])\
                             +s3.values*(1+opt[2])+s4.values*(1+opt[3])\
                             +s5.values*(1+opt[4])+s6.values*(1+opt[5]))== t)

This only works if s1-s6 are constant numerical values. If they are also Gekko variables then I'll give you some other suggestions.

akhilbhat060890 commented 3 years ago

Thank You for your response. Yes s1-s6 & c1-c6 are lists with numerical values and are not Gekko variables. s1-s2 and c1-c6 are non-negative. t =1053200. In future there will be s1-s20 and similarly c1-c20 and t will vary as well. The equation could also change depending on number of variables.

Having said that now when I run the two pieces of code: I either get an infinity as objective or no solution or an error

m.Equation(m.sum(s1.values*(1+opt[0])+s2.values*(1+opt[1])\ +s3.values*(1+opt[2])+s4.values*(1+opt[3])\ +s5.values*(1+opt[4])+s6.values*(1+opt[5]))== t) ``for i in range(len(s1)): m.Obj(-(b1 + 2.10m.log(s1.values[i](1+opt[0])+c1.values[i] +1) \

Data.xlsx

APMonitor commented 3 years ago

You can automate the equation by creating lists and intermediates:

s = [s1,s2,s3,s4,s5,s6]
c = [c1,c2,c3,c4,c5,c6]
e = [m.Intermediate(s[i]*(1+opt[i]) for i in range(len(s))]
m.Equation(m.sum(e)==t)

The error in the solution is because of terms in your objective function such as m.log() and m.sqrt() that have negative values inside the parenthesis. I recommend that you add constraints with the new variable positive to prevent the negative values such as:

positive = m.Array(m.Var,len(s1),lb=1e-4)
for i in range(len(s1)):
   m.Equation(positive[i] == s1.values[i]*(1+opt[0])+c1.values[i] +1) 
                               \ + 1.60*(s2.values[i]*(1+opt[1])+c2.values[i])
                               \ + 2.40*m.sqrt(s3.values[i]*(1+opt[2])+c3.values[i]))
   m.Maximize(b1 + 2.10*m.log(positive[i]))

You can convert the m.Obj(-()) to m.Maximize() because the negative of minimize is a maximize. This may also be causing your large objective function value because it will try to make it infinity. You can prevent this by adding constraints to your opt variables with opt = m.Array(m.Var,6,lb=0,ub=10).

Please consider posting your complete problem to Stack Overflow.

akhilbhat060890 commented 3 years ago

Thank You for the comments and all the help. I will post the problem on Stack Overflow if I face any more challenges.