下山单纯形法求函数最小值

在这里插入图片描述
上智能优化课的作业,老师布置的作业。无奈上课没听,不知道怎么做。找了一圈也没找到好用的代码,就一个C++的,用起来还麻烦。于是我索性自己写了一个python版的。

import numpy as np

def func(x, y):
    return x ** 2 - 4 * x + y ** 2 - y - x * y

def go(good: np.array, medium:np.array, bad:np.array, f: 'function'):
    alpha = good - bad
    beta = medium - bad
    new = bad + alpha + beta        # 先做一次反射
    if f(*new) < f(*good):              # 反射点比最好点好
        new_ex = new + (alpha + beta) / 2   # 扩张反射点
        if f(*new_ex) < f(*new):            # 扩张点比反射点好
            return [good, medium, new_ex]
        return [good, medium, new]
    elif f(*new) > f(*good):            # 反射点比最好点差
        new_sr = new - (alpha + beta) / 4   # 收缩扩张点
        if f(*new_sr) < f(*bad):            # 收缩点1比最坏点好
            return [good, medium, new_sr]
        bad_sr = bad + (alpha + beta) / 4   # 最坏点收缩
        if f(*bad_sr) < f(*bad):            # 收缩点2比最坏点好
            return [good, medium, bad_sr]
        good2 = bad - alpha / 2             # 压缩
        medium2 = medium - beta / 2
        return [good2, medium2, bad]
    else:
        return [good, medium, new]

def simplex(x0, f, d, n=100):
	'''
	x0: 初试点
	f: 目标函数
	d: 精度(没用上)
	n: 最大迭代次数
	'''
    sol = [np.array(x) for x in x0]
    pre_val = 1e10
    while True:
        sol = sorted(sol, key=lambda x: f(*x))
        if n < 0:       # 防止循环次数过多
            return
        n -= 1
        val = f(*sol[0])
        # if abs(val - pre_val) < d:	# 本来想用差值小于定值作为循环结束条件
        #     return					# 结果可能是我逻辑有问题,有时候一次迭代后函数值不变
        pre_val = val
        print('solution: ', [list(np.round(x, 5)) for x in sol], ', value: ', [f(*x) for x in sol], ', best: ', val)
        sol = go(*sol, f)

if __name__ == '__main__':
    simplex([[0, 0], [1.2, 0], [0, 0.8]], func, 1e-5, 24)

如果代码有问题欢迎大佬指正,我感觉可能有点小问题,不过可以正常求解。

solution:  [[1.2, 0.0], [0.0, 0.8], [0, 0]] , value:  [-3.36, -0.15999999999999992, 0] , best:  -3.36
solution:  [[1.8, 1.2], [1.2, 0.0], [0.0, 0.8]] , value:  [-5.88, -3.36, -0.15999999999999992] , best:  -5.88
solution:  [[1.8, 1.2], [2.25, 0.5], [1.2, 0.0]] , value:  [-5.88, -5.3125, -3.36] , best:  -5.88
solution:  [[2.85, 1.7], [1.8, 1.2], [2.25, 0.5]] , value:  [-6.932499999999999, -5.88, -5.3125] , best:  -6.932499999999999
solution:  [[2.85, 1.7], [2.3625, 1.925], [1.8, 1.2]] , value:  [-6.932499999999999, -6.63578125, -5.88] , best:  -6.932499999999999
solution:  [[3.00937, 2.11875], [2.85, 1.7], [2.3625, 1.925]] , value:  [-6.986923828125, -6.932499999999999, -6.63578125] , best:  -6.986923828125
  • 3
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
### 回答1: 下山单纯形法是一种数学优化方法,用来求解线性规划问题。它可以用多种编程语言实现,比如C/C++、Java、Python等。下面是一个用Python实现下山单纯形法的示例代码:import numpy as npdef simplex(A, b, c): n, m = A.shape assert n == len(b) assert m == len(c) B = np.array(range(m, m + n)) cB = c[B] AB = A[:, B] xB = np.linalg.solve(AB, b) while True: c_red = c - np.dot(cB.T, np.linalg.inv(AB).dot(A)) j = np.argmax(c_red) if c_red[j] <= 0: break u = np.linalg.solve(AB, A[:, j]) if np.all(u <= 0): return None theta = np.min(xB / u) xB = xB - theta * u i = np.argmin(xB / u) B[i] = j cB[i] = c[j] return xB, cB.sum() ### 回答2: 下山单纯形法(Nelder-Mead算法)是一种无约束优化算法,用于求解无约束非线性优化问题。其代码实现可以按照以下步骤进行: 1. 首先,定义目标函数,确定需要优化的变量个数和初始取值,设置收敛条件(例如最大迭代次数或误差限制)。 2. 创建一个初始简单形状,例如一个等边三角形,每个顶点代表一个变量取值组合。 3. 计算每个顶点对应的目标函数值,并按照目标函数值的大小对顶点进行排序。 4. 计算重心(剔除最差的顶点,即目标函数值最大的顶点,并计算其余顶点的质心)。 5. 尝试寻找更好的顶点(通过尝试不同的运算符,例如反射、扩展和收缩来获得新的顶点)。 6. 根据新的顶点计算目标函数值,并按照目标函数值的大小对顶点进行排序。 7. 检查是否满足终止条件,如达到最大迭代次数或目标函数值足够小。 8. 如果未满足终止条件,则返回第3步,继续优化。 这是一个简单的概述,实际代码的细节还要根据具体的编程语言和问题进行相应的实现。这个算法的关键是在每一步基于当前顶点选择合适的运算符来生成新的顶点,并通过比较目标函数值来进行排序。 ### 回答3: 下山单纯形法(Downhill simplex method)是一种用于非线性优化的算法。其基本思想是通过构建一个单纯形(simplex)的几何结构,在每一步迭代中不断缩小目标函数的范围,最终找到目标函数的最小值点。 下山单纯形法代码的实现主要包括以下几个步骤: 1. 初始化算法参数:包括单纯形的维度、单纯形各个顶点的初始化值、目标函数、迭代停止条件等。 2. 计算目标函数的值:根据当前单纯形的顶点坐标,计算目标函数在各个顶点上的值。 3. 对单纯形的顶点进行排序:根据目标函数值的大小,对单纯形的顶点进行排序,将目标函数值最小的顶点放在第一个位置。 4. 计算单纯形的重心:将目标函数值最小的顶点除外,通过计算剩余顶点的平均值,得到当前单纯形的重心坐标。 5. 根据重心坐标生成新的顶点:通过一定的步长和方向,生成离重心最远的点,也即单纯形的扩张点。 6. 比较新点和目标函数值最小的顶点,确定是否替换:如果新点的目标函数值小于目标函数值最小的顶点,则进行替换操作;否则,进行下一步。 7. 判断迭代停止条件:判断是否满足迭代停止条件,如达到最大迭代次数或目标函数值的变化小于一定阈值,如果满足则结束迭代,否则返回第3步。 8. 返回结果:返回当前单纯形各个顶点的坐标,以及目标函数在最小值点的值。 需要注意的是,下山单纯形法的代码实现比较复杂,需要仔细理解并正确实现各个步骤。同时,还需要根据具体问题进行适当的调整和优化,以提高算法的效率和准确性。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值