非线性规划问题——选址问题模型的建立与求解

非线性规划问题

一般形式

min ⁡ F ( x ) subject to: g i ( x ) ≥ 0 ( i = 1 , 2 , ⋯   , p ) h j ( x ) = 0 ( j = q + 1 , q + 2 , ⋯   , q ) \begin{aligned} & \min F(x) \\ & \text{subject to:} & & g_i(x) \geq 0 \quad (i = 1, 2, \cdots, p) \\ & & & h_j(x) = 0 \quad (j = q+1, q+2, \cdots, q) \end{aligned} minF(x)subject to:gi(x)0(i=1,2,,p)hj(x)=0(j=q+1,q+2,,q)

选址问题

问题背景

设某城市有某种物品的10个需求点,第 i i i个需求点 p i p_{i} pi的坐标为(a,b),道路网与坐标轴平行,彼此正交。现打算建一个物品的供应中心,且由于受到城市某些条件的限制,该供应中心只能设在 x x x界于[3,8], y y y界于[4,10]的范围之内(可以取小数)。问该中心应建在何处为好?

a i a_i ai1435912620178
b i b_i bi2108181451089

问题分析

这里来使用曼哈顿距离来定义两点之间的距离,曼哈顿距离(Manhattan Distance)是一种基于网格的距离度量方法。在二维平面中,两个点 ( x 1 x_1 x1, y 1 y_1 y1)和 ( x 2 x_2 x2, y 2 y_2 y2))之间的曼哈顿距离定义为:
d Manhattan = ∣ x 1 − x 2 ∣ + ∣ y 1 − y 2 ∣ d_\text{Manhattan}=|x_1-x_2|+|y_1-y_2| dManhattan=x1x2+y1y2
由于城市的道路网是平行于坐标轴的,因此两个点之间的距离计算使用曼哈顿距离是合理的。我们需要在给定的坐标范围内选择一个最佳位置 (x,y),使得供应中心到所有需求点的最大曼哈顿距离最小。这一问题实际上是一个优化问题,目标是最小化最大曼哈顿距离。

模型建立

目标函数

我们需要最小化从供应中心到所有需求点的总距离。这种情况下,距离是曼哈顿距离(因为道路网与坐标轴平行且彼此正交),即目标函数为:
min ⁡ ∑ i = 1 10 ( ∣ x − a i ∣ + ∣ y − b i ∣ ) \min\sum_{i=1}^{10}\left(|x-a_i|+|y-b_i|\right) mini=110(xai+ybi)
约束条件

该供应中心只能设在 x x x界于[3,8], y y y界于[4,10]的范围之内,所以供应中心的坐标需要满足以下约束:
3 ≤ x ≤ 8 4 ≤ y ≤ 10 \begin{aligned}3&\leq x\leq8\\4&\leq y\leq10\end{aligned} 34x8y10
建立完整的优化模型
min ⁡ ∑ i = 1 10 ( ∣ x − a i ∣ + ∣ y − b i ∣ ) s. t. { 3 ⩽ x ⩽ 8 4 ⩽ y ⩽ 10 \min\sum_{i=1}^{10}\left(|x-a_i|+|y-b_i|\right) \\\text{s. t.}\begin{cases}3\leqslant x\leqslant8\\4\leqslant y\leqslant10\end{cases} mini=110(xai+ybi)s. t.{3x84y10

模型求解

使用SLSQL算法进行优化
  1. 导入必要的库

    import numpy as np
    from scipy.optimize import minimize
    

    numpy:用于处理数组和数学运算的库。

    minimizescipy.optimize 模块中的一个函数,用于最小化标量函数。

  2. 定义需求点的坐标

    a = np.array([1, 4, 3, 5, 9, 12, 6, 20, 17, 8])
    b = np.array([2, 10, 8, 18, 1, 4, 5, 10, 8, 9])
    

    ab 是两个数组,分别表示10个需求点在二维平面上的横坐标和纵坐标。

    例如,第一个需求点的坐标为 (1, 2),第二个需求点的坐标为 (4, 10)。

  3. 定义目标函数

    def func(x):
        # 计算供应中心到各需求点的曼哈顿距离和
        total_distance = np.sum(np.abs(x[0] - a) + np.abs(x[1] - b))
        return total_distance
    

    func(x) 是需要最小化的目标函数。

    输入x 是一个包含两个元素的数组,分别表示供应中心的横坐标和纵坐标。

    计算np.abs(x[0] - a) 计算供应中心与各需求点在横坐标上的绝对距离,np.abs(x[1] - b) 计算在纵坐标上的绝对距离。两个绝对距离相加即为曼哈顿距离。

    返回值:将所有需求点的曼哈顿距离求和,作为目标函数的返回值。

  4. 定义约束条件

    bounds = [(3, 8), (4, 10)]
    

    bounds 是优化变量的约束条件。

    供应中心的横坐标 x x x的范围是 [3, 8]。供应中心的纵坐标 y y y 的范围是 [4, 10]。

  5. 定义初始猜测位置

    x0 = [6, 6]
    

    x0 是供应中心位置的初始猜测值。这里假设供应中心初始位于 (6, 6)。

  6. 使用SLSQP算法进行优化

    res = minimize(func, x0, bounds=bounds, method="SLSQP")
    

    minimize 函数尝试最小化目标函数 func

    输入参数

    func:需要最小化的目标函数。

    x0:初始猜测的供应中心位置。

    bounds:供应中心位置的约束条件。

    method="SLSQP":指定优化算法为 SLSQP(Sequential Least Squares Quadratic Programming)。

    输出res 是优化结果的对象,包含最优解、最小目标函数值等信息。

  7. 输出最优解和最小曼哈顿距离和

    print(f"供应中心应设置在坐标 ({res.x[0]:.2f}, {res.x[1]:.2f}) 处。")
    print(f"最小曼哈顿距离和为: {res.fun:.2f}")
    

    res.x:最优供应中心的坐标。res.x[0] 是横坐标,res.x[1] 是纵坐标。通过 :.2f 格式化为保留两位小数的浮点数。

    res.fun:优化后的最小目标函数值,即最小曼哈顿距离和。

完整代码:

import numpy as np
from scipy.optimize import minimize

# 需求点的坐标
a = np.array([1, 4, 3, 5, 9, 12, 6, 20, 17, 8])
b = np.array([2, 10, 8, 18, 1, 4, 5, 10, 8, 9])

# 定义目标函数
def func(x):
    # 计算供应中心到各需求点的曼哈顿距离和
    total_distance = np.sum(np.abs(x[0] - a) + np.abs(x[1] - b))
    return total_distance

# 定义坐标的约束条件
bounds = [(3, 8), (4, 10)]

# 初始猜测位置
x0 = [6, 6]

# 使用SLSQP算法进行优化
res = minimize(func, x0, bounds=bounds, method="SLSQP")

# 输出最优解
print(f"供应中心应设置在坐标 ({res.x[0]:.2f}, {res.x[1]:.2f}) 处。")
print(f"最小曼哈顿距离和为: {res.fun:.2f}")

使用模拟退火算法求解

模拟退火算法是一种用于全局优化问题的概率算法,尤其适用于寻找函数的全局最优解。它模拟物理退火过程,通过在初始阶段允许较大的随机性逐渐降低温度,从而逐步收敛到全局最优解。下面是使用模拟退火算法来求解供应中心位置优化问题的代码示例。

  1. 优化过程

    result = dual_annealing(func, bounds=bounds)
    

    使用 scipy.optimize.dual_annealing 函数,这是专门为模拟退火设计的优化函数。

    该函数不需要初始猜测值,只需要传入目标函数和边界。

  2. 输出结果

    同样返回一个 OptimizeResult 对象,通过 result.x 获取最优解,通过 result.fun 获取最小目标值。

    由于算法的随机性,它在全局范围内搜索,结果更可能是全局最优解。

完整代码:

from scipy.optimize import dual_annealing

# 调用模拟退火进行优化
result = dual_annealing(func, bounds=bounds)

# 输出结果
print(f"最优解: {result.x}")
print(f"最小曼哈顿距离和: {result.fun}")

两种算法的区别

对比维度SLSQP 代码模拟退火代码
优化函数scipy.optimize.minimize,指定 method="SLSQP"scipy.optimize.dual_annealing
初始猜测值需要提供初始猜测值 x0不需要初始猜测值,自动在边界内随机选择初始点
函数调用格式python<br>res = minimize(func, x0, bounds=bounds, method="SLSQP")<br>python<br>result = dual_annealing(func, bounds=bounds)<br>
返回结果res.x 获取最优解,res.fun 获取最小目标值result.x 获取最优解,result.fun 获取最小目标值
收敛速度较快,依赖梯度信息并通过局部优化实现相对较慢,因为模拟退火需要在初期进行广泛搜索
对初始条件敏感性高,结果强烈依赖初始猜测值,如果初始点不好,可能收敛到局部最优解低,由于在全局范围内搜索,即使初始点不好,也可能找到全局最优解
代码复杂度代码简洁,但需要合理选择初始猜测值代码简单,自动处理初始条件,但可能需要更多迭代时间
适用场景适用于规则连续且对初始猜测值比较明确的场景适用于复杂、不规则、具有多个局部最优的场景
  • 20
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

自由自在2004

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值