模型预测控制MPC详解(附带案例实现)

news2024/11/27 19:54:52

模型预测控制MPC详解(附带案例实现)

文章目录

  • 模型预测控制MPC详解(附带案例实现)
    • 1. 最优控制问题
    • 2. 什么是MPC
    • 3. 二次规划Quadratic Programming
    • 4. MPC为什么可以转换成QP问题(推导过程)
    • 5. MPC总结
      • 5.1 MPC的优势劣势
      • 5.2 MPC的衍生算法
    • 6. 示例实现
    • Reference

写在前面本文是记录学习B站博主Dr.can的学习笔记,如有侵权请联系笔者删除此文。

1. 最优控制问题

最优控制问题就是研究在约束条件下达到最优的系统表现,通常系统的表现是综合分析的结果。比如考虑一个单输入单输出的系统(SISO),状态变量 x x x,输出为 y y y,要求其输出能跟踪预设的参考值 r r r,误差可以表示为 e = y − r e=y-r e=yr,那么最优控制的目标是

min ⁡ ∫ 0 t e 2 d t \min \int_0^t e^2 dt min0te2dt

如果同时希望输入量 u u u也能越小越好(一般的目的是减少能耗),那最优控制的目标可以是

min ⁡ ∫ 0 t q × e 2 d t + r × u 2 d t \min \int_0^t q\times e^2 dt + r\times u^2 dt min0tq×e2dt+r×u2dt

其中 q , r q,r q,r分别是权重参数,用于调节两个目标的重要性。

考虑一个多输入多输出的系统(MIMO),系统的模型为:

d X d t = A X + B U Y = C X \begin{align*} \frac{dX}{dt} & = AX + BU \\ Y & = CX \end{align*} dtdXY=AX+BU=CX

那么可以将上述的最优化目标改写为:

J = ∫ 0 t E T Q E + U T R U d t J = \int^t_0 E^T Q E + U^T R U dt J=0tETQE+UTRUdt

举一个实际的例子,系统的模型如下所示:

d d t [ x 1 x 2 ] = A [ x 1 x 2 ] + B [ u 1 u 2 ] [ y 1 y 2 ] = [ x 1 x 2 ] \begin{align*} \frac{d}{dt} \begin{bmatrix} x_1 \\ x_2 \end{bmatrix} & = A \begin{bmatrix} x_1 \\ x_2 \end{bmatrix} + B \begin{bmatrix} u_1 \\ u_2 \end{bmatrix} \\ \begin{bmatrix} y_1 \\ y_2 \end{bmatrix} & = \begin{bmatrix} x_1 \\ x_2 \end{bmatrix} \end{align*} dtd[x1x2][y1y2]=A[x1x2]+B[u1u2]=[x1x2]

设置的参考值 R R R为:

R = [ r 1 r 2 ] = [ 0 0 ] R = \begin{bmatrix} r_1 \\ r_2 \end{bmatrix} = \begin{bmatrix} 0 \\ 0 \end{bmatrix} R=[r1r2]=[00]

那么可以推导出误差 E E E为:

E = [ e 1 e 2 ] = [ y 1 − r 1 y 2 − r 2 ] = [ x 1 x 2 ] E = \begin{bmatrix} e_1 \\ e_2 \end{bmatrix} = \begin{bmatrix} y_1 - r_1 \\ y_2 - r_2 \end{bmatrix} = \begin{bmatrix} x_1 \\ x_2 \end{bmatrix} E=[e1e2]=[y1r1y2r2]=[x1x2]

那么上述最优控制的目标函数可以写成:

E T Q E = [ x 1 x 2 ] T [ q 1 0 0 q 2 ] [ x 1 x 2 ] = q 1 x 1 2 + q 2 x 2 2 U T R U = [ u 1 u 2 ] T [ r 1 0 0 r 2 ] [ u 1 u 2 ] = r 1 u 1 2 + r 2 u 2 2 J = ∫ 0 t q 1 x 1 2 + q 2 x 2 2 + r 1 u 1 2 + r 2 u 2 2 \begin{align*} E^TQE & = \begin{bmatrix} x_1 \\ x_2 \end{bmatrix}^T \begin{bmatrix} q_1 & 0 \\ 0 & q_2 \end{bmatrix}\begin{bmatrix} x_1 \\ x_2 \end{bmatrix} = q_1 x_1^2 + q_2 x_2^2 \\ U^TRU & = \begin{bmatrix} u_1 \\ u_2 \end{bmatrix}^T \begin{bmatrix} r_1 & 0 \\ 0 & r_2 \end{bmatrix}\begin{bmatrix} u_1 \\ u_2 \end{bmatrix} = r_1 u_1^2 +r_2 u_2^2 \\ J & = \int^t_0 q_1 x_1^2 + q_2 x_2^2 + r_1 u_1^2 + r_2 u_2^2 \end{align*} ETQEUTRUJ=[x1x2]T[q100q2][x1x2]=q1x12+q2x22=[u1u2]T[r100r2][u1u2]=r1u12+r2u22=0tq1x12+q2x22+r1u12+r2u22

2. 什么是MPC

MPC(Model Predictive Control,模型预测控制)的基本思想是通过建立一个系统的动态模型,并在每一个控制时刻使用这个模型来预测系统未来的行为。基于这些预测,它可以生成一个优化控制序列,然后通过执行第一个控制动作来调整系统状态,接着在下一个时刻重新计算和执行。这个过程反复进行,以使系统能够在未来的一段时间内优化一个特定的性能指标。

通常来说,MPC包括以下四个基本步骤:

  • 系统模型化:建立描述系统动态行为的数学模型,通常是差分方程或微分方程。

  • 预测:在当前时刻基于系统状态和控制输入,使用模型预测未来一段时间内的系统响应。

  • 优化:基于预测的系统响应,通过求解一个优化问题来计算最优的控制输入序列,以最大化或最小化一个性能指标(如系统响应时间、能耗等)。

  • 执行:根据优化得到的控制输入序列中的第一个值,执行这个控制动作,并将实际的系统状态反馈到下一个控制周期中

在具体实施的过程中MPC主要分为下列的三个步骤:

k时刻:

  • step1:估计/测量/读取当前的系统状态;
  • step2:基于 u k , u k + 1 , ⋯   , u k + N \bold{u}_k, \bold{u}_{k+1}, \cdots, \bold{u}_{k+N} uk,uk+1,,uk+N来进行最优化
    J = ∑ k N − 1 E k T Q E k + U k T R U k + E N T F E N ⏟ Terminal Cost J = \sum_k^{N-1} E_k^TQE_k + U_k^T R U_k + \underbrace{E_N^TFE_N}_{\text{Terminal Cost}} J=kN1EkTQEk+UkTRUk+Terminal Cost ENTFEN
    其中Terminal Cost代表了模型滑动窗口的末端的控制误差。
  • step3:只取 u k \bold{u}_k uk,进行滚动优化控制。

3. 二次规划Quadratic Programming

为了能求解MPC问题,我们需要将其转换成二次规划(Quadratic Programming)的形式,对于二次规划已经有很多成熟的求解器了,我们只需要使用这些求解器就能顺利求解。

二次规划一般具有如下的形式:

min ⁡ x x T H x + f T x subject to . . . \begin{align*} & \min_\bold{x} \bold{x}^TH\bold{x} + f^T\bold{x} \\ & \text{subject to} \quad... \end{align*} xminxTHx+fTxsubject to...

其中 H H H是正定的对称矩阵, f f f x \bold{x} x是向量。

4. MPC为什么可以转换成QP问题(推导过程)

考虑一个离散的线性系统

x ( k + 1 ) = A n × n x ( k ) + B n × p u ( k ) x n × 1 = [ x 1 x 2 ⋮ x n ] , u p × 1 = [ u 1 u 2 ⋮ u p ] \bold{x}(k+1) = A_{n\times n}\bold{x}(k) + B_{n\times p}\bold{u}(k) \\ \bold{x}_{n\times 1} = \begin{bmatrix} x_1 \\ x_2 \\ \vdots \\ x_n \end{bmatrix}, \bold{u}_{p\times1} = \begin{bmatrix} u_1 \\ u_2 \\ \vdots \\ u_p \end{bmatrix} x(k+1)=An×nx(k)+Bn×pu(k)xn×1= x1x2xn ,up×1= u1u2up

假设滚动的窗口大小(预测区间,Predictive Horizon)为 N N N,在 k k k时刻,预测 k k k时刻的输入为 u ( k ∣ k ) \bold{u}(k|k) u(kk),预测 k + 1 k+1 k+1时刻的输入为 u ( k + 1 ∣ k ) \bold{u}(k+1|k) u(k+1∣k),以此类推预测,预测区间的最后一个时刻的输入为 u ( k + N − 1 ∣ k ) \bold{u}(k+N-1|k) u(k+N1∣k),将这些预测输入整合成一个向量

U k = [ u ( k ∣ k ) u ( k + 1 ∣ k ) ⋮ u ( k + i ∣ k ) u ( k + N − 1 ∣ k ) ] \bold{U}_k = \begin{bmatrix} \bold{u}(k|k) \\ \bold{u}(k+1|k) \\ \vdots \\ \bold{u}(k+i|k) \\ \bold{u}(k+N-1|k) \end{bmatrix} Uk= u(kk)u(k+1∣k)u(k+ik)u(k+N1∣k)

k k k时刻,系统的状态为 x ( k ∣ k ) \bold{x}(k|k) x(kk) k + 1 k+1 k+1系统的状态为 x ( k + 1 ∣ k ) \bold{x}(k+1|k) x(k+1∣k),以此类推预测,预测区间的最后一个时刻的系统的状态为 x ( k + N − 1 ∣ k ) \bold{x}(k+N-1|k) x(k+N1∣k),然后再加上区间结束后的第一个状态 x ( k + N ∣ k ) \bold{x}(k+N|k) x(k+Nk),将这些系统的状态整合成一个向量

X k = [ x ( k ∣ k ) x ( k + 1 ∣ k ) ⋮ x ( k + i ∣ k ) x ( k + N ∣ k ) ] \bold{X}_k = \begin{bmatrix} \bold{x}(k|k) \\ \bold{x}(k+1|k) \\ \vdots \\ \bold{x}(k+i|k) \\ \bold{x}(k+N|k) \end{bmatrix} Xk= x(kk)x(k+1∣k)x(k+ik)x(k+Nk)

假设系统的输出 y = x \bold{y}=\bold{x} y=x,设定的参考值 r = 0 \bold{r}=0 r=0,那么系统的误差为 e = y − r = x − 0 = x \bold{e}=\bold{y}-\bold{r}=\bold{x}-0 = \bold{x} e=yr=x0=x,为了最优化误差和最优化输入,我们可以这样表示代价函数(Cost Function)

min ⁡ u J = ∑ i = 0 N − 1 ( x ( k + i ∣ k ) T Q x ( k + i ∣ k ) + u ( k + i ∣ k ) T R u ( k + i ∣ k ) ) + x ( k + N ) T F x ( k + N ) ⏟ Terminal Cost \min_\bold{u} J = \sum^{N-1}_{i=0} \Big(\bold{x}(k+i|k)^TQ \bold{x}(k+i|k) + \bold{u}(k+i|k)^TR \bold{u}(k+i|k) \Big) + \underbrace{\bold{x}(k+N)^T F \bold{x}(k+N)}_{\text{Terminal Cost}} uminJ=i=0N1(x(k+ik)TQx(k+ik)+u(k+ik)TRu(k+ik))+Terminal Cost x(k+N)TFx(k+N)

但是乍一看这并不是二次规划的形式,我们可以通过化简将其转化为标准的二次规划形式。

k k k时刻,我们的系统状态可以表示为

x ( k ∣ k ) = x k x ( k + 1 ∣ k ) = A x ( k ∣ k ) + B u ( k ∣ k ) = A x k + B u ( k ∣ k ) x ( k + 2 ∣ k ) = A x ( k + 1 ∣ k ) + B u ( k ∣ k ) = A 2 x k + A B u ( k ∣ k ) + B u ( k + 1 ∣ k ) ⋮ x ( k + N ∣ k ) = A N x k + A N − 1 B u ( k ∣ k ) + ⋯ + B u ( k + N − 1 ∣ k ) \begin{align*} \bold{x}(k|k) & = \bold{x}_k \\ \bold{x}(k+1|k) & = A \bold{x}(k|k) + B\bold{u}(k|k) = A\bold{x}_k + B\bold{u}(k|k) \\ \bold{x}(k+2|k) & = A \bold{x}(k+1|k) + B\bold{u}(k|k) = A^2\bold{x}_k + AB\bold{u}(k|k) + B\bold{u}(k+1|k) \\ \vdots \\ \bold{x}(k+N|k) & = A^N \bold{x}_k + A^{N-1}B\bold{u}(k|k) + \cdots + B \bold{u}(k+N-1|k) \end{align*} x(kk)x(k+1∣k)x(k+2∣k)x(k+Nk)=xk=Ax(kk)+Bu(kk)=Axk+Bu(kk)=Ax(k+1∣k)+Bu(kk)=A2xk+ABu(kk)+Bu(k+1∣k)=ANxk+AN1Bu(kk)++Bu(k+N1∣k)

左边即为 X k \bold{X}_k Xk,然后将右边写成矩阵的形式

X k = [ I A A 2 ⋮ A N ] ⏟ M x k + [ 0 0 ⋯ 0 ⋮ ⋮ ⋱ ⋮ 0 0 ⋯ 0 B 0 ⋯ 0 A B B ⋯ 0 ⋮ ⋮ ⋱ ⋮ A N − 1 B A N − 2 B ⋯ B ] ⏟ C U k X k = M x k + C U k \begin{align*} \bold{X}_k & = \underbrace{\begin{bmatrix} I \\ A \\ A^2 \\ \vdots \\ A^N \end{bmatrix}}_{M} \bold{x}_k + \underbrace{\begin{bmatrix} 0 & 0 & \cdots & 0 \\ \vdots & \vdots & \ddots & \vdots \\ 0 & 0 & \cdots & 0 \\ B & 0 & \cdots & 0 \\ AB & B & \cdots & 0 \\ \vdots & \vdots & \ddots & \vdots \\ A^{N-1}B & A^{N-2}B & \cdots & B \end{bmatrix}}_{C} \bold{U}_k \\ \bold{X}_k & = M \bold{x}_k + C \bold{U}_k \end{align*} XkXk=M IAA2AN xk+C 00BABAN1B000BAN2B0000B Uk=Mxk+CUk

其中 M M M的前 n n n行都是 0 0 0。接下来,我们来将代价函数化成QP的形式

J = ∑ i = 0 N − 1 ( x ( k + i ∣ k ) T Q x ( k + i ∣ k ) + u ( k + i ∣ k ) T R u ( k + i ∣ k ) ) + x ( k + N ) T F x ( k + N ) = x ( k ∣ k ) T Q x ( k ∣ k ) + x ( k + 1 ∣ k ) T Q x ( k + 1 ∣ k ) + ⋯ + x ( k + N − 1 ∣ k ) T Q x ( k + N − 1 ∣ k ) + x ( k + N ∣ k ) T Q x ( k + N ∣ k ) + ∑ i = 0 N − 1 u ( k + i ∣ k ) T R u ( k + i ∣ k ) = [ x ( k ∣ k ) x ( k + 1 ∣ k ) ⋮ x ( k + i ∣ k ) x ( k + N ∣ k ) ] T [ Q Q Q ⋱ F ] ⏟ Q ˉ [ x ( k ∣ k ) x ( k + 1 ∣ k ) ⋮ x ( k + i ∣ k ) x ( k + N ∣ k ) ] + [ u ( k ∣ k ) u ( k + 1 ∣ k ) ⋮ u ( k + i ∣ k ) u ( k + N − 1 ∣ k ) ] T [ R R R ⋱ R ] ⏟ R ˉ [ u ( k ∣ k ) u ( k + 1 ∣ k ) ⋮ u ( k + i ∣ k ) u ( k + N − 1 ∣ k ) ] = X k T Q ˉ X k + U k R ˉ U k \begin{align*} J & = \sum^{N-1}_{i=0} \Big(\bold{x}(k+i|k)^TQ \bold{x}(k+i|k) + \bold{u}(k+i|k)^TR \bold{u}(k+i|k) \Big) + \bold{x}(k+N)^T F \bold{x}(k+N) \\ & = \bold{x}(k|k)^TQ\bold{x}(k|k) + \bold{x}(k+1|k)^TQ\bold{x}(k+1|k) + \cdots + \bold{x}(k+N-1|k)^TQ\bold{x}(k+N-1|k) + \bold{x}(k+N|k)^TQ\bold{x}(k+N|k) \\ & + \sum^{N-1}_{i=0}\bold{u}(k+i|k)^TR\bold{u}(k+i|k) \\ & = \begin{bmatrix} \bold{x}(k|k) \\ \bold{x}(k+1|k) \\ \vdots \\ \bold{x}(k+i|k) \\ \bold{x}(k+N|k) \end{bmatrix}^T \underbrace{\begin{bmatrix} Q & & & &\\ & Q & & &\\ & & Q & &\\ & & & \ddots & \\ & & & & F \end{bmatrix}}_{\bar{Q}}\begin{bmatrix} \bold{x}(k|k) \\ \bold{x}(k+1|k) \\ \vdots \\ \bold{x}(k+i|k) \\ \bold{x}(k+N|k) \end{bmatrix} + \begin{bmatrix} \bold{u}(k|k) \\ \bold{u}(k+1|k) \\ \vdots \\ \bold{u}(k+i|k) \\ \bold{u}(k+N-1|k) \end{bmatrix}^T \underbrace{\begin{bmatrix} R & & & &\\ & R & & &\\ & & R & &\\ & & & \ddots & \\ & & & & R \end{bmatrix}}_{\bar{R}}\begin{bmatrix} \bold{u}(k|k) \\ \bold{u}(k+1|k) \\ \vdots \\ \bold{u}(k+i|k) \\ \bold{u}(k+N-1|k) \end{bmatrix} \\ & = \bold{X}_k^T \bar{Q} \bold{X}_k + \bold{U}_k \bar{R} \bold{U}_k \end{align*} J=i=0N1(x(k+ik)TQx(k+ik)+u(k+ik)TRu(k+ik))+x(k+N)TFx(k+N)=x(kk)TQx(kk)+x(k+1∣k)TQx(k+1∣k)++x(k+N1∣k)TQx(k+N1∣k)+x(k+Nk)TQx(k+Nk)+i=0N1u(k+ik)TRu(k+ik)= x(kk)x(k+1∣k)x(k+ik)x(k+Nk) TQˉ QQQF x(kk)x(k+1∣k)x(k+ik)x(k+Nk) + u(kk)u(k+1∣k)u(k+ik)u(k+N1∣k) TRˉ RRRR u(kk)u(k+1∣k)u(k+ik)u(k+N1∣k) =XkTQˉXk+UkRˉUk

然后再将前面推导的条件带入

J = X k T Q ˉ X k + U k R ˉ U k = ( M x k + C U k ) T Q ˉ ( M x k + C U k ) + U k R ˉ U k = x k T M T Q ˉ M x k + U k T C T Q ˉ M x k + x k T M T Q ˉ C ⏟ 2 x T C T Q ˉ M U k U k + U k T C T Q ˉ C U k + U k R ˉ U k = x k T M T Q ˉ M x k + 2 x T C T Q ˉ M U k U k + U k T C T Q ˉ C U k + U k R ˉ U k \begin{align*} J & = \bold{X}_k^T \bar{Q} \bold{X}_k + \bold{U}_k \bar{R} \bold{U}_k \\ & = (M \bold{x}_k + C \bold{U}_k)^T \bar{Q}(M \bold{x}_k + C \bold{U}_k) + \bold{U}_k \bar{R} \bold{U}_k \\ & = \bold{x}_k^TM^T\bar{Q}M\bold{x}_k + \underbrace{\bold{U}_k^TC^T\bar{Q}M\bold{x}_k + \bold{x}_k^TM^T\bar{Q}C}_{2\bold{x}^TC^T\bar{Q}M\bold{U}_k} \bold{U}_k + \bold{U}_k^TC^T\bar{Q}C \bold{U}_k + \bold{U}_k \bar{R} \bold{U}_k \\ & = \bold{x}_k^TM^T\bar{Q}M\bold{x}_k + 2\bold{x}^TC^T\bar{Q}M\bold{U}_k \bold{U}_k + \bold{U}_k^TC^T\bar{Q}C \bold{U}_k + \bold{U}_k \bar{R} \bold{U}_k \end{align*} J=XkTQˉXk+UkRˉUk=(Mxk+CUk)TQˉ(Mxk+CUk)+UkRˉUk=xkTMTQˉMxk+2xTCTQˉMUk UkTCTQˉMxk+xkTMTQˉCUk+UkTCTQˉCUk+UkRˉUk=xkTMTQˉMxk+2xTCTQˉMUkUk+UkTCTQˉCUk+UkRˉUk

其中 G = M T Q ˉ M G=M^T\bar{Q}M G=MTQˉM E = C T Q ˉ M E=C^T\bar{Q}M E=CTQˉM H = C T R ˉ C + R ˉ H=C^T\bar{R}C+\bar{R} H=CTRˉC+Rˉ,那么 J J J可以化简为:

J = x k T G x k + 2 x k T E U k + U k T H U k J = \bold{x}_k^T G \bold{x}_k + 2\bold{x}_k^T E \bold{U}_k + \bold{U}_k^T H \bold{U}_k J=xkTGxk+2xkTEUk+UkTHUk

其中 x k T G x k \bold{x}_k^T G \bold{x}_k xkTGxk是初始状态,是一个常量,在优化的过程中可以忽略。最终的代价函数可以表示为

min ⁡ U J = x k T G x k + 2 x k T E U k + U k T H U k G = M T Q ˉ M E = C T Q ˉ M H = C T R ˉ C + R ˉ Q ˉ = [ Q ⋯ ⋮ Q ⋮ ⋯ F ] , R ˉ = [ R ⋯ ⋮ ⋱ ⋮ ⋯ R ] \min_\bold{U} J = \bold{x}_k^T G \bold{x}_k + 2\bold{x}_k^T E \bold{U}_k + \bold{U}_k^T H \bold{U}_k \\ G=M^T\bar{Q}M \\ E=C^T\bar{Q}M \\ H=C^T\bar{R}C+\bar{R} \\ \bar{Q} = \begin{bmatrix} Q & \cdots & \\ \vdots & Q & \vdots \\ & \cdots & F \end{bmatrix}, \bar{R} = \begin{bmatrix} R & \cdots & \\ \vdots & \ddots & \vdots \\ & \cdots & R \end{bmatrix} UminJ=xkTGxk+2xkTEUk+UkTHUkG=MTQˉME=CTQˉMH=CTRˉC+RˉQˉ= QQF ,Rˉ= RR

这就是一个标准的QP问题。

5. MPC总结

5.1 MPC的优势劣势

😄MPC的优势在于:

  • 可以处理多输入多数出的系统(MIMO),PID控制只能在一个PID环内控制一个系统状态,当系统状态相互影响的时候PID控制往往难以设计,MPC就体现出了其优势
  • MPC的另一个优势在于可以处理约束条件,约束很重要,因为违反它们会导致不良后果。

😄MPC的不足在于:

  • MPC是在线滚动优化的,所以需要比较强的算力。

5.2 MPC的衍生算法

😄如何选择合适的MPC?

自适应MPC(Adaptive MPC)

在自适应MPC 中,线性模型是随着工作条件的变化而动态计算的,并且在每个时间步长,您都可以使用此线性模型更新。MPC控制器使用的内部被控对象模型,请注意,在自适应MPC 中,优化问题的结构在不同的工作点上保持不变。这意味着在预测范围内,状态数量和约束数量不会因不同的操作条件而改变。

Image

增益调度MPC(Gain-scheduled MPC)

如果它们确实发生了变化,则应使用增益调度MPC。在增益调度MPC 中,您可以在感兴趣的工作点进行离线线性化,并为每个工作点设计一个线性MPC控制器。每个控制器彼此独立,因此可能具有不同数量的状态和不同数量的约束。

Image

小结:

如果被控对象是非线性的,但可以通过线性模型逼近,则可以使用自适应MPC 控制器和如果被控对象是非线性的且状态的维度和约束的数量会发生变化,那么应该使用增益调度的MPC控制器。如果优化问题的结构在不同的工作条件下没有变化,则应使用自适应 MPC;但是,如果该结构有变化,则使用增益调度 MPC;如果因您有一个无法通过线性化进行良好逼近的高度非线性系统,从而导致以上这些方法都不起作用,则可以使用非线性MPC。具体可以如下图所示:

Image

6. 示例实现

待完善

Reference

[1]MPC模型预测控制器
[2]Understanding Model Predictive Control
[3]CasADi_MPC_MHE_Python
[4]MPC-and-MHE-implementation-in-MATLAB-using-Casadi
[5]MPC and MHE implementation in Matlab using Casadi

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

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

相关文章

HTML静态网页成品作业(HTML+CSS+JS)——家乡莆田介绍网页(5个页面)

🎉不定期分享源码,关注不丢失哦 文章目录 一、作品介绍二、作品演示三、代码目录四、网站代码HTML部分代码 五、源码获取 一、作品介绍 🏷️本套采用HTMLCSS,使用Javacsript代码实现图片轮播,共有5个页面。 二、作品…

卓越的 App UI 风格引领潮流

卓越的 App UI 风格引领潮流

QT基础 - 常见图表绘制

目录 零. 前言 一. 添加模块 折线图 三. 树状图 四. 饼图 五. 堆叠柱状图 六. 百分比柱状图 七. 散点图和光滑曲线图 散点图 光滑曲线图 零. 前言 Qt Charts 是 Qt 框架的一个模块,用于创建各种类型的图表和数据可视化。它为开发者提供了一套功能强大的工…

【面试干货】Java的基础类型和字节大小

【面试干货】Java的基础类型和字节大小 💖The Begin💖点点关注,收藏不迷路💖 在Java编程语言中,有八种基本数据类型,它们分别是:布尔型(boolean)、字节型(byt…

什么是 SSH(安全外壳协议)以及如何工作

安全外壳协议(Secure Shell,简称SSH),旨在取代未加密的协议(如 Telnet 和 RSH)和未受保护的文件传输协议(如 FTP 和 RCP),在两个设备之间提供安全的加密连接。 安全外壳…

MyBatis 动态 SQL怎么使用?

引言:在现代的软件开发中,数据库操作是任何应用程序的核心部分之一。而在 Java 开发领域,MyBatis 作为一款优秀的持久层框架,以其简洁的配置和强大的灵活性被广泛应用。动态 SQL 允许开发人员根据不同的条件和场景动态地生成和执行…

Kubernetes部署Kanboard看板管理平台

【云原生】Kubernetes部署Kanboard项目管理平台 文章目录 【云原生】Kubernetes部署Kanboard项目管理平台介绍资源列表基础环境一、检查k8s环境1.1、检查工作节点状态1.2、检查系统pod状态 二、编辑kanboard.yaml文件2.1、创建项目目录2.2、编辑kanboard.yaml文件 三、部署Kanb…

字节跳动的丝绸之路,豆包或将成为赛博“杨枝甘露”

大数据产业创新服务媒体 ——聚焦数据 改变商业 关于字节跳动有一个所有人都知道的秘密,那就是他们正在想方设法地海外扩张,以全球市场来驱动企业的新增长。美国曾经是字节跳动的第二战场,但是随着华盛顿相关法案的出台,在各种不…

推荐5个AI辅助生成论文、降低查重率的网站【2024最新】

一、引言 对于忙碌的学生来说,毕业论文通常是一项艰巨的任务。幸运的是,随着人工智能技术的发展,现在有一些工具可以帮助学生轻松完成论文。本文将介绍五个免费的AI工具,它们能够一键帮助你生成毕业论文,让你的学术生…

2024广东省职业技能大赛云计算赛项实战——Redis主从架构

Redis主从架构 前言 Redis是一个开源的内存数据结构存储系统,一般用于作为数据库、缓存和消息代理使用,而主从架构是许多分布式系统中常见的设计模式,用来提高系统的性能、可靠性和扩展性。 虚拟机使用的是自行创建的CentOS7,如…

记录SpringBoot启动报错解决

记录SpringBoot启动报错解决 报错现场 Failed to configure a DataSource: url attribute is not specified and no embedded datasource could be configured. Reason: Failed to determine a suitable driver class Action: Consider the following:If you want an embedde…

反转链表(java精简版)

反转一个单向链表。 public class ReversingLinkedList {static class Node {int val;Node next;public Node(int val) {this.val val;}public boolean hasNext() {return next ! null;}}public static void main(String[] args) {//构造Node head null;Node shift null;for…

MobileNet系列论文阅读笔记(MobileNetV1、MobileNetV2和MobileNetV3)

目录 引言MobileNets: Efficient Convolutional Neural Networks for Mobile Vision Applications摘要Prior Work -- 先前工作MobileNet Architecture— MobileNet结构Depthwise Separable Convolution—深度可分离卷积Network Structure -- 网络结构 总结 MobileNetV2: Invert…

视频共享融合赋能平台LntonCVS视频监控业务平台建设安全煤矿矿井应用方案

随着我国经济的飞速增长,煤炭作为主要的能源之一,在我国的能源结构中扮演着至关重要的角色。然而,煤矿事故的频繁发生,不仅造成了巨大的人员伤亡和财产损失,也对社会产生了深远的负面影响。因此,实现煤矿的…

transformers Model

☆ 问题描述 在 transformers 框架中,Model 模块是核心组件之一,提供了多种预训练模型及其相关功能,广泛应用于自然语言处理(NLP)任务。 ★ 解决方案 # 导入相关文件 from transformers import AutoConfig, AutoM…

【odoo】常用的字符转义:“>“,“<“,““,“/“等

概要 字符转义是指在编写代码或处理文本数据时&#xff0c;将特殊字符转换为另一种形式&#xff0c;以便在特定的上下文中正确解析和处理这些字符。 内容 特殊字符描述XML转义表示法&和符号&amp;<小于符号<>大于符号>"双引号&quot;单引号&ap…

Day1:基础语法

今日目标&#xff1a;理解什么是变量、掌握常用的数据类型、学会数据类型转换 一、JavaScript 介绍 1. JavaScript 基础知识 主要讲解 &#xff1a;JavaScript 是什么、书写位置、注释、结束符、输入和输出语法、字面量。 1.1 JavaScript 是什么 是一种运行在客户端(浏览器…

B端业务需求分析的3大注意事项

通过深入分析业务需求&#xff0c;可以准确理解B端用户的具体需求&#xff0c;帮助项目团队设计出真正解决企业问题、提高工作效率的产品或服务。这减少了后期变更&#xff0c;节约了时间和资源。如果没有深入分析业务需求&#xff0c;产品或服务功能可能与实际业务需求脱节&am…

PHP转Go系列 | 数组切片的使用姿势

大家好&#xff0c;我是码农先森。 简介 在 PHP 语言中数组的使用很简单&#xff0c;易用程度简直变态&#xff0c;无论多么复杂的数据格式都可以用数组来表达&#xff0c;可以随心所欲的使用。 <?php $array [1, name, [sex > 男]]; print_r($array);$array []; $…

【LLM之NL2SQL】DAIL-SQL论文阅读笔记

研究背景 该研究旨在提供一个全面、系统的评估框架&#xff0c;用于评估基于大型语言模型&#xff08;LLM&#xff09;的Text-to-SQL技术。特别强调了不同的提示工程策略的有效性和效率&#xff0c;以及开源LLM的可行性。研究的重点是评估在零样本和少样本场景下的不同问题表示…