(最优化理论与方法)第六章无约束优化算法-第一节:线搜索方法

news2024/11/25 6:49:09

文章目录

  • 一:无约束优化问题概述
  • 二:线搜索方法
    • (1)概述
    • (2)线搜索准则
      • A:Armijo准则
        • ①:概述
        • ②:Armjio准则缺陷
        • ③:回退法
        • ④:代码
      • B:Goldstein准则
        • ①:概述
        • ②:代码
      • C:Wolfe准则
        • ①:概述
        • ②:代码
      • D:非单调线搜索准则
    • (3)线搜索方法

一:无约束优化问题概述

考虑如下无约束优化问题

m i n x ∈ R n f ( x ) \mathop{min}\limits_{x\in R^{n}}f(x) xRnminf(x)

无约束优化问题是众多优化问题中最基本的一类问题,它对自变量 x x x的取值范围不加限制,所以无需考虑 x x x的可行性

  • 对于光滑函数,我们可以较容易地利用梯度和海瑟矩阵的信息来设计算法
  • 对于非光滑函数,我们可以利用次梯度来构造迭代格式

无约束优化问题的优化算法主要分为如下两类

  • 线搜索类型:根据搜索方向的不同可以分为如下几种,一旦确定了搜索的方向,下一步即沿着该方向寻找下一个迭代点

    • 梯度类算法
    • 次梯度算法
    • 牛顿算法
    • 拟牛顿算法
  • 信赖域类型:主要针对 f ( x ) f(x) f(x)二阶可微的情形,它是在一个给定的区域内使用二阶模型近似原问题,通过不断直接求解该二阶模型从而找到最优值点

二:线搜索方法

(1)概述

线搜索方法:对于本文最开始的优化问题,采用线搜索方法求解 f ( x ) f(x) f(x)最小值点的过程类似于盲人下山:假设一个人处于某个点 x x x处, f ( x ) f(x) f(x)表示此地的高度,为了寻找最低点,在点 x x x处需要确定如下两件事情

  • 下一步应该向哪一个方向行走?
  • 沿着该方向行走多远后停下以便选取下一个下山方向

以上这两个因素确定后,便可以一直重复,直到到达 f ( x ) f(x) f(x)的最小值点

线搜索类算法的数学表述为:给定当前迭代点 x k x^{k} xk,首先通过某种算法选取向量 d k d^{k} dk,之后确定正数 α k \alpha_{k} αk,则下一步迭代点可以写作

x k + 1 = x k + α k d k x^{k+1}=x^{k}+\alpha_{k}d^{k} xk+1=xk+αkdk

  • d k d^{k} dk:是迭代点 x k x^{k} xk处的搜索方向。此处要求 d k d^{k} dk是一个下降方向,也即 ( d k ) T ∇ f ( x k ) < 0 (d^{k})^{T}\nabla f(x^{k})<0 (dk)Tf(xk)<0,这个下降性质保证了沿着此方向搜索函数值会减小
  • α k \alpha_{k} αk:是相应的步长

所以线搜索类算法的关键是如何选取一个好的方向 d k d^{k} dk和合适的步长 α k \alpha_{k} αk


不同的线搜索算法对于 d k d^{k} dk的选取有着不同的方式,但 α k \alpha_{k} αk的选取方法却基本一致。首先构造辅助函数

ϕ ( α ) = f ( x k + α d k ) \phi(\alpha)=f(x^{k}+\alpha d^{k}) ϕ(α)=f(xk+αdk)

  • d k d^{k} dk:是给定的下降方向
  • α > 0 \alpha >0 α>0:是该辅助函数的自变量

函数 ϕ ( α ) \phi(\alpha) ϕ(α)的几何意义非常直观:它是目标函数 f ( x ) f(x) f(x)在射线 { x k + α d k : α > 0 } \{x^{k}+\alpha d^{k}:\alpha>0\} {xk+αdk:α>0}上的限制。线搜索的目标时选取合适的 α k \alpha_{k} αk使得 ϕ ( α k ) \phi(\alpha_{k}) ϕ(αk)尽可能小,这要求

  • α k \alpha_{k} αk应该使得 f f f充分下降
  • 不应该在寻找 α k \alpha_{k} αk上花费过度的计算量

所以一个自然的想法是寻找 α k \alpha_{k} αk使得

α k = a r g m i n α > 0 ϕ ( α ) \alpha_{k}=\mathop{argmin}\limits_{\alpha>0}\phi(\alpha) αk=α>0argminϕ(α)

这种线搜索方法称之为精确线搜索算法,虽然精确线搜索算法可以在多数情况下找到问题的解,但这通常需要非常大的计算量,所以实际应用中很少使用。所以另一个想法是不要求 α k \alpha_{k} αk ϕ ( α ) \phi(\alpha) ϕ(α)的最小值点,而仅仅要求 ϕ ( α k ) \phi(\alpha_{k}) ϕ(αk)满足某些不等式性质,因此这类方法称之为非精确线搜索算法,所以我们接下来介绍该类算法的结构

(2)线搜索准则

线搜索准则:在非精确线搜索算法中,选取 α k \alpha_{k} αk需要满足一定的要求,这些要求被称为线搜索准则。不合适的线搜索准则会导致算法无法收敛

  • 例如下面这个例子,由于迭代过程中函数值 f ( x k ) f(x^{k}) f(xk)的下降量不够充分,以至于算法无法收敛至极小值点
    在这里插入图片描述

所以为了避免这种情况发生,必须要引入一些更合理的线搜索准则来确保迭代的收敛性

A:Armijo准则

①:概述

Armijo准则:设 d k d^{k} dk是点 x k x^{k} xk处的下降方向,若

f ( x k + α d k ) ≤ f ( x k ) + c 1 α ∇ f ( x k ) T d k f(x^{k}+\alpha d^{k})\leq f(x^{k})+c_{1}\alpha \nabla f(x^{k})^{T}d^{k} f(xk+αdk)f(xk)+c1αf(xk)Tdk

则称步长 α \alpha α满足Armijo准则,其中 c 1 ∈ ( 0 , 1 ) c_{1}\in(0,1) c1(0,1)是一个常数。其几何意义是指点 ( α , ϕ ( α ) ) (\alpha, \phi(\alpha)) (α,ϕ(α))必须在直线

l ( α ) = ϕ ( 0 ) + c 1 α ∇ f ( x k ) T d k l(\alpha)=\phi(0)+c_{1}\alpha\nabla f(x^{k})^{T}d^{k} l(α)=ϕ(0)+c1αf(xk)Tdk

的下方

如下图所示,区间 [ 0 , α 1 ] [0,\alpha_{1}] [0,α1]中的点均满足Armijo准则。 d k d^{k} dk为下降方向,这说明 l ( α ) l(\alpha) l(α)方向,这说明 l ( α ) l(\alpha) l(α)斜率为负,选取符合条件的 α \alpha α确实会使得函数值下降
在这里插入图片描述

②:Armjio准则缺陷

Armjio准则缺陷:实际应用中,参数 c 1 c_{1} c1通常选为一个很小的正数(例如 c 1 = 1 0 − 3 c_{1}=10^{-3} c1=103),这使得Armijo准则非常容易得到满足,但仅仅使用Armijo准则无法保证迭代的收敛性。这是因为 α = 0 \alpha=0 α=0时显然满足条件 f ( x k + α d k ) ≤ f ( x k ) + c 1 α ∇ f ( x k ) T d k f(x^{k}+\alpha d^{k})\leq f(x^{k})+c_{1}\alpha \nabla f(x^{k})^{T}d^{k} f(xk+αdk)f(xk)+c1αf(xk)Tdk,而这意味着迭代序列中的点固定不变,研究这样的步长是没有意义的,为此Armjio准则需要配合其他准则共同使用

③:回退法

回退法:在优化算法的实现中,寻找一个满足Armijo准则的步长是比较容易的,一个最常用的算法是回退法。给定初值 α ︿ \mathop{\alpha}\limits^{︿} α︿,回退法通过不断以指数方式缩小试探步长,找到第一个满足Armjio准则的点。具体来说,回退法选取

α k = γ j 0 α ︿ \alpha_{k}=\gamma^{j_{0}}\mathop{\alpha}\limits^{︿} αk=γj0α︿

其中

在这里插入图片描述

参数 γ ∈ ( 0 , 1 ) \gamma\in(0,1) γ(0,1)为一个定的实数,回退法基本过程如下所示

在这里插入图片描述
该算法被称为回退法是因为 α \alpha α的试验值是由大至小的,它可以确保输出的 α k \alpha_{k} αk能尽量大。此算法也会收敛,因为 d k d^{k} dk是一个下降方向,当 α \alpha α充分小时,Armijo准则总是成立的。在实际应用中我们通常也会给 α \alpha α设置一个下界,防止步长过小

④:代码

import numpy as np
from sympy import *

# 计算梯度函数
def cal_grad_funciton(function):
    res = []
    x = []
    x.append(Symbol('x1'))
    x.append(Symbol('x2'))
    for i in range(len(x)):
        res.append(diff(function, x[i]))
    return res

# 定义目标函数
def function_define():
    x = []
    x.append(Symbol('x1'))
    x.append(Symbol('x2'))
    # y = 2 * (x[0] - x[1] ** 2) ** 2 + (1 + x[1]) ** 2
    # Rosenbrock函数
    y = 100 * (x[1] - x[0] ** 2) ** 2 + (1 - x[0]) ** 2
    
    return y

# 计算函数返回值
def cal_function_ret(function, x):
    res = function.subs([('x1', x[0]), ('x2', x[1])])
    return res

# 计算梯度
def cal_grad_ret(grad_function, x):
    res = []
    
    for i in range(len(x)):
        res.append(grad_function[i].subs([('x1', x[0]), ('x2', x[1])]))
    return res

# armijo准则
"""
Parameter:
    function:函数
    grad_function:梯度函数
    x:初始迭代点
    d:下降方向
    c:armijo准的参数,范围为[0-1]
Return:
    alpha:步长

"""
def armijo(function, grad_function, x, d, c = 0.3):
    # 指定初始步长
    alpha = 1.0
    # 回退参数
    gamma = 0.333
    # 迭代次数
    k = 1.0
    
   # fd 表示 f(x + alpha * d)
    fd = cal_function_ret(function, np.add(x0, np.dot(alpha, d))) 
    # fk 表示 f(x) + c * alpha * gradf(x) * d
    fk = cal_function_ret(function, x0) + c * alpha * np.dot(cal_grad_ret(grad_function, x0), d)
    while fd  > fk :
        fd = cal_function_ret(function, np.add(x0, np.dot(alpha, d))) 
        fk = cal_function_ret(function, x0) + c * alpha * np.dot(cal_grad_ret(grad_function, x0), d)
        alpha *= gamma
        k += 1.0
    print("迭代次数:", k)
    return alpha


# armijo-goldstein准则
    
if __name__ == '__main__':
    function = function_define()
    grad_function = cal_grad_funciton(function)
    print("函数为:", function)
    print("梯度函数为:", grad_function)

    x0 = [-10, 10]
    d = cal_grad_ret(grad_function, x0)
    d = np.dot(-1, d).tolist()
    alpha = armijo(function, grad_function, x0, d)
    xk = np.add(x0, np.dot(alpha, d))
    f = cal_function_ret(function, xk)
    
    print("初始迭代点:", x0)
    print("搜索方向为:", d)
    print("获取步长为:", alpha)
    print("下降点为:", xk)
    print("下降点函数值为:", f)

在这里插入图片描述

B:Goldstein准则

①:概述

Goldstein准则:为了克服Armijo准则的缺陷,我们需要引入其他准则来保证每一步的 α k \alpha^{k} αk不会太小。既然Armijo准则只要求点 ( α , ϕ ( α ) ) (\alpha, \phi(\alpha)) (α,ϕ(α))必须在某直线下方,那么我们也可以使用相同的形式使得该点必须处在另一条直线的上方,这便是Armijo-Goldstein准则,简称Goldstein准则。设 d k d^{k} dk是点 x k x^{k} xk处的下降方向,若

  • f ( x k + α d k ) ≤ f ( x k ) + c α ∇ f ( x k ) T d k f(x^{k}+\alpha d^{k})\leq f(x^{k})+c\alpha \nabla f(x^{k})^{T}d^{k} f(xk+αdk)f(xk)+cαf(xk)Tdk
  • f ( x k + α d k ) ≥ f ( x k ) + ( 1 − c ) α ∇ f ( x k ) T d k f(x^{k}+\alpha d^{k})\geq f(x^{k})+(1-c)\alpha \nabla f(x^{k})^{T}d^{k} f(xk+αdk)f(xk)+(1c)αf(xk)Tdk

则称步长 α \alpha α满足Goldstein准则,其中 c ∈ ( 0 , 1 2 ) c\in (0,\frac{1}{2}) c(0,21)

同样,Goldstein准则也有非常直观的几何意义,它指的是点 ( α , ϕ ( α ) ) (\alpha, \phi(\alpha)) (α,ϕ(α))必须在以下两条直线之间

  • l 1 ( α ) = ϕ ( 0 ) + c α ∇ f ( x k ) T d k l_{1}(\alpha)=\phi(0)+c\alpha\nabla f(x^{k})^{T}d^{k} l1(α)=ϕ(0)+cαf(xk)Tdk
  • l 2 ( α ) = ϕ ( 0 ) + ( 1 − c ) α ∇ f ( x k ) T d k l_{2}(\alpha)=\phi(0)+(1-c)\alpha\nabla f(x^{k})^{T}d^{k} l2(α)=ϕ(0)+(1c)αf(xk)Tdk

在这里插入图片描述

②:代码

import numpy as np
from sympy import *

# 计算梯度函数
def cal_grad_funciton(function):
    res = []
    x = []
    x.append(Symbol('x1'))
    x.append(Symbol('x2'))
    for i in range(len(x)):
        res.append(diff(function, x[i]))
    return res

# 定义目标函数
def function_define():
    x = []
    x.append(Symbol('x1'))
    x.append(Symbol('x2'))
    # y = 2 * (x[0] - x[1] ** 2) ** 2 + (1 + x[1]) ** 2
    # Rosenbrock函数
    y = 100 * (x[1] - x[0] ** 2) ** 2 + (1 - x[0]) ** 2
    
    return y

# 计算函数返回值
def cal_function_ret(function, x):
    res = function.subs([('x1', x[0]), ('x2', x[1])])
    return res

# 计算梯度
def cal_grad_ret(grad_function, x):
    res = []
    
    for i in range(len(x)):
        res.append(grad_function[i].subs([('x1', x[0]), ('x2', x[1])]))
    return res

# armijo-goldstein准则
def armijo_goldstein(function, grad_function, x0, d, c = 0.3):
    # 指定初始步长
    alpha = 1.0
    # 回退参数
    gamma = 0.333
    # 迭代次数
    k = 1.0

    # fd 表示 f(x + alpha * d)
    fd = cal_function_ret(function, np.add(x0, np.dot(alpha, d))) 
    # fk 表示 f(x) + c * alpha * gradf(x) * d
    fk = cal_function_ret(function, x0) + c * alpha * np.dot(cal_grad_ret(grad_function, x0), d)
    # fp 表示 f(x) + (1-c) * alpha * gradf(x) * d
    fp = cal_function_ret(function, x0) + (1-c) * alpha * np.dot(cal_grad_ret(grad_function, x0), d)
    while fd > fk or fd < fp:
        alpha *= gamma
        fd = cal_function_ret(function, np.add(x0, np.dot(alpha, d))) 
        fk = cal_function_ret(function, x0) + c * alpha * np.dot(cal_grad_ret(grad_function, x0), d)
        fp = cal_function_ret(function, x0) + (1-c) * alpha * np.dot(cal_grad_ret(grad_function, x0), d)
        k += 1.0
    print("迭代次数:", k)
    return alpha
    
if __name__ == '__main__':
    function = function_define()
    grad_function = cal_grad_funciton(function)
    print("函数为:", function)
    print("梯度函数为:", grad_function)

    x0 = [-10, 10]
    d = cal_grad_ret(grad_function, x0)
    d = np.dot(-1, d).tolist()
    alpha = armijo_goldstein(function, grad_function, x0, d)
    xk = np.add(x0, np.dot(alpha, d))
    f = cal_function_ret(function, xk)
    
    print("初始迭代点:", x0)
    print("搜索方向为:", d)
    print("获取步长为:", alpha)
    print("下降点为:", xk)
    print("下降点函数值为:", f)

在这里插入图片描述

C:Wolfe准则

①:概述

Wolfe准则:Goldstein准则能够使得函数值充分下降,但是它可能避开了最优函数值

  • 如下图所示,一维函数 ϕ ( α ) \phi(\alpha) ϕ(α)的最小值点并不在满足Goldstein准则的区间 [ α 1 , α 2 ] [\alpha_{1}, \alpha_{2}] [α1,α2]

在这里插入图片描述

为此,我们引入Armijo准则-Wolfe准则,简称Wolfe准则。设 d k d^{k} dk是点 x k x^{k} xk处的下降方向,若

  • f ( x k + α d k ) ≤ f ( x k ) + c 1 α ∇ f ( x k ) T d k f(x^{k}+\alpha d^{k})\leq f(x^{k})+c_{1}\alpha \nabla f(x^{k})^{T}d^{k} f(xk+αdk)f(xk)+c1αf(xk)Tdk
  • ∇ f ( x k + α d k ) T d k ≥ c 2 ∇ f ( x k ) T d k \nabla f(x^{k}+\alpha d^{k})^{T}d^{k} \geq c_{2}\nabla f(x^{k})^{T}d^{k} f(xk+αdk)Tdkc2f(xk)Tdk(Wolfe准则本质要求)

∇ f ( x k + α d k ) T d k \nabla f(x^{k}+\alpha d^{k})^{T}d^{k} f(xk+αdk)Tdk恰好就是 ϕ ( α ) \phi(\alpha) ϕ(α)的导数,所以Wolfe助阵实则要求 ϕ ( α ) \phi(\alpha) ϕ(α)在点 α \alpha α处的切线斜率不能小于 ϕ ‘ ( 0 ) \phi^{`}(0) ϕ(0) c 2 c_{2} c2倍,如下图所示,区间 [ α 1 , α 2 ] [\alpha_{1}, \alpha_{2}] [α1,α2]中的点均满足Wolfe准则,在实际应用中参数 c 2 c_{2} c2一般取为0.9

在这里插入图片描述

②:代码

import numpy as np
from sympy import *

# 计算梯度函数
def cal_grad_funciton(function):
    res = []
    x = []
    x.append(Symbol('x1'))
    x.append(Symbol('x2'))
    for i in range(len(x)):
        res.append(diff(function, x[i]))
    return res

# 定义目标函数
def function_define():
    x = []
    x.append(Symbol('x1'))
    x.append(Symbol('x2'))
    # y = 2 * (x[0] - x[1] ** 2) ** 2 + (1 + x[1]) ** 2
    # Rosenbrock函数
    y = 100 * (x[1] - x[0] ** 2) ** 2 + (1 - x[0]) ** 2
    
    return y

# 计算函数返回值
def cal_function_ret(function, x):
    res = function.subs([('x1', x[0]), ('x2', x[1])])
    return res

# 计算梯度
def cal_grad_ret(grad_function, x):
    res = []
    
    for i in range(len(x)):
        res.append(grad_function[i].subs([('x1', x[0]), ('x2', x[1])]))
    return res


# armijo-wolfe准则
def armijo_wlofe(function, grad_function, x0, d, c = 0.3):
    # wolfe准则参数
    c2 = 0.9
    # 指定初始步长
    alpha = 1.0
    # 二分法确定alpah
    a, b = 0, np.inf
    # 迭代次数
    k = 1.0
    
    # gk表示gradf(x)
    gk = cal_grad_ret(grad_function, x0)
    # fd 表示 f(x + alpha * d)
    fd = cal_function_ret(function, np.add(x0, np.dot(alpha, d))) 
    # fk 表示 f(x) + c * alpha * gradf(x) * d
    fk = cal_function_ret(function, x0) + c * alpha * np.dot(cal_grad_ret(grad_function, x0), d)
    # gp表示gradf(x + alpha * d)
    gp = cal_grad_ret(grad_function, np.add(x0, np.dot(alpha, d)))
    while True:
        if fd > fk:
            b = alpha
            alpha = (a + b) / 2
            fd = cal_function_ret(function, np.add(x0, np.dot(alpha, d))) 
            fk = cal_function_ret(function, x0) + c * alpha * np.dot(cal_grad_ret(grad_function, x0), d)
            gp = cal_grad_ret(grad_function, np.add(x0, np.dot(alpha, d)))
            k = k + 1
            continue
        if np.dot(gp, d) < c2 * np.dot(gk, d):
            a = alpha
            alpha = np.min(2 * alpha, (a + b) / 2)
            fd = cal_function_ret(function, np.add(x0, np.dot(alpha, d))) 
            fk = cal_function_ret(function, x0) + c * alpha * np.dot(cal_grad_ret(grad_function, x0), d)
            gp = cal_grad_ret(grad_function, np.add(x0, np.dot(alpha, d)))
            k = k + 1
            continue
        break
    print("迭代次数:", k)
    return alpha
            
if __name__ == '__main__':
    function = function_define()
    grad_function = cal_grad_funciton(function)
    print("函数为:", function)
    print("梯度函数为:", grad_function)

    x0 = [-10, 10]
    d = cal_grad_ret(grad_function, x0)
    d = np.dot(-1, d).tolist()
    # alpha = armijo(function, grad_function, x0, d)
    alpha = armijo_wlofe(function, grad_function, x0, d)
    xk = np.add(x0, np.dot(alpha, d))
    f = cal_function_ret(function, xk)
    
    print("初始迭代点:", x0)
    print("搜索方向为:", d)
    print("获取步长为:", alpha)
    print("下降点为:", xk)
    print("下降点函数值为:", f)

在这里插入图片描述

D:非单调线搜索准则

以上三种准则都有一个共同点:使用这些准则产生的迭代点序列都是单调的,但在实际应用中,非单调算法有时会有更好的效果,这里主要介绍两种

Grippo准则:设 d k d^{k} dk是点 x k x^{k} xk处的下降方向, M > 0 M>0 M>0为给定的正整数,以下不等式可以作为一种线搜索准则

在这里插入图片描述

其中 c 1 ∈ ( 0 , 1 ) c_{1}\in (0,1) c1(0,1)为给定的常数。该准则和Armijo准非常相似,区别在于Armijo准则要求下一次迭代的函数值 f ( x k + 1 ) f(x^{k+1}) f(xk+1)相对于本次迭代的函数值 f ( x k ) f(x^{k}) f(xk)有充分的下降,而上述准则只需要下一步函数值相比前面至多 M M M步以内迭代的函数值有下降就可以了,显然该准则的要求要比Armijo准则更宽,它也不要求 f ( x k ) f(x^{k}) f(xk)的单调性

Zhang,Hager准则:设 d k d^{k} dk是点 x k x^{k} xk处的下降方向, M > 0 M>0 M>0为给定的正整数,以下不等式可以作为一种线搜索准则

在这里插入图片描述

我们可以用以下的方式理解此准则

  • 变量 C k C^{k} Ck实际上是本次搜索准则的参照函数值,也即充分下降性质的起始标准
  • 而下一步的标准 C k + 1 C^{k+1} Ck+1则是函数值 f ( x k + 1 ) f(x^{k+1}) f(xk+1) C k C^{k} Ck的凸组合,并非仅仅依赖于 f ( x k + 1 ) f(x^{k+1}) f(xk+1),而凸组合的两个系数由参数 η \eta η决定。可以看到,当 η = 0 \eta=0 η=0时,此准则就是Armijo准则

(3)线搜索方法

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/58082.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

从固定管线到可编程管线:十段代码入门OpenGL

文章目录1. 最简单的OpenGL应用程序2. 视点系统和投影矩阵3. 深度缓冲区和深度测试4. 模型的旋转和平移5. VBO和顶点混合数组6. 纹理映射和纹理坐标7. 光照和法向量计算8. 最简单的着色器程序9. 着色器中的MVP矩阵10. 着色器中的漫反射、镜面反射和高光计算1. 最简单的OpenGL应…

【什么是区块链】

区块链技术简介前言一、区块链技术简介二、区块链的特点1.去中心化2.去信任3.不可篡改和伪造4.可溯源5.匿名性三、区块链用到的技术1.非对称密码算法2.哈希函数3.P2P网络4.安全多方计算前言 比特币与区块链的关系&#xff1a; 2008年中本聪&#xff08;Satoshi Nakamoto&…

Python中logging日志模块详解

用Python写代码的时候&#xff0c;在想看的地方写个print xx 就能在控制台上显示打印信息&#xff0c;这样子就能知道它是什么了&#xff0c;但是当我需要看大量的地方或者在一个文件中查看的时候&#xff0c;这时候print就不大方便了&#xff0c;所以Python引入了logging模块来…

104.二叉树的最大深度 | 111.二叉树的最小深度

文章目录二叉树的深度104.二叉树的最大深度题目题解111.二叉树的最小深度题目题解二叉树的深度 104.二叉树的最大深度 题目 给定一个二叉树&#xff0c;找出其最大深度。 二叉树的深度为根节点到最远叶子节点的最长路径上的节点数。 说明: 叶子节点是指没有子节点的节点。…

Mac终端常用命令

1、打开窗口命令 快速打开&#xff1a;command空格&#xff08;打开查询&#xff09;&#xff0c;输入ter回车 打开多个窗口&#xff1a;commandN&#xff08;光标在终端执行此操作&#xff09; 2、目录操作 命令名 命令功能 备注 cd 打开当前目录 cd dirname pwd 显示…

Java 调用 Cpp 代码简单示例

Java 调用 Cpp 代码 前言&#xff1a;首先说明一下&#xff0c;本篇文章是干嘛的&#xff0c;简单来说就是在 Java 代码里调用 C 代码。但是呢&#xff0c;这里只做一个简单的示例&#xff0c;调用最简单的 C 代码&#xff0c;起到一个抛砖引玉的作用。如有不对之处&#xff0…

选择编码节点的最佳数量和位置研究(Matlab代码实现)

&#x1f468;‍&#x1f393;个人主页&#xff1a;研学社的博客 &#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜…

[附源码]计算机毕业设计校园招聘微信小程序Springboot程序

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

代码随想录训练营第39天|LeetCode 62.不同路径、63. 不同路径 II

参考 代码随想录 题目一&#xff1a;LeetCode 62.不同路径 相比于之前的爬楼梯&#xff0c;这题变成了二维&#xff0c;对于某个位置[i,j]&#xff0c;可以从[i-1,j]或者[i,j-1]走到[i,j]&#xff0c;因此在求解思想上其实是类似于爬楼梯的。 确定dp数组及其下标的含义 dp[…

Android Camera性能分析 - 第26讲 DequeueBuffer Latency

本讲是Android Camera性能分析专题的第26讲 ​&#xff0c;我们介绍DequeueBuffer Latency&#xff0c;包括如下内容&#xff1a; DequeueBuffer Latency是什么DequeueBuffer Latency配置DequeeuBuffer Latency实战 视频在线观看&#xff1a; 极客笔记&#xff1a;极客笔记在…

JavaScript正则表达式:正则表达式中的特殊字符

正则表达式的组成 一个正则表达式可以由简单的字符构成&#xff0c;比如 /abc/&#xff0c;也可以是简单和特殊字符的组合&#xff0c;比如 /ab*c/ 。其中特殊字符也被称为元字符&#xff0c;在正则表达式中是具有特殊意义的专用符号&#xff0c;如 ^ 、$ 、 等。 特殊字符非…

logos_HSST简要说明

HSST分为PCS和PMA&#xff0c; TX PCS&#xff1a;8b/10b编码 RX PCS TX PMA RX PMA 含1个HSST&#xff0c;有4个全双工收发LANE。 LINE和PLL的关系 PLL0可以为4个LANE提供时钟&#xff0c;PLL1只能为LANE2&3提供时钟。 PLL VCO 的转出频率范围为 2.125GHz~3.1875GHz。PLL…

【关于Linux中----文件接口、描述符、重定向、系统调用和缓冲区】

文章目录一、C文件接口中的那些事儿二、接口介绍三、文件描述符fd四、重定向五、缓冲区一、C文件接口中的那些事儿 众所周知&#xff0c;Linux是用C语言写成的&#xff0c;那在这篇文章的开头&#xff0c;自然要先对C语言中的文件操作进行一个概括&#xff01; 写文件&#x…

20221203英语学习

今日新词&#xff1a; lecturer n.讲演者, 讲课者, 讲授者, &#xff08;尤指英国大学的&#xff09;讲师 hypothetical adj.假设的, 假定的 rather adv.相当; 宁可, 宁愿; (常用于or后) 更确切些 ring n.戒指, 指环, 环状物; 圆圈; 敲钟, 按铃; 铃声, 钟声 yes adv.(回答…

1.2 Hadoop简介-hadoop-最全最完整的保姆级的java大数据学习资料

文章目录1.2 Hadoop简介1.2.1 什么是Hadoop1.2.2 Hadoop的起源1.2.3 Hadoop的特点1.2.4 Hadoop的发行版本1.2.5 Apache Hadoop版本更迭1.2.6 第六节 Hadoop的优缺点1.2 Hadoop简介 1.2.1 什么是Hadoop ​ Hadoop 是一个适合大数据的分布式存储和计算平台 ​ 如前所述&#x…

html5期末大作业:基于HTML+CSS技术实现——传统手工艺术雕刻网站(3页)

&#x1f389;精彩专栏推荐 &#x1f4ad;文末获取联系 ✍️ 作者简介: 一个热爱把逻辑思维转变为代码的技术博主 &#x1f482; 作者主页: 【主页——&#x1f680;获取更多优质源码】 &#x1f393; web前端期末大作业&#xff1a; 【&#x1f4da;毕设项目精品实战案例 (10…

深度强化学习的组合优化[1] 综述阅读笔记

文章目录前言零、组合优化问题基础1. 定义&#xff08;1&#xff09;定义&#xff08;2&#xff09;常见问题2. 方法&#xff08;1&#xff09;精确方法&#xff08;2&#xff09;近似方法&#xff08;3&#xff09;深度学习方法3. 文章架构一、概述1. 神经网络&#xff08;1&a…

【图文教程】若依前后端分离版本-菜单怎么设置

在使用若依前后端分离版本作为基础架构的时候&#xff0c;需要新建菜单怎么操作&#xff1f;本文凯哥将详细讲解怎么添加。 1&#xff1a;登录若依系统后&#xff0c;[系统管理]>>[菜单] 先新建一个一级菜单。可以模仿【系统管理】菜单来创建&#xff1a; 系统菜单&am…

226.翻转二叉树

226.翻转二叉树 题目 给你一棵二叉树的根节点 root &#xff0c;翻转这棵二叉树&#xff0c;并返回其根节点。 示例 1 输入&#xff1a;root [4,2,7,1,3,6,9] 输出&#xff1a;[4,7,2,9,6,3,1]示例 2&#xff1a; 输入&#xff1a;root [2,1,3] 输出&#xff1a;[2,3,…

神器必会!特别好使的编辑器Source Insight

已剪辑自: https://mp.weixin.qq.com/s/nA9VJeMjC4gDpDSI8r-2FA “Source Insight&#xff08;以下简称SI&#xff09;是世界上最好的编辑器”&#xff0c;说这句话不知道会不会出门被打呢&#xff1f;-_- 中国古话说得好&#xff0c;“文无第一&#xff0c;武无第二”&#x…