You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Python PuLP中实现绝对差之和约束?

解决方案

线性规划为线性模型,无法直接支持绝对值运算,要实现绝对差之和的约束,可通过引入非负辅助变量的标准方案实现,具体修改如下:

  1. 为每个非现金资产新增非负辅助变量,用于存储对应权重差的绝对值
  2. 为每个辅助变量添加双向约束,保证其取值等于权重差的绝对值
  3. 替换原有nearer constraint为辅助变量求和的约束

修改后完整代码如下:

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)
# 新增绝对值辅助变量
abs_diff = pulp.LpVariable.dicts("abs_diff", dfnc.index, 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']

# 新增辅助变量约束,保证abs_diff[i]等于权重差的绝对值
for i in dfnc.index:
    w_new = (dq[i] * dfnc.loc[i, 'prccd'] + dfnc.loc[i, 'q_tilde'] * dfnc.loc[i, 'prccd']) / nav
    diff = dfnc.loc[i, 'w_star'] - w_new
    mod += abs_diff[i] >= diff
    mod += abs_diff[i] >= -diff

# 替换后的nearer constraint:绝对差之和小于阈值
mod += sum([abs_diff[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())

内容的提问来源于stack exchange,提问作者quark99

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.06 17:15:03