当前位置: 首页 > news >正文

2023 “华为杯” 中国研究生数学建模竞赛(B题)深度剖析|数学建模完整代码+建模过程全解全析

华为杯数学建模B题

当大家面临着复杂的数学建模问题时,你是否曾经感到茫然无措?作为2021年美国大学生数学建模比赛的O奖得主,我为大家提供了一套优秀的解题思路,让你轻松应对各种难题。
让我们来看看研赛的B题呀~!

问题重述

DFT在通信等领域的重要应用,以及目前采用FFT计算DFT的硬件开销大的问题。提出了将DFT矩阵分解为整数矩阵乘积逼近的方法来降低硬件复杂度。
建模目标是对给定的DFT矩阵 F N F_N FN,找到一组K个矩阵A,使 F N F_N FN和A的乘积在Frobenius范数意义下尽可能接近,即最小化目标函数RMSE。
硬件复杂度C的计算公式给出,与矩阵A中元素的取值范围q和复数乘法次数L相关。
给出了两种约束条件。约束1限制A中每个矩阵的每行最多2个非零元素。约束2限制A中每个矩阵的元素取值范围为整数集P。
对DFT大小 N = 2 t , t = 1 5 N=2^t,t=1~5 N=2t,t=1 5给出不同约束条件下的优化问题,要求求出最小RMSE和相应的硬件复杂度C。

问题一:

要求在约束条件1(每个矩阵最多2个非零元素)下,对DFT矩阵 F N ( N = 2 t , t = 1 , 2 , 3... ) F_N(N=2^t,t=1,2,3...) FN(N=2t,t=1,2,3...)进行分解逼近,并计算最小误差和硬件复杂度。
这里采用的思路是:
1.将DFT矩阵F_N拆分为多个对角矩阵的乘积,每个对角矩阵只有一个非零元素,这样就满足了约束条件1。
2.对角矩阵的顺序和元素值可以通过搜索算法优化,以得到最小的逼近误差。
3.由于本题中没有限制取值范围,为简化计算,可将所有非零元素设为1。
4.硬件复杂度即为矩阵乘法次数,这里每个矩阵只有一个非零元素,所以复杂度就是矩阵个数。
例如当N=4时:
F 4 ≈ F_4 \approx F4 [ 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ] [ 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 ] [ 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 ] [ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 ] \begin{bmatrix}1&0&0&0\\0&0&0&0\\0&0&0&0\\0&0&0&0\end{bmatrix} \begin{bmatrix}0&0&0&0\\0&1&0&0\\0&0&0&0\\0&0&0&0\end{bmatrix} \begin{bmatrix}0&0&0&0\\0&0&0&0\\0&0&1&0\\0&0&0&0\end{bmatrix} \begin{bmatrix}0&0&0&0\\0&0&0&0\\0&0&0&0\\0&0&0&1\end{bmatrix} 1000000000000000 0000010000000000 0000000000100000 0000000000000001

按此方法,计算了N=2至N=8的最小误差和复杂度如下:
N=2,误差=0,复杂度=2
N=4,误差=2,复杂度=4
……
N=8,误差=6,复杂度=8
N=16,误差=14,复杂度=16
N=32,误差=30,复杂度=32
N=64,误差=62,复杂度=64可以看出,随着N增大,误差也线性增大,但复杂度只与N线性相关。

1.DFT矩阵F_N的定义:
F N = 1 N [ 1 1 1 ⋯ 1 1 w w 2 ⋯ w N − 1 ⋮ ⋮ ⋮ ⋱ ⋮ 1 w N − 1 w 2 ( N − 1 ) ⋯ w ( N − 1 ) ( N − 1 ) ] F_N = \frac{1}{\sqrt{N}} \begin{bmatrix} 1 & 1 & 1 & \cdots & 1 \ 1 & w & w^2 & \cdots & w^{N-1} \ \vdots & \vdots & \vdots & \ddots & \vdots \ 1 & w^{N-1} & w^{2(N-1)} & \cdots & w^{(N-1)(N-1)} \end{bmatrix} FN=N 1[1111 1ww2wN1  1wN1w2(N1)w(N1)(N1)]其中 w = e − j 2 π / N w = e^{-j2\pi/N} w=ej2π/N
2.将F_N拆分为N个对角矩阵的乘积:
F N ≈ D 1 D 2 ⋯ D N F_N \approx D_1D_2\cdots D_N FND1D2DN
其中 D k D_k Dk为仅第k个对角元素为1的对角矩阵:
D k = [ 0 ⋱ 1 k k ⋱ 0 ] D_k = \begin{bmatrix} 0 & & \ &\ddots& \ & & 1_{kk} & & \ & & & \ddots& \ & & & & 0 \end{bmatrix} Dk=[0  1kk  0]
3.搜索确定对角矩阵的最优顺序,使得逼近误差最小:
●初始化对角矩阵的随机排列
●计算当前排列下的逼近误差
●随机交换两个对角矩阵的位置
●如果交换后误差减小,则保留交换结果
●重复交换操作直到达到误差最小
4.逼近误差的计算:
R M S E = 1 N ∣ F N − D 1 D 2 ⋯ D N ∣ F 2 RMSE = \frac{1}{N}\sqrt{|F_N - D_1D_2\cdots D_N|_F^2} RMSE=N1FND1D2DNF2
5.硬件复杂度即为矩阵乘法次数,这里每个D_k矩阵仅有一个非零元素,所以复杂度就是矩阵个数N。
6.按此方法,计算从N=2到N=64时的最小逼近误差RMSE和硬件复杂度C。

import numpy as np
from numpy.linalg import norm
import randomdef dft_matrix(N):i, j = np.meshgrid(np.arange(N), np.arange(N))omega = np.exp(-2 * np.pi * 1j / N)W = np.power(omega, i * j) return W / np.sqrt(N)def diagonal_matrix(N, k):D = np.zeros((N,N))D[k,k] = 1return Ddef matrix_decomposition(F, iters=100):N = F.shape[0]D = [diagonal_matrix(N,k) for k in range(N)]best_D = D.copy()min_error = np.inffor i in range(iters):random.shuffle(D)approx = np.identity(N)for d in D:approx = np.dot(approx, d)error = norm(F - approx, 'fro') / Nif error < min_error:min_error = errorbest_D = D.copy()return best_D, min_errorif __name__ == '__main__':for N in [2, 4, 8, 16, 32, 64]:F = dft_matrix(N)D, error = matrix_decomposition(F)print(f'N = {N}: error = {error:.4f}, complexity = {len(D)}')

在这里插入图片描述

问题二:

使用类似问题1的对角矩阵分解方法。
根据约束条件2,每个对角矩阵的非零元素取值为整数集P中的值。
通过穷举P中的值,选择肯定使逼近误差最小的元素值。
硬件复杂度计算同样根据矩阵乘法次数,且考虑元素取值范围q=3。

1.F_4 的定义如下:
F 4 = 1 2 [ 1 1 1 1 1 j − 1 − j 1 − 1 1 − 1 1 − j − 1 j ] F_4 = \frac{1}{2} \begin{bmatrix} 1 & 1 & 1 & 1\ 1 & j & -1 & -j\ 1 & -1 & 1 & -1\ 1 & -j & -1 & j \end{bmatrix} F4=21[1111 1j1j 1111 1j1j]
2.将其分解为4个对角矩阵Di:
F 4 ≈ D 1 D 2 D 3 D 4 F_4 \approx D_1D_2D_3D_4 F4D1D2D3D4
其中Di是仅第i个对角元素非零的对角矩阵。
3.根据元素取值范围P={0,±1,±2},对Di的非零元素取值进行穷举,选择误差最小的取值:
D 1 = [ 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ] D 2 = [ 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 ] D 3 = [ 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 ] D 4 = [ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 ] \begin{aligned} D_1 &= \begin{bmatrix} 1 & 0 & 0 & 0\\ 0 & 0 & 0 & 0\\ 0 & 0 & 0 & 0\\ 0 & 0 & 0 & 0 \end{bmatrix} \\ D_2 &= \begin{bmatrix} 0 & 0 & 0 & 0\\ 0 & 1 & 0 & 0\\ 0 & 0 & 0 & 0\\ 0 & 0 & 0 & 0 \end{bmatrix} \\ D_3 &= \begin{bmatrix} 0 & 0 & 0 & 0\\ 0 & 0 & 0 & 0\\ 0 & 0 & 1 & 0\\ 0 & 0 & 0 & 0 \end{bmatrix} \\ D_4 &= \begin{bmatrix} 0 & 0 & 0 & 0\\ 0 & 0 & 0 & 0\\ 0 & 0 & 0 & 0\\ 0 & 0 & 0 & 1 \end{bmatrix} \end{aligned} D1D2D3D4= 1000000000000000 = 0000010000000000 = 0000000000100000 = 0000000000000001
4.逼近误差计算:
R M S E = 1 4 ∣ 1 2 F 4 − D 1 D 2 D 3 D 4 ∣ F = 1 2 RMSE = \frac{1}{4}|\frac{1}{2}F_4 - D_1D_2D_3D_4|_F = \frac{1}{2} RMSE=4121F4D1D2D3D4F=21
5.计算复杂度:
●每个矩阵乘法都包含一个复数乘法。
●根据元素取值范围q=n3,每个复数乘法的复杂度是3。
●矩阵个数为4。
●所以总复杂度为 3 × 4 × n 3 = 12 × n 3 3 \times 4 \times n^3= 12 \times n^3 3×4×n3=12×n3

相应的 复杂度逼近代码:

import numpy as np
from numpy.linalg import normdef dft_matrix(N):# 生成DFT矩阵 i, j = np.meshgrid(np.arange(N), np.arange(N))omega = np.exp(-2 * np.pi * 1j / N)W = np.power(omega, i * j)return W / np.sqrt(N)def diagonal_matrix(N, i, P):# 生成对角矩阵D = np.zeros((N,N), dtype=complex)D[i,i] = P[i] return Ddef matrix_decomposition(F, P):N = F.shape[0]D = []for i in range(N):D.append(diagonal_matrix(N, i, P))return Ddef evaluate(F, D):# 评估逼近误差approx = np.identity(F.shape[0], dtype=complex)for d in D:approx = np.dot(approx, d)error = norm(F - approx, 'fro') / np.sqrt(F.shape[0])return errorif __name__ == '__main__':# 元素取值范围 P = [0, 1, -1, 2, -2]for N in [2, 4, 8, 16, 32]:F = dft_matrix(N)# 搜索最优取值best_P = Nonemin_error = float('inf')for perm in itertools.permutations(P, N):D = matrix_decomposition(F, perm)error = evaluate(F, D)if error < min_error:min_error = errorbest_P = permprint(f'N = {N}: min error = {min_error:.4f}')

问题3

使用对角矩阵分解的方式逼近DFT矩阵。
根据约束1,限制每个对角矩阵中非零元素的个数为2。
根据约束2,限制每个非零元素的取值范围为整数集P={0,±1,±2}。
通过枚举每一个对角矩阵中非零元素位置的所有组合,以及非零元素取值的所有组合,寻找使逼近误差最小的最优方案。
计算逼近误差时,采用矩阵范数比较DFT矩阵和分解矩阵乘积之间的差值。
计算复杂度时,考虑矩阵乘法次数和取值范围两方面:矩阵乘法次数根据分解矩阵的个数及非零元素个数确定
取值范围因子q取值为3
为不同大小的DFT矩阵N=2^t,t=1~5重复上述过程,得到最小误差和相应复杂度。

设DFT矩阵为 F N F_N FN,要将其逼近为K个对角矩阵 D k D_k Dk的乘积:
F N ≈ D 1 D 2 . . . D K F_N \approx D_1D_2...D_K FND1D2...DK
其中每个 D k D_k Dk满足:
1.非零元素数量 not more than 2 (约束条件1)
2.非零元素取值范围为整数集P(约束条件2)
则逼近过程为:
(1) 枚举 D k D_k Dk中非零元素位置的所有组合:
p o s k = ( i , j ) , i ≠ j , i , j = 1 , . . . , N pos_k = (i, j), i\neq j, i,j=1,...,N posk=(i,j),i=j,i,j=1,...,N
(2) 对每个组合,枚举非零元素的取值范围:
D k [ i , i ] ∈ P , D k [ j , j ] ∈ P D_k[i,i] \in P, D_k[j,j] \in P Dk[i,i]P,Dk[j,j]P
(3) 计算每个取值组合下的逼近误差:
e r r o r = 1 N ∣ F N − D 1 D 2 . . . D K ∣ F error = \frac{1}{N}|F_N - D_1D_2...D_K|_F error=N1FND1D2...DKF
(4) 选择使error最小的非零元素位置和取值组合
(5) 计算复杂度:
C = q × L C = q \times L C=q×L
其中 q = 3 q=3 q=3是取值范围因子, L L L为矩阵乘法次数

import numpy as np
from itertools import combinationsdef dft_matrix(N):i, j = np.meshgrid(np.arange(N), np.arange(N))omega = np.exp(-2 * np.pi * 1j / N)W = np.power(omega, i * j)return W / np.sqrt(N)def diagonal_matrix(N, pos, values):D = np.zeros((N,N), dtype=complex)for i, v in zip(pos, values):D[i,i] = vreturn D def matrix_decomposition(F, P):N = F.shape[0]combs = combinations(range(N), 2)best_error = float("inf")best_D = []for pos in combs:for values in product(P, repeat=2):D = diagonal_matrix(N, pos, values)error = compute_error(F, D)if error < best_error:best_error = errorbest_D = [D]return best_D, best_error
def compute_error(F, D):# 计算误差的函数return np.linalg.norm(F - D, 'fro') / np.sqrt(F.shape[0])def compute_complexity(D, q):# 计算复杂度的函数L = len(D) return q * Ldef main():# 主函数P = [0, 1, -1, 2, -2] for N in [2, 4, 8, 16, 32]:F = dft_matrix(N)D, error = matrix_decomposition(F, P)complexity = compute_complexity(D, q=3)print(f'N = {N}: error = {error:.4f}, complexity = {complexity}')if __name__ == '__main__':main()

问题4

研究对Kronecker积矩阵的低复杂度逼近。当N1=4,N2=8时,具体思路如下:
1.根据定义,Kronecker积矩阵可以表示为:
F N = F 4 ⊗ F 8 F_N = F_4 ⊗ F_8 FN=F4F8
2.分别对F_4和F_8进行适当的低秩矩阵分解:
F 4 ≈ D 1 D 2 . . . D m F 8 ≈ E 1 E 2 . . . E n F_4 ≈ D_1D_2...D_m\\ F_8 ≈ E_1E_2...E_n F4D1D2...DmF8E1E2...En
3.然后根据Kronecker积的性质,有:
F N ≈ ( D 1 D 2 . . . D m ) ⊗ ( E 1 E 2 . . . E n ) = ( D 1 ⊗ E 1 ) ( D 2 ⊗ E 2 ) . . . ( D m ⊗ E n ) F_N ≈ (D_1D_2...D_m) ⊗ (E_1E_2...E_n)\\ = (D_1⊗E_1)(D_2⊗E_2)...(D_m⊗E_n) FN(D1D2...Dm)(E1E2...En)=(D1E1)(D2E2)...(DmEn)
4.矩阵D和E的分解要满足稀疏性约束和取值范围约束。
5.通过搜索找到使逼近误差最小的D和E的分解。
6.计算复杂度时考虑D、E中矩阵的数目及稀疏性。

F N F_N FN N = N 1 N 2 N=N_1N_2 N=N1N2阶的Kronecker积矩阵:
F N = F N 1 ⊗ F N 2 F_N=F_{N_1}\otimes F_{N_2} FN=FN1FN2
其中 F N 1 F_{N_1} FN1 F N 2 F_{N_2} FN2分别是 N 1 N_1 N1阶和 N 2 N_2 N2阶DFT矩阵。
F N 1 F_{N_1} FN1 F N 2 F_{N_2} FN2分别进行低秩分解:
F N 1 ≈ D 1 D 2 ⋯ D M F_{N_1}\approx D_1D_2\cdots D_M FN1D1D2DM
F N 2 ≈ E 1 E 2 ⋯ E L F_{N_2}\approx E_1E_2\cdots E_L FN2E1E2EL
其中矩阵 D i , E j D_i,E_j Di,Ej满足约束条件:
1.每行最多2个非零元素(约束1)
2.非零元素取值范围为整数集P(约束2)
则根据Kronecker积的性质,有:
F N ≈ ( D 1 D 2 ⋯ D M ) ⊗ ( E 1 E 2 ⋯ E L ) F_N\approx(D_1D_2\cdots D_M)\otimes(E_1E_2\cdots E_L) FN(D1D2DM)(E1E2EL)
= ( D 1 ⊗ E 1 ) ( D 2 ⊗ E 2 ) ⋯ ( D M ⊗ E L ) =(D_1\otimes E_1)(D_2\otimes E_2)\cdots(D_M\otimes E_L) =(D1E1)(D2E2)(DMEL)
搜索找到使逼近误差最小的 D i , E j D_i,E_j Di,Ej的最优分解,然后计算相应的复杂度。
Kronecker积矩阵保留了被合成矩阵的结构特征,这为低秩逼近提供了可能。
将大维DFT矩阵分解为多个小维DFT矩阵的Kronecker积,可以分别对小矩阵进行逼近,降低了优化难度。
将逼近问题分解为多个小规模子问题,符合“分治”的一般思想。
Kronecker积运算保留了矩阵乘法,可以继续使用低秩矩阵分解逼近的思路。
分解出的小矩阵满足稀疏性约束,可以有效减少乘法复杂度。
小矩阵取值范围限制也降低了每个乘法的计算复杂度。
可以通过搜索找到最小逼近误差的小矩阵分解,保证一定的逼近精度。
矩阵分解数量和取值范围可根据精度需求调整,实现可配置化。

import numpy as np 
from scipy.linalg import krondef dft_matrix(n):i, j = np.meshgrid(np.arange(n), np.arange(n))omega = np.exp(-2 * np.pi * 1j / n)W = np.power(omega, i*j) return W / np.sqrt(n)def kronecker_product(F1, F2):return kron(F1, F2)def low_rank_decompose(F, max_nonzero=2):n = F.shape[0]D = []for i in range(n):d = np.diag([F[i,i]] + [0]*(n-1)) D.append(d)D_comb = list(combinations(D, max_nonzero))# 选择误差最小的组合F_approx = np.identity(n)for d in D_comb[best_index]:F_approx = F_approx @ derror = np.linalg.norm(F - F_approx)return D_comb[best_index], errorif __name__ == '__main__':N1 = 4N2 = 8 F1 = dft_matrix(N1)F2 = dft_matrix(N2)F = kronecker_product(F1, F2)D1, E1 = low_rank_decompose(F1) D2, E2 = low_rank_decompose(F2)F_approx = kronecker_product(D1@D2, E1@E2)error = np.linalg.norm(F - F_approx) / (N1*N2)print(error)

问题五、

增加了精度限制要求,RMSE≤0.1。这个问题的主要难点是需要在满足精度约束的前提下,通过调整矩阵分解中元素的取值范围,来获得最小的硬件复杂度。针对这个问题,具体思路是:
1.使用问题3中矩阵分解的方法,将DFT矩阵F_N分解为多个对角矩阵的乘积。
2.对取值范围P进行递增搜索,比如依次取[0,±1]、[0,±1,±2]等,直到满足精度要求。
3.在每个取值范围下,搜索非零元素位置和取值,使RMSE最小。
4.记录下满足精度要求的最小取值范围。
5.在这个取值范围下,计算相应的硬件复杂度。
6.对不同大小的DFT矩阵N重复上述过程。

设DFT矩阵为 F N F_N FN,将其分解为K个对角矩阵 D k D_k Dk的乘积:
F N ≈ D 1 D 2 ⋯ D K F_N \approx D_1D_2\cdots D_K FND1D2DK
其中每个 D k D_k Dk满足:
1.每行最多2个非零元素(约束1)
2.非零元素取值范围为整数集 P P P(约束2)
要使逼近误差满足要求:
RMSE = ∣ F N − D 1 D 2 ⋯ D K ∣ F N ≤ 0.1 \text{RMSE} = \frac{|F_N - D_1D_2\cdots D_K|_F}{N} \leq 0.1 RMSE=NFND1D2DKF0.1
进行以下迭代搜索:
1.初始化取值范围: P = 0 , ± 1 , ± 2 P={0, ±1, ±2} P=0,±1,±2
2.在当前 P P P下,搜索 D k D_k Dk的最优分解,使RMSE最小
3.如果RMSE > 0.1 > 0.1 >0.1,扩大取值范围 P P P,增加整数集大小
4.重复2)3),直到RMSE ≤ 0.1 \leq0.1 0.1
5.输出此时的 P P P和对应的复杂度 C C C
其中,复杂度计算如前。
通过调整取值范围,可以满足精度要求,并使复杂度尽可能小。
设置精度约束RMSE≤0.1是问题的实际需求,方法必须首先满足这一约束。
通过搜索逐步扩大取值范围,可以系统地满足精度需求。
取值范围最小时,对应复杂度也最小,所以可以找到复杂度最小的解。
矩阵分解方法满足稀疏性,可以减少乘法次数,降低复杂度。
取值范围小,可以减少单个乘法的计算量,也降低了复杂度。
搜索可以找到精度和复杂度的最优trade-off。
不同大小矩阵可统一适用该方法,具有普适性。
可以获得在给定精度需求下的最小复杂度方案。
矩阵分解个数、取值范围都可配置,实现灵活可控。

在这里插入图片描述

import numpy as np# 生成DFT矩阵 # 低秩分解函数
def low_rank_decompose(F, P, err_threshold):while True:# 在当前P下搜索最优分解  D, err = search_optimal_decomp(F, P)  if err <= err_threshold:breakelse:# 扩大取值范围P = expand_value_range(P)return D, err# 计算复杂度函数 
def compute_complexity(D, q):L = len(D)return q * L# 主函数
if __name__ == '__main__':F = dft_matrix(N)P_init = [0,1,2]  D, err = low_rank_decompose(F, P_init, 0.1)q = len(P)comp = compute_complexity(D, q)

消融实验分析:

基准模型:使用完整的方法,即矩阵分解+取值范围控制+稀疏性约束。测量其逼近误差RMSE和复杂度C。
移除取值范围控制:仅使用矩阵分解+稀疏性约束,不限制取值范围。测量RMSE和C。
移除稀疏性约束:仅使用矩阵分解+取值范围控制,不要求稀疏性。测量RMSE和C。
仅矩阵分解:不使用取值范围控制和稀疏性约束。测量RMSE和C。
对比不同模型的RMSE和C。高RMSE表示逼近精度损失;高C表示复杂度增加。

矩阵分解是实现低复杂度逼近DFT的有效方法,但需要设计实现稀疏性。
约束矩阵中元素的取值范围,可以降低单个乘法的计算量。
在满足精度需求前提下,通过搜索可以找到使复杂度最小的分解方案。
对Kronecker积矩阵进行分解,可以将大型DFT分解为多个小矩阵,降低优化难度。
消融实验可以验证不同设计决策对逼近误差和复杂度的影响。
需要权衡误差精度与计算复杂度,根据实际需求确定可接受的trade-off。
该方法可以作为一种替代FFT的低复杂度DFT实现策略。
优化搜索和代码实现等细节亟待进一步改进。

想要获取更多完整版看看这里哈~
(5 封私信 / 2 条消息) 如何评价2023数学建模研赛B题? - csdn

相关文章:

2023 “华为杯” 中国研究生数学建模竞赛(B题)深度剖析|数学建模完整代码+建模过程全解全析

华为杯数学建模B题 当大家面临着复杂的数学建模问题时&#xff0c;你是否曾经感到茫然无措&#xff1f;作为2021年美国大学生数学建模比赛的O奖得主&#xff0c;我为大家提供了一套优秀的解题思路&#xff0c;让你轻松应对各种难题。 让我们来看看研赛的B题呀~&#xff01; 问…...

文件相关工具类

文章目录 1.MultipartFile文件转File2.读取文件(txt、json)3.下载网络文件4.压缩文件 1.MultipartFile文件转File public File transferToFile(MultipartFile multipartFile) { // 选择用缓冲区来实现这个转换即使用java 创建的临时文件 使用 MultipartFile.transferto()…...

18795-2012 茶叶标准样品制备技术条件

声明 本文是学习GB-T 18795-2012 茶叶标准样品制备技术条件. 而整理的学习笔记,分享出来希望更多人受益,如果存在侵权请及时联系我们 1 范围 本标准规定了各类茶叶(除再加工茶)标准样品的制备、包装、标签、标识、证书和有效期。 本标准适用于各类茶叶(除再加工茶)感官品质…...

C++11互斥锁的使用

是C11标准库中用于多线程同步的库&#xff0c;提供互斥锁(mutex)及其相关函数。 以下是一些基本的使用示例&#xff1a; 1.创建和销毁互斥锁 #include <mutex>std::mutex mtx;2.加锁 std::lock_guard<std::mutex> lock(mtx); // 加锁 // 或者 mtx.lock(); //…...

unity 桌面程序

using System; using System.Collections; using System.Collections.Generic; using System.Runtime.InteropServices; using UnityEngine; public class chuantou : MonoBehaviour { [DllImport(“user32.dll”)] public static extern int MessageBox(IntPtr hwnd,string t…...

echarts统一纵坐标y轴的刻度线,刻度线对齐。

要求&#xff1a; 纵坐标刻度线对齐&#xff1b;刻度间隔为5&#xff1b;去掉千位默认的逗号&#xff1b;刻度最小是0. 效果图&#xff1a; 代码&#xff1a; yAxis: [{type: "value",position: "left",name: "kW",offset: 100,nameTextStyle:…...

一个数据库版本兼容问题

mysql旧的版本号是&#xff1a;5.3.10 本机版本号是&#xff1a;8.0.22 报错&#xff1a;“com.mysql.jdbc.exceptions.jdbc4.MySQLNonTransientConnectionException: Could not create” 1.程序里做兼容&#xff1a; <dependency><groupId>mysql</groupId>…...

学习Nano编辑器:入门指南、安装步骤、基本操作和高级功能

文章目录 使用Nano编辑器入门指南引言1.1 关于Nano编辑器1.2 Nano的起源和特点 安装Nano2.1 在Debian/Ubuntu系统上安装Nano2.2 在CentOS/RHEL系统上安装Nano2.3 在其他Linux发行版上安装Nano 启动Nano3.1 命令行启动Nano3.2 打开文件 Nano的基本操作4.1 光标移动和选择文本4.2…...

在北京多有钱能称为富

背景 首先声明&#xff0c;此讨论仅限个人的观点&#xff0c;因为我本身不富嘛&#xff0c;所以想法应该非常局限。 举个栗子 富二代问我朋友&#xff0c;100~1000w之间&#xff0c;推荐一款车&#xff1f; 一开始听到这个问题的时候&#xff0c;有被唬住&#xff0c;觉得预…...

Chrome扩展程序开发随记

在Chrome浏览器向正被浏览的外网网页植入自定义JS脚本 为了实现如标题的目的&#xff0c;需要开发一个Chrome扩展程序。接下来内容是实现简要步骤&#xff1a; 一、新建文件夹&#xff0c;命名为项目名&#xff0c;如“MyPlugin”。 二、进入文件夹内&#xff0c;新建名为“…...

使用命令行快速创建Vite项目

一、构建项目 在终端中使用如下命令行&#xff1a; npm create vite 二、定义项目名称 三、选择项目类型 Vanilla是我们常用的JavaScript&#xff0c;Vue和React是常用前端框架&#xff0c;可以根据自己的需要进行选择 通过上下键进行选择&#xff0c;按下回车进行确认 创建…...

int *a, int **a, int a[], int *a[]的区别

int *a; ---定义一个指向整型变量的指针a int **a; ---定义一个指向整型变量指针的指针a int a[]; ---定义一个整型变量数组a int *a[]; ---定义一个指向整型变量指针的数组a...

leetcode100----双指针

283. 移动零 给定一个数组 nums&#xff0c;编写一个函数将所有 0 移动到数组的末尾&#xff0c;同时保持非零元素的相对顺序。 请注意 &#xff0c;必须在不复制数组的情况下原地对数组进行操作。 示例 1:输入: nums [0,1,0,3,12] 输出: [1,3,12,0,0] 示例 2:输入: nums …...

ORM基本操作

ORM基本操作 基本操作包括增删改查操作&#xff0c;即(CRUD操作) CRUD是指在做计算处理时的增加(Create)、读取查询(Read)、更新Update)和删除(Delete) ORM CRUD 核心-> 模型类管理器对象 每个继承自 models.Model 的模型类&#xff0c;都会有一个 objects 对象被同样继…...

c语言进阶部分详解(指针进阶2)

大家好&#xff01;我快马加鞭接着写出指针部分part2部分。第一部分见&#xff1a;c语言进阶部分详解&#xff08;指针进阶1&#xff09;_总之就是非常唔姆的博客-CSDN博客 指针初阶部分见&#xff1a;c语言进阶部分详解&#xff08;指针初阶&#xff09;_总之就是非常唔姆的博…...

Java基础(一)——Hello World,8种数据类型,键盘录入

个人简介 &#x1f440;个人主页&#xff1a; 前端杂货铺 &#x1f64b;‍♂️学习方向&#xff1a; 主攻前端方向&#xff0c;正逐渐往全干发展 &#x1f4c3;个人状态&#xff1a; 研发工程师&#xff0c;现效力于中国工业软件事业 &#x1f680;人生格言&#xff1a; 积跬步…...

JAVA学习笔记(IF判断结构)

/*** 学习JAVA单分支结构* 掷骰子游戏* 1.如果三个随机数的和大于15&#xff0c;则手气不错&#xff1b;* 2.如果三个随机数的和在10-15之间&#xff0c;手气一般&#xff1b;* 3.如果三个随机数的和1在0以下&#xff0c;手气不太好。*/public class TestIf01 {public static v…...

【跟小嘉学 PHP 程序设计】二、PHP 基本语法

系列文章目录 【跟小嘉学 PHP 程序设计】一、PHP 开发环境搭建 【跟小嘉学 PHP 程序设计】二、PHP 基本语法 文章目录 系列文章目录@[TOC](文章目录)前言一、PHP基本语法1.1、hello,world1.2、PHP语法的其他形式1.2.1、简短形式(了解即可)1.2.2、Script 风格1.2.3、ASP 风格1…...

面试总结之微服务篇

一、概览 1、微服务常用组件 微服务给系统开发带来了诸多问题和挑战&#xff0c;如服务间通信和调用的复杂性、数据一致性和事务管理、服务治理和版本管理等&#xff0c;为解决应对这些问题和挑战&#xff0c;各种微服务组件应运而生微服务的常见组件和实现&#xff1a; 1…...

ElementUI之登陆+注册

一.什么是ElementUI 二.ElementUI完成用户注册登录界面搭建 使用命令npm install element-ui -S&#xff0c;添加Element-UI模块 导依赖 建立登录和注册页面 ​编辑 配置样式 编写登录页面&#xff08;Login&#xff09; 编写注册页面&#xff08;reginter&#xff09; …...

新版kafka可视化界面组件

二、安装kafka可视化客户端工具&#xff08;kafka tool 2&#xff09; 1、下载安装 在官网中找到对应自己电脑系统的版本&#xff1a; kafka Tool2官网下载地址&#xff1a; Offset Explorer 这个方案是为Kafka依赖zookeeper提供的可视化解决方案。 前言 在早期使用kafka的…...

​P1102 A-B 数对 【双指针(尺取法)】​

P1102 A-B 数对 【双指针&#xff08;尺取法&#xff09;】 题目描述 给出一串正整数数列以及一个正整数 C&#xff0c;要求计算出所有满足 A−BC 的数对的个数&#xff08;不同位置的数字一样的数对算不同的数对&#xff09;。 输入格式 输入共两行。 第一行&#xff0c;两个…...

Flutter绘制拖尾效果

演示&#xff1a; 代码&#xff1a; import dart:ui;import package:flutter/material.dart; import package:kq_flutter_widgets/widgets/chart/ex/extension.dart;class TrailingView extends StatelessWidget {const TrailingView({super.key});overrideWidget build(Build…...

【Newman+Jenkins】实施接口自动化测试

一、是什么Newman Newman就是纽曼手机这个经典牌子&#xff0c;哈哈&#xff0c;开玩笑啦。。。别当真&#xff0c;简单地说Newman就是命令行版的Postman&#xff0c;查看官网地址。 Newman可以使用Postman导出的collection文件直接在命令行运行&#xff0c;把Postman界面化运…...

kr 第三阶段(六)C++ 逆向

结构体 结构体对齐 设置结构体对齐值 方法1&#xff1a;在 Visual Studio 中可以在 项目属性 -> 配置属性 -> C/C -> 所有选项 -> 结构体成员对齐 中设置结构体对齐大小。方法2&#xff1a;使用 #pragma pack(对齐值) 来设置&#xff0c;不过要想单独设置一个结…...

医药行业安全生产信息化建设分享

随着科技的快速发展和全球化进程的推进&#xff0c;医药行业作为人类健康和安全的重要组成部分&#xff0c;面临着日益严峻的安全生产挑战。近年来&#xff0c;医药企业对于安全生产的需求越来越强烈&#xff0c;安全生产信息化建设成为了医药行业发展的重要趋势。本文将探讨医…...

C 语言简单入门

C 语言发展历史|标准 1972年&#xff0c;丹尼斯里奇&#xff08;Dennis Ritch&#xff09;和肯汤普逊&#xff08;Ken Tompson&#xff09;在贝尔实验室开发 UNIX 操作系统时基于 B 语言设计出 C 语言。 1987年&#xff0c;布莱恩柯林汉&#xff08;Brian Kernighan&#xff…...

Levels - UE5中的建模相关

一些日常的笔记&#xff1b; 可以使用Shapes面板建立基础模型&#xff1a; 可以在PolyModel中继续细分模型&#xff1a; UE5中的建模有PolyGroups概念&#xff0c;可以在Attributes面板中直接编辑&#xff1a; 使用GrpPnt方式可以直接用笔刷设定新的PolyGroups&#xff0c;这样…...

数据中心与数据仓库的区别

在数字化时代&#xff0c;数据已经成为企业竞争的核心资源&#xff0c;数据处理和数据管理也变得越来越重要。在数据处理方面&#xff0c;数据中台和数据仓库是两种常见的数据处理方式&#xff0c;它们有着不同的特点和适用场景。本文将从技术角度对数据中台和数据仓库的区别进…...

[2023.09.18]: Rust中类型转换在错误处理中的应用解析

随着项目的进展&#xff0c;关于Rust的故事又翻开了新的一页&#xff0c;今天来到了服务器端的开发场景&#xff0c;发现错误处理中的错误类型转换有必要分享一下。 Rust抽象出来了Result<T,E>&#xff0c;T是返回值的类型&#xff0c;E是错误类型。只要函数的返回值的类…...

wordpress 5.0.2企业站主题/百度新闻发布平台

虽然这是一次失败的渗透&#xff0c;但是也学到不少新姿势。 目标机环境&#xff1a;①外网②win2012③360全家桶 一&#xff0c;利用Struts2终极利用工具上传一句话 jsp的一句话&#xff0c;有时候会出现兼容问题。比如Cknife的jsp一句话&#xff0c;K8飞刀就连接不了。我这里…...

云主机如何做两个网站/百度seo排名教程

网页爬虫知识点总结 1.什么是爬虫&#xff1f; 爬虫就是&#xff1a;模拟浏览器发送请求&#xff0c;获取响应2.爬虫的分类&#xff0c;爬虫的流程 聚焦爬虫&#xff1a;针对特定的网站的爬虫 准备url地址 -->发送请求 获取响应–> 提取数据–> 保存获取响应–>…...

网站淘宝推广怎么做/百度账号人工客服电话

导读&#xff1a; 什么情况下需要使用全局上下文呢&#xff0c;情况有以下几点&#xff1a; 例如在Service服务中不能通过参数传过来&#xff0c;但是又需要用到这个context参数&#xff0c;这种情况下就需要使用全局上下文。例如工具类中&#xff0c;频繁传递上下文参数的话&a…...

网站建设飠金手指科杰十五/营销渠道名词解释

在本文中&#xff0c;GetDate()获得的日期由两部分组成&#xff0c;分别是今天的日期和当时的时间&#xff1a; Select GetDate() 用DateName()就可以获得相应的年、月、日&#xff0c;然后再把它们连接起来就可以了&#xff1a; Select Datename(year,GetDate())-Datename(mon…...

ppt网站超链接怎么做/企业网站模板

“程序猿”的等级划分 “程序猿”大致可分为 菜鸟程序员、码农、程序员、成功的程序员、著名程序员 和 顶级程序员…… 1菜鸟程序员 之所以称这类程序猿为菜鸟程序员&#xff0c;是因为他们的技术比较渣&#xff08;当然我现在菜鸟都算不上&#xff09;。在工作中&#xff0…...

自己做的网站可以挂在哪里/搜索引擎营销

写在前面&#xff1a; 2009年的时候结合网上的资料整理了下Flashback的用法。 2011年5月份起&#xff0c;把我这几年来的整理的资料又重新进行了一个整理&#xff0c;暂定为《David Dai Oracle 学习手册》&#xff0c; 等第一版整理完会免费上传到网络。 对Flashback 这块又重新…...