尝试构造一个 matlab 抽象类, 但是 matlab 貌似不具备 抽象值类 的功能(matlab 具备抽象类功能!) 所以我们将在后学定义 group 这个类为抽象类,暂时将默认以 矩阵为对象(记为U),而其他对象的子类则重载算符即可。目前我们只尝试构建有限群, 后面有机会我们将构建连续群的类。
群论发展简记
- Late 1700s- Joseph-Louis Lagrange (1736-1813) 利用置换的概念,理解了三次和四次方程为什么有解。(Paolo Ruffini利用同样的思想证明了一般的五次或以上方程没有根式解)
- Early 1800s-Évariste Galois (killed in a duel in 1832 at age 20), and Niels
- Abel (died in 1829 at age 26 of TB) 阐述了代数方程的可解性和置换群的联系,真正利用群的概念解决了这个难题。
- 第一个正式的群的概念由Cayley于1854提出。Cayley, Hamilton, and Sylvester 引进了矩阵的表达。1890年Fedorov发展了各种对称性操作的数学方法,证明了晶体有且仅有230种空间群,次年Schönflies也独立的证明了这个结果。1920年群论开始应用于物理、化学等领域。里面还有很多著名数学家和物理学家的贡献,不一一而举。
群的定义
满足下列条件的二元组𝐺=(𝑆,⋅)可以称为群:
- 封闭性: ∀𝑥,𝑦∈𝑆,𝑥⋅𝑦∈𝑆;
- 结合律:∀𝑥,𝑦,𝑧∈𝑆,(𝑥⋅𝑦)⋅𝑧=𝑥⋅(𝑦⋅𝑧);
- 单位元:∃𝑒∈𝑆,∀𝑥∈𝑆,𝑒⋅𝑥=𝑥⋅𝑒=𝑥;
- 逆元:∀𝑥∈𝑆,∃𝑦∈𝑆,𝑥⋅𝑦=𝑦⋅𝑥=𝑒;
编码思路
把group类具象为一个含有矩阵U的对象, 实现一些基本的群操作,这样 后续继承的子类 只需重构 ( ==, < , .*, inv) 以及定义 E 强制单位元 这些函数,则可以满足群的要求
定义群对象
1function Gi = group(U)
2%构造此类的实例
3% G = group(U)
4 arguments
5 U = nan;
6 end
7 Gi.U = U;
8end
这里我们非常简单的初始化对象,方便继承;
定义单位元
1% Identity element
2% There exists an element 𝑒⋅𝑥=𝑥⋅𝑒=𝑥; It is called the identity element of the group.
3methods(Static)
4 function E = Identity()
5 E = group();
6 E.e = true;
7 end
8end
静态方法定义 单位元 ;直接附加一个属性叫 e; 在后续的基本操作中运用这个属性即可;
定义逆元
1% inv
2function G = inv(G1)
3 % Invert Operator
4 % Standerd definition
5 % need reload /
6 if length(G1) == 1
7 G =G1;
8 if isnan(G.U)
9 else
10 G.U = inv(G.U);
11 end
12 else
13 error('not support G-1 yet.');
14 end
15end
我们只需定义 除法 即可定义逆元, 注意这里使用 ./ 表示对单个元素的除法 后面可以使用 /(mrdivide) 表示商群
1function G3 = rdivide(G1,G2)
2 if m == 1 && n ==1
3 if G1.Identity
4 G3 = G2;
5 G3.U = inv(G2);
6 return;
7 elseif G2.Identity
8 G3 = G1;
9 return;
10 else
11 G3 = G1;
12 G3.U = G1.*G2.inv();
13 end
14 else
15 error('.*/ is elemenary operator');
16 end
17end
定义乘法(封闭性)
1% .*
2function G3 = times(G1,G2)
3 %
4 m = length(G1);
5 n = length(G2);
6 if m == 1 && n == 1
7 if G1.Identity
8 G3 = G2;
9 G3.U = inv(G2);
10 return;
11 elseif G2.Identity
12 G3 = G1;
13 return;
14 else
15 G3 = G1;
16 G3.U = G1.U*G2.U;
17 end
18 else
19 error('.*/ is elemenary operator');
20 end
21end
其他基本操作
我们仅仅重载这些函数是不可能复现群的结构的 想要满足群的封闭性, 我们必须得让每个群元互不相同
判别相等 以及 判别一个群和另一群是否等价
1% ==
2function TrueOrFalse = eq(G1,G2)
3 % return first
4 %
5 m = length(G1);
6 n = length(G2);
7 if m == 1 && n ==1
8 if isequal(G1.U,G2.U)
9 TrueOrFalse = true;
10 else
11 TrueOrFalse = false;
12 end
13 return;
14 elseif m == 1
15 TrueOrFalse(n) = false;
16 for i = 1:n
17 TrueOrFalse(n) = eq(G1,G2(i));
18 end
19 return;
20 elseif n == 1
21 TrueOrFalse(m) = false;
22 for i = 1:m
23 TrueOrFalse(m) = eq(G1(i),G2);
24 end
25 return;
26 elseif m == 0 && n == 0
27 TrueOrFalse =true;
28 return;
29 elseif m == 0 || n == 0
30 TrueOrFalse = false;
31 return
32 else
33 % unique need sort( sort need overload lt(less than))
34 G1 = unique(G1);
35 G2 = unique(G2);
36 %
37 m = length(G1);
38 n = length(G2);
39 if m == n
40 TrueOrFalse = false(size(G1));
41 for i =1:m
42 TrueOrFalse(i) = eq(G1(i),G2(i));
43 end
44 else
45 % generate_group ?
46 TrueOrFalse =false;
47 end
48 end
49end
定义 <
我们上面重载==时候,在最后判别 群与群等价时,使用了unique,unique会调用sort,sort 会调用 < 所以定义 lt 也是非常重要的
1function TrueOrFalse = lt(G1,G2)
2 % Sort group elements:
3 if G1.Identity && ~G2.Identity
4 TrueOrFalse = true;
5 return;
6 elseif ~G1.Identity && G2.Identity
7 TrueOrFalse = false;
8 return;
9 else
10 end
11 L = G1.U(:) < G2.U(:);
12 B = ~(G1.U(:) == G2.U(:));
13 for i =1:length(B)
14 if B(i)
15 TrueOrFalse = L(i);
16 return;
17 end
18 end
19 TrueOrFalse = false;
20end
这样重载sort使用插入排序即可
1% sort
2function [group_list,indSort] = sort(group_list)
3 % Use insertsort
4 [group_list,indSort] = group.insertsort(group_list);
5end
群论的一些特性
生成元 张成一个群
1function group = generate_group(gens)
2 % Generate group from gens
3 %
4 % Parameters
5 % ----------
6 % gens : iterable of generator of a group
7 %
8 % Returns
9 % -------
10 % group
11 %
12 % need reload minus
13 gens = unique(gens);
14 % here we keep all the elements generated so far
15 group = gens;
16 % these are the elements generated in the previous step
17 oldgroup = gens;
18 % fprintf('group muplicity: %d\n',group.order);
19 while true
20 newgroup= unique(oldgroup * gens);
21 % fprintf('newgroup muplicity: %d\n',newgroup.order);
22 % only keep those that are new
23 newgroup = newgroup - group;
24 % fprintf('newgroup muplicity (after -): %d\n',newgroup.order);
25 % if there are any new, add them to group and set them as old
26 if ~isempty(newgroup)
27 group = unique([group,newgroup]);
28 oldgroup = newgroup;
29 % if there were no new elements, we are done
30 else
31 break;
32 end
33 end
34 %group = group;
35end
测试
有了这个类 让我们来测试一下 完善我们对群的定义
验证群的定义
以pauli矩阵为例,探究群的定义
首先定义 三个pauli矩阵 并且初始化 group 对象
1sigma_x = sym([0 1;1 0]);sigma_y = sym([0 1i;-1i 0]);sigma_z = sym([1 0;0 -1]);
2Pauli_class = [group(sigma_x),group(sigma_y),group(sigma_z)];
结果告诉我们 Pauli_class = 1*3 group
封闭性
1ismember(group(sigma_x),Pauli_class)
2ismember(group(sigma_y),Pauli_class)
3ismember(group(sigma_x*sigma_y),Pauli_class)
4ismember(group(sigma_x)*group(sigma_y),Pauli_class)
可以看到,我们构建的这个群 并不具备封闭性;
所以使用 Pauli_class = Pauli_class.generate
可以看到 此时群元有 16个
结合率
1sigma_x*(sigma_y*sigma_z) == (sigma_x*sigma_y)*sigma_z
单位元
1Pauli_class(1).E == Pauli_class
唯一逆元
1Pauli_class(2).inv == Pauli_class
2Pauli_class(2).inv * Pauli_class(2) == Pauli_class(1).E
群的阶数
1Pauli_class.order
重排定理
群G中任意元素以相同方式作用在群中所有元素上, 得到的所有结果的集合仍是群本身.
1Pauli_class(1)*Pauli_class == Pauli_class
子群
任何一个群都含有两个子群
问如何找出一个群的全部子群?
Lagrange 定理
𝐺的每个子群的阶数都是𝐺的阶数的因数.
- 𝑝(𝑝是素数)阶群𝐺均是Abel群,且均同构于整数模𝑝的加法群ℤ𝑝.
因暴力运算太慢,转为数值运算
1sigma_x = group(([0 1;1 0]));
2sigma_y = group(([0 1i;-1i 0]));
3sigma_z = group(([1 0;0 -1]));
4Pauli_class = [sigma_x,sigma_y,sigma_z];
5Pauli_class = Pauli_class.generate_group();
6SubClassOfPauli_class = Pauli_class.subgroup();
我们搜索出了 由Pauli矩阵作为生成元的群的子群 其群阶为16 16 的因数有{1,16,2,8,4}, 共搜索出30个子群
陪集
共轭
里用Oper类创建2维的C4v旋转群,Oper类是group类的子类
1Square_group = Oper.square(false,false);
得到如下 group
Square_group =
1 : 1 2 : R(pi) 3 : M([1 0]) 4 : M([0.71 0.71]) 5 : R(pi/2) 6 : R(-pi/2) 7 : M([-0.71 0.71]) 8 : M([0 -1])
肉眼可见 5 和 6 是 C4z 的正向与反向旋转 属于同类
1G_alpha = Square_group(5);
2G_beta = Square_group(6);
3conjugate(G_alpha,G_beta,Square_group)
也可以找出一个元素的共轭类
1G_alphaConjugation = G_alpha.conjugation(Square_group)
利用共轭类也可以分割群
1ConjugationClassifyCollection = Square_group.conjugationseparation()
把群分成了5类,暗示其特征标表是5*5的
正规子群
对于 C4v群 求其正规子群, 有两个平凡正规子群+4个非平凡正规子群
1NormalSubgroup = normalsubgroup(Square_group);
商群
1Quotientgroups = Square_group/NormalSubgroup{3};
秩 生成元
暴力计算
1Generators = generator(Square_group);
2Rank = rank(Square_group)
C4v 有12种 最小生成元组合方式 其秩为2