梯度法

 
from sympy import *
import  math
# a,b,c代表三个未知数,l代表步长
a,b,c,l = symbols("a b c l")
#函数表达式
f = 4*a**2 + 2*b**2 + 2*c**2

def deriv(f, x):
    f_x = diff(f, x, 1)
    return f_x

def f_count(a, b, c):
    f_result = 2*a**2 + 2*b**2 + 2*c**2
    return f_result

def f_search(p,grads):
    l = symbols("l")
    t = f.subs({a: p[0] + l * grads[0], b: p[1] + l * grads[1], c: p[2] + l * grads[2]})
    print("搜索函数为:", t)
    return t

# 2-范数(模)
def norm(x,y,z):
    return math.sqrt(x**2 + y**2 + z**2)

def count_l(t):
    # 令 t函数的导数为零,求解步长l
    l = symbols("l")
    t_deriv = deriv(t, l)
    l = solve(Eq(t_deriv), l)
    l = float(l[0])
    print("步长l为:",l)
    return l

def next_point():
    pass

if __name__ == "__main__":
    p = []
    variable = ["x", "y", "z"]
    for i in variable:
        p.append(int(input("请输入初始点%c坐标---->" % i)))
    e = float(input("请输入收敛精度---->"))
    print("初始点坐标为:", p)



    # 分别对a,b,c求偏导
    f_a = deriv(f, a)
    f_b = deriv(f, b)
    f_c = deriv(f, c)
    # print(f_a, f_b, f_a)
    grads = [0,0,0]  # 初始化列表
    grads[0] = -(f_a.subs(a, p[0]))
    grads[1] = -(f_b.subs(b, p[1]))
    grads[2] = -(f_c.subs(c, p[2]))


    while norm(grads[0], grads[1], grads[2]) > e :
        # 求在P点的负梯度
        grads = [0,0,0] # 初始化列表
        grads[0] = -(f_a.subs(a, p[0]))
        grads[1] = -(f_b.subs(b, p[1]))
        grads[2] = -(f_c.subs(c, p[2]))
        print("在",p,"点负梯度为:",grads)
        # 沿负梯度方向做一维搜索
        # t = f.subs({a: p[0] + l * grads[0], b: p[1] + l * grads[1], c: p[2] + l * grads[2]})
        # print("搜索函数为:", t)
        t = f_search(p, grads)

        # # 令 t函数的导数为零,求解步长l
        # t_deriv = deriv(t, l)
        # print(t_deriv)
        # l = solve(Eq(t_deriv), l)
        # l = float(l[0])
        # print(l)
        l = count_l(t)

        # 下一迭代点
        for i in range(3):
            p[i] = p[i] + l * grads[i]
        print(p)
    else:
        print("循环结束")







  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值