如何用整数线性规划(ILP)求解满足严格单调性、归一化与阈值约束的每日权重

风芳同学_9885

风芳同学_9885

2026-08-16

165人浏览

原创

如何用整数线性规划(ILP)求解满足严格单调性、归一化与阈值约束的每日权重

本文介绍如何使用 SciPy 的 milp 求解器,构建整数线性规划模型,精确计算 7 天的每日权重,使其严格递减、和为 7,并确保恰好 7 个用户的加权平均消费值低于指定阈值(如 11)。

本文介绍如何使用 scipy 的 `milp` 求解器,构建整数线性规划模型,精确计算 7 天的每日权重,使其严格递减、和为 7,并确保**恰好 7 个用户**的加权平均消费值低于指定阈值(如 11)。

在时间序列加权分析中,仅靠指数衰减等启发式方法难以同时满足严格单调性、固定和约束与精确达标数量控制(如“恰好 7/10 用户低于阈值”)三大条件。此时,传统优化手段失效,需转向混合整数线性规划(MILP)——它能通过引入二元决策变量(binary predicates),将逻辑条件(如“加权均值 ≤ 阈值?”)转化为可求解的线性约束。

以下为完整实现流程(基于 scipy.optimize.milp):

✅ 核心建模要素

  • 决策变量:
    • w₀, w₋₁, ..., w₋₆:7 个连续型权重(要求 w₀ > w₋₁ > ... > w₋₆ > 0);
    • pᵢ ∈ {0,1}(i = 0..9):10 个二元变量,pᵢ = 1 表示第 i 个用户的加权均值 ≤ 阈值。
  • 关键约束:
    1. 和约束:∑wⱼ = 7;
    2. 严格递减:wⱼ − wⱼ₊₁ ≥ ε(ε = 1e-2,避免数值相等);
    3. 阈值逻辑(大M法):
      • 若 pᵢ = 1 → (w·df[i]) / 7 ≤ threshold;
      • 若 pᵢ = 0 → (w·df[i]) / 7 > threshold;
        等价于:
        w·df[i] + M·pᵢ ≤ M + 7·threshold(上界)
        w·df[i] + M·pᵢ ≥ 7·threshold(下界)
        其中 M 取足够大值(如 2 * max(row_sum));
    4. 精确计数:∑pᵢ = 7。

? 示例代码(精确解)

import numpy as np
import pandas as pd
from scipy.optimize import milp, LinearConstraint, Bounds
import scipy.sparse

# 构造示例数据(10用户 × 7天)
df = pd.DataFrame({
    'day_0': [10,10,10,12,12,13,8,13,8,14],
    'day_-1': [10,13,12,12,13,9,9,10,8,13],
    'day_-2': [14,11,9,9,8,8,8,14,10,13],
    'day_-3': [8,11,12,11,12,13,14,12,12,9],
    'day_-4': [14,8,9,9,8,9,8,8,11,11],
    'day_-5': [14,10,10,12,11,12,13,9,14,14],
    'day_-6': [14,10,10,13,9,10,14,11,14,13]
}, index=range(10))
df.columns = [0, -1, -2, -3, -4, -5, -6]  # 统一列名为整数天数

m, n = df.shape  # m=10 users, n=7 days
threshold = 11
n_up_to_threshold = 7  # 恰好7人满足
M = 2 * df.sum(axis=1).max()  # 大M值

# === 约束定义 ===
# 1. 权重和为7
sum_con = LinearConstraint(
    A=np.concatenate([np.ones(n), np.zeros(m)]),
    lb=7, ub=7
)

# 2. 严格递减(w_j - w_{j+1} >= 1e-2)
dec_con = LinearConstraint(
    A=scipy.sparse.diags_array(
        (np.ones(n-1), -np.ones(n-1)), offsets=(0,1), shape=(n-1, n+m)
    ),
    lb=1e-2
)

# 3. 阈值逻辑约束(大M法)
A_thresh = scipy.sparse.hstack([
    scipy.sparse.csr_matrix(df.values),  # w·df[i]
    scipy.sparse.diags(M * np.ones(m))    # + M·p_i
], format='csc')
thresh_con = LinearConstraint(
    A=A_thresh,
    lb=7*threshold * np.ones(m),
    ub=M + 7*threshold * np.ones(m)
)

# 4. 精确计数:sum(p_i) = 7
count_con = LinearConstraint(
    A=np.concatenate([np.zeros(n), np.ones(m)]),
    lb=n_up_to_threshold, ub=n_up_to_threshold
)

# === 变量边界 ===
bounds = Bounds(
    lb=np.concatenate([np.full(n, 1e-3), np.zeros(m)]),
    ub=np.concatenate([np.full(n, np.inf), np.ones(m)])
)

# === 求解(无目标函数,仅可行性)===
result = milp(
    c=np.zeros(n + m),
    integrality=np.concatenate([np.zeros(n), np.ones(m, dtype=int)]),
    bounds=bounds,
    constraints=[sum_con, dec_con, thresh_con, count_con]
)

if not result.success:
    raise RuntimeError(f"Optimization failed: {result.message}")

weights, preds = result.x[:n], result.x[n:]
means = df @ (weights / 7)

print("✅ 求解成功!")
print(f"每日权重 w₀..w₋₆ = {weights.round(4)}")
print(f"达标用户标识 p₀..p₉ = {preds.astype(int)} → 共{int(preds.sum())}人")
print(f"各用户加权均值:\n{means.round(4)}")

⚠️ 注意事项与进阶建议

  • 数值稳定性:严格不等式 > 在 LP 中需用 ≥ ε 近似,ε 过小易导致数值误差,建议 1e-3 ~ 1e-2;
  • 大M值选择:M 过大会削弱约束紧致性,应取理论最大可能值(如 2 * max(sum(row)));
  • 无解处理:若 milp 返回 success=False,说明约束冲突(如阈值过低且要求过高达标数),可尝试:
    • 放宽阈值(软约束法,见答案第二部分);
    • 增加最小权重下限;
    • 检查数据是否存在极端离群值;
  • 软约束扩展:当精确阈值不可行时,可将阈值设为变量并最小化其与目标值(如12)的绝对偏差,实现“近似达标”。

该方法将业务规则精准编码为数学约束,避免启发式调参,是金融风控、动态权重分配等场景的可靠基础工具。

PHP速学视频免费教程(入门到精通)
PHP速学视频免费教程(入门到精通)

PHP怎么学习?PHP怎么入门?PHP在哪学?PHP怎么学才快?不用担心,这里为大家提供了PHP速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载

相关标签:

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

相关专题

更多
python打包成可执行文件
python打包成可执行文件

本专题为大家带来python打包成可执行文件相关的文章,大家可以免费的下载体验。

2023.07.20

1631

4

python能做什么
python能做什么

python能做的有:可用于开发基于控制台的应用程序、多媒体部分开发、用于开发基于Web的应用程序、使用python处理数据、系统编程等等。本专题为大家提供python相关的各种文章、以及下载和课程。

2023.07.25

3984

7

format在python中的用法
format在python中的用法

Python中的format是一种字符串格式化方法,用于将变量或值插入到字符串中的占位符位置。通过format方法,我们可以动态地构建字符串,使其包含不同值。php中文网给大家带来了相关的教程以及文章,欢迎大家前来阅读学习。

2023.07.31

1629

3

python教程
python教程

Python已成为一门网红语言,即使是在非编程开发者当中,也掀起了一股学习的热潮。本专题为大家带来python教程的相关文章,大家可以免费体验学习。

2023.08.03

22977

23

python环境变量的配置
python环境变量的配置

Python是一种流行的编程语言,被广泛用于软件开发、数据分析和科学计算等领域。在安装Python之后,我们需要配置环境变量,以便在任何位置都能够访问Python的可执行文件。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

2023.08.04

2827

5

python eval
python eval

eval函数是Python中一个非常强大的函数,它可以将字符串作为Python代码进行执行,实现动态编程的效果。然而,由于其潜在的安全风险和性能问题,需要谨慎使用。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

2023.08.04

2867

5

scratch和python区别
scratch和python区别

scratch和python的区别:1、scratch是一种专为初学者设计的图形化编程语言,python是一种文本编程语言;2、scratch使用的是基于积木的编程语法,python采用更加传统的文本编程语法等等。本专题为大家提供scratch和python相关的文章、下载、课程内容,供大家免费下载体验。

2023.08.11

1123

5

python合并两个列表
python合并两个列表

Python是一种强大的编程语言,具有许多方便的功能和工具。在Python中,有多种方法可以合并两个列表。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

2023.08.10

596

4

python是前端还是后端
python是前端还是后端

Python属于前端也属于后端,其灵活性和丰富的生态系统使得开发人员能够在不同的领域中灵活运用。本专题为大家提供python相关的文章、下载、课程内容,供大家免费下载体验。

2023.08.11

2223

5

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
热门推荐
/
最新课程
phpStudy极速入门视频教程
phpStudy极速入门视频教程

共6课时 | 54.6万人学习

独孤九贱(4)_PHP视频教程
独孤九贱(4)_PHP视频教程

共89课时 | 133.4万人学习