关于python:Python干货python实现最优化算法

5次阅读

共计 5721 个字符,预计需要花费 15 分钟才能阅读完成。

二分法

函数详见 rres,此代码使该算法运行了两次

def asdf(x):
    rres=8*x**3-2*x**2-7*x+3
    return rres

i=2
left=0
right=1
while i>0 :
    i = i-1
    ans = 0.1
    mid1 = (left + right + ans) / 2
    mid2 = (left + right - ans) / 2
    a=asdf(mid1)
    c=asdf(mid2)
    if a > c :
        right = mid1
    else :
        left = mid2
b=(left+right) / 2
print("左极限 =%s, 右极限 =%s, 极小值 x =%s"%(left,right,b))
 左极限 =0.45, 右极限 =0.775, 极小值 x =0.6125

播种:
这是我第一个实现的代码。学习完该算法当前,逻辑框架基本上就有了,剩下须要明确的就是对应的 python 的语言。于是我就开始了查找“如何定义函数”(详见 mofan 的优酷),“循环体”和“if 条件语句”的格局(https://blog.csdn.net/qq\_39407518/article/details/79822498)“数学符号”(详见 mofan 的优酷),以及 print 的应用

1.def 是 python 中指定义,个别用来定义函数,如果须要深度学习搭建网络可用来定义网络。值得注意的一点是

return 必须要加在函数前面另起一行。

我不分明为什么,然而如果没有加的话,那个函数公式就是一个花瓶,就像一个后果输不进来。

2. 最坑的就是逻辑。一开始逻辑没理分明,或者说在代码上有疏漏,导致我将 left 和 right 放在了循环体里,后果可想而知。不过也是因为这个谬误,我晓得 pycharm 中的 debug 怎么用,挺简略的,百度一下就进去了。

3. 不晓得什么起因,看的莫烦视频中的 print 多个变量一起输入是没有方法在我的 pycharm 中应用的,进去的后果很奇怪。可能是因为我是 win10 不是 ios 吧。print 如果多个变量一起输入必须是 print(“ 名字:%s, 名字 2:%s”%(a,b)) 后果输入就是名字:a , 名字 2:b

问题:1. 为什么要加 return?

return 的意思是输入这个 def 外面任意一个变量值作为结果显示。个别状况而言,是输入函数的关系式的命名,这样当你调用这个函数的时候,变量对应的函数值能力显示进去,否则只运行没有后果,不会有成果。

格点法——三点等分法

import numpy as np
def qwer(x):
    third = np.exp(x) - 5*x
    return third

left = 1
right = 2
mid1 =float(left+right) / 2
mid2 = (left+mid1) / 2
mid3 = (mid1+right) /2
a = qwer(mid1)
b = qwer(mid2)
c = qwer(mid3)
i = 5
while i > 0:
    i=i-1
    if a > b:
        if c > b :
            #b
            right = mid1
            mid1 = mid2
            a=b
            mid2 = (left + mid1) / 2
            mid3 = (mid1 + right) / 2
            b = qwer(mid2)
            c = qwer(mid3)
        else:#b>c
            #c
            left = mid1
            mid1 = mid3
            a = c
            mid2 = (left + mid1) / 2
            mid3 = (mid1 + right) / 2
            b = qwer(mid2)
            c = qwer(mid3)
    else:#b>a
            if a > c:
                #C
                left = mid1
                mid1 = mid3
                a = c
                mid2 = (left + mid1) / 2
                mid3 = (mid1 + right) / 2
                b = qwer(mid2)
                c = qwer(mid3)
            else:#b>a&c>a
                # a
                left = mid2
                right = mid3
                mid2 = (left + mid1) / 2
                mid3 = (mid1 + right) / 2
                b = qwer(mid2)
                c = qwer(mid3)

print("最小值 =%s"%mid1)
print("函数值 =%s"%a)
 最小值 =1.609375
函数值 =-3.047189552275773

对于 python 中数据变量。第一遍运行后果呈现很显著不对,于是我采纳了 debug。后果发现,mid1 处始终为 1 而不是 1.5,于是就开始理解数据变量。起初我猜想 python 默认所有变量为整型,然而依据二分法的后果我意识到此猜想不对,所以要改整个 file 的变量格局没有必要。所以我就在 mid1 式子后面加了一个 float,后果就显示为 1.5 了。然而如果我将整个式子用()括起来,后面加 float,后果还是 1。我不太了解为什么。不过我晓得了 python 的数据格式是依据输入量决定的,也就是说你的输入量如果是整型,那么与其间接相干的计算输入后果肯定是整型,而且还是不采纳进位的整型。在我没有采纳 +float/+.0 这两种办法之前,mid1~3 全副是整型。

left = 1.0
right = 2.0
mid1 =(left+right) / 2

或者不再 mid1 后面加 float, 间接将输入量前面点个点就行
真的很想吐槽一下 print, 好麻烦啊啊啊啊每次都得弄个 %s, 而且有时候还不能放一起!!!!

Fibonacci 法

def fibonacci(n):
    i=0
    a = 0
    b = 1
    for i in range(n):
        i=i+1
        c = a+b
        a = b
        b = c
    return c
def bn(x):
    ert = x**2 - 6*x + 2
    return ert
z = 2
p = 0
left = 0.00000
right = 10.00000
L1 = right - left
while z < 100:
    m = fibonacci(z)
    l = L1/m
    k = 1.000/m
    if k < 0.03:
        print("n=%s,Fn=%s"%(z,m))
        L2 = l*fibonacci(z-1)
        t = left + L2
        r = right -L2
        while p < 3:
            p = p + 1
            l3 = t - r
            e= bn(t)
            o = bn(r)
            if e>o :
                right = t
                t = r
                r = left + l3
            else:#o>e
                left = r
                r = t
                t = right - l3
        break
    else:
        z = z + 1

okk=(left+right)/2
okky=bn(okk)
print(left)
print(right)
print("极小值 x =",okk)
print("极小值 y =",okky)

不要问我把握了什么,要问我当初写完这个代码后有如许的爱 python 的精度示意 :-) 我决定当前只有再编写数学公式的代码都将输入量的小数学点前面补很多 0
fibonacci 函数定义,每次 debug 后我的手都是抖的 O(∩\_∩)O~

黄金分割法

def gold(x):
    gg= x**2 - 6*x + 9
    return gg

left = 1
right = 7
ans = 0.4
a = left + 0.618 * (right - left)
b = left + 0.382*(right - left)
gga = gold(a)
ggb = gold(b)
i = 0
while i < 7:
    print("i=%s" % i)
    print("left=%s,right=%s" % (left, right))
    print("x 左 =%s,x 右 =%s" % (a, b))
    print("y 左 =%s,y 右 =%s" % (ggb, gga))
    c = right - left
    if c > 0.4:
        i = i + 1
        if gga > ggb:
            right = a
            a = b
            b = left + 0.382*(right - left)
            gga = ggb
            ggb = gold(b)
        else:#gga<ggb
            left = b
            b = a
            a = left + 0.618 * (right - left)
            ggb = gga
            gga = gold(a)
    else:
        break

不晓得本人什么时候有的强迫症,只有是代码上面有“~”我就必须要消掉。笑哭。这个很简略,前四个除了费波纳茨,都很简略。

间接法——二次插值法

def yy(x):
    y=x**4-4*x**3-6*x**2-16*x+4
    return y

def xing(xm1,xm2,xm3,fm1,fm2,fm3):
    yxxx=0.5000*((xm2**2-xm3**2)*fm1+(xm3**2-xm1**2)*fm2+(xm1**2-xm2**2)*fm3)/((xm2-xm3)*fm1+(xm3-xm1)*fm2+(xm1-xm2)*fm3)
    return yxxx

x1 = -1.0000
f1 = yy(x1)
x3 = 6
f3 = yy(x3)
x2 = 0.50000*(x1+x3)
f2 = yy(x2)
xp = xing(x1,x2,x3,f1,f2,f3)
fp = yy(xp)
a = abs(xp-x2)
while abs(xp-x2) > 0.05000:
    a = abs(xp - x2)
    if xp > x2:
        if fp > f2:
            x3=xp
            f3=fp
            xp = xing(x1, x2, x3, f1, f2, f3)
            fp = yy(xp)
            print("ans=%s" % a)
            print("left=%s,right=%s" % (x1, x3))
            print("x*=%s,fp*=%s" % (xp, fp))
            print("x2=%s,f2=%s" % (x2, f2))
            print("******************")
        else:#f2>fp
            x1 = x2
            f1 = f2
            x2 = xp
            f2 = fp
            xp = xing(x1, x2, x3, f1, f2, f3)
            fp = yy(xp)
            print("ans=%s" % a)
            print("left=%s,right=%s" % (x1, x3))
            print("x*=%s,fp*=%s" % (xp, fp))
            print("x2=%s,f2=%s" % (x2, f2))
            print("******************")
    else:#xp<x2
        if fp > f2:
            x1 = xp
            f1 = fp
            xp = xing(x1, x2, x3, f1, f2, f3)
            fp = yy(xp)
            print("ans=%s" % a)
            print("left=%s,right=%s" % (x1, x3))
            print("x*=%s,fp*=%s" % (xp, fp))
            print("x2=%s,f2=%s" % (x2, f2))
            print("******************")
        else:
            x3 = x2
            f3 = f2
            x2 = xp
            f2 = fp
            xp = xing(x1, x2, x3, f1, f2, f3)
            fp = yy(xp)
            print("ans=%s" % a)
            print("left=%s,right=%s" % (x1, x3))
            print("x*=%s,fp*=%s" % (xp, fp))
            print("x2=%s,f2=%s" % (x2, f2))
            print("******************")

这个公式看起来很麻烦,便写的时候更要审慎。我上回把那个 2 搁在了分号上面,后果很大,所以还是换算成 0.5 更好(PS:勿忘那长河般的 0)。
尽管代码很长,然而次要是因为 print 太多。本打算在结尾 print,最初后果会漏掉最初一部分。懒得想其余方法了,间接就这样吧

间接法——牛顿法

def fd(x):
    y = 4*x**3-12*x**2-12*x-16
    return y
def fdd(x):
    ys = 12*x**2-24*x-12
    return ys

i = 1
x0 = 3.00000
ans = 0.001
while i < 7:
    fd0 = fd(x0)
    fdd0 = fdd(x0)
    if abs(fd0) > ans:
        x1 = x0 - (fd0/fdd0)
        x0 = x1
        print("次数:%s, 所得的值 x:%s"%(i,x1))
        i = i + 1
    else:#fd0<0.001
        print("$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$")
        print("Bingo! 顺利通关!祝您开学欢快!")
        print("Boss  X=%s"%x0)
        break

一开始 while 外面 < 写成了 >, 导致 run 不进去。继而,debug 也没法用。在网上一查才晓得“没联网”+“没选断点”。最初想尝试将 else 外面的内容输入来,后果发现 run 当前被刷屏了。于是改成 i <7 当前还是不行,于是想着加一个 break 跳出循环,后果功效了。
而后刚刚由 debug 了一下,才晓得原来是 i + 1 在 if 外面,因为没有方法 +1,所以 i = 6 始终存在,就一直循环。因为加 break 也好,i+ 1 也好,都能够。

就在一个半小时前,我胜利搞完了最优化六大代码,纯手打,无外力。开心!

这是我第一组本人实现的 python 代码,就是数学公式用 python 语言组装起来。刚开始的时候晓得大略须要在语言中体现什么,但不太分明。于是我就在网上找了几个二分法的,他们都各有不同,但框架都差不多,不过如果要用到咱们的那个公式里还须要扭转很多。而后我就开始剖析咱们的题,我发现大体须要两局部,一部分函数定义,一部分循环体。但我不晓得如何定义函数,如何写数学公式,如何弄变量,也就是说一些小点不太会,所以我抉择间接百度。因为我晓得本人浏览的能力不错,相比于从视频中提取因素,我更善于通过浏览取得要点。有目的性地找知识点,把握地更牢固。
于是我就开始了第一个——二分法的编写。我发现,本人呈现了很多谬误而且有很多中央都很根底。但我仍然没抉择视频,而是将这些问题间接在百度上找,因为视频讲完或者你也没找到点。当然,这是一步一步走的,不是间接就将程序摆上去,一点一点改。
随着前两个的胜利,我发现自己对于这些代码有了自信,仿佛看透了他们的假装,抓住了实质。除此之外,我还意识到本人自从 8 月份当前,学习能力仿佛进步了不少,而且有了更为无效的学习办法。各方面都有了肯定的沉睡。除了第一个找了几个牛头不对马嘴的代码,其余都是依据本人的逻辑写,逻辑通下来当前,对应语言中某一部分不晓得如何翻译就去百度,其实这几个套路都一样或者说数学公式转化的套路都一样。
我还意识到,汇编其实是最难的语言,目前为止所学到的,因为很多都须要本人去定义,去死抠,须要记住大量的指令且不能灵便变通。然而其余的却只须要将一些对应的记下来就好。python 真的挺简略的。而且,我发现自己明天仿佛关上了新世界的大门,我爱上了这种充斥了灵性的货色,充斥了谨严的漂亮,还有那未知的变动,我发现我仿佛爱上了代码。可能不仅仅局限于 python,这些语言都充斥了挑战性。我感觉当你纳闷的时候,就须要置信直觉,至多我发现它很准

最初

如果文章对您有帮忙,点赞 + 关注,您的反对是我最大的能源

正文完
 0