代數結構:群與體· 把數學程式化

文章推薦指數: 80 %
投票人數:10人

在抽象代數中,體(Field)是一種可進行加、減、乘和除運算的代數結構。

體的概念是數體以及四則運算的推廣。

在台灣、Field 翻譯為《體》,在中國則翻譯為《域》 ... 把數學程式化--使用JavaScript的Rlab套件 Introduction Rlab科學計算套件 數值表示法 布林邏輯與公理系統 計算理論 集合論 測度論 代數 代數結構:群與體 求解方程式 微積分 微分方程 矩陣 線性代數 機率 統計 函數逼近 幾何學 PoweredbyGitBook 代數結構:群與體 代數結構:群與體 然後、老師開始講授一些代數的法則,像是《結合律、交換律、分配律》等等規則。

問題是、教這些規則要幹嘛呢?好像有用又好像沒太多用處。

其實這些規則屬於《抽象代數》的範圍,整個抽象代數就是研究《代數法則》所形成的結構體系,以及在這些結構體系下的定理等等議題。

《代數》建構在《數論》之上,研究《數》的運算,然後擴充到非數字型《元素》的運算上面,形成一整套的《運算體系》。

在《抽象代數》的運算體系中,最基本且重要的體系為《群、體、環》等等結構。

群(group) 群的定義 所謂的《群》,是具有《封閉性、結合性、單位元素、反元素》的一個《集合+運算》結構。

假如其中的運算用●代表,那麼《群》應該具有下列性質: 封閉性:對於所有G中a,b,運算a●b的結果也在G中。

結合性:對於所有G中的a,b和c,等式(a●b)●c=a●(b●c)成立。

單位元素:存在G中的一個元素e,使得對於所有G中的元素a,等式e●a=a●e=a成立。

反元素:對於每個G中的a,存在G中的一個元素b使得a●b=b●a=e,這裏的e是單位元素。

用數學符號的寫法,群(G,⋅)(G,\cdot)(G,⋅)應該具有下列特性: closability:∀a,b∈Ga⋅b∈G\foralla,b\inG\;a\cdotb\inG∀a,b∈Ga⋅b∈G associativity:∀a,b,c∈G(a⋅b)⋅c=a⋅(b⋅c)\foralla,b,c\inG\;(a\cdotb)\cdotc=a\cdot(b\cdotc)∀a,b,c∈G(a⋅b)⋅c=a⋅(b⋅c) identity:∀a∈Ga⋅e=e⋅a=a\foralla\inG\;a\cdote=e\cdota=a∀a∈Ga⋅e=e⋅a=a inversability:∀a∈G∃a−1∈Ga−1⋅a=a⋅a−1=e\foralla\inG\existsa^{-1}\inG\;a^{-1}\cdota=a\cdota^{-1}=e∀a∈G∃a​−1​​∈Ga​−1​​⋅a=a⋅a​−1​​=e 如果在《群》當中加入《交換律》,那麼這個群就稱為一個《交換群》(commutativegroup),或者稱為《阿貝爾群》(abeliangroup)。

群的範例 舉例而言、《實數》的加法運算,具有《封閉性、結合性、單位元素0與反元素-x》,因此《實數與加法》就形成了一個群。

但是《自然數》(不包含負數)的加法運算,就沒有反元素(因為-a不在自然數內,所以《自然數與加法》就不算是一個群。

同理、《實數與乘法》、《有理數與乘法》都可以形成一個群,但是《整數與乘法》卻無法形成一個群(因為反元素1/n不是整數)。

在線性代數當中,矩陣可以相加也可以相乘,其加法單位元素為一個全為0的矩陣。

而且對於 n*n矩陣的加法也符合《封閉性、結合性、單位元素、反元素》等等性質,因此《2*2》的矩陣與加法形成一個群。

而乘法雖然有單位元素為I,也就是對角線上全是1,其他部分全是0的矩陣。

但是卻不一定有反元素,因為有些矩陣A不具有反矩陣A−1A^{-1}A​−1​​,所以《矩陣與矩陣乘法》無法形成一個群。

於是《矩陣與乘法》自然就無法直接套用《群論》裡的那些定理,否則就可能會誤用數學定理,造成錯誤了! 對於更詳細的《群》之描述,請參考下列維基百科的文章: 維基百科:群 維基百科:初等群論 《抽象代數》當中的元素不一定要是數字,運算也不一定會是數字運算,像是《幾何操作》也可以當成一種《運算》作用在《幾何物體》上。

這種想法讓《代數學》可以連結上《幾何學》! 例如在《歐氏幾何》體系中,《公理與定理》在《平移、旋轉、鏡射》等運算下不會改變,因此這些《元素與運算》就形成了《歐氏幾何》中的一個不變群! 於是我們可以用《不變群》的角度來分類幾何學,像是《歐氏幾何、雙曲幾何、橢圓幾何、微分幾何》等等。

如果一個類似群的結構,但是《沒有反元素》,那麼就稱之為《么半群》(Monoid),如果《連單位元素也沒有》,那麼就稱之為《半群》。

體(Field) 在抽象代數中,體(Field)是一種可進行加、減、乘和除運算的代數結構。

體的概念是數體以及四則運算的推廣。

在台灣、Field翻譯為《體》,在中國則翻譯為《域》,以下我們將《兩者混用》,域和體都是指Field。

上述的群包含一個運算,而體則是包含兩個運算,像是《實數和加法與乘法》,就形成了一個《體結構》。

通常我們會將體的兩個運算,用加號與乘號代表,寫為《F,+,*》。

體的定義 一個體《F,+,*》必須滿足下列條件: 其中的《F,+》形成一個《交換群》,《F-{0},*》也形成一個《交換群》。

而且《乘法對加法》還必須具有《分配律》,也就是a∗(b+c)=a∗b+a∗ca*(b+c)=a*b+a*ca∗(b+c)=a∗b+a∗c。

這樣的一個《具有分配律的雙重交換群》結構《F,+,*》,就稱為體(Field)。

體的範例 《實數與乘法和加法》,也就是《R,+,*》就是一個《體結構》。

同樣的《複數與乘法和加法》,也就是《C,+,*》,也形成一個體結構。

《有理數與乘法和加法》,也就是《Q,+,*》,也同樣是一個體結構。

但是《整數與乘法和加法》,則無法形成一個體結構。

不過如果將《自然數對某質數p取mod運算後的元素,與乘法和加法》結合起來,就可以形成一個《體結構》。

這種進行mod之後的體結構,稱為《有限體》(finitefield)或《伽羅瓦體》(Galoisfield),在密碼學上的RSA公開金鑰系統,就是在這種《體結構》上運作的加解密系統。

體結構中的加法單位元素通常寫為0,乘法單位元素通常寫為1。

但是這不代表他們就一定是0或1。

線性代數當中的向量沒有定義乘法,但是有內積與外積,其中一個原因是《向量的乘法運算無法形成一個群》,關於這點請參考下文: 線代啟示錄:線性代數裡的代數結構 環 而所謂的《環結構》和《體結構》僅僅差一點點,差異是《環結構》的《乘法》,可以沒有反元素(但是有封閉性、結合性、單位元素),也就是《F,*》是一個《么半群》(monoid),那麼這個《F,+,*》結構就稱為《環》。

舉例而言,像是整數的加法與乘法,就形成一個《環結構》,但是因為整數乘法反元素1/n有可能不是整數,所以《無法形成體結構》。

模組field.js 抽象代數的定理 當我們對《代數結構》進行了詳細的區分,那麼就可以對各種結構進行數學推演,推演出來的《定理》就可以一層層的適用。

例如:《半群》的定理當然可以被套用在《群》結構裡面,因為一個群當然是個半群。

同樣的、在《環》當中成立的定理,也可以被套用在《體》上面,因為《體》也符合《環》的所有條件。

這就是為何要將《代數》抽象化的原因之一,因為同樣的定理,不需要證明兩次。

舉例而言、在《群論》裏面,有個《拉格朗日定理》),證明了群漢子群之間的關係,敘述如下: 敘述:設H是有限群G的子群,則H的階整除G的階。

其中的《階》代表群裡的元素個數),這個定理的證明牽涉到了陪集與子群的概念。

只要我們知道某個《F,+》是個群,那我們就可以套用拉格朗日定理,而不需要重新證明了! 在《么半群》當中,有個定理稱為克羅恩-羅德斯定理(Krohn–Rhodestheorem),這個定理可以套用在任何的《么半群》上面,當然也可以套用在任何的《群》上面。

程式解析 檔案:lib/field.js //module:Field&GroupTheory varF=require("./set"); F.Integer=require("./integer"); vareq=F.eq; //==========Group================= //注意:箭頭函數會自動將this變數綁定到其定義時所在的物件,因此以下很多地方不能用箭頭函數。

//參考:https://developer.mozilla.org/zh-TW/docs/Web/JavaScript/Reference/Functions/Arrow_functions F.Group={ invOp:function(x,y){ returnthis.op(x,this.inv(y)); }, power:function(x,n){ varp=this.e; for(vari=0;inewComplex(a,b); varenumComplex=[C(1,0),C(0,1),C(0,0),C(2,3),C(-5,4),C(-10,-7)]; F.ComplexSet=newF.Set(enumComplex); F.ComplexSet.has=(a)=>ainstanceofComplex; F.ComplexAddGroup={ e:newComplex(0,0), op:function(x,y){ x=Complex.toComplex(x),y=Complex.toComplex(y); returnnewComplex(x.a+y.a,x.b+y.b) }, inv:function(x){ x=Complex.toComplex(x); returnnewComplex(-x.a,-x.b) } } extend(F.ComplexAddGroup,F.Group,F.ComplexSet); F.ComplexMulGroup={ e:newComplex(1,0), op:function(x,y){ x=Complex.toComplex(x),y=Complex.toComplex(y); returnnewComplex(x.a*y.a-x.b*y.b,x.a*y.b+x.b*y.a); }, inv:function(x){ x=Complex.toComplex(x); vara=x.a,b=x.b,r=(a*a+b*b); returnnewComplex(a/r,-b/r); } } extend(F.ComplexMulGroup,F.Group,F.ComplexSet); extend(F.ComplexField,F.ComplexSet); F.ComplexField.init(F.ComplexAddGroup,F.ComplexMulGroup); //===========RatioField============== F.RatioField=extend({},F.Field); classRatioextendsFieldObj{ constructor(a,b){ super(F.RatioField); this.a=a;this.b=b; } reduce(){ vara=this.a,b=this.b; varc=F.Integer.gcd(a,b); returnnewRatio(a/c,b/c); } toString(){returnthis.a+'/'+this.b;} staticparse(s){ varm=s.match(/^(\d+)(\/(\d+))?$/); vara=parseInt(m[1]); varb=typeofm[3]==='undefined'?1:parseInt(m[3]); returnnewRatio(a,b) } } F.Ratio=Ratio; F.RatioAddGroup={ e:newRatio(0,1), op:function(x,y){returnnewRatio(x.a*y.b+x.b*y.a,x.b*y.b)}, inv:function(x){returnnewRatio(-x.a,x.b);}, } extend(F.RatioAddGroup,F.Group); F.RatioMulGroup={ e:newRatio(1,1), op:function(x,y){returnnewRatio(x.a*y.a,x.b*y.b)}, inv:function(x){returnnewRatio(x.b,x.a)}, } extend(F.RatioMulGroup,F.Group); F.RatioField.init(F.RatioAddGroup,F.RatioMulGroup); //===========FunctionOperation============== F.fneg=function(fx){returnfunction(v){ return-1*fx(v); }} F.finv=function(fx){returnfunction(v){ return1/fx(v); }} F.fadd=function(fx,fy){returnfunction(v){ returnfx(v).add(fy(v)); }} F.fsub=function(fx,fy){returnfunction(v){ returnfx(v).sub(fy(v)); }} F.fmul=function(fx,fy){returnfunction(v){ returnfx(v).mul(fy(v)); }} F.fdiv=function(fx,fy){returnfunction(v){ returnfx(v).div(fy(v)); }} F.fcompose=function(fx,fy){returnfunction(v){ returnfx(fy(v)); }} F.feval=function(f,x){returnf(x)} //f=(x,y)=>x*y+x*x; //f0=fa(f);f0([x,y]); F.fa=function(f){ returnfunction(x){ returnf.apply(null,x); } } //===========FunctionField============== F.FunctionField=extend({},F.Field); F.FunctionAddGroup={ e:function(x){return0}, op:function(x,y){returnF.fadd(x,y)}, inv:function(x){returnF.fneg(x)}, } extend(F.FunctionAddGroup,F.Group); F.FunctionMulGroup={ e:function(x){returnf(x)}, op:function(x,y){returnF.fsub(x,y)}, inv:function(x){returnF.finv(x)}, } extend(F.FunctionMulGroup,F.Group); F.FunctionField.init(F.FunctionAddGroup,F.FunctionMulGroup); //Function F.isField=function(x){ returnF.isBool(x)||F.isNumber(x)||xinstanceofF.FieldObj; } 我們將此模組放進rlab.Field這個物件中,於是我們就可以寫出一些簡單的使用範例如下: 檔案:example/fieldEx.js varR=require("../rlab"); varFF=R.FloatField; varbe=R.be; be('FF:2+3=5',FF.add(2,3)===5); be('FF:2^3=8',FF.power(2,3)===8); varF7=R.FiniteField.create(7); vara=3,b=6; be('F7:3+6=2',F7.add(a,b)===2); be('F7:3*6=4',F7.mul(a,b)===4); be('F7:closability(+)=>a+binF7',F7.addGroup.closability(3,6)); be('F7:associativity(+)=>(a+b)+c=a+(b+c)',F7.addGroup.associativity(3,6,4)); be('F7:identity(+)=>a+0=a',F7.addGroup.identity(3)); be('F7:inversability(+)=a-a=0',F7.addGroup.inversability(3)); varC=R.ComplexField; varc1=newR.Complex(2,3); be('C.has(c1)=true',C.has(c1)); be('C:c1==2+3i',c1.str()==='2+3i'); be('C:c1+c1=4+6i',C.add(c1,c1).str()==='4+6i'); be('C:c1*c1=-5+12i',C.mul(c1,c1).str()==='-5+12i'); be('C:(c1*c1)/c1=2+3i',C.div(C.mul(c1,c1),c1).str()==='2+3i'); varQ=R.RatioField; varq1=newR.Ratio(2,3); be('Q:q1=2/3',q1.str()==='2/3'); be('Q:q1+q1=4/3',Q.add(q1,q1).reduce().str()==='4/3'); be('Q:q1-q1=0',Q.sub(q1,q1).a===0); be('Q:q1*q1=4/9',Q.mul(q1,q1).str()==='4/9'); be('Q:q1/q1*q1=2/3',Q.mul(Q.div(q1,q1),q1).reduce().str()==='2/3'); be('Q:q1^3=8/27',q1.power(3).str()==='8/27'); varco=newR.Complex(2,3); be('C:co=2+3i',co.str()==='2+3i'); be('C:co+co=4+6i',co.add(co).str()==='4+6i'); be('C:co*co=-5+12i',co.mul(co).str()==='-5+12i'); be('C:co/co=1+0i',co.div(co).str()==='1+0i'); be('C:co*co/co=2+3i',co.mul(co).div(co).str()==='2+3i'); varc1=p('1+2i'),c2=p('2+1i'),c3=p('10+0i'); print('%s*%s=%s',c1,c2,c1.mul(c2)); print('(%s)*3=%s',c1,c1.mul(3)); print('3*3=%s',p('3').mul(3)); varsqrt2=Math.sqrt(2); varc=newR.Complex(sqrt2,sqrt2); print('c=%s',c); print('c.toPolar=%j',c.toPolar().str()); print('c*c=%s',c.mul(c)); print('c^2=%s',c.power(2)); print('c^2.sqrt()=%s',c.power(2).sqrt()); varP2=extend({e:[0,1]},R.PermutationGroup); print('[1,0].inv()=%j',P2.inv([1,0])); varP3=extend({e:[0,1,2]},R.PermutationGroup); print('[0,2,1].inv()=%j',P3.inv([0,2,1])); print('[2,1,0].inv()=%j',P3.inv([2,1,0])); print('[1,2,0].inv()=%j',P3.inv([1,2,0])); print('[1,2,0]*[1,2,0].inv()=%j',P3.op([1,2,0],P3.inv([1,2,0]))); print('[1,2,0].inv()*[1,2,0]=%j',P3.op(P3.inv([1,2,0]),[1,2,0])); varS2=[[0,1,2],[1,0,2]]; print('S2=',S2); print('leftCoset([1,2,0],S2)=',P3.leftCoset([1,2,0],S2)); print('rightCoset([1,2,0],S2)=',P3.rightCoset(S2,[1,2,0])); 執行結果: D:\Dropbox\github\rlab\example>nodefieldEx.js O:FF:2+3=5 O:FF:2^3=8 O:F7:3+6=2 O:F7:3*6=4 O:F7:closability(+)=>a+binF7 O:F7:associativity(+)=>(a+b)+c=a+(b+c) O:F7:identity(+)=>a+0=a O:F7:inversability(+)=a-a=0 O:C.has(c1)=true O:C:c1==2+3i O:C:c1+c1=4+6i O:C:c1*c1=-5+12i O:C:(c1*c1)/c1=2+3i O:Q:q1=2/3 O:Q:q1+q1=4/3 O:Q:q1-q1=0 O:Q:q1*q1=4/9 O:Q:q1/q1*q1=2/3 O:Q:q1^3=8/27 O:C:co=2+3i O:C:co+co=4+6i O:C:co*co=-5+12i O:C:co/co=1+0i O:C:co*co/co=2+3i 1+2i*2+1i=0+5i (1+2i)*3=3+6i 3*3=9 c=1.41+1.41i c.toPolar="{r:2,theta:0.79}" c*c=0+4.00i c^2=0.00+4i c^2.sqrt()=1.41+1.41i [1,0].inv()=["1","0"] [0,2,1].inv()=["0","2","1"] [2,1,0].inv()=["2","1","0"] [1,2,0].inv()=["2","0","1"] [1,2,0]*[1,2,0].inv()=["0","1","2"] [1,2,0].inv()*[1,2,0]=[0,1,2] S2=[[0,1,2],[1,0,2]] leftCoset([1,2,0],S2)=EnumSet{set:Set{[1,2,0],[0,2,1]},enumHea d:[]} rightCoset([1,2,0],S2)=EnumSet{set:Set{[1,2,0],[0,2,1]},enumHe ad:[]} 小結 透過《群、體》等嚴格的數學結構,我們可以建構出對應的程式,雖然程式和數學的表達方式,有些時候不太一樣,但其表達的內容是非常一致的。

程式中比較難處理的,主要是關於《無窮大、不可數與精確度》的部分,所以在上述程式中,我們使用《浮點數》Float代替實數,用《範圍很大的有限》來代替無限,然後用《電腦內部創建的型態,像是物件類的Group,Field,Complex,Ratio,IntegerField,FloatField,ComplexField等物件,來表達這些《代數結構》與對應的《數字結構》,這樣就能《用程式的語言表達數學的概念與運作邏輯》了! resultsmatching"" Noresultsmatching""



請為這篇文章評分?