如何在Scipy中表示由集合并集构成的可行域?
处理Scipy中并集形式可行域的非线性优化问题
对于可行域为多个集合并集的优化问题,Scipy的minimize无法直接通过单一约束描述(默认约束为交集逻辑),最可靠的解决方式是拆分到每个子集单独求解,再比较结果取全局最优。
问题分析
你的可行域由三个子集组成:
- 子集A:$x_0^2 + x_1^2 \leq 4$,且 $-2 \leq x_0 \leq 1$、$-2 \leq x_1 \leq 1$
- 子集B:$-4 \leq x_0 \leq 0$,且 $0 \leq x_1 \leq 1$
- 子集C:$0 \leq x_0 \leq 1$,且 $-4 \leq x_1 \leq 0$
原代码的约束函数逻辑错误,无法正确描述并集可行域,导致求解结果不符合预期。
修正后的实现方案
分别在三个子集上求解优化问题,最后对比三个结果的目标函数值,选择最小的解作为全局最优解:
import matplotlib.pyplot as plt from matplotlib.patches import Rectangle import numpy as np from scipy.optimize import NonlinearConstraint, Bounds, minimize ############ 绘图部分(保留原逻辑)############ def in_region(x): return (x[0]**2 + x[1]**2 <= 4 and -2 <= x[0] <= 1 and -2 <= x[1] <= 1) or \ (-4 <= x[0] <= 0 and 0 <= x[1] <= 1) or \ (-4 <= x[1] <= 0 and 0 <= x[0] <= 1) X, Y = np.meshgrid(np.linspace(-4, 1, 500), np.linspace(-4, 1, 500)) Z = np.zeros_like(X) for i in range(X.shape[0]): for j in range(X.shape[1]): Z[i,j] = in_region([X[i,j], Y[i,j]]) fig, ax = plt.subplots(figsize=(8,8)) ax.pcolormesh(X, Y, Z, cmap='binary') rect1 = Rectangle((-2,-2), 3, 3, linewidth=1, edgecolor='r', facecolor='none') # 修正矩形范围,覆盖x0到1、x1到1 ax.add_patch(rect1) rect2 = Rectangle((-4,0), 4, 1, linewidth=1, edgecolor='r', facecolor='none') ax.add_patch(rect2) rect3 = Rectangle((0,-4), 1, 4, linewidth=1, edgecolor='r', facecolor='none') ax.add_patch(rect3) ax.set_xlim([-4, 1]) ax.set_ylim([-4, 1]) ax.set_xlabel('x[0]') ax.set_ylabel('x[1]') plt.show() ############ 求解部分(拆分到三个子集)############ # 目标函数 def objective(x): return x[0] + x[1] # --- 子集A求解 --- def constraint_A(x): return x[0]**2 + x[1]**2 - 4 # 约束:x0²+x1² ≤4 → 函数值 ≤0 bounds_A = Bounds([-2, -2], [1, 1]) cons_A = NonlinearConstraint(constraint_A, -np.inf, 0) result_A = minimize(objective, [-2, -2], bounds=bounds_A, constraints=cons_A) # --- 子集B求解 --- bounds_B = Bounds([-4, 0], [0, 1]) result_B = minimize(objective, [-4, 1], bounds=bounds_B) # --- 子集C求解 --- bounds_C = Bounds([0, -4], [1, 0]) result_C = minimize(objective, [1, -4], bounds=bounds_C) # 比较三个子集的最优解 results = [result_A, result_B, result_C] min_idx = np.argmin([res.fun for res in results]) best_result = results[min_idx] print("全局最优解:") print(f"x1 = {best_result.x[0]:.4f}, x2 = {best_result.x[1]:.4f}") print(f"最小目标函数值:{best_result.fun:.4f}")
关键说明
- 子集拆分逻辑:每个子集对应独立的约束/边界条件,确保每个求解过程的可行域是原并集中的一个子集。
- 初始点选择:为每个子集选择靠近潜在最优解的初始点(比如子集A选(-2,-2),子集B选(-4,1),子集C选(1,-4)),避免优化器陷入局部最优。
- 结果对比:直接对比三个子集的目标函数值,取最小对应的解作为全局最优。
内容的提问来源于stack exchange,提问作者Leelou
相关产品推荐
相关产品推荐

