【问题标题】:How to use sum of absolute difference condition in python pulp?python - 如何在python纸浆中使用绝对差条件的总和?
【发布时间】:2021-08-29 10:43:27
【问题描述】:

我一直在查找有关线性规划中绝对值条件的类似帖子,并尝试提出的解决方案。但是,我仍在努力让我的纸浆设置在 python 中工作。

我在这里发布简化代码。具体来说,在下面的“较近约束”中,我想强制 绝对差之和 小于某个阈值“sum(df['diff_orig'])”。发布的代码有效,但这只是总和差异不是绝对差异

任何帮助将不胜感激!

J

import pandas as pd
import pulp

# initialize data
nav = 1000
data = [['A', 0.2], ['B', 0.4], ['C', 0.1], ['D', 0.3], ['cash', 0.0]]

# create the pandas DataFrame
df = pd.DataFrame(data, columns=['asset', 'w_star'])
df['prccd'] = [17, 21, 119, 49, None]
df['q_tilde'] = [11, 19, 0, 6, None]
df['val'] = df.prccd * df.q_tilde
df.loc[df.asset == 'cash', 'val'] = nav - sum(df.loc[~df.val.isna(), 'val'])
df['w_act'] = df.val / sum(df.val)
df['diff_orig'] = abs(df.w_star - df.w_act)
df = df.set_index('asset')

# manipulate cash
dfnc = df[df.index != 'cash']

# create variables and model
dq = pulp.LpVariable.dicts("dq", dfnc.index, cat='Integer', lowBound=0)
mod = pulp.LpProblem("CashReduction", pulp.LpMinimize)

# objective function
mod += nav - sum([dq[i] * dfnc.loc[i, 'prccd'] + dfnc.loc[i, 'q_tilde'] * dfnc.loc[i, 'prccd'] for i in dfnc.index])

# lower bounds:
for i in dfnc.index:
    mod += dq[i] >= 0

# budget constraint
mod += sum([dq[i] * dfnc.loc[i, 'prccd'] for i in dfnc.index]) <= df.loc['cash', 'val']

# nearer constraint
mod += sum(
    [dfnc.loc[i, 'w_star'] - (dq[i] * dfnc.loc[i, 'prccd'] + dfnc.loc[i, 'q_tilde'] * dfnc.loc[i, 'prccd']) / nav
     for i in dfnc.index]) <= sum(df['diff_orig'])

# individual diff cannot be bigger than 3%
for i in dfnc.index:
    mod += (dfnc.loc[i, 'w_star'] -
            (dq[i] * dfnc.loc[i, 'prccd'] + dfnc.loc[i, 'q_tilde'] * dfnc.loc[i, 'prccd']) / nav) <= 0.03
for i in dfnc.index:
    mod += (dfnc.loc[i, 'w_star'] -
            (dq[i] * dfnc.loc[i, 'prccd'] + dfnc.loc[i, 'q_tilde'] * dfnc.loc[i, 'prccd']) / nav) >= -0.03

# solve model
mod.solve()

# output solution
for i in dfnc.index:
    print(i, dq[i].value())```

【问题讨论】:

    标签: python linear-programming pulp


    【解决方案1】:

    您需要引入一个额外的索引变量来执行此操作。 ABS 是非线性的,因此处理一个 ABS 函数的典型方法是引入 一个 变量,并使该变量大于 pos 值并且大于 ABS 目标的否定,如下所示:

    if we are working with |x - y|...
    g > x - y
    g > -(x - y)
    

    在您的情况下,您对每个要求和的元素都有一个 ABS 函数,因此您可以通过创建一个新变量来扩展上述函数,该变量由您想要求和的相同事物索引,并使用它...

    import pandas as pd
    import pulp
    
    # initialize data
    nav = 1000
    data = [['A', 0.2], ['B', 0.4], ['C', 0.1], ['D', 0.3], ['cash', 0.0]]
    
    # create the pandas DataFrame
    df = pd.DataFrame(data, columns=['asset', 'w_star'])
    df['prccd'] = [17, 21, 119, 49, None]
    df['q_tilde'] = [11, 19, 0, 6, None]
    df['val'] = df.prccd * df.q_tilde
    df.loc[df.asset == 'cash', 'val'] = nav - sum(df.loc[~df.val.isna(), 'val'])
    df['w_act'] = df.val / sum(df.val)
    df['diff_orig'] = abs(df.w_star - df.w_act)
    df = df.set_index('asset')
    print(df)
    
    # manipulate cash
    dfnc = df[df.index != 'cash']
    
    # create variables and model
    dq = pulp.LpVariable.dicts("dq", dfnc.index, cat='Integer', lowBound=0)
    ab_dif_element = pulp.LpVariable.dicts("ab_dif", df.index)
    mod = pulp.LpProblem("CashReduction", pulp.LpMinimize)
    
    # objective function
    mod += nav - sum([dq[i] * dfnc.loc[i, 'prccd'] + dfnc.loc[i, 'q_tilde'] * dfnc.loc[i, 'prccd'] for i in dfnc.index])
    
    # this is redundant...you've already set lowBound
    # # lower bounds:
    # for i in dfnc.index:
    #     mod += dq[i] >= 0
    
    # budget constraint
    mod += sum([dq[i] * dfnc.loc[i, 'prccd'] for i in dfnc.index]) <= df.loc['cash', 'val']
    
    
    for i in dfnc.index:
        # pos ab_dif
        mod += ab_dif_element[i] >= dfnc.loc[i, 'w_star'] - (dq[i] * dfnc.loc[i, 'prccd'] + dfnc.loc[i, 'q_tilde'] * dfnc.loc[i, 'prccd']) / nav
        # neg ab_dif
        mod += ab_dif_element[i] >= -(dfnc.loc[i, 'w_star'] - (dq[i] * dfnc.loc[i, 'prccd'] + dfnc.loc[i, 'q_tilde'] * dfnc.loc[i, 'prccd']) / nav)
    
    # nearer constraint
    mod += sum(ab_dif_element[i] for i in dfnc.index) <= sum(df['diff_orig'])
    
    # individual diff cannot be bigger than 3%
    for i in dfnc.index:
        mod += (dfnc.loc[i, 'w_star'] -
                (dq[i] * dfnc.loc[i, 'prccd'] + dfnc.loc[i, 'q_tilde'] * dfnc.loc[i, 'prccd']) / nav) <= 0.03
    for i in dfnc.index:
        mod += (dfnc.loc[i, 'w_star'] -
                (dq[i] * dfnc.loc[i, 'prccd'] + dfnc.loc[i, 'q_tilde'] * dfnc.loc[i, 'prccd']) / nav) >= -0.03
    
    # solve model
    mod.solve()
    
    # output solution
    for i in dfnc.index:
        print(i, dq[i].value(), ab_dif_element[i].value())
    

    【讨论】:

    • 非常感谢。这正是我想知道的。我只是对概念有一个理解,所以我学会了如何在算法中实现它。非常感谢!
    • 太棒了。如果它回答了您的问题,您可以通过点击答案旁边的复选标记来关闭该问题。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-02-08
    相关资源
    最近更新 更多