


Solve list subsets and problems using SciPy: Optimized cropping strategy based on Knapsack algorithm
问题背景与挑战
在实际应用中,我们经常会遇到需要从一组具有特定属性(例如,面积、体积、成本等)的对象中,选择一个子集以满足某个总和目标的问题。具体来说,假设我们有一个MyClass实例列表obj_list,每个实例都含有一个area属性。我们的目标是从这个列表中移除最少数量的实例,使得剩余实例的总面积tot_area尽可能接近一个预设的target_area,允许一定的上下浮动。
一个直观但存在缺陷的思路是:首先对所有实例按面积进行排序,然后从最小的实例开始移除,直到总面积达到目标。然而,这种贪心策略可能不是最优的。例如,移除几个小面积实例可能不如移除一个特定的大面积实例更能有效地达到目标,同时保留更多的对象。因此,我们需要一种更系统、更优化的方法来解决这个问题。
问题建模:Knapsack算法
上述问题实际上是著名的Knapsack(背包)问题的一个变种。在经典的0/1背包问题中,我们有一组物品,每个物品都有一个重量和一个价值,目标是在不超过背包容量的前提下,最大化装入物品的总价值。
将我们的问题映射到Knapsack模型中:
- 物品(Items):obj_list中的每个MyClass实例。
- 重量(Weights):每个实例的area属性。
- 价值(Values):由于我们的目标是“移除最少数量的实例”,这等价于“最大化保留的实例数量”。因此,我们将每个实例的价值都设为1。
- 背包容量(Knapsack Capacity):不是一个固定的值,而是一个范围。我们希望总面积tot_area落在target_area附近的一个可接受区间内。
因此,我们的目标是选择一个实例子集,使得这些实例的总面积落在目标范围内,并且所选实例的总价值(即数量)最大化。
基于SciPy的混合整数线性规划(MILP)实现
解决0/1背包问题通常可以通过动态规划或整数线性规划(ILP)来实现。Python的SciPy库提供了scipy.optimize.milp函数,这是一个用于解决混合整数线性规划问题的强大工具,非常适合我们这里的0/1背包问题。
milp函数的核心思想是将问题表述为: 最小化 c @ x 受限于 lb <= A @ x <= ub 以及 x 的整数性和界限
其中:
- x 是决策变量向量,每个元素x_i代表是否选择第i个物品(0表示不选,1表示选择)。
- c 是目标函数的系数向量。由于milp是最小化问题,而我们希望最大化选中的物品数量,因此我们将c设置为物品价值的负值。
- A 是约束矩阵。
- lb 和 ub 是约束的下界和上界。
- integrality 指定哪些变量必须是整数。
- bounds 指定变量的取值范围。
示例代码与解析
下面通过一个具体的Python示例来展示如何使用scipy.optimize.milp解决此问题:
import numpy as np from scipy import optimize from scipy.optimize import milp # 1. 数据准备 # 假设的实例面积列表,代表MyClass实例的area属性 sizes = np.array([0.003968, 0.0148, 0.022912, 0.024832, 0.02912, 0.032448, 0.034176, 0.035136, 0.035584, 0.049344, 0.057984, 0.059904, 0.063744, 0.080064, 0.085824]) # 目标总面积 target_area = 0.45 # 允许的目标面积误差百分比,实现“软边界” pct_error = 0.03 # 2. 定义目标函数系数 # 由于我们希望最大化选择的实例数量,因此将所有实例的“价值”设为1。 # milp函数是最小化目标函数,所以我们将系数设为负值,以达到最大化效果。 values = np.full_like(sizes, 1.0) c = -values # 3. 定义决策变量的属性 # integrality: 决策变量x_i必须是整数(0或1),表示选中或未选中。 integrality = np.full_like(values, True) # bounds: 决策变量x_i的取值范围为[0, 1]。结合integrality,使其成为布尔变量。 bounds = optimize.Bounds(0, 1) # 4. 定义约束条件 # 计算目标面积的上下限,形成一个“软边界” lb = (1 - pct_error) * target_area ub = (1 + pct_error) * target_area # 线性约束:所有选中实例的面积之和必须落在[lb, ub]区间内。 # A矩阵在这里是一个行向量,其元素就是各个实例的面积。 constraints = optimize.LinearConstraint(A=sizes, lb=lb, ub=ub) # 5. 执行混合整数线性规划 optimization_result = milp(c=c, constraints=constraints, integrality=integrality, bounds=bounds) # 6. 结果解读 if not optimization_result.success: raise RuntimeError('MILP优化过程失败!') # optimization_result.x 是决策变量的最终值,表示哪些实例被选中(接近1) # 通过astype(bool)将其转换为布尔数组,方便筛选 selected_indices = optimization_result.x.astype(bool) print(f'优化后的总面积: {sizes[selected_indices].sum()}') # 示例输出: 优化后的总面积: 0.45998399999999995 print(f'决策变量结果 (选中为1,未选中为0):\n{optimization_result.x}') # 示例输出: 决策变量结果 (选中为1,未选中为0): # [0. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 0. 0.] print(f'选中的实例面积列表:\n{sizes[selected_indices]}') # 示例输出: 选中的实例面积列表: # [0.0148 0.022912 0.024832 0.02912 0.032448 0.034176 0.035136 0.035584 # 0.049344 0.057984 0.059904 0.063744]
代码解析要点:
- 数据准备:sizes数组包含了所有MyClass实例的面积。target_area是我们希望达到的总面积,pct_error定义了可接受的误差范围。
- 目标函数:values数组中的每个元素都为1,表示每个实例的“价值”相同。c = -values是为了将最大化问题(最大化选中的实例数量)转换为milp函数所需的最小化问题。
- 决策变量:integrality=True确保x_i只能取整数值。bounds=(0, 1)限制x_i在0到1之间。这两者结合,使得x_i成为0/1的布尔决策变量。
- 约束条件:lb和ub根据target_area和pct_error计算得出,定义了总面积的允许范围。optimize.LinearConstraint(A=sizes, lb=lb, ub=ub)构建了一个线性约束,要求所有被选中的实例的面积之和必须落在这个范围内。
- 优化执行:milp函数接收这些参数并执行优化,返回一个包含结果的对象optimization_result。
- 结果解读:optimization_result.x是最终的决策变量数组。其中值为1(或非常接近1)的索引对应被选中的实例,值为0的索引对应被移除的实例。通过布尔索引,我们可以轻松地获取选中的实例及其总面积。
注意事项与最佳实践
- “软边界”的灵活性:通过pct_error参数,我们可以灵活地控制目标面积的容忍度,这在许多实际场景中非常有用,比严格的单一目标值更具实用性。
- 0/1整数规划:milp函数非常适合处理这种二元决策(选或不选)的问题。对于更复杂的整数规划问题(如变量可以取任意整数值),milp同样适用。
- 错误处理:在调用milp后,务必检查optimization_result.success属性。如果为False,表示优化过程未能成功找到可行解,需要根据具体情况进行调试或调整参数。
- 性能考量:对于大规模问题(例如,实例数量非常庞大),MILP的求解时间可能会显著增加。在这种情况下,可能需要考虑使用更专业的优化求解器(如Gurobi、CPLEX)或探索近似算法。
- 问题泛化:此方法不仅适用于“面积”,还可以推广到任何需要从列表中选择子集以使某个属性总和接近目标值,同时最大化/最小化其他属性总和的问题。
总结
通过将列表裁剪问题建模为0/1背包问题,并利用SciPy库中的milp函数,我们能够高效且准确地找到一个最优的实例子集,使其总面积接近目标值,并最大化保留的实例数量。这种方法克服了简单贪心策略的局限性,提供了一个专业且可靠的解决方案,适用于各种需要进行组合优化的场景。
The above is the detailed content of Solve list subsets and problems using SciPy: Optimized cropping strategy based on Knapsack algorithm. For more information, please follow other related articles on the PHP Chinese website!

Hot AI Tools

Undress AI Tool
Undress images for free

Undresser.AI Undress
AI-powered app for creating realistic nude photos

AI Clothes Remover
Online AI tool for removing clothes from photos.

ArtGPT
AI image generator for creative art from text prompts.

Stock Market GPT
AI powered investment research for smarter decisions

Hot Article

Hot Tools

Notepad++7.3.1
Easy-to-use and free code editor

SublimeText3 Chinese version
Chinese version, very easy to use

Zend Studio 13.0.1
Powerful PHP integrated development environment

Dreamweaver CS6
Visual web development tools

SublimeText3 Mac version
God-level code editing software (SublimeText3)

Run pipinstall-rrequirements.txt to install the dependency package. It is recommended to create and activate the virtual environment first to avoid conflicts, ensure that the file path is correct and that the pip has been updated, and use options such as --no-deps or --user to adjust the installation behavior if necessary.

This tutorial details how to efficiently merge the PEFT LoRA adapter with the base model to generate a completely independent model. The article points out that it is wrong to directly use transformers.AutoModel to load the adapter and manually merge the weights, and provides the correct process to use the merge_and_unload method in the peft library. In addition, the tutorial also emphasizes the importance of dealing with word segmenters and discusses PEFT version compatibility issues and solutions.

Python is a simple and powerful testing tool in Python. After installation, test files are automatically discovered according to naming rules. Write a function starting with test_ for assertion testing, use @pytest.fixture to create reusable test data, verify exceptions through pytest.raises, supports running specified tests and multiple command line options, and improves testing efficiency.

Theargparsemoduleistherecommendedwaytohandlecommand-lineargumentsinPython,providingrobustparsing,typevalidation,helpmessages,anderrorhandling;usesys.argvforsimplecasesrequiringminimalsetup.

This article aims to explore the common problem of insufficient calculation accuracy of floating point numbers in Python and NumPy, and explains that its root cause lies in the representation limitation of standard 64-bit floating point numbers. For computing scenarios that require higher accuracy, the article will introduce and compare the usage methods, features and applicable scenarios of high-precision mathematical libraries such as mpmath, SymPy and gmpy to help readers choose the right tools to solve complex accuracy needs.

Getting the current time can be implemented in Python through the datetime module. 1. Use datetime.now() to obtain the local current time, 2. Use strftime("%Y-%m-%d%H:%M:%S") to format the output year, month, day, hour, minute and second, 3. Use datetime.now().time() to obtain only the time part, 4. It is recommended to use datetime.now(timezone.utc) to obtain UTC time, avoid using deprecated utcnow(), and daily operations can meet the needs by combining datetime.now() with formatted strings.

PyPDF2, pdfplumber and FPDF are the core libraries for Python to process PDF. Use PyPDF2 to perform text extraction, merging, splitting and encryption, such as reading the page through PdfReader and calling extract_text() to get content; pdfplumber is more suitable for retaining layout text extraction and table recognition, and supports extract_tables() to accurately capture table data; FPDF (recommended fpdf2) is used to generate PDF, and documents are built and output through add_page(), set_font() and cell(). When merging PDFs, PdfWriter's append() method can integrate multiple files

Import@contextmanagerfromcontextlibanddefineageneratorfunctionthatyieldsexactlyonce,wherecodebeforeyieldactsasenterandcodeafteryield(preferablyinfinally)actsas__exit__.2.Usethefunctioninawithstatement,wheretheyieldedvalueisaccessibleviaas,andthesetup
