Python:基于指数目标函数的优化



我正在做作业。到目前为止,我一直通过gurobipy使用Gurobi。在我现在的问题中,我有一个目标函数,它有一个指数项。在gurobipy中,这是

m.setObjective(ratings.prod(assign) ** 0.5, sense=GRB.MAXIMIZE)

Gurobi不支持,但**(或pow())。还有什么其他选择(使用除robi以外的其他工具)或变通方法?

下面是一个最小的工作示例:
import pandas as pd
import gurobipy as gp
from gurobipy import GRB
import random
def solve():
m = gp.Model()
assign = m.addVars(permutations, vtype=gp.GRB.BINARY, name="assign")
m.addConstrs((assign.sum(i, "*") == 1 for i in individuals))
capacity = {
'P1':40, 'P2':30, 'P3':30
}
m.addConstrs(
(assign.sum("*", p) <= capacity[p] for p in groups),
name="limit"
)

# objective function
m.setObjective(ratings.prod(assign) ** 0.5, sense=GRB.MAXIMIZE)
m.optimize()
return m, assign
def get_results(assign):
# create df with placeholder
results = pd.DataFrame(-1, index=individuals, columns=groups)

# fill in the results
for (i, j), x_ij in assign.items():
results.loc[i, j] = int(x_ij.X)
return results

# minimal example
outcomes = []
for i in range(0,100):
x = random.uniform(0, 1)  
outcomes.append(x)
data = {'P1': outcomes, 
'P2': random.sample(outcomes, len(outcomes)),
'P3': random.sample(outcomes, len(outcomes))}
df = pd.DataFrame(data)
individuals = list(df.index)
groups = ['P1', 'P2', 'P3']
# prepare
permutations, ratings = gp.multidict({
(i, j): df.loc[i, j]
for i in individuals
for j in groups
})  

# run   
m, assign = solve()    
results = get_results(assign)    
printresults)

正如评论中提到的,只需在事实之后取根号…除非我在ruby语法中遗漏了一些基本的东西。而不是使用这个:

m.setObjective(ratings.prod(assign) ** 0.5, sense=GRB.MAXIMIZE)

使用:

m.setObjective(ratings.prod(assign), sense=GRB.MAXIMIZE)

然后用此目标求解模型,该目标将获得assign的相同值,然后在求解之后,从模型中获得目标的值(不确定如何在ruby语法中做到这一点,因此这是伪代码:

obj_value = m.get_objective_value_somehow_in_gurobi_syntax  ??

然后取它的根号方根。

real_obj_value = math.sqrt(obj_value)

使obj_valuereal_obj_value最大化的变量的值是相同的。

编辑:使用sqrt

项新计划……对于每个评论,您实际上打算在和积中使用单个项的SQRT,因此上述策略将不起作用。

但是,因为您的决策变量是二进制的,所以您可以实现一个变通方法....

创建一个包含"更正值"的单独字典。这就是单个值的根号方根。(我假设你仍然想要原始值用于一些约束等,所以保留和使用这些)它们都是相同的索引,所以在约束中使用原始值,在目标中使用纠正。

那么在psuedocode中像这样:

corr_values = {k:v**0.5 for k, v in values_dict}

那么就在你的目标函数中使用修正值,这在数学上是好的,因为你只乘以1或0:

1 * v**0.5 == (1 * v)**0.5

你会得到你想要的结果低值会被适当加权

相关内容

  • 没有找到相关文章

最新更新