精华内容
下载资源
问答
  • Lund University抽象代数讲义系列,中文版会在我的博客中逐渐更新。 本资源主要讲述了域中的基本定理,包括的扩张、分割、代数闭包等内容。
  • 这可以通过将手性物质添加到对两个独立中心电荷具有任意值实现来扩展。 通过引入其他自由场,我们将构造扩展到最小超对称BMS 3代数和非线性高自旋BMS 3 -W 3代数。 我们还描述了通过Wakimoto表示实现SU(2)...
  • 我记得当我们接触到x2=−1x^2=-1x2=−1这个方程时候,虚数iii第一次进入到了我们世界,对于虚数而言,他加法和乘法运算都并无新意: i+i=2ii+i=2ii+i=2i 2i+3i=5i2i+3i=5i2i+3i=5i 唯一新奇之处就在于虚数...

    1 回顾:复数和复平面

    首先我们快速的回顾一下复数和复平面的基本知识,便于后续知识的介绍。我记得当我们接触到x2=1x^2=-1这个方程的时候,虚数ii第一次进入到了我们的世界中,对于虚数而言,他的加法和乘法运算都并无新意:

    i+i=2ii+i=2i
    2i+3i=5i2i+3i=5i

    唯一的新奇之处就在于虚数的平方运算,也就是在解方程x2=1x^2=-1的时候,其平方运算结果是i2=1i^2=-1

    那么对虚数有了认识之后,复数的概念就很自然的出来了。复数是一个形如a+bia+bi的数,他由实数aa和虚数bibi组成,其中复数的实部是Re(a+bi)=aRe(a+bi)=a,而他的虚部则是Im(a+bi)=bIm(a+bi)=b

    复数的加法运算很简单,他被描述成实部和虚部分别对应相加:
    (a+bi)+(c+di)=(a+c)+(b+d)i(a+bi)+(c+di)=(a+c)+(b+d)i

    例如:有两个复数z1=2+iz_1=2+iz2=3+2iz_2=3+2i,则z1z_1z2z_2的加法运算结果为:z1+z2=5+3iz_1+z_2=5+3i

    实际上,我们不难通过对比发现,复数的加法有点类似于向量空间R2R^2中的向量加法运算:[ab]+[cd]=[a+cb+d]\begin{bmatrix}a\\b\end{bmatrix}+\begin{bmatrix}c\\d\end{bmatrix}=\begin{bmatrix}a+c\\b+d\end{bmatrix}

    而复数的乘法运算则是需要应用分配律:

    (a+bi)(c+di)(a+bi)(c+di)=ac+adi+bci+bdi2=ac+adi+bci+bdi^2=(acbd)+(ad+bc)i=(ac-bd)+(ad+bc)i

    我们还是用上面的两个复数进行举例,则z1z_1z2z_2的乘法运算结果为:z1z2=(2+i)(3+2i)=6+7i+2i2=4+7iz_1z_2=(2+i)(3+2i)=6+7i+2i^2=4+7i

    将复数和二维向量进行对比后可以发现:我们可以在一个平面上来表示任意一个复数,这个平面就是复平面,我们将平面上的xx轴称之为实轴,yy轴称之为虚轴,通过分别将实部和虚部作为xx轴和yy轴上的坐标,我们就能够将每一个复数表示成为复平面上的对应点,实际上这就类似于在向量空间R2R^2上对二维向量进行表示。

    对于复数的模这个概念,大家应该不会陌生。复数z=a+biz=a+bi,我们将a2+b2\sqrt{a^2+b^2}称作是复数zz的模或绝对值,记作z|z|,也可以记作是rr

    引入了复数的模长rr这个概念,我们可以基于此谈谈复数的极坐标表示法。对于复数的极坐标,另一个重要的量是角度θ\theta,此时复数的实部记作是a=rcosθa=rcos\theta,虚部记作是b=rsinθb=rsin\theta,因此整个复数又被写作是z=a+bi=rcosθ+irsinθz=a+bi=rcos\theta+irsin\theta,最终我们把式子合并,记作:z=reiθz=re^{i\theta}

    我们在这里列举了三种复数的表示方法,尤其是极坐标的表示法为后面的重要内容埋下了伏笔,利用极坐标形式表示的复数,在进行幂运算的时候是非常方便的。复数zznn次幂为zn=rneinθz^n=r^ne^{in\theta},从式子中我们可以观察到:对于复数的nn次幂,在复平面上表示为:复数的模长(半径rr)变成了原始模长的nn次方,夹角θ\theta变为了原来的nn倍。

    共轭的概念也是复数中的一个重要基础概念,复数z=a+biz=a+bi的共轭复数记作是zˉ=abi\bar{z}=a-bi,即实部相同,虚部符号恰好相反。从几何意义的角度来说,复数zz和共轭复数zˉ\bar{z}在复平面上关于实轴对称。

    如下图7.2所示,我们来实际的在一个复平面上展示上述基本概念:

    图7.2  复平面上的复数表示

    从图中我们看到了一个半径为11的单位圆,即对于复数z=a+biz=a+bi而言,他表示所有a2+b2=1a^2+b^2=1的复数,我们可以把他们记作是z=cosθ+isinθz=cos\theta+isin\theta,极坐标表示形式为:z=eiθz=e^{i\theta}。我们把这两个等式结合起来,就有:

    eiθ=cosθ+isinθe^{i\theta}=cos\theta+isin\theta

    这就是大名鼎鼎的欧拉公式,大家可以稍作留意。对于这种模长(半径)为11的复数,他具备一个非常好的性质。大家可以思考一下他的nn次幂运算的最终结果,即结果所得的复数半径始终为11,保持不变,只有θ\theta角变为了原来的nn倍,也就是说幂运算的结果,始终都在复平面的单位圆上滑动。

    由此引出一个非常重要的复数:ω=e2πi/n\omega=e^{2\pi i/n},如图7.3所示,我们可以看出复数ω\omega的几何意义在于:他是复平面单位圆上的第一个nn等分点。

    图7.3  复平面单位圆上的8等分点

    复数ω=e2πi/n\omega=e^{2\pi i/n}有一个非常重要的性质,请大家务必要牢牢记住,那就是ω1\omega^1,ω2\omega^2,ω3\omega^3,ω4\omega^4,…,ωn\omega^nnn个复数的nn次幂的运算结果都是11。换句话说,这nn个复数就是方程zn=1z^n=1的解。

    讲到这里,知识点并不算太复杂,但是或许你暗暗在心中质疑这里讲的复数与我们本书的主题有什么关联?请你耐心的继续往下读,这里我们可以事先剧透一下,复数ω\omega将是离散傅里叶变换中傅里叶矩阵的核心元素。

    在知识回顾的最后,我们列举一下如何用python实现复数的常用基本运算:
    代码如下:

    z1 = 2 + 1j
    z2 = 3 + 5j
    print(z1.real)  #实部
    print(z2.imag)  #虚部
    print(z1+z2)    #加法
    print(z1*z2)    #乘法
    print(z1.conjugate())  #共轭
    print(abs(z1))  #模长
    

    运行结果:

    2.0
    5.0
    (5+6j)
    (1+13j)
    (2-1j)
    2.23606797749979
    

    2 实数域的拓展:共轭转置

    我们在前面的内容中已经学习过,列向量u=[u1u2u3...un]u=\begin{bmatrix}u_1\\u_2\\u_3\\...\\u_n\end{bmatrix}的转置是行向量,即:uT=[u1u2u3...un]u^T=\begin{bmatrix}u_1&u_2&u_3&...&u_n\end{bmatrix},而实数域中向量长度的平方就是向量与自身的内积,也可以写作是uTuu^Tu的形式。

    那么对于包含有复数成分的复向量zz呢?转置的概念能否直接迁移过来?我们先不忙着回答是还是否,先看一个实例:

    比如我们也想求一个复向量z=[10i]z=\begin{bmatrix}1\\0\\i\end{bmatrix}长度的平方,如果我们依旧沿用实数域中的操作方法,就会有:

    z2=zTz=[10i][10i]=1+01=0|z|^2=z^Tz=\begin{bmatrix}1&0&i\end{bmatrix}\begin{bmatrix}1\\0\\i\end{bmatrix}=1+0-1=0

    对于这个答案,我们的内心之中肯定是难以接受的,因为向量zz并非一个零向量,但是我们却计算出了他的长度为00。因此,复向量和实数向量对于转置的操作是有区别的,对于一个复向量zz和复矩阵AA而言,我们在对他进行与实数域中相同的转置操作时,还需要将其中的复数元素转换成他的共轭复数,因此整个过程合并称作是共轭转置。

    即,对于复向量z=[z1z2z3...zn]=[a1+b1ia2+b2ia3+b3i...an+bni]z=\begin{bmatrix}z_1\\z_2\\z_3\\...\\z_n\end{bmatrix}=\begin{bmatrix}a_1+b_1i\\a_2+b_2i\\a_3+b_3i\\...\\a_n+b_ni\end{bmatrix},我们将他的共轭转置记作是:zH=[z1ˉz2ˉz3ˉ...znˉ]z^H=\begin{bmatrix}\bar{z_1}&\bar{z_2}&\bar{z_3}&...&\bar{z_n}\end{bmatrix}=[a1b1ia2b2ia3b3i...anbni]=\begin{bmatrix}a_1-b_1i&a_2-b_2i&a_3-b_3i&...&a_n-b_ni\end{bmatrix}

    那么,在共轭转置的基础上,我们再来看看复数向量长度平方的计算结果:

    z2=zHz|z|^2=z^Hz=[a1b1ia2b2ia3b3i...anbni][a1+b1ia2+b2ia3+b3i...an+bni]=k=1n(ak2+bk2)=\begin{bmatrix}a_1-b_1i&a_2-b_2i&a_3-b_3i&...&a_n-b_ni\end{bmatrix}\begin{bmatrix}a_1+b_1i\\a_2+b_2i\\a_3+b_3i\\...\\a_n+b_ni\end{bmatrix}=\sum_{k=1}^{n}{(a^2_k+b^2_k)}

    从结果中我们发现,复数向量长度的平方就等于向量中各个成分的模长平方和:z2=zHz=i=1nzk2|z|^2=z^Hz=\sum_{i=1}^n{|z_k|^2}

    此时我们已经知道了复数向量长度的计算法则,那么我们再把这个概念引申一下,在复数域的范围内,求解复数向量u=[u1u2u3...un]u=\begin{bmatrix}u_1\\u_2\\u_3\\...\\u_n\end{bmatrix}v=[v1v2v3...vn]v=\begin{bmatrix}v_1\\v_2\\v_3\\...\\v_n\end{bmatrix}之间的内积:

    uv=uHv=[u1ˉu2ˉu3ˉ...unˉ][v1v2v3...vn]=u1ˉv1+u2ˉv2+u3ˉv3+...+unˉvnu\cdot v=u^Hv=\begin{bmatrix}\bar{u_1}&\bar{u_2}&\bar{u_3}&...&\bar{u_n}\end{bmatrix}\begin{bmatrix}v_1\\v_2\\v_3\\...\\v_n\end{bmatrix}=\bar{u_1}v_1+\bar{u_2}v_2+\bar{u_3}v_3+...+\bar{u_n}v_n

    其实复数域中的内积定义是可以把实数域的情况包含进去的,实数本质上就是虚部为00的复数,对这样的复数取其共轭复数,其结果仍然等于自身。那么对于一个实数向量而言,其共轭转置实质上就只有转置操作了。

    我们来看一个小例子,体会一下这里面的运算过程。我们有复向量u=[10i]u=\begin{bmatrix}1\\0\\i\end{bmatrix}和复向量v=[i31]v=\begin{bmatrix}i\\3\\1\end{bmatrix},求这两个向量的内积:

    很简单,一切都按照定义来进行操作:uvu\cdot v=uHv=[10i][i31]=u^Hv=\begin{bmatrix}1&0&-i\end{bmatrix}\begin{bmatrix}i\\3\\1\end{bmatrix}=ii=0=i-i=0

    从计算结果来看,复向量uuvv的内积为00,两个向量彼此正交。

    3 厄米特矩阵

    建立起了复向量的共轭转置概念之后,很自然的我们就能联想到矩阵的共轭转置操作,即同样在完成矩阵转置操作的同时,对矩阵的各元素取共轭复数。

    即,有原始矩阵A=[z11z12z13...z1nz21z22z23...z2nz31z32z33...z3n...............zm1zm2zm3...zmn]A=\begin{bmatrix}z_{11}&z_{12}&z_{13}&...&z_{1n}\\z_{21}&z_{22}&z_{23}&...&z_{2n}\\z_{31}&z_{32}&z_{33}&...&z_{3n}\\...&...&...&...&...\\z_{m1}&z_{m2}&z_{m3}&...&z_{mn}\end{bmatrix},则他的共轭转置矩阵为:AH=[zˉ11zˉ21zˉ31...zˉm1zˉ12zˉ22zˉ32...zˉm2zˉ13zˉ23zˉ33...zˉm3...............zˉ1nzˉ2nzˉ3n...zˉmn]A^H=\begin{bmatrix}\bar{z}_{11}&\bar{z}_{21}&\bar{z}_{31}&...&\bar{z}_{m1}\\\bar{z}_{12}&\bar{z}_{22}&\bar{z}_{32}&...&\bar{z}_{m2}\\\bar{z}_{13}&\bar{z}_{23}&\bar{z}_{33}&...&\bar{z}_{m3}\\...&...&...&...&...\\\bar{z}_{1n}&\bar{z}_{2n}&\bar{z}_{3n}&...&\bar{z}_{mn}\end{bmatrix},这和向量的共轭转置操作并无二致。

    到这里,其实我们可以同样提炼出这样一个事实,那就是:实数域内的转置操作就是复数域中共轭转置的一种特殊情况。

    由此,我们引出复数域中的一个极其重要的矩阵:厄米特矩阵,又称为自共轭矩阵。最好的方法还是在实数域中去找到对应的概念,那就是对称矩阵。在实数域中,如果矩阵SS的转置矩阵等于自身,即满足S=STS=S^T,则矩阵SS称之为是对称矩阵。引申到复数域中,如果一个复数矩阵SS,他的共轭转置矩阵等于自身,即满足S=sSHS=sSH,则矩阵S就是厄米特矩阵。

    我们举一个复数域内的厄米特矩阵来实际的看一看:

    S=[11+i2+3i1i22i23i2i3]S=\begin{bmatrix}1&1+i&2+3i\\1-i&2&-2i\\2-3i&2i&3\end{bmatrix},很显然,矩阵SS满足SH=SS^H=S,他的共轭转置矩阵等于他自身,矩阵SS就是一个厄米特矩阵,他的对角线上的元素必须是实数。

    很显然,实对称矩阵也是复数域中厄米特矩阵的一种特殊情况,那么我们还是按照之前类比思考的思路,在前面的章节中,我们重点学习过,实对称矩阵SS拥有非常好的性质,他拥有实数特征值和正交的特征向量。

    那么作为复数域中的延伸概念,厄米特矩阵是否拥有类似的性质?答案一定是肯定的,我们简要的来说明一下:

    第一个性质:厄米特矩阵SS的特征值一定是实数。

    这个证明过程很简单:

    Sz=λzzHSz=zHλzzHSz=λzHzSz=\lambda z \Rightarrow z^HSz=z^H\lambda z\Rightarrow z^HSz=\lambda z^Hz

    我们抓住zHSz=λzHzz^HSz=\lambda z^Hz这个关键等式进行观察,很显然等式的左侧有:

    (zHSz)H=zHSH(zH)H=zHSz(z^HSz)^H=z^HS^H(z^H)^H=z^HSz,我们可以观察出两个事实,一方面zHSzz^HSz是自共轭的,同时可以观察出zHSzz^HSz计算结果的维度是1×11\times 1,即结果是一个数,因此zHSzz^HSz显然只能是一个实数了。

    同时在等式右侧λzHz\lambda z^Hz当中,zHzz^Hz是复数向量zz长度的平方,显然也是实数,那么作为系数的特征值λ\lambda也必须是一个实数了。

    第二个性质:厄米特矩阵SS中,不同特征值对应的特征向量满足彼此正交。

    我们来看看任意两个特征值λ1\lambda_1λ2\lambda_2以及他们所分别对应的特征向量:z1z_1z2z_2。依照定义显然有Sz1=λ1z1Sz_1=\lambda_1z_1Sz2=λ2z2Sz_2=\lambda_2z_2

    我们处理第一个特征值定义式子:Sz1=λ1z1z2HSz1=λ1z2Hz1Sz_1=\lambda_1z_1\Rightarrow z_2^HSz_1=\lambda_1z^H_2z_1

    而对于第二个特征值定义式,我们有:(Sz2)H=(λ2z2)Hz2HSH=λ2z2H(Sz_2)^H=(\lambda_2z_2)^H \Rightarrow z_2^HS^H=\lambda_2z^H_2,等式两侧同时乘以向量z1z_1,我们可以得到z2HSHz1=λ2z2Hz1z^H_2S^Hz_1=\lambda_2z^H_2z_1

    由于SS是厄米特矩阵,满足自共轭特性,因此有λ1z2Hz1=λ2z2Hz1\lambda_1z^H_2z_1=\lambda_2z^H_2z_1,由于λ1\lambda_1λ2\lambda_2是不等的两个特征值,那么为了满足等式左右两边相等,则必须要求:z2Hz1=0z^H_2z_1=0,这不正是复数向量内积的定义式吗?两个复数向量内积为0,则二者必然正交。

    4 酉矩阵

    还是采用同样的思路,在讨论新概念酉矩阵之前,我们首先还是在实数矩阵中寻找对应的概念,还记得那个神奇的矩阵QQ吗?

    矩阵QQ是一个方阵,他的各列由一组标准正交向量q1q_1,q2q_2,q3q_3,......,qnq_n所构成,方阵QQ满足QTQ=IQ^TQ=I的等式关系,我们称之为正交矩阵,这是我们前面学习过的概念,大家应该非常熟悉。

    那么将这个概念拓展到复数域当中,在复数域中各列满足标准正交的方阵QQ我们也给他起了一个新名字,叫酉矩阵。很显然,基于复数向量内积的定义,这里实矩阵的转置操作就应该变成复数矩阵的共轭转置操作,即QTQHQ^T\Rightarrow Q^H。最终我们得出:酉矩阵QQ是一个方阵,满足QHQ=IQH=Q1Q^HQ=I\Rightarrow Q^H=Q^{-1}的关系。

    #5 傅里叶矩阵与离散傅里叶变换
    讲清楚酉矩阵的定义之后,我们不再过多的陷于细节性质的讨论。这里,我们直接抛出傅里叶矩阵的介绍,傅里叶矩阵号称是最重要的酉矩阵,用于进行离散傅里叶变换的处理工作。

    一个n×nn\times n的傅里叶矩阵的形式如下:

    Fn=1n[111...11ωω2...ωn11ω2ω4...ω2(n1)...............1ωn1ω2(n1)...ω(n1)2]F_n=\frac{1}{\sqrt{n}}\begin{bmatrix}1&1&1&...&1\\1&\omega&\omega^2&...&\omega^{n-1}\\1&\omega^2&\omega^4&...&\omega^{2(n-1)}\\...&...&...&...&...\\1&\omega^{n-1}&\omega^{2(n-1)}&...&\omega^{(n-1)^2}\end{bmatrix},其中ω=e2πi/n\omega=e^{2\pi i/n},傅里叶矩阵中第ii行,第jj列的元素表达式为ωij\omega^{ij}

    这里又一次的出现了ω=e2πi/n\omega=e^{2\pi i/n},在前面一部分中我们已经讲过,这个量表示复平面单位圆上的第一个nn等分点,因此nn阶傅里叶矩阵中的所有元素都位于单位圆的nn等分点上。

    为了便于我们计算,我们将ω=e2πi/n\omega=e^{2\pi i/n}按照欧拉公式eiθ=cosθ+isinθe^{i\theta}=cos\theta+isin\theta进行展开,得到e2πi/n=cos2πn+isin2πne^{2\pi i/n}=cos\frac{2\pi}{n}+isin\frac{2\pi}{n}

    了解了傅里叶矩阵的概念和形态之后,读者也许会问,这种矩阵有什么用处?前面不是已经对周期函数和非周期函数的傅里叶变换方法都做过介绍了吗?

    首先,顾名思义,傅里叶矩阵是用来辅助计算机进行傅里叶变换的,而前面介绍过的方法是提供给我们人来计算使用的。因为在信号处理的过程中,机器能够处理的都必须是离散的信号,因此我们前面介绍的连续时间周期函数和连续时间非周期函数都无法直接借助机器进行处理。

    机器能够处理什么样的信号?一方面是有限长度的信号,另一方面是离散的信号,这里的离散包含两个方面,一个是傅里叶变换前时域的信号必须离散,另一个是变换后频域里的频谱也必须离散。

    要想使用机器来进行傅里叶变换,就必须满足这三个条件,这称之为离散傅里叶变换(DFTDFT)。有限长度很好满足,我们对一段连续时间信号进行截断即可,截断区间我们可以取2π2\pi,通过对连续时间信号进行采样,获取时域内的离散输入。

    采样的个数一般定为2n2^n,如32,64,…,1024等等。我们在前面学习过,只有时域内的周期信号经过傅里叶变换才能得到离散的频谱,不过这个很好处理,我们将这段有限长度的时域信号进行周期延拓即可实现。

    我们通常借助计算机来实现离散傅里叶变换,那么理解好这个变换过程的输入和输出则非常重要。例如:我们对一个连续时间信号f(t)f(t)2π2\pi的采样区间内采样3232次,那么时间信号的输入就变成了离散的形式:

    x[n]=f(2πn32)x[n]=f(2\pi\frac{n}{32}),其中,n=0,1,2,...,31n=0,1,2,...,31

    即输入向量的元素为32个,即采样次数。

    然后,我们同样是把这个离散化后的函数x[n]x[n]用一组谐波基来进行表示,那么首先我们就要确定这一组谐波的基频率ω0\omega_0:具备该基频率的谐波是在整个2π2\pi采样周期内只震动一个周期的谐波函数cos(2πn32)cos(2\pi\frac{n}{32})sin(2πn32)sin(2\pi\frac{n}{32}),所有基函数的频率都是这个基频率的整数倍,因此经过离散傅里叶变换后的基函数依次为:1,cos(2πn32)cos(2\pi\frac{n}{32})sin(2πn32)sin(2\pi\frac{n}{32})cos(2π2n32)cos(2\pi\frac{2n}{32})sin(2π2n32)sin(2\pi\frac{2n}{32})cos(2π3n32)cos(2\pi\frac{3n}{32})sin(2π3n32)sin(2\pi\frac{3n}{32})cos(2π4n32)cos(2\pi\frac{4n}{32})sin(2π4n32)sin(2\pi\frac{4n}{32}),…,cos(2π31n32)cos(2\pi\frac{31n}{32})sin(2π32n32)sin(2\pi\frac{32n}{32}),同频的正余弦函数算作一组,即含32组基函数。

    因此,经过离散傅里叶变换后的输出向量里的元素也是3232个,但是这3232个量是复数形式的ak+bkja_k+b_kj,分别对应了每个频率的余弦和正弦基函数的系数,通过aka_kbkb_k就可以计算出每个频率谐波基的幅度和相位。

    傅里叶矩阵是离散傅里叶变换中的核心数据结构,而通过针对矩阵结构进行优化设计而形成的高速、优化的算法,我们称之为快速傅里叶变换,也就是我们常听说的FFT。他大幅提升了信号处理的效率。

    最后我们利用python语言来实际进行离散傅里叶变换的处理,首先我们来看看我们要处理的时域信号:

    f(t)=sin(t)+2sin(3t)+2cos(3t)+4sin(15t)f(t)=sin(t)+2sin(3t)+2cos(3t)+4sin(15t)

    绘制函数图像的代码如下:

    import numpy as np
    import matplotlib.pyplot as plt
    
    def f(x):
        return np.sin(x)+2*np.sin(3*x)+2*np.cos(3*x)+4*np.sin(15*x)
    
    x = np.linspace(0, 2*np.pi, 2048)
    plt.scatter(x, f(x))
    plt.grid()
    plt.show()
    

    如图7.4所示,我们来实际看看时域中信号在一个2π2\pi周期内的形态:
    图7.4  时域信号的形态

    下面我们就用python中的fft工具来对这段时域信号进行频域分析,代码如下:

    import numpy as np
    from scipy.fftpack import fft
    import matplotlib.pyplot as plt
    
    x = np.linspace(0, 2*np.pi, 128)
    y = np.sin(x)+2*np.sin(3*x)+2*np.cos(3*x)+4*np.sin(15*x)
    
    xf = np.arange(len(y))               #离散频率
    xf_half = xf[range(int(len(x)/2))]   #由于对称性,只取一半区域
    yf = abs(fft(y))/len(x)              #执行完fft后,对各频率的能量归一化处理
    yf_half = yf[range(int(len(x)/2))]   #由于对称性,只取一半区间
    
    plt.plot(xf_half, yf_half)
    plt.show()
    

    经过快速傅里叶变换之后,我们最终得到的结果如图7.5所示:
    图7.5  快速傅里叶变换后得到的频谱图

    我们仔细观察图中的数据,图中三个能量最高的峰值点,正对应我们时域函数f(t)=sin(t)+2sin(3t)+2cos(3t)+4sin(15t)f(t)=sin(t)+2sin(3t)+2cos(3t)+4sin(15t)中合成的三个谐波频率,且能量也和各谐波系数取模后的比例保持一致。

    展开全文
  • 我们同样采用类比的思考学习方法,将实数域中的转置操作延伸至复数域中的共轭转置,重新定义了复数中向量的内积和正交概念,同时将实数域中的重要矩阵,如对称矩阵、正交矩阵拓展到复数中,并找到其对应的厄米特...

    041c76b37b539ec43edf54f2e466eb42.gif

    337df2e2bfa4a3f340e9aef46fa9c471.png

    在这一小节中,我们尝试另一个维度的概念与应用拓展,即将向量和矩阵的概念从实数域拓展到复数域。我们同样采用类比的思考学习方法,将实数域中的转置操作延伸至复数域中的共轭转置,重新定义了复数域中向量的内积和正交概念,同时将实数域中的重要矩阵,如对称矩阵、正交矩阵拓展到复数域中,并找到其对应的厄米特矩阵和酉矩阵,在实数域和复数域的整体框架下,统一了他们的概念和方法。

    基于复数域中的这些重要矩阵,我们举例讨论了如何在这些概念的指引下,使用计算机进行离散傅里叶变换,可以说通过这部分的内容介绍,相信大家能够从整体的角度很好的理解和把握实数与复数、连续与离散、时域与频域、函数与向量这些概念之间的区别与联系。

    7.2.1  回顾:复数和复平面b8937bc49ec2112f0c9e7649565f5db7.png

    首先我们快速的回顾一下复数和复平面的基本知识,便于后续知识的介绍。我记得当我们接触到45b07c845dd90b319b30ecb044ecdb7d.png这个方程的时候,虚数97dbe68063a9c7a97ccce8f576691d8e.png第一次进入到了我们的世界中,对于虚数而言,他的加法和乘法运算都并无新意:

    58938cc3fdda314629dda09065b13413.png

    唯一的新奇之处就在于虚数的平方运算,也就是在解方程1bd99586d5469e9ac2499ac35f1cfc80.png的时候,其平方运算结果是47b2e64e7c6f7aec61aa8da3ed010028.png

    那么对虚数有了认识之后,复数的概念就很自然的出来了。复数是一个形如da4c60acccbe13a765426a3751262a5d.png的数,他由实数956b3bca462d6a16057dcc36abed28e3.png和虚数d25c5582571a454501a36c0377618a26.png组成,其中复数的实部是2db5b637d3df68c617b560aefc5802fe.png,而他的虚部则是5f1fdfb7851fe0452020dc88a5481273.png

    复数的加法运算很简单,他被描述成实部和虚部分别对应相加:

    fb066fee2b1b42ae337ad15723cdd681.png

    例如:有两个复数daf0eb5594e8af768d9de9b684d382c1.png,则620bb4b167668233b421e923b59aebc8.png19ca0f0a692293810a0f8c1c75f3eb1c.png的加法运算结果为:ee6b2dc7140e3023b6ffbf6d377f4fa5.png

    实际上,我们不难通过对比发现,复数的加法有点类似于向量空间8d0d25ea671e04ad8bca3fa01bce8ba4.png中的向量加法运算:a7981dbffa3ef5d2929e5df4da0ed44c.png

    而复数的乘法运算则是需要应用分配律:

    8ed2d84e8931beaa0cfdeda5eac356db.png

    我们还是用上面的两个复数进行举例,则6985772e087d6e844ebdaac36dacfcc2.png73a98c7acea3c0b8d92403ff431f0cda.png的乘法运算结果为:05216c413c6504ebf0eb44f44349fc13.png

    将复数和二维向量进行对比后可以发现:我们可以在一个平面上来表示任意一个复数,这个平面就是复平面,我们将平面上的fa6f77e331dce741bf035d073a24e9a1.png轴称之为实轴,8ff7962f8a05fd153583ce28d52c096e.png轴称之为虚轴,通过分别将实部和虚部作为fa6f77e331dce741bf035d073a24e9a1.png轴和8ff7962f8a05fd153583ce28d52c096e.png轴上的坐标,我们就能够将每一个复数表示成为复平面上的对应点,实际上这就类似于在向量空间5a218dfa0abdd15af21c3e981c8d79f8.png上对二维向量进行表示。

    对于复数的模这个概念,大家应该不会陌生。复数a33bb886dcb28f9dedf5183209db22b2.png,我们将041991ca6f126ac1767235f2e1ecee95.png称作是复数26db7ac683e4d363bb908dd1af846e96.png的模或绝对值,记作df31e553cb732377a31d89dcb5484e71.png,也可以记作是35d816b49f94c861f85f18589aaa70f5.png

    引入了复数的模长dcde7679364711fc8cf17142a4c4ed00.png这个概念,我们可以基于此谈谈复数的极坐标表示法。对于复数的极坐标,另一个重要的量是角度0c35a2b62e2de26c3d95b98e59f879c8.png,此时复数的实部记作是04095ef07839f1da24ddaf8a442e9db5.png,虚部记作是00dd3b941f0d2efe60ffaa5b3910524e.png,因此整个复数又被写作是44dc80599acf95aa34dbc57ab12965dd.png,最终我们把式子合并,记作:baf20cdc5f4f3b04899938ed442d1245.png

    我们在这里列举了三种复数的表示方法,尤其是极坐标的表示法为后面的重要内容埋下了伏笔,利用极坐标形式表示的复数,在进行幂运算的时候是非常方便的。复数d7dc794cf8635599a32124c30c3f5e98.png1fc639b40fbcc8cb1c44e81cb44b65c8.png次幂为d95b1d6f1d8356a4668ddb2822688bdf.png,从式子中我们可以观察到:对于复数的9ee0bb08d2f1030a36497ea4ea323f36.png次幂,在复平面上表示为:复数的模长(半径1b6014be26ffde9c1ba924e233cbf300.png)变成了原始模长的c699d129a6482ef79a49394ca68aec31.png次方,夹角c17db1522f25f06e369d899e198e8abc.png变为了原来的2d464821fb589f12be1780282eb0d847.png倍。

    共轭的概念也是复数中的一个重要基础概念,复数28e1043f691a48eb7db230bbe70099b9.png的共轭复数记作是caa474e79ae7a6de51353cdfc33f443b.png,即实部相同,虚部符号恰好相反。从几何意义的角度来说,复数eddd831747b351d95a301098c4bd3643.png和共轭复数cbc8b9c9cc72def004f7843c510631fd.png在复平面上关于实轴对称。

    如下图7.2所示,我们来实际的在一个复平面上展示上述基本概念:

    43592920094fadff0f2656540e30ec94.png

    图7.2  复平面上的复数表示

    从图中我们看到了一个半径为1的单位圆,即对于复数3846df3dbc42cb0e04b294d14caac357.png而言,他表示所有e37a92b74992a168c30f44bf70faebd1.png的复数,我们可以把他们记作是c4410b7e596ce4f2034fe50f09a7e269.png,极坐标表示形式为:e967358ed9249edfe8747014a5553ea2.png。我们把这两个等式结合起来,就有:

    8f258316e3c56bb812aa4a7ec63c6a6f.png

    这就是大名鼎鼎的欧拉公式,大家可以稍作留意。对于这种模长(半径)为1的复数,他具备一个非常好的性质。大家可以思考一下他的58fb09450004b0314f6c4571409e7315.png次幂运算的最终结果,即结果所得的复数半径始终为1,保持不变,只有0ee5de6d0fbb62ab8980fe5d44293bb9.png角变为了原来的d819bed45a78aeb51785ea43b60f0466.png倍,也就是说幂运算的结果,始终都在复平面的单位圆上滑动。

    由此引出一个非常重要的复数:628e41150d895332b20e3d64529e5be7.png,如图7.3所示,我们可以看出复数6413bec738f9f96d078f0384a2d7c478.png的几何意义在于:他是复平面单位圆上的第一个189555ec49bd025f31b2193634a459db.png等分点。

     b870eb474be4b284b4a821b431eb0a28.png

    图7.3  复平面单位圆上的8等分点

    复数8f40e785a1e6cfe40f1547d00456b1fb.png有一个非常重要的性质,请大家务必要牢牢记住,那就是9d9f62d14af365a8f1875e21019c7809.png4b0abd739766e88fba381871352ea021.png个复数的4a059f1c250107e754889c1fc4a842a0.png次幂的运算结果都是1。换句话说,这7747af202da8e9eb2d57dd26991d3e12.png个复数就是方程58878d591c2d0721da88f5410ca946ee.png的解。

    讲到这里,知识点并不算太复杂,但是或许你暗暗在心中质疑这里讲的复数与我们本书的主题有什么关联?请你耐心的继续往下读,这里我们可以事先剧透一下,复数b9eaecb364091c0492f3ed220305278e.png将是离散傅里叶变换中傅里叶矩阵的核心元素。

    在知识回顾的最后,我们列举一下如何用python实现复数的常用基本运算:

    代码如下:

    z1 = 2 + 1j
    z2 = 3 + 5j
    print(z1.real)  #实部
    print(z2.imag)  #虚部
    print(z1+z2)    #加法
    print(z1*z2)    #乘法
    print(z1.conjugate())  #共轭
    print(abs(z1))  #模长

    运行结果:

    2.0
    5.0
    (5+6j)
    (1+13j)
    (2-1j)
    2.23606797749979
    7.2.2  实数域的拓展:共轭转置b8937bc49ec2112f0c9e7649565f5db7.png

    我们在前面的内容中已经学习过,列向量fd0d27c2f6f6613a8a8ea0eddbc5aa10.png的转置是行向量,即:c187b6149cdb1f8055609c0ae76940f2.png,而实数域中向量长度的平方就是向量与自身的内积,也可以写作是dbd02719d01ef6442f6e124ad9c0caaf.png的形式。

    那么对于包含有复数成分的复向量ff9275d7f7707916f6be4090eb2240f2.png呢?转置的概念能否直接迁移过来?我们先不忙着回答是还是否,先看一个实例:

    比如我们也想求一个复向量35ec8fad269e1a7937b9121c4a84aec0.png长度的平方,如果我们依旧沿用实数域中的操作方法,就会有:

    6e50f88d8edfd3794e9e98cbcc82602b.png

    对于这个答案,我们的内心之中肯定是难以接受的,因为向量z并非一个零向量,但是我们却计算出了他的长度为0。因此,复向量和实数向量对于转置的操作是有区别的,对于一个复向量z和复矩阵A而言,我们在对他进行与实数域中相同的转置操作时,还需要将其中的复数元素转换成他的共轭复数,因此整个过程合并称作是共轭转置。

    即,对于复向量44e8c4e9557aa190c9a5ed377c343147.png,我们将他的共轭转置记作是:

    8574db45341b4751ddd17b3a2cd3813f.png

    那么,在共轭转置的基础上,我们再来看看复数向量长度平方的计算结果:

    b9a6ec9930c6148483d82d1851728d90.png

    从结果中我们发现,复数向量长度的平方就等于向量中各个成分的模长平方和:c18541f8b17451cf3fc3a22d57e52fff.png

    此时我们已经知道了复数向量长度的计算法则,那么我们再把这个概念引申一下,在复数域的范围内,求解复数向量0c47de171ac74b08a0c32b23db688f0e.pngc3b38bb4e34f676963b42a7fc3df3907.png之间的内积:

    47ead26db72133dc80d321a929cdbff2.png

    其实复数域中的内积定义是可以把实数域的情况包含进去的,实数本质上就是虚部为0的复数,对这样的复数取其共轭复数,其结果仍然等于自身。那么对于一个实数向量而言,其共轭转置实质上就只有转置操作了。

    我们来看一个小例子,体会一下这里面的运算过程。我们有复向量fe9d3d06f3b46fa9441dc23c063c6295.png和复向量d9a911d78cec35960d92176b642393d6.png,求这两个向量的内积:

    很简单,一切都按照定义来进行操作:

    3d1d585e77fd81813792b04020d8e451.png

    从计算结果来看,复向量uv的内积为0,两个向量彼此正交。

    7.2.3  厄米特矩阵b8937bc49ec2112f0c9e7649565f5db7.png

    建立起了复向量的共轭转置概念之后,很自然的我们就能联想到矩阵的共轭转置操作,即同样在完成矩阵转置操作的同时,对矩阵的各元素取共轭复数。

    即,有原始矩阵55081e6fbc27b21e71389857ede18161.png,则他的共轭转置矩阵为:c0d6f15d82fcb9ede7a1b7b71ed0213f.png,这和向量的共轭转置操作并无二致。

    到这里,其实我们可以同样提炼出这样一个事实,那就是:实数域内的转置操作就是复数域中共轭转置的一种特殊情况。

    由此,我们引出复数域中的一个极其重要的矩阵:厄米特矩阵,又称为自共轭矩阵。最好的方法还是在实数域中去找到对应的概念,那就是对称矩阵。在实数域中,如果矩阵S的转置矩阵等于自身,即满足30e7878fe0e6860e2b5e637e096825ca.png,则矩阵S称之为是对称矩阵。引申到复数域中,如果一个复数矩阵S,他的共轭转置矩阵等于自身,即满足23626b8ca4aff836a941447322518b2f.png,则矩阵S就是厄米特矩阵。

    我们举一个复数域内的厄米特矩阵来实际的看一看:

    4fc43a85c72008a2cb288dcdc4194188.png,很显然,矩阵S满足32ffe3d0f6992f94f3a6e3b49bdb4aeb.png,他的共轭转置矩阵等于他自身,矩阵S就是一个厄米特矩阵,他的对角线上的元素必须是实数。

    很显然,实对称矩阵也是复数域中厄米特矩阵的一种特殊情况,那么我们还是按照之前类比思考的思路,在前面的章节中,我们重点学习过,实对称矩阵S拥有非常好的性质,他拥有实数特征值和正交的特征向量。

    那么作为复数域中的延伸概念,厄米特矩阵是否拥有类似的性质?答案一定是肯定的,我们简要的来说明一下:

    第一个性质:厄米特矩阵S的特征值一定是实数。

    这个证明过程很简单:

    622e4aaf32e794ad42a51b15df6079d1.png

    我们抓住4732c9d26ee35c983ee338c9e48c5708.png这个关键等式进行观察,很显然等式的左侧有:

    7b687db26dbabf27617fe52565d021e4.png,我们可以观察出两个事实,一方面376d768ad1902822cc25818bf07c52ed.png是自共轭的,同时可以观察出6b20118117e9004d113e6ea7cb0c333b.png计算结果的维度是c4960d8377ea60b6704503497bf2fd7c.png,即结果是一个数,因此26298dc14fa90dbd19cc92ba5636fb8b.png显然只能是一个实数了。

    同时在等式右侧1ca2de0b22c0419343a7523909d2150f.png当中,a2abe05ad670696326aa5f8f85514060.png是复数向量z长度的平方,显然也是实数,那么作为系数的特征值92576fe2fc572be5696f28d9d269e229.png也必须是一个实数了。

    第二个性质:厄米特矩阵S中,不同特征值对应的特征向量满足彼此正交。

    我们来看看任意两个特征值0a0856e53a2c40bad378a18cc53e44ca.png6a0867e40c41fc116f3b4308eb8a9f5a.png以及他们所分别对应的特征向量:c5858bbf2ba133a7e965fa6b9d241574.png9b22fa452375406e95ba4ddc5aa49e1b.png。依照定义显然有48ad642798d9697195455a4ddf89c013.pngf61670c0533fce4c16a1d2b427d3fabb.png

    我们处理第一个特征值定义式子:3633be2e6488c231b16acf4629095c27.png

    而对于第二个特征值定义式,我们有:bd1bb553fa6959efb629361393fcc77e.png,等式两侧同时乘以向量ca3090a56fdcb3f63364eae9fb2b1daa.png,我们可以得到cb44ad7e903eb7af8b2fc6090c7636ee.png

    由于S是厄米特矩阵,满足自共轭特性,因此有,550a002403576fc310acc7459a961ec4.png,由于44eda4e5952d4626c054c671ac0e4d52.png89df5c83b4d6a7c2ecdeef7c5f74f6ec.png是不等的两个特征值,那么为了满足等式左右两边相等,则必须要求:7c356b62b5a2054df6309510093a219f.png,这不正是复数向量内积的定义式吗?两个复数向量内积为0,则二者必然正交。

    7.2.4  酉矩阵b8937bc49ec2112f0c9e7649565f5db7.png

    还是采用同样的思路,在讨论新概念酉矩阵之前,我们首先还是在实数矩阵中寻找对应的概念,还记得那个神奇的矩阵Q吗?

    矩阵Q是一个方阵,他的各列由一组标准正交向量0a414298fec7c966fdf9c64ce9cd8626.png所构成,方阵Q满足1defea5e06e2ba0315f6022a4b91d3a0.png的等式关系,我们称之为正交矩阵,这是我们前面学习过的概念,大家应该非常熟悉。

    那么将这个概念拓展到复数域当中,在复数域中各列满足标准正交的方阵Q我们也给他起了一个新名字,叫酉矩阵。很显然,基于复数向量内积的定义,这里实矩阵的转置操作就应该变成复数矩阵的共轭转置操作,即416ac4939eb98994cc47a9b442f0fa13.png。最终我们得出:酉矩阵Q是一个方阵,满足c5979feced5b7535529105f2fb3041cb.png的关系。

    7.2.5  傅里叶矩阵与离散傅里叶变换b8937bc49ec2112f0c9e7649565f5db7.png

    讲清楚酉矩阵的定义之后,我们不再过多的陷于细节性质的讨论。这里,我们直接抛出傅里叶矩阵的介绍,傅里叶矩阵号称是最重要的酉矩阵,用于进行离散傅里叶变换的处理工作。

    一个ac530985e7a96e0672491709b32a64a9.png的傅里叶矩阵的形式如下:

    dddc29cd6b7b09a7263c16a8390ac728.png,其中b41c9015af689fc14d08c8f40fc9345b.png,傅里叶矩阵中第i行,第j列的元素表达式为6e4efa055af4ccfc0aec345c1b03f347.png

    这里又一次的出现了6cfd99c681187e157b8a97e714548860.png,在前面一部分中我们已经讲过,这个量表示复平面单位圆上的第一个n等分点,因此n阶傅里叶矩阵中的所有元素都位于单位圆的n等分点上。

    我们来看几个实际的例子,为了便于我们计算,我们将b9110f6f795b83bf7ce6a856423b1b70.png按照欧拉公式0f841b565cce1fcc569ac6452dccf43c.png进行展开,得到:c9023d9b03303ada48f5746cc84feea1.png

    那么我们来看一看二阶、三阶和四阶的傅里叶矩阵分别是什么样的,大家一起实际找找感觉:

    0ae1f1736fb56ebd4dad58d73b9ce7ba.png

    了解了傅里叶矩阵的概念和形态之后,读者也许会问,这种矩阵有什么用处?前面不是已经对周期函数和非周期函数的傅里叶变换方法都做过介绍了吗?

    首先,顾名思义,傅里叶矩阵是用来辅助计算机进行傅里叶变换的,而前面介绍过的方法是提供给我们人来计算使用的。因为在信号处理的过程中,机器能够处理的都必须是离散的信号,因此我们前面介绍的连续时间周期函数和连续时间非周期函数都无法直接借助机器进行处理。

    机器能够处理什么样的信号?一方面是有限长度的信号,另一方面是离散的信号,这里的离散包含两个方面,一个是傅里叶变换前时域的信号必须离散,另一个是变换后频域里的频谱也必须离散。

    要想使用机器来进行傅里叶变换,就必须满足这三个条件,这称之为离散傅里叶变换(DFT)。有限长度很好满足,我们对一段连续时间信号进行截断即可,截断区间我们可以取cab04e43b8e6daadd888eed5a988fe46.png,通过对连续时间信号进行采样,获取时域内的离散输入。

    采样的个数一般定为,96cc774f18daa15e8845bfd0c92c593a.png如32,64,...,1024等等。我们在前面学习过,只有时域内的周期信号经过傅里叶变换才能得到离散的频谱,不过这个很好处理,我们将这段有限长度的时域信号进行周期延拓即可实现。

    我们通常借助计算机来实现离散傅里叶变换,那么理解好这个变换过程的输入和输出则非常重要。例如:我们对一个连续时间信号c82cab5131db2f2bff15db1357d36c90.png47458ff0bf69fb8298757a6fbea30141.png的采样区间内采样32次,那么时间信号的输入就变成了离散的形式:

    80b15cfab93f7c3192461c592fd49006.png

    即输入向量的元素为32个,即采样次数。

    然后,我们同样是把这个离散化后的函数4f254ee4b85a1e89cbb7a8b88e6e934f.png用一组谐波基来进行表示,那么首先我们就要确定这一组谐波的基频率706cb09aaabeed3dc57afcc41f05ce11.png:具备该基频率的谐波是在整个f5eae832c4847177a020c28e4b5a8391.png采样周期内只震动一个周期的谐波函数6c2f3ee432985229d12899540b3264ed.pngfab99df8bb29d1c560ca7006a84c45d2.png,所有基函数的频率都是这个基频率的整数倍,因此经过离散傅里叶变换后的基函数依次为:1,0b4ec6fce5adcea920ed26a07d295d36.png3b672596138dc6f84db5e735a888e514.pngc4effd16a1e1dde5d27c734fbc248895.pngc548234a313310aad3b3b275a8ae76f5.png0924ed700a1d767d9fb8d5af74c9d1f3.png8e47d366a070a62191585b3448aa11a4.png1ca74a5c00a10b5d311ad3d15baaa035.png41af1ec2a13a9890bea6a6c58e66088f.png,......,c7798fcb0bf65e27b8c65a2bff695ee8.png9490c46aeddcf1ecb9b23a09be6bdfa7.png,同频的正余弦函数算作一组,即含32组基函数。

    因此,经过离散傅里叶变换后的输出向量里的元素也是32个,但是这32个量是复数形式的7a6374184a923b57706ef8efd0c7e4bd.png,分别对应了每个频率的余弦和正弦基函数的系数,通过fcdfec6e5a32a06acd63232707909fef.pngc067f26a2a61c3ffd897c1e2e41cc067.png就可以计算出每个频率谐波基的幅度和相位。

    傅里叶矩阵是离散傅里叶变换中的核心数据结构,而通过针对矩阵结构进行优化设计而形成的高速、优化的算法,我们称之为快速傅里叶变换,也就是我们常听说的FFT。他大幅提升了信号处理的效率。

    最后我们利用python语言来实际进行离散傅里叶变换的处理,首先我们来看看我们要处理的时域信号:

    5bead0e5df5eb953c97ee820c4e7e337.png

    绘制函数图像的代码如下:

    import numpy as np
    import matplotlib.pyplot as plt

    def f(x):
        return np.sin(x)+2*np.sin(3*x)+2*np.cos(3*x)+4*np.sin(15*x)

    x = np.linspace(02*np.pi, 2048)
    plt.scatter(x, f(x))
    plt.grid()
    plt.show()

    如图7.4所示,我们来实际看看时域中信号在一个c1a957584114848039678cbcb1012085.png周期内的形态:

    1b8ef7b8f233a6158153ae1416ff77e8.png

    图7.4  时域信号263e7e8a0d3c60b8aee8784ce369f49a.png的形态

    下面我们就用python中的fft工具来对这段时域信号进行频域分析,代码如下:

    import numpy as np
    from scipy.fftpack import fft
    import matplotlib.pyplot as plt

    x = np.linspace(0, 2*np.pi, 128)
    y = np.sin(x)+2*np.sin(3*x)+2*np.cos(3*x)+4*np.sin(15*x)

    xf = np.arange(len(y))               #离散频率
    xf_half = xf[range(int(len(x)/2))]   #由于对称性,只取一半区域
    yf = abs(fft(y))/len(x)              #执行完fft后,对各频率的能量归一化处理
    yf_half = yf[range(int(len(x)/2))]   #由于对称性,只取一半区间

    plt.plot(xf_half, yf_half)
    plt.show()

    经过快速傅里叶变换之后,我们最终得到的结果如图7.5所示:

    1f4b4ebfbc1945b173e4095fbc7598f0.png

    图7.5  快速傅里叶变换后得到的频谱图

    我们仔细观察图中的数据,图中三个能量最高的峰值点,正对应我们时域函数c320b3a3eb35eb8c59216d066ce9bc87.png中合成的三个谐波频率,且能量也和各谐波系数取模后的比例保持一致。

    7.2.6  思维拓展分析b8937bc49ec2112f0c9e7649565f5db7.png

    对于快速傅里叶变换FFT的算法细节,限于本书的讨论主线,我们就不再对其展开介绍了。通过这一节内容的讨论,我们将思维和视野做了另一个维度的拓展,即从实数域拓展到了复数域,并将实数域中的一些重要矩阵和定理法则相应的做了类比分析,最终将实数域和复数域的向量与矩阵概念进行了统一和整合,从而探索出线性代数更为广阔的应用舞台。

    b8937bc49ec2112f0c9e7649565f5db7.png▼往期精彩回顾▼前言1.1 描述空间的工具:向量1.2 基底构建一切,基底决定坐标1.3 矩阵,让向量动起来1.4 矩阵乘向量的新视角:变换基底2.1 矩阵:描述空间中的映射2.2 追因溯源:逆矩阵和逆映射3.1 投影,寻找距离最近的向量3.2 深入剖析最小二乘法的本质3.3 施密特正交化:寻找最佳投影基地4.1相似变换:不同的视角,同一个变换4.2 对角化:寻找最简明的相似矩阵4.3  关键要素:特征向量与特征值

    5.1  最重要的矩阵:对称矩阵

    5.2 数据分布的度量

    5.3利用特征值分解进行主成分分析(PCA)

    5.4  更通用的利器:奇异值分解(SVD)

    5.5  利用奇异值分解进行数据降维

    d2be0b2aa7b7a83d11f6f24dba7a3154.png本书所涉及的源代码已上传到百度网盘,供读者下载。请读者关注封底“博雅读书社”微信公众号,找到“资源下载”栏目,根据提示获取。29c895aaf3b8a34ea1ab03686a8462a7.gif

    如果您对本书感兴趣,请进入当当网选购!

    e66d4ce1350c6e160d4bf5c7f4393d70.png

    5cb53741164c7b638cb51b8476a02388.gif

    7508425c3842e28f5f28d3231bdd0f32.png

    展开全文
  • 相比群来说,增加了一个运算,假设有集合A,运算{+},运算{•},如果集合A对{+}运算做成一个群,称作加法群,加法群A中的单位元称为零元,A中去除零元后的集合对{•}运算也做成一个群,并且+和•满足分配律,即 ...

    上一篇文章讲了群的概念,现在来介绍一下域的概念。群是一个集合和运算,集合中元素的运算满足群的4条性质。相比群来说,域增加了一个运算,假设有集合A,运算{+},运算{•},如果集合A对{+}运算做成一个群,称作加法群,加法群A中的单位元称为零元,A中去除零元后的集合对{•}运算也做成一个群,并且+和•满足分配律,即

    a•(b+c) = a•b+a•c

    那么我们把A叫做一个域,要注意+和•不一定是我们熟知的加法和乘法,也可以定义成其他运算,只要满足域的性质就行了,通常按照习惯,{•}运算在表达时可以省略。接下来举两个常见域的常见例子。

    有理数域

    有理数是我们比较熟悉的一个例子,所有有理数的集合对加法和乘法做成一个域。整数的集合并不是一个域,例如3这个数对于乘法来说在整数范围内并不存在逆元,但是在有理数范围内就存在逆元1/3,而有理数是一个域,可以举一些有理数的加法和乘法运算

    加法组成一个群:

    • 结合律
      例如 (5/4+(2/1+4/3)=(5/4+2/1)+4/3 = 55/12
    • 单位元(零元)
      例如0+3/2 = 3/2
    • 有逆元
      例如3/2的逆元是-3/2

    除0外乘法组成一个群:

    • 结合律
      (5/4•(2/1•4/3)=(5/4•2/1)•4/3 = 40/12 = 10/3
    • 单位元(1)
      例如1•3/2 = 3/2
    • 有逆元
      例如3/2的逆元是2/3,因为(3/2)•(2/3)=1

    剩余类

    设p是素数,以p为模的剩余类组成一个域,后面的代码会说明为什么p是素数。例如p=5,则剩余类{0,1,2,3,4}是一个域。

    加法组成一个群:

    • 结合律
      例如 0+(1+2)=(0+1)+2=0
    • 单位元(0)
      例如0+2 = 2
    • 有逆元
      例如1的逆元是4

    除0外乘法组成一个群:

    • 结合律
      1•(3•4)=(1•3)•4 = 2
    • 单位元(1)
      例如1•4 = 4
    • 有逆元
      例如2的逆元是3,因为2•3=6(mod 5) = 1

    代码实现

    有理数域

    先定义域的结构体:

    struct FieldSys
    {
        OperateSys *pGroup1;//加法群
        OperateSys *pGroup2;//乘法群
    };
    

    有理数元的结构体如下,由分子、分母、正负符号组成:

    typedef struct FieldEle FieldEle;
    struct FieldEle
    {
        u32 nmrtr;//分子
        u32 dnmtr;//分母
        u8 eSymb;//符号
    };
    
    

    接下来就要实现加法群和乘法群的相关函数。为了简单点,这里先不考虑溢出这些细节,把生成的数限制在100以内。代码的实现都非常简单,这里只列出接口,具体代码略去。

    加法群:

    //这里生成自然数,也可以RationGen生成有理数
    FieldEle *NatureGen(OperateSys *pOpSys,u32 num) 
    //有理数加法
    FieldEle *RationPlusOp(FieldEle *p1,FieldEle *p2)
    //判断有理数是否相等
    int RationEqual(FieldEle *p1, FieldEle *p2)
    //有理数加法取逆,即取负号
    FieldEle *RationPlusInv(FieldEle *p1)
    

    乘法群:

    //有理数的生成,由于需要分子、分母、符号3个参数,这里只有一个,
    //另外2个放在pOpSys里,参数都限制在100以内,要注意不能生成0
    FieldEle *RationGen(OperateSys *pOpSys,u32 num)
    //有理数乘法
    FieldEle *RationMultOp(FieldEle *p1,FieldEle *p2)
    //有理数求逆
    FieldEle *RationMultInv(FieldEle *p1)
    //判断有理数是否相等
    int RationEqual(FieldEle *p1, FieldEle *p2)
    
    

    剩余类域

    先定义剩余类结构体

    typedef struct ModEle ModEle;
    struct ModEle
    {
        u32 num;//自然数
        u32 mod;//取模
    };
    

    和上面类似实现加法群和乘法群的相关接口,这里以模5的剩余类为例

    加法群:

    OperateSys *ModPlusObj(void)
    {
        static ModEle baseItem =
        {
            0,
            5,
        };
    
        static OperateSys plus;
        memset(&plus,0,sizeof(plus));
    
        plus.pBaseEle = &baseItem;
        plus.nPara = 1;
        plus.xIsEqual = (void*)ModEqual;
        plus.xGen = (void*)ModNumGen;
        plus.xInvEle = (void*)ModPlusInv;
        plus.xOperat =  (void*)ModPlus;
    
        return +
    }
    

    乘法群:

    OperateSys *ModMultObj(void)
    {
        static ModEle baseItem =
        {
            1,
            5,
        };
    
        static OperateSys mult;
        memset(&mult,0,sizeof(mult));
    
        mult.pBaseEle = &baseItem;
        mult.nPara = 1;
        mult.isMult = 1;
        mult.xIsEqual = (void*)ModEqual;
        mult.xGen = (void*)ModNumGen;
        mult.xInvEle = (void*)ModMultInv;
        mult.xOperat =  (void*)ModMult;
    
        return &mult;
    }
    

    其他都很简单,这里主要说一下乘法求逆元的算法,根据费马定理如果a和p的最大公约数是1,那么a^(p-1)≡1(mod p),即a*a ^(p-2)≡1(mod p),因此a的逆元就是a ^(p-2),所以代码如下

    ModEle *ModMultInv(ModEle *p1)
    {
        ModEle *p;
        int i;
        u32 mod = p1->mod;
        p = malloc(sizeof(ModEle));
        memset(p,0,sizeof(ModEle));
    
        p->mod = mod;
        p->num = 1;
        for(i=0; i<mod-2; i++)
        {
            p->num = (p->num*p1->num)%mod;
        }
    
        return p;
    }
    

    域的证明

    只需要证明加法是群,乘法是群,加法和乘法之间满足分配律

    void IsGroup(OperateSys *pOpSys)
    {
        AssociativeLaw(pOpSys);
        HasIdentityEle(pOpSys);
        HasInvEle(pOpSys);
    }
    
    void IsField(FieldSys *pField)
    {
        IsGroup(pField->pGroup1);//加法成群
        IsGroup(pField->pGroup2);//乘法成群
        DistributiveLaw(pField);//分配律
    }
    

    有了这些证明之后就可以解决一些奇怪的问题,比如

    为什么分数的乘法是这么算的
    abcd=acbd \frac{a}{b}\cdot\frac{c}{d} = \frac{ac}{bd}
    而不是
    abcd=acb+d \frac{a}{b}\cdot\frac{c}{d} = \frac{ac}{b+d}
    我们可以把分数的乘法实现改成第2种形式,那么在证明乘法群时HasIdentityEle(pOpSys);函数会触发断言,单位元和任何元素相乘都不变

            pGen = pOpSys->xGen(pOpSys,k);//生成一个元素
            pEle = pOpSys->xOperat(pOpSys->pBaseEle,pGen);//该元素和单位元相乘后的结果
            rc = pOpSys->xIsEqual(pGen,pEle);//是否相等
            assert( rc );
    

    又比如分数的加法很奇怪,为什么是这么算的
    ab+cd=ad+bcbd \frac{a}{b}+\frac{c}{d} = \frac{ad+bc}{bd}
    而不是下面这种更符合直觉的算法呢
    ab+cd=a+cb+d \frac{a}{b}+\frac{c}{d} = \frac{a+c}{b+d}
    因为如果按照第2种算法,那么就会触发下面分配律的断言

            //随机生成3个元素
            for(j=0; j<3; j++)
            {
                k = FakeRand(i+j*10);
                SetGenPara(pMult,k);
                pT[j] = pMult->xGen(pMult,k);
            }
            //后2个元素相加再和第1个元素相乘
            pT[3] = pLus->xOperat(pT[1],pT[2]);
            pT[4] = pMult->xOperat(pT[0],pT[3]);
            //第一个元素分别于后2个元素相乘再相加
            pT[5] = pMult->xOperat(pT[0],pT[1]);
            pT[6] = pMult->xOperat(pT[0],pT[2]);
            pT[7] = pLus->xOperat(pT[5],pT[6]);
            //结果不变
            rc = pMult->xIsEqual(pT[4],pT[7]);
            assert( rc );
    

    最后要求模p的剩余类是一个域,为什么只有p是素数才成立,为了说明这个问题,我们可以在乘法初始化中把模改为4

        static ModEle baseItem =
        {
            1,
            4,
        };
    

    但这样运行代码后, 就会在函数HasInvEle中触发乘法存在可逆元的断言,因为对于2不存在元素x使得2*x≡1(mod 4)

    参考代码

    具体实现的代码细节见
    https://github.com/pfysw/CMath/tree/master/Algebra

    展开全文
  • 有限GF28GF2^8GF28LagrangeLagrangeLagrange插值分析ZUC流密码S盒的代数结构 背景 欧洲2000-2003年NESSIE计划和2004-2008年eSTREAM计划大大促进了流密码发展,提出了很多新兴流密码设计思路和分析方法...

    背景

    欧洲2000-2003年的NESSIE计划和2004-2008年的eSTREAM计划大大促进了流密码的发展,提出了很多新兴的流密码的设计思路和分析方法,很多新型的密码部件都在计划中提出了。提出了具有代表性的多个流密码,例如Grain,rivium,Mickey。我国密码专家在充分分析研究了前人的方案后,提出了国产的流密码方案——ZUC流密码。

    ZUC流密码的结构

    在这里插入图片描述

    ZUC流密码的S盒

    在密码学中,S盒(Substitution-box)是对称密钥算法执行置换计算的基本结构。S盒用在对称密码算法中,是唯一的非线性结构,其S盒的指标的好坏直接决定了密码算法的好坏。因此ZUC流密码结构中出现的两个S盒直接影响着ZUC流密码性能好坏。而然站在密码分析的角度,我们分析该密码部件的非线性度最佳方式就是对S盒的代数结构进行分析。所以我尝试采用C++语言来尝试用有限域GF28GF2^8的Lagrange插值得到可以代表S盒代数结构的多项式。

    S盒(左)

    在这里插入图片描述

    S盒(右)

    在这里插入图片描述

    C++求解ZUC流密码的S盒的代数结构

    由于不是简单的计算某个Lagrange差值的数值结果,而是需要得到LagrangeLagrange差值得到的多项式。因此我采用256256维数组代表这个最高次数为255255的多项式,数组存的便是这个多项式的系数。也就是程序运行的结果是一个256256维数组。

    有限域GF2^8的运算

    多项式的加法和乘法运算过程中,系数在有限域GF28GF2^8上进行运算,因此我首先写了进行有限域GF28GF2^8加减乘除运算的类,代码核心是:采用查表的形式提高有限域运算的效率。有限域的素多项式选择为:
    f(x)=x8+x4+x3+x+1f(x)=x^8+x^4+x^3+x+1
    有限域的生成元选择为:
    g(x)=x+1g(x)=x+1
    类的私有成员用来存储三张表:正表,反表,逆表。正表的下标代表有限域元素的阶,对应的数组内容即为该元素。反表的下标代表有限域元素本身,对应的数组内容为该元素对应的阶,逆表的每个下标对应的有限域元素与对应的数组内容存储的有限域元素互为逆元。

    class Operator
    {
    private:
        int P_Table[255];//正表:下标为阶数,元素为值,取值范围[0,255].
        int N_Table[256];//反表:下标为值,取值范围[0,255],元素为阶数.
        int R_Table[255];//逆元表:下标值与下标对应元素的值互为逆元。
    public:
        Operator()//构造函数:用于得到运算所需的表
        {
            //用于构造正表
            P_Table[0] = 1;
            for(int i=1; i<255; ++i)
            {
                P_Table[i] = (P_Table[i-1] << 1) ^ P_Table[i-1];//计算g^i
                if(P_Table[i] & 0x100)//判断上述过程得到的多项式次数是否达到8
                {
                    P_Table[i] ^= 0x11b;//用技巧模m(x) = x^8 + x^4 + x^3 +x +1
                }
                
            }
            
            //用于构造反表
            for(int i=0; i<255; ++i)
            {
                N_Table[ P_Table[i] ] = i;
            }
            
            //用于构造逆元表
            for(int i=1; i<256; ++i)//0没有逆元,所以从1开始
            {
                int k = N_Table[i];
                k = (255 - k) % 255;//m_table的取值范围为 [0, 254]
                R_Table[i] = P_Table[k];
            }
        }
        
        //有限域上的加法
        int GF_Add(const int &a, const int &b)
        {
            return a^b;
        }
        
        //有限域上的乘法
        int GF_Mul(const int &x, const int &y)
        {
            return(((x == 0) || (y == 0)) ? 0 : P_Table[(N_Table[x] + N_Table[y]) % 255] );
        }
        
        //有限域上的除法
        int GF_Div(const int &x, const int &y)
        {
            return GF_Mul(x, R_Table[y]);
        }
        
        //观察正表,反表,逆表的内容
        void Show()
        {
            for(int i=0; i<255; ++i)
            {
                cout << hex << P_Table[i] << " ";
            }
            cout << "\n" << endl;
            for(int i=1; i<256; ++i)
            {
                cout << N_Table[i] << " ";
            }
            cout << "\n" << endl;
            for(int i=1; i<255; ++i)
            {
                cout << hex << R_Table[i] << " ";
            }
            cout << "\n" << endl;
        }
    };
    }
    

    多项式的运算

    在整个LagrangeLagrange差值过程中,多项式的运算只需要多项式的加法和多项式的乘法。因此本代码也只包含多项式的这两种运算。

    多项式的加法
    //多项式加法
        template <typename Type>
        Type* P_A(const Type *a, const int &Len1, const Type *b, const int &Len2)
        {
            int Len3 = Max(Len1, Len2);//获得用于表示和多项式的数组的长度
            Type *arr = new Type[Len3];//为和多项式的数组开辟动态内存空间
            for(int i = 0; i<Len3; ++i)//将每个元素初始化为0
            {
                arr[i] = 0;
            }
            
            if (Len1 == Len3)
            {
                for (int i=0; i<Len3; ++i)//将多项式最高次的次数高的数组赋给新的数组
                {
                    arr[i] = a[i];
                    
                }
                for (int i=Len2-1 ; i>=0; --i)//将多项式最高次的次数低的数组与新的数组相加
                {
                    arr[Len1-(Len2-i)] = Operate_main.GF_Add(arr[Len1-(Len2-i)], b[i]);
                }
            }
            else
            {
                for (int i=0; i<Len3; ++i)//将多项式最高次的次数高的数组赋给新的数组
                {
                    arr[i] = b[i];
                }
                for (int i=Len1-1; i>=0; --i)//将多项式最高次的次数低的数组与新的数组相加
                {
                    arr[Len2-(Len1-i)] = Operate_main.GF_Add(arr[Len2-(Len1-i)], a[i]);
                }
            }
            return arr;
        }
    
    多项式的乘法
    //多项式乘法
        template <typename Type>
        Type* P_M(const Type *a, const int &Len1, const Type *b, const int &Len2)
        {
            Type *arr = new Type[Len1 + Len2 - 1];//为积多项式的数组开辟动态内存空间
            for(int i = 0; i<Len1 + Len2 - 1; ++i)//将每个元素初始化为0
            {
                arr[i] = 0;
            }
            
            for (int i=Len2-1; i>=0; --i)//用数组b的元素分别去乘数组a
            {
                for (int j=Len1-1; j>=0 ; --j)
                {
                    arr[j+i] = Operate_main.GF_Add(arr[j+i], Operate_main.GF_Mul(b[i], a[j]));
                }
            }
            return arr;
        }
    
    

    Lagrange差值

    我将多项式Lagrange插值过程分为三步。
    第一步,计算LagrangeLagrange基函数的系数:
    Coe=yi(xi+x1)(xi+x2)(xi+x256) Coe=\frac{y_i}{(x_i+x_1)(x_i+x_2)\ldots(x_i+x_{256})}
    第二步,计算LagrangeLagrange基函数:
    Bas=yi(xx1)(xx2)(xx256)(xi+x1)(xi+x2)(xi+x256) Bas=\frac{y_i(x-x_1)(x-x_2)\ldots(x-x_{256})}{(x_i+x_1)(x_i+x_2)\ldots(x_i+x_{256})}
    第三步,计算LagrangeLagrange差值多项式:
    Pol=y1(x+x2)(x+x256)(x1+x2)(x1+x256)+y2(x+x1)(x+x256)(x2+x1)(x2+x256)++y256(x+x1)(x+x255)(x256+x1)(x256+x255) Pol=\frac{y_1(x+x_2)\ldots(x+x_{256})}{(x_1+x_2)\ldots(x_1+x_{256})}+\frac{y_2(x+x_1)\ldots(x+x_{256})}{(x_2+x_1)\ldots(x_2+x_{256})}+\ldots+\frac{y_{256}(x+x_1)\ldots(x+x_{255})}{(x_{256}+x_1)\ldots(x_{256}+x_{255})}
    因此为此我以为写了三个函数分别来实现上述三步:

    计算LagrangeLagrange基函数的系数
    //定义插值基函数的系数
    int Lag_Bas_Coe(const int S[16][16], const int &Row, const int &Column)
    {
        int X = Row * 0x10 + Column;//插值点的x值
        int Den = 1;//初始化分母
        for(int i=0; i<0x100; ++i)//迭代计算分母
        {
            if(i != X)
            {
                Den = Operate_main.GF_Mul(Den, Operate_main.GF_Add(X, i));
            }
        }
        int Coe;//初始化系数
        return Coe = Operate_main.GF_Div(S[Row][Column], Den);
    }
    
    计算LagrangeLagrange基函数
    //定义拉格朗日插值的基函数
    int* Lag_Bas_Fun(const int S[16][16], const int &Row, const int &Column)
    {
        int X = Row * 0x10 + Column;//插值点的x值
        
        int tmp_1[2];//每一步迭代相乘的多项式
        int *tmp_main = new int[2];//主迭代多项式
        int count = 0;//用于迭代更新返回数组的长度
        for(int i=0; i<0x100; ++i)
        {
            if(i != X)
            {
                tmp_1[0] = 1;
                tmp_1[1] = i;
                int *tmp_2 = new int[2 + count];
                if(count == 0)
                {
                    for(int j=0; j<2; ++j)
                    {
                        tmp_2[j] = tmp_1[j];
                    }
                }
                else
                {
                    tmp_2 = Polynomial_Operation::P_M<int>(tmp_main, 1 + count, tmp_1, 2);
                    delete[] tmp_main;
                }
                tmp_main = new int[2 + count];//主迭代多项式
                for(int j=0; j<2+count; ++j)
                {
                    tmp_main[j] = tmp_2[j];
                }
                delete[] tmp_2;
                count++;
            }
        }
        
        int Coe = Lag_Bas_Coe(S, Row, Column);
        for(int i=0; i<0x100; ++i)
        {
            tmp_main[i] = Operate_main.GF_Mul(tmp_main[i], Coe);
        }
        return tmp_main;
    }
    
    计算LagrangeLagrange差值多项式
    //定义差值多项式函数
    int* Lag_Pol(const int S[16][16])
    {
        int* tmp = new int[256];
        int* Pol = new int[256];
        for(int i=0; i<256; ++i)
        {
            Pol[i] = 0;
        }
        for(int i=0; i<0x10; ++i)
        {
            for(int j=0; j<0x10; ++j)
            {
                tmp = Lag_Bas_Fun(S, i, j);
                Pol = Polynomial_Operation::P_A<int>(tmp, 256, Pol, 256);
            }
        }
        delete[] tmp;
        return Pol;
    }
    
    

    插值结果

    现在我们来调用主函数查看差值多项式的结果:

    int main()
    {
        int *Pol = new int[256];
        //计算S盒的有限域拉格朗日插值多项式
        Pol = Lagrange::Lag_Pol();
        for(int i=0; i<256; ++i)
        {
            cout << hex << Pol[i] <<" ";
        }
        cout << endl;
        delete[] Pol;
        return 0;
    }
    
    S盒(左)的差值多项式Pol1Pol_1

    在这里插入图片描述

    S盒(右)的差值多项式Pol2Pol_2

    在这里插入图片描述

    插值结果验证

    为了验证这里得到多项式的正确性,我们需要计算有限域上全部256256点对应的结果是否正确。为此我写了一个测试函数来测试结果的正确性:

    //测试函数_用于验证多项式的正确性
    int Test_Fun(const int *a, const int &len, const int &Row, const int &Column)
    {
        int test_1;
        int test_2 = 0;
        int X = Row * 16 + Column;
        for(int i=0; i<256; ++i)
        {
            test_1 = 1;
            for(int j=0; j<255-i; ++j)
            {
                test_1 = Operate_main.GF_Mul(test_1,X);
            }
            test_2 = Operate_main.GF_Add(Operate_main.GF_Mul(test_1, a[i]), test_2);
        }
        return test_2;
    }
    

    并在主函数中调用该函数来进行测试:

    int main()
    {
        int* Pol = new int[256];
        Pol = Lagrange::Lag_Pol();
        for(int i=0; i<0x10; ++i)
        {
            for(int j=0; j<0x10; ++j)
            {
                cout << hex << Lagrange::Test_Fun(Pol, 256, i, j)<<" ";
            }
            cout << endl;
        }
        cout << endl;
        delete[] Pol;
        return 0;
    }
    
    
    验证S盒(左)的差值多项式Pol1Pol_1

    在这里插入图片描述

    验证S盒(右)的差值多项式Pol2Pol_2

    在这里插入图片描述
    经过验证,我发现得到的结果和ZUC流密码的两个S盒保持了一致。因此可以充分说明我成功的利用有限域GF28GF2^8LagrangeLagrange插值得到了可以用来描述S盒非线性性质的多项式。

    展开全文
  • 在Clifford代数的域中给出了Maxwell方程的新统一形式,其方式类似于用Pauli和Dirac代数获得的形式。 结果表明,可以从与经典电磁的标量和矢量势密切相关的势函数获得新的电磁场多矢量。 此外,与通过应用其他方法...
  • 群 群G(group)是指由一个集合和一个...对于任意G中的两个元素,\(a\) 和 \(b\),\(a*b\) 也是 \(G\) 中的一个元素。 群中有一个元素 \(e\),称为单位元 对于群中的每个元素 \(a\) 都满足 \(a*e=e*a\) 群中每个...
  • JavaScript中的代数效果,包括作用处理程序,多行定界延续和do表示法 如何开始? 您可以在试用它,或将其安装在npm中: $ npm install effkit 文献资料 您可以在阅读文档。 什么是代数效应? 代数效应基于两个...
  • 元组则是这张表(关系)中的一行;属性则是这张表中的一列。是有相同数据类型值的集合,类似于表中某个属性的并集。笛卡尔积则是在上的一种集合运算。 (2)若关系中的某一属性组的值能够唯一地标识一个元组,则...
  • 抽象代数作为数学一门学科,主要研究对象是代数结构,比如群、环、、模、向量空间、格与域代数。“抽象代数”一词出现于20世纪初,作为与其他代数领域相区别之学科。 代数结构与其相关之同态,构成数学范畴。...
  • R中Y与S中的Y可以有不同的属性名,但必须出自相同的域集。R与S的除运算可以得到一个新的关系P(X),P是R中满足下列条件的元组在X 属性列上的投影: 元组在X上的分量值x的像集Y(x)包含S在Y上的投影的集合。 定义过于抽象...
  • 博主是初学近世代数(群环),本意是想整理一些较难理解定理、算法,加深记忆也方便日后查找;如果有错,欢迎指正。 四元数体是爱尔兰数学家哈密顿(W.R.Hamilton)于1843年发现,是数学史上一件划时代事件...
  • 一个Hopf代数的代数自同构,陈惠香,王文娟,设k是一个特征为零的代数,q是k一个非零元,且q不是单位根。再设C是k上一个Hopf代数,由一个群样元x和一个半本原元y生成,满
  • 数据库存储了大量关系(表)之后,要对其进行增删查改等操作,其一般通过SQL类语言来实现,而语言实现基础就是对关系进行一定集合(关系代数)或逻辑处理(关系演算、演算),然后返回处理结果。...
  • 运用已知类别训练样本进行学习,产生若干个代数界面d(x)=0,将特征空间划分为一些互不重叠子区域。 2.判别函数:表示界面函数d(x)称为判别函数; 对于两类分类问题, 若线性可分,它们边界线就是一个判别...
  • 代数结构笔记 - 半群,群,环与 初版日期: 2020-6-27 最后更新日期: 2020-6-7 更新次数: 概要 介绍命题之间关系 正文 首先要明白二元运算符在集合上有幺元, 零元定义, 它们都是代数常量. 二元运算符...
  • 还是觉得《[转]MIT牛人解说数学体系》中的描述最深入浅出,如下: 代数主要研究的是运算规则。一门代数, 其实都是从某种具体的运算体系中抽象出一些基本规则,建立一个公理体系,然后在这基础上进行研究。一个...
  • SQL语句实现关系代数中的“除法”

    千次阅读 2016-12-04 20:39:30
    R中Y与S中的Y可以有不同的属性名,但必须出自相同的域集。R与S的除运算可以得到一个新的关系P(X),P是R中满足下列条件的元组在X 属性列上的投影: 元组在X上的分量值x的像集Y(x)包含S在Y上的投影的集合。2.求解步骤过程...
  • 关系代数中的基本运算包括并,差,笛卡尔积,选择,投影。这五种基本代数运算可以推导出交、连接(包括自然连接)、和除法。其中前两者比较容易推导,直接根据定义不难得出,而除法定义理解起来较为复杂,且同时牵涉...
  • 提出了一种新基于几何代数的彩色光流场计算...然后依据物体色彩在运动过程保持不变原理,在几何代数域内推导了彩色图像序列光流约束方程及其解法。结果表明,该算法能够显著提高各种情况下彩色光流场计算能力。
  • 近世代数--欧几里得整环 博主是初学近世代数(群环),本意是想整理一些较难理解定理、算法,加深记忆也方便日后查找;如果有错,欢迎指正。 我整理成一个系列:近世代数,方便检索。 ...
  • 近世代数--整环上唯一分解问题--唯一分解整环元素标准分解式 博主是初学近世代数(群环),本意是想整理一些较难理解定理、算法,加深记忆也方便日后查找;如果有错,欢迎指正。 我整理成一个系列:近世...
  • 包括一个运算集合,集合运算以一个或两个关系为输入,产生一个新关系作为结果。 关系代数的基本运算包括:选择、投影、并、集合差、笛卡尔积、更名。 其他运算:集合交、自然连接、赋值,可用基本运算来定义...
  • 这是一个在有限域中实现算术Haskell库。 地位 到目前为止,我们已经实现了: 通用素数字段-模块Math.FiniteField.PrimeField.Generic 小质数字段,其中小意为p < 2^31模块Math.FiniteField.PrimeField.Small ...
  • 也许你会感兴趣,所以我们这里提供之前提纲高等代数|复习提纲(1)——矩阵与方程组高等代数|复习提纲(2)——线性空间与映射我们开始本节内容。1. 一元多项式和运算其实多项式这个概念你在初中就见过(整式)...
  • 本文讨论代数簇的(代数)德拉姆上同调,为了简单起见,... 具体来说,若 ,那么 ,直观地说,仿射代数簇 无非是仿射空间 中的一组多项式的公共零点集 .代数德拉姆上同调设 是 上的代数,仿射代数簇 的Kahler微分...
  • 近世代数--主理想整环 博主是初学近世代数(群环),本意是想整理一些较难理解定理、算法,加深记忆也方便日后查找;如果有错,欢迎指正。 我整理成一个系列:近世代数,方便检索。 ...
  • 如同上一篇笔记末尾所说的,从这个部分开始,我们暂时跳...格论在现实中的一个重要应用就是Boole代数了,故当我们对格论中的一些定理摸不着头脑时或者难以直观地理解时,有时从0-1的Boole代数的角度理解可能会带给我...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 538
精华内容 215
关键字:

代数中的域