python 集合并的可行域在科学中的表示

jm2pwxwz  于 2023-04-19  发布在  Python
关注(0)|答案(1)|浏览(117)

我是scipy优化的新手。我有一个非线性问题,其中可行域如下:

我怎样用scipy表达这个区域?
我所能做的就是将可行域定义为约束的交集,但当涉及到用联合运算符定义区域时,我就卡住了。
下面是我想到的:

import matplotlib.pyplot as plt
from matplotlib.patches import Rectangle
import numpy as np
from scipy.optimize import NonlinearConstraint, Bounds, minimize

############ plot ############

# Define fesible region X
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)

# Generate a grid of points to plot X
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]])

# Create a figure and plot X
fig, ax = plt.subplots(figsize=(8,8))
ax.pcolormesh(X, Y, Z, cmap='binary')

# Show the individual parts of the region
rect1 = Rectangle((-2,-2), 2, 2, linewidth=1, edgecolor='r', facecolor='none')
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)

# Set limits and labels
ax.set_xlim([-4, 1])
ax.set_ylim([-4, 1])
ax.set_xlabel('x[0]')
ax.set_ylabel('x[1]')

plt.show()

############ solve ############

# Define the objective function
def objective(x):
    return (x[0]+x[1])

# Define the feasible region
def constraint(x):
    if -4 <= x[0] <= -2: 
     return x[1]
    if 0<=x[0]<=1:
        return x[1]+4
    return  x[0]**2 + x[1]**2-4

# Define the bounds for the (x1, x2)
b = [(-4, 1), (-4, 1)]

# Define the constraints 
cons =  NonlinearConstraint(constraint,lb=0, ub=np.inf)

# Minimize the defined problem
result = minimize(objective, [0, 0], bounds=b, constraints=cons)

# Print (x1,x2)
print("The value of x1 at the minimum is:", result.x[0])
print("The value of x2 at the minimum is:", result.x[1])
ulydmbyx

ulydmbyx1#

上、右、左约束为单变量常数,下约束可以建模为分段非线性约束。

import matplotlib.pyplot as plt
import numpy as np
from matplotlib.axes import Axes
from scipy.optimize import minimize, Bounds, NonlinearConstraint

fig, ax = plt.subplots()
ax: Axes

'''
y^2 <= 4 - x^2
y <= +/- sqrt(4 - x^2)

x^2 + y^2 - 4 <= 0, -2 <= x <= 1, -2 <= y <= 1   |
                    -4 <= x <= 0,  0 <= y <= 1   |
                     0 <= x <= 1, -4 <= y <= 0
'''
x = np.linspace(start=-2, stop=1, num=100)
ax.fill_between(x, -np.sqrt(4 - x*x), np.ones_like(x), color='green')
ax.fill_between((-4, 0), ( 0,  0), (1, 1), color='blue')
ax.fill_between(( 0, 1), (-4, -4), (0, 0), color='red')
plt.show()

def objective(xy: np.ndarray) -> float:
    x, y = xy
    return x + y

def y_piecewise(xy: np.ndarray) -> float:
    x, y = xy
    if x < -2:
        return y
    if x >= 0:
        return y + 4
    return y + np.sqrt(4 - x**2)

result = minimize(
    fun=objective,
    x0=(0,0),
    bounds=Bounds(lb=(-4, -4), ub=(1, 1)),
    constraints=NonlinearConstraint(
        fun=y_piecewise, lb=0, ub=np.inf,
    ),
)
print(result)

请注意,这本身并不一定足以产生有意义的优化。由于约束是不可微的,问题对起始条件很敏感。

相关问题