在抽象代數中,體(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""