【问题标题】:Pyomo optimization Investments/RevenuePyomo 优化投资/收入
【发布时间】:2021-06-28 13:31:42
【问题描述】:

我是 Pyomo 的新手,我正在尝试根据预算优化投资。
我有一个总预算,我想找到在不同媒体上分配预算的最佳方式。
例如:total_budget = 5000 --> tv = 3000,电影院 = 500,广播 = 1500。

我正在努力将预算与相应的收入“联系起来”。 媒体有不同的回报曲线(在达到一定预算之前投资特定媒体可能会更好,然后再投资其他媒体)。
不同媒体的收入由如下函数返回:tv_1k_revenue = calculate_revenue(budget=1000, media="tv")
假设我唯一的限制是简化问题的总预算(我可以管理我认为的其他限制)。

到目前为止,这是我的代码:

model = pyo.ConcreteModel(doc="Optimization model")

# Declaration of possible budgets
model.S1 = Set(initialize=[*df.TV_Budget.values])
model.tv_budget = Var(model.S1, initialize=0.0)
model.S2 = Set(initialize=[*df.Cinema_Budget.values])
model.cinema_budget = Var(model.S2, initialize=0.0)
model.S3 = Set(initialize=[*df.Radio_Budget.values])
model.radio_budget = Var(model.S3, initialize=0.0)

# Objective function
def func_objective(model):
    objective_expr = sum(model.tv_revenue +
                         model.cinema_revenue +
                         model.radio_revenue)
return objective_expr

model.objective = pyo.Objective(rule=func_objective, sense=pyo.maximize)

所以我的问题是,如何声明 model.tv_revenue、model.cinema_revenue、model.radio_revenue,以便优化电视、电影和广播预算,以最大限度地提高电视、电影、广播产生的总收入? 现在我为每个媒体创建了一个包含预算和收入列的 DataFrame,但最好的方法应该是使用我的calculate_revenue 函数并在每个媒体预算上设置bounds=(min_budget, max_budget)

感谢您的帮助!

【问题讨论】:

  • 这里没有足够的信息来帮助您。每个“预算”都只是一个数量吗?您似乎在为它们索引而苦苦挣扎。这是必需的吗?是否有时间段或预算?如果您添加一些有关问题性质的其他信息,您要尝试使用它做什么,并添加数据框的 sn-p,那将很有帮助。 :)
  • 我同意@AirSquid。关于数据集、参数和约束的信息不足。
  • @AirSquid 我添加了更多细节,希望对您有所帮助。谢谢你的回答!

标签: python optimization pyomo maximize


【解决方案1】:

非常感谢@AirSquid!
就是这样。
在我的情况下,扔熊猫确实很有意义。
另外,是的,我的收入函数是非线性的。
我可能会尝试做一个线性近似,看看我是否能做到这一点。 我打算尝试将我的目标函数声明为:

def func_objective(model):
    objective_expr = sum([calculate_revenue(model.budget[media], media=media) for media in model.medias])
return objective_expr
model.objective = pyo.Objective(rule=func_objective, sense=pyo.maximize)

你知道我为什么不能这样声明吗?

【讨论】:

  • 查看我上面关于这个问题的更新答案。
【解决方案2】:

根据您提供的内容以及您在pyomo 方面的有限经验,这是我的建议...

您似乎有预算和收入,而且这些似乎是按媒体类型编入索引的。目前尚不清楚您现在使用索引做什么。所以我会期待这样的事情:

model.medias = pyo.Set(initialize=['radio', 'tv', ... ])

model.budget = pyo.Var(model.medias, domain=pyo.NonNegativeReals)
...

pandas扔出窗外。这是一个很棒的 pkg,但对建立模型没有多大帮助。尝试仅使用 python 字典来保存您的常量和参数。 (如果这令人困惑,请参阅我的其他一些示例)。

我敢打赌,您最终会遇到的问题是您的收入函数可能是非线性的。对?我将从一个简单的线性近似开始,看看你是否可以让该模型工作,然后考虑进行分段线性近似或使用某种非线性求解器。

==================== 编辑/附加信息。

关于 obj 函数,您不能只是填充对返回值的非线性函数的引用。目标必须是有效的pyomo 表达式(线性或非线性),由模型元素组成。我会从这样的东西开始......

# media mix

import pyomo.environ as pyo

# data for linear approximations of form revenue = c1 * budget + c0

#           media      c0  c1
consts = {  'radio' : (4,  0.6),
            'tv'    : (12, 0.45)}

# a bunch of other parameters....??  limits, minimums, etc.


### MODEL

m = pyo.ConcreteModel('media mix')

### SETS
m.medias = pyo.Set(initialize=consts.keys())


### VARIABLES
m.budget = pyo.Var(m.medias, domain=pyo.NonNegativeReals)


### OBJ
m.obj = pyo.Objective(expr=sum(consts[media][1]*m.budget[media] + consts[media][0] for media in m.medias), 
                sense=pyo.maximize)

m.pprint()

产量:

1 Set Declarations
    medias : Size=1, Index=None, Ordered=Insertion
        Key  : Dimen : Domain : Size : Members
        None :     1 :    Any :    2 : {'radio', 'tv'}

1 Var Declarations
    budget : Size=2, Index=medias
        Key   : Lower : Value : Upper : Fixed : Stale : Domain
        radio :     0 :  None :  None : False :  True : NonNegativeReals
           tv :     0 :  None :  None : False :  True : NonNegativeReals

1 Objective Declarations
    obj : Size=1, Index=None, Active=True
        Key  : Active : Sense    : Expression
        None :   True : maximize : 0.6*budget[radio] + 4 + 0.45*budget[tv] + 12

3 Declarations: medias budget obj

【讨论】:

  • " 尝试仅使用 python 字典来保存您的常量和参数" 或者他可以创建一个 AbstractModel 并使用 dat 文件创建实例。
  • @Corralien 我同意,但是,我认为开始使用纯 python 设置数据要容易得多,这在集合和字典(甚至在读取大型数据文件时)而不是抽象模型,这可能更难排除故障。
猜你喜欢
  • 2016-07-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-10-08
  • 2022-11-18
  • 1970-01-01
  • 2013-04-20
  • 1970-01-01
相关资源
最近更新 更多