'Is there a way to make GEKKO work with pandas?

I'm trying to make GEKKO maximize the function "Profit" but I can't make it work. I always end up with the error below.

I need GEKKO solver to choose the best values for (Weight1, Weight2, Weight3... Weight8) so the "Result" returned by the function "Profit" is the highest possible.

Each Weight can be any value between 0 (0%) and 15 (15%) and the sum of all Weights must be 100 (100%).

All DataFrames are required to calculate the final profit of eack Pick (Pick1, Pick2, Pick3... Pick8) and the Benchmark.

In the end the "Result" is the sum of each Pick's profit minus the Benchmark's profit.

So: Weights are the Variables; Their bounds are from 0 to 15; The constraint is their sum must be 100.

So far I could only find examples of GEKKO Maximizing defined equations. Can it do something like this?

Here is my code:

from gekko import GEKKO
import pandas as pd

m = GEKKO()

Weight1 = m.Var(value=15,lb=0, ub=15)
Weight2 = m.Var(value=15,lb=0, ub=15)
Weight3 = m.Var(value=15,lb=0, ub=15)
Weight4 = m.Var(value=15,lb=0, ub=15)
Weight5 = m.Var(value=15,lb=0, ub=15)
Weight6 = m.Var(value=15,lb=0, ub=15)
Weight7 = m.Var(value=15,lb=0, ub=15)
Weight8 = m.Var(value=15,lb=0, ub=15)

m.Param(Weight1 + Weight2 + Weight3 + Weight4 + Weight5 + Weight6 + Weight7 + Weight8 == 100) #Sum of Weights must be 100%

def Profit(Weight1, Weight2, Weight3, Weight4, Weight5, Weight6, Weight7, Weight8):

    RETURNS  = OPTIMIZATION_TABLE

    PICKS = RETURNS[["picks"]].drop_duplicates()
    PICKS["Weights"] = ""

    PICKS.loc[(PICKS['picks']== "pick2") ,'Weights'] = Weight1/100
    PICKS.loc[(PICKS['picks']== "pick1") ,'Weights'] = Weight2/100
    PICKS.loc[(PICKS['picks']== "pick3") ,'Weights'] = Weight3/100
    PICKS.loc[(PICKS['picks']== "pick4") ,'Weights'] = Weight4/100
    PICKS.loc[(PICKS['picks']== "pick5") ,'Weights'] = Weight5/100
    PICKS.loc[(PICKS['picks']== "pick6") ,'Weights'] = Weight6/100
    PICKS.loc[(PICKS['picks']== "pick7") ,'Weights'] = Weight7/100
    PICKS.loc[(PICKS['picks']== "pick8") ,'Weights'] = Weight8/100

    COMPLETE = pd.merge(RETURNS, PICKS, left_on="picks", right_on="picks", how="left")
    COMPLETE["final_return"] = COMPLETE.Weights * COMPLETE.daily_return

    DATE_GROUP = pd.DataFrame(COMPLETE.groupby(['date'],as_index=False)['final_return'].sum())
    DATE_GROUP = DATE_GROUP.sort_values("final_return", ascending=True)
    DATE_GROUP = DATE_GROUP.reset_index(drop=True)

    BENCHMARK_GROUP = BENCHMARK[["date", "daily_return"]]
    BENCHMARK_GROUP = BENCHMARK_GROUP.sort_values('daily_return', ascending=True)
    BENCHMARK_GROUP = BENCHMARK_GROUP.reset_index(drop=True)

    FINAL_TABLE = pd.merge(BENCHMARK_GROUP, DATE_GROUP, left_index=True, right_index=True)
    FINAL_TABLE["dif"] = FINAL_TABLE.final_return - FINAL_TABLE.daily_return

    Result = sum(FINAL_TABLE.dif)

    return Result

m.Maximize(Profit)

m.solve(disp=True)

And this is what I get in the end:

    --------- APM Model Size ------------
 Each time step contains
   Objects      :            0
   Constants    :            0
   Variables    :            9
   Intermediates:            0
   Connections  :            0
   Equations    :            1
   Residuals    :            1
 
 @error: Model Expression
 *** Error in syntax of function string: Invalid element: <functionsolverat0x000
 001c63000dfc0>
 
Position: 1                   
 <functionsolverat0x000001c63000dfc0>
 ?

Can someome help me, please? Thank you for your time!



Solution 1:[1]

Gekko builds a symbolic form of a model the first time through and then compiles the variables and equations into byte-code with automatic differentiation for the gradient-based solvers. This means that any function call is only used when building the model, not when solving the model.

There are ways to reformulate the model with binary variables for selections. Here is an example of a binary variable.

x = m.Var(lb=0,ub=1,integer=True)

Other logical conditions include if statements such as m.if3(x,0,1) and sos1 (special ordered sets of type-1). The SOS is a combination of binary variables with only one that is allowed to be non-zero. Chose one from a set of possible numeric values that are mutually exclusive options.

from gekko import GEKKO
m = GEKKO()
y = m.sos1([19.05, 25.0, 29.3, 30.2])
m.Obj(y) # select the minimum value
m.solve()
print(y.value)

Numpy, Pandas or other functions that create a symbolic representation of the equation are allowed in Gekko.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 John Hedengren