Otimização não linear restrita em GEKKO, função objetivo não corresponde à solução esperada

Uma vez

Eu tenho um problema de otimização não linear restrito bastante simples, maximizando a receita, dadas algumas restrições de gastos (manter o gasto geral constante e aumentar / diminuir o gasto em cada canal em até 50%) e uma função de objetivo que é receita = gasto * roi (onde roi é calculado usando os coeficientes do modelo log-log para cada canal).

Em primeiro lugar, a solução não corresponde ao que acredito ser a solução ideal. Além disso, quando pegar os valores de gasto ideais sugeridos por GEKKO e colocá-los na função objetivo, isso também não corresponde ao que GEKKO fornece como o valor de função objetivo ideal.

Se o problema acima não for bem articulado, o código de exemplo abaixo deve trazer à vida o problema ...

Alguém sabe o que estou perdendo?

Código abaixo:

from gekko import GEKKO
import numpy as np
import pandas as pd

df1 = pd.DataFrame({'channel': ['fb', 'tv', 'ppc'],
                    'value': [5000, 5000, 5000],                    
                    'alpha': [1.00, 1.00, 1.00],
                    'beta': [0.03, 0.02, 0.01]
})

total_spend = df1['value'].sum()

m = GEKKO()

# Constraint parameters
spend_inc = 0.00
spend_dec = 0.00
channel_inc = 0.50
channel_dec = 0.50

channels = len(df1)

# Initialise decision variables
x = m.Array(m.Var, (channels), integer=True)
i = 0
for xi in x:
    xi.value = df1['value'][i]
    xi.lower = df1['value'][i] * (1 - channel_dec)
    xi.upper = df1['value'][i] * (1 + channel_inc)
    i += 1

# Initialise alpha
a = m.Array(m.Param, (channels))
i = 0
for ai in a:
    ai.value = df1['alpha'][i]
    i += 1
    
# Initialise beta
b = m.Array(m.Param, (channels))
i = 0
for bi in b:
    bi.value = df1['beta'][i]
    i += 1
    
# Initial global contraints
spend_min = total_spend * (1 - spend_dec)
spend_max = total_spend * (1 + spend_dec)
    
# Print out variabales
print(f'spend min: {spend_min}')
print(f'spend max: {spend_max}')
print('')
for i in range(0, channels):
    print(f'x{i+1} value: {str(x[i].value)}')    
    print(f'x{i+1} lower: {str(x[i].lower)}')
    print(f'x{i+1} upper: {str(x[i].upper)}')
    print(f'x{i+1} alpha: {str(a[i].value)}')
    print(f'x{i+1} beta: {str(b[i].value)}')
    print('')

# Constraints
m.Equation(sum(x) >= spend_min)
m.Equation(sum(x) <= spend_max)

# Log-Log model
def roi(a, b, x):
    roi = a + b * m.log(x[0])
    roi = m.exp(roi[0])
    return roi

# Objective function
m.Maximize(m.sum(x * roi(a, b, x)))
m.options.IMODE = 3
m.solve()

for i in range(0, channels):
    print(f'x{i+1}: {str(x[i].value[0])}')
print('')
print(f'optimal solution: {str(m.options.objfcnval)}')

# THIS DOESN'T MATCH THE OBJECTIVE FUNCTION VALUE SUGGESTED BY GEKKO
opt = 0
for i in range(0, channels):
    opt += x[i].value[0] * (np.exp((a[0].value[0] + b[i].value[0] * np.log(x[i].value[0]))))
print(f'optimal solution: {opt}')

# THIS IS THE EXPECETD SOLUTION, WHICH ALSO DOESN'T MATCH THE OBJECTIVE FUNCTION VALUE SUGGESTED BY GEKKO
7500 * np.exp(1.00 + 0.03 * np.log(7500)) + 5000 * np.exp(1.00 + 0.02 * np.log(5000)) + 2500 * np.exp(1.00 + 0.01 * np.log(2500))
John Hedengren

Houve um problema com a definição da função objetivo. A correção para o problema é usar a[i], b[i], x[i]um de cada vez nas funções. Gekko permite mais de uma definição de função objetivo. Ao maximizar, ele se converte em um problema de minimização com min = -max. O objetivo maximizado é, portanto -m.options.OBJFCNVAL.

# Log-Log model
def roi(ai, bi, xi):
    return m.exp(ai + bi * m.log(xi))

# Objective function
for i,xi in enumerate(x):
    m.Maximize(xi * roi(a[i], b[i], x[i]))

Também ajuda a definir uma nova variável sum_xcom limites superior spend_maxe inferior spend_min.

# Constraints
sum_x = m.Var(lb=spend_min,ub=spend_max)
m.Equation(sum_x==m.sum(x))

Aqui está o roteiro completo.

from gekko import GEKKO
import numpy as np
import pandas as pd

df1 = pd.DataFrame({'channel': ['fb', 'tv', 'ppc'],
                    'value': [5000, 5000, 5000],                    
                    'alpha': [1.00, 1.00, 1.00],
                    'beta': [0.03, 0.02, 0.01]
})

total_spend = df1['value'].sum()

m = GEKKO()

# Constraint parameters
spend_inc = 0.00
spend_dec = 0.00
channel_inc = 0.50
channel_dec = 0.50

channels = len(df1)

# Initialise decision variables
x = m.Array(m.Var, (channels), integer=True)
i = 0
for xi in x:
    xi.value = df1['value'][i]
    xi.lower = df1['value'][i] * (1 - channel_dec)
    xi.upper = df1['value'][i] * (1 + channel_inc)
    i += 1

# Initialise alpha
a = m.Array(m.Param, (channels))
i = 0
for ai in a:
    ai.value = df1['alpha'][i]
    i += 1
    
# Initialise beta
b = m.Array(m.Param, (channels))
i = 0
for bi in b:
    bi.value = df1['beta'][i]
    i += 1
    
# Initial global contraints
spend_min = total_spend * (1 - spend_dec)
spend_max = total_spend * (1 + spend_dec)
    
# Print out variabales
print(f'spend min: {spend_min}')
print(f'spend max: {spend_max}')
print('')
for i in range(0, channels):
    print(f'x{i+1} value: {str(x[i].value)}')    
    print(f'x{i+1} lower: {str(x[i].lower)}')
    print(f'x{i+1} upper: {str(x[i].upper)}')
    print(f'x{i+1} alpha: {str(a[i].value)}')
    print(f'x{i+1} beta: {str(b[i].value)}')
    print('')

# Constraints
sum_x = m.Var(lb=spend_min,ub=spend_max)
m.Equation(sum_x==m.sum(x))

# Log-Log model
def roi(ai, bi, xi):
    return m.exp(ai + bi * m.log(xi))

# Objective function
for i,xi in enumerate(x):
    m.Maximize(xi * roi(a[i], b[i], x[i]))
m.options.IMODE = 3
m.solve()

for i in range(0, channels):
    print(f'x{i+1}: {str(x[i].value[0])}')
print('')
print(f'optimal solution: {str(-m.options.objfcnval)}')

opt = 0
for i in range(0, channels):
    opt += x[i].value[0] * (np.exp((a[i].value[0] \
                                    + b[i].value[0] \
                                    * np.log(x[i].value[0]))))
print(f'optimal solution: {opt}')

# THIS IS THE EXPECTED SOLUTION
# IT NOW MATCHES THE OBJECTIVE FUNCTION VALUE SUGGESTED BY GEKKO
sol = 7500 * np.exp(1.00 + 0.03 * np.log(7500)) \
      + 5000 * np.exp(1.00 + 0.02 * np.log(5000)) \
      + 2500 * np.exp(1.00 + 0.01 * np.log(2500))
print(f'expected optimal solution: {sol}')

A solução é mostrada abaixo.

EXIT: Optimal Solution Found.
 
 The solution was found.
 
 The final value of the objective function is   -50108.7613900549     
 
 ---------------------------------------------------
 Solver         :  IPOPT (v3.12)
 Solution time  :   9.499999985564500E-003 sec
 Objective      :   -50108.7611889392     
 Successful solution
 ---------------------------------------------------
 
x1: 7500.0
x2: 4999.9999497
x3: 2500.0

optimal solution: 50108.761189
optimal solution: 50108.7611890521
expected optimal solution: 50108.76135441651

Este artigo é coletado da Internet.

Se houver alguma infração, entre em [email protected] Delete.

editar em
0

deixe-me dizer algumas palavras

0comentários
loginDepois de participar da revisão

Artigos relacionados

Otimização restrita para função multivariável não linear em Java

TypeError: objeto do tipo 'int' não tem len () na função Objetivo otimização não linear Gekko

Otimização de objetivo único restrita

Configuração de otimização linear restrita

Maximização restrita (otimização) em R

Otimização restrita onde a restrição é calculada como parte da função objetivo

Restrição na função objetivo em Python Gekko

otimização restrita sem gradiente

Regex não corresponde à saída esperada em python

Como maximizar uma função objetivo em Python Gekko?

Regressão multilinear restrita usando Gekko

Por que, ao usar Mystic em Python para otimizar uma otimização não linear restrita, recebo um erro 'não pode simplesmente desigualdades'?

A saída de minha solução (string a, string b) não corresponde à saída esperada em Shuffle Hashing

Otimização Gekko

Regressão não linear multivariada GEKKO

Python GEKKO: otimizando o desempenho da otimização não linear

Python GEKKO: otimizando o desempenho da otimização não linear

GEKKO - otimização em forma de matriz

Qual solucionador devo usar se minha função objetivo for uma função não linear (também explicação exponencial)? Python GEKKO

Otimização restrita em uma grade, mantendo as proporções

Bibliotecas de código aberto Java puras para seleção de portfólio (= otimização restrita, não linear)?

otimização de uma função objetivo linear com restrições lineares e variáveis binárias em python

é possível usar função não linear ifor objetivo em julia?

Otimização limitada não linear em R

Como reinicializar a otimização em Python Gekko da solução anterior

Tentando resolver essa otimização não linear usando GEKKO, obtendo este erro

A solução no hackerrank não corresponde

Como otimizar uma função objetivo não linear com restrições não lineares em R?

Minha intenção não corresponde à resposta esperada

TOP lista

  1. 1

    R Shiny: use HTML em funções (como textInput, checkboxGroupInput)

  2. 2

    O Chromium e o Firefox exibem as cores de maneira diferente e não sei qual deles está fazendo certo

  3. 3

    Como assinar digitalmente um documento PDF com assinatura e texto visíveis usando Java

  4. 4

    R Folheto. Dados de pontos de grupo em células para resumir muitos pontos de dados

  5. 5

    Gerenciar recurso shake de Windows Aero com barra de título personalizado

  6. 6

    Como obter dados API adequados para o aplicativo angular?

  7. 7

    UITextView não está exibindo texto longo

  8. 8

    Por que meus intervalos de confiança de 95% da minha regressão multivariada estão sendo plotados como uma linha de loess?

  9. 9

    Acessando relatório de campanhas na AdMob usando a API do Adsense

  10. 10

    Usando o plug-in Platform.js do Google

  11. 11

    Como posso modificar esse algoritmo de linha de visada para aceitar raios que passam pelos cantos?

  12. 12

    Dependência circular de diálogo personalizado

  13. 13

    Coloque uma caixa de texto HTML em uma imagem em uma posição fixa para site para desktop e celular

  14. 14

    iOS: como adicionar sombra projetada e sombra de traço no UIView?

  15. 15

    Como usar a caixa de diálogo de seleção de nomes com VBA para enviar e-mail para mais de um destinatário?

  16. 16

    Tabela CSS: barra de rolagem para a primeira coluna e largura automática para a coluna restante

  17. 17

    How to create dynamic navigation menu select from database using Codeigniter?

  18. 18

    Converter valores de linha SQL em colunas

  19. 19

    ChartJS, várias linhas no rótulo do gráfico de barras

  20. 20

    用@StyleableRes注释的getStyledAttributes。禁止警告

  21. 21

    não é possível adicionar dependência para com.google.android.gms.tasks.OnSuccessListener

quentelabel

Arquivo